protected List <SubdividableEdgeLoop <EdgeType> > CollectChildren(SubdividableEdgeLoop <EdgeType> parent, List <DividingEdge> dividingEdges)
    {
        List <EdgeType[]> formedChildLoops = CollectChildLoops(parent, dividingEdges);
        List <SubdividableEdgeLoop <EdgeType> > children = new List <SubdividableEdgeLoop <EdgeType> >();

        foreach (EdgeType[] childLoop in formedChildLoops)
        {
            children.Add(parent.GetNextChild(childLoop));
        }
        return(children);
    }
Example #2
0
    public override List <SubdividableEdgeLoop <CityEdge> > GetChildren(SubdividableEdgeLoop <CityEdge> parent)
    {
        Polygon parentPoly    = parent.GetPolygon();
        Path    polygonAsClip = parentPoly.ClipperPath(HelperFunctions.clipperScale);

        EdgeLoopEdge[] edges             = parent.GetEdges();
        EdgeLoopEdge   longestEdge       = edges[0];
        float          longestEdgeLength = 0;

        parent.EnumerateEdges((EdgeLoopEdge edge) =>
        {
            float edgeLength = Vector2.Distance(edge.a.pt, edge.b.pt);
            if (edgeLength > longestEdgeLength)
            {
                longestEdgeLength = edgeLength;
                longestEdge       = edge;
            }
        });

        Vector2 edgeDirection = longestEdge.b.pt - longestEdge.a.pt;

        float angle        = Mathf.Atan2(edgeDirection.y, edgeDirection.x) * Mathf.Rad2Deg;
        Rect  bounds       = parentPoly.bounds;
        float maxDimension = Mathf.Max(bounds.width, bounds.height);

        bounds.width  = maxDimension;
        bounds.height = maxDimension;

        Rect expandedBounds = new Rect(bounds.center - bounds.size * 0.55f, bounds.size * 1.1f);

        ILinkedGraphEdgeFactory <CityEdge> factory = new CityEdgeFactory();
        List <DividingEdge> edgePaths = new List <DividingEdge>();
        Vector2             centroid  = parentPoly.centroid;

        float relativeBoundAngle  = 0f;
        Rect  parentRotatedBounds = HelperFunctions.GetOrientedBounds(new List <Vector2>(parentPoly.points), ref relativeBoundAngle);

        float rotation = relativeBoundAngle * Mathf.Rad2Deg;

        if (parentRotatedBounds.width > parentRotatedBounds.height * 0.7f)
        {
            //edgePaths.Add(new DividingEdge((centroid - Vector2.right * 1000f).RotatedAround(centroid, rotation), (centroid + Vector2.right * 1000f).RotatedAround(centroid, rotation), factory, factoryParams));
            edgePaths.Add(new DividingEdge((centroid - Vector2.up * 1000f).RotatedAround(centroid, rotation), (centroid + Vector2.up * 1000f).RotatedAround(centroid, rotation), factory, factoryParams));
        }
        if (parentRotatedBounds.height > parentRotatedBounds.width * 0.7f)
        {
            //edgePaths.Add(new DividingEdge((centroid - Vector2.up * 1000f).RotatedAround(centroid, rotation), (centroid + Vector2.up * 1000f).RotatedAround(centroid, rotation), factory, factoryParams));
            edgePaths.Add(new DividingEdge((centroid - Vector2.right * 1000f).RotatedAround(centroid, rotation), (centroid + Vector2.right * 1000f).RotatedAround(centroid, rotation), factory, factoryParams));
        }
        return(CollectChildren(parent, edgePaths));
    }
Example #3
0
 private void GetPlotsRecursive(SubdividableEdgeLoop <CityEdge> some, List <Plot> storage)
 {
     if (some is Plot)
     {
         storage.Add((Plot)some);
     }
     else
     {
         SubdividableEdgeLoop <CityEdge>[] children = some.GetChildren();
         foreach (SubdividableEdgeLoop <CityEdge> child in children)
         {
             GetPlotsRecursive(child, storage);
         }
     }
 }
Example #4
0
    public override List <SubdividableEdgeLoop <EdgeType> > GetChildren(SubdividableEdgeLoop <EdgeType> parent)
    {
        Polygon parentPoly = new Polygon(parent.GetSimplifiedPoints(1f * Mathf.Deg2Rad));

        //build a list of dividing edges and pass it to the child collector
        List <DividingEdge> dividingEdges = new List <DividingEdge>();

        Vector2 center = parentPoly.centroid;
        float   width  = parentPoly.bounds.width;

        Vector2 a = center + Vector2.right * width;
        Vector2 b = center - Vector2.right * width;

        dividingEdges.Add(new DividingEdge(a, b, factory, factoryParams));

        return(CollectChildren(parent, dividingEdges));
    }
Example #5
0
    public override List <SubdividableEdgeLoop <EdgeType> > GetChildren(SubdividableEdgeLoop <EdgeType> parent)
    {
        Vector2[] simplifiedPoints = parent.GetSimplifiedPoints(1f * Mathf.Deg2Rad);
        Polygon   parentPoly       = new Polygon(simplifiedPoints);
        Vector2   centroid         = parentPoly.centroid;

        float centroidDistance = parent.DistToPerimeter(centroid);

        float circleRadius = centroidDistance / 2f;

        int circleResolution = Random.Range(3, 8);
        int numRays          = Mathf.CeilToInt(circleResolution / 3f);

        Vector2[] circlePoints = new Vector2[circleResolution];
        for (int i = 0; i < circleResolution; i++)
        {
            float angle = (i / (float)circleResolution) * Mathf.PI * 2;
            circlePoints[i] = centroid + new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * circleRadius;
        }

        //build a list of dividing edges and pass it to the child collector
        List <DividingEdge> dividingEdges = new List <DividingEdge>();

        for (int i = 0; i < circleResolution; i++)
        {
            dividingEdges.Add(new DividingEdge(circlePoints[i], circlePoints[(i + 1) % circleResolution], factory, factoryParams));

            //if (i % numRays == 0)
            //{
            Vector2 extended = (circlePoints[i] - centroid) * 100f + centroid;
            dividingEdges.Add(new DividingEdge(circlePoints[i], extended, factory, factoryParams));
            //}
        }

        return(CollectChildren(parent, dividingEdges));
    }
Example #6
0
    public override List <SubdividableEdgeLoop <EdgeType> > GetChildren(SubdividableEdgeLoop <EdgeType> parent)
    {
        Vector2[]      simplifiedPoints = parent.GetSimplifiedPoints(1f * Mathf.Deg2Rad);
        Polygon        parentPoly       = new Polygon(simplifiedPoints);
        Vector2        centroid         = parentPoly.centroid;
        List <Vector2> edgeCrossings    = new List <Vector2>();

        parentPoly.EnumerateEdges((Edge edge) =>
        {
            Vector2 edgeCrossing = HelperFunctions.ScaleFrom(Vector2.Lerp(edge.a, edge.b, Random.Range(0.4f, 0.6f)), centroid, 1.5f);
            edgeCrossings.Add(edgeCrossing);
            //points.Add(HelperFunctions.ScaleFrom(edgeCrossing, centroid, 5));
        });

        //build a list of dividing edges and pass it to the child collector
        List <DividingEdge> dividingEdges = new List <DividingEdge>();

        foreach (Vector2 crossing in edgeCrossings)
        {
            dividingEdges.Add(new DividingEdge(crossing, centroid, factory, factoryParams));
        }

        return(CollectChildren(parent, dividingEdges));
    }
    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 abstract List <SubdividableEdgeLoop <EdgeType> > GetChildren(SubdividableEdgeLoop <EdgeType> parent);
Example #9
0
    public override List <SubdividableEdgeLoop <CityEdge> > GetChildren(SubdividableEdgeLoop <CityEdge> parent)
    {
        Vector2[] parentPoints = parent.GetPoints();
        Polygon   parentPoly   = parent.GetPolygon();
        //generate points of interest
        List <RoadDestination> pointsOfInterest = new List <RoadDestination>();
        Vector2 centroid = parent.GetCenter();
        //parent.EnumerateEdges((EdgeLoopEdge edge) =>
        //{
        //    pointsOfInterest.Add(new RoadDestination(Vector2.Lerp(edge.a.pt, edge.b.pt, Random.Range(0.2f, 0.8f)), 1, false, true));
        //});
        Rect bounds = parent.GetBounds();

        bounds.width  = bounds.width * 2;
        bounds.height = bounds.height * 2;
        int potentialRoadPointsRt = Mathf.CeilToInt(Mathf.Sqrt(potentialRoadPoints));

        float approxDiameter           = Mathf.Sqrt(parentPoly.area);
        float minimumPerimeterDistance = approxDiameter / 4f;

        for (int x = 0; x < potentialRoadPointsRt; x++)
        {
            for (int y = 0; y < potentialRoadPointsRt; y++)
            {
                Vector2 point = new Vector2((x / (float)potentialRoadPointsRt) * bounds.width + bounds.xMin,
                                            (y / (float)potentialRoadPointsRt) * bounds.height + bounds.yMin);
                float distBtwnPts = (bounds.width + bounds.height) / (potentialRoadPoints * 2);
                point = point + new Vector2(Random.Range(-1f, 1f), Random.Range(-1, 1f)) * distBtwnPts * 3f;

                if (parentPoly.ContainsPoint(point)) // && parent.DistToPerimeter(point) > minimumPerimeterDistance)
                {
                    pointsOfInterest.Add(new RoadDestination(point, 0, false, false));
                }
            }
        }
        pointsOfInterest.Add(new RoadDestination(bounds.center + new Vector2(bounds.width * 100, bounds.height * 100), 0, false, false));
        pointsOfInterest.Add(new RoadDestination(bounds.center + new Vector2(bounds.width * 100, -bounds.height * 100), 0, false, false));
        pointsOfInterest.Add(new RoadDestination(bounds.center + new Vector2(-bounds.width * 100, -bounds.height * 100), 0, false, false));
        pointsOfInterest.Add(new RoadDestination(bounds.center + new Vector2(-bounds.width * 100, bounds.height * 100), 0, false, false));

        //triangulate points of interest to get potential road segments
        TriangleNet.Geometry.Polygon polygon = new TriangleNet.Geometry.Polygon();
        Dictionary <TriangleNet.Geometry.Vertex, RoadDestination> vertexDestMap = new Dictionary <TriangleNet.Geometry.Vertex, RoadDestination>();

        foreach (RoadDestination dest in pointsOfInterest)
        {
            TriangleNet.Geometry.Vertex vert = new TriangleNet.Geometry.Vertex(dest.point.x, dest.point.y);
            vertexDestMap.Add(vert, dest);
            polygon.Add(vert);
        }
        TriangleNet.Meshing.ConstraintOptions options =
            new TriangleNet.Meshing.ConstraintOptions()
        {
            ConformingDelaunay = true
        };
        TriangleNet.Meshing.GenericMesher mesher = new TriangleNet.Meshing.GenericMesher();
        TriangleNet.Meshing.IMesh         mesh   = mesher.Triangulate(polygon);

        TriangleNet.Voronoi.StandardVoronoi      voronoi      = new TriangleNet.Voronoi.StandardVoronoi((TriangleNet.Mesh)mesh);
        IEnumerable <TriangleNet.Geometry.IEdge> voronoiEdges = voronoi.Edges;
        List <TriangleNet.Topology.DCEL.Vertex>  voronoiVerts = voronoi.Vertices;

        List <DividingEdge> dividingEdges          = new List <DividingEdge>();
        ILinkedGraphEdgeFactory <CityEdge> factory = new CityEdgeFactory();

        foreach (TriangleNet.Geometry.IEdge edge in voronoiEdges)
        {
            Vector2 a = new Vector2((float)voronoiVerts[edge.P0].X, (float)voronoiVerts[edge.P0].Y);
            Vector2 b = new Vector2((float)voronoiVerts[edge.P1].X, (float)voronoiVerts[edge.P1].Y);

            dividingEdges.Add(new DividingEdge(a, b, factory, factoryParams));
        }



        //get vertices as list
        //ICollection<TriangleNet.Geometry.Vertex> vertices = mesh.Vertices;
        //TriangleNet.Geometry.Vertex[] vertexList = new TriangleNet.Geometry.Vertex[vertices.Count];
        //vertices.CopyTo(vertexList, 0);
        //IEnumerable<TriangleNet.Geometry.Edge> meshEdges = mesh.Edges;


        //build a list of dividing edges and pass it to the child collector


        //foreach (TriangleNet.Geometry.Edge edge in meshEdges) {
        //    //if (vertConnections[edge.P0] > 4)
        //    //{
        //    //    vertConnections[edge.P0]--;
        //    //    continue;
        //    //}
        //    //if (vertConnections[edge.P1] > 4)
        //    //{
        //    //    vertConnections[edge.P1]--;
        //    //    continue;
        //    //}
        //    Vector2 a = new Vector2((float)vertexList[edge.P0].X, (float)vertexList[edge.P0].Y);
        //    Vector2 b = new Vector2((float)vertexList[edge.P1].X, (float)vertexList[edge.P1].Y);

        //    dividingEdges.Add(new DividingEdge(a, b, factory, CityEdgeType.LandPath));
        //}

        return(CollectChildren(parent, dividingEdges));
    }
Example #10
0
    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> >());
    }