public void Smooth(IMesh mesh, int limit)
        {
            var smoothedMesh = (Mesh)mesh;

            var mesher     = new GenericMesher(config);
            var predicates = config.Predicates();

            // The smoother should respect the mesh segment splitting behavior.
            this.options.SegmentSplitting = smoothedMesh.behavior.NoBisect;

            // Take a few smoothing rounds (Lloyd's algorithm).
            for (int i = 0; i < limit; i++)
            {
                Step(smoothedMesh, factory, predicates);

                // Actually, we only want to rebuild, if the mesh is no longer
                // Delaunay. Flipping edges could be the right choice instead
                // of re-triangulating...
                smoothedMesh = (Mesh)mesher.Triangulate(Rebuild(smoothedMesh), options);

                factory.Reset();
            }

            smoothedMesh.CopyTo((Mesh)mesh);
        }
예제 #2
0
        private static IMesh GetScatteredDataMesh(Rectangle domain)
        {
            var r = new Rectangle(domain);

            double h = domain.Width / SIZE;

            // Generate a rectangle boundary point set (SIZE points on each side).
            var input = Generate.Rectangle(r, h);

            // Making sure we add some margin to the boundary.
            h = -h / 2;
            r.Resize(h, h);

            int n = Math.Max(1, SIZE * SIZE - input.Points.Count);

            // Add more input points (more sampling points, better interpolation).
            input.Points.AddRange(Generate.RandomPoints(n, r));

            var mesher = new GenericMesher(new Dwyer());

            // Generate mesh.
            var mesh = mesher.Triangulate(input.Points);

            mesh.Renumber();

            return(mesh);
        }
예제 #3
0
        public void TestAdjacencyMatrixDuplicate()
        {
            var p      = GetVertices(true);
            var mesher = new GenericMesher();
            var mesh   = (Mesh)mesher.Triangulate(p);

            mesh.Renumber();

            var matrix = new AdjacencyMatrix(mesh);

            var ai = matrix.RowIndices;

            // Highest vertex id after renumbering is 4, duplicates
            // are ignored.
            Assert.AreEqual(4, ai.Max());

            // Get the single, duplicate vertex.
            var dup = mesh.Vertices
                      .Where(v => v.Type == VertexType.UndeadVertex)
                      .Single();

            // Side effect: undead vertices will have negative indices
            // after computing the adjacency matrix.
            Assert.IsTrue(dup.id < 0);
            Assert.IsTrue(!ai.Contains(dup.id));
        }
예제 #4
0
        public void Execute()
        {
            Util.Tic();
            var polygons = LoadPolygons();
            //Console.WriteLine("  Polygons: {0} (took {1}ms to load)", polygons.Count, Util.Toc());
            string loadingPolygons = $"Polygons: {polygons.Count} (took {Util.Toc()}ms to load)";

            Util.Tic();
            var sequentialInfo = RunSequential(polygons);
            //Console.WriteLine("Sequential: {0}ms", Util.Toc());
            string sequential = $"Sequential: {Util.Toc()}ms";

            Util.Tic();
            var parallelInfo = RunParallel(polygons);
            //Console.WriteLine("  Parallel: {0}ms", Util.Toc());
            string parallel = $"Parallel: {Util.Toc()}ms";
            //var dummymesh = new Mesh(new Configuration());
            var mesher = new GenericMesher(new Configuration());

            DarkMessageBox.Show($"{Name} - {Description}", $"{loadingPolygons}\n{sequential} {sequentialInfo} \n{parallel} {parallelInfo}");

            foreach (var poly in polygons)
            {
                InputGenerated(mesher.Triangulate(poly), EventArgs.Empty);
                DarkMessageBox.Show("Just showing all the read poly files", "Show next");
            }
        }
예제 #5
0
        public static string RunSequential(List <IPolygon> polygons)
        {
            var pool       = new TrianglePool();
            var predicates = new RobustPredicates();

            var config = new Configuration();

            config.Predicates   = () => predicates;
            config.TrianglePool = () => pool.Restart();

            var mesher = new GenericMesher(config);
            var result = new MeshResult();

            foreach (var poly in polygons)
            {
                var mesh = mesher.Triangulate(poly);

                ProcessMesh(mesh, result);
            }

            pool.Clear();

            //Console.WriteLine("Total number of triangles processed: {0}", result.NumberOfTriangles);
            var sequential = $"Total number of triangles processed: {result.NumberOfTriangles}";

            if (result.Invalid > 0)
            {
                //Console.WriteLine("   Number of invalid triangulations: {0}", result.Invalid);
                sequential += $"Number of invalid triangulations: {result.Invalid}";
            }
            return(sequential);
        }
