public override string ToString() { return(string.Format("Vert {0}; PolyEdge {1}; Poly {2};", Vert?.Join(","), PolyEdge?.Join(","), Poly?.Join(","))); }
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); }
/// <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()); }
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)); }
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; } } } }
public Edge(int index, PolyEdge edge) { this.index = index; position = edge.vertex.ToVector2(); }
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 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); } }