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; }
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; }
/** * 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); }
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); }
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); } }
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); } }
//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); }
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; }
/// <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; }
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)); } }
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; }
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 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); } } }
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; }
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; }
/// <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); } }
/// <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); } }
/// <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; }
/// <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); } }
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" }); }
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)); }
/// <summary> /// Reconstruct a triangulation from its raw data representation. /// </summary> public static Mesh ToMesh(Polygon polygon, IList<ITriangle> triangles) { return ToMesh(polygon, triangles.ToArray()); }
/// <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; }
/// <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); }
/// <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; }
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); }
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); }
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); } } }
/// <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; }
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"); }
/// <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; }
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)); } } }
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); }
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) )); } }
/// <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; }
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 )); } } }