예제 #6
0
        internal void CalcDL(Structure str)
        {
            if (str == null || str.RedPlanning == null || str.RedPlanning.Count == 0)
            {
                return;
            }

            List <Vertex> vrtxs = new List <Vertex>();
            Vertex        vrtx;
            int           i = 1;

            foreach (PlanningVertex item in str.RedPlanning)
            {
                vrtx = new Vertex(item.X, item.Y, item.Number, 2);
                vrtx.Attributes[0] = item.Red;
                vrtx.Attributes[1] = item.Black;
                vrtxs.Add(vrtx);
                i++;
            }

            Contour cnt = new Contour(vrtxs);

            TriangleNet.Geometry.Polygon polygon = new TriangleNet.Geometry.Polygon();
            polygon.Add(cnt);
            GenericMesher     mesher     = new GenericMesher();
            ConstraintOptions constraint = new ConstraintOptions();

            constraint.Convex = true;
            Mesh             meshPlanning = (Mesh)mesher.Triangulate(polygon, constraint);
            TriangleQuadTree meshTree     = new TriangleQuadTree(meshPlanning);

            TriangleNet.Topology.Triangle trgl = (TriangleNet.Topology.Triangle)meshTree.Query(X, Y);
            if (trgl == null)
            {
                Dictionary <Vertex, double> valuePairs = new Dictionary <Vertex, double>();
                Line2d ln;
                foreach (Vertex item in meshPlanning.Vertices)
                {
                    ln = new Line2d(new Point2d(X, Y), new Point2d(item.X, item.Y));
                    valuePairs.Add(item, ln.Length);
                }
                IOrderedEnumerable <KeyValuePair <Vertex, double> > selected = from v in valuePairs // определяем каждый объект как
                                                                               orderby v.Value      // упорядочиваем по возрастанию
                                                                               select v;            // выбираем объект
                List <KeyValuePair <Vertex, double> > lst = selected.ToList();
                foreach (TriangleNet.Topology.Triangle item in meshPlanning.Triangles)
                {
                    if (item.Contains(lst[0].Key) && item.Contains(lst[1].Key))
                    {
                        trgl = item; break;
                    }
                }
            }
            vrtx = new Vertex(X, Y, Number, 2);
            Interpolation.InterpolateAttributes(vrtx, trgl, 1);
            DL = Math.Round(vrtx.Attributes[0], 3);
        }
예제 #7
0
        public static void ExtrudeText(this MeshBuilder builder, string text, string font, FontStyle fontStyle, FontWeight fontWeight, double fontSize, Vector3D textDirection, Point3D p0, Point3D p1)
        {
            var outlineList = GetTextOutlines(text, font, fontStyle, fontWeight, fontSize);

            // Build the polygon to mesh (using Triangle.NET to triangulate)
            var polygon = new TriangleNet.Geometry.Polygon();
            int marker  = 0;

            foreach (var outlines in outlineList)
            {
                var outerOutline = outlines.OrderBy(x => x.AreaOfSegment()).Last();

                for (int i = 0; i < outlines.Count; i++)
                {
                    var outline = outlines[i];
                    var isHole  = i != outlines.Count - 1 && IsPointInPolygon(outerOutline, outline[0]);
                    polygon.AddContour(outline.Select(p => new Vertex(p.X, p.Y)), marker++, isHole);
                    builder.AddExtrudedSegments(outline.ToSegments().Select(x => new SharpDX.Vector2((float)x.X, (float)x.Y)).ToList(),
                                                textDirection, p0, p1);
                }
            }

            var mesher  = new GenericMesher();
            var options = new ConstraintOptions();
            var mesh    = mesher.Triangulate(polygon, options);

            var u = textDirection;

            u.Normalize();
            var z = p1 - p0;

            z.Normalize();
            var v = Vector3D.Cross(z, u);

            // Convert the triangles
            foreach (var t in mesh.Triangles)
            {
                var v0 = t.GetVertex(2);
                var v1 = t.GetVertex(1);
                var v2 = t.GetVertex(0);

                // Add the top triangle.
                // Project the X/Y vertices onto a plane defined by textdirection, p0 and p1.
                builder.AddTriangle(v0.Project(p0, u, v, z, 1), v1.Project(p0, u, v, z, 1), v2.Project(p0, u, v, z, 1));

                // Add the bottom triangle.
                builder.AddTriangle(v2.Project(p0, u, v, z, 0), v1.Project(p0, u, v, z, 0), v0.Project(p0, u, v, z, 0));
            }
            if (builder.CreateNormals)
            {
                builder.Normals = null;
                builder.ComputeNormalsAndTangents(MeshFaces.Default, builder.HasTangents);
            }
        }
예제 #8
0
        public void TestTriangulateDwyer()
        {
            var m = new GenericMesher();

            var vertices = GetVertices();

            var mesh = m.Triangulate(vertices);

            Assert.AreEqual(6, vertices.Count);
            Assert.AreEqual(6, mesh.Vertices.Count);
            Assert.AreEqual(1, mesh.Vertices
                            .Where(v => v.Type == VertexType.UndeadVertex)
                            .Count());
        }
예제 #9
0
        public void TestAdjacencyMatrix()
        {
            var p      = GetVertices(false);
            var mesher = new GenericMesher();
            var mesh   = (Mesh)mesher.Triangulate(p);

            Assert.AreEqual(5, mesh.Vertices.Max(v => v.ID));

            mesh.Renumber();

            var matrix = new AdjacencyMatrix(mesh);

            // Highest vertex id after renumbering is 4, since there
            // is no duplicate vertex.
            Assert.AreEqual(4, matrix.RowIndices.Max());
        }
