//box2D rev 32 - for details, see http://www.box2d.org/forum/viewtopic.php?f=4&t=83&start=50 /// <summary> /// Decompose the polygon into several smaller non-concave polygon. /// Each resulting polygon will have no more than Settings.MaxPolygonVertices vertices. /// </summary> /// <param name="vertices">The vertices.</param> /// <param name="tolerance">The tolerance.</param> // TS - public static List<Vertices> ConvexPartition(Vertices vertices, FP tolerance = 0.001f) public static List <Vertices> ConvexPartition(Vertices vertices, FP tolerance) { Debug.Assert(vertices.Count > 3); Debug.Assert(!vertices.IsCounterClockWise()); return(TriangulatePolygon(vertices, tolerance)); }
/// <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. /// </summary> public static List <Vertices> ConvexPartition(Vertices vertices) { vertices.ForceCounterClockWise(); Debug.Assert(vertices.Count > 3); Debug.Assert(vertices.IsCounterClockWise()); return(TriangulatePolygon(vertices)); }
/// <summary> /// Decompose the polygon into triangles. /// /// Properties: /// - Only works on counter clockwise polygons /// /// </summary> /// <param name="vertices">The list of points describing the polygon</param> public static List <Vertices> ConvexPartition(Vertices vertices) { Debug.Assert(vertices.Count > 3); Debug.Assert(vertices.IsCounterClockWise()); int[] polygon = new int[vertices.Count]; for (int v = 0; v < vertices.Count; v++) { polygon[v] = v; } int nv = vertices.Count; // 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 = vertices[polygon[u]]; _tmpB = vertices[polygon[v]]; _tmpC = vertices[polygon[w]]; if (Snip(vertices, u, v, w, nv, polygon)) { 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++) { polygon[s] = polygon[t]; } nv--; // Reset error detection counter count = 2 * nv; } } return(result); }
// TS - public static List<Vertices> ConvexPartition(Vertices vertices, TriangulationAlgorithm algorithm, bool discardAndFixInvalid = true, FP tolerance = 0.001f) public static List <Vertices> ConvexPartition(Vertices vertices, TriangulationAlgorithm algorithm, bool discardAndFixInvalid, FP tolerance) { if (vertices.Count <= 3) { return new List <Vertices> { vertices } } ; List <Vertices> results; switch (algorithm) { case TriangulationAlgorithm.Earclip: if (Settings.SkipSanityChecks) { Debug.Assert(!vertices.IsCounterClockWise(), "The Earclip algorithm expects the polygon to be clockwise."); } else { if (vertices.IsCounterClockWise()) { Vertices temp = new Vertices(vertices); temp.Reverse(); results = EarclipDecomposer.ConvexPartition(temp, tolerance); } else { results = EarclipDecomposer.ConvexPartition(vertices, tolerance); } } break; case TriangulationAlgorithm.Bayazit: if (Settings.SkipSanityChecks) { Debug.Assert(vertices.IsCounterClockWise(), "The polygon is not counter clockwise. This is needed for Bayazit to work correctly."); } else { if (!vertices.IsCounterClockWise()) { Vertices temp = new Vertices(vertices); temp.Reverse(); results = BayazitDecomposer.ConvexPartition(temp); } else { results = BayazitDecomposer.ConvexPartition(vertices); } } break; case TriangulationAlgorithm.Flipcode: if (Settings.SkipSanityChecks) { Debug.Assert(vertices.IsCounterClockWise(), "The polygon is not counter clockwise. This is needed for Bayazit to work correctly."); } else { if (!vertices.IsCounterClockWise()) { Vertices temp = new Vertices(vertices); temp.Reverse(); results = FlipcodeDecomposer.ConvexPartition(temp); } else { results = FlipcodeDecomposer.ConvexPartition(vertices); } } break; case TriangulationAlgorithm.Seidel: results = SeidelDecomposer.ConvexPartition(vertices, tolerance); break; case TriangulationAlgorithm.SeidelTrapezoids: results = SeidelDecomposer.ConvexPartitionTrapezoid(vertices, tolerance); break; case TriangulationAlgorithm.Delauny: results = CDTDecomposer.ConvexPartition(vertices); break; default: throw new ArgumentOutOfRangeException("algorithm"); } if (discardAndFixInvalid) { for (int i = results.Count - 1; i >= 0; i--) { Vertices polygon = results[i]; if (!ValidatePolygon(polygon)) { results.RemoveAt(i); } } } return(results); }