public void DualMaterialNoRetraction(int material) { GCodeExport.CheckForZeroPositions = false; string shortCubeName = "CubePoint2High"; string shortCube = TestUtilities.GetStlPath(shortCubeName); string outputGCodeFileName = TestUtilities.GetTempGCodePath($"CubeNoRetractions{material}"); var config = new ConfigSettings(); config.ExtruderCount = 2; config.FirstLayerThickness = .2; config.LayerThickness = .2; var processor = new FffProcessor(config); processor.SetTargetFile(outputGCodeFileName); for (int i = 0; i < material; i++) { string skipExtruder = TestUtilities.GetStlPath("TooSmallToPrint"); processor.LoadStlFile(skipExtruder); } processor.LoadStlFile(shortCube); // slice and save it processor.DoProcessing(); processor.Dispose(); string[] gCodeContent = TestUtilities.LoadGCodeFile(outputGCodeFileName); // test layer count int layerCount = TestUtilities.LayerCount(gCodeContent); Assert.AreEqual(1, layerCount); int retractions = TestUtilities.CountRetractions(gCodeContent); Assert.AreEqual(1, retractions, $"Material {material} should have no retractions"); }
public static int ProcessArgs(string[] args) { if (args.Length == 0) { print_usage(); return(0); } ConfigSettings config = new ConfigSettings(); FffProcessor processor = new FffProcessor(config); LogOutput.Log("\nMatterSlice version {0}\n\n".FormatWith(ConfigConstants.VERSION)); if (ProcessArgs(args, config, processor) == 0) { return(0); } if (!Canceled) { using (new QuickTimer2("DoProcessing")) { processor.DoProcessing(); } } if (!Canceled) { processor.Dispose(); } if (Canceled) { processor.Cancel(); } Canceled = true; return(0); }
public void SupportConnectedOptimaly() { string thinWallsSTL = TestUtilities.GetStlPath("two disks"); string thinWallsGCode = TestUtilities.GetTempGCodePath("two disks.gcode"); { // load a model that is correctly manifold var config = new ConfigSettings(); config.GenerateSupport = true; var processor = new FffProcessor(config); processor.SetTargetFile(thinWallsGCode); processor.LoadStlFile(thinWallsSTL); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] loadedGCode = TestUtilities.LoadGCodeFile(thinWallsGCode); int layerCount = TestUtilities.LayerCount(loadedGCode); for (int i = 0; i < layerCount; i++) { var movements = loadedGCode.GetGCodeForLayer(i).Movements().ToList(); int longMoveCount = 0; for (var j = 1; j < movements.Count - 2; j++) { var start = movements[j - 1]; var end = movements[j]; if (end.extrusion - start.extrusion == 0 && (end.position - start.position).Length > 5) { longMoveCount++; } } Assert.LessOrEqual(longMoveCount, 6); } } }
public void SupportTowerHasCorrectRetractions() { string infillSTLA = TestUtilities.GetStlPath("dice_body"); string infillSTLB = TestUtilities.GetStlPath("dice_numbers"); string infillGCode = TestUtilities.GetTempGCodePath("dice_dual.gcode"); { // load a model that is correctly manifold var config = new ConfigSettings(); string settingsPath = TestContext.CurrentContext.ResolveProjectPath(4, "Tests", "TestData", "thin_ring_config.ini"); config.ReadSettings(settingsPath); var processor = new FffProcessor(config); processor.SetTargetFile(infillGCode); processor.LoadStlFile(infillSTLA); processor.LoadStlFile(infillSTLB); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] loadedGCode = TestUtilities.LoadGCodeFile(infillGCode); Assert.IsTrue(loadedGCode.Contains("T1 ; switch extruder")); Assert.IsTrue(loadedGCode.Contains("T0 ; switch extruder")); var layers = loadedGCode.GetAllExtrusionPolygons(); for (int i = 0; i < layers.Count; i++) { var polys = layers[i]; foreach (var poly in polys) { for (int j = 0; j < poly.Count - 1; j++) { int a = 0; } } } } }
static void Main(string[] args) { Console.WriteLine("Hello World!"); ConfigSettings config = new ConfigSettings(); FffProcessor processor = new FffProcessor(config); MemoryStream result = new MemoryStream(); processor.SetTargetStream(result); var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase).Replace("file:\\", ""); path = $"{path}\\SampleSTLs\\AvoidCrossing9Holes.stl"; var stream = new FileStream(path, FileMode.Open); using (new QuickTimer2("LoadStlFile")) { processor.LoadStlStream(stream); } using (new QuickTimer2("DoProcessing")) { processor.DoProcessing(); } var data = processor.Finalize(); //GenericGCodeParser parser = new GenericGCodeParser(); //result.Position = 0; //TextReader tr = new StreamReader(result); //var gcode = parser.Parse(tr); }
public void CorrectIslandCount() { string engineStlFile = TestUtilities.GetStlPath("Engine-Benchmark"); string engineGCodeFile = TestUtilities.GetTempGCodePath("Engine-Benchmark.gcode"); var config = new ConfigSettings(); config.FirstLayerThickness = .2; config.LayerThickness = .2; config.NumberOfSkirtLoops = 0; config.InfillPercent = 0; config.NumberOfTopLayers = 0; config.NumberOfBottomLayers = 0; config.NumberOfPerimeters = 1; config.MergeOverlappingLines = false; var processor = new FffProcessor(config); processor.SetTargetFile(engineGCodeFile); processor.LoadStlFile(engineStlFile); // slice and save it processor.DoProcessing(); processor.Dispose(); var loadedGCode = TestUtilities.LoadGCodeFile(engineGCodeFile); var layers = TestUtilities.LayerCount(loadedGCode); Assert.AreEqual(195, layers); var layerPolygons = TestUtilities.GetAllLayersExtrusionPolygons(loadedGCode); Assert.AreEqual(17, layerPolygons[32].Count); for (int i = 33; i < 44; i++) { Assert.AreEqual(13, layerPolygons[i].Where(p => p.Count > 2).Count()); } }
private static void CheckSpiralCylinder(string stlFile, string gcodeFile, int expectedLayers, bool enableThinWalls = false) { string cylinderStlFile = TestUtilities.GetStlPath(stlFile); string cylinderGCodeFileName = TestUtilities.GetTempGCodePath(gcodeFile); ConfigSettings config = new ConfigSettings(); config.FirstLayerThickness = .2; config.LayerThickness = .2; if (enableThinWalls) { config.ExpandThinWalls = true; config.FillThinGaps = true; } config.NumberOfBottomLayers = 0; config.ContinuousSpiralOuterPerimeter = true; FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(cylinderGCodeFileName); processor.LoadStlFile(cylinderStlFile); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] cylinderGCodeContent = TestUtilities.LoadGCodeFile(cylinderGCodeFileName); // test .1 layer height int layerCount = TestUtilities.CountLayers(cylinderGCodeContent); Assert.IsTrue(layerCount == expectedLayers); for (int i = 2; i < layerCount - 3; i++) { string[] layerInfo = TestUtilities.GetGCodeForLayer(cylinderGCodeContent, i); // check that all layers move up continuously MovementInfo lastMovement = new MovementInfo(); foreach (MovementInfo movement in TestUtilities.Movements(layerInfo)) { Assert.IsTrue(movement.position.z > lastMovement.position.z); lastMovement = movement; } bool first = true; lastMovement = new MovementInfo(); // check that all moves are on the outside of the cylinder (not crossing to a new point) foreach (MovementInfo movement in TestUtilities.Movements(layerInfo)) { if (!first) { Assert.IsTrue((movement.position - lastMovement.position).Length < 2); Vector3 xyOnly = new Vector3(movement.position.x, movement.position.y, 0); Assert.AreEqual(9.8, xyOnly.Length, .3); } lastMovement = movement; first = false; } } }
private static void CheckSpiralCone(string stlFile, string gcodeFile, bool enableThinWalls = false) { string cylinderStlFile = TestUtilities.GetStlPath(stlFile); string cylinderGCodeFileName = TestUtilities.GetTempGCodePath(gcodeFile); var config = new ConfigSettings { FirstLayerThickness = .2, LayerThickness = .2, NumberOfBottomLayers = 0, ContinuousSpiralOuterPerimeter = true }; if (enableThinWalls) { config.ExpandThinWalls = true; config.FillThinGaps = true; } var processor = new FffProcessor(config); processor.SetTargetFile(cylinderGCodeFileName); processor.LoadStlFile(cylinderStlFile); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] cylinderGCodeContent = TestUtilities.LoadGCodeFile(cylinderGCodeFileName); // test .1 layer height int layerCount = TestUtilities.CountLayers(cylinderGCodeContent); Assert.AreEqual(50, layerCount, "SpiralCone should have 50 layers"); for (int i = 2; i < layerCount - 3; i++) { string[] layerInfo = TestUtilities.GetGCodeForLayer(cylinderGCodeContent, i); // check that all layers move up continuously MovementInfo lastMovement = new MovementInfo(); foreach (MovementInfo movement in TestUtilities.Movements(layerInfo)) { #if __ANDROID__ Assert.IsTrue(movement.position.z > lastMovement.position.z); #else Assert.Greater(movement.position.z, lastMovement.position.z, "Z position should increment per layer"); #endif lastMovement = movement; } double radiusForLayer = 5.0 + (20.0 - 5.0) / layerCount * i; bool first = true; lastMovement = new MovementInfo(); // check that all moves are on the outside of the cylinder (not crossing to a new point) foreach (MovementInfo movement in TestUtilities.Movements(layerInfo)) { if (!first) { Assert.IsTrue((movement.position - lastMovement.position).Length < 2); Vector3 xyOnly = new Vector3(movement.position.x, movement.position.y, 0); Assert.AreEqual(radiusForLayer, xyOnly.Length, .3); } lastMovement = movement; first = false; } } }
public void DualMaterialPrintMovesCorrectly(bool createWipeTower) { string leftPart = "Box Left"; string rightPart = "Box Right"; string leftStlFile = TestUtilities.GetStlPath(leftPart); string rightStlFile = TestUtilities.GetStlPath(rightPart); string outputGCodeFileName = TestUtilities.GetTempGCodePath("DualPartMoves"); ConfigSettings config = new ConfigSettings(); config.ExtruderCount = 2; config.FirstLayerThickness = .2; config.LayerThickness = .2; config.NumberOfBottomLayers = 0; if (createWipeTower) { config.WipeTowerSize = 10; } else { config.WipeTowerSize = 0; } var processor = new FffProcessor(config); processor.SetTargetFile(outputGCodeFileName); processor.LoadStlFile(leftStlFile); processor.LoadStlFile(rightStlFile); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gCodeContent = TestUtilities.LoadGCodeFile(outputGCodeFileName); // test .1 layer height int layerCount = TestUtilities.CountLayers(gCodeContent); Assert.IsTrue(layerCount == 50); bool hadMoveLessThan85 = false; MovementInfo lastMovement = new MovementInfo(); for (int i = 0; i < layerCount - 3; i++) { string[] layerInfo = TestUtilities.GetGCodeForLayer(gCodeContent, i); // check that all layers move up continuously foreach (MovementInfo movement in TestUtilities.Movements(layerInfo, lastMovement, onlyG1s: true)) { if (i > 2) { if (createWipeTower) { Assert.IsTrue(movement.position.x > 75 && movement.position.y > 10, "Moves don't go to 0"); if (movement.position.x < 85) { hadMoveLessThan85 = true; } } else { Assert.IsTrue(movement.position.x > 85 && movement.position.y > 10, "Moves don't go to 0"); } } lastMovement = movement; } } if (createWipeTower) { Assert.IsTrue(hadMoveLessThan85, "found a wipe tower"); } }
public void DoHas2WallRingsAllTheWayUp(string fileName, int expectedLayerCount, bool checkRadius = false) { string stlFile = TestUtilities.GetStlPath(fileName); string gCodeFile = TestUtilities.GetTempGCodePath(fileName + ".gcode"); ConfigSettings config = new ConfigSettings(); config.InfillPercent = 0; config.NumberOfPerimeters = 1; config.FirstLayerExtrusionWidth = .2; config.LayerThickness = .2; config.NumberOfBottomLayers = 0; config.NumberOfTopLayers = 0; FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(gCodeFile); processor.LoadStlFile(stlFile); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gcodeLines = TestUtilities.LoadGCodeFile(gCodeFile); int layerCount = TestUtilities.CountLayers(gcodeLines); Assert.IsTrue(layerCount == expectedLayerCount); MovementInfo movement = new MovementInfo(); for (int i = 0; i < layerCount - 5; i++) { string[] layerInfo = TestUtilities.GetGCodeForLayer(gcodeLines, i); if (i > 0) { Polygons layerPolygons = TestUtilities.GetExtrusionPolygons(layerInfo, ref movement); Assert.IsTrue(layerPolygons.Count == 2); if (checkRadius) { Assert.IsTrue(layerPolygons[0].Count > 10); Assert.IsTrue(layerPolygons[1].Count > 10); if (false) { foreach (var polygon in layerPolygons) { double radiusForPolygon = polygon[0].LengthMm(); foreach (var point in polygon) { Assert.AreEqual(radiusForPolygon, point.LengthMm(), 15); } } } } } else { TestUtilities.GetExtrusionPolygons(layerInfo, ref movement); } } }
public void CanSetExtruderForSupportMaterial() { string baseFileName = "Support Material 2 Bars"; string stlToLoad = TestUtilities.GetStlPath(baseFileName + ".stl"); string supportToLoad = TestUtilities.GetStlPath("2BarsSupport.stl"); // check that default is support printed with extruder 0 { string gcodeToCreate = TestUtilities.GetTempGCodePath(baseFileName + "_0_.gcode"); ConfigSettings config = new ConfigSettings(); FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(gcodeToCreate); processor.LoadStlFile(stlToLoad); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gcodeContents = TestUtilities.LoadGCodeFile(gcodeToCreate); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 1)); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 2)); } // check that support is printed with extruder 0 { string gcodeToCreate = TestUtilities.GetTempGCodePath(baseFileName + "_1b_.gcode"); ConfigSettings config = new ConfigSettings(); config.ExtruderCount = 1; config.SupportExtruder = 1; // from a 0 based index // this is a hack, but it is the signaling mechanism for support config.BooleanOperations = "S"; FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(gcodeToCreate); processor.LoadStlFile(stlToLoad); processor.LoadStlFile(supportToLoad); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gcodeContents = TestUtilities.LoadGCodeFile(gcodeToCreate); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 1)); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 2)); } // check that support is printed with extruder 1 { string gcodeToCreate = TestUtilities.GetTempGCodePath(baseFileName + "_1b_.gcode"); ConfigSettings config = new ConfigSettings(); config.SupportExtruder = 1; config.ExtruderCount = 2; // this is a hack, but it is the signaling mechanism for support config.BooleanOperations = "S"; FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(gcodeToCreate); processor.LoadStlFile(stlToLoad); // we have to have a mesh for every extruder processor.LoadStlFile(stlToLoad); processor.LoadStlFile(supportToLoad); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gcodeContents = TestUtilities.LoadGCodeFile(gcodeToCreate); Assert.IsTrue(TestUtilities.UsesExtruder(gcodeContents, 1)); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 2)); } // check that support interface is printed with extruder 0 { string gcodeToCreate = TestUtilities.GetTempGCodePath(baseFileName + "_1i_.gcode"); ConfigSettings config = new ConfigSettings(); config.ExtruderCount = 1; config.SupportInterfaceExtruder = 1; // this is a hack, but it is the signaling mechanism for support config.BooleanOperations = "S"; FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(gcodeToCreate); processor.LoadStlFile(stlToLoad); processor.LoadStlFile(supportToLoad); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gcodeContents = TestUtilities.LoadGCodeFile(gcodeToCreate); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 1)); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 2)); } // check that support interface is printed with extruder 1 { string gcodeToCreate = TestUtilities.GetTempGCodePath(baseFileName + "_1i_.gcode"); ConfigSettings config = new ConfigSettings(); config.ExtruderCount = 2; config.SupportInterfaceExtruder = 1; // this is a hack, but it is the signaling mechanism for support config.BooleanOperations = "S"; FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(gcodeToCreate); processor.LoadStlFile(stlToLoad); // we have to have a mesh for every extruder processor.LoadStlFile(stlToLoad); processor.LoadStlFile(supportToLoad); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gcodeContents = TestUtilities.LoadGCodeFile(gcodeToCreate); Assert.IsTrue(TestUtilities.UsesExtruder(gcodeContents, 0)); Assert.IsTrue(TestUtilities.UsesExtruder(gcodeContents, 1)); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 2)); } // check that support and interface can be set separately { string gcodeToCreate = TestUtilities.GetTempGCodePath(baseFileName + "_1b2i_.gcode"); ConfigSettings config = new ConfigSettings(); config.ExtruderCount = 1; config.SupportExtruder = 1; config.SupportInterfaceExtruder = 2; // this is a hack, but it is the signaling mechanism for support config.BooleanOperations = "S"; FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(gcodeToCreate); processor.LoadStlFile(stlToLoad); processor.LoadStlFile(supportToLoad); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gcodeContents = TestUtilities.LoadGCodeFile(gcodeToCreate); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 1)); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 2)); } // check that support and interface can be set separately { string gcodeToCreate = TestUtilities.GetTempGCodePath(baseFileName + "_1b2i_.gcode"); ConfigSettings config = new ConfigSettings(); config.ExtruderCount = 2; config.SupportExtruder = 1; config.SupportInterfaceExtruder = 2; // this is a hack, but it is the signaling mechanism for support config.BooleanOperations = "S"; FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(gcodeToCreate); processor.LoadStlFile(stlToLoad); // we have to have a mesh for every extruder processor.LoadStlFile(stlToLoad); processor.LoadStlFile(supportToLoad); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gcodeContents = TestUtilities.LoadGCodeFile(gcodeToCreate); Assert.IsTrue(TestUtilities.UsesExtruder(gcodeContents, 1)); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 2)); } // check that support and interface can be set separately { string gcodeToCreate = TestUtilities.GetTempGCodePath(baseFileName + "_1b2i_.gcode"); ConfigSettings config = new ConfigSettings(); config.ExtruderCount = 3; config.SupportExtruder = 1; config.SupportInterfaceExtruder = 2; // this is a hack, but it is the signaling mechanism for support config.BooleanOperations = "S"; FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(gcodeToCreate); processor.LoadStlFile(stlToLoad); // we have to have a mesh for every extruder processor.LoadStlFile(stlToLoad); processor.LoadStlFile(stlToLoad); processor.LoadStlFile(supportToLoad); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gcodeContents = TestUtilities.LoadGCodeFile(gcodeToCreate); Assert.IsTrue(TestUtilities.UsesExtruder(gcodeContents, 1)); Assert.IsTrue(TestUtilities.UsesExtruder(gcodeContents, 2)); } }
public void AllMovesRequiringRetractionDoRetraction(string baseFileName, string settingsIniFile = "") { string stlToLoad = TestUtilities.GetStlPath(baseFileName + ".stl"); // check that default is support printed with extruder 0 string gcodeToCreate = TestUtilities.GetTempGCodePath(baseFileName + "_retract_.gcode"); ConfigSettings config = new ConfigSettings(); if (settingsIniFile == "") { config.MinimumTravelToCauseRetraction = 2; config.MinimumExtrusionBeforeRetraction = 0; config.MergeOverlappingLines = false; config.FirstLayerExtrusionWidth = .5; } else { config.ReadSettings(settingsIniFile); } // this is what we detect config.RetractionZHop = 5; FffProcessor processor = new FffProcessor(config); processor.SetTargetFile(gcodeToCreate); processor.LoadStlFile(stlToLoad); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] gcodeContents = TestUtilities.LoadGCodeFile(gcodeToCreate); int layerCount = TestUtilities.CountLayers(gcodeContents); bool firstPosition = true; MovementInfo lastMovement = new MovementInfo(); MovementInfo lastExtrusion = new MovementInfo(); bool lastMoveIsExtrusion = true; for (int layerIndex = 0; layerIndex < layerCount; layerIndex++) { string[] layerGCode = TestUtilities.GetGCodeForLayer(gcodeContents, layerIndex); int movementIndex = 0; foreach (MovementInfo movement in TestUtilities.Movements(layerGCode, lastMovement)) { if (!firstPosition) { bool isTravel = lastMovement.extrusion == movement.extrusion; if (isTravel) { Vector3 lastPosition = lastMovement.position; lastPosition.z = 0; Vector3 currenPosition = movement.position; currenPosition.z = 0; double xyLength = (lastPosition - currenPosition).Length; if (xyLength > config.MinimumTravelToCauseRetraction && lastMoveIsExtrusion) { Assert.GreaterOrEqual(movement.position.z, lastExtrusion.position.z); } lastMoveIsExtrusion = false; } else { lastMoveIsExtrusion = true; lastExtrusion = movement; } lastMoveIsExtrusion = !isTravel; } lastMovement = movement; firstPosition = false; movementIndex++; } } // make sure we don't switch extruders Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 1)); Assert.IsFalse(TestUtilities.UsesExtruder(gcodeContents, 2)); }
public void ExpandThinWallsFindsWalls() { string thinWallsSTL = TestUtilities.GetStlPath("ThinWalls"); // without expand thin walls { string thinWallsGCode = TestUtilities.GetTempGCodePath("ThinWalls1.gcode"); var config = new ConfigSettings { FirstLayerThickness = .2, LayerThickness = .2, NumberOfSkirtLoops = 0, InfillPercent = 0, NumberOfTopLayers = 0, NumberOfBottomLayers = 0, NumberOfPerimeters = 1, ExpandThinWalls = false, MergeOverlappingLines = false }; var processor = new FffProcessor(config); processor.SetTargetFile(thinWallsGCode); processor.LoadStlFile(thinWallsSTL); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] loadedGCode = TestUtilities.LoadGCodeFile(thinWallsGCode); int layerCount = TestUtilities.LayerCount(loadedGCode); Assert.AreEqual(50, layerCount); var layerPolygons = loadedGCode.GetAllExtrusionPolygons(); Assert.AreEqual(6, layerPolygons[10].Where(i => i.Count > 2).Count()); } // with expand thin walls { string thinWallsGCode = TestUtilities.GetTempGCodePath("ThinWalls2.gcode"); var config = new ConfigSettings(); config.FirstLayerThickness = .2; config.LayerThickness = .2; config.NumberOfSkirtLoops = 0; config.InfillPercent = 0; config.NumberOfTopLayers = 0; config.NumberOfBottomLayers = 0; config.NumberOfPerimeters = 1; config.ExpandThinWalls = true; config.MergeOverlappingLines = false; var processor = new FffProcessor(config); processor.SetTargetFile(thinWallsGCode); processor.LoadStlFile(thinWallsSTL); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] loadedGCode = TestUtilities.LoadGCodeFile(thinWallsGCode); int layerCount = TestUtilities.LayerCount(loadedGCode); Assert.AreEqual(50, layerCount); var layerPolygons = loadedGCode.GetAllExtrusionPolygons(); Assert.AreEqual(10, layerPolygons[10].Count); } // with expand thin walls and with merge overlapping lines { string thinWallsGCode = TestUtilities.GetTempGCodePath("ThinWalls3.gcode"); var config = new ConfigSettings(); config.FirstLayerThickness = .2; config.LayerThickness = .2; config.NumberOfSkirtLoops = 0; config.InfillPercent = 0; config.NumberOfTopLayers = 0; config.NumberOfBottomLayers = 0; config.NumberOfPerimeters = 1; config.ExpandThinWalls = true; config.MergeOverlappingLines = true; var processor = new FffProcessor(config); processor.SetTargetFile(thinWallsGCode); processor.LoadStlFile(thinWallsSTL); // slice and save it processor.DoProcessing(); processor.Finalize(); string[] loadedGCode = TestUtilities.LoadGCodeFile(thinWallsGCode); int layerCount = TestUtilities.LayerCount(loadedGCode); Assert.AreEqual(50, layerCount); var layerPolygons = loadedGCode.GetAllExtrusionPolygons(); Assert.AreEqual(10, layerPolygons[10].Count); } }