88
99namespace convex_plane_decomposition {
1010
11- CgalPolygon2d createRegularPolygon (const CgalPoint2d& center, double radius, int numberOfVertices) {
12- assert (numberOfVertices > 2 );
13- CgalPolygon2d polygon;
14- polygon.container ().reserve (numberOfVertices);
15- double angle = (2 . * M_PI) / numberOfVertices;
16- for (int i = 0 ; i < numberOfVertices; ++i) {
17- double phi = i * angle;
18- double px = radius * std::cos (phi) + center.x ();
19- double py = radius * std::sin (phi) + center.y ();
20- // Counter clockwise
21- polygon.push_back ({px, py});
22- }
23- return polygon;
24- }
11+ namespace {
2512
2613int getCounterClockWiseNeighbour (int i, int lastVertex) {
2714 return (i > 0 ) ? i - 1 : lastVertex;
@@ -31,12 +18,6 @@ int getClockWiseNeighbour(int i, int lastVertex) {
3118 return (i < lastVertex) ? i + 1 : 0 ;
3219}
3320
34- void updateMean (CgalPoint2d& mean, const CgalPoint2d& oldValue, const CgalPoint2d& updatedValue, int N) {
35- // old_mean = 1/N * ( others + old_value); -> others = N*old_mean - old_value
36- // new_mean = 1/N * ( others + new_value); -> new_mean = old_mean - 1/N * oldValue + 1/N * updatedValue
37- mean += 1.0 / N * (updatedValue - oldValue);
38- }
39-
4021std::array<CgalPoint2d, 2 > getNeighbours (const CgalPolygon2d& polygon, int i) {
4122 assert (i < polygon.size ());
4223 assert (polygon.size () > 1 );
@@ -75,6 +56,55 @@ bool pointAndNeighboursAreWithinFreeSphere(const std::array<CgalPoint2d, 2>& nei
7556 return isInside (neighbours[0 ], circle) && isInside (point, circle) && isInside (neighbours[1 ], circle);
7657}
7758
59+ /* *
60+ * Returns {true, 0.0} if either one of the point -> neighbour segments intersects the parent shape
61+ * Returns {false, minSquareDistance} if none of the segments intersects. minSquareDistance is the minimum square distance between the
62+ * point and the parent shape
63+ */
64+ template <typename T>
65+ std::pair<bool , double > doEdgesIntersectAndSquareDistance (const std::array<CgalPoint2d, 2 >& neighbours, const CgalPoint2d& point,
66+ const T& parentShape);
67+
68+ template <>
69+ std::pair<bool , double > doEdgesIntersectAndSquareDistance (const std::array<CgalPoint2d, 2 >& neighbours, const CgalPoint2d& point,
70+ const CgalPolygon2d& parentShape) {
71+ CgalSegment2d segment0{neighbours[0 ], point};
72+ CgalSegment2d segment1{neighbours[1 ], point};
73+
74+ double minDistSquared = std::numeric_limits<double >::max ();
75+ for (auto edgeIt = parentShape.edges_begin (); edgeIt != parentShape.edges_end (); ++edgeIt) {
76+ const auto edge = *edgeIt;
77+ if (CGAL::do_intersect (segment0, edge) || CGAL::do_intersect (segment1, edge)) {
78+ return {true , 0.0 };
79+ } else {
80+ minDistSquared = std::min (minDistSquared, CGAL::squared_distance (point, edge));
81+ }
82+ }
83+
84+ return {false , minDistSquared};
85+ }
86+
87+ template <>
88+ std::pair<bool , double > doEdgesIntersectAndSquareDistance (const std::array<CgalPoint2d, 2 >& neighbours, const CgalPoint2d& point,
89+ const CgalPolygonWithHoles2d& parentShape) {
90+ const auto intersectAndDistance = doEdgesIntersectAndSquareDistance (neighbours, point, parentShape.outer_boundary ());
91+ if (intersectAndDistance.first ) {
92+ return {true , 0.0 };
93+ }
94+
95+ double minDistSquared = intersectAndDistance.second ;
96+ for (const auto & hole : parentShape.holes ()) {
97+ const auto holeIntersectAndDistance = doEdgesIntersectAndSquareDistance (neighbours, point, hole);
98+ if (holeIntersectAndDistance.first ) {
99+ return {true , 0.0 };
100+ } else {
101+ minDistSquared = std::min (minDistSquared, holeIntersectAndDistance.second );
102+ }
103+ }
104+
105+ return {false , minDistSquared};
106+ }
107+
78108template <typename T>
79109bool pointCanBeMoved (const CgalPolygon2d& growthShape, int i, const CgalPoint2d& candidatePoint, CgalCircle2d& freeSphere,
80110 const T& parentShape) {
@@ -83,25 +113,22 @@ bool pointCanBeMoved(const CgalPolygon2d& growthShape, int i, const CgalPoint2d&
83113 if (pointAndNeighboursAreWithinFreeSphere (neighbours, candidatePoint, freeSphere)) {
84114 return true ;
85115 } else {
86- // Update free sphere around new point
87- freeSphere = CgalCircle2d (candidatePoint, squaredDistance (candidatePoint, parentShape));
88- CgalSegment2d segment0{neighbours[0 ], candidatePoint};
89- CgalSegment2d segment1{neighbours[1 ], candidatePoint};
90-
91- bool segment0IsFree = isInside (neighbours[0 ], freeSphere) || !doEdgesIntersect (segment0, parentShape);
92- if (segment0IsFree) {
93- bool segment1IsFree = isInside (neighbours[1 ], freeSphere) || !doEdgesIntersect (segment1, parentShape);
94- return segment1IsFree;
95- } else {
116+ // Look for intersections and minimum distances simultaneously
117+ const auto intersectAndDistance = doEdgesIntersectAndSquareDistance (neighbours, candidatePoint, parentShape);
118+
119+ if (intersectAndDistance.first ) {
96120 return false ;
121+ } else {
122+ // Update free sphere around new point
123+ freeSphere = CgalCircle2d (candidatePoint, intersectAndDistance.second );
124+ return true ;
97125 }
98126 }
99127 } else {
100128 return false ;
101129 }
102130}
103131
104- namespace {
105132inline std::ostream& operator <<(std::ostream& os, const CgalPolygon2d& p) {
106133 os << " CgalPolygon2d: \n " ;
107134 for (auto it = p.vertices_begin (); it != p.vertices_end (); ++it) {
@@ -119,7 +146,6 @@ inline std::ostream& operator<<(std::ostream& os, const CgalPolygonWithHoles2d&
119146 }
120147 return os;
121148}
122- } // namespace
123149
124150template <typename T>
125151CgalPolygon2d growConvexPolygonInsideShape_impl (const T& parentShape, CgalPoint2d center, int numberOfVertices, double growthFactor) {
@@ -164,10 +190,26 @@ CgalPolygon2d growConvexPolygonInsideShape_impl(const T& parentShape, CgalPoint2
164190 std::cerr << " Center: " << centerCopy.x () << " , " << centerCopy.y () << " \n " ;
165191 std::cerr << parentShape << " \n " ;
166192 }
167-
168193 return growthShape;
169194}
170195
196+ } // namespace
197+
198+ CgalPolygon2d createRegularPolygon (const CgalPoint2d& center, double radius, int numberOfVertices) {
199+ assert (numberOfVertices > 2 );
200+ CgalPolygon2d polygon;
201+ polygon.container ().reserve (numberOfVertices);
202+ double angle = (2 . * M_PI) / numberOfVertices;
203+ for (int i = 0 ; i < numberOfVertices; ++i) {
204+ double phi = i * angle;
205+ double px = radius * std::cos (phi) + center.x ();
206+ double py = radius * std::sin (phi) + center.y ();
207+ // Counter clockwise
208+ polygon.push_back ({px, py});
209+ }
210+ return polygon;
211+ }
212+
171213CgalPolygon2d growConvexPolygonInsideShape (const CgalPolygon2d& parentShape, CgalPoint2d center, int numberOfVertices,
172214 double growthFactor) {
173215 return growConvexPolygonInsideShape_impl (parentShape, center, numberOfVertices, growthFactor);
@@ -177,4 +219,11 @@ CgalPolygon2d growConvexPolygonInsideShape(const CgalPolygonWithHoles2d& parentS
177219 double growthFactor) {
178220 return growConvexPolygonInsideShape_impl (parentShape, center, numberOfVertices, growthFactor);
179221}
222+
223+ void updateMean (CgalPoint2d& mean, const CgalPoint2d& oldValue, const CgalPoint2d& updatedValue, int N) {
224+ // old_mean = 1/N * ( others + old_value); -> others = N*old_mean - old_value
225+ // new_mean = 1/N * ( others + new_value); -> new_mean = old_mean - 1/N * oldValue + 1/N * updatedValue
226+ mean += 1.0 / N * (updatedValue - oldValue);
227+ }
228+
180229} // namespace convex_plane_decomposition
0 commit comments