예제 #10
0
    void CreateMesh()
    {
        colors  = new Color[points.Length];
        normals = new Vector3[points.Length];

        for (int i = 0; i < points.Length; i++)
        {
            float cscale = (points [i].y - 0.9f) / 0.2f;
            colors [i]  = new Color(cscale, 0, 1 - cscale);
            normals [i] = new Vector3(0, 1, 0);
        }
        GenericMesher gm       = new GenericMesher();
        List <Vertex> vertices = new List <Vertex> ();

        for (int i = 0; i < points.Length; i++)
        {
            Vertex v = new Vertex(points [i].x, points [i].z);
            vertices.Add(v);
        }

        //Dwyer dw = new Dwyer ();
        //Configuration con = new Configuration ();
        //dw.Triangulate (vertices, con);

        IMesh imesh = gm.Triangulate(vertices);
        ICollection <Triangle> tri = imesh.Triangles;
        int ntri = tri.Count;

        triangles = new int[3 * ntri];
        int ctri = 0;

        foreach (Triangle triangle in tri)
        {
            triangles[ctri]     = triangle.GetVertexID(0);
            triangles[ctri + 1] = triangle.GetVertexID(1);
            triangles[ctri + 2] = triangle.GetVertexID(2);
            ctri += 3;
        }

        UnityEngine.Mesh mesh = GetComponent <MeshFilter> ().mesh;
        mesh.vertices  = points;
        mesh.triangles = triangles;
        mesh.normals   = normals;
        mesh.colors    = colors;
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
    }
예제 #11
0
        /// <summary>
        /// Smooth mesh with a maximum given number of rounds of Voronoi
        /// iteration.
        /// </summary>
        /// <param name="mesh">The mesh.</param>
        /// <param name="limit">The maximum number of iterations. If
        /// non-positive, no iteration is applied at all.</param>
        /// <param name="tol">The desired tolerance on the result. At each
        /// iteration, the maximum movement by any side is considered, both for
        /// the previous and the current solutions. If their relative difference
        /// is not greater than the tolerance, the current solution is
        /// considered good enough already.</param>
        /// <returns>The number of actual iterations performed. It is 0 if a
        /// non-positive limit is passed. Otherwise, it is always a value
        /// between 1 and the limit (inclusive).
        /// </returns>
        public int Smooth(IMesh mesh, int limit = 10, double tol = .01)
        {
            if (limit <= 0)
            {
                return(0);
            }

            var smoothedMesh = (Mesh)mesh;

            var mesher     = new GenericMesher(config);
            var predicates = config.Predicates();

            // The smoother should respect the mesh segment splitting behavior.
            this.options.SegmentSplitting = smoothedMesh.behavior.NoBisect;

            // The maximum distances moved from any site at the previous and
            // current iterations.
            double
                prevMax = Double.PositiveInfinity,
                currMax = Step(smoothedMesh, factory, predicates);
            // Take a few smoothing rounds (Lloyd's algorithm). The stop
            // criteria are the maximum number of iterations and the convergence
            // criterion.
            int i = 1;

            while (i < limit && Math.Abs(currMax - prevMax) > tol * currMax)
            {
                prevMax = currMax;
                currMax = Step(smoothedMesh, factory, predicates);

                // Actually, we only want to rebuild, if the mesh is no longer
                // Delaunay. Flipping edges could be the right choice instead
                // of re-triangulating...
                smoothedMesh = (Mesh)mesher.Triangulate(Rebuild(smoothedMesh), options);

                factory.Reset();

                i++;
            }

            smoothedMesh.CopyTo((Mesh)mesh);

            return(i);
        }
