public SLSPrintGenerator(PrintMeshAssembly meshes, PlanarSliceStack slices, SingleMaterialFFFSettings settings, ThreeAxisLaserCompiler compiler) { Initialize(meshes, slices, settings, compiler); }
public SingleMaterialFFFPrintGenPro(PrintMeshAssembly meshes, PlanarSliceStack slices, SingleMaterialFFFSettings settings, AssemblerFactoryF overrideAssemblerF = null) : base(meshes, slices, settings, overrideAssemblerF) { }
public SingleMaterialFFFPrintGenerator(PrintMeshAssembly meshes, PlanarSliceStack slices, SingleMaterialFFFSettings settings, AssemblerFactoryF overrideAssemblerF = null) { Initialize(meshes, slices, settings, overrideAssemblerF); }
public SLSPrintGenerator(PrintMeshAssembly meshes, PlanarSliceStack slices, PrintProfileFFF settings, IThreeAxisLaserCompiler compiler) { Initialize(meshes, slices, settings, compiler); }
public GCodeFile GCodeFromPrintMeshAssembly(PrintMeshAssembly printMeshAssembly, out IEnumerable <string> generationReport, TPrintSettings settings = null) { PlanarSliceStack slices = null; if (AcceptsParts) { SliceMesh(printMeshAssembly, out slices); } var globalSettings = settings ?? settingsBuilder.Settings; // Run the print generator logger.WriteLine("Running print generator..."); var printGenerator = new TPrintGenerator(); AssemblerFactoryF overrideAssemblerF = globalSettings.AssemblerType(); printGenerator.Initialize(printMeshAssembly, slices, globalSettings, overrideAssemblerF); if (printGenerator.Generate()) { generationReport = printGenerator.GenerationReport; return(printGenerator.Result); } else { throw new Exception("PrintGenerator failed to generate gcode!"); } }
public virtual GCodeFile GCodeFromPrintMeshAssembly(PrintMeshAssembly printMeshAssembly, out GCodeGenerationDetails details, TPrintSettings settings = null, CancellationToken?cancellationToken = null) { PlanarSliceStack slices = null; var globalSettings = settings ?? settingsBuilder.Settings; if (AcceptsParts) { SliceMesh(printMeshAssembly, out slices, globalSettings.Part.LayerHeightMM); } // Run the print generator logger.WriteLine("Running print generator..."); var printGenerator = new TPrintGenerator(); AssemblerFactoryF overrideAssemblerF = (globalSettings.MachineProfile as MachineProfileBase).AssemblerFactory(); printGenerator.Initialize(printMeshAssembly, slices, globalSettings, overrideAssemblerF); if (printGenerator.Generate(cancellationToken)) { details = new GCodeGenerationDetails(printGenerator.PrintTimeEstimate, printGenerator.MaterialUsageEstimate, printGenerator.Warnings); return(printGenerator.Result); } else { throw new Exception("PrintGenerator failed to generate gcode!"); } }
public void Initialize(PrintMeshAssembly meshes, PlanarSliceStack slices, SingleMaterialFFFSettings settings, ThreeAxisLaserCompiler compiler) { PrintMeshes = meshes; Slices = slices; Settings = settings; Compiler = compiler; }
public void Initialize(PrintMeshAssembly meshes, PlanarSliceStack slices, PrintProfileFFF settings, IThreeAxisLaserCompiler compiler) { PrintMeshes = meshes; Slices = slices; Settings = settings; Compiler = compiler; }
public GenericSLSPrintGenerator(PrintMeshAssembly meshes, PlanarSliceStack slices, SingleMaterialFFFSettings settings) { file_accumulator = new GCodeFileAccumulator(); //builder = new GCodeBuilder(file_accumulator); //compiler = new SLSCompiler(builder, settings); compiler = new SLSCompiler(settings); base.Initialize(meshes, slices, settings, compiler); }
public override void Initialize(PrintMeshAssembly meshes, PlanarSliceStack slices, SingleMaterialFFFSettings settings, AssemblerFactoryF overrideAssemblerF = null) { file_accumulator = new GCodeFileAccumulator(); builder = new GCodeBuilder(file_accumulator); AssemblerFactoryF useAssembler = overrideAssemblerF ?? settings.AssemblerType(); compiler = new SingleMaterialFFFCompiler(builder, settings, useAssembler); Initialize(meshes, slices, settings, compiler); }
private void SliceMesh(PrintMeshAssembly meshes, out PlanarSliceStack slices) { logger?.WriteLine("Slicing..."); // Do slicing MeshPlanarSlicer slicer = new MeshPlanarSlicer() { LayerHeightMM = Settings.LayerHeightMM }; slicer.Add(meshes); slices = slicer.Compute(); }
protected virtual void SliceMesh(PrintMeshAssembly meshes, out PlanarSliceStack slices, double layerHeight) { logger?.WriteLine("Slicing..."); // Do slicing MeshPlanarSlicer slicer = new MeshPlanarSlicer() { LayerHeightMM = layerHeight, }; slicer.Add(meshes); slices = slicer.Compute(); }
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!"); } }
/// <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); }
/// <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 Result() { Clearing = new PlanarSliceStack(); HorizontalFinish = new PlanarSliceStack(); }