├── .gitignore
├── LICENSE
├── Poly2Tri.Test
├── Poly2Tri.Test.csproj
└── Properties
│ └── AssemblyInfo.cs
├── Poly2Tri.sln
├── Poly2Tri
├── P2T.cs
├── Poly2Tri.csproj
├── Poly2Tri.nuspec
├── Properties
│ └── AssemblyInfo.cs
├── Triangulation
│ ├── Delaunay
│ │ ├── DelaunayTriangle.cs
│ │ └── Sweep
│ │ │ ├── AdvancingFront.cs
│ │ │ ├── AdvancingFrontNode.cs
│ │ │ ├── DTSweep.cs
│ │ │ ├── DTSweepBasin.cs
│ │ │ ├── DTSweepConstraint.cs
│ │ │ ├── DTSweepContext.cs
│ │ │ ├── DTSweepDebugContext.cs
│ │ │ ├── DTSweepEdgeEvent.cs
│ │ │ ├── DTSweepPointComparator.cs
│ │ │ └── PointOnEdgeException.cs
│ ├── ITriangulatable.cs
│ ├── Orientation.cs
│ ├── Polygon
│ │ ├── Contour.cs
│ │ ├── Polygon.cs
│ │ ├── PolygonPoint.cs
│ │ └── PolygonUtil.cs
│ ├── Sets
│ │ ├── ConstrainedPointSet.cs
│ │ └── PointSet.cs
│ ├── TriangulationAlgorithm.cs
│ ├── TriangulationConstraint.cs
│ ├── TriangulationContext.cs
│ ├── TriangulationDebugContext.cs
│ ├── TriangulationMode.cs
│ ├── TriangulationPoint.cs
│ └── Util
│ │ ├── PointGenerator.cs
│ │ ├── PolygonGenerator.cs
│ │ └── TriangulationUtil.cs
└── Utility
│ ├── FixedArray3.cs
│ ├── MathUtil.cs
│ ├── Point2D.cs
│ ├── Point2DList.cs
│ └── Rect2D.cs
├── push-all.ps1
└── readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.user
2 | *.suo
3 | *.ncrunchsolution
4 | *.ncrunchproject
5 | *.cache
6 | _Resharper.Caches
7 | _Resharper.Poly2Tri
8 |
9 | Poly2Tri/bin
10 | Poly2Tri/obj
11 |
12 | Poly2Tri.Test/bin
13 | Poly2Tri.Test/obj
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
2 |
3 | All rights reserved.
4 | Redistribution and use in source and binary forms, with or without modification,
5 | are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice,
8 | this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 | * Neither the name of Poly2Tri nor the names of its contributors may be
13 | used to endorse or promote products derived from this software without specific
14 | prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/Poly2Tri.Test/Poly2Tri.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {F5BF959A-8FBF-4336-BDBD-F76E281AFACA}
7 | Library
8 | Properties
9 | Poly2Tri.Test
10 | Poly2Tri.Test
11 | v4.5.2
12 | 512
13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 10.0
15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
17 | False
18 | UnitTest
19 |
20 |
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 |
29 |
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | {a21a4d0a-f045-4736-96a7-0053bea98410}
58 | Poly2Tri
59 |
60 |
61 |
62 |
63 |
64 |
65 | False
66 |
67 |
68 | False
69 |
70 |
71 | False
72 |
73 |
74 | False
75 |
76 |
77 |
78 |
79 |
80 |
81 |
88 |
--------------------------------------------------------------------------------
/Poly2Tri.Test/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Poly2Tri.Test")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Poly2Tri.Test")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("f5bf959a-8fbf-4336-bdbd-f76e281afaca")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Poly2Tri.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Poly2Tri", "Poly2Tri\Poly2Tri.csproj", "{A21A4D0A-F045-4736-96A7-0053BEA98410}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Poly2Tri.Test", "Poly2Tri.Test\Poly2Tri.Test.csproj", "{F5BF959A-8FBF-4336-BDBD-F76E281AFACA}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {A21A4D0A-F045-4736-96A7-0053BEA98410}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {A21A4D0A-F045-4736-96A7-0053BEA98410}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {A21A4D0A-F045-4736-96A7-0053BEA98410}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {A21A4D0A-F045-4736-96A7-0053BEA98410}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {F5BF959A-8FBF-4336-BDBD-F76E281AFACA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {F5BF959A-8FBF-4336-BDBD-F76E281AFACA}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {F5BF959A-8FBF-4336-BDBD-F76E281AFACA}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {F5BF959A-8FBF-4336-BDBD-F76E281AFACA}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/Poly2Tri/P2T.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System.Collections.Generic;
33 | using Poly2Tri.Triangulation;
34 | using Poly2Tri.Triangulation.Delaunay.Sweep;
35 | using Poly2Tri.Triangulation.Polygon;
36 |
37 | namespace Poly2Tri
38 | {
39 | public static class P2T
40 | {
41 | private const TriangulationAlgorithm DEFAULT_ALGORITHM = TriangulationAlgorithm.DTSweep;
42 |
43 | public static void Triangulate(IEnumerable polygons)
44 | {
45 | foreach (var p in polygons)
46 | Triangulate(p);
47 | }
48 |
49 | private static TriangulationContext CreateContext(TriangulationAlgorithm algorithm)
50 | {
51 | switch (algorithm)
52 | {
53 | default:
54 | return new DTSweepContext();
55 | }
56 | }
57 |
58 | public static void Triangulate(ITriangulatable t, TriangulationAlgorithm algorithm = DEFAULT_ALGORITHM)
59 | {
60 | TriangulationContext tcx = CreateContext(algorithm);
61 | tcx.PrepareTriangulation(t);
62 | Triangulate(tcx);
63 | }
64 |
65 | private static void Triangulate(TriangulationContext tcx)
66 | {
67 | switch (tcx.Algorithm)
68 | {
69 | default:
70 | DTSweep.Triangulate((DTSweepContext)tcx);
71 | break;
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Poly2Tri/Poly2Tri.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {A21A4D0A-F045-4736-96A7-0053BEA98410}
8 | Library
9 | Properties
10 | Poly2Tri
11 | Poly2Tri
12 | v3.5
13 | 512
14 | Client
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
88 |
--------------------------------------------------------------------------------
/Poly2Tri/Poly2Tri.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $id$
5 | $version$
6 | https://code.google.com/p/poly2tri/people/list
7 | https://code.google.com/p/poly2tri/people/detail?u=113158675721513411716
8 | http://opensource.org/licenses/BSD-3-Clause
9 | https://code.google.com/p/poly2tri/
10 | false
11 | $description$
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Poly2Tri/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("Poly2Tri")]
8 | [assembly: AssemblyDescription("A 2D constrained Delaunay triangulation library")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("Poly2Tri")]
12 | [assembly: AssemblyCopyright("Copyright © 2015")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("efc06da6-3d71-48ea-8abf-f310499f4d51")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.1")]
35 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Delaunay/DelaunayTriangle.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | // Changes from the Java version
33 | // attributification
34 | // Future possibilities
35 | // Flattening out the number of indirections
36 | // Replacing arrays of 3 with fixed-length arrays?
37 | // Replacing bool[3] with a bit array of some sort?
38 | // Bundling everything into an AoS mess?
39 | // Hardcode them all as ABC ?
40 |
41 | using Poly2Tri.Triangulation.Delaunay.Sweep;
42 | using Poly2Tri.Utility;
43 | using System;
44 | using System.Collections.Generic;
45 |
46 | namespace Poly2Tri.Triangulation.Delaunay
47 | {
48 | public class DelaunayTriangle
49 | : IEquatable
50 | {
51 |
52 | public FixedArray3 Points;
53 | public FixedArray3 Neighbors;
54 | private FixedArray3 _edgeIsConstrained;
55 | public FixedArray3 EdgeIsConstrained { get { return _edgeIsConstrained; } }
56 | public FixedArray3 EdgeIsDelaunay;
57 | public bool IsInterior { get; set; }
58 |
59 | public DelaunayTriangle(TriangulationPoint p1, TriangulationPoint p2, TriangulationPoint p3)
60 | {
61 | Points[0] = p1;
62 | Points[1] = p2;
63 | Points[2] = p3;
64 | }
65 |
66 |
67 | public int IndexOf(TriangulationPoint p)
68 | {
69 | int i = Points.IndexOf(p);
70 | if (i == -1)
71 | {
72 | throw new Exception("Calling index with a point that doesn't exist in triangle");
73 | }
74 |
75 | return i;
76 | }
77 |
78 | internal void CircumCircleCenter(out double x, out double y)
79 | {
80 | var a = Points.Item0;
81 | var b = Points.Item1;
82 | var c = Points.Item2;
83 |
84 | var tx = (a.X + c.X) / 2;
85 | var ty = (a.Y + c.Y) / 2;
86 |
87 | var vx = (b.X + c.X) / 2;
88 | var vy = (b.Y + c.Y) / 2;
89 |
90 | double ux, uy, wx, wy;
91 |
92 | if (a.X == c.X)
93 | {
94 | ux = 1;
95 | uy = 0;
96 | }
97 | else
98 | {
99 | ux = (c.Y - a.Y) / (a.X - c.X);
100 | uy = 1;
101 | }
102 |
103 | if (b.X == c.X)
104 | {
105 | wx = -1;
106 | wy = 0;
107 | }
108 | else
109 | {
110 | wx = (b.Y - c.Y) / (b.X - c.X);
111 | wy = -1;
112 | }
113 |
114 | var alpha = (wy * (vx - tx) - wx * (vy - ty)) / (ux * wy - wx * uy);
115 |
116 | x = tx + alpha * ux;
117 | y = ty + alpha * uy;
118 | }
119 |
120 | public int IndexCWFrom(TriangulationPoint p)
121 | {
122 | return (IndexOf(p) + 2) % 3;
123 | }
124 |
125 | private int IndexCCWFrom(TriangulationPoint p)
126 | {
127 | return (IndexOf(p) + 1) % 3;
128 | }
129 |
130 |
131 | public bool Contains(TriangulationPoint p)
132 | {
133 | return Points.Contains(p);
134 | }
135 |
136 |
137 | ///
138 | /// Update neighbor pointers
139 | ///
140 | /// Point 1 of the shared edge
141 | /// Point 2 of the shared edge
142 | /// This triangle's new neighbor
143 | private void MarkNeighbor(TriangulationPoint p1, TriangulationPoint p2, DelaunayTriangle t)
144 | {
145 | int i = EdgeIndex(p1, p2);
146 | if (i == -1)
147 | {
148 | throw new Exception("Error marking neighbors -- t doesn't contain edge p1-p2!");
149 | }
150 | Neighbors[i] = t;
151 | }
152 |
153 |
154 | ///
155 | /// Exhaustive search to update neighbor pointers
156 | ///
157 | public void MarkNeighbor(DelaunayTriangle t)
158 | {
159 | // Points of this triangle also belonging to t
160 | bool a = t.Contains(Points[0]);
161 | bool b = t.Contains(Points[1]);
162 | bool c = t.Contains(Points[2]);
163 |
164 | if (b && c)
165 | {
166 | Neighbors[0] = t;
167 | t.MarkNeighbor(Points[1], Points[2], this);
168 | }
169 | else if (a && c)
170 | {
171 | Neighbors[1] = t;
172 | t.MarkNeighbor(Points[0], Points[2], this);
173 | }
174 | else if (a && b)
175 | {
176 | Neighbors[2] = t;
177 | t.MarkNeighbor(Points[0], Points[1], this);
178 | }
179 | else
180 | {
181 | throw new Exception("Failed to mark neighbor, doesn't share an edge!");
182 | }
183 | }
184 |
185 | private void ClearNeighbors()
186 | {
187 | Neighbors[0] = Neighbors[1] = Neighbors[2] = null;
188 | }
189 |
190 | private void ClearNeighbor(DelaunayTriangle triangle)
191 | {
192 | if (Neighbors[0] == triangle)
193 | {
194 | Neighbors[0] = null;
195 | }
196 | else if (Neighbors[1] == triangle)
197 | {
198 | Neighbors[1] = null;
199 | }
200 | else if( Neighbors[2] == triangle)
201 | {
202 | Neighbors[2] = null;
203 | }
204 | }
205 |
206 | ///
207 | /// Clears all references to all other triangles and points
208 | ///
209 | public void Clear()
210 | {
211 | for (int i = 0; i < 3; i++)
212 | {
213 | DelaunayTriangle t = Neighbors[i];
214 | if (t != null)
215 | {
216 | t.ClearNeighbor(this);
217 | }
218 | }
219 | ClearNeighbors();
220 | Points[0] = Points[1] = Points[2] = null;
221 | }
222 |
223 | /// Opposite triangle
224 | /// The point in t that isn't shared between the triangles
225 | public TriangulationPoint OppositePoint(DelaunayTriangle t, TriangulationPoint p)
226 | {
227 | return PointCWFrom(t.PointCWFrom(p));
228 | }
229 |
230 |
231 | public DelaunayTriangle NeighborCWFrom(TriangulationPoint point)
232 | {
233 | return Neighbors[(Points.IndexOf(point) + 1) % 3];
234 | }
235 |
236 |
237 | public DelaunayTriangle NeighborCCWFrom(TriangulationPoint point)
238 | {
239 | return Neighbors[(Points.IndexOf(point) + 2) % 3];
240 | }
241 |
242 |
243 | public DelaunayTriangle NeighborAcrossFrom(TriangulationPoint point)
244 | {
245 | return Neighbors[Points.IndexOf(point)];
246 | }
247 |
248 |
249 | public TriangulationPoint PointCCWFrom(TriangulationPoint point)
250 | {
251 | return Points[(IndexOf(point) + 1) % 3];
252 | }
253 |
254 |
255 | public TriangulationPoint PointCWFrom(TriangulationPoint point)
256 | {
257 | return Points[(IndexOf(point) + 2) % 3];
258 | }
259 |
260 |
261 | private void RotateCW()
262 | {
263 | var t = Points[2];
264 | Points[2] = Points[1];
265 | Points[1] = Points[0];
266 | Points[0] = t;
267 | }
268 |
269 |
270 | ///
271 | /// Legalize triangle by rotating clockwise around oPoint
272 | ///
273 | /// The origin point to rotate around
274 | /// ???
275 | public void Legalize(TriangulationPoint oPoint, TriangulationPoint nPoint)
276 | {
277 | RotateCW();
278 | Points[IndexCCWFrom(oPoint)] = nPoint;
279 | }
280 |
281 |
282 | public override string ToString()
283 | {
284 | return Points[0] + "," + Points[1] + "," + Points[2];
285 | }
286 |
287 |
288 | ///
289 | /// Finalize edge marking
290 | ///
291 | public void MarkNeighborEdges()
292 | {
293 | for (int i = 0; i < 3; i++)
294 | {
295 | if (EdgeIsConstrained[i] && Neighbors[i] != null)
296 | {
297 | Neighbors[i].MarkConstrainedEdge(Points[(i + 1) % 3], Points[(i + 2) % 3]);
298 | }
299 | }
300 | }
301 |
302 |
303 | public void MarkEdge(DelaunayTriangle triangle)
304 | {
305 | for (int i = 0; i < 3; i++) if (EdgeIsConstrained[i])
306 | {
307 | triangle.MarkConstrainedEdge(Points[(i + 1) % 3], Points[(i + 2) % 3]);
308 | }
309 | }
310 |
311 | public void MarkEdge(IEnumerable tList)
312 | {
313 | foreach (DelaunayTriangle t in tList)
314 | {
315 | for (int i = 0; i < 3; i++)
316 | {
317 | if (t.EdgeIsConstrained[i])
318 | {
319 | MarkConstrainedEdge(t.Points[(i + 1) % 3], t.Points[(i + 2) % 3]);
320 | }
321 | }
322 | }
323 | }
324 |
325 |
326 | public void MarkConstrainedEdge(int index)
327 | {
328 | _edgeIsConstrained[index] = true;
329 | }
330 |
331 |
332 | public void MarkConstrainedEdge(DTSweepConstraint edge)
333 | {
334 | MarkConstrainedEdge(edge.P, edge.Q);
335 | }
336 |
337 |
338 | ///
339 | /// Mark edge as constrained
340 | ///
341 | public void MarkConstrainedEdge(TriangulationPoint p, TriangulationPoint q)
342 | {
343 | int i = EdgeIndex(p, q);
344 | if (i != -1)
345 | {
346 | _edgeIsConstrained[i] = true;
347 | }
348 | }
349 |
350 |
351 | public double Area()
352 | {
353 | double b = Points[0].X - Points[1].X;
354 | double h = Points[2].Y - Points[1].Y;
355 |
356 | return Math.Abs((b * h * 0.5f));
357 | }
358 |
359 | public TriangulationPoint Centroid()
360 | {
361 | double cx = (Points[0].X + Points[1].X + Points[2].X) / 3f;
362 | double cy = (Points[0].Y + Points[1].Y + Points[2].Y) / 3f;
363 | return new TriangulationPoint(cx, cy);
364 | }
365 |
366 |
367 | ///
368 | /// Get the index of the neighbor that shares this edge (or -1 if it isn't shared)
369 | ///
370 | /// index of the shared edge or -1 if edge isn't shared
371 | public int EdgeIndex(TriangulationPoint p1, TriangulationPoint p2)
372 | {
373 | int i1 = Points.IndexOf(p1);
374 | int i2 = Points.IndexOf(p2);
375 |
376 | // Points of this triangle in the edge p1-p2
377 | bool a = (i1 == 0 || i2 == 0);
378 | bool b = (i1 == 1 || i2 == 1);
379 | bool c = (i1 == 2 || i2 == 2);
380 |
381 | if (b && c)
382 | {
383 | return 0;
384 | }
385 | if (a && c)
386 | {
387 | return 1;
388 | }
389 | if (a && b)
390 | {
391 | return 2;
392 | }
393 |
394 | return -1;
395 | }
396 |
397 |
398 | public bool GetConstrainedEdgeCCW(TriangulationPoint p) { return EdgeIsConstrained[(IndexOf(p) + 2) % 3]; }
399 | public bool GetConstrainedEdgeCW(TriangulationPoint p) { return EdgeIsConstrained[(IndexOf(p) + 1) % 3]; }
400 | public bool GetConstrainedEdgeAcross(TriangulationPoint p) { return EdgeIsConstrained[IndexOf(p)]; }
401 |
402 | private void SetConstrainedEdge(int idx, bool ce)
403 | {
404 | //if (ce == false && EdgeIsConstrained[idx])
405 | //{
406 | // DTSweepConstraint edge = null;
407 | // if (GetEdge(idx, out edge))
408 | // {
409 | // Console.WriteLine("Removing pre-defined constraint from edge " + edge.ToString());
410 | // }
411 | //}
412 | _edgeIsConstrained[idx] = ce;
413 | }
414 | public void SetConstrainedEdgeCCW(TriangulationPoint p, bool ce)
415 | {
416 | int idx = (IndexOf(p) + 2) % 3;
417 | SetConstrainedEdge(idx, ce);
418 | }
419 | public void SetConstrainedEdgeCW(TriangulationPoint p, bool ce)
420 | {
421 | int idx = (IndexOf(p) + 1) % 3;
422 | SetConstrainedEdge(idx, ce);
423 | }
424 | public void SetConstrainedEdgeAcross(TriangulationPoint p, bool ce)
425 | {
426 | int idx = IndexOf(p);
427 | SetConstrainedEdge(idx, ce);
428 | }
429 |
430 | public bool GetDelaunayEdgeCCW(TriangulationPoint p) { return EdgeIsDelaunay[(IndexOf(p) + 2) % 3]; }
431 | public bool GetDelaunayEdgeCW(TriangulationPoint p) { return EdgeIsDelaunay[(IndexOf(p) + 1) % 3]; }
432 | public bool GetDelaunayEdgeAcross(TriangulationPoint p) { return EdgeIsDelaunay[IndexOf(p)]; }
433 | public void SetDelaunayEdgeCCW(TriangulationPoint p, bool ce) { EdgeIsDelaunay[(IndexOf(p) + 2) % 3] = ce; }
434 | public void SetDelaunayEdgeCW(TriangulationPoint p, bool ce) { EdgeIsDelaunay[(IndexOf(p) + 1) % 3] = ce; }
435 | public void SetDelaunayEdgeAcross(TriangulationPoint p, bool ce) { EdgeIsDelaunay[IndexOf(p)] = ce; }
436 |
437 | private bool GetEdge(int idx, out DTSweepConstraint edge)
438 | {
439 | edge = null;
440 | if (idx < 0 || idx > 2)
441 | {
442 | return false;
443 | }
444 | TriangulationPoint p1 = Points[(idx + 1) % 3];
445 | TriangulationPoint p2 = Points[(idx + 2) % 3];
446 | if (p1.GetEdge(p2, out edge))
447 | {
448 | return true;
449 | }
450 | else if (p2.GetEdge(p1, out edge))
451 | {
452 | return true;
453 | }
454 |
455 | return false;
456 | }
457 |
458 |
459 | public bool GetEdgeCCW(TriangulationPoint p, out DTSweepConstraint edge)
460 | {
461 | int pointIndex = IndexOf(p);
462 | int edgeIdx = (pointIndex + 2)%3;
463 |
464 | return GetEdge(edgeIdx, out edge);
465 | }
466 |
467 | public bool GetEdgeCW(TriangulationPoint p, out DTSweepConstraint edge)
468 | {
469 | int pointIndex = IndexOf(p);
470 | int edgeIdx = (pointIndex + 1) % 3;
471 |
472 | return GetEdge(edgeIdx, out edge);
473 | }
474 |
475 | public bool GetEdgeAcross(TriangulationPoint p, out DTSweepConstraint edge)
476 | {
477 | int pointIndex = IndexOf(p);
478 | int edgeIdx = pointIndex;
479 |
480 | return GetEdge(edgeIdx, out edge);
481 | }
482 |
483 | public bool Equals(DelaunayTriangle other)
484 | {
485 | return ReferenceEquals(this, other);
486 | }
487 | }
488 | }
489 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Delaunay/Sweep/AdvancingFront.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | // Changes from the Java version
33 | // Removed BST code, but not all artifacts of it
34 | // Future possibilities
35 | // Eliminate Add/RemoveNode ?
36 | // Comments comments and more comments!
37 |
38 | using System;
39 | using System.Text;
40 |
41 | namespace Poly2Tri.Triangulation.Delaunay.Sweep
42 | {
43 | /**
44 | * @author Thomas Åhlen (thahlen@gmail.com)
45 | */
46 | public class AdvancingFront
47 | {
48 | public AdvancingFrontNode Head;
49 | public AdvancingFrontNode Tail;
50 | private AdvancingFrontNode _search;
51 |
52 | public AdvancingFront(AdvancingFrontNode head, AdvancingFrontNode tail)
53 | {
54 | Head = head;
55 | Tail = tail;
56 | _search = head;
57 | }
58 |
59 | public override string ToString()
60 | {
61 | StringBuilder sb = new StringBuilder();
62 | AdvancingFrontNode node = Head;
63 | while (node != Tail)
64 | {
65 | sb.Append(node.Point.X).Append("->");
66 | node = node.Next;
67 | }
68 | sb.Append(Tail.Point.X);
69 | return sb.ToString();
70 | }
71 |
72 | ///
73 | /// We use a balancing tree to locate a node smaller or equal to given key value (in theory)
74 | ///
75 | public AdvancingFrontNode LocateNode(TriangulationPoint point)
76 | {
77 | return LocateNode(point.X);
78 | }
79 |
80 | private AdvancingFrontNode LocateNode(double x)
81 | {
82 | AdvancingFrontNode node = _search;
83 | if (x < node.Value)
84 | {
85 | while ((node = node.Prev) != null)
86 | {
87 | if (x >= node.Value)
88 | {
89 | _search = node;
90 | return node;
91 | }
92 | }
93 | }
94 | else
95 | {
96 | while ((node = node.Next) != null)
97 | {
98 | if (x < node.Value)
99 | {
100 | _search = node.Prev;
101 | return node.Prev;
102 | }
103 | }
104 | }
105 |
106 | return null;
107 | }
108 |
109 |
110 | ///
111 | /// This implementation will use simple node traversal algorithm to find a point on the front
112 | ///
113 | public AdvancingFrontNode LocatePoint(TriangulationPoint point)
114 | {
115 | double px = point.X;
116 | AdvancingFrontNode node = _search;
117 | double nx = node.Point.X;
118 |
119 | // ReSharper disable CompareOfFloatsByEqualityOperator
120 | if (px == nx)
121 | // ReSharper restore CompareOfFloatsByEqualityOperator
122 | {
123 | if (!point.Equals(node.Point))
124 | {
125 | // We might have two nodes with same x value for a short time
126 | if (point.Equals(node.Prev.Point))
127 | {
128 | node = node.Prev;
129 | }
130 | else if (point.Equals(node.Next.Point))
131 | {
132 | node = node.Next;
133 | }
134 | else
135 | {
136 | throw new Exception("Failed to find Node for given afront point");
137 | }
138 | }
139 | }
140 | else if (px < nx)
141 | {
142 | while ((node = node.Prev) != null)
143 | {
144 | if (point.Equals(node.Point))
145 | {
146 | break;
147 | }
148 | }
149 | }
150 | else
151 | {
152 | while ((node = node.Next) != null)
153 | {
154 | if (point.Equals(node.Point))
155 | {
156 | break;
157 | }
158 | }
159 | }
160 | _search = node;
161 |
162 | return node;
163 | }
164 | }
165 | }
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Delaunay/Sweep/AdvancingFrontNode.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | // Changes from the Java version
33 | // Removed getters
34 | // Has* turned into attributes
35 | // Future possibilities
36 | // Comments!
37 |
38 | namespace Poly2Tri.Triangulation.Delaunay.Sweep
39 | {
40 | public class AdvancingFrontNode
41 | {
42 | public AdvancingFrontNode Next;
43 | public AdvancingFrontNode Prev;
44 | public readonly double Value;
45 | public readonly TriangulationPoint Point;
46 | public DelaunayTriangle Triangle;
47 |
48 | public AdvancingFrontNode(TriangulationPoint point)
49 | {
50 | Point = point;
51 | Value = point.X;
52 | }
53 |
54 | public bool HasNext { get { return Next != null; } }
55 | public bool HasPrev { get { return Prev != null; } }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Delaunay/Sweep/DTSweepBasin.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | namespace Poly2Tri.Triangulation.Delaunay.Sweep
33 | {
34 | public class DTSweepBasin
35 | {
36 | public AdvancingFrontNode LeftNode;
37 | public AdvancingFrontNode BottomNode;
38 | public AdvancingFrontNode RightNode;
39 | public double Width;
40 | public bool LeftHighest;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Delaunay/Sweep/DTSweepConstraint.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using Poly2Tri.Utility;
33 |
34 | namespace Poly2Tri.Triangulation.Delaunay.Sweep
35 | {
36 | public class DTSweepConstraint : TriangulationConstraint
37 | {
38 | ///
39 | /// Give two points in any order. Will always be ordered so
40 | /// that q.y > p.y and q.x > p.x if same y value
41 | ///
42 | public DTSweepConstraint(Point2D p1, Point2D p2)
43 | : base(p1, p2)
44 | {
45 | Q.AddEdge(this);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Delaunay/Sweep/DTSweepContext.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | namespace Poly2Tri.Triangulation.Delaunay.Sweep
33 | {
34 | /**
35 | *
36 | * @author Thomas Åhlén, thahlen@gmail.com
37 | *
38 | */
39 | public class DTSweepContext : TriangulationContext
40 | {
41 | // Inital triangle factor, seed triangle will extend 30% of
42 | // PointSet width to both left and right.
43 | private const float ALPHA = 0.3f;
44 |
45 | public AdvancingFront Front;
46 | private TriangulationPoint Head { get; set; }
47 | private TriangulationPoint Tail { get; set; }
48 |
49 | public readonly DTSweepBasin Basin = new DTSweepBasin();
50 | public readonly DTSweepEdgeEvent EdgeEvent = new DTSweepEdgeEvent();
51 |
52 | private readonly DTSweepPointComparator _comparator = new DTSweepPointComparator();
53 |
54 | public override TriangulationAlgorithm Algorithm { get { return TriangulationAlgorithm.DTSweep; } }
55 |
56 |
57 |
58 | public DTSweepContext()
59 | : base(new DTSweepDebugContext())
60 | {
61 | }
62 |
63 | public new DTSweepDebugContext DebugContext
64 | {
65 | get
66 | {
67 | return (DTSweepDebugContext)base.DebugContext;
68 | }
69 | }
70 |
71 | public void RemoveFromList(DelaunayTriangle triangle)
72 | {
73 | Triangles.Remove(triangle);
74 | // TODO: remove all neighbor pointers to this triangle
75 | // for( int i=0; i<3; i++ )
76 | // {
77 | // if( triangle.neighbors[i] != null )
78 | // {
79 | // triangle.neighbors[i].clearNeighbor( triangle );
80 | // }
81 | // }
82 | // triangle.clearNeighbors();
83 | }
84 |
85 |
86 | public void MeshClean(DelaunayTriangle triangle)
87 | {
88 | MeshCleanReq(triangle);
89 | }
90 |
91 |
92 | private void MeshCleanReq(DelaunayTriangle triangle)
93 | {
94 | if (triangle != null && !triangle.IsInterior)
95 | {
96 | triangle.IsInterior = true;
97 | Triangulatable.AddTriangle(triangle);
98 |
99 | for (int i = 0; i < 3; i++)
100 | {
101 | if (!triangle.EdgeIsConstrained[i])
102 | {
103 | MeshCleanReq(triangle.Neighbors[i]);
104 | }
105 | }
106 | }
107 | }
108 |
109 | public AdvancingFrontNode LocateNode(TriangulationPoint point)
110 | {
111 | return Front.LocateNode(point);
112 | }
113 |
114 |
115 | public void CreateAdvancingFront()
116 | {
117 | // Initial triangle
118 | DelaunayTriangle iTriangle = new DelaunayTriangle(Points[0], Tail, Head);
119 | Triangles.Add(iTriangle);
120 |
121 | AdvancingFrontNode head = new AdvancingFrontNode(iTriangle.Points[1]) {
122 | Triangle = iTriangle
123 | };
124 | AdvancingFrontNode middle = new AdvancingFrontNode(iTriangle.Points[0]) {
125 | Triangle = iTriangle
126 | };
127 | AdvancingFrontNode tail = new AdvancingFrontNode(iTriangle.Points[2]);
128 |
129 | Front = new AdvancingFront(head, tail) {
130 | Head = {
131 | Next = middle
132 | }
133 | };
134 |
135 | // TODO: I think it would be more intuitive if head is middles next and not previous
136 | // so swap head and tail
137 | middle.Next = Front.Tail;
138 | middle.Prev = Front.Head;
139 | Front.Tail.Prev = middle;
140 | }
141 |
142 |
143 | ///
144 | /// Try to map a node to all sides of this triangle that don't have
145 | /// a neighbor.
146 | ///
147 | public void MapTriangleToNodes(DelaunayTriangle t)
148 | {
149 | for (int i = 0; i < 3; i++)
150 | {
151 | if (t.Neighbors[i] == null)
152 | {
153 | AdvancingFrontNode n = Front.LocatePoint(t.PointCWFrom(t.Points[i]));
154 | if (n != null)
155 | {
156 | n.Triangle = t;
157 | }
158 | }
159 | }
160 | }
161 |
162 |
163 | public override void PrepareTriangulation(ITriangulatable t)
164 | {
165 | base.PrepareTriangulation(t);
166 |
167 | double xmin;
168 | double ymin;
169 |
170 | double xmax = xmin = Points[0].X;
171 | double ymax = ymin = Points[0].Y;
172 |
173 | // Calculate bounds. Should be combined with the sorting
174 | foreach (TriangulationPoint p in Points)
175 | {
176 | if (p.X > xmax)
177 | {
178 | xmax = p.X;
179 | }
180 | if (p.X < xmin)
181 | {
182 | xmin = p.X;
183 | }
184 | if (p.Y > ymax)
185 | {
186 | ymax = p.Y;
187 | }
188 | if (p.Y < ymin)
189 | {
190 | ymin = p.Y;
191 | }
192 | }
193 |
194 | double deltaX = ALPHA * (xmax - xmin);
195 | double deltaY = ALPHA * (ymax - ymin);
196 | TriangulationPoint p1 = new TriangulationPoint(xmax + deltaX, ymin - deltaY);
197 | TriangulationPoint p2 = new TriangulationPoint(xmin - deltaX, ymin - deltaY);
198 |
199 | Head = p1;
200 | Tail = p2;
201 |
202 | // long time = System.nanoTime();
203 | // Sort the points along y-axis
204 | Points.Sort(_comparator);
205 | // logger.info( "Triangulation setup [{}ms]", ( System.nanoTime() - time ) / 1e6 );
206 | }
207 |
208 |
209 | public void FinalizeTriangulation()
210 | {
211 | Triangulatable.AddTriangles(Triangles);
212 | Triangles.Clear();
213 | }
214 |
215 |
216 | public override DTSweepConstraint NewConstraint(TriangulationPoint a, TriangulationPoint b)
217 | {
218 | return new DTSweepConstraint(a, b);
219 | }
220 |
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Delaunay/Sweep/DTSweepDebugContext.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | namespace Poly2Tri.Triangulation.Delaunay.Sweep
33 | {
34 | public class DTSweepDebugContext : TriangulationDebugContext
35 | {
36 | public DelaunayTriangle PrimaryTriangle { get; set; }
37 | public DelaunayTriangle SecondaryTriangle { get; set; }
38 | public TriangulationPoint ActivePoint { get; set; }
39 | public AdvancingFrontNode ActiveNode { get; set; }
40 | public DTSweepConstraint ActiveConstraint { get; set; }
41 |
42 | public bool IsDebugContext { get { return true; } }
43 |
44 | public override void Clear()
45 | {
46 | PrimaryTriangle = null;
47 | SecondaryTriangle = null;
48 | ActivePoint = null;
49 | ActiveNode = null;
50 | ActiveConstraint = null;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Delaunay/Sweep/DTSweepEdgeEvent.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | // Changes from the Java version
33 | // Turned DTSweepEdgeEvent into a value type
34 |
35 | namespace Poly2Tri.Triangulation.Delaunay.Sweep
36 | {
37 | public class DTSweepEdgeEvent
38 | {
39 | public DTSweepConstraint ConstrainedEdge;
40 | public bool Right;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Delaunay/Sweep/DTSweepPointComparator.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System.Collections.Generic;
33 |
34 | namespace Poly2Tri.Triangulation.Delaunay.Sweep
35 | {
36 | public class DTSweepPointComparator : IComparer
37 | {
38 | public int Compare(TriangulationPoint p1, TriangulationPoint p2)
39 | {
40 | if (p1.Y < p2.Y)
41 | {
42 | return -1;
43 | }
44 | else if (p1.Y > p2.Y)
45 | {
46 | return 1;
47 | }
48 | else
49 | {
50 | if (p1.X < p2.X)
51 | {
52 | return -1;
53 | }
54 | else if (p1.X > p2.X)
55 | {
56 | return 1;
57 | }
58 | else
59 | {
60 | return 0;
61 | }
62 | }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Delaunay/Sweep/PointOnEdgeException.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System;
33 |
34 | namespace Poly2Tri.Triangulation.Delaunay.Sweep
35 | {
36 | public class PointOnEdgeException : NotImplementedException
37 | {
38 | public TriangulationPoint A { get; set; }
39 | public TriangulationPoint B { get; set; }
40 | public TriangulationPoint C { get; set; }
41 |
42 | public PointOnEdgeException(string message, TriangulationPoint a, TriangulationPoint b, TriangulationPoint c)
43 | : base(message)
44 | {
45 | A = a;
46 | B = b;
47 | C = c;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/ITriangulatable.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System.Collections.Generic;
33 | using Poly2Tri.Triangulation.Delaunay;
34 | using Poly2Tri.Utility;
35 |
36 | namespace Poly2Tri.Triangulation
37 | {
38 | public interface ITriangulatable
39 | {
40 | //IList Points { get; } // MM: Neither of these are used via interface (yet?)
41 | IList Triangles { get; }
42 | TriangulationMode TriangulationMode { get; }
43 | bool DisplayFlipX { get; set; }
44 | bool DisplayFlipY { get; set; }
45 | float DisplayRotate { get; set; }
46 | double Precision { get; set; }
47 | double MinX { get; }
48 | double MaxX { get; }
49 | double MinY { get; }
50 | double MaxY { get; }
51 | Rect2D Bounds { get; }
52 |
53 | void Prepare(TriangulationContext tcx);
54 | void AddTriangle(DelaunayTriangle t);
55 | void AddTriangles(IEnumerable list);
56 | void ClearTriangles();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Orientation.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | namespace Poly2Tri.Triangulation
33 | {
34 | public enum Orientation
35 | {
36 | Clockwise,
37 | AntiClockwise,
38 | Collinear
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Polygon/Contour.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System;
33 | using System.Collections.Generic;
34 | using System.Linq;
35 | using Poly2Tri.Triangulation.Delaunay;
36 | using Poly2Tri.Triangulation.Sets;
37 | using Poly2Tri.Utility;
38 |
39 | namespace Poly2Tri.Triangulation.Polygon
40 | {
41 |
42 | ///
43 | /// This is basically a light-weight version of the Polygon class, but with limited functionality and
44 | /// used for different purposes. Nonetheless, for all intents and purposes, this should actually be
45 | /// a polygon (though not a Polygon..)
46 | ///
47 | public class Contour : Point2DList, ITriangulatable, IEnumerable, IList
48 | {
49 | private readonly List _holes = new List();
50 | private ITriangulatable _parent = null;
51 |
52 | public new TriangulationPoint this[int index]
53 | {
54 | get { return MPoints[index] as TriangulationPoint; }
55 | set { MPoints[index] = value; }
56 | }
57 |
58 | public IList Triangles
59 | {
60 | get
61 | {
62 | throw new NotImplementedException("PolyHole.Triangles should never get called");
63 | }
64 | }
65 |
66 | public TriangulationMode TriangulationMode { get { return _parent.TriangulationMode; } }
67 | public bool DisplayFlipX { get { return _parent.DisplayFlipX; } set { } }
68 | public bool DisplayFlipY { get { return _parent.DisplayFlipY; } set { } }
69 | public float DisplayRotate { get { return _parent.DisplayRotate; } set { } }
70 | public double Precision { get { return _parent.Precision; } set { } }
71 | public double MinX { get { return BoundingBox.MinX; } }
72 | public double MaxX { get { return BoundingBox.MaxX; } }
73 | public double MinY { get { return BoundingBox.MinY; } }
74 | public double MaxY { get { return BoundingBox.MaxY; } }
75 | public Rect2D Bounds { get { return BoundingBox; } }
76 |
77 |
78 | public Contour(ITriangulatable parent)
79 | {
80 | _parent = parent;
81 | }
82 |
83 |
84 | public Contour(ITriangulatable parent, IList points, WindingOrderType windingOrder)
85 | {
86 | // Currently assumes that input is pre-checked for validity
87 | _parent = parent;
88 | AddRange(points, windingOrder);
89 | }
90 |
91 | IEnumerator IEnumerable.GetEnumerator()
92 | {
93 | return MPoints.Cast().GetEnumerator();
94 | }
95 |
96 |
97 | public int IndexOf(TriangulationPoint p)
98 | {
99 | return MPoints.IndexOf(p);
100 | }
101 |
102 |
103 | public void Add(TriangulationPoint p)
104 | {
105 | Add(p, -1, true);
106 | }
107 |
108 |
109 | protected override void Add(Point2D p, int idx, bool bCalcWindingOrderAndEpsilon)
110 | {
111 | TriangulationPoint pt;
112 | if (p is TriangulationPoint)
113 | {
114 | pt = p as TriangulationPoint;
115 | }
116 | else
117 | {
118 | pt = new TriangulationPoint(p.X, p.Y);
119 | }
120 | if (idx < 0)
121 | {
122 | MPoints.Add(pt);
123 | }
124 | else
125 | {
126 | MPoints.Insert(idx, pt);
127 | }
128 | BoundingBox = BoundingBox.AddPoint(pt);
129 | if (bCalcWindingOrderAndEpsilon)
130 | {
131 | if (WindingOrder == WindingOrderType.Unknown)
132 | {
133 | WindingOrder = CalculateWindingOrder();
134 | }
135 | Epsilon = CalculateEpsilon();
136 | }
137 | }
138 |
139 | protected override void AddRange(IEnumerator iter, WindingOrderType windingOrder)
140 | {
141 | if (iter == null)
142 | {
143 | return;
144 | }
145 |
146 | if (WindingOrder == WindingOrderType.Unknown && Count == 0)
147 | {
148 | WindingOrder = windingOrder;
149 | }
150 | bool bReverseReadOrder = (WindingOrder != WindingOrderType.Unknown) && (windingOrder != WindingOrderType.Unknown) && (WindingOrder != windingOrder);
151 | bool bAddedFirst = true;
152 | int startCount = MPoints.Count;
153 | iter.Reset();
154 | while (iter.MoveNext())
155 | {
156 | TriangulationPoint pt;
157 | if (iter.Current is TriangulationPoint)
158 | {
159 | pt = iter.Current as TriangulationPoint;
160 | }
161 | else
162 | {
163 | pt = new TriangulationPoint(iter.Current.X, iter.Current.Y);
164 | }
165 | if (!bAddedFirst)
166 | {
167 | bAddedFirst = true;
168 | MPoints.Add(pt);
169 | }
170 | else if (bReverseReadOrder)
171 | {
172 | MPoints.Insert(startCount, pt);
173 | }
174 | else
175 | {
176 | MPoints.Add(pt);
177 | }
178 | BoundingBox = BoundingBox.AddPoint(iter.Current);
179 | }
180 | if (WindingOrder == WindingOrderType.Unknown && windingOrder == WindingOrderType.Unknown)
181 | {
182 | WindingOrder = CalculateWindingOrder();
183 | }
184 | Epsilon = CalculateEpsilon();
185 | }
186 |
187 | private void AddRange(IList points, WindingOrderType windingOrder)
188 | {
189 | if (points == null || points.Count < 1)
190 | {
191 | return;
192 | }
193 |
194 | if (WindingOrder == WindingOrderType.Unknown && Count == 0)
195 | {
196 | WindingOrder = windingOrder;
197 | }
198 |
199 | int numPoints = points.Count;
200 | bool bReverseReadOrder = (WindingOrder != WindingOrderType.Unknown) && (windingOrder != WindingOrderType.Unknown) && (WindingOrder != windingOrder);
201 | for (int i = 0; i < numPoints; ++i)
202 | {
203 | int idx = i;
204 | if (bReverseReadOrder)
205 | {
206 | idx = points.Count - i - 1;
207 | }
208 | Add(points[idx], -1, false);
209 | }
210 | if (WindingOrder == WindingOrderType.Unknown)
211 | {
212 | WindingOrder = CalculateWindingOrder();
213 | }
214 | Epsilon = CalculateEpsilon();
215 | }
216 |
217 |
218 | public void Insert(int idx, TriangulationPoint p)
219 | {
220 | Add(p, idx, true);
221 | }
222 |
223 |
224 | public bool Remove(TriangulationPoint p)
225 | {
226 | return Remove(p as Point2D);
227 | }
228 |
229 |
230 | public bool Contains(TriangulationPoint p)
231 | {
232 | return MPoints.Contains(p);
233 | }
234 |
235 |
236 | public void CopyTo(TriangulationPoint[] array, int arrayIndex)
237 | {
238 | int numElementsToCopy = Math.Min(Count, array.Length - arrayIndex);
239 | for (int i = 0; i < numElementsToCopy; ++i)
240 | {
241 | array[arrayIndex + i] = MPoints[i] as TriangulationPoint;
242 | }
243 | }
244 |
245 | private void AddHole(Contour c)
246 | {
247 | // no checking is done here as we rely on InitializeHoles for that
248 | c._parent = this;
249 | _holes.Add(c);
250 | }
251 |
252 |
253 | ///
254 | /// returns number of holes that are actually holes, including all children of children, etc. Does NOT
255 | /// include holes that are not actually holes. For example, if the parent is not a hole and this contour has
256 | /// a hole that contains a hole, then the number of holes returned would be 2 - one for the current hole (because
257 | /// the parent is NOT a hole and thus this hole IS a hole), and 1 for the child of the child.
258 | ///
259 | ///
260 | ///
261 | public int GetNumHoles(bool parentIsHole)
262 | {
263 | return (parentIsHole ? 0 : 1) + _holes.Sum(c => c.GetNumHoles(!parentIsHole));
264 | }
265 |
266 | ///
267 | /// returns the basic number of child holes of THIS contour, not including any children of children, etc nor
268 | /// examining whether any children are actual holes.
269 | ///
270 | ///
271 | private int GetNumHoles()
272 | {
273 | return _holes.Count;
274 | }
275 |
276 | private Contour GetHole(int idx)
277 | {
278 | if (idx < 0 || idx >= _holes.Count)
279 | {
280 | return null;
281 | }
282 |
283 | return _holes[idx];
284 | }
285 |
286 |
287 | public void GetActualHoles(bool parentIsHole, ref List holes)
288 | {
289 | if (parentIsHole)
290 | {
291 | holes.Add(this);
292 | }
293 |
294 | foreach (Contour c in _holes)
295 | {
296 | c.GetActualHoles(!parentIsHole, ref holes);
297 | }
298 | }
299 |
300 |
301 | public List.Enumerator GetHoleEnumerator()
302 | {
303 | return _holes.GetEnumerator();
304 | }
305 |
306 |
307 | public void InitializeHoles(ConstrainedPointSet cps)
308 | {
309 | InitializeHoles(_holes, this, cps);
310 | foreach (Contour c in _holes)
311 | {
312 | c.InitializeHoles(cps);
313 | }
314 | }
315 |
316 |
317 | public static void InitializeHoles(List holes, ITriangulatable parent, ConstrainedPointSet cps)
318 | {
319 | int numHoles = holes.Count;
320 | int holeIdx = 0;
321 |
322 | // pass 1 - remove duplicates
323 | while (holeIdx < numHoles)
324 | {
325 | int hole2Idx = holeIdx + 1;
326 | while (hole2Idx < numHoles)
327 | {
328 | bool bSamePolygon = PolygonUtil.PolygonsAreSame2D(holes[holeIdx], holes[hole2Idx]);
329 | if (bSamePolygon)
330 | {
331 | // remove one of them
332 | holes.RemoveAt(hole2Idx);
333 | --numHoles;
334 | }
335 | else
336 | {
337 | ++hole2Idx;
338 | }
339 | }
340 | ++holeIdx;
341 | }
342 |
343 | // pass 2: Intersections and Containment
344 | holeIdx = 0;
345 | while (holeIdx < numHoles)
346 | {
347 | bool bIncrementHoleIdx = true;
348 | int hole2Idx = holeIdx + 1;
349 | while (hole2Idx < numHoles)
350 | {
351 | if (PolygonUtil.PolygonContainsPolygon(holes[holeIdx], holes[holeIdx].Bounds, holes[hole2Idx], holes[hole2Idx].Bounds, false))
352 | {
353 | holes[holeIdx].AddHole(holes[hole2Idx]);
354 | holes.RemoveAt(hole2Idx);
355 | --numHoles;
356 | }
357 | else if (PolygonUtil.PolygonContainsPolygon(holes[hole2Idx], holes[hole2Idx].Bounds, holes[holeIdx], holes[holeIdx].Bounds, false))
358 | {
359 | holes[hole2Idx].AddHole(holes[holeIdx]);
360 | holes.RemoveAt(holeIdx);
361 | --numHoles;
362 | bIncrementHoleIdx = false;
363 | break;
364 | }
365 | else
366 | {
367 | bool bIntersect = PolygonUtil.PolygonsIntersect2D(holes[holeIdx], holes[holeIdx].Bounds, holes[hole2Idx], holes[hole2Idx].Bounds);
368 | if (bIntersect)
369 | {
370 | // this is actually an error condition
371 | // fix by merging hole1 and hole2 into hole1 (including the holes inside hole2!) and delete hole2
372 | // Then, because hole1 is now changed, restart it's check.
373 | PolygonOperationContext ctx = new PolygonOperationContext();
374 | if (!ctx.Init(PolygonUtil.PolyOperation.Union | PolygonUtil.PolyOperation.Intersect, holes[holeIdx], holes[hole2Idx]))
375 | {
376 | if (ctx.Error == PolygonUtil.PolyUnionError.Poly1InsidePoly2)
377 | {
378 | holes[hole2Idx].AddHole(holes[holeIdx]);
379 | holes.RemoveAt(holeIdx);
380 | --numHoles;
381 | bIncrementHoleIdx = false;
382 | break;
383 | }
384 | else
385 | {
386 | throw new Exception("PolygonOperationContext.Init had an error during initialization");
387 | }
388 | }
389 | PolygonUtil.PolyUnionError pue = PolygonUtil.PolygonOperation(ctx);
390 | if (pue == PolygonUtil.PolyUnionError.None)
391 | {
392 | Point2DList union = ctx.Union;
393 | Point2DList intersection = ctx.Intersect;
394 |
395 | // create a new contour for the union
396 | Contour c = new Contour(parent);
397 | c.AddRange(union);
398 | c.WindingOrder = WindingOrderType.Default;
399 |
400 | // add children from both of the merged contours
401 | int numChildHoles = holes[holeIdx].GetNumHoles();
402 | for(int i = 0; i < numChildHoles; ++i)
403 | {
404 | c.AddHole(holes[holeIdx].GetHole(i));
405 | }
406 | numChildHoles = holes[hole2Idx].GetNumHoles();
407 | for (int i = 0; i < numChildHoles; ++i)
408 | {
409 | c.AddHole(holes[hole2Idx].GetHole(i));
410 | }
411 |
412 | // make sure we preserve the contours of the intersection
413 | Contour cInt = new Contour(c);
414 | cInt.AddRange(intersection);
415 | cInt.WindingOrder = WindingOrderType.Default;
416 | c.AddHole(cInt);
417 |
418 | // replace the current contour with the merged contour
419 | holes[holeIdx] = c;
420 |
421 | // toss the second contour
422 | holes.RemoveAt(hole2Idx);
423 | --numHoles;
424 |
425 | // current hole is "examined", so move to the next one
426 | hole2Idx = holeIdx + 1;
427 | }
428 | else
429 | {
430 | throw new Exception("PolygonOperation had an error!");
431 | }
432 | }
433 | else
434 | {
435 | ++hole2Idx;
436 | }
437 | }
438 | }
439 | if (bIncrementHoleIdx)
440 | {
441 | ++holeIdx;
442 | }
443 | }
444 |
445 | numHoles = holes.Count;
446 | holeIdx = 0;
447 | while (holeIdx < numHoles)
448 | {
449 | int numPoints = holes[holeIdx].Count;
450 | for (int i = 0; i < numPoints; ++i)
451 | {
452 | int j = holes[holeIdx].NextIndex(i);
453 | uint constraintCode = TriangulationConstraint.CalculateContraintCode(holes[holeIdx][i], holes[holeIdx][j]);
454 | TriangulationConstraint tc;
455 | if (!cps.TryGetConstraint(constraintCode, out tc))
456 | {
457 | tc = new TriangulationConstraint(holes[holeIdx][i], holes[holeIdx][j]);
458 | cps.AddConstraint(tc);
459 | }
460 |
461 | // replace the points in the holes with valid points
462 | if (holes[holeIdx][i].VertexCode == tc.P.VertexCode)
463 | {
464 | holes[holeIdx][i] = tc.P;
465 | }
466 | else if (holes[holeIdx][j].VertexCode == tc.P.VertexCode)
467 | {
468 | holes[holeIdx][j] = tc.P;
469 | }
470 | if (holes[holeIdx][i].VertexCode == tc.Q.VertexCode)
471 | {
472 | holes[holeIdx][i] = tc.Q;
473 | }
474 | else if (holes[holeIdx][j].VertexCode == tc.Q.VertexCode)
475 | {
476 | holes[holeIdx][j] = tc.Q;
477 | }
478 | }
479 | ++holeIdx;
480 | }
481 | }
482 |
483 |
484 | public void Prepare(TriangulationContext tcx)
485 | {
486 | throw new NotImplementedException("PolyHole.Prepare should never get called");
487 | }
488 |
489 |
490 | public void AddTriangle(DelaunayTriangle t)
491 | {
492 | throw new NotImplementedException("PolyHole.AddTriangle should never get called");
493 | }
494 |
495 |
496 | public void AddTriangles(IEnumerable list)
497 | {
498 | throw new NotImplementedException("PolyHole.AddTriangles should never get called");
499 | }
500 |
501 |
502 | public void ClearTriangles()
503 | {
504 | throw new NotImplementedException("PolyHole.ClearTriangles should never get called");
505 | }
506 |
507 |
508 | public Point2D FindPointInContour()
509 | {
510 | if (Count < 3)
511 | {
512 | return null;
513 | }
514 |
515 | // first try the simple approach:
516 | Point2D p = GetCentroid();
517 | if (IsPointInsideContour(p))
518 | {
519 | return p;
520 | }
521 |
522 | // brute force it...
523 | Random random = new Random();
524 | while (true)
525 | {
526 | p.X = (random.NextDouble() * (MaxX - MinX)) + MinX;
527 | p.Y = (random.NextDouble() * (MaxY - MinY)) + MinY;
528 | if (IsPointInsideContour(p))
529 | {
530 | return p;
531 | }
532 | }
533 | }
534 |
535 | private bool IsPointInsideContour(Point2D p)
536 | {
537 | if (PolygonUtil.PointInPolygon2D(this, p))
538 | return _holes.All(c => !c.IsPointInsideContour(p));
539 |
540 | return false;
541 | }
542 |
543 | }
544 | }
545 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Polygon/Polygon.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | // Changes from the Java version
33 | // Polygon constructors sprused up, checks for 3+ polys
34 | // Naming of everything
35 | // getTriangulationMode() -> TriangulationMode { get; }
36 | // Exceptions replaced
37 | // Future possibilities
38 | // We have a lot of Add/Clear methods -- we may prefer to just expose the container
39 | // Some self-explanatory methods may deserve commenting anyways
40 |
41 | using System;
42 | using System.Collections.Generic;
43 | using System.Linq;
44 | using Poly2Tri.Triangulation.Delaunay;
45 | using Poly2Tri.Utility;
46 |
47 | namespace Poly2Tri.Triangulation.Polygon
48 | {
49 | public class Polygon : Point2DList, ITriangulatable, IEnumerable, IList
50 | {
51 | // ITriangulatable Implementation
52 | private readonly Dictionary _pointMap = new Dictionary();
53 | public IList Points { get { return this; } }
54 | private List _triangles;
55 | public IList Triangles { get { return _triangles; } }
56 | public TriangulationMode TriangulationMode { get { return TriangulationMode.Polygon; } }
57 | public string FileName { get; set; }
58 | public bool DisplayFlipX { get; set; }
59 | public bool DisplayFlipY { get; set; }
60 | public float DisplayRotate { get; set; }
61 | private double _precision = TriangulationPoint.VERTEX_CODE_DEFAULT_PRECISION;
62 | public double Precision { get { return _precision; } set { _precision = value; } }
63 | public double MinX { get { return BoundingBox.MinX; } }
64 | public double MaxX { get { return BoundingBox.MaxX; } }
65 | public double MinY { get { return BoundingBox.MinY; } }
66 | public double MaxY { get { return BoundingBox.MaxY; } }
67 | public Rect2D Bounds { get { return BoundingBox; } }
68 |
69 | // Point2DList overrides
70 | public new TriangulationPoint this[int index]
71 | {
72 | get { return MPoints[index] as TriangulationPoint; }
73 | set { MPoints[index] = value; }
74 | }
75 |
76 | // Polygon Implementation
77 | private List Holes { get; set; }
78 | private PolygonPoint _last;
79 |
80 |
81 |
82 | ///
83 | /// Create a polygon from a list of at least 3 points with no duplicates.
84 | ///
85 | /// A list of unique points
86 | private Polygon(IList points)
87 | {
88 | if (points.Count < 3)
89 | {
90 | throw new ArgumentException("List has fewer than 3 points", "points");
91 | }
92 |
93 | AddRange(points, WindingOrderType.Unknown);
94 | }
95 |
96 |
97 | ///
98 | /// Create a polygon from a list of at least 3 points with no duplicates.
99 | ///
100 | /// A list of unique points.
101 | public Polygon(IEnumerable points)
102 | : this((points as IList) ?? points.ToArray())
103 | {}
104 |
105 |
106 | ///
107 | /// Create a polygon from a list of at least 3 points with no duplicates.
108 | ///
109 | /// A list of unique points.
110 | public Polygon(params PolygonPoint[] points)
111 | : this((IList)points)
112 | {}
113 |
114 |
115 | IEnumerator IEnumerable.GetEnumerator()
116 | {
117 | return MPoints.Cast().GetEnumerator();
118 | }
119 |
120 |
121 | public int IndexOf(TriangulationPoint p)
122 | {
123 | return MPoints.IndexOf(p);
124 | }
125 |
126 |
127 | public override void Add(Point2D p)
128 | {
129 | Add(p, -1, true);
130 | }
131 |
132 |
133 | public void Add(TriangulationPoint p)
134 | {
135 | Add(p, -1, true);
136 | }
137 |
138 |
139 | public void Add(PolygonPoint p)
140 | {
141 | Add(p, -1, true);
142 | }
143 |
144 |
145 | protected override void Add(Point2D p, int idx, bool bCalcWindingOrderAndEpsilon)
146 | {
147 | TriangulationPoint pt = p as TriangulationPoint;
148 | if (pt == null)
149 | {
150 | // we only store TriangulationPoints and PolygonPoints in this class
151 | return;
152 | }
153 |
154 | // do not insert duplicate points
155 | if (_pointMap.ContainsKey(pt.VertexCode))
156 | {
157 | return;
158 | }
159 | _pointMap.Add(pt.VertexCode, pt);
160 |
161 | base.Add(p, idx, bCalcWindingOrderAndEpsilon);
162 |
163 | PolygonPoint pp = p as PolygonPoint;
164 | if (pp != null)
165 | {
166 | pp.Previous = _last;
167 | if (_last != null)
168 | {
169 | pp.Next = _last.Next;
170 | _last.Next = pp;
171 | }
172 | _last = pp;
173 | }
174 | }
175 |
176 | private void AddRange(IList points, WindingOrderType windingOrder)
177 | {
178 | if (points == null || points.Count < 1)
179 | return;
180 |
181 | if (WindingOrder == WindingOrderType.Unknown && Count == 0)
182 | WindingOrder = windingOrder;
183 |
184 | int numPoints = points.Count;
185 | bool bReverseReadOrder = (WindingOrder != WindingOrderType.Unknown) && (windingOrder != WindingOrderType.Unknown) && (WindingOrder != windingOrder);
186 | for (int i = 0; i < numPoints; ++i)
187 | {
188 | int idx = i;
189 | if (bReverseReadOrder)
190 | {
191 | idx = points.Count - i - 1;
192 | }
193 | Add(points[idx], -1, false);
194 | }
195 | if (WindingOrder == WindingOrderType.Unknown)
196 | {
197 | WindingOrder = CalculateWindingOrder();
198 | }
199 | Epsilon = CalculateEpsilon();
200 | }
201 |
202 |
203 | public void AddRange(IList points, WindingOrderType windingOrder)
204 | {
205 | if (points == null || points.Count < 1)
206 | {
207 | return;
208 | }
209 |
210 | if (WindingOrder == WindingOrderType.Unknown && Count == 0)
211 | WindingOrder = windingOrder;
212 |
213 | int numPoints = points.Count;
214 | bool bReverseReadOrder = (WindingOrder != WindingOrderType.Unknown) && (windingOrder != WindingOrderType.Unknown) && (WindingOrder != windingOrder);
215 | for (int i = 0; i < numPoints; ++i)
216 | {
217 | int idx = i;
218 | if (bReverseReadOrder)
219 | {
220 | idx = points.Count - i - 1;
221 | }
222 | Add(points[idx], -1, false);
223 | }
224 | if (WindingOrder == WindingOrderType.Unknown)
225 | WindingOrder = CalculateWindingOrder();
226 |
227 | Epsilon = CalculateEpsilon();
228 | }
229 |
230 |
231 | public void Insert(int idx, TriangulationPoint p)
232 | {
233 | Add(p, idx, true);
234 | }
235 |
236 |
237 | public bool Remove(TriangulationPoint p)
238 | {
239 | return base.Remove(p);
240 | }
241 |
242 |
243 | ///
244 | /// Removes a point from the polygon. Note this can be a somewhat expensive operation
245 | /// as it must recalculate the bounding area from scratch.
246 | ///
247 | ///
248 | public void RemovePoint(PolygonPoint p)
249 | {
250 | PolygonPoint next = p.Next;
251 | PolygonPoint prev = p.Previous;
252 | prev.Next = next;
253 | next.Previous = prev;
254 | MPoints.Remove(p);
255 |
256 | BoundingBox = new Rect2D();
257 | foreach (var point2D in MPoints)
258 | BoundingBox = BoundingBox.AddPoint(point2D);
259 | }
260 |
261 |
262 |
263 | public bool Contains(TriangulationPoint p)
264 | {
265 | return MPoints.Contains(p);
266 | }
267 |
268 |
269 | public void CopyTo(TriangulationPoint[] array, int arrayIndex)
270 | {
271 | int numElementsToCopy = Math.Min(Count, array.Length - arrayIndex);
272 | for (int i = 0; i < numElementsToCopy; ++i)
273 | {
274 | array[arrayIndex + i] = MPoints[i] as TriangulationPoint;
275 | }
276 | }
277 |
278 | ///
279 | /// Add a hole to the polygon.
280 | ///
281 | /// A subtraction polygon fully contained inside this polygon.
282 | public void AddHole(Polygon poly)
283 | {
284 | if (Holes == null)
285 | {
286 | Holes = new List();
287 | }
288 | Holes.Add(poly);
289 | // XXX: tests could be made here to be sure it is fully inside
290 | // addSubtraction( poly.getPoints() );
291 | }
292 |
293 |
294 | public void AddTriangle(DelaunayTriangle t)
295 | {
296 | _triangles.Add(t);
297 | }
298 |
299 |
300 | public void AddTriangles(IEnumerable list)
301 | {
302 | _triangles.AddRange(list);
303 | }
304 |
305 |
306 | public void ClearTriangles()
307 | {
308 | if (_triangles != null)
309 | {
310 | _triangles.Clear();
311 | }
312 | }
313 |
314 |
315 | public bool IsPointInside(TriangulationPoint p)
316 | {
317 | return PolygonUtil.PointInPolygon2D(this, p);
318 | }
319 |
320 |
321 | ///
322 | /// Creates constraints and populates the context with points
323 | ///
324 | /// The context
325 | public void Prepare(TriangulationContext tcx)
326 | {
327 | if (_triangles == null)
328 | {
329 | _triangles = new List(MPoints.Count);
330 | }
331 | else
332 | {
333 | _triangles.Clear();
334 | }
335 |
336 | // Outer constraints
337 | for (int i = 0; i < MPoints.Count - 1; i++)
338 | {
339 | //tcx.NewConstraint(mPoints[i], mPoints[i + 1]);
340 | tcx.NewConstraint(this[i], this[i + 1]);
341 | }
342 | tcx.NewConstraint(this[0], this[Count - 1]);
343 | tcx.Points.AddRange(this);
344 |
345 | // Hole constraints
346 | if (Holes != null)
347 | {
348 | foreach (Polygon p in Holes)
349 | {
350 | for (int i = 0; i < p.MPoints.Count - 1; i++)
351 | {
352 | tcx.NewConstraint(p[i], p[i + 1]);
353 | }
354 | tcx.NewConstraint(p[0], p[p.Count - 1]);
355 | tcx.Points.AddRange(p);
356 | }
357 | }
358 | }
359 | }
360 | }
361 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Polygon/PolygonPoint.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | // Changes from the Java version
33 | // Replaced get/set Next/Previous with attributes
34 | // Future possibilities
35 | // Documentation!
36 |
37 |
38 | namespace Poly2Tri.Triangulation.Polygon
39 | {
40 | public class PolygonPoint : TriangulationPoint
41 | {
42 | public PolygonPoint(double x, double y) : base(x, y) { }
43 |
44 | public PolygonPoint Next { get; set; }
45 | public PolygonPoint Previous { get; set; }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Sets/ConstrainedPointSet.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System.Collections.Generic;
33 | using System.Linq;
34 | using Poly2Tri.Triangulation.Delaunay;
35 | using Poly2Tri.Triangulation.Polygon;
36 | using Poly2Tri.Utility;
37 |
38 | namespace Poly2Tri.Triangulation.Sets
39 | {
40 | /*
41 | * Extends the PointSet by adding some Constraints on how it will be triangulated
42 | * A constraint defines an edge between two points in the set, these edges can not
43 | * be crossed. They will be enforced triangle edges after a triangulation.
44 | *
45 | *
46 | * @author Thomas Åhlén, thahlen@gmail.com
47 | * @author Lee Wilson, lwilson@ea.com
48 | */
49 | public class ConstrainedPointSet : PointSet
50 | {
51 | private readonly Dictionary _constraintMap = new Dictionary();
52 | private readonly List _holes = new List();
53 |
54 | public override TriangulationMode TriangulationMode { get { return TriangulationMode.Constrained; } }
55 |
56 |
57 | public ConstrainedPointSet(IEnumerable bounds)
58 | : base(bounds)
59 | {
60 | AddBoundaryConstraints();
61 | }
62 |
63 | public ConstrainedPointSet(IEnumerable bounds, IEnumerable constraints)
64 | : base(bounds)
65 | {
66 | AddBoundaryConstraints();
67 | AddConstraints(constraints);
68 | }
69 |
70 | public ConstrainedPointSet(IList bounds, ICollection indices)
71 | : base(bounds)
72 | {
73 | AddBoundaryConstraints();
74 | List l = new List();
75 | for (int i = 0; i < indices.Count; i += 2)
76 | {
77 | TriangulationConstraint tc = new TriangulationConstraint(bounds[i], bounds[i + 1]);
78 | l.Add(tc);
79 | }
80 | AddConstraints(l);
81 | }
82 |
83 | private void AddBoundaryConstraints()
84 | {
85 | TriangulationPoint ptLL;
86 | TriangulationPoint ptLR;
87 | TriangulationPoint ptUR;
88 | TriangulationPoint ptUL;
89 | if (!TryGetPoint(MinX, MinY, out ptLL))
90 | {
91 | ptLL = new TriangulationPoint(MinX, MinY);
92 | Add(ptLL);
93 | }
94 | if (!TryGetPoint(MaxX, MinY, out ptLR))
95 | {
96 | ptLR = new TriangulationPoint(MaxX, MinY);
97 | Add(ptLR);
98 | }
99 | if (!TryGetPoint(MaxX, MaxY, out ptUR))
100 | {
101 | ptUR = new TriangulationPoint(MaxX, MaxY);
102 | Add(ptUR);
103 | }
104 | if (!TryGetPoint(MinX, MaxY, out ptUL))
105 | {
106 | ptUL = new TriangulationPoint(MinX, MaxY);
107 | Add(ptUL);
108 | }
109 | TriangulationConstraint tcLLtoLR = new TriangulationConstraint(ptLL, ptLR);
110 | AddConstraint(tcLLtoLR);
111 | TriangulationConstraint tcLRtoUR = new TriangulationConstraint(ptLR, ptUR);
112 | AddConstraint(tcLRtoUR);
113 | TriangulationConstraint tcURtoUL = new TriangulationConstraint(ptUR, ptUL);
114 | AddConstraint(tcURtoUL);
115 | TriangulationConstraint tcULtoLL = new TriangulationConstraint(ptUL, ptLL);
116 | AddConstraint(tcULtoLL);
117 | }
118 |
119 |
120 | public override void Add(Point2D p)
121 | {
122 | Add(p as TriangulationPoint, -1, true);
123 | }
124 |
125 |
126 | public override void Add(TriangulationPoint p)
127 | {
128 | Add(p, -1, true);
129 | }
130 |
131 |
132 | public override bool AddRange(IEnumerable points)
133 | {
134 | bool bOk = true;
135 | foreach (TriangulationPoint p in points)
136 | {
137 | bOk = Add(p, -1, true) && bOk;
138 | }
139 |
140 | return bOk;
141 | }
142 |
143 |
144 | // Assumes that points being passed in the list are connected and form a polygon.
145 | // Note that some error checking is done for robustness, but for the most part,
146 | // we have to rely on the user to feed us "correct" data
147 | public bool AddHole(List points)
148 | {
149 | if (points == null)
150 | {
151 | return false;
152 | }
153 |
154 | //// split our self-intersection sections into their own lists
155 | List pts = new List();
156 | int listIdx = 0;
157 | {
158 | Contour c = new Contour(this, points, WindingOrderType.Unknown);
159 | pts.Add(c);
160 |
161 | // only constrain the points if we actually HAVE a bounding rect
162 | if (MPoints.Count > 1)
163 | {
164 | // constrain the points to bounding rect
165 | int numPoints = pts[listIdx].Count;
166 | for (int i = 0; i < numPoints; ++i)
167 | {
168 | ConstrainPointToBounds(pts[listIdx][i]);
169 | }
170 | }
171 | }
172 |
173 | while (listIdx < pts.Count)
174 | {
175 | // simple sanity checking - remove duplicate coincident points before
176 | // we check the polygon: fast, simple algorithm that eliminate lots of problems
177 | // that only more expensive checks will find
178 | pts[listIdx].RemoveDuplicateNeighborPoints();
179 | pts[listIdx].WindingOrder = WindingOrderType.Default;
180 |
181 | bool bListOk = true;
182 | PolygonError err = pts[listIdx].CheckPolygon();
183 | while (bListOk && err != PolygonError.None)
184 | {
185 | if ((err & PolygonError.NotEnoughVertices) == PolygonError.NotEnoughVertices)
186 | {
187 | bListOk = false;
188 | continue;
189 | }
190 | if ((err & PolygonError.NotSimple) == PolygonError.NotSimple)
191 | {
192 | // split the polygons, remove the current list and add the resulting list to the end
193 | //List l = TriangulationUtil.SplitSelfIntersectingPolygon(pts[listIdx], pts[listIdx].Epsilon);
194 | IEnumerable l = PolygonUtil.SplitComplexPolygon(pts[listIdx], pts[listIdx].Epsilon);
195 | pts.RemoveAt(listIdx);
196 | foreach (Point2DList newList in l)
197 | {
198 | Contour c = new Contour(this);
199 | c.AddRange(newList);
200 | pts.Add(c);
201 | }
202 | err = pts[listIdx].CheckPolygon();
203 | continue;
204 | }
205 | if ((err & PolygonError.Degenerate) == PolygonError.Degenerate)
206 | {
207 | pts[listIdx].Simplify(Epsilon);
208 | err = pts[listIdx].CheckPolygon();
209 | continue;
210 | //err &= ~(PolygonError.Degenerate);
211 | //if (pts[listIdx].Count < 3)
212 | //{
213 | // err |= PolygonError.NotEnoughVertices;
214 | // bListOK = false;
215 | // continue;
216 | //}
217 | }
218 | if ((err & PolygonError.AreaTooSmall) == PolygonError.AreaTooSmall ||
219 | (err & PolygonError.SidesTooCloseToParallel) == PolygonError.SidesTooCloseToParallel ||
220 | (err & PolygonError.TooThin) == PolygonError.TooThin ||
221 | (err & PolygonError.Unknown) == PolygonError.Unknown)
222 | {
223 | bListOk = false;
224 | }
225 | // non-convex polygons are ok
226 | //if ((err & PolygonError.NotConvex) == PolygonError.NotConvex)
227 | //{
228 | //}
229 | }
230 | if (!bListOk && pts[listIdx].Count != 2)
231 | {
232 | pts.RemoveAt(listIdx);
233 | }
234 | else
235 | {
236 | ++listIdx;
237 | }
238 | }
239 |
240 | bool bOk = true;
241 | listIdx = 0;
242 | while (listIdx < pts.Count)
243 | {
244 | int numPoints = pts[listIdx].Count;
245 | if (numPoints < 2)
246 | {
247 | // should not be possible by this point...
248 | ++listIdx;
249 | bOk = false;
250 | continue;
251 | }
252 | else if (numPoints == 2)
253 | {
254 | uint constraintCode = TriangulationConstraint.CalculateContraintCode(pts[listIdx][0], pts[listIdx][1]);
255 | TriangulationConstraint tc;
256 | if (!_constraintMap.TryGetValue(constraintCode, out tc))
257 | {
258 | tc = new TriangulationConstraint(pts[listIdx][0], pts[listIdx][1]);
259 | AddConstraint(tc);
260 | }
261 | }
262 | else
263 | {
264 | Contour ph = new Contour(this, pts[listIdx], WindingOrderType.Unknown) {
265 | WindingOrder = WindingOrderType.Default,
266 | };
267 | _holes.Add(ph);
268 | }
269 | ++listIdx;
270 | }
271 |
272 | return bOk;
273 | }
274 |
275 |
276 | // this method adds constraints singly and does not assume that they form a contour
277 | // If you are trying to add a "series" or edges (or "contour"), use AddHole instead.
278 | private void AddConstraints(IEnumerable constraints)
279 | {
280 | if (constraints == null)
281 | return;
282 |
283 | foreach (TriangulationConstraint tc in constraints)
284 | {
285 | if (ConstrainPointToBounds(tc.P) || ConstrainPointToBounds(tc.Q))
286 | {
287 | tc.CalculateContraintCode();
288 | }
289 |
290 | TriangulationConstraint tcTmp;
291 | if (!_constraintMap.TryGetValue(tc.ConstraintCode, out tcTmp))
292 | {
293 | tcTmp = tc;
294 | AddConstraint(tcTmp);
295 | }
296 | }
297 | }
298 |
299 |
300 | public void AddConstraint(TriangulationConstraint tc)
301 | {
302 | if (tc == null || tc.P == null || tc.Q == null)
303 | {
304 | return;
305 | }
306 |
307 | // If we already have this constraint, then there's nothing to do. Since we already have
308 | // a valid constraint in the map with the same ConstraintCode, then we're guaranteed that
309 | // the points are also valid (and have the same coordinates as the ones being passed in with
310 | // this constrain). Return true to indicate that we successfully "added" the constraint
311 | if (_constraintMap.ContainsKey(tc.ConstraintCode))
312 | {
313 | return;
314 | }
315 |
316 | // Make sure the constraint is not using points that are duplicates of ones already stored
317 | // If it is, replace the Constraint Points with the points already stored.
318 | TriangulationPoint p;
319 | if (TryGetPoint(tc.P.X, tc.P.Y, out p))
320 | {
321 | tc.P = p;
322 | }
323 | else
324 | {
325 | Add(tc.P);
326 | }
327 |
328 | if (TryGetPoint(tc.Q.X, tc.Q.Y, out p))
329 | {
330 | tc.Q = p;
331 | }
332 | else
333 | {
334 | Add(tc.Q);
335 | }
336 |
337 | _constraintMap.Add(tc.ConstraintCode, tc);
338 | }
339 |
340 |
341 | public bool TryGetConstraint(uint constraintCode, out TriangulationConstraint tc)
342 | {
343 | return _constraintMap.TryGetValue(constraintCode, out tc);
344 | }
345 |
346 |
347 | public int GetNumConstraints()
348 | {
349 | return _constraintMap.Count;
350 | }
351 |
352 |
353 | public Dictionary.Enumerator GetConstraintEnumerator()
354 | {
355 | return _constraintMap.GetEnumerator();
356 | }
357 |
358 |
359 | public int GetNumHoles()
360 | {
361 | return _holes.Sum(c => c.GetNumHoles(false));
362 | }
363 |
364 | public Contour GetHole(int idx)
365 | {
366 | if (idx < 0 || idx >= _holes.Count)
367 | {
368 | return null;
369 | }
370 |
371 | return _holes[idx];
372 | }
373 |
374 |
375 | public int GetActualHoles(out List holes)
376 | {
377 | holes = new List();
378 | foreach (Contour c in _holes)
379 | {
380 | c.GetActualHoles(false, ref holes);
381 | }
382 |
383 | return holes.Count;
384 | }
385 |
386 | private void InitializeHoles()
387 | {
388 | Contour.InitializeHoles(_holes, this, this);
389 | foreach (Contour c in _holes)
390 | {
391 | c.InitializeHoles(this);
392 | }
393 | }
394 |
395 | protected override bool Initialize()
396 | {
397 | InitializeHoles();
398 | return base.Initialize();
399 | }
400 |
401 |
402 | public override void Prepare(TriangulationContext tcx)
403 | {
404 | if (!Initialize())
405 | {
406 | return;
407 | }
408 |
409 | base.Prepare(tcx);
410 |
411 | Dictionary.Enumerator it = _constraintMap.GetEnumerator();
412 | while (it.MoveNext())
413 | {
414 | TriangulationConstraint tc = it.Current.Value;
415 | tcx.NewConstraint(tc.P, tc.Q);
416 | }
417 | }
418 |
419 |
420 | public override void AddTriangle(DelaunayTriangle t)
421 | {
422 | Triangles.Add(t);
423 | }
424 |
425 | }
426 | }
427 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Sets/PointSet.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System;
33 | using System.Collections.Generic;
34 | using System.Linq;
35 | using Poly2Tri.Triangulation.Delaunay;
36 | using Poly2Tri.Utility;
37 |
38 | namespace Poly2Tri.Triangulation.Sets
39 | {
40 | public class PointSet : Point2DList, ITriangulatable, IEnumerable, IList
41 | {
42 | private readonly Dictionary _pointMap = new Dictionary();
43 | public IList Triangles { get; private set; }
44 |
45 | public string FileName { get; set; }
46 | public bool DisplayFlipX { get; set; }
47 | public bool DisplayFlipY { get; set; }
48 | public float DisplayRotate { get; set; }
49 |
50 | private double _precision = TriangulationPoint.VERTEX_CODE_DEFAULT_PRECISION;
51 | public double Precision { get { return _precision; } set { _precision = value; } }
52 |
53 | public double MinX { get { return BoundingBox.MinX; } }
54 | public double MaxX { get { return BoundingBox.MaxX; } }
55 | public double MinY { get { return BoundingBox.MinY; } }
56 | public double MaxY { get { return BoundingBox.MaxY; } }
57 | public Rect2D Bounds { get { return BoundingBox; } }
58 |
59 | public virtual TriangulationMode TriangulationMode { get { return TriangulationMode.Unconstrained; } }
60 |
61 | public new TriangulationPoint this[int index]
62 | {
63 | get { return MPoints[index] as TriangulationPoint; }
64 | set { MPoints[index] = value; }
65 | }
66 |
67 | protected PointSet(IEnumerable bounds)
68 | {
69 | //Points = new List();
70 | foreach (TriangulationPoint p in bounds)
71 | {
72 | Add(p, -1, false);
73 |
74 | // Only the initial points are counted toward min/max x/y as they
75 | // are considered to be the boundaries of the point-set
76 | BoundingBox = BoundingBox.AddPoint(p);
77 | }
78 | Epsilon = CalculateEpsilon();
79 | WindingOrder = WindingOrderType.Unknown; // not valid for a point-set
80 | }
81 |
82 |
83 | IEnumerator IEnumerable.GetEnumerator()
84 | {
85 | return MPoints.Cast().GetEnumerator();
86 | }
87 |
88 |
89 | public int IndexOf(TriangulationPoint p)
90 | {
91 | return MPoints.IndexOf(p);
92 | }
93 |
94 |
95 | public override void Add(Point2D p)
96 | {
97 | Add(p as TriangulationPoint, -1, false);
98 | }
99 |
100 | public virtual void Add(TriangulationPoint p)
101 | {
102 | Add(p, -1, false);
103 | }
104 |
105 |
106 | protected override void Add(Point2D p, int idx, bool constrainToBounds)
107 | {
108 | Add(p as TriangulationPoint, idx, constrainToBounds);
109 | }
110 |
111 |
112 | protected bool Add(TriangulationPoint p, int idx, bool constrainToBounds)
113 | {
114 | if (p == null)
115 | {
116 | return false;
117 | }
118 |
119 | if (constrainToBounds)
120 | {
121 | ConstrainPointToBounds(p);
122 | }
123 |
124 | // if we already have an instance of the point, then don't bother inserting it again as duplicate points
125 | // will actually cause some real problems later on. Still return true though to indicate that the point
126 | // is successfully "added"
127 | if (_pointMap.ContainsKey(p.VertexCode))
128 | {
129 | return true;
130 | }
131 | _pointMap.Add(p.VertexCode, p);
132 |
133 | if (idx < 0)
134 | {
135 | MPoints.Add(p);
136 | }
137 | else
138 | {
139 | MPoints.Insert(idx, p);
140 | }
141 |
142 | return true;
143 | }
144 |
145 | protected override void AddRange(IEnumerator iter, WindingOrderType windingOrder)
146 | {
147 | if (iter == null)
148 | {
149 | return;
150 | }
151 |
152 | iter.Reset();
153 | while (iter.MoveNext())
154 | {
155 | Add(iter.Current);
156 | }
157 | }
158 |
159 |
160 | public virtual bool AddRange(IEnumerable points)
161 | {
162 | bool bOk = true;
163 | foreach (TriangulationPoint p in points)
164 | {
165 | bOk = Add(p, -1, false) && bOk;
166 | }
167 |
168 | return bOk;
169 | }
170 |
171 | protected bool TryGetPoint(double x, double y, out TriangulationPoint p)
172 | {
173 | uint vc = TriangulationPoint.CreateVertexCode(x, y, Precision);
174 | if (_pointMap.TryGetValue(vc, out p))
175 | {
176 | return true;
177 | }
178 |
179 | return false;
180 | }
181 |
182 | public void Insert(int idx, TriangulationPoint item)
183 | {
184 | MPoints.Insert(idx, item);
185 | }
186 |
187 |
188 | public override bool Remove(Point2D p)
189 | {
190 | return MPoints.Remove(p);
191 | }
192 |
193 |
194 | public bool Remove(TriangulationPoint p)
195 | {
196 | return MPoints.Remove(p);
197 | }
198 |
199 |
200 | public override void RemoveAt(int idx)
201 | {
202 | if (idx < 0 || idx >= Count)
203 | {
204 | return;
205 | }
206 | MPoints.RemoveAt(idx);
207 | }
208 |
209 |
210 | public bool Contains(TriangulationPoint p)
211 | {
212 | return MPoints.Contains(p);
213 | }
214 |
215 |
216 | public void CopyTo(TriangulationPoint[] array, int arrayIndex)
217 | {
218 | int numElementsToCopy = Math.Min(Count, array.Length - arrayIndex);
219 | for (int i = 0; i < numElementsToCopy; ++i)
220 | {
221 | array[arrayIndex + i] = MPoints[i] as TriangulationPoint;
222 | }
223 | }
224 |
225 |
226 | // returns true if the point is changed, false if the point is unchanged
227 | protected bool ConstrainPointToBounds(Point2D p)
228 | {
229 | double oldX = p.X;
230 | double oldY = p.Y;
231 | p.X = Math.Max(MinX, p.X);
232 | p.X = Math.Min(MaxX, p.X);
233 | p.Y = Math.Max(MinY, p.Y);
234 | p.Y = Math.Min(MaxY, p.Y);
235 |
236 | // ReSharper disable CompareOfFloatsByEqualityOperator
237 | return (p.X != oldX) || (p.Y != oldY);
238 | // ReSharper restore CompareOfFloatsByEqualityOperator
239 | }
240 |
241 |
242 | protected bool ConstrainPointToBounds(TriangulationPoint p)
243 | {
244 | double oldX = p.X;
245 | double oldY = p.Y;
246 | p.X = Math.Max(MinX, p.X);
247 | p.X = Math.Min(MaxX, p.X);
248 | p.Y = Math.Max(MinY, p.Y);
249 | p.Y = Math.Min(MaxY, p.Y);
250 |
251 | // ReSharper disable CompareOfFloatsByEqualityOperator
252 | return (p.X != oldX) || (p.Y != oldY);
253 | // ReSharper restore CompareOfFloatsByEqualityOperator
254 | }
255 |
256 |
257 | public virtual void AddTriangle(DelaunayTriangle t)
258 | {
259 | Triangles.Add(t);
260 | }
261 |
262 |
263 | public void AddTriangles(IEnumerable list)
264 | {
265 | foreach (var tri in list)
266 | {
267 | AddTriangle(tri);
268 | }
269 | }
270 |
271 |
272 | public void ClearTriangles()
273 | {
274 | Triangles.Clear();
275 | }
276 |
277 | protected virtual bool Initialize()
278 | {
279 | return true;
280 | }
281 |
282 |
283 | public virtual void Prepare(TriangulationContext tcx)
284 | {
285 | if (Triangles == null)
286 | {
287 | Triangles = new List(Count);
288 | }
289 | else
290 | {
291 | Triangles.Clear();
292 | }
293 | tcx.Points.AddRange(this);
294 | }
295 | }
296 | }
297 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/TriangulationAlgorithm.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | namespace Poly2Tri.Triangulation
33 | {
34 | public enum TriangulationAlgorithm
35 | {
36 | DTSweep
37 | }
38 | }
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/TriangulationConstraint.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 | /**
32 | * Forces a triangle edge between two points p and q
33 | * when triangulating. For example used to enforce
34 | * Polygon Edges during a polygon triangulation.
35 | *
36 | * @author Thomas Åhlén, thahlen@gmail.com
37 | */
38 |
39 | using System;
40 | using Poly2Tri.Utility;
41 |
42 | namespace Poly2Tri.Triangulation
43 | {
44 | public class Edge
45 | {
46 | public Point2D EdgeStart { get; set; }
47 | public Point2D EdgeEnd { get; set; }
48 |
49 | public Edge() { EdgeStart = null; EdgeEnd = null; }
50 | public Edge(Point2D edgeStart, Point2D edgeEnd)
51 | {
52 | EdgeStart = edgeStart;
53 | EdgeEnd = edgeEnd;
54 | }
55 | }
56 |
57 |
58 | public class TriangulationConstraint : Edge
59 | {
60 | public TriangulationPoint P
61 | {
62 | get { return EdgeStart as TriangulationPoint; }
63 | set
64 | {
65 | if (value != null && !value.Equals(EdgeStart))
66 | {
67 | EdgeStart = value;
68 | CalculateContraintCode();
69 | }
70 | }
71 | }
72 | public TriangulationPoint Q
73 | {
74 | get { return EdgeEnd as TriangulationPoint; }
75 | set
76 | {
77 | // Note: intentionally use != instead of !Equals() because we
78 | // WANT to compare pointer values here rather than VertexCode values
79 | if (value != null && !value.Equals(EdgeEnd))
80 | {
81 | EdgeEnd = value;
82 | CalculateContraintCode();
83 | }
84 | }
85 | }
86 |
87 | public uint ConstraintCode { get; private set; }
88 |
89 | ///
90 | /// Give two points in any order. Will always be ordered so
91 | /// that q.y > p.y and q.x > p.x if same y value
92 | ///
93 | public TriangulationConstraint(Point2D p1, Point2D p2)
94 | {
95 | ConstraintCode = 0;
96 | EdgeStart = p1;
97 | EdgeEnd = p2;
98 | if (p1.Y > p2.Y)
99 | {
100 | EdgeEnd = p1;
101 | EdgeStart = p2;
102 | }
103 | else if (p1.Y == p2.Y)
104 | {
105 | if (p1.X > p2.X)
106 | {
107 | EdgeEnd = p1;
108 | EdgeStart = p2;
109 | }
110 | else if (p1.X == p2.X)
111 | {
112 | // logger.info( "Failed to create constraint {}={}", p1, p2 );
113 | // throw new DuplicatePointException( p1 + "=" + p2 );
114 | // return;
115 | }
116 | }
117 | CalculateContraintCode();
118 | }
119 |
120 |
121 | public override string ToString()
122 | {
123 | return string.Format("[P={0}, Q={1} : {{{2}}}]", P, Q, ConstraintCode);
124 | }
125 |
126 |
127 | public void CalculateContraintCode()
128 | {
129 | ConstraintCode = CalculateContraintCode(P, Q);
130 | }
131 |
132 |
133 | public static uint CalculateContraintCode(TriangulationPoint p, TriangulationPoint q)
134 | {
135 | if (p == null || p == null)
136 | {
137 | throw new ArgumentNullException();
138 | }
139 |
140 | uint constraintCode = MathUtil.Jenkins32Hash(BitConverter.GetBytes(p.VertexCode), 0);
141 | constraintCode = MathUtil.Jenkins32Hash(BitConverter.GetBytes(q.VertexCode), constraintCode);
142 |
143 | return constraintCode;
144 | }
145 |
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/TriangulationContext.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System.Collections.Generic;
33 | using Poly2Tri.Triangulation.Delaunay;
34 | using Poly2Tri.Triangulation.Delaunay.Sweep;
35 |
36 | namespace Poly2Tri.Triangulation
37 | {
38 | public abstract class TriangulationContext
39 | {
40 | protected TriangulationDebugContext DebugContext { get; private set; }
41 | public bool IsDebugEnabled { get; protected set; }
42 |
43 | public readonly List Triangles = new List();
44 | public readonly List Points = new List(200);
45 | public TriangulationMode TriangulationMode { get; private set; }
46 | public ITriangulatable Triangulatable { get; private set; }
47 |
48 | public abstract TriangulationAlgorithm Algorithm { get; }
49 |
50 | protected TriangulationContext(TriangulationDebugContext debug)
51 | {
52 | DebugContext = debug;
53 | }
54 |
55 | public virtual void PrepareTriangulation(ITriangulatable t)
56 | {
57 | Triangulatable = t;
58 | TriangulationMode = t.TriangulationMode;
59 | t.Prepare(this);
60 |
61 | //List constraints = new List();
62 |
63 | //Console.WriteLine("Points for " + t.FileName + ":");
64 | //Console.WriteLine("Idx,X,Y,VC,Edges");
65 | //int numPoints = Points.Count;
66 | //for (int i = 0; i < numPoints; ++i)
67 | //{
68 | // StringBuilder sb = new StringBuilder(128);
69 | // sb.Append(i.ToString());
70 | // sb.Append(",");
71 | // sb.Append(Points[i].X.ToString());
72 | // sb.Append(",");
73 | // sb.Append(Points[i].Y.ToString());
74 | // sb.Append(",");
75 | // sb.Append(Points[i].VertexCode.ToString());
76 | // int numEdges = (Points[i].Edges != null) ? Points[i].Edges.Count : 0;
77 | // for (int j = 0; j < numEdges; ++j)
78 | // {
79 | // TriangulationConstraint tc = Points[i].Edges[j];
80 | // sb.Append(",");
81 | // sb.Append(tc.ConstraintCode.ToString());
82 | // constraints.Add(tc);
83 | // }
84 | // Console.WriteLine(sb.ToString());
85 | //}
86 |
87 | //int idx = 0;
88 | //Console.WriteLine("Constraints " + t.FileName + ":");
89 | //Console.WriteLine("EdgeIdx,Px,Py,PVC,Qx,Qy,QVC,ConstraintCode,Owner");
90 | //foreach (TriangulationConstraint tc in constraints)
91 | //{
92 | // StringBuilder sb = new StringBuilder(128);
93 |
94 | // sb.Append(idx.ToString());
95 | // sb.Append(",");
96 | // sb.Append(tc.P.X.ToString());
97 | // sb.Append(",");
98 | // sb.Append(tc.P.Y.ToString());
99 | // sb.Append(",");
100 | // sb.Append(tc.P.VertexCode.ToString());
101 | // sb.Append(",");
102 | // sb.Append(tc.Q.X.ToString());
103 | // sb.Append(",");
104 | // sb.Append(tc.Q.Y.ToString());
105 | // sb.Append(",");
106 | // sb.Append(tc.Q.VertexCode.ToString());
107 | // sb.Append(",");
108 | // sb.Append(tc.ConstraintCode.ToString());
109 | // sb.Append(",");
110 | // if (tc.Q.HasEdge(tc.P))
111 | // {
112 | // sb.Append("Q");
113 | // }
114 | // else
115 | // {
116 | // sb.Append("P");
117 | // }
118 | // Console.WriteLine(sb.ToString());
119 |
120 | // ++idx;
121 | //}
122 | }
123 |
124 |
125 | // ReSharper disable UnusedMethodReturnValue.Global
126 | public abstract DTSweepConstraint NewConstraint(TriangulationPoint a, TriangulationPoint b);
127 | // ReSharper restore UnusedMethodReturnValue.Global
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/TriangulationDebugContext.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | namespace Poly2Tri.Triangulation
33 | {
34 | public abstract class TriangulationDebugContext
35 | {
36 | public abstract void Clear();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/TriangulationMode.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | namespace Poly2Tri.Triangulation
33 | {
34 | public enum TriangulationMode
35 | {
36 | Unconstrained,
37 | Constrained,
38 | Polygon
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/TriangulationPoint.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System;
33 | using System.Collections.Generic;
34 | using System.Linq;
35 | using Poly2Tri.Triangulation.Delaunay.Sweep;
36 | using Poly2Tri.Utility;
37 |
38 | namespace Poly2Tri.Triangulation
39 | {
40 |
41 | public class TriangulationPoint : Point2D, IEquatable
42 | {
43 | public const double VERTEX_CODE_DEFAULT_PRECISION = 3.0;
44 |
45 | public override double X
46 | {
47 | get { return base.X; }
48 | set
49 | {
50 | // ReSharper disable CompareOfFloatsByEqualityOperator
51 | if (value != base.X)
52 | // ReSharper restore CompareOfFloatsByEqualityOperator
53 | {
54 | base.X = value;
55 | VertexCode = CreateVertexCode(base.X, base.Y, VERTEX_CODE_DEFAULT_PRECISION);
56 |
57 | // Technically, we should change the ConstraintCodes of any edges that contain this point.
58 | // We don't for 2 reasons:
59 | // 1) Currently the only time we care about Vertex/Constraint Codes is when entering data in the point-set.
60 | // Once the data is being used by the algorithm, the point locations are (currently) not modified.
61 | // 2) Since this Point's Edge list will only contain SOME of the edges that this point is a part of,
62 | // there currently isn't a way to (easily) get any edges that contain this point but are not in this
63 | // point's edge list.
64 | }
65 | }
66 | }
67 | public override double Y
68 | {
69 | get { return base.Y; }
70 | set
71 | {
72 | // ReSharper disable CompareOfFloatsByEqualityOperator
73 | if (value != base.Y)
74 | // ReSharper restore CompareOfFloatsByEqualityOperator
75 | {
76 | base.Y = value;
77 | VertexCode = CreateVertexCode(base.X, base.Y, VERTEX_CODE_DEFAULT_PRECISION);
78 |
79 | // Technically, we should change the ConstraintCodes of any edges that contain this point.
80 | // We don't for 2 reasons:
81 | // 1) Currently the only time we care about Vertex/Constraint Codes is when entering data in the point-set.
82 | // Once the data is being used by the algorithm, the point locations are (currently) not modified.
83 | // 2) Since this Point's Edge list will only contain SOME of the edges that this point is a part of,
84 | // there currently isn't a way to (easily) get any edges that contain this point but are not in this
85 | // point's edge list.
86 | }
87 | }
88 | }
89 |
90 | public uint VertexCode { get; private set; }
91 |
92 | // List of edges this point constitutes an upper ending point (CDT)
93 | public List Edges { get; private set; }
94 | public bool HasEdges { get { return Edges != null; } }
95 |
96 | public TriangulationPoint(double x, double y, double precision = VERTEX_CODE_DEFAULT_PRECISION)
97 | : base(x,y)
98 | {
99 | VertexCode = CreateVertexCode(x, y, precision);
100 | }
101 |
102 |
103 | public override string ToString()
104 | {
105 | return base.ToString() + ":{" + VertexCode + "}";
106 | }
107 |
108 |
109 | public override int GetHashCode()
110 | {
111 | return (int)VertexCode;
112 | }
113 |
114 |
115 | public override bool Equals(object obj)
116 | {
117 | return Equals(obj as TriangulationPoint);
118 | }
119 |
120 | public bool Equals(TriangulationPoint other)
121 | {
122 | if (other == null)
123 | return false;
124 |
125 | return VertexCode == other.VertexCode && base.Equals(other);
126 | }
127 |
128 |
129 | public override void Set(double x, double y)
130 | {
131 | X = x;
132 | Y = y;
133 | }
134 |
135 |
136 | public static uint CreateVertexCode(double x, double y, double precision)
137 | {
138 | float fx = (float)MathUtil.RoundWithPrecision(x, precision);
139 | float fy = (float)MathUtil.RoundWithPrecision(y, precision);
140 | uint vc = MathUtil.Jenkins32Hash(BitConverter.GetBytes(fx), 0);
141 | vc = MathUtil.Jenkins32Hash(BitConverter.GetBytes(fy), vc);
142 |
143 | return vc;
144 | }
145 |
146 |
147 | public void AddEdge(DTSweepConstraint e)
148 | {
149 | if (Edges == null)
150 | {
151 | Edges = new List();
152 | }
153 | Edges.Add(e);
154 | }
155 |
156 |
157 | public bool HasEdge(TriangulationPoint p)
158 | {
159 | DTSweepConstraint tmp;
160 | return GetEdge(p, out tmp);
161 | }
162 |
163 |
164 | public bool GetEdge(TriangulationPoint p, out DTSweepConstraint edge)
165 | {
166 | edge = null;
167 | if (Edges == null || Edges.Count < 1 || p == null || p.Equals(this))
168 | {
169 | return false;
170 | }
171 |
172 | foreach (DTSweepConstraint sc in Edges.Where(sc => (sc.P.Equals(this) && sc.Q.Equals(p)) || (sc.P.Equals(p) && sc.Q.Equals(this))))
173 | {
174 | edge = sc;
175 | return true;
176 | }
177 |
178 | return false;
179 | }
180 |
181 | }
182 | }
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Util/PointGenerator.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System;
33 | using System.Collections.Generic;
34 |
35 | namespace Poly2Tri.Triangulation.Util
36 | {
37 | public class PointGenerator
38 | {
39 | static readonly Random _rng = new Random();
40 |
41 |
42 | public static List UniformDistribution(int n, double scale)
43 | {
44 | List points = new List();
45 | for (int i = 0; i < n; i++)
46 | {
47 | points.Add(new TriangulationPoint(scale * (0.5 - _rng.NextDouble()), scale * (0.5 - _rng.NextDouble())));
48 | }
49 |
50 | return points;
51 | }
52 |
53 |
54 | public static List UniformGrid(int n, double scale)
55 | {
56 | double size = scale / n;
57 | double halfScale = 0.5 * scale;
58 |
59 | List points = new List();
60 | for (int i = 0; i < n + 1; i++)
61 | {
62 | double x = halfScale - i * size;
63 | for (int j = 0; j < n + 1; j++)
64 | {
65 | points.Add(new TriangulationPoint(x, halfScale - j * size));
66 | }
67 | }
68 |
69 | return points;
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Util/PolygonGenerator.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System;
33 | using Poly2Tri.Triangulation.Polygon;
34 |
35 | namespace Poly2Tri.Triangulation.Util
36 | {
37 | public class PolygonGenerator
38 | {
39 | static readonly Random _rng = new Random();
40 |
41 | private const double PI_2 = 2.0 * Math.PI;
42 |
43 | public static Polygon.Polygon RandomCircleSweep(double scale, int vertexCount)
44 | {
45 | double radius = scale / 4;
46 |
47 | PolygonPoint[] points = new PolygonPoint[vertexCount];
48 | for (int i = 0; i < vertexCount; i++)
49 | {
50 | do
51 | {
52 | if (i % 250 == 0)
53 | {
54 | radius += scale / 2 * (0.5 - _rng.NextDouble());
55 | }
56 | else if (i % 50 == 0)
57 | {
58 | radius += scale / 5 * (0.5 - _rng.NextDouble());
59 | }
60 | else
61 | {
62 | radius += 25 * scale / vertexCount * (0.5 - _rng.NextDouble());
63 | }
64 | radius = radius > scale / 2 ? scale / 2 : radius;
65 | radius = radius < scale / 10 ? scale / 10 : radius;
66 | } while (radius < scale / 10 || radius > scale / 2);
67 | PolygonPoint point = new PolygonPoint(radius * Math.Cos((PI_2 * i) / vertexCount), radius * Math.Sin((PI_2 * i) / vertexCount));
68 | points[i] = point;
69 | }
70 | return new Polygon.Polygon(points);
71 | }
72 |
73 | public static Polygon.Polygon RandomCircleSweep2(double scale, int vertexCount)
74 | {
75 | double radius = scale / 4;
76 |
77 | PolygonPoint[] points = new PolygonPoint[vertexCount];
78 | for (int i = 0; i < vertexCount; i++)
79 | {
80 | do
81 | {
82 | radius += scale / 5 * (0.5 - _rng.NextDouble());
83 | radius = radius > scale / 2 ? scale / 2 : radius;
84 | radius = radius < scale / 10 ? scale / 10 : radius;
85 | } while (radius < scale / 10 || radius > scale / 2);
86 | PolygonPoint point = new PolygonPoint(radius * Math.Cos((PI_2 * i) / vertexCount), radius * Math.Sin((PI_2 * i) / vertexCount));
87 | points[i] = point;
88 | }
89 | return new Polygon.Polygon(points);
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Poly2Tri/Triangulation/Util/TriangulationUtil.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System;
33 | using Poly2Tri.Utility;
34 |
35 | namespace Poly2Tri.Triangulation.Util
36 | {
37 | /**
38 | * @author Thomas Åhlén, thahlen@gmail.com
39 | */
40 | public class TriangulationUtil
41 | {
42 | ///
43 | /// Requirements:
44 | /// 1. a,b and c form a triangle.
45 | /// 2. a and d is know to be on opposite side of bc
46 | ///
47 | /// a
48 | /// +
49 | /// / \
50 | /// / \
51 | /// b/ \c
52 | /// +-------+
53 | /// / B \
54 | /// / \
55 | ///
56 | /// Facts:
57 | /// d has to be in area B to have a chance to be inside the circle formed by a,b and c
58 | /// d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW
59 | /// This preknowledge gives us a way to optimize the incircle test
60 | ///
61 | /// triangle point, opposite d
62 | /// triangle point
63 | /// triangle point
64 | /// point opposite a
65 | /// true if d is inside circle, false if on circle edge
66 | public static bool SmartIncircle(Point2D pa, Point2D pb, Point2D pc, Point2D pd)
67 | {
68 | double pdx = pd.X;
69 | double pdy = pd.Y;
70 | double adx = pa.X - pdx;
71 | double ady = pa.Y - pdy;
72 | double bdx = pb.X - pdx;
73 | double bdy = pb.Y - pdy;
74 |
75 | double adxbdy = adx * bdy;
76 | double bdxady = bdx * ady;
77 | double oabd = adxbdy - bdxady;
78 | // oabd = orient2d(pa,pb,pd);
79 | if (oabd <= 0)
80 | {
81 | return false;
82 | }
83 |
84 | double cdx = pc.X - pdx;
85 | double cdy = pc.Y - pdy;
86 |
87 | double cdxady = cdx * ady;
88 | double adxcdy = adx * cdy;
89 | double ocad = cdxady - adxcdy;
90 | // ocad = orient2d(pc,pa,pd);
91 | if (ocad <= 0)
92 | {
93 | return false;
94 | }
95 |
96 | double bdxcdy = bdx * cdy;
97 | double cdxbdy = cdx * bdy;
98 |
99 | double alift = adx * adx + ady * ady;
100 | double blift = bdx * bdx + bdy * bdy;
101 | double clift = cdx * cdx + cdy * cdy;
102 |
103 | double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
104 |
105 | return det > 0;
106 | }
107 |
108 |
109 | public static bool InScanArea(Point2D pa, Point2D pb, Point2D pc, Point2D pd)
110 | {
111 | double pdx = pd.X;
112 | double pdy = pd.Y;
113 | double adx = pa.X - pdx;
114 | double ady = pa.Y - pdy;
115 | double bdx = pb.X - pdx;
116 | double bdy = pb.Y - pdy;
117 |
118 | double adxbdy = adx * bdy;
119 | double bdxady = bdx * ady;
120 | double oabd = adxbdy - bdxady;
121 | // oabd = orient2d(pa,pb,pd);
122 | if (oabd <= 0)
123 | {
124 | return false;
125 | }
126 |
127 | double cdx = pc.X - pdx;
128 | double cdy = pc.Y - pdy;
129 |
130 | double cdxady = cdx * ady;
131 | double adxcdy = adx * cdy;
132 | double ocad = cdxady - adxcdy;
133 | // ocad = orient2d(pc,pa,pd);
134 | if (ocad <= 0)
135 | {
136 | return false;
137 | }
138 | return true;
139 | }
140 |
141 |
142 | /// Forumla to calculate signed area
143 | /// Positive if CCW
144 | /// Negative if CW
145 | /// 0 if collinear
146 | /// A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
147 | /// = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
148 | public static Orientation Orient2d(Point2D pa, Point2D pb, Point2D pc)
149 | {
150 | double detleft = (pa.X - pc.X) * (pb.Y - pc.Y);
151 | double detright = (pa.Y - pc.Y) * (pb.X - pc.X);
152 | double val = detleft - detright;
153 | if (val > -MathUtil.EPSILON && val < MathUtil.EPSILON)
154 | {
155 | return Orientation.Collinear;
156 | }
157 | else if (val > 0)
158 | {
159 | return Orientation.AntiClockwise;
160 | }
161 | return Orientation.Clockwise;
162 | }
163 |
164 |
165 | ///////////////////////////////////////////////////////////////////////////////
166 | // PointRelativeToLine2D
167 | //
168 | // Returns -1 if point is on left of line, 0 if point is on line, and 1 if
169 | // the point is to the right of the line. This assumes a coordinate system
170 | // whereby the y axis goes upward when the x axis goes rightward. This is how
171 | // 3D systems (both right and left-handed) and PostScript works, but is not
172 | // how the Win32 GUI works. If you are using a 'y goes downward' coordinate
173 | // system, simply negate the return value from this function.
174 | //
175 | // Given a point (a,b) and a line from (x1,y1) to (x2,y2), we calculate the
176 | // following equation:
177 | // (y2-y1)*(a-x1)-(x2-x1)*(b-y1) (left)
178 | // If the result is > 0, the point is on 1 --------------> 2
179 | // the right, else left. (right)
180 | //
181 | // For example, with a point at (1,1) and a
182 | // line going from (0,0) to (2,0), we get:
183 | // (0-0)*(1-0)-(2-0)*(1-0)
184 | // which equals:
185 | // -2
186 | // Which indicates the point is (correctly)
187 | // on the left of the directed line.
188 | //
189 | // This function has been checked to a good degree.
190 | //
191 | /////////////////////////////////////////////////////////////////////////////
192 | //public static double PointRelativeToLine2D(Point2D ptPoint, Point2D ptLineBegin, Point2D ptLineEnd)
193 | //{
194 | // return (ptLineEnd.Y - ptLineBegin.Y) * (ptPoint.X - ptLineBegin.X) - (ptLineEnd.X - ptLineBegin.X) * (ptPoint.Y - ptLineBegin.Y);
195 | //}
196 |
197 |
198 | ///////////////////////////////////////////////////////////////////////////
199 | // PointInBoundingBox - checks if a point is completely inside an
200 | // axis-aligned bounding box defined by xmin, xmax, ymin, and ymax.
201 | // Note that the point must be fully inside for this method to return
202 | // true - it cannot lie on the border of the bounding box.
203 | ///////////////////////////////////////////////////////////////////////////
204 | public static bool PointInBoundingBox(double xmin, double xmax, double ymin, double ymax, Point2D p)
205 | {
206 | return (p.X > xmin && p.X < xmax && p.Y > ymin && p.Y < ymax);
207 | }
208 |
209 |
210 | public static bool PointOnLineSegment2D(Point2D lineStart, Point2D lineEnd, Point2D p, double epsilon)
211 | {
212 | return PointOnLineSegment2D(lineStart.X, lineStart.Y, lineEnd.X, lineEnd.Y, p.X, p.Y, epsilon);
213 | }
214 |
215 | private static bool PointOnLineSegment2D(double x1, double y1, double x2, double y2, double x, double y, double epsilon)
216 | {
217 | // First checking if (x, z) is in the range of the line segment's end points.
218 | if (MathUtil.IsValueBetween(x, x1, x2, epsilon) && MathUtil.IsValueBetween(y, y1, y2, epsilon))
219 | {
220 | if (MathUtil.AreValuesEqual(x2 - x1, 0.0f, epsilon))
221 | {
222 | // Vertical line.
223 | return true;
224 | }
225 |
226 | double slope = (y2 - y1) / (x2 - x1);
227 | double yIntercept = -(slope * x1) + y1;
228 |
229 | // Checking if (x, y) is on the line passing through the end points.
230 | double t = y - ((slope * x) + yIntercept);
231 |
232 | return MathUtil.AreValuesEqual(t, 0.0f, epsilon);
233 | }
234 |
235 | return false;
236 | }
237 |
238 |
239 | public static bool RectsIntersect(Rect2D r1, Rect2D r2)
240 | {
241 | return (r1.Right > r2.Left) &&
242 | (r1.Left < r2.Right) &&
243 | (r1.Bottom > r2.Top) &&
244 | (r1.Top < r2.Bottom);
245 | }
246 |
247 | ///
248 | /// This method detects if two line segments (or lines) intersect,
249 | /// and, if so, the point of intersection. Use the and
250 | /// parameters to set whether the intersection point
251 | /// must be on the first and second line segments. Setting these
252 | /// both to true means you are doing a line-segment to line-segment
253 | /// intersection. Setting one of them to true means you are doing a
254 | /// line to line-segment intersection test, and so on.
255 | /// Note: If two line segments are coincident, then
256 | /// no intersection is detected (there are actually
257 | /// infinite intersection points).
258 | ///
259 | /// The first point of the first line segment.
260 | /// The second point of the first line segment.
261 | /// The first point of the second line segment.
262 | /// The second point of the second line segment.
263 | /// Set this to true to require that the
264 | /// intersection point be on the first line segment.
265 | /// Set this to true to require that the
266 | /// intersection point be on the second line segment.
267 | /// Set this to true to enable collisions if the line segments share
268 | /// an endpoint
269 | /// This is set to the intersection
270 | /// point if an intersection is detected.
271 | ///
272 | /// True if an intersection is detected, false otherwise.
273 | public static bool LinesIntersect2D( Point2D ptStart0, Point2D ptEnd0,
274 | Point2D ptStart1, Point2D ptEnd1,
275 | bool firstIsSegment, bool secondIsSegment, bool coincidentEndPointCollisions,
276 | ref Point2D pIntersectionPt,
277 | double epsilon)
278 | {
279 | double d = (ptEnd0.X - ptStart0.X) * (ptStart1.Y - ptEnd1.Y) - (ptStart1.X - ptEnd1.X) * (ptEnd0.Y - ptStart0.Y);
280 | if (Math.Abs(d) < epsilon)
281 | {
282 | //The lines are parallel.
283 | return false;
284 | }
285 |
286 | double d0 = (ptStart1.X - ptStart0.X) * (ptStart1.Y - ptEnd1.Y) - (ptStart1.X - ptEnd1.X) * (ptStart1.Y - ptStart0.Y);
287 | double d1 = (ptEnd0.X - ptStart0.X) * (ptStart1.Y - ptStart0.Y) - (ptStart1.X - ptStart0.X) * (ptEnd0.Y - ptStart0.Y);
288 | double kOneOverD = 1 / d;
289 | double t0 = d0 * kOneOverD;
290 | double t1 = d1 * kOneOverD;
291 |
292 | if ((!firstIsSegment || ((t0 >= 0.0) && (t0 <= 1.0))) &&
293 | (!secondIsSegment || ((t1 >= 0.0) && (t1 <= 1.0))) &&
294 | (coincidentEndPointCollisions || (!MathUtil.AreValuesEqual(0.0, t0, epsilon) && !MathUtil.AreValuesEqual(0.0, t1, epsilon))))
295 | {
296 | if (pIntersectionPt != null)
297 | {
298 | pIntersectionPt.X = ptStart0.X + t0 * (ptEnd0.X - ptStart0.X);
299 | pIntersectionPt.Y = ptStart0.Y + t0 * (ptEnd0.Y - ptStart0.Y);
300 | }
301 |
302 | return true;
303 | }
304 |
305 | return false;
306 | }
307 |
308 |
309 | public static bool LinesIntersect2D( Point2D ptStart0, Point2D ptEnd0,
310 | Point2D ptStart1, Point2D ptEnd1,
311 | ref Point2D pIntersectionPt,
312 | double epsilon)
313 | {
314 | return LinesIntersect2D(ptStart0, ptEnd0, ptStart1, ptEnd1, true, true, false, ref pIntersectionPt, epsilon);
315 | }
316 |
317 |
318 | ///////////////////////////////////////////////////////////////////////////
319 | // RaysIntersect2D
320 | //
321 | // Given two lines defined by (sorry about the lame notation):
322 | // x0 = x00 + vector_x0*s;
323 | // y0 = y00 + vector_y0*s;
324 | //
325 | // x1 = x10 + vector_x1*t;
326 | // y1 = y10 + vector_y1*t;
327 | //
328 | // This function determines the intersection between them, if there is any.
329 | //
330 | // This function assumes the lines to have no endpoints and will intersect
331 | // them anywhere in 2D space.
332 | //
333 | // This algorithm taken from "Realtime-Rendering" section 10.12.
334 | //
335 | // This function has been checked to a good degree.
336 | //
337 | ///////////////////////////////////////////////////////////////////////////
338 | private static double LI2DDotProduct(Point2D v0, Point2D v1)
339 | {
340 | return ((v0.X * v1.X) + (v0.Y * v1.Y));
341 | }
342 |
343 |
344 | public static bool RaysIntersect2D( Point2D ptRayOrigin0, Point2D ptRayVector0,
345 | Point2D ptRayOrigin1, Point2D ptRayVector1,
346 | ref Point2D ptIntersection)
347 | {
348 | const double K_EPSILON = 0.01;
349 |
350 | if (ptIntersection != null)
351 | {
352 | //If the user wants an actual intersection result...
353 |
354 | //This is a vector from pLineOrigin0 to ptLineOrigin1.
355 | Point2D ptTemp1 = new Point2D(ptRayOrigin1.X - ptRayOrigin0.X, ptRayOrigin1.Y - ptRayOrigin0.Y);
356 |
357 | //This is a vector perpendicular to ptVector1.
358 | Point2D ptTemp2 = new Point2D(-ptRayVector1.Y, ptRayVector1.X);
359 |
360 | double fDot1 = LI2DDotProduct(ptRayVector0, ptTemp2);
361 |
362 | if (Math.Abs(fDot1) < K_EPSILON)
363 | {
364 | return false; //The lines are essentially parallel.
365 | }
366 |
367 | double fDot2 = LI2DDotProduct(ptTemp1, ptTemp2);
368 | double s = fDot2 / fDot1;
369 | ptIntersection.X = ptRayOrigin0.X + ptRayVector0.X * s;
370 | ptIntersection.Y = ptRayOrigin0.Y + ptRayVector0.Y * s;
371 | return true;
372 | }
373 |
374 | //Else the user just wants to know if there is an intersection...
375 | //In this case we need only compare the slopes of the lines.
376 | double delta = ptRayVector1.X - ptRayVector0.X;
377 | if (Math.Abs(delta) > K_EPSILON)
378 | {
379 | delta = ptRayVector1.Y - ptRayVector0.Y;
380 | if (Math.Abs(delta) > K_EPSILON)
381 | {
382 | return true; //The lines are not parallel.
383 | }
384 | }
385 |
386 | return false;
387 | }
388 |
389 | }
390 |
391 |
392 | }
393 |
--------------------------------------------------------------------------------
/Poly2Tri/Utility/FixedArray3.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System;
33 | using System.Collections;
34 | using System.Collections.Generic;
35 |
36 | namespace Poly2Tri.Utility
37 | {
38 | public struct FixedArray3 : IEnumerable where T : IEquatable
39 | {
40 | public T Item0;
41 | public T Item1;
42 | public T Item2;
43 |
44 | public T this[int index]
45 | {
46 | get
47 | {
48 | switch (index)
49 | {
50 | case 0:
51 | return Item0;
52 | case 1:
53 | return Item1;
54 | case 2:
55 | return Item2;
56 | default:
57 | throw new IndexOutOfRangeException();
58 | }
59 | }
60 | set
61 | {
62 | switch (index)
63 | {
64 | case 0:
65 | Item0 = value;
66 | break;
67 | case 1:
68 | Item1 = value;
69 | break;
70 | case 2:
71 | Item2 = value;
72 | break;
73 | default:
74 | throw new IndexOutOfRangeException();
75 | }
76 | }
77 | }
78 |
79 |
80 | public bool Contains(T value)
81 | {
82 | return IndexOf(value) != -1;
83 | }
84 |
85 |
86 | public int IndexOf(T value)
87 | {
88 | for (int i = 0; i < 3; ++i)
89 | {
90 | if (!this[i].Equals(default(T)) && this[i].Equals(value))
91 | {
92 | return i;
93 | }
94 | }
95 |
96 | return -1;
97 | }
98 |
99 |
100 | public void Clear()
101 | {
102 | Item0 = Item1 = Item2 = default(T);
103 | }
104 |
105 |
106 | public void Clear(T value)
107 | {
108 | for (int i = 0; i < 3; ++i)
109 | {
110 | if (this[i].Equals(default(T)) && this[i].Equals(value))
111 | {
112 | this[i] = default(T);
113 | }
114 | }
115 | }
116 |
117 |
118 | private IEnumerable Enumerate()
119 | {
120 | for (int i = 0; i < 3; ++i)
121 | {
122 | yield return this[i];
123 | }
124 | }
125 |
126 |
127 | public IEnumerator GetEnumerator() { return Enumerate().GetEnumerator(); }
128 |
129 |
130 | IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/Poly2Tri/Utility/MathUtil.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Poly2Tri.Utility
5 | {
6 | public class MathUtil
7 | {
8 | public const double EPSILON = 1e-12;
9 |
10 | public static bool AreValuesEqual(double val1, double val2, double tolerance = EPSILON)
11 | {
12 | if (val1 >= (val2 - tolerance) && val1 <= (val2 + tolerance))
13 | {
14 | return true;
15 | }
16 |
17 | return false;
18 | }
19 |
20 |
21 | public static bool IsValueBetween(double val, double min, double max, double tolerance)
22 | {
23 | if (min > max)
24 | {
25 | double tmp = min;
26 | min = max;
27 | max = tmp;
28 | }
29 | if ((val + tolerance) >= min && (val - tolerance) <= max)
30 | {
31 | return true;
32 | }
33 |
34 | return false;
35 | }
36 |
37 |
38 | public static double RoundWithPrecision(double f, double precision)
39 | {
40 | if (precision < 0.0)
41 | {
42 | return f;
43 | }
44 |
45 | double mul = Math.Pow(10.0, precision);
46 | double fTemp = Math.Floor(f * mul) / mul;
47 |
48 | return fTemp;
49 | }
50 |
51 |
52 | public static double Clamp(double a, double low, double high)
53 | {
54 | return Math.Max(low, Math.Min(a, high));
55 | }
56 |
57 |
58 | public static void Swap(ref T a, ref T b)
59 | {
60 | T tmp = a;
61 | a = b;
62 | b = tmp;
63 | }
64 |
65 |
66 | public static uint Jenkins32Hash(IEnumerable data, uint nInitialValue)
67 | {
68 | foreach (byte b in data)
69 | {
70 | nInitialValue += b;
71 | nInitialValue += (nInitialValue << 10);
72 | nInitialValue += (nInitialValue >> 6);
73 | }
74 |
75 | nInitialValue += (nInitialValue << 3);
76 | nInitialValue ^= (nInitialValue >> 11);
77 | nInitialValue += (nInitialValue << 15);
78 |
79 | return nInitialValue;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/Poly2Tri/Utility/Point2D.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System;
33 |
34 | namespace Poly2Tri.Utility
35 | {
36 | public class Point2D : IComparable
37 | {
38 | private double _x;
39 | public virtual double X { get { return _x; } set { _x = value; } }
40 | private double _y;
41 | public virtual double Y { get { return _y; } set { _y = value; } }
42 |
43 | public float Xf { get { return (float)X; } }
44 | public float Yf { get { return (float)Y; } }
45 |
46 |
47 | public Point2D()
48 | {
49 | _x = 0.0;
50 | _y = 0.0;
51 | }
52 |
53 |
54 | public Point2D(double x, double y)
55 | {
56 | _x = x;
57 | _y = y;
58 | }
59 |
60 | public override string ToString()
61 | {
62 | return string.Format("[{0},{1}]", X, Y);
63 | }
64 |
65 |
66 | public override int GetHashCode()
67 | {
68 | unchecked
69 | {
70 | return 378163771 * _x.GetHashCode()
71 | + 113137337 * _y.GetHashCode();
72 | }
73 | }
74 |
75 |
76 | public override bool Equals(Object obj)
77 | {
78 | Point2D p = obj as Point2D;
79 | if (p != null)
80 | return Equals(p);
81 |
82 | return false;
83 | }
84 |
85 | public bool Equals(Point2D p, double epsilon = 0.0)
86 | {
87 | if (p == null || !MathUtil.AreValuesEqual(X, p.X, epsilon) || !MathUtil.AreValuesEqual(Y, p.Y, epsilon))
88 | return false;
89 |
90 | return true;
91 | }
92 |
93 |
94 | public int CompareTo(Point2D other)
95 | {
96 | if (Y < other.Y)
97 | {
98 | return -1;
99 | }
100 | else if (Y > other.Y)
101 | {
102 | return 1;
103 | }
104 | else
105 | {
106 | if (X < other.X)
107 | {
108 | return -1;
109 | }
110 | else if (X > other.X)
111 | {
112 | return 1;
113 | }
114 | }
115 |
116 | return 0;
117 | }
118 |
119 |
120 | public virtual void Set(double x, double y) { X = x; Y = y; }
121 |
122 | public void Subtract(Point2D p) { X -= p.X; Y -= p.Y; }
123 | private void Multiply(double scalar) { X *= scalar; Y *= scalar; }
124 | public double Magnitude() { return Math.Sqrt(MagnitudeSquared()); }
125 | public double MagnitudeSquared() { return (X * X) + (Y * Y); }
126 | private double MagnitudeReciprocal() { return 1.0 / Magnitude(); }
127 | public void Normalize() { Multiply(MagnitudeReciprocal()); }
128 | public double Dot(Point2D p) { return (X * p.X) + (Y * p.Y); }
129 | public double Cross(Point2D p) { return (X * p.Y) - (Y * p.X); }
130 |
131 | public static double Dot(Point2D lhs, Point2D rhs) { return (lhs.X * rhs.X) + (lhs.Y * rhs.Y); }
132 | public static double Cross(Point2D lhs, Point2D rhs) { return (lhs.X * rhs.Y) - (lhs.Y * rhs.X); }
133 |
134 | // returns a scaled perpendicular vector. Which direction it goes depends on the order in which the arguments are passed
135 | public static Point2D Perpendicular(Point2D lhs, double scalar) { Point2D p = new Point2D(lhs.Y * scalar, lhs.X * -scalar); return p; }
136 | public static Point2D Perpendicular(double scalar, Point2D rhs) { Point2D p = new Point2D(-scalar * rhs.Y, scalar * rhs.X); return p; }
137 |
138 |
139 | //
140 | // operator overloading
141 | //
142 |
143 | // Binary Operators
144 | // Note that in C#, when a binary operator is overloaded, its corresponding compound assignment operator is also automatically
145 | // overloaded. So, for example, overloading operator + implicitly overloads += as well
146 | public static Point2D operator +(Point2D lhs, Point2D rhs) { return new Point2D(lhs.X + rhs.X, lhs.Y + rhs.Y); }
147 | public static Point2D operator +(Point2D lhs, double scalar) { return new Point2D(lhs.X + scalar, lhs.Y + scalar); }
148 | public static Point2D operator -(Point2D lhs, Point2D rhs) { return new Point2D(lhs.X - rhs.X, lhs.Y - rhs.Y); }
149 | public static Point2D operator -(Point2D lhs, double scalar) { return new Point2D(lhs.X - scalar, lhs.Y - scalar); }
150 | public static Point2D operator *(Point2D lhs, Point2D rhs) { return new Point2D(lhs.X * rhs.X, lhs.Y * rhs.Y); }
151 | public static Point2D operator *(Point2D lhs, double scalar) { return new Point2D(lhs.X * scalar, lhs.Y * scalar); }
152 | public static Point2D operator *(double scalar, Point2D rhs) { return rhs * scalar; }
153 | public static Point2D operator /(Point2D lhs, Point2D rhs) { return new Point2D(lhs.X / rhs.X, lhs.Y / rhs.Y); }
154 | public static Point2D operator /(Point2D lhs, double scalar) { return new Point2D(lhs.X / scalar, lhs.Y / scalar); }
155 |
156 | // Unary Operators
157 | public static Point2D operator -(Point2D p) { return new Point2D(-p.X, -p.Y); }
158 |
159 | // Relational Operators
160 | //public static bool operator ==(Point2D lhs, Point2D rhs) { if ((object)lhs != null) { return lhs.Equals(rhs, 0.0); } if ((object)rhs == null) { return true; } else { return false; } }
161 | //public static bool operator !=(Point2D lhs, Point2D rhs) { if ((object)lhs != null) { return !lhs.Equals(rhs, 0.0); } if ((object)rhs == null) { return false; } else { return true; } }
162 | public static bool operator <(Point2D lhs, Point2D rhs) { return (lhs.CompareTo(rhs) == -1); }
163 | public static bool operator >(Point2D lhs, Point2D rhs) { return (lhs.CompareTo(rhs) == 1); }
164 | public static bool operator <=(Point2D lhs, Point2D rhs) { return (lhs.CompareTo(rhs) <= 0); }
165 | public static bool operator >=(Point2D lhs, Point2D rhs) { return (lhs.CompareTo(rhs) >= 0); }
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/Poly2Tri/Utility/Rect2D.cs:
--------------------------------------------------------------------------------
1 | /* Poly2Tri
2 | * Copyright (c) 2009-2010, Poly2Tri Contributors
3 | * http://code.google.com/p/poly2tri/
4 | *
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without modification,
8 | * are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice,
11 | * this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above copyright notice,
13 | * this list of conditions and the following disclaimer in the documentation
14 | * and/or other materials provided with the distribution.
15 | * * Neither the name of Poly2Tri nor the names of its contributors may be
16 | * used to endorse or promote products derived from this software without specific
17 | * prior written permission.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | using System;
33 |
34 | namespace Poly2Tri.Utility
35 | {
36 | public struct Rect2D
37 | {
38 | private readonly double _minX;
39 | private readonly double _maxX;
40 | private readonly double _minY;
41 | private readonly double _maxY;
42 |
43 | public double MinX { get { return _minX; } }
44 | public double MaxX { get { return _maxX; } }
45 | public double MinY { get { return _minY; } }
46 | public double MaxY { get { return _maxY; } }
47 | public double Left { get { return _minX; } }
48 | public double Right { get { return _maxX; } }
49 | public double Top { get { return _maxY; } }
50 | public double Bottom { get { return _minY; } }
51 |
52 | public double Width { get { return (Right - Left); } }
53 | public double Height { get { return (Top - Bottom); } }
54 |
55 | public bool IsEmpty
56 | {
57 | get
58 | {
59 | return Math.Abs(Width) < float.Epsilon || Math.Abs(Height) < float.Epsilon;
60 | }
61 | }
62 |
63 | private Rect2D(double minX, double maxX, double minY, double maxY)
64 | {
65 | _minX = minX;
66 | _maxX = maxX;
67 | _minY = minY;
68 | _maxY = maxY;
69 | }
70 |
71 | public override int GetHashCode()
72 | {
73 | unchecked
74 | {
75 | // ReSharper disable ImpureMethodCallOnReadonlyValueField
76 | return 54734431 * _minX.GetHashCode()
77 | + 1122547711 * _minY.GetHashCode()
78 | + 1097393683 * _maxX.GetHashCode()
79 | + 1198754321 * _maxY.GetHashCode();
80 | // ReSharper restore ImpureMethodCallOnReadonlyValueField
81 | }
82 |
83 | }
84 |
85 | public override bool Equals(Object obj)
86 | {
87 | return obj is Rect2D && Equals((Rect2D)obj);
88 | }
89 |
90 | private bool Equals(Rect2D r, double epsilon = MathUtil.EPSILON)
91 | {
92 | return MathUtil.AreValuesEqual(MinX, r.MinX, epsilon)
93 | && MathUtil.AreValuesEqual(MaxX, r.MaxX, epsilon)
94 | && MathUtil.AreValuesEqual(MinY, r.MinY, epsilon)
95 | && MathUtil.AreValuesEqual(MaxY, r.MaxY, epsilon);
96 | }
97 |
98 | public bool Intersects(Rect2D r)
99 | {
100 | return (Right > r.Left) &&
101 | (Left < r.Right) &&
102 | (Bottom < r.Top) &&
103 | (Top > r.Bottom);
104 | }
105 |
106 | public Rect2D AddPoint(Point2D p)
107 | {
108 | return new Rect2D(
109 | Math.Min(MinX, p.X),
110 | Math.Max(MaxX, p.X),
111 | Math.Min(MinY, p.Y),
112 | Math.Max(MaxY, p.Y)
113 | );
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/push-all.ps1:
--------------------------------------------------------------------------------
1 | function Push-Nuget($path, $csproj) {
2 | $fullPathToCsprog = Join-Path -Path $path -ChildPath $csproj -resolve;
3 |
4 | nuget pack $fullPathToCsprog -Prop Configuration=Release -IncludeReferencedProjects -Symbols
5 |
6 | get-childitem -Filter *.nupkg -name | foreach ($_) {
7 | Write-Host "Pushing " $_ -backgroundcolor darkgreen -foregroundcolor white;
8 |
9 | nuget push $_
10 | Remove-Item $_
11 |
12 | Write-Host "Done " $_ -backgroundcolor darkgreen -foregroundcolor white;
13 | }
14 | }
15 |
16 | Push-Nuget "Poly2Tri" "Poly2Tri.csproj"
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | This is a fork of the C# version of [poly2tri](https://code.google.com/p/poly2tri/). Changes to the code are just to bring things in line with C# style.
2 |
3 | This is the code behind the poly2tri [nuget package](https://www.nuget.org/packages/Poly2Tri/).
--------------------------------------------------------------------------------