// A parent is a shape which fully contains another shape public bool IsParentOf(CompositeShapeData 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(CompositeShapeData 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); }
// Checks if any of the line segments making up this shape intersect public bool IntersectsWithSelf() { for (int i = 0; i < points.Length; i++) { LineSegment segA = new LineSegment(points[i], points[(i + 1) % points.Length]); for (int j = i + 2; j < points.Length; j++) { if ((j + 1) % points.Length == i) { continue; } LineSegment segB = new LineSegment(points[j], points[(j + 1) % points.Length]); if (Maths2D.LineSegmentsIntersect(segA.a, segA.b, segB.a, segB.b)) { return(true); } } } return(false); }
void SetInnerRing(Vector3[] verts, List <Vector3> validQuads, List <Vector3> validTris) { bool isClosed = verts[0] == verts[verts.Length - 1]; Vector2[] points = new List <Vector2>(verts.Select(v => new Vector2(v.x, v.z))).GetRange(0, verts.Count() - (isClosed ? 1 : 0)).ToArray(); debugList = new List <Vector3>(); List <Vector3> pathVerts = new List <Vector3>(); if (points.Length >= 3) { Polygon polygon = new Polygon(points); int[] triangles = new Triangulator(polygon).Triangulate(); Vector3 min = GetScaledMin(); for (float i = min.x; i < bounds.max.x; i += gridScale) { for (float j = min.z; j < bounds.max.z; j += gridScale) { bool intersects1 = false; bool intersects2 = false; bool intersects34 = false; for (int k = 0; k < outerRing.Count - 1; k++) { if (Maths2D.LineSegmentsIntersect(new Vector2(i, j), new Vector2(i + gridScale, j), new Vector2(outerRing[k].x, outerRing[k].z), new Vector2(outerRing[k + 1].x, outerRing[k + 1].z))) { intersects1 = true; break; } if (Maths2D.LineSegmentsIntersect(new Vector2(i, j), new Vector2(i, j + gridScale), new Vector2(outerRing[k].x, outerRing[k].z), new Vector2(outerRing[k + 1].x, outerRing[k + 1].z))) { intersects2 = true; break; } if (Maths2D.LineSegmentsIntersect(new Vector2(i + gridScale, j), new Vector2(i + gridScale, j + gridScale), new Vector2(outerRing[k].x, outerRing[k].z), new Vector2(outerRing[k + 1].x, outerRing[k + 1].z)) || Maths2D.LineSegmentsIntersect(new Vector2(i, j + gridScale), new Vector2(i + gridScale, j + gridScale), new Vector2(outerRing[k].x, outerRing[k].z), new Vector2(outerRing[k + 1].x, outerRing[k + 1].z))) { intersects34 = true; } } if (intersects1) { if (PointInTriangles(polygon.points, triangles, new Vector2(i, j))) { pathVerts.Add(new Vector3(i, pathHeight, j)); } if (PointInTriangles(polygon.points, triangles, new Vector2(i + gridScale, j))) { pathVerts.Add(new Vector3(i + gridScale, pathHeight, j)); } } else if (intersects2) { if (PointInTriangles(polygon.points, triangles, new Vector2(i, j))) { pathVerts.Add(new Vector3(i, pathHeight, j)); } if (PointInTriangles(polygon.points, triangles, new Vector2(i, j + gridScale))) { pathVerts.Add(new Vector3(i, pathHeight, j + gridScale)); } } else if (!intersects34 && PointInTriangles(polygon.points, triangles, new Vector2(i, j))) { validQuads.Add(new Vector3(i, pathHeight, j)); } if (intersects1 || intersects2 || intersects34) { List <Vector3> possibleTris = new List <Vector3>(); if (PointInTriangles(polygon.points, triangles, new Vector2(i, j))) { possibleTris.Add(new Vector3(i, pathHeight, j)); } if (PointInTriangles(polygon.points, triangles, new Vector2(i + gridScale, j))) { possibleTris.Add(new Vector3(i + gridScale, pathHeight, j)); } if (PointInTriangles(polygon.points, triangles, new Vector2(i, j + gridScale))) { possibleTris.Add(new Vector3(i, pathHeight, j + gridScale)); } if (PointInTriangles(polygon.points, triangles, new Vector2(i + gridScale, j + gridScale))) { possibleTris.Add(new Vector3(i + gridScale, pathHeight, j + gridScale)); } if (possibleTris.Count == 3) { validTris.AddRange(possibleTris); } if (possibleTris.Count == 2) { if (!possibleTris.Contains(new Vector3(i, pathHeight, j)) && !possibleTris.Contains(new Vector3(i + gridScale, pathHeight, j)) && PointInTriangles(polygon.points, triangles, new Vector2(i + gridScale + gridScale, j))) { pathVerts.Add(possibleTris[1]); //validTris.AddRange(new Vector3[] { possibleTris[0], possibleTris[1], new Vector3(i + gridScale + gridScale, 0, j) }); } /* * if (!possibleTris.Contains(new Vector3(i + gridScale, 0, j)) && !possibleTris.Contains(new Vector3(i + gridScale, 0, j + gridScale)) && * PointInTriangles(polygon.points, triangles, new Vector2(i + gridScale, j - gridScale)) && !PointInTriangles(polygon.points, triangles, new Vector2(i, j + gridScale + gridScale))) { * //validTris.AddRange(new Vector3[] { possibleTris[0], possibleTris[1], new Vector3(i + gridScale, 0, j - gridScale) }); * }*/ } } } } pathVerts = Utility.TrimDuplicates(pathVerts); innerRing = new List <Vector3> { pathVerts[0] }; Vector3 previous = pathVerts[0]; int reverseCount = pathVerts.Count; //if (debug) debugList.Add(pathVerts[0]); pathVerts.RemoveAt(0); while (pathVerts.Count > 0 && reverseCount > 0) { Vector3 closest = previous; foreach (Vector3 vert in pathVerts) { if (Vector3.Distance(previous, vert) < gridScale * 1.1f) { closest = vert; break; } } if (closest == previous) { foreach (Vector3 vert in pathVerts) { if (Vector3.Distance(previous, vert) < gridScale * 1.5f) { closest = vert; break; } } } if (closest != previous) { innerRing.Add(closest); pathVerts.Remove(closest); if (debug) { debugList.Add(closest); } previous = closest; } else { --reverseCount; innerRing.Reverse(); previous = innerRing[innerRing.Count - 1]; } } if (pathVerts.Count > 0) { for (int i = 0; i < pathVerts.Count; i++) { debugSegList.Add(new LineSegment(pathVerts[i], pathVerts[i] + Vector3.up * 10)); } innerRing.AddRange(pathVerts); print("Verts Left: " + pathVerts.Count); } if (Vector3.Distance(innerRing[0], Utility.NoY(outerRing[0])) > gridScale * 1.5f && !isClosed) { innerRing.Reverse(); } } }