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(); }