public void AddMeshes(IEnumerable <DMesh3> meshes, PrintMeshOptions options) { foreach (var v in meshes) { AddMesh(v, options); } }
public void AddMesh(DMesh3 mesh, PrintMeshOptions options) { MeshInfo mi = new MeshInfo() { Mesh = mesh, Options = options }; meshes.Add(mi); }
public int AddMesh(DMesh3 mesh, PrintMeshOptions options) { SliceMesh m = new SliceMesh() { mesh = mesh, bounds = mesh.CachedBounds, options = options }; int idx = Meshes.Count; Meshes.Add(m); return(idx); }
public GCodeFile GenerateGCode(IList <Tuple <DMesh3, TPrintSettings> > parts, TPrintSettings globalSettings, out IEnumerable <string> generationReport, Action <GCodeLine> gcodeLineReadyF = null, Action <string> progressMessageF = null) { if (AcceptsParts == false && parts != null && parts.Count > 0) { throw new Exception("Must pass null or empty list of parts to generator that does not accept parts."); } // Create print mesh set PrintMeshAssembly meshes = new PrintMeshAssembly(); foreach (var part in parts) { if (part.Item2 != null) { throw new ArgumentException($"Entries for the `parts` arguments must have a null second item since this generator does not handle per-part settings."); } meshes.AddMesh(part.Item1, PrintMeshOptions.Default()); } progressMessageF?.Invoke("Slicing..."); // Do slicing MeshPlanarSlicer slicer = new MeshPlanarSlicer() { LayerHeightMM = globalSettings.LayerHeightMM }; slicer.Add(meshes); PlanarSliceStack slices = slicer.Compute(); // Run the print generator progressMessageF?.Invoke("Running print generator..."); var printGenerator = new TPrintGenerator(); AssemblerFactoryF overrideAssemblerF = globalSettings.AssemblerType(); printGenerator.Initialize(meshes, slices, globalSettings, overrideAssemblerF); if (printGenerator.Generate()) { generationReport = printGenerator.GenerationReport; return(printGenerator.Result); } else { throw new Exception("PrintGenerator failed to generate gcode!"); } }
protected virtual void add_solid_polygons(PlanarSlice slice, List <GeneralPolygon2d> polygons, PrintMeshOptions options) { slice.AddPolygons(polygons); if (options.ClearanceXY != 0) { foreach (var poly in polygons) { slice.Clearances.Add(poly, options.ClearanceXY); } } if (options.OffsetXY != 0) { foreach (var poly in polygons) { slice.Offsets.Add(poly, options.OffsetXY); } } }
protected virtual void add_crop_region_polygons(PlanarSlice slice, List <GeneralPolygon2d> polygons, PrintMeshOptions options) { slice.AddCropRegions(polygons); }
protected virtual void add_support_polygons(PlanarSlice slice, List <GeneralPolygon2d> polygons, PrintMeshOptions options) { slice.AddSupportPolygons(polygons); }
/// <summary> /// Slice the meshes and return the slice stack. /// </summary> public PlanarSliceStack Compute() { if (Meshes.Count == 0) { return(new PlanarSliceStack()); } Interval1d zrange = Interval1d.Empty; foreach (var meshinfo in Meshes) { zrange.Contain(meshinfo.bounds.Min.z); zrange.Contain(meshinfo.bounds.Max.z); } if (SetMinZValue != double.MinValue) { zrange.a = SetMinZValue; } // construct layers List <PlanarSlice> slice_list = new List <PlanarSlice>(); double cur_layer_z = zrange.a; int layer_i = 0; while (cur_layer_z < zrange.b) { double layer_height = get_layer_height(layer_i); double z = cur_layer_z; Interval1d zspan = new Interval1d(z, z + layer_height); if (SliceLocation == SliceLocations.EpsilonBase) { z += 0.01 * layer_height; } else if (SliceLocation == SliceLocations.MidLine) { z += 0.5 * layer_height; } PlanarSlice slice = SliceFactoryF(zspan, z, layer_i); slice.EmbeddedPathWidth = OpenPathDefaultWidthMM; slice_list.Add(slice); layer_i++; cur_layer_z += layer_height; } int NH = slice_list.Count; if (NH > MaxLayerCount) { throw new Exception("MeshPlanarSlicer.Compute: exceeded layer limit. Increase .MaxLayerCount."); } PlanarSlice[] slices = slice_list.ToArray(); // determine if we have crop objects bool have_crop_objects = false; foreach (var mesh in Meshes) { if (mesh.options.IsCropRegion) { have_crop_objects = true; } } // assume Resolve() takes 2x as long as meshes... TotalCompute = (Meshes.Count * NH) + (2 * NH); Progress = 0; // compute slices separately for each mesh for (int mi = 0; mi < Meshes.Count; ++mi) { if (Cancelled()) { break; } DMesh3 mesh = Meshes[mi].mesh; PrintMeshOptions mesh_options = Meshes[mi].options; // [TODO] should we hang on to this spatial? or should it be part of assembly? DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true); AxisAlignedBox3d bounds = Meshes[mi].bounds; bool is_cavity = mesh_options.IsCavity; bool is_crop = mesh_options.IsCropRegion; bool is_support = mesh_options.IsSupport; bool is_closed = (mesh_options.IsOpen) ? false : mesh.IsClosed(); var useOpenMode = (mesh_options.OpenPathMode == OpenPathsModes.Default) ? DefaultOpenPathMode : mesh_options.OpenPathMode; // each layer is independent so we can do in parallel gParallel.ForEach(Interval1i.Range(NH), (i) => { if (Cancelled()) { return; } double z = slices[i].Z; if (z < bounds.Min.z || z > bounds.Max.z) { return; } // compute cut Polygon2d[] polys; PolyLine2d[] paths; compute_plane_curves(mesh, spatial, z, is_closed, out polys, out paths); // if we didn't hit anything, try again with jittered plane // [TODO] this could be better... if ((is_closed && polys.Length == 0) || (is_closed == false && polys.Length == 0 && paths.Length == 0)) { double jitterz = slices[i].LayerZSpan.Interpolate(0.75); compute_plane_curves(mesh, spatial, jitterz, is_closed, out polys, out paths); } if (is_closed) { // construct planar complex and "solids" // (ie outer polys and nested holes) PlanarComplex complex = new PlanarComplex(); foreach (Polygon2d poly in polys) { complex.Add(poly); } PlanarComplex.FindSolidsOptions options = PlanarComplex.FindSolidsOptions.Default; options.WantCurveSolids = false; options.SimplifyDeviationTolerance = 0.001; options.TrustOrientations = true; options.AllowOverlappingHoles = true; PlanarComplex.SolidRegionInfo solids = complex.FindSolidRegions(options); List <GeneralPolygon2d> solid_polygons = ApplyValidRegions(solids.Polygons); if (is_support) { add_support_polygons(slices[i], solid_polygons, mesh_options); } else if (is_cavity) { add_cavity_polygons(slices[i], solid_polygons, mesh_options); } else if (is_crop) { add_crop_region_polygons(slices[i], solid_polygons, mesh_options); } else { add_solid_polygons(slices[i], solid_polygons, mesh_options); } } else if (useOpenMode != OpenPathsModes.Ignored) { // [TODO] // - does not really handle clipped polygons properly, there will be an extra break somewhere... List <PolyLine2d> all_paths = new List <PolyLine2d>(paths); foreach (Polygon2d poly in polys) { all_paths.Add(new PolyLine2d(poly, true)); } List <PolyLine2d> open_polylines = ApplyValidRegions(all_paths); foreach (PolyLine2d pline in open_polylines) { if (useOpenMode == OpenPathsModes.Embedded) { slices[i].AddEmbeddedPath(pline); } else { slices[i].AddClippedPath(pline); } } } Interlocked.Increment(ref Progress); }); // end of parallel.foreach } // end mesh iter // resolve planar intersections, etc gParallel.ForEach(Interval1i.Range(NH), (i) => { if (Cancelled()) { return; } if (have_crop_objects && slices[i].InputCropRegions.Count == 0) { // don't resolve, we have fully cropped this layer } else { slices[i].Resolve(); } Interlocked.Add(ref Progress, 2); }); // discard spurious empty slices int last = slices.Length - 1; while (slices[last].IsEmpty && last > 0) { last--; } int first = 0; if (DiscardEmptyBaseSlices || have_crop_objects) { while (slices[first].IsEmpty && first < slices.Length) { first++; } } PlanarSliceStack stack = SliceStackFactoryF(); for (int k = first; k <= last; ++k) { stack.Add(slices[k]); } if (SupportMinZTips) { stack.AddMinZTipSupportPoints(MinZTipMaxDiam, MinZTipExtraLayers); } return(stack); }
public int AddMesh(DMesh3 mesh) { return(AddMesh(mesh, PrintMeshOptions.Default())); }
protected virtual void add_cavity_polygons(PlanarSlice slice, List <GeneralPolygon2d> polygons, PrintMeshOptions options) { slice.AddCavityPolygons(polygons); }
/// <summary> /// Slice the meshes and return the slice stack. /// </summary> public PlanarSliceStack Compute() { if (Meshes.Count == 0) { return(new PlanarSliceStack()); } Interval1d zrange = Interval1d.Empty; foreach (var meshinfo in Meshes) { zrange.Contain(meshinfo.bounds.Min.z); zrange.Contain(meshinfo.bounds.Max.z); } if (SetMinZValue != double.MinValue) { zrange.a = SetMinZValue; } int nLayers = (int)(zrange.Length / LayerHeightMM); if (nLayers > MaxLayerCount) { throw new Exception("MeshPlanarSlicer.Compute: exceeded layer limit. Increase .MaxLayerCount."); } // make list of slice heights (could be irregular) List <double> heights = new List <double>(); for (int i = 0; i < nLayers + 1; ++i) { double t = zrange.a + (double)i * LayerHeightMM; if (SliceLocation == SliceLocations.EpsilonBase) { t += 0.01 * LayerHeightMM; } else if (SliceLocation == SliceLocations.MidLine) { t += 0.5 * LayerHeightMM; } heights.Add(t); } int NH = heights.Count; // process each *slice* in parallel PlanarSlice[] slices = new PlanarSlice[NH]; for (int i = 0; i < NH; ++i) { slices[i] = SliceFactoryF(heights[i], i); slices[i].EmbeddedPathWidth = OpenPathDefaultWidthMM; } // assume Resolve() takes 2x as long as meshes... TotalCompute = (Meshes.Count * NH) + (2 * NH); Progress = 0; // compute slices separately for each mesh for (int mi = 0; mi < Meshes.Count; ++mi) { if (Cancelled()) { break; } DMesh3 mesh = Meshes[mi].mesh; PrintMeshOptions mesh_options = Meshes[mi].options; // [TODO] should we hang on to this spatial? or should it be part of assembly? DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true); AxisAlignedBox3d bounds = Meshes[mi].bounds; bool is_cavity = mesh_options.IsCavity; bool is_crop = mesh_options.IsCropRegion; bool is_support = mesh_options.IsSupport; bool is_closed = (mesh_options.IsOpen) ? false : mesh.IsClosed(); var useOpenMode = (mesh_options.OpenPathMode == PrintMeshOptions.OpenPathsModes.Default) ? DefaultOpenPathMode : mesh_options.OpenPathMode; // each layer is independent so we can do in parallel gParallel.ForEach(Interval1i.Range(NH), (i) => { if (Cancelled()) { return; } double z = heights[i]; if (z < bounds.Min.z || z > bounds.Max.z) { return; } // compute cut Polygon2d[] polys; PolyLine2d[] paths; compute_plane_curves(mesh, spatial, z, is_closed, out polys, out paths); // if we didn't hit anything, try again with jittered plane // [TODO] this could be better... if ((is_closed && polys.Length == 0) || (is_closed == false && polys.Length == 0 && paths.Length == 0)) { compute_plane_curves(mesh, spatial, z + LayerHeightMM * 0.25, is_closed, out polys, out paths); } if (is_closed) { // construct planar complex and "solids" // (ie outer polys and nested holes) PlanarComplex complex = new PlanarComplex(); foreach (Polygon2d poly in polys) { complex.Add(poly); } PlanarComplex.FindSolidsOptions options = PlanarComplex.FindSolidsOptions.Default; options.WantCurveSolids = false; options.SimplifyDeviationTolerance = 0.001; options.TrustOrientations = true; options.AllowOverlappingHoles = true; PlanarComplex.SolidRegionInfo solids = complex.FindSolidRegions(options); if (is_support) { add_support_polygons(slices[i], solids.Polygons, mesh_options); } else if (is_cavity) { add_cavity_polygons(slices[i], solids.Polygons, mesh_options); } else if (is_crop) { add_crop_region_polygons(slices[i], solids.Polygons, mesh_options); } else { add_solid_polygons(slices[i], solids.Polygons, mesh_options); } } else if (useOpenMode != PrintMeshOptions.OpenPathsModes.Ignored) { foreach (PolyLine2d pline in paths) { if (useOpenMode == PrintMeshOptions.OpenPathsModes.Embedded) { slices[i].AddEmbeddedPath(pline); } else { slices[i].AddClippedPath(pline); } } // [TODO] // - does not really handle clipped polygons properly, there will be an extra break somewhere... foreach (Polygon2d poly in polys) { PolyLine2d pline = new PolyLine2d(poly, true); if (useOpenMode == PrintMeshOptions.OpenPathsModes.Embedded) { slices[i].AddEmbeddedPath(pline); } else { slices[i].AddClippedPath(pline); } } } Interlocked.Increment(ref Progress); }); // end of parallel.foreach } // end mesh iter // resolve planar intersections, etc gParallel.ForEach(Interval1i.Range(NH), (i) => { if (Cancelled()) { return; } slices[i].Resolve(); Interlocked.Add(ref Progress, 2); }); // discard spurious empty slices int last = slices.Length - 1; while (slices[last].IsEmpty && last > 0) { last--; } int first = 0; if (DiscardEmptyBaseSlices) { while (slices[first].IsEmpty && first < slices.Length) { first++; } } PlanarSliceStack stack = SliceStackFactoryF(); for (int k = first; k <= last; ++k) { stack.Add(slices[k]); } if (SupportMinZTips) { stack.AddMinZTipSupportPoints(MinZTipMaxDiam, MinZTipExtraLayers); } return(stack); }
public void AddMeshes(IEnumerable <DMesh3> meshes) { AddMeshes(meshes, PrintMeshOptions.Default()); }
public void AddMesh(DMesh3 mesh) { AddMesh(mesh, PrintMeshOptions.Default()); }
protected PlanarSlice ComputeSolidSliceAtZ(double z, bool bCavitySolids) { PlanarSlice temp = new PlanarSlice(); for (int mi = 0; mi < Meshes.Count; ++mi) { if (Cancelled()) { break; } DMesh3 mesh = Meshes[mi].mesh; PrintMeshOptions mesh_options = Meshes[mi].options; // [TODO] should we hang on to this spatial? or should it be part of assembly? DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true); AxisAlignedBox3d bounds = Meshes[mi].bounds; bool is_cavity = mesh_options.IsCavity; bool is_crop = mesh_options.IsCropRegion; bool is_support = mesh_options.IsSupport; bool is_closed = (mesh_options.IsOpen) ? false : mesh.IsClosed(); var useOpenMode = (mesh_options.OpenPathMode == PrintMeshOptions.OpenPathsModes.Default) ? DefaultOpenPathMode : mesh_options.OpenPathMode; if (is_crop || is_support) { throw new Exception("Not supported!"); } if (bCavitySolids && is_cavity == false) { continue; } // compute cut Polygon2d[] polys; PolyLine2d[] paths; ComputeSlicePlaneCurves(mesh, spatial, z, is_closed, out polys, out paths); if (is_closed) { // construct planar complex and "solids" // (ie outer polys and nested holes) PlanarComplex complex = new PlanarComplex(); foreach (Polygon2d poly in polys) { complex.Add(poly); } PlanarComplex.FindSolidsOptions options = PlanarComplex.FindSolidsOptions.Default; options.WantCurveSolids = false; options.SimplifyDeviationTolerance = 0.001; options.TrustOrientations = true; options.AllowOverlappingHoles = true; PlanarComplex.SolidRegionInfo solids = complex.FindSolidRegions(options); List <GeneralPolygon2d> solid_polygons = ApplyValidRegions(solids.Polygons); if (is_cavity && bCavitySolids == false) { add_cavity_polygons(temp, solid_polygons, mesh_options); } else { add_solid_polygons(temp, solid_polygons, mesh_options); } } } return(temp); }
/// <summary> /// Slice the meshes and return the slice stack. /// </summary> public Result Compute() { Result result = new Result(); if (Meshes.Count == 0) { return(result); } // find Z interval we want to slice in Interval1d zrange = Interval1d.Empty; foreach (var meshinfo in Meshes) { zrange.Contain(meshinfo.bounds.Min.z); zrange.Contain(meshinfo.bounds.Max.z); } if (SetMinZValue != double.MinValue) { zrange.a = SetMinZValue; } result.TopZ = Math.Round(zrange.b, PrecisionDigits); result.BaseZ = Math.Round(zrange.a, PrecisionDigits); // [TODO] might be able to make better decisions if we took flat regions // into account when constructing initial Z-heights? if we have large flat // region just below Zstep, might make sense to do two smaller Z-steps so we // can exactly hit it?? // construct list of clearing Z-heights List <double> clearingZLayers = new List <double>(); double cur_layer_z = zrange.b; int layer_i = 0; while (cur_layer_z > zrange.a) { double layer_height = get_layer_height(layer_i); cur_layer_z -= layer_height; double z = Math.Round(cur_layer_z, PrecisionDigits); clearingZLayers.Add(z); layer_i++; } if (clearingZLayers.Last() < result.BaseZ) { clearingZLayers[clearingZLayers.Count - 1] = result.BaseZ; } if (clearingZLayers.Last() == clearingZLayers[clearingZLayers.Count - 2]) { clearingZLayers.RemoveAt(clearingZLayers.Count - 1); } // construct layer slices from Z-heights List <PlanarSlice> clearing_slice_list = new List <PlanarSlice>(); layer_i = 0; for (int i = 0; i < clearingZLayers.Count; ++i) { double layer_height = (i == clearingZLayers.Count - 1) ? (result.TopZ - clearingZLayers[i]) : (clearingZLayers[i + 1] - clearingZLayers[i]); double z = clearingZLayers[i]; Interval1d zspan = new Interval1d(z, z + layer_height); if (SliceLocation == SliceLocations.EpsilonBase) { z += 0.001; } PlanarSlice slice = SliceFactoryF(zspan, z, layer_i); clearing_slice_list.Add(slice); layer_i++; } int NH = clearing_slice_list.Count; if (NH > MaxLayerCount) { throw new Exception("MeshPlanarSlicer.Compute: exceeded layer limit. Increase .MaxLayerCount."); } PlanarSlice[] clearing_slices = clearing_slice_list.ToArray(); // assume Resolve() takes 2x as long as meshes... TotalCompute = (Meshes.Count * NH) + (2 * NH); Progress = 0; // compute slices separately for each mesh for (int mi = 0; mi < Meshes.Count; ++mi) { if (Cancelled()) { break; } DMesh3 mesh = Meshes[mi].mesh; PrintMeshOptions mesh_options = Meshes[mi].options; // [TODO] should we hang on to this spatial? or should it be part of assembly? DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true); AxisAlignedBox3d bounds = Meshes[mi].bounds; bool is_cavity = mesh_options.IsCavity; bool is_crop = mesh_options.IsCropRegion; bool is_support = mesh_options.IsSupport; bool is_closed = (mesh_options.IsOpen) ? false : mesh.IsClosed(); var useOpenMode = (mesh_options.OpenPathMode == PrintMeshOptions.OpenPathsModes.Default) ? DefaultOpenPathMode : mesh_options.OpenPathMode; if (is_crop || is_support) { throw new Exception("Not supported!"); } // each layer is independent so we can do in parallel gParallel.ForEach(Interval1i.Range(NH), (i) => { if (Cancelled()) { return; } double z = clearing_slices[i].Z; if (z < bounds.Min.z || z > bounds.Max.z) { return; } // compute cut Polygon2d[] polys; PolyLine2d[] paths; ComputeSlicePlaneCurves(mesh, spatial, z, is_closed, out polys, out paths); if (is_closed) { // construct planar complex and "solids" // (ie outer polys and nested holes) PlanarComplex complex = new PlanarComplex(); foreach (Polygon2d poly in polys) { complex.Add(poly); } PlanarComplex.FindSolidsOptions options = PlanarComplex.FindSolidsOptions.Default; options.WantCurveSolids = false; options.SimplifyDeviationTolerance = 0.001; options.TrustOrientations = true; options.AllowOverlappingHoles = true; PlanarComplex.SolidRegionInfo solids = complex.FindSolidRegions(options); List <GeneralPolygon2d> solid_polygons = ApplyValidRegions(solids.Polygons); if (is_cavity) { add_cavity_polygons(clearing_slices[i], solid_polygons, mesh_options); } else { if (ExpandStockAmount > 0) { solid_polygons = ClipperUtil.MiterOffset(solid_polygons, ExpandStockAmount); } add_solid_polygons(clearing_slices[i], solid_polygons, mesh_options); } } Interlocked.Increment(ref Progress); }); // end of parallel.foreach } // end mesh iter // resolve planar intersections, etc gParallel.ForEach(Interval1i.Range(NH), (i) => { if (Cancelled()) { return; } clearing_slices[i].Resolve(); Interlocked.Add(ref Progress, 2); }); // add to clearing stack result.Clearing = SliceStackFactoryF(); for (int k = 0; k < clearing_slices.Length; ++k) { result.Clearing.Add(clearing_slices[k]); } /* * Horizontal planar regions finishing pass. * First we find all planar horizontal Z-regions big enough to mill. * Then we add slices at the Z's we haven't touched yet. * * Cannot just 'fill' planar regions because we will miss edges that might * be millable. So we grow region and then intersect with full-slice millable area. */ // find set of horizontal flat regions Dictionary <double, List <PlanarRegion> > flat_regions = FindPlanarZRegions(ToolDiameter); if (flat_regions.Count == 0) { goto done_slicing; } // if we have already milled this exact Z-height in clearing pass, then we can skip it List <double> doneZ = new List <double>(); foreach (double z in flat_regions.Keys) { if (clearingZLayers.Contains(z)) { doneZ.Add(z); } } foreach (var z in doneZ) { flat_regions.Remove(z); } // create slice for each layer PlanarSlice[] horz_slices = new PlanarSlice[flat_regions.Count]; List <double> flatZ = new List <double>(flat_regions.Keys); flatZ.Sort(); for (int k = 0; k < horz_slices.Length; ++k) { double z = flatZ[k]; Interval1d zspan = new Interval1d(z, z + LayerHeightMM); horz_slices[k] = SliceFactoryF(zspan, z, k); // compute full millable region slightly above this slice. PlanarSlice clip_slice = ComputeSolidSliceAtZ(z + 0.0001, false); clip_slice.Resolve(); // extract planar polys List <Polygon2d> polys = GetPlanarPolys(flat_regions[z]); PlanarComplex complex = new PlanarComplex(); foreach (Polygon2d poly in polys) { complex.Add(poly); } // convert to planar solids PlanarComplex.FindSolidsOptions options = PlanarComplex.FindSolidsOptions.SortPolygons; options.SimplifyDeviationTolerance = 0.001; options.TrustOrientations = true; options.AllowOverlappingHoles = true; PlanarComplex.SolidRegionInfo solids = complex.FindSolidRegions(options); List <GeneralPolygon2d> solid_polygons = ApplyValidRegions(solids.Polygons); // If planar solid has holes, then when we do inset later, we might lose // too-thin parts. Shrink the holes to avoid this case. //FilterHoles(solid_polygons, 0.55 * ToolDiameter); // ok now we need to expand region and intersect with full region. solid_polygons = ClipperUtil.MiterOffset(solid_polygons, ToolDiameter * 0.5, 0.0001); solid_polygons = ClipperUtil.Intersection(solid_polygons, clip_slice.Solids, 0.0001); // Same idea as above, but if we do after, we keep more of the hole and // hence do less extra clearing. // Also this could then be done at the slicer level instead of here... // (possibly this entire thing should be done at slicer level, except we need clip_slice!) FilterHoles(solid_polygons, 1.1 * ToolDiameter); add_solid_polygons(horz_slices[k], solid_polygons, PrintMeshOptions.Default()); } // resolve planar intersections, etc int NF = horz_slices.Length; gParallel.ForEach(Interval1i.Range(NF), (i) => { if (Cancelled()) { return; } horz_slices[i].Resolve(); Interlocked.Add(ref Progress, 2); }); // add to clearing stack result.HorizontalFinish = SliceStackFactoryF(); for (int k = 0; k < horz_slices.Length; ++k) { result.HorizontalFinish.Add(horz_slices[k]); } done_slicing: return(result); }
protected override void add_cavity_polygons(PlanarSlice slice, List <GeneralPolygon2d> polygons, PrintMeshOptions options) { slice.AddCavityPolygons(polygons); if (options.Extended != null && options.Extended is ExtendedPrintMeshOptions) { ExtendedPrintMeshOptions ext = options.Extended as ExtendedPrintMeshOptions; if (slice is PlanarSlicePro) { PlanarSlicePro sp = slice as PlanarSlicePro; if (ext.ClearanceXY != 0) { foreach (var poly in polygons) { sp.Cavity_Clearances.Add(poly, ext.ClearanceXY); } } if (ext.OffsetXY != 0) { foreach (var poly in polygons) { sp.Cavity_Offsets.Add(poly, ext.OffsetXY); } } } } }