예제 #12
0
    //public void GenHighway() {
    public IEnumerator GenHighwayCoroutine()
    {
        WorldManager.GenHighwayState = true;
        Dictionary <Vector2, float> densityLookup = new Dictionary <Vector2, float>();

        // cluster nearby points with DBScan
        List <Vector2> features = new List <Vector2>();// = new MyFeatureDataSource().GetFeatureData();

        for (int i = 0; i < patchDensityCenters.Count; i++)
        {
            (Vector2, float)cd = ((Vector2, float))patchDensityCenters[i];
            features.Add(cd.Item1);
            densityLookup[cd.Item1] = cd.Item2;
        }

        var result = RunOfflineDbscan(features);

        // Build highway graph
        var points = new List <Vertex>();

        foreach (int i in result.Clusters.Keys)
        {
            points.Add(new Vertex(result.Clusters[i][0].Feature.x, result.Clusters[i][0].Feature.y));
        }

        // Generate a default mesher
        var mesher = new GenericMesher(new Dwyer());

        // Generate mesh (Delaunay Triangulation)
        mesh = mesher.Triangulate(points);

        // Init edge/vertex lists for mutation
        foreach (Vertex v in mesh.Vertices)
        {
            vertices.Add(v);
        }
        foreach (Edge e in mesh.Edges)
        {
            edges.Add(e);

            // build neighbor map
            Vertex v0 = (Vertex)vertices[e.P0];
            Vertex v1 = (Vertex)vertices[e.P1];
            if (!neighbors.ContainsKey(v0))
            {
                neighbors[v0] = new List <Vertex>();
            }
            neighbors[v0].Add(v1);
        }

        // Remove unecessary edges on cost basis
        foreach (Edge e in mesh.Edges)
        {
            Vertex v0 = (Vertex)vertices[e.P0];
            Vertex v1 = (Vertex)vertices[e.P1];
            (Vector2, Vector2)tup1 = (Util.VertexToVector2(v0), Util.VertexToVector2(v1));
            (Vector2, Vector2)tup2 = (Util.VertexToVector2(v1), Util.VertexToVector2(v0));

            if (!InPatchBounds(regionIdx, tup1.Item1, tup1.Item2))
            {
                RemoveEdge(e);
                continue;
            }

            if (!WorldManager.edgeState.ContainsKey(tup1)) //needs removal check
            {
                if (ShouldRemoveEdge(e, densityLookup))
                {
                    // remove edge for first time
                    WorldManager.edgeState[tup1] = false;
                    WorldManager.edgeState[tup2] = false;
                    RemoveEdge(e);
                }
                else
                {
                    // keep edge, register with edgeState
                    WorldManager.edgeState[tup1] = true;
                    WorldManager.edgeState[tup2] = true;
                }
            }
            else // remove if removed before
            {
                if (!WorldManager.edgeState[tup1])
                {
                    RemoveEdge(e);
                }
            }
        }

        // Generate final highway segments for each edge
        // Uses A* search to pathfind
        int hwCount = 0;

        foreach (Edge e in edges)
        {
            hwCount++;
            (Vector2Int, Vector2Int)eVec = (Util.VertexToVector2Int((Vertex)vertices[e.P0]), Util.VertexToVector2Int((Vertex)vertices[e.P1]));
            Vertex v0 = (Vertex)vertices[e.P0];
            Vertex v1 = (Vertex)vertices[e.P1];

            // Skip pathfinding for edges that have been generated/built already
            if (WorldBuilder.builtHighways.ContainsKey((Util.VertexToVector2(v0), Util.VertexToVector2(v0))) &&
                WorldBuilder.builtHighways[(Util.VertexToVector2(v0), Util.VertexToVector2(v0))])
            {
                //Debug.Log("Aborting pathfind since already built!");
                continue;
            }

            // A* pathfind from v0 to v1
            ArrayList segments = pathfinding.FindPath(Util.VertexToVector2(v0), Util.VertexToVector2(v1));

            // Removal of redundant paths
            int firstIdx = -1, secondIdx = -1;
            List <(Vector2, (Vector2Int, Vector2Int))> vertListFirst = null, vertListSecond = null;
            // traverse from beginning
            for (int i = 0; i < segments.Count - 1; i++)
            {
                Vector2 v = (Vector2)segments[i];

                if (WorldBuilder.DoesChunkContainHighway(v))
                {
                    firstIdx      = i;
                    vertListFirst = WorldBuilder.GetHighwayVertList(v);
                    break;
                }
            }
            // traverse from end
            if (firstIdx >= 0)
            {
                for (int i = segments.Count - 1; i > 0; i--)
                {
                    Vector2 v = (Vector2)segments[i];
                    if (WorldBuilder.DoesChunkContainHighway(v))
                    {
                        secondIdx      = i;
                        vertListSecond = WorldBuilder.GetHighwayVertList(v);
                        break;
                    }
                }
            }

            // segment join logic
            if (vertListFirst != null && vertListSecond != null && firstIdx >= 0 && secondIdx >= 0)
            {
                // Direct connection with existing path
                bool done = false;
                // *--|____/*
                foreach ((Vector2, (Vector2Int, Vector2Int))tup in vertListFirst)
                {
                    if (eVec.Item2 == tup.Item2.Item2 || eVec.Item2 == tup.Item2.Item1)
                    {
                        segments.RemoveRange(firstIdx, segments.Count - firstIdx);
                        segments.Insert(firstIdx, tup.Item1);
                        done = true;
                        break;
                    }
                }
                if (!done)
                {
                    // *\____|--*
                    foreach ((Vector2, (Vector2Int, Vector2Int))tup in vertListSecond)
                    {
                        if (eVec.Item1 == tup.Item2.Item2 || eVec.Item1 == tup.Item2.Item1)
                        {
                            segments.RemoveRange(0, secondIdx);

                            segments.Insert(0, tup.Item1);
                            done = true;
                            break;
                        }
                    }
                }

                if (!done)
                {
                    // No direct connection cases (needs paths from start and end)
                    (bool, (Vector2Int, Vector2Int))sameEdgeRes = DoListsContainSameEdge(vertListFirst, vertListSecond);
                    if (sameEdgeRes.Item1)
                    {
                        Vector2 con1 = FindVecWithEdge(sameEdgeRes.Item2, vertListFirst), con2 = FindVecWithEdge(sameEdgeRes.Item2, vertListSecond);
                        if (con1 == con2) // same vert
                                          // *--|-----* pass through path
                        {
                            segments.RemoveAt(firstIdx);
                            segments.Insert(firstIdx, con1);
                        }
                        else // diff vert
                             // *--|__|--* join at existing path
                             //Debug.Log(firstIdx + " " + secondIdx);
                        {
                            segments.RemoveRange(firstIdx, secondIdx - firstIdx + 1);
                            segments.Insert(firstIdx, con2);
                            segments.Insert(firstIdx, WorldBuilder.SignalVector);
                            segments.Insert(firstIdx, con1);
                        }
                    }
                    else// not matched so edges different!
                    {
                        Vector2 con1 = vertListFirst[0].Item1, con2 = vertListSecond[0].Item1;
                        //neighbor or not
                        if (DoListsContainNeighbors(vertListFirst, vertListSecond))
                        {
                            // *--\./---*
                            segments.RemoveRange(firstIdx, secondIdx - firstIdx + 1);
                            segments.Insert(firstIdx, con2);
                            segments.Insert(firstIdx, WorldBuilder.SignalVector);
                            segments.Insert(firstIdx, con1);
                        }
                        else
                        {
                            // *--|--|--* pass through paths
                            segments.RemoveAt(secondIdx);
                            segments.RemoveAt(firstIdx);
                            segments.Insert(firstIdx, con1);
                            segments.Insert(secondIdx, con2);
                        }
                    }
                }
            }

            foreach (Vector2 v in segments)
            {
                WorldBuilder.AddHighwayVertToChunkHash(v, eVec);
            }

            if (segments != null)
            {
                highways.Add(segments);
            }

            if (hwCount % Settings.hwPathfindingIncrement == 0)
            {
                yield return(null);
            }
        }
        WorldManager.GenHighwayState = false;
    }
