예제 #1
0
        public override IPolygon Generate(double param0, double param1, double param2)
        {
            int numRays = GetParamValueInt(0, param0);

            var g = new Polygon(numRays + 4);

            g.Add(new Vertex(0, 0)); // Center

            double x, y, r, e, step = 2 * Math.PI / numRays;

            for (int i = 0; i < numRays; i++)
            {
                e = Util.Random.NextDouble() * step * 0.7;
                r = (Util.Random.NextDouble() + 0.7) * 0.5;
                x = r * Math.Cos(i * step + e);
                y = r * Math.Sin(i * step + e);

                g.Add(new Vertex(x, y, 2));
                g.Add(new Segment(g.Points[0], g.Points[i + 1], 2));
            }

            g.Add(new Vertex(-1, -1, 1)); // Box
            g.Add(new Vertex(1, -1, 1));
            g.Add(new Vertex(1, 1, 1));
            g.Add(new Vertex(-1, 1, 1));

            numRays = g.Count;
            g.Add(new Segment(g.Points[numRays - 1], g.Points[numRays - 2], 1));
            g.Add(new Segment(g.Points[numRays - 2], g.Points[numRays - 3], 1));
            g.Add(new Segment(g.Points[numRays - 3], g.Points[numRays - 4], 1));
            g.Add(new Segment(g.Points[numRays - 4], g.Points[numRays - 1], 1));

            return g;
        }
예제 #2
0
        public override IPolygon Generate(double param0, double param1, double param2)
        {
            // Number of points on the outer circle
            int n = GetParamValueInt(0, param0);

            double radius = GetParamValueInt(1, param1);

            // Current radius and step size
            double r, h = radius / n;

            var input = new Polygon(n + 1);

            // Inner cirlce (radius = 1) (hole)
            r = 1;
            input.AddContour(CreateCircle(r, (int)(r / h), 1), 1, new Point(0, 0));

            // Center cirlce
            r = (radius + 1.0) / 2.0;
            input.AddContour(CreateCircle(r, (int)(r / h), 2), 2);

            //count = input.Count;

            // Outer cirlce
            r = radius;
            input.AddContour(CreateCircle(r, (int)(r / h), 3), 3);

            // Regions: |++++++|++++++|---|
            //          r             1   0

            input.Regions.Add(new RegionPointer((r + 3.0) / 4.0, 0, 1));
            input.Regions.Add(new RegionPointer((3 * r + 1.0) / 4.0, 0, 2));

            return input;
        }
예제 #3
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);
    }
예제 #5
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);
        }
예제 #6
0
        public Polygon(List <PolygonPart> parts)
        {
            this.parts = parts;
            polygon    = new TriangleNet.Geometry.Polygon(parts.Count);

            foreach (var part in parts)
            {
                polygon.Add(part.contour, part.IsHole);
            }
        }
예제 #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
 //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);
 }
예제 #9
0
        public override IPolygon Generate(double param0, double param1, double param2)
        {
            int n = GetParamValueInt(0, param0);
            int m = n / 2;

            var input = new Polygon(n + 1);

            double ro, r = 10;
            double step = 2 * Math.PI / m;

            var inner = new List<Vertex>(m);

            // Inner ring
            for (int i = 0; i < m; i++)
            {
                inner.Add(new Vertex(r * Math.Cos(i * step), r * Math.Sin(i * step)));
            }

            input.AddContour(inner, 1);

            r = 1.5 * r;

            var outer = new List<Vertex>(n);

            step = 2 * Math.PI / n;
            double offset = step / 2;

            // Outer ring
            for (int i = 0; i < n; i++)
            {
                ro = r;

                if (i % 2 == 0)
                {
                    ro = r + r * Util.Random.NextDouble() * (param1 / 100);
                }

                outer.Add(new Vertex(ro * Math.Cos(i * step + offset), ro * Math.Sin(i * step + offset)));
            }

            input.AddContour(outer, 2);

            input.Holes.Add(new Point(0, 0));

            return input;
        }
예제 #10
0
        /// <summary>
        /// Reconstruct a triangulation from its raw data representation.
        /// </summary>
        public static Mesh ToMesh(Polygon polygon, ITriangle[] triangles)
        {
            Otri tri = default(Otri);
            Osub subseg = default(Osub);
            int i = 0;

            int elements = triangles == null ? 0 : triangles.Length;
            int segments = polygon.Segments.Count;

            // TODO: Configuration should be a function argument.
            var mesh = new Mesh(new Configuration());

            mesh.TransferNodes(polygon.Points);

            mesh.regions.AddRange(polygon.Regions);
            mesh.behavior.useRegions = polygon.Regions.Count > 0;

            if (polygon.Segments.Count > 0)
            {
                mesh.behavior.Poly = true;
                mesh.holes.AddRange(polygon.Holes);
            }

            // Create the triangles.
            for (i = 0; i < elements; i++)
            {
                mesh.MakeTriangle(ref tri);
            }

            if (mesh.behavior.Poly)
            {
                mesh.insegments = segments;

                // Create the subsegments.
                for (i = 0; i < segments; i++)
                {
                    mesh.MakeSegment(ref subseg);
                }
            }

            var vertexarray = SetNeighbors(mesh, triangles);

            SetSegments(mesh, polygon, vertexarray);

            return mesh;
        }
예제 #11
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().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.CrossProduct(z, u);

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

                // 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));
            }
        }
예제 #12
0
        public override IPolygon Generate(double param0, double param1, double param2)
        {
            int n = GetParamValueInt(1, param1);

            var input = new Polygon(n + 4);

            double r = GetParamValueInt(2, param2);

            // Generate circle (hole)
            input.AddContour(CreateCircle(r, n, 1), 1, new Point(0, 0));

            n = GetParamValueInt(0, param0);

            // Generate box
            input.AddContour(CreateRectangle(new Rectangle(-50, -50, 100, 100), n, 2), 2);

            return input;
        }
예제 #13
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);
        }
예제 #14
0
        public void RegeneratePolygon()
        {
            polygon = new TriangleNet.Geometry.Polygon(parts.Count);
            foreach (var part in parts)
            {
                if (part.IsHole)
                {
                    polygon.Add(part.contour, part.IsHole);
                }
            }

            foreach (var part in parts)
            {
                if (!part.IsHole)
                {
                    polygon.Add(part.contour, part.IsHole);
                }
            }
        }
예제 #15
0
    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++;
        }
    }
        public override IPolygon Generate(double param0, double param1, double param2)
        {
            int numPoints = GetParamValueInt(0, param0);
            numPoints = (numPoints / 10) * 10;

            if (numPoints < 5)
            {
                numPoints = 5;
            }

            double exp = (param1 + 10) / 100;

            var input = new Polygon(numPoints);

            int i = 0, cNum = 2 * (int)Math.Floor(Math.Sqrt(numPoints));

            double r, phi, radius = 100, step = 2 * Math.PI / cNum;

            // Distrubute points equally on circle border
            for (; i < cNum; i++)
            {
                // Add a little error
                r = Util.Random.NextDouble();

                input.Add(new Vertex((radius + r) * Math.Cos(i * step),
                    (radius + r) * Math.Sin(i * step)));
            }

            for (; i < numPoints; i++)
            {
                // Use sqrt(rand) to get normal distribution right.
                r = Math.Pow(Util.Random.NextDouble(), exp) * radius;
                phi = Util.Random.NextDouble() * Math.PI * 2;

                input.Add(new Vertex(r * Math.Cos(phi), r * Math.Sin(phi)));
            }

            return input;
        }
예제 #17
0
        public override IPolygon Generate(double param0, double param1, double param2)
        {
            int numPoints = GetParamValueInt(0, param0);
            numPoints = (numPoints / 10) * 10;

            if (numPoints < ranges[0][0])
            {
                numPoints = ranges[0][0];
            }

            var input = new Polygon(numPoints);

            int width = GetParamValueInt(1, param1);
            int height = GetParamValueInt(2, param2);

            for (int i = 0; i < numPoints; i++)
            {
                input.Add(new Vertex(Util.Random.NextDouble() * width,
                        Util.Random.NextDouble() * height));
            }

            return input;
        }
예제 #18
0
        /// <summary>
        /// Reads geometry information from .node or .poly files.
        /// </summary>
        public static void Read(string filename, out Polygon geometry)
        {
            geometry = null;

            string path = Path.ChangeExtension(filename, ".poly");

            if (File.Exists(path))
            {
                geometry = TriangleReader.ReadPolyFile(path);
            }
            else
            {
                path = Path.ChangeExtension(filename, ".node");
                geometry = TriangleReader.ReadNodeFile(path);
            }
        }
예제 #19
0
        /// <summary>
        /// Reads a mesh from .node, .poly or .ele files.
        /// </summary>
        public static void Read(string filename, out Polygon geometry, out List<ITriangle> triangles)
        {
            triangles = null;

            TriangleReader.Read(filename, out geometry);

            string path = Path.ChangeExtension(filename, ".ele");

            if (File.Exists(path) && geometry != null)
            {
                triangles = TriangleReader.ReadEleFile(path);
            }
        }
예제 #20
0
        /// <summary>
        /// Rebuild the input geometry.
        /// </summary>
        private Polygon Rebuild(Mesh mesh)
        {
            var data = new Polygon(mesh.vertices.Count);

            foreach (var v in mesh.vertices.Values)
            {
                // Reset to input vertex.
                v.type = VertexType.InputVertex;

                data.Points.Add(v);
            }

            System.Collections.Generic.List<ISegment> tlist = new System.Collections.Generic.List<ISegment>();

            foreach (Topology.SubSegment tseg in mesh.subsegs.Values)
            {
                tlist.Add(tseg);
            }

            data.Segments.AddRange(tlist);

            data.Holes.AddRange(mesh.holes);
            data.Regions.AddRange(mesh.regions);

            return data;
        }
