Beispiel #1
0
        /// <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);
                    }
                }
            });
        }
Beispiel #2
0
        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());
 }
Beispiel #4
0
 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);
     });
 }
Beispiel #5
0
        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
        }));
    }
Beispiel #8
0
    /** 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;
    }
Beispiel #9
0
    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;
    }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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();
        }
Beispiel #13
0
        private void Create()
        {
            if (points.Count < 3)
            {
                return;
            }

            Clear();

            delaunator = new Delaunator(points.ToArray());

            CreateMesh();
            CreateTriangle();
            CreateHull();
            CreateVoronoi();
        }
Beispiel #14
0
    void Clear()
    {
        delaunator = null;

        if (delaunayVisualsContainer != null)
        {
            Destroy(delaunayVisualsContainer.gameObject);
            delaunayVisualsContainer = null;
        }

        if (voronoiVisualContainer != null)
        {
            Destroy(voronoiVisualContainer.gameObject);
            voronoiVisualContainer = null;
        }
    }
Beispiel #15
0
    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);
    }
Beispiel #16
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;
    }
Beispiel #17
0
        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));
                }
            }
        }
Beispiel #18
0
        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;
        }
Beispiel #19
0
        /// <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());
            }
        }
Beispiel #20
0
 public void GlobalSetup()
 {
     points     = distribution.GetPoints(Type, Count).ToArray();
     delaunator = new Delaunator(points);
 }
Beispiel #21
0
        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);
                }
            }
        }