feat: Initial commit

This commit is contained in:
2025-02-14 16:06:00 +08:00
commit da75a84e02
1056 changed files with 163517 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
Primary Contributors:
Mason Green <mason.green@gmail.com> (C++, Python)
Thomas <20>hl<68>n <thahlen@gmail.com> (Java)
Other Contributors:
Michael Rickert (C#)
Lee Wilson <devnull@devnullsoftware.com> (C#)

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f8915cc67e651c44da46d4406ac14831
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,123 @@
Poly2Tri Copyright (c) 2009-2011, Poly2Tri Contributors
http://code.google.com/p/poly2tri/
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Poly2Tri nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
The Following notice applies to the Methods SplitComplexPolygon and the
class SplitComplexPolygonNode in Triangulation/Polygon/PolygonUtil.cs.
Both are altered only enough to convert to C#
and take advantage of some of C#'s language features. Any errors
are thus mine from the conversion and not Eric's.
Copyright (c) 2007 Eric Jordan
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
------------------------------------------------------------------------------
Portions of the this code (notably: the methods PolygonUnion,
PolygonSubtract, PolygonIntersect, PolygonOperationContext.Init,
PolygonOperationContext.VerticesIntersect,
PolygonOperationContext.PointInPolygonAngle, and
PolygonOperationContext.VectorAngle in the file
Triangulation/Polygon/PolygonUtil.cs are from the Farseer Physics Engine 3.0
and are covered under the Microsoft Permissive License V1.1
(http://farseerphysics.codeplex.com/license)
Microsoft Permissive License (Ms-PL)
This license governs use of the accompanying software. If you use the
software, you accept this license. If you do not accept the license, do not
use the software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and
"distribution" have the same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to
the software.
A "contributor" is any person that distributes its contribution under this
license.
"Licensed patents" are a contributor's patent claims that read directly on
its contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the
license conditions and limitations in section 3, each contributor grants
you a non-exclusive, worldwide, royalty-free copyright license to reproduce
its contribution, prepare derivative works of its contribution, and
distribute its contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the
license conditions and limitations in section 3, each contributor grants
you a non-exclusive, worldwide, royalty-free license under its licensed
patents to make, have made, use, sell, offer for sale, import, and/or
otherwise dispose of its contribution in the software or derivative works
of the contribution in the software.
3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use
any contributors' name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that
you claim are infringed by the software, your patent license from such
contributor to the software ends automatically.
(C) If you distribute any portion of the software, you must retain all
copyright, patent, trademark, and attribution notices that are present
in the software.
(D) If you distribute any portion of the software in source code form, you
may do so only under this license by including a complete copy of this
license with your distribution. If you distribute any portion of the
software in compiled or object code form, you may only do so under a
license that complies with this license.
(E) The software is licensed "as-is." You bear the risk of using it. The
contributors give no express warranties, guarantees or conditions. You may
have additional consumer rights under your local laws which this license
cannot change. To the extent permitted under your local laws, the
contributors exclude the implied warranties of merchantability, fitness for
a particular purpose and non-infringement.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ad85343b1a5acaa4d99ef62487bde508
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
{
"name": "Poly2Tri",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": true
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e5b7e7f40a80a814ba706299d68f9213
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a1df0a761a6faee41910a01a2901e475
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 24f46f7445d706343b6a44b48a6504cf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,447 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/// Changes from the Java version
/// attributification
/// Future possibilities
/// Flattening out the number of indirections
/// Replacing arrays of 3 with fixed-length arrays?
/// Replacing bool[3] with a bit array of some sort?
/// Bundling everything into an AoS mess?
/// Hardcode them all as ABC ?
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace Poly2Tri
{
public class DelaunayTriangle
{
public FixedArray3<TriangulationPoint> Points;
public FixedArray3<DelaunayTriangle> Neighbors;
private FixedBitArray3 mEdgeIsConstrained;
public FixedBitArray3 EdgeIsConstrained { get { return mEdgeIsConstrained; } }
public FixedBitArray3 EdgeIsDelaunay;
public bool IsInterior { get; set; }
public DelaunayTriangle(TriangulationPoint p1, TriangulationPoint p2, TriangulationPoint p3)
{
Points[0] = p1;
Points[1] = p2;
Points[2] = p3;
}
public int IndexOf(TriangulationPoint p)
{
int i = Points.IndexOf(p);
if (i == -1)
{
throw new Exception("Calling index with a point that doesn't exist in triangle");
}
return i;
}
public int IndexCWFrom(TriangulationPoint p)
{
return (IndexOf(p) + 2) % 3;
}
public int IndexCCWFrom(TriangulationPoint p)
{
return (IndexOf(p) + 1) % 3;
}
public bool Contains(TriangulationPoint p)
{
return Points.Contains(p);
}
/// <summary>
/// Update neighbor pointers
/// </summary>
/// <param name="p1">Point 1 of the shared edge</param>
/// <param name="p2">Point 2 of the shared edge</param>
/// <param name="t">This triangle's new neighbor</param>
private void MarkNeighbor(TriangulationPoint p1, TriangulationPoint p2, DelaunayTriangle t)
{
int i = EdgeIndex(p1, p2);
if (i == -1)
{
throw new Exception("Error marking neighbors -- t doesn't contain edge p1-p2!");
}
Neighbors[i] = t;
}
/// <summary>
/// Exhaustive search to update neighbor pointers
/// </summary>
public void MarkNeighbor(DelaunayTriangle t)
{
// Points of this triangle also belonging to t
bool a = t.Contains(Points[0]);
bool b = t.Contains(Points[1]);
bool c = t.Contains(Points[2]);
if (b && c)
{
Neighbors[0] = t;
t.MarkNeighbor(Points[1], Points[2], this);
}
else if (a && c)
{
Neighbors[1] = t;
t.MarkNeighbor(Points[0], Points[2], this);
}
else if (a && b)
{
Neighbors[2] = t;
t.MarkNeighbor(Points[0], Points[1], this);
}
else
{
throw new Exception("Failed to mark neighbor, doesn't share an edge!");
}
}
public void ClearNeighbors()
{
Neighbors[0] = Neighbors[1] = Neighbors[2] = null;
}
public void ClearNeighbor(DelaunayTriangle triangle)
{
if (Neighbors[0] == triangle)
{
Neighbors[0] = null;
}
else if (Neighbors[1] == triangle)
{
Neighbors[1] = null;
}
else if( Neighbors[2] == triangle)
{
Neighbors[2] = null;
}
}
/// <summary>
/// Clears all references to all other triangles and points
/// </summary>
public void Clear()
{
DelaunayTriangle t;
for (int i = 0; i < 3; i++)
{
t = Neighbors[i];
if (t != null)
{
t.ClearNeighbor(this);
}
}
ClearNeighbors();
Points[0] = Points[1] = Points[2] = null;
}
/// <param name="t">Opposite triangle</param>
/// <param name="p">The point in t that isn't shared between the triangles</param>
public TriangulationPoint OppositePoint(DelaunayTriangle t, TriangulationPoint p)
{
Debug.Assert(t != this, "self-pointer error");
return PointCWFrom(t.PointCWFrom(p));
}
public DelaunayTriangle NeighborCWFrom(TriangulationPoint point)
{
return Neighbors[(Points.IndexOf(point) + 1) % 3];
}
public DelaunayTriangle NeighborCCWFrom(TriangulationPoint point)
{
return Neighbors[(Points.IndexOf(point) + 2) % 3];
}
public DelaunayTriangle NeighborAcrossFrom(TriangulationPoint point)
{
return Neighbors[Points.IndexOf(point)];
}
public TriangulationPoint PointCCWFrom(TriangulationPoint point)
{
return Points[(IndexOf(point) + 1) % 3];
}
public TriangulationPoint PointCWFrom(TriangulationPoint point)
{
return Points[(IndexOf(point) + 2) % 3];
}
private void RotateCW()
{
var t = Points[2];
Points[2] = Points[1];
Points[1] = Points[0];
Points[0] = t;
}
/// <summary>
/// Legalize triangle by rotating clockwise around oPoint
/// </summary>
/// <param name="oPoint">The origin point to rotate around</param>
/// <param name="nPoint">???</param>
public void Legalize(TriangulationPoint oPoint, TriangulationPoint nPoint)
{
RotateCW();
Points[IndexCCWFrom(oPoint)] = nPoint;
}
public override string ToString()
{
return Points[0] + "," + Points[1] + "," + Points[2];
}
/// <summary>
/// Finalize edge marking
/// </summary>
public void MarkNeighborEdges()
{
for (int i = 0; i < 3; i++)
{
if (EdgeIsConstrained[i] && Neighbors[i] != null)
{
Neighbors[i].MarkConstrainedEdge(Points[(i + 1) % 3], Points[(i + 2) % 3]);
}
}
}
public void MarkEdge(DelaunayTriangle triangle)
{
for (int i = 0; i < 3; i++) if (EdgeIsConstrained[i])
{
triangle.MarkConstrainedEdge(Points[(i + 1) % 3], Points[(i + 2) % 3]);
}
}
public void MarkEdge(List<DelaunayTriangle> tList)
{
foreach (DelaunayTriangle t in tList)
{
for (int i = 0; i < 3; i++)
{
if (t.EdgeIsConstrained[i])
{
MarkConstrainedEdge(t.Points[(i + 1) % 3], t.Points[(i + 2) % 3]);
}
}
}
}
public void MarkConstrainedEdge(int index)
{
mEdgeIsConstrained[index] = true;
}
public void MarkConstrainedEdge(DTSweepConstraint edge)
{
MarkConstrainedEdge(edge.P, edge.Q);
}
/// <summary>
/// Mark edge as constrained
/// </summary>
public void MarkConstrainedEdge(TriangulationPoint p, TriangulationPoint q)
{
int i = EdgeIndex(p, q);
if (i != -1)
{
mEdgeIsConstrained[i] = true;
}
}
public double Area()
{
double b = Points[0].X - Points[1].X;
double h = Points[2].Y - Points[1].Y;
return Math.Abs((b * h * 0.5f));
}
public TriangulationPoint Centroid()
{
double cx = (Points[0].X + Points[1].X + Points[2].X) / 3f;
double cy = (Points[0].Y + Points[1].Y + Points[2].Y) / 3f;
return new TriangulationPoint(cx, cy);
}
/// <summary>
/// Get the index of the neighbor that shares this edge (or -1 if it isn't shared)
/// </summary>
/// <returns>index of the shared edge or -1 if edge isn't shared</returns>
public int EdgeIndex(TriangulationPoint p1, TriangulationPoint p2)
{
int i1 = Points.IndexOf(p1);
int i2 = Points.IndexOf(p2);
// Points of this triangle in the edge p1-p2
bool a = (i1 == 0 || i2 == 0);
bool b = (i1 == 1 || i2 == 1);
bool c = (i1 == 2 || i2 == 2);
if (b && c)
{
return 0;
}
if (a && c)
{
return 1;
}
if (a && b)
{
return 2;
}
return -1;
}
public bool GetConstrainedEdgeCCW(TriangulationPoint p) { return EdgeIsConstrained[(IndexOf(p) + 2) % 3]; }
public bool GetConstrainedEdgeCW(TriangulationPoint p) { return EdgeIsConstrained[(IndexOf(p) + 1) % 3]; }
public bool GetConstrainedEdgeAcross(TriangulationPoint p) { return EdgeIsConstrained[IndexOf(p)]; }
protected void SetConstrainedEdge(int idx, bool ce)
{
//if (ce == false && EdgeIsConstrained[idx])
//{
// DTSweepConstraint edge = null;
// if (GetEdge(idx, out edge))
// {
// Console.WriteLine("Removing pre-defined constraint from edge " + edge.ToString());
// }
//}
mEdgeIsConstrained[idx] = ce;
}
public void SetConstrainedEdgeCCW(TriangulationPoint p, bool ce)
{
int idx = (IndexOf(p) + 2) % 3;
SetConstrainedEdge(idx, ce);
}
public void SetConstrainedEdgeCW(TriangulationPoint p, bool ce)
{
int idx = (IndexOf(p) + 1) % 3;
SetConstrainedEdge(idx, ce);
}
public void SetConstrainedEdgeAcross(TriangulationPoint p, bool ce)
{
int idx = IndexOf(p);
SetConstrainedEdge(idx, ce);
}
public bool GetDelaunayEdgeCCW(TriangulationPoint p) { return EdgeIsDelaunay[(IndexOf(p) + 2) % 3]; }
public bool GetDelaunayEdgeCW(TriangulationPoint p) { return EdgeIsDelaunay[(IndexOf(p) + 1) % 3]; }
public bool GetDelaunayEdgeAcross(TriangulationPoint p) { return EdgeIsDelaunay[IndexOf(p)]; }
public void SetDelaunayEdgeCCW(TriangulationPoint p, bool ce) { EdgeIsDelaunay[(IndexOf(p) + 2) % 3] = ce; }
public void SetDelaunayEdgeCW(TriangulationPoint p, bool ce) { EdgeIsDelaunay[(IndexOf(p) + 1) % 3] = ce; }
public void SetDelaunayEdgeAcross(TriangulationPoint p, bool ce) { EdgeIsDelaunay[IndexOf(p)] = ce; }
public bool GetEdge(int idx, out DTSweepConstraint edge)
{
edge = null;
if (idx < 0 || idx > 2)
{
return false;
}
TriangulationPoint p1 = Points[(idx + 1) % 3];
TriangulationPoint p2 = Points[(idx + 2) % 3];
if (p1.GetEdge(p2, out edge))
{
return true;
}
else if (p2.GetEdge(p1, out edge))
{
return true;
}
return false;
}
public bool GetEdgeCCW(TriangulationPoint p, out DTSweepConstraint edge)
{
int pointIndex = IndexOf(p);
int edgeIdx = (pointIndex + 2)%3;
return GetEdge(edgeIdx, out edge);
}
public bool GetEdgeCW(TriangulationPoint p, out DTSweepConstraint edge)
{
int pointIndex = IndexOf(p);
int edgeIdx = (pointIndex + 1) % 3;
return GetEdge(edgeIdx, out edge);
}
public bool GetEdgeAcross(TriangulationPoint p, out DTSweepConstraint edge)
{
int pointIndex = IndexOf(p);
int edgeIdx = pointIndex;
return GetEdge(edgeIdx, out edge);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b61ca8480a824b4eab0f5a7c6587932
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ca0c831d398dcf043875b7e514c4f9ee
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,177 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/// Changes from the Java version
/// Removed BST code, but not all artifacts of it
/// Future possibilities
/// Eliminate Add/RemoveNode ?
/// Comments comments and more comments!
using System.Text;
using System;
namespace Poly2Tri
{
/**
* @author Thomas Åhlen (thahlen@gmail.com)
*/
public class AdvancingFront
{
public AdvancingFrontNode Head;
public AdvancingFrontNode Tail;
protected AdvancingFrontNode Search;
public AdvancingFront(AdvancingFrontNode head, AdvancingFrontNode tail)
{
this.Head = head;
this.Tail = tail;
this.Search = head;
AddNode(head);
AddNode(tail);
}
public void AddNode(AdvancingFrontNode node) { }
public void RemoveNode(AdvancingFrontNode node) { }
public override string ToString()
{
StringBuilder sb = new StringBuilder();
AdvancingFrontNode node = Head;
while (node != Tail)
{
sb.Append(node.Point.X).Append("->");
node = node.Next;
}
sb.Append(Tail.Point.X);
return sb.ToString();
}
/// <summary>
/// MM: This seems to be used by LocateNode to guess a position in the implicit linked list of AdvancingFrontNodes near x
/// Removed an overload that depended on this being exact
/// </summary>
private AdvancingFrontNode FindSearchNode(double x)
{
return Search;
}
/// <summary>
/// We use a balancing tree to locate a node smaller or equal to given key value (in theory)
/// </summary>
public AdvancingFrontNode LocateNode(TriangulationPoint point)
{
return LocateNode(point.X);
}
private AdvancingFrontNode LocateNode(double x)
{
AdvancingFrontNode node = FindSearchNode(x);
if (x < node.Value)
{
while ((node = node.Prev) != null)
{
if (x >= node.Value)
{
Search = node;
return node;
}
}
}
else
{
while ((node = node.Next) != null)
{
if (x < node.Value)
{
Search = node.Prev;
return node.Prev;
}
}
}
return null;
}
/// <summary>
/// This implementation will use simple node traversal algorithm to find a point on the front
/// </summary>
public AdvancingFrontNode LocatePoint(TriangulationPoint point)
{
double px = point.X;
AdvancingFrontNode node = FindSearchNode(px);
double nx = node.Point.X;
if (px == nx)
{
if (point != node.Point)
{
// We might have two nodes with same x value for a short time
if (point == node.Prev.Point)
{
node = node.Prev;
}
else if (point == node.Next.Point)
{
node = node.Next;
}
else
{
throw new Exception("Failed to find Node for given afront point");
}
}
}
else if (px < nx)
{
while ((node = node.Prev) != null)
{
if (point == node.Point)
{
break;
}
}
}
else
{
while ((node = node.Next) != null)
{
if (point == node.Point)
{
break;
}
}
}
Search = node;
return node;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bba5ad2e582edd14a9b9f4c2269e83e2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/// Changes from the Java version
/// Removed getters
/// Has* turned into attributes
/// Future possibilities
/// Comments!
namespace Poly2Tri
{
public class AdvancingFrontNode
{
public AdvancingFrontNode Next;
public AdvancingFrontNode Prev;
public double Value;
public TriangulationPoint Point;
public DelaunayTriangle Triangle;
public AdvancingFrontNode(TriangulationPoint point)
{
this.Point = point;
Value = point.X;
}
public bool HasNext { get { return Next != null; } }
public bool HasPrev { get { return Prev != null; } }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f50404d2892ffc42b70043a773f577f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 18835840dca416041bff74eaaf5dcc47
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Poly2Tri
{
public class DTSweepBasin
{
public AdvancingFrontNode leftNode;
public AdvancingFrontNode bottomNode;
public AdvancingFrontNode rightNode;
public double width;
public bool leftHighest;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 295b5899a6bed9d4187f6a49c293fc2f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,52 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
//using System.Collections.Generic;
using System.Diagnostics;
//using System.Linq;
namespace Poly2Tri
{
public class DTSweepConstraint : TriangulationConstraint
{
/// <summary>
/// Give two points in any order. Will always be ordered so
/// that q.y > p.y and q.x > p.x if same y value
/// </summary>
public DTSweepConstraint(TriangulationPoint p1, TriangulationPoint p2)
: base(p1, p2)
{
Q.AddEdge(this);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 24c139533abc53242a5fda851aed1f90
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,252 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Poly2Tri
{
/**
*
* @author Thomas Åhlén, thahlen@gmail.com
*
*/
public class DTSweepContext : TriangulationContext
{
// Inital triangle factor, seed triangle will extend 30% of
// PointSet width to both left and right.
private readonly float ALPHA = 0.3f;
public AdvancingFront Front;
public TriangulationPoint Head { get; set; }
public TriangulationPoint Tail { get; set; }
public DTSweepBasin Basin = new DTSweepBasin();
public DTSweepEdgeEvent EdgeEvent = new DTSweepEdgeEvent();
private DTSweepPointComparator _comparator = new DTSweepPointComparator();
public override TriangulationAlgorithm Algorithm { get { return TriangulationAlgorithm.DTSweep; } }
public DTSweepContext()
{
Clear();
}
public override bool IsDebugEnabled
{
get
{
return base.IsDebugEnabled;
}
protected set
{
if (value && DebugContext == null)
{
DebugContext = new DTSweepDebugContext(this);
}
base.IsDebugEnabled = value;
}
}
public void RemoveFromList(DelaunayTriangle triangle)
{
Triangles.Remove(triangle);
// TODO: remove all neighbor pointers to this triangle
// for( int i=0; i<3; i++ )
// {
// if( triangle.neighbors[i] != null )
// {
// triangle.neighbors[i].clearNeighbor( triangle );
// }
// }
// triangle.clearNeighbors();
}
public void MeshClean(DelaunayTriangle triangle)
{
MeshCleanReq(triangle);
}
private void MeshCleanReq(DelaunayTriangle triangle)
{
if (triangle != null && !triangle.IsInterior)
{
triangle.IsInterior = true;
Triangulatable.AddTriangle(triangle);
for (int i = 0; i < 3; i++)
{
if (!triangle.EdgeIsConstrained[i])
{
MeshCleanReq(triangle.Neighbors[i]);
}
}
}
}
public override void Clear()
{
base.Clear();
Triangles.Clear();
}
public void AddNode(AdvancingFrontNode node)
{
// Console.WriteLine( "add:" + node.key + ":" + System.identityHashCode(node.key));
// m_nodeTree.put( node.getKey(), node );
Front.AddNode(node);
}
public void RemoveNode(AdvancingFrontNode node)
{
// Console.WriteLine( "remove:" + node.key + ":" + System.identityHashCode(node.key));
// m_nodeTree.delete( node.getKey() );
Front.RemoveNode(node);
}
public AdvancingFrontNode LocateNode(TriangulationPoint point)
{
return Front.LocateNode(point);
}
public void CreateAdvancingFront()
{
AdvancingFrontNode head, tail, middle;
// Initial triangle
DelaunayTriangle iTriangle = new DelaunayTriangle(Points[0], Tail, Head);
Triangles.Add(iTriangle);
head = new AdvancingFrontNode(iTriangle.Points[1]);
head.Triangle = iTriangle;
middle = new AdvancingFrontNode(iTriangle.Points[0]);
middle.Triangle = iTriangle;
tail = new AdvancingFrontNode(iTriangle.Points[2]);
Front = new AdvancingFront(head, tail);
Front.AddNode(middle);
// TODO: I think it would be more intuitive if head is middles next and not previous
// so swap head and tail
Front.Head.Next = middle;
middle.Next = Front.Tail;
middle.Prev = Front.Head;
Front.Tail.Prev = middle;
}
/// <summary>
/// Try to map a node to all sides of this triangle that don't have
/// a neighbor.
/// </summary>
public void MapTriangleToNodes(DelaunayTriangle t)
{
for (int i = 0; i < 3; i++)
{
if (t.Neighbors[i] == null)
{
AdvancingFrontNode n = Front.LocatePoint(t.PointCWFrom(t.Points[i]));
if (n != null)
{
n.Triangle = t;
}
}
}
}
public override void PrepareTriangulation(ITriangulatable t)
{
base.PrepareTriangulation(t);
double xmax, xmin;
double ymax, ymin;
xmax = xmin = Points[0].X;
ymax = ymin = Points[0].Y;
// Calculate bounds. Should be combined with the sorting
foreach (TriangulationPoint p in Points)
{
if (p.X > xmax)
{
xmax = p.X;
}
if (p.X < xmin)
{
xmin = p.X;
}
if (p.Y > ymax)
{
ymax = p.Y;
}
if (p.Y < ymin)
{
ymin = p.Y;
}
}
double deltaX = ALPHA * (xmax - xmin);
double deltaY = ALPHA * (ymax - ymin);
TriangulationPoint p1 = new TriangulationPoint(xmax + deltaX, ymin - deltaY);
TriangulationPoint p2 = new TriangulationPoint(xmin - deltaX, ymin - deltaY);
Head = p1;
Tail = p2;
// long time = System.nanoTime();
// Sort the points along y-axis
Points.Sort(_comparator);
// logger.info( "Triangulation setup [{}ms]", ( System.nanoTime() - time ) / 1e6 );
}
public void FinalizeTriangulation()
{
Triangulatable.AddTriangles(Triangles);
Triangles.Clear();
}
public override TriangulationConstraint NewConstraint(TriangulationPoint a, TriangulationPoint b)
{
return new DTSweepConstraint(a, b);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5ee2e0932fff59f429c452bba590cf83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Poly2Tri
{
public class DTSweepDebugContext : TriangulationDebugContext
{
/*
* Fields used for visual representation of current triangulation
*/
public DelaunayTriangle PrimaryTriangle { get { return _primaryTriangle; } set { _primaryTriangle = value; _tcx.Update("set PrimaryTriangle"); } }
public DelaunayTriangle SecondaryTriangle { get { return _secondaryTriangle; } set { _secondaryTriangle = value; _tcx.Update("set SecondaryTriangle"); } }
public TriangulationPoint ActivePoint { get { return _activePoint; } set { _activePoint = value; _tcx.Update("set ActivePoint"); } }
public AdvancingFrontNode ActiveNode { get { return _activeNode; } set { _activeNode = value; _tcx.Update("set ActiveNode"); } }
public DTSweepConstraint ActiveConstraint { get { return _activeConstraint; } set { _activeConstraint = value; _tcx.Update("set ActiveConstraint"); } }
public DTSweepDebugContext(DTSweepContext tcx) : base(tcx) { }
public bool IsDebugContext { get { return true; } }
public override void Clear()
{
PrimaryTriangle = null;
SecondaryTriangle = null;
ActivePoint = null;
ActiveNode = null;
ActiveConstraint = null;
}
private DelaunayTriangle _primaryTriangle;
private DelaunayTriangle _secondaryTriangle;
private TriangulationPoint _activePoint;
private AdvancingFrontNode _activeNode;
private DTSweepConstraint _activeConstraint;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c80776e6f580608498870e9ba0c7fdca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/// Changes from the Java version
/// Turned DTSweepEdgeEvent into a value type
namespace Poly2Tri
{
public class DTSweepEdgeEvent
{
public DTSweepConstraint ConstrainedEdge;
public bool Right;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3c7810b370713bb4985dfa014259efbc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System.Collections.Generic;
namespace Poly2Tri
{
public class DTSweepPointComparator : IComparer<TriangulationPoint>
{
public int Compare(TriangulationPoint p1, TriangulationPoint p2)
{
if (p1.Y < p2.Y)
{
return -1;
}
else if (p1.Y > p2.Y)
{
return 1;
}
else
{
if (p1.X < p2.X)
{
return -1;
}
else if (p1.X > p2.X)
{
return 1;
}
else
{
return 0;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dfb17679c246e5f4fa5a535f717d47d5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
namespace Poly2Tri
{
public class PointOnEdgeException : NotImplementedException
{
public readonly TriangulationPoint A, B, C;
public PointOnEdgeException(string message, TriangulationPoint a, TriangulationPoint b, TriangulationPoint c)
: base(message)
{
A = a;
B = b;
C = c;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a6f5e106faca1c442a1def9a56695eac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System.Collections.Generic;
namespace Poly2Tri
{
public interface ITriangulatable
{
//IList<TriangulationPoint> Points { get; } // MM: Neither of these are used via interface (yet?)
IList<DelaunayTriangle> Triangles { get; }
TriangulationMode TriangulationMode { get; }
string FileName { get; set; }
bool DisplayFlipX { get; set; }
bool DisplayFlipY { get; set; }
float DisplayRotate { get; set; }
double Precision { get; set; }
double MinX { get; }
double MaxX { get; }
double MinY { get; }
double MaxY { get; }
Rect2D Bounds { get; }
void Prepare(TriangulationContext tcx);
void AddTriangle(DelaunayTriangle t);
void AddTriangles(IEnumerable<DelaunayTriangle> list);
void ClearTriangles();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 75ea7f139cb97ce4c8150e06934491d7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Poly2Tri
{
public enum Orientation
{
CW,
CCW,
Collinear
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f53cc2457ddb3dd4c82e5b3eb98327c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 30e3877e8ca306440ac44dfc20462e1d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,577 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Poly2Tri
{
/// <summary>
/// This is basically a light-weight version of the Polygon class, but with limited functionality and
/// used for different purposes. Nonetheless, for all intents and purposes, this should actually be
/// a polygon (though not a Polygon..)
/// </summary>
public class Contour : Point2DList, ITriangulatable, IEnumerable<TriangulationPoint>, IList<TriangulationPoint>
{
private List<Contour> mHoles = new List<Contour>();
private ITriangulatable mParent = null;
private string mName = "";
public new TriangulationPoint this[int index]
{
get { return mPoints[index] as TriangulationPoint; }
set { mPoints[index] = value; }
}
public string Name { get { return mName; } set { mName = value; } }
public IList<DelaunayTriangle> Triangles
{
get
{
throw new NotImplementedException("PolyHole.Triangles should never get called");
}
private set { }
}
public TriangulationMode TriangulationMode { get { return mParent.TriangulationMode; } }
public string FileName { get { return mParent.FileName; } set { } }
public bool DisplayFlipX { get { return mParent.DisplayFlipX; } set { } }
public bool DisplayFlipY { get { return mParent.DisplayFlipY; } set { } }
public float DisplayRotate { get { return mParent.DisplayRotate; } set { } }
public double Precision { get { return mParent.Precision; } set { } }
public double MinX { get { return mBoundingBox.MinX; } }
public double MaxX { get { return mBoundingBox.MaxX; } }
public double MinY { get { return mBoundingBox.MinY; } }
public double MaxY { get { return mBoundingBox.MaxY; } }
public Rect2D Bounds { get { return mBoundingBox; } }
public Contour(ITriangulatable parent)
{
mParent = parent;
}
public Contour(ITriangulatable parent, IList<TriangulationPoint> points, Point2DList.WindingOrderType windingOrder)
{
// Currently assumes that input is pre-checked for validity
mParent = parent;
AddRange(points, windingOrder);
}
public override string ToString()
{
return mName + " : " + base.ToString();
}
IEnumerator<TriangulationPoint> IEnumerable<TriangulationPoint>.GetEnumerator()
{
return new TriangulationPointEnumerator(mPoints);
}
public int IndexOf(TriangulationPoint p)
{
return mPoints.IndexOf(p);
}
public void Add(TriangulationPoint p)
{
Add(p, -1, true);
}
protected override void Add(Point2D p, int idx, bool bCalcWindingOrderAndEpsilon)
{
TriangulationPoint pt = null;
if (p is TriangulationPoint)
{
pt = p as TriangulationPoint;
}
else
{
pt = new TriangulationPoint(p.X, p.Y);
}
if (idx < 0)
{
mPoints.Add(pt);
}
else
{
mPoints.Insert(idx, pt);
}
mBoundingBox.AddPoint(pt);
if (bCalcWindingOrderAndEpsilon)
{
if (mWindingOrder == WindingOrderType.Unknown)
{
mWindingOrder = CalculateWindingOrder();
}
mEpsilon = CalculateEpsilon();
}
}
public override void AddRange(IEnumerator<Point2D> iter, WindingOrderType windingOrder)
{
if (iter == null)
{
return;
}
if (mWindingOrder == WindingOrderType.Unknown && Count == 0)
{
mWindingOrder = windingOrder;
}
bool bReverseReadOrder = (WindingOrder != WindingOrderType.Unknown) && (windingOrder != WindingOrderType.Unknown) && (WindingOrder != windingOrder);
bool bAddedFirst = true;
int startCount = mPoints.Count;
iter.Reset();
while (iter.MoveNext())
{
TriangulationPoint pt = null;
if (iter.Current is TriangulationPoint)
{
pt = iter.Current as TriangulationPoint;
}
else
{
pt = new TriangulationPoint(iter.Current.X, iter.Current.Y);
}
if (!bAddedFirst)
{
bAddedFirst = true;
mPoints.Add(pt);
}
else if (bReverseReadOrder)
{
mPoints.Insert(startCount, pt);
}
else
{
mPoints.Add(pt);
}
mBoundingBox.AddPoint(iter.Current);
}
if (mWindingOrder == WindingOrderType.Unknown && windingOrder == WindingOrderType.Unknown)
{
mWindingOrder = CalculateWindingOrder();
}
mEpsilon = CalculateEpsilon();
}
public void AddRange(IList<TriangulationPoint> points, Point2DList.WindingOrderType windingOrder)
{
if (points == null || points.Count < 1)
{
return;
}
if (mWindingOrder == Point2DList.WindingOrderType.Unknown && Count == 0)
{
mWindingOrder = windingOrder;
}
int numPoints = points.Count;
bool bReverseReadOrder = (WindingOrder != WindingOrderType.Unknown) && (windingOrder != WindingOrderType.Unknown) && (WindingOrder != windingOrder);
for (int i = 0; i < numPoints; ++i)
{
int idx = i;
if (bReverseReadOrder)
{
idx = points.Count - i - 1;
}
Add(points[idx], -1, false);
}
if (mWindingOrder == WindingOrderType.Unknown)
{
mWindingOrder = CalculateWindingOrder();
}
mEpsilon = CalculateEpsilon();
}
public void Insert(int idx, TriangulationPoint p)
{
Add(p, idx, true);
}
public bool Remove(TriangulationPoint p)
{
return Remove(p as Point2D);
}
public bool Contains(TriangulationPoint p)
{
return mPoints.Contains(p);
}
public void CopyTo(TriangulationPoint[] array, int arrayIndex)
{
int numElementsToCopy = Math.Min(Count, array.Length - arrayIndex);
for (int i = 0; i < numElementsToCopy; ++i)
{
array[arrayIndex + i] = mPoints[i] as TriangulationPoint;
}
}
protected void AddHole(Contour c)
{
// no checking is done here as we rely on InitializeHoles for that
c.mParent = this;
mHoles.Add(c);
}
/// <summary>
/// returns number of holes that are actually holes, including all children of children, etc. Does NOT
/// include holes that are not actually holes. For example, if the parent is not a hole and this contour has
/// a hole that contains a hole, then the number of holes returned would be 2 - one for the current hole (because
/// the parent is NOT a hole and thus this hole IS a hole), and 1 for the child of the child.
/// </summary>
/// <param name="parentIsHole"></param>
/// <returns></returns>
public int GetNumHoles(bool parentIsHole)
{
int numHoles = parentIsHole ? 0 : 1;
foreach (Contour c in mHoles)
{
numHoles += c.GetNumHoles(!parentIsHole);
}
return numHoles;
}
/// <summary>
/// returns the basic number of child holes of THIS contour, not including any children of children, etc nor
/// examining whether any children are actual holes.
/// </summary>
/// <returns></returns>
public int GetNumHoles()
{
return mHoles.Count;
}
public Contour GetHole(int idx)
{
if (idx < 0 || idx >= mHoles.Count)
{
return null;
}
return mHoles[idx];
}
public void GetActualHoles(bool parentIsHole, ref List<Contour> holes)
{
if (parentIsHole)
{
holes.Add(this);
}
foreach (Contour c in mHoles)
{
c.GetActualHoles(!parentIsHole, ref holes);
}
}
public List<Contour>.Enumerator GetHoleEnumerator()
{
return mHoles.GetEnumerator();
}
public void InitializeHoles(ConstrainedPointSet cps)
{
Contour.InitializeHoles(mHoles, this, cps);
foreach (Contour c in mHoles)
{
c.InitializeHoles(cps);
}
}
public static void InitializeHoles(List<Contour> holes, ITriangulatable parent, ConstrainedPointSet cps)
{
int numHoles = holes.Count;
int holeIdx = 0;
// pass 1 - remove duplicates
while (holeIdx < numHoles)
{
int hole2Idx = holeIdx + 1;
while (hole2Idx < numHoles)
{
bool bSamePolygon = PolygonUtil.PolygonsAreSame2D(holes[holeIdx], holes[hole2Idx]);
if (bSamePolygon)
{
// remove one of them
holes.RemoveAt(hole2Idx);
--numHoles;
}
else
{
++hole2Idx;
}
}
++holeIdx;
}
// pass 2: Intersections and Containment
holeIdx = 0;
while (holeIdx < numHoles)
{
bool bIncrementHoleIdx = true;
int hole2Idx = holeIdx + 1;
while (hole2Idx < numHoles)
{
if (PolygonUtil.PolygonContainsPolygon(holes[holeIdx], holes[holeIdx].Bounds, holes[hole2Idx], holes[hole2Idx].Bounds, false))
{
holes[holeIdx].AddHole(holes[hole2Idx]);
holes.RemoveAt(hole2Idx);
--numHoles;
}
else if (PolygonUtil.PolygonContainsPolygon(holes[hole2Idx], holes[hole2Idx].Bounds, holes[holeIdx], holes[holeIdx].Bounds, false))
{
holes[hole2Idx].AddHole(holes[holeIdx]);
holes.RemoveAt(holeIdx);
--numHoles;
bIncrementHoleIdx = false;
break;
}
else
{
bool bIntersect = PolygonUtil.PolygonsIntersect2D(holes[holeIdx], holes[holeIdx].Bounds, holes[hole2Idx], holes[hole2Idx].Bounds);
if (bIntersect)
{
// this is actually an error condition
// fix by merging hole1 and hole2 into hole1 (including the holes inside hole2!) and delete hole2
// Then, because hole1 is now changed, restart it's check.
PolygonOperationContext ctx = new PolygonOperationContext();
if (!ctx.Init(PolygonUtil.PolyOperation.Union | PolygonUtil.PolyOperation.Intersect, holes[holeIdx], holes[hole2Idx]))
{
if (ctx.mError == PolygonUtil.PolyUnionError.Poly1InsidePoly2)
{
holes[hole2Idx].AddHole(holes[holeIdx]);
holes.RemoveAt(holeIdx);
--numHoles;
bIncrementHoleIdx = false;
break;
}
else
{
throw new Exception("PolygonOperationContext.Init had an error during initialization");
}
}
PolygonUtil.PolyUnionError pue = PolygonUtil.PolygonOperation(ctx);
if (pue == PolygonUtil.PolyUnionError.None)
{
Point2DList union = ctx.Union;
Point2DList intersection = ctx.Intersect;
// create a new contour for the union
Contour c = new Contour(parent);
c.AddRange(union);
c.Name = "(" + holes[holeIdx].Name + " UNION " + holes[hole2Idx].Name + ")";
c.WindingOrder = Point2DList.WindingOrderType.Default;
// add children from both of the merged contours
int numChildHoles = holes[holeIdx].GetNumHoles();
for(int i = 0; i < numChildHoles; ++i)
{
c.AddHole(holes[holeIdx].GetHole(i));
}
numChildHoles = holes[hole2Idx].GetNumHoles();
for (int i = 0; i < numChildHoles; ++i)
{
c.AddHole(holes[hole2Idx].GetHole(i));
}
// make sure we preserve the contours of the intersection
Contour cInt = new Contour(c);
cInt.AddRange(intersection);
cInt.Name = "(" + holes[holeIdx].Name + " INTERSECT " + holes[hole2Idx].Name + ")";
cInt.WindingOrder = Point2DList.WindingOrderType.Default;
c.AddHole(cInt);
// replace the current contour with the merged contour
holes[holeIdx] = c;
// toss the second contour
holes.RemoveAt(hole2Idx);
--numHoles;
// current hole is "examined", so move to the next one
hole2Idx = holeIdx + 1;
}
else
{
throw new Exception("PolygonOperation had an error!");
}
}
else
{
++hole2Idx;
}
}
}
if (bIncrementHoleIdx)
{
++holeIdx;
}
}
numHoles = holes.Count;
holeIdx = 0;
while (holeIdx < numHoles)
{
int numPoints = holes[holeIdx].Count;
for (int i = 0; i < numPoints; ++i)
{
int j = holes[holeIdx].NextIndex(i);
uint constraintCode = TriangulationConstraint.CalculateContraintCode(holes[holeIdx][i], holes[holeIdx][j]);
TriangulationConstraint tc = null;
if (!cps.TryGetConstraint(constraintCode, out tc))
{
tc = new TriangulationConstraint(holes[holeIdx][i], holes[holeIdx][j]);
cps.AddConstraint(tc);
}
// replace the points in the holes with valid points
if (holes[holeIdx][i].VertexCode == tc.P.VertexCode)
{
holes[holeIdx][i] = tc.P;
}
else if (holes[holeIdx][j].VertexCode == tc.P.VertexCode)
{
holes[holeIdx][j] = tc.P;
}
if (holes[holeIdx][i].VertexCode == tc.Q.VertexCode)
{
holes[holeIdx][i] = tc.Q;
}
else if (holes[holeIdx][j].VertexCode == tc.Q.VertexCode)
{
holes[holeIdx][j] = tc.Q;
}
}
++holeIdx;
}
}
public void Prepare(TriangulationContext tcx)
{
throw new NotImplementedException("PolyHole.Prepare should never get called");
}
public void AddTriangle(DelaunayTriangle t)
{
throw new NotImplementedException("PolyHole.AddTriangle should never get called");
}
public void AddTriangles(IEnumerable<DelaunayTriangle> list)
{
throw new NotImplementedException("PolyHole.AddTriangles should never get called");
}
public void ClearTriangles()
{
throw new NotImplementedException("PolyHole.ClearTriangles should never get called");
}
public Point2D FindPointInContour()
{
if (Count < 3)
{
return null;
}
// first try the simple approach:
Point2D p = GetCentroid();
if (IsPointInsideContour(p))
{
return p;
}
// brute force it...
Random random = new Random();
while (true)
{
p.X = (random.NextDouble() * (MaxX - MinX)) + MinX;
p.Y = (random.NextDouble() * (MaxY - MinY)) + MinY;
if (IsPointInsideContour(p))
{
return p;
}
}
}
public bool IsPointInsideContour(Point2D p)
{
if (PolygonUtil.PointInPolygon2D(this, p))
{
foreach (Contour c in mHoles)
{
if (c.IsPointInsideContour(p))
{
return false;
}
}
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5dfd11dff63cdeb4f8543c5ee276d3f9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,409 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/// Changes from the Java version
/// Polygon constructors sprused up, checks for 3+ polys
/// Naming of everything
/// getTriangulationMode() -> TriangulationMode { get; }
/// Exceptions replaced
/// Future possibilities
/// We have a lot of Add/Clear methods -- we may prefer to just expose the container
/// Some self-explanatory methods may deserve commenting anyways
using System;
using System.Collections.Generic;
using System.Linq;
namespace Poly2Tri
{
public class Polygon : Point2DList, ITriangulatable, IEnumerable<TriangulationPoint>, IList<TriangulationPoint>
{
// ITriangulatable Implementation
protected Dictionary<uint, TriangulationPoint> mPointMap = new Dictionary<uint, TriangulationPoint>();
public IList<TriangulationPoint> Points { get { return this; } }
protected List<DelaunayTriangle> mTriangles;
public IList<DelaunayTriangle> Triangles { get { return mTriangles; } }
public TriangulationMode TriangulationMode { get { return TriangulationMode.Polygon; } }
public string FileName { get; set; }
public bool DisplayFlipX { get; set; }
public bool DisplayFlipY { get; set; }
public float DisplayRotate { get; set; }
private double mPrecision = TriangulationPoint.kVertexCodeDefaultPrecision;
public double Precision { get { return mPrecision; } set { mPrecision = value; } }
public double MinX { get { return mBoundingBox.MinX; } }
public double MaxX { get { return mBoundingBox.MaxX; } }
public double MinY { get { return mBoundingBox.MinY; } }
public double MaxY { get { return mBoundingBox.MaxY; } }
public Rect2D Bounds { get { return mBoundingBox; } }
// Point2DList overrides
public new TriangulationPoint this[int index]
{
get { return mPoints[index] as TriangulationPoint; }
set { mPoints[index] = value; }
}
// Polygon Implementation
protected List<Polygon> mHoles;
public IList<Polygon> Holes { get { return mHoles; } }
protected List<TriangulationPoint> mSteinerPoints;
protected PolygonPoint _last;
/// <summary>
/// Create a polygon from a list of at least 3 points with no duplicates.
/// </summary>
/// <param name="points">A list of unique points</param>
public Polygon(IList<PolygonPoint> points)
{
if (points.Count < 3)
{
throw new ArgumentException("List has fewer than 3 points", "points");
}
AddRange(points, WindingOrderType.Unknown);
}
/// <summary>
/// Create a polygon from a list of at least 3 points with no duplicates.
/// </summary>
/// <param name="points">A list of unique points.</param>
public Polygon(IEnumerable<PolygonPoint> points)
: this((points as IList<PolygonPoint>) ?? points.ToArray())
{}
/// <summary>
/// Create a polygon from a list of at least 3 points with no duplicates.
/// </summary>
/// <param name="points">A list of unique points.</param>
public Polygon(params PolygonPoint[] points)
: this((IList<PolygonPoint>)points)
{}
IEnumerator<TriangulationPoint> IEnumerable<TriangulationPoint>.GetEnumerator()
{
return new TriangulationPointEnumerator(mPoints);
}
public int IndexOf(TriangulationPoint p)
{
return mPoints.IndexOf(p);
}
public override void Add(Point2D p)
{
Add(p, -1, true);
}
public void Add(TriangulationPoint p)
{
Add(p, -1, true);
}
public void Add(PolygonPoint p)
{
Add(p, -1, true);
}
protected override void Add(Point2D p, int idx, bool bCalcWindingOrderAndEpsilon)
{
TriangulationPoint pt = p as TriangulationPoint;
if (pt == null)
{
// we only store TriangulationPoints and PolygonPoints in this class
return;
}
// do not insert duplicate points
if (mPointMap.ContainsKey(pt.VertexCode))
{
return;
}
mPointMap.Add(pt.VertexCode, pt);
base.Add(p, idx, bCalcWindingOrderAndEpsilon);
PolygonPoint pp = p as PolygonPoint;
if (pp != null)
{
pp.Previous = _last;
if (_last != null)
{
pp.Next = _last.Next;
_last.Next = pp;
}
_last = pp;
}
return;
}
public void AddRange(IList<PolygonPoint> points, Point2DList.WindingOrderType windingOrder)
{
if (points == null || points.Count < 1)
{
return;
}
if (mWindingOrder == Point2DList.WindingOrderType.Unknown && Count == 0)
{
mWindingOrder = windingOrder;
}
int numPoints = points.Count;
bool bReverseReadOrder = (WindingOrder != WindingOrderType.Unknown) && (windingOrder != WindingOrderType.Unknown) && (WindingOrder != windingOrder);
for (int i = 0; i < numPoints; ++i)
{
int idx = i;
if (bReverseReadOrder)
{
idx = points.Count - i - 1;
}
Add(points[idx], -1, false);
}
if (mWindingOrder == WindingOrderType.Unknown)
{
mWindingOrder = CalculateWindingOrder();
}
mEpsilon = CalculateEpsilon();
}
public void AddRange(IList<TriangulationPoint> points, Point2DList.WindingOrderType windingOrder)
{
if (points == null || points.Count < 1)
{
return;
}
if (mWindingOrder == Point2DList.WindingOrderType.Unknown && Count == 0)
{
mWindingOrder = windingOrder;
}
int numPoints = points.Count;
bool bReverseReadOrder = (WindingOrder != WindingOrderType.Unknown) && (windingOrder != WindingOrderType.Unknown) && (WindingOrder != windingOrder);
for (int i = 0; i < numPoints; ++i)
{
int idx = i;
if (bReverseReadOrder)
{
idx = points.Count - i - 1;
}
Add(points[idx], -1, false);
}
if (mWindingOrder == WindingOrderType.Unknown)
{
mWindingOrder = CalculateWindingOrder();
}
mEpsilon = CalculateEpsilon();
}
public void Insert(int idx, TriangulationPoint p)
{
Add(p, idx, true);
}
public bool Remove(TriangulationPoint p)
{
return base.Remove(p);
}
/// <summary>
/// Removes a point from the polygon. Note this can be a somewhat expensive operation
/// as it must recalculate the bounding area from scratch.
/// </summary>
/// <param name="p"></param>
public void RemovePoint(PolygonPoint p)
{
PolygonPoint next, prev;
next = p.Next;
prev = p.Previous;
prev.Next = next;
next.Previous = prev;
mPoints.Remove(p);
mBoundingBox.Clear();
foreach (PolygonPoint tmp in mPoints)
{
mBoundingBox.AddPoint(tmp);
}
}
public bool Contains(TriangulationPoint p)
{
return mPoints.Contains(p);
}
public void CopyTo(TriangulationPoint[] array, int arrayIndex)
{
int numElementsToCopy = Math.Min(Count, array.Length - arrayIndex);
for (int i = 0; i < numElementsToCopy; ++i)
{
array[arrayIndex + i] = mPoints[i] as TriangulationPoint;
}
}
public void AddSteinerPoint(TriangulationPoint point)
{
if (mSteinerPoints == null)
{
mSteinerPoints = new List<TriangulationPoint>();
}
mSteinerPoints.Add(point);
}
public void AddSteinerPoints(List<TriangulationPoint> points)
{
if (mSteinerPoints == null)
{
mSteinerPoints = new List<TriangulationPoint>();
}
mSteinerPoints.AddRange(points);
}
public void ClearSteinerPoints()
{
if (mSteinerPoints != null)
{
mSteinerPoints.Clear();
}
}
/// <summary>
/// Add a hole to the polygon.
/// </summary>
/// <param name="poly">A subtraction polygon fully contained inside this polygon.</param>
public void AddHole(Polygon poly)
{
if (mHoles == null)
{
mHoles = new List<Polygon>();
}
mHoles.Add(poly);
// XXX: tests could be made here to be sure it is fully inside
// addSubtraction( poly.getPoints() );
}
public void AddTriangle(DelaunayTriangle t)
{
mTriangles.Add(t);
}
public void AddTriangles(IEnumerable<DelaunayTriangle> list)
{
mTriangles.AddRange(list);
}
public void ClearTriangles()
{
if (mTriangles != null)
{
mTriangles.Clear();
}
}
public bool IsPointInside(TriangulationPoint p)
{
return PolygonUtil.PointInPolygon2D(this, p);
}
/// <summary>
/// Creates constraints and populates the context with points
/// </summary>
/// <param name="tcx">The context</param>
public void Prepare(TriangulationContext tcx)
{
if (mTriangles == null)
{
mTriangles = new List<DelaunayTriangle>(mPoints.Count);
}
else
{
mTriangles.Clear();
}
// Outer constraints
for (int i = 0; i < mPoints.Count - 1; i++)
{
//tcx.NewConstraint(mPoints[i], mPoints[i + 1]);
tcx.NewConstraint(this[i], this[i + 1]);
}
tcx.NewConstraint(this[0], this[Count - 1]);
tcx.Points.AddRange(this);
// Hole constraints
if (mHoles != null)
{
foreach (Polygon p in mHoles)
{
for (int i = 0; i < p.mPoints.Count - 1; i++)
{
tcx.NewConstraint(p[i], p[i + 1]);
}
tcx.NewConstraint(p[0], p[p.Count - 1]);
tcx.Points.AddRange(p);
}
}
if (mSteinerPoints != null)
{
tcx.Points.AddRange(mSteinerPoints);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 98daeea2e71d727429a84a799a9b1706
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/// Changes from the Java version
/// Replaced get/set Next/Previous with attributes
/// Future possibilities
/// Documentation!
namespace Poly2Tri
{
public class PolygonPoint : TriangulationPoint
{
public PolygonPoint(double x, double y) : base(x, y) { }
public PolygonPoint Next { get; set; }
public PolygonPoint Previous { get; set; }
public static Point2D ToBasePoint(PolygonPoint p)
{
return (Point2D)p;
}
public static TriangulationPoint ToTriangulationPoint(PolygonPoint p)
{
return (TriangulationPoint)p;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 55fd89ec8383d3b48b01e6abebf915c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,60 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/// Changes from the Java version
/// Replaced getPolygons with attribute
/// Future possibilities
/// Replace Add(Polygon) with exposed container?
/// Replace entire class with HashSet<Polygon> ?
using System.Collections.Generic;
namespace Poly2Tri
{
public class PolygonSet
{
protected List<Polygon> _polygons = new List<Polygon>();
public PolygonSet() { }
public PolygonSet(Polygon poly)
{
_polygons.Add(poly);
}
public void Add(Polygon p)
{
_polygons.Add(p);
}
public IEnumerable<Polygon> Polygons { get { return _polygons; } }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b9b966d2e3f8d543beed734daa9b289
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3c2b8bdeed61807438a69bc54de1a423
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0fe19f49cb73334418d2abe53ddbe747
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,444 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Poly2Tri
{
/*
* Extends the PointSet by adding some Constraints on how it will be triangulated<br>
* A constraint defines an edge between two points in the set, these edges can not
* be crossed. They will be enforced triangle edges after a triangulation.
* <p>
*
*
* @author Thomas Åhlén, thahlen@gmail.com
* @author Lee Wilson, lwilson@ea.com
*/
public class ConstrainedPointSet : PointSet
{
protected Dictionary<uint, TriangulationConstraint> mConstraintMap = new Dictionary<uint, TriangulationConstraint>();
protected List<Contour> mHoles = new List<Contour>();
public override TriangulationMode TriangulationMode { get { return TriangulationMode.Constrained; } }
public ConstrainedPointSet(List<TriangulationPoint> bounds)
: base(bounds)
{
AddBoundaryConstraints();
}
public ConstrainedPointSet(List<TriangulationPoint> bounds, List<TriangulationConstraint> constraints)
: base(bounds)
{
AddBoundaryConstraints();
AddConstraints(constraints);
}
public ConstrainedPointSet(List<TriangulationPoint> bounds, int[] indices)
: base(bounds)
{
AddBoundaryConstraints();
List<TriangulationConstraint> l = new List<TriangulationConstraint>();
for (int i = 0; i < indices.Length; i += 2)
{
TriangulationConstraint tc = new TriangulationConstraint(bounds[i], bounds[i + 1]);
l.Add(tc);
}
AddConstraints(l);
}
protected void AddBoundaryConstraints()
{
TriangulationPoint ptLL = null;
TriangulationPoint ptLR = null;
TriangulationPoint ptUR = null;
TriangulationPoint ptUL = null;
if (!TryGetPoint(MinX, MinY, out ptLL))
{
ptLL = new TriangulationPoint(MinX, MinY);
Add(ptLL);
}
if (!TryGetPoint(MaxX, MinY, out ptLR))
{
ptLR = new TriangulationPoint(MaxX, MinY);
Add(ptLR);
}
if (!TryGetPoint(MaxX, MaxY, out ptUR))
{
ptUR = new TriangulationPoint(MaxX, MaxY);
Add(ptUR);
}
if (!TryGetPoint(MinX, MaxY, out ptUL))
{
ptUL = new TriangulationPoint(MinX, MaxY);
Add(ptUL);
}
TriangulationConstraint tcLLtoLR = new TriangulationConstraint(ptLL, ptLR);
AddConstraint(tcLLtoLR);
TriangulationConstraint tcLRtoUR = new TriangulationConstraint(ptLR, ptUR);
AddConstraint(tcLRtoUR);
TriangulationConstraint tcURtoUL = new TriangulationConstraint(ptUR, ptUL);
AddConstraint(tcURtoUL);
TriangulationConstraint tcULtoLL = new TriangulationConstraint(ptUL, ptLL);
AddConstraint(tcULtoLL);
}
public override void Add(Point2D p)
{
Add(p as TriangulationPoint, -1, true);
}
public override void Add(TriangulationPoint p)
{
Add(p, -1, true);
}
public override bool AddRange(List<TriangulationPoint> points)
{
bool bOK = true;
foreach (TriangulationPoint p in points)
{
bOK = Add(p, -1, true) && bOK;
}
return bOK;
}
// Assumes that points being passed in the list are connected and form a polygon.
// Note that some error checking is done for robustness, but for the most part,
// we have to rely on the user to feed us "correct" data
public bool AddHole(List<TriangulationPoint> points, string name)
{
if (points == null)
{
return false;
}
//// split our self-intersection sections into their own lists
List<Contour> pts = new List<Contour>();
int listIdx = 0;
{
Contour c = new Contour(this, points, WindingOrderType.Unknown);
pts.Add(c);
// only constrain the points if we actually HAVE a bounding rect
if (mPoints.Count > 1)
{
// constrain the points to bounding rect
int numPoints = pts[listIdx].Count;
for (int i = 0; i < numPoints; ++i)
{
ConstrainPointToBounds(pts[listIdx][i]);
}
}
}
while (listIdx < pts.Count)
{
// simple sanity checking - remove duplicate coincident points before
// we check the polygon: fast, simple algorithm that eliminate lots of problems
// that only more expensive checks will find
pts[listIdx].RemoveDuplicateNeighborPoints();
pts[listIdx].WindingOrder = Point2DList.WindingOrderType.Default;
bool bListOK = true;
Point2DList.PolygonError err = pts[listIdx].CheckPolygon();
while (bListOK && err != PolygonError.None)
{
if ((err & PolygonError.NotEnoughVertices) == PolygonError.NotEnoughVertices)
{
bListOK = false;
continue;
}
if ((err & PolygonError.NotSimple) == PolygonError.NotSimple)
{
// split the polygons, remove the current list and add the resulting list to the end
//List<Point2DList> l = TriangulationUtil.SplitSelfIntersectingPolygon(pts[listIdx], pts[listIdx].Epsilon);
List<Point2DList> l = PolygonUtil.SplitComplexPolygon(pts[listIdx], pts[listIdx].Epsilon);
pts.RemoveAt(listIdx);
foreach (Point2DList newList in l)
{
Contour c = new Contour(this);
c.AddRange(newList);
pts.Add(c);
}
err = pts[listIdx].CheckPolygon();
continue;
}
if ((err & PolygonError.Degenerate) == PolygonError.Degenerate)
{
pts[listIdx].Simplify(this.Epsilon);
err = pts[listIdx].CheckPolygon();
continue;
//err &= ~(PolygonError.Degenerate);
//if (pts[listIdx].Count < 3)
//{
// err |= PolygonError.NotEnoughVertices;
// bListOK = false;
// continue;
//}
}
if ((err & PolygonError.AreaTooSmall) == PolygonError.AreaTooSmall ||
(err & PolygonError.SidesTooCloseToParallel) == PolygonError.SidesTooCloseToParallel ||
(err & PolygonError.TooThin) == PolygonError.TooThin ||
(err & PolygonError.Unknown) == PolygonError.Unknown)
{
bListOK = false;
continue;
}
// non-convex polygons are ok
//if ((err & PolygonError.NotConvex) == PolygonError.NotConvex)
//{
//}
}
if (!bListOK && pts[listIdx].Count != 2)
{
pts.RemoveAt(listIdx);
}
else
{
++listIdx;
}
}
bool bOK = true;
listIdx = 0;
while (listIdx < pts.Count)
{
int numPoints = pts[listIdx].Count;
if (numPoints < 2)
{
// should not be possible by this point...
++listIdx;
bOK = false;
continue;
}
else if (numPoints == 2)
{
uint constraintCode = TriangulationConstraint.CalculateContraintCode(pts[listIdx][0], pts[listIdx][1]);
TriangulationConstraint tc = null;
if (!mConstraintMap.TryGetValue(constraintCode, out tc))
{
tc = new TriangulationConstraint(pts[listIdx][0], pts[listIdx][1]);
AddConstraint(tc);
}
}
else
{
Contour ph = new Contour(this, pts[listIdx], Point2DList.WindingOrderType.Unknown);
ph.WindingOrder = Point2DList.WindingOrderType.Default;
ph.Name = name + ":" + listIdx.ToString();
mHoles.Add(ph);
}
++listIdx;
}
return bOK;
}
// this method adds constraints singly and does not assume that they form a contour
// If you are trying to add a "series" or edges (or "contour"), use AddHole instead.
public bool AddConstraints(List<TriangulationConstraint> constraints)
{
if (constraints == null || constraints.Count < 1)
{
return false;
}
bool bOK = true;
foreach (TriangulationConstraint tc in constraints)
{
if (ConstrainPointToBounds(tc.P) || ConstrainPointToBounds(tc.Q))
{
tc.CalculateContraintCode();
}
TriangulationConstraint tcTmp = null;
if (!mConstraintMap.TryGetValue(tc.ConstraintCode, out tcTmp))
{
tcTmp = tc;
bOK = AddConstraint(tcTmp) && bOK;
}
}
return bOK;
}
public bool AddConstraint(TriangulationConstraint tc)
{
if (tc == null || tc.P == null || tc.Q == null)
{
return false;
}
// If we already have this constraint, then there's nothing to do. Since we already have
// a valid constraint in the map with the same ConstraintCode, then we're guaranteed that
// the points are also valid (and have the same coordinates as the ones being passed in with
// this constrain). Return true to indicate that we successfully "added" the constraint
if (mConstraintMap.ContainsKey(tc.ConstraintCode))
{
return true;
}
// Make sure the constraint is not using points that are duplicates of ones already stored
// If it is, replace the Constraint Points with the points already stored.
TriangulationPoint p;
if (TryGetPoint(tc.P.X, tc.P.Y, out p))
{
tc.P = p;
}
else
{
Add(tc.P);
}
if (TryGetPoint(tc.Q.X, tc.Q.Y, out p))
{
tc.Q = p;
}
else
{
Add(tc.Q);
}
mConstraintMap.Add(tc.ConstraintCode, tc);
return true;
}
public bool TryGetConstraint(uint constraintCode, out TriangulationConstraint tc)
{
return mConstraintMap.TryGetValue(constraintCode, out tc);
}
public int GetNumConstraints()
{
return mConstraintMap.Count;
}
public Dictionary<uint, TriangulationConstraint>.Enumerator GetConstraintEnumerator()
{
return mConstraintMap.GetEnumerator();
}
public int GetNumHoles()
{
int numHoles = 0;
foreach (Contour c in mHoles)
{
numHoles += c.GetNumHoles(false);
}
return numHoles;
}
public Contour GetHole(int idx)
{
if (idx < 0 || idx >= mHoles.Count)
{
return null;
}
return mHoles[idx];
}
public int GetActualHoles(out List<Contour> holes)
{
holes = new List<Contour>();
foreach (Contour c in mHoles)
{
c.GetActualHoles(false, ref holes);
}
return holes.Count;
}
protected void InitializeHoles()
{
Contour.InitializeHoles(mHoles, this, this);
foreach (Contour c in mHoles)
{
c.InitializeHoles(this);
}
}
public override bool Initialize()
{
InitializeHoles();
return base.Initialize();
}
public override void Prepare(TriangulationContext tcx)
{
if (!Initialize())
{
return;
}
base.Prepare(tcx);
Dictionary<uint, TriangulationConstraint>.Enumerator it = mConstraintMap.GetEnumerator();
while (it.MoveNext())
{
TriangulationConstraint tc = it.Current.Value;
tcx.NewConstraint(tc.P, tc.Q);
}
}
public override void AddTriangle(DelaunayTriangle t)
{
Triangles.Add(t);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 916d5f1fd714de84cbff36c5f382d155
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,303 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Poly2Tri
{
public class PointSet : Point2DList, ITriangulatable, IEnumerable<TriangulationPoint>, IList<TriangulationPoint>
{
protected Dictionary<uint, TriangulationPoint> mPointMap = new Dictionary<uint, TriangulationPoint>();
public IList<TriangulationPoint> Points { get { return this; } private set { } }
public IList<DelaunayTriangle> Triangles { get; private set; }
public string FileName { get; set; }
public bool DisplayFlipX { get; set; }
public bool DisplayFlipY { get; set; }
public float DisplayRotate { get; set; }
protected double mPrecision = TriangulationPoint.kVertexCodeDefaultPrecision;
public double Precision { get { return mPrecision; } set { mPrecision = value; } }
public double MinX { get { return mBoundingBox.MinX; } }
public double MaxX { get { return mBoundingBox.MaxX; } }
public double MinY { get { return mBoundingBox.MinY; } }
public double MaxY { get { return mBoundingBox.MaxY; } }
public Rect2D Bounds { get { return mBoundingBox; } }
public virtual TriangulationMode TriangulationMode { get { return TriangulationMode.Unconstrained; } }
public new TriangulationPoint this[int index]
{
get { return mPoints[index] as TriangulationPoint; }
set { mPoints[index] = value; }
}
public PointSet(List<TriangulationPoint> bounds)
{
//Points = new List<TriangulationPoint>();
foreach (TriangulationPoint p in bounds)
{
Add(p, -1, false);
// Only the initial points are counted toward min/max x/y as they
// are considered to be the boundaries of the point-set
mBoundingBox.AddPoint(p);
}
mEpsilon = CalculateEpsilon();
mWindingOrder = WindingOrderType.Unknown; // not valid for a point-set
}
IEnumerator<TriangulationPoint> IEnumerable<TriangulationPoint>.GetEnumerator()
{
return new TriangulationPointEnumerator(mPoints);
}
public int IndexOf(TriangulationPoint p)
{
return mPoints.IndexOf(p);
}
public override void Add(Point2D p)
{
Add(p as TriangulationPoint, -1, false);
}
public virtual void Add(TriangulationPoint p)
{
Add(p, -1, false);
}
protected override void Add(Point2D p, int idx, bool constrainToBounds)
{
Add(p as TriangulationPoint, idx, constrainToBounds);
}
protected bool Add(TriangulationPoint p, int idx, bool constrainToBounds)
{
if (p == null)
{
return false;
}
if (constrainToBounds)
{
ConstrainPointToBounds(p);
}
// if we already have an instance of the point, then don't bother inserting it again as duplicate points
// will actually cause some real problems later on. Still return true though to indicate that the point
// is successfully "added"
if (mPointMap.ContainsKey(p.VertexCode))
{
return true;
}
mPointMap.Add(p.VertexCode, p);
if (idx < 0)
{
mPoints.Add(p);
}
else
{
mPoints.Insert(idx, p);
}
return true;
}
public override void AddRange(IEnumerator<Point2D> iter, WindingOrderType windingOrder)
{
if (iter == null)
{
return;
}
iter.Reset();
while (iter.MoveNext())
{
Add(iter.Current);
}
}
public virtual bool AddRange(List<TriangulationPoint> points)
{
bool bOK = true;
foreach (TriangulationPoint p in points)
{
bOK = Add(p, -1, false) && bOK;
}
return bOK;
}
public bool TryGetPoint(double x, double y, out TriangulationPoint p)
{
uint vc = TriangulationPoint.CreateVertexCode(x, y, Precision);
if (mPointMap.TryGetValue(vc, out p))
{
return true;
}
return false;
}
//public override void Insert(int idx, Point2D item)
//{
// Add(item, idx, true);
//}
public void Insert(int idx, TriangulationPoint item)
{
mPoints.Insert(idx, item);
}
public override bool Remove(Point2D p)
{
return mPoints.Remove(p);
}
public bool Remove(TriangulationPoint p)
{
return mPoints.Remove(p);
}
public override void RemoveAt(int idx)
{
if (idx < 0 || idx >= Count)
{
return;
}
mPoints.RemoveAt(idx);
}
public bool Contains(TriangulationPoint p)
{
return mPoints.Contains(p);
}
public void CopyTo(TriangulationPoint[] array, int arrayIndex)
{
int numElementsToCopy = Math.Min(Count, array.Length - arrayIndex);
for (int i = 0; i < numElementsToCopy; ++i)
{
array[arrayIndex + i] = mPoints[i] as TriangulationPoint;
}
}
// returns true if the point is changed, false if the point is unchanged
protected bool ConstrainPointToBounds(Point2D p)
{
double oldX = p.X;
double oldY = p.Y;
p.X = Math.Max(MinX, p.X);
p.X = Math.Min(MaxX, p.X);
p.Y = Math.Max(MinY, p.Y);
p.Y = Math.Min(MaxY, p.Y);
return (p.X != oldX) || (p.Y != oldY);
}
protected bool ConstrainPointToBounds(TriangulationPoint p)
{
double oldX = p.X;
double oldY = p.Y;
p.X = Math.Max(MinX, p.X);
p.X = Math.Min(MaxX, p.X);
p.Y = Math.Max(MinY, p.Y);
p.Y = Math.Min(MaxY, p.Y);
return (p.X != oldX) || (p.Y != oldY);
}
public virtual void AddTriangle(DelaunayTriangle t)
{
Triangles.Add(t);
}
public void AddTriangles(IEnumerable<DelaunayTriangle> list)
{
foreach (var tri in list)
{
AddTriangle(tri);
}
}
public void ClearTriangles()
{
Triangles.Clear();
}
public virtual bool Initialize()
{
return true;
}
public virtual void Prepare(TriangulationContext tcx)
{
if (Triangles == null)
{
Triangles = new List<DelaunayTriangle>(Points.Count);
}
else
{
Triangles.Clear();
}
tcx.Points.AddRange(Points);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 268d5ee20b0e0264ba2e0fb6a609f767
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Poly2Tri
{
public enum TriangulationAlgorithm
{
DTSweep
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: abc66d7b94e2899478944d8ff73c7130
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,153 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Forces a triangle edge between two points p and q
* when triangulating. For example used to enforce
* Polygon Edges during a polygon triangulation.
*
* @author Thomas Åhlén, thahlen@gmail.com
*/
using System;
namespace Poly2Tri
{
public class Edge
{
protected Point2D mP = null;
protected Point2D mQ = null;
public Point2D EdgeStart { get { return mP; } set { mP= value;} }
public Point2D EdgeEnd { get { return mQ; } set { mQ = value; } }
public Edge() { mP = null; mQ = null; }
public Edge(Point2D edgeStart, Point2D edgeEnd)
{
mP = edgeStart;
mQ = edgeEnd;
}
}
public class TriangulationConstraint : Edge
{
private uint mContraintCode = 0;
public TriangulationPoint P
{
get { return mP as TriangulationPoint; }
set
{
// Note: intentionally use != instead of !Equals() because we
// WANT to compare pointer values here rather than VertexCode values
if (value != null && mP != value)
{
mP = value;
CalculateContraintCode();
}
}
}
public TriangulationPoint Q
{
get { return mQ as TriangulationPoint; }
set
{
// Note: intentionally use != instead of !Equals() because we
// WANT to compare pointer values here rather than VertexCode values
if (value != null && mQ != value)
{
mQ = value;
CalculateContraintCode();
}
}
}
public uint ConstraintCode { get { return mContraintCode; } }
/// <summary>
/// Give two points in any order. Will always be ordered so
/// that q.y > p.y and q.x > p.x if same y value
/// </summary>
public TriangulationConstraint(TriangulationPoint p1, TriangulationPoint p2)
{
mP = p1;
mQ = p2;
if (p1.Y > p2.Y)
{
mQ = p1;
mP = p2;
}
else if (p1.Y == p2.Y)
{
if (p1.X > p2.X)
{
mQ = p1;
mP = p2;
}
else if (p1.X == p2.X)
{
// logger.info( "Failed to create constraint {}={}", p1, p2 );
// throw new DuplicatePointException( p1 + "=" + p2 );
// return;
}
}
CalculateContraintCode();
}
public override string ToString()
{
return "[P=" + P.ToString() + ", Q=" + Q.ToString() + " : {" + mContraintCode.ToString() + "}]";
}
public void CalculateContraintCode()
{
mContraintCode = TriangulationConstraint.CalculateContraintCode(P, Q);
}
public static uint CalculateContraintCode(TriangulationPoint p, TriangulationPoint q)
{
if (p == null || p == null)
{
throw new ArgumentNullException();
}
uint constraintCode = MathUtil.Jenkins32Hash(BitConverter.GetBytes(p.VertexCode), 0);
constraintCode = MathUtil.Jenkins32Hash(BitConverter.GetBytes(q.VertexCode), constraintCode);
return constraintCode;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 83093633ca35eae438bb30032fb94cc7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,149 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Poly2Tri
{
public abstract class TriangulationContext
{
public TriangulationDebugContext DebugContext { get; protected set; }
public readonly List<DelaunayTriangle> Triangles = new List<DelaunayTriangle>();
public readonly List<TriangulationPoint> Points = new List<TriangulationPoint>(200);
public TriangulationMode TriangulationMode { get; protected set; }
public ITriangulatable Triangulatable { get; private set; }
public int StepCount { get; private set; }
public void Done()
{
StepCount++;
}
public abstract TriangulationAlgorithm Algorithm { get; }
public virtual void PrepareTriangulation(ITriangulatable t)
{
Triangulatable = t;
TriangulationMode = t.TriangulationMode;
t.Prepare(this);
//List<TriangulationConstraint> constraints = new List<TriangulationConstraint>();
//Console.WriteLine("Points for " + t.FileName + ":");
//Console.WriteLine("Idx,X,Y,VC,Edges");
//int numPoints = Points.Count;
//for (int i = 0; i < numPoints; ++i)
//{
// StringBuilder sb = new StringBuilder(128);
// sb.Append(i.ToString());
// sb.Append(",");
// sb.Append(Points[i].X.ToString());
// sb.Append(",");
// sb.Append(Points[i].Y.ToString());
// sb.Append(",");
// sb.Append(Points[i].VertexCode.ToString());
// int numEdges = (Points[i].Edges != null) ? Points[i].Edges.Count : 0;
// for (int j = 0; j < numEdges; ++j)
// {
// TriangulationConstraint tc = Points[i].Edges[j];
// sb.Append(",");
// sb.Append(tc.ConstraintCode.ToString());
// constraints.Add(tc);
// }
// Console.WriteLine(sb.ToString());
//}
//int idx = 0;
//Console.WriteLine("Constraints " + t.FileName + ":");
//Console.WriteLine("EdgeIdx,Px,Py,PVC,Qx,Qy,QVC,ConstraintCode,Owner");
//foreach (TriangulationConstraint tc in constraints)
//{
// StringBuilder sb = new StringBuilder(128);
// sb.Append(idx.ToString());
// sb.Append(",");
// sb.Append(tc.P.X.ToString());
// sb.Append(",");
// sb.Append(tc.P.Y.ToString());
// sb.Append(",");
// sb.Append(tc.P.VertexCode.ToString());
// sb.Append(",");
// sb.Append(tc.Q.X.ToString());
// sb.Append(",");
// sb.Append(tc.Q.Y.ToString());
// sb.Append(",");
// sb.Append(tc.Q.VertexCode.ToString());
// sb.Append(",");
// sb.Append(tc.ConstraintCode.ToString());
// sb.Append(",");
// if (tc.Q.HasEdge(tc.P))
// {
// sb.Append("Q");
// }
// else
// {
// sb.Append("P");
// }
// Console.WriteLine(sb.ToString());
// ++idx;
//}
}
public abstract TriangulationConstraint NewConstraint(TriangulationPoint a, TriangulationPoint b);
public void Update(string message) { }
public virtual void Clear()
{
Points.Clear();
if (DebugContext != null)
{
DebugContext.Clear();
}
StepCount = 0;
}
public virtual bool IsDebugEnabled { get; protected set; }
public DTSweepDebugContext DTDebugContext { get { return DebugContext as DTSweepDebugContext; } }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a4a56fa5d3520ee40b011ac6f4741f62
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Poly2Tri
{
public abstract class TriangulationDebugContext
{
protected TriangulationContext _tcx;
public TriangulationDebugContext(TriangulationContext tcx)
{
_tcx = tcx;
}
public abstract void Clear();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 90234b8ef08f44743bae557c23b08fb5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Poly2Tri
{
public enum TriangulationMode
{
Unconstrained,
Constrained,
Polygon
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38eec52c05bc87545aa65be96865e8f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,244 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
namespace Poly2Tri
{
public class TriangulationPoint : Point2D
{
public static readonly double kVertexCodeDefaultPrecision = 8.0;
public override double X
{
get { return mX; }
set
{
if (value != mX)
{
mX = value;
mVertexCode = TriangulationPoint.CreateVertexCode(mX, mY, kVertexCodeDefaultPrecision);
// Technically, we should change the ConstraintCodes of any edges that contain this point.
// We don't for 2 reasons:
// 1) Currently the only time we care about Vertex/Constraint Codes is when entering data in the point-set.
// Once the data is being used by the algorithm, the point locations are (currently) not modified.
// 2) Since this Point's Edge list will only contain SOME of the edges that this point is a part of,
// there currently isn't a way to (easily) get any edges that contain this point but are not in this
// point's edge list.
}
}
}
public override double Y
{
get { return mY; }
set
{
if (value != mY)
{
mY = value;
mVertexCode = TriangulationPoint.CreateVertexCode(mX, mY, kVertexCodeDefaultPrecision);
// Technically, we should change the ConstraintCodes of any edges that contain this point.
// We don't for 2 reasons:
// 1) Currently the only time we care about Vertex/Constraint Codes is when entering data in the point-set.
// Once the data is being used by the algorithm, the point locations are (currently) not modified.
// 2) Since this Point's Edge list will only contain SOME of the edges that this point is a part of,
// there currently isn't a way to (easily) get any edges that contain this point but are not in this
// point's edge list.
}
}
}
protected uint mVertexCode = 0;
public uint VertexCode { get { return mVertexCode; } }
// List of edges this point constitutes an upper ending point (CDT)
public List<DTSweepConstraint> Edges { get; private set; }
public bool HasEdges { get { return Edges != null; } }
public TriangulationPoint(double x, double y)
: this(x, y, kVertexCodeDefaultPrecision)
{
}
public TriangulationPoint(double x, double y, double precision)
: base(x,y)
{
mVertexCode = TriangulationPoint.CreateVertexCode(x, y, precision);
}
public override string ToString()
{
return base.ToString() + ":{" + mVertexCode.ToString() + "}";
}
public override int GetHashCode()
{
return (int)mVertexCode;
}
public override bool Equals(object obj)
{
TriangulationPoint p2 = obj as TriangulationPoint;
if (p2 != null)
{
return mVertexCode == p2.VertexCode;
}
else
{
return base.Equals(obj);
}
}
public override void Set(double x, double y)
{
if (x != mX || y != mY)
{
mX = x;
mY = y;
mVertexCode = TriangulationPoint.CreateVertexCode(mX, mY, kVertexCodeDefaultPrecision);
}
}
public static uint CreateVertexCode(double x, double y, double precision)
{
float fx = (float)MathUtil.RoundWithPrecision(x, precision);
float fy = (float)MathUtil.RoundWithPrecision(y, precision);
uint vc = MathUtil.Jenkins32Hash(BitConverter.GetBytes(fx), 0);
vc = MathUtil.Jenkins32Hash(BitConverter.GetBytes(fy), vc);
return vc;
}
public void AddEdge(DTSweepConstraint e)
{
if (Edges == null)
{
Edges = new List<DTSweepConstraint>();
}
Edges.Add(e);
}
public bool HasEdge(TriangulationPoint p)
{
DTSweepConstraint tmp = null;
return GetEdge(p, out tmp);
}
public bool GetEdge(TriangulationPoint p, out DTSweepConstraint edge)
{
edge = null;
if (Edges == null || Edges.Count < 1 || p == null || p.Equals(this))
{
return false;
}
foreach (DTSweepConstraint sc in Edges)
{
if ((sc.P.Equals(this) && sc.Q.Equals(p)) || (sc.P.Equals(p) && sc.Q.Equals(this)))
{
edge = sc;
return true;
}
}
return false;
}
public static Point2D ToPoint2D(TriangulationPoint p)
{
return p as Point2D;
}
}
public class TriangulationPointEnumerator : IEnumerator<TriangulationPoint>
{
protected IList<Point2D> mPoints;
protected int position = -1; // Enumerators are positioned before the first element until the first MoveNext() call.
public TriangulationPointEnumerator(IList<Point2D> points)
{
mPoints = points;
}
public bool MoveNext()
{
position++;
return (position < mPoints.Count);
}
public void Reset()
{
position = -1;
}
void IDisposable.Dispose() { }
Object IEnumerator.Current { get { return Current; } }
public TriangulationPoint Current
{
get
{
if (position < 0 || position >= mPoints.Count)
{
return null;
}
return mPoints[position] as TriangulationPoint;
}
}
}
public class TriangulationPointList : Point2DList
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d759c8fa408c9344ab9f1e8a4de1001d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 26805279e83c13546a2544ddbbfa3a01
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,73 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
namespace Poly2Tri
{
public class PointGenerator
{
static readonly Random RNG = new Random();
public static List<TriangulationPoint> UniformDistribution(int n, double scale)
{
List<TriangulationPoint> points = new List<TriangulationPoint>();
for (int i = 0; i < n; i++)
{
points.Add(new TriangulationPoint(scale * (0.5 - RNG.NextDouble()), scale * (0.5 - RNG.NextDouble())));
}
return points;
}
public static List<TriangulationPoint> UniformGrid(int n, double scale)
{
double x = 0;
double size = scale / n;
double halfScale = 0.5 * scale;
List<TriangulationPoint> points = new List<TriangulationPoint>();
for (int i = 0; i < n + 1; i++)
{
x = halfScale - i * size;
for (int j = 0; j < n + 1; j++)
{
points.Add(new TriangulationPoint(x, halfScale - j * size));
}
}
return points;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 30b228dc7fbacd740a8ee42d783fcd5f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,95 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
namespace Poly2Tri
{
public class PolygonGenerator
{
static readonly Random RNG = new Random();
private static double PI_2 = 2.0 * Math.PI;
public static Polygon RandomCircleSweep(double scale, int vertexCount)
{
PolygonPoint point;
PolygonPoint[] points;
double radius = scale / 4;
points = new PolygonPoint[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
do
{
if (i % 250 == 0)
{
radius += scale / 2 * (0.5 - RNG.NextDouble());
}
else if (i % 50 == 0)
{
radius += scale / 5 * (0.5 - RNG.NextDouble());
}
else
{
radius += 25 * scale / vertexCount * (0.5 - RNG.NextDouble());
}
radius = radius > scale / 2 ? scale / 2 : radius;
radius = radius < scale / 10 ? scale / 10 : radius;
} while (radius < scale / 10 || radius > scale / 2);
point = new PolygonPoint(radius * Math.Cos((PI_2 * i) / vertexCount), radius * Math.Sin((PI_2 * i) / vertexCount));
points[i] = point;
}
return new Polygon(points);
}
public static Polygon RandomCircleSweep2(double scale, int vertexCount)
{
PolygonPoint point;
PolygonPoint[] points;
double radius = scale / 4;
points = new PolygonPoint[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
do
{
radius += scale / 5 * (0.5 - RNG.NextDouble());
radius = radius > scale / 2 ? scale / 2 : radius;
radius = radius < scale / 10 ? scale / 10 : radius;
} while (radius < scale / 10 || radius > scale / 2);
point = new PolygonPoint(radius * Math.Cos((PI_2 * i) / vertexCount), radius * Math.Sin((PI_2 * i) / vertexCount));
points[i] = point;
}
return new Polygon(points);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de075d11f8eef4d4c8f1e7053057e893
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,395 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace Poly2Tri
{
/**
* @author Thomas Åhlén, thahlen@gmail.com
*/
public class TriangulationUtil
{
/// <summary>
/// Requirements:
/// 1. a,b and c form a triangle.
/// 2. a and d is know to be on opposite side of bc
/// <code>
/// a
/// +
/// / \
/// / \
/// b/ \c
/// +-------+
/// / B \
/// / \
/// </code>
/// Facts:
/// d has to be in area B to have a chance to be inside the circle formed by a,b and c
/// d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW
/// This preknowledge gives us a way to optimize the incircle test
/// </summary>
/// <param name="pa">triangle point, opposite d</param>
/// <param name="pb">triangle point</param>
/// <param name="pc">triangle point</param>
/// <param name="pd">point opposite a</param>
/// <returns>true if d is inside circle, false if on circle edge</returns>
public static bool SmartIncircle(Point2D pa, Point2D pb, Point2D pc, Point2D pd)
{
double pdx = pd.X;
double pdy = pd.Y;
double adx = pa.X - pdx;
double ady = pa.Y - pdy;
double bdx = pb.X - pdx;
double bdy = pb.Y - pdy;
double adxbdy = adx * bdy;
double bdxady = bdx * ady;
double oabd = adxbdy - bdxady;
// oabd = orient2d(pa,pb,pd);
if (oabd <= 0)
{
return false;
}
double cdx = pc.X - pdx;
double cdy = pc.Y - pdy;
double cdxady = cdx * ady;
double adxcdy = adx * cdy;
double ocad = cdxady - adxcdy;
// ocad = orient2d(pc,pa,pd);
if (ocad <= 0)
{
return false;
}
double bdxcdy = bdx * cdy;
double cdxbdy = cdx * bdy;
double alift = adx * adx + ady * ady;
double blift = bdx * bdx + bdy * bdy;
double clift = cdx * cdx + cdy * cdy;
double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
return det > 0;
}
public static bool InScanArea(Point2D pa, Point2D pb, Point2D pc, Point2D pd)
{
double pdx = pd.X;
double pdy = pd.Y;
double adx = pa.X - pdx;
double ady = pa.Y - pdy;
double bdx = pb.X - pdx;
double bdy = pb.Y - pdy;
double adxbdy = adx * bdy;
double bdxady = bdx * ady;
double oabd = adxbdy - bdxady;
// oabd = orient2d(pa,pb,pd);
if (oabd <= 0)
{
return false;
}
double cdx = pc.X - pdx;
double cdy = pc.Y - pdy;
double cdxady = cdx * ady;
double adxcdy = adx * cdy;
double ocad = cdxady - adxcdy;
// ocad = orient2d(pc,pa,pd);
if (ocad <= 0)
{
return false;
}
return true;
}
/// Forumla to calculate signed area
/// Positive if CCW
/// Negative if CW
/// 0 if collinear
/// A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
/// = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
public static Orientation Orient2d(Point2D pa, Point2D pb, Point2D pc)
{
double detleft = (pa.X - pc.X) * (pb.Y - pc.Y);
double detright = (pa.Y - pc.Y) * (pb.X - pc.X);
double val = detleft - detright;
if (val > -MathUtil.EPSILON && val < MathUtil.EPSILON)
{
return Orientation.Collinear;
}
else if (val > 0)
{
return Orientation.CCW;
}
return Orientation.CW;
}
///////////////////////////////////////////////////////////////////////////////
// PointRelativeToLine2D
//
// Returns -1 if point is on left of line, 0 if point is on line, and 1 if
// the point is to the right of the line. This assumes a coordinate system
// whereby the y axis goes upward when the x axis goes rightward. This is how
// 3D systems (both right and left-handed) and PostScript works, but is not
// how the Win32 GUI works. If you are using a 'y goes downward' coordinate
// system, simply negate the return value from this function.
//
// Given a point (a,b) and a line from (x1,y1) to (x2,y2), we calculate the
// following equation:
// (y2-y1)*(a-x1)-(x2-x1)*(b-y1) (left)
// If the result is > 0, the point is on 1 --------------> 2
// the right, else left. (right)
//
// For example, with a point at (1,1) and a
// line going from (0,0) to (2,0), we get:
// (0-0)*(1-0)-(2-0)*(1-0)
// which equals:
// -2
// Which indicates the point is (correctly)
// on the left of the directed line.
//
// This function has been checked to a good degree.
//
/////////////////////////////////////////////////////////////////////////////
//public static double PointRelativeToLine2D(Point2D ptPoint, Point2D ptLineBegin, Point2D ptLineEnd)
//{
// return (ptLineEnd.Y - ptLineBegin.Y) * (ptPoint.X - ptLineBegin.X) - (ptLineEnd.X - ptLineBegin.X) * (ptPoint.Y - ptLineBegin.Y);
//}
///////////////////////////////////////////////////////////////////////////
// PointInBoundingBox - checks if a point is completely inside an
// axis-aligned bounding box defined by xmin, xmax, ymin, and ymax.
// Note that the point must be fully inside for this method to return
// true - it cannot lie on the border of the bounding box.
///////////////////////////////////////////////////////////////////////////
public static bool PointInBoundingBox(double xmin, double xmax, double ymin, double ymax, Point2D p)
{
return (p.X > xmin && p.X < xmax && p.Y > ymin && p.Y < ymax);
}
public static bool PointOnLineSegment2D(Point2D lineStart, Point2D lineEnd, Point2D p, double epsilon)
{
return TriangulationUtil.PointOnLineSegment2D(lineStart.X, lineStart.Y, lineEnd.X, lineEnd.Y, p.X, p.Y, epsilon);
}
public static bool PointOnLineSegment2D(double x1, double y1, double x2, double y2, double x, double y, double epsilon)
{
// First checking if (x, z) is in the range of the line segment's end points.
if (MathUtil.IsValueBetween(x, x1, x2, epsilon) && MathUtil.IsValueBetween(y, y1, y2, epsilon))
{
if (MathUtil.AreValuesEqual(x2 - x1, 0.0f, epsilon))
{
// Vertical line.
return true;
}
double slope = (y2 - y1) / (x2 - x1);
double yIntercept = -(slope * x1) + y1;
// Checking if (x, y) is on the line passing through the end points.
double t = y - ((slope * x) + yIntercept);
return MathUtil.AreValuesEqual(t, 0.0f, epsilon);
}
return false;
}
public static bool RectsIntersect(Rect2D r1, Rect2D r2)
{
return (r1.Right > r2.Left) &&
(r1.Left < r2.Right) &&
(r1.Bottom > r2.Top) &&
(r1.Top < r2.Bottom);
}
/// <summary>
/// This method detects if two line segments (or lines) intersect,
/// and, if so, the point of intersection. Use the <paramref name="firstIsSegment"/> and
/// <paramref name="secondIsSegment"/> parameters to set whether the intersection point
/// must be on the first and second line segments. Setting these
/// both to true means you are doing a line-segment to line-segment
/// intersection. Setting one of them to true means you are doing a
/// line to line-segment intersection test, and so on.
/// Note: If two line segments are coincident, then
/// no intersection is detected (there are actually
/// infinite intersection points).
/// </summary>
/// <param name="ptStart0">The first point of the first line segment.</param>
/// <param name="ptEnd0">The second point of the first line segment.</param>
/// <param name="ptStart1">The first point of the second line segment.</param>
/// <param name="ptEnd1">The second point of the second line segment.</param>
/// <param name="firstIsSegment">Set this to true to require that the
/// intersection point be on the first line segment.</param>
/// <param name="secondIsSegment">Set this to true to require that the
/// intersection point be on the second line segment.</param>
/// <param name="coincidentEndPointCollisions">Set this to true to enable collisions if the line segments share
/// an endpoint</param>
/// <param name="pIntersectionPt">This is set to the intersection
/// point if an intersection is detected.</param>
/// <returns>True if an intersection is detected, false otherwise.</returns>
public static bool LinesIntersect2D( Point2D ptStart0, Point2D ptEnd0,
Point2D ptStart1, Point2D ptEnd1,
bool firstIsSegment, bool secondIsSegment, bool coincidentEndPointCollisions,
ref Point2D pIntersectionPt,
double epsilon)
{
double d = (ptEnd0.X - ptStart0.X) * (ptStart1.Y - ptEnd1.Y) - (ptStart1.X - ptEnd1.X) * (ptEnd0.Y - ptStart0.Y);
if (Math.Abs(d) < epsilon)
{
//The lines are parallel.
return false;
}
double d0 = (ptStart1.X - ptStart0.X) * (ptStart1.Y - ptEnd1.Y) - (ptStart1.X - ptEnd1.X) * (ptStart1.Y - ptStart0.Y);
double d1 = (ptEnd0.X - ptStart0.X) * (ptStart1.Y - ptStart0.Y) - (ptStart1.X - ptStart0.X) * (ptEnd0.Y - ptStart0.Y);
double kOneOverD = 1 / d;
double t0 = d0 * kOneOverD;
double t1 = d1 * kOneOverD;
if ((!firstIsSegment || ((t0 >= 0.0) && (t0 <= 1.0))) &&
(!secondIsSegment || ((t1 >= 0.0) && (t1 <= 1.0))) &&
(coincidentEndPointCollisions || (!MathUtil.AreValuesEqual(0.0, t0, epsilon) && !MathUtil.AreValuesEqual(0.0, t1, epsilon))))
{
if (pIntersectionPt != null)
{
pIntersectionPt.X = ptStart0.X + t0 * (ptEnd0.X - ptStart0.X);
pIntersectionPt.Y = ptStart0.Y + t0 * (ptEnd0.Y - ptStart0.Y);
}
return true;
}
return false;
}
public static bool LinesIntersect2D( Point2D ptStart0, Point2D ptEnd0,
Point2D ptStart1, Point2D ptEnd1,
ref Point2D pIntersectionPt,
double epsilon)
{
return TriangulationUtil.LinesIntersect2D(ptStart0, ptEnd0, ptStart1, ptEnd1, true, true, false, ref pIntersectionPt, epsilon);
}
///////////////////////////////////////////////////////////////////////////
// RaysIntersect2D
//
// Given two lines defined by (sorry about the lame notation):
// x0 = x00 + vector_x0*s;
// y0 = y00 + vector_y0*s;
//
// x1 = x10 + vector_x1*t;
// y1 = y10 + vector_y1*t;
//
// This function determines the intersection between them, if there is any.
//
// This function assumes the lines to have no endpoints and will intersect
// them anywhere in 2D space.
//
// This algorithm taken from "Realtime-Rendering" section 10.12.
//
// This function has been checked to a good degree.
//
///////////////////////////////////////////////////////////////////////////
public static double LI2DDotProduct(Point2D v0, Point2D v1)
{
return ((v0.X * v1.X) + (v0.Y * v1.Y));
}
public static bool RaysIntersect2D( Point2D ptRayOrigin0, Point2D ptRayVector0,
Point2D ptRayOrigin1, Point2D ptRayVector1,
ref Point2D ptIntersection)
{
double kEpsilon = 0.01;
if (ptIntersection != null)
{
//If the user wants an actual intersection result...
//This is a vector from pLineOrigin0 to ptLineOrigin1.
Point2D ptTemp1 = new Point2D(ptRayOrigin1.X - ptRayOrigin0.X, ptRayOrigin1.Y - ptRayOrigin0.Y);
//This is a vector perpendicular to ptVector1.
Point2D ptTemp2 = new Point2D(-ptRayVector1.Y, ptRayVector1.X);
double fDot1 = TriangulationUtil.LI2DDotProduct(ptRayVector0, ptTemp2);
if (Math.Abs(fDot1) < kEpsilon)
{
return false; //The lines are essentially parallel.
}
double fDot2 = TriangulationUtil.LI2DDotProduct(ptTemp1, ptTemp2);
double s = fDot2 / fDot1;
ptIntersection.X = ptRayOrigin0.X + ptRayVector0.X * s;
ptIntersection.Y = ptRayOrigin0.Y + ptRayVector0.Y * s;
return true;
}
//Else the user just wants to know if there is an intersection...
//In this case we need only compare the slopes of the lines.
double delta = ptRayVector1.X - ptRayVector0.X;
if (Math.Abs(delta) > kEpsilon)
{
delta = ptRayVector1.Y - ptRayVector0.Y;
if (Math.Abs(delta) > kEpsilon)
{
return true; //The lines are not parallel.
}
}
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9973d31339415d74185f362976b190e2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1f2be784c64a930428658203464f8bc6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
namespace Poly2Tri
{
public struct FixedArray3<T> : IEnumerable<T> where T : class
{
public T _0, _1, _2;
public T this[int index]
{
get
{
switch (index)
{
case 0:
return _0;
case 1:
return _1;
case 2:
return _2;
default:
throw new IndexOutOfRangeException();
}
}
set
{
switch (index)
{
case 0:
_0 = value;
break;
case 1:
_1 = value;
break;
case 2:
_2 = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
}
public bool Contains(T value)
{
for (int i = 0; i < 3; ++i)
{
if (this[i] != null && this[i].Equals(value))
{
return true;
}
}
return false;
}
public int IndexOf(T value)
{
for (int i = 0; i < 3; ++i)
{
if (this[i] != null && this[i].Equals(value))
{
return i;
}
}
return -1;
}
public void Clear()
{
_0 = _1 = _2 = null;
}
public void Clear(T value)
{
for (int i = 0; i < 3; ++i)
{
if (this[i] != null && this[i].Equals(value))
{
this[i] = null;
}
}
}
private IEnumerable<T> Enumerate()
{
for (int i = 0; i < 3; ++i)
{
yield return this[i];
}
}
public IEnumerator<T> GetEnumerator() { return Enumerate().GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d981e23ca4f5ac84e8ca45f87420f90a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
namespace Poly2Tri
{
public struct FixedBitArray3 : IEnumerable<bool>
{
public bool _0, _1, _2;
public bool this[int index]
{
get
{
switch (index)
{
case 0:
return _0;
case 1:
return _1;
case 2:
return _2;
default:
throw new IndexOutOfRangeException();
}
}
set
{
switch (index)
{
case 0:
_0 = value;
break;
case 1:
_1 = value;
break;
case 2:
_2 = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
}
public bool Contains(bool value)
{
for (int i = 0; i < 3; ++i)
{
if (this[i] == value)
{
return true;
}
}
return false;
}
public int IndexOf(bool value)
{
for (int i = 0; i < 3; ++i)
{
if (this[i] == value)
{
return i;
}
}
return -1;
}
public void Clear()
{
_0 = _1 = _2 = false;
}
public void Clear(bool value)
{
for (int i = 0; i < 3; ++i)
{
if (this[i] == value)
{
this[i] = false;
}
}
}
private IEnumerable<bool> Enumerate()
{
for (int i = 0; i < 3; ++i)
{
yield return this[i];
}
}
public IEnumerator<bool> GetEnumerator() { return Enumerate().GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dd393331db7c67b4583d7563f1ecd0ad
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Poly2Tri
{
public class MathUtil
{
public static double EPSILON = 1e-12;
public static bool AreValuesEqual(double val1, double val2)
{
return AreValuesEqual(val1, val2, EPSILON);
}
public static bool AreValuesEqual(double val1, double val2, double tolerance)
{
if (val1 >= (val2 - tolerance) && val1 <= (val2 + tolerance))
{
return true;
}
return false;
}
public static bool IsValueBetween(double val, double min, double max, double tolerance)
{
if (min > max)
{
double tmp = min;
min = max;
max = tmp;
}
if ((val + tolerance) >= min && (val - tolerance) <= max)
{
return true;
}
return false;
}
public static double RoundWithPrecision(double f, double precision)
{
if (precision < 0.0)
{
return f;
}
double mul = Math.Pow(10.0, precision);
double fTemp = Math.Floor(f * mul) / mul;
return fTemp;
}
public static double Clamp(double a, double low, double high)
{
return Math.Max(low, Math.Min(a, high));
}
public static void Swap<T>(ref T a, ref T b)
{
T tmp = a;
a = b;
b = tmp;
}
public static uint Jenkins32Hash(byte[] data, uint nInitialValue)
{
foreach (byte b in data)
{
nInitialValue += (uint)b;
nInitialValue += (nInitialValue << 10);
nInitialValue += (nInitialValue >> 6);
}
nInitialValue += (nInitialValue << 3);
nInitialValue ^= (nInitialValue >> 11);
nInitialValue += (nInitialValue << 15);
return nInitialValue;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8d6dd55f740849b41994d1d937652e56
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,262 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
namespace Poly2Tri
{
public class Point2D : IComparable<Point2D>
{
protected double mX = 0.0;
public virtual double X { get { return mX; } set { mX = value; } }
protected double mY = 0.0;
public virtual double Y { get { return mY; } set { mY = value; } }
public float Xf { get { return (float)X; } }
public float Yf { get { return (float)Y; } }
public Point2D()
{
mX = 0.0;
mY = 0.0;
}
public Point2D(double x, double y)
{
mX = x;
mY = y;
}
public Point2D(Point2D p)
{
mX = p.X;
mY = p.Y;
}
public override string ToString()
{
return "[" + X.ToString() + "," + Y.ToString() + "]";
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(Object obj)
{
Point2D p = obj as Point2D;
if (p != null)
{
return Equals(p);
}
return base.Equals(obj);
}
public bool Equals(Point2D p)
{
return Equals(p, 0.0);
}
public bool Equals(Point2D p, double epsilon)
{
if ((object)p == null || !MathUtil.AreValuesEqual(X, p.X, epsilon) || !MathUtil.AreValuesEqual(Y, p.Y, epsilon))
{
return false;
}
return true;
}
public int CompareTo(Point2D other)
{
if (Y < other.Y)
{
return -1;
}
else if (Y > other.Y)
{
return 1;
}
else
{
if (X < other.X)
{
return -1;
}
else if (X > other.X)
{
return 1;
}
}
return 0;
}
public virtual void Set(double x, double y) { X = x; Y = y; }
public virtual void Set(Point2D p) { X = p.X; Y = p.Y; }
public void Add(Point2D p) { X += p.X; Y += p.Y; }
public void Add(double scalar) { X += scalar; Y += scalar; }
public void Subtract(Point2D p) { X -= p.X; Y -= p.Y; }
public void Subtract(double scalar) { X -= scalar; Y -= scalar; }
public void Multiply(Point2D p) { X *= p.X; Y *= p.Y; }
public void Multiply(double scalar) { X *= scalar; Y *= scalar; }
public void Divide(Point2D p) { X /= p.X; Y /= p.Y; }
public void Divide(double scalar) { X /= scalar; Y /= scalar; }
public void Negate() { X = -X; Y = -Y; }
public double Magnitude() { return Math.Sqrt((X * X) + (Y * Y)); }
public double MagnitudeSquared() { return (X * X) + (Y * Y); }
public double MagnitudeReciprocal() { return 1.0 / Magnitude(); }
public void Normalize() { Multiply(MagnitudeReciprocal()); }
public double Dot(Point2D p) { return (X * p.X) + (Y * p.Y); }
public double Cross(Point2D p) { return (X * p.Y) - (Y * p.X); }
public void Clamp(Point2D low, Point2D high) { X = Math.Max(low.X, Math.Min(X, high.X)); Y = Math.Max(low.Y, Math.Min(Y, high.Y)); }
public void Abs() { X = Math.Abs(X); Y = Math.Abs(Y); }
public void Reciprocal() { if (X != 0.0 && Y != 0.0) { X = 1.0 / X; Y = 1.0 / Y; } }
public void Translate(Point2D vector) { Add(vector); }
public void Translate(double x, double y) { X += x; Y += y; }
public void Scale(Point2D vector) { Multiply(vector); }
public void Scale(double scalar) { Multiply(scalar); }
public void Scale(double x, double y) { X *= x; Y *= y; }
public void Rotate(double radians)
{
double cosr = Math.Cos(radians);
double sinr = Math.Sin(radians);
double xold = X;
double yold = Y;
X = (xold * cosr) - (yold * sinr);
Y = (xold * sinr) + (yold * cosr);
}
public void RotateDegrees(double degrees)
{
double radians = degrees * Math.PI / 180.0;
Rotate(radians);
}
public static double Dot(Point2D lhs, Point2D rhs) { return (lhs.X * rhs.X) + (lhs.Y * rhs.Y); }
public static double Cross(Point2D lhs, Point2D rhs) { return (lhs.X * rhs.Y) - (lhs.Y * rhs.X); }
public static Point2D Clamp(Point2D a, Point2D low, Point2D high) { Point2D p = new Point2D(a); p.Clamp(low, high); return p; }
public static Point2D Min(Point2D a, Point2D b) { Point2D p = new Point2D(); p.X = Math.Min(a.X, b.X); p.Y = Math.Min(a.Y, b.Y); return p; }
public static Point2D Max(Point2D a, Point2D b) { Point2D p = new Point2D(); p.X = Math.Max(a.X, b.X); p.Y = Math.Max(a.Y, b.Y); return p; }
public static Point2D Abs(Point2D a) { Point2D p = new Point2D(Math.Abs(a.X), Math.Abs(a.Y)); return p; }
public static Point2D Reciprocal(Point2D a) { Point2D p = new Point2D(1.0 / a.X, 1.0 / a.Y); return p; }
// returns a scaled perpendicular vector. Which direction it goes depends on the order in which the arguments are passed
public static Point2D Perpendicular(Point2D lhs, double scalar) { Point2D p = new Point2D(lhs.Y * scalar, lhs.X * -scalar); return p; }
public static Point2D Perpendicular(double scalar, Point2D rhs) { Point2D p = new Point2D(-scalar * rhs.Y, scalar * rhs.X); return p; }
//
// operator overloading
//
// Binary Operators
// Note that in C#, when a binary operator is overloaded, its corresponding compound assignment operator is also automatically
// overloaded. So, for example, overloading operator + implicitly overloads += as well
public static Point2D operator +(Point2D lhs, Point2D rhs) { Point2D result = new Point2D(lhs); result.Add(rhs); return result; }
public static Point2D operator +(Point2D lhs, double scalar) { Point2D result = new Point2D(lhs); result.Add(scalar); return result; }
public static Point2D operator -(Point2D lhs, Point2D rhs) { Point2D result = new Point2D(lhs); result.Subtract(rhs); return result; }
public static Point2D operator -(Point2D lhs, double scalar) { Point2D result = new Point2D(lhs); result.Subtract(scalar); return result; }
public static Point2D operator *(Point2D lhs, Point2D rhs) { Point2D result = new Point2D(lhs); result.Multiply(rhs); return result; }
public static Point2D operator *(Point2D lhs, double scalar) { Point2D result = new Point2D(lhs); result.Multiply(scalar); return result; }
public static Point2D operator *(double scalar, Point2D lhs) { Point2D result = new Point2D(lhs); result.Multiply(scalar); return result; }
public static Point2D operator /(Point2D lhs, Point2D rhs) { Point2D result = new Point2D(lhs); result.Divide(rhs); return result; }
public static Point2D operator /(Point2D lhs, double scalar) { Point2D result = new Point2D(lhs); result.Divide(scalar); return result; }
// Unary Operators
public static Point2D operator -(Point2D p) { Point2D tmp = new Point2D(p); tmp.Negate(); return tmp; }
// Relational Operators
//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; } }
//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; } }
public static bool operator <(Point2D lhs, Point2D rhs) { return (lhs.CompareTo(rhs) == -1) ? true : false; }
public static bool operator >(Point2D lhs, Point2D rhs) { return (lhs.CompareTo(rhs) == 1) ? true : false; }
public static bool operator <=(Point2D lhs, Point2D rhs) { return (lhs.CompareTo(rhs) <= 0) ? true : false; }
public static bool operator >=(Point2D lhs, Point2D rhs) { return (lhs.CompareTo(rhs) >= 0) ? true : false; }
}
public class Point2DEnumerator : IEnumerator<Point2D>
{
protected IList<Point2D> mPoints;
protected int position = -1; // Enumerators are positioned before the first element until the first MoveNext() call.
public Point2DEnumerator(IList<Point2D> points)
{
mPoints = points;
}
public bool MoveNext()
{
position++;
return (position < mPoints.Count);
}
public void Reset()
{
position = -1;
}
void IDisposable.Dispose() { }
Object IEnumerator.Current { get { return Current; } }
public Point2D Current
{
get
{
if (position < 0 || position >= mPoints.Count)
{
return null;
}
return mPoints[position];
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6906e61511580494d946ed1a07dd0e82
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dd6f3a734edccfb4d912e7d1322c5d83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,321 @@
/* Poly2Tri
* Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Poly2Tri nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
namespace Poly2Tri
{
public class Rect2D
{
private double mMinX; // left
private double mMaxX; // right
private double mMinY; // bottom // top
private double mMaxY; // top // bottom
public double MinX { get { return mMinX; } set { mMinX = value; } }
public double MaxX { get { return mMaxX; } set { mMaxX = value; } }
public double MinY { get { return mMinY; } set { mMinY = value; } }
public double MaxY { get { return mMaxY; } set { mMaxY = value; } }
public double Left { get { return mMinX; } set { mMinX = value; } }
public double Right { get { return mMaxX; } set { mMaxX = value; } }
public double Top { get { return mMaxY; } set { mMaxY = value; } }
public double Bottom { get { return mMinY; } set { mMinY = value; } }
public double Width { get { return (Right - Left); } }
public double Height { get { return (Top - Bottom); } }
public bool Empty { get { return (Left == Right) || (Top == Bottom); } }
public Rect2D()
{
Clear();
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(Object obj)
{
Rect2D r = obj as Rect2D;
if( r != null)
{
return Equals(r);
}
return base.Equals(obj);
}
public bool Equals(Rect2D r)
{
return Equals(r, MathUtil.EPSILON);
}
public bool Equals(Rect2D r, double epsilon)
{
if (!MathUtil.AreValuesEqual(MinX, r.MinX, epsilon))
{
return false;
}
if (!MathUtil.AreValuesEqual(MaxX, r.MaxX))
{
return false;
}
if (!MathUtil.AreValuesEqual(MinY, r.MinY, epsilon))
{
return false;
}
if (!MathUtil.AreValuesEqual(MaxY, r.MaxY, epsilon))
{
return false;
}
return true;
}
public void Clear()
{
MinX = Double.MaxValue;
MaxX = Double.MinValue;
MinY = Double.MaxValue;
MaxY = Double.MinValue;
}
public void Set(double xmin, double xmax, double ymin, double ymax)
{
MinX = xmin;
MaxX = xmax;
MinY = ymin;
MaxY = ymax;
Normalize();
}
public void Set(Rect2D b)
{
MinX = b.MinX;
MaxX = b.MaxX;
MinY = b.MinY;
MaxY = b.MaxY;
}
public void SetSize(double w, double h)
{
Right = Left + w;
Top = Bottom + h;
}
/// <summary>
/// Returns whether the coordinate is inside the bounding box. Note that this will return
/// false if the point is ON the edge of the bounding box. If you want to test for whether
/// the point is inside OR on the rect, use ContainsInclusive
/// </summary>
public bool Contains(double x, double y)
{
return (x > Left) && (y > Bottom) && (x < Right) && (y < Top);
}
public bool Contains(Point2D p) { return Contains(p.X, p.Y); }
public bool Contains(Rect2D r)
{
return (Left < r.Left) && (Right > r.Right) && (Top < r.Top) && (Bottom > r.Bottom);
}
/// <summary>
/// Returns whether the coordinate is inside the bounding box. Note that this will return
/// false if the point is ON the edge of the bounding box. If you want to test for whether
/// the point is inside OR on the rect, use ContainsInclusive
/// </summary>
public bool ContainsInclusive(double x, double y)
{
return (x >= Left) && (y >= Top) && (x <= Right) && (y <= Bottom);
}
public bool ContainsInclusive(double x, double y, double epsilon)
{
return ((x + epsilon) >= Left) && ((y + epsilon) >= Top) && ((x - epsilon) <= Right) && ((y - epsilon) <= Bottom);
}
public bool ContainsInclusive(Point2D p) { return ContainsInclusive(p.X, p.Y); }
public bool ContainsInclusive(Point2D p, double epsilon) { return ContainsInclusive(p.X, p.Y, epsilon); }
public bool ContainsInclusive(Rect2D r)
{
return (Left <= r.Left) && (Right >= r.Right) && (Top <= r.Top) && (Bottom >= r.Bottom);
}
public bool ContainsInclusive(Rect2D r, double epsilon)
{
return ((Left - epsilon) <= r.Left) && ((Right + epsilon) >= r.Right) && ((Top - epsilon) <= r.Top) && ((Bottom + epsilon) >= r.Bottom);
}
public bool Intersects(Rect2D r)
{
return (Right > r.Left) &&
(Left < r.Right) &&
(Bottom < r.Top) &&
(Top > r.Bottom);
}
public Point2D GetCenter()
{
Point2D p = new Point2D((Left + Right ) / 2, (Bottom + Top) / 2);
return p;
}
public bool IsNormalized()
{
return (Right >= Left) && (Bottom <= Top);
}
public void Normalize()
{
if (Left > Right)
{
MathUtil.Swap<double>(ref mMinX, ref mMaxX);
}
if (Bottom < Top)
{
MathUtil.Swap<double>(ref mMinY, ref mMaxY);
}
}
public void AddPoint(Point2D p)
{
MinX = Math.Min(MinX, p.X);
MaxX = Math.Max(MaxX, p.X);
MinY = Math.Min(MinY, p.Y);
MaxY = Math.Max(MaxY, p.Y);
}
public void Inflate(double w, double h)
{
Left -= w;
Top += h;
Right += w;
Bottom -= h;
}
public void Inflate(double left, double top, double right, double bottom)
{
Left -= left;
Top += top;
Right += right;
Bottom -= bottom;
}
public void Offset(double w, double h)
{
Left += w;
Top += h;
Right += w;
Bottom += h;
}
public void SetPosition(double x, double y)
{
double w = Right - Left;
double h = Bottom - Top;
Left = x;
Bottom = y;
Right = x + w;
Top = y + h;
}
/// Intersection
///
/// Sets the rectangle to the intersection of two rectangles.
/// Returns true if there is any intersection between the two rectangles.
/// If there is no intersection, the rectangle is set to 0, 0, 0, 0.
/// Either of the input rectangles may be the same as destination rectangle.
///
public bool Intersection(Rect2D r1, Rect2D r2)
{
if (!TriangulationUtil.RectsIntersect(r1, r2))
{
Left = Right = Top = Bottom = 0.0;
return false;
}
Left = (r1.Left > r2.Left) ? r1.Left : r2.Left;
Top = (r1.Top < r2.Top ) ? r1.Top : r2.Top;
Right = (r1.Right < r2.Right) ? r1.Right : r2.Right;
Bottom = (r1.Bottom > r2.Bottom) ? r1.Bottom : r2.Bottom;
return true;
}
/// Union
///
/// Sets the rectangle to the union of two rectangles r1 and r2.
/// If either rect is empty, it is ignored. If both are empty, the rectangle
/// is set to r1.
/// Either of the input rectangle references may refer to the destination rectangle.
///
public void Union(Rect2D r1, Rect2D r2)
{
if ((r2.Right == r2.Left) || (r2.Bottom == r2.Top))
{
Set(r1);
}
else if ((r1.Right == r1.Left) || (r1.Bottom == r1.Top))
{
Set(r2);
}
else
{
Left = (r1.Left < r2.Left) ? r1.Left : r2.Left;
Top = (r1.Top > r2.Top) ? r1.Top : r2.Top;
Right = (r1.Right > r2.Right) ? r1.Right : r2.Right;
Bottom = (r1.Bottom < r2.Bottom) ? r1.Bottom : r2.Bottom;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d90c83ef75550a34b8be1b39c495defc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: