private static void test_meshGen1() { Console.WriteLine("test_meshGen1"); TriangulatedPolygonGenerator tg = new TriangulatedPolygonGenerator(); tg.Polygon = new GeneralPolygon2d(new Polygon2d( new List <Vector2d>() { // clockwise new Vector2d(0, 0), new Vector2d(0, 4), new Vector2d(5, 4), new Vector2d(5, 0) } )); tg.Polygon.AddHole(new Polygon2d( new List <Vector2d>() { // counter-clockwise new Vector2d(1, 1), new Vector2d(2, 1), new Vector2d(1, 2) } )); tg.Generate(); var m = tg.MakeDMesh(); Console.WriteLine(TestUtil.WriteTestOutputMesh(m)); }
/// <summary> /// available after call to UpdateSection() /// </summary> public DMesh3 GetSectionMesh(double simplifyTol = 0.01) { DMesh3 mesh = new DMesh3(); if (localCurves.Loops == null) { return(mesh); } List <GeneralPolygon2d> solids = GetSolids(); foreach (GeneralPolygon2d poly in solids) { poly.Simplify(simplifyTol, simplifyTol / 10, true); TriangulatedPolygonGenerator gen = new TriangulatedPolygonGenerator() { Polygon = poly }; DMesh3 polyMesh = gen.Generate().MakeDMesh(); MeshTransforms.PerVertexTransform(polyMesh, (uv) => { return(frameL.FromPlaneUV((Vector2f)uv.xy, 2)); }); MeshEditor.Append(mesh, polyMesh); } if (OutputSpace != CoordSpace.ObjectCoords) { MeshTransforms.PerVertexTransform(mesh, (v) => { return(SceneTransforms.TransformTo((Vector3f)v, SO, CoordSpace.ObjectCoords, OutputSpace)); }); } return(mesh); }
public static List <Polygon2d> Compute(GeneralPolygon2d poly, double minArea) { TriangulatedPolygonGenerator generator = new TriangulatedPolygonGenerator() { Polygon = poly, Subdivisions = 16 }; DMesh3 mesh = generator.Generate().MakeDMesh(); return(decompose_cluster_up(mesh, minArea)); }
private static void test_meshGen3() { Console.WriteLine("test_meshGen3"); TriangulatedPolygonGenerator tg = new TriangulatedPolygonGenerator(); var poly = new Polygon2d( new List <Vector2d>() { // clockwise new Vector2d(0, 0), new Vector2d(0, 9), new Vector2d(9, 9), new Vector2d(7, 7), new Vector2d(6.99999, 7), new Vector2d(2, 7), new Vector2d(2, 2.00001), new Vector2d(2, 2) }); tg.Polygon = new GeneralPolygon2d(poly); tg.Generate(); var mesh = tg.MakeDMesh(); Console.WriteLine(TestUtil.WriteTestOutputMesh(mesh)); }
/// <summary> /// test added to demonstrate https://github.com/gradientspace/geometry3Sharp/issues/114 /// </summary> public static void test_TriangulatedPolygonGenerator_114() { Console.WriteLine("Testing TriangulatedPolygonGenerator"); TriangulatedPolygonGenerator tg = new TriangulatedPolygonGenerator(); tg.Polygon = new GeneralPolygon2d(new Polygon2d( new List <Vector2d>() { new Vector2d(0, 0), new Vector2d(0, 4), new Vector2d(5, 4), new Vector2d(5, 0) } )); tg.Polygon.AddHole(new Polygon2d( new List <Vector2d>() { new Vector2d(1, 1), new Vector2d(2, 1), new Vector2d(1, 2) } )); WriteGeneratedMesh(tg, "TriangulatedPolygonGenerator.obj"); }
virtual public void PreRender() { if (in_shutdown()) { return; } if (parameters_dirty) { // offset List <GeneralPolygon2d> offset = ClipperUtil.RoundOffset(combined_all, offset_distance); // aggressively simplify after round offset... foreach (var poly in offset) { poly.Simplify(path_width); } // subtract initial and add tiny gap so these don't get merged by slicer if (SubtractSolids) { offset = ClipperUtil.Difference(offset, combined_solid); offset = ClipperUtil.MiterOffset(offset, -path_width * 0.1); } offset = CurveUtils2.FilterDegenerate(offset, 0.001); foreach (var poly in offset) { poly.Simplify(path_width * 0.02); } DMesh3 mesh = new DMesh3(); MeshEditor editor = new MeshEditor(mesh); foreach (var poly in offset) { TriangulatedPolygonGenerator polygen = new TriangulatedPolygonGenerator() { Polygon = poly }; editor.AppendMesh(polygen.Generate().MakeDMesh()); } MeshTransforms.ConvertZUpToYUp(mesh); if (mesh.TriangleCount > 0) { MeshExtrudeMesh extrude = new MeshExtrudeMesh(mesh); extrude.ExtrudedPositionF = (v, n, vid) => { return(v + Layers * layer_height * Vector3d.AxisY); }; extrude.Extrude(); MeshTransforms.Translate(mesh, -mesh.CachedBounds.Min.y * Vector3d.AxisY); } PreviewSO.ReplaceMesh(mesh, true); //Vector3d translate = scene_bounds.Point(1, -1, 1); //translate.x += spiral.Bounds.Width + PathWidth; //Frame3f sceneF = Frame3f.Identity.Translated((Vector3f)translate); //PreviewSO.SetLocalFrame(sceneF, CoordSpace.SceneCoords); parameters_dirty = false; } }
protected virtual void fill_bridge_region_decompose(GeneralPolygon2d poly, IFillPathScheduler2d scheduler, PrintLayerData layer_data) { poly.Simplify(0.1, 0.01, true); TriangulatedPolygonGenerator generator = new TriangulatedPolygonGenerator() { Polygon = poly, Subdivisions = 16 }; DMesh3 mesh = generator.Generate().MakeDMesh(); //Util.WriteDebugMesh(mesh, "/Users/rms/scratch/bridgemesh.obj"); //List<Polygon2d> polys = decompose_mesh_recursive(mesh); List <Polygon2d> polys = decompose_cluster_up(mesh); Util.WriteDebugMesh(mesh, "/Users/rms/scratch/bridgemesh_reduce.obj"); double spacing = Settings.BridgeFillPathSpacingMM(); foreach (Polygon2d polypart in polys) { Box2d box = polypart.MinimalBoundingBox(0.00001); Vector2d axis = (box.Extent.x > box.Extent.y) ? box.AxisY : box.AxisX; double angle = Math.Atan2(axis.y, axis.x) * MathUtil.Rad2Deg; GeneralPolygon2d gp = new GeneralPolygon2d(polypart); ShellsFillPolygon shells_fill = new ShellsFillPolygon(gp); shells_fill.PathSpacing = Settings.SolidFillPathSpacingMM(); shells_fill.ToolWidth = Settings.Machine.NozzleDiamMM; shells_fill.Layers = 1; shells_fill.InsetFromInputPolygonX = 0.25; shells_fill.ShellType = ShellsFillPolygon.ShellTypes.BridgeShell; shells_fill.FilterSelfOverlaps = false; shells_fill.Compute(); scheduler.AppendCurveSets(shells_fill.GetFillCurves()); var fillPolys = shells_fill.InnerPolygons; double offset = Settings.Machine.NozzleDiamMM * Settings.SolidFillBorderOverlapX; fillPolys = ClipperUtil.MiterOffset(fillPolys, offset); foreach (var fp in fillPolys) { BridgeLinesFillPolygon fill_gen = new BridgeLinesFillPolygon(fp) { InsetFromInputPolygon = false, PathSpacing = spacing, ToolWidth = Settings.Machine.NozzleDiamMM, AngleDeg = angle, }; fill_gen.Compute(); scheduler.AppendCurveSets(fill_gen.GetFillCurves()); } } // fit bbox to try to find fill angle that has shortest spans //Box2d box = poly.Outer.MinimalBoundingBox(0.00001); //Vector2d axis = (box.Extent.x > box.Extent.y) ? box.AxisY : box.AxisX; //double angle = Math.Atan2(axis.y, axis.x) * MathUtil.Rad2Deg; // [RMS] should we do something like this? //if (Settings.SolidFillBorderOverlapX > 0) { // double offset = Settings.Machine.NozzleDiamMM * Settings.SolidFillBorderOverlapX; // fillPolys = ClipperUtil.MiterOffset(fillPolys, offset); //} }
public IntermediateMeshGenerator Generate() { var plateSegmentGenerator = Context.Plate2d; var cornerPoints = Context .SegmentIndexes .Select(idx => plateSegmentGenerator.InnerBendCorner.rotate2d(Context.Config.SegmentAngle(idx))) .ToList(); if (Context.Config.spindelRadius == 0) { for (var idx = 0; idx < cornerPoints.Count; idx++) { var nextIdx = (idx + 1) % cornerPoints.Count; Intermediate.counterClockwiseSingleSidedFromFront( Vector2d.Zero.to3d(Context.halfPlateHeight), cornerPoints[idx].to3d(Context.halfPlateHeight), cornerPoints[nextIdx].to3d(Context.halfPlateHeight) ); Intermediate.counterClockwiseSingleSidedFromFront( Vector2d.Zero.to3d(-Context.halfPlateHeight), cornerPoints[nextIdx].to3d(-Context.halfPlateHeight), cornerPoints[idx].to3d(-Context.halfPlateHeight) ); } return(Intermediate); } List <Vector2d> spindelPoints = new List <Vector2d>(); if (Context.Config.spindelCut == 0) { spindelPoints = Generators.counterClockwiseCirclePoints( Context.Config.spindelPoints, Vector2d.Zero, Context.Config.spindelRadius ); /* * Intermediate.Extrude(spindelPoints, Context.Config.plateHeight, true); * * var nearestDistanceIndexes = cornerPoints.Select(point => * { * var distances = spindelPoints.Select(p => p.Distance(point)).ToList(); * var nearestPointIndex = distances.FindIndex(d => d == distances.Min()); * return nearestPointIndex; * }).ToList(); * * for (var idx = 0; idx < cornerPoints.Count; idx++) * { * var nearestPointIndex = nearestDistanceIndexes[idx]; * * var nextIdx = (idx + 1) % cornerPoints.Count; * var nextNearestPointIndex = nearestDistanceIndexes[nextIdx]; * * var polygonPoints = new List<Vector2d>(); * polygonPoints.AddRange( * new [] * { * cornerPoints[idx], * cornerPoints[nextIdx] * }); * * var spindelPart = new List<Vector2d>(); * var pointsToTake = nextNearestPointIndex < nearestPointIndex * ? nextNearestPointIndex + spindelPoints.Count - nearestPointIndex + 1 * : nextNearestPointIndex - nearestPointIndex + 1; * * spindelPart = Enumerable.Range(nearestPointIndex, pointsToTake) * .Select(i => spindelPoints[i % spindelPoints.Count]) * .Reverse() * .ToList(); * * polygonPoints.AddRange(spindelPart); * * var polygonizer = new TriangulatedPolygonGenerator() * { * Polygon = new GeneralPolygon2d( new Polygon2d(polygonPoints) ) * }; * polygonizer.Generate(); * * var polygonMesh = new IntermediateMeshGenerator(); * polygonMesh.Append(polygonizer); * * Intermediate.Append(new IntermediateMeshGenerator().Append(polygonMesh).Offset(new Vector3d(0, 0, Context.halfPlateHeight))); * Intermediate.Append(new IntermediateMeshGenerator().Append(polygonMesh).Offset(new Vector3d(0, 0, -Context.halfPlateHeight)).ReverseTriagles()); * } */ } else { var spindelCutX = Context.Config.spindelRadius - Context.Config.spindelCut; var cutItx = Intersector.CircelLineIntersection( Vector2d.Zero, Context.Config.spindelRadius, new Vector2d(spindelCutX, 0), new Vector2d(spindelCutX, 1) ); spindelPoints = Generators.counterClockwiseCircleSegments( Context.Config.spindelPoints, Vector2d.Zero, cutItx.Single(p => p.y > 0), cutItx.Single(p => p.y < 0) ); //Intermediate.Extrude(spindelSegments, Context.Config.plateHeight, true); } Intermediate.Extrude(spindelPoints, Context.Config.plateHeight, true); var nearestDistanceIndexes = cornerPoints.Select(point => { var distances = spindelPoints.Select(p => p.Distance(point)).ToList(); var nearestPointIndex = distances.FindIndex(d => d == distances.Min()); return(nearestPointIndex); }).ToList(); for (var idx = 0; idx < cornerPoints.Count; idx++) { var nearestPointIndex = nearestDistanceIndexes[idx]; var nextIdx = (idx + 1) % cornerPoints.Count; var nextNearestPointIndex = nearestDistanceIndexes[nextIdx]; var polygonPoints = new List <Vector2d>(); polygonPoints.AddRange( new[] { cornerPoints[idx], cornerPoints[nextIdx] }); var spindelPart = new List <Vector2d>(); var pointsToTake = nextNearestPointIndex < nearestPointIndex ? nextNearestPointIndex + spindelPoints.Count - nearestPointIndex + 1 : nextNearestPointIndex - nearestPointIndex + 1; spindelPart = Enumerable.Range(nearestPointIndex, pointsToTake) .Select(i => spindelPoints[i % spindelPoints.Count]) .Reverse() .ToList(); polygonPoints.AddRange(spindelPart); var polygonizer = new TriangulatedPolygonGenerator() { Polygon = new GeneralPolygon2d(new Polygon2d(polygonPoints)) }; polygonizer.Generate(); var polygonMesh = new IntermediateMeshGenerator(); polygonMesh.Append(polygonizer); Intermediate.Append(new IntermediateMeshGenerator().Append(polygonMesh).Offset(new Vector3d(0, 0, Context.halfPlateHeight))); Intermediate.Append(new IntermediateMeshGenerator().Append(polygonMesh).Offset(new Vector3d(0, 0, -Context.halfPlateHeight)).ReverseTriagles()); } return(Intermediate); }
/// <summary> /// Generates the actual mesh for the polyhedron /// </summary> private void MakeMesh() { MeshFilter mf; mf = Shape.GetComponent <MeshFilter>(); if (mf == null) { mf = Shape.AddComponent <MeshFilter>(); } mf.mesh = null; Mesh mesh = new Mesh(); TriangulatedPolygonGenerator tpg = new TriangulatedPolygonGenerator(); Frame3f frame = new Frame3f(); tpg.Polygon = Polygon.ToPolygon(ref frame); tpg.Generate(); int nv = tpg.vertices.Count; VertexTable.Clear(); foreach (Dataline ring in Polygon) { foreach (VertexLookup v in ring.VertexTable) { VertexTable.Add(v); } } IEnumerable <Vector3d> vlist = tpg.vertices.AsVector3d(); Vector3[] vertices = new Vector3[vlist.Count()]; for (int i = 0; i < vlist.Count(); i++) { Vector3d v = vlist.ElementAt(i); try { VertexLookup vl = VertexTable.Find(item => v.xy.Distance(frame.ToPlaneUV(item.Com.transform.position, 3)) < 0.001); vertices[i] = Shape.transform.InverseTransformPoint(vl.Com.transform.position); vl.pVertex = i; } catch { VertexTable.Add(new VertexLookup() { pVertex = i, Com = VertexTable[0].Com }); vertices[i] = Shape.transform.InverseTransformPoint((Vector3)frame.FromFrameV(v)); } } List <Vector2> uvs = new List <Vector2>(); IEnumerable <Vector2d> uv2d = tpg.uv.AsVector2f(); foreach (Vector2d uv in uv2d) { uvs.Add((Vector2)uv); } mesh.vertices = vertices.ToArray(); mesh.triangles = tpg.triangles.ToArray <int>(); mesh.uv = uvs.ToArray <Vector2>(); mesh.RecalculateBounds(); mesh.RecalculateNormals(); mf.mesh = mesh; }