// [TODO] no reason we couldn't start on edge midpoint?? public virtual void AppendPolygon2d(FillPolygon2d poly) { Vector3d currentPos = Builder.Position; Vector2d currentPos2 = currentPos.xy; int N = poly.VertexCount; if (N < 2) { throw new Exception("PathScheduler.AppendPolygon2d: degenerate curve!"); } int iNearest = CurveUtils2.FindNearestVertex(currentPos2, poly.Vertices); Vector2d startPt = poly[iNearest]; Builder.AppendTravel(startPt, Settings.RapidTravelSpeed); List <Vector2d> loopV = new List <Vector2d>(N + 1); for (int i = 0; i <= N; i++) { int k = (iNearest + i) % N; loopV.Add(poly[k]); } double useSpeed = select_speed(poly); Builder.AppendExtrude(loopV, useSpeed, poly.TypeFlags, null); }
// Clipper uses integer coordinates, so we need to scale our doubles. // This value determines # of integers per mm. 8 feet ~= 2500mm // Clipper docs say for 32-bit ints the max is 46340, so for 64=bit... ? public static double GetIntScale(IEnumerable <Vector2d> vertices) { // details: http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/CInt.htm // const max_int = 9.2e18 / 2 // 9.2e18 is max int, give ourselves room to breathe const long max_int = int.MaxValue / 2; // int.MaxValue=2,147,483,647 // find maximum distance to origin. not ideal, efficiency-wise... Vector2d maxDist = CurveUtils2.GetMaxOriginDistances(vertices); double max_origin_dist = Math.Max(maxDist.x, maxDist.y); if (max_accuracy == false) { // if max int coord is within our max-int range, we are safe int max_dist_int = (int)(max_origin_dist * inv_default_precision); if (max_dist_int < max_int) { return(inv_default_precision); } // get as close to max_int as we can return((double)max_int / max_origin_dist); } else { return((max_origin_dist < 1) ? (double)max_int : ((double)max_int / max_origin_dist)); } }
protected virtual ElementLocation FindLoopEntryPoint(FillLoop poly, Vector2d currentPos2) { int startIndex; if (Settings.Part.ZipperAlignedToPoint && poly.FillType.IsEntryLocationSpecified()) { // split edges to position zipper closer to the desired point? // TODO: Enter midsegment Vector2d zipperLocation = new Vector2d(Settings.Part.ZipperLocationX, Settings.Part.ZipperLocationY); startIndex = CurveUtils2.FindNearestVertex(zipperLocation, poly.Vertices(true)); } else if (Settings.Part.ShellRandomizeStart && poly.FillType.IsEntryLocationSpecified()) { // split edges for a actual random location along the perimeter instead of a random vertex? Random rnd = new Random(); startIndex = rnd.Next(poly.ElementCount); } else { // use the vertex closest to the current nozzle position startIndex = CurveUtils2.FindNearestVertex(currentPos2, poly.Vertices(true)); } return(new ElementLocation(startIndex, 0)); }
private GeneralPolygon2d SimplifyInputPolygon(GeneralPolygon2d poly) { GeneralPolygon2d smoothed = poly.Duplicate(); CurveUtils2.LaplacianSmoothConstrained(smoothed, 0.5, 5, ToolWidth / 2, true, false); poly = smoothed; return(poly); }
DMesh3 BuildPlanarMesh(bool bPreservePolygon) { DMesh3 planarMesh = new DMesh3(); Vector2d center = CurveUtils2.CentroidVtx(Loop.Vertices); int center_id = planarMesh.AppendVertex(new Vector3d(center.x, center.y, 0)); int prev_id = -1; int first_id = -1; foreach (Vector2d v in Loop.Vertices) { int next_id = planarMesh.AppendVertex(new Vector3d(v.x, v.y, Thickness)); if (prev_id > 0) { planarMesh.AppendTriangle(center_id, prev_id, next_id); prev_id = next_id; } else { first_id = next_id; prev_id = next_id; } } planarMesh.AppendTriangle(center_id, prev_id, first_id); if (ReverseOrientation) { planarMesh.ReverseOrientation(); } Debug.Assert(planarMesh.CheckValidity()); double edge_len = (TargetEdgeLength == 0) ? Loop.AverageEdgeLength : TargetEdgeLength; Remesher r = new Remesher(planarMesh); r.SetTargetEdgeLength(edge_len); r.SmoothSpeedT = 1.0f; if (bPreservePolygon) { MeshConstraintUtil.FixAllBoundaryEdges(r); } else { MeshConstraintUtil.PreserveBoundaryLoops(r); } for (int k = 0; k < 20; ++k) { r.BasicRemeshPass(); } return(planarMesh); }
protected virtual List <GeneralPolygon2d> filter_solids(List <GeneralPolygon2d> solids) { if (MIN_AREA > 0) { return(CurveUtils2.FilterDegenerate(solids, MIN_AREA)); } else { return(solids); } }
virtual protected void cache_brim_polys() { combined_solid = new List <GeneralPolygon2d>(); combined_support = new List <GeneralPolygon2d>(); subtract = new List <GeneralPolygon2d>(); Frame3f cutPlane = new Frame3f((float)layer_height * 0.5f * Vector3f.AxisY, Vector3f.AxisY); foreach (var so in CC.Objects.PrintMeshes) { if (so.Settings.ObjectType == PrintMeshSettings.ObjectTypes.Ignored) { continue; } SOSectionPlane section = new SOSectionPlane(so); section.UpdateSection(cutPlane, CoordSpace.SceneCoords); List <GeneralPolygon2d> solids = section.GetSolids(); // [TODO] should subtract holes explicitly here, like we do in slicer? if (so.Settings.ObjectType == PrintMeshSettings.ObjectTypes.Cavity) { subtract = ClipperUtil.Union(solids, subtract); } else if (so.Settings.ObjectType == PrintMeshSettings.ObjectTypes.Support) { combined_support = ClipperUtil.Union(solids, combined_support); } else if (so.Settings.ObjectType == PrintMeshSettings.ObjectTypes.Solid) { combined_solid = ClipperUtil.Union(solids, combined_solid); } } if (subtract.Count > 0) { combined_solid = ClipperUtil.Difference(combined_solid, subtract); } combined_all = ClipperUtil.Union(combined_solid, combined_support); combined_all = CurveUtils2.FilterDegenerate(combined_all, 0.001); foreach (var poly in combined_all) { poly.Simplify(path_width * 0.02); } }
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; } }