1#ifndef DUNE_MMESH_GRID_POLYGONCUTTING_HH
2#define DUNE_MMESH_GRID_POLYGONCUTTING_HH
8template <
class Scalar,
class Po
int>
16 template <
typename Polygon>
17 static std::vector<Point> sutherlandHodgman(
const Polygon& subjectPolygon,
18 const Polygon& clipPolygonInput) {
19 std::vector<Point> outputPolygon(subjectPolygon.begin(),
20 subjectPolygon.end());
21 std::vector<Point> clipPolygon(clipPolygonInput.begin(),
22 clipPolygonInput.end());
24 const int clipSize = clipPolygon.size();
28 for (
int clipIdx = 0; clipIdx < clipSize; clipIdx++) {
29 const int clipIdxNext = (clipIdx + 1) % clipSize;
31 std::vector<Point> inputPolygon(outputPolygon);
32 outputPolygon.clear();
33 const int inputSize = inputPolygon.size();
39 for (
int inputIdx = 0; inputIdx < inputSize; inputIdx++) {
40 const int inputIdxNext = (inputIdx + 1) % inputSize;
51 Point deltaQ = clipPolygon[clipIdxNext] - clipPolygon[clipIdx];
54 clipPolygon[clipIdx][1] * clipPolygon[clipIdxNext][0] -
55 clipPolygon[clipIdx][0] * clipPolygon[clipIdxNext][1];
57 Scalar firstPos = -deltaQ[0] * inputPolygon[inputIdx][1] +
58 deltaQ[1] * inputPolygon[inputIdx][0] + q2_cross_q1;
59 Scalar secondPos = -deltaQ[0] * inputPolygon[inputIdxNext][1] +
60 deltaQ[1] * inputPolygon[inputIdxNext][0] +
63 static constexpr double EPSILON = 1e-14;
65 if (firstPos > EPSILON && secondPos < -EPSILON) {
67 outputPolygon.push_back(lineIntersectionPoint(
68 inputPolygon[inputIdx], inputPolygon[inputIdxNext],
69 clipPolygon[clipIdx], clipPolygon[clipIdxNext]));
70 outputPolygon.push_back(inputPolygon[inputIdxNext]);
74 else if (firstPos < -EPSILON && secondPos > EPSILON) {
76 outputPolygon.push_back(lineIntersectionPoint(
77 inputPolygon[inputIdx], inputPolygon[inputIdxNext],
78 clipPolygon[clipIdx], clipPolygon[clipIdxNext]));
82 else if (firstPos >= -EPSILON && secondPos > EPSILON) {
90 outputPolygon.push_back(inputPolygon[inputIdxNext]);
100 static Point lineIntersectionPoint(
const Point& p1,
const Point& p2,
101 const Point& q1,
const Point& q2) {
102 Point deltaP = p1 - p2;
103 Point deltaQ = q1 - q2;
105 Scalar scaleFactor = deltaP[0] * deltaQ[1] - deltaQ[0] * deltaP[1];
107 deltaP *= q1[0] * q2[1] - q1[1] * q2[0];
108 deltaQ *= p1[0] * p2[1] - p1[1] * p2[0];
110 Point intersection = deltaQ - deltaP;
111 intersection /= scaleFactor;
120 template <
typename Po
ints>
121 static Scalar polygonArea(
const Points& polygonPoints) {
122 const int polygonSize = polygonPoints.size();
124 if (polygonSize < 3) {
130 for (
int i = 0; i < polygonSize; i++) {
131 const int j = (i + 1) % polygonSize;
132 area += polygonPoints[i][0] * polygonPoints[j][1];
133 area -= polygonPoints[j][0] * polygonPoints[i][1];
140 template <
typename Triang>
141 static Scalar intersectionVolumeCGAL(
const Triang& subjectTriangle,
142 const Triang& clipTriangle) {
143 using Epeck = CGAL::Exact_predicates_exact_constructions_kernel;
144 using PointCGAL = CGAL::Point_2<Epeck>;
145 using Triangle = CGAL::Triangle_2<Epeck>;
147 std::array<PointCGAL, 3> v;
148 for (
int i = 0; i < 3; ++i) {
149 const auto& p = makePoint(subjectTriangle[i]);
150 v[i] = PointCGAL(p.x(), p.y());
152 const Triangle triangle1(v[0], v[1], v[2]);
154 for (
int i = 0; i < 3; ++i) {
155 const auto& p = makePoint(clipTriangle[i]);
156 v[i] = PointCGAL(p.x(), p.y());
158 const Triangle triangle2(v[0], v[1], v[2]);
160 const auto result = CGAL::intersection(triangle1, triangle2);
162 using PointList = std::vector<PointCGAL>;
163 using Polygon = CGAL::Polygon_2<Epeck>;
166 if (
const Triangle* t = boost::get<Triangle>(&*result))
167 return std::abs(CGAL::to_double(
168 CGAL::area(t->vertex(0), t->vertex(1), t->vertex(2))));
171 else if (
const PointList* points = boost::get<PointList>(&*result)) {
172 Polygon polygon(points->begin(), points->end());
173 return std::abs(CGAL::to_double(polygon.area()));