예제 #13
0
    void GenMap()
    {
        /*
         *  <settings>
         */
        int starsAm = 10000;

        // What percentage of space is taken up by stars.
        int starDensity = 20;

        // Minimal corridor length relative to maximal star size.
        float minCorridorLengthCoeff = 3.0f;

        // What percentage of space is taken up by corridors.
        int corridorDensity = 60;

        float maxz = 3.0f;

        /*
         *  </settings>
         */

        float max_star_size = Mathf.Max(pos_star_sizes);

        Debug.Log("Max star size: " + max_star_size);
        float min_corridor_length         = max_star_size * minCorridorLengthCoeff;
        float min_corridor_length_squared = Mathf.Pow(min_corridor_length, 2);

        int starsx = Mathf.RoundToInt(Mathf.Sqrt(starsAm));
        int starsy = starsx;

        float width  = (starsx * max_star_size) + ((starsx - 1) * min_corridor_length);
        float height = (starsy * max_star_size) + ((starsy - 1) * min_corridor_length);

        background.transform.localScale = new Vector3(width * 0.11f, 1.0f, height * 0.11f);
        background.GetComponent <MeshRenderer>().material.SetTextureScale("_MainTex", new Vector2(width / 70.0f, height / 70.0f));

        Debug.Log("Dimensions: " + width + ", " + height);

        float minx = width * -0.5f;
        float miny = height * -0.5f;

        float maxx = width * 0.5f;
        float maxy = height * 0.5f;

        float max_offset_x = (width / starsx) - ((min_corridor_length - max_star_size) * 0.5f);
        float max_offset_y = (height / starsy) - ((min_corridor_length - max_star_size) * 0.5f);

        Debug.Log("Offsets: " + max_offset_x + ", " + max_offset_y);

        Rectangle bounds = new Rectangle(minx, miny, width, height);

        TriangleNet.Mesh mesh = (TriangleNet.Mesh)GenericMesher.StructuredMesh(bounds, starsx - 1, starsy - 1);

        List <TriangleNet.Geometry.Vertex> stars = new List <TriangleNet.Geometry.Vertex>();

        List <TriangleNet.Geometry.Vertex> shuffled_verts = new List <TriangleNet.Geometry.Vertex>(mesh.Vertices);

        shuffled_verts.Shuffle();

        int stars_amount = 0;

        foreach (TriangleNet.Geometry.Vertex v in shuffled_verts)
        {
            if (stars_amount > 3 && Random.Range(0, 101) > starDensity)
            {
                continue;
            }
            stars.Add(v);
            stars_amount++;
        }
        GenericMesher gm = new GenericMesher(new SweepLine());

        mesh = (TriangleNet.Mesh)gm.Triangulate(stars);

        StandardVoronoi sv = new StandardVoronoi(mesh);

        Polygon final = new Polygon(sv.Vertices.Count);

        Dictionary <int, TriangleNet.Geometry.Vertex> good_stars = new Dictionary <int, TriangleNet.Geometry.Vertex>();
        Dictionary <int, int> bad2goodstar  = new Dictionary <int, int>();
        List <int>            outBoundStars = new List <int>();

        foreach (TriangleNet.Topology.DCEL.Vertex v in sv.Vertices)
        {
            if (v.x < minx || v.x > maxx || v.y < miny || v.y > maxy)
            {
                outBoundStars.Add(v.id);
                continue;
            }

            bool invalid = false;
            foreach (TriangleNet.Geometry.Vertex other in good_stars.Values)
            {
                Vector2 v1 = new Vector2((float)v.x, (float)v.y);
                Vector2 v2 = new Vector2((float)other.x, (float)other.y);

                if ((v2 - v1).sqrMagnitude < min_corridor_length_squared)
                {
                    invalid = true;

                    bad2goodstar[v.id] = other.id;
                }
            }

            if (invalid)
            {
                continue;
            }

            TriangleNet.Geometry.Vertex new_v = new TriangleNet.Geometry.Vertex(v.x, v.y);
            new_v.id         = v.id;
            good_stars[v.id] = new_v;
            final.Add(new_v);
        }

        List <Segment> good_segments = new List <Segment>();

        foreach (Edge e in sv.Edges)
        {
            if (outBoundStars.Contains(e.P0) || outBoundStars.Contains(e.P1))
            {
                continue;
            }

            int P0_id;
            int P1_id;

            if (bad2goodstar.ContainsKey(e.P0))
            {
                P0_id = bad2goodstar[e.P0];
            }
            else
            {
                P0_id = e.P0;
            }

            if (bad2goodstar.ContainsKey(e.P1))
            {
                P1_id = bad2goodstar[e.P1];
            }
            else
            {
                P1_id = e.P1;
            }

            if (P0_id == P1_id)
            {
                continue;
            }

            good_segments.Add(new Segment(good_stars[P0_id], good_stars[P1_id]));
        }

        Dictionary <int, List <int> > connected_stars = new Dictionary <int, List <int> >();

        foreach (Segment s in good_segments)
        {
            if (!connected_stars.ContainsKey(s.P0))
            {
                connected_stars[s.P0] = new List <int>();
            }
            connected_stars[s.P0].Add(s.P1);

            if (!connected_stars.ContainsKey(s.P1))
            {
                connected_stars[s.P1] = new List <int>();
            }
            connected_stars[s.P1].Add(s.P0);
        }

        Debug.Log("Currently edges: " + good_segments.Count);

        List <Segment> temp_segments = new List <Segment>(good_segments);

        temp_segments.Shuffle();

        foreach (Segment s in temp_segments)
        {
            if (Random.Range(0, 101) > corridorDensity && RemovalConnectionsCheck(connected_stars, s.P0, s.P1))
            {
                connected_stars[s.P0].Remove(s.P1);
                connected_stars[s.P1].Remove(s.P0);
                good_segments.Remove(s);
            }
        }

        foreach (Segment s in good_segments)
        {
            final.Add(s);
        }

        Debug.Log("Stars after everything: " + final.Points.Count);
        Debug.Log("Corridors after everything: " + good_segments.Count);
        CreateMap(final, maxz, 0.0f);
    }
