Merge ~sethh/kicad:tesselation into ~kicad-product-committers/kicad:master

Proposed by Seth Hillbrand
Status: Merged
Merge reported by: Seth Hillbrand
Merged at revision: d6b1a676c7df443227c9a73b5018776705d89ca4
Proposed branch: ~sethh/kicad:tesselation
Merge into: ~kicad-product-committers/kicad:master
Diff against target: 4195 lines (+652/-581)
11 files modified
3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp (+0/-18)
3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp (+2/-1)
3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.cpp (+12/-166)
3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h (+1/-1)
3d-viewer/CMakeLists.txt (+0/-6)
common/gal/opengl/opengl_gal.cpp (+2/-2)
common/geometry/shape_poly_set.cpp (+6/-170)
dev/null (+0/-186)
include/geometry/polygon_triangulation.h (+608/-0)
include/geometry/shape_poly_set.h (+21/-26)
polygon/CMakeLists.txt (+0/-5)
Reviewer Review Type Date Requested Status
Jeff Young (community) Approve
Wayne Stambaugh Approve
Review via email: mp+353697@code.launchpad.net

Commit message

Merge new tesselation code for triangulation in OpenGL as well as 3d-viewer.

Description of the change

This commit removes the previous poly2tri code and clears the associated limitations allowing more robust triangulation, including overlapping holes, degenerate vertices and others.

To post a comment you must log in.
Revision history for this message
Wayne Stambaugh (stambaughw) wrote :

I just tested this and I didn't run into any issues. As for any performance improvements, I really didn't notice any significant difference one way or the other but I don't have any really complex boards to test so my testing may not be accurate. Visually, I didn't notice any differences. If someone has some really complex boards, please test this and give your feedback. I do like the idea that we are replacing the Poly2Tri. I'm going to tentatively approve this assuming additional testing by other developers.

review: Approve
Revision history for this message
jean-pierre charras (jp-charras) wrote :

I made a few tests (one with a complex board) and did not notice any issue or difference.
I also did not see performance improvements: roughly 3D viewer takes the same time to build the 3D scene.
(W7/32 bits)

Revision history for this message
Seth Hillbrand (sethh) wrote :

Jeff, would you mind giving this a test-run to ensure there's no funny business on the Mac-side?

Revision history for this message
Seth Hillbrand (sethh) wrote :

@jp/wayne- Thanks for the tests. Speed is not expected to be noticeably different unless the board has overlapping holes. Then poly2tri cannot cache the polygon and we triangulate using whatever routine the user's OpenGL driver implements. Since the OpenGL routine runs on a single processor and re-runs each time the zone is highlighted, the speed difference is primarily visible there. This is related to
https://bugs.launchpad.net/kicad/+bug/1745050
and
https://bugs.launchpad.net/kicad/+bug/1780130

Revision history for this message
Jeff Young (jeyjey) wrote :

