Adding initial files
This commit is contained in:
253
axios/Common/Decomposition/BayazitDecomposer.cs
Normal file
253
axios/Common/Decomposition/BayazitDecomposer.cs
Normal file
@@ -0,0 +1,253 @@
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Common.PolygonManipulation;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition
|
||||
{
|
||||
//From phed rev 36
|
||||
|
||||
/// <summary>
|
||||
/// Convex decomposition algorithm created by Mark Bayazit (http://mnbayazit.com/)
|
||||
/// For more information about this algorithm, see http://mnbayazit.com/406/bayazit
|
||||
/// </summary>
|
||||
public static class BayazitDecomposer
|
||||
{
|
||||
private static Vector2 At(int i, Vertices vertices)
|
||||
{
|
||||
int s = vertices.Count;
|
||||
return vertices[i < 0 ? s - (-i % s) : i % s];
|
||||
}
|
||||
|
||||
private static Vertices Copy(int i, int j, Vertices vertices)
|
||||
{
|
||||
Vertices p = new Vertices();
|
||||
while (j < i) j += vertices.Count;
|
||||
//p.reserve(j - i + 1);
|
||||
for (; i <= j; ++i)
|
||||
{
|
||||
p.Add(At(i, vertices));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decompose the polygon into several smaller non-concave polygon.
|
||||
/// If the polygon is already convex, it will return the original polygon, unless it is over Settings.MaxPolygonVertices.
|
||||
/// Precondition: Counter Clockwise polygon
|
||||
/// </summary>
|
||||
/// <param name="vertices"></param>
|
||||
/// <returns></returns>
|
||||
public static List<Vertices> ConvexPartition(Vertices vertices)
|
||||
{
|
||||
//We force it to CCW as it is a precondition in this algorithm.
|
||||
vertices.ForceCounterClockWise();
|
||||
|
||||
List<Vertices> list = new List<Vertices>();
|
||||
float d, lowerDist, upperDist;
|
||||
Vector2 p;
|
||||
Vector2 lowerInt = new Vector2();
|
||||
Vector2 upperInt = new Vector2(); // intersection points
|
||||
int lowerIndex = 0, upperIndex = 0;
|
||||
Vertices lowerPoly, upperPoly;
|
||||
|
||||
for (int i = 0; i < vertices.Count; ++i)
|
||||
{
|
||||
if (Reflex(i, vertices))
|
||||
{
|
||||
lowerDist = upperDist = float.MaxValue; // std::numeric_limits<qreal>::max();
|
||||
for (int j = 0; j < vertices.Count; ++j)
|
||||
{
|
||||
// if line intersects with an edge
|
||||
if (Left(At(i - 1, vertices), At(i, vertices), At(j, vertices)) &&
|
||||
RightOn(At(i - 1, vertices), At(i, vertices), At(j - 1, vertices)))
|
||||
{
|
||||
// find the point of intersection
|
||||
p = LineTools.LineIntersect(At(i - 1, vertices), At(i, vertices), At(j, vertices),
|
||||
At(j - 1, vertices));
|
||||
if (Right(At(i + 1, vertices), At(i, vertices), p))
|
||||
{
|
||||
// make sure it's inside the poly
|
||||
d = SquareDist(At(i, vertices), p);
|
||||
if (d < lowerDist)
|
||||
{
|
||||
// keep only the closest intersection
|
||||
lowerDist = d;
|
||||
lowerInt = p;
|
||||
lowerIndex = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Left(At(i + 1, vertices), At(i, vertices), At(j + 1, vertices)) &&
|
||||
RightOn(At(i + 1, vertices), At(i, vertices), At(j, vertices)))
|
||||
{
|
||||
p = LineTools.LineIntersect(At(i + 1, vertices), At(i, vertices), At(j, vertices),
|
||||
At(j + 1, vertices));
|
||||
if (Left(At(i - 1, vertices), At(i, vertices), p))
|
||||
{
|
||||
d = SquareDist(At(i, vertices), p);
|
||||
if (d < upperDist)
|
||||
{
|
||||
upperDist = d;
|
||||
upperIndex = j;
|
||||
upperInt = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if there are no vertices to connect to, choose a point in the middle
|
||||
if (lowerIndex == (upperIndex + 1) % vertices.Count)
|
||||
{
|
||||
Vector2 sp = ((lowerInt + upperInt) / 2);
|
||||
|
||||
lowerPoly = Copy(i, upperIndex, vertices);
|
||||
lowerPoly.Add(sp);
|
||||
upperPoly = Copy(lowerIndex, i, vertices);
|
||||
upperPoly.Add(sp);
|
||||
}
|
||||
else
|
||||
{
|
||||
double highestScore = 0, bestIndex = lowerIndex;
|
||||
while (upperIndex < lowerIndex) upperIndex += vertices.Count;
|
||||
for (int j = lowerIndex; j <= upperIndex; ++j)
|
||||
{
|
||||
if (CanSee(i, j, vertices))
|
||||
{
|
||||
double score = 1 / (SquareDist(At(i, vertices), At(j, vertices)) + 1);
|
||||
if (Reflex(j, vertices))
|
||||
{
|
||||
if (RightOn(At(j - 1, vertices), At(j, vertices), At(i, vertices)) &&
|
||||
LeftOn(At(j + 1, vertices), At(j, vertices), At(i, vertices)))
|
||||
{
|
||||
score += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
score += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
score += 1;
|
||||
}
|
||||
if (score > highestScore)
|
||||
{
|
||||
bestIndex = j;
|
||||
highestScore = score;
|
||||
}
|
||||
}
|
||||
}
|
||||
lowerPoly = Copy(i, (int)bestIndex, vertices);
|
||||
upperPoly = Copy((int)bestIndex, i, vertices);
|
||||
}
|
||||
list.AddRange(ConvexPartition(lowerPoly));
|
||||
list.AddRange(ConvexPartition(upperPoly));
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
// polygon is already convex
|
||||
if (vertices.Count > Settings.MaxPolygonVertices)
|
||||
{
|
||||
lowerPoly = Copy(0, vertices.Count / 2, vertices);
|
||||
upperPoly = Copy(vertices.Count / 2, 0, vertices);
|
||||
list.AddRange(ConvexPartition(lowerPoly));
|
||||
list.AddRange(ConvexPartition(upperPoly));
|
||||
}
|
||||
else
|
||||
list.Add(vertices);
|
||||
|
||||
//The polygons are not guaranteed to be without collinear points. We remove
|
||||
//them to be sure.
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
list[i] = SimplifyTools.CollinearSimplify(list[i], 0);
|
||||
}
|
||||
|
||||
//Remove empty vertice collections
|
||||
for (int i = list.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (list[i].Count == 0)
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static bool CanSee(int i, int j, Vertices vertices)
|
||||
{
|
||||
if (Reflex(i, vertices))
|
||||
{
|
||||
if (LeftOn(At(i, vertices), At(i - 1, vertices), At(j, vertices)) &&
|
||||
RightOn(At(i, vertices), At(i + 1, vertices), At(j, vertices))) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RightOn(At(i, vertices), At(i + 1, vertices), At(j, vertices)) ||
|
||||
LeftOn(At(i, vertices), At(i - 1, vertices), At(j, vertices))) return false;
|
||||
}
|
||||
if (Reflex(j, vertices))
|
||||
{
|
||||
if (LeftOn(At(j, vertices), At(j - 1, vertices), At(i, vertices)) &&
|
||||
RightOn(At(j, vertices), At(j + 1, vertices), At(i, vertices))) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RightOn(At(j, vertices), At(j + 1, vertices), At(i, vertices)) ||
|
||||
LeftOn(At(j, vertices), At(j - 1, vertices), At(i, vertices))) return false;
|
||||
}
|
||||
for (int k = 0; k < vertices.Count; ++k)
|
||||
{
|
||||
if ((k + 1) % vertices.Count == i || k == i || (k + 1) % vertices.Count == j || k == j)
|
||||
{
|
||||
continue; // ignore incident edges
|
||||
}
|
||||
Vector2 intersectionPoint;
|
||||
if (LineTools.LineIntersect(At(i, vertices), At(j, vertices), At(k, vertices), At(k + 1, vertices), out intersectionPoint))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// precondition: ccw
|
||||
private static bool Reflex(int i, Vertices vertices)
|
||||
{
|
||||
return Right(i, vertices);
|
||||
}
|
||||
|
||||
private static bool Right(int i, Vertices vertices)
|
||||
{
|
||||
return Right(At(i - 1, vertices), At(i, vertices), At(i + 1, vertices));
|
||||
}
|
||||
|
||||
private static bool Left(Vector2 a, Vector2 b, Vector2 c)
|
||||
{
|
||||
return MathUtils.Area(ref a, ref b, ref c) > 0;
|
||||
}
|
||||
|
||||
private static bool LeftOn(Vector2 a, Vector2 b, Vector2 c)
|
||||
{
|
||||
return MathUtils.Area(ref a, ref b, ref c) >= 0;
|
||||
}
|
||||
|
||||
private static bool Right(Vector2 a, Vector2 b, Vector2 c)
|
||||
{
|
||||
return MathUtils.Area(ref a, ref b, ref c) < 0;
|
||||
}
|
||||
|
||||
private static bool RightOn(Vector2 a, Vector2 b, Vector2 c)
|
||||
{
|
||||
return MathUtils.Area(ref a, ref b, ref c) <= 0;
|
||||
}
|
||||
|
||||
private static float SquareDist(Vector2 a, Vector2 b)
|
||||
{
|
||||
float dx = b.X - a.X;
|
||||
float dy = b.Y - a.Y;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
}
|
||||
}
|
420
axios/Common/Decomposition/CDT/Delaunay/DelaunayTriangle.cs
Normal file
420
axios/Common/Decomposition/CDT/Delaunay/DelaunayTriangle.cs
Normal file
@@ -0,0 +1,420 @@
|
||||
/* 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.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Poly2Tri.Triangulation.Delaunay.Sweep;
|
||||
using Poly2Tri.Triangulation.Util;
|
||||
|
||||
namespace Poly2Tri.Triangulation.Delaunay
|
||||
{
|
||||
public class DelaunayTriangle
|
||||
{
|
||||
/** Neighbor pointers */
|
||||
|
||||
/** Flags to determine if an edge is a Delauney edge */
|
||||
public FixedBitArray3 EdgeIsConstrained;
|
||||
|
||||
/** Flags to determine if an edge is a Constrained edge */
|
||||
public FixedBitArray3 EdgeIsDelaunay;
|
||||
public FixedArray3<DelaunayTriangle> Neighbors;
|
||||
|
||||
/** Has this triangle been marked as an interior triangle? */
|
||||
|
||||
public FixedArray3<TriangulationPoint> Points;
|
||||
|
||||
public DelaunayTriangle(TriangulationPoint p1, TriangulationPoint p2, TriangulationPoint p3)
|
||||
{
|
||||
Points[0] = p1;
|
||||
Points[1] = p2;
|
||||
Points[2] = p3;
|
||||
}
|
||||
|
||||
public bool IsInterior { get; set; }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//TODO: Port note - different implementation
|
||||
public int IndexCW(TriangulationPoint p)
|
||||
{
|
||||
int index = IndexOf(p);
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return 2;
|
||||
case 1:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Port note - different implementation
|
||||
public int IndexCCW(TriangulationPoint p)
|
||||
{
|
||||
int index = IndexOf(p);
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return 1;
|
||||
case 1:
|
||||
return 2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(TriangulationPoint p)
|
||||
{
|
||||
return (p == Points[0] || p == Points[1] || p == Points[2]);
|
||||
}
|
||||
|
||||
public bool Contains(DTSweepConstraint e)
|
||||
{
|
||||
return (Contains(e.P) && Contains(e.Q));
|
||||
}
|
||||
|
||||
public bool Contains(TriangulationPoint p, TriangulationPoint q)
|
||||
{
|
||||
return (Contains(p) && Contains(q));
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
if ((p1 == Points[2] && p2 == Points[1]) || (p1 == Points[1] && p2 == Points[2]))
|
||||
{
|
||||
Neighbors[0] = t;
|
||||
}
|
||||
else if ((p1 == Points[0] && p2 == Points[2]) || (p1 == Points[2] && p2 == Points[0]))
|
||||
{
|
||||
Neighbors[1] = t;
|
||||
}
|
||||
else if ((p1 == Points[0] && p2 == Points[1]) || (p1 == Points[1] && p2 == Points[0]))
|
||||
{
|
||||
Neighbors[2] = t;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("Neighbor error, please report!");
|
||||
// throw new Exception("Neighbor error, please report!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exhaustive search to update neighbor pointers
|
||||
/// </summary>
|
||||
public void MarkNeighbor(DelaunayTriangle t)
|
||||
{
|
||||
if (t.Contains(Points[1], Points[2]))
|
||||
{
|
||||
Neighbors[0] = t;
|
||||
t.MarkNeighbor(Points[1], Points[2], this);
|
||||
}
|
||||
else if (t.Contains(Points[0], Points[2]))
|
||||
{
|
||||
Neighbors[1] = t;
|
||||
t.MarkNeighbor(Points[0], Points[2], this);
|
||||
}
|
||||
else if (t.Contains(Points[0], Points[1]))
|
||||
{
|
||||
Neighbors[2] = t;
|
||||
t.MarkNeighbor(Points[0], Points[1], this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("markNeighbor failed");
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
Neighbors[2] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all references to all other triangles and points
|
||||
*/
|
||||
|
||||
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 PointCW(t.PointCW(p));
|
||||
}
|
||||
|
||||
public DelaunayTriangle NeighborCW(TriangulationPoint point)
|
||||
{
|
||||
return Neighbors[(Points.IndexOf(point) + 1)%3];
|
||||
}
|
||||
|
||||
public DelaunayTriangle NeighborCCW(TriangulationPoint point)
|
||||
{
|
||||
return Neighbors[(Points.IndexOf(point) + 2)%3];
|
||||
}
|
||||
|
||||
public DelaunayTriangle NeighborAcross(TriangulationPoint point)
|
||||
{
|
||||
return Neighbors[Points.IndexOf(point)];
|
||||
}
|
||||
|
||||
public TriangulationPoint PointCCW(TriangulationPoint point)
|
||||
{
|
||||
return Points[(IndexOf(point) + 1)%3];
|
||||
}
|
||||
|
||||
public TriangulationPoint PointCW(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[IndexCCW(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)
|
||||
{
|
||||
EdgeIsConstrained[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) EdgeIsConstrained[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)];
|
||||
}
|
||||
|
||||
public void SetConstrainedEdgeCCW(TriangulationPoint p, bool ce)
|
||||
{
|
||||
EdgeIsConstrained[(IndexOf(p) + 2)%3] = ce;
|
||||
}
|
||||
|
||||
public void SetConstrainedEdgeCW(TriangulationPoint p, bool ce)
|
||||
{
|
||||
EdgeIsConstrained[(IndexOf(p) + 1)%3] = ce;
|
||||
}
|
||||
|
||||
public void SetConstrainedEdgeAcross(TriangulationPoint p, bool ce)
|
||||
{
|
||||
EdgeIsConstrained[IndexOf(p)] = 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;
|
||||
}
|
||||
}
|
||||
}
|
180
axios/Common/Decomposition/CDT/Delaunay/Sweep/AdvancingFront.cs
Normal file
180
axios/Common/Decomposition/CDT/Delaunay/Sweep/AdvancingFront.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
/* 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;
|
||||
using System.Text;
|
||||
|
||||
namespace Poly2Tri.Triangulation.Delaunay.Sweep
|
||||
{
|
||||
/**
|
||||
* @author Thomas Åhlen (thahlen@gmail.com)
|
||||
*/
|
||||
|
||||
public class AdvancingFront
|
||||
{
|
||||
public AdvancingFrontNode Head;
|
||||
protected AdvancingFrontNode Search;
|
||||
public AdvancingFrontNode Tail;
|
||||
|
||||
public AdvancingFront(AdvancingFrontNode head, AdvancingFrontNode tail)
|
||||
{
|
||||
Head = head;
|
||||
Tail = tail;
|
||||
Search = head;
|
||||
AddNode(head);
|
||||
AddNode(tail);
|
||||
}
|
||||
|
||||
public void AddNode(AdvancingFrontNode node)
|
||||
{
|
||||
//_searchTree.put(node.key, node);
|
||||
}
|
||||
|
||||
public void RemoveNode(AdvancingFrontNode node)
|
||||
{
|
||||
//_searchTree.delete( node.key );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// TODO: implement BST index
|
||||
return Search;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We use a balancing tree to locate a node smaller or equal to given key value
|
||||
/// </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");
|
||||
//node = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/* 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.Triangulation.Delaunay.Sweep
|
||||
{
|
||||
public class AdvancingFrontNode
|
||||
{
|
||||
public AdvancingFrontNode Next;
|
||||
public TriangulationPoint Point;
|
||||
public AdvancingFrontNode Prev;
|
||||
public DelaunayTriangle Triangle;
|
||||
public double Value;
|
||||
|
||||
public AdvancingFrontNode(TriangulationPoint point)
|
||||
{
|
||||
Point = point;
|
||||
Value = point.X;
|
||||
}
|
||||
|
||||
public bool HasNext
|
||||
{
|
||||
get { return Next != null; }
|
||||
}
|
||||
|
||||
public bool HasPrev
|
||||
{
|
||||
get { return Prev != null; }
|
||||
}
|
||||
}
|
||||
}
|
1132
axios/Common/Decomposition/CDT/Delaunay/Sweep/DTSweep.cs
Normal file
1132
axios/Common/Decomposition/CDT/Delaunay/Sweep/DTSweep.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,66 @@
|
||||
/* 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.Triangulation.Delaunay.Sweep
|
||||
{
|
||||
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)
|
||||
{
|
||||
P = p1;
|
||||
Q = p2;
|
||||
if (p1.Y > p2.Y)
|
||||
{
|
||||
Q = p1;
|
||||
P = p2;
|
||||
}
|
||||
else if (p1.Y == p2.Y)
|
||||
{
|
||||
if (p1.X > p2.X)
|
||||
{
|
||||
Q = p1;
|
||||
P = p2;
|
||||
}
|
||||
else if (p1.X == p2.X)
|
||||
{
|
||||
// logger.info( "Failed to create constraint {}={}", p1, p2 );
|
||||
// throw new DuplicatePointException( p1 + "=" + p2 );
|
||||
// return;
|
||||
}
|
||||
}
|
||||
Q.AddEdge(this);
|
||||
}
|
||||
}
|
||||
}
|
236
axios/Common/Decomposition/CDT/Delaunay/Sweep/DTSweepContext.cs
Normal file
236
axios/Common/Decomposition/CDT/Delaunay/Sweep/DTSweepContext.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
/* 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.Triangulation.Delaunay.Sweep
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @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 const float ALPHA = 0.3f;
|
||||
|
||||
public DTSweepBasin Basin = new DTSweepBasin();
|
||||
public DTSweepEdgeEvent EdgeEvent = new DTSweepEdgeEvent();
|
||||
|
||||
private DTSweepPointComparator _comparator = new DTSweepPointComparator();
|
||||
public AdvancingFront aFront;
|
||||
|
||||
public DTSweepContext()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
public TriangulationPoint Head { get; set; }
|
||||
public TriangulationPoint Tail { get; set; }
|
||||
|
||||
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 );
|
||||
aFront.AddNode(node);
|
||||
}
|
||||
|
||||
public void RemoveNode(AdvancingFrontNode node)
|
||||
{
|
||||
// Console.WriteLine( "remove:" + node.key + ":" + System.identityHashCode(node.key));
|
||||
// m_nodeTree.delete( node.getKey() );
|
||||
aFront.RemoveNode(node);
|
||||
}
|
||||
|
||||
public AdvancingFrontNode LocateNode(TriangulationPoint point)
|
||||
{
|
||||
return aFront.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]);
|
||||
|
||||
aFront = new AdvancingFront(head, tail);
|
||||
aFront.AddNode(middle);
|
||||
|
||||
// TODO: I think it would be more intuitive if head is middles next and not previous
|
||||
// so swap head and tail
|
||||
aFront.Head.Next = middle;
|
||||
middle.Next = aFront.Tail;
|
||||
middle.Prev = aFront.Head;
|
||||
aFront.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)
|
||||
{
|
||||
AdvancingFrontNode n;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (t.Neighbors[i] == null)
|
||||
{
|
||||
n = aFront.LocatePoint(t.PointCW(t.Points[i]));
|
||||
if (n != null)
|
||||
{
|
||||
n.Triangle = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void PrepareTriangulation(Triangulatable 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);
|
||||
}
|
||||
|
||||
#region Nested type: DTSweepBasin
|
||||
|
||||
public class DTSweepBasin
|
||||
{
|
||||
public AdvancingFrontNode bottomNode;
|
||||
public bool leftHighest;
|
||||
public AdvancingFrontNode leftNode;
|
||||
public AdvancingFrontNode rightNode;
|
||||
public double width;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nested type: DTSweepEdgeEvent
|
||||
|
||||
public class DTSweepEdgeEvent
|
||||
{
|
||||
public DTSweepConstraint ConstrainedEdge;
|
||||
public bool Right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/* 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.Triangulation.Delaunay.Sweep
|
||||
{
|
||||
public class DTSweepPointComparator : IComparer<TriangulationPoint>
|
||||
{
|
||||
#region IComparer<TriangulationPoint> Members
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/* 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.Triangulation.Delaunay.Sweep
|
||||
{
|
||||
public class PointOnEdgeException : NotImplementedException
|
||||
{
|
||||
public PointOnEdgeException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
48
axios/Common/Decomposition/CDT/ITriangulatable.cs
Normal file
48
axios/Common/Decomposition/CDT/ITriangulatable.cs
Normal 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.Collections.Generic;
|
||||
using Poly2Tri.Triangulation.Delaunay;
|
||||
|
||||
namespace Poly2Tri.Triangulation
|
||||
{
|
||||
public interface Triangulatable
|
||||
{
|
||||
IList<TriangulationPoint> Points { get; } // MM: Neither of these are used via interface (yet?)
|
||||
IList<DelaunayTriangle> Triangles { get; }
|
||||
TriangulationMode TriangulationMode { get; }
|
||||
void PrepareTriangulation(TriangulationContext tcx);
|
||||
|
||||
void AddTriangle(DelaunayTriangle t);
|
||||
void AddTriangles(IEnumerable<DelaunayTriangle> list);
|
||||
void ClearTriangles();
|
||||
}
|
||||
}
|
40
axios/Common/Decomposition/CDT/Orientation.cs
Normal file
40
axios/Common/Decomposition/CDT/Orientation.cs
Normal 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 FarseerPhysics.Common.Decomposition.CDT
|
||||
{
|
||||
public enum Orientation
|
||||
{
|
||||
CW,
|
||||
CCW,
|
||||
Collinear
|
||||
}
|
||||
}
|
272
axios/Common/Decomposition/CDT/Polygon/Polygon.cs
Normal file
272
axios/Common/Decomposition/CDT/Polygon/Polygon.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
/* 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-explanitory methods may deserve commenting anyways
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Poly2Tri.Triangulation.Delaunay;
|
||||
|
||||
namespace Poly2Tri.Triangulation.Polygon
|
||||
{
|
||||
public class Polygon : Triangulatable
|
||||
{
|
||||
protected List<Polygon> _holes;
|
||||
protected PolygonPoint _last;
|
||||
protected List<TriangulationPoint> _points = new List<TriangulationPoint>();
|
||||
protected List<TriangulationPoint> _steinerPoints;
|
||||
protected List<DelaunayTriangle> _triangles;
|
||||
|
||||
/// <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");
|
||||
|
||||
// Lets do one sanity check that first and last point hasn't got same position
|
||||
// Its something that often happen when importing polygon data from other formats
|
||||
if (points[0].Equals(points[points.Count - 1])) points.RemoveAt(points.Count - 1);
|
||||
|
||||
_points.AddRange(points.Cast<TriangulationPoint>());
|
||||
}
|
||||
|
||||
/// <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())
|
||||
{
|
||||
}
|
||||
|
||||
public Polygon()
|
||||
{
|
||||
}
|
||||
|
||||
public IList<Polygon> Holes
|
||||
{
|
||||
get { return _holes; }
|
||||
}
|
||||
|
||||
#region Triangulatable Members
|
||||
|
||||
public TriangulationMode TriangulationMode
|
||||
{
|
||||
get { return TriangulationMode.Polygon; }
|
||||
}
|
||||
|
||||
public IList<TriangulationPoint> Points
|
||||
{
|
||||
get { return _points; }
|
||||
}
|
||||
|
||||
public IList<DelaunayTriangle> Triangles
|
||||
{
|
||||
get { return _triangles; }
|
||||
}
|
||||
|
||||
public void AddTriangle(DelaunayTriangle t)
|
||||
{
|
||||
_triangles.Add(t);
|
||||
}
|
||||
|
||||
public void AddTriangles(IEnumerable<DelaunayTriangle> list)
|
||||
{
|
||||
_triangles.AddRange(list);
|
||||
}
|
||||
|
||||
public void ClearTriangles()
|
||||
{
|
||||
if (_triangles != null) _triangles.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates constraints and populates the context with points
|
||||
/// </summary>
|
||||
/// <param name="tcx">The context</param>
|
||||
public void PrepareTriangulation(TriangulationContext tcx)
|
||||
{
|
||||
if (_triangles == null)
|
||||
{
|
||||
_triangles = new List<DelaunayTriangle>(_points.Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
_triangles.Clear();
|
||||
}
|
||||
|
||||
// Outer constraints
|
||||
for (int i = 0; i < _points.Count - 1; i++)
|
||||
{
|
||||
tcx.NewConstraint(_points[i], _points[i + 1]);
|
||||
}
|
||||
tcx.NewConstraint(_points[0], _points[_points.Count - 1]);
|
||||
tcx.Points.AddRange(_points);
|
||||
|
||||
// Hole constraints
|
||||
if (_holes != null)
|
||||
{
|
||||
foreach (Polygon p in _holes)
|
||||
{
|
||||
for (int i = 0; i < p._points.Count - 1; i++)
|
||||
{
|
||||
tcx.NewConstraint(p._points[i], p._points[i + 1]);
|
||||
}
|
||||
tcx.NewConstraint(p._points[0], p._points[p._points.Count - 1]);
|
||||
tcx.Points.AddRange(p._points);
|
||||
}
|
||||
}
|
||||
|
||||
if (_steinerPoints != null)
|
||||
{
|
||||
tcx.Points.AddRange(_steinerPoints);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void AddSteinerPoint(TriangulationPoint point)
|
||||
{
|
||||
if (_steinerPoints == null)
|
||||
{
|
||||
_steinerPoints = new List<TriangulationPoint>();
|
||||
}
|
||||
_steinerPoints.Add(point);
|
||||
}
|
||||
|
||||
public void AddSteinerPoints(List<TriangulationPoint> points)
|
||||
{
|
||||
if (_steinerPoints == null)
|
||||
{
|
||||
_steinerPoints = new List<TriangulationPoint>();
|
||||
}
|
||||
_steinerPoints.AddRange(points);
|
||||
}
|
||||
|
||||
public void ClearSteinerPoints()
|
||||
{
|
||||
if (_steinerPoints != null)
|
||||
{
|
||||
_steinerPoints.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 (_holes == null) _holes = new List<Polygon>();
|
||||
_holes.Add(poly);
|
||||
// XXX: tests could be made here to be sure it is fully inside
|
||||
// addSubtraction( poly.getPoints() );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts newPoint after point.
|
||||
/// </summary>
|
||||
/// <param name="point">The point to insert after in the polygon</param>
|
||||
/// <param name="newPoint">The point to insert into the polygon</param>
|
||||
public void InsertPointAfter(PolygonPoint point, PolygonPoint newPoint)
|
||||
{
|
||||
// Validate that
|
||||
int index = _points.IndexOf(point);
|
||||
if (index == -1)
|
||||
throw new ArgumentException(
|
||||
"Tried to insert a point into a Polygon after a point not belonging to the Polygon", "point");
|
||||
newPoint.Next = point.Next;
|
||||
newPoint.Previous = point;
|
||||
point.Next.Previous = newPoint;
|
||||
point.Next = newPoint;
|
||||
_points.Insert(index + 1, newPoint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts list (after last point in polygon?)
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
public void AddPoints(IEnumerable<PolygonPoint> list)
|
||||
{
|
||||
PolygonPoint first;
|
||||
foreach (PolygonPoint p in list)
|
||||
{
|
||||
p.Previous = _last;
|
||||
if (_last != null)
|
||||
{
|
||||
p.Next = _last.Next;
|
||||
_last.Next = p;
|
||||
}
|
||||
_last = p;
|
||||
_points.Add(p);
|
||||
}
|
||||
first = (PolygonPoint) _points[0];
|
||||
_last.Next = first;
|
||||
first.Previous = _last;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a point after the last in the polygon.
|
||||
/// </summary>
|
||||
/// <param name="p">The point to add</param>
|
||||
public void AddPoint(PolygonPoint p)
|
||||
{
|
||||
p.Previous = _last;
|
||||
p.Next = _last.Next;
|
||||
_last.Next = p;
|
||||
_points.Add(p);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a point from the polygon.
|
||||
/// </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;
|
||||
_points.Remove(p);
|
||||
}
|
||||
}
|
||||
}
|
48
axios/Common/Decomposition/CDT/Polygon/PolygonPoint.cs
Normal file
48
axios/Common/Decomposition/CDT/Polygon/PolygonPoint.cs
Normal 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.
|
||||
*/
|
||||
|
||||
// Changes from the Java version
|
||||
// Replaced get/set Next/Previous with attributes
|
||||
// Future possibilities
|
||||
// Documentation!
|
||||
|
||||
namespace Poly2Tri.Triangulation.Polygon
|
||||
{
|
||||
public class PolygonPoint : TriangulationPoint
|
||||
{
|
||||
public PolygonPoint(double x, double y) : base(x, y)
|
||||
{
|
||||
}
|
||||
|
||||
public PolygonPoint Next { get; set; }
|
||||
public PolygonPoint Previous { get; set; }
|
||||
}
|
||||
}
|
65
axios/Common/Decomposition/CDT/Polygon/PolygonSet.cs
Normal file
65
axios/Common/Decomposition/CDT/Polygon/PolygonSet.cs
Normal 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.
|
||||
*/
|
||||
|
||||
// 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.Triangulation.Polygon
|
||||
{
|
||||
public class PolygonSet
|
||||
{
|
||||
protected List<Polygon> _polygons = new List<Polygon>();
|
||||
|
||||
public PolygonSet()
|
||||
{
|
||||
}
|
||||
|
||||
public PolygonSet(Polygon poly)
|
||||
{
|
||||
_polygons.Add(poly);
|
||||
}
|
||||
|
||||
public IEnumerable<Polygon> Polygons
|
||||
{
|
||||
get { return _polygons; }
|
||||
}
|
||||
|
||||
public void Add(Polygon p)
|
||||
{
|
||||
_polygons.Add(p);
|
||||
}
|
||||
}
|
||||
}
|
114
axios/Common/Decomposition/CDT/Sets/ConstrainedPointSet.cs
Normal file
114
axios/Common/Decomposition/CDT/Sets/ConstrainedPointSet.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
/* 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.Triangulation.Sets
|
||||
{
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
public class ConstrainedPointSet : PointSet
|
||||
{
|
||||
private List<TriangulationPoint> _constrainedPointList = null;
|
||||
|
||||
public ConstrainedPointSet(List<TriangulationPoint> points, int[] index)
|
||||
: base(points)
|
||||
{
|
||||
EdgeIndex = index;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param points - A list of all points in PointSet
|
||||
* @param constraints - Pairs of two points defining a constraint, all points <b>must</b> be part of given PointSet!
|
||||
*/
|
||||
|
||||
public ConstrainedPointSet(List<TriangulationPoint> points, IEnumerable<TriangulationPoint> constraints)
|
||||
: base(points)
|
||||
{
|
||||
_constrainedPointList = new List<TriangulationPoint>();
|
||||
_constrainedPointList.AddRange(constraints);
|
||||
}
|
||||
|
||||
public int[] EdgeIndex { get; private set; }
|
||||
|
||||
public override TriangulationMode TriangulationMode
|
||||
{
|
||||
get { return TriangulationMode.Constrained; }
|
||||
}
|
||||
|
||||
public override void PrepareTriangulation(TriangulationContext tcx)
|
||||
{
|
||||
base.PrepareTriangulation(tcx);
|
||||
if (_constrainedPointList != null)
|
||||
{
|
||||
TriangulationPoint p1, p2;
|
||||
List<TriangulationPoint>.Enumerator iterator = _constrainedPointList.GetEnumerator();
|
||||
while (iterator.MoveNext())
|
||||
{
|
||||
p1 = iterator.Current;
|
||||
iterator.MoveNext();
|
||||
p2 = iterator.Current;
|
||||
tcx.NewConstraint(p1, p2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < EdgeIndex.Length; i += 2)
|
||||
{
|
||||
// XXX: must change!!
|
||||
tcx.NewConstraint(Points[EdgeIndex[i]], Points[EdgeIndex[i + 1]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: TO BE IMPLEMENTED!
|
||||
* Peforms a validation on given input<br>
|
||||
* 1. Check's if there any constraint edges are crossing or collinear<br>
|
||||
* 2.
|
||||
* @return
|
||||
*/
|
||||
|
||||
public bool isValid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
84
axios/Common/Decomposition/CDT/Sets/PointSet.cs
Normal file
84
axios/Common/Decomposition/CDT/Sets/PointSet.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
/* 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;
|
||||
using Poly2Tri.Triangulation.Delaunay;
|
||||
|
||||
namespace Poly2Tri.Triangulation.Sets
|
||||
{
|
||||
public class PointSet : Triangulatable
|
||||
{
|
||||
public PointSet(List<TriangulationPoint> points)
|
||||
{
|
||||
Points = new List<TriangulationPoint>(points);
|
||||
}
|
||||
|
||||
#region Triangulatable Members
|
||||
|
||||
public IList<TriangulationPoint> Points { get; private set; }
|
||||
public IList<DelaunayTriangle> Triangles { get; private set; }
|
||||
|
||||
public virtual TriangulationMode TriangulationMode
|
||||
{
|
||||
get { return TriangulationMode.Unconstrained; }
|
||||
}
|
||||
|
||||
public void AddTriangle(DelaunayTriangle t)
|
||||
{
|
||||
Triangles.Add(t);
|
||||
}
|
||||
|
||||
public void AddTriangles(IEnumerable<DelaunayTriangle> list)
|
||||
{
|
||||
foreach (DelaunayTriangle tri in list) Triangles.Add(tri);
|
||||
}
|
||||
|
||||
public void ClearTriangles()
|
||||
{
|
||||
Triangles.Clear();
|
||||
}
|
||||
|
||||
public virtual void PrepareTriangulation(TriangulationContext tcx)
|
||||
{
|
||||
if (Triangles == null)
|
||||
{
|
||||
Triangles = new List<DelaunayTriangle>(Points.Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
Triangles.Clear();
|
||||
}
|
||||
tcx.Points.AddRange(Points);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
46
axios/Common/Decomposition/CDT/TriangulationConstraint.cs
Normal file
46
axios/Common/Decomposition/CDT/TriangulationConstraint.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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
|
||||
*/
|
||||
namespace Poly2Tri.Triangulation
|
||||
{
|
||||
public class TriangulationConstraint
|
||||
{
|
||||
public TriangulationPoint P;
|
||||
public TriangulationPoint Q;
|
||||
}
|
||||
}
|
87
axios/Common/Decomposition/CDT/TriangulationContext.cs
Normal file
87
axios/Common/Decomposition/CDT/TriangulationContext.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Poly2Tri.Triangulation.Delaunay;
|
||||
|
||||
namespace Poly2Tri.Triangulation
|
||||
{
|
||||
public abstract class TriangulationContext
|
||||
{
|
||||
public readonly List<TriangulationPoint> Points = new List<TriangulationPoint>(200);
|
||||
public readonly List<DelaunayTriangle> Triangles = new List<DelaunayTriangle>();
|
||||
|
||||
#pragma warning disable 414
|
||||
private int _stepTime = -1;
|
||||
#pragma warning restore 414
|
||||
|
||||
public TriangulationContext()
|
||||
{
|
||||
Terminated = false;
|
||||
}
|
||||
|
||||
public TriangulationMode TriangulationMode { get; protected set; }
|
||||
public Triangulatable Triangulatable { get; private set; }
|
||||
|
||||
public bool WaitUntilNotified { get; private set; }
|
||||
public bool Terminated { get; set; }
|
||||
|
||||
public int StepCount { get; private set; }
|
||||
public virtual bool IsDebugEnabled { get; protected set; }
|
||||
|
||||
public void Done()
|
||||
{
|
||||
StepCount++;
|
||||
}
|
||||
|
||||
public virtual void PrepareTriangulation(Triangulatable t)
|
||||
{
|
||||
Triangulatable = t;
|
||||
TriangulationMode = t.TriangulationMode;
|
||||
t.PrepareTriangulation(this);
|
||||
}
|
||||
|
||||
public abstract TriangulationConstraint NewConstraint(TriangulationPoint a, TriangulationPoint b);
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public void Update(string message)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Clear()
|
||||
{
|
||||
Points.Clear();
|
||||
Terminated = false;
|
||||
StepCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
40
axios/Common/Decomposition/CDT/TriangulationMode.cs
Normal file
40
axios/Common/Decomposition/CDT/TriangulationMode.cs
Normal 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.Triangulation
|
||||
{
|
||||
public enum TriangulationMode
|
||||
{
|
||||
Unconstrained,
|
||||
Constrained,
|
||||
Polygon
|
||||
}
|
||||
}
|
82
axios/Common/Decomposition/CDT/TriangulationPoint.cs
Normal file
82
axios/Common/Decomposition/CDT/TriangulationPoint.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
/* 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;
|
||||
using Poly2Tri.Triangulation.Delaunay.Sweep;
|
||||
|
||||
namespace Poly2Tri.Triangulation
|
||||
{
|
||||
public class TriangulationPoint
|
||||
{
|
||||
// List of edges this point constitutes an upper ending point (CDT)
|
||||
|
||||
public double X, Y;
|
||||
|
||||
public TriangulationPoint(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public List<DTSweepConstraint> Edges { get; private set; }
|
||||
|
||||
public float Xf
|
||||
{
|
||||
get { return (float) X; }
|
||||
set { X = value; }
|
||||
}
|
||||
|
||||
public float Yf
|
||||
{
|
||||
get { return (float) Y; }
|
||||
set { Y = value; }
|
||||
}
|
||||
|
||||
public bool HasEdges
|
||||
{
|
||||
get { return Edges != null; }
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "[" + X + "," + Y + "]";
|
||||
}
|
||||
|
||||
public void AddEdge(DTSweepConstraint e)
|
||||
{
|
||||
if (Edges == null)
|
||||
{
|
||||
Edges = new List<DTSweepConstraint>();
|
||||
}
|
||||
Edges.Add(e);
|
||||
}
|
||||
}
|
||||
}
|
160
axios/Common/Decomposition/CDT/TriangulationUtil.cs
Normal file
160
axios/Common/Decomposition/CDT/TriangulationUtil.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
/* 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 FarseerPhysics.Common.Decomposition.CDT;
|
||||
|
||||
namespace Poly2Tri.Triangulation
|
||||
{
|
||||
/**
|
||||
* @author Thomas Åhlén, thahlen@gmail.com
|
||||
*/
|
||||
|
||||
public class TriangulationUtil
|
||||
{
|
||||
public static double EPSILON = 1e-12;
|
||||
|
||||
/// <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(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc,
|
||||
TriangulationPoint 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(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc,
|
||||
TriangulationPoint 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(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint 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 > -EPSILON && val < EPSILON)
|
||||
{
|
||||
return Orientation.Collinear;
|
||||
}
|
||||
else if (val > 0)
|
||||
{
|
||||
return Orientation.CCW;
|
||||
}
|
||||
return Orientation.CW;
|
||||
}
|
||||
}
|
||||
}
|
118
axios/Common/Decomposition/CDT/Util/FixedArray3.cs
Normal file
118
axios/Common/Decomposition/CDT/Util/FixedArray3.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
/* 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.Triangulation.Util
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region IEnumerable<T> Members
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return Enumerate().GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public bool Contains(T value)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) if (this[i] == value) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public int IndexOf(T value)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) if (this[i] == 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] == value) this[i] = null;
|
||||
}
|
||||
|
||||
private IEnumerable<T> Enumerate()
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) yield return this[i];
|
||||
}
|
||||
}
|
||||
}
|
118
axios/Common/Decomposition/CDT/Util/FixedBitArray3.cs
Normal file
118
axios/Common/Decomposition/CDT/Util/FixedBitArray3.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
/* 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.Triangulation.Util
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region IEnumerable<bool> Members
|
||||
|
||||
public IEnumerator<bool> GetEnumerator()
|
||||
{
|
||||
return Enumerate().GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
38
axios/Common/Decomposition/CDT/Util/PointGenerator.cs
Normal file
38
axios/Common/Decomposition/CDT/Util/PointGenerator.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Poly2Tri.Triangulation.Util
|
||||
{
|
||||
public class PointGenerator
|
||||
{
|
||||
private 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;
|
||||
}
|
||||
}
|
||||
}
|
98
axios/Common/Decomposition/CDT/Util/PolygonGenerator.cs
Normal file
98
axios/Common/Decomposition/CDT/Util/PolygonGenerator.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
/* 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 Poly2Tri.Triangulation.Polygon;
|
||||
|
||||
namespace Poly2Tri.Triangulation.Util
|
||||
{
|
||||
public class PolygonGenerator
|
||||
{
|
||||
private static readonly Random RNG = new Random();
|
||||
|
||||
private static double PI_2 = 2.0*Math.PI;
|
||||
|
||||
public static Polygon.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.Polygon(points);
|
||||
}
|
||||
|
||||
public static Polygon.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.Polygon(points);
|
||||
}
|
||||
}
|
||||
}
|
110
axios/Common/Decomposition/CDTDecomposer.cs
Normal file
110
axios/Common/Decomposition/CDTDecomposer.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
/* 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;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Poly2Tri.Triangulation;
|
||||
using Poly2Tri.Triangulation.Delaunay;
|
||||
using Poly2Tri.Triangulation.Delaunay.Sweep;
|
||||
using Poly2Tri.Triangulation.Polygon;
|
||||
|
||||
using System.Linq;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition
|
||||
{
|
||||
public static class CDTDecomposer
|
||||
{
|
||||
public static List<Vertices> ConvexPartition(Vertices vertices)
|
||||
{
|
||||
Polygon poly = new Polygon();
|
||||
|
||||
foreach (Vector2 vertex in vertices)
|
||||
{
|
||||
poly.Points.Add(new TriangulationPoint(vertex.X, vertex.Y));
|
||||
}
|
||||
|
||||
DTSweepContext tcx = new DTSweepContext();
|
||||
tcx.PrepareTriangulation(poly);
|
||||
DTSweep.Triangulate(tcx);
|
||||
|
||||
List<Vertices> results = new List<Vertices>();
|
||||
|
||||
foreach (DelaunayTriangle triangle in poly.Triangles)
|
||||
{
|
||||
Vertices v = new Vertices();
|
||||
foreach (TriangulationPoint p in triangle.Points)
|
||||
{
|
||||
v.Add(new Vector2((float)p.X, (float)p.Y));
|
||||
}
|
||||
results.Add(v);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public static List<Vertices> ConvexPartition(DetectedVertices vertices)
|
||||
{
|
||||
Polygon poly = new Polygon();
|
||||
foreach (var vertex in vertices)
|
||||
poly.Points.Add(new TriangulationPoint(vertex.X, vertex.Y));
|
||||
|
||||
if (vertices.Holes != null)
|
||||
{
|
||||
foreach (var holeVertices in vertices.Holes)
|
||||
{
|
||||
Polygon hole = new Polygon();
|
||||
foreach (var vertex in holeVertices)
|
||||
hole.Points.Add(new TriangulationPoint(vertex.X, vertex.Y));
|
||||
|
||||
poly.AddHole(hole);
|
||||
}
|
||||
}
|
||||
|
||||
DTSweepContext tcx = new DTSweepContext();
|
||||
tcx.PrepareTriangulation(poly);
|
||||
DTSweep.Triangulate(tcx);
|
||||
|
||||
List<Vertices> results = new List<Vertices>();
|
||||
|
||||
foreach (DelaunayTriangle triangle in poly.Triangles)
|
||||
{
|
||||
Vertices v = new Vertices();
|
||||
foreach (TriangulationPoint p in triangle.Points)
|
||||
{
|
||||
v.Add(new Vector2((float)p.X, (float)p.Y));
|
||||
}
|
||||
results.Add(v);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
691
axios/Common/Decomposition/EarclipDecomposer.cs
Normal file
691
axios/Common/Decomposition/EarclipDecomposer.cs
Normal file
@@ -0,0 +1,691 @@
|
||||
/*
|
||||
* C# Version Ported by Matt Bettcher and Ian Qvist 2009-2010
|
||||
*
|
||||
* Original C++ Version 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FarseerPhysics.Common.PolygonManipulation;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition
|
||||
{
|
||||
/// <summary>
|
||||
/// Ported from jBox2D. Original author: ewjordan
|
||||
/// Triangulates a polygon using simple ear-clipping algorithm.
|
||||
///
|
||||
/// Only works on simple polygons.
|
||||
///
|
||||
/// Triangles may be degenerate, especially if you have identical points
|
||||
/// in the input to the algorithm. Check this before you use them.
|
||||
/// </summary>
|
||||
public static class EarclipDecomposer
|
||||
{
|
||||
//box2D rev 32 - for details, see http://www.box2d.org/forum/viewtopic.php?f=4&t=83&start=50
|
||||
|
||||
private const float Tol = .001f;
|
||||
|
||||
/// <summary>
|
||||
/// Decomposes a non-convex polygon into a number of convex polygons, up
|
||||
/// to maxPolys (remaining pieces are thrown out).
|
||||
///
|
||||
/// Each resulting polygon will have no more than Settings.MaxPolygonVertices
|
||||
/// vertices.
|
||||
///
|
||||
/// Warning: Only works on simple polygons
|
||||
/// </summary>
|
||||
/// <param name="vertices">The vertices.</param>
|
||||
/// <returns></returns>
|
||||
public static List<Vertices> ConvexPartition(Vertices vertices)
|
||||
{
|
||||
return ConvexPartition(vertices, int.MaxValue, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decomposes a non-convex polygon into a number of convex polygons, up
|
||||
/// to maxPolys (remaining pieces are thrown out).
|
||||
/// Each resulting polygon will have no more than Settings.MaxPolygonVertices
|
||||
/// vertices.
|
||||
/// Warning: Only works on simple polygons
|
||||
/// </summary>
|
||||
/// <param name="vertices">The vertices.</param>
|
||||
/// <param name="maxPolys">The maximum number of polygons.</param>
|
||||
/// <param name="tolerance">The tolerance.</param>
|
||||
/// <returns></returns>
|
||||
public static List<Vertices> ConvexPartition(Vertices vertices, int maxPolys, float tolerance)
|
||||
{
|
||||
if (vertices.Count < 3)
|
||||
return new List<Vertices> { vertices };
|
||||
/*
|
||||
if (vertices.IsConvex() && vertices.Count <= Settings.MaxPolygonVertices)
|
||||
{
|
||||
if (vertices.IsCounterClockWise())
|
||||
{
|
||||
Vertices tempP = new Vertices(vertices);
|
||||
tempP.Reverse();
|
||||
tempP = SimplifyTools.CollinearSimplify(tempP);
|
||||
tempP.ForceCounterClockWise();
|
||||
return new List<Vertices> { tempP };
|
||||
}
|
||||
vertices = SimplifyTools.CollinearSimplify(vertices);
|
||||
vertices.ForceCounterClockWise();
|
||||
return new List<Vertices> { vertices };
|
||||
}
|
||||
*/
|
||||
List<Triangle> triangulated;
|
||||
|
||||
if (vertices.IsCounterClockWise())
|
||||
{
|
||||
Vertices tempP = new Vertices(vertices);
|
||||
tempP.Reverse();
|
||||
triangulated = TriangulatePolygon(tempP);
|
||||
}
|
||||
else
|
||||
{
|
||||
triangulated = TriangulatePolygon(vertices);
|
||||
}
|
||||
if (triangulated.Count < 1)
|
||||
{
|
||||
//Still no luck? Oh well...
|
||||
throw new Exception("Can't triangulate your polygon.");
|
||||
}
|
||||
|
||||
List<Vertices> polygonizedTriangles = PolygonizeTriangles(triangulated, maxPolys, tolerance);
|
||||
|
||||
//The polygonized triangles are not guaranteed to be without collinear points. We remove
|
||||
//them to be sure.
|
||||
for (int i = 0; i < polygonizedTriangles.Count; i++)
|
||||
{
|
||||
polygonizedTriangles[i] = SimplifyTools.CollinearSimplify(polygonizedTriangles[i], 0);
|
||||
}
|
||||
|
||||
//Remove empty vertice collections
|
||||
for (int i = polygonizedTriangles.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (polygonizedTriangles[i].Count == 0)
|
||||
polygonizedTriangles.RemoveAt(i);
|
||||
}
|
||||
|
||||
return polygonizedTriangles;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turns a list of triangles into a list of convex polygons. Very simple
|
||||
/// method - start with a seed triangle, keep adding triangles to it until
|
||||
/// you can't add any more without making the polygon non-convex.
|
||||
///
|
||||
/// Returns an integer telling how many polygons were created. Will fill
|
||||
/// polys array up to polysLength entries, which may be smaller or larger
|
||||
/// than the return value.
|
||||
///
|
||||
/// Takes O(N///P) where P is the number of resultant polygons, N is triangle
|
||||
/// count.
|
||||
///
|
||||
/// The final polygon list will not necessarily be minimal, though in
|
||||
/// practice it works fairly well.
|
||||
/// </summary>
|
||||
/// <param name="triangulated">The triangulated.</param>
|
||||
///<param name="maxPolys">The maximun number of polygons</param>
|
||||
///<param name="tolerance">The tolerance</param>
|
||||
///<returns></returns>
|
||||
public static List<Vertices> PolygonizeTriangles(List<Triangle> triangulated, int maxPolys, float tolerance)
|
||||
{
|
||||
List<Vertices> polys = new List<Vertices>(50);
|
||||
|
||||
int polyIndex = 0;
|
||||
|
||||
if (triangulated.Count <= 0)
|
||||
{
|
||||
//return empty polygon list
|
||||
return polys;
|
||||
}
|
||||
|
||||
bool[] covered = new bool[triangulated.Count];
|
||||
for (int i = 0; i < triangulated.Count; ++i)
|
||||
{
|
||||
covered[i] = false;
|
||||
|
||||
//Check here for degenerate triangles
|
||||
if (((triangulated[i].X[0] == triangulated[i].X[1]) && (triangulated[i].Y[0] == triangulated[i].Y[1]))
|
||||
||
|
||||
((triangulated[i].X[1] == triangulated[i].X[2]) && (triangulated[i].Y[1] == triangulated[i].Y[2]))
|
||||
||
|
||||
((triangulated[i].X[0] == triangulated[i].X[2]) && (triangulated[i].Y[0] == triangulated[i].Y[2])))
|
||||
{
|
||||
covered[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool notDone = true;
|
||||
while (notDone)
|
||||
{
|
||||
int currTri = -1;
|
||||
for (int i = 0; i < triangulated.Count; ++i)
|
||||
{
|
||||
if (covered[i])
|
||||
continue;
|
||||
currTri = i;
|
||||
break;
|
||||
}
|
||||
if (currTri == -1)
|
||||
{
|
||||
notDone = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vertices poly = new Vertices(3);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
poly.Add(new Vector2(triangulated[currTri].X[i], triangulated[currTri].Y[i]));
|
||||
}
|
||||
|
||||
covered[currTri] = true;
|
||||
int index = 0;
|
||||
for (int i = 0; i < 2 * triangulated.Count; ++i, ++index)
|
||||
{
|
||||
while (index >= triangulated.Count) index -= triangulated.Count;
|
||||
if (covered[index])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Vertices newP = AddTriangle(triangulated[index], poly);
|
||||
if (newP == null)
|
||||
continue; // is this right
|
||||
|
||||
if (newP.Count > Settings.MaxPolygonVertices)
|
||||
continue;
|
||||
|
||||
if (newP.IsConvex())
|
||||
{
|
||||
//Or should it be IsUsable? Maybe re-write IsConvex to apply the angle threshold from Box2d
|
||||
poly = new Vertices(newP);
|
||||
covered[index] = true;
|
||||
}
|
||||
}
|
||||
|
||||
//We have a maximum of polygons that we need to keep under.
|
||||
if (polyIndex < maxPolys)
|
||||
{
|
||||
//SimplifyTools.MergeParallelEdges(poly, tolerance);
|
||||
|
||||
//If identical points are present, a triangle gets
|
||||
//borked by the MergeParallelEdges function, hence
|
||||
//the vertex number check
|
||||
if (poly.Count >= 3)
|
||||
polys.Add(new Vertices(poly));
|
||||
//else
|
||||
// printf("Skipping corrupt poly\n");
|
||||
}
|
||||
if (poly.Count >= 3)
|
||||
polyIndex++; //Must be outside (polyIndex < polysLength) test
|
||||
}
|
||||
}
|
||||
|
||||
return polys;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triangulates a polygon using simple ear-clipping algorithm. Returns
|
||||
/// size of Triangle array unless the polygon can't be triangulated.
|
||||
/// This should only happen if the polygon self-intersects,
|
||||
/// though it will not _always_ return null for a bad polygon - it is the
|
||||
/// caller's responsibility to check for self-intersection, and if it
|
||||
/// doesn't, it should at least check that the return value is non-null
|
||||
/// before using. You're warned!
|
||||
///
|
||||
/// Triangles may be degenerate, especially if you have identical points
|
||||
/// in the input to the algorithm. Check this before you use them.
|
||||
///
|
||||
/// This is totally unoptimized, so for large polygons it should not be part
|
||||
/// of the simulation loop.
|
||||
///
|
||||
/// Warning: Only works on simple polygons.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<Triangle> TriangulatePolygon(Vertices vertices)
|
||||
{
|
||||
List<Triangle> results = new List<Triangle>();
|
||||
if (vertices.Count < 3)
|
||||
return new List<Triangle>();
|
||||
|
||||
//Recurse and split on pinch points
|
||||
Vertices pA, pB;
|
||||
Vertices pin = new Vertices(vertices);
|
||||
if (ResolvePinchPoint(pin, out pA, out pB))
|
||||
{
|
||||
List<Triangle> mergeA = TriangulatePolygon(pA);
|
||||
List<Triangle> mergeB = TriangulatePolygon(pB);
|
||||
|
||||
if (mergeA.Count == -1 || mergeB.Count == -1)
|
||||
throw new Exception("Can't triangulate your polygon.");
|
||||
|
||||
for (int i = 0; i < mergeA.Count; ++i)
|
||||
{
|
||||
results.Add(new Triangle(mergeA[i]));
|
||||
}
|
||||
for (int i = 0; i < mergeB.Count; ++i)
|
||||
{
|
||||
results.Add(new Triangle(mergeB[i]));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
Triangle[] buffer = new Triangle[vertices.Count - 2];
|
||||
int bufferSize = 0;
|
||||
float[] xrem = new float[vertices.Count];
|
||||
float[] yrem = new float[vertices.Count];
|
||||
for (int i = 0; i < vertices.Count; ++i)
|
||||
{
|
||||
xrem[i] = vertices[i].X;
|
||||
yrem[i] = vertices[i].Y;
|
||||
}
|
||||
|
||||
int vNum = vertices.Count;
|
||||
|
||||
while (vNum > 3)
|
||||
{
|
||||
// Find an ear
|
||||
int earIndex = -1;
|
||||
float earMaxMinCross = -10.0f;
|
||||
for (int i = 0; i < vNum; ++i)
|
||||
{
|
||||
if (IsEar(i, xrem, yrem, vNum))
|
||||
{
|
||||
int lower = Remainder(i - 1, vNum);
|
||||
int upper = Remainder(i + 1, vNum);
|
||||
Vector2 d1 = new Vector2(xrem[upper] - xrem[i], yrem[upper] - yrem[i]);
|
||||
Vector2 d2 = new Vector2(xrem[i] - xrem[lower], yrem[i] - yrem[lower]);
|
||||
Vector2 d3 = new Vector2(xrem[lower] - xrem[upper], yrem[lower] - yrem[upper]);
|
||||
|
||||
d1.Normalize();
|
||||
d2.Normalize();
|
||||
d3.Normalize();
|
||||
float cross12;
|
||||
MathUtils.Cross(ref d1, ref d2, out cross12);
|
||||
cross12 = Math.Abs(cross12);
|
||||
|
||||
float cross23;
|
||||
MathUtils.Cross(ref d2, ref d3, out cross23);
|
||||
cross23 = Math.Abs(cross23);
|
||||
|
||||
float cross31;
|
||||
MathUtils.Cross(ref d3, ref d1, out cross31);
|
||||
cross31 = Math.Abs(cross31);
|
||||
|
||||
//Find the maximum minimum angle
|
||||
float minCross = Math.Min(cross12, Math.Min(cross23, cross31));
|
||||
if (minCross > earMaxMinCross)
|
||||
{
|
||||
earIndex = i;
|
||||
earMaxMinCross = minCross;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we still haven't found an ear, we're screwed.
|
||||
// Note: sometimes this is happening because the
|
||||
// remaining points are collinear. Really these
|
||||
// should just be thrown out without halting triangulation.
|
||||
if (earIndex == -1)
|
||||
{
|
||||
for (int i = 0; i < bufferSize; i++)
|
||||
{
|
||||
results.Add(new Triangle(buffer[i]));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// Clip off the ear:
|
||||
// - remove the ear tip from the list
|
||||
|
||||
--vNum;
|
||||
float[] newx = new float[vNum];
|
||||
float[] newy = new float[vNum];
|
||||
int currDest = 0;
|
||||
for (int i = 0; i < vNum; ++i)
|
||||
{
|
||||
if (currDest == earIndex) ++currDest;
|
||||
newx[i] = xrem[currDest];
|
||||
newy[i] = yrem[currDest];
|
||||
++currDest;
|
||||
}
|
||||
|
||||
// - add the clipped triangle to the triangle list
|
||||
int under = (earIndex == 0) ? (vNum) : (earIndex - 1);
|
||||
int over = (earIndex == vNum) ? 0 : (earIndex + 1);
|
||||
Triangle toAdd = new Triangle(xrem[earIndex], yrem[earIndex], xrem[over], yrem[over], xrem[under],
|
||||
yrem[under]);
|
||||
buffer[bufferSize] = toAdd;
|
||||
++bufferSize;
|
||||
|
||||
// - replace the old list with the new one
|
||||
xrem = newx;
|
||||
yrem = newy;
|
||||
}
|
||||
|
||||
Triangle tooAdd = new Triangle(xrem[1], yrem[1], xrem[2], yrem[2], xrem[0], yrem[0]);
|
||||
buffer[bufferSize] = tooAdd;
|
||||
++bufferSize;
|
||||
|
||||
for (int i = 0; i < bufferSize; i++)
|
||||
{
|
||||
results.Add(new Triangle(buffer[i]));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds and fixes "pinch points," points where two polygon
|
||||
/// vertices are at the same point.
|
||||
///
|
||||
/// If a pinch point is found, pin is broken up into poutA and poutB
|
||||
/// and true is returned; otherwise, returns false.
|
||||
///
|
||||
/// Mostly for internal use.
|
||||
///
|
||||
/// O(N^2) time, which sucks...
|
||||
/// </summary>
|
||||
/// <param name="pin">The pin.</param>
|
||||
/// <param name="poutA">The pout A.</param>
|
||||
/// <param name="poutB">The pout B.</param>
|
||||
/// <returns></returns>
|
||||
private static bool ResolvePinchPoint(Vertices pin, out Vertices poutA, out Vertices poutB)
|
||||
{
|
||||
poutA = new Vertices();
|
||||
poutB = new Vertices();
|
||||
|
||||
if (pin.Count < 3)
|
||||
return false;
|
||||
|
||||
bool hasPinchPoint = false;
|
||||
int pinchIndexA = -1;
|
||||
int pinchIndexB = -1;
|
||||
for (int i = 0; i < pin.Count; ++i)
|
||||
{
|
||||
for (int j = i + 1; j < pin.Count; ++j)
|
||||
{
|
||||
//Don't worry about pinch points where the points
|
||||
//are actually just dupe neighbors
|
||||
if (Math.Abs(pin[i].X - pin[j].X) < Tol && Math.Abs(pin[i].Y - pin[j].Y) < Tol && j != i + 1)
|
||||
{
|
||||
pinchIndexA = i;
|
||||
pinchIndexB = j;
|
||||
hasPinchPoint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasPinchPoint) break;
|
||||
}
|
||||
if (hasPinchPoint)
|
||||
{
|
||||
int sizeA = pinchIndexB - pinchIndexA;
|
||||
if (sizeA == pin.Count) return false; //has dupe points at wraparound, not a problem here
|
||||
for (int i = 0; i < sizeA; ++i)
|
||||
{
|
||||
int ind = Remainder(pinchIndexA + i, pin.Count); // is this right
|
||||
poutA.Add(pin[ind]);
|
||||
}
|
||||
|
||||
int sizeB = pin.Count - sizeA;
|
||||
for (int i = 0; i < sizeB; ++i)
|
||||
{
|
||||
int ind = Remainder(pinchIndexB + i, pin.Count); // is this right
|
||||
poutB.Add(pin[ind]);
|
||||
}
|
||||
}
|
||||
return hasPinchPoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fix for obnoxious behavior for the % operator for negative numbers...
|
||||
/// </summary>
|
||||
/// <param name="x">The x.</param>
|
||||
/// <param name="modulus">The modulus.</param>
|
||||
/// <returns></returns>
|
||||
private static int Remainder(int x, int modulus)
|
||||
{
|
||||
int rem = x % modulus;
|
||||
while (rem < 0)
|
||||
{
|
||||
rem += modulus;
|
||||
}
|
||||
return rem;
|
||||
}
|
||||
|
||||
private static Vertices AddTriangle(Triangle t, Vertices vertices)
|
||||
{
|
||||
// First, find vertices that connect
|
||||
int firstP = -1;
|
||||
int firstT = -1;
|
||||
int secondP = -1;
|
||||
int secondT = -1;
|
||||
for (int i = 0; i < vertices.Count; i++)
|
||||
{
|
||||
if (t.X[0] == vertices[i].X && t.Y[0] == vertices[i].Y)
|
||||
{
|
||||
if (firstP == -1)
|
||||
{
|
||||
firstP = i;
|
||||
firstT = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
secondP = i;
|
||||
secondT = 0;
|
||||
}
|
||||
}
|
||||
else if (t.X[1] == vertices[i].X && t.Y[1] == vertices[i].Y)
|
||||
{
|
||||
if (firstP == -1)
|
||||
{
|
||||
firstP = i;
|
||||
firstT = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
secondP = i;
|
||||
secondT = 1;
|
||||
}
|
||||
}
|
||||
else if (t.X[2] == vertices[i].X && t.Y[2] == vertices[i].Y)
|
||||
{
|
||||
if (firstP == -1)
|
||||
{
|
||||
firstP = i;
|
||||
firstT = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
secondP = i;
|
||||
secondT = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fix ordering if first should be last vertex of poly
|
||||
if (firstP == 0 && secondP == vertices.Count - 1)
|
||||
{
|
||||
firstP = vertices.Count - 1;
|
||||
secondP = 0;
|
||||
}
|
||||
|
||||
// Didn't find it
|
||||
if (secondP == -1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find tip index on triangle
|
||||
int tipT = 0;
|
||||
if (tipT == firstT || tipT == secondT)
|
||||
tipT = 1;
|
||||
if (tipT == firstT || tipT == secondT)
|
||||
tipT = 2;
|
||||
|
||||
Vertices result = new Vertices(vertices.Count + 1);
|
||||
for (int i = 0; i < vertices.Count; i++)
|
||||
{
|
||||
result.Add(vertices[i]);
|
||||
|
||||
if (i == firstP)
|
||||
result.Add(new Vector2(t.X[tipT], t.Y[tipT]));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if vertex i is the tip of an ear in polygon defined by xv[] and
|
||||
/// yv[].
|
||||
///
|
||||
/// Assumes clockwise orientation of polygon...ick
|
||||
/// </summary>
|
||||
/// <param name="i">The i.</param>
|
||||
/// <param name="xv">The xv.</param>
|
||||
/// <param name="yv">The yv.</param>
|
||||
/// <param name="xvLength">Length of the xv.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified i is ear; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
private static bool IsEar(int i, float[] xv, float[] yv, int xvLength)
|
||||
{
|
||||
float dx0, dy0, dx1, dy1;
|
||||
if (i >= xvLength || i < 0 || xvLength < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int upper = i + 1;
|
||||
int lower = i - 1;
|
||||
if (i == 0)
|
||||
{
|
||||
dx0 = xv[0] - xv[xvLength - 1];
|
||||
dy0 = yv[0] - yv[xvLength - 1];
|
||||
dx1 = xv[1] - xv[0];
|
||||
dy1 = yv[1] - yv[0];
|
||||
lower = xvLength - 1;
|
||||
}
|
||||
else if (i == xvLength - 1)
|
||||
{
|
||||
dx0 = xv[i] - xv[i - 1];
|
||||
dy0 = yv[i] - yv[i - 1];
|
||||
dx1 = xv[0] - xv[i];
|
||||
dy1 = yv[0] - yv[i];
|
||||
upper = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dx0 = xv[i] - xv[i - 1];
|
||||
dy0 = yv[i] - yv[i - 1];
|
||||
dx1 = xv[i + 1] - xv[i];
|
||||
dy1 = yv[i + 1] - yv[i];
|
||||
}
|
||||
float cross = dx0 * dy1 - dx1 * dy0;
|
||||
if (cross > 0)
|
||||
return false;
|
||||
Triangle myTri = new Triangle(xv[i], yv[i], xv[upper], yv[upper],
|
||||
xv[lower], yv[lower]);
|
||||
for (int j = 0; j < xvLength; ++j)
|
||||
{
|
||||
if (j == i || j == lower || j == upper)
|
||||
continue;
|
||||
if (myTri.IsInside(xv[j], yv[j]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class Triangle
|
||||
{
|
||||
public float[] X;
|
||||
public float[] Y;
|
||||
|
||||
//Constructor automatically fixes orientation to ccw
|
||||
public Triangle(float x1, float y1, float x2, float y2, float x3, float y3)
|
||||
{
|
||||
X = new float[3];
|
||||
Y = new float[3];
|
||||
float dx1 = x2 - x1;
|
||||
float dx2 = x3 - x1;
|
||||
float dy1 = y2 - y1;
|
||||
float dy2 = y3 - y1;
|
||||
float cross = dx1 * dy2 - dx2 * dy1;
|
||||
bool ccw = (cross > 0);
|
||||
if (ccw)
|
||||
{
|
||||
X[0] = x1;
|
||||
X[1] = x2;
|
||||
X[2] = x3;
|
||||
Y[0] = y1;
|
||||
Y[1] = y2;
|
||||
Y[2] = y3;
|
||||
}
|
||||
else
|
||||
{
|
||||
X[0] = x1;
|
||||
X[1] = x3;
|
||||
X[2] = x2;
|
||||
Y[0] = y1;
|
||||
Y[1] = y3;
|
||||
Y[2] = y2;
|
||||
}
|
||||
}
|
||||
|
||||
public Triangle(Triangle t)
|
||||
{
|
||||
X = new float[3];
|
||||
Y = new float[3];
|
||||
|
||||
X[0] = t.X[0];
|
||||
X[1] = t.X[1];
|
||||
X[2] = t.X[2];
|
||||
Y[0] = t.Y[0];
|
||||
Y[1] = t.Y[1];
|
||||
Y[2] = t.Y[2];
|
||||
}
|
||||
|
||||
public bool IsInside(float x, float y)
|
||||
{
|
||||
if (x < X[0] && x < X[1] && x < X[2]) return false;
|
||||
if (x > X[0] && x > X[1] && x > X[2]) return false;
|
||||
if (y < Y[0] && y < Y[1] && y < Y[2]) return false;
|
||||
if (y > Y[0] && y > Y[1] && y > Y[2]) return false;
|
||||
|
||||
float vx2 = x - X[0];
|
||||
float vy2 = y - Y[0];
|
||||
float vx1 = X[1] - X[0];
|
||||
float vy1 = Y[1] - Y[0];
|
||||
float vx0 = X[2] - X[0];
|
||||
float vy0 = Y[2] - Y[0];
|
||||
|
||||
float dot00 = vx0 * vx0 + vy0 * vy0;
|
||||
float dot01 = vx0 * vx1 + vy0 * vy1;
|
||||
float dot02 = vx0 * vx2 + vy0 * vy2;
|
||||
float dot11 = vx1 * vx1 + vy1 * vy1;
|
||||
float dot12 = vx1 * vx2 + vy1 * vy2;
|
||||
float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
|
||||
float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
|
||||
float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
|
||||
|
||||
return ((u > 0) && (v > 0) && (u + v < 1));
|
||||
}
|
||||
}
|
||||
}
|
160
axios/Common/Decomposition/FlipcodeDecomposer.cs
Normal file
160
axios/Common/Decomposition/FlipcodeDecomposer.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FarseerPhysics.Common.Decomposition
|
||||
{
|
||||
// Original code can be found here: http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml
|
||||
|
||||
/// <summary>
|
||||
/// Triangulates a polygon into triangles.
|
||||
/// Doesn't handle holes.
|
||||
/// </summary>
|
||||
public static class FlipcodeDecomposer
|
||||
{
|
||||
private static Vector2 _tmpA;
|
||||
private static Vector2 _tmpB;
|
||||
private static Vector2 _tmpC;
|
||||
|
||||
/// <summary>
|
||||
/// Check if the point P is inside the triangle defined by
|
||||
/// the points A, B, C
|
||||
/// </summary>
|
||||
/// <param name="a">The A point.</param>
|
||||
/// <param name="b">The B point.</param>
|
||||
/// <param name="c">The C point.</param>
|
||||
/// <param name="p">The point to be tested.</param>
|
||||
/// <returns>True if the point is inside the triangle</returns>
|
||||
private static bool InsideTriangle(ref Vector2 a, ref Vector2 b, ref Vector2 c, ref Vector2 p)
|
||||
{
|
||||
//A cross bp
|
||||
float abp = (c.X - b.X) * (p.Y - b.Y) - (c.Y - b.Y) * (p.X - b.X);
|
||||
|
||||
//A cross ap
|
||||
float aap = (b.X - a.X) * (p.Y - a.Y) - (b.Y - a.Y) * (p.X - a.X);
|
||||
|
||||
//b cross cp
|
||||
float bcp = (a.X - c.X) * (p.Y - c.Y) - (a.Y - c.Y) * (p.X - c.X);
|
||||
|
||||
return ((abp >= 0.0f) && (bcp >= 0.0f) && (aap >= 0.0f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cut a the contour and add a triangle into V to describe the
|
||||
/// location of the cut
|
||||
/// </summary>
|
||||
/// <param name="contour">The list of points defining the polygon</param>
|
||||
/// <param name="u">The index of the first point</param>
|
||||
/// <param name="v">The index of the second point</param>
|
||||
/// <param name="w">The index of the third point</param>
|
||||
/// <param name="n">The number of elements in the array.</param>
|
||||
/// <param name="V">The array to populate with indicies of triangles.</param>
|
||||
/// <returns>True if a triangle was found</returns>
|
||||
private static bool Snip(Vertices contour, int u, int v, int w, int n,
|
||||
int[] V)
|
||||
{
|
||||
if (Settings.Epsilon > MathUtils.Area(ref _tmpA, ref _tmpB, ref _tmpC))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int p = 0; p < n; p++)
|
||||
{
|
||||
if ((p == u) || (p == v) || (p == w))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector2 point = contour[V[p]];
|
||||
|
||||
if (InsideTriangle(ref _tmpA, ref _tmpB, ref _tmpC, ref point))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decompose the polygon into triangles
|
||||
/// </summary>
|
||||
/// <param name="contour">The list of points describing the polygon</param>
|
||||
/// <returns></returns>
|
||||
public static List<Vertices> ConvexPartition(Vertices contour)
|
||||
{
|
||||
int n = contour.Count;
|
||||
if (n < 3)
|
||||
return new List<Vertices>();
|
||||
|
||||
int[] V = new int[n];
|
||||
|
||||
// We want a counter-clockwise polygon in V
|
||||
if (contour.IsCounterClockWise())
|
||||
{
|
||||
for (int v = 0; v < n; v++)
|
||||
V[v] = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int v = 0; v < n; v++)
|
||||
V[v] = (n - 1) - v;
|
||||
}
|
||||
|
||||
int nv = n;
|
||||
|
||||
// Remove nv-2 Vertices, creating 1 triangle every time
|
||||
int count = 2 * nv; /* error detection */
|
||||
|
||||
List<Vertices> result = new List<Vertices>();
|
||||
|
||||
for (int v = nv - 1; nv > 2; )
|
||||
{
|
||||
// If we loop, it is probably a non-simple polygon
|
||||
if (0 >= (count--))
|
||||
{
|
||||
// Triangulate: ERROR - probable bad polygon!
|
||||
return new List<Vertices>();
|
||||
}
|
||||
|
||||
// Three consecutive vertices in current polygon, <u,v,w>
|
||||
int u = v;
|
||||
if (nv <= u)
|
||||
u = 0; // Previous
|
||||
v = u + 1;
|
||||
if (nv <= v)
|
||||
v = 0; // New v
|
||||
int w = v + 1;
|
||||
if (nv <= w)
|
||||
w = 0; // Next
|
||||
|
||||
_tmpA = contour[V[u]];
|
||||
_tmpB = contour[V[v]];
|
||||
_tmpC = contour[V[w]];
|
||||
|
||||
if (Snip(contour, u, v, w, nv, V))
|
||||
{
|
||||
int s, t;
|
||||
|
||||
// Output Triangle
|
||||
Vertices triangle = new Vertices(3);
|
||||
triangle.Add(_tmpA);
|
||||
triangle.Add(_tmpB);
|
||||
triangle.Add(_tmpC);
|
||||
result.Add(triangle);
|
||||
|
||||
// Remove v from remaining polygon
|
||||
for (s = v, t = v + 1; t < nv; s++, t++)
|
||||
{
|
||||
V[s] = V[t];
|
||||
}
|
||||
nv--;
|
||||
|
||||
// Reset error detection counter
|
||||
count = 2 * nv;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
1057
axios/Common/Decomposition/SeidelDecomposer.cs
Normal file
1057
axios/Common/Decomposition/SeidelDecomposer.cs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user