예제 #14
0
        /// <summary>
        /// Reads all .poly files from given directory and processes them in parallel.
        /// </summary>
        public static bool Run(string dir)
        {
            var files = Directory.EnumerateFiles(dir, "*.poly", SearchOption.AllDirectories);

            var queue = new ConcurrentQueue <string>(files);

            int concurrencyLevel = Environment.ProcessorCount / 2;

            var tasks = new Task <MeshResult> [concurrencyLevel];

            for (int i = 0; i < concurrencyLevel; i++)
            {
                tasks[i] = Task.Run(() =>
                {
                    // Each task has it's own triangle pool and predicates instance.
                    var pool       = new TrianglePool();
                    var predicates = new RobustPredicates();

                    // The factory methods return the above instances.
                    var config = new Configuration()
                    {
                        Predicates   = () => predicates,
                        TrianglePool = () => pool.Restart(),
                        RandomSource = () => Random.Shared
                    };

                    var mesher = new GenericMesher(config);
                    var result = new MeshResult();

                    while (queue.Count > 0)
                    {
                        if (queue.TryDequeue(out var file))
                        {
                            var poly = FileProcessor.Read(file);

                            var mesh = mesher.Triangulate(poly);

                            ProcessMesh(mesh, result);
                        }
                    }

                    pool.Clear();

                    return(result);
                });
            }

            Task.WaitAll(tasks);

            int numberOfTriangles = tasks.Sum(t => t.Result.NumberOfTriangles);
            int invalid           = tasks.Sum(t => t.Result.Invalid);

            Console.WriteLine("Total number of triangles processed: {0}", numberOfTriangles);

            if (invalid > 0)
            {
                Console.WriteLine("   Number of invalid triangulations: {0}", invalid);
            }

            return(invalid == 0);
        }
예제 #15
0
    private MeshData UpdateMeshData(MeshData oldData, IClipShape clipShape)
    {
        var clipPolygon  = clipShape.ClipPolygon();
        var oldVertices  = oldData.vertices;
        var oldTriangles = oldData.triangles;
        var oldPaths     = oldData.paths;

        var newVertices = new List <Vector2>(oldVertices.Length);

        var     vertexIndex = new Dictionary <int, int>(oldVertices.Length);
        Vector2 v;

        for (int i = 0; i < oldVertices.Length; i++)
        {
            v = oldVertices[i];
            if (clipPolygon.PointInPolygon(v))
            {
                vertexIndex.Add(i, -1);
            }
            else
            {
                vertexIndex.Add(i, newVertices.Count);
                newVertices.Add(v);
            }
        }

        var        newTriangles     = new List <int>(oldTriangles.Length);
        var        clippedTriangles = new List <int[]>();
        List <int> oldTriangle      = new List <int>(3);

        for (int i = 0; i < oldTriangles.Length / 3; i++)
        {
            oldTriangle.Clear();
            oldTriangle.Add(oldTriangles[3 * i]);
            oldTriangle.Add(oldTriangles[3 * i + 1]);
            oldTriangle.Add(oldTriangles[3 * i + 2]);
            var newTriangle = oldTriangle.Select(oldIndex => vertexIndex[oldIndex]).ToArray();
            if (newTriangle.Any(newIndex => newIndex > -1))
            {
                if (newTriangle.All(newIndex => newIndex > -1) && !clipShape.ShouldClipTriangle(newTriangle.Select(newIndex => newVertices[newIndex])))
                {
                    newTriangles.AddRange(newTriangle);
                }
                else
                {
                    clippedTriangles.Add(oldTriangle.ToArray());
                }
            }
        }

        var newPolygons = clippedTriangles
                          .Select(t => t.Select(oldIndex => (Vector2)oldVertices[oldIndex]))
                          .SelectMany(t => PSClipperHelper.difference(t, clipPolygon.points));

        var mesher = new GenericMesher();

        foreach (var points in newPolygons)
        {
            var poly = new Polygon();
            poly.Add(TerrainMesh.createContour(points));
            var imesh = mesher.Triangulate(poly);
            TerrainMesh.getTriangles(imesh, ref newVertices, ref newTriangles);
        }

        var newPaths = oldPaths
                       .SelectMany(p => PSClipperHelper.difference(p, clipPolygon.points))
                       .Select(p => p.ToArray())
                       .ToArray();

        var particles = oldPaths
                        .SelectMany(p => PSClipperHelper.intersection(p, clipPolygon.points))
                        .Select(p => GenerateParticles(new PSPolygon(p)))
                        .ToArray();

        return(new MeshData(
                   newVertices.Select(c => new Vector3(c.x, c.y, 0)).ToArray(),
                   newVertices.Select(c => (Color32)terrainMesh.terrainTintColor(c, doNotWrapUV)).ToArray(),
                   newVertices.Select(c => terrainMesh.getUV(c, doNotWrapUV)).ToArray(),
                   newVertices.Select(c => terrainMesh.getUV2(c, doNotWrapUV, floorEdges)).ToArray(),
                   newTriangles.ToArray(),
                   newPaths,
                   particles));
    }
예제 #16
0
        public static string RunParallel(List <IPolygon> polygons)
        {
            var queue = new ConcurrentQueue <IPolygon>(polygons);

            int concurrencyLevel = Environment.ProcessorCount;

            var tasks = new Task <MeshResult> [concurrencyLevel];

            for (int i = 0; i < concurrencyLevel; i++)
            {
                tasks[i] = Task.Run(() =>
                {
                    // Each task has it's own triangle pool and predicates instance.
                    var pool       = new TrianglePool();
                    var predicates = new RobustPredicates();

                    var config = new Configuration();

                    // The factory methods return the above instances.
                    config.Predicates   = () => predicates;
                    config.TrianglePool = () => pool.Restart();

                    IPolygon poly;

                    var mesher = new GenericMesher(config);
                    var result = new MeshResult();

                    while (queue.Count > 0)
                    {
                        if (queue.TryDequeue(out poly))
                        {
                            var mesh = mesher.Triangulate(poly);

                            ProcessMesh(mesh, result);
                        }
                    }

                    pool.Clear();

                    return(result);
                });
            }

            Task.WaitAll(tasks);

            int numberOfTriangles = 0;
            int invalid           = 0;

            for (int i = 0; i < concurrencyLevel; i++)
            {
                var result = tasks[i].Result;

                numberOfTriangles += result.NumberOfTriangles;
                invalid           += result.Invalid;
            }
            string parallel = $"Total number of triangles processed: {numberOfTriangles}";

            //Console.WriteLine("Total number of triangles processed: {0}", numberOfTriangles);

            if (invalid > 0)
            {
                //Console.WriteLine("   Number of invalid triangulations: {0}", invalid);
                parallel += $"\tNumber of invalid triangulations: {invalid}";
            }
            return(parallel);
        }
예제 #17
0
    ///////////////////////////////////////////////////////////////////
    // GENERATION FUNCTIONS ///////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////
    ///
    public void GenBlock()
    {
        //List<Vector2f> points = new List<Vector2f>();
        List <Vector2> startLotCenters = new List <Vector2>();

        // find corners
        for (int i = 0; i < verts.Count - 1; i++)
        {
            Vector2 vc = (Vector2)verts[i];
            Vector2 vp = (Vector2)(i == 0 ? verts[verts.Count - 1] : verts[i - 1]);
            Vector2 vn = (Vector2)verts[i + 1];

            Vector2 diffP = vp - vc;
            Vector2 diffN = vn - vc;
            float   angle = Mathf.Abs(Vector2.Angle(diffP, diffN));
            if (angle < 165)
            {
                corners.Add(vc);
                cornersIdx.Add(i);
                //points.Add(new Vector2f(vc.x, vc.y));
            }
        }
        Vector2 avgCorner = Vector2.zero;

        foreach (Vector2 c in corners)
        {
            avgCorner += c;
        }
        avgCorner /= corners.Count;

        foreach (Vector2 c in corners)
        {
            Vector2 dir = (avgCorner - c).normalized;
            startLotCenters.Add(c + dir * 3);
        }
        //corners = new List<Vector2>(tempCorners);

        // gen points

        if (true)
        {
            for (int i = 0; i < startLotCenters.Count - 1; i++)
            {
                Vector2 corner1 = startLotCenters[i];
                Vector2 corner2 = startLotCenters[i + 1];
                lotCenters.Add(corner1);

                Vector2 diff     = corner2 - corner1;
                Vector2 dir      = diff.normalized;
                float   lineDist = diff.magnitude;
                int     numLots  = (int)(lineDist / 7);
                float   lotWidth = lineDist / numLots;

                //traverse corner to corner
                Vector2 cur           = corner1 + (lotWidth / 2) * dir;
                float   distTraversed = lotWidth / 2;

                if (!(
                        cur.x == Mathf.Infinity || cur.x == -Mathf.Infinity || cur.y == Mathf.Infinity || cur.y == -Mathf.Infinity ||
                        float.IsNaN(cur.x) || float.IsNaN(cur.y)
                        ))
                {
                    lotCenters.Add(cur);
                    //points.Add(new Vector2f(cur.x, cur.y));
                    int lotsPlaced = 1;
                    while (distTraversed < lineDist && lotsPlaced < numLots)
                    {
                        cur += (lotWidth / 2) * dir;
                        if (!bounds.InBounds(cur))
                        {
                            break;
                        }
                        //points.Add(new Vector2f(cur.x, cur.y));
                        lotCenters.Add(cur);
                        lotsPlaced++;
                    }
                }
            }
        }



        // Build lot graph
        if (lotCenters.Count >= 3)
        {
            List <Vector2> lotGuides = new List <Vector2>(lotCenters);
            for (int i = 0; i < verts.Count - 1; i++)
            {
                Vector2 v    = (Vector2)verts[i];
                Vector2 dir  = (avgCorner - v).normalized;
                Vector2 newv = v + dir * 1;
                lotGuides.Add(newv);
                outerBoundary.Add(newv);
            }

            List <Vertex> points = new List <Vertex>();
            foreach (Vector2 v in lotGuides)
            {
                points.Add(new Vertex(v.x, v.y));
            }
            //Debug.Log("LotCenters: " + Util.List2String(lotCenters));
            // Generate a default mesher
            var mesher = new GenericMesher(new Dwyer());
            // Generate mesh (Delaunay Triangulation)
            IMesh mesh = mesher.Triangulate(points);
            // Init edge/vertex lists for mutation
            ArrayList vertices = new ArrayList();
            foreach (Vertex v in mesh.Vertices)
            {
                vertices.Add(v);
            }
            foreach (Edge e in mesh.Edges)
            {
                Vertex  vert1 = (Vertex)vertices[e.P0];
                Vertex  vert2 = (Vertex)vertices[e.P1];
                Vector2 vec1  = Util.VertexToVector2(vert1);
                Vector2 vec2  = Util.VertexToVector2(vert2);

                edges.Add((vec1, vec2));

                // build neighbor map
                if (!neighbors.ContainsKey(vec1))
                {
                    neighbors[vec1] = new List <Vector2>();
                }
                if (!neighbors.ContainsKey(vec2))
                {
                    neighbors[vec2] = new List <Vector2>();
                }
                neighbors[vec1].Add(vec2);
                neighbors[vec2].Add(vec1);
            }

            // find lot bounds
            foreach (Vector2 v in lotCenters)
            {
                Lot lot = new Lot(v);
                foreach (Vector2 vn in neighbors[v])
                {
                    Vector2 vNew;
                    if (outerBoundary.Contains(vn))
                    {
                        vNew = vn;
                        // accept as outer bound
                        // 0=N, 1=E, 2=S, 3=W

                        /*if (vn.y > (float)lot.extrema[0]) {
                         * lot.extrema[0] = vn.y;
                         * }
                         * if (vn.x > (float)lot.extrema[1]) {
                         * lot.extrema[1] = vn.x;
                         * }
                         * if (vn.y < (float)lot.extrema[2]) {
                         * lot.extrema[2] = vn.y;
                         * }
                         * if (vn.x < (float)lot.extrema[3]) {
                         * lot.extrema[3] = vn.x;
                         * }*/
                    }
                    else
                    {
                        vNew = (v + vn) / 2;
                    }
                    if (vNew.y > v.y && vNew.y < (float)lot.extrema[0])
                    {
                        lot.extrema[0] = vNew.y;
                    }
                    if (vNew.x > v.x && vNew.x < (float)lot.extrema[1])
                    {
                        lot.extrema[1] = vNew.x;
                    }
                    if (vNew.y < v.y && vNew.y > (float)lot.extrema[2])
                    {
                        lot.extrema[2] = vNew.y;
                    }
                    if (vNew.x < v.x && vNew.x > (float)lot.extrema[3])
                    {
                        lot.extrema[3] = vNew.x;
                    }
                }
                lot.Calc();
                if (!lots.ContainsKey(v))
                {
                    lots.Add(v, lot);
                }
            }
        }


        ///////////////////////////////////////////////////////////////

        /*for (int i = 0; i < verts.Count; i++) {
         * if (i % 6 == 0) {
         *    Vector2 v = (Vector2)verts[i];
         *    points.Add(new Vector2f(v.x, v.y));
         * }
         * }*/

        /*
         * //List<Vector2f> p = CreateRandomPoint();
         *
         *
         * Rectf rect = new Rectf(//0, 0, 20, 20);
         *  bounds.xMin - 500, bounds.zMin - 500,
         *  bounds.xMax + 500, bounds.zMax + 500);
         *
         * Voronoi voronoi = new Voronoi(points, rect, 0);
         *
         * // Now retreive the edges from it, and the new sites position if you used lloyd relaxtion
         * sites = voronoi.SitesIndexedByLocation;
         * edges = voronoi.Edges;
         *
         * //GenVoronoi(points);
         *
         * Debug.Log("Voronoi sites: " + sites.Count + " edges:" + edges.Count);
         */
        // place points along road side

        // building plots

        // extrude plots into buildings
    }