// Start is called before the first frame update void Start() { var SPoints = new List <Point2D>() { MakePoint(-20, -10), MakePoint(0, 30), MakePoint(20, -10) }; var SuperTriangle = MakeTriangle(SPoints[0], SPoints[1], SPoints[2]); List <Point2D> ListOfPoints = new List <Point2D>(); for (int i = 0; i < 75; i++) { ListOfPoints.Add(gameObject.MakeRandomPoint(Prefab)); } DelaunayTriangulator DelaOBJ = new DelaunayTriangulator(Prefab, SPoints, ListOfPoints); HashSet <VirtualTriangle> Triangles = DelaOBJ.BowyerWatson(); foreach (VirtualTriangle vtrs in Triangles) { if (!vtrs.ISPointExists(SPoints)) { MakeTriangle(vtrs.Vertices[0], vtrs.Vertices[1], vtrs.Vertices[2]); } } }
/// <summary> /// Performs Delaunay triangulation over the specified collection of <see cref="Minutia"/>. /// </summary> /// <param name="minutiae">The collection of <see cref="Minutia"/> to triangulate.</param> /// <returns>The Delaunay triangles.</returns> public static IntegerTriangle[] Triangulate(ICollection<Minutia> minutiae) { ICollection<PointF> pointsCollection = new List<PointF>(minutiae.Count); foreach (var minutia in minutiae) { pointsCollection.Add(new PointF(minutia.X, minutia.Y)); } DelaunayTriangulator edges = new DelaunayTriangulator(); if (edges.Initialize(pointsCollection, 0.00001f)) edges.Process(); return edges.ToArray(); }
/// <summary> /// Performs Delaunay triangulation over the specified collection of <see cref="Minutia"/>. /// </summary> /// <param name="minutiae">The collection of <see cref="Minutia"/> to triangulate.</param> /// <returns>The Delaunay triangles.</returns> public static IntegerTriangle[] Triangulate(ICollection <Minutia> minutiae) { ICollection <PointF> pointsCollection = new List <PointF>(minutiae.Count); foreach (var minutia in minutiae) { pointsCollection.Add(new PointF(minutia.X, minutia.Y)); } DelaunayTriangulator edges = new DelaunayTriangulator(); if (edges.Initialize(pointsCollection, 0.00001f)) { edges.Process(); } return(edges.ToArray()); }
void DelaunayTriangulation(List <Point2D> RandomPoints) { List <Point2D> SPoints = new List <Point2D>() { MakePoint(-2100, -1100), MakePoint(0, 3100), MakePoint(2100, -1100) }; DelaunayTriangulator Triangulator = new DelaunayTriangulator(Prefab, SPoints, RandomPoints); HashSet <VirtualTriangle> Triangles = Triangulator.BowyerWatson(); foreach (VirtualTriangle tr in Triangles) { if (!tr.ISPointExists(SPoints)) { MakeTriangle(tr.Vertices[0], tr.Vertices[1], tr.Vertices[2]); } } }
public VoronoiDiagram(DelaunayTriangulator triangulation) { sites = new HashSet <Point>(); edges = new HashSet <Edge>(); foreach (Vertex vertex in triangulation.triangles) { foreach (Vertex neighbor in vertex.neighbors) { if (neighbor != null) { Point a = vertex.center; Point b = neighbor.center; this.edges.Add(new Edge(a, b)); } } this.sites.UnionWith(vertex.points); } }
static void Main(string[] args) { var delaunay = new DelaunayTriangulator(); var points = delaunay.GeneratePoints(2500, 512, 512); var triangulation = delaunay.BowyerWatson(points); newBitmap(); var image = new Bitmap(Image.FromFile("map.png")); using (var g = Graphics.FromImage(image)) { foreach (var var in triangulation) { g.DrawLines(White, var.Vertices.Select(var2 => new Point((int)var2.X, (int)var2.Y)).ToArray()); } image.Save("map.png"); image.Dispose(); Console.WriteLine("world generated!"); } }
void Start() { Cursor.lockState = CursorLockMode.None; Cursor.visible = true; float minDistance = pointPrefab.GetComponent <CircleCollider2D>().radius * 2; DelaunayTriangulator delaunay = new DelaunayTriangulator(); var points = delaunay.GeneratePoints(numberOfPoints, spawnArea, minDistance); var triangulation = delaunay.BowyerWatson(points); //remove junctions that are subjectively too long float maxDistanceBetweenPoints = Player.Instance.maxTravelDistance / 3; SpawnPOIs(pointPrefab, points, maxDistanceBetweenPoints, parentCanvas); Vector2 southernPoint = FindStartingPosition(points); playerToken.transform.SetPositionAndRotation(southernPoint, Quaternion.identity); playerToken.GetComponent <PlayerToken>().OnReachedDestination += GetComponent <RandomEventController>().StartEvent; OnPlayerReady?.Invoke(playerToken.transform.position); }
internal bool Initialize(ICollection <PointF> pointsCollection, float tolerance) { this.points = null; this.pointsIndices = null; this.edgesBuckets = null; this.edgesEntries = null; this.Triangles = null; this.Triangles = null; // Initialize triangle table this.TrianglesFirst = -1; this.TrianglesLast = -1; this.TrianglesCount = 0; this.firstNonCompletedTriangle = -1; this.lastNonCompletedTriangle = -1; // Initialize edge table this.edgesGeneration = 1; this.edgesCount = 0; this.tolerance = tolerance > 0 ? tolerance : float.Epsilon; // Ensure tolerance is valid this.pointsCount = pointsCollection == null ? 0 : pointsCollection.Count; if (pointsCollection.Count < 3) { return(false); // We need a non null collection with at least 3 vertices! } // Create the array of points. // We need 3 more items to add supertriangle vertices this.points = new PointF[this.pointsCount + 3]; pointsCollection.CopyTo(points, 0); // Create an array of indices to points sorted by Y (firstly), X (secondly) and insertion order (thirdly) this.pointsIndices = DelaunayTriangulator.GetSortedPointIndices(points, this.pointsCount, tolerance); // Calculate min and max X and Y coomponents of points PointF pointsMin, pointsMax; PointF d = new PointF(); DelaunayTriangulator.GetMinMaxPointCoordinates(points, this.pointsCount, out pointsMin, out pointsMax); // Create supertriangle vertices d.X = pointsMax.X - pointsMin.X; d.Y = pointsMax.Y - pointsMin.Y; float dmax = (d.X > d.Y) ? d.X : d.Y; PointF mid = new PointF(); mid.X = (pointsMax.X + pointsMin.X) * 0.5f; mid.Y = (pointsMax.Y + pointsMin.Y) * 0.5f; points[this.pointsCount] = new PointF(mid.X - 2 * dmax, mid.Y - dmax); points[this.pointsCount + 1] = new PointF(mid.X, mid.Y + 2 * dmax); points[this.pointsCount + 2] = new PointF(mid.X + 2 * dmax, mid.Y - dmax); // Initialize triangle array this.Triangles = new Triangle[this.pointsCount * 4 + 1]; Triangle triangleEntry = new Triangle(); triangleEntry.prevNonCompleted = -1; triangleEntry.nextNonCompleted = -1; // Initialized free triangles this.Triangles = new Triangle[this.Triangles.Length]; this.firstFreeTriangle = 0; for (int i = 0; i < this.Triangles.Length; ++i) { triangleEntry.Previous = i - 1; triangleEntry.Next = i + 1; this.Triangles[i] = triangleEntry; } this.Triangles[this.Triangles.Length - 1].Next = -1; // Initialize edge table int size = SPMath.GetPrime(this.Triangles.Length * 3 + 1); this.edgesBuckets = new EdgeBucketEntry[size]; this.edgesEntries = new EdgeEntry[size]; // Add supertriangle this.AddTriangle(this.pointsCount, this.pointsCount + 1, this.pointsCount + 2); return(true); }
protected override void SolveInstance(IGH_DataAccess DA) { iPoints = new List <Point3d>(); DA.GetDataList <Point3d>("Points", iPoints); iApicals = new List <Circle>(); DA.GetDataList <Circle>("Apicals", iApicals); iMasses = new List <double>(); DA.GetDataList <double>("Masses", iMasses); DA.GetData <Curve>("Boundary Curve", ref iBoundaryCurve); DA.GetData <double>("Rest Length Scale", ref iRestLengthScale); DA.GetData <double>("Rest Length Offset", ref iRestLengthOffset); DA.GetData <double>("Stiffness", ref iStiffness); DA.GetData <double>("Bending Stiffness", ref iBendingStiffness); DA.GetData <bool>("In/Out Switch", ref iInOutSwitch); DA.GetData <double>("In/Out Threshold", ref iInOutThreshold); DA.GetData <double>("Fixed Point Threshold", ref iFixedPointThreshold); iFixedPointExclusion = new List <Curve>(); DA.GetDataList <Curve>("Fixed Point Exclusion", iFixedPointExclusion); iFixedPointInclusion = new List <Curve>(); DA.GetDataList <Curve>("Fixed Point Inclusion", iFixedPointInclusion); // =========================================================================================== // Compute Delaunay Triangulation // =========================================================================================== List <DelaunayVertex> delaunayVertices = new List <DelaunayVertex>(); foreach (Point3d point in iPoints) { delaunayVertices.Add(new DelaunayVertex(point.X, point.Y)); } List <Triad> triads = new DelaunayTriangulator().Triangulation(delaunayVertices); HashSet <Tuple <int, int> > delaunayEdgeTuples = new HashSet <Tuple <int, int> >(); for (int i = 0; i < triads.Count; i++) { Triad triad = triads[i]; delaunayEdgeTuples.Add(triad.a < triad.b ? new Tuple <int, int>(triad.a, triad.b) : new Tuple <int, int>(triad.b, triad.a)); delaunayEdgeTuples.Add(triad.b < triad.c ? new Tuple <int, int>(triad.b, triad.c) : new Tuple <int, int>(triad.c, triad.b)); delaunayEdgeTuples.Add(triad.c < triad.a ? new Tuple <int, int>(triad.c, triad.a) : new Tuple <int, int>(triad.a, triad.c)); } // =========================================================================================== // Convert Delaunay mesh to particle-spring mesh // =========================================================================================== oSpringMesh = new SpringMesh(); // Create edge list ----------------------------------------------------------------------------------------------- foreach (Tuple <int, int> delaunayEdgeTuple in delaunayEdgeTuples) { Point3d A = iPoints[delaunayEdgeTuple.Item1]; Point3d B = iPoints[delaunayEdgeTuple.Item2]; Point3d M = 0.5 * (A + B); // Skip if the edge lies outside of the boundary double t; iBoundaryCurve.ClosestPoint(M, out t); Point3d N = iBoundaryCurve.PointAt(t); if (Vector3d.CrossProduct(iBoundaryCurve.TangentAt(t), M - N).Z *(iInOutSwitch ? -1.0 : 1.0) < 0.0 && Utils.DistanceSquared(M, N) > iInOutThreshold * iInOutThreshold) { continue; } double edgeLength = Utils.Distance(A, B); double restLength = iRestLengthScale * edgeLength + iRestLengthOffset; oSpringMesh.Edges.Add(new Edge(delaunayEdgeTuple.Item1, delaunayEdgeTuple.Item2, restLength, iStiffness, Math.PI, iBendingStiffness)); } // Create vertex list ----------------------------------------------------------------------------------------------- List <HashSet <int> > neighborVerticesSets = new List <HashSet <int> >(); for (int i = 0; i < iPoints.Count; i++) { neighborVerticesSets.Add(new HashSet <int>()); } foreach (Edge edge in oSpringMesh.Edges) { neighborVerticesSets[edge.FirstVertexIndex].Add(edge.SecondVertexIndex); neighborVerticesSets[edge.SecondVertexIndex].Add(edge.FirstVertexIndex); } for (int i = 0; i < iPoints.Count; i++) { Point3d p = iPoints[i]; double t; iBoundaryCurve.ClosestPoint(p, out t); bool vertexFixedness = true; if (Utils.Distance(p, iBoundaryCurve.PointAt(t)) > iFixedPointThreshold) { vertexFixedness = false; } else { foreach (Curve curve in iFixedPointExclusion) { if (curve.Contains(p) == PointContainment.Inside) { vertexFixedness = false; break; } } } foreach (Curve curve in iFixedPointInclusion) { if (curve.Contains(p) == PointContainment.Inside) { vertexFixedness = true; break; } } Vertex vertex = new Vertex(p, Vector3d.Zero, neighborVerticesSets[i].ToList <int>(), iMasses.Count == 1 ? iMasses[0] : iMasses[i], vertexFixedness); oSpringMesh.Vertices.Add(vertex); } // Set boundary edge ----------------------------------------------------------------------------------------------- foreach (Edge edge in oSpringMesh.Edges) { if (oSpringMesh.Vertices[edge.FirstVertexIndex].IsFixed && oSpringMesh.Vertices[edge.SecondVertexIndex].IsFixed) { edge.IsBoundaryEdge = true; } } // Create triangle list ------------------------------------------------------------------------------------------------ Dictionary <Tuple <int, int, int>, int> tripletDict = new Dictionary <Tuple <int, int, int>, int>(); for (int k = 0; k < oSpringMesh.Edges.Count; k++) { Edge edge = oSpringMesh.Edges[k]; Vertex A = oSpringMesh.Vertices[edge.FirstVertexIndex]; Vertex B = oSpringMesh.Vertices[edge.SecondVertexIndex]; for (int i = 0; i < A.NeighborVertexIndices.Count; i++) { for (int j = 0; j < B.NeighborVertexIndices.Count; j++) { if (A.NeighborVertexIndices[i] == B.NeighborVertexIndices[j]) { Tuple <int, int, int> triplet = sortTriplet(edge.FirstVertexIndex, edge.SecondVertexIndex, A.NeighborVertexIndices[i]); if (tripletDict.ContainsKey(triplet)) { if (edge.FirstTriangleIndex < 0) { edge.FirstTriangleIndex = tripletDict[triplet]; edge.FirstAdjacentVertexIndex = A.NeighborVertexIndices[i]; } else { edge.SecondTriangleIndex = tripletDict[triplet]; edge.SecondAdjacentVertexIndex = A.NeighborVertexIndices[i]; } } else { oSpringMesh.Triangles.Add(new Triangle(triplet.Item1, triplet.Item2, triplet.Item3)); int triangleIndex = oSpringMesh.Triangles.Count - 1; if (edge.FirstTriangleIndex < 0) { edge.FirstTriangleIndex = triangleIndex; edge.FirstAdjacentVertexIndex = A.NeighborVertexIndices[i]; } else { edge.SecondTriangleIndex = triangleIndex; edge.SecondAdjacentVertexIndex = A.NeighborVertexIndices[i]; } tripletDict.Add(triplet, triangleIndex); } } } } } // =========================================================================================== // Compute edge indices for each triangle // =========================================================================================== for (int i = 0; i < oSpringMesh.Edges.Count; i++) { Edge edge = oSpringMesh.Edges[i]; Triangle triangle = oSpringMesh.Triangles[edge.FirstTriangleIndex]; if (triangle.FirstEdgeIndex == -1) { triangle.FirstEdgeIndex = i; } else if (triangle.SecondEdgeIndex == -1) { triangle.SecondEdgeIndex = i; } else { triangle.ThirdEdgeIndex = i; } if (edge.SecondTriangleIndex == -1) { continue; } triangle = oSpringMesh.Triangles[edge.SecondTriangleIndex]; if (triangle.FirstEdgeIndex == -1) { triangle.FirstEdgeIndex = i; } else if (triangle.SecondEdgeIndex == -1) { triangle.SecondEdgeIndex = i; } else { triangle.ThirdEdgeIndex = i; } } // =========================================================================================== // Rearange the vertex order in each triangle so the normal calculation is consistent // =========================================================================================== for (int i = 0; i < oSpringMesh.Triangles.Count; i++) { if (oSpringMesh.ComputeTriangleNormal(i).Z < 0.0) { int temp = oSpringMesh.Triangles[i].SecondVertexIndex; oSpringMesh.Triangles[i].SecondVertexIndex = oSpringMesh.Triangles[i].ThirdVertexIndex; oSpringMesh.Triangles[i].ThirdVertexIndex = temp; } } // =========================================================================================== // Rearranging edge adjacent vertex indices for consitency // =========================================================================================== foreach (Edge edge in oSpringMesh.Edges) { if (edge.SecondAdjacentVertexIndex == -1) { Point3d A = oSpringMesh.Vertices[edge.FirstVertexIndex].Position; Point3d B = oSpringMesh.Vertices[edge.SecondVertexIndex].Position; Point3d M = oSpringMesh.Vertices[edge.FirstAdjacentVertexIndex].Position; if (Vector3d.CrossProduct(B - A, M - A) * oSpringMesh.ComputeTriangleNormal(edge.FirstTriangleIndex) < 0.0) { Point3d temp = A; A = B; B = temp; } } else { Point3d A = oSpringMesh.Vertices[edge.FirstVertexIndex].Position; Point3d B = oSpringMesh.Vertices[edge.SecondVertexIndex].Position; Point3d M = oSpringMesh.Vertices[edge.FirstAdjacentVertexIndex].Position; Point3d N = oSpringMesh.Vertices[edge.SecondAdjacentVertexIndex].Position; if (Vector3d.CrossProduct(B - A, M - A) * oSpringMesh.ComputeTriangleNormal(edge.FirstAdjacentVertexIndex) < 0.0) { int temp = edge.FirstAdjacentVertexIndex; edge.FirstAdjacentVertexIndex = edge.SecondAdjacentVertexIndex; edge.SecondAdjacentVertexIndex = temp; temp = edge.FirstTriangleIndex; edge.FirstTriangleIndex = edge.SecondTriangleIndex; edge.SecondTriangleIndex = temp; } } } // =========================================================================================== // Compute adjacent vertex index for each triangle // =========================================================================================== //foreach (Triangle triangle in oSpringMesh.Triangles) //{ // Vertex firstVertex = oSpringMesh.Vertices[triangle.FirstVertexIndex]; // Vertex secondVertex = oSpringMesh.Vertices[triangle.SecondVertexIndex]; // Vertex thirdVertex = oSpringMesh.Vertices[triangle.ThirdVertexIndex]; // foreach (int firstNeighbourIndex in firstVertex.NeighborVertexIndices) // foreach (int secondNeighbourIndex in secondVertex.NeighborVertexIndices) // if (firstNeighbourIndex == secondNeighbourIndex && firstNeighbourIndex != triangle.ThirdVertexIndex) // triangle.FirstSecondAdjacentVertexIndex = firstNeighbourIndex; // foreach (int secondNeighbourIndex in secondVertex.NeighborVertexIndices) // foreach (int thirdNeighbourIndex in thirdVertex.NeighborVertexIndices) // if (secondNeighbourIndex == thirdNeighbourIndex && secondNeighbourIndex != triangle.FirstVertexIndex) // triangle.SecondThirdAdjacentVertexIndex = secondNeighbourIndex; // foreach (int thirdNeighbourIndex in thirdVertex.NeighborVertexIndices) // foreach (int firstNeighbourIndex in firstVertex.NeighborVertexIndices) // if (thirdNeighbourIndex == firstNeighbourIndex && thirdNeighbourIndex != triangle.SecondVertexIndex) // triangle.ThirdFirstAdjacentVertexIndex = thirdNeighbourIndex; //} // =========================================================================================== // Initial curving bias // =========================================================================================== DA.GetData <double>("Initial Curving Bias", ref iInitialCurvingBias); DA.GetData <bool>("Bias Apical Regions", ref iBiasApicalRegion); foreach (Vertex vertex in oSpringMesh.Vertices) { vertex.Position.Z = computeBiasHeight(vertex.Position, iBiasApicalRegion); } // =========================================================================================== // Conclusion // =========================================================================================== foreach (Edge edge in oSpringMesh.Edges) { oDebugCurves1.Add(new LineCurve(oSpringMesh.Vertices[edge.FirstVertexIndex].Position, oSpringMesh.Vertices[edge.SecondVertexIndex].Position)); } DA.SetData(0, oInfo); DA.SetDataList(1, oDebugCurves1); DA.SetData(6, oSpringMesh); }
protected override void SolveInstance(IGH_DataAccess DA) { iPoints = new List<Point3d>(); DA.GetDataList<Point3d>("Points", iPoints); iApicals = new List<Circle>(); DA.GetDataList<Circle>("Apicals", iApicals); iMasses = new List<double>(); DA.GetDataList<double>("Masses", iMasses); DA.GetData<Curve>("Boundary Curve", ref iBoundaryCurve); DA.GetData<double>("Rest Length Scale", ref iRestLengthScale); DA.GetData<double>("Rest Length Offset", ref iRestLengthOffset); DA.GetData<double>("Stiffness", ref iStiffness); DA.GetData<double>("Bending Stiffness", ref iBendingStiffness); DA.GetData<bool>("In/Out Switch", ref iInOutSwitch); DA.GetData<double>("In/Out Threshold", ref iInOutThreshold); DA.GetData<double>("Fixed Point Threshold", ref iFixedPointThreshold); iFixedPointExclusion = new List<Curve>(); DA.GetDataList<Curve>("Fixed Point Exclusion", iFixedPointExclusion); iFixedPointInclusion = new List<Curve>(); DA.GetDataList<Curve>("Fixed Point Inclusion", iFixedPointInclusion); // =========================================================================================== // Compute Delaunay Triangulation // =========================================================================================== List<DelaunayVertex> delaunayVertices = new List<DelaunayVertex>(); foreach (Point3d point in iPoints) delaunayVertices.Add(new DelaunayVertex(point.X, point.Y)); List<Triad> triads = new DelaunayTriangulator().Triangulation(delaunayVertices); HashSet<Tuple<int, int>> delaunayEdgeTuples = new HashSet<Tuple<int, int>>(); for (int i = 0; i < triads.Count; i++) { Triad triad = triads[i]; delaunayEdgeTuples.Add(triad.a < triad.b ? new Tuple<int, int>(triad.a, triad.b) : new Tuple<int, int>(triad.b, triad.a)); delaunayEdgeTuples.Add(triad.b < triad.c ? new Tuple<int, int>(triad.b, triad.c) : new Tuple<int, int>(triad.c, triad.b)); delaunayEdgeTuples.Add(triad.c < triad.a ? new Tuple<int, int>(triad.c, triad.a) : new Tuple<int, int>(triad.a, triad.c)); } // =========================================================================================== // Convert Delaunay mesh to particle-spring mesh // =========================================================================================== oSpringMesh = new SpringMesh(); // Create edge list ----------------------------------------------------------------------------------------------- foreach (Tuple<int, int> delaunayEdgeTuple in delaunayEdgeTuples) { Point3d A = iPoints[delaunayEdgeTuple.Item1]; Point3d B = iPoints[delaunayEdgeTuple.Item2]; Point3d M = 0.5 * (A + B); // Skip if the edge lies outside of the boundary double t; iBoundaryCurve.ClosestPoint(M, out t); Point3d N = iBoundaryCurve.PointAt(t); if (Vector3d.CrossProduct(iBoundaryCurve.TangentAt(t), M - N).Z * (iInOutSwitch ? -1.0 : 1.0) < 0.0 && Utils.DistanceSquared(M, N) > iInOutThreshold * iInOutThreshold) continue; double edgeLength = Utils.Distance(A, B); double restLength = iRestLengthScale * edgeLength + iRestLengthOffset; oSpringMesh.Edges.Add(new Edge(delaunayEdgeTuple.Item1, delaunayEdgeTuple.Item2, restLength, iStiffness, Math.PI, iBendingStiffness)); } // Create vertex list ----------------------------------------------------------------------------------------------- List<HashSet<int>> neighborVerticesSets = new List<HashSet<int>>(); for (int i = 0; i < iPoints.Count; i++) neighborVerticesSets.Add(new HashSet<int>()); foreach (Edge edge in oSpringMesh.Edges) { neighborVerticesSets[edge.FirstVertexIndex].Add(edge.SecondVertexIndex); neighborVerticesSets[edge.SecondVertexIndex].Add(edge.FirstVertexIndex); } for (int i = 0; i < iPoints.Count; i++) { Point3d p = iPoints[i]; double t; iBoundaryCurve.ClosestPoint(p, out t); bool vertexFixedness = true; if (Utils.Distance(p, iBoundaryCurve.PointAt(t)) > iFixedPointThreshold) vertexFixedness = false; else foreach (Curve curve in iFixedPointExclusion) if (curve.Contains(p) == PointContainment.Inside) { vertexFixedness = false; break; } foreach (Curve curve in iFixedPointInclusion) if (curve.Contains(p) == PointContainment.Inside) { vertexFixedness = true; break; } Vertex vertex = new Vertex(p, Vector3d.Zero, neighborVerticesSets[i].ToList<int>(), iMasses.Count == 1 ? iMasses[0] : iMasses[i], vertexFixedness); oSpringMesh.Vertices.Add(vertex); } // Set boundary edge ----------------------------------------------------------------------------------------------- foreach (Edge edge in oSpringMesh.Edges) { if (oSpringMesh.Vertices[edge.FirstVertexIndex].IsFixed && oSpringMesh.Vertices[edge.SecondVertexIndex].IsFixed) { edge.IsBoundaryEdge = true; } } // Create triangle list ------------------------------------------------------------------------------------------------ Dictionary<Tuple<int, int, int>, int> tripletDict = new Dictionary<Tuple<int, int, int>, int>(); for (int k = 0; k < oSpringMesh.Edges.Count; k++) { Edge edge = oSpringMesh.Edges[k]; Vertex A = oSpringMesh.Vertices[edge.FirstVertexIndex]; Vertex B = oSpringMesh.Vertices[edge.SecondVertexIndex]; for (int i = 0; i < A.NeighborVertexIndices.Count; i++) { for (int j = 0; j < B.NeighborVertexIndices.Count; j++) { if (A.NeighborVertexIndices[i] == B.NeighborVertexIndices[j]) { Tuple<int, int, int> triplet = sortTriplet(edge.FirstVertexIndex, edge.SecondVertexIndex, A.NeighborVertexIndices[i]); if (tripletDict.ContainsKey(triplet)) { if (edge.FirstTriangleIndex < 0) { edge.FirstTriangleIndex = tripletDict[triplet]; edge.FirstAdjacentVertexIndex = A.NeighborVertexIndices[i]; } else { edge.SecondTriangleIndex = tripletDict[triplet]; edge.SecondAdjacentVertexIndex = A.NeighborVertexIndices[i]; } } else { oSpringMesh.Triangles.Add(new Triangle(triplet.Item1, triplet.Item2, triplet.Item3)); int triangleIndex = oSpringMesh.Triangles.Count - 1; if (edge.FirstTriangleIndex < 0) { edge.FirstTriangleIndex = triangleIndex; edge.FirstAdjacentVertexIndex = A.NeighborVertexIndices[i]; } else { edge.SecondTriangleIndex = triangleIndex; edge.SecondAdjacentVertexIndex = A.NeighborVertexIndices[i]; } tripletDict.Add(triplet, triangleIndex); } } } } } // =========================================================================================== // Compute edge indices for each triangle // =========================================================================================== for (int i = 0; i < oSpringMesh.Edges.Count; i++) { Edge edge = oSpringMesh.Edges[i]; Triangle triangle = oSpringMesh.Triangles[edge.FirstTriangleIndex]; if (triangle.FirstEdgeIndex == -1) triangle.FirstEdgeIndex = i; else if (triangle.SecondEdgeIndex == -1) triangle.SecondEdgeIndex = i; else triangle.ThirdEdgeIndex = i; if (edge.SecondTriangleIndex == -1) continue; triangle = oSpringMesh.Triangles[edge.SecondTriangleIndex]; if (triangle.FirstEdgeIndex == -1) triangle.FirstEdgeIndex = i; else if (triangle.SecondEdgeIndex == -1) triangle.SecondEdgeIndex = i; else triangle.ThirdEdgeIndex = i; } // =========================================================================================== // Rearange the vertex order in each triangle so the normal calculation is consistent // =========================================================================================== for (int i = 0; i < oSpringMesh.Triangles.Count; i++) { if (oSpringMesh.ComputeTriangleNormal(i).Z < 0.0) { int temp = oSpringMesh.Triangles[i].SecondVertexIndex; oSpringMesh.Triangles[i].SecondVertexIndex = oSpringMesh.Triangles[i].ThirdVertexIndex; oSpringMesh.Triangles[i].ThirdVertexIndex = temp; } } // =========================================================================================== // Rearranging edge adjacent vertex indices for consitency // =========================================================================================== foreach (Edge edge in oSpringMesh.Edges) { if (edge.SecondAdjacentVertexIndex == -1) { Point3d A = oSpringMesh.Vertices[edge.FirstVertexIndex].Position; Point3d B = oSpringMesh.Vertices[edge.SecondVertexIndex].Position; Point3d M = oSpringMesh.Vertices[edge.FirstAdjacentVertexIndex].Position; if (Vector3d.CrossProduct(B - A, M - A) * oSpringMesh.ComputeTriangleNormal(edge.FirstTriangleIndex) < 0.0) { Point3d temp = A; A = B; B = temp; } } else { Point3d A = oSpringMesh.Vertices[edge.FirstVertexIndex].Position; Point3d B = oSpringMesh.Vertices[edge.SecondVertexIndex].Position; Point3d M = oSpringMesh.Vertices[edge.FirstAdjacentVertexIndex].Position; Point3d N = oSpringMesh.Vertices[edge.SecondAdjacentVertexIndex].Position; if (Vector3d.CrossProduct(B - A, M - A) * oSpringMesh.ComputeTriangleNormal(edge.FirstAdjacentVertexIndex) < 0.0) { int temp = edge.FirstAdjacentVertexIndex; edge.FirstAdjacentVertexIndex = edge.SecondAdjacentVertexIndex; edge.SecondAdjacentVertexIndex = temp; temp = edge.FirstTriangleIndex; edge.FirstTriangleIndex = edge.SecondTriangleIndex; edge.SecondTriangleIndex = temp; } } } // =========================================================================================== // Compute adjacent vertex index for each triangle // =========================================================================================== //foreach (Triangle triangle in oSpringMesh.Triangles) //{ // Vertex firstVertex = oSpringMesh.Vertices[triangle.FirstVertexIndex]; // Vertex secondVertex = oSpringMesh.Vertices[triangle.SecondVertexIndex]; // Vertex thirdVertex = oSpringMesh.Vertices[triangle.ThirdVertexIndex]; // foreach (int firstNeighbourIndex in firstVertex.NeighborVertexIndices) // foreach (int secondNeighbourIndex in secondVertex.NeighborVertexIndices) // if (firstNeighbourIndex == secondNeighbourIndex && firstNeighbourIndex != triangle.ThirdVertexIndex) // triangle.FirstSecondAdjacentVertexIndex = firstNeighbourIndex; // foreach (int secondNeighbourIndex in secondVertex.NeighborVertexIndices) // foreach (int thirdNeighbourIndex in thirdVertex.NeighborVertexIndices) // if (secondNeighbourIndex == thirdNeighbourIndex && secondNeighbourIndex != triangle.FirstVertexIndex) // triangle.SecondThirdAdjacentVertexIndex = secondNeighbourIndex; // foreach (int thirdNeighbourIndex in thirdVertex.NeighborVertexIndices) // foreach (int firstNeighbourIndex in firstVertex.NeighborVertexIndices) // if (thirdNeighbourIndex == firstNeighbourIndex && thirdNeighbourIndex != triangle.SecondVertexIndex) // triangle.ThirdFirstAdjacentVertexIndex = thirdNeighbourIndex; //} // =========================================================================================== // Initial curving bias // =========================================================================================== DA.GetData<double>("Initial Curving Bias", ref iInitialCurvingBias); DA.GetData<bool>("Bias Apical Regions", ref iBiasApicalRegion); foreach (Vertex vertex in oSpringMesh.Vertices) { vertex.Position.Z = computeBiasHeight(vertex.Position, iBiasApicalRegion); } // =========================================================================================== // Conclusion // =========================================================================================== foreach (Edge edge in oSpringMesh.Edges) oDebugCurves1.Add(new LineCurve(oSpringMesh.Vertices[edge.FirstVertexIndex].Position, oSpringMesh.Vertices[edge.SecondVertexIndex].Position)); DA.SetData(0, oInfo); DA.SetDataList(1, oDebugCurves1); DA.SetData(6, oSpringMesh); }
public Room GenerateConnections(List <Room> rooms) { var triangulator = new DelaunayTriangulator(); var roomMidpoints = new List <DelaunayVoronoi.Point>(); var minX = float.MaxValue; var minY = float.MaxValue; var maxX = float.MinValue; var maxY = float.MinValue; foreach (var room in rooms) { var x = room.position.x; var y = room.position.y; minX = Mathf.Min(x, minX); minY = Mathf.Min(y, minY); maxX = Mathf.Max(x, maxX); maxY = Mathf.Max(y, maxY); roomMidpoints.Add(new DelaunayVoronoi.Point(room.position.x, room.position.y)); } // Add buffer to the sides. minX -= 100; minY -= 100; maxX += 100; maxY += 100; minX = Mathf.CeilToInt(minX); minY = Mathf.CeilToInt(minY); maxX = Mathf.CeilToInt(maxX); maxY = Mathf.CeilToInt(maxY); this.minX = minX; this.minY = minY; this.maxX = maxX; this.maxY = maxY; var point0 = new DelaunayVoronoi.Point(minX, minY); var point1 = new DelaunayVoronoi.Point(minX, maxY); var point2 = new DelaunayVoronoi.Point(maxX, maxY); var point3 = new DelaunayVoronoi.Point(maxX, minY); var borderTriangle1 = new Triangle(point0, point1, point2); var borderTriangle2 = new Triangle(point0, point2, point3); triangulator.border = new List <Triangle>() { borderTriangle1, borderTriangle2 }; var delaunayTriangles = new List <Triangle>(triangulator.BowyerWatson(roomMidpoints)); foreach (var triangle in delaunayTriangles) { // Check if this is actually part of the delaunay triangulation, or if it's a bordering region. var valid = true; foreach (var vertex in triangle.Vertices) { if (vertex.X == minX || vertex.X == maxX || vertex.Y == minY || vertex.Y == maxY) { valid = false; break; } } if (!valid) { continue; } var edges = new List <System.Tuple <DelaunayVoronoi.Point, DelaunayVoronoi.Point> >() { new System.Tuple <DelaunayVoronoi.Point, DelaunayVoronoi.Point>(triangle.Vertices[0], triangle.Vertices[1]), new System.Tuple <DelaunayVoronoi.Point, DelaunayVoronoi.Point>(triangle.Vertices[1], triangle.Vertices[2]), new System.Tuple <DelaunayVoronoi.Point, DelaunayVoronoi.Point>(triangle.Vertices[2], triangle.Vertices[0]), }; foreach (var edge in edges) { var p1 = new Vector2((float)edge.Item1.X, (float)edge.Item1.Y); var p2 = new Vector2((float)edge.Item2.X, (float)edge.Item2.Y); var r1 = GetRoomByMidpoint(rooms, p1); var r2 = GetRoomByMidpoint(rooms, p2); if (r1 == null || r2 == null) { continue; } r1.connectedRooms.Add(r2); r2.connectedRooms.Add(r1); } } Room spawnRoom = null; var spawnRoomDistanceSq = float.MaxValue; foreach (var room in rooms) { var distanceSq = room.position.x * room.position.x + room.position.y * room.position.y; if (distanceSq < spawnRoomDistanceSq) { spawnRoomDistanceSq = distanceSq; spawnRoom = room; } } if (GeneratorDebugSettings.DebugStartingRoom) { Debug.DrawLine(new Vector3(spawnRoom.position.x, 0, spawnRoom.position.y), new Vector3(spawnRoom.position.x, 5, spawnRoom.position.y), Color.yellow, 100000f); } // Center room has no entrance; you spawn there. spawnRoom.DeleteConnectionsIntoSelf(); // Remove as many connections as possible while preventing islands. spawnRoom.DeleteAsManyConnectionsAsPossible(); // Remove any loops while preventing islands. spawnRoom.DeleteLoops(); // Add some more connections randomly. var extraConnections = rooms.Count * 0.1; var madeConnections = 0f; while (madeConnections < extraConnections) { var randomRoomA = rooms[Random.Range(0, rooms.Count - 1)]; var randomRoomB = rooms[Random.Range(0, rooms.Count - 1)]; if (randomRoomA == randomRoomB) { madeConnections += 0.1f; continue; } if (randomRoomA.connectedRooms.Contains(randomRoomB) && randomRoomB.connectedRooms.Contains(randomRoomA)) { madeConnections += 0.1f; continue; } if (randomRoomB == spawnRoom) { madeConnections += 0.1f; continue; } randomRoomA.connectedRooms.Add(randomRoomB); madeConnections++; } if (GeneratorDebugSettings.DebugGraph) { spawnRoom.DebugGraph(); } foreach (var room in rooms) { room.AlignToHallwayGrid(hallwaySize, minX, minY); room.FinalizePosition(); } return(spawnRoom); }
public void Test1000() { var t = DelaunayTriangulator.Triangulate(RandomPoints.Take(1000)); }