/** * @brief Returns the first {@link TSCollider2D} within a rectangular area. Returns null if there is none. * * @param pointA Top-left corner of the rectangle. * @param radius Bottom-right corner of the rectangle. * @param layerMask Unity's layer mask to filter objects. **/ public static object _OverlapArea(TSVector2 pointA, TSVector2 pointB, Physics2D.BodySpecialSensor sensorType, int layerMask = UnityEngine.Physics.DefaultRaycastLayers) { TSVector2 center; center.x = (pointA.x + pointB.x) * FP.Half; center.y = (pointA.y + pointB.y) * FP.Half; Physics2D.Vertices vertices = new Physics2D.Vertices(4); vertices.Add(new TSVector2(pointA.x, pointA.y) - center); vertices.Add(new TSVector2(pointB.x, pointA.y) - center); vertices.Add(new TSVector2(pointB.x, pointB.y) - center); vertices.Add(new TSVector2(pointA.x, pointB.y) - center); return(OverlapGeneric(new Physics2D.PolygonShape(vertices, 1), center, sensorType, layerMask)); }
/** * @brief Create the internal shape used to represent a PolygonCollider. **/ public override SyncFrame.Physics2D.Shape[] CreateShapes() { if (_points == null || _points.Length == 0) { return(null); } TSVector2 lossy2D = new TSVector2(lossyScale.x, lossyScale.y); SyncFrame.Physics2D.Vertices v = new Physics2D.Vertices(); for (int index = 0, length = _points.Length; index < length; index++) { v.Add(TSVector2.Scale(_points[index], lossy2D)); } List <SyncFrame.Physics2D.Vertices> convexShapeVs = SyncFrame.Physics2D.BayazitDecomposer.ConvexPartition(v); SyncFrame.Physics2D.Shape[] result = new Physics2D.Shape[convexShapeVs.Count]; for (int index = 0, length = result.Length; index < length; index++) { result[index] = new SyncFrame.Physics2D.PolygonShape(convexShapeVs[index], 1); } return(result); }
/// <summary> /// Combine a list of triangles into a list of convex polygons. /// /// Note: This only works on triangles. /// </summary> ///<param name="triangles">The triangles.</param> ///<param name="maxPolys">The maximun number of polygons to return.</param> ///<param name="tolerance">The tolerance</param> public static List <Vertices> PolygonizeTriangles(List <Vertices> triangles, int maxPolys = int.MaxValue, float tolerance = 0.001f) { if (triangles.Count <= 0) { return(triangles); } List <Vertices> polys = new List <Vertices>(); bool[] covered = new bool[triangles.Count]; for (int i = 0; i < triangles.Count; ++i) { covered[i] = false; //Check here for degenerate triangles Vertices triangle = triangles[i]; TSVector2 a = triangle[0]; TSVector2 b = triangle[1]; TSVector2 c = triangle[2]; if ((a.x == b.x && a.y == b.y) || (b.x == c.x && b.y == c.y) || (a.x == c.x && a.y == c.y)) { covered[i] = true; } } int polyIndex = 0; bool notDone = true; while (notDone) { int currTri = -1; for (int i = 0; i < triangles.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(triangles[currTri][i]); } covered[currTri] = true; int index = 0; for (int i = 0; i < 2 * triangles.Count; ++i, ++index) { while (index >= triangles.Count) { index -= triangles.Count; } if (covered[index]) { continue; } Vertices newP = AddTriangle(triangles[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 { Debug.WriteLine("Skipping corrupt poly."); } } if (poly.Count >= 3) { polyIndex++; //Must be outside (polyIndex < polysLength) test } } } //TODO: Add sanity check //Remove empty vertice collections for (int i = polys.Count - 1; i >= 0; i--) { if (polys[i].Count == 0) { polys.RemoveAt(i); } } return(polys); }
private static Vertices AddTriangle(Vertices 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[0].x == vertices[i].x && t[0].y == vertices[i].y) { if (firstP == -1) { firstP = i; firstT = 0; } else { secondP = i; secondT = 0; } } else if (t[1].x == vertices[i].x && t[1].y == vertices[i].y) { if (firstP == -1) { firstP = i; firstT = 1; } else { secondP = i; secondT = 1; } } else if (t[2].x == vertices[i].x && t[2].y == 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(t[tipT]); } } return(result); }
/// <summary> /// Returns the convex hull from the given vertices.. /// </summary> public static Vertices GetConvexHull(Vertices vertices) { if (vertices.Count <= 3) { return(vertices); } Vertices pointSet = new Vertices(vertices); //Sort by X-axis pointSet.Sort(_pointComparer); TSVector2[] h = new TSVector2[pointSet.Count]; Vertices res; int top = -1; // indices for bottom and top of the stack int i; // array scan index // Get the indices of points with min x-coord and min|max y-coord const int minmin = 0; FP xmin = pointSet[0].x; for (i = 1; i < pointSet.Count; i++) { if (pointSet[i].x != xmin) { break; } } // degenerate case: all x-coords == xmin int minmax = i - 1; if (minmax == pointSet.Count - 1) { h[++top] = pointSet[minmin]; if (pointSet[minmax].y != pointSet[minmin].y) // a nontrivial segment { h[++top] = pointSet[minmax]; } h[++top] = pointSet[minmin]; // add polygon endpoint res = new Vertices(top + 1); for (int j = 0; j < top + 1; j++) { res.Add(h[j]); } return(res); } top = -1; // Get the indices of points with max x-coord and min|max y-coord int maxmax = pointSet.Count - 1; FP xmax = pointSet[pointSet.Count - 1].x; for (i = pointSet.Count - 2; i >= 0; i--) { if (pointSet[i].x != xmax) { break; } } int maxmin = i + 1; // Compute the lower hull on the stack H h[++top] = pointSet[minmin]; // push minmin point onto stack i = minmax; while (++i <= maxmin) { // the lower line joins P[minmin] with P[maxmin] if (MathUtils.Area(pointSet[minmin], pointSet[maxmin], pointSet[i]) >= 0 && i < maxmin) { continue; // ignore P[i] above or on the lower line } while (top > 0) // there are at least 2 points on the stack { // test if P[i] is left of the line at the stack top if (MathUtils.Area(h[top - 1], h[top], pointSet[i]) > 0) { break; // P[i] is a new hull vertex } top--; // pop top point off stack } h[++top] = pointSet[i]; // push P[i] onto stack } // Next, compute the upper hull on the stack H above the bottom hull if (maxmax != maxmin) // if distinct xmax points { h[++top] = pointSet[maxmax]; // push maxmax point onto stack } int bot = top; i = maxmin; while (--i >= minmax) { // the upper line joins P[maxmax] with P[minmax] if (MathUtils.Area(pointSet[maxmax], pointSet[minmax], pointSet[i]) >= 0 && i > minmax) { continue; // ignore P[i] below or on the upper line } while (top > bot) // at least 2 points on the upper stack { // test if P[i] is left of the line at the stack top if (MathUtils.Area(h[top - 1], h[top], pointSet[i]) > 0) { break; // P[i] is a new hull vertex } top--; // pop top point off stack } h[++top] = pointSet[i]; // push P[i] onto stack } if (minmax != minmin) { h[++top] = pointSet[minmin]; // push joining endpoint onto stack } res = new Vertices(top + 1); for (int j = 0; j < top + 1; j++) { res.Add(h[j]); } return(res); }