Esempio n. 1
0
    public PolyGraph(
        int width, int height, int sparcity, int padding,
        int smoothingSteps, ICornerMode cornerMode)
    {
        this.width  = width;
        this.height = height;

        edgeIdCounter   = 0;
        cornerIdCounter = 0;

        faces   = new Dictionary <int, PolyFace>();
        corners = new Dictionary <int, PolyCorner>();
        edges   = new Dictionary <int, PolyEdge>();

        Mesh faceMesh;

        // Randomly generate a delaunay trianglulation to use as faces for the PolyGraph.
        {
            Polygon  polygon = new Polygon();
            Vertex[] bounds  = new Vertex[4] {
                new Vertex(0, 0),
                new Vertex(0, height),
                new Vertex(width, height),
                new Vertex(width, 0)
            };

            PoissonDiscSampler sampler = new PoissonDiscSampler(
                width - 2 * padding, height - 2 * padding, sparcity);


            SimpleSmoother smoother = new SimpleSmoother();

            for (int i = 0; i < 4; i++)
            {
                polygon.Add(new Segment(
                                bounds[i],
                                bounds[(i + 1) % 4],
                                1
                                ), 0);
            }

            foreach (UnityEngine.Vector2 sample in sampler.Samples())
            {
                polygon.Add(new Vertex(sample.x + padding, sample.y + padding));
            }

            faceMesh = (Mesh)polygon.Triangulate(
                new ConstraintOptions()
            {
                ConformingDelaunay = true
            });

            smoother.Smooth(faceMesh, smoothingSteps);
        }

        // Compose and add faces to face dictionary.


        foreach (Vertex vertex in faceMesh.Vertices)
        {
            int xInt = Convert.ToInt32(vertex.x);
            int yInt = Convert.ToInt32(vertex.y);

            bool x0Border = xInt == 0;
            bool x1Border = xInt == width;
            bool y0Border = yInt == 0;
            bool y1Border = yInt == height;

            PolyFace face;

            if (x0Border | x1Border | y0Border | y1Border)
            {
                Vertex borderVertex = new Vertex();
                borderVertex.x = vertex.x;
                borderVertex.y = vertex.y;

                if (x0Border)
                {
                    vertex.x += padding / 2;
                }
                if (x1Border)
                {
                    vertex.x -= padding / 2;
                }
                if (y0Border)
                {
                    vertex.y += padding / 2;
                }
                if (y1Border)
                {
                    vertex.y -= padding / 2;
                }

                PolyCorner borderCorner = new PolyCorner(cornerIdCounter++, borderVertex);
                face = new PolyFace(vertex);
                face.borderCorner = borderCorner;

                if ((x0Border?1:0) + (x1Border?1:0) + (y0Border?1:0) + (y1Border?1:0) == 2)
                {
                    face.isFaceBorderCorner = true;
                }

                borderCorner.surroundingFaces.Add(face);
                face.surroundingCorners.Add(borderCorner);

                corners.Add(borderCorner.id, borderCorner);
            }
            else
            {
                face = new PolyFace(vertex);
            }

            faces.Add(face.id, face);
        }

        foreach (Triangle triangle in faceMesh.triangles)
        {
            // Compose corner dicitonary from remaining faces.
            PolyCorner corner = new PolyCorner(cornerIdCounter++, triangle, cornerMode);

            foreach (Vertex faceVertex in triangle.vertices)
            {
                PolyFace face = faces[faceVertex.id];

                face.surroundingCorners.Add(corner);
                corner.surroundingFaces.Add(face);
            }
            corners.Add(corner.id, corner);
        }

        // Compose and add edges to edge dictionary.
        foreach (TriangleNet.Geometry.Edge meshEdge in faceMesh.Edges)
        {
            // Add pointers between corners faces and edges.
            PolyFace face0 = faces[meshEdge.P0];
            PolyFace face1 = faces[meshEdge.P1];

            face0.neighbouringFaces.Add(face1);
            face1.neighbouringFaces.Add(face0);

            PolyEdge edge = new PolyEdge(edgeIdCounter++, face0, face1);
            edges.Add(edge.id, edge);

            face0.surroundingEdges.Add(edge);
            face1.surroundingEdges.Add(edge);

            foreach (PolyCorner corner in face0.surroundingCorners)
            {
                if (face1.surroundingCorners.Contains(corner))
                {
                    edge.surroundingCorners.Add(corner);
                    corner.surroundingEdges.Add(edge);
                }
            }

            if (edge.surroundingCorners.Count == 1)
            {
                PolyCorner faceCorner0 = face0.borderCorner;
                PolyCorner faceCorner1 = face1.borderCorner;

                Vertex f0 = faceCorner0.vertex;
                Vertex f1 = faceCorner1.vertex;

                Vertex v0 = edge.surroundingCorners[0].vertex;

                Vertex f = f1 - f0;
                Vertex v = v0 - f0;

                Vertex projvf = (((f * v) / Math.Pow(f.Magnitude(), 2)) * f);

                PolyCorner corner = new PolyCorner(cornerIdCounter++, projvf + f0);

                edge.surroundingCorners.Add(corner);
                corner.surroundingEdges.Add(edge);

                corner.surroundingFaces.Add(face1);
                corner.surroundingFaces.Add(face0);

                face0.surroundingCorners.Add(corner);
                face1.surroundingCorners.Add(corner);


                corners.Add(corner.id, corner);

                PolyEdge faceEdge0 = new PolyEdge(edgeIdCounter++, face0);
                PolyEdge faceEdge1 = new PolyEdge(edgeIdCounter++, face1);

                edges.Add(faceEdge0.id, faceEdge0);
                edges.Add(faceEdge1.id, faceEdge1);

                faceEdge0.surroundingCorners.Add(faceCorner0);
                faceEdge0.surroundingCorners.Add(corner);

                faceCorner0.surroundingEdges.Add(faceEdge0);

                faceEdge1.surroundingCorners.Add(faceCorner1);
                faceEdge1.surroundingCorners.Add(corner);

                faceCorner1.surroundingEdges.Add(faceEdge1);
            }
        }

        foreach (KeyValuePair <int, PolyEdge> kvp in edges)
        {
            PolyEdge edge = kvp.Value;
            edge.vertex =
                (edge.surroundingCorners[0].vertex
                 + edge.surroundingCorners[1].vertex) / 2;
        }

        ConstraintOptions options = new ConstraintOptions()
        {
            ConformingDelaunay = false
        };

        foreach (KeyValuePair <int, PolyFace> kvp in faces)
        {
            PolyFace face = kvp.Value;
            face.GenerateMeshData(options);
        }
    }
    private void Initialize(PolyGraph polyGraph)
    {
        width  = polyGraph.width;
        height = polyGraph.height;

        faces = polyGraph.faces
                .Select((kvp, i) => new Face(i, kvp.Value))
                .ToArray();
        corners = polyGraph.corners
                  .Select((kvp, i) => new Corner(i, kvp.Value))
                  .ToArray();
        edges = polyGraph.edges
                .Select((kvp, i) => new Edge(i, kvp.Value))
                .ToArray();

        int index;

        for (index = 0; index < faces.Length; index++)
        {
            Face     face     = faces[index];
            PolyFace polyFace = polyGraph.faces[index];

            face.corners = polyFace.surroundingCorners
                           .Select(polyCorner => corners[polyCorner.id])
                           .OrderBy(corner => face.position.GetAngle(corner.position))
                           .ToArray();
            face.faces = polyFace.neighbouringFaces
                         .Select(otherPolyFace => faces[otherPolyFace.id])
                         .OrderBy(otherFace => face.position.GetAngle(otherFace.position))
                         .ToArray();
            face.edges = polyFace.surroundingEdges
                         .Select(polyEdge => edges[polyEdge.id])
                         .OrderBy(edge => face.position.GetAngle(edge.position))
                         .ToArray();

            face.triangles = polyFace.triangles;
            face.vertices  = polyFace.vertices
                             .Select(vertex => vertex.ToVector2())
                             .ToArray();
            face.normals = polyFace.normals
                           .Select((vertex => vertex.ToVector2()))
                           .ToArray();
        }


        for (index = 0; index < corners.Length; index++)
        {
            Corner     corner     = corners[index];
            PolyCorner polyCorner = polyGraph.corners[index];

            corner.faces = polyCorner.surroundingFaces
                           .Select(polyFace => faces[polyFace.id])
                           .OrderBy(face => corner.position.GetAngle(face.position))
                           .ToArray();
            corner.edges = polyCorner.surroundingEdges
                           .Select(polyEdge => edges[polyEdge.id])
                           .OrderBy(edge => corner.position.GetAngle(edge.position))
                           .ToArray();
        }

        for (index = 0; index < edges.Length; index++)
        {
            Edge     edge     = edges[index];
            PolyEdge polyEdge = polyGraph.edges[index];

            edge.faces = polyEdge.surroundingFaces
                         .Select(polyFace => faces[polyFace.id])
                         .OrderBy(face => edge.position.GetAngle(face.position))
                         .ToArray();

            edge.corners = polyEdge.surroundingCorners
                           .Select(polyCorner => corners[polyCorner.id])
                           .OrderBy(corner => edge.position.GetAngle(corner.position))
                           .ToArray();
        }
    }
    //public Dictionary<int, Edge> EdgeMap;

    public Corner(int index, PolyCorner polyCorner)
    {
        this.index = index;
        position   = polyCorner.vertex.ToVector2();
    }