protected List <EdgeType[]> CollectChildLoops(SubdividableEdgeLoop <EdgeType> parent, List <DividingEdge> dividingEdges) { List <EdgeType> knownEdges = new List <EdgeType>(parent.GetEdgesEnumerable()); Polygon parentPoly = parent.GetPolygon(); Path polygonAsClip = parentPoly.ClipperPath(HelperFunctions.clipperScale); Vector2[] parentPoints = parent.GetPoints(); //kinda ugly, these two variables are implicitly paired together Paths edgePaths = new Paths(); List <ILinkedGraphEdgeFactory <EdgeType> > edgePathFactories = new List <ILinkedGraphEdgeFactory <EdgeType> >(); List <System.Object[]> edgePathFactoriesParams = new List <System.Object[]>(); foreach (DividingEdge edge in dividingEdges) { Path edgePath = new Path(); edgePath.Add(HelperFunctions.GetIntPoint(edge.p1)); edgePath.Add(HelperFunctions.GetIntPoint(edge.p2)); PolyTree clippedResults = new PolyTree(); Clipper clipper = new Clipper(); clipper.AddPath(edgePath, PolyType.ptSubject, false); clipper.AddPath(polygonAsClip, PolyType.ptClip, true); clipper.Execute(ClipType.ctIntersection, clippedResults); Paths subPaths = Clipper.OpenPathsFromPolyTree(clippedResults); edgePaths.AddRange(subPaths); //if this edge was split into multiple paths when intersecting with parent poly, note that each subpath has the same factory foreach (Path path in subPaths) { edgePathFactories.Add(edge.factory); edgePathFactoriesParams.Add(edge.factoryParams); } } DebugLines debug = GameObject.FindObjectOfType <DebugLines>(); int totalAddedEdges = 0; for (int j = 0; j < edgePaths.Count; j++) { Path edgePath = edgePaths[j]; ILinkedGraphEdgeFactory <EdgeType> edgeFactory = edgePathFactories[j]; System.Object[] edgeParams = edgePathFactoriesParams[j]; //this is almost always just 2 elements in which case it runs once for (int i = 0; i < edgePath.Count - 1; i++) { //convert path back into regular coordinates. Watch out that there is high enough resolution //that when this conversion happens, the linkedGraph still thinks points/edges are adjacent and connects them Vector2 p1 = HelperFunctions.GetPoint(edgePath[i]); Vector2 p2 = HelperFunctions.GetPoint(edgePath[i + 1]); LinkedGraph <EdgeType> .ConnectNewEdge(p1, p2, edgeFactory, edgeParams, knownEdges); totalAddedEdges++; } } List <EdgeType[]> formedChildLoops = parent.GetInteriorEdgeLoops(); if (formedChildLoops.Count == 0) { Debug.Log("No Children " + parent.GetHashCode()); } return(formedChildLoops); }
public override List <SubdividableEdgeLoop <CityEdge> > GetChildren(SubdividableEdgeLoop <CityEdge> parent) { Polygon parentPoly = parent.GetPolygon(); Path polygonAsClip = parentPoly.ClipperPath(HelperFunctions.clipperScale); CityEdge[] edges = parent.GetEdges(); //------------------------------------------ OLD BAD STUFF //Paths edgePaths = new Paths(); //Paths expandedLine = new Paths(); //float width = 2f; //ClipperOffset clipperOffset = new ClipperOffset(); //clipperOffset.AddPath(polygonAsClip, JoinType.jtSquare, EndType.etClosedPolygon); //clipperOffset.Execute(ref expandedLine, HelperFunctions.clipperScale * (-width / 2)); //if (expandedLine.Count > 0) //{ // Path shrunkPoly = expandedLine[0]; // LinkedGraphVertex[] subPlotVerts = new LinkedGraphVertex[shrunkPoly.Count]; // for (int i = 0; i < shrunkPoly.Count; i++) // { // subPlotVerts[i] = new LinkedGraphVertex(HelperFunctions.GetPoint(shrunkPoly[i])); // } // CityEdge[] subPlotEdges = new CityEdge[shrunkPoly.Count]; // for (int i = 0; i < shrunkPoly.Count; i++) // { // subPlotEdges[i] = new CityEdge(subPlotVerts[i], subPlotVerts[(i + 1) % shrunkPoly.Count], CityEdgeType.PlotBoundary, 0f); // } // SubdividableEdgeLoop<CityEdge> plot = parent.GetNextChild(subPlotEdges); // Polygon plotPoly = parent.GetPolygon(); // return new List<SubdividableEdgeLoop<CityEdge>> { plot }; //} //return new List<SubdividableEdgeLoop<CityEdge>>(); //--------------------------------------------------------------------------- OLD BAD STUFF END bool shapeRemains = true; //int uniqueEdgeStartEdge = -1; //for (int i = 0; i < edges.Length; i ++) //{ // if (!edges[(i+1)%edges.Length].GetID().Equals(edges[i].GetID())) // { // uniqueEdgeStartEdge = (i + 1) % edges.Length; // break; // } //} //LinkedGraphVertex anchorVert = edges[uniqueEdgeStartEdge].GetOppositeVertex(edges[uniqueEdgeStartEdge].GetSharedVertex(edges[(uniqueEdgeStartEdge+1)%edges.Length])); //LinkedGraphVertex previusVert = null; for (int j = 0; j < edges.Length; j++) { CityEdge edge = edges[j]; //int nextIndex = (j + uniqueEdgeStartEdge + 1) % edges.Length; //LinkedGraphVertex thisVert = edge.GetOppositeVertex() Path edgeLine = new Path(); edgeLine.Add(HelperFunctions.GetIntPoint(edge.a.pt)); edgeLine.Add(HelperFunctions.GetIntPoint(edge.b.pt)); Paths expandedLine = new Paths(); float width = edge.GetWidth() * HelperFunctions.clipperScale; ClipperOffset clipperOffset = new ClipperOffset(); clipperOffset.AddPath(edgeLine, JoinType.jtMiter, EndType.etOpenSquare); clipperOffset.Execute(ref expandedLine, width / 2); //since we only expand a single line, we should only have one path left Paths differenceSolution = new Paths(); Clipper clipper = new Clipper(); clipper.AddPath(polygonAsClip, PolyType.ptSubject, true); clipper.AddPath(expandedLine[0], PolyType.ptClip, true); clipper.Execute(ClipType.ctDifference, differenceSolution); //Debug.Log("diff sol count: " + differenceSolution.Count); if (differenceSolution.Count == 0) { shapeRemains = false; break; } else { Path maxAreaPath = null; float maxArea = 0f; foreach (Path path in differenceSolution) { Vector2[] points = new Vector2[path.Count]; int i = 0; foreach (IntPoint p in path) { points[i] = HelperFunctions.GetPoint(p); i++; } Polygon testPoly = new Polygon(points); if (testPoly.area > maxArea) { maxArea = testPoly.area; maxAreaPath = path; } } polygonAsClip = maxAreaPath; if (maxAreaPath == null) { shapeRemains = false; break; } } } if (shapeRemains) { for (int i = polygonAsClip.Count - 1; i >= 0; i--) { for (int j = 0; j < i; j++) { if (polygonAsClip[i].X == polygonAsClip[j].X && polygonAsClip[i].Y == polygonAsClip[j].Y) { polygonAsClip.RemoveAt(i); Debug.Log("removed dup of interior plot"); } } } } Vector2[] parentPoints = parent.GetPoints(); ILinkedGraphEdgeFactory <CityEdge> factory = new CityEdgeFactory(); System.Object[] roadCapBoundarySettings = new System.Object[] { CityEdgeType.EdgeCap, 0f }; System.Object[] plotBoundarySettings = new System.Object[] { CityEdgeType.PlotBoundary, 0f }; if (shapeRemains && polygonAsClip.Count > 0) { List <DividingEdge> dividingEdges = new List <DividingEdge>(); Vector2[] subPlotVerts = new Vector2[polygonAsClip.Count]; for (int i = 0; i < polygonAsClip.Count; i++) { subPlotVerts[i] = HelperFunctions.GetPoint(polygonAsClip[i]); } List <CityEdge> knownEdges = new List <CityEdge>(parent.GetEdgesEnumerable()); for (int i = 0; i < parentPoints.Length; i++) { float closestVertDistance = float.MaxValue; int closestVertIndex = -1; for (int j = 0; j < subPlotVerts.Length; j++) { float thisDist = (parentPoints[i] - subPlotVerts[j]).sqrMagnitude; if (thisDist < closestVertDistance) { closestVertDistance = thisDist; closestVertIndex = j; } } dividingEdges.Add(new DividingEdge(parentPoints[i], subPlotVerts[closestVertIndex], factory, roadCapBoundarySettings)); } for (int i = 0; i < subPlotVerts.Length; i++) { dividingEdges.Add(new DividingEdge(subPlotVerts[i], subPlotVerts[(i + 1) % subPlotVerts.Length], factory, plotBoundarySettings)); } List <CityEdge[]> formedChildRegions = CollectChildLoops(parent, dividingEdges); List <SubdividableEdgeLoop <CityEdge> > children = new List <SubdividableEdgeLoop <CityEdge> >(); for (int i = 0; i < formedChildRegions.Count; i++) { CityEdge[] loop = formedChildRegions[i]; bool allPlotBoundaries = true; for (int j = 0; j < loop.Length; j++) { if (loop[j].GetRoadType() != CityEdgeType.PlotBoundary) { allPlotBoundaries = false; } } if (allPlotBoundaries) { children.Add(parent.GetNextChild(loop)); } else { children.Add(new Road(loop, city)); } } return(children); //return new List<SubdividableEdgeLoop<CityEdge>>(); } return(new List <SubdividableEdgeLoop <CityEdge> >()); }