static string GenerateGCodeForMeshes(PrintMeshAssembly meshes) { AxisAlignedBox3d bounds = meshes.TotalBounds; double top_z = bounds.Depth; // configure settings RepRapSettings settings = new RepRapSettings(RepRap.Models.Unknown); settings.GenerateSupport = false; settings.EnableBridging = false; int nSpeed = 1200; // foam //int nSpeed = 700; // wood settings.RapidTravelSpeed = nSpeed; settings.RapidExtrudeSpeed = nSpeed; settings.CarefulExtrudeSpeed = nSpeed; settings.OuterPerimeterSpeedX = 1.0; settings.ZTravelSpeed = nSpeed; settings.RetractSpeed = nSpeed; settings.LayerHeightMM = 4.0; settings.Machine.NozzleDiamMM = 6.35; settings.Machine.BedSizeXMM = 240; settings.Machine.BedSizeYMM = 190; settings.RetractDistanceMM = 1; settings.EnableRetraction = true; settings.ShellsFillNozzleDiamStepX = 0.5; settings.SolidFillNozzleDiamStepX = 0.9; settings.SolidFillBorderOverlapX = 0.5; LastSettings = settings.CloneAs <SingleMaterialFFFSettings>(); System.Console.WriteLine("Slicing..."); // slice meshes MeshPlanarMillSlicer slicer = new MeshPlanarMillSlicer() { LayerHeightMM = settings.LayerHeightMM, ToolDiameter = settings.Machine.NozzleDiamMM, ExpandStockAmount = 0.4 * settings.Machine.NozzleDiamMM }; slicer.Add(meshes); MeshPlanarMillSlicer.Result sliceResult = slicer.Compute(); PlanarSliceStack slices = sliceResult.Clearing; System.Console.WriteLine("Generating GCode..."); ToolpathSet accumPaths; GCodeFile genGCode = generate_cnc_test(sliceResult, settings, out accumPaths); System.Console.WriteLine("Writing GCode..."); string sWritePath = "../../../sample_output/generated.nc"; StandardGCodeWriter writer = new StandardGCodeWriter() { CommentStyle = StandardGCodeWriter.CommentStyles.Bracket }; using (StreamWriter w = new StreamWriter(sWritePath)) { writer.WriteFile(genGCode, w); } //DMesh3 tube_mesh = GenerateTubeMeshesForGCode(sWritePath, settings.Machine.NozzleDiamMM); DMesh3 tube_mesh = GenerateTubeMeshesForGCode(sWritePath, 0.4); StandardMeshWriter.WriteMesh("../../../sample_output/generated_tubes.obj", tube_mesh, WriteOptions.Defaults); if (SHOW_RELOADED_GCODE_PATHS == false) { View.SetPaths(accumPaths, settings); View.PathDiameterMM = (float)settings.Machine.NozzleDiamMM; } slices.Add(sliceResult.HorizontalFinish.Slices); slices.Slices.Sort((a, b) => { return(a.Z.CompareTo(b.Z)); }); View.SetSlices(slices); View.CurrentLayer = slices.Slices.Count - 1; return(sWritePath); }
static GCodeFile generate_cnc_test(MeshPlanarMillSlicer.Result sliceSets, RepRapSettings settings, out ToolpathSet AccumulatedPaths) { int PLUNGE_SPEED = 800; AccumulatedPaths = new ToolpathSet(); GCodeFileAccumulator file_accumulator = new GCodeFileAccumulator(); GCodeBuilder builder = new GCodeBuilder(file_accumulator); BaseThreeAxisMillingCompiler Compiler = new BaseThreeAxisMillingCompiler(builder, settings, GenericMillingAssembler.Factory); Compiler.Begin(); /* * Clearing pass */ PlanarSliceStack clearingSlices = sliceSets.Clearing; int N = clearingSlices.Count; // assuming origin is at top of stock so we actaully are going down in Z layers for (int k = 0; k < N; ++k) { clearingSlices[k].Z = -(sliceSets.TopZ - clearingSlices[k].Z); } for (int layeri = 0; layeri < N; layeri++) { PlanarSlice slice = clearingSlices[layeri]; Compiler.AppendComment(string.Format("clearing layer {0} - {1}mm", layeri, slice.Z)); ToolpathSetBuilder layer_builder = new ToolpathSetBuilder() { MoveType = ToolpathTypes.Cut }; layer_builder.Initialize(Compiler.ToolPosition); // To do a layer-change, we need to plunge down at the first scheduled cutting position. // However we will not know that until we schedule the first set of paths. // So, we configure SequentialScheduler2d to call this function when it knows this information, // and then we can travel to the new XY position before we plunge to new Z Action <List <FillCurveSet2d>, SequentialScheduler2d> DoZChangeF = (curves, scheduler) => { Vector2d startPosXY = (curves[0].Loops.Count > 0) ? curves[0].Loops[0].Start : curves[0].Curves[0].Start; Vector3d startPosXYZ = new Vector3d(startPosXY.x, startPosXY.y, slice.Z); // TODO: we should retract at faster speed here? maybe use custom function that does this better? layer_builder.AppendTravel(startPosXYZ, PLUNGE_SPEED); scheduler.OnAppendCurveSetsF = null; }; SequentialScheduler2d layerScheduler = new SequentialScheduler2d(layer_builder, settings) { ExtrudeOnShortTravels = true, ShortTravelDistance = settings.Machine.NozzleDiamMM * 1.5 }; layerScheduler.OnAppendCurveSetsF = DoZChangeF; GroupScheduler2d groupScheduler = new GroupScheduler2d(layerScheduler, Compiler.ToolPosition.xy); foreach (GeneralPolygon2d shape in slice.Solids) { ShellsFillPolygon shells_gen = new ShellsFillPolygon(shape) { PathSpacing = settings.ShellsFillPathSpacingMM(), ToolWidth = settings.Machine.NozzleDiamMM, Layers = 10, OuterShellLast = false, DiscardTinyPerimterLengthMM = 1, DiscardTinyPolygonAreaMM2 = 1 }; shells_gen.Compute(); groupScheduler.BeginGroup(); groupScheduler.AppendCurveSets(shells_gen.Shells); groupScheduler.EndGroup(); } Compiler.AppendPaths(layer_builder.Paths, settings); AccumulatedPaths.Append(layer_builder.Paths); } /* * Horizontal finish pass */ PlanarSliceStack horzSlices = sliceSets.HorizontalFinish; int NH = horzSlices.Count; // assuming origin is at top of stock so we actaully are going down in Z layers for (int k = 0; k < NH; ++k) { horzSlices[k].Z = -(sliceSets.TopZ - horzSlices[k].Z); } for (int layeri = 0; layeri < NH; layeri++) { PlanarSlice slice = horzSlices[layeri]; Compiler.AppendComment(string.Format("horz finish layer {0} - {1}mm", layeri, slice.Z)); ToolpathSetBuilder layer_builder = new ToolpathSetBuilder() { MoveType = ToolpathTypes.Cut }; layer_builder.Initialize(Compiler.ToolPosition); Action <List <FillCurveSet2d>, SequentialScheduler2d> DoZChangeF = (curves, scheduler) => { Vector2d startPosXY = (curves[0].Loops.Count > 0) ? curves[0].Loops[0].Start : curves[0].Curves[0].Start; Vector3d startPosXYZ = new Vector3d(startPosXY.x, startPosXY.y, slice.Z); // TODO: we should retract at faster speed here? maybe use custom function that does this better? layer_builder.AppendTravel(startPosXYZ, PLUNGE_SPEED); scheduler.OnAppendCurveSetsF = null; }; SequentialScheduler2d layerScheduler = new SequentialScheduler2d(layer_builder, settings) { ExtrudeOnShortTravels = true, ShortTravelDistance = settings.Machine.NozzleDiamMM * 1.5 }; layerScheduler.OnAppendCurveSetsF = DoZChangeF; GroupScheduler2d groupScheduler = new GroupScheduler2d(layerScheduler, Compiler.ToolPosition.xy); foreach (GeneralPolygon2d shape in slice.Solids) { ShellsFillPolygon shells_gen = new ShellsFillPolygon(shape) { //InsetFromInputPolygonX = 0.0, PathSpacing = settings.ShellsFillPathSpacingMM(), ToolWidth = settings.Machine.NozzleDiamMM, Layers = 10, OuterShellLast = false, PreserveInputInsetTopology = false, DiscardTinyPerimterLengthMM = 1, DiscardTinyPolygonAreaMM2 = 1 }; shells_gen.Compute(); groupScheduler.BeginGroup(); groupScheduler.AppendCurveSets(shells_gen.Shells); groupScheduler.EndGroup(); } Compiler.AppendPaths(layer_builder.Paths, settings); AccumulatedPaths.Append(layer_builder.Paths); } // return to home position ToolpathSetBuilder finishBuilder = new ToolpathSetBuilder() { MoveType = ToolpathTypes.Cut }; finishBuilder.Initialize(Compiler.ToolPosition); finishBuilder.AppendTravel(Vector3d.Zero, PLUNGE_SPEED); Compiler.AppendPaths(finishBuilder.Paths, settings); Compiler.End(); return(file_accumulator.File); }