Ejemplo n.º 1
0
 public override string ToString()
 {
     return(string.Format("Vert {0}; PolyEdge {1}; Poly {2};",
                          Vert?.Join(","),
                          PolyEdge?.Join(","),
                          Poly?.Join(",")));
 }
Ejemplo n.º 2
0
        void CreateBridge(ref PolyEdge srcEdge, ref PolyEdge dstEdge)
        {
            SplitPoly.Add(new PolyEdge(srcEdge.StartPos, srcEdge.StartSide));
            PolyEdge a = SplitPoly.LastOrDefault();

            SplitPoly.Add(new PolyEdge(dstEdge.StartPos, dstEdge.StartSide));
            PolyEdge b = SplitPoly.LastOrDefault();

            a.Next            = dstEdge;
            a.Prev            = srcEdge.Prev;
            b.Next            = srcEdge;
            b.Prev            = dstEdge.Prev;
            srcEdge.Prev.Next = a;
            srcEdge.Prev      = b;
            dstEdge.Prev.Next = b;
            dstEdge.Prev      = a;
            // dstEdge.DistOnLine = 999;

            //SplitPoly.push_back(*srcEdge);
            // PolyEdge *a = &SplitPoly.back();
            // SplitPoly.push_back(*dstEdge);
            // PolyEdge *b = &SplitPoly.back();
            // a->Next = dstEdge;
            // a->Prev = srcEdge->Prev;
            // b->Next = srcEdge;
            // b->Prev = dstEdge->Prev;
            // srcEdge->Prev->Next = a;
            // srcEdge->Prev = b;
            // dstEdge->Prev->Next = b;
            // dstEdge->Prev = a;
        }
        /// <summary>
        /// Creates PolyEdges from all TileEdges in the isometric axis (instead of the cartesian axis) and maps them to
        /// each other.
        /// </summary>
        /// <param name="edgeColl"></param>
        /// <returns>Two Dictionaries that map TileEdges to their respective PolyEdges and vice versa.</returns>
        private static Dictionary <PolyEdge, TileEdge> _InitTilePolyBiDict(EdgeCollection <TileEdge> edgeColl)
        {
            var polyToTileMap = new Dictionary <PolyEdge, TileEdge>();

            foreach (TileEdge tileEdge in edgeColl)
            {
                var polyEdge = new PolyEdge(AxisFuncs.CoordToIsoAxis(tileEdge.a), AxisFuncs.CoordToIsoAxis(tileEdge.b));
                polyToTileMap[polyEdge] = tileEdge;
            }
            return(polyToTileMap);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Simplifies the outer perim using EdgeCollections simplification algorithm.
        /// </summary>
        private Vector2[] _SimplifyOuterPerim()
        {
            var edgeCollection = new EdgeCollection <PolyEdge>();

            for (int i = 0; i < this.outerPerimNodes.Count; i++)
            {
                var thisCoord = new Vector2(this.outerPerimNodes[i].x, this.outerPerimNodes[i].y);
                var nextCoord = new Vector2(this.outerPerimNodes[(i + 1) % this.outerPerimNodes.Count].x,
                                            this.outerPerimNodes[(i + 1) % this.outerPerimNodes.Count].y);
                if (thisCoord == nextCoord)
                {
                    continue;
                }
                var polyEdge = new PolyEdge(thisCoord, nextCoord);
                edgeCollection.Add(polyEdge);
            }
            return(edgeCollection.GetSimplifiedPerim().ToArray());
        }
Ejemplo n.º 5
0
        private static (List <PolyEdge>, HashSet <Vector2>) _AddBridgesToExtensions(ChordlessPolygon polygon)
        {
            var extensions      = new List <PolyEdge>();
            var alreadyExtended = new HashSet <Vector2>();

            foreach (Vector2 bridgeA in polygon.bridges.Keys)
            {
                foreach (Vector2 bridgeB in polygon.bridges[bridgeA])
                {
                    var bridgeExtension = new PolyEdge(bridgeA, bridgeB);
                    if (!extensions.Contains(bridgeExtension) && !extensions.Contains(bridgeExtension.GetReverseEdge()))
                    {
                        extensions.Add(bridgeExtension);
                        alreadyExtended.Add(bridgeA);
                        alreadyExtended.Add(bridgeB);
                    }
                }
            }
            return(extensions, alreadyExtended);
        }
 static int CmpEdges(PolyEdge e1, PolyEdge e2)
 {
     return(bool2int(int2bool(e1.y0 - e2.y0) ? e1.y0 < e2.y0 : int2bool(e1.x - e2.x) ? e1.x < e2.x : e1.dx < e2.dx));
 }
Ejemplo n.º 7
0
        void SplitPolygon()
        {
            PolyEdge useSrc = null;

            for (int i = 0; i < EdgesOnLine.Count; i++)
            {
                // find source
                PolyEdge srcEdge = useSrc;
                useSrc = null;

                // for (; !srcEdge && i < EdgesOnLine.size(); i++)
                for (; (srcEdge == null) && (i < EdgesOnLine.Count); i++)
                // for (int jj = 0; (srcEdge == null) && (jj < EdgesOnLine.Count); jj++)
                {
                    PolyEdge curEdge  = EdgesOnLine.ElementAtOrDefault(i);
                    var      curSide  = curEdge.StartSide;
                    var      prevSide = curEdge.Prev.StartSide;
                    var      nextSide = curEdge.Next.StartSide;
                    // PolyEdge* curEdge = EdgesOnLine[i];
                    // const auto curSide = curEdge->StartSide;
                    // const auto prevSide = curEdge->Prev->StartSide;
                    // const auto nextSide = curEdge->Next->StartSide;
                    // assert(curSide == LineSide::On);

                    // if ((prevSide == LineSide::Left && nextSide == LineSide::Right) ||
                    // (prevSide == LineSide::Left && nextSide == LineSide::On && curEdge->Next->DistOnLine < curEdge->DistOnLine) ||
                    // (prevSide == LineSide::On && nextSide == LineSide::Right && curEdge->Prev->DistOnLine < curEdge->DistOnLine))

                    if ((prevSide == LineSide.Left && nextSide == LineSide.Right) ||
                        (prevSide == LineSide.Left && nextSide == LineSide.On && curEdge.Next.DistOnLine < curEdge.DistOnLine) ||
                        (prevSide == LineSide.On && nextSide == LineSide.Right && curEdge.Prev.DistOnLine < curEdge.DistOnLine))
                    {
                        srcEdge           = curEdge;
                        srcEdge.IsSrcEdge = true;
                        // srcEdge->IsSrcEdge = true;
                    }
                }

                // find destination
                // PolyEdge* dstEdge = nullptr;
                PolyEdge dstEdge = null;

                // for (; !dstEdge && i < EdgesOnLine.size();)
                // for (; (dstEdge == null) && i < EdgesOnLine.Count;)
                for (; (dstEdge == null) && i < EdgesOnLine.Count;)
                // for (int jj = 0; (dstEdge == null) && (jj < EdgesOnLine.Count); jj++)
                {
                    PolyEdge curEdge = EdgesOnLine.ElementAtOrDefault(i);
                    // PolyEdge* curEdge = EdgesOnLine[i];
                    var curSide  = curEdge.StartSide;
                    var prevSide = curEdge.Prev.StartSide;
                    var nextSide = curEdge.Next.StartSide;
                    // const auto curSide = curEdge->StartSide;
                    // const auto prevSide = curEdge->Prev->StartSide;
                    // const auto nextSide = curEdge->Next->StartSide;
                    // assert(curSide == LineSide.On);

                    if ((prevSide == LineSide.Right && nextSide == LineSide.Left) ||
                        (prevSide == LineSide.On && nextSide == LineSide.Left) ||
                        (prevSide == LineSide.Right && nextSide == LineSide.On) ||
                        (prevSide == LineSide.Right && nextSide == LineSide.Right) ||
                        (prevSide == LineSide.Left && nextSide == LineSide.Left))
                    {
                        dstEdge = curEdge;
                        // dstEdge->IsDstEdge = true;
                        dstEdge.IsDstEdge = true;
                    }
                    else
                    {
                        i++;
                    }
                }

                // bridge source and destination
                // if (srcEdge && dstEdge)
                // bool test_judge = ReferenceEquals(srcEdge, EdgesOnLine.ElementAtOrDefault(0));
                // test_judge = ReferenceEquals(srcEdge, EdgesOnLine.ElementAtOrDefault(1));
                if ((srcEdge != null) && (dstEdge != null))
                {
                    CreateBridge(ref srcEdge, ref dstEdge);
                    VerifyCycles();

                    // is it a configuration in which a vertex
                    // needs to be reused as source vertex?
                    // if (srcEdge->Prev->Prev->StartSide == LineSide::Left)
                    if (srcEdge.Prev.Prev.StartSide == LineSide.Left)
                    {
                        useSrc = srcEdge.Prev;
                        // useSrc = srcEdge->Prev;
                        useSrc.IsSrcEdge = true;
                        // useSrc->IsSrcEdge = true;
                    }
                    // else if (dstEdge->Next->StartSide == LineSide::Right)
                    else if (dstEdge.Next.StartSide == LineSide.Right)
                    {
                        useSrc = dstEdge;
                        // useSrc->IsSrcEdge = true;
                        useSrc.IsSrcEdge = true;
                    }
                }
            }
        }
Ejemplo n.º 8
0
 public Edge(int index, PolyEdge edge)
 {
     this.index = index;
     position   = edge.vertex.ToVector2();
 }
Ejemplo n.º 9
0
    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();
        }
    }
Ejemplo n.º 10
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);
        }
    }