Nothing looks out of place on my boards or a few customer boards I checked.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
2index b7914e8..90b7590 100644
3--- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
4+++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp
5@@ -506,10 +506,6 @@ void CINFO3D_VISU::createNewPadWithClearance( const D_PAD* aPad,
6 if( aClearanceValue.x )
7 polyList.Inflate( aClearanceValue.x, 32 );
8
9- // This convert the poly in outline and holes
10- polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
11- polyList.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
12-
13 // Add the PAD polygon
14 Convert_shape_line_polygon_to_triangles( polyList, *aDstContainer, m_biuTo3Dunits, *aPad );
15
16@@ -830,11 +826,6 @@ void CINFO3D_VISU::AddShapeWithClearanceToContainer( const DRAWSEGMENT* aDrawSeg
17
18 aDrawSegment->TransformShapeWithClearanceToPolygon( polyList, aClearanceValue,
19 segcountforcircle, correctionFactor );
20- // This convert the poly in outline and holes
21- // Note: This two sequencial calls are need in order to get
22- // the triangulation function to work properly.
23- polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
24- polyList.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
25
26 if( polyList.IsEmpty() ) // Just for caution
27 break;
28@@ -861,15 +852,6 @@ void CINFO3D_VISU::AddSolidAreasShapesToContainer( const ZONE_CONTAINER* aZoneCo
29 SHAPE_POLY_SET polyList = SHAPE_POLY_SET(aZoneContainer->GetFilledPolysList());
30
31 // This convert the poly in outline and holes
32-
33- // Note: This two sequencial calls are need in order to get
34- // the triangulation function to work properly.
35- polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
36- polyList.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
37-
38- if( polyList.IsEmpty() )
39- return;
40-
41 Convert_shape_line_polygon_to_triangles( polyList,
42 *aDstContainer,
43 m_biuTo3Dunits,
44diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp
45index 9412318..bcd099b 100644
46--- a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp
47+++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp
48@@ -369,7 +369,8 @@ void C3D_RENDER_OGL_LEGACY::reload( REPORTER *aStatusTextReporter )
49 // /////////////////////////////////////////////////////////////////////////
50
51 CCONTAINER2D boardContainer;
52- Convert_shape_line_polygon_to_triangles( m_settings.GetBoardPoly(),
53+ SHAPE_POLY_SET tmpBoard = m_settings.GetBoardPoly();
54+ Convert_shape_line_polygon_to_triangles( tmpBoard,
55 boardContainer,
56 m_settings.BiuTo3Dunits(),
57 (const BOARD_ITEM &)*m_settings.GetBoard() );
58diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.cpp
59index 0ed9d61..45d0cca 100644
60--- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.cpp
61+++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.cpp
62@@ -35,9 +35,9 @@
63
64 #include <wx/glcanvas.h> // CALLBACK definition, needed on Windows
65 // alse needed on OSX to define __DARWIN__
66-
67+#include <geometry/polygon_triangulation.h>
68 #include "../../../3d_fastmath.h"
69-#include <poly2tri/poly2tri.h>
70+
71
72
73 CTRIANGLE2D::CTRIANGLE2D ( const SFVEC2F &aV1,
74@@ -126,172 +126,28 @@ bool CTRIANGLE2D::IsPointInside( const SFVEC2F &aPoint ) const
75 const float c = 1.0f - a - b;
76
77 return 0.0f <= c && c <= 1.0f;
78-/*
79- return 0.0f <= a && a <= 1.0f &&
80- 0.0f <= b && b <= 1.0f &&
81- 0.0f <= c && c <= 1.0f;*/
82-}
83-
84-
85-template <class C> void FreeClear( C & cntr )
86-{
87- for( typename C::iterator it = cntr.begin();
88- it != cntr.end();
89- ++it )
90- {
91- delete * it;
92- }
93-
94- cntr.clear();
95 }
96
97-// Note: Please check edgeshrink.cpp in order to learn the EdgeShrink propose
98
99-#define APPLY_EDGE_SHRINK
100-
101-#ifdef APPLY_EDGE_SHRINK
102-extern void EdgeShrink( std::vector<SFVEC2I64> &aPath );
103-
104-#define POLY_SCALE_FACT 256
105-#define POLY_SCALE_FACT_INVERSE (1.0 / (double)(POLY_SCALE_FACT))
106-#endif
107-
108-void Convert_shape_line_polygon_to_triangles( const SHAPE_POLY_SET &aPolyList,
109+void Convert_shape_line_polygon_to_triangles( SHAPE_POLY_SET &aPolyList,
110 CGENERICCONTAINER2D &aDstContainer,
111 float aBiuTo3DunitsScale ,
112 const BOARD_ITEM &aBoardItem )
113 {
114- unsigned int nOutlines = aPolyList.OutlineCount();
115
116+ aPolyList.CacheTriangulation();
117+ const double conver_d = (double)aBiuTo3DunitsScale;
118
119- for( unsigned int idx = 0; idx < nOutlines; ++idx )
120+ for( unsigned int i = 0; i < aPolyList.TriangulatedPolyCount(); i++ )
121 {
122- const SHAPE_LINE_CHAIN &outlinePath = aPolyList.COutline( idx );
123-
124- wxASSERT( outlinePath.PointCount() >= 3 );
125-
126- std::vector<SFVEC2I64> scaledOutline;
127- scaledOutline.resize( outlinePath.PointCount() );
128-
129- // printf("\nidx: %u\n", idx);
130-
131- // Apply a scale to the points
132- for( unsigned int i = 0;
133- i < (unsigned int)outlinePath.PointCount();
134- ++i )
135- {
136- const VECTOR2I& a = outlinePath.CPoint( i );
137-
138-#ifdef APPLY_EDGE_SHRINK
139- scaledOutline[i] = SFVEC2I64( (glm::int64)a.x * POLY_SCALE_FACT,
140- (glm::int64)a.y * POLY_SCALE_FACT );
141-#else
142- scaledOutline[i] = SFVEC2I64( (glm::int64)a.x,
143- (glm::int64)a.y );
144-#endif
145- }
146-
147-#ifdef APPLY_EDGE_SHRINK
148- // Apply a modification to the points
149- EdgeShrink( scaledOutline );
150-#endif
151- // Copy to a array of pointers
152- std::vector<p2t::Point*> polyline;
153- polyline.resize( outlinePath.PointCount() );
154-
155- for( unsigned int i = 0;
156- i < (unsigned int)scaledOutline.size();
157- ++i )
158- {
159- const SFVEC2I64 &a = scaledOutline[i];
160-
161- //printf("%lu %lu\n", a.x, a.y);
162-
163- polyline[i] = new p2t::Point( (double)a.x,
164- (double)a.y );
165- }
166-
167- // Start creating the structured to be triangulated
168- p2t::CDT* cdt = new p2t::CDT( polyline );
169-
170- // Add holes for this outline
171- unsigned int nHoles = aPolyList.HoleCount( idx );
172-
173- std::vector< std::vector<p2t::Point*> > polylineHoles;
174-
175- polylineHoles.resize( nHoles );
176-
177- for( unsigned int idxHole = 0; idxHole < nHoles; ++idxHole )
178- {
179- const SHAPE_LINE_CHAIN &outlineHoles = aPolyList.CHole( idx,
180- idxHole );
181-
182- wxASSERT( outlineHoles.PointCount() >= 3 );
183-
184- std::vector<SFVEC2I64> scaledHole;
185- scaledHole.resize( outlineHoles.PointCount() );
186-
187- // Apply a scale to the points
188- for( unsigned int i = 0;
189- i < (unsigned int)outlineHoles.PointCount();
190- ++i )
191- {
192- const VECTOR2I &h = outlineHoles.CPoint( i );
193-#ifdef APPLY_EDGE_SHRINK
194- scaledHole[i] = SFVEC2I64( (glm::int64)h.x * POLY_SCALE_FACT,
195- (glm::int64)h.y * POLY_SCALE_FACT );
196-#else
197- scaledHole[i] = SFVEC2I64( (glm::int64)h.x,
198- (glm::int64)h.y );
199-#endif
200- }
201-
202-#ifdef APPLY_EDGE_SHRINK
203- // Apply a modification to the points
204- EdgeShrink( scaledHole );
205-#endif
206-
207- // Resize and reserve space
208- polylineHoles[idxHole].resize( outlineHoles.PointCount() );
209-
210- for( unsigned int i = 0;
211- i < (unsigned int)outlineHoles.PointCount();
212- ++i )
213- {
214- const SFVEC2I64 &h = scaledHole[i];
215-
216- polylineHoles[idxHole][i] = new p2t::Point( h.x, h.y );
217- }
218-
219- cdt->AddHole( polylineHoles[idxHole] );
220- }
221-
222- // Triangulate
223- cdt->Triangulate();
224-
225- // Hint: if you find any crashes on the triangulation poly2tri library,
226- // you can use the following site to debug the points and it will mark
227- // the errors in the polygon:
228- // http://r3mi.github.io/poly2tri.js/
229-
230-
231- // Get and add triangles
232- std::vector<p2t::Triangle*> triangles;
233- triangles = cdt->GetTriangles();
234+ auto triPoly = aPolyList.TriangulatedPolygon( i );
235
236-#ifdef APPLY_EDGE_SHRINK
237- const double conver_d = (double)aBiuTo3DunitsScale *
238- POLY_SCALE_FACT_INVERSE;
239-#else
240- const double conver_d = (double)aBiuTo3DunitsScale;
241-#endif
242- for( unsigned int i = 0; i < triangles.size(); ++i )
243+ for( size_t i = 0; i < triPoly->GetTriangleCount(); i++ )
244 {
245- p2t::Triangle& t = *triangles[i];
246-
247- p2t::Point& a = *t.GetPoint( 0 );
248- p2t::Point& b = *t.GetPoint( 1 );
249- p2t::Point& c = *t.GetPoint( 2 );
250+ VECTOR2I a;
251+ VECTOR2I b;
252+ VECTOR2I c;
253+ triPoly->GetTriangle( i, a, b, c );
254
255 aDstContainer.Add( new CTRIANGLE2D( SFVEC2F( a.x * conver_d,
256 -a.y * conver_d ),
257@@ -302,15 +158,5 @@ void Convert_shape_line_polygon_to_triangles( const SHAPE_POLY_SET &aPolyList,
258 aBoardItem ) );
259 }
260
261- // Delete created data
262- delete cdt;
263-
264- // Free points
265- FreeClear(polyline);
266-
267- for( unsigned int idxHole = 0; idxHole < nHoles; ++idxHole )
268- {
269- FreeClear( polylineHoles[idxHole] );
270- }
271 }
272 }
273diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h
274index e43f2b8..c4b6689 100644
275--- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h
276+++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h
277@@ -68,7 +68,7 @@ public:
278 };
279
280
281-void Convert_shape_line_polygon_to_triangles( const SHAPE_POLY_SET &aPolyList,
282+void Convert_shape_line_polygon_to_triangles( SHAPE_POLY_SET &aPolyList,
283 CGENERICCONTAINER2D &aDstContainer,
284 float aBiuTo3DunitsScale,
285 const BOARD_ITEM &aBoardItem );
286diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/edgeshrink.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/edgeshrink.cpp
287deleted file mode 100644
288index 1027ec3..0000000
289--- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/edgeshrink.cpp
290+++ /dev/null
291@@ -1,89 +0,0 @@
292-/*
293- * This program source code file is part of KiCad, a free EDA CAD application.
294- *
295- * Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
296- * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
297- *
298- * This program is free software; you can redistribute it and/or
299- * modify it under the terms of the GNU General Public License
300- * as published by the Free Software Foundation; either version 2
301- * of the License, or (at your option) any later version.
302- *
303- * This program is distributed in the hope that it will be useful,
304- * but WITHOUT ANY WARRANTY; without even the implied warranty of
305- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
306- * GNU General Public License for more details.
307- *
308- * You should have received a copy of the GNU General Public License
309- * along with this program; if not, you may find one here:
310- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
311- * or you may search the http://www.gnu.org website for the version 2 license,
312- * or you may write to the Free Software Foundation, Inc.,
313- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
314- */
315-
316-/**
317- * @file edgeshrink.cpp
318- * @brief The edgeShrink function was found in the project clip2tri by the:
319- * Bitfighter project (http://bitfighter.org)
320- * https://github.com/raptor/clip2tri
321- * https://github.com/raptor/clip2tri/blob/f62a734d22733814b8a970ed8a68a4d94c24fa5f/clip2tri/clip2tri.cpp#L150
322- */
323-
324-#include <plugins/3dapi/xv3d_types.h>
325-#include <vector>
326-
327-// clip2tri is Licenced under:
328-
329-// The MIT License (MIT)
330-
331-// Copyright (c) 2014 Bitfighter developers
332-
333-// Permission is hereby granted, free of charge, to any person obtaining a copy
334-// of this software and associated documentation files (the "Software"), to deal
335-// in the Software without restriction, including without limitation the rights
336-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
337-// copies of the Software, and to permit persons to whom the Software is
338-// furnished to do so, subject to the following conditions:
339-
340-// The above copyright notice and this permission notice shall be included in all
341-// copies or substantial portions of the Software.
342-
343-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
344-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
345-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
346-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
347-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
348-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
349-// SOFTWARE.
350-
351-
352-// Shrink large polygons by reducing each coordinate by 1 in the
353-// general direction of the last point as we wind around
354-//
355-// This normally wouldn't work in every case, but our upscaled-by-1000 polygons
356-// have little chance to create new duplicate points with this method.
357-//
358-// For information on why this was needed, see:
359-//
360-// https://github.com/greenm01/poly2tri/issues/90
361-//
362-
363-#define S_INC 1
364-
365-void EdgeShrink( std::vector<SFVEC2I64> &aPath )
366-{
367- unsigned int prev = aPath.size() - 1;
368-
369- for( unsigned int i = 0; i < aPath.size(); i++ )
370- {
371- // Adjust coordinate by 1 depending on the direction
372- (aPath[i].x - aPath[prev].x) > 0 ? aPath[i].x -= S_INC :
373- aPath[i].x += S_INC;
374-
375- (aPath[i].y - aPath[prev].y) > 0 ? aPath[i].y -= S_INC :
376- aPath[i].y += S_INC;
377-
378- prev = i;
379- }
380-}
381diff --git a/3d-viewer/CMakeLists.txt b/3d-viewer/CMakeLists.txt
382index 76ce150..6cea78a 100644
383--- a/3d-viewer/CMakeLists.txt
384+++ b/3d-viewer/CMakeLists.txt
385@@ -37,11 +37,6 @@ set(3D-VIEWER_SRCS
386 ${DIR_DLG}/dlg_select_3dmodel.cpp
387 ${DIR_DLG}/panel_prev_3d_base.cpp
388 ${DIR_DLG}/panel_prev_model.cpp
389- ../polygon/poly2tri/common/shapes.cc
390- ../polygon/poly2tri/sweep/advancing_front.cc
391- ../polygon/poly2tri/sweep/cdt.cc
392- ../polygon/poly2tri/sweep/sweep.cc
393- ../polygon/poly2tri/sweep/sweep_context.cc
394 3d_canvas/cinfo3d_visu.cpp
395 3d_canvas/create_layer_items.cpp
396 3d_canvas/create_3Dgraphic_brd_items.cpp
397@@ -76,7 +71,6 @@ set(3D-VIEWER_SRCS
398 ${DIR_RAY_2D}/cring2d.cpp
399 ${DIR_RAY_2D}/croundsegment2d.cpp
400 ${DIR_RAY_2D}/ctriangle2d.cpp
401- ${DIR_RAY_2D}/edgeshrink.cpp
402 ${DIR_RAY_3D}/cbbox.cpp
403 ${DIR_RAY_3D}/cbbox_ray.cpp
404 ${DIR_RAY_3D}/ccylinder.cpp
405diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp
406index 291b3a4..41de80c 100644
407--- a/common/gal/opengl/opengl_gal.cpp
408+++ b/common/gal/opengl/opengl_gal.cpp
409@@ -907,10 +907,10 @@ void OPENGL_GAL::drawTriangulatedPolyset( const SHAPE_POLY_SET& aPolySet )
410 {
411 auto triPoly = aPolySet.TriangulatedPolygon( j );
412
413- for( int i = 0; i < triPoly->GetTriangleCount(); i++ )
414+ for( size_t i = 0; i < triPoly->GetTriangleCount(); i++ )
415 {
416 VECTOR2I a, b, c;
417- triPoly->GetTriangle( i ,a,b,c);
418+ triPoly->GetTriangle( i, a, b, c );
419 currentManager->Vertex( a.x, a.y, layerDepth );
420 currentManager->Vertex( b.x, b.y, layerDepth );
421 currentManager->Vertex( c.x, c.y, layerDepth );
422diff --git a/common/geometry/shape_poly_set.cpp b/common/geometry/shape_poly_set.cpp
423index 9cba55d..637c93e 100644
424--- a/common/geometry/shape_poly_set.cpp
425+++ b/common/geometry/shape_poly_set.cpp
426@@ -42,8 +42,7 @@
427 #include <geometry/shape.h>
428 #include <geometry/shape_line_chain.h>
429 #include <geometry/shape_poly_set.h>
430-
431-#include "poly2tri/poly2tri.h"
432+#include <geometry/polygon_triangulation.h>
433
434 using namespace ClipperLib;
435
436@@ -1862,164 +1861,6 @@ SHAPE_POLY_SET &SHAPE_POLY_SET::operator=( const SHAPE_POLY_SET& aOther )
437 return *this;
438 }
439
440-
441-class SHAPE_POLY_SET::TRIANGULATION_CONTEXT
442-{
443-public:
444-
445- TRIANGULATION_CONTEXT( TRIANGULATED_POLYGON* aResultPoly ) :
446- m_triPoly( aResultPoly )
447- {
448- }
449-
450- void AddOutline( const SHAPE_LINE_CHAIN& outl, bool aIsHole = false )
451- {
452- m_points.reserve( outl.PointCount() );
453- m_points.clear();
454-
455- for( int i = 0; i < outl.PointCount(); i++ )
456- {
457- m_points.push_back( addPoint( outl.CPoint( i ) ) );
458- }
459-
460- if ( aIsHole )
461- m_cdt->AddHole( m_points );
462- else
463- m_cdt.reset( new p2t::CDT( m_points ) );
464- }
465-
466- void Triangulate()
467- {
468- m_cdt->Triangulate();
469-
470- m_triPoly->AllocateTriangles( m_cdt->GetTriangles().size() );
471-
472- int i = 0;
473-
474- for( auto tri : m_cdt->GetTriangles() )
475- {
476- TRIANGULATED_POLYGON::TRI t;
477-
478- t.a = tri->GetPoint( 0 )->id;
479- t.b = tri->GetPoint( 1 )->id;
480- t.c = tri->GetPoint( 2 )->id;
481-
482- m_triPoly->SetTriangle(i, t);
483- i++;
484- }
485-
486- for( auto p : m_uniquePoints )
487- delete p;
488- }
489-
490-private:
491-
492- class comparePoints
493- {
494- public:
495- bool operator()( p2t::Point* a, p2t::Point* b ) const
496- {
497- if (a->x < b->x)
498- return true;
499-
500- if( a->x == b->x )
501- return ( a->y > b->y );
502-
503- return false;
504- }
505- };
506-
507-
508- p2t::Point* addPoint( const VECTOR2I& aP )
509- {
510- p2t::Point check( aP.x, aP.y );
511- auto it = m_uniquePoints.find( &check );
512-
513- if( it != m_uniquePoints.end() )
514- {
515- return *it;
516- }
517- else
518- {
519- auto lastId = m_triPoly->GetVertexCount();
520- auto p = new p2t::Point( aP.x, aP.y, lastId );
521- m_triPoly->AddVertex( aP );
522- m_uniquePoints.insert ( p );
523- return p;
524- }
525- }
526-
527- typedef std::set<p2t::Point*, comparePoints> P2T_SET;
528- typedef std::vector<p2t::Point*> P2T_VEC;
529-
530- P2T_VEC m_points;
531- P2T_SET m_uniquePoints;
532- TRIANGULATED_POLYGON *m_triPoly;
533- std::unique_ptr<p2t::CDT> m_cdt;
534-};
535-
536-SHAPE_POLY_SET::TRIANGULATED_POLYGON::~TRIANGULATED_POLYGON()
537-{
538- Clear();
539-}
540-
541-
542-void SHAPE_POLY_SET::TRIANGULATED_POLYGON::Clear()
543-{
544- if( m_vertices )
545- delete[] m_vertices;
546-
547- if( m_triangles )
548- delete[] m_triangles;
549-}
550-
551-
552-void SHAPE_POLY_SET::TRIANGULATED_POLYGON::AllocateVertices( int aSize )
553-{
554- m_vertices = new VECTOR2I[aSize];
555-}
556-
557-
558-void SHAPE_POLY_SET::TRIANGULATED_POLYGON::AllocateTriangles( int aSize )
559-{
560- m_triangles = new TRI[aSize];
561- m_triangleCount = aSize;
562-}
563-
564-
565-static int totalVertexCount( const SHAPE_POLY_SET::POLYGON& aPoly )
566-{
567- int cnt = 0;
568-
569- for( const auto& outl : aPoly )
570- {
571- cnt += outl.PointCount();
572- }
573-
574- return cnt;
575-}
576-
577-
578-void SHAPE_POLY_SET::triangulateSingle( const POLYGON& aPoly,
579- SHAPE_POLY_SET::TRIANGULATED_POLYGON& aResult )
580-{
581- if( aPoly.size() == 0 )
582- return;
583-
584- TRIANGULATION_CONTEXT ctx ( &aResult );
585-
586- aResult.AllocateVertices( totalVertexCount( aPoly ) );
587- ctx.AddOutline( aPoly[0], false );
588-
589- for( unsigned i = 1; i < aPoly.size(); i++ )
590- {
591- ctx.AddOutline( aPoly[i], true ); // add holes
592- }
593-
594- ctx.Triangulate();
595-}
596-
597-
598 MD5_HASH SHAPE_POLY_SET::GetHash() const
599 {
600 if( !m_hash.IsValid() )
601@@ -2067,22 +1908,17 @@ void SHAPE_POLY_SET::CacheTriangulation()
602
603 SHAPE_POLY_SET tmpSet = *this;
604
605- if( !tmpSet.HasHoles() )
606- tmpSet.Unfracture( PM_FAST );
607+ if( tmpSet.HasHoles() )
608+ tmpSet.Fracture( PM_FAST );
609
610 m_triangulatedPolys.clear();
611
612- if( tmpSet.HasTouchingHoles() )
613- {
614- // temporary workaround for overlapping hole vertices that poly2tri doesn't handle
615- m_triangulationValid = false;
616- return;
617- }
618-
619 for( int i = 0; i < tmpSet.OutlineCount(); i++ )
620 {
621 m_triangulatedPolys.push_back( std::make_unique<TRIANGULATED_POLYGON>() );
622- triangulateSingle( tmpSet.Polygon( i ), *m_triangulatedPolys.back() );
623+ PolygonTriangulation tess( *m_triangulatedPolys.back() );
624+
625+ tess.TesselatePolygon( tmpSet.Polygon( i ).front() );
626 }
627
628 m_triangulationValid = true;
629diff --git a/include/geometry/polygon_triangulation.h b/include/geometry/polygon_triangulation.h
630new file mode 100644
631index 0000000..58f3fc5
632--- /dev/null
633+++ b/include/geometry/polygon_triangulation.h
634@@ -0,0 +1,608 @@
635+/*
636+ * This program source code file is part of KiCad, a free EDA CAD application.
637+ *
638+ * Modifications Copyright (C) 2018 KiCad Developers
639+ *
640+ * This program is free software; you can redistribute it and/or
641+ * modify it under the terms of the GNU General Public License
642+ * as published by the Free Software Foundation; either version 2
643+ * of the License, or (at your option) any later version.
644+ *
645+ * This program is distributed in the hope that it will be useful,
646+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
647+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
648+ * GNU General Public License for more details.
649+ *
650+ * You should have received a copy of the GNU General Public License
651+ * along with this program; if not, you may find one here:
652+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
653+ * or you may search the http://www.gnu.org website for the version 2 license,
654+ * or you may write to the Free Software Foundation, Inc.,
655+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
656+ *
657+ * Based on Uniform Plane Subdivision algorithm from Lamot, Marko, and Borut Žalik.
658+ * "A fast polygon triangulation algorithm based on uniform plane subdivision."
659+ * Computers & graphics 27, no. 2 (2003): 239-253.
660+ *
661+ * Code derived from:
662+ * K-3D which is Copyright (c) 2005-2006, Romain Behar, GPL-2, license above
663+ * earcut which is Copyright (c) 2016, Mapbox, ISC
664+ *
665+ * ISC License:
666+ * Permission to use, copy, modify, and/or distribute this software for any purpose
667+ * with or without fee is hereby granted, provided that the above copyright notice
668+ * and this permission notice appear in all copies.
669+ *
670+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
671+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
672+ * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
673+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
674+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
675+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
676+ * THIS SOFTWARE.
677+ *
678+ */
679+
680+#ifndef __POLYGON_TRIANGULATION_H
681+#define __POLYGON_TRIANGULATION_H
682+
683+#include <algorithm>
684+#include <cmath>
685+#include <vector>
686+#include <math/box2.h>
687+
688+class PolygonTriangulation
689+{
690+
691+public:
692+
693+ PolygonTriangulation( SHAPE_POLY_SET::TRIANGULATED_POLYGON& aResult ) :
694+ m_result( aResult )
695+ {};
696+
697+private:
698+ struct Vertex
699+ {
700+ Vertex( size_t aIndex, double aX, double aY, PolygonTriangulation* aParent ) :
701+ i( aIndex ), x( aX ), y( aY ), parent( aParent )
702+ {
703+ }
704+ Vertex& operator=( const Vertex& ) = delete;
705+ Vertex& operator=( Vertex&& ) = delete;
706+
707+ bool operator==( const Vertex& rhs ) const
708+ {
709+ return this->x == rhs.x && this->y == rhs.y;
710+ }
711+ bool operator!=( const Vertex& rhs ) const { return !( *this == rhs ); }
712+
713+
714+ /**
715+ * Function split
716+ * Splits the referenced polygon between the reference point and
717+ * vertex b, assuming they are in the same polygon. Notes that while we
718+ * create a new vertex pointer for the linked list, we maintain the same
719+ * vertex index value from the original polygon. In this way, we have
720+ * two polygons that both share the same vertices.
721+ *
722+ * Returns the pointer to the newly created vertex in the polygon that
723+ * does not include the reference vertex.
724+ */
725+ Vertex* split( Vertex* b )
726+ {
727+ parent->m_vertices.emplace_back( i, x, y, parent );
728+ Vertex* a2 = &parent->m_vertices.back();
729+ parent->m_vertices.emplace_back( b->i, b->x, b->y, parent );
730+ Vertex* b2 = &parent->m_vertices.back();
731+ Vertex* an = next;
732+ Vertex* bp = b->prev;
733+
734+ next = b;
735+ b->prev = this;
736+
737+ a2->next = an;
738+ an->prev = a2;
739+
740+ b2->next = a2;
741+ a2->prev = b2;
742+
743+ bp->next = b2;
744+ b2->prev = bp;
745+
746+ return b2;
747+ }
748+
749+ /**
750+ * Function remove
751+ * Removes the node from the linked list and z-ordered linked list.
752+ */
753+ void remove()
754+ {
755+ next->prev = prev;
756+ prev->next = next;
757+
758+ if( prevZ )
759+ prevZ->nextZ = nextZ;
760+ if( nextZ )
761+ nextZ->prevZ = prevZ;
762+ next = NULL;
763+ prev = NULL;
764+ nextZ = NULL;
765+ prevZ = NULL;
766+ }
767+
768+
769+ void updateOrder()
770+ {
771+ if( !z )
772+ z = parent->zOrder( x, y );
773+ }
774+
775+ /**
776+ * Function updateList
777+ * After inserting or changing nodes, this function should be called to
778+ * remove duplicate vertices and ensure z-ordering is correct
779+ */
780+ void updateList()
781+ {
782+ Vertex* p = next;
783+
784+ while( p != this )
785+ {
786+ /**
787+ * Remove duplicates
788+ */
789+ if( *p == *p->next )
790+ {
791+ p = p->prev;
792+ p->next->remove();
793+
794+ if( p == p->next )
795+ break;
796+ }
797+
798+ p->updateOrder();
799+ p = p->next;
800+ };
801+
802+ updateOrder();
803+ zSort();
804+ }
805+
806+ /**
807+ * Sort all vertices in this vertex's list by their Morton code
808+ */
809+ void zSort()
810+ {
811+ std::deque<Vertex*> queue;
812+
813+ queue.push_back( this );
814+
815+ for( auto p = next; p && p != this; p = p->next )
816+ queue.push_back( p );
817+
818+ std::sort( queue.begin(), queue.end(), []( const Vertex* a, const Vertex* b)
819+ {
820+ return a->z < b->z;
821+ } );
822+
823+ Vertex* prev_elem = nullptr;
824+ for( auto elem : queue )
825+ {
826+ if( prev_elem )
827+ prev_elem->nextZ = elem;
828+
829+ elem->prevZ = prev_elem;
830+ prev_elem = elem;
831+ }
832+
833+ prev_elem->nextZ = nullptr;
834+ }
835+
836+
837+ /**
838+ * Check to see if triangle surrounds our current vertex
839+ */
840+ bool inTriangle( const Vertex& a, const Vertex& b, const Vertex& c )
841+ {
842+ return ( c.x - x ) * ( a.y - y ) - ( a.x - x ) * ( c.y - y ) >= 0
843+ && ( a.x - x ) * ( b.y - y ) - ( b.x - x ) * ( a.y - y ) >= 0
844+ && ( b.x - x ) * ( c.y - y ) - ( c.x - x ) * ( b.y - y ) >= 0;
845+ }
846+
847+ const size_t i;
848+ const double x;
849+ const double y;
850+ PolygonTriangulation* parent;
851+
852+ // previous and next vertices nodes in a polygon ring
853+ Vertex* prev = nullptr;
854+ Vertex* next = nullptr;
855+
856+ // z-order curve value
857+ int32_t z = 0;
858+
859+ // previous and next nodes in z-order
860+ Vertex* prevZ = nullptr;
861+ Vertex* nextZ = nullptr;
862+ };
863+
864+ BOX2I m_bbox;
865+ std::deque<Vertex> m_vertices;
866+ SHAPE_POLY_SET::TRIANGULATED_POLYGON& m_result;
867+
868+ /**
869+ * Calculate the Morton code of the Vertex
870+ * http://www.graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN
871+ *
872+ */
873+ int32_t zOrder( const double aX, const double aY ) const
874+ {
875+ int32_t x = static_cast<int32_t>( 32767.0 * ( aX - m_bbox.GetX() ) / m_bbox.GetWidth() );
876+ int32_t y = static_cast<int32_t>( 32767.0 * ( aY - m_bbox.GetY() ) / m_bbox.GetHeight() );
877+
878+ x = ( x | ( x << 8 ) ) & 0x00FF00FF;
879+ x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
880+ x = ( x | ( x << 2 ) ) & 0x33333333;
881+ x = ( x | ( x << 1 ) ) & 0x55555555;
882+
883+ y = ( y | ( y << 8 ) ) & 0x00FF00FF;
884+ y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
885+ y = ( y | ( y << 2 ) ) & 0x33333333;
886+ y = ( y | ( y << 1 ) ) & 0x55555555;
887+
888+ return x | ( y << 1 );
889+ }
890+
891+ /**
892+ * Function removeNullTriangles
893+ * Iterates through the list to remove NULL triangles if they exist.
894+ * This should only be called as a last resort when tesselation fails
895+ * as the NULL triangles are inserted as Steiner points to improve the
896+ * triangulation regularity of polygons
897+ */
898+ bool removeNullTriangles( Vertex* aStart )
899+ {
900+ bool retval = false;
901+ Vertex* p = aStart->next;
902+
903+ while( p != aStart )
904+ {
905+ if( area( p->prev, p, p->next ) == 0.0 )
906+ {
907+ p = p->prev;
908+ p->next->remove();
909+ retval = true;
910+
911+ if( p == p->next )
912+ break;
913+ }
914+ p = p->next;
915+ };
916+
917+ // We needed an end point above that wouldn't be removed, so
918+ // here we do the final check for this as a Steiner point
919+ if( area( aStart->prev, aStart, aStart->next ) == 0.0 )
920+ {
921+ p->remove();
922+ retval = true;
923+ }
924+
925+ return retval;
926+ }
927+
928+ /**
929+ * Function createList
930+ * Takes the SHAPE_LINE_CHAIN and links each point into a
931+ * circular, doubly-linked list
932+ */
933+ Vertex* createList( const SHAPE_LINE_CHAIN& points )
934+ {
935+ Vertex* tail = nullptr;
936+
937+ for( int i = 0; i < points.PointCount(); i++ )
938+ tail = insertVertex( points.CPoint( i ), tail );
939+
940+ if( tail && ( *tail == *tail->next ) )
941+ {
942+ tail->next->remove();
943+ }
944+
945+ return tail;
946+ }
947+
948+ /**
949+ * Function: earcutList
950+ * Walks through a circular linked list starting at aPoint. For each point,
951+ * test to see if the adjacent points form a triangle that is completely enclosed
952+ * by the remaining polygon (an "ear" sticking off the polygon). If the three points
953+ * form an ear, we log the ear's location and remove the center point from the linked list.
954+ *
955+ * This function can be called recursively in the case of difficult polygons. In cases where
956+ * there is an intersection (not technically allowed by KiCad, but could exist in an edited file),
957+ * we create a single triangle and remove both vertices before attempting to
958+ */
959+ void earcutList( Vertex* aPoint, int pass = 0 )
960+ {
961+ if( !aPoint )
962+ return;
963+
964+ Vertex* stop = aPoint;
965+ Vertex* prev;
966+ Vertex* next;
967+
968+ while( aPoint->prev != aPoint->next )
969+ {
970+ prev = aPoint->prev;
971+ next = aPoint->next;
972+
973+ if( isEar( aPoint ) )
974+ {
975+ m_result.AddTriangle( prev->i, aPoint->i, next->i );
976+ aPoint->remove();
977+
978+ // Skip one vertex as the triangle will account for the prev node
979+ aPoint = next->next;
980+ stop = next->next;
981+
982+ continue;
983+ }
984+
985+ Vertex* nextNext = next->next;
986+
987+ if( *prev != *nextNext && intersects( prev, aPoint, next, nextNext ) &&
988+ locallyInside( prev, nextNext ) &&
989+ locallyInside( nextNext, prev ) )
990+ {
991+ m_result.AddTriangle( prev->i, aPoint->i, nextNext->i );
992+
993+ // remove two nodes involved
994+ next->remove();
995+ aPoint->remove();
996+
997+ aPoint = nextNext;
998+
999+ continue;
1000+ }
1001+
1002+ aPoint = next;
1003+
1004+ /**
1005+ * We've searched the entire polygon for available ears and there are still un-sliced nodes
1006+ * remaining
1007+ */
1008+ if( aPoint == stop )
1009+ {
1010+ // First, try to remove the remaining steiner points
1011+ if( removeNullTriangles( aPoint ) )
1012+ continue;
1013+
1014+ // If we don't have any NULL triangles left, cut the polygon in two and try again
1015+ splitPolygon( aPoint );
1016+ break;
1017+ }
1018+ }
1019+
1020+ /**
1021+ * At this point, our polygon should be fully tesselated.
1022+ */
1023+ assert( aPoint->prev == aPoint->next );
1024+ }
1025+
1026+ /**
1027+ * Function isEar
1028+ * Checks whether the given vertex is in the middle of an ear.
1029+ * This works by walking forward and backward in zOrder to the limits
1030+ * of the minimal bounding box formed around the triangle, checking whether
1031+ * any points are located inside the given triangle.
1032+ *
1033+ * Returns true if aEar is the apex point of a ear in the polygon
1034+ */
1035+ bool isEar( Vertex* aEar ) const
1036+ {
1037+ const Vertex* a = aEar->prev;
1038+ const Vertex* b = aEar;
1039+ const Vertex* c = aEar->next;
1040+
1041+ // If the area >=0, then the three points for a concave sequence
1042+ // with b as the reflex point
1043+ if( area( a, b, c ) >= 0 )
1044+ return false;
1045+
1046+ // triangle bbox
1047+ const double minTX = std::min( a->x, std::min( b->x, c->x ) );
1048+ const double minTY = std::min( a->y, std::min( b->y, c->y ) );
1049+ const double maxTX = std::max( a->x, std::max( b->x, c->x ) );
1050+ const double maxTY = std::max( a->y, std::max( b->y, c->y ) );
1051+
1052+ // z-order range for the current triangle bounding box
1053+ const int32_t minZ = zOrder( minTX, minTY );
1054+ const int32_t maxZ = zOrder( maxTX, maxTY );
1055+
1056+ // first look for points inside the triangle in increasing z-order
1057+ Vertex* p = aEar->nextZ;
1058+
1059+ while( p && p->z <= maxZ )
1060+ {
1061+ if( p != a && p != c
1062+ && p->inTriangle( *a, *b, *c )
1063+ && area( p->prev, p, p->next ) >= 0 )
1064+ return false;
1065+ p = p->nextZ;
1066+ }
1067+
1068+ // then look for points in decreasing z-order
1069+ p = aEar->prevZ;
1070+
1071+ while( p && p->z >= minZ )
1072+ {
1073+ if( p != a && p != c
1074+ && p->inTriangle( *a, *b, *c )
1075+ && area( p->prev, p, p->next ) >= 0 )
1076+ return false;
1077+ p = p->prevZ;
1078+ }
1079+
1080+ return true;
1081+ }
1082+
1083+ /**
1084+ * Function splitPolygon
1085+ * If we cannot find an ear to slice in the current polygon list, we
1086+ * use this to split the polygon into two separate lists and slice them each
1087+ * independently. This is assured to generate at least one new ear if the
1088+ * split is successful
1089+ */
1090+ void splitPolygon( Vertex* start )
1091+ {
1092+ Vertex* origPoly = start;
1093+ do
1094+ {
1095+ Vertex* marker = origPoly->next->next;
1096+ while( marker != origPoly->prev )
1097+ {
1098+ // Find a diagonal line that is wholly enclosed by the polygon interior
1099+ if( origPoly->i != marker->i && goodSplit( origPoly, marker ) )
1100+ {
1101+ Vertex* newPoly = origPoly->split( marker );
1102+
1103+ origPoly->updateList();
1104+ newPoly->updateList();
1105+
1106+ earcutList( origPoly );
1107+ earcutList( newPoly );
1108+ return;
1109+ }
1110+ marker = marker->next;
1111+ }
1112+ origPoly = origPoly->next;
1113+ } while( origPoly != start );
1114+ }
1115+
1116+ /**
1117+ * Check if a segment joining two vertices lies fully inside the polygon.
1118+ * To do this, we first ensure that the line isn't along the polygon edge.
1119+ * Next, we know that if the line doesn't intersect the polygon, then it is
1120+ * either fully inside or fully outside the polygon. Finally, by checking whether
1121+ * the segment is enclosed by the local triangles, we distinguish between
1122+ * these two cases and no further checks are needed.
1123+ */
1124+ bool goodSplit( const Vertex* a, const Vertex* b ) const
1125+ {
1126+ return a->next->i != b->i &&
1127+ a->prev->i != b->i &&
1128+ !intersectsPolygon( a, b ) &&
1129+ locallyInside( a, b );
1130+ }
1131+
1132+ /**
1133+ * Function area
1134+ * Returns the twice the signed area of the triangle formed by vertices
1135+ * p, q, r.
1136+ */
1137+ double area( const Vertex* p, const Vertex* q, const Vertex* r ) const
1138+ {
1139+ return ( q->y - p->y ) * ( r->x - q->x ) - ( q->x - p->x ) * ( r->y - q->y );
1140+ }
1141+
1142+ /**
1143+ * Function intersects
1144+ * Checks for intersection between two segments, end points included.
1145+ * Returns true if p1-p2 intersects q1-q2
1146+ */
1147+ bool intersects( const Vertex* p1, const Vertex* q1, const Vertex* p2, const Vertex* q2 ) const
1148+ {
1149+ if( ( *p1 == *q1 && *p2 == *q2 ) || ( *p1 == *q2 && *p2 == *q1 ) )
1150+ return true;
1151+
1152+ return ( area( p1, q1, p2 ) > 0 ) != ( area( p1, q1, q2 ) > 0 )
1153+ && ( area( p2, q2, p1 ) > 0 ) != ( area( p2, q2, q1 ) > 0 );
1154+ }
1155+
1156+ /**
1157+ * Function intersectsPolygon
1158+ * Checks whether the segment from vertex a -> vertex b crosses any of the segments
1159+ * of the polygon of which vertex a is a member.
1160+ * Return true if the segment intersects the edge of the polygon
1161+ */
1162+ bool intersectsPolygon( const Vertex* a, const Vertex* b ) const
1163+ {
1164+ const Vertex* p = a->next;
1165+ do
1166+ {
1167+ if( p->i != a->i &&
1168+ p->next->i != a->i &&
1169+ p->i != b->i &&
1170+ p->next->i != b->i && intersects( p, p->next, a, b ) )
1171+ return true;
1172+
1173+ p = p->next;
1174+ } while( p != a );
1175+
1176+ return false;
1177+ }
1178+
1179+ /**
1180+ * Function locallyInside
1181+ * Checks whether the segment from vertex a -> vertex b is inside the polygon
1182+ * around the immediate area of vertex a. We don't define the exact area
1183+ * over which the segment is inside but it is guaranteed to be inside the polygon
1184+ * immediately adjacent to vertex a.
1185+ * Returns true if the segment from a->b is inside a's polygon next to vertex a
1186+ */
1187+ bool locallyInside( const Vertex* a, const Vertex* b ) const
1188+ {
1189+ if( area( a->prev, a, a->next ) < 0 )
1190+ return area( a, b, a->next ) >= 0 && area( a, a->prev, b ) >= 0;
1191+ else
1192+ return area( a, b, a->prev ) < 0 || area( a, a->next, b ) < 0;
1193+ }
1194+
1195+ /**
1196+ * Function insertVertex
1197+ * Creates an entry in the vertices lookup and optionally inserts the newly
1198+ * created vertex into an existing linked list.
1199+ * Returns a pointer to the newly created vertex
1200+ */
1201+ Vertex* insertVertex( const VECTOR2I& pt, Vertex* last )
1202+ {
1203+ m_result.AddVertex( pt );
1204+ m_vertices.emplace_back( m_result.GetVertexCount() - 1, pt.x, pt.y, this );
1205+
1206+ Vertex* p = &m_vertices.back();
1207+ if( !last )
1208+ {
1209+ p->prev = p;
1210+ p->next = p;
1211+ }
1212+ else
1213+ {
1214+ p->next = last->next;
1215+ p->prev = last;
1216+ last->next->prev = p;
1217+ last->next = p;
1218+ }
1219+ return p;
1220+ }
1221+
1222+public:
1223+
1224+ void TesselatePolygon( const SHAPE_LINE_CHAIN& aPoly )
1225+ {
1226+ m_bbox = aPoly.BBox();
1227+
1228+ if( !m_bbox.GetWidth() || !m_bbox.GetHeight() )
1229+ return;
1230+
1231+ Vertex* outerNode = createList( aPoly );
1232+ if( !outerNode )
1233+ return;
1234+
1235+ outerNode->updateList();
1236+ earcutList( outerNode );
1237+
1238+ m_vertices.clear();
1239+ }
1240+};
1241+
1242+#endif //__POLYGON_TRIANGULATION_H
1243diff --git a/include/geometry/shape_poly_set.h b/include/geometry/shape_poly_set.h
1244index 8714c5d..2d29e00 100644
1245--- a/include/geometry/shape_poly_set.h
1246+++ b/include/geometry/shape_poly_set.h
1247@@ -58,64 +58,60 @@ class SHAPE_POLY_SET : public SHAPE
1248 public:
1249 ///> represents a single polygon outline with holes. The first entry is the outline,
1250 ///> the remaining (if any), are the holes
1251+ ///> N.B. SWIG only supports typedef, so avoid c++ 'using' keyword
1252 typedef std::vector<SHAPE_LINE_CHAIN> POLYGON;
1253
1254- class TRIANGULATION_CONTEXT;
1255-
1256 class TRIANGULATED_POLYGON
1257 {
1258 public:
1259 struct TRI
1260 {
1261- TRI() : a(0), b(0), c(0)
1262+ TRI( int _a = 0, int _b = 0, int _c = 0 ) : a( _a ), b( _b ), c( _c )
1263 {
1264 }
1265
1266 int a, b, c;
1267 };
1268
1269- ~TRIANGULATED_POLYGON();
1270-
1271 void Clear();
1272
1273- void AllocateVertices( int aSize );
1274- void AllocateTriangles ( int aSize );
1275-
1276 void GetTriangle( int index, VECTOR2I& a, VECTOR2I& b, VECTOR2I& c ) const
1277 {
1278- auto tri = &m_triangles[ index ];
1279- a = m_vertices[ tri->a ];
1280- b = m_vertices[ tri->b ];
1281- c = m_vertices[ tri->c ];
1282+ auto tri = m_triangles[ index ];
1283+ a = m_vertices[ tri.a ];
1284+ b = m_vertices[ tri.b ];
1285+ c = m_vertices[ tri.c ];
1286+ }
1287+
1288+ void AddTriangle( const TRI& aTri )
1289+ {
1290+ m_triangles.push_back( aTri );
1291 }
1292
1293- void SetTriangle( int aIndex, const TRI& aTri )
1294+ void AddTriangle( int a, int b, int c )
1295 {
1296- m_triangles[aIndex] = aTri;
1297+ m_triangles.emplace_back( a, b, c );
1298 }
1299
1300- int AddVertex( const VECTOR2I& aP )
1301+ void AddVertex( const VECTOR2I& aP )
1302 {
1303- m_vertices[ m_vertexCount ] = aP;
1304- return (m_vertexCount++);
1305+ m_vertices.push_back( aP );
1306 }
1307
1308- int GetTriangleCount() const
1309+ size_t GetTriangleCount() const
1310 {
1311- return m_triangleCount;
1312+ return m_triangles.size();
1313 }
1314
1315- int GetVertexCount() const
1316+ size_t GetVertexCount() const
1317 {
1318- return m_vertexCount;
1319+ return m_vertices.size();
1320 }
1321
1322 private:
1323
1324- TRI* m_triangles = nullptr;
1325- VECTOR2I* m_vertices = nullptr;
1326- int m_vertexCount = 0;
1327- int m_triangleCount = 0;
1328+ std::deque<TRI> m_triangles;
1329+ std::deque<VECTOR2I> m_vertices;
1330 };
1331
1332 /**
1333@@ -1184,7 +1180,6 @@ class SHAPE_POLY_SET : public SHAPE
1334 MD5_HASH GetHash() const;
1335
1336 private:
1337- void triangulateSingle( const POLYGON& aPoly, SHAPE_POLY_SET::TRIANGULATED_POLYGON& aResult );
1338
1339 MD5_HASH checksum() const;
1340
1341diff --git a/polygon/CMakeLists.txt b/polygon/CMakeLists.txt
1342index 6205d07..cd5959e 100644
1343--- a/polygon/CMakeLists.txt
1344+++ b/polygon/CMakeLists.txt
1345@@ -13,11 +13,6 @@ set(POLYGON_SRCS
1346 PolyLine.cpp
1347 polygon_test_point_inside.cpp
1348 clipper.cpp
1349- ./poly2tri/sweep/sweep.cc
1350- ./poly2tri/sweep/sweep_context.cc
1351- ./poly2tri/sweep/cdt.cc
1352- ./poly2tri/sweep/advancing_front.cc
1353- ./poly2tri/common/shapes.cc
1354 )
1355
1356 add_library(polygon STATIC ${POLYGON_SRCS})
1357diff --git a/polygon/poly2tri/common/shapes.cc b/polygon/poly2tri/common/shapes.cc
1358deleted file mode 100644
1359index 5ad7fab..0000000
1360--- a/polygon/poly2tri/common/shapes.cc
1361+++ /dev/null
1362@@ -1,375 +0,0 @@
1363-/*
1364- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
1365- * http://code.google.com/p/poly2tri/
1366- *
1367- * All rights reserved.
1368- *
1369- * Redistribution and use in source and binary forms, with or without modification,
1370- * are permitted provided that the following conditions are met:
1371- *
1372- * * Redistributions of source code must retain the above copyright notice,
1373- * this list of conditions and the following disclaimer.
1374- * * Redistributions in binary form must reproduce the above copyright notice,
1375- * this list of conditions and the following disclaimer in the documentation
1376- * and/or other materials provided with the distribution.
1377- * * Neither the name of Poly2Tri nor the names of its contributors may be
1378- * used to endorse or promote products derived from this software without specific
1379- * prior written permission.
1380- *
1381- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1382- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1383- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1384- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
1385- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1386- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1387- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1388- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1389- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1390- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1391- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1392- */
1393-#include "shapes.h"
1394-#include <iostream>
1395-#include <stdexcept>
1396-
1397-namespace p2t {
1398-
1399-Triangle::Triangle(Point& a, Point& b, Point& c)
1400-{
1401- points_[0] = &a; points_[1] = &b; points_[2] = &c;
1402- neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL;
1403- constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false;
1404- delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
1405- interior_ = false;
1406-}
1407-
1408-// Update neighbor pointers
1409-void Triangle::MarkNeighbor(Point* p1, Point* p2, Triangle* t)
1410-{
1411- if ((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2]))
1412- neighbors_[0] = t;
1413- else if ((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0]))
1414- neighbors_[1] = t;
1415- else if ((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0]))
1416- neighbors_[2] = t;
1417- else
1418- throw std::runtime_error("Polygon contains overlapping hole vertices.");
1419-}
1420-
1421-// Exhaustive search to update neighbor pointers
1422-void Triangle::MarkNeighbor(Triangle& t)
1423-{
1424- if (t.Contains(points_[1], points_[2])) {
1425- neighbors_[0] = &t;
1426- t.MarkNeighbor(points_[1], points_[2], this);
1427- } else if (t.Contains(points_[0], points_[2])) {
1428- neighbors_[1] = &t;
1429- t.MarkNeighbor(points_[0], points_[2], this);
1430- } else if (t.Contains(points_[0], points_[1])) {
1431- neighbors_[2] = &t;
1432- t.MarkNeighbor(points_[0], points_[1], this);
1433- }
1434-}
1435-
1436-/**
1437- * Clears all references to all other triangles and points
1438- */
1439-void Triangle::Clear()
1440-{
1441- Triangle *t;
1442- for( int i=0; i<3; i++ )
1443- {
1444- t = neighbors_[i];
1445- if( t != NULL )
1446- {
1447- t->ClearNeighbor( this );
1448- }
1449- }
1450- ClearNeighbors();
1451- points_[0]=points_[1]=points_[2] = NULL;
1452-}
1453-
1454-void Triangle::ClearNeighbor(Triangle *triangle )
1455-{
1456- if( neighbors_[0] == triangle )
1457- {
1458- neighbors_[0] = NULL;
1459- }
1460- else if( neighbors_[1] == triangle )
1461- {
1462- neighbors_[1] = NULL;
1463- }
1464- else
1465- {
1466- neighbors_[2] = NULL;
1467- }
1468-}
1469-
1470-void Triangle::ClearNeighbors()
1471-{
1472- neighbors_[0] = NULL;
1473- neighbors_[1] = NULL;
1474- neighbors_[2] = NULL;
1475-}
1476-
1477-void Triangle::ClearDelunayEdges()
1478-{
1479- delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
1480-}
1481-
1482-Point* Triangle::OppositePoint(Triangle& t, Point& p)
1483-{
1484- Point* cw = t.PointCW( p );
1485-
1486- /*
1487- double x = cw->x;
1488- double y = cw->y;
1489-
1490- x = p.x;
1491- y = p.y;
1492- */
1493-
1494- return PointCW( *cw );
1495-}
1496-
1497-// Legalized triangle by rotating clockwise around point(0)
1498-void Triangle::Legalize(Point& point)
1499-{
1500- points_[1] = points_[0];
1501- points_[0] = points_[2];
1502- points_[2] = &point;
1503-}
1504-
1505-// Legalize triagnle by rotating clockwise around oPoint
1506-void Triangle::Legalize(Point& opoint, Point& npoint)
1507-{
1508- if (&opoint == points_[0]) {
1509- points_[1] = points_[0];
1510- points_[0] = points_[2];
1511- points_[2] = &npoint;
1512- } else if (&opoint == points_[1]) {
1513- points_[2] = points_[1];
1514- points_[1] = points_[0];
1515- points_[0] = &npoint;
1516- } else if (&opoint == points_[2]) {
1517- points_[0] = points_[2];
1518- points_[2] = points_[1];
1519- points_[1] = &npoint;
1520- } else {
1521- throw std::runtime_error("Polygon contains overlapping hole vertices.");
1522- }
1523-}
1524-
1525-int Triangle::Index(const Point* p)
1526-{
1527- if (p == points_[0]) {
1528- return 0;
1529- } else if (p == points_[1]) {
1530- return 1;
1531- } else if (p == points_[2]) {
1532- return 2;
1533- }
1534- throw std::runtime_error("Polygon contains overlapping hole vertices.");
1535- return 0;
1536-}
1537-
1538-int Triangle::EdgeIndex(const Point* p1, const Point* p2)
1539-{
1540- if (points_[0] == p1) {
1541- if (points_[1] == p2) {
1542- return 2;
1543- } else if (points_[2] == p2) {
1544- return 1;
1545- }
1546- } else if (points_[1] == p1) {
1547- if (points_[2] == p2) {
1548- return 0;
1549- } else if (points_[0] == p2) {
1550- return 2;
1551- }
1552- } else if (points_[2] == p1) {
1553- if (points_[0] == p2) {
1554- return 1;
1555- } else if (points_[1] == p2) {
1556- return 0;
1557- }
1558- }
1559- return -1;
1560-}
1561-
1562-void Triangle::MarkConstrainedEdge(const int index)
1563-{
1564- constrained_edge[index] = true;
1565-}
1566-
1567-void Triangle::MarkConstrainedEdge(Edge& edge)
1568-{
1569- MarkConstrainedEdge(edge.p, edge.q);
1570-}
1571-
1572-// Mark edge as constrained
1573-void Triangle::MarkConstrainedEdge(Point* p, Point* q)
1574-{
1575- if ((q == points_[0] && p == points_[1]) || (q == points_[1] && p == points_[0])) {
1576- constrained_edge[2] = true;
1577- } else if ((q == points_[0] && p == points_[2]) || (q == points_[2] && p == points_[0])) {
1578- constrained_edge[1] = true;
1579- } else if ((q == points_[1] && p == points_[2]) || (q == points_[2] && p == points_[1])) {
1580- constrained_edge[0] = true;
1581- }
1582-}
1583-
1584-// The point counter-clockwise to given point
1585-Point* Triangle::PointCW(Point& point)
1586-{
1587- if (&point == points_[0]) {
1588- return points_[2];
1589- } else if (&point == points_[1]) {
1590- return points_[0];
1591- } else if (&point == points_[2]) {
1592- return points_[1];
1593- }
1594- throw std::runtime_error("Polygon contains overlapping hole vertices.");
1595- return NULL;
1596-}
1597-
1598-// The point counter-clockwise to given point
1599-Point* Triangle::PointCCW(Point& point)
1600-{
1601- if (&point == points_[0]) {
1602- return points_[1];
1603- } else if (&point == points_[1]) {
1604- return points_[2];
1605- } else if (&point == points_[2]) {
1606- return points_[0];
1607- }
1608- throw std::runtime_error("Polygon contains overlapping hole vertices.");
1609- return NULL;
1610-}
1611-
1612-// The neighbor clockwise to given point
1613-Triangle* Triangle::NeighborCW(Point& point)
1614-{
1615- if (&point == points_[0]) {
1616- return neighbors_[1];
1617- } else if (&point == points_[1]) {
1618- return neighbors_[2];
1619- }
1620- return neighbors_[0];
1621-}
1622-
1623-// The neighbor counter-clockwise to given point
1624-Triangle* Triangle::NeighborCCW(Point& point)
1625-{
1626- if (&point == points_[0]) {
1627- return neighbors_[2];
1628- } else if (&point == points_[1]) {
1629- return neighbors_[0];
1630- }
1631- return neighbors_[1];
1632-}
1633-
1634-bool Triangle::GetConstrainedEdgeCCW(Point& p)
1635-{
1636- if (&p == points_[0]) {
1637- return constrained_edge[2];
1638- } else if (&p == points_[1]) {
1639- return constrained_edge[0];
1640- }
1641- return constrained_edge[1];
1642-}
1643-
1644-bool Triangle::GetConstrainedEdgeCW(Point& p)
1645-{
1646- if (&p == points_[0]) {
1647- return constrained_edge[1];
1648- } else if (&p == points_[1]) {
1649- return constrained_edge[2];
1650- }
1651- return constrained_edge[0];
1652-}
1653-
1654-void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
1655-{
1656- if (&p == points_[0]) {
1657- constrained_edge[2] = ce;
1658- } else if (&p == points_[1]) {
1659- constrained_edge[0] = ce;
1660- } else {
1661- constrained_edge[1] = ce;
1662- }
1663-}
1664-
1665-void Triangle::SetConstrainedEdgeCW(Point& p, bool ce)
1666-{
1667- if (&p == points_[0]) {
1668- constrained_edge[1] = ce;
1669- } else if (&p == points_[1]) {
1670- constrained_edge[2] = ce;
1671- } else {
1672- constrained_edge[0] = ce;
1673- }
1674-}
1675-
1676-bool Triangle::GetDelunayEdgeCCW(Point& p)
1677-{
1678- if (&p == points_[0]) {
1679- return delaunay_edge[2];
1680- } else if (&p == points_[1]) {
1681- return delaunay_edge[0];
1682- }
1683- return delaunay_edge[1];
1684-}
1685-
1686-bool Triangle::GetDelunayEdgeCW(Point& p)
1687-{
1688- if (&p == points_[0]) {
1689- return delaunay_edge[1];
1690- } else if (&p == points_[1]) {
1691- return delaunay_edge[2];
1692- }
1693- return delaunay_edge[0];
1694-}
1695-
1696-void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
1697-{
1698- if (&p == points_[0]) {
1699- delaunay_edge[2] = e;
1700- } else if (&p == points_[1]) {
1701- delaunay_edge[0] = e;
1702- } else {
1703- delaunay_edge[1] = e;
1704- }
1705-}
1706-
1707-void Triangle::SetDelunayEdgeCW(Point& p, bool e)
1708-{
1709- if (&p == points_[0]) {
1710- delaunay_edge[1] = e;
1711- } else if (&p == points_[1]) {
1712- delaunay_edge[2] = e;
1713- } else {
1714- delaunay_edge[0] = e;
1715- }
1716-}
1717-
1718-// The neighbor across to given point
1719-Triangle* Triangle::NeighborAcross(Point& opoint)
1720-{
1721- if (&opoint == points_[0]) {
1722- return neighbors_[0];
1723- } else if (&opoint == points_[1]) {
1724- return neighbors_[1];
1725- }
1726- return neighbors_[2];
1727-}
1728-
1729-void Triangle::DebugPrint()
1730-{
1731- using namespace std;
1732- cout << points_[0]->x << "," << points_[0]->y << " ";
1733- cout << points_[1]->x << "," << points_[1]->y << " ";
1734- cout << points_[2]->x << "," << points_[2]->y << endl;
1735-}
1736-
1737-}
1738diff --git a/polygon/poly2tri/common/shapes.h b/polygon/poly2tri/common/shapes.h
1739deleted file mode 100644
1740index 3ec2f98..0000000
1741--- a/polygon/poly2tri/common/shapes.h
1742+++ /dev/null
1743@@ -1,325 +0,0 @@
1744-/*
1745- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
1746- * http://code.google.com/p/poly2tri/
1747- *
1748- * All rights reserved.
1749- *
1750- * Redistribution and use in source and binary forms, with or without modification,
1751- * are permitted provided that the following conditions are met:
1752- *
1753- * * Redistributions of source code must retain the above copyright notice,
1754- * this list of conditions and the following disclaimer.
1755- * * Redistributions in binary form must reproduce the above copyright notice,
1756- * this list of conditions and the following disclaimer in the documentation
1757- * and/or other materials provided with the distribution.
1758- * * Neither the name of Poly2Tri nor the names of its contributors may be
1759- * used to endorse or promote products derived from this software without specific
1760- * prior written permission.
1761- *
1762- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1763- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1764- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1765- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
1766- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1767- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1768- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1769- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1770- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1771- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1772- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1773- */
1774-
1775-// Include guard
1776-#ifndef SHAPES_H
1777-#define SHAPES_H
1778-
1779-#include <vector>
1780-#include <cstddef>
1781-#include <assert.h>
1782-#include <cmath>
1783-
1784-namespace p2t {
1785-
1786-struct Edge;
1787-
1788-struct Point {
1789-
1790- double x, y;
1791- int id;
1792-
1793- /// Default constructor does nothing (for performance).
1794- Point()
1795- {
1796- x = 0.0;
1797- y = 0.0;
1798- id = 0;
1799- }
1800-
1801- /// The edges this point constitutes an upper ending point
1802- std::vector<Edge*> edge_list;
1803-
1804- /// Construct using coordinates.
1805- Point(double ax, double ay, int aid = 0) : x(ax), y(ay), id(aid) {}
1806-
1807- /// Set this point to all zeros.
1808- void set_zero()
1809- {
1810- x = 0.0;
1811- y = 0.0;
1812- }
1813-
1814- /// Set this point to some specified coordinates.
1815- void set(double x_, double y_)
1816- {
1817- x = x_;
1818- y = y_;
1819- }
1820-
1821- /// Negate this point.
1822- Point operator -() const
1823- {
1824- Point v;
1825- v.set(-x, -y);
1826- return v;
1827- }
1828-
1829- /// Add a point to this point.
1830- void operator +=(const Point& v)
1831- {
1832- x += v.x;
1833- y += v.y;
1834- }
1835-
1836- /// Subtract a point from this point.
1837- void operator -=(const Point& v)
1838- {
1839- x -= v.x;
1840- y -= v.y;
1841- }
1842-
1843- /// Multiply this point by a scalar.
1844- void operator *=(double a)
1845- {
1846- x *= a;
1847- y *= a;
1848- }
1849-
1850- /// Get the length of this point (the norm).
1851- double Length() const
1852- {
1853- return sqrt(x * x + y * y);
1854- }
1855-
1856- /// Convert this point into a unit point. Returns the Length.
1857- double Normalize()
1858- {
1859- double len = Length();
1860- x /= len;
1861- y /= len;
1862- return len;
1863- }
1864-
1865-};
1866-
1867-// Represents a simple polygon's edge
1868-struct Edge {
1869-
1870- Point* p, *q;
1871-
1872- /// Constructor
1873- Edge(Point& p1, Point& p2) : p(&p1), q(&p2)
1874- {
1875- if (p1.y > p2.y) {
1876- q = &p1;
1877- p = &p2;
1878- } else if (p1.y == p2.y) {
1879- if (p1.x > p2.x) {
1880- q = &p1;
1881- p = &p2;
1882- } else if (p1.x == p2.x) {
1883- // Repeat points
1884- assert(false);
1885- }
1886- }
1887-
1888- q->edge_list.push_back(this);
1889- }
1890-};
1891-
1892-// Triangle-based data structures are know to have better performance than quad-edge structures
1893-// See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator"
1894-// "Triangulations in CGAL"
1895-class Triangle {
1896-public:
1897-
1898-/// Constructor
1899-Triangle(Point& a, Point& b, Point& c);
1900-
1901-/// Flags to determine if an edge is a Constrained edge
1902-bool constrained_edge[3];
1903-/// Flags to determine if an edge is a Delauney edge
1904-bool delaunay_edge[3];
1905-
1906-Point* GetPoint(const int& index);
1907-Point* PointCW(Point& point);
1908-Point* PointCCW(Point& point);
1909-Point* OppositePoint(Triangle& t, Point& p);
1910-
1911-Triangle* GetNeighbor(const int& index);
1912-void MarkNeighbor(Point* p1, Point* p2, Triangle* t);
1913-void MarkNeighbor(Triangle& t);
1914-
1915-void MarkConstrainedEdge(const int index);
1916-void MarkConstrainedEdge(Edge& edge);
1917-void MarkConstrainedEdge(Point* p, Point* q);
1918-
1919-int Index(const Point* p);
1920-int EdgeIndex(const Point* p1, const Point* p2);
1921-
1922-Triangle* NeighborCW(Point& point);
1923-Triangle* NeighborCCW(Point& point);
1924-bool GetConstrainedEdgeCCW(Point& p);
1925-bool GetConstrainedEdgeCW(Point& p);
1926-void SetConstrainedEdgeCCW(Point& p, bool ce);
1927-void SetConstrainedEdgeCW(Point& p, bool ce);
1928-bool GetDelunayEdgeCCW(Point& p);
1929-bool GetDelunayEdgeCW(Point& p);
1930-void SetDelunayEdgeCCW(Point& p, bool e);
1931-void SetDelunayEdgeCW(Point& p, bool e);
1932-
1933-bool Contains(Point* p);
1934-bool Contains(const Edge& e);
1935-bool Contains(Point* p, Point* q);
1936-void Legalize(Point& point);
1937-void Legalize(Point& opoint, Point& npoint);
1938-/**
1939- * Clears all references to all other triangles and points
1940- */
1941-void Clear();
1942-void ClearNeighbor(Triangle *triangle );
1943-void ClearNeighbors();
1944-void ClearDelunayEdges();
1945-
1946-inline bool IsInterior();
1947-inline void IsInterior(bool b);
1948-
1949-Triangle* NeighborAcross(Point& opoint);
1950-
1951-void DebugPrint();
1952-
1953-private:
1954-
1955-/// Triangle points
1956-Point* points_[3];
1957-/// Neighbor list
1958-Triangle* neighbors_[3];
1959-
1960-/// Has this triangle been marked as an interior triangle?
1961-bool interior_;
1962-};
1963-
1964-inline bool cmp(const Point* a, const Point* b)
1965-{
1966- if (a->y < b->y) {
1967- return true;
1968- } else if (a->y == b->y) {
1969- // Make sure q is point with greater x value
1970- if (a->x < b->x) {
1971- return true;
1972- }
1973- }
1974- return false;
1975-}
1976-
1977-/// Add two points_ component-wise.
1978-inline Point operator +(const Point& a, const Point& b)
1979-{
1980- return Point(a.x + b.x, a.y + b.y);
1981-}
1982-
1983-/// Subtract two points_ component-wise.
1984-inline Point operator -(const Point& a, const Point& b)
1985-{
1986- return Point(a.x - b.x, a.y - b.y);
1987-}
1988-
1989-/// Multiply point by scalar
1990-inline Point operator *(double s, const Point& a)
1991-{
1992- return Point(s * a.x, s * a.y);
1993-}
1994-
1995-inline bool operator ==(const Point& a, const Point& b)
1996-{
1997- return a.x == b.x && a.y == b.y;
1998-}
1999-
2000-inline bool operator !=(const Point& a, const Point& b)
2001-{
2002- return !(a.x == b.x) && !(a.y == b.y);
2003-}
2004-
2005-/// Peform the dot product on two vectors.
2006-inline double Dot(const Point& a, const Point& b)
2007-{
2008- return a.x * b.x + a.y * b.y;
2009-}
2010-
2011-/// Perform the cross product on two vectors. In 2D this produces a scalar.
2012-inline double Cross(const Point& a, const Point& b)
2013-{
2014- return a.x * b.y - a.y * b.x;
2015-}
2016-
2017-/// Perform the cross product on a point and a scalar. In 2D this produces
2018-/// a point.
2019-inline Point Cross(const Point& a, double s)
2020-{
2021- return Point(s * a.y, -s * a.x);
2022-}
2023-
2024-/// Perform the cross product on a scalar and a point. In 2D this produces
2025-/// a point.
2026-inline Point Cross(const double s, const Point& a)
2027-{
2028- return Point(-s * a.y, s * a.x);
2029-}
2030-
2031-inline Point* Triangle::GetPoint(const int& index)
2032-{
2033- return points_[index];
2034-}
2035-
2036-inline Triangle* Triangle::GetNeighbor(const int& index)
2037-{
2038- return neighbors_[index];
2039-}
2040-
2041-inline bool Triangle::Contains(Point* p)
2042-{
2043- return p == points_[0] || p == points_[1] || p == points_[2];
2044-}
2045-
2046-inline bool Triangle::Contains(const Edge& e)
2047-{
2048- return Contains(e.p) && Contains(e.q);
2049-}
2050-
2051-inline bool Triangle::Contains(Point* p, Point* q)
2052-{
2053- return Contains(p) && Contains(q);
2054-}
2055-
2056-inline bool Triangle::IsInterior()
2057-{
2058- return interior_;
2059-}
2060-
2061-inline void Triangle::IsInterior(bool b)
2062-{
2063- interior_ = b;
2064-}
2065-
2066-}
2067-
2068-#endif
2069diff --git a/polygon/poly2tri/common/utils.h b/polygon/poly2tri/common/utils.h
2070deleted file mode 100644
2071index 78416f2..0000000
2072--- a/polygon/poly2tri/common/utils.h
2073+++ /dev/null
2074@@ -1,123 +0,0 @@
2075-/*
2076- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
2077- * http://code.google.com/p/poly2tri/
2078- *
2079- * All rights reserved.
2080- *
2081- * Redistribution and use in source and binary forms, with or without modification,
2082- * are permitted provided that the following conditions are met:
2083- *
2084- * * Redistributions of source code must retain the above copyright notice,
2085- * this list of conditions and the following disclaimer.
2086- * * Redistributions in binary form must reproduce the above copyright notice,
2087- * this list of conditions and the following disclaimer in the documentation
2088- * and/or other materials provided with the distribution.
2089- * * Neither the name of Poly2Tri nor the names of its contributors may be
2090- * used to endorse or promote products derived from this software without specific
2091- * prior written permission.
2092- *
2093- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2094- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2095- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2096- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2097- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2098- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2099- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2100- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2101- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2102- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2103- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2104- */
2105-
2106-#ifndef UTILS_H
2107-#define UTILS_H
2108-
2109-// Otherwise #defines like M_PI are undeclared under Visual Studio
2110-#define _USE_MATH_DEFINES
2111-
2112-#include <exception>
2113-#include <math.h>
2114-
2115-namespace p2t {
2116-
2117-const double PI_3div4 = 3 * M_PI / 4;
2118-const double PI_div2 = 1.57079632679489661923;
2119-const double EPSILON = 1e-12;
2120-
2121-enum Orientation { CW, CCW, COLLINEAR };
2122-
2123-/**
2124- * Forumla to calculate signed area<br>
2125- * Positive if CCW<br>
2126- * Negative if CW<br>
2127- * 0 if collinear<br>
2128- * <pre>
2129- * A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
2130- * = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
2131- * </pre>
2132- */
2133-Orientation Orient2d(Point& pa, Point& pb, Point& pc)
2134-{
2135- double detleft = (pa.x - pc.x) * (pb.y - pc.y);
2136- double detright = (pa.y - pc.y) * (pb.x - pc.x);
2137- double val = detleft - detright;
2138- if (val > -EPSILON && val < EPSILON) {
2139- return COLLINEAR;
2140- } else if (val > 0) {
2141- return CCW;
2142- }
2143- return CW;
2144-}
2145-
2146-/*
2147-bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
2148-{
2149- double pdx = pd.x;
2150- double pdy = pd.y;
2151- double adx = pa.x - pdx;
2152- double ady = pa.y - pdy;
2153- double bdx = pb.x - pdx;
2154- double bdy = pb.y - pdy;
2155-
2156- double adxbdy = adx * bdy;
2157- double bdxady = bdx * ady;
2158- double oabd = adxbdy - bdxady;
2159-
2160- if (oabd <= EPSILON) {
2161- return false;
2162- }
2163-
2164- double cdx = pc.x - pdx;
2165- double cdy = pc.y - pdy;
2166-
2167- double cdxady = cdx * ady;
2168- double adxcdy = adx * cdy;
2169- double ocad = cdxady - adxcdy;
2170-
2171- if (ocad <= EPSILON) {
2172- return false;
2173- }
2174-
2175- return true;
2176-}
2177-
2178-*/
2179-
2180-bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
2181-{
2182- double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y);
2183- if (oadb >= -EPSILON) {
2184- return false;
2185- }
2186-
2187- double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y);
2188- if (oadc <= EPSILON) {
2189- return false;
2190- }
2191- return true;
2192-}
2193-
2194-}
2195-
2196-#endif
2197-
2198diff --git a/polygon/poly2tri/poly2tri.h b/polygon/poly2tri/poly2tri.h
2199deleted file mode 100644
2200index 487755e..0000000
2201--- a/polygon/poly2tri/poly2tri.h
2202+++ /dev/null
2203@@ -1,39 +0,0 @@
2204-/*
2205- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
2206- * http://code.google.com/p/poly2tri/
2207- *
2208- * All rights reserved.
2209- *
2210- * Redistribution and use in source and binary forms, with or without modification,
2211- * are permitted provided that the following conditions are met:
2212- *
2213- * * Redistributions of source code must retain the above copyright notice,
2214- * this list of conditions and the following disclaimer.
2215- * * Redistributions in binary form must reproduce the above copyright notice,
2216- * this list of conditions and the following disclaimer in the documentation
2217- * and/or other materials provided with the distribution.
2218- * * Neither the name of Poly2Tri nor the names of its contributors may be
2219- * used to endorse or promote products derived from this software without specific
2220- * prior written permission.
2221- *
2222- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2223- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2224- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2225- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2226- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2227- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2228- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2229- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2230- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2231- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2232- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2233- */
2234-
2235-#ifndef POLY2TRI_H
2236-#define POLY2TRI_H
2237-
2238-#include "common/shapes.h"
2239-#include "sweep/cdt.h"
2240-
2241-#endif
2242-
2243diff --git a/polygon/poly2tri/sweep/advancing_front.cc b/polygon/poly2tri/sweep/advancing_front.cc
2244deleted file mode 100644
2245index 019df4a..0000000
2246--- a/polygon/poly2tri/sweep/advancing_front.cc
2247+++ /dev/null
2248@@ -1,109 +0,0 @@
2249-/*
2250- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
2251- * http://code.google.com/p/poly2tri/
2252- *
2253- * All rights reserved.
2254- *
2255- * Redistribution and use in source and binary forms, with or without modification,
2256- * are permitted provided that the following conditions are met:
2257- *
2258- * * Redistributions of source code must retain the above copyright notice,
2259- * this list of conditions and the following disclaimer.
2260- * * Redistributions in binary form must reproduce the above copyright notice,
2261- * this list of conditions and the following disclaimer in the documentation
2262- * and/or other materials provided with the distribution.
2263- * * Neither the name of Poly2Tri nor the names of its contributors may be
2264- * used to endorse or promote products derived from this software without specific
2265- * prior written permission.
2266- *
2267- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2268- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2269- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2270- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2271- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2272- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2273- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2274- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2275- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2276- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2277- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2278- */
2279-#include "advancing_front.h"
2280-
2281-namespace p2t {
2282-
2283-AdvancingFront::AdvancingFront(Node& head, Node& tail)
2284-{
2285- head_ = &head;
2286- tail_ = &tail;
2287- search_node_ = &head;
2288-}
2289-
2290-Node* AdvancingFront::LocateNode(const double& x)
2291-{
2292- Node* node = search_node_;
2293-
2294- if (x < node->value) {
2295- while ((node = node->prev) != NULL) {
2296- if (x >= node->value) {
2297- search_node_ = node;
2298- return node;
2299- }
2300- }
2301- } else {
2302- while ((node = node->next) != NULL) {
2303- if (x < node->value) {
2304- search_node_ = node->prev;
2305- return node->prev;
2306- }
2307- }
2308- }
2309- return NULL;
2310-}
2311-
2312-Node* AdvancingFront::FindSearchNode(const double& x)
2313-{
2314- (void)x; // suppress compiler warnings "unused parameter 'x'"
2315- // TODO: implement BST index
2316- return search_node_;
2317-}
2318-
2319-Node* AdvancingFront::LocatePoint(const Point* point)
2320-{
2321- const double px = point->x;
2322- Node* node = FindSearchNode(px);
2323- const double nx = node->point->x;
2324-
2325- if (px == nx) {
2326- if (point != node->point) {
2327- // We might have two nodes with same x value for a short time
2328- if (point == node->prev->point) {
2329- node = node->prev;
2330- } else if (point == node->next->point) {
2331- node = node->next;
2332- } else {
2333- assert(0);
2334- }
2335- }
2336- } else if (px < nx) {
2337- while ((node = node->prev) != NULL) {
2338- if (point == node->point) {
2339- break;
2340- }
2341- }
2342- } else {
2343- while ((node = node->next) != NULL) {
2344- if (point == node->point)
2345- break;
2346- }
2347- }
2348- if(node) search_node_ = node;
2349- return node;
2350-}
2351-
2352-AdvancingFront::~AdvancingFront()
2353-{
2354-}
2355-
2356-}
2357-
2358diff --git a/polygon/poly2tri/sweep/advancing_front.h b/polygon/poly2tri/sweep/advancing_front.h
2359deleted file mode 100644
2360index bab73d4..0000000
2361--- a/polygon/poly2tri/sweep/advancing_front.h
2362+++ /dev/null
2363@@ -1,118 +0,0 @@
2364-/*
2365- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
2366- * http://code.google.com/p/poly2tri/
2367- *
2368- * All rights reserved.
2369- *
2370- * Redistribution and use in source and binary forms, with or without modification,
2371- * are permitted provided that the following conditions are met:
2372- *
2373- * * Redistributions of source code must retain the above copyright notice,
2374- * this list of conditions and the following disclaimer.
2375- * * Redistributions in binary form must reproduce the above copyright notice,
2376- * this list of conditions and the following disclaimer in the documentation
2377- * and/or other materials provided with the distribution.
2378- * * Neither the name of Poly2Tri nor the names of its contributors may be
2379- * used to endorse or promote products derived from this software without specific
2380- * prior written permission.
2381- *
2382- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2383- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2384- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2385- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2386- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2387- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2388- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2389- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2390- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2391- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2392- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2393- */
2394-
2395-#ifndef ADVANCED_FRONT_H
2396-#define ADVANCED_FRONT_H
2397-
2398-#include "../common/shapes.h"
2399-
2400-namespace p2t {
2401-
2402-struct Node;
2403-
2404-// Advancing front node
2405-struct Node {
2406- Point* point;
2407- Triangle* triangle;
2408-
2409- Node* next;
2410- Node* prev;
2411-
2412- double value;
2413-
2414- Node(Point& p) : point(&p), triangle(NULL), next(NULL), prev(NULL), value(p.x)
2415- {
2416- }
2417-
2418- Node(Point& p, Triangle& t) : point(&p), triangle(&t), next(NULL), prev(NULL), value(p.x)
2419- {
2420- }
2421-
2422-};
2423-
2424-// Advancing front
2425-class AdvancingFront {
2426-public:
2427-
2428-AdvancingFront(Node& head, Node& tail);
2429-// Destructor
2430-~AdvancingFront();
2431-
2432-Node* head();
2433-void set_head(Node* node);
2434-Node* tail();
2435-void set_tail(Node* node);
2436-Node* search();
2437-void set_search(Node* node);
2438-
2439-/// Locate insertion point along advancing front
2440-Node* LocateNode(const double& x);
2441-
2442-Node* LocatePoint(const Point* point);
2443-
2444-private:
2445-
2446-Node* head_, *tail_, *search_node_;
2447-
2448-Node* FindSearchNode(const double& x);
2449-};
2450-
2451-inline Node* AdvancingFront::head()
2452-{
2453- return head_;
2454-}
2455-inline void AdvancingFront::set_head(Node* node)
2456-{
2457- head_ = node;
2458-}
2459-
2460-inline Node* AdvancingFront::tail()
2461-{
2462- return tail_;
2463-}
2464-inline void AdvancingFront::set_tail(Node* node)
2465-{
2466- tail_ = node;
2467-}
2468-
2469-inline Node* AdvancingFront::search()
2470-{
2471- return search_node_;
2472-}
2473-
2474-inline void AdvancingFront::set_search(Node* node)
2475-{
2476- search_node_ = node;
2477-}
2478-
2479-}
2480-
2481-#endif
2482diff --git a/polygon/poly2tri/sweep/cdt.cc b/polygon/poly2tri/sweep/cdt.cc
2483deleted file mode 100644
2484index cae6157..0000000
2485--- a/polygon/poly2tri/sweep/cdt.cc
2486+++ /dev/null
2487@@ -1,74 +0,0 @@
2488-/*
2489- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
2490- * http://code.google.com/p/poly2tri/
2491- *
2492- * All rights reserved.
2493- *
2494- * Redistribution and use in source and binary forms, with or without modification,
2495- * are permitted provided that the following conditions are met:
2496- *
2497- * * Redistributions of source code must retain the above copyright notice,
2498- * this list of conditions and the following disclaimer.
2499- * * Redistributions in binary form must reproduce the above copyright notice,
2500- * this list of conditions and the following disclaimer in the documentation
2501- * and/or other materials provided with the distribution.
2502- * * Neither the name of Poly2Tri nor the names of its contributors may be
2503- * used to endorse or promote products derived from this software without specific
2504- * prior written permission.
2505- *
2506- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2507- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2508- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2509- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2510- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2511- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2512- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2513- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2514- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2515- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2516- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2517- */
2518-#include "cdt.h"
2519-
2520-#include <utility>
2521-
2522-namespace p2t {
2523-
2524-CDT::CDT(std::vector<Point*> polyline)
2525-{
2526- sweep_context_ = new SweepContext( std::move( polyline ) );
2527- sweep_ = new Sweep;
2528-}
2529-
2530-void CDT::AddHole(std::vector<Point*> polyline)
2531-{
2532- sweep_context_->AddHole(polyline);
2533-}
2534-
2535-void CDT::AddPoint(Point* point) {
2536- sweep_context_->AddPoint(point);
2537-}
2538-
2539-void CDT::Triangulate()
2540-{
2541- sweep_->Triangulate(*sweep_context_);
2542-}
2543-
2544-std::vector<p2t::Triangle*> CDT::GetTriangles()
2545-{
2546- return sweep_context_->GetTriangles();
2547-}
2548-
2549-std::list<p2t::Triangle*> CDT::GetMap()
2550-{
2551- return sweep_context_->GetMap();
2552-}
2553-
2554-CDT::~CDT()
2555-{
2556- delete sweep_context_;
2557- delete sweep_;
2558-}
2559-
2560-}
2561-
2562diff --git a/polygon/poly2tri/sweep/cdt.h b/polygon/poly2tri/sweep/cdt.h
2563deleted file mode 100644
2564index 3e6f024..0000000
2565--- a/polygon/poly2tri/sweep/cdt.h
2566+++ /dev/null
2567@@ -1,105 +0,0 @@
2568-/*
2569- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
2570- * http://code.google.com/p/poly2tri/
2571- *
2572- * All rights reserved.
2573- *
2574- * Redistribution and use in source and binary forms, with or without modification,
2575- * are permitted provided that the following conditions are met:
2576- *
2577- * * Redistributions of source code must retain the above copyright notice,
2578- * this list of conditions and the following disclaimer.
2579- * * Redistributions in binary form must reproduce the above copyright notice,
2580- * this list of conditions and the following disclaimer in the documentation
2581- * and/or other materials provided with the distribution.
2582- * * Neither the name of Poly2Tri nor the names of its contributors may be
2583- * used to endorse or promote products derived from this software without specific
2584- * prior written permission.
2585- *
2586- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2587- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2588- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2589- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2590- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2591- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2592- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2593- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2594- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2595- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2596- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2597- */
2598-
2599-#ifndef CDT_H
2600-#define CDT_H
2601-
2602-#include "advancing_front.h"
2603-#include "sweep_context.h"
2604-#include "sweep.h"
2605-
2606-/**
2607- *
2608- * @author Mason Green <mason.green@gmail.com>
2609- *
2610- */
2611-
2612-namespace p2t {
2613-
2614-class CDT
2615-{
2616-public:
2617-
2618- /**
2619- * Constructor - add polyline with non repeating points
2620- *
2621- * @param polyline
2622- */
2623- CDT(std::vector<Point*> polyline);
2624-
2625- /**
2626- * Destructor - clean up memory
2627- */
2628- ~CDT();
2629-
2630- /**
2631- * Add a hole
2632- *
2633- * @param polyline
2634- */
2635- void AddHole(std::vector<Point*> polyline);
2636-
2637- /**
2638- * Add a steiner point
2639- *
2640- * @param point
2641- */
2642- void AddPoint(Point* point);
2643-
2644- /**
2645- * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points
2646- */
2647- void Triangulate();
2648-
2649- /**
2650- * Get CDT triangles
2651- */
2652- std::vector<Triangle*> GetTriangles();
2653-
2654- /**
2655- * Get triangle map
2656- */
2657- std::list<Triangle*> GetMap();
2658-
2659- private:
2660-
2661- /**
2662- * Internals
2663- */
2664-
2665- SweepContext* sweep_context_;
2666- Sweep* sweep_;
2667-
2668-};
2669-
2670-}
2671-
2672-#endif
2673diff --git a/polygon/poly2tri/sweep/sweep.cc b/polygon/poly2tri/sweep/sweep.cc
2674deleted file mode 100644
2675index dcd815f..0000000
2676--- a/polygon/poly2tri/sweep/sweep.cc
2677+++ /dev/null
2678@@ -1,811 +0,0 @@
2679-/*
2680- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
2681- * http://code.google.com/p/poly2tri/
2682- *
2683- * All rights reserved.
2684- *
2685- * Redistribution and use in source and binary forms, with or without modification,
2686- * are permitted provided that the following conditions are met:
2687- *
2688- * * Redistributions of source code must retain the above copyright notice,
2689- * this list of conditions and the following disclaimer.
2690- * * Redistributions in binary form must reproduce the above copyright notice,
2691- * this list of conditions and the following disclaimer in the documentation
2692- * and/or other materials provided with the distribution.
2693- * * Neither the name of Poly2Tri nor the names of its contributors may be
2694- * used to endorse or promote products derived from this software without specific
2695- * prior written permission.
2696- *
2697- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2698- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2699- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2700- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2701- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2702- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2703- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2704- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2705- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2706- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2707- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2708- */
2709-#include "sweep.h"
2710-#include "sweep_context.h"
2711-#include "advancing_front.h"
2712-#include "../common/utils.h"
2713-#include <stdexcept>
2714-
2715-namespace p2t {
2716-
2717-// Triangulate simple polygon with holes
2718-void Sweep::Triangulate(SweepContext& tcx)
2719-{
2720- tcx.InitTriangulation();
2721- tcx.CreateAdvancingFront(nodes_);
2722- // Sweep points; build mesh
2723- SweepPoints(tcx);
2724- // Clean up
2725- FinalizationPolygon(tcx);
2726-}
2727-
2728-void Sweep::SweepPoints(SweepContext& tcx)
2729-{
2730- for (int i = 1; i < tcx.point_count(); i++) {
2731- Point& point = *tcx.GetPoint(i);
2732- Node* node = &PointEvent(tcx, point);
2733- for (unsigned int j = 0; j < point.edge_list.size(); j++) {
2734- EdgeEvent(tcx, point.edge_list[j], node);
2735- }
2736- }
2737-}
2738-
2739-void Sweep::FinalizationPolygon(SweepContext& tcx)
2740-{
2741- // Get an Internal triangle to start with
2742- Triangle* t = tcx.front()->head()->next->triangle;
2743- Point* p = tcx.front()->head()->next->point;
2744- while (!t->GetConstrainedEdgeCW(*p)) {
2745- t = t->NeighborCCW(*p);
2746- }
2747-
2748- // Collect interior triangles constrained by edges
2749- tcx.MeshClean(*t);
2750-}
2751-
2752-Node& Sweep::PointEvent(SweepContext& tcx, Point& point)
2753-{
2754- Node& node = tcx.LocateNode(point);
2755- Node& new_node = NewFrontTriangle(tcx, point, node);
2756-
2757- // Only need to check +epsilon since point never have smaller
2758- // x value than node due to how we fetch nodes from the front
2759- if (point.x <= node.point->x + EPSILON) {
2760- Fill(tcx, node);
2761- }
2762-
2763- //tcx.AddNode(new_node);
2764-
2765- FillAdvancingFront(tcx, new_node);
2766- return new_node;
2767-}
2768-
2769-void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node)
2770-{
2771- tcx.edge_event.constrained_edge = edge;
2772- tcx.edge_event.right = (edge->p->x > edge->q->x);
2773-
2774- if (IsEdgeSideOfTriangle(*node->triangle, *edge->p, *edge->q)) {
2775- return;
2776- }
2777-
2778- // For now we will do all needed filling
2779- // TODO: integrate with flip process might give some better performance
2780- // but for now this avoid the issue with cases that needs both flips and fills
2781- FillEdgeEvent(tcx, edge, node);
2782- EdgeEvent(tcx, *edge->p, *edge->q, node->triangle, *edge->q);
2783-}
2784-
2785-void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point)
2786-{
2787- if (IsEdgeSideOfTriangle(*triangle, ep, eq)) {
2788- return;
2789- }
2790-
2791- Point* p1 = triangle->PointCCW(point);
2792- Orientation o1 = Orient2d(eq, *p1, ep);
2793- if (o1 == COLLINEAR) {
2794- if( triangle->Contains(&eq, p1)) {
2795- triangle->MarkConstrainedEdge(&eq, p1 );
2796- // We are modifying the constraint maybe it would be better to
2797- // not change the given constraint and just keep a variable for the new constraint
2798- tcx.edge_event.constrained_edge->q = p1;
2799- triangle = triangle->NeighborAcross(point);
2800- EdgeEvent( tcx, ep, *p1, triangle, *p1 );
2801- } else {
2802- std::runtime_error("EdgeEvent - collinear points not supported");
2803- }
2804- return;
2805- }
2806-
2807- Point* p2 = triangle->PointCW(point);
2808- Orientation o2 = Orient2d(eq, *p2, ep);
2809- if (o2 == COLLINEAR) {
2810- if( triangle->Contains(&eq, p2)) {
2811- triangle->MarkConstrainedEdge(&eq, p2 );
2812- // We are modifying the constraint maybe it would be better to
2813- // not change the given constraint and just keep a variable for the new constraint
2814- tcx.edge_event.constrained_edge->q = p2;
2815- triangle = triangle->NeighborAcross(point);
2816- EdgeEvent( tcx, ep, *p2, triangle, *p2 );
2817- } else {
2818- std::runtime_error("EdgeEvent - collinear points not supported");
2819- }
2820- return;
2821- }
2822-
2823- if (o1 == o2) {
2824- // Need to decide if we are rotating CW or CCW to get to a triangle
2825- // that will cross edge
2826- if (o1 == CW) {
2827- triangle = triangle->NeighborCCW(point);
2828- } else{
2829- triangle = triangle->NeighborCW(point);
2830- }
2831- EdgeEvent(tcx, ep, eq, triangle, point);
2832- } else {
2833- // This triangle crosses constraint so lets flippin start!
2834- FlipEdgeEvent(tcx, ep, eq, triangle, point);
2835- }
2836-}
2837-
2838-bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq)
2839-{
2840- int index = triangle.EdgeIndex(&ep, &eq);
2841-
2842- if (index != -1) {
2843- triangle.MarkConstrainedEdge(index);
2844- Triangle* t = triangle.GetNeighbor(index);
2845- if (t) {
2846- t->MarkConstrainedEdge(&ep, &eq);
2847- }
2848- return true;
2849- }
2850- return false;
2851-}
2852-
2853-Node& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node)
2854-{
2855- Triangle* triangle = new Triangle(point, *node.point, *node.next->point);
2856-
2857- triangle->MarkNeighbor(*node.triangle);
2858- tcx.AddToMap(triangle);
2859-
2860- Node* new_node = new Node(point);
2861- nodes_.push_back(new_node);
2862-
2863- new_node->next = node.next;
2864- new_node->prev = &node;
2865- node.next->prev = new_node;
2866- node.next = new_node;
2867-
2868- if (!Legalize(tcx, *triangle)) {
2869- tcx.MapTriangleToNodes(*triangle);
2870- }
2871-
2872- return *new_node;
2873-}
2874-
2875-void Sweep::Fill(SweepContext& tcx, Node& node)
2876-{
2877- Triangle* triangle = new Triangle(*node.prev->point, *node.point, *node.next->point);
2878-
2879- // TODO: should copy the constrained_edge value from neighbor triangles
2880- // for now constrained_edge values are copied during the legalize
2881- triangle->MarkNeighbor(*node.prev->triangle);
2882- triangle->MarkNeighbor(*node.triangle);
2883-
2884- tcx.AddToMap(triangle);
2885-
2886- // Update the advancing front
2887- node.prev->next = node.next;
2888- node.next->prev = node.prev;
2889-
2890- // If it was legalized the triangle has already been mapped
2891- if (!Legalize(tcx, *triangle)) {
2892- tcx.MapTriangleToNodes(*triangle);
2893- }
2894-
2895-}
2896-
2897-void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
2898-{
2899-
2900- // Fill right holes
2901- Node* node = n.next;
2902-
2903- while (node->next) {
2904- // if HoleAngle exceeds 90 degrees then break.
2905- if (LargeHole_DontFill(node)) break;
2906- Fill(tcx, *node);
2907- node = node->next;
2908- }
2909-
2910- // Fill left holes
2911- node = n.prev;
2912-
2913- while (node->prev) {
2914- // if HoleAngle exceeds 90 degrees then break.
2915- if (LargeHole_DontFill(node)) break;
2916- Fill(tcx, *node);
2917- node = node->prev;
2918- }
2919-
2920- // Fill right basins
2921- if (n.next && n.next->next) {
2922- double angle = BasinAngle(n);
2923- if (angle < PI_3div4) {
2924- FillBasin(tcx, n);
2925- }
2926- }
2927-}
2928-
2929-// True if HoleAngle exceeds 90 degrees.
2930-bool Sweep::LargeHole_DontFill(Node* node) {
2931-
2932- Node* nextNode = node->next;
2933- Node* prevNode = node->prev;
2934- if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point))
2935- return false;
2936-
2937- // Check additional points on front.
2938- Node* next2Node = nextNode->next;
2939- // "..Plus.." because only want angles on same side as point being added.
2940- if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point))
2941- return false;
2942-
2943- Node* prev2Node = prevNode->prev;
2944- // "..Plus.." because only want angles on same side as point being added.
2945- if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point))
2946- return false;
2947-
2948- return true;
2949-}
2950-
2951-bool Sweep::AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb) {
2952- double angle = Angle(*origin, *pa, *pb);
2953- bool exceeds90Degrees = ((angle > PI_div2) || (angle < -PI_div2));
2954- return exceeds90Degrees;
2955-}
2956-
2957-bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb) {
2958- double angle = Angle(*origin, *pa, *pb);
2959- bool exceedsPlus90DegreesOrIsNegative = (angle > PI_div2) || (angle < 0);
2960- return exceedsPlus90DegreesOrIsNegative;
2961-}
2962-
2963-double Sweep::Angle(Point& origin, Point& pa, Point& pb) {
2964- /* Complex plane
2965- * ab = cosA +i*sinA
2966- * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
2967- * atan2(y,x) computes the principal value of the argument function
2968- * applied to the complex number x+iy
2969- * Where x = ax*bx + ay*by
2970- * y = ax*by - ay*bx
2971- */
2972- double px = origin.x;
2973- double py = origin.y;
2974- double ax = pa.x- px;
2975- double ay = pa.y - py;
2976- double bx = pb.x - px;
2977- double by = pb.y - py;
2978- double x = ax * by - ay * bx;
2979- double y = ax * bx + ay * by;
2980- double angle = atan2(x, y);
2981- return angle;
2982-}
2983-
2984-double Sweep::BasinAngle(Node& node)
2985-{
2986- double ax = node.point->x - node.next->next->point->x;
2987- double ay = node.point->y - node.next->next->point->y;
2988- return atan2(ay, ax);
2989-}
2990-
2991-double Sweep::HoleAngle(Node& node)
2992-{
2993- /* Complex plane
2994- * ab = cosA +i*sinA
2995- * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
2996- * atan2(y,x) computes the principal value of the argument function
2997- * applied to the complex number x+iy
2998- * Where x = ax*bx + ay*by
2999- * y = ax*by - ay*bx
3000- */
3001- double ax = node.next->point->x - node.point->x;
3002- double ay = node.next->point->y - node.point->y;
3003- double bx = node.prev->point->x - node.point->x;
3004- double by = node.prev->point->y - node.point->y;
3005- return atan2(ax * by - ay * bx, ax * bx + ay * by);
3006-}
3007-
3008-bool Sweep::Legalize(SweepContext& tcx, Triangle& t)
3009-{
3010- // To legalize a triangle we start by finding if any of the three edges
3011- // violate the Delaunay condition
3012- for (int i = 0; i < 3; i++) {
3013- if (t.delaunay_edge[i])
3014- continue;
3015-
3016- Triangle* ot = t.GetNeighbor(i);
3017-
3018- if (ot) {
3019- Point* p = t.GetPoint(i);
3020- Point* op = ot->OppositePoint(t, *p);
3021- int oi = ot->Index(op);
3022-
3023- // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
3024- // then we should not try to legalize
3025- if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) {
3026- t.constrained_edge[i] = ot->constrained_edge[oi];
3027- continue;
3028- }
3029-
3030- bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op);
3031-
3032- if (inside) {
3033- // Lets mark this shared edge as Delaunay
3034- t.delaunay_edge[i] = true;
3035- ot->delaunay_edge[oi] = true;
3036-
3037- // Lets rotate shared edge one vertex CW to legalize it
3038- RotateTrianglePair(t, *p, *ot, *op);
3039-
3040- // We now got one valid Delaunay Edge shared by two triangles
3041- // This gives us 4 new edges to check for Delaunay
3042-
3043- // Make sure that triangle to node mapping is done only one time for a specific triangle
3044- bool not_legalized = !Legalize(tcx, t);
3045- if (not_legalized) {
3046- tcx.MapTriangleToNodes(t);
3047- }
3048-
3049- not_legalized = !Legalize(tcx, *ot);
3050- if (not_legalized)
3051- tcx.MapTriangleToNodes(*ot);
3052-
3053- // Reset the Delaunay edges, since they only are valid Delaunay edges
3054- // until we add a new triangle or point.
3055- // XXX: need to think about this. Can these edges be tried after we
3056- // return to previous recursive level?
3057- t.delaunay_edge[i] = false;
3058- ot->delaunay_edge[oi] = false;
3059-
3060- // If triangle have been legalized no need to check the other edges since
3061- // the recursive legalization will handles those so we can end here.
3062- return true;
3063- }
3064- }
3065- }
3066- return false;
3067-}
3068-
3069-bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd)
3070-{
3071- double adx = pa.x - pd.x;
3072- double ady = pa.y - pd.y;
3073- double bdx = pb.x - pd.x;
3074- double bdy = pb.y - pd.y;
3075-
3076- double adxbdy = adx * bdy;
3077- double bdxady = bdx * ady;
3078- double oabd = adxbdy - bdxady;
3079-
3080- if (oabd <= 0)
3081- return false;
3082-
3083- double cdx = pc.x - pd.x;
3084- double cdy = pc.y - pd.y;
3085-
3086- double cdxady = cdx * ady;
3087- double adxcdy = adx * cdy;
3088- double ocad = cdxady - adxcdy;
3089-
3090- if (ocad <= 0)
3091- return false;
3092-
3093- double bdxcdy = bdx * cdy;
3094- double cdxbdy = cdx * bdy;
3095-
3096- double alift = adx * adx + ady * ady;
3097- double blift = bdx * bdx + bdy * bdy;
3098- double clift = cdx * cdx + cdy * cdy;
3099-
3100- double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
3101-
3102- return det > 0;
3103-}
3104-
3105-void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op)
3106-{
3107- Triangle* n1, *n2, *n3, *n4;
3108- n1 = t.NeighborCCW(p);
3109- n2 = t.NeighborCW(p);
3110- n3 = ot.NeighborCCW(op);
3111- n4 = ot.NeighborCW(op);
3112-
3113- bool ce1, ce2, ce3, ce4;
3114- ce1 = t.GetConstrainedEdgeCCW(p);
3115- ce2 = t.GetConstrainedEdgeCW(p);
3116- ce3 = ot.GetConstrainedEdgeCCW(op);
3117- ce4 = ot.GetConstrainedEdgeCW(op);
3118-
3119- bool de1, de2, de3, de4;
3120- de1 = t.GetDelunayEdgeCCW(p);
3121- de2 = t.GetDelunayEdgeCW(p);
3122- de3 = ot.GetDelunayEdgeCCW(op);
3123- de4 = ot.GetDelunayEdgeCW(op);
3124-
3125- t.Legalize(p, op);
3126- ot.Legalize(op, p);
3127-
3128- // Remap delaunay_edge
3129- ot.SetDelunayEdgeCCW(p, de1);
3130- t.SetDelunayEdgeCW(p, de2);
3131- t.SetDelunayEdgeCCW(op, de3);
3132- ot.SetDelunayEdgeCW(op, de4);
3133-
3134- // Remap constrained_edge
3135- ot.SetConstrainedEdgeCCW(p, ce1);
3136- t.SetConstrainedEdgeCW(p, ce2);
3137- t.SetConstrainedEdgeCCW(op, ce3);
3138- ot.SetConstrainedEdgeCW(op, ce4);
3139-
3140- // Remap neighbors
3141- // XXX: might optimize the markNeighbor by keeping track of
3142- // what side should be assigned to what neighbor after the
3143- // rotation. Now mark neighbor does lots of testing to find
3144- // the right side.
3145- t.ClearNeighbors();
3146- ot.ClearNeighbors();
3147- if (n1) ot.MarkNeighbor(*n1);
3148- if (n2) t.MarkNeighbor(*n2);
3149- if (n3) t.MarkNeighbor(*n3);
3150- if (n4) ot.MarkNeighbor(*n4);
3151- t.MarkNeighbor(ot);
3152-}
3153-
3154-void Sweep::FillBasin(SweepContext& tcx, Node& node)
3155-{
3156- if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {
3157- tcx.basin.left_node = node.next->next;
3158- } else {
3159- tcx.basin.left_node = node.next;
3160- }
3161-
3162- // Find the bottom and right node
3163- tcx.basin.bottom_node = tcx.basin.left_node;
3164- while (tcx.basin.bottom_node->next
3165- && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) {
3166- tcx.basin.bottom_node = tcx.basin.bottom_node->next;
3167- }
3168- if (tcx.basin.bottom_node == tcx.basin.left_node) {
3169- // No valid basin
3170- return;
3171- }
3172-
3173- tcx.basin.right_node = tcx.basin.bottom_node;
3174- while (tcx.basin.right_node->next
3175- && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) {
3176- tcx.basin.right_node = tcx.basin.right_node->next;
3177- }
3178- if (tcx.basin.right_node == tcx.basin.bottom_node) {
3179- // No valid basins
3180- return;
3181- }
3182-
3183- tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x;
3184- tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y;
3185-
3186- FillBasinReq(tcx, tcx.basin.bottom_node);
3187-}
3188-
3189-void Sweep::FillBasinReq(SweepContext& tcx, Node* node)
3190-{
3191- // if shallow stop filling
3192- if (IsShallow(tcx, *node)) {
3193- return;
3194- }
3195-
3196- Fill(tcx, *node);
3197-
3198- if (node->prev == tcx.basin.left_node && node->next == tcx.basin.right_node) {
3199- return;
3200- } else if (node->prev == tcx.basin.left_node) {
3201- Orientation o = Orient2d(*node->point, *node->next->point, *node->next->next->point);
3202- if (o == CW) {
3203- return;
3204- }
3205- node = node->next;
3206- } else if (node->next == tcx.basin.right_node) {
3207- Orientation o = Orient2d(*node->point, *node->prev->point, *node->prev->prev->point);
3208- if (o == CCW) {
3209- return;
3210- }
3211- node = node->prev;
3212- } else {
3213- // Continue with the neighbor node with lowest Y value
3214- if (node->prev->point->y < node->next->point->y) {
3215- node = node->prev;
3216- } else {
3217- node = node->next;
3218- }
3219- }
3220-
3221- FillBasinReq(tcx, node);
3222-}
3223-
3224-bool Sweep::IsShallow(SweepContext& tcx, Node& node)
3225-{
3226- double height;
3227-
3228- if (tcx.basin.left_highest) {
3229- height = tcx.basin.left_node->point->y - node.point->y;
3230- } else {
3231- height = tcx.basin.right_node->point->y - node.point->y;
3232- }
3233-
3234- // if shallow stop filling
3235- if (tcx.basin.width > height) {
3236- return true;
3237- }
3238- return false;
3239-}
3240-
3241-void Sweep::FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node)
3242-{
3243- if (tcx.edge_event.right) {
3244- FillRightAboveEdgeEvent(tcx, edge, node);
3245- } else {
3246- FillLeftAboveEdgeEvent(tcx, edge, node);
3247- }
3248-}
3249-
3250-void Sweep::FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node)
3251-{
3252- while (node->next->point->x < edge->p->x) {
3253- // Check if next node is below the edge
3254- if (Orient2d(*edge->q, *node->next->point, *edge->p) == CCW) {
3255- FillRightBelowEdgeEvent(tcx, edge, *node);
3256- } else {
3257- node = node->next;
3258- }
3259- }
3260-}
3261-
3262-void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
3263-{
3264- if (node.point->x < edge->p->x) {
3265- if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {
3266- // Concave
3267- FillRightConcaveEdgeEvent(tcx, edge, node);
3268- } else{
3269- // Convex
3270- FillRightConvexEdgeEvent(tcx, edge, node);
3271- // Retry this one
3272- FillRightBelowEdgeEvent(tcx, edge, node);
3273- }
3274- }
3275-}
3276-
3277-void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
3278-{
3279- Fill(tcx, *node.next);
3280- if (node.next->point != edge->p) {
3281- // Next above or below edge?
3282- if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) {
3283- // Below
3284- if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {
3285- // Next is concave
3286- FillRightConcaveEdgeEvent(tcx, edge, node);
3287- } else {
3288- // Next is convex
3289- }
3290- }
3291- }
3292-
3293-}
3294-
3295-void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
3296-{
3297- // Next concave or convex?
3298- if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) {
3299- // Concave
3300- FillRightConcaveEdgeEvent(tcx, edge, *node.next);
3301- } else{
3302- // Convex
3303- // Next above or below edge?
3304- if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) {
3305- // Below
3306- FillRightConvexEdgeEvent(tcx, edge, *node.next);
3307- } else{
3308- // Above
3309- }
3310- }
3311-}
3312-
3313-void Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node)
3314-{
3315- while (node->prev->point->x > edge->p->x) {
3316- // Check if next node is below the edge
3317- if (Orient2d(*edge->q, *node->prev->point, *edge->p) == CW) {
3318- FillLeftBelowEdgeEvent(tcx, edge, *node);
3319- } else {
3320- node = node->prev;
3321- }
3322- }
3323-}
3324-
3325-void Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
3326-{
3327- if (node.point->x > edge->p->x) {
3328- if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) {
3329- // Concave
3330- FillLeftConcaveEdgeEvent(tcx, edge, node);
3331- } else {
3332- // Convex
3333- FillLeftConvexEdgeEvent(tcx, edge, node);
3334- // Retry this one
3335- FillLeftBelowEdgeEvent(tcx, edge, node);
3336- }
3337- }
3338-}
3339-
3340-void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
3341-{
3342- // Next concave or convex?
3343- if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) {
3344- // Concave
3345- FillLeftConcaveEdgeEvent(tcx, edge, *node.prev);
3346- } else{
3347- // Convex
3348- // Next above or below edge?
3349- if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) {
3350- // Below
3351- FillLeftConvexEdgeEvent(tcx, edge, *node.prev);
3352- } else{
3353- // Above
3354- }
3355- }
3356-}
3357-
3358-void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
3359-{
3360- Fill(tcx, *node.prev);
3361- if (node.prev->point != edge->p) {
3362- // Next above or below edge?
3363- if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) {
3364- // Below
3365- if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) {
3366- // Next is concave
3367- FillLeftConcaveEdgeEvent(tcx, edge, node);
3368- } else{
3369- // Next is convex
3370- }
3371- }
3372- }
3373-
3374-}
3375-
3376-void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p)
3377-{
3378- Triangle* ot = t->NeighborAcross(p);
3379- Point& op = *ot->OppositePoint(*t, p);
3380-
3381- if (ot == nullptr) {
3382- throw std::runtime_error("Polygon contains overlapping hole vertices.");
3383- }
3384-
3385- if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) {
3386- // Lets rotate shared edge one vertex CW
3387- RotateTrianglePair(*t, p, *ot, op);
3388- tcx.MapTriangleToNodes(*t);
3389- tcx.MapTriangleToNodes(*ot);
3390-
3391- if (p == eq && op == ep) {
3392- if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) {
3393- t->MarkConstrainedEdge(&ep, &eq);
3394- ot->MarkConstrainedEdge(&ep, &eq);
3395- Legalize(tcx, *t);
3396- Legalize(tcx, *ot);
3397- } else {
3398- // XXX: I think one of the triangles should be legalized here?
3399- }
3400- } else {
3401- Orientation o = Orient2d(eq, op, ep);
3402- t = &NextFlipTriangle(tcx, (int)o, *t, *ot, p, op);
3403- FlipEdgeEvent(tcx, ep, eq, t, p);
3404- }
3405- } else {
3406- Point& newP = NextFlipPoint(ep, eq, *ot, op);
3407- FlipScanEdgeEvent(tcx, ep, eq, *t, *ot, newP);
3408- EdgeEvent(tcx, ep, eq, t, p);
3409- }
3410-}
3411-
3412-Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op)
3413-{
3414- if (o == CCW) {
3415- // ot is not crossing edge after flip
3416- int edge_index = ot.EdgeIndex(&p, &op);
3417-
3418- if(edge_index < 0)
3419- throw std::runtime_error("Edge not found in the triangle");
3420-
3421- ot.delaunay_edge[edge_index] = true;
3422- Legalize(tcx, ot);
3423- ot.ClearDelunayEdges();
3424- return t;
3425- }
3426-
3427- // t is not crossing edge after flip
3428- int edge_index = t.EdgeIndex(&p, &op);
3429-
3430- if(edge_index < 0)
3431- throw std::runtime_error("Edge not found in the triangle");
3432-
3433- t.delaunay_edge[edge_index] = true;
3434- Legalize(tcx, t);
3435- t.ClearDelunayEdges();
3436- return ot;
3437-}
3438-
3439-Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
3440-{
3441- Orientation o2d = Orient2d(eq, op, ep);
3442- if (o2d == CW) {
3443- // Right
3444- return *ot.PointCCW(op);
3445- } else if (o2d == CCW) {
3446- // Left
3447- return *ot.PointCW(op);
3448- } else{
3449- throw std::runtime_error("Polygon contains overlapping hole vertices.");
3450- return ep; // Arbitrary return val -- fixes warning
3451- }
3452-}
3453-
3454-void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
3455- Triangle& t, Point& p)
3456-{
3457- Triangle* ot = t.NeighborAcross(p);
3458- Point& op = *ot->OppositePoint(t, p);
3459-
3460- if (ot == NULL) {
3461- throw std::runtime_error("Polygon contains overlapping hole vertices.");
3462- }
3463-
3464- if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) {
3465- // flip with new edge op->eq
3466- FlipEdgeEvent(tcx, eq, op, ot, op);
3467- // TODO: Actually I just figured out that it should be possible to
3468- // improve this by getting the next ot and op before the the above
3469- // flip and continue the flipScanEdgeEvent here
3470- // set new ot and op here and loop back to inScanArea test
3471- // also need to set a new flip_triangle first
3472- // Turns out at first glance that this is somewhat complicated
3473- // so it will have to wait.
3474- } else{
3475- Point& newP = NextFlipPoint(ep, eq, *ot, op);
3476- FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, *ot, newP);
3477- }
3478-}
3479-
3480-Sweep::~Sweep() {
3481-
3482- // Clean up memory
3483- for(unsigned i = 0; i < nodes_.size(); i++) {
3484- delete nodes_[i];
3485- }
3486-
3487-}
3488-
3489-}
3490diff --git a/polygon/poly2tri/sweep/sweep.h b/polygon/poly2tri/sweep/sweep.h
3491deleted file mode 100644
3492index f62c4cc..0000000
3493--- a/polygon/poly2tri/sweep/sweep.h
3494+++ /dev/null
3495@@ -1,285 +0,0 @@
3496-/*
3497- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
3498- * http://code.google.com/p/poly2tri/
3499- *
3500- * All rights reserved.
3501- *
3502- * Redistribution and use in source and binary forms, with or without modification,
3503- * are permitted provided that the following conditions are met:
3504- *
3505- * * Redistributions of source code must retain the above copyright notice,
3506- * this list of conditions and the following disclaimer.
3507- * * Redistributions in binary form must reproduce the above copyright notice,
3508- * this list of conditions and the following disclaimer in the documentation
3509- * and/or other materials provided with the distribution.
3510- * * Neither the name of Poly2Tri nor the names of its contributors may be
3511- * used to endorse or promote products derived from this software without specific
3512- * prior written permission.
3513- *
3514- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3515- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3516- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3517- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
3518- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
3519- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3520- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3521- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3522- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3523- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3524- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3525- */
3526-/**
3527- * Sweep-line, Constrained Delauney Triangulation (CDT) See: Domiter, V. and
3528- * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
3529- * International Journal of Geographical Information Science
3530- *
3531- * "FlipScan" Constrained Edge Algorithm invented by Thomas �hl�n, thahlen@gmail.com
3532- */
3533-
3534-#ifndef SWEEP_H
3535-#define SWEEP_H
3536-
3537-#include <vector>
3538-
3539-namespace p2t {
3540-
3541-class SweepContext;
3542-struct Node;
3543-struct Point;
3544-struct Edge;
3545-class Triangle;
3546-
3547-class Sweep
3548-{
3549-public:
3550-
3551- /**
3552- * Triangulate
3553- *
3554- * @param tcx
3555- */
3556- void Triangulate(SweepContext& tcx);
3557-
3558- /**
3559- * Destructor - clean up memory
3560- */
3561- ~Sweep();
3562-
3563-private:
3564-
3565- /**
3566- * Start sweeping the Y-sorted point set from bottom to top
3567- *
3568- * @param tcx
3569- */
3570- void SweepPoints(SweepContext& tcx);
3571-
3572- /**
3573- * Find closes node to the left of the new point and
3574- * create a new triangle. If needed new holes and basins
3575- * will be filled to.
3576- *
3577- * @param tcx
3578- * @param point
3579- * @return
3580- */
3581- Node& PointEvent(SweepContext& tcx, Point& point);
3582-
3583- /**
3584- *
3585- *
3586- * @param tcx
3587- * @param edge
3588- * @param node
3589- */
3590- void EdgeEvent(SweepContext& tcx, Edge* edge, Node* node);
3591-
3592- void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point);
3593-
3594- /**
3595- * Creates a new front triangle and legalize it
3596- *
3597- * @param tcx
3598- * @param point
3599- * @param node
3600- * @return
3601- */
3602- Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node);
3603-
3604- /**
3605- * Adds a triangle to the advancing front to fill a hole.
3606- * @param tcx
3607- * @param node - middle node, that is the bottom of the hole
3608- */
3609- void Fill(SweepContext& tcx, Node& node);
3610-
3611- /**
3612- * Returns true if triangle was legalized
3613- */
3614- bool Legalize(SweepContext& tcx, Triangle& t);
3615-
3616- /**
3617- * <b>Requirement</b>:<br>
3618- * 1. a,b and c form a triangle.<br>
3619- * 2. a and d is know to be on opposite side of bc<br>
3620- * <pre>
3621- * a
3622- * +
3623- * / \
3624- * / \
3625- * b/ \c
3626- * +-------+
3627- * / d \
3628- * / \
3629- * </pre>
3630- * <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by
3631- * a,b and c<br>
3632- * d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br>
3633- * This preknowledge gives us a way to optimize the incircle test
3634- * @param a - triangle point, opposite d
3635- * @param b - triangle point
3636- * @param c - triangle point
3637- * @param d - point opposite a
3638- * @return true if d is inside circle, false if on circle edge
3639- */
3640- bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd);
3641-
3642- /**
3643- * Rotates a triangle pair one vertex CW
3644- *<pre>
3645- * n2 n2
3646- * P +-----+ P +-----+
3647- * | t /| |\ t |
3648- * | / | | \ |
3649- * n1| / |n3 n1| \ |n3
3650- * | / | after CW | \ |
3651- * |/ oT | | oT \|
3652- * +-----+ oP +-----+
3653- * n4 n4
3654- * </pre>
3655- */
3656- void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op);
3657-
3658- /**
3659- * Fills holes in the Advancing Front
3660- *
3661- *
3662- * @param tcx
3663- * @param n
3664- */
3665- void FillAdvancingFront(SweepContext& tcx, Node& n);
3666-
3667- // Decision-making about when to Fill hole.
3668- // Contributed by ToolmakerSteve2
3669- bool LargeHole_DontFill(Node* node);
3670- bool AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb);
3671- bool AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb);
3672- double Angle(Point& origin, Point& pa, Point& pb);
3673-
3674- /**
3675- *
3676- * @param node - middle node
3677- * @return the angle between 3 front nodes
3678- */
3679- double HoleAngle(Node& node);
3680-
3681- /**
3682- * The basin angle is decided against the horizontal line [1,0]
3683- */
3684- double BasinAngle(Node& node);
3685-
3686- /**
3687- * Fills a basin that has formed on the Advancing Front to the right
3688- * of given node.<br>
3689- * First we decide a left,bottom and right node that forms the
3690- * boundaries of the basin. Then we do a reqursive fill.
3691- *
3692- * @param tcx
3693- * @param node - starting node, this or next node will be left node
3694- */
3695- void FillBasin(SweepContext& tcx, Node& node);
3696-
3697- /**
3698- * Recursive algorithm to fill a Basin with triangles
3699- *
3700- * @param tcx
3701- * @param node - bottom_node
3702- * @param cnt - counter used to alternate on even and odd numbers
3703- */
3704- void FillBasinReq(SweepContext& tcx, Node* node);
3705-
3706- bool IsShallow(SweepContext& tcx, Node& node);
3707-
3708- bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq);
3709-
3710- void FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node);
3711-
3712- void FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node);
3713-
3714- void FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
3715-
3716- void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
3717-
3718- void FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
3719-
3720- void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node);
3721-
3722- void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
3723-
3724- void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
3725-
3726- void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
3727-
3728- void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p);
3729-
3730- /**
3731- * After a flip we have two triangles and know that only one will still be
3732- * intersecting the edge. So decide which to contiune with and legalize the other
3733- *
3734- * @param tcx
3735- * @param o - should be the result of an orient2d( eq, op, ep )
3736- * @param t - triangle 1
3737- * @param ot - triangle 2
3738- * @param p - a point shared by both triangles
3739- * @param op - another point shared by both triangles
3740- * @return returns the triangle still intersecting the edge
3741- */
3742- Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op);
3743-
3744- /**
3745- * When we need to traverse from one triangle to the next we need
3746- * the point in current triangle that is the opposite point to the next
3747- * triangle.
3748- *
3749- * @param ep
3750- * @param eq
3751- * @param ot
3752- * @param op
3753- * @return
3754- */
3755- Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op);
3756-
3757- /**
3758- * Scan part of the FlipScan algorithm<br>
3759- * When a triangle pair isn't flippable we will scan for the next
3760- * point that is inside the flip triangle scan area. When found
3761- * we generate a new flipEdgeEvent
3762- *
3763- * @param tcx
3764- * @param ep - last point on the edge we are traversing
3765- * @param eq - first point on the edge we are traversing
3766- * @param flipTriangle - the current triangle sharing the point eq with edge
3767- * @param t
3768- * @param p
3769- */
3770- void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p);
3771-
3772- void FinalizationPolygon(SweepContext& tcx);
3773-
3774- std::vector<Node*> nodes_;
3775-
3776-};
3777-
3778-}
3779-
3780-#endif
3781diff --git a/polygon/poly2tri/sweep/sweep_context.cc b/polygon/poly2tri/sweep/sweep_context.cc
3782deleted file mode 100644
3783index fe5f06b..0000000
3784--- a/polygon/poly2tri/sweep/sweep_context.cc
3785+++ /dev/null
3786@@ -1,217 +0,0 @@
3787-/*
3788- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
3789- * http://code.google.com/p/poly2tri/
3790- *
3791- * All rights reserved.
3792- *
3793- * Redistribution and use in source and binary forms, with or without modification,
3794- * are permitted provided that the following conditions are met:
3795- *
3796- * * Redistributions of source code must retain the above copyright notice,
3797- * this list of conditions and the following disclaimer.
3798- * * Redistributions in binary form must reproduce the above copyright notice,
3799- * this list of conditions and the following disclaimer in the documentation
3800- * and/or other materials provided with the distribution.
3801- * * Neither the name of Poly2Tri nor the names of its contributors may be
3802- * used to endorse or promote products derived from this software without specific
3803- * prior written permission.
3804- *
3805- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3806- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3807- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3808- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
3809- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
3810- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3811- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3812- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3813- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3814- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3815- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3816- */
3817-#include "sweep_context.h"
3818-#include <algorithm>
3819-#include <utility>
3820-#include "advancing_front.h"
3821-
3822-namespace p2t {
3823-
3824-SweepContext::SweepContext(std::vector<Point*> polyline) :
3825- front_(0),
3826- head_(0),
3827- tail_(0),
3828- af_head_(0),
3829- af_middle_(0),
3830- af_tail_(0)
3831-{
3832- basin = Basin();
3833- edge_event = EdgeEvent();
3834-
3835- points_ = std::move( polyline );
3836-
3837- InitEdges(points_);
3838-}
3839-
3840-void SweepContext::AddHole(std::vector<Point*> polyline)
3841-{
3842- InitEdges(polyline);
3843- for(unsigned int i = 0; i < polyline.size(); i++) {
3844- points_.push_back(polyline[i]);
3845- }
3846-}
3847-
3848-void SweepContext::AddPoint(Point* point) {
3849- points_.push_back(point);
3850-}
3851-
3852-std::vector<Triangle*> SweepContext::GetTriangles()
3853-{
3854- return triangles_;
3855-}
3856-
3857-std::list<Triangle*> SweepContext::GetMap()
3858-{
3859- return map_;
3860-}
3861-
3862-void SweepContext::InitTriangulation()
3863-{
3864- double xmax(points_[0]->x), xmin(points_[0]->x);
3865- double ymax(points_[0]->y), ymin(points_[0]->y);
3866-
3867- // Calculate bounds.
3868- for (unsigned int i = 0; i < points_.size(); i++) {
3869- Point& p = *points_[i];
3870- if (p.x > xmax)
3871- xmax = p.x;
3872- if (p.x < xmin)
3873- xmin = p.x;
3874- if (p.y > ymax)
3875- ymax = p.y;
3876- if (p.y < ymin)
3877- ymin = p.y;
3878- }
3879-
3880- double dx = kAlpha * (xmax - xmin);
3881- double dy = kAlpha * (ymax - ymin);
3882- head_ = new Point(xmax + dx, ymin - dy);
3883- tail_ = new Point(xmin - dx, ymin - dy);
3884-
3885- // Sort points along y-axis
3886- std::sort(points_.begin(), points_.end(), cmp);
3887-
3888-}
3889-
3890-void SweepContext::InitEdges(std::vector<Point*> polyline)
3891-{
3892- int num_points = polyline.size();
3893- for (int i = 0; i < num_points; i++) {
3894- int j = i < num_points - 1 ? i + 1 : 0;
3895- edge_list.push_back(new Edge(*polyline[i], *polyline[j]));
3896- }
3897-}
3898-
3899-Point* SweepContext::GetPoint(const int& index)
3900-{
3901- return points_[index];
3902-}
3903-
3904-void SweepContext::AddToMap(Triangle* triangle)
3905-{
3906- map_.push_back(triangle);
3907-}
3908-
3909-Node& SweepContext::LocateNode(Point& point)
3910-{
3911- // TODO implement search tree
3912- return *front_->LocateNode(point.x);
3913-}
3914-
3915-void SweepContext::CreateAdvancingFront(std::vector<Node*> nodes)
3916-{
3917-
3918- (void) nodes;
3919- // Initial triangle
3920- Triangle* triangle = new Triangle(*points_[0], *tail_, *head_);
3921-
3922- map_.push_back(triangle);
3923-
3924- af_head_ = new Node(*triangle->GetPoint(1), *triangle);
3925- af_middle_ = new Node(*triangle->GetPoint(0), *triangle);
3926- af_tail_ = new Node(*triangle->GetPoint(2));
3927- front_ = new AdvancingFront(*af_head_, *af_tail_);
3928-
3929- // TODO: More intuitive if head is middles next and not previous?
3930- // so swap head and tail
3931- af_head_->next = af_middle_;
3932- af_middle_->next = af_tail_;
3933- af_middle_->prev = af_head_;
3934- af_tail_->prev = af_middle_;
3935-}
3936-
3937-void SweepContext::RemoveNode(Node* node)
3938-{
3939- delete node;
3940-}
3941-
3942-void SweepContext::MapTriangleToNodes(Triangle& t)
3943-{
3944- for (int i = 0; i < 3; i++) {
3945- if (!t.GetNeighbor(i)) {
3946- Node* n = front_->LocatePoint(t.PointCW(*t.GetPoint(i)));
3947- if (n)
3948- n->triangle = &t;
3949- }
3950- }
3951-}
3952-
3953-void SweepContext::RemoveFromMap(Triangle* triangle)
3954-{
3955- map_.remove(triangle);
3956-}
3957-
3958-void SweepContext::MeshClean(Triangle& triangle)
3959-{
3960- std::vector<Triangle *> triangles;
3961- triangles.push_back(&triangle);
3962-
3963- while(!triangles.empty()){
3964- Triangle *t = triangles.back();
3965- triangles.pop_back();
3966-
3967- if (t != NULL && !t->IsInterior()) {
3968- t->IsInterior(true);
3969- triangles_.push_back(t);
3970- for (int i = 0; i < 3; i++) {
3971- if (!t->constrained_edge[i])
3972- triangles.push_back(t->GetNeighbor(i));
3973- }
3974- }
3975- }
3976-}
3977-
3978-SweepContext::~SweepContext()
3979-{
3980-
3981- // Clean up memory
3982-
3983- delete head_;
3984- delete tail_;
3985- delete front_;
3986- delete af_head_;
3987- delete af_middle_;
3988- delete af_tail_;
3989-
3990- typedef std::list<Triangle*> type_list;
3991-
3992- for(type_list::iterator iter = map_.begin(); iter != map_.end(); ++iter) {
3993- Triangle* ptr = *iter;
3994- delete ptr;
3995- }
3996-
3997- for(unsigned int i = 0; i < edge_list.size(); i++) {
3998- delete edge_list[i];
3999- }
4000-
4001-}
4002-
4003-}
4004diff --git a/polygon/poly2tri/sweep/sweep_context.h b/polygon/poly2tri/sweep/sweep_context.h
4005deleted file mode 100644
4006index 1010c0e..0000000
4007--- a/polygon/poly2tri/sweep/sweep_context.h
4008+++ /dev/null
4009@@ -1,186 +0,0 @@
4010-/*
4011- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
4012- * http://code.google.com/p/poly2tri/
4013- *
4014- * All rights reserved.
4015- *
4016- * Redistribution and use in source and binary forms, with or without modification,
4017- * are permitted provided that the following conditions are met:
4018- *
4019- * * Redistributions of source code must retain the above copyright notice,
4020- * this list of conditions and the following disclaimer.
4021- * * Redistributions in binary form must reproduce the above copyright notice,
4022- * this list of conditions and the following disclaimer in the documentation
4023- * and/or other materials provided with the distribution.
4024- * * Neither the name of Poly2Tri nor the names of its contributors may be
4025- * used to endorse or promote products derived from this software without specific
4026- * prior written permission.
4027- *
4028- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4029- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4030- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4031- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
4032- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4033- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
4034- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
4035- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
4036- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4037- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4038- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4039- */
4040-
4041-#ifndef SWEEP_CONTEXT_H
4042-#define SWEEP_CONTEXT_H
4043-
4044-#include <list>
4045-#include <vector>
4046-#include <cstddef>
4047-
4048-namespace p2t {
4049-
4050-// Inital triangle factor, seed triangle will extend 30% of
4051-// PointSet width to both left and right.
4052-const double kAlpha = 0.3;
4053-
4054-struct Point;
4055-class Triangle;
4056-struct Node;
4057-struct Edge;
4058-class AdvancingFront;
4059-
4060-class SweepContext {
4061-public:
4062-
4063-/// Constructor
4064-SweepContext(std::vector<Point*> polyline);
4065-/// Destructor
4066-~SweepContext();
4067-
4068-void set_head(Point* p1);
4069-
4070-Point* head();
4071-
4072-void set_tail(Point* p1);
4073-
4074-Point* tail();
4075-
4076-int point_count();
4077-
4078-Node& LocateNode(Point& point);
4079-
4080-void RemoveNode(Node* node);
4081-
4082-void CreateAdvancingFront(std::vector<Node*> nodes);
4083-
4084-/// Try to map a node to all sides of this triangle that don't have a neighbor
4085-void MapTriangleToNodes(Triangle& t);
4086-
4087-void AddToMap(Triangle* triangle);
4088-
4089-Point* GetPoint(const int& index);
4090-
4091-Point* GetPoints();
4092-
4093-void RemoveFromMap(Triangle* triangle);
4094-
4095-void AddHole(std::vector<Point*> polyline);
4096-
4097-void AddPoint(Point* point);
4098-
4099-AdvancingFront* front();
4100-
4101-void MeshClean(Triangle& triangle);
4102-
4103-std::vector<Triangle*> GetTriangles();
4104-std::list<Triangle*> GetMap();
4105-
4106-std::vector<Edge*> edge_list;
4107-
4108-struct Basin {
4109- Node* left_node;
4110- Node* bottom_node;
4111- Node* right_node;
4112- double width;
4113- bool left_highest;
4114-
4115- Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false)
4116- {
4117- }
4118-
4119- void Clear()
4120- {
4121- left_node = NULL;
4122- bottom_node = NULL;
4123- right_node = NULL;
4124- width = 0.0;
4125- left_highest = false;
4126- }
4127-};
4128-
4129-struct EdgeEvent {
4130- Edge* constrained_edge;
4131- bool right;
4132-
4133- EdgeEvent() : constrained_edge(NULL), right(false)
4134- {
4135- }
4136-};
4137-
4138-Basin basin;
4139-EdgeEvent edge_event;
4140-
4141-private:
4142-
4143-friend class Sweep;
4144-
4145-std::vector<Triangle*> triangles_;
4146-std::list<Triangle*> map_;
4147-std::vector<Point*> points_;
4148-
4149-// Advancing front
4150-AdvancingFront* front_;
4151-// head point used with advancing front
4152-Point* head_;
4153-// tail point used with advancing front
4154-Point* tail_;
4155-
4156-Node *af_head_, *af_middle_, *af_tail_;
4157-
4158-void InitTriangulation();
4159-void InitEdges(std::vector<Point*> polyline);
4160-
4161-};
4162-
4163-inline AdvancingFront* SweepContext::front()
4164-{
4165- return front_;
4166-}
4167-
4168-inline int SweepContext::point_count()
4169-{
4170- return points_.size();
4171-}
4172-
4173-inline void SweepContext::set_head(Point* p1)
4174-{
4175- head_ = p1;
4176-}
4177-
4178-inline Point* SweepContext::head()
4179-{
4180- return head_;
4181-}
4182-
4183-inline void SweepContext::set_tail(Point* p1)
4184-{
4185- tail_ = p1;
4186-}
4187-
4188-inline Point* SweepContext::tail()
4189-{
4190- return tail_;
4191-}
4192-
4193-}
4194-
4195-#endif

Subscribers

People subscribed via source and target branches

to status/vote changes: