예제 #1
0
    /**
     * Creates a TriangleNet IMesh from a list of shapes. The first shape is considered the base
     * and the rest as hole in that base.
     */
    public static IMesh makeMesh(this List <Shape> shapes)
    {
        var polygon = new TriangleNet.Geometry.Polygon();

        // Add shapes
        for (int i = 0; i < shapes.Count; i++)
        {
            var points = shapes[i].points;
            if (points.Count < 3)
            {
                return(null);
            }

            var isHole = i > 0;
            polygon.Add(new Contour(points.ToListVertex()), isHole);
        }

        var quality = new QualityOptions()
        {
            MinimumAngle = 25
        };

        // return polygon.Triangulate();
        return(polygon.Triangulate(quality));
    }
    public static Mesh MeshFromVoronoi(Voronoi voronoi)
    {
        var options = new TriangleNet.Meshing.ConstraintOptions
        {
            ConformingDelaunay = true
        };

        var vertices      = new List <Vector3>();
        var verticesIndex = 0;
        var triangles     = new List <int>();
        var colors        = new List <Color>();

        var regions = voronoi.Regions();

        for (var i = 0; i < regions.Count; i++)
        {
            var region = regions[i];

            var polygon = new TriangleNetGeo.Polygon();
            foreach (var corner in region)
            {
                polygon.Add(new TriangleNetGeo.Vertex(corner.x, corner.y));
            }

            var cellMesh = (TriangleNet.Mesh)polygon.Triangulate(options);

            vertices.AddRange(
                cellMesh.Vertices.Select(v => new Vector3((float)v.x, 0, (float)v.y))
                );

            triangles.AddRange(
                cellMesh.Triangles.SelectMany(

                    t => t.vertices.Select(v => v.id + verticesIndex)
                    .Reverse()     // Reverse triangles so they're facing the right way
                    )
                );

            // Update index so the next batch of triangles point to the correct vertices
            verticesIndex = vertices.Count;

            // Assign same color to all vertices in region
            var regionColor = new Color(Random.Range(0, 1f), Random.Range(0, 1f), Random.Range(0, 1f));
            colors.AddRange(cellMesh.Vertices.Select(v => regionColor));
        }

        // Just make world-space UVs for now
        var uvs = vertices.Select(v => new Vector2(v.x, v.y));

        var mesh = new Mesh {
            vertices  = vertices.ToArray(),
            colors    = colors.ToArray(),
            uv        = uvs.ToArray(),
            triangles = triangles.ToArray()
        };

        mesh.RecalculateNormals();

        return(mesh);
    }
예제 #3
0
 //create 2D Delauny Triangulation out of the planeCoords[]
 void StartDelaunayTriangulation()
 {
     TriangleNet.Geometry.Polygon polygon = new TriangleNet.Geometry.Polygon();
     for (int i = 0; i < planeCoords.Length; i++)
     {
         polygon.Add(new TriangleNet.Geometry.Vertex(planeCoords[i].x, planeCoords[i].z));
     }
     TriangleNet.Meshing.ConstraintOptions options = new TriangleNet.Meshing.ConstraintOptions()
     {
         ConformingDelaunay = false
     };
     generatedMesh = (TriangleNet.Mesh)polygon.Triangulate(options);
 }
예제 #4
0
        List <PopulationCentreConnection> getNearestNeighbourConnections(List <PopulationCentre> pops, RoadType roadType, List <PopulationCentreConnection> connections = null)
        {
            var geometry = new TriangleNet.Geometry.Polygon();
            //Dictionary<Vertex, PopulationCentre> popDictionary = new Dictionary<Vertex, PopulationCentre>();
            var connectionList = new List <PopulationCentreConnection>();

            foreach (var pop in pops)
            {
                var vertex = new Vertex(pop.Position.x, pop.Position.y);
                //popDictionary.Add(vertex, pop);
                geometry.Add(vertex);
            }
            var       mesh = geometry.Triangulate();
            int       org, dest;
            ITriangle neighbor;
            int       nid;

            foreach (var tri in mesh.Triangles)
            {
                for (int i = 0; i < 3; i++)
                {
                    // The neighbor opposite of vertex i.
                    GetNeighbor(tri, i, out neighbor, out nid);

                    // Consider each edge only once.
                    if ((tri.ID < nid) || (nid < 0))
                    {
                        // Get the edge endpoints.

                        org  = tri.GetVertexID((i + 1) % 3);
                        dest = tri.GetVertexID((i + 2) % 3);
                        var pop1       = pops[org];
                        var pop2       = pops[dest];
                        var connection = new PopulationCentreConnection(pop1, pop2);
                        connection.roadType = roadType;
                        if (connections == null || !connections.Any(x => x.Equal(connection)))
                        {
                            connectionList.Add(connection);
                        }
                    }
                }
            }
            return(connectionList);
        }
    public void GenerateMeshData(ConstraintOptions options)
    {
        var polygon = new TriangleNet.Geometry.Polygon();

        vertices = surroundingCorners
                   .Where(corner => isFaceBorderCorner | corner != borderCorner)
                   .Select(corner => corner.vertex - vertex)
                   .OrderBy(difference => difference.GetAngle())
                   .ToArray();

        normals = new Vertex[vertices.Length];

        for (int q = 0; q < vertices.Length; q++)
        {
            Vertex v0 = vertices[q];
            Vertex v1 = vertices[(q + 1) % vertices.Length];
            normals[q] = (v1 - v0).Perpendicular().Normalize();
        }

        foreach (Vertex vertex in vertices)
        {
            polygon.Add(vertex);
        }

        Mesh mesh = (Mesh)polygon.Triangulate(options);

        triangles = new int[mesh.triangles.Count * 3];
        int index = 0;

        // if conforming delauny is off Id should eqaul index
        // if not I will have to develop a work around
        foreach (var triangle in mesh.triangles)
        {
            var vertices = triangle.vertices;
            triangles[index * 3]     = vertices[2].id;
            triangles[index * 3 + 1] = vertices[1].id;
            triangles[index * 3 + 2] = vertices[0].id;
            index++;
        }
    }
예제 #6
0
        public static UnityEngine.Mesh Mesh(this EPPZ.Geometry.Model.Polygon this_, Color color, TriangulatorType triangulator, string name = "")
        {
            // Create geometry.
            TriangleNet.Geometry.Polygon polygon = this_.TriangleNetPolygon();

            // Triangulate.
            ConstraintOptions options = new ConstraintOptions();
            // ConformingDelaunay
            // Convex
            // SegmentSplitting
            QualityOptions quality = new QualityOptions();
            // MinimumAngle
            // MaximumArea
            // UserTest
            // VariableArea
            // SteinerPoints
            IMesh triangulatedMesh = polygon.Triangulate(options, quality, TriangulatorForType(triangulator));

            // Counts.
            int vertexCount   = triangulatedMesh.Vertices.Count;
            int triangleCount = triangulatedMesh.Triangles.Count;

            // Mesh store.
            Vector3[]  _vertices  = new Vector3[vertexCount];
            Vector2[]  _uv        = new Vector2[vertexCount];
            Vector3[]  _normals   = new Vector3[vertexCount];
            Color[]    _colors    = new Color[vertexCount];
            List <int> _triangles = new List <int>();           // Size may vary

            // Vertices.
            int index = 0;

            foreach (TriangleNet.Geometry.Vertex eachVertex in triangulatedMesh.Vertices)
            {
                _vertices[index] = new Vector3(
                    (float)eachVertex.X,
                    (float)eachVertex.Y,
                    0.0f                     // As of 2D
                    );

                _uv[index]      = _vertices[index];
                _normals[index] = Vector3.forward;
                _colors[index]  = color;

                index++;
            }

            // Triangles.
            foreach (TriangleNet.Topology.Triangle eachTriangle in triangulatedMesh.Triangles)
            {
                // Get vertices.
                Point P2 = eachTriangle.GetVertex(2);
                Point P1 = eachTriangle.GetVertex(1);
                Point P0 = eachTriangle.GetVertex(0);

                // Get centroid.
                Vector2 centroid = new Vector2(
                    (float)(P2.X + P1.X + P0.X) / 3.0f,
                    (float)(P2.Y + P1.Y + P0.Y) / 3.0f
                    );

                // Add only if centroid contained.
                if (this_.ContainsPoint(centroid) || skipCentroidTest)
                {
                    _triangles.Add(P2.ID);
                    _triangles.Add(P1.ID);
                    _triangles.Add(P0.ID);
                }
            }

            // Create / setup mesh.
            Mesh mesh = new Mesh();

            mesh.vertices     = _vertices;
            mesh.uv           = _uv;
            mesh.normals      = _normals;
            mesh.colors       = _colors;
            mesh.subMeshCount = 1;
            mesh.SetTriangles(_triangles.ToArray(), 0);
            mesh.name = name;

            return(mesh);
        }
예제 #7
0
        protected override void ProcessContext(Canvas canvas, List <Point> points)
        {
            if (points.Count < 3)
            {
                return;
            }

            var options = new ConstraintOptions();

            options.ConformingDelaunay = true;

            var quality = new QualityOptions();

            quality.MinimumAngle = MinAngel;
            quality.MaximumArea  = MaxSquare;

            var polygon = new TriangleNet.Geometry.Polygon();

            points.ForEach(p => polygon.Add(new Vertex(p.X, p.Y)));
            for (int i = 0; i < points.Count - 1; i++)
            {
                polygon.Add(new Segment(new Vertex(points[i].X, points[i].Y), new Vertex(points[i + 1].X, points[i + 1].Y)));
            }
            Point last  = points.LastOrDefault();
            Point first = points.FirstOrDefault();

            polygon.Add(new Segment(new Vertex(last.X, last.Y), new Vertex(first.X, first.Y)));
            var mesh = polygon.Triangulate(options, quality);

            this.mesh = mesh;
            if (mesh != null)
            {
                mesh.Refine(quality, true);
            }
            this.mesh.Renumber();
            foreach (ITriangle triangle in mesh.Triangles)
            {
                Point p1 = new Point
                {
                    X  = (triangle.GetVertex(0).X + 1) * 100,
                    Y  = (triangle.GetVertex(0).Y + 1) * 100,
                    ID = triangle.GetVertex(0).ID
                };
                Point p2 = new Point
                {
                    X  = (triangle.GetVertex(1).X + 1) * 100,
                    Y  = (triangle.GetVertex(1).Y + 1) * 100,
                    ID = triangle.GetVertex(1).ID
                };
                Point p3 = new Point
                {
                    X  = (triangle.GetVertex(2).X + 1) * 100,
                    Y  = (triangle.GetVertex(2).Y + 1) * 100,
                    ID = triangle.GetVertex(2).ID
                };
                Triangle myTriangle = new Triangle
                {
                    Points = new List <Point> {
                        p1, p2, p3
                    },
                    SegmentId = triangle.ID
                };

                myTriangle.Stroke      = Brushes.Black;
                myTriangle.MouseEnter += (sender, e) => { MouseEnterAction(sender, e); };
                myTriangle.MouseLeave += (sender, e) => { MouseLeaveAction(sender, e); };
                myTriangle.MouseDown  += (sender, e) => { MouseUp(sender, e); };
                if (canvas != null)
                {
                    canvas.Children.Add(myTriangle);
                }
            }
        }
예제 #8
0
        private void Triangulate_Click(object sender, RoutedEventArgs e)
        {
            var qualityOptions = new TriangleNet.Meshing.QualityOptions();

            qualityOptions.MaximumArea  = double.Parse(hTextBox.Text);
            qualityOptions.MinimumAngle = double.Parse(LTextBox.Text);

            var objct = new TriangleNet.Geometry.Polygon();

            foreach (var item in mycoordinates)
            {
                objct.Add(item);
            }

            for (int i = 0; i < mycoordinates.Count - 1; i++)
            {
                objct.Add(new Segment(mycoordinates[i], mycoordinates[i + 1]));
            }
            objct.Add(new Segment(mycoordinates.LastOrDefault(), mycoordinates.FirstOrDefault()));


            //var test = new TriangleNet.Meshing.Algorithm.SweepLine();
            var constraintOption = new TriangleNet.Meshing.ConstraintOptions();

            meshResult = objct.Triangulate(constraintOption, qualityOptions, new TriangleNet.Meshing.Algorithm.Incremental());
            //Triangulation
            //meshResult = objct.Triangulate(qualityOptions);
            meshResult.Renumber();

            //triangleResult = new List<TriangleNet.Topology.Triangle>(meshResult.Triangles);
            //Triangles
            trianglesResult = GetTrianglesFromMeshTriangles(meshResult.Triangles);
            resultsTriangles.ItemsSource = trianglesResult;
            //Vertices
            verticesResult   = new List <Vertex>(meshResult.Vertices);
            myvertixesResult = meshResult.Vertices.Select(v => new MyVertex {
                Id = v.ID, X = v.X, Y = v.Y
            }).ToList();
            results.ItemsSource = myvertixesResult;

            //Заповнення граничних сегментів
            for (int i = 0; i < boundaries.Count; i++)
            {
                boundaries[i].SetSegments(meshResult.Segments, boundaries.Count);
            }
            //Перетворення орієнтації всіх сегментів проти годинникової стрілки
            for (int i = 0; i < boundaries.Count; i++)
            {
                if (i != boundaries.Count - 1)
                {
                    boundaries[i].SetSegmentsOrientationToCounterclockwise(i, i + 1);
                }
                else
                {
                    boundaries[i].SetSegmentsOrientationToCounterclockwise(i, 0);
                }
            }
            //
            FillGridWithBoundaries(resultsBoundaries, boundaries);
            DrawData(meshResult);

            //Етап 2: Створення матриць Me, Ke, Qe, Re, Pe
            //Підготовка
            //Зчитування параметрів
            double a11 = double.Parse(a11TextBox.Text);
            double a22 = double.Parse(a22TextBox.Text);
            double d   = double.Parse(dTextBox.Text);
            double f   = double.Parse(fTextBox.Text);
            //Створення масиву точок
            var CT = GetPointsArray(myvertixesResult);
            //Створення масиву трикутників
            var NT = GetTrianglesArray(trianglesResult);
            //Створення масиву граничних сегментів
            var NTGR = GetBoundarySegments(boundaries);
            //Створення масиву значень ф-кції f у точках
            var fe = GetFe(CT, f);
            //Етап 3 (ініціалізація A,B)
            //Кількість вузлів
            int nodeNumber = CT.Length;
            var A          = new double[nodeNumber][];

            for (int i = 0; i < nodeNumber; i++)
            {
                A[i] = new double[nodeNumber];
            }

            var b = new double[nodeNumber];

            //Створення Me, Ke, Qe (та їх розсилання)
            double[] function_value = new double[3];
            for (int k = 0; k < trianglesResult.Count; k++)
            {
                //трикутник містить координати вузлів скінченного елемента
                var triangle = NT[k];
                //Підготовка
                double[] i = CT[triangle[0]],
                j = CT[triangle[1]],
                m = CT[triangle[2]];
                double Se = GetArea(i, j, m);
                double ai = GetA(j, m), bi = GetB(j, m), ci = GetC(j, m),
                       aj = GetA(m, i), bj = GetB(m, i), cj = GetC(m, i),
                       am = GetA(i, j), bm = GetB(i, j), cm = GetC(i, j);
                double[] a = new double[] { ai, aj, am },
                B = new double[] { bi, bj, bm },
                c = new double[] { ci, cj, cm };
                function_value[0] = fe[triangle[0]];
                function_value[1] = fe[triangle[1]];
                function_value[2] = fe[triangle[2]];
                //Ke
                var ke = new KE(k, Se, a11, a22, B, c);
                ke.print();
                //Me
                var me = new ME(k, Se, d);
                me.print();
                //Qe
                var qe = new QE(k, Se, fe);
                qe.print();
                //Етап 3
                for (int q = 0; q < 3; q++)
                {
                    //triangle[q] це номер вузла елемента
                    for (int w = 0; w < 3; w++)
                    {
                        A[triangle[q]][triangle[w]] += ke.Ke[q][w] + me.Me[q][w];
                    }

                    b[triangle[q]] += qe.Qe[q][0];
                }
            }
            //Створення Re, Pe (та їх розсилання)
            for (int k = 0; k < boundaries.Count; k++)
            {
                for (int l = 0; l < NTGR[k].Length; l++)
                {
                    //сегмент містить координати вузлів граничного сегмента
                    var segment = NTGR[k][l];
                    //Підготовка
                    double[] i = CT[NTGR[k][l][0]],
                    j = CT[NTGR[k][l][1]];
                    double Length = GetLength(i, j);
                    //Re
                    var re = new RE(k + l, boundaries[k].G, boundaries[k].B,
                                    Length, k + "|" + l + "|" + NTGR[k][l][0] + "-" + NTGR[k][l][1]);
                    re.print();
                    //Pe
                    var pe = new PE(k + l, boundaries[k].G, boundaries[k].B, boundaries[k].Uc,
                                    Length, k + "|" + l + "|" + NTGR[k][l][0] + "-" + NTGR[k][l][1]);
                    pe.print();

                    //Етап 3
                    for (int q = 0; q < 2; q++)
                    {
                        //segment[q] це номер вузла сегмента
                        for (int w = 0; w < 2; w++)
                        {
                            A[segment[q]][segment[w]] += re.Re[q][w];
                        }

                        b[segment[q]] += pe.Pe[q][0];
                    }
                }
            }
            //Запис у файл A,b
            print(A, b);
            //Етап 3-2
            var u = GausseMethod(nodeNumber, A, b);

            printNonFormatted(CT, u, "results.txt");
        }
예제 #9
0
    private static Mesh GetTriangleDotNetMesh(List <Vector2[]> poly_vertices)
    {
        var num_vxs = 0;

        foreach (var ring_vxs in poly_vertices)
        {
            num_vxs += ring_vxs.Length + 1;
        }

        var poly = new TriangleNet.Geometry.Polygon(num_vxs);

        // set vertices
        var ri = 0;

        foreach (var ring_vxs in poly_vertices)
        {
            var vxs_input = new List <TriangleNet.Geometry.Vertex>(ring_vxs.Length + 1);
            foreach (var vx in ring_vxs)
            {
                vxs_input.Add(new TriangleNet.Geometry.Vertex(vx.x, vx.y));
            }

            // add to poly
            bool is_hole = ri != 0;
            var  contour = new TriangleNet.Geometry.Contour(vxs_input);
            poly.Add(contour, is_hole);
            ++ri;
        }

        // triangulate
        var opts = new TriangleNet.Meshing.ConstraintOptions()
        {
            ConformingDelaunay = true
        };
        var tn_mesh = (TriangleNet.Mesh)poly.Triangulate(opts);

        // write
        var tri_vxs = new Vector3[tn_mesh.Triangles.Count * 3];
        var tri_ids = new int[tn_mesh.Triangles.Count * 3];
        int i       = 0;

        foreach (var tri in tn_mesh.Triangles)
        {
            tri_vxs[i + 0] = new Vector3((float)tri.GetVertex(0).x, (float)tri.GetVertex(0).y, 0);
            tri_vxs[i + 1] = new Vector3((float)tri.GetVertex(2).x, (float)tri.GetVertex(2).y, 0);
            tri_vxs[i + 2] = new Vector3((float)tri.GetVertex(1).x, (float)tri.GetVertex(1).y, 0);

            tri_ids[i + 0] = i + 0;
            tri_ids[i + 1] = i + 1;
            tri_ids[i + 2] = i + 2;

            i += 3;
        }

        // create mesh
        var m = new Mesh();

        // assign to mesh
        m.vertices  = tri_vxs;
        m.triangles = tri_ids;

        // recompute geometry
        // QUESTION why do we need bounds?
        m.RecalculateNormals();
        m.RecalculateBounds();

        return(m);
    }