public void Test() { quality = new QualityOptions() { MinimumAngle = 5 }; Debug.Log("test!"); List <Vector3> v = new List <Vector3>(); v.Add(new Vector3(0, 0, 0)); v.Add(new Vector3(10, 0, 95)); v.Add(new Vector3(250, 0, 140)); v.Add(new Vector3(200, 0, 20)); v.Add(new Vector3(150, 0, 60)); Generate(v); }
private void Refine() { if (mesh == null) { return; } double area = meshControlView.ParamMaxAreaValue; var quality = new QualityOptions(); if (area > 0 && area < 1) { quality.MaximumArea = area * statisticView.Statistic.LargestArea; } quality.MinimumAngle = meshControlView.ParamMinAngleValue; double maxAngle = meshControlView.ParamMaxAngleValue; if (maxAngle < 180) { quality.MaximumAngle = maxAngle; } try { mesh.Refine(quality, meshControlView.ParamConformDelChecked); statisticView.UpdateStatistic(mesh); HandleMeshUpdate(); } catch (Exception ex) { LockOnException(); DarkMessageBox.Show("Exception - Refine", ex.Message, MessageBoxButtons.OK); } UpdateLog(); }
public static TriangleNet.Mesh GetTriangleMesh(this IPolygonEntity polyEntity, float segmentLength = 0.1F) { int count = polyEntity.Points.Count; var triPolygon = new Polygon(); for (int i = 0, j = 1; i < count; i++, j = (i + 1) % count) { var curPoint = polyEntity.Points[i]; var nextPoint = polyEntity.Points[j]; var dis = curPoint.DistanceTo(nextPoint); var num = (int)(dis / segmentLength); int id = i + 1; var segments = curPoint.SplitToSegments(nextPoint, num).Select(p => new Vertex(p.x, p.y, id)).ToArray(); for (int m = 0, n = 1; m < segments.Count( ) - 1; m++, n = m + 1) { triPolygon.Add(new Segment(segments [m], segments [n], id), 0); } } //等边三角形面积公式 : S=√3a²/4; √3/4 = 0.443F; var area = 0.443F * segmentLength * segmentLength;// * 1.25F; var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 30F, MaximumArea = area }; // 0.2F }; var triMesh = (TriangleNet.Mesh)triPolygon.Triangulate(options, quality); triMesh.Renumber( ); return(triMesh); }
public static bool Run(bool print = false) { // Generate the input geometry. var poly = CreatePolygon(); // Set minimum angle quality option. var quality = new QualityOptions() { MinimumAngle = 30.0 }; // Generate mesh using the polygons Triangulate extension method. var mesh = poly.Triangulate(quality); if (print) { SvgImage.Save(mesh, "example-3.svg", 500); } return(mesh.Triangles.Count > 0); }
public Region(RegionRule x, int[,] biomeMap) { Id = regionCount++; biome = x.biome; foreach (var edge in x.edges) { foreach (int direction in startDirections(edge.touchPoint, biomeMap)) { calculateBounds(edge, direction, biomeMap); } } Simplify(); if (holes.Count == 0) { foreach (var edge in x.edges) { foreach (int direction in startDirections(edge.touchPoint, biomeMap)) { calculateBounds(edge, direction, biomeMap); } } } outerEdge = holes.First().Border; holes.RemoveAt(0); //holes.ForEach(hole => hole.Border.Reverse()); var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 25 }; var polygon = getPolygon(); pathMesh = polygon.Triangulate(options, quality); graphicsMesh = polygon.Triangulate(); }
public static Mesh GenerateUnityMesh(this TriangleNetMesh triangleNetMesh, QualityOptions options = null) { if (options != null) { triangleNetMesh.Refine(options); } Mesh mesh = new Mesh(); var triangleNetVerts = triangleNetMesh.Vertices.ToList(); var triangles = triangleNetMesh.Triangles; Vector3[] verts = new Vector3[triangleNetVerts.Count]; int[] trisIndex = new int[triangles.Count * 3]; for (int i = 0; i < verts.Length; i++) { verts[i] = (Vector3)triangleNetVerts[i]; } int k = 0; foreach (var triangle in triangles) { for (int i = 2; i >= 0; i--) { trisIndex[k] = triangleNetVerts.IndexOf(triangle.GetVertex(i)); k++; } } mesh.vertices = verts; mesh.triangles = trisIndex; mesh.RecalculateBounds(); mesh.RecalculateNormals(); return(mesh); }
public void FillPath(Color c, PointF [] path) { var polygon = new Polygon(); List <TriangleNet.Geometry.Vertex> V = new List <TriangleNet.Geometry.Vertex>(); for (int j = 0; j < path.Length; j++) { V.Add(new TriangleNet.Geometry.Vertex(path[j].X, path[j].Y)); } polygon.AddContour(V); if (V.Count >= 3) { try { var options = new ConstraintOptions() { }; var quality = new QualityOptions() { }; var mesh = polygon.Triangulate(options, quality); foreach (var t in mesh.Triangles) { var A = t.GetVertex(0); var B = t.GetVertex(1); var C = t.GetVertex(2); AddTriangle((float)A.X, (float)A.Y, (float)B.X, (float)B.Y, (float)C.X, (float)C.Y, c); } } catch (Exception) { } } }
public static Mesh Triangulate(Polyline poly, Plane plane, double min_angle = 0.436332, double max_angle = Math.PI, double max_area = double.MaxValue) { min_angle = Rhino.RhinoMath.ToDegrees(min_angle); max_angle = Rhino.RhinoMath.ToDegrees(max_angle); var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = min_angle, MaximumAngle = max_angle, MaximumArea = max_area, VariableArea = true }; Contour cnt = ToContour(poly, plane); Polygon pgon = new Polygon(); pgon.Add(cnt); var tmesh = pgon.Triangulate(options, quality); return(ToRhinoMesh(tmesh)); }
public static bool Run(bool print = false) { // Generate the input geometry. var poly = CreatePolygon(); // Define regions (first one defines the area constraint). poly.Regions.Add(new RegionPointer(1.5, 0.0, 1, 0.01)); poly.Regions.Add(new RegionPointer(2.5, 0.0, 2)); // Set quality and constraint options. var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 25.0, VariableArea = true }; //quality.UserTest = (t, area) => t.Label == 1 && area > 0.01; var mesh = poly.Triangulate(options, quality); var smoother = new SimpleSmoother(); smoother.Smooth(mesh, 5); if (print) { SvgImage.Save(mesh, "example-5.svg", 500); } return(mesh.Triangles.Count > 0); }
// [Output("Mesh")] // public IDXMeshOut MOut; #endregion fields & pins /* public void Unify(IMesh mesh, ISpread<Vector2D> UniOut, ISpread<int> Indices, I) * { * var vertices = mesh.Vertices; * int vCount = vertices.Count; * * } */ //called when data for any output pin is requested public void Evaluate(int SpreadMax) { SpreadMax = SpreadUtils.SpreadMax(Fvert, FInput, FIsH, FMaxAngle, FMinAngle, FMaxArea, FConDel, FSplit, FSteiner, FBmark, FSmooth, FSmoothLimit, Freg, FRegInd, FConSeg); FOutput.SliceCount = SpreadMax; FVmark.SliceCount = SpreadMax; // FMesh.SliceCount = SpreadMax; FRmark.SliceCount = SpreadMax; FInd.SliceCount = SpreadMax; int index = 0; if (FCal[0]) { List <int> shift = new List <int>(); shift.Add(0); for (int meshID = 0; meshID < SpreadMax; meshID++) { var polygon = new Polygon(); for (int contourID = 0; contourID < Fvert[meshID].SliceCount; contourID++) { int vertexcount = 0; if (Fvert[meshID][contourID] != 0) { vertexcount = Fvert[meshID][contourID]; } else { vertexcount = FInput[meshID].SliceCount; } ISpread <Vertex> vcsSpread = new Spread <Vertex>(); vcsSpread.SliceCount = vertexcount; for (int i = 0; i < vertexcount; i++) { vcsSpread[i] = new Vertex(FInput[meshID][index + i].x, FInput[meshID][index + i].y, FBmark[meshID][index + i]); } if (vertexcount > 1) { if (FConSeg[meshID][contourID]) { for (int segID = 0; segID < vertexcount - 1; segID++) { polygon.Add(new Segment(vcsSpread[segID], vcsSpread[segID + 1]), true); } } else { polygon.Add(new Contour(vcsSpread, contourID + 1), FIsH[meshID][contourID]); } } else { polygon.Add(vcsSpread[0]); } index += vertexcount; } var quality = new QualityOptions() { MinimumAngle = FMinAngle[meshID], MaximumAngle = FMaxAngle[meshID], SteinerPoints = FSteiner[meshID] }; if (Freg[meshID]) { for (int regionID = 0; regionID < FRegInd[meshID].SliceCount; regionID++) { polygon.Regions.Add(new RegionPointer(FRegInd[meshID][regionID].x, FRegInd[meshID][regionID].x, FRegMark[meshID][regionID])); } } else { quality.MaximumArea = FMaxArea[meshID][0]; } // Triangulate the polygon var options = new ConstraintOptions() { ConformingDelaunay = FConDel[meshID], SegmentSplitting = FSplit[meshID] }; if (FSmooth[meshID]) { options = new ConstraintOptions() { ConformingDelaunay = true, SegmentSplitting = FSplit[meshID] } } ; var mesh = polygon.Triangulate(options, quality); if (Freg[meshID]) { foreach (var t in mesh.Triangles) { // Set area constraint for all triangles t.Area = FMaxArea[meshID][t.Label - 1]; } // Use per triangle area constraint for next refinement quality.VariableArea = true; // Refine mesh to meet area constraint. mesh.Refine(quality, FConDel[meshID]); } // Do some smoothing. if (FSmooth[meshID]) { (new SimpleSmoother()).Smooth(mesh, FSmoothLimit[meshID]); } mesh.Renumber(); int triangleCount = mesh.Triangles.Count; int SliceOut = triangleCount * 3; int vertexCount = mesh.Vertices.Count; var vertices = mesh.Vertices.ToSpread(); var triangles = mesh.Triangles.ToSpread(); FRmark[meshID] = new Spread <int>(); FInd[meshID].SliceCount = SliceOut; if (FUni[meshID]) { shift.Add(shift[meshID] + vertexCount * (Convert.ToInt32(FShift[0]))); FOutput[meshID].SliceCount = vertexCount; FVmark[meshID].SliceCount = vertexCount; FRmark[meshID].SliceCount = vertexCount; // FMesh[meshID] = mesh; for (int i = 0; i < triangleCount; i++) { for (int tri = 0; tri < 3; tri++) { FInd[meshID][i * 3 + tri] = triangles[i].GetVertexID(tri) + shift[meshID]; if (triangles[i].Label >= FRmark[meshID][triangles[i].GetVertexID(tri)]) { FRmark[meshID][triangles[i].GetVertexID(tri)] = triangles[i].Label; } } } for (int j = 0; j < vertexCount; j++) { FOutput[meshID][j] = new Vector2D(vertices[j].X, vertices[j].Y); FVmark[meshID][j] = vertices[j].Label; } /* List<int> OldIndices = new List<int>(); * List<int> NewIndices = new List<int>(); * * for (int s=0; s<FConSeg[meshID].SliceCount;s++){ * if (FConSeg[meshID][s]){ * int startindex=0; * * int first=0; * for (int u=0; u<s;u++){ * startindex+=Fvert[meshID][u]; * } * * //only check for points on segments, excluding start and end points * * for (int segPID=1; segPID<Fvert[meshID][s]-1;segPID++){ * int counter=0; * for (int vertID=0;vertID<vertexCount;vertID++){ * if (vertices[vertID].X==FInput[meshID][startindex+segPID].x && vertices[vertID].Y==FInput[meshID][startindex+segPID].y){ * counter++; * if (counter>1){ * OldIndices.Add(vertID); * NewIndices.Add(first); * } * else{ * first = vertID; * } * } * } * } * * for (int indexID=0; indexID<OldIndices.Count;indexID++){ * * FInd[meshID].Select(num => num == OldIndices[indexID] ? NewIndices[indexID] : num); * } * } * } */ //remove duplicate points which do not belong to any triangle List <int> GarbageIndex = new List <int>(); for (int vecID = 0; vecID < FOutput[meshID].SliceCount; vecID++) { bool isPart = false; isPart = FInd[meshID].Contains(vecID); if (!isPart) { GarbageIndex.Add(vecID); } } GarbageIndex.Reverse(); for (int vecID = 0; vecID < GarbageIndex.Count; vecID++) { FOutput[meshID].RemoveAt(GarbageIndex[vecID]); } for (int g = 0; g < FInd[meshID].SliceCount; g++) { for (int h = 0; h < GarbageIndex.Count; h++) { if (FInd[meshID][g] >= GarbageIndex[h]) { int r = FInd[meshID][g] - 1; FInd[meshID][g] = r < 0 ? r + FOutput[meshID].SliceCount : r; } //can be -1? } } } else { shift.Add(shift[meshID] + SliceOut * (Convert.ToInt32(FShift[0]))); FOutput[meshID].SliceCount = SliceOut; FVmark[meshID].SliceCount = SliceOut; FRmark[meshID].SliceCount = SliceOut; for (int i = 0; i < triangleCount; i++) { for (int tri = 0; tri < 3; tri++) { FOutput[meshID][i * 3 + tri] = new Vector2D(triangles[i].GetVertex(tri).X, triangles[i].GetVertex(tri).Y); FVmark[meshID][i * 3 + tri] = triangles[i].GetVertex(tri).Label; FRmark[meshID][i * 3 + tri] = triangles[i].Label; FInd[meshID][i * 3 + tri] = i * 3 + tri + +shift[meshID]; } } } } } } }
private void Triangulate() { if (input == null) { return; } var options = new ConstraintOptions(); var quality = new QualityOptions(); if (meshControlView.ParamConformDelChecked) { options.ConformingDelaunay = true; } if (meshControlView.ParamQualityChecked) { quality.MinimumAngle = meshControlView.ParamMinAngleValue; double maxAngle = meshControlView.ParamMaxAngleValue; if (maxAngle < 180) { quality.MaximumAngle = maxAngle; } // Ignore area constraints on initial triangulation. //double area = slMaxArea.Value * 0.01; //if (area > 0 && area < 1) //{ // var size = input.Bounds; // double min = Math.Min(size.Width, size.Height); // mesh.SetOption(Options.MaxArea, area * min); //} } if (meshControlView.ParamConvexChecked) { options.Convex = true; } try { if (meshControlView.ParamSweeplineChecked) { mesh = (Mesh)input.Triangulate(options, quality, new SweepLine()); } else { mesh = (Mesh)input.Triangulate(options, quality); } statisticView.UpdateStatistic(mesh); HandleMeshUpdate(); if (meshControlView.ParamQualityChecked) { settings.RefineMode = true; } } catch (Exception ex) { LockOnException(); DarkMessageBox.Show("Exception - Triangulate", ex.Message, MessageBoxButtons.OK); } UpdateLog(); }
public OutlineTriangulator(int width, int height) { this.Width = width; this.Height = height; _qualityOptions = new QualityOptions(); }
private Mesh3 meshSlab(Shell slab, List <List <MWPoint3D> > walls) { Shell s = slab; double z = s.Points.Min(p => p.Z); List <List <MWPoint3D> > wallSegments = new List <List <MWPoint3D> >(); foreach (var w in walls) { if (Math.Abs(w[0].Z - z) < 1e-5 && Math.Abs(w[1].Z - z) < 1e-5) { wallSegments.Add(w); } } // we reorder the walls according to their center X coordinate then center Y coordinate wallSegments = wallSegments.OrderBy(seg => 0.5 * (seg[0].X + seg[1].X)).ToList(); //wallSegments = wallSegments.OrderBy(seg => 0.5 * (seg[0].Y + seg[1].Y)).ToList(); foreach (var w in wallSegments) { s.IncludedSegments.Add(new List <MWPoint3D>() { new MWPoint3D(w[0].X, w[0].Y, w[0].Z), new MWPoint3D(w[1].X, w[1].Y, w[1].Z) }); } List <MWPoint2D> s2D = s.Points.Select(p => new MWPoint2D(p.X, p.Y)).ToList(); foreach (var b in modelGeo.Beams) { if (Polygons.isInside(s2D, new MWPoint2D(b.Start.X, b.Start.Y))) { if (b.Start.Z == z) { if (!s.IncludedVertices.Contains(b.Start)) { s.IncludedVertices.Add(b.Start); } } else if (b.End.Z == z) { if (!s.IncludedVertices.Contains(b.End)) { s.IncludedVertices.Add(b.End); } } } } // create mesh using Triangle.NET library Polygon pol = new Polygon(); var res = NormalizeShell(s); GeoTransform transform = res.Item2; var holesN = s.Holes.Select(h => ApplyGeoTransform(h, transform)).ToList(); var segN = s.IncludedSegments.Select(seg => ApplyGeoTransform(seg, transform)).ToList(); var cols = ApplyGeoTransform(s.IncludedVertices, transform); pol.Add(new Contour(res.Item1)); // holes are added for (int j = 0; j < s.Holes.Count; j++) { pol.Add(new Contour(holesN[j]), true); } // segments coming from wall meshes are added List <Vertex> addedVertices = new List <Vertex>(); // WARNING : Here are just added the segments with both endpoints new. It might not work every time. // If a problem is encountered, it might be worth adding the points as vertices and not as segments. for (int j = 0; j < segN.Count; j++) { //if (!addedVertices.Contains(new Vertex(segN[j][0].X, segN[j][0].Y)) && !addedVertices.Contains(new Vertex(segN[j][1].X, segN[j][1].Y))) if (!ContainsVertex(addedVertices, segN[j][0]) && !ContainsVertex(addedVertices, segN[j][1])) { pol.Add(new Segment(segN[j][0], segN[j][1]), true); addedVertices.Add(segN[j][0]); addedVertices.Add(segN[j][1]); } //else if (addedVertices.Contains(new Vertex(segN[j][0].X, segN[j][0].Y)) && addedVertices.Contains(new Vertex(segN[j][1].X, segN[j][1].Y))) else if (ContainsVertex(addedVertices, segN[j][0]) && ContainsVertex(addedVertices, segN[j][1])) { //Console.WriteLine("Both endpoints already added..."); } //else if (addedVertices.Contains(new Vertex(segN[j][0].X, segN[j][0].Y))) else if (ContainsVertex(addedVertices, segN[j][0])) { //pol.Add(new Segment(segN[j][0], segN[j][1]), 1); //addedVertices.Add(segN[j][1]); } //else if (addedVertices.Contains(new Vertex(segN[j][1].X, segN[j][1].Y))) else if (ContainsVertex(addedVertices, segN[j][1])) { //pol.Add(new Segment(segN[j][0], segN[j][1]), 0); //addedVertices.Add(segN[j][0]); } } // vertices coming from columns are added cols.ForEach(c => pol.Add(c)); //pol.Add(new Segment(new Vertex(segN[0][0].X, segN[0][0].Y), new Vertex(segN[0][1].X, segN[0][1].Y)), true); //pol.Add(new Segment(new Vertex(segN[2][0].X, segN[2][0].Y), new Vertex(segN[2][1].X, segN[2][1].Y)), true); double maxL = getMaxDim(s); double maxarea = 0.1 / maxL; Configuration config = new Configuration(); QualityOptions qo = new QualityOptions() { MinimumAngle = 15, MaximumArea = maxarea }; //ConstraintOptions co = new ConstraintOptions() //{ // SegmentSplitting = 1 //}; Mesh MyMesh = (new GenericMesher()).Triangulate(pol, qo) as Mesh; List <Point3> meshPts = deNormalizeMesh(MyMesh.Vertices, s, transform); // return(new Mesh3(meshPts, MyMesh.Triangles.Select(t => new Face3(MyMesh.Vertices.ToList().IndexOf(t.GetVertex(0)), MyMesh.Vertices.ToList().IndexOf(t.GetVertex(1)), MyMesh.Vertices.ToList().IndexOf(t.GetVertex(2)))).ToList())); }
private (Mesh3, List <List <MWPoint3D> >) meshWall(Shell wall, List <List <MWPoint3D> > existingPts = null) { // create mesh using Triangle.NET library Shell w = wall.Clone(); // pre addition of points on the contours List <MWPoint3D> refinedPts = new List <MWPoint3D>(); for (int i = 0; i < w.Points.Count; i++) { int k = i == w.Points.Count - 1 ? 0 : i + 1; MWPoint3D p0 = w.Points[i]; MWPoint3D p1 = w.Points[k]; MWVector3D vec = new MWVector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); vec = vec.Normalised(); double dist = Points.Distance3D(p0, p1); int n = Convert.ToInt32(dist / 0.75) + 1; double inc = dist / n; refinedPts.Add(p0); for (int j = 1; j < n; j++) { MWPoint3D ptAdded = new MWPoint3D(p0.X + j * vec.X * inc, p0.Y + j * vec.Y * inc, p0.Z + j * vec.Z * inc); refinedPts.Add(ptAdded); } } w.Points = refinedPts; if (existingPts != null) { List <MWPoint3D> exPts = existingPts.SelectMany(l => l).ToList(); for (int i = 0; i < exPts.Count; i++) { for (int j = 0; j < w.Points.Count; j++) { int k = j == w.Points.Count - 1 ? 0 : j + 1; if (PointIsOnLine(w.Points[j], w.Points[k], exPts[i])) { w.Points.Insert(k, exPts[i]); j = 0; } } } } Polygon pol = new Polygon(); var res = NormalizeShell(w); var vertices = res.Item1; pol.Add(new Contour(res.Item1)); for (int i = 0; i < vertices.Count; i++) { int k = i == res.Item1.Count - 1 ? 0 : i + 1; if (Math.Sqrt(Math.Pow(vertices[i].X - vertices[k].X, 2) + Math.Pow(vertices[i].Y - vertices[k].Y, 2)) < 0.15) { pol.Add(new Segment(vertices[i], vertices[k]), false); } } GeoTransform transform = res.Item2; double maxL = getMaxDim(w); double maxarea = 0.1 / maxL; Configuration config = new Configuration(); QualityOptions qo = new QualityOptions() { MinimumAngle = 20, MaximumArea = maxarea, }; Mesh MyMesh = (new GenericMesher()).Triangulate(pol, qo) as Mesh; List <Point3> meshPts = deNormalizeMesh(MyMesh.Vertices, wall, transform); // extracting the contour edges for future wall and slab meshing double xmax = MyMesh.Vertices.Max(p => p.X); double xmin = MyMesh.Vertices.Min(p => p.X); double ymax = MyMesh.Vertices.Max(p => p.Y); double ymin = MyMesh.Vertices.Min(p => p.Y); List <List <int> > edgesPtsIdx = MyMesh.Edges.Select(e => new List <int>() { MyMesh.Vertices.ToList().IndexOf(MyMesh.Vertices.Single(p => p.ID == e.P0)), MyMesh.Vertices.ToList().IndexOf(MyMesh.Vertices.Single(p => p.ID == e.P1)) }).ToList(); List <Edge> edges = MyMesh.Edges.ToList(); List <List <MWPoint3D> > TBEdges = new List <List <MWPoint3D> >(); List <Vertex> lv = MyMesh.Vertices.ToList(); for (int i = 0; i < edges.Count; i++) { bool b1 = lv[edgesPtsIdx[i][0]].X == xmin && lv[edgesPtsIdx[i][1]].X == xmin; bool b2 = lv[edgesPtsIdx[i][0]].X == xmax && lv[edgesPtsIdx[i][1]].X == xmax; bool b3 = lv[edgesPtsIdx[i][0]].Y == ymin && lv[edgesPtsIdx[i][1]].Y == ymin; bool b4 = lv[edgesPtsIdx[i][0]].Y == ymax && lv[edgesPtsIdx[i][1]].Y == ymax; if (b1 || b2 || b3 || b4) { TBEdges.Add(new List <MWPoint3D>() { new MWPoint3D(meshPts[edgesPtsIdx[i][0]].X, meshPts[edgesPtsIdx[i][0]].Y, meshPts[edgesPtsIdx[i][0]].Z), new MWPoint3D(meshPts[edgesPtsIdx[i][1]].X, meshPts[edgesPtsIdx[i][1]].Y, meshPts[edgesPtsIdx[i][1]].Z) }); } } return(new Mesh3(meshPts, MyMesh.Triangles.Select(t => new Face3(MyMesh.Vertices.ToList().IndexOf(t.GetVertex(0)), MyMesh.Vertices.ToList().IndexOf(t.GetVertex(1)), MyMesh.Vertices.ToList().IndexOf(t.GetVertex(2)))).ToList()), TBEdges); }
public static bool Triangulate(List <Vector3> points, List <List <Vector3> > holes, out List <int> outIndices, out List <Vector3> outVertices) { outVertices = new List <Vector3>(); outIndices = new List <int>(); Polygon poly = new Polygon(); for (int i = 0; i < points.Count; i++) { float x = points[i].x; float y = points[i].z; poly.Add(new Vertex(x, y)); if (i == points.Count - 1) { poly.Add(new Segment(new Vertex(x, y), new Vertex(points[0].x, points[0].z))); } else { poly.Add(new Segment(new Vertex(x, y), new Vertex(points[i + 1].x, points[i + 1].z))); } } for (int i = 0; i < holes.Count; i++) { List <Vertex> vertices = new List <Vertex>(); for (int j = 0; j < holes[i].Count; j++) { vertices.Add(new Vertex(holes[i][j].x, holes[i][j].z)); } poly.Add(new Contour(vertices), true); } ConstraintOptions constraints = new ConstraintOptions(); QualityOptions quality = new QualityOptions(); quality.MinimumAngle = MinimumAngle; quality.MaximumArea = MaximumArea; var mesh = poly.Triangulate(constraints, quality); foreach (ITriangle t in mesh.Triangles) { for (int j = 2; j >= 0; j--) { bool found = false; for (int k = 0; k < outVertices.Count; k++) { if ((outVertices[k].x == t.GetVertex(j).X) && (outVertices[k].y == t.GetVertex(j).Y)) { outIndices.Add(k); found = true; break; } } if (!found) { outVertices.Add(new Vector3((float)t.GetVertex(j).X, 0, (float)t.GetVertex(j).Y)); outIndices.Add(outVertices.Count - 1); } } } return(true); }
private void RenderColorPath(float[] path) { // triangulate polygon into mesh var polyVertices = new Vertex[path.Length / 2]; var dimX = _graph.DimX; var dimY = _graph.DimY; for (var i = 0; i < path.Length / 2; i++) { polyVertices[i] = new Vertex(dimX.Scale(path[i * 2]), dimY.Scale(path[i * 2 + 1])); } var polygon = new Polygon(); polygon.Add(new Contour(polyVertices)); var options = new ConstraintOptions { Convex = false, ConformingDelaunay = false }; var quality = new QualityOptions { }; if (UseCategories) { quality = new QualityOptions { MaximumArea = 0.002 } } ; var generatedMesh = polygon.Triangulate(options, quality); // convert triangulated mesh into unity mesh var triangles = new int[generatedMesh.Triangles.Count * 3]; var vertices = new Vector3[generatedMesh.Triangles.Count * 3]; var colors = new Color32[vertices.Length]; var counter = 0; foreach (var triangle in generatedMesh.Triangles) { var vectors = triangle.vertices; triangles[counter + 0] = counter + 0; triangles[counter + 1] = counter + 2; triangles[counter + 2] = counter + 1; vertices[counter + 0] = new Vector3(Convert.ToSingle(vectors[0].x), Convert.ToSingle(vectors[0].y), 0); vertices[counter + 1] = new Vector3(Convert.ToSingle(vectors[1].x), Convert.ToSingle(vectors[1].y), 0); vertices[counter + 2] = new Vector3(Convert.ToSingle(vectors[2].x), Convert.ToSingle(vectors[2].y), 0); if (_useCategories && CategoryAxis == 'x') { colors[counter + 0] = GetCategoryColor(vectors[0].x); colors[counter + 1] = GetCategoryColor(vectors[1].x); colors[counter + 2] = GetCategoryColor(vectors[2].x); } else if (_useCategories && CategoryAxis == 'y') { colors[counter + 0] = GetCategoryColor(vectors[0].y); colors[counter + 1] = GetCategoryColor(vectors[1].y); colors[counter + 2] = GetCategoryColor(vectors[2].y); } else { colors[counter + 0] = _color; colors[counter + 1] = _color; colors[counter + 2] = _color; } counter += 3; } var mesh = new Mesh(); _filter.mesh = mesh; mesh.vertices = vertices; mesh.triangles = triangles; mesh.colors32 = colors; mesh.RecalculateBounds(); }
private async void RenderPath(float[][] path) { _currentRenderingCancelSource?.Cancel(); _currentRenderingCancelSource = new CancellationTokenSource(); var cancelToken = _currentRenderingCancelSource.Token; var triangulationTask = Task.Factory.StartNew(() => { try { cancelToken.ThrowIfCancellationRequested(); // triangulate polygon into mesh var polyVertices = new Vertex[path.Length]; for (var i = 0; i < path.Length; i++) { polyVertices[i] = new Vertex(path[i][0], path[i][1]); } cancelToken.ThrowIfCancellationRequested(); var polygon = new Polygon(); polygon.Add(new Contour(polyVertices)); cancelToken.ThrowIfCancellationRequested(); var options = new ConstraintOptions { Convex = false, ConformingDelaunay = false }; var quality = new QualityOptions { }; var result = polygon.Triangulate(options, quality); cancelToken.ThrowIfCancellationRequested(); return(result); } catch (Exception e) { Debug.LogError(e.Message); return(null); } }); var generatedMesh = await triangulationTask; if (cancelToken.IsCancellationRequested || generatedMesh == null) { return; } if (generatedMesh.Triangles.Count == 0) { return; } // convert triangulated mesh into unity mesh var triangles = new int[generatedMesh.Triangles.Count * 3]; var vertices = new Vector3[generatedMesh.Triangles.Count * 3]; var uv = new Vector2[generatedMesh.Triangles.Count * 3]; var meshTask = Task.Factory.StartNew(() => { var counter = 0; double minX = generatedMesh.Triangles.First().vertices[0].x; double maxX = generatedMesh.Triangles.First().vertices[0].x; double minY = generatedMesh.Triangles.First().vertices[0].y; double maxY = generatedMesh.Triangles.First().vertices[0].y; foreach (var triangle in generatedMesh.Triangles) { var vectors = triangle.vertices; foreach (var vertex in vectors) { minX = Math.Min(minX, vertex.x); maxX = Math.Max(maxX, vertex.x); minY = Math.Min(minY, vertex.y); maxY = Math.Max(maxY, vertex.y); } } var rangeX = maxX - minX; var rangeY = maxY - minY; foreach (var triangle in generatedMesh.Triangles) { if (cancelToken.IsCancellationRequested) { return; } var vectors = triangle.vertices; triangles[counter + 0] = counter + 0; triangles[counter + 1] = counter + 2; triangles[counter + 2] = counter + 1; vertices[counter + 0] = new Vector3(Convert.ToSingle(vectors[0].x), Convert.ToSingle(vectors[0].y), 0); vertices[counter + 1] = new Vector3(Convert.ToSingle(vectors[1].x), Convert.ToSingle(vectors[1].y), 0); vertices[counter + 2] = new Vector3(Convert.ToSingle(vectors[2].x), Convert.ToSingle(vectors[2].y), 0); uv[counter + 0] = new Vector2(Convert.ToSingle((vectors[0].x - minX) / rangeX), Convert.ToSingle((vectors[0].y - minY) / rangeY)); uv[counter + 1] = new Vector2(Convert.ToSingle((vectors[1].x - minX) / rangeX), Convert.ToSingle((vectors[1].y - minY) / rangeY)); uv[counter + 2] = new Vector2(Convert.ToSingle((vectors[2].x - minX) / rangeX), Convert.ToSingle((vectors[2].y - minY) / rangeY)); counter += 3; } }); await meshTask; if (cancelToken.IsCancellationRequested) { return; } _currentRenderingCancelSource = null; var mesh = new Mesh { vertices = vertices, triangles = triangles, uv = uv }; mesh.RecalculateBounds(); _meshFilter.mesh = mesh; }
// Use this for initialization void Start( ) { var p = new Polygon(); p.Add(CosSegements(-Size, -Size, Size, -Size, partsNum, 1)); p.Add(CosSegements(Size, -Size, Size, Size, partsNum, 2)); p.Add(CosSegements(Size, Size, -Size, Size, partsNum, 3)); p.Add(CosSegements(-Size, Size, -Size, -Size, partsNum, 4)); //var polygon = FileProcessor.Read("Assets/Plugins/Data/box_with_a_hole.poly"); var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 25F, MaximumArea = 0.1F }; var triMesh = (TriangleNet.Mesh)p.Triangulate(options, quality); var smoothing = new SimpleSmoother(); smoothing.Smooth(triMesh); triMesh.Refine(quality); triMesh.Renumber( ); int boneIndex0 = 0; var bindposes = new List <Matrix4x4>(); var bones = new List <Transform>(); var fBoneWeights = new List <BoneWeight>(); var vertexLookup = new Dictionary <Point, Rigidbody>(); Root = new GameObject( ); Root.transform.parent = transform; Root.transform.localRotation = Quaternion.identity; var voronoi = new StandardVoronoi(triMesh); var triAreas = triMesh.Triangles.Sum(t => t.Area()); Debug.Log("Tri Areas : " + triAreas); Debug.Log("Vor Count : " + voronoi.Faces.Count); float SumArea = 0F; foreach (var face in voronoi.Faces) { var origins = face.GetAllVertices(); //var origins = face.EnumerateEdges().Select(e => (Point) e.Origin); if (origins.Count() > 0) { SumArea += origins.Area( ); var obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);//new GameObject(); obj.transform.localScale = Vector3.one * 0.005F; var renderer = obj.GetComponent <MeshRenderer> ( ); if (renderer) { renderer.enabled = false; } //obj.GetComponent<SphereCollider> ( ).enabled = false; var center = face.generator;// origins.MassCenter(); var worldPosition = transform.TransformPoint(new Vector3(( float )center.x, ( float )center.y, 0)); obj.transform.position = worldPosition; obj.transform.parent = Root.transform; bones.Add(obj.transform); bindposes.Add(obj.transform.worldToLocalMatrix * transform.localToWorldMatrix); var weight = new BoneWeight(); weight.boneIndex0 = boneIndex0; weight.weight0 = 1.0F; fBoneWeights.Add(weight); var rigidbody = obj.AddComponent <Rigidbody>(); rigidbody.useGravity = false; rigidbody.interpolation = RigidbodyInterpolation.Interpolate; rigidbody.mass = origins.Area( ) * KGSM; rigidbody.drag = 4; rigidbody.angularDrag = 2; rigidbody.constraints ^= RigidbodyConstraints.FreezeRotation; //if ( center.y > 1.9 ) rigidbody.isKinematic = true; if (center.y == Size) { rigid_Up.Add(rigidbody); } else if (center.y == -Size) { rigid_Down.Add(rigidbody); } else if (center.x == Size) { rigid_Right.Add(rigidbody); } else if (center.x == -Size) { rigid_Left.Add(rigidbody); } else { others.Add(rigidbody); } All.Add(rigidbody); vertexLookup.Add(center, rigidbody); boneIndex0++; } //SkinnedMeshRenderer.BakeMesh } foreach (var edge in triMesh.Edges) { var v0 = triMesh.Vertices.ElementAt(edge.P0); var v1 = triMesh.Vertices.ElementAt(edge.P1); var pt_0 = new Vector2((float)v0.x, (float)v0.y); var pt_1 = new Vector2((float)v1.x, (float)v1.y); var distance = Vector2.Distance(pt_0, pt_1); var rigid_0 = vertexLookup[v0]; var rigid_1 = vertexLookup[v1]; var spring = rigid_0.gameObject.AddComponent <SpringJoint>(); spring.connectedBody = rigid_1; spring.minDistance = distance * .96F; spring.maxDistance = distance * 1.00F; spring.spring = 8F; spring.damper = 0F; spring.autoConfigureConnectedAnchor = false; spring.enableCollision = false; spring.connectedAnchor = spring.anchor = Vector3.zero; spring.axis = Vector3.back; spring.tolerance = 0.01F; spring.enablePreprocessing = false; } var vertices = triMesh.Vertices.Select(v => new Vector3((float)v.x, (float)v.y, 0)).ToArray(); var triangles = triMesh.Triangles.SelectMany(t => t.vertices.Select(v => v.id)).ToArray();//.Reverse() var normals = triMesh.Vertices.Select(v => transform.forward); var bounds = triMesh.bounds; var l = bounds.Left; var b = bounds.Bottom; var w = bounds.Width; var h = bounds.Height; var uvs = triMesh.Vertices.Select(v => new Vector2(-(float)((v.x - l) / w), (float)((v.y - b) / h))).ToArray(); Debug.Log(string.Format("Vertices : {0}, Edge : {1}, Segments : {2}, Triangles : {3}, Holes : {4}", triMesh.Vertices.Count, triMesh.Edges.Count( ), triMesh.Segments.Count, triMesh.Triangles.Count, triMesh.Holes.Count)); var skinnedRenderer = GetComponent <SkinnedMeshRenderer>(); //var meshFilter = GetComponent<MeshFilter>(); //if ( !meshFilter ) //{ // meshFilter = gameObject.AddComponent<MeshFilter> ( ); //} var uniMesh = new Mesh(); uniMesh.vertices = vertices; uniMesh.triangles = triangles; uniMesh.uv = uvs; uniMesh.normals = normals.ToArray( ); uniMesh.boneWeights = fBoneWeights.ToArray( ); uniMesh.bindposes = bindposes.ToArray( ); skinnedRenderer.sharedMesh = uniMesh; skinnedRenderer.bones = bones.ToArray( ); skinnedRenderer.rootBone = Root.transform; //GetComponent<MeshCollider> ( ).sharedMesh = uniMesh; }
void set2DMesh(List <Vector3> staticPositions, MPath path2) { var mesh = meshes[0]; mesh.Clear(); var polygon = new Polygon(); var points = getPoints(path2); var vertices = ToVertex(points); var contour = new Contour(vertices); Point point = null; for (int i = 0; i < staticPositions.Count; i++) { if (IsPointInPolygon(staticPositions[i], vertices)) { point = new Point(staticPositions[i].x, staticPositions[i].y); UnityEngine.Debug.Log("Is inside"); break; } else { if (IsPointInPolygon(constpoint, vertices)) { UnityEngine.Debug.Log(constpoint + " Is inside"); } } } if (point != null) { polygon.Add(contour, point); } else { polygon.Add(contour); } var options = new ConstraintOptions() { }; var quality = new QualityOptions() { // MinimumAngle = 25, // MaximumArea = 0.01d }; // Triangulate the polygon var polyMesh = polygon.Triangulate(options, quality); var polyVertices = polyMesh.Vertices; var polyTriangles = polyMesh.Triangles; List <Vector3> meshVertices = new List <Vector3> (); List <int> triangles = getTriangles(polyTriangles, meshVertices); mesh.vertices = meshVertices.ToArray(); mesh.triangles = triangles.ToArray(); // Vector3[] normals = mesh.normals; // for (int i = 0; i < normals.Length; i++) // normals [i] = -normals [i]; // mesh.normals = normals; // for (int m = 0; m < mesh.subMeshCount; m++) { // int[] triangles2 = mesh.GetTriangles (m); // for (int i = 0; i < triangles2.Length; i += 3) { // int temp = triangles2 [i + 0]; // triangles2 [i + 0] = triangles2 [i + 1]; // triangles2 [i + 1] = temp; // } // mesh.SetTriangles (triangles2, m); // } }
public void GeneratePolygon() { if (lockHeight) { for (int i = 1; i < points.Count; i++) { Vector3 vec = points[i]; vec.y = points[0].y; points[i] = vec; } } if (points.Count < 3) { return; } CenterPivot(); splinePoints.Clear(); for (int i = 0; i < points.Count; i++) { //if ((i == 0 || i == points.Count - 2 || i == points.Count - 1) && !true) //{ // continue; //} DisplayCatmullRomSpline(i); } List <Vector3> verticesList = new List <Vector3>(); List <Vector3> verts = new List <Vector3>(); List <int> indices = new List <int>(); verticesList.AddRange(splinePoints.ToArray()); //Triangulator traingulator = new Triangulator(verts2d.ToArray()); // indices.AddRange(traingulator.Triangulate()); Polygon polygon = new Polygon(); List <Vertex> vertexs = new List <Vertex>(); for (int i = 0; i < verticesList.Count; i++) { Vertex vert = new Vertex(verticesList[i].x, verticesList[i].z); vert.z = verticesList[i].y; vertexs.Add(vert); } polygon.Add(new Contour(vertexs)); var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 25, MaximumArea = maximumTriangleSize }; TriangleNet.Mesh mesh = (TriangleNet.Mesh)polygon.Triangulate(options, quality); indices.Clear(); foreach (var triangle in mesh.triangles) { Vertex vertex = mesh.vertices[triangle.vertices[2].id]; Vector3 v0 = new Vector3((float)vertex.x, (float)vertex.z, (float)vertex.y); vertex = mesh.vertices[triangle.vertices[1].id]; Vector3 v1 = new Vector3((float)vertex.x, (float)vertex.z, (float)vertex.y); vertex = mesh.vertices[triangle.vertices[0].id]; Vector3 v2 = new Vector3((float)vertex.x, (float)vertex.z, (float)vertex.y); indices.Add(verts.Count); indices.Add(verts.Count + 1); indices.Add(verts.Count + 2); verts.Add(v0); verts.Add(v1); verts.Add(v2); } Vector3[] vertices = verts.ToArray(); for (int i = 0; i < vertices.Length; i++) { vertices[i].y += yOffset; } currentMesh = new Mesh(); currentMesh.vertices = vertices; currentMesh.subMeshCount = 1; currentMesh.SetTriangles(indices, 0); Vector2[] uvs = new Vector2[vertices.Length]; for (int i = 0; i < uvs.Length; i++) { uvs[i] = new Vector2(vertices[i].x, vertices[i].z) * 0.01f * uvScale; } Vector3[] normals = new Vector3[vertices.Length]; for (int i = 0; i < normals.Length; i++) { normals[i] = Vector3.up; } Color[] colors = new Color[vertices.Length]; for (int i = 0; i < colors.Length; i++) { colors[i] = Color.black; } currentMesh.uv = uvs; currentMesh.normals = normals; currentMesh.colors = colors; currentMesh.RecalculateTangents(); currentMesh.RecalculateBounds(); currentMesh.RecalculateTangents(); currentMesh.RecalculateBounds(); trianglesGenerated = indices.Count / 3; MeshFilter filter = GetComponent <MeshFilter>(); filter.mesh = currentMesh; MeshCollider meshCollider = GetComponent <MeshCollider>(); if (meshCollider != null) { meshCollider.sharedMesh = currentMesh; } }
public static UnityEngine.Mesh Triangulate2(List <List <Vector3> > polygons) { UnityEngine.Mesh m = new UnityEngine.Mesh(); List <List <int> > Triangles = new List <List <int> >(); List <int> Edges = new List <int>(); List <Vector3> Vertices = new List <Vector3>(); ConstraintOptions options = new ConstraintOptions() { ConformingDelaunay = false }; QualityOptions quality = new QualityOptions() { MinimumAngle = 25.0 }; //if (polygons.Count < 3) // return null; var data = new List <int>(); var polygon = new Polygon(); Vertex firstVert = null; Vertex nextVert = null; Vertex currentVert = null; /* * foreach (var sub in polygons) * { * if (IsClockwise(sub)) * { * nextVert = null; * var wist = new List<Vector3>(); * for (int i = 0; i < sub.Count; i++) * { * if (nextVert == null) * { * currentVert = new Vertex(sub[i].x, sub[i].y, sub[i].z); * nextVert = new Vertex(sub[i + 1].x, sub[i].y, sub[i + 1].z); * } * else * { * currentVert = nextVert; * if (i == sub.Count - 1) * { * nextVert = firstVert; * } * else * { * nextVert = new Vertex(sub[i + 1].x, sub[i + 1].y, sub[i + 1].z); * } * } * * if (i == 0) * firstVert = currentVert; * * wist.Add(sub[i]); * polygon.Add(currentVert); * polygon.Add(new Segment(currentVert, nextVert)); * } * } * else * { * var cont = new List<Vertex>(); * var wist = new List<Vector3>(); * for (int i = 0; i < sub.Count; i++) * { * wist.Add(sub[i]); * cont.Add(new Vertex(sub[i].x, sub[i].y, sub[i].z)); * } * polygon.Add(new Contour(cont), true); * } * } */ foreach (var sub in polygons) { var poly = new Polygon(); var w = new List <Vector3>(); for (int i = 0; i < sub.Count; i++) { //w.Add(sub[i]); poly.Add(new Vertex(sub[i].x, sub[i].y, sub[i].z)); } var mesh = poly.Triangulate(); //crashes //var mesh = poly.Triangulate(options, quality); foreach (var tri in mesh.Triangles) { data.Add(tri.GetVertexID(0)); data.Add(tri.GetVertexID(2)); data.Add(tri.GetVertexID(1)); } foreach (var edge in mesh.Edges) { if (edge.Label == 0) { continue; } Edges.Add(edge.P0); Edges.Add(edge.P1); } using (var sequenceEnum = mesh.Vertices.GetEnumerator()) { while (sequenceEnum.MoveNext()) { //Vertices.Add(new Vector3((float)sequenceEnum.Current.x, (float)sequenceEnum.Current.z, (float)sequenceEnum.Current.y)); Vertices.Add(new Vector3((float)sequenceEnum.Current.x, (float)0, (float)sequenceEnum.Current.y)); } } Triangles.Add(data); } //smoother mesh with smaller triangles and extra vertices in the middle //var mesh = (TriangleNet.Mesh)polygon.Triangulate(options, quality); m.SetVertices(Vertices); m.subMeshCount = Triangles.Count; for (int i = 0; i < Triangles.Count; i++) { var triangle = Triangles[i]; m.SetTriangles(triangle, i); } //m.RecalculateNormals(); return(m); }
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); }
public static Mesh RefineRegions() { // Generate the input geometry. var poly = new Polygon(); var center = new Point(0, 0); // Three concentric circles. poly.Add(Example2.Circle(1.0, center, 0.1, 1), center); poly.Add(Example2.Circle(2.0, center, 0.1, 2)); poly.Add(Example2.Circle(3.0, center, 0.3, 3)); // Define regions. poly.Regions.Add(new RegionPointer(1.5, 0.0, 1)); poly.Regions.Add(new RegionPointer(2.5, 0.0, 2)); // Set quality and constraint options. var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 25.0 }; // Generate mesh. var mesh = (Mesh)poly.Triangulate(options, quality); var smoother = new SimpleSmoother(); // Smooth mesh and re-apply quality options. smoother.Smooth(mesh); mesh.Refine(quality); // Calculate mesh quality var statistic = new QualityMeasure(); statistic.Update(mesh); // Use the minimum triangle area for region refinement double area = 1.75 * statistic.AreaMinimum; foreach (var t in mesh.Triangles) { // Set area constraint for all triangles in region 1 if (t.Label == 1) { t.Area = area; } } // Use per triangle area constraint for next refinement quality.VariableArea = true; // Refine mesh to meet area constraint. mesh.Refine(quality); // Smooth once again. smoother.Smooth(mesh); return(mesh); }
/// <summary> /// Triangulates a polygon, applying quality and constraint options. /// </summary> /// <param name="polygon">Polygon instance.</param> /// <param name="options">Constraint options.</param> /// <param name="quality">Quality options.</param> /// <param name="triangulator">The triangulation algorithm.</param> public static IMesh Triangulate(this IPolygon polygon, ConstraintOptions options, QualityOptions quality, ITriangulator triangulator) { return((new GenericMesher(triangulator)).Triangulate(polygon, options, quality)); }
/// <summary> /// Triangulates a polygon, applying quality options. /// </summary> /// <param name="polygon">Polygon instance.</param> /// <param name="quality">Quality options.</param> public static IMesh Triangulate(this IPolygon polygon, QualityOptions quality) { return((new GenericMesher()).Triangulate(polygon, null, quality)); }
private void RenderGradientPath(float[] path) { // triangulate polygon into mesh var polyVertices = new Vertex[path.Length / 2]; var dimX = _graph.DimX; var dimY = _graph.DimY; for (var i = 0; i < path.Length / 2; i++) { polyVertices[i] = new Vertex(dimX.Scale(path[i * 2]), dimY.Scale(path[i * 2 + 1])); } var polygon = new Polygon(); polygon.Add(new Contour(polyVertices)); var options = new ConstraintOptions { Convex = false, ConformingDelaunay = false }; // restrict maximumarea to allow proper vertex-colouring of gradients var quality = new QualityOptions { MaximumArea = 0.005 }; var generatedMesh = polygon.Triangulate(options, quality); // quick hack: gradient cannot expand outside of graph bounds [-0.5, 0.5] float min, max; if (GradientAxis == 'x') { min = dimX.Scale(MinGradient); max = dimX.Scale(MaxGradient); } else { min = dimY.Scale(MinGradient); max = dimY.Scale(MaxGradient); } var range = max - min; // convert triangulated mesh into unity mesh var triangles = new int[generatedMesh.Triangles.Count * 3]; var vertices = new Vector3[generatedMesh.Triangles.Count * 3]; var colors = new Color32[vertices.Length]; var counter = 0; foreach (var triangle in generatedMesh.Triangles) { var vectors = triangle.vertices; triangles[counter + 0] = counter + 0; triangles[counter + 1] = counter + 2; triangles[counter + 2] = counter + 1; vertices[counter + 0] = new Vector3(Convert.ToSingle(vectors[0].x), Convert.ToSingle(vectors[0].y), 0); vertices[counter + 1] = new Vector3(Convert.ToSingle(vectors[1].x), Convert.ToSingle(vectors[1].y), 0); vertices[counter + 2] = new Vector3(Convert.ToSingle(vectors[2].x), Convert.ToSingle(vectors[2].y), 0); if (GradientAxis == 'x') { colors[counter + 0] = GetGradient((vectors[0].x - min) / range); colors[counter + 1] = GetGradient((vectors[1].x - min) / range); colors[counter + 2] = GetGradient((vectors[2].x - min) / range); } else { colors[counter + 0] = GetGradient((vectors[0].y - min) / range); colors[counter + 1] = GetGradient((vectors[1].y - min) / range); colors[counter + 2] = GetGradient((vectors[2].y - min) / range); } counter += 3; } var mesh = new Mesh(); _filter.mesh = mesh; mesh.vertices = vertices; mesh.triangles = triangles; mesh.colors32 = colors; mesh.RecalculateBounds(); }
/// <summary> Triangulates a polygon, applying quality and constraint options. </summary> /// <param name="polygon">Polygon.</param> /// <param name="options">Constraint options.</param> /// <param name="quality">Quality options.</param> public static Mesh Triangulate(this Polygon polygon, ConstraintOptions options, QualityOptions quality) { return(new Dwyer() .Triangulate(polygon.Points) .ApplyConstraints(polygon, options, quality)); }
/// <summary> /// Triangulates a polygon, applying quality and constraint options. /// </summary> /// <param name="options">Constraint options.</param> /// <param name="quality">Quality options.</param> internal static IMesh Triangulate(this IPolygon polygon, ConstraintOptions options, QualityOptions quality) { return((new GenericMesher()).Triangulate(polygon, options, quality)); }
public static void Tessellate(float minAngle, float maxAngle, float meshAreaFactor, float largestTriangleAreaFactor, int smoothIterations, IList <Vector2> vertices, IList <Edge> edges, IList <int> indices) { if (vertices.Count < 3) { return; } largestTriangleAreaFactor = Mathf.Clamp01(largestTriangleAreaFactor); var polygon = new Polygon(vertices.Count); for (int i = 0; i < vertices.Count; ++i) { Vector2 position = vertices[i]; polygon.Add(new Vertex(position.x, position.y, 1)); } for (int i = 0; i < edges.Count; ++i) { Edge edge = edges[i]; polygon.Add(new Segment(polygon.Points[edge.index1], polygon.Points[edge.index2])); } var mesh = polygon.Triangulate(); var statistic = new Statistic(); statistic.Update((UnityEngine.Experimental.U2D.TriangleNet.Mesh)mesh, 1); var maxAreaToApply = (double)Mathf.Max((float)statistic.LargestArea * largestTriangleAreaFactor, (float)(statistic.MeshArea * meshAreaFactor)); var qualityOptions = new QualityOptions() { SteinerPoints = 0 }; if (maxAreaToApply > 0f) { qualityOptions.MaximumArea = maxAreaToApply; } qualityOptions.MinimumAngle = minAngle; qualityOptions.MaximumAngle = maxAngle; mesh.Refine(qualityOptions, false); mesh.Renumber(); if (smoothIterations > 0) { try { var smoother = new SimpleSmoother(); smoother.Smooth(mesh, smoothIterations); } catch (System.Exception) { Debug.Log(TextContent.smoothMeshError); } } vertices.Clear(); edges.Clear(); indices.Clear(); foreach (Vertex vertex in mesh.Vertices) { vertices.Add(new Vector2((float)vertex.X, (float)vertex.Y)); } foreach (ISegment segment in mesh.Segments) { edges.Add(new Edge(segment.P0, segment.P1)); } foreach (ITriangle triangle in mesh.Triangles) { int id0 = triangle.GetVertexID(0); int id1 = triangle.GetVertexID(1); int id2 = triangle.GetVertexID(2); if (id0 < 0 || id1 < 0 || id2 < 0 || id0 >= vertices.Count || id1 >= vertices.Count || id2 >= vertices.Count) { continue; } indices.Add(id0); indices.Add(id2); indices.Add(id1); } }
/// <summary> Triangulates a polygon, applying quality and constraint options. </summary> /// <param name="polygon">Polygon.</param> /// <param name="options">Constraint options.</param> /// <param name="quality">Quality options.</param> /// <param name="triangulator">The triangulation algorithm.</param> public static Mesh Triangulate(this Polygon polygon, ConstraintOptions options, QualityOptions quality, ITriangulator triangulator) { return(triangulator .Triangulate(polygon.Points) .ApplyConstraints(polygon, options, quality)); }