void Infill::generateCubicInfill(Polygons& result) { int64_t shift = one_over_sqrt_2 * z; generateLineInfill(result, line_distance, fill_angle, shift); generateLineInfill(result, line_distance, fill_angle + 120, shift); generateLineInfill(result, line_distance, fill_angle + 240, shift); }
void generateGridInfill(const Polygons& in_outline, int outlineOffset, Polygons& result, int extrusionWidth, int lineSpacing, double infillOverlap, double rotation) { generateLineInfill(in_outline, outlineOffset, result, extrusionWidth, lineSpacing, infillOverlap, rotation); generateLineInfill(in_outline, outlineOffset, result, extrusionWidth, lineSpacing, infillOverlap, rotation + 90); }
void Infill::generateTetrahedralInfill(Polygons& result) { int period = line_distance * 2; int shift = int64_t(one_over_sqrt_2 * z) % period; shift = std::min(shift, period - shift); // symmetry due to the fact that we are applying the shift in both directions shift = std::min(shift, period / 2 - infill_line_width / 2); // don't put lines too close to each other shift = std::max(shift, infill_line_width / 2); // don't put lines too close to each other generateLineInfill(result, period, fill_angle, shift); generateLineInfill(result, period, fill_angle, -shift); generateLineInfill(result, period, fill_angle + 90, shift); generateLineInfill(result, period, fill_angle + 90, -shift); }
void generateAutomaticInfill(const Polygons& in_outline, Polygons& result, int extrusionWidth, int lineSpacing, int infillOverlap, double rotation, int posZ) { if (lineSpacing > extrusionWidth * 4) { generateTroctInfill(in_outline, result, extrusionWidth, lineSpacing, infillOverlap, rotation, posZ); } else { generateLineInfill(in_outline, result, extrusionWidth, lineSpacing, infillOverlap, rotation); } }
void Infill::generate(Polygons& result_polygons, Polygons& result_lines, Polygons* in_between) { if (in_outline.size() == 0) return; if (line_distance == 0) return; const Polygons* outline = &in_outline; Polygons outline_offsetted; switch(pattern) { case EFillMethod::GRID: generateGridInfill(in_outline, outlineOffset, result_lines, extrusion_width, line_distance * 2, infill_overlap, fill_angle); break; case EFillMethod::LINES: generateLineInfill(in_outline, outlineOffset, result_lines, extrusion_width, line_distance, infill_overlap, fill_angle); break; case EFillMethod::TRIANGLES: generateTriangleInfill(in_outline, outlineOffset, result_lines, extrusion_width, line_distance * 3, infill_overlap, fill_angle); break; case EFillMethod::CONCENTRIC: if (outlineOffset != 0) { PolygonUtils::offsetSafe(in_outline, outlineOffset, extrusion_width, outline_offsetted, avoidOverlappingPerimeters); outline = &outline_offsetted; } if (abs(extrusion_width - line_distance) < 10) { generateConcentricInfillDense(*outline, result_polygons, in_between, extrusion_width, avoidOverlappingPerimeters); } else { generateConcentricInfill(*outline, result_polygons, line_distance); } break; case EFillMethod::ZIG_ZAG: if (outlineOffset != 0) { PolygonUtils::offsetSafe(in_outline, outlineOffset, extrusion_width, outline_offsetted, avoidOverlappingPerimeters); outline = &outline_offsetted; } generateZigZagInfill(*outline, result_lines, extrusion_width, line_distance, infill_overlap, fill_angle, connect_zigzags, use_endPieces); break; default: logError("Fill pattern has unknown value.\n"); break; } }
void Infill::generate(Polygons& result_polygons, Polygons& result_lines, SliceMeshStorage* mesh) { if (in_outline.size() == 0) return; if (line_distance == 0) return; Polygons outline_offsetted; switch(pattern) { case EFillMethod::GRID: generateGridInfill(result_lines); break; case EFillMethod::LINES: generateLineInfill(result_lines, line_distance, fill_angle, 0); break; case EFillMethod::CUBIC: generateCubicInfill(result_lines); break; case EFillMethod::TETRAHEDRAL: generateTetrahedralInfill(result_lines); break; case EFillMethod::TRIANGLES: generateTriangleInfill(result_lines); break; case EFillMethod::CONCENTRIC: generateConcentricInfill(result_polygons, line_distance); break; case EFillMethod::CONCENTRIC_3D: generateConcentric3DInfill(result_polygons); break; case EFillMethod::ZIG_ZAG: generateZigZagInfill(result_lines, line_distance, fill_angle, connected_zigzags, use_endpieces); break; case EFillMethod::CUBICSUBDIV: if (!mesh) { logError("Cannot generate Cubic Subdivision infill without a mesh!\n"); break; } generateCubicSubDivInfill(result_lines, *mesh); break; default: logError("Fill pattern has unknown value.\n"); break; } }
void PrimeTower::generatePaths3(SliceDataStorage& storage) { int n_patterns = 2; // alternating patterns between layers double infill_overlap = 15; // so that it can't be zero generateGroundpoly(storage); for (int extruder = 0; extruder < extruder_count; extruder++) { int line_width = storage.meshgroup->getExtruderTrain(extruder)->getSettingInMicrons("prime_tower_line_width"); patterns_per_extruder.emplace_back(n_patterns); std::vector<Polygons>& patterns = patterns_per_extruder.back(); for (int pattern_idx = 0; pattern_idx < n_patterns; pattern_idx++) { generateLineInfill(ground_poly, -line_width/2, patterns[pattern_idx], line_width, line_width, infill_overlap, 45 + pattern_idx*90); } } }
void processFile(const char* input_filename, ConfigSettings& config, GCodeExport& gcode, bool firstFile) { for(unsigned int n=1; n<16; n++) gcode.setExtruderOffset(n, config.extruderOffset[n].p()); gcode.setFlavor(config.gcodeFlavor); double t = getTime(); log("Loading %s from disk...\n", input_filename); SimpleModel* m = loadModel(input_filename, config.matrix); if (!m) { log("Failed to load model: %s\n", input_filename); return; } log("Loaded from disk in %5.3fs\n", timeElapsed(t)); log("Analyzing and optimizing model...\n"); OptimizedModel* om = new OptimizedModel(m, Point3(config.objectPosition.X, config.objectPosition.Y, -config.objectSink)); for(unsigned int v = 0; v < m->volumes.size(); v++) { log(" Face counts: %i -> %i %0.1f%%\n", (int)m->volumes[v].faces.size(), (int)om->volumes[v].faces.size(), float(om->volumes[v].faces.size()) / float(m->volumes[v].faces.size()) * 100); log(" Vertex counts: %i -> %i %0.1f%%\n", (int)m->volumes[v].faces.size() * 3, (int)om->volumes[v].points.size(), float(om->volumes[v].points.size()) / float(m->volumes[v].faces.size() * 3) * 100); } delete m; log("Optimize model %5.3fs \n", timeElapsed(t)); //om->saveDebugSTL("c:\\models\\output.stl"); log("Slicing model...\n"); vector<Slicer*> slicerList; for(unsigned int volumeIdx=0; volumeIdx < om->volumes.size(); volumeIdx++) { slicerList.push_back(new Slicer(&om->volumes[volumeIdx], config.initialLayerThickness / 2, config.layerThickness, config.fixHorrible & FIX_HORRIBLE_KEEP_NONE_CLOSED, config.fixHorrible & FIX_HORRIBLE_EXTENSIVE_STITCHING)); //slicerList[volumeIdx]->dumpSegmentsToHTML("C:\\models\\output.html"); } log("Sliced model in %5.3fs\n", timeElapsed(t)); SliceDataStorage storage; fprintf(stdout,"Generating support map...\n"); generateSupportGrid(storage.support, om, config.supportAngle, config.supportEverywhere > 0, config.supportXYDistance, config.supportZDistance); storage.modelSize = om->modelSize; storage.modelMin = om->vMin; storage.modelMax = om->vMax; delete om; log("Generating layer parts...\n"); for(unsigned int volumeIdx=0; volumeIdx < slicerList.size(); volumeIdx++) { storage.volumes.push_back(SliceVolumeStorage()); createLayerParts(storage.volumes[volumeIdx], slicerList[volumeIdx], config.fixHorrible & (FIX_HORRIBLE_UNION_ALL_TYPE_A | FIX_HORRIBLE_UNION_ALL_TYPE_B | FIX_HORRIBLE_UNION_ALL_TYPE_C)); delete slicerList[volumeIdx]; } //carveMultipleVolumes(storage.volumes); generateMultipleVolumesOverlap(storage.volumes, config.multiVolumeOverlap); log("Generated layer parts in %5.3fs\n", timeElapsed(t)); //dumpLayerparts(storage, "c:/models/output.html"); const unsigned int totalLayers = storage.volumes[0].layers.size(); for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { int insetCount = config.insetCount; if (config.spiralizeMode && int(layerNr) < config.downSkinCount && layerNr % 2 == 1)//Add extra insets every 2 layers when spiralizing, this makes bottoms of cups watertight. insetCount += 5; generateInsets(&storage.volumes[volumeIdx].layers[layerNr], config.extrusionWidth, insetCount); } logProgress("inset",layerNr+1,totalLayers); } log("Generated inset in %5.3fs\n", timeElapsed(t)); for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { if (!config.spiralizeMode || int(layerNr) < config.downSkinCount) //Only generate up/downskin and infill for the first X layers when spiralize is choosen. { for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { generateSkins(layerNr, storage.volumes[volumeIdx], config.extrusionWidth, config.downSkinCount, config.upSkinCount, config.infillOverlap); generateSparse(layerNr, storage.volumes[volumeIdx], config.extrusionWidth, config.downSkinCount, config.upSkinCount); } } logProgress("skin",layerNr+1,totalLayers); } log("Generated up/down skin in %5.3fs\n", timeElapsed(t)); generateSkirt(storage, config.skirtDistance, config.extrusionWidth, config.skirtLineCount, config.skirtMinLength); generateRaft(storage, config.raftMargin); for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int partNr=0; partNr<storage.volumes[volumeIdx].layers[layerNr].parts.size(); partNr++) { if (layerNr > 0) storage.volumes[volumeIdx].layers[layerNr].parts[partNr].bridgeAngle = bridgeAngle(&storage.volumes[volumeIdx].layers[layerNr].parts[partNr], &storage.volumes[volumeIdx].layers[layerNr-1]); else storage.volumes[volumeIdx].layers[layerNr].parts[partNr].bridgeAngle = -1; } } } gcode.setRetractionSettings(config.retractionAmount, config.retractionSpeed, config.retractionAmountExtruderSwitch, config.minimalExtrusionBeforeRetraction); if (firstFile) { if (gcode.getFlavor() == GCODE_FLAVOR_ULTIGCODE) { gcode.addCode(";FLAVOR:UltiGCode"); gcode.addCode(";TIME:<__TIME__>"); gcode.addCode(";MATERIAL:<FILAMENT>"); } gcode.addCode(config.startCode); } else { gcode.addFanCommand(0); gcode.resetExtrusionValue(); gcode.addRetraction(); gcode.setZ(maxObjectHeight + 5000); gcode.addMove(Point(storage.modelMin.x, storage.modelMin.y), config.moveSpeed, 0); } gcode.addComment("total_layers=%d",totalLayers); GCodePathConfig skirtConfig(config.printSpeed, config.extrusionWidth, "SKIRT"); GCodePathConfig inset0Config(config.printSpeed, config.extrusionWidth, "WALL-OUTER"); GCodePathConfig inset1Config(config.printSpeed, config.extrusionWidth, "WALL-INNER"); GCodePathConfig fillConfig(config.infillSpeed, config.extrusionWidth, "FILL"); GCodePathConfig supportConfig(config.printSpeed, config.extrusionWidth, "SUPPORT"); if (config.raftBaseThickness > 0 && config.raftInterfaceThickness > 0) { GCodePathConfig raftBaseConfig(config.initialLayerSpeed, config.raftBaseLinewidth, "SUPPORT"); GCodePathConfig raftInterfaceConfig(config.initialLayerSpeed, config.raftInterfaceLinewidth, "SUPPORT"); { gcode.addComment("LAYER:-2"); gcode.addComment("RAFT"); GCodePlanner gcodeLayer(gcode, config.moveSpeed, config.retractionMinimalDistance); gcode.setZ(config.raftBaseThickness); gcode.setExtrusion(config.raftBaseThickness, config.filamentDiameter, config.filamentFlow); gcodeLayer.addPolygonsByOptimizer(storage.raftOutline, &raftBaseConfig); Polygons raftLines; generateLineInfill(storage.raftOutline, raftLines, config.raftBaseLinewidth, config.raftLineSpacing, config.infillOverlap, 0); gcodeLayer.addPolygonsByOptimizer(raftLines, &raftBaseConfig); gcodeLayer.writeGCode(false, config.raftBaseThickness); } { gcode.addComment("LAYER:-1"); gcode.addComment("RAFT"); GCodePlanner gcodeLayer(gcode, config.moveSpeed, config.retractionMinimalDistance); gcode.setZ(config.raftBaseThickness + config.raftInterfaceThickness); gcode.setExtrusion(config.raftInterfaceThickness, config.filamentDiameter, config.filamentFlow); Polygons raftLines; generateLineInfill(storage.raftOutline, raftLines, config.raftInterfaceLinewidth, config.raftLineSpacing, config.infillOverlap, 90); gcodeLayer.addPolygonsByOptimizer(raftLines, &raftInterfaceConfig); gcodeLayer.writeGCode(false, config.raftInterfaceThickness); } } int volumeIdx = 0; for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { logProgress("export", layerNr+1, totalLayers); GCodePlanner gcodeLayer(gcode, config.moveSpeed, config.retractionMinimalDistance); gcode.addComment("LAYER:%d", layerNr); int32_t z = config.initialLayerThickness + layerNr * config.layerThickness; z += config.raftBaseThickness + config.raftInterfaceThickness; gcode.setZ(z); if (layerNr == 0) gcodeLayer.addPolygonsByOptimizer(storage.skirt, &skirtConfig); for(unsigned int volumeCnt = 0; volumeCnt < storage.volumes.size(); volumeCnt++) { if (volumeCnt > 0) volumeIdx = (volumeIdx + 1) % storage.volumes.size(); SliceLayer* layer = &storage.volumes[volumeIdx].layers[layerNr]; gcodeLayer.setExtruder(volumeIdx); PathOrderOptimizer partOrderOptimizer(gcode.getPositionXY()); for(unsigned int partNr=0; partNr<layer->parts.size(); partNr++) { partOrderOptimizer.addPolygon(layer->parts[partNr].insets[0][0]); } partOrderOptimizer.optimize(); for(unsigned int partCounter=0; partCounter<partOrderOptimizer.polyOrder.size(); partCounter++) { SliceLayerPart* part = &layer->parts[partOrderOptimizer.polyOrder[partCounter]]; if (config.enableCombing) gcodeLayer.setCombBoundary(&part->combBoundery); else gcodeLayer.setAlwaysRetract(true); gcodeLayer.forceRetract(); if (config.insetCount > 0) { if (config.spiralizeMode) { if (int(layerNr) >= config.downSkinCount) inset0Config.spiralize = true; if (int(layerNr) == config.downSkinCount && part->insets.size() > 0) gcodeLayer.addPolygonsByOptimizer(part->insets[0], &inset1Config); } for(int insetNr=part->insets.size()-1; insetNr>-1; insetNr--) { if (insetNr == 0) gcodeLayer.addPolygonsByOptimizer(part->insets[insetNr], &inset0Config); else gcodeLayer.addPolygonsByOptimizer(part->insets[insetNr], &inset1Config); } } Polygons fillPolygons; int fillAngle = 45; if (layerNr & 1) fillAngle += 90; //int sparseSteps[1] = {config.extrusionWidth}; //generateConcentricInfill(part->skinOutline, fillPolygons, sparseSteps, 1); generateLineInfill(part->skinOutline, fillPolygons, config.extrusionWidth, config.extrusionWidth, config.infillOverlap, (part->bridgeAngle > -1) ? part->bridgeAngle : fillAngle); //int sparseSteps[2] = {config.extrusionWidth*5, config.extrusionWidth * 0.8}; //generateConcentricInfill(part->sparseOutline, fillPolygons, sparseSteps, 2); if (config.sparseInfillLineDistance > 0) { if (config.sparseInfillLineDistance > config.extrusionWidth * 4) { generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance * 2, config.infillOverlap, 45); generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance * 2, config.infillOverlap, 45 + 90); } else { generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance, config.infillOverlap, fillAngle); } } gcodeLayer.addPolygonsByOptimizer(fillPolygons, &fillConfig); //After a layer part, make sure the nozzle is inside the comb boundary, so we do not retract on the perimeter. if (!config.spiralizeMode || int(layerNr) < config.downSkinCount) gcodeLayer.moveInsideCombBoundary(config.extrusionWidth * 2); } gcodeLayer.setCombBoundary(NULL); } if (storage.support.generated) { if (config.supportExtruder > -1) gcodeLayer.setExtruder(config.supportExtruder); SupportPolyGenerator supportGenerator(storage.support, z); for(unsigned int volumeCnt = 0; volumeCnt < storage.volumes.size(); volumeCnt++) { SliceLayer* layer = &storage.volumes[volumeIdx].layers[layerNr]; Polygons polys; for(unsigned int n=0; n<layer->parts.size(); n++) supportGenerator.polygons = supportGenerator.polygons.difference(layer->parts[n].outline.offset(config.supportXYDistance)); } //Contract and expand the suppory polygons so small sections are removed and the final polygon is smoothed a bit. supportGenerator.polygons = supportGenerator.polygons.offset(-1000); supportGenerator.polygons = supportGenerator.polygons.offset(1000); Polygons supportLines; if (config.supportLineDistance > 0) { if (config.supportLineDistance > config.extrusionWidth * 4) { generateLineInfill(supportGenerator.polygons, supportLines, config.extrusionWidth, config.supportLineDistance*2, config.infillOverlap, 0); generateLineInfill(supportGenerator.polygons, supportLines, config.extrusionWidth, config.supportLineDistance*2, config.infillOverlap, 90); } else { generateLineInfill(supportGenerator.polygons, supportLines, config.extrusionWidth, config.supportLineDistance, config.infillOverlap, (layerNr & 1) ? 0 : 90); } } gcodeLayer.addPolygonsByOptimizer(supportGenerator.polygons, &supportConfig); gcodeLayer.addPolygonsByOptimizer(supportLines, &supportConfig); } //Finish the layer by applying speed corrections for minimal layer times and slowdown for the initial layer. if (int(layerNr) < config.initialSpeedupLayers) { int n = config.initialSpeedupLayers; int layer0Factor = config.initialLayerSpeed * 100 / config.printSpeed; gcodeLayer.setExtrudeSpeedFactor((layer0Factor * (n - layerNr) + 100 * (layerNr)) / n); if (layerNr == 0)//On the first layer, also slow down the travel gcodeLayer.setTravelSpeedFactor(layer0Factor); } gcodeLayer.forceMinimalLayerTime(config.minimalLayerTime, config.minimalFeedrate); if (layerNr == 0) gcode.setExtrusion(config.initialLayerThickness, config.filamentDiameter, config.filamentFlow); else gcode.setExtrusion(config.layerThickness, config.filamentDiameter, config.filamentFlow); int fanSpeed = config.fanSpeedMin; if (gcodeLayer.getExtrudeSpeedFactor() <= 50) { fanSpeed = config.fanSpeedMax; } else { int n = gcodeLayer.getExtrudeSpeedFactor() - 50; fanSpeed = config.fanSpeedMin * n / 50 + config.fanSpeedMax * (50 - n) / 50; } if (int(layerNr) < config.fanFullOnLayerNr) { //Slow down the fan on the layers below the [fanFullOnLayerNr], where layer 0 is speed 0. fanSpeed = fanSpeed * layerNr / config.fanFullOnLayerNr; } gcode.addFanCommand(fanSpeed); gcodeLayer.writeGCode(config.coolHeadLift > 0, int(layerNr) > 0 ? config.layerThickness : config.initialLayerThickness); } /* support debug for(int32_t y=0; y<storage.support.gridHeight; y++) { for(int32_t x=0; x<storage.support.gridWidth; x++) { unsigned int n = x+y*storage.support.gridWidth; if (storage.support.grid[n].size() < 1) continue; int32_t z = storage.support.grid[n][0].z; gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, 0), 0); gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, z), z); gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, 0), 0); } } //*/ log("Wrote layers in %5.2fs.\n", timeElapsed(t)); gcode.tellFileSize(); gcode.addFanCommand(0); logProgress("process", 1, 1); log("Total time elapsed %5.2fs.\n", timeElapsed(t,true)); //Store the object height for when we are printing multiple objects, as we need to clear every one of them when moving to the next position. maxObjectHeight = std::max(maxObjectHeight, storage.modelSize.z); }
void Infill::generateTriangleInfill(Polygons& result) { generateLineInfill(result, line_distance, fill_angle, 0); generateLineInfill(result, line_distance, fill_angle + 60, 0); generateLineInfill(result, line_distance, fill_angle + 120, 0); }
void Infill::generateGridInfill(Polygons& result) { generateLineInfill(result, line_distance, fill_angle, 0); generateLineInfill(result, line_distance, fill_angle + 90, 0); }
void processFile(const char* input_filename, Config& config, GCodeExport& gcode, bool firstFile) { for(unsigned int n=1; n<16;n++) gcode.setExtruderOffset(n, config.extruderOffset[n]); double t = getTime(); log("Loading %s from disk...\n", input_filename); SimpleModel* m = loadModel(input_filename, config.matrix); if (!m) { log("Failed to load model: %s\n", input_filename); return; } log("Loaded from disk in %5.3fs\n", timeElapsed(t)); log("Analyzing and optimizing model...\n"); OptimizedModel* om = new OptimizedModel(m, Point3(config.objectPosition.X, config.objectPosition.Y, -config.objectSink)); for(unsigned int v = 0; v < m->volumes.size(); v++) { log(" Face counts: %i -> %i %0.1f%%\n", (int)m->volumes[v].faces.size(), (int)om->volumes[v].faces.size(), float(om->volumes[v].faces.size()) / float(m->volumes[v].faces.size()) * 100); log(" Vertex counts: %i -> %i %0.1f%%\n", (int)m->volumes[v].faces.size() * 3, (int)om->volumes[v].points.size(), float(om->volumes[v].points.size()) / float(m->volumes[v].faces.size() * 3) * 100); } delete m; log("Optimize model %5.3fs \n", timeElapsed(t)); //om->saveDebugSTL("c:\\models\\output.stl"); log("Slicing model...\n"); vector<Slicer*> slicerList; for(unsigned int volumeIdx=0; volumeIdx < om->volumes.size(); volumeIdx++) { slicerList.push_back(new Slicer(&om->volumes[volumeIdx], config.initialLayerThickness / 2, config.layerThickness, config.fixHorrible & FIX_HORRIBLE_KEEP_NONE_CLOSED, config.fixHorrible & FIX_HORRIBLE_EXTENSIVE_STITCHING)); //slicerList[volumeIdx]->dumpSegments("C:\\models\\output.html"); } log("Sliced model in %5.3fs\n", timeElapsed(t)); SliceDataStorage storage; if (config.supportAngle > -1) { fprintf(stdout,"Generating support map...\n"); generateSupportGrid(storage.support, om, config.initialLayerThickness / 2, config.layerThickness); } storage.modelSize = om->modelSize; storage.modelMin = om->vMin; storage.modelMax = om->vMax; delete om; log("Generating layer parts...\n"); for(unsigned int volumeIdx=0; volumeIdx < slicerList.size(); volumeIdx++) { storage.volumes.push_back(SliceVolumeStorage()); createLayerParts(storage.volumes[volumeIdx], slicerList[volumeIdx], config.fixHorrible & (FIX_HORRIBLE_UNION_ALL_TYPE_A | FIX_HORRIBLE_UNION_ALL_TYPE_B)); delete slicerList[volumeIdx]; } //carveMultipleVolumes(storage.volumes); generateMultipleVolumesOverlap(storage.volumes, config.multiVolumeOverlap); log("Generated layer parts in %5.3fs\n", timeElapsed(t)); //dumpLayerparts(storage, "c:/models/output.html"); const unsigned int totalLayers = storage.volumes[0].layers.size(); for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { generateInsets(&storage.volumes[volumeIdx].layers[layerNr], config.extrusionWidth, config.insetCount); } logProgress("inset",layerNr+1,totalLayers); } log("Generated inset in %5.3fs\n", timeElapsed(t)); //dumpLayerparts(storage, "c:/models/output.html"); for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { generateSkins(layerNr, storage.volumes[volumeIdx], config.extrusionWidth, config.downSkinCount, config.upSkinCount, config.infillOverlap); generateSparse(layerNr, storage.volumes[volumeIdx], config.extrusionWidth, config.downSkinCount, config.upSkinCount); } logProgress("skin",layerNr+1,totalLayers); } log("Generated up/down skin in %5.3fs\n", timeElapsed(t)); generateSkirt(storage, config.skirtDistance, config.extrusionWidth, config.skirtLineCount); generateRaft(storage, config.raftMargin); log("Generated skirt and raft in %5.3fs\n", timeElapsed(t)); for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int partNr=0; partNr<storage.volumes[volumeIdx].layers[layerNr].parts.size(); partNr++) { if (layerNr > 0) storage.volumes[volumeIdx].layers[layerNr].parts[partNr].bridgeAngle = bridgeAngle(&storage.volumes[volumeIdx].layers[layerNr].parts[partNr], &storage.volumes[volumeIdx].layers[layerNr-1]); else storage.volumes[volumeIdx].layers[layerNr].parts[partNr].bridgeAngle = -1; } } } log("Stored volumes in %5.3fs\n", timeElapsed(t)); gcode.setRetractionSettings(config.retractionAmount, config.retractionSpeed, config.retractionAmountExtruderSwitch); if (firstFile) { gcode.addCode(config.startCode); }else{ gcode.resetExtrusionValue(); gcode.addRetraction(); gcode.setZ(maxObjectHeight + 5000); gcode.addMove(config.objectPosition, config.moveSpeed, 0); } gcode.addComment("total_layers=%d",totalLayers); log("Added general info to gcode in %5.3fs\n", timeElapsed(t)); GCodePathConfig skirtConfig(config.printSpeed, config.extrusionWidth, "SKIRT"); GCodePathConfig inset0Config(config.printSpeed, config.extrusionWidth, "WALL-OUTER"); GCodePathConfig inset1Config(config.printSpeed, config.extrusionWidth, "WALL-INNER"); GCodePathConfig fillConfig(config.infillSpeed, config.extrusionWidth, "FILL"); GCodePathConfig supportConfig(config.printSpeed, config.supportLineWidth, "SUPPORT"); if (config.raftBaseThickness > 0 && config.raftInterfaceThickness > 0) { GCodePathConfig raftBaseConfig(config.initialLayerSpeed, config.raftBaseLinewidth, "SUPPORT"); GCodePathConfig raftInterfaceConfig(config.initialLayerSpeed, config.raftInterfaceLinewidth, "SUPPORT"); { gcode.addComment("LAYER:-2"); gcode.addComment("RAFT"); GCodePlanner gcodeLayer(gcode, config.moveSpeed); gcode.setZ(config.raftBaseThickness); gcode.setExtrusion(config.raftBaseThickness, config.filamentDiameter, config.filamentFlow); gcodeLayer.addPolygonsByOptimizer(storage.raftOutline, &raftBaseConfig); Polygons raftLines; generateLineInfill(storage.raftOutline, raftLines, config.raftBaseLinewidth, config.raftLineSpacing, config.infillOverlap, 0); gcodeLayer.addPolygonsByOptimizer(raftLines, &raftBaseConfig); gcodeLayer.writeGCode(false); } { gcode.addComment("LAYER:-1"); gcode.addComment("RAFT"); GCodePlanner gcodeLayer(gcode, config.moveSpeed); gcode.setZ(config.raftBaseThickness + config.raftInterfaceThickness); gcode.setExtrusion(config.raftInterfaceThickness, config.filamentDiameter, config.filamentFlow); Polygons raftLines; generateLineInfill(storage.raftOutline, raftLines, config.raftInterfaceLinewidth, config.raftLineSpacing, config.infillOverlap, 90); gcodeLayer.addPolygonsByOptimizer(raftLines, &raftInterfaceConfig); gcodeLayer.writeGCode(false); } } int volumeIdx = 0; for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { logProgress("export", layerNr+1, totalLayers); log("Handling layer %u out of %u \n", layerNr+1, totalLayers); GCodePlanner gcodeLayer(gcode, config.moveSpeed); gcode.addComment("LAYER:%d", layerNr); int32_t z = config.initialLayerThickness + layerNr * config.layerThickness; z += config.raftBaseThickness + config.raftInterfaceThickness; gcode.setZ(z); //if (layerNr == 0) // gcodeLayer.addPolygonsByOptimizer(storage.skirt, &skirtConfig); //log("Mark1 in %5.3fs\n", timeElapsed(t)); for(unsigned int volumeCnt = 0; volumeCnt < storage.volumes.size(); volumeCnt++) { log(" Going through volume %u out of %u \n", volumeCnt+1, storage.volumes.size()); if (volumeCnt > 0) volumeIdx = (volumeIdx + 1) % storage.volumes.size(); SliceLayer* layer = &storage.volumes[volumeIdx].layers[layerNr]; gcodeLayer.setExtruder(volumeIdx); PathOptimizer partOrderOptimizer(gcode.getPositionXY()); for(unsigned int partNr=0; partNr<layer->parts.size(); partNr++) { partOrderOptimizer.addPolygon(layer->parts[partNr].insets[0][0]); } log("partOrderOptimizer polygons %u \n", partOrderOptimizer.polygons.size()); log("partOrderOptimizer polyorder %u \n", partOrderOptimizer.polyOrder.size()); partOrderOptimizer.optimize(); log("POST OPTIM partOrderOptimizer polygons %u \n", partOrderOptimizer.polygons.size()); log("POST OPTIM partOrderOptimizer polyorder %u \n", partOrderOptimizer.polyOrder.size()); //log("POST OPTIM polyorder at 0 %u \n", partOrderOptimizer.polyOrder[0]); log("toto\n"); for(unsigned int partCounter=0; partCounter<partOrderOptimizer.polyOrder.size(); partCounter++) { //log(" Going through part %u out of %u \n", partCounter+1, partOrderOptimizer.polyOrder.size()); SliceLayerPart* part = &layer->parts[partOrderOptimizer.polyOrder[partCounter]]; log("order index %u \n", partOrderOptimizer.polyOrder[partCounter]); try { if(part->skinOutline.size()>0) { if(part->skinOutline[0].size()>0) { Point p0 = (part->skinOutline)[0][0]; log("bla %f pof\n",p0.X); } } } catch (int e) { log("An exception occurred. Exception Nr.%i \n",e); } /*gcodeLayer.setCombBoundary(&part->combBoundery); gcodeLayer.forceRetract(); if (config.insetCount > 0) { for(int insetNr=part->insets.size()-1; insetNr>-1; insetNr--) { if (insetNr == 0) gcodeLayer.addPolygonsByOptimizer(part->insets[insetNr], &inset0Config); else gcodeLayer.addPolygonsByOptimizer(part->insets[insetNr], &inset1Config); } }*/ Polygons fillPolygons; int fillAngle = 45; if (layerNr & 1) fillAngle += 90; //int sparseSteps[1] = {config.extrusionWidth}; //generateConcentricInfill(part->skinOutline, fillPolygons, sparseSteps, 1); log("Passing skinOutline of size %u to generator\n", (part->skinOutline).size()); generateLineInfill(part->skinOutline, fillPolygons, config.extrusionWidth, config.extrusionWidth, config.infillOverlap, (part->bridgeAngle > -1) ? part->bridgeAngle : fillAngle); //int sparseSteps[2] = {config.extrusionWidth*5, config.extrusionWidth * 0.8}; //generateConcentricInfill(part->sparseOutline, fillPolygons, sparseSteps, 2); //log("Mark1-2: after infillLineGen\n"); if (config.sparseInfillLineDistance > 0) { if (config.sparseInfillLineDistance > config.extrusionWidth * 4) { generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance * 2, config.infillOverlap, 45); generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance * 2, config.infillOverlap, 45 + 90); } else { generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance, config.infillOverlap, fillAngle); } } //log("Mark1-3: after before adding polygons\n"); gcodeLayer.addPolygonsByOptimizer(fillPolygons, &fillConfig); } gcodeLayer.setCombBoundary(NULL); } //log("Mark2: before supportAngle\n"); if (config.supportAngle > -1) { SupportPolyGenerator supportGenerator(storage.support, z, config.supportAngle, config.supportEverywhere > 0, true); gcodeLayer.addPolygonsByOptimizer(supportGenerator.polygons, &supportConfig); if (layerNr == 0) { SupportPolyGenerator supportGenerator2(storage.support, z, config.supportAngle, config.supportEverywhere > 0, false); gcodeLayer.addPolygonsByOptimizer(supportGenerator2.polygons, &supportConfig); } } //log("Mark2: before speedup\n"); //Finish the layer by applying speed corrections for minimal layer times and slowdown for the initial layer. if (int(layerNr) < config.initialSpeedupLayers) { int n = config.initialSpeedupLayers; int layer0Factor = config.initialLayerSpeed * 100 / config.printSpeed; gcodeLayer.setSpeedFactor((layer0Factor * (n - layerNr) + 100 * (layerNr)) / n); } gcodeLayer.forceMinimalLayerTime(config.minimalLayerTime, config.minimalFeedrate); if (layerNr == 0) gcode.setExtrusion(config.initialLayerThickness, config.filamentDiameter, config.filamentFlow); else gcode.setExtrusion(config.layerThickness, config.filamentDiameter, config.filamentFlow); //log("Mark3: before fan on\n"); if (int(layerNr) >= config.fanOnLayerNr) { int speed = config.fanSpeedMin; if (gcodeLayer.getSpeedFactor() <= 50) { speed = config.fanSpeedMax; }else{ int n = gcodeLayer.getSpeedFactor() - 50; speed = config.fanSpeedMin * n / 50 + config.fanSpeedMax * (50 - n) / 50; } gcode.addFanCommand(speed); }else{ gcode.addFanCommand(0); } //log("Finished layer in %5.3fs\n", timeElapsed(t)); gcodeLayer.writeGCode(config.coolHeadLift > 0); //log("Finished writing layer in %5.3fs\n", timeElapsed(t)); } /* support debug for(int32_t y=0; y<storage.support.gridHeight; y++) { for(int32_t x=0; x<storage.support.gridWidth; x++) { unsigned int n = x+y*storage.support.gridWidth; if (storage.support.grid[n].size() < 1) continue; int32_t z = storage.support.grid[n][0].z; gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, 0), 0); gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, z), z); gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, 0), 0); } } //*/ log("Wrote layers in %5.2fs.\n", timeElapsed(t)); gcode.tellFileSize(); gcode.addFanCommand(0); logProgress("process", 1, 1); log("Total time elapsed %5.2fs.\n", timeElapsed(t,true)); //Store the object height for when we are printing multiple objects, as we need to clear every one of them when moving to the next position. maxObjectHeight = std::max(maxObjectHeight, storage.modelSize.z); }