1#ifndef DUNE_MMESH_GRID_POLYGONCUTTING_HH
2#define DUNE_MMESH_GRID_POLYGONCUTTING_HH
9 template<
class Scalar,
class Po
int>
19 template<
typename Polygon >
20 static std::vector<Point> sutherlandHodgman(
const Polygon& subjectPolygon,
21 const Polygon& clipPolygonInput)
24 outputPolygon(subjectPolygon.begin(), subjectPolygon.end());
26 clipPolygon(clipPolygonInput.begin(), clipPolygonInput.end());
28 const int clipSize = clipPolygon.size();
32 for (
int clipIdx = 0; clipIdx < clipSize; clipIdx++)
34 const int clipIdxNext = (clipIdx + 1) % clipSize;
36 std::vector<Point> inputPolygon(outputPolygon);
37 outputPolygon.clear();
38 const int inputSize = inputPolygon.size();
44 for (
int inputIdx = 0; inputIdx < inputSize; inputIdx++)
46 const int inputIdxNext = (inputIdx + 1) % inputSize;
57 Point deltaQ = clipPolygon[clipIdxNext] - clipPolygon[clipIdx];
60 clipPolygon[clipIdx][1] * clipPolygon[clipIdxNext][0] -
61 clipPolygon[clipIdx][0] * clipPolygon[clipIdxNext][1];
63 Scalar firstPos = - deltaQ[0] * inputPolygon[inputIdx][1]
64 + deltaQ[1] * inputPolygon[inputIdx][0] + q2_cross_q1;
65 Scalar secondPos = - deltaQ[0] * inputPolygon[inputIdxNext][1]
66 + deltaQ[1] * inputPolygon[inputIdxNext][0] + q2_cross_q1;
68 static constexpr double EPSILON = 1e-14;
70 if ( firstPos > EPSILON && secondPos < -EPSILON )
73 outputPolygon.push_back( lineIntersectionPoint(
74 inputPolygon[inputIdx], inputPolygon[inputIdxNext],
75 clipPolygon[clipIdx], clipPolygon[clipIdxNext] )
77 outputPolygon.push_back( inputPolygon[inputIdxNext] );
81 else if ( firstPos < -EPSILON && secondPos > EPSILON )
84 outputPolygon.push_back( lineIntersectionPoint(
85 inputPolygon[inputIdx], inputPolygon[inputIdxNext],
86 clipPolygon[clipIdx], clipPolygon[clipIdxNext] )
91 else if ( firstPos >= -EPSILON && secondPos > EPSILON )
101 outputPolygon.push_back( inputPolygon[inputIdxNext] );
106 return outputPolygon;
111 static Point lineIntersectionPoint(
const Point& p1,
const Point& p2,
112 const Point& q1,
const Point& q2)
114 Point deltaP = p1 - p2;
115 Point deltaQ = q1 - q2;
117 Scalar scaleFactor = deltaP[0] * deltaQ[1] - deltaQ[0] * deltaP[1];
119 deltaP *= q1[0] * q2[1] - q1[1] * q2[0];
120 deltaQ *= p1[0] * p2[1] - p1[1] * p2[0];
122 Point intersection = deltaQ - deltaP;
123 intersection /= scaleFactor;
133 template<
typename Po
ints >
134 static Scalar polygonArea (
const Points& polygonPoints)
136 const int polygonSize = polygonPoints.size();
145 for (
int i = 0; i < polygonSize; i++)
147 const int j = (i+1) % polygonSize;
148 area += polygonPoints[i][0] * polygonPoints[j][1];
149 area -= polygonPoints[j][0] * polygonPoints[i][1];
156 template<
typename Triang >
157 static Scalar intersectionVolumeCGAL(
const Triang& subjectTriangle,
158 const Triang& clipTriangle )
160 using Epeck = CGAL::Exact_predicates_exact_constructions_kernel;
161 using PointCGAL = CGAL::Point_2<Epeck>;
162 using Triangle = CGAL::Triangle_2<Epeck>;
164 std::array<PointCGAL, 3> v;
165 for (
int i = 0; i < 3; ++i )
167 const auto& p = makePoint( subjectTriangle[i] );
168 v[i] = PointCGAL( p.x(), p.y() );
170 const Triangle triangle1 ( v[0], v[1], v[2] );
172 for (
int i = 0; i < 3; ++i )
174 const auto& p = makePoint( clipTriangle[i] );
175 v[i] = PointCGAL( p.x(), p.y() );
177 const Triangle triangle2 ( v[0], v[1], v[2] );
179 const auto result = CGAL::intersection( triangle1, triangle2 );
181 using PointList = std::vector<PointCGAL>;
182 using Polygon = CGAL::Polygon_2<Epeck>;
186 if (
const Triangle* t = boost::get<Triangle>(&*result))
187 return std::abs( CGAL::to_double(
188 CGAL::area( t->vertex(0), t->vertex(1), t->vertex(2) ) ) );
191 else if (
const PointList* points = boost::get<PointList>(&*result))
193 Polygon polygon( points->begin(), points->end() );
194 return std::abs( CGAL::to_double( polygon.area() ) );