// A parent is a shape which fully contains another shape public bool IsParentOf(CompositeSolidShapeData otherShape) { if (otherShape.parents.Contains(this)) { return(true); } if (parents.Contains(otherShape)) { return(false); } // check if first point in otherShape is inside this shape. If not, parent test fails. // if yes, then continue to line seg intersection test between the two shapes // (this point test is important because without it, if all line seg intersection tests fail, // we wouldn't know if otherShape is entirely inside or entirely outside of this shape) bool pointInsideShape = false; for (int i = 0; i < triangles.Length; i += 3) { if (Maths2D.PointInTriangle(polygon.points[triangles[i]], polygon.points[triangles[i + 1]], polygon.points[triangles[i + 2]], otherShape.points[0])) { pointInsideShape = true; break; } } if (!pointInsideShape) { return(false); } // Check for intersections between line segs of this shape and otherShape (any intersections will fail the parent test) for (int i = 0; i < points.Length; i++) { LineSegment parentSeg = new LineSegment(points[i], points[(i + 1) % points.Length]); for (int j = 0; j < otherShape.points.Length; j++) { LineSegment childSeg = new LineSegment(otherShape.points[j], otherShape.points[(j + 1) % otherShape.points.Length]); if (Maths2D.LineSegmentsIntersect(parentSeg.a, parentSeg.b, childSeg.a, childSeg.b)) { return(false); } } } return(true); }
// Test if the shapes overlap partially (test will fail if one shape entirely contains other shape, i.e. one is parent of the other). public bool OverlapsPartially(CompositeSolidShapeData otherShape) { // Check for intersections between line segs of this shape and otherShape (any intersection will validate the overlap test) for (int i = 0; i < points.Length; i++) { LineSegment segA = new LineSegment(points[i], points[(i + 1) % points.Length]); for (int j = 0; j < otherShape.points.Length; j++) { LineSegment segB = new LineSegment(otherShape.points[j], otherShape.points[(j + 1) % otherShape.points.Length]); if (Maths2D.LineSegmentsIntersect(segA.a, segA.b, segB.a, segB.b)) { return(true); } } } return(false); }
public void Process() { // Generate array of valid shape data CompositeSolidShapeData[] eligibleShapes = shapes.Select(x => new CompositeSolidShapeData(x.points.ToArray())).Where(x => x.IsValidShape).ToArray(); // Set parents for all shapes. A parent is a shape which completely contains another shape. for (int i = 0; i < eligibleShapes.Length; i++) { for (int j = 0; j < eligibleShapes.Length; j++) { if (i == j) { continue; } if (eligibleShapes[i].IsParentOf(eligibleShapes[j])) { eligibleShapes[j].parents.Add(eligibleShapes[i]); } } } // Holes are shapes with an odd number of parents. CompositeSolidShapeData[] holeShapes = eligibleShapes.Where(x => x.parents.Count % 2 != 0).ToArray(); foreach (CompositeSolidShapeData holeShape in holeShapes) { // The most immediate parent (i.e the smallest parent shape) will be the one that has the highest number of parents of its own. CompositeSolidShapeData immediateParent = holeShape.parents.OrderByDescending(x => x.parents.Count).First(); immediateParent.holes.Add(holeShape); } // Solid shapes have an even number of parents CompositeSolidShapeData[] solidShapes = eligibleShapes.Where(x => x.parents.Count % 2 == 0).ToArray(); foreach (CompositeSolidShapeData solidShape in solidShapes) { solidShape.ValidateHoles(); } // Create polygons from the solid shapes and their associated hole shapes Polygon[] polygons = solidShapes.Select(x => new Polygon(x.polygon.points, x.holes.Select(h => h.polygon.points).ToArray())).ToArray(); // Flatten the points arrays from all polygons into a single array, and convert the vector2s to vector3s. vertices = polygons.SelectMany(x => x.points.Select(v2 => new Vector3(v2.x, height, v2.y))).ToArray(); // Triangulate each polygon and flatten the triangle arrays into a single array. List <int> allTriangles = new List <int>(); int startVertexIndex = 0; for (int i = 0; i < polygons.Length; i++) { Triangulator triangulator = new Triangulator(polygons[i]); int[] polygonTriangles = triangulator.Triangulate(); for (int j = 0; j < polygonTriangles.Length; j++) { allTriangles.Add(polygonTriangles[j] + startVertexIndex); } startVertexIndex += polygons[i].numPoints; } triangles = allTriangles.ToArray(); }