/// <summary> /// This method utilizes the Delaunay Triangulation. /// </summary> public void DelaunayTriangulation() { // This is here because we're going to refresh the delaunator every time // it finishes doing the calculation. delaunator = new Delaunator(cells.Select( o => (IPoint) new DelaunayTriangulation.Models.Point(o.LocationCenter.X, o.LocationCenter.Y, o.GetHashCode())).ToArray()); // Process the result. delaunator.ForEachTriangleEdge(edge => { foreach (Cell cell in cells) { //if (edge.P.CellReference == cell.GetHashCode()) { // cell.ConnectedCell.Add(cells.Single(o => o.GetHashCode() == edge.Q.CellReference).GetHashCode()); //} //break; // You probably don't want to do this. This is a temporary fix. if (cell.LocationCenter.X == (int)edge.Q.X && cell.LocationCenter.Y == (int)edge.Q.Y) { cell.ConnectedCell.Add(edge.P.CellReference); } if (cell.LocationCenter.X == (int)edge.P.X && cell.LocationCenter.Y == (int)edge.P.Y) { cell.ConnectedCell.Add(edge.Q.CellReference); } } }); }
private void BuildGalaxy() { var spiralPoints = SpiralPoints(); var poissonPoints = PoissonPoints(); var enumerable = poissonPoints as Vector2[] ?? poissonPoints.ToArray(); var stars = enumerable.ToPoints(); var del = new Delaunator(stars); var delPoints = del.Points; del.ForEachVoronoiCell(cell => { // Where the hell even is the star? var curStarPoint = delPoints[cell.Index].ToVector3(); // Return if the star is outside of the galaxy if (OutsideGalaxy(curStarPoint, spiralPoints)) { return; } // Setup the star container to hold the star, the cell around it, etc var curStarContainer = SetupStarContainer(curStarPoint); StarContainers.Add(curStarPoint, curStarContainer.GetComponent <StarContainer>().Setup(curStarPoint, cell)); }); }
private void RefreshDelaunator() { if (!IsLengthOfPointsValid || Points.Count() == delaunator?.Points.Count()) { return; } delaunator = new Delaunator(Points.ToArray()); }
void SpawnCells(Delaunator delaunator, List <Vector3> cellCenters) { delaunator.ForEachVoronoiCell(dCell => { var center = cellCenters[dCell.Index]; List <int> neighbours = GetNeighbours(dCell.Index).ToList(); Cell cell = new GameObject("Cell" + dCell.Index).AddComponent <Cell>(); cell.Init(map, dCell, center, neighbours); }); }
private void Clear() { CreateNewContainers(); if (meshObject != null) { Destroy(meshObject); } delaunator = null; }
public static IEnumerable <Poly> GetTriangles(this IEnumerable <IPoint> points) { var delauney = new Delaunator(points.ToArray()); var triangles = delauney.GetTriangles(); return(triangles.Select(tri => new Poly() { Points = tri.Points.ToPointCollection(), Index = tri.Index })); }
public static IEnumerable <Poly> GetVoroni(this IEnumerable <IPoint> points) { var delauney = new Delaunator(points.ToArray()); var voroni = delauney.GetVoronoiCells(); return(voroni.Select(vor => new Poly() { Points = vor.Points.ToPointCollection(), Index = vor.Index })); }
/** Add south pole back into the mesh. * * We run the Delaunay Triangulation on all points *except* the south * pole, which gets mapped to infinity with the stereographic * projection. This function adds the south pole into the * triangulation. The Delaunator guide explains how the halfedges have * to be connected to make the mesh work. * <https://mapbox.github.io/delaunator/> * * Returns the new {triangles, halfedges} for the triangulation with * one additional point added around the convex hull. */ private static void addSouthPoleToMesh(int southPoleId, Delaunator delaunator) { // This logic is from <https://github.com/redblobgames/dual-mesh>, // where I use it to insert a "ghost" region on the "back" side of // the planar map. The same logic works here. In that code I use // "s" for edges ("sides"), "r" for regions ("points"), t for triangles var triangles = delaunator.triangles; var halfedges = delaunator.halfedges; var numSides = triangles.Length; //int s_next_s(int s) { return (s % 3 == 2) ? s - 2 : s + 1; } int numUnpairedSides = 0, firstUnpairedSide = -1; var pointIdToSideId = new Dictionary <int, int>(); // seed to side for (var s = 0; s < numSides; s++) { if (halfedges[s] == -1) { numUnpairedSides++; pointIdToSideId[triangles[s]] = s; firstUnpairedSide = s; } } var newTriangles = new int[numSides + 3 * numUnpairedSides]; var newHalfedges = new int[numSides + 3 * numUnpairedSides]; Array.Copy(triangles, newTriangles, triangles.Length); Array.Copy(halfedges, newHalfedges, halfedges.Length); for (int i = 0, s = firstUnpairedSide; i < numUnpairedSides; i++, s = pointIdToSideId[newTriangles[s_next_s(s)]]) { // Construct a pair for the unpaired side s var newSide = numSides + 3 * i; newHalfedges[s] = newSide; newHalfedges[newSide] = s; newTriangles[newSide] = newTriangles[s_next_s(s)]; // Construct a triangle connecting the new side to the south pole newTriangles[newSide + 1] = newTriangles[s]; newTriangles[newSide + 2] = southPoleId; var k = numSides + (3 * i + 4) % (3 * numUnpairedSides); newHalfedges[newSide + 2] = k; newHalfedges[k] = newSide + 2; } delaunator.triangles = newTriangles; delaunator.halfedges = newHalfedges; }
private static void DelaunayTriangulatePoints() { List <IPoint> delaunatorPoints = new List <IPoint>(); foreach (Vector2 v in m_VerticesDelaunayPlane) { delaunatorPoints.Add(new Point(v.x, v.y)); } Delaunator del = new Delaunator(delaunatorPoints.ToArray()); m_DelaunayTrianglesPlane = del.Triangles; m_DelaunayTrianglesSphere = del.Triangles; }
public static Delaunator fromPoints(List <double[]> points) { var coords = new double[2 * points.Count]; int i = 0; for (int p = 0; p < points.Count; ++p) { coords[i++] = points[p][0]; coords[i++] = points[p][1]; } var delauny = new Delaunator(coords); return(delauny); }
private void TriangulateRoom() { List <IPoint> points = new List <IPoint>(); foreach (var room in this.floorNodes) { if (room.isMain) { points.Add(new Point(room.rect.center.x, room.rect.center.y)); } } this.delaunator = new Delaunator(points.ToArray()); }
private void DrawDiagram() { if (!IsLengthOfPointsValid) { return; } ClearDiagram(); delaunator = new Delaunator(Points.ToArray()); DrawCircles(Points); DrawDelaunay(); DrawVoronoi(); DrawHull(); }
private void Create() { if (points.Count < 3) { return; } Clear(); delaunator = new Delaunator(points.ToArray()); CreateMesh(); CreateTriangle(); CreateHull(); CreateVoronoi(); }
void Clear() { delaunator = null; if (delaunayVisualsContainer != null) { Destroy(delaunayVisualsContainer.gameObject); delaunayVisualsContainer = null; } if (voronoiVisualContainer != null) { Destroy(voronoiVisualContainer.gameObject); voronoiVisualContainer = null; } }
public void GenerateMap(float mapSize, float delaunayRMin) { blueNoisePoints = UniformPoissonDiskSampler.SampleCircle(Vector2.zero, mapSize / 2, delaunayRMin); delaunator = new Delaunator(blueNoisePoints.ToPoints()); DrawDelaunay(); DrawVoronoi(); // fill heightmap into y coordinates cellPoints = HeightField.PerlinIsland(blueNoisePoints, mapSize, 0.1f, 0.7f, 4f, 3f, 6); map = new Map(cellPoints.Count); SpawnCells(delaunator, cellPoints); var camHeight = mapSize * 0.5f / Mathf.Tan(Camera.main.fieldOfView * 0.5f * Mathf.Deg2Rad); Camera.main.transform.position = new Vector3(0, camHeight * 1.1f, 0); }
public static void makeSphere(int N, double jitter, int seed, out DualMesh mesh, out List <double> d) { var latlong = generateFibonacciSphere(N, jitter, seed); //DebugHelper.SaveArray("generateFibonacciSphere.txt", latlong); var r_xyz = new List <double>(); for (var r = 0; r < latlong.Count / 2; r++) { pushCartesianFromSpherical(r_xyz, latlong[2 * r], latlong[2 * r + 1]); } var r_xy = stereographicProjection(r_xyz); //DebugHelper.SaveArray("stereographicProjection.txt", r_xy); var delaunay = new Delaunator(r_xy.ToArray()); /* TODO: rotate an existing point into this spot instead of creating one */ r_xyz.AddRange(new double[] { 0, 0, 1 }); addSouthPoleToMesh(r_xyz.Count / 3 - 1, delaunay); var dummy_r_vertex = new Float2[N + 1]; dummy_r_vertex[0] = new Float2(0, 0); for (var i = 1; i < N + 1; i++) { dummy_r_vertex[i] = dummy_r_vertex[0]; } mesh = new DualMesh(new Graph() { numBoundaryRegions = 0, numSolidSides = delaunay.triangles.Length, _r_vertex = dummy_r_vertex, _triangles = delaunay.triangles, _halfedges = delaunay.halfedges, }); d = r_xyz; }
public static void iiii(Vector3[] points, int start, List <int> triangles) { var coords = new double[points.Length * 2]; //var colors = new Color[points.Length]; for (var i = 0; i < points.Length; ++i) { coords[i * 2 + 0] = points[i].x; coords[i * 2 + 1] = points[i].y; //colors[i] = new Color(rd(), rd(), rd(), 0.382f); } var delauny = new Delaunator(coords); var dts = delauny.triangles; var n = dts.Length / 3; for (var i = 0; i < n; ++i) { var tt = new List <int>(); tt.Add(dts[i * 3 + 0]); tt.Add(dts[i * 3 + 1]); tt.Add(dts[i * 3 + 2]); var st = tt.ToArray(); Array.Sort(st); var a = points[st[0]]; var b = points[st[1]]; var c = points[st[2]]; var cross = Vector3.Cross(b - a, c - a); if (cross.z > 0) { triangles.AddRange(tt.Select(t => t + start)); } } }
public void SetPositions(Vector3[] points) { //舍弃距离太近的点 points = BezierCurve.duplicate(points); var rd = Rander.makeRandFloat(Random.Next()); var coords = new double[points.Length * 2]; //var colors = new Color[points.Length]; for (var i = 0; i < points.Length; ++i) { coords[i * 2 + 0] = points[i].x; coords[i * 2 + 1] = points[i].y; //colors[i] = new Color(rd(), rd(), rd(), 0.382f); } var delauny = new Delaunator(coords); var triangle = new List <int>(); var n = delauny.triangles.Length / 3; for (var i = 0; i < n; ++i) { var tt = new List <int>(); tt.Add(delauny.triangles[i * 3 + 0]); tt.Add(delauny.triangles[i * 3 + 1]); tt.Add(delauny.triangles[i * 3 + 2]); var st = tt.ToArray(); Array.Sort(st); var a = points[st[0]]; var b = points[st[1]]; var c = points[st[2]]; var cross = Vector3.Cross(b - a, c - a); if (cross.z > 0) { triangle.AddRange(tt); } } var length = points.Length; var pppp = new Vector3[length * 2]; Array.Copy(points, 0, pppp, 0, length); Array.Copy(points, 0, pppp, length, length); var nnnn = new Vector3[length * 2]; var tttt = new List <int>(); pp = points; pd = new Vector3[pp.Length]; for (var idx0 = 0; idx0 < length; ++idx0) { var idx1 = (idx0 + 1) % length; var idx2 = (idx0 - 1 + length) % length; var p0 = points[idx0]; var p1 = points[idx1] - p0; var p2 = points[idx2] - p0; var aa = Utils.angle(p1.x, p1.y, p2.x, p2.y); var normal = Quaternion.AngleAxis(aa / 2, Vector3.forward) * p1; pd[idx0] = pp[idx0] + normal; //pppp[idx0] += normal * 2f; //pppp[idx0 + length] -= normal * 2f; nnnn[idx0] = new Vector3(normal.x, normal.y, 0.682f); nnnn[idx0 + length] = new Vector3(-normal.x, -normal.y, 0); //跟我想象的逆时针顺序不一致,需要顺时针方向 //顶点数据是逆时针方向的,三角面顺序要顺时针 var tt = new int[] { idx0, idx1, idx0 + length, idx0 + length, idx1, idx1 + length }; tttt.AddRange(tt); } triangle.AddRange(tttt); tttt = triangle; //DebugHelper.SaveArray($"{gameObject.name}.txt", delauny.triangles); mesh = new Mesh(); mesh.vertices = pppp; mesh.normals = nnnn; mesh.triangles = tttt.ToArray(); mf.mesh = mesh; SetColor(new Color(rd(), rd(), rd(), rd())); //var render = gameObject.AddComponent<LineRenderer>(); //render.positionCount = points.Length; //render.SetPositions(points); //render.startWidth = 0.5f; //render.endWidth = 0.5f; //render.loop = true; }
/// <summary> /// Makes the actual mesh /// </summary> protected void _redraw() { if (lines.Count > 0) { Polygon = new List <DCurve3>(); foreach (Dataline ring in lines) { foreach (VertexLookup v in ring.VertexTable) { VertexTable.Add(v); } DCurve3 curve = new DCurve3(); curve.Vector3(ring.GetVertexPositions(), true); Polygon.Add(curve); } } MeshFilter mf = Shape.GetComponent <MeshFilter>(); MeshCollider[] mc = Shape.GetComponents <MeshCollider>(); mf.mesh = null; Mesh mesh = new Mesh(); Mesh imesh = new Mesh(); mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; imesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; Frame3f frame = new Frame3f(); Vector3[] vertices; GeneralPolygon2d polygon2d; Delaunator delaunator; List <int> triangles = new List <int>(); try { // // Map 3d Polygon to the bext fit 2d polygon and also return the frame used for the mapping // polygon2d = Polygon.ToPolygon(ref frame); // // calculate the dalaunay triangulation of the 2d polygon // delaunator = new Delaunator(polygon2d.AllVerticesItr().ToPoints()); IEnumerable <Vector2d> vlist = delaunator.Points.ToVectors2d(); vertices = new Vector3[vlist.Count()]; // // for each vertex in the dalaunay triangulatin - map back to a 3d point and also populate the vertex table // for (int i = 0; i < vlist.Count(); i++) { Vector2d v = vlist.ElementAt(i); try { Vector3d v1 = Polygon.AllVertexItr().Find(item => v.Distance(frame.ToPlaneUV((Vector3f)item, 2)) < 0.001); vertices[i] = Shape.transform.InverseTransformPoint((Vector3)v1); VertexLookup vl = VertexTable.Find(item => v1.Distance(item.Com.transform.position) < 0.001); if (vl != null) { vl.pVertex = i; } } catch { Debug.Log("Mesh Error"); } } // // eaxtract the triangles from the delaunay triangulation // IEnumerable <ITriangle> tris = delaunator.GetTriangles(); for (int i = 0; i < tris.Count(); i++) { ITriangle tri = tris.ElementAt(i); if (polygon2d.Contains(tri.CetIncenter())) { int index = 3 * i; triangles.Add(delaunator.Triangles[index]); triangles.Add(delaunator.Triangles[index + 1]); triangles.Add(delaunator.Triangles[index + 2]); } } } catch (Exception e) { throw new Exception("feature is not a valid Polygon : " + e.ToString()); } // // build the mesh entity // mesh.vertices = vertices; mesh.triangles = triangles.ToArray(); mesh.uv = BuildUVs(vertices); mesh.RecalculateBounds(); mesh.RecalculateNormals(); imesh.vertices = mesh.vertices; imesh.triangles = triangles.Reverse <int>().ToArray(); imesh.uv = mesh.uv; imesh.RecalculateBounds(); imesh.RecalculateNormals(); mf.mesh = mesh; try { mc[0].sharedMesh = mesh; mc[1].sharedMesh = imesh; } catch (Exception e) { Debug.Log(e.ToString()); } }
public void GlobalSetup() { points = distribution.GetPoints(Type, Count).ToArray(); delaunator = new Delaunator(points); }
public Voronoi(Delaunator delaunay, List <double[]> points, int pointsN) { var triangles = delaunay.triangles; var numSides = triangles.Length; var numTriangles = numSides / 3; cells = new Cells()//数组大小为区域数 { v = new int[pointsN][], c = new int[pointsN][], b = new bool[pointsN], //i = new int[numTriangles][], }; vertices = new Vertices()//数组大小为三角数 { p = new double[numTriangles][], v = new int[numTriangles][], c = new int[numTriangles][], }; List <int> edgesAroundPoint(int start) { var result = new List <int>(); var incoming = start; do { result.Add(incoming); var outgoing = nextHalfedge(incoming); incoming = delaunay.halfedges[outgoing]; } while (incoming != -1 && incoming != start && result.Count < 20); return(result); } int[] pointsOfTriangle(int t) { return(edgesOfTriangle(t).Select(s => triangles[s]).ToArray()); } double[] triangleCenter(int t) { var vertices = pointsOfTriangle(t).Select(p => points[p]).ToArray(); return(circumcenter(vertices[0], vertices[1], vertices[2])); } int[] trianglesAdjacentToTriangle(int t) { var edges = edgesOfTriangle(t); return(edges.Select((edge, index) => { var opposite = delaunay.halfedges[edge]; return triangleOfEdge(opposite); }).ToArray()); } for (var e = 0; e < numSides; ++e) { var p = triangles[nextHalfedge(e)]; //if (p >= pointsN) Debug.Log($"e:{e} p:{p} >= pointsN:{pointsN}"); //if (cells.c[p] != null) Debug.Log($"e:{e} cells.c[p] != null"); if (p < pointsN && cells.c[p] == null) { var edges = edgesAroundPoint(e); // cell: adjacent vertex cells.v[p] = edges.Select(s => triangleOfEdge(s)).ToArray(); // cell: adjacent valid cells cells.c[p] = edges.Select(s => triangles[s]).Where(c => c < pointsN).ToArray(); // cell: is border cells.b[p] = edges.Count > cells.c[p].Length ? true : false; } var t = triangleOfEdge(e);// numSides/3 //if (vertices.p[t] != null) Debug.Log($"e:{e} t:{t} vertices.p[t] != null"); if (vertices.p[t] == null) { // vertex: coordinates vertices.p[t] = triangleCenter(t); // vertex: adjacent vertices vertices.v[t] = trianglesAdjacentToTriangle(t); // vertex: adjacent cells vertices.c[t] = pointsOfTriangle(t); } } }