예제 #21
0
        /// <summary>
        /// Reads geometry information from .node or .poly files.
        /// </summary>
        public void Read(string filename, out Polygon polygon)
        {
            polygon = null;

            string path = Path.ChangeExtension(filename, ".poly");

            if (File.Exists(path))
            {
                polygon = ReadPolyFile(path);
            }
            else
            {
                path = Path.ChangeExtension(filename, ".node");
                polygon = ReadNodeFile(path);
            }
        }
예제 #22
0
        private void button5_Click(object sender, EventArgs e)
        {
            var poly2 = new TriangleNet.Geometry.Polygon();
            var plh   = dataModel.SelectedItem as PolygonHelper;

            //foreach (var item in plh.Polygon.Points)
            {
                var pn = plh.TransformedPoints();
                if (StaticHelpers.signed_area(pn) < 0)
                {
                    pn = pn.Reverse().ToArray();
                }
                var a = pn.Select(z => new Vertex(z.X, z.Y, 0)).ToArray();

                poly2.Add(new Contour(a));
            }

            var rev = plh.Polygon.Childrens.ToArray();

            rev = rev.Reverse().ToArray();
            foreach (var item in rev)
            {
                var pn = item.Points.Select(z => plh.Transform(z)).ToArray();
                var ar = StaticHelpers.signed_area(pn);

                /*if (StaticHelpers.signed_area(pn) > 0)
                 * {
                 *  pn = pn.Reverse().ToArray();
                 * }*/
                var    a    = pn.Select(z => new Vertex(z.X, z.Y, 0)).ToArray();
                var    p0   = plh.Transform(item.Points[0]);
                PointF test = new PointF((float)p0.X, (float)p0.Y);
                var    maxx = pn.Max(z => z.X);
                var    minx = pn.Min(z => z.X);
                var    maxy = pn.Max(z => z.Y);
                var    miny = pn.Min(z => z.Y);

                var tx = rand.Next((int)(minx * 100), (int)(maxx * 100)) / 100f;
                var ty = rand.Next((int)(miny * 100), (int)(maxy * 100)) / 100f;
                while (true)
                {
                    if (StaticHelpers.pnpoly(pn, test.X, test.Y))
                    {
                        break;
                    }

                    tx = rand.Next((int)(minx * 100),
                                   (int)(maxx * 100)) / 100f;
                    ty = rand.Next((int)(miny * 100),
                                   (int)(maxy * 100)) / 100f;
                    test = new PointF(tx, ty);
                }

                poly2.Add(new Contour(a), new TriangleNet.Geometry.Point(test.X, test.Y));
                //poly2.Add(new Contour(a), true);
            }

            var trng = (new GenericMesher()).Triangulate(poly2, new ConstraintOptions(), new QualityOptions());

            var tr = trng.Triangles.Select(z => new PointF[] {
                new PointF((float)z.GetVertex(0).X, (float)z.GetVertex(0).Y),
                new PointF((float)z.GetVertex(1).X, (float)z.GetVertex(1).Y),
                new PointF((float)z.GetVertex(2).X, (float)z.GetVertex(2).Y)
            }).ToArray();

            dataModel.AddItem(new MeshHelper(tr)
            {
                Name = "triangulate"
            });
        }
예제 #23
0
    public override List <SubdividableEdgeLoop <CityEdge> > GetChildren(SubdividableEdgeLoop <CityEdge> parent)
    {
        Vector2[] parentPoints = parent.GetPoints();
        Polygon   parentPoly   = parent.GetPolygon();
        //generate points of interest
        List <RoadDestination> pointsOfInterest = new List <RoadDestination>();
        Vector2 centroid = parent.GetCenter();
        //parent.EnumerateEdges((EdgeLoopEdge edge) =>
        //{
        //    pointsOfInterest.Add(new RoadDestination(Vector2.Lerp(edge.a.pt, edge.b.pt, Random.Range(0.2f, 0.8f)), 1, false, true));
        //});
        Rect bounds = parent.GetBounds();

        bounds.width  = bounds.width * 2;
        bounds.height = bounds.height * 2;
        int potentialRoadPointsRt = Mathf.CeilToInt(Mathf.Sqrt(potentialRoadPoints));

        float approxDiameter           = Mathf.Sqrt(parentPoly.area);
        float minimumPerimeterDistance = approxDiameter / 4f;

        for (int x = 0; x < potentialRoadPointsRt; x++)
        {
            for (int y = 0; y < potentialRoadPointsRt; y++)
            {
                Vector2 point = new Vector2((x / (float)potentialRoadPointsRt) * bounds.width + bounds.xMin,
                                            (y / (float)potentialRoadPointsRt) * bounds.height + bounds.yMin);
                float distBtwnPts = (bounds.width + bounds.height) / (potentialRoadPoints * 2);
                point = point + new Vector2(Random.Range(-1f, 1f), Random.Range(-1, 1f)) * distBtwnPts * 3f;

                if (parentPoly.ContainsPoint(point)) // && parent.DistToPerimeter(point) > minimumPerimeterDistance)
                {
                    pointsOfInterest.Add(new RoadDestination(point, 0, false, false));
                }
            }
        }
        pointsOfInterest.Add(new RoadDestination(bounds.center + new Vector2(bounds.width * 100, bounds.height * 100), 0, false, false));
        pointsOfInterest.Add(new RoadDestination(bounds.center + new Vector2(bounds.width * 100, -bounds.height * 100), 0, false, false));
        pointsOfInterest.Add(new RoadDestination(bounds.center + new Vector2(-bounds.width * 100, -bounds.height * 100), 0, false, false));
        pointsOfInterest.Add(new RoadDestination(bounds.center + new Vector2(-bounds.width * 100, bounds.height * 100), 0, false, false));

        //triangulate points of interest to get potential road segments
        TriangleNet.Geometry.Polygon polygon = new TriangleNet.Geometry.Polygon();
        Dictionary <TriangleNet.Geometry.Vertex, RoadDestination> vertexDestMap = new Dictionary <TriangleNet.Geometry.Vertex, RoadDestination>();

        foreach (RoadDestination dest in pointsOfInterest)
        {
            TriangleNet.Geometry.Vertex vert = new TriangleNet.Geometry.Vertex(dest.point.x, dest.point.y);
            vertexDestMap.Add(vert, dest);
            polygon.Add(vert);
        }
        TriangleNet.Meshing.ConstraintOptions options =
            new TriangleNet.Meshing.ConstraintOptions()
        {
            ConformingDelaunay = true
        };
        TriangleNet.Meshing.GenericMesher mesher = new TriangleNet.Meshing.GenericMesher();
        TriangleNet.Meshing.IMesh         mesh   = mesher.Triangulate(polygon);

        TriangleNet.Voronoi.StandardVoronoi      voronoi      = new TriangleNet.Voronoi.StandardVoronoi((TriangleNet.Mesh)mesh);
        IEnumerable <TriangleNet.Geometry.IEdge> voronoiEdges = voronoi.Edges;
        List <TriangleNet.Topology.DCEL.Vertex>  voronoiVerts = voronoi.Vertices;

        List <DividingEdge> dividingEdges          = new List <DividingEdge>();
        ILinkedGraphEdgeFactory <CityEdge> factory = new CityEdgeFactory();

        foreach (TriangleNet.Geometry.IEdge edge in voronoiEdges)
        {
            Vector2 a = new Vector2((float)voronoiVerts[edge.P0].X, (float)voronoiVerts[edge.P0].Y);
            Vector2 b = new Vector2((float)voronoiVerts[edge.P1].X, (float)voronoiVerts[edge.P1].Y);

            dividingEdges.Add(new DividingEdge(a, b, factory, factoryParams));
        }



        //get vertices as list
        //ICollection<TriangleNet.Geometry.Vertex> vertices = mesh.Vertices;
        //TriangleNet.Geometry.Vertex[] vertexList = new TriangleNet.Geometry.Vertex[vertices.Count];
        //vertices.CopyTo(vertexList, 0);
        //IEnumerable<TriangleNet.Geometry.Edge> meshEdges = mesh.Edges;


        //build a list of dividing edges and pass it to the child collector


        //foreach (TriangleNet.Geometry.Edge edge in meshEdges) {
        //    //if (vertConnections[edge.P0] > 4)
        //    //{
        //    //    vertConnections[edge.P0]--;
        //    //    continue;
        //    //}
        //    //if (vertConnections[edge.P1] > 4)
        //    //{
        //    //    vertConnections[edge.P1]--;
        //    //    continue;
        //    //}
        //    Vector2 a = new Vector2((float)vertexList[edge.P0].X, (float)vertexList[edge.P0].Y);
        //    Vector2 b = new Vector2((float)vertexList[edge.P1].X, (float)vertexList[edge.P1].Y);

        //    dividingEdges.Add(new DividingEdge(a, b, factory, CityEdgeType.LandPath));
        //}

        return(CollectChildren(parent, dividingEdges));
    }
예제 #24
0
 /// <summary>
 /// Reconstruct a triangulation from its raw data representation.
 /// </summary>
 public static Mesh ToMesh(Polygon polygon, IList<ITriangle> triangles)
 {
     return ToMesh(polygon, triangles.ToArray());
 }
예제 #25
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public IPolygon Read(string filename)
        {
            ParseJson(filename);

            var data = new Polygon();

            if (json == null)
            {
                // TODO: Exception?
                return data;
            }

            if (json.ContainsKey("config"))
            {

            }

            int count = 0;

            if (json.ContainsKey("points"))
            {
                var points = json["points"] as Dictionary<string, object>;

                if (points != null)
                {
                    ReadPoints(data, points, ref count);
                }
                else
                {
                    // TODO: Exception?
                    return data;
                }
            }

            if (json.ContainsKey("segments"))
            {
                var segments = json["segments"] as Dictionary<string, object>;

                if (segments != null)
                {
                    ReadSegments(data, segments, count);
                }
            }

            if (json.ContainsKey("holes"))
            {
                var holes = json["holes"] as ArrayList;

                if (holes != null)
                {
                    ReadHoles(data, holes);
                }
            }

            return data;
        }
예제 #26
0
        /// <summary>
        /// Generates a structured mesh.
        /// </summary>
        /// <param name="bounds">Bounds of the mesh.</param>
        /// <param name="nx">Number of segments in x direction.</param>
        /// <param name="ny">Number of segments in y direction.</param>
        /// <returns>Mesh</returns>
        public static IMesh StructuredMesh(Rectangle bounds, int nx, int ny)
        {
            var polygon = new Polygon((nx + 1) * (ny + 1));

            double x, y, dx, dy, left, bottom;

            dx = bounds.Width / nx;
            dy = bounds.Height / ny;

            left = bounds.Left;
            bottom = bounds.Bottom;

            int i, j, k, l, n = 0;

            // Add vertices.
            var points = new Vertex[(nx + 1) * (ny + 1)];

            for (i = 0; i <= nx; i++)
            {
                x = left + i * dx;

                for (j = 0; j <= ny; j++)
                {
                    y = bottom + j * dy;

                    points[n++] = new Vertex(x, y);
                }
            }

            polygon.Points.AddRange(points);

            n = 0;

            // Set vertex hash and id.
            foreach (var v in points)
            {
                v.hash = v.id = n++;
            }

            // Add boundary segments.
            var segments = polygon.Segments;

            segments.Capacity = 2 * (nx + ny);

            Vertex a, b;

            for (j = 0; j < ny; j++)
            {
                // Left
                a = points[j];
                b = points[j + 1];

                segments.Add(new Segment(a, b, 1));

                a.Label = b.Label = 1;

                // Right
                a = points[nx * (ny + 1) + j];
                b = points[nx * (ny + 1) + (j + 1)];

                segments.Add(new Segment(a, b, 1));

                a.Label = b.Label = 1;
            }

            for (i = 0; i < nx; i++)
            {
                // Bottom
                a = points[(ny + 1) * i];
                b = points[(ny + 1) * (i + 1)];

                segments.Add(new Segment(a, b, 1));

                a.Label = b.Label = 1;

                // Top
                a = points[ny + (ny + 1) * i];
                b = points[ny + (ny + 1) * (i + 1)];

                segments.Add(new Segment(a, b, 1));

                a.Label = b.Label = 1;
            }

            // Add triangles.
            var triangles = new InputTriangle[2 * nx * ny];

            n = 0;

            for (i = 0; i < nx; i++)
            {
                for (j = 0; j < ny; j++)
                {
                    k = j + (ny + 1) * i;
                    l = j + (ny + 1) * (i + 1);

                    // Create 2 triangles in rectangle [k, l, l + 1, k + 1].

                    if ((i + j) % 2 == 0)
                    {
                        // Diagonal from bottom left to top right.
                        triangles[n++] = new InputTriangle(k, l, l + 1);
                        triangles[n++] = new InputTriangle(k, l + 1, k + 1);
                    }
                    else
                    {
                        // Diagonal from top left to bottom right.
                        triangles[n++] = new InputTriangle(k, l, k + 1);
                        triangles[n++] = new InputTriangle(l, l + 1, k + 1);
                    }
                }
            }

            return Converter.ToMesh(polygon, triangles);
        }
예제 #27
0
        /// <summary>
        /// Read the vertices from a file, which may be a .node or .poly file.
        /// </summary>
        /// <param name="nodefilename"></param>
        /// <param name="readElements"></param>
        public static Polygon ReadNodeFile(string nodefilename, bool readElements)
        {
            Polygon data;

            startIndex = 0;

            string[] line;
            int invertices = 0, attributes = 0, nodemarkers = 0;

            using (StreamReader reader = new StreamReader(nodefilename))
            {
                if (!TryReadLine(reader, out line))
                {
                    throw new Exception("Can't read input file.");
                }

                // Read number of vertices, number of dimensions, number of vertex
                // attributes, and number of boundary markers.
                invertices = int.Parse(line[0]);

                if (invertices < 3)
                {
                    throw new Exception("Input must have at least three input vertices.");
                }

                if (line.Length > 1)
                {
                    if (int.Parse(line[1]) != 2)
                    {
                        throw new Exception("Triangle only works with two-dimensional meshes.");
                    }
                }

                if (line.Length > 2)
                {
                    attributes = int.Parse(line[2]);
                }

                if (line.Length > 3)
                {
                    nodemarkers = int.Parse(line[3]);
                }

                data = new Polygon(invertices);

                // Read the vertices.
                if (invertices > 0)
                {
                    for (int i = 0; i < invertices; i++)
                    {
                        if (!TryReadLine(reader, out line))
                        {
                            throw new Exception("Can't read input file (vertices).");
                        }

                        if (line.Length < 3)
                        {
                            throw new Exception("Invalid vertex.");
                        }

                        if (i == 0)
                        {
                            startIndex = int.Parse(line[0], nfi);
                        }

                        ReadVertex(data.Points, i, line, attributes, nodemarkers);
                    }
                }
            }

            if (readElements)
            {
                // Read area file
                string elefile = Path.ChangeExtension(nodefilename, ".ele");
                if (File.Exists(elefile))
                {
                    ReadEleFile(elefile, true);
                }
            }

            return data;
        }
예제 #28
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);
    }
예제 #29
0
 static bool IsInside(PolyNode node, Vector2 point)
 {
     foreach (PolyNode childNode in node.Childs)
     {
         var polygon = new Polygon(childNode.Contour);
         if (polygon.Contains(point)) return false;
     }
     return new Polygon(node.Contour).Contains(point);
 }
예제 #30
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);
                }
            }
        }
예제 #31
0
        /// <summary>
        /// Read the vertices and segments from a .poly file.
        /// </summary>
        /// <param name="polyfilename"></param>
        /// <param name="readElements">If true, look for an associated .ele file.</param>
        /// <param name="readElements">If true, look for an associated .area file.</param>
        public static Polygon ReadPolyFile(string polyfilename, bool readElements, bool readArea)
        {
            // Read poly file
            Polygon data;

            startIndex = 0;

            string[] line;
            int invertices = 0, attributes = 0, nodemarkers = 0;

            using (StreamReader reader = new StreamReader(polyfilename))
            {
                if (!TryReadLine(reader, out line))
                {
                    throw new Exception("Can't read input file.");
                }

                // Read number of vertices, number of dimensions, number of vertex
                // attributes, and number of boundary markers.
                invertices = int.Parse(line[0]);

                if (line.Length > 1)
                {
                    if (int.Parse(line[1]) != 2)
                    {
                        throw new Exception("Triangle only works with two-dimensional meshes.");
                    }
                }

                if (line.Length > 2)
                {
                    attributes = int.Parse(line[2]);
                }

                if (line.Length > 3)
                {
                    nodemarkers = int.Parse(line[3]);
                }

                // Read the vertices.
                if (invertices > 0)
                {
                    data = new Polygon(invertices);

                    for (int i = 0; i < invertices; i++)
                    {
                        if (!TryReadLine(reader, out line))
                        {
                            throw new Exception("Can't read input file (vertices).");
                        }

                        if (line.Length < 3)
                        {
                            throw new Exception("Invalid vertex.");
                        }

                        if (i == 0)
                        {
                            // Set the start index!
                            startIndex = int.Parse(line[0], nfi);
                        }

                        ReadVertex(data.Points, i, line, attributes, nodemarkers);
                    }
                }
                else
                {
                    // If the .poly file claims there are zero vertices, that means that
                    // the vertices should be read from a separate .node file.
                    data = ReadNodeFile(Path.ChangeExtension(polyfilename, ".node"));

                    invertices = data.Points.Count;
                }

                var points = data.Points;

                if (points.Count == 0)
                {
                    throw new Exception("No nodes available.");
                }

                // Read the segments from a .poly file.

                // Read number of segments and number of boundary markers.
                if (!TryReadLine(reader, out line))
                {
                    throw new Exception("Can't read input file (segments).");
                }

                int insegments = int.Parse(line[0]);

                int segmentmarkers = 0;
                if (line.Length > 1)
                {
                    segmentmarkers = int.Parse(line[1]);
                }

                int end1, end2, mark;
                // Read and insert the segments.
                for (int i = 0; i < insegments; i++)
                {
                    if (!TryReadLine(reader, out line))
                    {
                        throw new Exception("Can't read input file (segments).");
                    }

                    if (line.Length < 3)
                    {
                        throw new Exception("Segment has no endpoints.");
                    }

                    // TODO: startIndex ok?
                    end1 = int.Parse(line[1]) - startIndex;
                    end2 = int.Parse(line[2]) - startIndex;
                    mark = 0;

                    if (segmentmarkers > 0 && line.Length > 3)
                    {
                        mark = int.Parse(line[3]);
                    }

                    if ((end1 < 0) || (end1 >= invertices))
                    {
                        if (Log.Verbose)
                        {
                            Log.Instance.Warning("Invalid first endpoint of segment.",
                                "MeshReader.ReadPolyfile()");
                        }
                    }
                    else if ((end2 < 0) || (end2 >= invertices))
                    {
                        if (Log.Verbose)
                        {
                            Log.Instance.Warning("Invalid second endpoint of segment.",
                                "MeshReader.ReadPolyfile()");
                        }
                    }
                    else
                    {
                        data.Add(new Segment(points[end1], points[end2], mark));
                    }
                }

                // Read holes from a .poly file.

                // Read the holes.
                if (!TryReadLine(reader, out line))
                {
                    throw new Exception("Can't read input file (holes).");
                }

                int holes = int.Parse(line[0]);
                if (holes > 0)
                {
                    for (int i = 0; i < holes; i++)
                    {
                        if (!TryReadLine(reader, out line))
                        {
                            throw new Exception("Can't read input file (holes).");
                        }

                        if (line.Length < 3)
                        {
                            throw new Exception("Invalid hole.");
                        }

                        data.Holes.Add(new Point(double.Parse(line[1], nfi),
                            double.Parse(line[2], nfi)));
                    }
                }

                // Read area constraints (optional).
                if (TryReadLine(reader, out line))
                {
                    int regions = int.Parse(line[0]);

                    if (regions > 0)
                    {
                        for (int i = 0; i < regions; i++)
                        {
                            if (!TryReadLine(reader, out line))
                            {
                                throw new Exception("Can't read input file (region).");
                            }

                            if (line.Length < 4)
                            {
                                throw new Exception("Invalid region attributes.");
                            }

                            data.Regions.Add(new RegionPointer(
                                double.Parse(line[1], nfi), // Region x
                                double.Parse(line[2], nfi), // Region y
                                int.Parse(line[3]))); // Region id
                        }
                    }
                }
            }

            // Read ele file
            if (readElements)
            {
                string elefile = Path.ChangeExtension(polyfilename, ".ele");
                if (File.Exists(elefile))
                {
                    ReadEleFile(elefile, readArea);
                }
            }

            return data;
        }
예제 #32
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");
        }
예제 #33
0
        /// <summary>
        /// Finds the adjacencies between triangles and subsegments.
        /// </summary>
        private static void SetSegments(Mesh mesh, Polygon polygon, List<Otri>[] vertexarray)
        {
            Otri checktri = default(Otri);
            Otri nexttri; // Triangle
            TVertex checkdest;
            Otri checkneighbor = default(Otri);
            Osub subseg = default(Osub);
            Otri prevlink; // Triangle

            TVertex tmp;
            TVertex sorg, sdest;

            bool notfound;

            //bool segmentmarkers = false;
            int boundmarker;
            int aroundvertex;
            int i;

            int hullsize = 0;

            // Prepare to count the boundary edges.
            if (mesh.behavior.Poly)
            {
                // Link the segments to their neighboring triangles.
                boundmarker = 0;
                i = 0;
                foreach (var item in mesh.subsegs.Values)
                {
                    subseg.seg = item;

                    sorg = polygon.Segments[i].GetVertex(0);
                    sdest = polygon.Segments[i].GetVertex(1);

                    boundmarker = polygon.Segments[i].Label;

                    if ((sorg.id < 0 || sorg.id >= mesh.invertices) || (sdest.id < 0 || sdest.id >= mesh.invertices))
                    {
                        Log.Instance.Error("Segment has an invalid vertex index.", "MeshReader.Reconstruct()");
                        throw new Exception("Segment has an invalid vertex index.");
                    }

                    // set the subsegment's vertices.
                    subseg.orient = 0;
                    subseg.SetOrg(sorg);
                    subseg.SetDest(sdest);
                    subseg.SetSegOrg(sorg);
                    subseg.SetSegDest(sdest);
                    subseg.seg.boundary = boundmarker;
                    // Try linking the subsegment to triangles that share these vertices.
                    for (subseg.orient = 0; subseg.orient < 2; subseg.orient++)
                    {
                        // Take the number for the destination of subsegloop.
                        aroundvertex = subseg.orient == 1 ? sorg.id : sdest.id;

                        int index = vertexarray[aroundvertex].Count - 1;

                        // Look for triangles having this vertex.
                        prevlink = vertexarray[aroundvertex][index];
                        nexttri = vertexarray[aroundvertex][index];

                        checktri = nexttri;
                        tmp = subseg.Org();
                        notfound = true;
                        // Look for triangles having this edge.  Note that I'm only
                        // comparing each triangle's destination with the subsegment;
                        // each triangle's apex is handled through a different vertex.
                        // Because each triangle appears on three vertices' lists, each
                        // occurrence of a triangle on a list can (and does) represent
                        // an edge.  In this way, most edges are represented twice, and
                        // every triangle-subsegment bond is represented once.
                        while (notfound && (checktri.tri.id != Mesh.DUMMY))
                        {
                            checkdest = checktri.Dest();

                            if (tmp == checkdest)
                            {
                                // We have a match. Remove this triangle from the list.
                                //prevlink = vertexarray[aroundvertex][index];
                                vertexarray[aroundvertex].Remove(prevlink);
                                // Bond the subsegment to the triangle.
                                checktri.SegBond(ref subseg);
                                // Check if this is a boundary edge.
                                checktri.Sym(ref checkneighbor);
                                if (checkneighbor.tri.id == Mesh.DUMMY)
                                {
                                    // The next line doesn't insert a subsegment (because there's
                                    // already one there), but it sets the boundary markers of
                                    // the existing subsegment and its vertices.
                                    mesh.InsertSubseg(ref checktri, 1);
                                    hullsize++;
                                }
                                notfound = false;
                            }
                            index--;
                            // Find the next triangle in the stack.
                            prevlink = vertexarray[aroundvertex][index];
                            nexttri = vertexarray[aroundvertex][index];

                            checktri = nexttri;
                        }
                    }

                    i++;
                }
            }

            // Mark the remaining edges as not being attached to any subsegment.
            // Also, count the (yet uncounted) boundary edges.
            for (i = 0; i < mesh.vertices.Count; i++)
            {
                // Search the stack of triangles adjacent to a vertex.
                int index = vertexarray[i].Count - 1;
                nexttri = vertexarray[i][index];
                checktri = nexttri;

                while (checktri.tri.id != Mesh.DUMMY)
                {
                    // Find the next triangle in the stack before this
                    // information gets overwritten.
                    index--;
                    nexttri = vertexarray[i][index];
                    // No adjacent subsegment.  (This overwrites the stack info.)
                    checktri.SegDissolve(mesh.dummysub);
                    checktri.Sym(ref checkneighbor);
                    if (checkneighbor.tri.id == Mesh.DUMMY)
                    {
                        mesh.InsertSubseg(ref checktri, 1);
                        hullsize++;
                    }

                    checktri = nexttri;
                }
            }

            mesh.hullsize = hullsize;
        }
예제 #34
0
        private void ReadSegments(Polygon geometry, Dictionary<string, object> segments, int count)
        {
            ArrayList data = segments["data"] as ArrayList;

            ArrayList markers = null;

            if (segments.ContainsKey("markers"))
            {
                markers = segments["markers"] as ArrayList;
            }

            if (data != null)
            {
                int mark, n = data.Count;

                if (n % 2 != 0)
                {
                    throw new Exception("JSON format error (segments).");
                }

                int p0, p1;

                throw new NotImplementedException();
                // TODO: Fix JSON format

                for (int i = 0; i < n; i += 2)
                {
                    mark = 0;

                    if (markers != null && markers.Count == n)
                    {
                        mark = int.Parse(markers[i / 2].ToString());
                    }

                    p0 = int.Parse(data[i].ToString());
                    p1 = int.Parse(data[i + 1].ToString());

                    if (p0 < 0 || p0 >= count || p1 < 0 || p1 >= count)
                    {
                        throw new Exception("JSON format error (segment index).");
                    }

                    //geometry.Add(new Edge(p0, p1, mark));
                }
            }
        }
예제 #35
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);
        }
예제 #36
0
        private void ReadHoles(Polygon geometry, ArrayList holes)
        {
            int n = holes.Count;

            if (n % 2 != 0)
            {
                throw new Exception("JSON format error (holes).");
            }

            for (int i = 0; i < n; i += 2)
            {
                geometry.Holes.Add(new Point(
                    double.Parse(holes[i].ToString(), Util.Nfi),
                    double.Parse(holes[i + 1].ToString(), Util.Nfi)
                ));
            }
        }
예제 #37
0
        /// <summary>
        /// Rebuild the input geometry.
        /// </summary>
        private Polygon Rebuild(Mesh mesh)
        {
            var data = new Polygon(mesh.vertices.Count);

            foreach (var v in mesh.vertices.Values)
            {
                // Reset to input vertex.
                v.type = VertexType.InputVertex;

                data.Points.Add(v);
            }

            data.Segments.AddRange(mesh.subsegs.ToEdges());

            data.Holes.AddRange(mesh.holes);
            data.Regions.AddRange(mesh.regions);

            return data;
        }
예제 #38
0
        private void ReadPoints(Polygon geometry, Dictionary<string, object> points, ref int count)
        {
            ArrayList data = points["data"] as ArrayList;

            ArrayList markers = null;
            ArrayList attributes = null;

            if (points.ContainsKey("markers"))
            {
                markers = points["markers"] as ArrayList;
            }

            if (points.ContainsKey("attributes"))
            {
                attributes = points["attributes"] as ArrayList;
            }

            if (data != null)
            {
                int mark, n = data.Count;

                if (n % 2 != 0)
                {
                    throw new Exception("JSON format error (points).");
                }

                // Number of points
                count = n / 2;

                for (int i = 0; i < n; i += 2)
                {
                    mark = 0;

                    if (markers != null && markers.Count == count)
                    {
                        mark = int.Parse(markers[i / 2].ToString());
                    }

                    geometry.Add(new Vertex(
                        double.Parse(data[i].ToString(), Util.Nfi),
                        double.Parse(data[i + 1].ToString(), Util.Nfi),
                        mark
                    ));
                }
            }
        }