Comparar commits

...

14 Commits

Autor SHA1 Mensagem Data
Tim Kuipers 5a48d86bd7 refactor: handle layer plans outside of buffer (CURA-3339)
allocation is handled outside buffer
writing gcode is handled outside buffer
buffer processing is handled separately from adding to the buffer
2017-02-17 11:44:53 +01:00
Tim Kuipers 79cb7850e9 refactor: simplified processLayer calls (CURA-3339) 2017-02-17 11:44:53 +01:00
Tim Kuipers 9e4a786f3d refactor: clean up GCodePathConfig (CURA-3339)
have one constructor rather than a constructor, init, setLayerHeight and smoothSpeed
2017-02-17 11:44:53 +01:00
Tim Kuipers fe49157ca8 refactor: PathConfigs ==> PathConfigStorage (CURA-3339)
because the structure follows the structure of SliceDataStorage.
2017-02-17 11:44:53 +01:00
Tim Kuipers 889c2e4b13 fix: GCodePathConfig extrusion_per_mm was calculated too early (CURA-3339)
this resulted in all extrusion lines being replaced by travel paths.
This problem was introduced a couple of commits ago.
The underlying problem, that there needs to be a definite order between init and setLayerHeight, will be solved in a commit soon to come.
2017-02-17 11:44:53 +01:00
Tim Kuipers ca3848f79a fix: const correctness (except some const_cast instances!) (CURA-3339) 2017-02-17 11:44:53 +01:00
Tim Kuipers 77f1aebef9 fix: bundle state from gcodePlanner into class (CURA-3339)
this helps in making GCodePlanner multithreaded
The state of the gcodePlanner which is carried over to the next layer is bundled in a nice package, which is to be dealt with soon in a coming commit
2017-02-17 11:44:53 +01:00
Tim Kuipers 046c34b31b lil gitignore 2017-02-17 11:44:53 +01:00
Tim Kuipers 066a0d7318 fix: move writeGcode configs out of sliceDataStorage (CURA-3339)
This contributes to making sliceDataStorage const after FffPolygonGenerator has been called
2017-02-17 11:44:53 +01:00
Tim Kuipers 989317a293 fix: const correctness in combing (CURA-3339) 2017-02-17 11:43:45 +01:00
Tim Kuipers cf3d18eb75 fix: const correctness in prime tower (CURA-3339) 2017-02-17 11:43:45 +01:00
Tim Kuipers c9096424c1 fix: lil const correctnes MergeInfillLines (CURA-3339) 2017-02-17 11:43:45 +01:00
Tim Kuipers d489143fcb fix: const correctness in polygon (CURA-3339) 2017-02-17 11:43:45 +01:00
Tim Kuipers 8ac3b49549 refactor: introduced ConstPolygonRef (CURA-3339)
Adapted from 9712301aa8
From @Johan3DV 'Improve const correctness and remove const_cast'
2017-02-17 11:43:45 +01:00
44 arquivos alterados com 1098 adições e 979 exclusões
+6
Ver Arquivo
@@ -7,8 +7,14 @@
NUL NUL
*.gcode *.gcode
## Directories used for other stuff
Trash/*
output/*
callgrind/*
## Building result. ## Building result.
build/* build/*
debug_build/*
*.pyc *.pyc
*.exe *.exe
*.a *.a
+1
Ver Arquivo
@@ -106,6 +106,7 @@ set(engine_SRCS # Except main.cpp.
src/progress/Progress.cpp src/progress/Progress.cpp
src/progress/ProgressStageEstimator.cpp src/progress/ProgressStageEstimator.cpp
src/settings/PathConfigStorage.cpp
src/settings/SettingConfig.cpp src/settings/SettingConfig.cpp
src/settings/SettingContainer.cpp src/settings/SettingContainer.cpp
src/settings/SettingRegistry.cpp src/settings/SettingRegistry.cpp
+181 -212
Ver Arquivo
@@ -25,11 +25,11 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep
// set the initial extruder of this meshgroup // set the initial extruder of this meshgroup
if (FffProcessor::getInstance()->getMeshgroupNr() == 0) if (FffProcessor::getInstance()->getMeshgroupNr() == 0)
{ // first meshgroup { // first meshgroup
current_extruder_planned = getStartExtruder(storage); planner_state.current_extruder = getStartExtruder(storage);
} }
else else
{ {
current_extruder_planned = gcode.getExtruderNr(); planner_state.current_extruder = gcode.getExtruderNr();
} }
if (CommandSocket::isInstantiated()) if (CommandSocket::isInstantiated())
@@ -42,12 +42,9 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep
setConfigCoasting(storage); setConfigCoasting(storage);
setConfigRetraction(storage); setConfigRetraction(storage);
initConfigs(storage);
for (int extruder = 0; extruder < storage.meshgroup->getExtruderCount(); extruder++) for (int extruder = 0; extruder < storage.meshgroup->getExtruderCount(); extruder++)
{ //Skirt and brim. { //Skirt and brim.
storage.skirt_brim_config[extruder].setLayerHeight(getSettingInMicrons("layer_height_0"));
skirt_brim_is_processed[extruder] = false; skirt_brim_is_processed[extruder] = false;
} }
@@ -71,17 +68,6 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep
gcode.writeLayerCountComment(total_layers); gcode.writeLayerCountComment(total_layers);
bool has_raft = getSettingAsPlatformAdhesion("adhesion_type") == EPlatformAdhesion::RAFT;
if (has_raft)
{
processRaft(storage, total_layers);
// process filler layers to fill the airgap with helper object (support etc) so that they stick better to the raft.
for (int layer_nr = -Raft::getFillerLayerCount(storage); layer_nr < 0; layer_nr++)
{
processLayer(storage, layer_nr, total_layers);
}
}
{ // calculate the mesh order for each extruder { // calculate the mesh order for each extruder
int extruder_count = storage.meshgroup->getExtruderCount(); int extruder_count = storage.meshgroup->getExtruderCount();
mesh_order_per_extruder.reserve(extruder_count); mesh_order_per_extruder.reserve(extruder_count);
@@ -91,9 +77,26 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep
} }
} }
for(unsigned int layer_nr=0; layer_nr<total_layers; layer_nr++) int process_layer_starting_layer_nr = 0;
bool has_raft = getSettingAsPlatformAdhesion("adhesion_type") == EPlatformAdhesion::RAFT;
if (has_raft)
{ {
processLayer(storage, layer_nr, total_layers); processRaft(storage, total_layers);
// process filler layers to fill the airgap with helper object (support etc) so that they stick better to the raft.
process_layer_starting_layer_nr = -Raft::getFillerLayerCount(storage);
}
for (unsigned int layer_nr = process_layer_starting_layer_nr; layer_nr < total_layers; layer_nr++)
{
GCodePlanner& gcode_layer = processLayer(storage, layer_nr, total_layers);
layer_plan_buffer.push(gcode_layer);
planner_state = gcode_layer.getPlanningState();
GCodePlanner* to_be_written = layer_plan_buffer.processBuffer();
if (to_be_written)
{
to_be_written->writeGCode(gcode);
delete to_be_written;
}
} }
Progress::messageProgressStage(Progress::Stage::FINISH, &time_keeper); Progress::messageProgressStage(Progress::Stage::FINISH, &time_keeper);
@@ -172,49 +175,7 @@ void FffGcodeWriter::setConfigRetraction(SliceDataStorage& storage)
} }
} }
void FffGcodeWriter::initConfigs(SliceDataStorage& storage) unsigned int FffGcodeWriter::getStartExtruder(const SliceDataStorage& storage)
{
for (int extruder = 0; extruder < storage.meshgroup->getExtruderCount(); extruder++)
{ //Skirt and brim.
SettingsBase* train = storage.meshgroup->getExtruderTrain(extruder);
storage.skirt_brim_config[extruder].init(train->getSettingInMillimetersPerSecond("skirt_brim_speed"), train->getSettingInMillimetersPerSecond("acceleration_skirt_brim"), train->getSettingInMillimetersPerSecond("jerk_skirt_brim"), train->getSettingInMicrons("skirt_brim_line_width"), train->getSettingInPercentage("material_flow"));
storage.travel_config_per_extruder[extruder].init(train->getSettingInMillimetersPerSecond("speed_travel"), train->getSettingInMillimetersPerSecond("acceleration_travel"), train->getSettingInMillimetersPerSecond("jerk_travel"), 0, 0);
}
{ // support
SettingsBase* infill_train = storage.meshgroup->getExtruderTrain(getSettingAsIndex("support_infill_extruder_nr"));
storage.support_config.init(infill_train->getSettingInMillimetersPerSecond("speed_support_infill"), infill_train->getSettingInMillimetersPerSecond("acceleration_support_infill"), infill_train->getSettingInMillimetersPerSecond("jerk_support_infill"), infill_train->getSettingInMicrons("support_line_width"), infill_train->getSettingInPercentage("material_flow"));
SettingsBase* interface_train = storage.meshgroup->getExtruderTrain(getSettingAsIndex("support_interface_extruder_nr"));
storage.support_skin_config.init(interface_train->getSettingInMillimetersPerSecond("speed_support_interface"), interface_train->getSettingInMillimetersPerSecond("acceleration_support_interface"), interface_train->getSettingInMillimetersPerSecond("jerk_support_interface"), interface_train->getSettingInMicrons("support_interface_line_width"), interface_train->getSettingInPercentage("material_flow"));
}
for (SliceMeshStorage& mesh : storage.meshes)
{
mesh.inset0_config.init(mesh.getSettingInMillimetersPerSecond("speed_wall_0"), mesh.getSettingInMillimetersPerSecond("acceleration_wall_0"), mesh.getSettingInMillimetersPerSecond("jerk_wall_0"), mesh.getSettingInMicrons("wall_line_width_0"), mesh.getSettingInPercentage("material_flow"));
mesh.insetX_config.init(mesh.getSettingInMillimetersPerSecond("speed_wall_x"), mesh.getSettingInMillimetersPerSecond("acceleration_wall_x"), mesh.getSettingInMillimetersPerSecond("jerk_wall_x"), mesh.getSettingInMicrons("wall_line_width_x"), mesh.getSettingInPercentage("material_flow"));
mesh.skin_config.init(mesh.getSettingInMillimetersPerSecond("speed_topbottom"), mesh.getSettingInMillimetersPerSecond("acceleration_topbottom"), mesh.getSettingInMillimetersPerSecond("jerk_topbottom"), mesh.getSettingInMicrons("skin_line_width"), mesh.getSettingInPercentage("material_flow"));
// The perimeter gap config follows the skin config, but has a different line width:
// wall_line_width_x divided by two because the gaps are between 0 and 1 times the wall line width
const int perimeter_gaps_line_width = mesh.getSettingInMicrons("wall_line_width_x") / 2;
double perimeter_gaps_speed = mesh.getSettingInMillimetersPerSecond("speed_topbottom");
if (mesh.getSettingBoolean("speed_equalize_flow_enabled"))
{
perimeter_gaps_speed = perimeter_gaps_speed * mesh.getSettingInMicrons("skin_line_width") / perimeter_gaps_line_width;
}
mesh.perimeter_gap_config.init(perimeter_gaps_speed, mesh.getSettingInMillimetersPerSecond("acceleration_topbottom"), mesh.getSettingInMillimetersPerSecond("jerk_topbottom"), perimeter_gaps_line_width, mesh.getSettingInPercentage("material_flow"));
for (unsigned int idx = 0; idx < MAX_INFILL_COMBINE; idx++)
{
mesh.infill_config[idx].init(mesh.getSettingInMillimetersPerSecond("speed_infill"), mesh.getSettingInMillimetersPerSecond("acceleration_infill"), mesh.getSettingInMillimetersPerSecond("jerk_infill"), mesh.getSettingInMicrons("infill_line_width") * (idx + 1), mesh.getSettingInPercentage("material_flow"));
}
}
storage.primeTower.initConfigs(storage.meshgroup);
}
unsigned int FffGcodeWriter::getStartExtruder(SliceDataStorage& storage)
{ {
int start_extruder_nr = getSettingAsIndex("adhesion_extruder_nr"); int start_extruder_nr = getSettingAsIndex("adhesion_extruder_nr");
if (getSettingAsPlatformAdhesion("adhesion_type") == EPlatformAdhesion::NONE) if (getSettingAsPlatformAdhesion("adhesion_type") == EPlatformAdhesion::NONE)
@@ -233,7 +194,7 @@ unsigned int FffGcodeWriter::getStartExtruder(SliceDataStorage& storage)
return start_extruder_nr; return start_extruder_nr;
} }
void FffGcodeWriter::processStartingCode(SliceDataStorage& storage, const unsigned int start_extruder_nr) void FffGcodeWriter::processStartingCode(const SliceDataStorage& storage, const unsigned int start_extruder_nr)
{ {
if (!CommandSocket::isInstantiated()) if (!CommandSocket::isInstantiated())
{ {
@@ -296,12 +257,12 @@ void FffGcodeWriter::processStartingCode(SliceDataStorage& storage, const unsign
gcode.writeTemperatureCommand(start_extruder_nr, print_temp_here, wait); gcode.writeTemperatureCommand(start_extruder_nr, print_temp_here, wait);
gcode.writePrimeTrain(train.getSettingInMillimetersPerSecond("speed_travel")); gcode.writePrimeTrain(train.getSettingInMillimetersPerSecond("speed_travel"));
extruder_prime_is_planned[start_extruder_nr] = true; extruder_prime_is_planned[start_extruder_nr] = true;
RetractionConfig& retraction_config = storage.retraction_config_per_extruder[start_extruder_nr]; const RetractionConfig& retraction_config = storage.retraction_config_per_extruder[start_extruder_nr];
gcode.writeRetraction(retraction_config); gcode.writeRetraction(retraction_config);
} }
} }
void FffGcodeWriter::processNextMeshGroupCode(SliceDataStorage& storage) void FffGcodeWriter::processNextMeshGroupCode(const SliceDataStorage& storage)
{ {
gcode.writeFanCommand(0); gcode.writeFanCommand(0);
@@ -313,11 +274,11 @@ void FffGcodeWriter::processNextMeshGroupCode(SliceDataStorage& storage)
gcode.setZ(max_object_height + 5000); gcode.setZ(max_object_height + 5000);
gcode.writeMove(gcode.getPositionXY(), storage.meshgroup->getExtruderTrain(gcode.getExtruderNr())->getSettingInMillimetersPerSecond("speed_travel"), 0); gcode.writeMove(gcode.getPositionXY(), storage.meshgroup->getExtruderTrain(gcode.getExtruderNr())->getSettingInMillimetersPerSecond("speed_travel"), 0);
last_position_planned = Point(storage.model_min.x, storage.model_min.y); planner_state.last_position = Point(storage.model_min.x, storage.model_min.y);
gcode.writeMove(last_position_planned, storage.meshgroup->getExtruderTrain(gcode.getExtruderNr())->getSettingInMillimetersPerSecond("speed_travel"), 0); gcode.writeMove(planner_state.last_position, storage.meshgroup->getExtruderTrain(gcode.getExtruderNr())->getSettingInMillimetersPerSecond("speed_travel"), 0);
} }
void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_layers) void FffGcodeWriter::processRaft(const SliceDataStorage& storage, unsigned int total_layers)
{ {
int extruder_nr = getSettingAsIndex("adhesion_extruder_nr"); int extruder_nr = getSettingAsIndex("adhesion_extruder_nr");
ExtruderTrain* train = storage.meshgroup->getExtruderTrain(extruder_nr); ExtruderTrain* train = storage.meshgroup->getExtruderTrain(extruder_nr);
@@ -326,16 +287,7 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
int z = 0; int z = 0;
{ // set configs
storage.raft_base_config.init(train->getSettingInMillimetersPerSecond("raft_base_speed"), train->getSettingInMillimetersPerSecond("raft_base_acceleration"), train->getSettingInMillimetersPerSecond("raft_base_jerk"), train->getSettingInMicrons("raft_base_line_width"), train->getSettingInPercentage("material_flow"));
storage.raft_base_config.setLayerHeight(train->getSettingInMicrons("raft_base_thickness"));
storage.raft_interface_config.init(train->getSettingInMillimetersPerSecond("raft_interface_speed"), train->getSettingInMillimetersPerSecond("raft_interface_acceleration"), train->getSettingInMillimetersPerSecond("raft_interface_jerk"), train->getSettingInMicrons("raft_interface_line_width"), train->getSettingInPercentage("material_flow"));
storage.raft_interface_config.setLayerHeight(train->getSettingInMicrons("raft_interface_thickness"));
storage.raft_surface_config.init(train->getSettingInMillimetersPerSecond("raft_surface_speed"), train->getSettingInMillimetersPerSecond("raft_surface_acceleration"), train->getSettingInMillimetersPerSecond("raft_surface_jerk"), train->getSettingInMicrons("raft_surface_line_width"), train->getSettingInPercentage("material_flow"));
storage.raft_surface_config.setLayerHeight(train->getSettingInMicrons("raft_surface_thickness"));
}
const int initial_raft_layer_nr = -Raft::getTotalExtraLayers(storage); const int initial_raft_layer_nr = -Raft::getTotalExtraLayers(storage);
@@ -351,7 +303,7 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
int layer_height = train->getSettingInMicrons("raft_base_thickness"); int layer_height = train->getSettingInMicrons("raft_base_thickness");
z += layer_height; z += layer_height;
int64_t comb_offset = train->getSettingInMicrons("raft_base_line_spacing"); int64_t comb_offset = train->getSettingInMicrons("raft_base_line_spacing");
GCodePlanner& gcode_layer = layer_plan_buffer.emplace_back(storage, layer_nr, z, layer_height, last_position_planned, current_extruder_planned, is_inside_mesh_layer_part, fan_speed_layer_time_settings_per_extruder, combing_mode, comb_offset, train->getSettingBoolean("travel_avoid_other_parts"), train->getSettingInMicrons("travel_avoid_distance")); GCodePlanner& gcode_layer = *new GCodePlanner(storage, layer_nr, z, layer_height, planner_state, fan_speed_layer_time_settings_per_extruder, combing_mode, comb_offset, train->getSettingBoolean("travel_avoid_other_parts"), train->getSettingInMicrons("travel_avoid_distance"));
gcode_layer.setIsInside(true); gcode_layer.setIsInside(true);
gcode_layer.setExtruder(extruder_nr); gcode_layer.setExtruder(extruder_nr);
@@ -361,26 +313,31 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
CommandSocket::getInstance()->sendOptimizedLayerInfo(layer_nr, z, layer_height); CommandSocket::getInstance()->sendOptimizedLayerInfo(layer_nr, z, layer_height);
} }
Polygons wall = storage.raftOutline.offset(-storage.raft_base_config.getLineWidth() / 2); Polygons wall = storage.raftOutline.offset(-gcode_layer.configs_storage.raft_base_config.getLineWidth() / 2);
gcode_layer.addPolygonsByOptimizer(wall, &storage.raft_base_config); gcode_layer.addPolygonsByOptimizer(wall, &gcode_layer.configs_storage.raft_base_config);
Polygons raftLines; Polygons raftLines;
double fill_angle = 0; double fill_angle = 0;
Infill infill_comp(EFillMethod::LINES, wall, offset_from_poly_outline, storage.raft_base_config.getLineWidth(), train->getSettingInMicrons("raft_base_line_spacing"), fill_overlap, fill_angle, z, extra_infill_shift); Infill infill_comp(EFillMethod::LINES, wall, offset_from_poly_outline, gcode_layer.configs_storage.raft_base_config.getLineWidth(), train->getSettingInMicrons("raft_base_line_spacing"), fill_overlap, fill_angle, z, extra_infill_shift);
infill_comp.generate(raft_polygons, raftLines); infill_comp.generate(raft_polygons, raftLines);
gcode_layer.addLinesByOptimizer(raftLines, &storage.raft_base_config, SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(raftLines, &gcode_layer.configs_storage.raft_base_config, SpaceFillType::Lines);
if (getExtrudersNeedPrimeDuringFirstLayer()) if (getExtrudersNeedPrimeDuringFirstLayer())
{ {
ensureAllExtrudersArePrimed(storage, gcode_layer, layer_nr); ensureAllExtrudersArePrimed(storage, gcode_layer, layer_nr);
} }
last_position_planned = gcode_layer.getLastPosition();
current_extruder_planned = gcode_layer.getExtruder();
is_inside_mesh_layer_part = gcode_layer.getIsInsideMesh();
gcode_layer.processFanSpeedAndMinimalLayerTime(); gcode_layer.processFanSpeedAndMinimalLayerTime();
gcode_layer.overrideFanSpeeds(train->getSettingInPercentage("raft_base_fan_speed")); gcode_layer.overrideFanSpeeds(train->getSettingInPercentage("raft_base_fan_speed"));
layer_plan_buffer.push(gcode_layer);
planner_state = gcode_layer.getPlanningState();
GCodePlanner* to_be_written = layer_plan_buffer.processBuffer();
if (to_be_written)
{
to_be_written->writeGCode(gcode);
delete to_be_written;
}
} }
{ // raft interface layer { // raft interface layer
@@ -388,7 +345,7 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
int layer_height = train->getSettingInMicrons("raft_interface_thickness"); int layer_height = train->getSettingInMicrons("raft_interface_thickness");
z += layer_height; z += layer_height;
int64_t comb_offset = train->getSettingInMicrons("raft_interface_line_spacing"); int64_t comb_offset = train->getSettingInMicrons("raft_interface_line_spacing");
GCodePlanner& gcode_layer = layer_plan_buffer.emplace_back(storage, layer_nr, z, layer_height, last_position_planned, current_extruder_planned, is_inside_mesh_layer_part, fan_speed_layer_time_settings_per_extruder, combing_mode, comb_offset, train->getSettingBoolean("travel_avoid_other_parts"), train->getSettingInMicrons("travel_avoid_distance")); GCodePlanner& gcode_layer = *new GCodePlanner(storage, layer_nr, z, layer_height, planner_state, fan_speed_layer_time_settings_per_extruder, combing_mode, comb_offset, train->getSettingBoolean("travel_avoid_other_parts"), train->getSettingInMicrons("travel_avoid_distance"));
gcode_layer.setIsInside(true); gcode_layer.setIsInside(true);
gcode_layer.setExtruder(extruder_nr); // reset to extruder number, because we might have primed in the last layer gcode_layer.setExtruder(extruder_nr); // reset to extruder number, because we might have primed in the last layer
@@ -401,16 +358,21 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
Polygons raftLines; Polygons raftLines;
int offset_from_poly_outline = 0; int offset_from_poly_outline = 0;
double fill_angle = train->getSettingAsCount("raft_surface_layers") > 0 ? 45 : 90; double fill_angle = train->getSettingAsCount("raft_surface_layers") > 0 ? 45 : 90;
Infill infill_comp(EFillMethod::ZIG_ZAG, storage.raftOutline, offset_from_poly_outline, storage.raft_interface_config.getLineWidth(), train->getSettingInMicrons("raft_interface_line_spacing"), fill_overlap, fill_angle, z, extra_infill_shift); Infill infill_comp(EFillMethod::ZIG_ZAG, storage.raftOutline, offset_from_poly_outline, gcode_layer.configs_storage.raft_interface_config.getLineWidth(), train->getSettingInMicrons("raft_interface_line_spacing"), fill_overlap, fill_angle, z, extra_infill_shift);
infill_comp.generate(raft_polygons, raftLines); infill_comp.generate(raft_polygons, raftLines);
gcode_layer.addLinesByOptimizer(raftLines, &storage.raft_interface_config, SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(raftLines, &gcode_layer.configs_storage.raft_interface_config, SpaceFillType::Lines);
last_position_planned = gcode_layer.getLastPosition();
current_extruder_planned = gcode_layer.getExtruder();
is_inside_mesh_layer_part = gcode_layer.getIsInsideMesh();
gcode_layer.processFanSpeedAndMinimalLayerTime(); gcode_layer.processFanSpeedAndMinimalLayerTime();
gcode_layer.overrideFanSpeeds(train->getSettingInPercentage("raft_interface_fan_speed")); gcode_layer.overrideFanSpeeds(train->getSettingInPercentage("raft_interface_fan_speed"));
layer_plan_buffer.push(gcode_layer);
planner_state = gcode_layer.getPlanningState();
GCodePlanner* to_be_written = layer_plan_buffer.processBuffer();
if (to_be_written)
{
to_be_written->writeGCode(gcode);
delete to_be_written;
}
} }
int layer_height = train->getSettingInMicrons("raft_surface_thickness"); int layer_height = train->getSettingInMicrons("raft_surface_thickness");
@@ -420,7 +382,7 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
const int layer_nr = initial_raft_layer_nr + 2 + raftSurfaceLayer - 1; // 2: 1 base layer, 1 interface layer const int layer_nr = initial_raft_layer_nr + 2 + raftSurfaceLayer - 1; // 2: 1 base layer, 1 interface layer
z += layer_height; z += layer_height;
const int64_t comb_offset = train->getSettingInMicrons("raft_surface_line_spacing"); const int64_t comb_offset = train->getSettingInMicrons("raft_surface_line_spacing");
GCodePlanner& gcode_layer = layer_plan_buffer.emplace_back(storage, layer_nr, z, layer_height, last_position_planned, current_extruder_planned, is_inside_mesh_layer_part, fan_speed_layer_time_settings_per_extruder, combing_mode, comb_offset, train->getSettingBoolean("travel_avoid_other_parts"), train->getSettingInMicrons("travel_avoid_distance")); GCodePlanner& gcode_layer = *new GCodePlanner(storage, layer_nr, z, layer_height, planner_state, fan_speed_layer_time_settings_per_extruder, combing_mode, comb_offset, train->getSettingBoolean("travel_avoid_other_parts"), train->getSettingInMicrons("travel_avoid_distance"));
gcode_layer.setIsInside(true); gcode_layer.setIsInside(true);
if (CommandSocket::isInstantiated()) if (CommandSocket::isInstantiated())
@@ -431,20 +393,25 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
Polygons raft_lines; Polygons raft_lines;
int offset_from_poly_outline = 0; int offset_from_poly_outline = 0;
double fill_angle = 90 * raftSurfaceLayer; double fill_angle = 90 * raftSurfaceLayer;
Infill infill_comp(EFillMethod::ZIG_ZAG, storage.raftOutline, offset_from_poly_outline, storage.raft_surface_config.getLineWidth(), train->getSettingInMicrons("raft_surface_line_spacing"), fill_overlap, fill_angle, z, extra_infill_shift); Infill infill_comp(EFillMethod::ZIG_ZAG, storage.raftOutline, offset_from_poly_outline, gcode_layer.configs_storage.raft_surface_config.getLineWidth(), train->getSettingInMicrons("raft_surface_line_spacing"), fill_overlap, fill_angle, z, extra_infill_shift);
infill_comp.generate(raft_polygons, raft_lines); infill_comp.generate(raft_polygons, raft_lines);
gcode_layer.addLinesByOptimizer(raft_lines, &storage.raft_surface_config, SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(raft_lines, &gcode_layer.configs_storage.raft_surface_config, SpaceFillType::Lines);
last_position_planned = gcode_layer.getLastPosition();
current_extruder_planned = gcode_layer.getExtruder();
is_inside_mesh_layer_part = gcode_layer.getIsInsideMesh();
gcode_layer.processFanSpeedAndMinimalLayerTime(); gcode_layer.processFanSpeedAndMinimalLayerTime();
gcode_layer.overrideFanSpeeds(train->getSettingInPercentage("raft_surface_fan_speed")); gcode_layer.overrideFanSpeeds(train->getSettingInPercentage("raft_surface_fan_speed"));
layer_plan_buffer.push(gcode_layer);
planner_state = gcode_layer.getPlanningState();
GCodePlanner* to_be_written = layer_plan_buffer.processBuffer();
if (to_be_written)
{
to_be_written->writeGCode(gcode);
delete to_be_written;
}
} }
} }
void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsigned int total_layers) GCodePlanner& FffGcodeWriter::processLayer(const SliceDataStorage& storage, int layer_nr, unsigned int total_layers) const
{ {
Progress::messageProgress(Progress::Stage::EXPORT, std::max(0, layer_nr) + 1, total_layers); Progress::messageProgress(Progress::Stage::EXPORT, std::max(0, layer_nr) + 1, total_layers);
logDebug("GcodeWriter processing layer %i of %i\n", layer_nr, total_layers); logDebug("GcodeWriter processing layer %i of %i\n", layer_nr, total_layers);
@@ -496,15 +463,14 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
} }
coord_t max_inner_wall_width = 0; coord_t max_inner_wall_width = 0;
for (SettingsBaseVirtual& mesh_settings : storage.meshes) for (const SettingsBaseVirtual& mesh_settings : storage.meshes)
{ {
max_inner_wall_width = std::max(max_inner_wall_width, mesh_settings.getSettingInMicrons((mesh_settings.getSettingAsCount("wall_line_count") > 1) ? "wall_line_width_x" : "wall_line_width_0")); max_inner_wall_width = std::max(max_inner_wall_width, mesh_settings.getSettingInMicrons((mesh_settings.getSettingAsCount("wall_line_count") > 1) ? "wall_line_width_x" : "wall_line_width_0"));
} }
int64_t comb_offset_from_outlines = max_inner_wall_width * 2; int64_t comb_offset_from_outlines = max_inner_wall_width * 2;
GCodePlanner& gcode_layer = *new GCodePlanner(storage, layer_nr, z, layer_thickness, planner_state, fan_speed_layer_time_settings_per_extruder, getSettingAsCombingMode("retraction_combing"), comb_offset_from_outlines, avoid_other_parts, avoid_distance);
GCodePlanner& gcode_layer = layer_plan_buffer.emplace_back(storage, layer_nr, z, layer_thickness, last_position_planned, current_extruder_planned, is_inside_mesh_layer_part, fan_speed_layer_time_settings_per_extruder, getSettingAsCombingMode("retraction_combing"), comb_offset_from_outlines, avoid_other_parts, avoid_distance);
if (include_helper_parts && layer_nr == 0) if (include_helper_parts && layer_nr == 0)
{ // process the skirt or the brim of the starting extruder. { // process the skirt or the brim of the starting extruder.
@@ -535,10 +501,10 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
if (layer_nr >= 0) if (layer_nr >= 0)
{ {
std::vector<unsigned int>& mesh_order = mesh_order_per_extruder[extruder_nr]; const std::vector<unsigned int>& mesh_order = mesh_order_per_extruder[extruder_nr];
unsigned int mesh_order_idx_starting_mesh = 0; unsigned int mesh_order_idx_starting_mesh = 0;
{ // calculate mesh_order_idx_starting_mesh { // calculate mesh_order_idx_starting_mesh
Point layer_start_position = last_position_planned; Point layer_start_position = planner_state.last_position;
if (storage.getSettingBoolean("start_layers_at_same_position")) if (storage.getSettingBoolean("start_layers_at_same_position"))
{ {
layer_start_position = Point(storage.getSettingInMicrons("layer_start_x"), storage.getSettingInMicrons("layer_start_y")); layer_start_position = Point(storage.getSettingInMicrons("layer_start_x"), storage.getSettingInMicrons("layer_start_y"));
@@ -546,12 +512,12 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
coord_t best_dist2 = std::numeric_limits<coord_t>::max(); coord_t best_dist2 = std::numeric_limits<coord_t>::max();
for (unsigned int mesh_order_idx = 0; mesh_order_idx < mesh_order.size(); mesh_order_idx++) for (unsigned int mesh_order_idx = 0; mesh_order_idx < mesh_order.size(); mesh_order_idx++)
{ {
unsigned int mesh_idx = mesh_order[mesh_order_idx]; const unsigned int mesh_idx = mesh_order[mesh_order_idx];
SliceMeshStorage& mesh = storage.meshes[mesh_idx]; const SliceMeshStorage& mesh = storage.meshes[mesh_idx];
for (SliceLayerPart& part : mesh.layers[layer_nr].parts) for (const SliceLayerPart& part : mesh.layers[layer_nr].parts)
{ {
Point middle = (part.boundaryBox.min + part.boundaryBox.max) / 2; const Point middle = (part.boundaryBox.min + part.boundaryBox.max) / 2;
coord_t dist2 = vSize2(middle - layer_start_position); const coord_t dist2 = vSize2(middle - layer_start_position);
if (dist2 < best_dist2) if (dist2 < best_dist2)
{ {
best_dist2 = dist2; best_dist2 = dist2;
@@ -565,14 +531,15 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
{ {
unsigned int mesh_order_idx = (mesh_iterator_idx + mesh_order_idx_starting_mesh) % mesh_order.size(); unsigned int mesh_order_idx = (mesh_iterator_idx + mesh_order_idx_starting_mesh) % mesh_order.size();
unsigned int mesh_idx = mesh_order[mesh_order_idx]; unsigned int mesh_idx = mesh_order[mesh_order_idx];
SliceMeshStorage* mesh = &storage.meshes[mesh_idx]; const SliceMeshStorage* mesh = &storage.meshes[mesh_idx];
const PathConfigStorage::MeshPathConfigs& mesh_config = gcode_layer.configs_storage.mesh_configs[mesh_idx];
if (mesh->getSettingAsSurfaceMode("magic_mesh_surface_mode") == ESurfaceMode::SURFACE) if (mesh->getSettingAsSurfaceMode("magic_mesh_surface_mode") == ESurfaceMode::SURFACE)
{ {
addMeshLayerToGCode_meshSurfaceMode(storage, mesh, gcode_layer, layer_nr); addMeshLayerToGCode_meshSurfaceMode(storage, mesh, mesh_config, gcode_layer, layer_nr);
} }
else else
{ {
addMeshLayerToGCode(storage, mesh, gcode_layer, layer_nr); addMeshLayerToGCode(storage, mesh, mesh_config, gcode_layer, layer_nr);
} }
} }
} }
@@ -589,15 +556,13 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
int prev_extruder = gcode_layer.getExtruder(); // most likely the same extruder as we are extruding with now int prev_extruder = gcode_layer.getExtruder(); // most likely the same extruder as we are extruding with now
addPrimeTower(storage, gcode_layer, layer_nr, prev_extruder); addPrimeTower(storage, gcode_layer, layer_nr, prev_extruder);
} }
last_position_planned = gcode_layer.getLastPosition();
current_extruder_planned = gcode_layer.getExtruder();
is_inside_mesh_layer_part = gcode_layer.getIsInsideMesh();
gcode_layer.processFanSpeedAndMinimalLayerTime(); gcode_layer.processFanSpeedAndMinimalLayerTime();
return gcode_layer;
} }
bool FffGcodeWriter::getExtrudersNeedPrimeDuringFirstLayer() bool FffGcodeWriter::getExtrudersNeedPrimeDuringFirstLayer() const
{ {
switch(gcode.getFlavor()) switch(gcode.getFlavor())
{ {
@@ -608,7 +573,7 @@ bool FffGcodeWriter::getExtrudersNeedPrimeDuringFirstLayer()
} }
} }
void FffGcodeWriter::ensureAllExtrudersArePrimed(SliceDataStorage& storage, GCodePlanner& gcode_layer, const int layer_nr) void FffGcodeWriter::ensureAllExtrudersArePrimed(const SliceDataStorage& storage, GCodePlanner& gcode_layer, const int layer_nr) const
{ {
// Add prime for all extruders which haven't primed yet. // Add prime for all extruders which haven't primed yet.
@@ -622,23 +587,23 @@ void FffGcodeWriter::ensureAllExtrudersArePrimed(SliceDataStorage& storage, GCod
} }
} }
void FffGcodeWriter::processSkirtBrim(SliceDataStorage& storage, GCodePlanner& gcode_layer, unsigned int extruder_nr) void FffGcodeWriter::processSkirtBrim(const SliceDataStorage& storage, GCodePlanner& gcode_layer, unsigned int extruder_nr) const
{ {
if (skirt_brim_is_processed[extruder_nr]) if (skirt_brim_is_processed[extruder_nr])
{ {
return; return;
} }
Polygons& skirt_brim = storage.skirt_brim[extruder_nr]; const Polygons& skirt_brim = storage.skirt_brim[extruder_nr];
skirt_brim_is_processed[extruder_nr] = true; const_cast<bool&>(skirt_brim_is_processed[extruder_nr]) = true; // TODO: resolve const cast!
if (skirt_brim.size() == 0) if (skirt_brim.size() == 0)
{ {
return; return;
} }
gcode_layer.addTravel(skirt_brim.back().closestPointTo(gcode_layer.getLastPosition())); gcode_layer.addTravel(skirt_brim.back().closestPointTo(gcode_layer.getLastPosition()));
gcode_layer.addPolygonsByOptimizer(skirt_brim, &storage.skirt_brim_config[extruder_nr]); gcode_layer.addPolygonsByOptimizer(skirt_brim, &gcode_layer.configs_storage.skirt_brim_config[extruder_nr]);
} }
void FffGcodeWriter::processOozeShield(SliceDataStorage& storage, GCodePlanner& gcode_layer, unsigned int layer_nr) void FffGcodeWriter::processOozeShield(const SliceDataStorage& storage, GCodePlanner& gcode_layer, unsigned int layer_nr) const
{ {
if (layer_nr == 0 && storage.getSettingAsPlatformAdhesion("adhesion_type") == EPlatformAdhesion::BRIM) if (layer_nr == 0 && storage.getSettingAsPlatformAdhesion("adhesion_type") == EPlatformAdhesion::BRIM)
{ {
@@ -646,11 +611,11 @@ void FffGcodeWriter::processOozeShield(SliceDataStorage& storage, GCodePlanner&
} }
if (storage.oozeShield.size() > 0 && layer_nr < storage.oozeShield.size()) if (storage.oozeShield.size() > 0 && layer_nr < storage.oozeShield.size())
{ {
gcode_layer.addPolygonsByOptimizer(storage.oozeShield[layer_nr], &storage.skirt_brim_config[0]); //TODO: Skirt and brim configuration index should correspond to draft shield extruder number. gcode_layer.addPolygonsByOptimizer(storage.oozeShield[layer_nr], &gcode_layer.configs_storage.skirt_brim_config[0]); //TODO: Skirt and brim configuration index should correspond to draft shield extruder number.
} }
} }
void FffGcodeWriter::processDraftShield(SliceDataStorage& storage, GCodePlanner& gcode_layer, unsigned int layer_nr) void FffGcodeWriter::processDraftShield(const SliceDataStorage& storage, GCodePlanner& gcode_layer, unsigned int layer_nr) const
{ {
if (storage.draft_protection_shield.size() == 0) if (storage.draft_protection_shield.size() == 0)
{ {
@@ -677,10 +642,10 @@ void FffGcodeWriter::processDraftShield(SliceDataStorage& storage, GCodePlanner&
} }
} }
gcode_layer.addPolygonsByOptimizer(storage.draft_protection_shield, &storage.skirt_brim_config[0]); //TODO: Skirt and brim configuration index should correspond to draft shield extruder number. gcode_layer.addPolygonsByOptimizer(storage.draft_protection_shield, &gcode_layer.configs_storage.skirt_brim_config[0]); //TODO: Skirt and brim configuration index should correspond to draft shield extruder number.
} }
std::vector<int> FffGcodeWriter::calculateExtruderOrder(SliceDataStorage& storage, int current_extruder) std::vector<int> FffGcodeWriter::calculateExtruderOrder(const SliceDataStorage& storage, int current_extruder) const
{ {
int extruder_count = storage.getSettingAsCount("machine_extruder_count"); int extruder_count = storage.getSettingAsCount("machine_extruder_count");
std::vector<int> ret; std::vector<int> ret;
@@ -697,17 +662,17 @@ std::vector<int> FffGcodeWriter::calculateExtruderOrder(SliceDataStorage& storag
return ret; return ret;
} }
std::vector<unsigned int> FffGcodeWriter::calculateMeshOrder(SliceDataStorage& storage, int extruder_nr) std::vector<unsigned int> FffGcodeWriter::calculateMeshOrder(const SliceDataStorage& storage, int extruder_nr) const
{ {
OrderOptimizer<unsigned int> mesh_idx_order_optimizer; OrderOptimizer<unsigned int> mesh_idx_order_optimizer;
for (unsigned int mesh_idx = 0; mesh_idx < storage.meshes.size(); mesh_idx++) for (unsigned int mesh_idx = 0; mesh_idx < storage.meshes.size(); mesh_idx++)
{ {
SliceMeshStorage& mesh = storage.meshes[mesh_idx]; const SliceMeshStorage& mesh = storage.meshes[mesh_idx];
if (mesh.getSettingAsIndex("extruder_nr") == extruder_nr) if (mesh.getSettingAsIndex("extruder_nr") == extruder_nr)
{ {
Mesh& mesh_data = storage.meshgroup->meshes[mesh_idx]; const Mesh& mesh_data = storage.meshgroup->meshes[mesh_idx];
Point3 middle = (mesh_data.getAABB().min + mesh_data.getAABB().max) / 2; const Point3 middle = (mesh_data.getAABB().min + mesh_data.getAABB().max) / 2;
mesh_idx_order_optimizer.addItem(Point(middle.x, middle.y), mesh_idx); mesh_idx_order_optimizer.addItem(Point(middle.x, middle.y), mesh_idx);
} }
} }
@@ -722,7 +687,7 @@ std::vector<unsigned int> FffGcodeWriter::calculateMeshOrder(SliceDataStorage& s
return ret; return ret;
} }
void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr) void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(const SliceDataStorage& storage, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, GCodePlanner& gcode_layer, int layer_nr) const
{ {
if (layer_nr > mesh->layer_nr_max_filled_layer) if (layer_nr > mesh->layer_nr_max_filled_layer)
{ {
@@ -738,7 +703,7 @@ void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& stora
setExtruder_addPrime(storage, gcode_layer, layer_nr, mesh->getSettingAsIndex("extruder_nr")); setExtruder_addPrime(storage, gcode_layer, layer_nr, mesh->getSettingAsIndex("extruder_nr"));
SliceLayer* layer = &mesh->layers[layer_nr]; const SliceLayer* layer = &mesh->layers[layer_nr];
Polygons polygons; Polygons polygons;
@@ -749,17 +714,17 @@ void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& stora
EZSeamType z_seam_type = mesh->getSettingAsZSeamType("z_seam_type"); EZSeamType z_seam_type = mesh->getSettingAsZSeamType("z_seam_type");
Point z_seam_pos(mesh->getSettingInMicrons("z_seam_x"), mesh->getSettingInMicrons("z_seam_y")); Point z_seam_pos(mesh->getSettingInMicrons("z_seam_x"), mesh->getSettingInMicrons("z_seam_y"));
gcode_layer.addPolygonsByOptimizer(polygons, &mesh->inset0_config, nullptr, z_seam_type, z_seam_pos, mesh->getSettingInMicrons("wall_0_wipe_dist"), mesh->getSettingBoolean("magic_spiralize")); gcode_layer.addPolygonsByOptimizer(polygons, &mesh_config.inset0_config, nullptr, z_seam_type, z_seam_pos, mesh->getSettingInMicrons("wall_0_wipe_dist"), mesh->getSettingBoolean("magic_spiralize"));
addMeshOpenPolyLinesToGCode(storage, mesh, gcode_layer, layer_nr); addMeshOpenPolyLinesToGCode(storage, mesh, mesh_config, gcode_layer, layer_nr);
} }
void FffGcodeWriter::addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr) void FffGcodeWriter::addMeshOpenPolyLinesToGCode(const SliceDataStorage& storage, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, GCodePlanner& gcode_layer, int layer_nr) const
{ {
SliceLayer* layer = &mesh->layers[layer_nr]; const SliceLayer* layer = &mesh->layers[layer_nr];
Polygons lines; Polygons lines;
for(PolygonRef polyline : layer->openPolyLines) for(ConstPolygonRef polyline : layer->openPolyLines)
{ {
for(unsigned int point_idx = 1; point_idx<polyline.size(); point_idx++) for(unsigned int point_idx = 1; point_idx<polyline.size(); point_idx++)
{ {
@@ -769,11 +734,11 @@ void FffGcodeWriter::addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, Slic
lines.add(p); lines.add(p);
} }
} }
gcode_layer.addLinesByOptimizer(lines, &mesh->inset0_config, SpaceFillType::PolyLines); gcode_layer.addLinesByOptimizer(lines, &mesh_config.inset0_config, SpaceFillType::PolyLines);
} }
void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr) void FffGcodeWriter::addMeshLayerToGCode(const SliceDataStorage& storage, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, GCodePlanner& gcode_layer, int layer_nr) const
{ {
if (layer_nr > mesh->layer_nr_max_filled_layer) if (layer_nr > mesh->layer_nr_max_filled_layer)
{ {
@@ -787,7 +752,7 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshSto
return; return;
} }
SliceLayer* layer = &mesh->layers[layer_nr]; const SliceLayer* layer = &mesh->layers[layer_nr];
if (layer->parts.size() == 0) if (layer->parts.size() == 0)
{ {
@@ -797,7 +762,7 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshSto
if (mesh->getSettingAsCount("wall_line_count") > 0) if (mesh->getSettingAsCount("wall_line_count") > 0)
{ // don't switch extruder if there's nothing to print { // don't switch extruder if there's nothing to print
bool empty = true; bool empty = true;
for (SliceLayerPart& part : layer->parts) for (const SliceLayerPart& part : layer->parts)
{ {
if (part.insets.size() > 0) if (part.insets.size() > 0)
{ {
@@ -815,7 +780,7 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshSto
EZSeamType z_seam_type = mesh->getSettingAsZSeamType("z_seam_type"); EZSeamType z_seam_type = mesh->getSettingAsZSeamType("z_seam_type");
Point z_seam_pos(mesh->getSettingInMicrons("z_seam_x"), mesh->getSettingInMicrons("z_seam_y")); Point z_seam_pos(mesh->getSettingInMicrons("z_seam_x"), mesh->getSettingInMicrons("z_seam_y"));
Point layer_start_position = last_position_planned; Point layer_start_position = planner_state.last_position;
if (storage.getSettingBoolean("start_layers_at_same_position")) if (storage.getSettingBoolean("start_layers_at_same_position"))
{ {
layer_start_position = Point(storage.getSettingInMicrons("layer_start_x"), storage.getSettingInMicrons("layer_start_y")); layer_start_position = Point(storage.getSettingInMicrons("layer_start_x"), storage.getSettingInMicrons("layer_start_y"));
@@ -829,16 +794,16 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshSto
for (int part_idx : part_order_optimizer.polyOrder) for (int part_idx : part_order_optimizer.polyOrder)
{ {
SliceLayerPart& part = layer->parts[part_idx]; const SliceLayerPart& part = layer->parts[part_idx];
addMeshPartToGCode(storage, mesh, part, gcode_layer, layer_nr); addMeshPartToGCode(storage, mesh, mesh_config, part, gcode_layer, layer_nr);
} }
if (mesh->getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL) if (mesh->getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL)
{ {
addMeshOpenPolyLinesToGCode(storage, mesh, gcode_layer, layer_nr); addMeshOpenPolyLinesToGCode(storage, mesh, mesh_config, gcode_layer, layer_nr);
} }
} }
void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, SliceLayerPart& part, GCodePlanner& gcode_layer, int layer_nr) void FffGcodeWriter::addMeshPartToGCode(const SliceDataStorage& storage, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, GCodePlanner& gcode_layer, int layer_nr) const
{ {
bool skin_alternate_rotation = mesh->getSettingBoolean("skin_alternate_rotation") && ( mesh->getSettingAsCount("top_layers") >= 4 || mesh->getSettingAsCount("bottom_layers") >= 4 ); bool skin_alternate_rotation = mesh->getSettingBoolean("skin_alternate_rotation") && ( mesh->getSettingAsCount("top_layers") >= 4 || mesh->getSettingAsCount("bottom_layers") >= 4 );
@@ -860,18 +825,18 @@ void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, SliceMeshStor
if (mesh->getSettingBoolean("infill_before_walls")) if (mesh->getSettingBoolean("infill_before_walls"))
{ {
processMultiLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle); processMultiLayerInfill(gcode_layer, mesh, mesh_config, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
processSingleLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle); processSingleLayerInfill(gcode_layer, mesh, mesh_config, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
} }
EZSeamType z_seam_type = mesh->getSettingAsZSeamType("z_seam_type"); EZSeamType z_seam_type = mesh->getSettingAsZSeamType("z_seam_type");
Point z_seam_pos(mesh->getSettingInMicrons("z_seam_x"), mesh->getSettingInMicrons("z_seam_y")); Point z_seam_pos(mesh->getSettingInMicrons("z_seam_x"), mesh->getSettingInMicrons("z_seam_y"));
processInsets(gcode_layer, mesh, part, layer_nr, z_seam_type, z_seam_pos); processInsets(gcode_layer, mesh, mesh_config, part, layer_nr, z_seam_type, z_seam_pos);
if (!mesh->getSettingBoolean("infill_before_walls")) if (!mesh->getSettingBoolean("infill_before_walls"))
{ {
processMultiLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle); processMultiLayerInfill(gcode_layer, mesh, mesh_config, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
processSingleLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle); processSingleLayerInfill(gcode_layer, mesh, mesh_config, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
} }
EFillMethod skin_pattern = (layer_nr == 0)? EFillMethod skin_pattern = (layer_nr == 0)?
@@ -886,7 +851,7 @@ void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, SliceMeshStor
skin_angle -= 45; skin_angle -= 45;
int64_t skin_overlap = mesh->getSettingInMicrons("skin_overlap_mm"); int64_t skin_overlap = mesh->getSettingInMicrons("skin_overlap_mm");
processSkinAndPerimeterGaps(gcode_layer, mesh, part, layer_nr, skin_overlap, skin_angle); processSkinAndPerimeterGaps(gcode_layer, mesh, mesh_config, part, layer_nr, skin_overlap, skin_angle);
//After a layer part, make sure the nozzle is inside the comb boundary, so we do not retract on the perimeter. //After a layer part, make sure the nozzle is inside the comb boundary, so we do not retract on the perimeter.
if (!mesh->getSettingBoolean("magic_spiralize") || static_cast<int>(layer_nr) < mesh->getSettingAsCount("bottom_layers")) if (!mesh->getSettingBoolean("magic_spiralize") || static_cast<int>(layer_nr) < mesh->getSettingAsCount("bottom_layers"))
@@ -900,7 +865,7 @@ void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, SliceMeshStor
void FffGcodeWriter::processMultiLayerInfill(GCodePlanner& gcode_layer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int infill_angle) void FffGcodeWriter::processMultiLayerInfill(GCodePlanner& gcode_layer, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int infill_angle) const
{ {
int64_t z = layer_nr * getSettingInMicrons("layer_height"); int64_t z = layer_nr * getSettingInMicrons("layer_height");
if (infill_line_distance > 0) if (infill_line_distance > 0)
@@ -908,7 +873,7 @@ void FffGcodeWriter::processMultiLayerInfill(GCodePlanner& gcode_layer, SliceMes
//Print the thicker infill lines first. (double or more layer thickness, infill combined with previous layers) //Print the thicker infill lines first. (double or more layer thickness, infill combined with previous layers)
for(unsigned int combine_idx = 1; combine_idx < part.infill_area_per_combine_per_density[0].size(); combine_idx++) for(unsigned int combine_idx = 1; combine_idx < part.infill_area_per_combine_per_density[0].size(); combine_idx++)
{ {
const unsigned int infill_line_width = mesh->infill_config[combine_idx].getLineWidth(); const unsigned int infill_line_width = mesh_config.infill_config[combine_idx].getLineWidth();
EFillMethod infill_pattern = mesh->getSettingAsFillMethod("infill_pattern"); EFillMethod infill_pattern = mesh->getSettingAsFillMethod("infill_pattern");
Polygons infill_polygons; Polygons infill_polygons;
Polygons infill_lines; Polygons infill_lines;
@@ -925,19 +890,19 @@ void FffGcodeWriter::processMultiLayerInfill(GCodePlanner& gcode_layer, SliceMes
Infill infill_comp(infill_pattern, part.infill_area_per_combine_per_density[density_idx][combine_idx], 0, infill_line_width, infill_line_distance_here, infill_overlap, infill_angle, z, infill_shift); Infill infill_comp(infill_pattern, part.infill_area_per_combine_per_density[density_idx][combine_idx], 0, infill_line_width, infill_line_distance_here, infill_overlap, infill_angle, z, infill_shift);
infill_comp.generate(infill_polygons, infill_lines, mesh); infill_comp.generate(infill_polygons, infill_lines, mesh);
} }
gcode_layer.addPolygonsByOptimizer(infill_polygons, &mesh->infill_config[combine_idx]); gcode_layer.addPolygonsByOptimizer(infill_polygons, &mesh_config.infill_config[combine_idx]);
gcode_layer.addLinesByOptimizer(infill_lines, &mesh->infill_config[combine_idx], (infill_pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(infill_lines, &mesh_config.infill_config[combine_idx], (infill_pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
} }
} }
} }
void FffGcodeWriter::processSingleLayerInfill(GCodePlanner& gcode_layer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int infill_angle) void FffGcodeWriter::processSingleLayerInfill(GCodePlanner& gcode_layer, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int infill_angle) const
{ {
if (infill_line_distance == 0 || part.infill_area_per_combine_per_density[0].size() == 0) if (infill_line_distance == 0 || part.infill_area_per_combine_per_density[0].size() == 0)
{ {
return; return;
} }
const unsigned int infill_line_width = mesh->infill_config[0].getLineWidth(); const unsigned int infill_line_width = mesh_config.infill_config[0].getLineWidth();
//Combine the 1 layer thick infill with the top/bottom skin and print that as one thing. //Combine the 1 layer thick infill with the top/bottom skin and print that as one thing.
Polygons infill_polygons; Polygons infill_polygons;
@@ -981,18 +946,18 @@ void FffGcodeWriter::processSingleLayerInfill(GCodePlanner& gcode_layer, SliceMe
Infill infill_comp(pattern, part.infill_area_per_combine_per_density[density_idx][0], 0, infill_line_width, infill_line_distance_here, infill_overlap, infill_angle, z, infill_shift); Infill infill_comp(pattern, part.infill_area_per_combine_per_density[density_idx][0], 0, infill_line_width, infill_line_distance_here, infill_overlap, infill_angle, z, infill_shift);
infill_comp.generate(infill_polygons, infill_lines, mesh); infill_comp.generate(infill_polygons, infill_lines, mesh);
} }
gcode_layer.addPolygonsByOptimizer(infill_polygons, &mesh->infill_config[0]); gcode_layer.addPolygonsByOptimizer(infill_polygons, &mesh_config.infill_config[0]);
if (pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES) if (pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES)
{ {
gcode_layer.addLinesByOptimizer(infill_lines, &mesh->infill_config[0], SpaceFillType::Lines, mesh->getSettingInMicrons("infill_wipe_dist")); gcode_layer.addLinesByOptimizer(infill_lines, &mesh_config.infill_config[0], SpaceFillType::Lines, mesh->getSettingInMicrons("infill_wipe_dist"));
} }
else else
{ {
gcode_layer.addLinesByOptimizer(infill_lines, &mesh->infill_config[0], (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(infill_lines, &mesh_config.infill_config[0], (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
} }
} }
void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, EZSeamType z_seam_type, Point z_seam_pos) void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, unsigned int layer_nr, EZSeamType z_seam_type, Point z_seam_pos) const
{ {
bool compensate_overlap_0 = mesh->getSettingBoolean("travel_compensate_overlapping_walls_0_enabled"); bool compensate_overlap_0 = mesh->getSettingBoolean("travel_compensate_overlapping_walls_0_enabled");
bool compensate_overlap_x = mesh->getSettingBoolean("travel_compensate_overlapping_walls_x_enabled"); bool compensate_overlap_x = mesh->getSettingBoolean("travel_compensate_overlapping_walls_x_enabled");
@@ -1009,7 +974,7 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, SliceMeshStorage*
{ // on the last normal layer first make the outer wall normally and then start a second outer wall from the same hight, but gradually moving upward { // on the last normal layer first make the outer wall normally and then start a second outer wall from the same hight, but gradually moving upward
WallOverlapComputation* wall_overlap_computation(nullptr); WallOverlapComputation* wall_overlap_computation(nullptr);
int wall_0_wipe_dist(0); int wall_0_wipe_dist(0);
gcode_layer.addPolygonsByOptimizer(part.insets[0], &mesh->insetX_config, wall_overlap_computation, EZSeamType::SHORTEST, z_seam_pos, wall_0_wipe_dist, spiralize); gcode_layer.addPolygonsByOptimizer(part.insets[0], &mesh_config.insetX_config, wall_overlap_computation, EZSeamType::SHORTEST, z_seam_pos, wall_0_wipe_dist, spiralize);
} }
} }
int processed_inset_number = -1; int processed_inset_number = -1;
@@ -1025,26 +990,26 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, SliceMeshStorage*
if (!compensate_overlap_0) if (!compensate_overlap_0)
{ {
WallOverlapComputation* wall_overlap_computation(nullptr); WallOverlapComputation* wall_overlap_computation(nullptr);
gcode_layer.addPolygonsByOptimizer(part.insets[0], &mesh->inset0_config, wall_overlap_computation, z_seam_type, z_seam_pos, mesh->getSettingInMicrons("wall_0_wipe_dist"), spiralize); gcode_layer.addPolygonsByOptimizer(part.insets[0], &mesh_config.inset0_config, wall_overlap_computation, z_seam_type, z_seam_pos, mesh->getSettingInMicrons("wall_0_wipe_dist"), spiralize);
} }
else else
{ {
Polygons& outer_wall = part.insets[0]; Polygons outer_wall = part.insets[0];
WallOverlapComputation wall_overlap_computation(outer_wall, mesh->getSettingInMicrons("wall_line_width_0")); WallOverlapComputation wall_overlap_computation(outer_wall, mesh->getSettingInMicrons("wall_line_width_0"));
gcode_layer.addPolygonsByOptimizer(outer_wall, &mesh->inset0_config, &wall_overlap_computation, z_seam_type, z_seam_pos, mesh->getSettingInMicrons("wall_0_wipe_dist"), spiralize); gcode_layer.addPolygonsByOptimizer(outer_wall, &mesh_config.inset0_config, &wall_overlap_computation, z_seam_type, z_seam_pos, mesh->getSettingInMicrons("wall_0_wipe_dist"), spiralize);
} }
} }
else else
{ {
if (!compensate_overlap_x) if (!compensate_overlap_x)
{ {
gcode_layer.addPolygonsByOptimizer(part.insets[processed_inset_number], &mesh->insetX_config); gcode_layer.addPolygonsByOptimizer(part.insets[processed_inset_number], &mesh_config.insetX_config);
} }
else else
{ {
Polygons& outer_wall = part.insets[processed_inset_number]; Polygons outer_wall = part.insets[processed_inset_number];
WallOverlapComputation wall_overlap_computation(outer_wall, mesh->getSettingInMicrons("wall_line_width_x")); WallOverlapComputation wall_overlap_computation(outer_wall, mesh->getSettingInMicrons("wall_line_width_x"));
gcode_layer.addPolygonsByOptimizer(outer_wall, &mesh->insetX_config, &wall_overlap_computation); gcode_layer.addPolygonsByOptimizer(outer_wall, &mesh_config.insetX_config, &wall_overlap_computation);
} }
} }
} }
@@ -1052,11 +1017,11 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, SliceMeshStorage*
} }
void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, int skin_overlap, int skin_angle) void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, unsigned int layer_nr, int skin_overlap, int skin_angle) const
{ {
int64_t z = layer_nr * getSettingInMicrons("layer_height"); int64_t z = layer_nr * getSettingInMicrons("layer_height");
const unsigned int skin_line_width = mesh->skin_config.getLineWidth(); const unsigned int skin_line_width = mesh_config.skin_config.getLineWidth();
const unsigned int perimeter_gaps_line_width = mesh->perimeter_gap_config.getLineWidth(); const unsigned int perimeter_gaps_line_width = mesh_config.perimeter_gap_config.getLineWidth();
constexpr int perimeter_gaps_extra_offset = 15; // extra offset so that the perimeter gaps aren't created everywhere due to rounding errors constexpr int perimeter_gaps_extra_offset = 15; // extra offset so that the perimeter gaps aren't created everywhere due to rounding errors
bool fill_perimeter_gaps = mesh->getSettingAsFillPerimeterGapMode("fill_perimeter_gaps") != FillPerimeterGapMode::NOWHERE bool fill_perimeter_gaps = mesh->getSettingAsFillPerimeterGapMode("fill_perimeter_gaps") != FillPerimeterGapMode::NOWHERE
@@ -1066,14 +1031,14 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
PathOrderOptimizer part_order_optimizer(gcode_layer.getLastPosition(), z_seam_pos, EZSeamType::SHORTEST); PathOrderOptimizer part_order_optimizer(gcode_layer.getLastPosition(), z_seam_pos, EZSeamType::SHORTEST);
for (unsigned int skin_part_idx = 0; skin_part_idx < part.skin_parts.size(); skin_part_idx++) for (unsigned int skin_part_idx = 0; skin_part_idx < part.skin_parts.size(); skin_part_idx++)
{ {
PolygonsPart& outline = part.skin_parts[skin_part_idx].outline; const PolygonsPart& outline = part.skin_parts[skin_part_idx].outline;
part_order_optimizer.addPolygon(outline.outerPolygon()); part_order_optimizer.addPolygon(outline.outerPolygon());
} }
part_order_optimizer.optimize(); part_order_optimizer.optimize();
for (int ordered_skin_part_idx : part_order_optimizer.polyOrder) for (int ordered_skin_part_idx : part_order_optimizer.polyOrder)
{ {
SkinPart& skin_part = part.skin_parts[ordered_skin_part_idx]; const SkinPart& skin_part = part.skin_parts[ordered_skin_part_idx];
Polygons skin_polygons; Polygons skin_polygons;
Polygons skin_lines; Polygons skin_lines;
@@ -1092,30 +1057,30 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
Polygons perimeter_gaps; // the perimeter gaps of the insets of this skin part Polygons perimeter_gaps; // the perimeter gaps of the insets of this skin part
Polygons* inner_skin_outline = nullptr; const Polygons* inner_skin_outline = nullptr;
int offset_from_inner_skin_outline = 0; int offset_from_inner_skin_outline = 0;
if (pattern != EFillMethod::CONCENTRIC) if (pattern != EFillMethod::CONCENTRIC)
{ {
for (Polygons& skin_perimeter : skin_part.insets) for (const Polygons& skin_perimeter : skin_part.insets)
{ {
gcode_layer.addPolygonsByOptimizer(skin_perimeter, &mesh->insetX_config); // add polygons to gcode in inward order gcode_layer.addPolygonsByOptimizer(skin_perimeter, &mesh_config.insetX_config); // add polygons to gcode in inward order
} }
if (skin_part.insets.size() > 0) if (skin_part.insets.size() > 0)
{ {
inner_skin_outline = &skin_part.insets.back(); inner_skin_outline = &skin_part.insets.back();
offset_from_inner_skin_outline = -mesh->insetX_config.getLineWidth() / 2; offset_from_inner_skin_outline = -mesh_config.insetX_config.getLineWidth() / 2;
if (fill_perimeter_gaps) if (fill_perimeter_gaps)
{ {
// add perimeter gaps between the outer skin inset and the innermost wall // add perimeter gaps between the outer skin inset and the innermost wall
const Polygons outer = skin_part.outline; const Polygons outer = skin_part.outline;
const Polygons inner = skin_part.insets[0].offset(mesh->insetX_config.getLineWidth() / 2 + perimeter_gaps_extra_offset); const Polygons inner = skin_part.insets[0].offset(mesh_config.insetX_config.getLineWidth() / 2 + perimeter_gaps_extra_offset);
perimeter_gaps.add(outer.difference(inner)); perimeter_gaps.add(outer.difference(inner));
for (unsigned int inset_idx = 1; inset_idx < skin_part.insets.size(); inset_idx++) for (unsigned int inset_idx = 1; inset_idx < skin_part.insets.size(); inset_idx++)
{ // add perimeter gaps between consecutive skin walls { // add perimeter gaps between consecutive skin walls
const Polygons outer = skin_part.insets[inset_idx - 1].offset(-1 * mesh->insetX_config.getLineWidth() / 2 - perimeter_gaps_extra_offset); const Polygons outer = skin_part.insets[inset_idx - 1].offset(-1 * mesh_config.insetX_config.getLineWidth() / 2 - perimeter_gaps_extra_offset);
const Polygons inner = skin_part.insets[inset_idx].offset(mesh->insetX_config.getLineWidth() / 2); const Polygons inner = skin_part.insets[inset_idx].offset(mesh_config.insetX_config.getLineWidth() / 2);
perimeter_gaps.add(outer.difference(inner)); perimeter_gaps.add(outer.difference(inner));
} }
} }
@@ -1132,15 +1097,15 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
Infill infill_comp(pattern, *inner_skin_outline, offset_from_inner_skin_outline, skin_line_width, skin_line_width, skin_overlap, skin_angle, z, extra_infill_shift, perimeter_gaps_output); Infill infill_comp(pattern, *inner_skin_outline, offset_from_inner_skin_outline, skin_line_width, skin_line_width, skin_overlap, skin_angle, z, extra_infill_shift, perimeter_gaps_output);
infill_comp.generate(skin_polygons, skin_lines); infill_comp.generate(skin_polygons, skin_lines);
gcode_layer.addPolygonsByOptimizer(skin_polygons, &mesh->skin_config); gcode_layer.addPolygonsByOptimizer(skin_polygons, &mesh_config.skin_config);
if (pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES) if (pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES)
{ {
gcode_layer.addLinesByOptimizer(skin_lines, &mesh->skin_config, SpaceFillType::Lines, mesh->getSettingInMicrons("infill_wipe_dist")); gcode_layer.addLinesByOptimizer(skin_lines, &mesh_config.skin_config, SpaceFillType::Lines, mesh->getSettingInMicrons("infill_wipe_dist"));
} }
else else
{ {
gcode_layer.addLinesByOptimizer(skin_lines, &mesh->skin_config, (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(skin_lines, &mesh_config.skin_config, (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
} }
if (fill_perimeter_gaps) if (fill_perimeter_gaps)
@@ -1150,18 +1115,18 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
int offset = 0; int offset = 0;
Infill infill_comp(EFillMethod::LINES, perimeter_gaps, offset, perimeter_gaps_line_width, perimeter_gaps_line_width, skin_overlap, skin_angle, z, extra_infill_shift); Infill infill_comp(EFillMethod::LINES, perimeter_gaps, offset, perimeter_gaps_line_width, perimeter_gaps_line_width, skin_overlap, skin_angle, z, extra_infill_shift);
infill_comp.generate(gap_polygons, gap_lines); infill_comp.generate(gap_polygons, gap_lines);
gcode_layer.addLinesByOptimizer(gap_lines, &mesh->perimeter_gap_config, SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(gap_lines, &mesh_config.perimeter_gap_config, SpaceFillType::Lines);
} }
} }
if (fill_perimeter_gaps) if (fill_perimeter_gaps)
{ // handle perimeter gaps of normal insets { // handle perimeter gaps of normal insets
Polygons perimeter_gaps; Polygons perimeter_gaps;
int line_width = mesh->inset0_config.getLineWidth(); int line_width = mesh_config.inset0_config.getLineWidth();
for (unsigned int inset_idx = 0; inset_idx < part.insets.size() - 1; inset_idx++) for (unsigned int inset_idx = 0; inset_idx < part.insets.size() - 1; inset_idx++)
{ {
const Polygons outer = part.insets[inset_idx].offset(-1 * line_width / 2 - perimeter_gaps_extra_offset); const Polygons outer = part.insets[inset_idx].offset(-1 * line_width / 2 - perimeter_gaps_extra_offset);
line_width = mesh->insetX_config.getLineWidth(); line_width = mesh_config.insetX_config.getLineWidth();
Polygons inner = part.insets[inset_idx + 1].offset(line_width / 2); Polygons inner = part.insets[inset_idx + 1].offset(line_width / 2);
perimeter_gaps.add(outer.difference(inner)); perimeter_gaps.add(outer.difference(inner));
@@ -1175,7 +1140,7 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
const Polygons outer = part.insets.back().offset(-1 * line_width / 2 - perimeter_gaps_extra_offset); const Polygons outer = part.insets.back().offset(-1 * line_width / 2 - perimeter_gaps_extra_offset);
Polygons inner = part.infill_area; Polygons inner = part.infill_area;
for (SkinPart& skin_part : part.skin_parts) for (const SkinPart& skin_part : part.skin_parts)
{ {
inner.add(skin_part.outline); inner.add(skin_part.outline);
} }
@@ -1191,11 +1156,11 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
Infill infill_comp(EFillMethod::LINES, perimeter_gaps, offset, perimeter_gaps_line_width, perimeter_gaps_line_width, skin_overlap, skin_angle, z, extra_infill_shift); Infill infill_comp(EFillMethod::LINES, perimeter_gaps, offset, perimeter_gaps_line_width, perimeter_gaps_line_width, skin_overlap, skin_angle, z, extra_infill_shift);
infill_comp.generate(gap_polygons, gap_lines); infill_comp.generate(gap_polygons, gap_lines);
gcode_layer.addLinesByOptimizer(gap_lines, &mesh->perimeter_gap_config, SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(gap_lines, &mesh_config.perimeter_gap_config, SpaceFillType::Lines);
} }
} }
bool FffGcodeWriter::addSupportToGCode(SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr, int extruder_nr) bool FffGcodeWriter::addSupportToGCode(const SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr, int extruder_nr) const
{ {
bool support_added = false; bool support_added = false;
if (!storage.support.generated || layer_nr > storage.support.layer_nr_max_filled_layer) if (!storage.support.generated || layer_nr > storage.support.layer_nr_max_filled_layer)
@@ -1206,7 +1171,7 @@ bool FffGcodeWriter::addSupportToGCode(SliceDataStorage& storage, GCodePlanner&
int support_interface_extruder_nr = getSettingAsIndex("support_interface_extruder_nr"); int support_interface_extruder_nr = getSettingAsIndex("support_interface_extruder_nr");
int support_infill_extruder_nr = (layer_nr <= 0)? getSettingAsIndex("support_extruder_nr_layer_0") : getSettingAsIndex("support_infill_extruder_nr"); int support_infill_extruder_nr = (layer_nr <= 0)? getSettingAsIndex("support_extruder_nr_layer_0") : getSettingAsIndex("support_infill_extruder_nr");
SupportLayer& support_layer = storage.support.supportLayers[layer_nr]; const SupportLayer& support_layer = storage.support.supportLayers[layer_nr];
if (support_layer.skin.size() == 0 && support_layer.supportAreas.size() == 0) if (support_layer.skin.size() == 0 && support_layer.supportAreas.size() == 0)
{ {
return support_added; return support_added;
@@ -1224,12 +1189,14 @@ bool FffGcodeWriter::addSupportToGCode(SliceDataStorage& storage, GCodePlanner&
return support_added; return support_added;
} }
bool FffGcodeWriter::addSupportInfillToGCode(SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr) bool FffGcodeWriter::addSupportInfillToGCode(const SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr) const
{ {
const SupportLayer& support_layer = storage.support.supportLayers[std::max(0, layer_nr)]; // account for negative layer numbers for raft filler layers
bool added = false; bool added = false;
if (!storage.support.generated if (!storage.support.generated
|| layer_nr > storage.support.layer_nr_max_filled_layer || layer_nr > storage.support.layer_nr_max_filled_layer
|| storage.support.supportLayers[layer_nr].supportAreas.size() == 0) || support_layer.supportAreas.size() == 0)
{ {
return added; return added;
} }
@@ -1238,14 +1205,14 @@ bool FffGcodeWriter::addSupportInfillToGCode(SliceDataStorage& storage, GCodePla
const ExtruderTrain& infill_extr = *storage.meshgroup->getExtruderTrain(getSettingAsIndex("support_infill_extruder_nr")); const ExtruderTrain& infill_extr = *storage.meshgroup->getExtruderTrain(getSettingAsIndex("support_infill_extruder_nr"));
int support_line_distance = infill_extr.getSettingInMicrons("support_line_distance"); // first layer line distance must be the same as the second layer line distance int support_line_distance = infill_extr.getSettingInMicrons("support_line_distance"); // first layer line distance must be the same as the second layer line distance
const int support_line_width = storage.support_config.getLineWidth(); const int support_line_width = gcode_layer.configs_storage.support_infill_config.getLineWidth();
EFillMethod support_pattern = infill_extr.getSettingAsFillMethod("support_pattern"); // first layer pattern must be same as other layers EFillMethod support_pattern = infill_extr.getSettingAsFillMethod("support_pattern"); // first layer pattern must be same as other layers
if (layer_nr <= 0 && (support_pattern == EFillMethod::LINES || support_pattern == EFillMethod::ZIG_ZAG)) { support_pattern = EFillMethod::GRID; } if (layer_nr <= 0 && (support_pattern == EFillMethod::LINES || support_pattern == EFillMethod::ZIG_ZAG)) { support_pattern = EFillMethod::GRID; }
int infill_extruder_nr_here = (layer_nr <= 0)? getSettingAsIndex("support_extruder_nr_layer_0") : getSettingAsIndex("support_infill_extruder_nr"); int infill_extruder_nr_here = (layer_nr <= 0)? getSettingAsIndex("support_extruder_nr_layer_0") : getSettingAsIndex("support_infill_extruder_nr");
const ExtruderTrain& infill_extr_here = *storage.meshgroup->getExtruderTrain(infill_extruder_nr_here); const ExtruderTrain& infill_extr_here = *storage.meshgroup->getExtruderTrain(infill_extruder_nr_here);
Polygons& support = storage.support.supportLayers[std::max(0, layer_nr)].supportAreas; const Polygons& support = support_layer.supportAreas;
std::vector<PolygonsPart> support_islands = support.splitIntoParts(); std::vector<PolygonsPart> support_islands = support.splitIntoParts();
@@ -1269,7 +1236,7 @@ bool FffGcodeWriter::addSupportInfillToGCode(SliceDataStorage& storage, GCodePla
if (boundary.size() > 0) if (boundary.size() > 0)
{ {
setExtruder_addPrime(storage, gcode_layer, layer_nr, infill_extruder_nr_here); // only switch extruder if we're sure we're going to switch setExtruder_addPrime(storage, gcode_layer, layer_nr, infill_extruder_nr_here); // only switch extruder if we're sure we're going to switch
gcode_layer.addPolygonsByOptimizer(boundary, &storage.support_config); gcode_layer.addPolygonsByOptimizer(boundary, &gcode_layer.configs_storage.support_infill_config);
} }
offset_from_outline = -support_line_width; offset_from_outline = -support_line_width;
support_infill_overlap = infill_extr_here.getSettingInMicrons("infill_overlap_mm"); // support lines area should be expanded outward to overlap with the boundary polygon support_infill_overlap = infill_extr_here.getSettingInMicrons("infill_overlap_mm"); // support lines area should be expanded outward to overlap with the boundary polygon
@@ -1286,20 +1253,22 @@ bool FffGcodeWriter::addSupportInfillToGCode(SliceDataStorage& storage, GCodePla
if (support_lines.size() > 0 || support_polygons.size() > 0) if (support_lines.size() > 0 || support_polygons.size() > 0)
{ {
setExtruder_addPrime(storage, gcode_layer, layer_nr, infill_extruder_nr_here); // only switch extruder if we're sure we're going to switch setExtruder_addPrime(storage, gcode_layer, layer_nr, infill_extruder_nr_here); // only switch extruder if we're sure we're going to switch
gcode_layer.addPolygonsByOptimizer(support_polygons, &storage.support_config); gcode_layer.addPolygonsByOptimizer(support_polygons, &gcode_layer.configs_storage.support_infill_config);
gcode_layer.addLinesByOptimizer(support_lines, &storage.support_config, (support_pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(support_lines, &gcode_layer.configs_storage.support_infill_config, (support_pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
added = true; added = true;
} }
} }
return added; return added;
} }
bool FffGcodeWriter::addSupportRoofsToGCode(SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr) bool FffGcodeWriter::addSupportRoofsToGCode(const SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr) const
{ {
const SupportLayer& support_layer = storage.support.supportLayers[std::max(0, layer_nr)];
bool added = false; bool added = false;
if (!storage.support.generated if (!storage.support.generated
|| layer_nr > storage.support.layer_nr_max_filled_layer || layer_nr > storage.support.layer_nr_max_filled_layer
|| storage.support.supportLayers[std::max(0, layer_nr)].skin.size() == 0) || support_layer.skin.size() == 0)
{ {
return added; return added;
} }
@@ -1314,7 +1283,7 @@ bool FffGcodeWriter::addSupportRoofsToGCode(SliceDataStorage& storage, GCodePlan
bool all_roofs_are_low = true; bool all_roofs_are_low = true;
for (SliceMeshStorage& mesh : storage.meshes) for (const SliceMeshStorage& mesh : storage.meshes)
{ {
if (mesh.getSettingInMicrons("support_roof_height") >= 2 * getSettingInMicrons("layer_height")) if (mesh.getSettingInMicrons("support_roof_height") >= 2 * getSettingInMicrons("layer_height"))
{ {
@@ -1343,7 +1312,7 @@ bool FffGcodeWriter::addSupportRoofsToGCode(SliceDataStorage& storage, GCodePlan
Polygons* perimeter_gaps = nullptr; Polygons* perimeter_gaps = nullptr;
bool use_endpieces = true; bool use_endpieces = true;
bool connected_zigzags = false; bool connected_zigzags = false;
Infill infill_comp(pattern, storage.support.supportLayers[std::max(0, layer_nr)].skin, outline_offset, storage.support_skin_config.getLineWidth(), support_line_distance, support_skin_overlap, fillAngle, z, extra_infill_shift, perimeter_gaps, connected_zigzags, use_endpieces); Infill infill_comp(pattern, support_layer.skin, outline_offset, gcode_layer.configs_storage.support_interface_config.getLineWidth(), support_line_distance, support_skin_overlap, fillAngle, z, extra_infill_shift, perimeter_gaps, connected_zigzags, use_endpieces);
Polygons support_polygons; Polygons support_polygons;
Polygons support_lines; Polygons support_lines;
infill_comp.generate(support_polygons, support_lines); infill_comp.generate(support_polygons, support_lines);
@@ -1351,14 +1320,14 @@ bool FffGcodeWriter::addSupportRoofsToGCode(SliceDataStorage& storage, GCodePlan
if (support_lines.size() > 0 || support_polygons.size() > 0) if (support_lines.size() > 0 || support_polygons.size() > 0)
{ {
setExtruder_addPrime(storage, gcode_layer, layer_nr, skin_extruder_nr); setExtruder_addPrime(storage, gcode_layer, layer_nr, skin_extruder_nr);
gcode_layer.addPolygonsByOptimizer(support_polygons, &storage.support_skin_config); gcode_layer.addPolygonsByOptimizer(support_polygons, &gcode_layer.configs_storage.support_interface_config);
gcode_layer.addLinesByOptimizer(support_lines, &storage.support_skin_config, (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(support_lines, &gcode_layer.configs_storage.support_interface_config, (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
added = true; added = true;
} }
return added; return added;
} }
void FffGcodeWriter::setExtruder_addPrime(SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr, int extruder_nr) void FffGcodeWriter::setExtruder_addPrime(const SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr, int extruder_nr) const
{ {
if (extruder_nr == -1) // an object with extruder_nr==-1 means it will be printed with any current nozzle if (extruder_nr == -1) // an object with extruder_nr==-1 means it will be printed with any current nozzle
return; return;
@@ -1369,7 +1338,7 @@ void FffGcodeWriter::setExtruder_addPrime(SliceDataStorage& storage, GCodePlanne
if (extruder_changed) if (extruder_changed)
{ {
if (!extruder_prime_is_planned[extruder_nr]) if (!const_cast<bool&>(extruder_prime_is_planned[extruder_nr])) // TODO: const cast!
{ {
ExtruderTrain* train = storage.meshgroup->getExtruderTrain(extruder_nr); ExtruderTrain* train = storage.meshgroup->getExtruderTrain(extruder_nr);
@@ -1380,7 +1349,7 @@ void FffGcodeWriter::setExtruder_addPrime(SliceDataStorage& storage, GCodePlanne
gcode_layer.planPrime(); gcode_layer.planPrime();
extruder_prime_is_planned[extruder_nr] = true; const_cast<bool&>(extruder_prime_is_planned[extruder_nr]) = true; // TODO: const cast!
} }
assert(extruder_prime_is_planned[extruder_nr] && "extruders should be primed before they are used!"); assert(extruder_prime_is_planned[extruder_nr] && "extruders should be primed before they are used!");
@@ -1395,7 +1364,7 @@ void FffGcodeWriter::setExtruder_addPrime(SliceDataStorage& storage, GCodePlanne
} }
} }
void FffGcodeWriter::addPrimeTower(SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr, int prev_extruder) void FffGcodeWriter::addPrimeTower(const SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr, int prev_extruder) const
{ {
if (!getSettingBoolean("prime_tower_enable")) if (!getSettingBoolean("prime_tower_enable"))
{ {
+41 -42
Ver Arquivo
@@ -74,18 +74,19 @@ private:
std::vector<FanSpeedLayerTimeSettings> fan_speed_layer_time_settings_per_extruder; //!< The settings used relating to minimal layer time and fan speeds. Configured for each extruder. std::vector<FanSpeedLayerTimeSettings> fan_speed_layer_time_settings_per_extruder; //!< The settings used relating to minimal layer time and fan speeds. Configured for each extruder.
Point last_position_planned; //!< The position of the head before planning the next layer
int current_extruder_planned; //!< The extruder train in use before planning the next layer GCodePlanner::PlanningState planner_state;
bool is_inside_mesh_layer_part; //!< Whether the last position was inside a layer part (used in combing)
public: public:
FffGcodeWriter(SettingsBase* settings_) FffGcodeWriter(SettingsBase* settings_)
: SettingsMessenger(settings_) : SettingsMessenger(settings_)
, max_object_height(0) , max_object_height(0)
, layer_plan_buffer(this, gcode) , layer_plan_buffer(this, gcode)
, extruder_prime_is_planned {} // initialize all values in array with [false] , extruder_prime_is_planned {} // initialize all values in array with [false]
, last_position_planned(no_point) , planner_state{ no_point
, current_extruder_planned(0) // changed somewhere early in FffGcodeWriter::writeGCode , 0 // changed somewhere early in FffGcodeWriter::writeGCode
, is_inside_mesh_layer_part(false) , false
}
{ {
} }
@@ -172,17 +173,6 @@ private:
* \param[out] storage The data storage to which to save the configurations * \param[out] storage The data storage to which to save the configurations
*/ */
void setConfigRetraction(SliceDataStorage& storage); void setConfigRetraction(SliceDataStorage& storage);
/*!
* Initialize the GcodePathConfig config parameters which don't change over
* all layers, for each feature.
*
* The features are: skirt or brim, support and for each mesh: outer wall,
* inner walls, skin, infill (and combined infill).
*
* \param[out] storage The data storage to which to save the configurations.
*/
void initConfigs(SliceDataStorage& storage);
/*! /*!
* Get the extruder with which to start the print. * Get the extruder with which to start the print.
@@ -192,7 +182,7 @@ private:
* *
* \param[in] storage where to get settings from. * \param[in] storage where to get settings from.
*/ */
unsigned int getStartExtruder(SliceDataStorage& storage); unsigned int getStartExtruder(const SliceDataStorage& storage);
/*! /*!
* Set temperatures and perform initial priming. * Set temperatures and perform initial priming.
@@ -202,14 +192,14 @@ private:
* \param[in] storage where the slice data is stored. * \param[in] storage where the slice data is stored.
* \param[in] start_extruder_nr The extruder with which to start the print. * \param[in] start_extruder_nr The extruder with which to start the print.
*/ */
void processStartingCode(SliceDataStorage& storage, const unsigned int start_extruder_nr); void processStartingCode(const SliceDataStorage& storage, const unsigned int start_extruder_nr);
/*! /*!
* Move up and over the already printed meshgroups to print the next meshgroup. * Move up and over the already printed meshgroups to print the next meshgroup.
* *
* \param[in] storage where the slice data is stored. * \param[in] storage where the slice data is stored.
*/ */
void processNextMeshGroupCode(SliceDataStorage& storage); void processNextMeshGroupCode(const SliceDataStorage& storage);
/*! /*!
* Add raft layer plans onto the FffGcodeWriter::layer_plan_buffer * Add raft layer plans onto the FffGcodeWriter::layer_plan_buffer
@@ -217,7 +207,7 @@ private:
* \param[in,out] storage where the slice data is stored. * \param[in,out] storage where the slice data is stored.
* \param total_layers The total number of layers. * \param total_layers The total number of layers.
*/ */
void processRaft(SliceDataStorage& storage, unsigned int total_layers); void processRaft(const SliceDataStorage& storage, unsigned int total_layers);
/*! /*!
* Convert the polygon data of a layer into a layer plan on the FffGcodeWriter::layer_plan_buffer * Convert the polygon data of a layer into a layer plan on the FffGcodeWriter::layer_plan_buffer
@@ -228,15 +218,16 @@ private:
* \param[in] storage where the slice data is stored. * \param[in] storage where the slice data is stored.
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
* \param total_layers The total number of layers. * \param total_layers The total number of layers.
* \return The layer plans
*/ */
void processLayer(SliceDataStorage& storage, int layer_nr, unsigned int total_layers); GCodePlanner& processLayer(const SliceDataStorage& storage, int layer_nr, unsigned int total_layers) const;
/*! /*!
* Whether the extruders need to be primed separately just before they are used. * Whether the extruders need to be primed separately just before they are used.
* *
* \return whether the extruders need to be primed separately just before they are used * \return whether the extruders need to be primed separately just before they are used
*/ */
bool getExtrudersNeedPrimeDuringFirstLayer(); bool getExtrudersNeedPrimeDuringFirstLayer() const;
/*! /*!
* Plan priming of all used extruders which haven't been primed yet * Plan priming of all used extruders which haven't been primed yet
@@ -244,7 +235,7 @@ private:
* \param layer_plan The initial planning of the g-code of the layer. * \param layer_plan The initial planning of the g-code of the layer.
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
*/ */
void ensureAllExtrudersArePrimed(SliceDataStorage& storage, GCodePlanner& layer_plan, const int layer_nr); void ensureAllExtrudersArePrimed(const SliceDataStorage& storage, GCodePlanner& layer_plan, const int layer_nr) const;
/*! /*!
* Add the skirt or the brim to the layer plan \p gcodeLayer. * Add the skirt or the brim to the layer plan \p gcodeLayer.
@@ -254,7 +245,7 @@ private:
* \param extruder_nr The extruder train for which to process the skirt or * \param extruder_nr The extruder train for which to process the skirt or
* brim. * brim.
*/ */
void processSkirtBrim(SliceDataStorage& storage, GCodePlanner& gcodeLayer, unsigned int extruder_nr); void processSkirtBrim(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, unsigned int extruder_nr) const;
/*! /*!
* Adds the ooze shield to the layer plan \p gcodeLayer. * Adds the ooze shield to the layer plan \p gcodeLayer.
@@ -263,7 +254,7 @@ private:
* \param gcodeLayer The initial planning of the gcode of the layer. * \param gcodeLayer The initial planning of the gcode of the layer.
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
*/ */
void processOozeShield(SliceDataStorage& storage, GCodePlanner& gcodeLayer, unsigned int layer_nr); void processOozeShield(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, unsigned int layer_nr) const;
/*! /*!
* Adds the draft protection screen to the layer plan \p gcodeLayer. * Adds the draft protection screen to the layer plan \p gcodeLayer.
@@ -272,7 +263,7 @@ private:
* \param gcodeLayer The initial planning of the gcode of the layer. * \param gcodeLayer The initial planning of the gcode of the layer.
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
*/ */
void processDraftShield(SliceDataStorage& storage, GCodePlanner& gcodeLayer, unsigned int layer_nr); void processDraftShield(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, unsigned int layer_nr) const;
/*! /*!
* Calculate in which order to plan the extruders * Calculate in which order to plan the extruders
@@ -281,7 +272,7 @@ private:
* \param current_extruder The current extruder with which we last printed * \param current_extruder The current extruder with which we last printed
* \return A vector of pairs of extruder numbers coupled with the mesh indices ordered on print order for that extruder. * \return A vector of pairs of extruder numbers coupled with the mesh indices ordered on print order for that extruder.
*/ */
std::vector<int> calculateExtruderOrder(SliceDataStorage& storage, int current_extruder); std::vector<int> calculateExtruderOrder(const SliceDataStorage& storage, int current_extruder) const;
/*! /*!
* Calculate in which order to plan the meshes of a specific extruder * Calculate in which order to plan the meshes of a specific extruder
@@ -290,88 +281,95 @@ private:
* \param extruder_nr The extruder for which to determine the order * \param extruder_nr The extruder for which to determine the order
* \return A vector of pairs of extruder numbers coupled with the mesh indices ordered on print order for that extruder. * \return A vector of pairs of extruder numbers coupled with the mesh indices ordered on print order for that extruder.
*/ */
std::vector<unsigned int> calculateMeshOrder(SliceDataStorage& storage, int extruder_nr); std::vector<unsigned int> calculateMeshOrder(const SliceDataStorage& storage, int extruder_nr) const;
/*! /*!
* Add a single layer from a single mesh-volume to the layer plan \p gcodeLayer in mesh surface mode. * Add a single layer from a single mesh-volume to the layer plan \p gcodeLayer in mesh surface mode.
* *
* \param[in] storage where the slice data is stored. * \param[in] storage where the slice data is stored.
* \param mesh The mesh to add to the layer plan \p gcodeLayer. * \param mesh The mesh to add to the layer plan \p gcodeLayer.
* \param mesh_config the line config with which to print a print feature
* \param gcodeLayer The initial planning of the gcode of the layer. * \param gcodeLayer The initial planning of the gcode of the layer.
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
* *
*/ */
void addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcodeLayer, int layer_nr); void addMeshLayerToGCode_meshSurfaceMode(const SliceDataStorage& storage, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, GCodePlanner& gcodeLayer, int layer_nr) const;
/*! /*!
* Add the open polylines from a single layer from a single mesh-volume to the layer plan \p gcodeLayer for mesh the surface modes. * Add the open polylines from a single layer from a single mesh-volume to the layer plan \p gcodeLayer for mesh the surface modes.
* *
* \param[in] storage where the slice data is stored. * \param[in] storage where the slice data is stored.
* \param mesh The mesh for which to add to the layer plan \p gcodeLayer. * \param mesh The mesh for which to add to the layer plan \p gcodeLayer.
* \param mesh_config the line config with which to print a print feature
* \param gcodeLayer The initial planning of the gcode of the layer. * \param gcodeLayer The initial planning of the gcode of the layer.
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
* *
*/ */
void addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr); void addMeshOpenPolyLinesToGCode(const SliceDataStorage& storage, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, GCodePlanner& gcode_layer, int layer_nr) const;
/*! /*!
* Add a single layer from a single mesh-volume to the layer plan \p gcode_layer. * Add a single layer from a single mesh-volume to the layer plan \p gcode_layer.
* *
* \param[in] storage where the slice data is stored. * \param[in] storage where the slice data is stored.
* \param mesh The mesh to add to the layer plan \p gcode_layer. * \param mesh The mesh to add to the layer plan \p gcode_layer.
* \param mesh_config the line config with which to print a print feature
* \param gcode_layer The initial planning of the gcode of the layer. * \param gcode_layer The initial planning of the gcode of the layer.
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
* *
*/ */
void addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr); void addMeshLayerToGCode(const SliceDataStorage& storage, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, GCodePlanner& gcode_layer, int layer_nr) const;
/*! /*!
* Add a single part from a given layer of a mesh-volume to the layer plan \p gcode_layer. * Add a single part from a given layer of a mesh-volume to the layer plan \p gcode_layer.
* *
* \param[in] storage where the slice data is stored. * \param[in] storage where the slice data is stored.
* \param mesh The mesh to add to the layer plan \p gcode_layer. * \param mesh The mesh to add to the layer plan \p gcode_layer.
* \param mesh_config the line config with which to print a print feature
* \param part The part to add * \param part The part to add
* \param gcode_layer The initial planning of the gcode of the layer. * \param gcode_layer The initial planning of the gcode of the layer.
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
* *
*/ */
void addMeshPartToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, SliceLayerPart& part, GCodePlanner& gcode_layer, int layer_nr); void addMeshPartToGCode(const SliceDataStorage& storage, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, GCodePlanner& gcode_layer, int layer_nr) const;
/*! /*!
* Add thicker (multiple layers) sparse infill for a given part in a layer plan. * Add thicker (multiple layers) sparse infill for a given part in a layer plan.
* *
* \param gcodeLayer The initial planning of the gcode of the layer. * \param gcodeLayer The initial planning of the gcode of the layer.
* \param mesh The mesh for which to add to the layer plan \p gcodeLayer. * \param mesh The mesh for which to add to the layer plan \p gcodeLayer.
* \param mesh_config the line config with which to print a print feature
* \param part The part for which to create gcode * \param part The part for which to create gcode
* \param layer_nr The current layer number. * \param layer_nr The current layer number.
* \param infill_line_distance The distance between the infill lines * \param infill_line_distance The distance between the infill lines
* \param infill_overlap The distance by which the infill overlaps with the wall insets. * \param infill_overlap The distance by which the infill overlaps with the wall insets.
* \param fillAngle The angle in the XY plane at which the infill is generated. * \param fillAngle The angle in the XY plane at which the infill is generated.
*/ */
void processMultiLayerInfill(GCodePlanner& gcodeLayer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int fillAngle); void processMultiLayerInfill(GCodePlanner& gcodeLayer, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int fillAngle) const;
/*! /*!
* Add normal sparse infill for a given part in a layer. * Add normal sparse infill for a given part in a layer.
* \param gcodeLayer The initial planning of the gcode of the layer. * \param gcodeLayer The initial planning of the gcode of the layer.
* \param mesh The mesh for which to add to the layer plan \p gcodeLayer. * \param mesh The mesh for which to add to the layer plan \p gcodeLayer.
* \param mesh_config the line config with which to print a print feature
* \param part The part for which to create gcode * \param part The part for which to create gcode
* \param layer_nr The current layer number. * \param layer_nr The current layer number.
* \param infill_line_distance The distance between the infill lines * \param infill_line_distance The distance between the infill lines
* \param infill_overlap The distance by which the infill overlaps with the wall insets. * \param infill_overlap The distance by which the infill overlaps with the wall insets.
* \param fillAngle The angle in the XY plane at which the infill is generated. * \param fillAngle The angle in the XY plane at which the infill is generated.
*/ */
void processSingleLayerInfill(GCodePlanner& gcodeLayer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int fillAngle); void processSingleLayerInfill(GCodePlanner& gcodeLayer, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int fillAngle) const;
/*! /*!
* Generate the insets for the walls of a given layer part. * Generate the insets for the walls of a given layer part.
* \param gcodeLayer The initial planning of the gcode of the layer. * \param gcodeLayer The initial planning of the gcode of the layer.
* \param mesh The mesh for which to add to the layer plan \p gcodeLayer. * \param mesh The mesh for which to add to the layer plan \p gcodeLayer.
* \param mesh_config the line config with which to print a print feature
* \param part The part for which to create gcode * \param part The part for which to create gcode
* \param layer_nr The current layer number. * \param layer_nr The current layer number.
* \param z_seam_type dir3ective for where to start the outer paerimeter of a part * \param z_seam_type dir3ective for where to start the outer paerimeter of a part
* \param z_seam_pos The location near where to start the outer inset in case \p z_seam_type is 'back' * \param z_seam_pos The location near where to start the outer inset in case \p z_seam_type is 'back'
*/ */
void processInsets(GCodePlanner& gcodeLayer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, EZSeamType z_seam_type, Point z_seam_pos); void processInsets(GCodePlanner& gcodeLayer, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, unsigned int layer_nr, EZSeamType z_seam_type, Point z_seam_pos) const;
/*! /*!
@@ -382,12 +380,13 @@ private:
* *
* \param gcodeLayer The initial planning of the gcode of the layer. * \param gcodeLayer The initial planning of the gcode of the layer.
* \param mesh The mesh for which to add to the layer plan \p gcodeLayer. * \param mesh The mesh for which to add to the layer plan \p gcodeLayer.
* \param mesh_config the line config with which to print a print feature
* \param part The part for which to create gcode * \param part The part for which to create gcode
* \param layer_nr The current layer number. * \param layer_nr The current layer number.
* \param skin_overlap The distance by which the skin overlaps with the wall insets and the distance by which the perimeter gaps overlap with adjacent print features. * \param skin_overlap The distance by which the skin overlaps with the wall insets and the distance by which the perimeter gaps overlap with adjacent print features.
* \param fillAngle The angle in the XY plane at which the infill is generated. * \param fillAngle The angle in the XY plane at which the infill is generated.
*/ */
void processSkinAndPerimeterGaps(cura::GCodePlanner& gcode_layer, cura::SliceMeshStorage* mesh, cura::SliceLayerPart& part, unsigned int layer_nr, int skin_overlap, int infill_angle); void processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, const SliceMeshStorage* mesh, const PathConfigStorage::MeshPathConfigs& mesh_config, const SliceLayerPart& part, unsigned int layer_nr, int skin_overlap, int infill_angle) const;
/*! /*!
* Add the support to the layer plan \p gcodeLayer of the current layer for all support parts with the given \p extruder_nr. * Add the support to the layer plan \p gcodeLayer of the current layer for all support parts with the given \p extruder_nr.
@@ -396,7 +395,7 @@ private:
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
* \return whether any support was added to the layer plan * \return whether any support was added to the layer plan
*/ */
bool addSupportToGCode(SliceDataStorage& storage, GCodePlanner& gcodeLayer, int layer_nr, int extruder_nr); bool addSupportToGCode(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, int layer_nr, int extruder_nr) const;
/*! /*!
* Add the support lines/walls to the layer plan \p gcodeLayer of the current layer. * Add the support lines/walls to the layer plan \p gcodeLayer of the current layer.
* \param[in] storage where the slice data is stored. * \param[in] storage where the slice data is stored.
@@ -404,7 +403,7 @@ private:
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
* \return whether any support infill was added to the layer plan * \return whether any support infill was added to the layer plan
*/ */
bool addSupportInfillToGCode(SliceDataStorage& storage, GCodePlanner& gcodeLayer, int layer_nr); bool addSupportInfillToGCode(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, int layer_nr) const;
/*! /*!
* Add the support skins to the layer plan \p gcodeLayer of the current layer. * Add the support skins to the layer plan \p gcodeLayer of the current layer.
* \param[in] storage where the slice data is stored. * \param[in] storage where the slice data is stored.
@@ -412,7 +411,7 @@ private:
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
* \return whether any support skin was added to the layer plan * \return whether any support skin was added to the layer plan
*/ */
bool addSupportRoofsToGCode(SliceDataStorage& storage, GCodePlanner& gcodeLayer, int layer_nr); bool addSupportRoofsToGCode(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, int layer_nr) const;
/*! /*!
* Change to a new extruder, and add the prime tower instructions if the new extruder is different from the last. * Change to a new extruder, and add the prime tower instructions if the new extruder is different from the last.
@@ -424,7 +423,7 @@ private:
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
* \param extruder_nr The extruder to which to switch * \param extruder_nr The extruder to which to switch
*/ */
void setExtruder_addPrime(SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr, int extruder_nr); void setExtruder_addPrime(const SliceDataStorage& storage, GCodePlanner& gcode_layer, int layer_nr, int extruder_nr) const;
/*! /*!
* Add the prime tower gcode for the current layer. * Add the prime tower gcode for the current layer.
@@ -433,7 +432,7 @@ private:
* \param layer_nr The index of the layer to write the gcode of. * \param layer_nr The index of the layer to write the gcode of.
* \param prev_extruder The current extruder with which we last printed. * \param prev_extruder The current extruder with which we last printed.
*/ */
void addPrimeTower(SliceDataStorage& storage, GCodePlanner& gcodeLayer, int layer_nr, int prev_extruder); void addPrimeTower(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, int layer_nr, int prev_extruder) const;
/*! /*!
* Add the end gcode and set all temperatures to zero. * Add the end gcode and set all temperatures to zero.
+33 -64
Ver Arquivo
@@ -6,105 +6,74 @@
namespace cura namespace cura
{ {
GCodePathConfig::BasicConfig::BasicConfig() GCodePathConfig::GCodePathConfig(const GCodePathConfig& other)
: speed(0) : type(other.type)
, acceleration(0) , speed_derivatives(other.speed_derivatives)
, jerk(0) , line_width(other.line_width)
, line_width(0) , layer_thickness(other.layer_thickness)
, flow(100) , flow(other.flow)
, extrusion_mm3_per_mm(other.extrusion_mm3_per_mm)
{ {
} }
GCodePathConfig::BasicConfig::BasicConfig(double speed, double acceleration, double jerk, int line_width, double flow)
: speed(speed) GCodePathConfig::GCodePathConfig(PrintFeatureType type, int line_width, int layer_height, double flow, GCodePathConfig::SpeedDerivatives speed_derivatives)
, acceleration(acceleration) : type(type)
, jerk(jerk) , speed_derivatives(speed_derivatives)
, line_width(line_width) , line_width(line_width)
, layer_thickness(layer_height)
, flow(flow) , flow(flow)
, extrusion_mm3_per_mm(calculateExtrusion())
{ {
} }
void GCodePathConfig::BasicConfig::set(double speed, double acceleration, double jerk, int line_width, double flow) void GCodePathConfig::smoothSpeed(GCodePathConfig::SpeedDerivatives first_layer_config, int layer_nr, int max_speed_layer_nr)
{ {
this->speed = speed; double max_speed_layer = max_speed_layer_nr;
this->acceleration = acceleration; speed_derivatives.speed = (speed_derivatives.speed * layer_nr) / max_speed_layer + (first_layer_config.speed * (max_speed_layer - layer_nr) / max_speed_layer);
this->jerk = jerk; speed_derivatives.acceleration = (speed_derivatives.acceleration * layer_nr) / max_speed_layer + (first_layer_config.acceleration * (max_speed_layer - layer_nr) / max_speed_layer);
this->line_width = line_width; speed_derivatives.jerk = (speed_derivatives.jerk * layer_nr) / max_speed_layer + (first_layer_config.jerk * (max_speed_layer - layer_nr) / max_speed_layer);
this->flow = flow;
} }
double GCodePathConfig::getExtrusionMM3perMM() const
GCodePathConfig::GCodePathConfig(PrintFeatureType type)
: extrusion_mm3_per_mm(0.0)
, type(type)
{
}
void GCodePathConfig::init(double speed, double acceleration, double jerk, int line_width, double flow)
{
iconic_config.set(speed, acceleration, jerk, line_width, flow);
current_config = iconic_config;
}
void GCodePathConfig::setLayerHeight(int layer_height)
{
this->layer_thickness = layer_height;
calculateExtrusion();
}
void GCodePathConfig::smoothSpeed(GCodePathConfig::BasicConfig first_layer_config, int layer_nr, double max_speed_layer)
{
current_config.speed = (iconic_config.speed * layer_nr) / max_speed_layer + (first_layer_config.speed * (max_speed_layer - layer_nr) / max_speed_layer);
current_config.acceleration = (iconic_config.acceleration * layer_nr) / max_speed_layer + (first_layer_config.acceleration * (max_speed_layer - layer_nr) / max_speed_layer);
current_config.jerk = (iconic_config.jerk * layer_nr) / max_speed_layer + (first_layer_config.jerk * (max_speed_layer - layer_nr) / max_speed_layer);
}
void GCodePathConfig::setSpeedIconic()
{
current_config.speed = iconic_config.speed;
current_config.acceleration = iconic_config.acceleration;
current_config.jerk = iconic_config.jerk;
}
double GCodePathConfig::getExtrusionMM3perMM()
{ {
return extrusion_mm3_per_mm; return extrusion_mm3_per_mm;
} }
double GCodePathConfig::getSpeed() double GCodePathConfig::getSpeed() const
{ {
return current_config.speed; return speed_derivatives.speed;
} }
double GCodePathConfig::getAcceleration() double GCodePathConfig::getAcceleration() const
{ {
return current_config.acceleration; return speed_derivatives.acceleration;
} }
double GCodePathConfig::getJerk() double GCodePathConfig::getJerk() const
{ {
return current_config.jerk; return speed_derivatives.jerk;
} }
int GCodePathConfig::getLineWidth() int GCodePathConfig::getLineWidth() const
{ {
return current_config.line_width; return line_width;
} }
bool GCodePathConfig::isTravelPath() bool GCodePathConfig::isTravelPath() const
{ {
return current_config.line_width == 0; return line_width == 0;
} }
double GCodePathConfig::getFlowPercentage() double GCodePathConfig::getFlowPercentage() const
{ {
return current_config.flow; return flow;
} }
void GCodePathConfig::calculateExtrusion() double GCodePathConfig::calculateExtrusion() const
{ {
extrusion_mm3_per_mm = INT2MM(current_config.line_width) * INT2MM(layer_thickness) * double(current_config.flow) / 100.0; return INT2MM(line_width) * INT2MM(layer_thickness) * double(flow) / 100.0;
} }
+24 -48
Ver Arquivo
@@ -16,94 +16,70 @@ class GCodePathConfig
friend class GCodePlannerTest; friend class GCodePlannerTest;
public: public:
/*! /*!
* The path config settings which may change from layer to layer * A simple wrapper class for all derivatives of position which are used when printing a line
*/ */
struct BasicConfig struct SpeedDerivatives
{ {
double speed; //!< movement speed (mm/s) double speed; //!< movement speed (mm/s)
double acceleration; //!< acceleration of head movement (mm/s^2) double acceleration; //!< acceleration of head movement (mm/s^2)
double jerk; //!< jerk of the head movement (around stand still) (mm/s^3) double jerk; //!< jerk of the head movement (around stand still) as instantaneous speed change (mm/s)
int line_width; //!< width of the line extruded
double flow; //!< extrusion flow modifier in %
BasicConfig(); //!< basic contructor initializing with inaccurate values
BasicConfig(double speed, double acceleration, double jerk, int line_width, double flow); //!< basic contructor initializing all values
void set(double speed, double acceleration, double jerk, int line_width, double flow); //!< Set all config values
}; };
private:
BasicConfig iconic_config; //!< The basic path configuration iconic to this print feature type
BasicConfig current_config; //!< The current path configuration for the current layer
int layer_thickness; //!< current layer height in micron
double extrusion_mm3_per_mm;//!< current mm^3 filament moved per mm line traversed
public:
const PrintFeatureType type; //!< name of the feature type const PrintFeatureType type; //!< name of the feature type
private:
SpeedDerivatives speed_derivatives; //!< The speed settings (and acceleration and jerk) of the extruded line. May be changed when smoothSpeed is called.
const int line_width; //!< width of the line extruded
const int layer_thickness; //!< current layer height in micron
const double flow; //!< extrusion flow modifier in %
const double extrusion_mm3_per_mm;//!< current mm^3 filament moved per mm line traversed
public:
GCodePathConfig(PrintFeatureType type, int line_width, int layer_height, double flow, SpeedDerivatives speed_derivatives); // , SpeedDerivatives slowdown_speed_derivatives, int layer_nr, int max_speed_layer_nr);
/*! /*!
* Basic constructor. * copy constructor
*/ */
GCodePathConfig(PrintFeatureType type); GCodePathConfig(const GCodePathConfig& other);
/*!
* Initialize some of the member variables.
*
* \warning GCodePathConfig::setLayerHeight still has to be called before this object can be used.
*
* \param speed The regular speed with which to print this feature
* \param line_width The line width for this feature
* \param flow The flow modifier to apply to the extruded filament when printing this feature
*/
void init(double speed, double acceleration, double jerk, int line_width, double flow);
/*!
* Set the layer height and (re)compute the extrusion_per_mm
*/
void setLayerHeight(int layer_height);
/*! /*!
* Set the speed to somewhere between the speed of @p first_layer_config and the iconic speed. * Set the speed to somewhere between the speed of @p first_layer_config and the iconic speed.
* *
* \warning This functions should not be called with @p layer_nr > @p max_speed_layer ! * \warning This functions should not be called with @p layer_nr > @p max_speed_layer !
* *
* \warning Calling this function twice will smooth the speed more toward \p first_layer_config
*
* \param first_layer_config The speed settings at layer zero * \param first_layer_config The speed settings at layer zero
* \param layer_nr The layer number * \param layer_nr The layer number
* \param max_speed_layer The layer number for which the speed_iconic should be used. * \param max_speed_layer The layer number for which the speed_iconic should be used.
*/ */
void smoothSpeed(BasicConfig first_layer_config, int layer_nr, double max_speed_layer); void smoothSpeed(SpeedDerivatives first_layer_config, int layer_nr, int max_speed_layer);
/*!
* Set the speed config to the iconic speed config, i.e. the normal speed of the feature type for which this is a config.
*
* Does the same for acceleration and jerk.
*/
void setSpeedIconic();
/*! /*!
* Can only be called after the layer height has been set (which is done while writing the gcode!) * Can only be called after the layer height has been set (which is done while writing the gcode!)
*/ */
double getExtrusionMM3perMM(); double getExtrusionMM3perMM() const;
/*! /*!
* Get the movement speed in mm/s * Get the movement speed in mm/s
*/ */
double getSpeed(); double getSpeed() const;
/*! /*!
* Get the current acceleration of this config * Get the current acceleration of this config
*/ */
double getAcceleration(); double getAcceleration() const;
/*! /*!
* Get the current jerk of this config * Get the current jerk of this config
*/ */
double getJerk(); double getJerk() const;
int getLineWidth(); int getLineWidth() const;
bool isTravelPath(); bool isTravelPath() const;
double getFlowPercentage(); double getFlowPercentage() const;
private: private:
void calculateExtrusion(); double calculateExtrusion() const;
}; };
+5 -5
Ver Arquivo
@@ -17,7 +17,7 @@ void LayerPlanBuffer::flush()
} }
while (!buffer.empty()) while (!buffer.empty())
{ {
buffer.front().writeGCode(gcode); buffer.front()->writeGCode(gcode);
if (CommandSocket::isInstantiated()) if (CommandSocket::isInstantiated())
{ {
CommandSocket::getInstance()->flushGcode(); CommandSocket::getInstance()->flushGcode();
@@ -324,7 +324,7 @@ void LayerPlanBuffer::insertFinalPrintTempCommand(std::vector<ExtruderPlan*>& ex
void LayerPlanBuffer::insertTempCommands() void LayerPlanBuffer::insertTempCommands()
{ {
if (buffer.back().extruder_plans.size() == 0 || (buffer.back().extruder_plans.size() == 1 && buffer.back().extruder_plans[0].paths.size() == 0)) if (buffer.back()->extruder_plans.size() == 0 || (buffer.back()->extruder_plans.size() == 1 && buffer.back()->extruder_plans[0].paths.size() == 0))
{ // disregard empty layer { // disregard empty layer
buffer.pop_back(); buffer.pop_back();
return; return;
@@ -332,9 +332,9 @@ void LayerPlanBuffer::insertTempCommands()
std::vector<ExtruderPlan*> extruder_plans; std::vector<ExtruderPlan*> extruder_plans;
extruder_plans.reserve(buffer.size() * 2); extruder_plans.reserve(buffer.size() * 2);
for (GCodePlanner& layer_plan : buffer) for (GCodePlanner* layer_plan : buffer)
{ {
for (ExtruderPlan& extr_plan : layer_plan.extruder_plans) for (ExtruderPlan& extr_plan : layer_plan->extruder_plans)
{ {
extruder_plans.push_back(&extr_plan); extruder_plans.push_back(&extr_plan);
} }
@@ -342,7 +342,7 @@ void LayerPlanBuffer::insertTempCommands()
// insert commands for all extruder plans on this layer // insert commands for all extruder plans on this layer
GCodePlanner& layer_plan = buffer.back(); GCodePlanner& layer_plan = *buffer.back();
for (unsigned int extruder_plan_idx = 0; extruder_plan_idx < layer_plan.extruder_plans.size(); extruder_plan_idx++) for (unsigned int extruder_plan_idx = 0; extruder_plan_idx < layer_plan.extruder_plans.size(); extruder_plan_idx++)
{ {
unsigned int overall_extruder_plan_idx = extruder_plans.size() - layer_plan.extruder_plans.size() + extruder_plan_idx; unsigned int overall_extruder_plan_idx = extruder_plans.size() - layer_plan.extruder_plans.size() + extruder_plan_idx;
+19 -9
Ver Arquivo
@@ -42,7 +42,7 @@ class LayerPlanBuffer : SettingsMessenger
std::vector<bool> extruder_used_in_meshgroup; //!< For each extruder whether it has already been planned once in this meshgroup. This is used to see whether we should heat to the initial_print_temp or to the printing_temperature std::vector<bool> extruder_used_in_meshgroup; //!< For each extruder whether it has already been planned once in this meshgroup. This is used to see whether we should heat to the initial_print_temp or to the printing_temperature
public: public:
std::list<GCodePlanner> buffer; //!< The buffer containing several layer plans (GCodePlanner) before writing them to gcode. std::list<GCodePlanner*> buffer; //!< The buffer containing several layer plans (GCodePlanner) before writing them to gcode.
LayerPlanBuffer(SettingsBaseVirtual* settings, GCodeExport& gcode) LayerPlanBuffer(SettingsBaseVirtual* settings, GCodeExport& gcode)
: SettingsMessenger(settings) : SettingsMessenger(settings)
@@ -54,29 +54,39 @@ public:
{ {
preheat_config.setConfig(settings); preheat_config.setConfig(settings);
} }
/*! /*!
* Place a new layer plan (GcodePlanner) by constructing it with the given arguments. * Push a new layer plan into the buffer
* Pop back the oldest layer plan is it exceeds the buffer size and write it to gcode.
*/ */
template<typename... Args> void push(GCodePlanner& layer_plan)
GCodePlanner& emplace_back(Args&&... constructor_args) {
buffer.push_back(&layer_plan);
}
/*!
* Process all layers in the buffer
* This inserts the temperature commands to start warming for a given layer in earlier layers
*
* Pop out the earliest layer in the buffer if the buffer size is exceeded
* \return A nullptr or the popped gcode_layer
*/
GCodePlanner* processBuffer()
{ {
if (buffer.size() > 0) if (buffer.size() > 0)
{ {
insertTempCommands(); // insert preheat commands of the just completed layer plan (not the newly emplaced one) insertTempCommands(); // insert preheat commands of the just completed layer plan (not the newly emplaced one)
} }
buffer.emplace_back(constructor_args...);
if (buffer.size() > buffer_size) if (buffer.size() > buffer_size)
{ {
buffer.front().writeGCode(gcode); GCodePlanner* ret = buffer.front();
if (CommandSocket::isInstantiated()) if (CommandSocket::isInstantiated())
{ {
CommandSocket::getInstance()->flushGcode(); CommandSocket::getInstance()->flushGcode();
} }
buffer.pop_front(); buffer.pop_front();
return ret;
} }
return buffer.back(); return nullptr;
} }
/*! /*!
+13 -4
Ver Arquivo
@@ -17,7 +17,7 @@ class MergeInfillLines
std::vector<GCodePath>& paths; //!< The paths currently under consideration std::vector<GCodePath>& paths; //!< The paths currently under consideration
ExtruderPlan& extruder_plan; //!< The extruder plan of the paths currently under consideration ExtruderPlan& extruder_plan; //!< The extruder plan of the paths currently under consideration
GCodePathConfig& travelConfig; //!< The travel settings used to see whether a path is a travel path or an extrusion path const GCodePathConfig& travelConfig; //!< The travel settings used to see whether a path is a travel path or an extrusion path
int64_t nozzle_size; //!< The diameter of the hole in the nozzle int64_t nozzle_size; //!< The diameter of the hole in the nozzle
bool speed_equalize_flow_enabled; //!< Should the speed be varied with extrusion width bool speed_equalize_flow_enabled; //!< Should the speed be varied with extrusion width
double speed_equalize_flow_max; //!< Maximum speed when adjusting speed for flow double speed_equalize_flow_max; //!< Maximum speed when adjusting speed for flow
@@ -64,9 +64,18 @@ public:
/*! /*!
* Simple constructor only used by MergeInfillLines::isConvertible to easily convey the environment * Simple constructor only used by MergeInfillLines::isConvertible to easily convey the environment
*/ */
MergeInfillLines(GCodeExport& gcode, int layer_nr, std::vector<GCodePath>& paths, ExtruderPlan& extruder_plan, GCodePathConfig& travelConfig, int64_t nozzle_size, bool speed_equalize_flow_enabled, double speed_equalize_flow_max) MergeInfillLines(GCodeExport& gcode, int layer_nr, std::vector<GCodePath>& paths, ExtruderPlan& extruder_plan, const GCodePathConfig& travelConfig, int64_t nozzle_size, bool speed_equalize_flow_enabled, double speed_equalize_flow_max)
: gcode(gcode), layer_nr(layer_nr), paths(paths), extruder_plan(extruder_plan), travelConfig(travelConfig), nozzle_size(nozzle_size), speed_equalize_flow_enabled(speed_equalize_flow_enabled), speed_equalize_flow_max(speed_equalize_flow_max) { } : gcode(gcode)
, layer_nr(layer_nr)
, paths(paths)
, extruder_plan(extruder_plan)
, travelConfig(travelConfig)
, nozzle_size(nozzle_size)
, speed_equalize_flow_enabled(speed_equalize_flow_enabled)
, speed_equalize_flow_max(speed_equalize_flow_max)
{
}
/*! /*!
* Check for lots of small moves and combine them into one large line. * Check for lots of small moves and combine them into one large line.
* Updates \p path_idx to the next path which is not combined. * Updates \p path_idx to the next path which is not combined.
+14 -52
Ver Arquivo
@@ -15,12 +15,7 @@ namespace cura
PrimeTower::PrimeTower(const SliceDataStorage& storage) PrimeTower::PrimeTower(const SliceDataStorage& storage)
: is_hollow(false) : is_hollow(false)
, wipe_from_middle(false) , wipe_from_middle(false)
, current_pre_wipe_location_idx(0)
{ {
for (int extruder_nr = 0; extruder_nr < MAX_EXTRUDERS; extruder_nr++)
{
last_prime_tower_poly_printed[extruder_nr] = -1;
}
enabled = storage.getSettingBoolean("prime_tower_enable") enabled = storage.getSettingBoolean("prime_tower_enable")
&& storage.getSettingInMicrons("prime_tower_wall_thickness") > 10 && storage.getSettingInMicrons("prime_tower_wall_thickness") > 10
&& storage.getSettingInMicrons("prime_tower_size") > 10; && storage.getSettingInMicrons("prime_tower_size") > 10;
@@ -30,34 +25,6 @@ PrimeTower::PrimeTower(const SliceDataStorage& storage)
} }
} }
void PrimeTower::initConfigs(const MeshGroup* meshgroup)
{
extruder_count = meshgroup->getExtruderCount();
for (int extr = 0; extr < extruder_count; extr++)
{
config_per_extruder.emplace_back(PrintFeatureType::Support);// so that visualization in the old Cura still works (TODO)
}
for (int extr = 0; extr < extruder_count; extr++)
{
const ExtruderTrain* train = meshgroup->getExtruderTrain(extr);
config_per_extruder[extr].init(train->getSettingInMillimetersPerSecond("speed_prime_tower"), train->getSettingInMillimetersPerSecond("acceleration_prime_tower"), train->getSettingInMillimetersPerSecond("jerk_prime_tower"), train->getSettingInMicrons("prime_tower_line_width"), train->getSettingInPercentage("prime_tower_flow"));
}
}
void PrimeTower::setConfigs(const MeshGroup* meshgroup, const int layer_thickness)
{
extruder_count = meshgroup->getExtruderCount();
for (int extr = 0; extr < extruder_count; extr++)
{
GCodePathConfig& conf = config_per_extruder[extr];
conf.setLayerHeight(layer_thickness);
}
}
void PrimeTower::generateGroundpoly(const SliceDataStorage& storage) void PrimeTower::generateGroundpoly(const SliceDataStorage& storage)
{ {
extruder_count = storage.meshgroup->getExtruderCount(); extruder_count = storage.meshgroup->getExtruderCount();
@@ -127,18 +94,13 @@ void PrimeTower::generatePaths_denseInfill(const SliceDataStorage& storage)
} }
void PrimeTower::addToGcode(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, const GCodeExport& gcode, const int layer_nr, const int prev_extruder, const int new_extruder) void PrimeTower::addToGcode(const SliceDataStorage& storage, GCodePlanner& gcodeLayer, const GCodeExport& gcode, const int layer_nr, const int prev_extruder, const int new_extruder) const
{ {
if (!enabled) if (!enabled)
{ {
return; return;
} }
bool prime_tower_added = false; if (gcodeLayer.getPrimeTowerIsPlanned())
for (int extruder = 0; extruder < storage.meshgroup->getExtruderCount() && !prime_tower_added; extruder++)
{
prime_tower_added = last_prime_tower_poly_printed[extruder] == int(layer_nr);
}
if (prime_tower_added)
{ // don't print the prime tower if it has been printed already { // don't print the prime tower if it has been printed already
return; return;
} }
@@ -159,7 +121,7 @@ void PrimeTower::addToGcode(const SliceDataStorage& storage, GCodePlanner& gcode
// pre-wipe: // pre-wipe:
if (pre_wipe) if (pre_wipe)
{ {
preWipe(storage, gcodeLayer, new_extruder); preWipe(storage, gcodeLayer, layer_nr, new_extruder);
} }
addToGcode_denseInfill(gcodeLayer, layer_nr, new_extruder); addToGcode_denseInfill(gcodeLayer, layer_nr, new_extruder);
@@ -169,21 +131,21 @@ void PrimeTower::addToGcode(const SliceDataStorage& storage, GCodePlanner& gcode
{ //Make sure we wipe the old extruder on the prime tower. { //Make sure we wipe the old extruder on the prime tower.
gcodeLayer.addTravel(post_wipe_point - gcode.getExtruderOffset(prev_extruder) + gcode.getExtruderOffset(new_extruder)); gcodeLayer.addTravel(post_wipe_point - gcode.getExtruderOffset(prev_extruder) + gcode.getExtruderOffset(new_extruder));
} }
gcodeLayer.setPrimeTowerIsPlanned();
} }
void PrimeTower::addToGcode_denseInfill(GCodePlanner& gcodeLayer, const int layer_nr, const int extruder) void PrimeTower::addToGcode_denseInfill(GCodePlanner& gcode_layer, const int layer_nr, const int extruder_nr) const
{ {
ExtrusionMoves& pattern = patterns_per_extruder[extruder][((layer_nr % 2) + 2) % 2]; // +2) %2 to handle negative layer numbers const ExtrusionMoves& pattern = patterns_per_extruder[extruder_nr][((layer_nr % 2) + 2) % 2]; // +2) %2 to handle negative layer numbers
GCodePathConfig& config = config_per_extruder[extruder]; const GCodePathConfig& config = gcode_layer.configs_storage.prime_tower_config_per_extruder[extruder_nr];
gcodeLayer.addPolygonsByOptimizer(pattern.polygons, &config); gcode_layer.addPolygonsByOptimizer(pattern.polygons, &config);
gcodeLayer.addLinesByOptimizer(pattern.lines, &config, SpaceFillType::Lines); gcode_layer.addLinesByOptimizer(pattern.lines, &config, SpaceFillType::Lines);
last_prime_tower_poly_printed[extruder] = layer_nr;
} }
Point PrimeTower::getLocationBeforePrimeTower(const SliceDataStorage& storage) Point PrimeTower::getLocationBeforePrimeTower(const SliceDataStorage& storage) const
{ {
Point ret(0, 0); Point ret(0, 0);
int absolute_starting_points = 0; int absolute_starting_points = 0;
@@ -263,10 +225,10 @@ void PrimeTower::generateWipeLocations(const SliceDataStorage& storage)
PolygonUtils::spreadDots(segment_start, segment_end, number_of_pre_wipe_locations, pre_wipe_locations); PolygonUtils::spreadDots(segment_start, segment_end, number_of_pre_wipe_locations, pre_wipe_locations);
} }
void PrimeTower::preWipe(const SliceDataStorage& storage, GCodePlanner& gcode_layer, const int extruder_nr) void PrimeTower::preWipe(const SliceDataStorage& storage, GCodePlanner& gcode_layer, const int layer_nr, const int extruder_nr) const
{ {
int current_pre_wipe_location_idx = (pre_wipe_location_skip * layer_nr) % number_of_pre_wipe_locations;
const ClosestPolygonPoint wipe_location = pre_wipe_locations[current_pre_wipe_location_idx]; const ClosestPolygonPoint wipe_location = pre_wipe_locations[current_pre_wipe_location_idx];
current_pre_wipe_location_idx = (current_pre_wipe_location_idx + pre_wipe_location_skip) % number_of_pre_wipe_locations;
ExtruderTrain& train = *storage.meshgroup->getExtruderTrain(extruder_nr); ExtruderTrain& train = *storage.meshgroup->getExtruderTrain(extruder_nr);
const int inward_dist = train.getSettingInMicrons("machine_nozzle_size") * 3 / 2 ; const int inward_dist = train.getSettingInMicrons("machine_nozzle_size") * 3 / 2 ;
@@ -294,7 +256,7 @@ void PrimeTower::preWipe(const SliceDataStorage& storage, GCodePlanner& gcode_la
gcode_layer.addTravel(start); gcode_layer.addTravel(start);
} }
float flow = 0.0001; // force this path being interpreted as an extrusion path, so that no Z hop will occur (TODO: really separately handle travel and extrusion moves) float flow = 0.0001; // force this path being interpreted as an extrusion path, so that no Z hop will occur (TODO: really separately handle travel and extrusion moves)
gcode_layer.addExtrusionMove(end, &config_per_extruder[extruder_nr], SpaceFillType::None, flow); gcode_layer.addExtrusionMove(end, &gcode_layer.configs_storage.prime_tower_config_per_extruder[extruder_nr], SpaceFillType::None, flow);
} }
void PrimeTower::subtractFromSupport(SliceDataStorage& storage) void PrimeTower::subtractFromSupport(SliceDataStorage& storage)
+5 -27
Ver Arquivo
@@ -34,7 +34,6 @@ private:
Polygons lines; Polygons lines;
}; };
int extruder_count; //!< number of extruders int extruder_count; //!< number of extruders
std::vector<GCodePathConfig> config_per_extruder; //!< Path config for prime tower for each extruder
bool is_hollow; //!< Whether the prime tower is hollow bool is_hollow; //!< Whether the prime tower is hollow
@@ -47,7 +46,6 @@ private:
const unsigned int pre_wipe_location_skip = 13; //!< How big the steps are when stepping through \ref PrimeTower::wipe_locations const unsigned int pre_wipe_location_skip = 13; //!< How big the steps are when stepping through \ref PrimeTower::wipe_locations
const unsigned int number_of_pre_wipe_locations = 21; //!< The required size of \ref PrimeTower::wipe_locations const unsigned int number_of_pre_wipe_locations = 21; //!< The required size of \ref PrimeTower::wipe_locations
// note that the above are two consecutive numbers in the Fibonacci sequence // note that the above are two consecutive numbers in the Fibonacci sequence
int current_pre_wipe_location_idx; //!< Index into \ref PrimeTower::wipe_locations of where to pre-wipe the nozzle
public: public:
bool enabled; //!< Whether the prime tower is enabled. bool enabled; //!< Whether the prime tower is enabled.
@@ -63,21 +61,6 @@ public:
*/ */
PrimeTower(const SliceDataStorage& storage); PrimeTower(const SliceDataStorage& storage);
/*!
* Initialize \ref PrimeTower::config_per_extruder with speed and line width settings.
*
* \param meshgroup Where to retrieve the setttings for each extruder
*/
void initConfigs(const MeshGroup* meshgroup);
/*!
* Complete the \ref PrimeTower::config_per_extruder by settings the layer height.
*
* \param meshgroup Where to retrieve the setttings for each extruder
* \param layer_thickness The current layer thickness
*/
void setConfigs(const MeshGroup* meshgroup, const int layer_thickness);
/*! /*!
* Generate the prime tower area to be used on each layer * Generate the prime tower area to be used on each layer
* *
@@ -104,7 +87,7 @@ public:
* \param prev_extruder The previous extruder with which paths were planned; from which extruder a switch was made * \param prev_extruder The previous extruder with which paths were planned; from which extruder a switch was made
* \param new_extruder The switched to extruder with which the prime tower paths should be generated. * \param new_extruder The switched to extruder with which the prime tower paths should be generated.
*/ */
void addToGcode(const SliceDataStorage& storage, GCodePlanner& gcode_layer, const GCodeExport& gcode, const int layer_nr, const int prev_extruder, const int new_extruder); void addToGcode(const SliceDataStorage& storage, GCodePlanner& gcode_layer, const GCodeExport& gcode, const int layer_nr, const int prev_extruder, const int new_extruder) const;
/*! /*!
* \brief Subtract the prime tower from the support areas in storage. * \brief Subtract the prime tower from the support areas in storage.
@@ -115,12 +98,6 @@ public:
void subtractFromSupport(SliceDataStorage& storage); void subtractFromSupport(SliceDataStorage& storage);
private: private:
/*!
* Layer number of the last layer in which a prime tower has been printed per extruder train.
*
* This is recorded per extruder to account for a prime tower per extruder, instead of the mixed prime tower.
*/
int last_prime_tower_poly_printed[MAX_EXTRUDERS];
/*! /*!
* Find an approriate representation for the point representing the location before going to the prime tower * Find an approriate representation for the point representing the location before going to the prime tower
@@ -130,7 +107,7 @@ private:
* \param storage where to get settings from * \param storage where to get settings from
* \return that location * \return that location
*/ */
Point getLocationBeforePrimeTower(const SliceDataStorage& storage); Point getLocationBeforePrimeTower(const SliceDataStorage& storage) const;
/*! /*!
* \param storage where to get settings from * \param storage where to get settings from
@@ -159,16 +136,17 @@ private:
* \param extruder The extruder we just switched to, with which the prime * \param extruder The extruder we just switched to, with which the prime
* tower paths should be drawn. * tower paths should be drawn.
*/ */
void addToGcode_denseInfill(GCodePlanner& gcode_layer, const int layer_nr, const int extruder); void addToGcode_denseInfill(GCodePlanner& gcode_layer, const int layer_nr, const int extruder) const;
/*! /*!
* Plan the moves for wiping the current nozzles oozed material before starting to print the prime tower. * Plan the moves for wiping the current nozzles oozed material before starting to print the prime tower.
* *
* \param storage where to get settings from * \param storage where to get settings from
* \param[out] gcode_layer where to add the planned paths for wiping * \param[out] gcode_layer where to add the planned paths for wiping
* \param layer_nr The layer number of the \p gcode_layer
* \param extruder_nr The current extruder * \param extruder_nr The current extruder
*/ */
void preWipe(const SliceDataStorage& storage, GCodePlanner& gcode_layer, const int extruder_nr); void preWipe(const SliceDataStorage& storage, GCodePlanner& gcode_layer, const int layer_nr, const int extruder_nr) const;
}; };
+2 -2
Ver Arquivo
@@ -389,7 +389,7 @@ void Weaver::chainify_polygons(Polygons& parts1, Point start_close_to, Polygons&
{ {
for (unsigned int prt = 0 ; prt < parts1.size(); prt++) for (unsigned int prt = 0 ; prt < parts1.size(); prt++)
{ {
const PolygonRef upperPart = parts1[prt]; ConstPolygonRef upperPart = parts1[prt];
ClosestPolygonPoint closestInPoly = PolygonUtils::findClosest(start_close_to, upperPart); ClosestPolygonPoint closestInPoly = PolygonUtils::findClosest(start_close_to, upperPart);
@@ -439,7 +439,7 @@ void Weaver::connect_polygons(Polygons& supporting, int z0, Polygons& supported,
for (unsigned int prt = 0 ; prt < supported.size(); prt++) for (unsigned int prt = 0 ; prt < supported.size(); prt++)
{ {
const PolygonRef upperPart = supported[prt]; ConstPolygonRef upperPart(supported[prt]);
parts.emplace_back(prt); parts.emplace_back(prt);
+1 -1
Ver Arquivo
@@ -5,7 +5,7 @@
namespace cura { namespace cura {
int bridgeAngle(Polygons outline, SliceLayer* prevLayer) int bridgeAngle(Polygons outline, const SliceLayer* prevLayer)
{ {
AABB boundaryBox(outline); AABB boundaryBox(outline);
//To detect if we have a bridge, first calculate the intersection of the current layer with the previous layer. //To detect if we have a bridge, first calculate the intersection of the current layer with the previous layer.
+1 -1
Ver Arquivo
@@ -6,7 +6,7 @@ namespace cura {
class Polygons; class Polygons;
class SliceLayer; class SliceLayer;
int bridgeAngle(Polygons outline, SliceLayer* prevLayer); int bridgeAngle(Polygons outline, const SliceLayer* prevLayer);
}//namespace cura }//namespace cura
+3 -3
Ver Arquivo
@@ -215,7 +215,7 @@ public:
/*! /*!
* Adds closed polygon to the current path * Adds closed polygon to the current path
*/ */
void sendPolygon(PrintFeatureType print_feature_type, Polygon poly, int width); void sendPolygon(PrintFeatureType print_feature_type, ConstPolygonRef poly, int width);
private: private:
/*! /*!
* Convert and add a point to the points buffer, each point being represented as two consecutive floats. All members adding a 2D point to the data should use this function. * Convert and add a point to the points buffer, each point being represented as two consecutive floats. All members adding a 2D point to the data should use this function.
@@ -522,7 +522,7 @@ void CommandSocket::sendPolygons(PrintFeatureType type, const Polygons& polygons
#endif #endif
} }
void CommandSocket::sendPolygon(PrintFeatureType type, Polygon& polygon, int line_width) void CommandSocket::sendPolygon(PrintFeatureType type, ConstPolygonRef polygon, int line_width)
{ {
#ifdef ARCUS #ifdef ARCUS
if (CommandSocket::isInstantiated()) if (CommandSocket::isInstantiated())
@@ -799,7 +799,7 @@ void CommandSocket::PathCompiler::sendLineTo(PrintFeatureType print_feature_type
} }
} }
void CommandSocket::PathCompiler::sendPolygon(PrintFeatureType print_feature_type, Polygon polygon, int width) void CommandSocket::PathCompiler::sendPolygon(PrintFeatureType print_feature_type, ConstPolygonRef polygon, int width)
{ {
if (polygon.size() < 2) if (polygon.size() < 2)
{ {
+1 -1
Ver Arquivo
@@ -64,7 +64,7 @@ public:
/*! /*!
* Send a polygon to the front-end. This is used for the layerview in the GUI * Send a polygon to the front-end. This is used for the layerview in the GUI
*/ */
static void sendPolygon(cura::PrintFeatureType type, Polygon& polygon, int line_width); static void sendPolygon(cura::PrintFeatureType type, ConstPolygonRef polygon, int line_width);
/*! /*!
* Send a line to the front-end. This is used for the layerview in the GUI * Send a line to the front-end. This is used for the layerview in the GUI
+2 -2
Ver Arquivo
@@ -270,7 +270,7 @@ void GCodeExport::setFlavor(EGCodeFlavor flavor)
} }
} }
EGCodeFlavor GCodeExport::getFlavor() EGCodeFlavor GCodeExport::getFlavor() const
{ {
return this->flavor; return this->flavor;
} }
@@ -775,7 +775,7 @@ void GCodeExport::switchExtruder(int new_extruder, const RetractionConfig& retra
bool force = true; bool force = true;
bool extruder_switch = true; bool extruder_switch = true;
writeRetraction(const_cast<RetractionConfig&>(retraction_config_old_extruder), force, extruder_switch); writeRetraction(retraction_config_old_extruder, force, extruder_switch);
resetExtrusionValue(); // zero the E value on the old extruder, so that the current_e_value is registered on the old extruder resetExtrusionValue(); // zero the E value on the old extruder, so that the current_e_value is registered on the old extruder
+1 -1
Ver Arquivo
@@ -188,7 +188,7 @@ public:
Point getGcodePos(const int64_t x, const int64_t y, const int extruder_train) const; Point getGcodePos(const int64_t x, const int64_t y, const int extruder_train) const;
void setFlavor(EGCodeFlavor flavor); void setFlavor(EGCodeFlavor flavor);
EGCodeFlavor getFlavor(); EGCodeFlavor getFlavor() const;
void setZ(int z); void setZ(int z);
+34 -136
Ver Arquivo
@@ -10,7 +10,7 @@
namespace cura { namespace cura {
ExtruderPlan::ExtruderPlan(int extruder, Point start_position, int layer_nr, bool is_initial_layer, int layer_thickness, FanSpeedLayerTimeSettings& fan_speed_layer_time_settings, const RetractionConfig& retraction_config) ExtruderPlan::ExtruderPlan(int extruder, Point start_position, int layer_nr, bool is_initial_layer, int layer_thickness, const FanSpeedLayerTimeSettings& fan_speed_layer_time_settings, const RetractionConfig& retraction_config)
: extruder(extruder) : extruder(extruder)
, heated_pre_travel_time(0) , heated_pre_travel_time(0)
, initial_printing_temperature(-1) , initial_printing_temperature(-1)
@@ -56,7 +56,7 @@ double ExtruderPlan::getFanSpeed()
} }
GCodePath* GCodePlanner::getLatestPathWithConfig(GCodePathConfig* config, SpaceFillType space_fill_type, float flow, bool spiralize) GCodePath* GCodePlanner::getLatestPathWithConfig(const GCodePathConfig* config, SpaceFillType space_fill_type, float flow, bool spiralize)
{ {
std::vector<GCodePath>& paths = extruder_plans.back().paths; std::vector<GCodePath>& paths = extruder_plans.back().paths;
if (paths.size() > 0 && paths.back().config == config && !paths.back().done && paths.back().flow == flow) // spiralize can only change when a travel path is in between if (paths.size() > 0 && paths.back().config == config && !paths.back().done && paths.back().flow == flow) // spiralize can only change when a travel path is in between
@@ -81,23 +81,26 @@ void GCodePlanner::forceNewPathStart()
paths[paths.size()-1].done = true; paths[paths.size()-1].done = true;
} }
GCodePlanner::GCodePlanner(SliceDataStorage& storage, int layer_nr, int z, int layer_thickness, Point last_position, int current_extruder, bool is_inside_mesh, std::vector<FanSpeedLayerTimeSettings>& fan_speed_layer_time_settings_per_extruder, CombingMode combing_mode, int64_t comb_boundary_offset, bool travel_avoid_other_parts, int64_t travel_avoid_distance) GCodePlanner::GCodePlanner(const SliceDataStorage& storage, int layer_nr, int z, int layer_thickness, PlanningState last_planned_state, const std::vector<FanSpeedLayerTimeSettings>& fan_speed_layer_time_settings_per_extruder, CombingMode combing_mode, int64_t comb_boundary_offset, bool travel_avoid_other_parts, int64_t travel_avoid_distance)
: storage(storage) : storage(storage)
, configs_storage(storage, layer_nr, layer_thickness)
, layer_nr(layer_nr) , layer_nr(layer_nr)
, is_initial_layer(layer_nr == 0 - Raft::getTotalExtraLayers(storage)) , is_initial_layer(layer_nr == 0 - Raft::getTotalExtraLayers(storage))
, z(z) , z(z)
, layer_thickness(layer_thickness) , layer_thickness(layer_thickness)
, start_position(last_position) , start_position(last_planned_state.last_position)
, lastPosition(last_position) , lastPosition(last_planned_state.last_position)
, last_extruder_previous_layer(current_extruder) , has_prime_tower_planned(false)
, last_planned_extruder_setting_base(storage.meshgroup->getExtruderTrain(current_extruder)) , last_extruder_previous_layer(last_planned_state.current_extruder)
, last_planned_extruder_setting_base(storage.meshgroup->getExtruderTrain(last_planned_state.current_extruder))
, comb_boundary_inside(computeCombBoundaryInside(combing_mode)) , comb_boundary_inside(computeCombBoundaryInside(combing_mode))
, fan_speed_layer_time_settings_per_extruder(fan_speed_layer_time_settings_per_extruder) , fan_speed_layer_time_settings_per_extruder(fan_speed_layer_time_settings_per_extruder)
{ {
int current_extruder = last_planned_state.current_extruder;
extruder_plans.reserve(storage.meshgroup->getExtruderCount()); extruder_plans.reserve(storage.meshgroup->getExtruderCount());
extruder_plans.emplace_back(current_extruder, start_position, layer_nr, is_initial_layer, layer_thickness, fan_speed_layer_time_settings_per_extruder[current_extruder], storage.retraction_config_per_extruder[current_extruder]); extruder_plans.emplace_back(current_extruder, start_position, layer_nr, is_initial_layer, layer_thickness, fan_speed_layer_time_settings_per_extruder[current_extruder], storage.retraction_config_per_extruder[current_extruder]);
comb = nullptr; comb = nullptr;
was_inside = is_inside_mesh; was_inside = last_planned_state.is_inside_mesh_layer_part;
is_inside = false; // assumes the next move will not be to inside a layer part (overwritten just before going into a layer part) is_inside = false; // assumes the next move will not be to inside a layer part (overwritten just before going into a layer part)
if (combing_mode != CombingMode::OFF) if (combing_mode != CombingMode::OFF)
{ {
@@ -139,12 +142,12 @@ Polygons GCodePlanner::computeCombBoundaryInside(CombingMode combing_mode)
else else
{ {
Polygons comb_boundary; Polygons comb_boundary;
for (SliceMeshStorage& mesh : storage.meshes) for (const SliceMeshStorage& mesh : storage.meshes)
{ {
SliceLayer& layer = mesh.layers[layer_nr]; const SliceLayer& layer = mesh.layers[layer_nr];
if (mesh.getSettingAsCombingMode("retraction_combing") == CombingMode::NO_SKIN) if (mesh.getSettingAsCombingMode("retraction_combing") == CombingMode::NO_SKIN)
{ {
for (SliceLayerPart& part : layer.parts) for (const SliceLayerPart& part : layer.parts)
{ {
comb_boundary.add(part.infill_area); comb_boundary.add(part.infill_area);
} }
@@ -241,12 +244,12 @@ void GCodePlanner::moveInsideCombBoundary(int distance)
GCodePath& GCodePlanner::addTravel(Point p) GCodePath& GCodePlanner::addTravel(Point p)
{ {
GCodePath* path = nullptr; GCodePath* path = nullptr;
GCodePathConfig& travel_config = storage.travel_config_per_extruder[getExtruder()]; const GCodePathConfig& travel_config = configs_storage.travel_config_per_extruder[getExtruder()];
RetractionConfig& retraction_config = storage.retraction_config_per_extruder[getExtruder()]; const RetractionConfig& retraction_config = storage.retraction_config_per_extruder[getExtruder()];
bool combed = false; bool combed = false;
SettingsBaseVirtual* extr = getLastPlannedExtruderTrainSettings(); const SettingsBaseVirtual* extr = getLastPlannedExtruderTrainSettings();
const bool perform_z_hops = extr->getSettingBoolean("retraction_hop_enabled"); const bool perform_z_hops = extr->getSettingBoolean("retraction_hop_enabled");
@@ -333,7 +336,7 @@ GCodePath& GCodePlanner::addTravel_simple(Point p, GCodePath* path)
{ {
if (path == nullptr) if (path == nullptr)
{ {
path = getLatestPathWithConfig(&storage.travel_config_per_extruder[getExtruder()], SpaceFillType::None); path = getLatestPathWithConfig(&configs_storage.travel_config_per_extruder[getExtruder()], SpaceFillType::None);
} }
path->points.push_back(p); path->points.push_back(p);
lastPosition = p; lastPosition = p;
@@ -349,13 +352,13 @@ void GCodePlanner::planPrime()
forceNewPathStart(); forceNewPathStart();
} }
void GCodePlanner::addExtrusionMove(Point p, GCodePathConfig* config, SpaceFillType space_fill_type, float flow, bool spiralize) void GCodePlanner::addExtrusionMove(Point p, const GCodePathConfig* config, SpaceFillType space_fill_type, float flow, bool spiralize)
{ {
getLatestPathWithConfig(config, space_fill_type, flow, spiralize)->points.push_back(p); getLatestPathWithConfig(config, space_fill_type, flow, spiralize)->points.push_back(p);
lastPosition = p; lastPosition = p;
} }
void GCodePlanner::addPolygon(PolygonRef polygon, int start_idx, GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation, coord_t wall_0_wipe_dist, bool spiralize) void GCodePlanner::addPolygon(ConstPolygonRef polygon, int start_idx, const GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation, coord_t wall_0_wipe_dist, bool spiralize)
{ {
Point p0 = polygon[start_idx]; Point p0 = polygon[start_idx];
addTravel(p0); addTravel(p0);
@@ -368,7 +371,7 @@ void GCodePlanner::addPolygon(PolygonRef polygon, int start_idx, GCodePathConfig
} }
if (polygon.size() > 2) if (polygon.size() > 2)
{ {
Point& p1 = polygon[start_idx]; const Point& p1 = polygon[start_idx];
float flow = (wall_overlap_computation)? wall_overlap_computation->getFlow(p0, p1) : 1.0; float flow = (wall_overlap_computation)? wall_overlap_computation->getFlow(p0, p1) : 1.0;
addExtrusionMove(p1, config, SpaceFillType::Polygons, flow, spiralize); addExtrusionMove(p1, config, SpaceFillType::Polygons, flow, spiralize);
@@ -403,7 +406,7 @@ void GCodePlanner::addPolygon(PolygonRef polygon, int start_idx, GCodePathConfig
} }
} }
void GCodePlanner::addPolygonsByOptimizer(Polygons& polygons, GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation, EZSeamType z_seam_type, Point z_seam_pos, coord_t wall_0_wipe_dist, bool spiralize) void GCodePlanner::addPolygonsByOptimizer(const Polygons& polygons, const GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation, EZSeamType z_seam_type, Point z_seam_pos, coord_t wall_0_wipe_dist, bool spiralize)
{ {
if (polygons.size() == 0) if (polygons.size() == 0)
{ {
@@ -420,7 +423,7 @@ void GCodePlanner::addPolygonsByOptimizer(Polygons& polygons, GCodePathConfig* c
addPolygon(polygons[poly_idx], orderOptimizer.polyStart[poly_idx], config, wall_overlap_computation, wall_0_wipe_dist, spiralize); addPolygon(polygons[poly_idx], orderOptimizer.polyStart[poly_idx], config, wall_overlap_computation, wall_0_wipe_dist, spiralize);
} }
} }
void GCodePlanner::addLinesByOptimizer(Polygons& polygons, GCodePathConfig* config, SpaceFillType space_fill_type, int wipe_dist) void GCodePlanner::addLinesByOptimizer(const Polygons& polygons, const GCodePathConfig* config, SpaceFillType space_fill_type, int wipe_dist)
{ {
LineOrderOptimizer orderOptimizer(lastPosition); LineOrderOptimizer orderOptimizer(lastPosition);
for (unsigned int line_idx = 0; line_idx < polygons.size(); line_idx++) for (unsigned int line_idx = 0; line_idx < polygons.size(); line_idx++)
@@ -430,12 +433,12 @@ void GCodePlanner::addLinesByOptimizer(Polygons& polygons, GCodePathConfig* conf
orderOptimizer.optimize(); orderOptimizer.optimize();
for (int poly_idx : orderOptimizer.polyOrder) for (int poly_idx : orderOptimizer.polyOrder)
{ {
PolygonRef polygon = polygons[poly_idx]; ConstPolygonRef polygon = polygons[poly_idx];
int start = orderOptimizer.polyStart[poly_idx]; int start = orderOptimizer.polyStart[poly_idx];
int end = 1 - start; int end = 1 - start;
Point& p0 = polygon[start]; const Point& p0 = polygon[start];
addTravel(p0); addTravel(p0);
Point& p1 = polygon[end]; const Point& p1 = polygon[end];
addExtrusionMove(p1, config, space_fill_type); addExtrusionMove(p1, config, space_fill_type);
if (wipe_dist != 0) if (wipe_dist != 0)
{ {
@@ -553,7 +556,7 @@ TimeMaterialEstimates ExtruderPlan::computeNaiveTimeEstimates()
void ExtruderPlan::processFanSpeedAndMinimalLayerTime(bool force_minimal_layer_time) void ExtruderPlan::processFanSpeedAndMinimalLayerTime(bool force_minimal_layer_time)
{ {
FanSpeedLayerTimeSettings& fsml = fan_speed_layer_time_settings; const FanSpeedLayerTimeSettings& fsml = fan_speed_layer_time_settings;
TimeMaterialEstimates estimates = computeNaiveTimeEstimates(); TimeMaterialEstimates estimates = computeNaiveTimeEstimates();
totalPrintTime = estimates.getTotalTime(); totalPrintTime = estimates.getTotalTime();
if (force_minimal_layer_time) if (force_minimal_layer_time)
@@ -636,8 +639,6 @@ void GCodePlanner::processFanSpeedAndMinimalLayerTime()
void GCodePlanner::writeGCode(GCodeExport& gcode) void GCodePlanner::writeGCode(GCodeExport& gcode)
{ {
completeConfigs();
CommandSocket::setLayerForSend(layer_nr); CommandSocket::setLayerForSend(layer_nr);
CommandSocket::setSendCurrentPosition( gcode.getPositionXY() ); CommandSocket::setSendCurrentPosition( gcode.getPositionXY() );
gcode.setLayerNr(layer_nr); gcode.setLayerNr(layer_nr);
@@ -653,7 +654,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
gcode.setZ(z); gcode.setZ(z);
GCodePathConfig* last_extrusion_config = nullptr; // used to check whether we need to insert a TYPE comment in the gcode. const GCodePathConfig* last_extrusion_config = nullptr; // used to check whether we need to insert a TYPE comment in the gcode.
int extruder = gcode.getExtruderNr(); int extruder = gcode.getExtruderNr();
bool acceleration_enabled = storage.getSettingBoolean("acceleration_enabled"); bool acceleration_enabled = storage.getSettingBoolean("acceleration_enabled");
@@ -662,7 +663,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
for(unsigned int extruder_plan_idx = 0; extruder_plan_idx < extruder_plans.size(); extruder_plan_idx++) for(unsigned int extruder_plan_idx = 0; extruder_plan_idx < extruder_plans.size(); extruder_plan_idx++)
{ {
ExtruderPlan& extruder_plan = extruder_plans[extruder_plan_idx]; ExtruderPlan& extruder_plan = extruder_plans[extruder_plan_idx];
RetractionConfig& retraction_config = storage.retraction_config_per_extruder[extruder_plan.extruder]; const RetractionConfig& retraction_config = storage.retraction_config_per_extruder[extruder_plan.extruder];
if (extruder != extruder_plan.extruder) if (extruder != extruder_plan.extruder)
{ {
@@ -764,7 +765,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
else else
speed *= extruder_plan.getExtrudeSpeedFactor(); speed *= extruder_plan.getExtrudeSpeedFactor();
if (MergeInfillLines(gcode, layer_nr, paths, extruder_plan, storage.travel_config_per_extruder[extruder], nozzle_size, speed_equalize_flow_enabled, speed_equalize_flow_max).mergeInfillLines(path_idx)) // !! has effect on path_idx !! if (MergeInfillLines(gcode, layer_nr, paths, extruder_plan, configs_storage.travel_config_per_extruder[extruder], nozzle_size, speed_equalize_flow_enabled, speed_equalize_flow_max).mergeInfillLines(path_idx)) // !! has effect on path_idx !!
{ // !! has effect on path_idx !! { // !! has effect on path_idx !!
// works when path_idx is the index of the travel move BEFORE the infill lines to be merged // works when path_idx is the index of the travel move BEFORE the infill lines to be merged
continue; continue;
@@ -787,7 +788,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
bool spiralize = path.spiralize; bool spiralize = path.spiralize;
if (!spiralize) // normal (extrusion) move (with coasting if (!spiralize) // normal (extrusion) move (with coasting
{ {
CoastingConfig& coasting_config = storage.coasting_config[extruder]; const CoastingConfig& coasting_config = storage.coasting_config[extruder];
bool coasting = coasting_config.coasting_enable; bool coasting = coasting_config.coasting_enable;
if (coasting) if (coasting)
{ {
@@ -858,15 +859,15 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
if (train->getSettingBoolean("cool_lift_head") && extruder_plan.extraTime > 0.0) if (train->getSettingBoolean("cool_lift_head") && extruder_plan.extraTime > 0.0)
{ {
gcode.writeComment("Small layer, adding delay"); gcode.writeComment("Small layer, adding delay");
RetractionConfig& retraction_config = storage.retraction_config_per_extruder[gcode.getExtruderNr()]; const RetractionConfig& retraction_config = storage.retraction_config_per_extruder[gcode.getExtruderNr()];
gcode.writeRetraction(retraction_config); gcode.writeRetraction(retraction_config);
if (extruder_plan_idx == extruder_plans.size() - 1 || !train->getSettingBoolean("machine_extruder_end_pos_abs")) if (extruder_plan_idx == extruder_plans.size() - 1 || !train->getSettingBoolean("machine_extruder_end_pos_abs"))
{ // only move the head if it's the last extruder plan; otherwise it's already at the switching bay area { // only move the head if it's the last extruder plan; otherwise it's already at the switching bay area
// or do it anyway when we switch extruder in-place // or do it anyway when we switch extruder in-place
gcode.setZ(gcode.getPositionZ() + MM2INT(3.0)); gcode.setZ(gcode.getPositionZ() + MM2INT(3.0));
gcode.writeMove(gcode.getPositionXY(), storage.travel_config_per_extruder[extruder].getSpeed(), 0); gcode.writeMove(gcode.getPositionXY(), configs_storage.travel_config_per_extruder[extruder].getSpeed(), 0);
// TODO: is this safe?! wouldn't the head move into the sides then?! // TODO: is this safe?! wouldn't the head move into the sides then?!
gcode.writeMove(gcode.getPositionXY() - Point(-MM2INT(20.0), 0), storage.travel_config_per_extruder[extruder].getSpeed(), 0); gcode.writeMove(gcode.getPositionXY() - Point(-MM2INT(20.0), 0), configs_storage.travel_config_per_extruder[extruder].getSpeed(), 0);
} }
gcode.writeDelay(extruder_plan.extraTime); gcode.writeDelay(extruder_plan.extraTime);
} }
@@ -886,109 +887,6 @@ void GCodePlanner::overrideFanSpeeds(double speed)
} }
void GCodePlanner::completeConfigs()
{
storage.support_config.setLayerHeight(layer_thickness);
storage.support_skin_config.setLayerHeight(layer_thickness);
for (SliceMeshStorage& mesh : storage.meshes)
{
mesh.inset0_config.setLayerHeight(layer_thickness);
mesh.insetX_config.setLayerHeight(layer_thickness);
mesh.skin_config.setLayerHeight(layer_thickness);
mesh.perimeter_gap_config.setLayerHeight(layer_thickness);
for(unsigned int idx=0; idx<MAX_INFILL_COMBINE; idx++)
{
mesh.infill_config[idx].setLayerHeight(layer_thickness);
}
}
storage.primeTower.setConfigs(storage.meshgroup, layer_thickness);
processInitialLayersSpeedup();
}
void GCodePlanner::processInitialLayersSpeedup()
{
int initial_speedup_layers = storage.getSettingAsCount("speed_slowdown_layers");
if (layer_nr >= 0 && layer_nr < initial_speedup_layers)
{
GCodePathConfig::BasicConfig initial_layer_speed_config;
int extruder_nr_support_infill = storage.getSettingAsIndex((layer_nr == 0)? "support_extruder_nr_layer_0" : "support_infill_extruder_nr");
initial_layer_speed_config.speed = storage.meshgroup->getExtruderTrain(extruder_nr_support_infill)->getSettingInMillimetersPerSecond("speed_print_layer_0");
initial_layer_speed_config.acceleration = storage.meshgroup->getExtruderTrain(extruder_nr_support_infill)->getSettingInMillimetersPerSecond("acceleration_print_layer_0");
initial_layer_speed_config.jerk = storage.meshgroup->getExtruderTrain(extruder_nr_support_infill)->getSettingInMillimetersPerSecond("jerk_print_layer_0");
//Support (global).
storage.support_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layers);
//Support roof (global).
int extruder_nr_support_skin = storage.getSettingAsIndex("support_interface_extruder_nr");
initial_layer_speed_config.speed = storage.meshgroup->getExtruderTrain(extruder_nr_support_skin)->getSettingInMillimetersPerSecond("speed_print_layer_0");
initial_layer_speed_config.acceleration = storage.meshgroup->getExtruderTrain(extruder_nr_support_skin)->getSettingInMillimetersPerSecond("acceleration_print_layer_0");
initial_layer_speed_config.jerk = storage.meshgroup->getExtruderTrain(extruder_nr_support_skin)->getSettingInMillimetersPerSecond("jerk_print_layer_0");
storage.support_skin_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layers);
for (int extruder_nr = 0; extruder_nr < storage.meshgroup->getExtruderCount(); ++extruder_nr)
{
const ExtruderTrain* extruder_train = storage.meshgroup->getExtruderTrain(extruder_nr);
initial_layer_speed_config.speed = extruder_train->getSettingInMillimetersPerSecond("speed_travel_layer_0");
initial_layer_speed_config.acceleration = extruder_train->getSettingInMillimetersPerSecond("acceleration_travel_layer_0");
initial_layer_speed_config.jerk = extruder_train->getSettingInMillimetersPerSecond("jerk_travel_layer_0");
//Travel speed (per extruder).
storage.travel_config_per_extruder[extruder_nr].smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layers);
}
for (SliceMeshStorage& mesh : storage.meshes)
{
initial_layer_speed_config.speed = mesh.getSettingInMillimetersPerSecond("speed_print_layer_0");
initial_layer_speed_config.acceleration = mesh.getSettingInMillimetersPerSecond("acceleration_print_layer_0");
initial_layer_speed_config.jerk = mesh.getSettingInMillimetersPerSecond("jerk_print_layer_0");
//Outer wall speed (per mesh).
mesh.inset0_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layers);
//Inner wall speed (per mesh).
mesh.insetX_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layers);
//Skin speed (per mesh).
mesh.skin_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layers);
mesh.perimeter_gap_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layers);
for (unsigned int idx = 0; idx < MAX_INFILL_COMBINE; idx++)
{
//Infill speed (per combine part per mesh).
mesh.infill_config[idx].smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layers);
}
}
}
else if (layer_nr == initial_speedup_layers) //At the topmost layer of the gradient, reset all speeds to the typical speeds.
{
storage.support_config.setSpeedIconic();
storage.support_skin_config.setSpeedIconic();
for (int extruder_nr = 0; extruder_nr < storage.meshgroup->getExtruderCount(); ++extruder_nr)
{
storage.travel_config_per_extruder[extruder_nr].setSpeedIconic();
}
for (SliceMeshStorage& mesh : storage.meshes)
{
mesh.inset0_config.setSpeedIconic();
mesh.insetX_config.setSpeedIconic();
mesh.skin_config.setSpeedIconic();
mesh.perimeter_gap_config.setSpeedIconic();
for (unsigned int idx = 0; idx < MAX_INFILL_COMBINE; idx++)
{
mesh.infill_config[idx].setSpeedIconic();
}
}
}
}
bool GCodePlanner::makeRetractSwitchRetract(GCodeExport& gcode, unsigned int extruder_plan_idx, unsigned int path_idx) bool GCodePlanner::makeRetractSwitchRetract(GCodeExport& gcode, unsigned int extruder_plan_idx, unsigned int path_idx)
{ {
std::vector<GCodePath>& paths = extruder_plans[extruder_plan_idx].paths; std::vector<GCodePath>& paths = extruder_plans[extruder_plan_idx].paths;
+57 -31
Ver Arquivo
@@ -16,6 +16,7 @@
#include "FanSpeedLayerTime.h" #include "FanSpeedLayerTime.h"
#include "SpaceFillType.h" #include "SpaceFillType.h"
#include "GCodePathConfig.h" #include "GCodePathConfig.h"
#include "settings/PathConfigStorage.h"
#include "utils/optional.h" #include "utils/optional.h"
@@ -57,7 +58,7 @@ public:
* \param extruder The extruder number for which this object is a plan. * \param extruder The extruder number for which this object is a plan.
* \param start_position The position the head is when this extruder plan starts * \param start_position The position the head is when this extruder plan starts
*/ */
ExtruderPlan(int extruder, Point start_position, int layer_nr, bool is_initial_layer, int layer_thickness, FanSpeedLayerTimeSettings& fan_speed_layer_time_settings, const RetractionConfig& retraction_config); ExtruderPlan(int extruder, Point start_position, int layer_nr, bool is_initial_layer, int layer_thickness, const FanSpeedLayerTimeSettings& fan_speed_layer_time_settings, const RetractionConfig& retraction_config);
/*! /*!
* Add a new Insert, constructed with the given arguments * Add a new Insert, constructed with the given arguments
@@ -165,7 +166,7 @@ protected:
int layer_thickness; //!< The thickness of this layer in Z-direction int layer_thickness; //!< The thickness of this layer in Z-direction
FanSpeedLayerTimeSettings& fan_speed_layer_time_settings; //!< The fan speed and layer time settings used to limit this extruder plan const FanSpeedLayerTimeSettings& fan_speed_layer_time_settings; //!< The fan speed and layer time settings used to limit this extruder plan
const RetractionConfig& retraction_config; //!< The retraction settings for the extruder of this plan const RetractionConfig& retraction_config; //!< The retraction settings for the extruder of this plan
@@ -215,9 +216,25 @@ class GCodePlanner : public NoCopy
{ {
friend class LayerPlanBuffer; friend class LayerPlanBuffer;
friend class GCodePlannerTest; friend class GCodePlannerTest;
public:
/*!
* The state which is passed along between layer plans.
* This is what a \ref GCodePlanner delivers to further computation in \ref FffGcodeWriter
* This is the state which is currently planned, not which is written to gcode.
*/
struct PlanningState
{
Point last_position; //!< The position of the head before planning the next layer
int current_extruder; //!< The extruder train in use before planning the next layer
bool is_inside_mesh_layer_part; //!< Whether the last position was inside a layer part (used in combing)
};
private: private:
SliceDataStorage& storage; //!< The polygon data obtained from FffPolygonProcessor const SliceDataStorage& storage; //!< The polygon data obtained from FffPolygonProcessor
public:
const PathConfigStorage configs_storage; //!< The line configs for this layer for each feature type
private:
int layer_nr; //!< The layer number of this layer plan int layer_nr; //!< The layer number of this layer plan
int is_initial_layer; //!< Whether this is the first layer (which might be raft) int is_initial_layer; //!< Whether this is the first layer (which might be raft)
@@ -227,7 +244,9 @@ private:
Point start_position; Point start_position;
Point lastPosition; Point lastPosition;
bool has_prime_tower_planned;
std::vector<ExtruderPlan> extruder_plans; //!< should always contain at least one ExtruderPlan std::vector<ExtruderPlan> extruder_plans; //!< should always contain at least one ExtruderPlan
int last_extruder_previous_layer; //!< The last id of the extruder with which was printed in the previous layer int last_extruder_previous_layer; //!< The last id of the extruder with which was printed in the previous layer
@@ -238,7 +257,7 @@ private:
Comb* comb; Comb* comb;
std::vector<FanSpeedLayerTimeSettings>& fan_speed_layer_time_settings_per_extruder; const std::vector<FanSpeedLayerTimeSettings>& fan_speed_layer_time_settings_per_extruder;
private: private:
/*! /*!
@@ -251,7 +270,7 @@ private:
* \param spiralize Whether to gradually increase the z while printing. (Note that this path may be part of a sequence of spiralized paths, forming one polygon) * \param spiralize Whether to gradually increase the z while printing. (Note that this path may be part of a sequence of spiralized paths, forming one polygon)
* \return A path with the given config which is now the last path in GCodePlanner::paths * \return A path with the given config which is now the last path in GCodePlanner::paths
*/ */
GCodePath* getLatestPathWithConfig(GCodePathConfig* config, SpaceFillType space_fill_type, float flow = 1.0, bool spiralize = false); GCodePath* getLatestPathWithConfig(const GCodePathConfig* config, SpaceFillType space_fill_type, float flow = 1.0, bool spiralize = false);
public: public:
/*! /*!
@@ -274,7 +293,7 @@ public:
* \param last_position The position of the head at the start of this gcode layer * \param last_position The position of the head at the start of this gcode layer
* \param combing_mode Whether combing is enabled and full or within infill only. * \param combing_mode Whether combing is enabled and full or within infill only.
*/ */
GCodePlanner(SliceDataStorage& storage, int layer_nr, int z, int layer_height, Point last_position, int current_extruder, bool is_inside_mesh, std::vector<FanSpeedLayerTimeSettings>& fan_speed_layer_time_settings_per_extruder, CombingMode combing_mode, int64_t comb_boundary_offset, bool travel_avoid_other_parts, int64_t travel_avoid_distance); GCodePlanner(const SliceDataStorage& storage, int layer_nr, int z, int layer_height, PlanningState last_planned_state, const std::vector<FanSpeedLayerTimeSettings>& fan_speed_layer_time_settings_per_extruder, CombingMode combing_mode, int64_t comb_boundary_offset, bool travel_avoid_other_parts, int64_t travel_avoid_distance);
~GCodePlanner(); ~GCodePlanner();
void overrideFanSpeeds(double speed); void overrideFanSpeeds(double speed);
@@ -292,12 +311,21 @@ private:
Polygons computeCombBoundaryInside(CombingMode combing_mode); Polygons computeCombBoundaryInside(CombingMode combing_mode);
public: public:
int getLayerNr() int getLayerNr() const
{ {
return layer_nr; return layer_nr;
} }
Point getLastPosition() PlanningState getPlanningState() const
{
PlanningState ret;
ret.last_position = lastPosition;
ret.current_extruder = getExtruder();
ret.is_inside_mesh_layer_part = was_inside;
return ret;
}
Point getLastPosition() const
{ {
return lastPosition; return lastPosition;
} }
@@ -305,14 +333,25 @@ public:
/*! /*!
* return whether the last position planned was inside the mesh (used in combing) * return whether the last position planned was inside the mesh (used in combing)
*/ */
bool getIsInsideMesh() bool getIsInsideMesh() const
{ {
return was_inside; return was_inside;
} }
bool getPrimeTowerIsPlanned() const
{
return has_prime_tower_planned;
}
void setPrimeTowerIsPlanned()
{
has_prime_tower_planned = true;
}
/*! /*!
* send a line segment through the command socket from the previous point to the given point \p to * send a line segment through the command socket from the previous point to the given point \p to
*/ */
void sendLineTo(PrintFeatureType print_feature_type, Point to, int line_width) void sendLineTo(PrintFeatureType print_feature_type, Point to, int line_width) const
{ {
CommandSocket::sendLineTo(print_feature_type, to, line_width); CommandSocket::sendLineTo(print_feature_type, to, line_width);
} }
@@ -336,7 +375,7 @@ public:
/*! /*!
* Get the last planned extruder. * Get the last planned extruder.
*/ */
int getExtruder() int getExtruder() const
{ {
return extruder_plans.back().extruder; return extruder_plans.back().extruder;
} }
@@ -377,7 +416,7 @@ public:
* \param flow A modifier of the extrusion width which would follow from the \p config * \param flow A modifier of the extrusion width which would follow from the \p config
* \param spiralize Whether to gradually increase the z while printing. (Note that this path may be part of a sequence of spiralized paths, forming one polygon) * \param spiralize Whether to gradually increase the z while printing. (Note that this path may be part of a sequence of spiralized paths, forming one polygon)
*/ */
void addExtrusionMove(Point p, GCodePathConfig* config, SpaceFillType space_fill_type, float flow = 1.0, bool spiralize = false); void addExtrusionMove(Point p, const GCodePathConfig* config, SpaceFillType space_fill_type, float flow = 1.0, bool spiralize = false);
/*! /*!
* Add polygon to the gcode starting at vertex \p startIdx * Add polygon to the gcode starting at vertex \p startIdx
@@ -388,7 +427,7 @@ public:
* \param wall_0_wipe_dist The distance to travel along the polygon after it has been laid down, in order to wipe the start and end of the wall together * \param wall_0_wipe_dist The distance to travel along the polygon after it has been laid down, in order to wipe the start and end of the wall together
* \param spiralize Whether to gradually increase the z height from the normal layer height to the height of the next layer over this polygon * \param spiralize Whether to gradually increase the z height from the normal layer height to the height of the next layer over this polygon
*/ */
void addPolygon(PolygonRef polygon, int startIdx, GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation = nullptr, coord_t wall_0_wipe_dist = 0, bool spiralize = false); void addPolygon(ConstPolygonRef polygon, int startIdx, const GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation = nullptr, coord_t wall_0_wipe_dist = 0, bool spiralize = false);
/*! /*!
* Add polygons to the gcode with optimized order. * Add polygons to the gcode with optimized order.
@@ -407,7 +446,7 @@ public:
* \param wall_0_wipe_dist The distance to travel along each polygon after it has been laid down, in order to wipe the start and end of the wall together * \param wall_0_wipe_dist The distance to travel along each polygon after it has been laid down, in order to wipe the start and end of the wall together
* \param spiralize Whether to gradually increase the z height from the normal layer height to the height of the next layer over each polygon printed * \param spiralize Whether to gradually increase the z height from the normal layer height to the height of the next layer over each polygon printed
*/ */
void addPolygonsByOptimizer(Polygons& polygons, GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation = nullptr, EZSeamType z_seam_type = EZSeamType::SHORTEST, Point z_seam_pos = Point(0, 0), coord_t wall_0_wipe_dist = 0, bool spiralize = false); void addPolygonsByOptimizer(const Polygons& polygons, const GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation = nullptr, EZSeamType z_seam_type = EZSeamType::SHORTEST, Point z_seam_pos = Point(0, 0), coord_t wall_0_wipe_dist = 0, bool spiralize = false);
/*! /*!
* Add lines to the gcode with optimized order. * Add lines to the gcode with optimized order.
@@ -416,7 +455,7 @@ public:
* \param space_fill_type The type of space filling used to generate the line segments (should be either Lines or PolyLines!) * \param space_fill_type The type of space filling used to generate the line segments (should be either Lines or PolyLines!)
* \param wipe_dist (optional) the distance wiped without extruding after laying down a line. * \param wipe_dist (optional) the distance wiped without extruding after laying down a line.
*/ */
void addLinesByOptimizer(Polygons& polygons, GCodePathConfig* config, SpaceFillType space_fill_type, int wipe_dist = 0); void addLinesByOptimizer(const Polygons& polygons, const GCodePathConfig* config, SpaceFillType space_fill_type, int wipe_dist = 0);
/*! /*!
* Compute naive time estimates (without accounting for slow down at corners etc.) and naive material estimates (without accounting for MergeInfillLines) * Compute naive time estimates (without accounting for slow down at corners etc.) and naive material estimates (without accounting for MergeInfillLines)
@@ -434,20 +473,7 @@ public:
* \param gcode The gcode to write the planned paths to * \param gcode The gcode to write the planned paths to
*/ */
void writeGCode(GCodeExport& gcode); void writeGCode(GCodeExport& gcode);
/*!
* Complete all GcodePathConfigs by
* - altering speeds to conform to speed_print_layer_0 and
* speed_travel_layer_0
* - setting the layer_height (and thereby computing the extrusionMM3perMM)
*/
void completeConfigs();
/*!
* Interpolate between the initial layer speeds and the eventual speeds.
*/
void processInitialLayersSpeedup();
/*! /*!
* Whether the current retracted path is to be an extruder switch retraction. * Whether the current retracted path is to be an extruder switch retraction.
* This function is used to avoid a G10 S1 after a G10. * This function is used to avoid a G10 S1 after a G10.
+2 -2
Ver Arquivo
@@ -17,7 +17,7 @@ int Infill::computeScanSegmentIdx(int x, int line_width)
return x / line_width; return x / line_width;
} }
void Infill::generate(Polygons& result_polygons, Polygons& result_lines, SliceMeshStorage* mesh) void Infill::generate(Polygons& result_polygons, Polygons& result_lines, const SliceMeshStorage* mesh)
{ {
if (in_outline.size() == 0) return; if (in_outline.size() == 0) return;
if (line_distance == 0) return; if (line_distance == 0) return;
@@ -144,7 +144,7 @@ void Infill::generateTriangleInfill(Polygons& result)
generateLineInfill(result, line_distance, fill_angle + 120, 0); generateLineInfill(result, line_distance, fill_angle + 120, 0);
} }
void Infill::generateCubicSubDivInfill(Polygons& result, SliceMeshStorage& mesh) void Infill::generateCubicSubDivInfill(Polygons& result, const SliceMeshStorage& mesh)
{ {
Polygons uncropped; Polygons uncropped;
mesh.base_subdiv_cube->generateSubdivisionLines(z, uncropped); mesh.base_subdiv_cube->generateSubdivisionLines(z, uncropped);
+3 -3
Ver Arquivo
@@ -80,7 +80,7 @@ public:
* \param result_lines (output) The resulting line segments (from linear infill types) * \param result_lines (output) The resulting line segments (from linear infill types)
* \param mesh The mesh for which to geenrate infill (should only be used for non-helper objects) * \param mesh The mesh for which to geenrate infill (should only be used for non-helper objects)
*/ */
void generate(Polygons& result_polygons, Polygons& result_lines, SliceMeshStorage* mesh = nullptr); void generate(Polygons& result_polygons, Polygons& result_lines, const SliceMeshStorage* mesh = nullptr);
private: private:
/*! /*!
@@ -148,8 +148,8 @@ private:
* \param[out] result The resulting lines * \param[out] result The resulting lines
* \param[in] mesh Where the Cubic Subdivision Infill precomputation is stored * \param[in] mesh Where the Cubic Subdivision Infill precomputation is stored
*/ */
void generateCubicSubDivInfill(Polygons& result, SliceMeshStorage& mesh); void generateCubicSubDivInfill(Polygons& result, const SliceMeshStorage& mesh);
/*! /*!
* Convert a mapping from scanline to line_segment-scanline-intersections (\p cut_list) into line segments, using the even-odd rule * Convert a mapping from scanline to line_segment-scanline-intersections (\p cut_list) into line segments, using the even-odd rule
* \param result (output) The resulting lines * \param result (output) The resulting lines
+10 -10
Ver Arquivo
@@ -16,7 +16,7 @@ void PathOrderOptimizer::optimize()
bool picked[polygons.size()]; bool picked[polygons.size()];
memset(picked, false, sizeof(bool) * polygons.size());/// initialized as falses memset(picked, false, sizeof(bool) * polygons.size());/// initialized as falses
for (PolygonRef poly : polygons) /// find closest point to initial starting point within each polygon +initialize picked for (ConstPolygonRef poly : polygons) /// find closest point to initial starting point within each polygon +initialize picked
{ {
int best = -1; int best = -1;
float bestDist = std::numeric_limits<float>::infinity(); float bestDist = std::numeric_limits<float>::infinity();
@@ -102,15 +102,15 @@ int PathOrderOptimizer::getPolyStart(Point prev_point, int poly_idx)
int PathOrderOptimizer::getClosestPointInPolygon(Point prev_point, int poly_idx) int PathOrderOptimizer::getClosestPointInPolygon(Point prev_point, int poly_idx)
{ {
PolygonRef poly = polygons[poly_idx]; ConstPolygonRef poly = polygons[poly_idx];
int best_point_idx = -1; int best_point_idx = -1;
float best_point_score = std::numeric_limits<float>::infinity(); float best_point_score = std::numeric_limits<float>::infinity();
Point p0 = poly.back(); Point p0 = poly.back();
for (unsigned int point_idx = 0; point_idx < poly.size(); point_idx++) for (unsigned int point_idx = 0; point_idx < poly.size(); point_idx++)
{ {
Point& p1 = poly[point_idx]; const Point& p1 = poly[point_idx];
Point& p2 = poly[(point_idx + 1) % poly.size()]; const Point& p2 = poly[(point_idx + 1) % poly.size()];
int64_t dist = vSize2(p1 - prev_point); int64_t dist = vSize2(p1 - prev_point);
float is_on_inside_corner_score = -LinearAlg2D::getAngleLeft(p0, p1, p2) / M_PI * 5000 * 5000; // prefer inside corners float is_on_inside_corner_score = -LinearAlg2D::getAngleLeft(p0, p1, p2) / M_PI * 5000 * 5000; // prefer inside corners
// this score is in the order of 5 mm // this score is in the order of 5 mm
@@ -143,7 +143,7 @@ void LineOrderOptimizer::optimize()
{ {
int best_point_idx = -1; int best_point_idx = -1;
float best_point_dist = std::numeric_limits<float>::infinity(); float best_point_dist = std::numeric_limits<float>::infinity();
PolygonRef poly = polygons[poly_idx]; ConstPolygonRef poly = polygons[poly_idx];
for (unsigned int point_idx = 0; point_idx < poly.size(); point_idx++) /// get closest point from polygon for (unsigned int point_idx = 0; point_idx < poly.size(); point_idx++) /// get closest point from polygon
{ {
float dist = vSize2f(poly[point_idx] - startPoint); float dist = vSize2f(poly[point_idx] - startPoint);
@@ -199,13 +199,13 @@ void LineOrderOptimizer::optimize()
if (best_line_idx > -1) /// should always be true; we should have been able to identify the best next polygon if (best_line_idx > -1) /// should always be true; we should have been able to identify the best next polygon
{ {
PolygonRef best_line = polygons[best_line_idx]; ConstPolygonRef best_line = polygons[best_line_idx];
assert(best_line.size() == 2); assert(best_line.size() == 2);
int line_start_point_idx = polyStart[best_line_idx]; int line_start_point_idx = polyStart[best_line_idx];
int line_end_point_idx = line_start_point_idx * -1 + 1; /// 1 -> 0 , 0 -> 1 int line_end_point_idx = line_start_point_idx * -1 + 1; /// 1 -> 0 , 0 -> 1
Point& line_start = best_line[line_start_point_idx]; const Point& line_start = best_line[line_start_point_idx];
Point& line_end = best_line[line_end_point_idx]; const Point& line_end = best_line[line_end_point_idx];
prev_point = line_end; prev_point = line_end;
incoming_perpundicular_normal = turn90CCW(normal(line_end - line_start, 1000)); incoming_perpundicular_normal = turn90CCW(normal(line_end - line_start, 1000));
@@ -221,8 +221,8 @@ void LineOrderOptimizer::optimize()
inline void LineOrderOptimizer::updateBestLine(unsigned int poly_idx, int& best, float& best_score, Point prev_point, Point incoming_perpundicular_normal) inline void LineOrderOptimizer::updateBestLine(unsigned int poly_idx, int& best, float& best_score, Point prev_point, Point incoming_perpundicular_normal)
{ {
Point& p0 = polygons[poly_idx][0]; const Point& p0 = polygons[poly_idx][0];
Point& p1 = polygons[poly_idx][1]; const Point& p1 = polygons[poly_idx][1];
float dot_score = getAngleScore(incoming_perpundicular_normal, p0, p1); float dot_score = getAngleScore(incoming_perpundicular_normal, p0, p1);
{ /// check distance to first point on line (0) { /// check distance to first point on line (0)
float score = vSize2f(p0 - prev_point) + dot_score; // prefer 90 degree corners float score = vSize2f(p0 - prev_point) + dot_score; // prefer 90 degree corners
+14 -4
Ver Arquivo
@@ -20,7 +20,7 @@ public:
EZSeamType type; EZSeamType type;
Point startPoint; //!< A location near the prefered start location Point startPoint; //!< A location near the prefered start location
Point z_seam_pos; //!< The position near where to create the z_seam (if \ref PathOrderOptimizer::type == 'back') Point z_seam_pos; //!< The position near where to create the z_seam (if \ref PathOrderOptimizer::type == 'back')
std::vector<PolygonRef> polygons; //!< the parts of the layer (in arbitrary order) std::vector<ConstPolygonRef> polygons; //!< the parts of the layer (in arbitrary order)
std::vector<int> polyStart; //!< polygons[i][polyStart[i]] = point of polygon i which is to be the starting point in printing the polygon std::vector<int> polyStart; //!< polygons[i][polyStart[i]] = point of polygon i which is to be the starting point in printing the polygon
std::vector<int> polyOrder; //!< the optimized order as indices in #polygons std::vector<int> polyOrder; //!< the optimized order as indices in #polygons
@@ -33,10 +33,15 @@ public:
void addPolygon(PolygonRef polygon) void addPolygon(PolygonRef polygon)
{ {
this->polygons.push_back(polygon); this->polygons.emplace_back(polygon);
} }
void addPolygons(Polygons& polygons) void addPolygon(ConstPolygonRef polygon)
{
this->polygons.emplace_back(polygon);
}
void addPolygons(const Polygons& polygons)
{ {
for(unsigned int i=0;i<polygons.size(); i++) for(unsigned int i=0;i<polygons.size(); i++)
this->polygons.push_back(polygons[i]); this->polygons.push_back(polygons[i]);
@@ -66,7 +71,7 @@ class LineOrderOptimizer
{ {
public: public:
Point startPoint; //!< The location of the nozzle before starting to print the current layer Point startPoint; //!< The location of the nozzle before starting to print the current layer
std::vector<PolygonRef> polygons; //!< the parts of the layer (in arbitrary order) std::vector<ConstPolygonRef> polygons; //!< the parts of the layer (in arbitrary order)
std::vector<int> polyStart; //!< polygons[i][polyStart[i]] = point of polygon i which is to be the starting point in printing the polygon std::vector<int> polyStart; //!< polygons[i][polyStart[i]] = point of polygon i which is to be the starting point in printing the polygon
std::vector<int> polyOrder; //!< the optimized order as indices in #polygons std::vector<int> polyOrder; //!< the optimized order as indices in #polygons
@@ -80,6 +85,11 @@ public:
this->polygons.push_back(polygon); this->polygons.push_back(polygon);
} }
void addPolygon(ConstPolygonRef polygon)
{
this->polygons.push_back(polygon);
}
void addPolygons(Polygons& polygons) void addPolygons(Polygons& polygons)
{ {
for(unsigned int i=0;i<polygons.size(); i++) for(unsigned int i=0;i<polygons.size(); i++)
+5 -4
Ver Arquivo
@@ -6,6 +6,7 @@
#include <unordered_set> #include <unordered_set>
#include "../utils/polygonUtils.h" #include "../utils/polygonUtils.h"
#include "../utils/linearAlg2D.h"
#include "../utils/PolygonsPointIndex.h" #include "../utils/PolygonsPointIndex.h"
#include "../sliceDataStorage.h" #include "../sliceDataStorage.h"
#include "../utils/SVG.h" #include "../utils/SVG.h"
@@ -22,7 +23,7 @@ Polygons& Comb::getBoundaryOutside()
return *boundary_outside; return *boundary_outside;
} }
Comb::Comb(SliceDataStorage& storage, int layer_nr, Polygons& comb_boundary_inside, int64_t comb_boundary_offset, bool travel_avoid_other_parts, int64_t travel_avoid_distance) Comb::Comb(const SliceDataStorage& storage, int layer_nr, const Polygons& comb_boundary_inside, int64_t comb_boundary_offset, bool travel_avoid_other_parts, int64_t travel_avoid_distance)
: storage(storage) : storage(storage)
, layer_nr(layer_nr) , layer_nr(layer_nr)
, offset_from_outlines(comb_boundary_offset) // between second wall and infill / other walls , offset_from_outlines(comb_boundary_offset) // between second wall and infill / other walls
@@ -31,7 +32,7 @@ Comb::Comb(SliceDataStorage& storage, int layer_nr, Polygons& comb_boundary_insi
, offset_from_inside_to_outside(offset_from_outlines + offset_from_outlines_outside) , offset_from_inside_to_outside(offset_from_outlines + offset_from_outlines_outside)
, max_crossing_dist2(offset_from_inside_to_outside * offset_from_inside_to_outside * 2) // so max_crossing_dist = offset_from_inside_to_outside * sqrt(2) =approx 1.5 to allow for slightly diagonal crossings and slightly inaccurate crossing computation , max_crossing_dist2(offset_from_inside_to_outside * offset_from_inside_to_outside * 2) // so max_crossing_dist = offset_from_inside_to_outside * sqrt(2) =approx 1.5 to allow for slightly diagonal crossings and slightly inaccurate crossing computation
, avoid_other_parts(travel_avoid_other_parts) , avoid_other_parts(travel_avoid_other_parts)
, boundary_inside( comb_boundary_inside ) , boundary_inside( comb_boundary_inside ) // copy the boundary, because the partsView_inside will reorder the polygons
, partsView_inside( boundary_inside.splitIntoPartsView() ) // WARNING !! changes the order of boundary_inside !! , partsView_inside( boundary_inside.splitIntoPartsView() ) // WARNING !! changes the order of boundary_inside !!
, inside_loc_to_line(PolygonUtils::createLocToLineGrid(boundary_inside, comb_boundary_offset)) , inside_loc_to_line(PolygonUtils::createLocToLineGrid(boundary_inside, comb_boundary_offset))
, boundary_outside( , boundary_outside(
@@ -213,7 +214,7 @@ Comb::Crossing::Crossing(const Point& dest_point, const bool dest_is_inside, con
{ {
if (dest_is_inside) if (dest_is_inside)
{ {
dest_crossing_poly = boundary_inside[dest_part_boundary_crossing_poly_idx]; // initialize with most obvious poly, cause mostly a combing move will move outside the part, rather than inside a hole in the part dest_crossing_poly.emplace(boundary_inside[dest_part_boundary_crossing_poly_idx]); // initialize with most obvious poly, cause mostly a combing move will move outside the part, rather than inside a hole in the part
} }
} }
@@ -332,7 +333,7 @@ bool Comb::Crossing::findOutside(const Polygons& outside, const Point close_to,
} }
std::shared_ptr<std::pair<ClosestPolygonPoint, ClosestPolygonPoint>> Comb::Crossing::findBestCrossing(const Polygons& outside, const PolygonRef from, const Point estimated_start, const Point estimated_end, Comb& comber) std::shared_ptr<std::pair<ClosestPolygonPoint, ClosestPolygonPoint>> Comb::Crossing::findBestCrossing(const Polygons& outside, ConstPolygonRef from, const Point estimated_start, const Point estimated_end, Comb& comber)
{ {
ClosestPolygonPoint* best_in = nullptr; ClosestPolygonPoint* best_in = nullptr;
ClosestPolygonPoint* best_out = nullptr; ClosestPolygonPoint* best_out = nullptr;
+6 -6
Ver Arquivo
@@ -48,7 +48,7 @@ private:
Point in_or_mid; //!< The point on the inside boundary, or in between the inside and outside boundary if the start/end point isn't inside the inside boudary Point in_or_mid; //!< The point on the inside boundary, or in between the inside and outside boundary if the start/end point isn't inside the inside boudary
Point out; //!< The point on the outside boundary Point out; //!< The point on the outside boundary
PolygonsPart dest_part; //!< The assembled inside-boundary PolygonsPart in which the dest_point lies. (will only be initialized when Crossing::dest_is_inside holds) PolygonsPart dest_part; //!< The assembled inside-boundary PolygonsPart in which the dest_point lies. (will only be initialized when Crossing::dest_is_inside holds)
std::optional<PolygonRef> dest_crossing_poly; //!< The polygon of the part in which dest_point lies, which will be crossed (often will be the outside polygon) std::optional<ConstPolygonRef> dest_crossing_poly; //!< The polygon of the part in which dest_point lies, which will be crossed (often will be the outside polygon)
const Polygons& boundary_inside; //!< The inside boundary as in \ref Comb::boundary_inside const Polygons& boundary_inside; //!< The inside boundary as in \ref Comb::boundary_inside
const LocToLineGrid* inside_loc_to_line; //!< The loc to line grid \ref Comb::inside_loc_to_line const LocToLineGrid* inside_loc_to_line; //!< The loc to line grid \ref Comb::inside_loc_to_line
@@ -97,11 +97,11 @@ private:
* \param comber[in] The combing calculator which has references to the offsets and boundaries to use in combing. * \param comber[in] The combing calculator which has references to the offsets and boundaries to use in combing.
* \return A pair of which the first is the crossing point on the inside boundary and the second the crossing point on the outside boundary * \return A pair of which the first is the crossing point on the inside boundary and the second the crossing point on the outside boundary
*/ */
std::shared_ptr<std::pair<ClosestPolygonPoint, ClosestPolygonPoint>> findBestCrossing(const Polygons& outside, const PolygonRef from, Point estimated_start, Point estimated_end, Comb& comber); std::shared_ptr<std::pair<ClosestPolygonPoint, ClosestPolygonPoint>> findBestCrossing(const Polygons& outside, ConstPolygonRef from, Point estimated_start, Point estimated_end, Comb& comber);
}; };
SliceDataStorage& storage; //!< The storage from which to compute the outside boundary, when needed. const SliceDataStorage& storage; //!< The storage from which to compute the outside boundary, when needed.
const int layer_nr; //!< The layer number for the layer for which to compute the outside boundary, when needed. const int layer_nr; //!< The layer number for the layer for which to compute the outside boundary, when needed.
const int64_t offset_from_outlines; //!< Offset from the boundary of a part to the comb path. (nozzle width / 2) const int64_t offset_from_outlines; //!< Offset from the boundary of a part to the comb path. (nozzle width / 2)
@@ -115,8 +115,8 @@ private:
const bool avoid_other_parts; //!< Whether to perform inverse combing a.k.a. avoid parts. const bool avoid_other_parts; //!< Whether to perform inverse combing a.k.a. avoid parts.
Polygons& boundary_inside; //!< The boundary within which to comb. Polygons boundary_inside; //!< The boundary within which to comb. (Will be reordered by the partsView_inside)
PartsView partsView_inside; //!< Structured indices onto boundary_inside which shows which polygons belong to which part. const PartsView partsView_inside; //!< Structured indices onto boundary_inside which shows which polygons belong to which part.
LocToLineGrid* inside_loc_to_line; //!< The SparsePointGridInclusive mapping locations to line segments of the inner boundary. LocToLineGrid* inside_loc_to_line; //!< The SparsePointGridInclusive mapping locations to line segments of the inner boundary.
LazyInitialization<Polygons> boundary_outside; //!< The boundary outside of which to stay to avoid collision with other layer parts. This is a pointer cause we only compute it when we move outside the boundary (so not when there is only a single part in the layer) LazyInitialization<Polygons> boundary_outside; //!< The boundary outside of which to stay to avoid collision with other layer parts. This is a pointer cause we only compute it when we move outside the boundary (so not when there is only a single part in the layer)
LazyInitialization<LocToLineGrid, Comb*, const int64_t> outside_loc_to_line; //!< The SparsePointGridInclusive mapping locations to line segments of the outside boundary. LazyInitialization<LocToLineGrid, Comb*, const int64_t> outside_loc_to_line; //!< The SparsePointGridInclusive mapping locations to line segments of the outside boundary.
@@ -153,7 +153,7 @@ public:
* \param travel_avoid_other_parts Whether to avoid other layer parts when traveling through air. * \param travel_avoid_other_parts Whether to avoid other layer parts when traveling through air.
* \param travel_avoid_distance The distance by which to avoid other layer parts when traveling through air. * \param travel_avoid_distance The distance by which to avoid other layer parts when traveling through air.
*/ */
Comb(SliceDataStorage& storage, int layer_nr, Polygons& comb_boundary_inside, int64_t offset_from_outlines, bool travel_avoid_other_parts, int64_t travel_avoid_distance); Comb(const SliceDataStorage& storage, int layer_nr, const Polygons& comb_boundary_inside, int64_t offset_from_outlines, bool travel_avoid_other_parts, int64_t travel_avoid_distance);
~Comb(); ~Comb();
+1 -1
Ver Arquivo
@@ -23,7 +23,7 @@ namespace cura
class GCodePath class GCodePath
{ {
public: public:
GCodePathConfig* config; //!< The configuration settings of the path. const GCodePathConfig* config; //!< The configuration settings of the path.
SpaceFillType space_fill_type; //!< The type of space filling of which this path is a part SpaceFillType space_fill_type; //!< The type of space filling of which this path is a part
float flow; //!< A type-independent flow configuration (used for wall overlap compensation) float flow; //!< A type-independent flow configuration (used for wall overlap compensation)
bool retract; //!< Whether the path is a move path preceded by a retraction move; whether the path is a retracted move path. bool retract; //!< Whether the path is a move path preceded by a retraction move; whether the path is a retracted move path.
+235
Ver Arquivo
@@ -0,0 +1,235 @@
/** Copyright (C) 2017 Ultimaker - Released under terms of the AGPLv3 License */
#include "PathConfigStorage.h"
#include "settings.h" // MAX_INFILL_COMBINE
#include "../sliceDataStorage.h" // SliceDataStorage
namespace cura
{
GCodePathConfig getPerimeterGapConfig(const SliceMeshStorage& mesh, int layer_thickness)
{
// The perimeter gap config follows the skin config, but has a different line width:
// wall_line_width_x divided by two because the gaps are between 0 and 1 times the wall line width
const int perimeter_gaps_line_width = mesh.getSettingInMicrons("wall_line_width_x") / 2;
double perimeter_gaps_speed = mesh.getSettingInMillimetersPerSecond("speed_topbottom");
if (mesh.getSettingBoolean("speed_equalize_flow_enabled"))
{
perimeter_gaps_speed = perimeter_gaps_speed * mesh.getSettingInMicrons("skin_line_width") / perimeter_gaps_line_width;
}
return GCodePathConfig(
PrintFeatureType::Skin
, perimeter_gaps_line_width
, layer_thickness
, mesh.getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{perimeter_gaps_speed, mesh.getSettingInMillimetersPerSecond("acceleration_topbottom"), mesh.getSettingInMillimetersPerSecond("jerk_topbottom")}
);
}
PathConfigStorage::MeshPathConfigs::MeshPathConfigs(const SliceMeshStorage& mesh, int layer_thickness)
: inset0_config(
PrintFeatureType::OuterWall
, mesh.getSettingInMicrons("wall_line_width_0")
, layer_thickness
, mesh.getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{mesh.getSettingInMillimetersPerSecond("speed_wall_0"), mesh.getSettingInMillimetersPerSecond("acceleration_wall_0"), mesh.getSettingInMillimetersPerSecond("jerk_wall_0")}
)
, insetX_config(
PrintFeatureType::InnerWall
, mesh.getSettingInMicrons("wall_line_width_x")
, layer_thickness
, mesh.getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{mesh.getSettingInMillimetersPerSecond("speed_wall_x"), mesh.getSettingInMillimetersPerSecond("acceleration_wall_x"), mesh.getSettingInMillimetersPerSecond("jerk_wall_x")}
)
, skin_config(
PrintFeatureType::Skin
, mesh.getSettingInMicrons("skin_line_width")
, layer_thickness
, mesh.getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{mesh.getSettingInMillimetersPerSecond("speed_topbottom"), mesh.getSettingInMillimetersPerSecond("acceleration_topbottom"), mesh.getSettingInMillimetersPerSecond("jerk_topbottom")}
)
, perimeter_gap_config(getPerimeterGapConfig(mesh, layer_thickness))
{
infill_config.reserve(MAX_INFILL_COMBINE);
for (int combine_idx = 0; combine_idx < MAX_INFILL_COMBINE; combine_idx++)
{
infill_config.emplace_back(
PrintFeatureType::Infill
, mesh.getSettingInMicrons("infill_line_width") * (combine_idx + 1)
, layer_thickness
, mesh.getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{mesh.getSettingInMillimetersPerSecond("speed_infill"), mesh.getSettingInMillimetersPerSecond("acceleration_infill"), mesh.getSettingInMillimetersPerSecond("jerk_infill")}
);
}
}
PathConfigStorage::PathConfigStorage(const SliceDataStorage& storage, int layer_nr, int layer_thickness)
: adhesion_extruder_train(storage.meshgroup->getExtruderTrain(storage.getSettingAsIndex("adhesion_extruder_nr")))
, support_infill_train(storage.meshgroup->getExtruderTrain(storage.getSettingAsIndex("support_infill_extruder_nr")))
, support_interface_train(storage.meshgroup->getExtruderTrain(storage.getSettingAsIndex("support_interface_extruder_nr")))
, raft_base_config(
PrintFeatureType::SupportInterface
, adhesion_extruder_train->getSettingInMicrons("raft_base_line_width")
, adhesion_extruder_train->getSettingInMicrons("raft_base_thickness")
, adhesion_extruder_train->getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{adhesion_extruder_train->getSettingInMillimetersPerSecond("raft_base_speed"), adhesion_extruder_train->getSettingInMillimetersPerSecond("raft_base_acceleration"), adhesion_extruder_train->getSettingInMillimetersPerSecond("raft_base_jerk")}
)
, raft_interface_config(
PrintFeatureType::Support
, adhesion_extruder_train->getSettingInMicrons("raft_interface_line_width")
, adhesion_extruder_train->getSettingInMicrons("raft_interface_thickness")
, adhesion_extruder_train->getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{adhesion_extruder_train->getSettingInMillimetersPerSecond("raft_interface_speed"), adhesion_extruder_train->getSettingInMillimetersPerSecond("raft_interface_acceleration"), adhesion_extruder_train->getSettingInMillimetersPerSecond("raft_interface_jerk")}
)
, raft_surface_config(
PrintFeatureType::SupportInterface
, adhesion_extruder_train->getSettingInMicrons("raft_surface_line_width")
, adhesion_extruder_train->getSettingInMicrons("raft_surface_thickness")
, adhesion_extruder_train->getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{adhesion_extruder_train->getSettingInMillimetersPerSecond("raft_surface_speed"), adhesion_extruder_train->getSettingInMillimetersPerSecond("raft_surface_acceleration"), adhesion_extruder_train->getSettingInMillimetersPerSecond("raft_surface_jerk")}
)
, support_infill_config(
PrintFeatureType::Support
, support_infill_train->getSettingInMicrons("support_line_width")
, layer_thickness
, support_infill_train->getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{support_infill_train->getSettingInMillimetersPerSecond("speed_support_infill"), support_infill_train->getSettingInMillimetersPerSecond("acceleration_support_infill"), support_infill_train->getSettingInMillimetersPerSecond("jerk_support_infill")}
)
, support_interface_config(
PrintFeatureType::SupportInterface
, support_interface_train->getSettingInMicrons("support_interface_line_width")
, layer_thickness
, support_interface_train->getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{support_interface_train->getSettingInMillimetersPerSecond("speed_support_interface"), support_interface_train->getSettingInMillimetersPerSecond("acceleration_support_interface"), support_interface_train->getSettingInMillimetersPerSecond("jerk_support_interface")}
)
{
int extruder_count = storage.meshgroup->getExtruderCount();
travel_config_per_extruder.reserve(extruder_count);
skirt_brim_config.reserve(extruder_count);
prime_tower_config_per_extruder.reserve(extruder_count);
for (int extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++)
{
const ExtruderTrain* train = storage.meshgroup->getExtruderTrain(extruder_nr);
travel_config_per_extruder.emplace_back(
PrintFeatureType::MoveCombing
, 0
, 0
, 0.0
, GCodePathConfig::SpeedDerivatives{train->getSettingInMillimetersPerSecond("speed_travel"), train->getSettingInMillimetersPerSecond("acceleration_travel"), train->getSettingInMillimetersPerSecond("jerk_travel")}
);
skirt_brim_config.emplace_back(
PrintFeatureType::SkirtBrim
, train->getSettingInMicrons("skirt_brim_line_width")
, layer_thickness
, train->getSettingInPercentage("material_flow")
, GCodePathConfig::SpeedDerivatives{train->getSettingInMillimetersPerSecond("skirt_brim_speed"), train->getSettingInMillimetersPerSecond("acceleration_skirt_brim"), train->getSettingInMillimetersPerSecond("jerk_skirt_brim")}
);
prime_tower_config_per_extruder.emplace_back(
PrintFeatureType::SupportInfill
, train->getSettingInMicrons("prime_tower_line_width")
, layer_thickness
, train->getSettingInPercentage("prime_tower_flow")
, GCodePathConfig::SpeedDerivatives{train->getSettingInMillimetersPerSecond("speed_prime_tower"), train->getSettingInMillimetersPerSecond("acceleration_prime_tower"), train->getSettingInMillimetersPerSecond("jerk_prime_tower")}
);
}
mesh_configs.reserve(storage.meshes.size());
for (const SliceMeshStorage& mesh_storage : storage.meshes)
{
mesh_configs.emplace_back(mesh_storage, layer_thickness);
}
int initial_speedup_layer_count = storage.getSettingAsCount("speed_slowdown_layers");
if (layer_nr < initial_speedup_layer_count)
{
handleInitialLayerSpeedup(storage, layer_nr, initial_speedup_layer_count);
}
}
void cura::PathConfigStorage::handleInitialLayerSpeedup(const SliceDataStorage& storage, int layer_nr, int initial_speedup_layer_count)
{
std::vector<GCodePathConfig::SpeedDerivatives> global_first_layer_config_per_extruder;
global_first_layer_config_per_extruder.reserve(storage.meshgroup->getExtruderCount());
for (int extruder_nr = 0; extruder_nr < storage.meshgroup->getExtruderCount(); extruder_nr++)
{
const ExtruderTrain* extruder = storage.meshgroup->getExtruderTrain(extruder_nr);
global_first_layer_config_per_extruder.emplace_back(
GCodePathConfig::SpeedDerivatives{
extruder->getSettingInMillimetersPerSecond("speed_print_layer_0")
, extruder->getSettingInMillimetersPerSecond("acceleration_print_layer_0")
, extruder->getSettingInMillimetersPerSecond("jerk_print_layer_0")
});
}
{ // support
if (layer_nr < initial_speedup_layer_count)
{
int extruder_nr_support_infill = storage.getSettingAsIndex((layer_nr <= 0)? "support_extruder_nr_layer_0" : "support_infill_extruder_nr");
GCodePathConfig::SpeedDerivatives& first_layer_config_infill = global_first_layer_config_per_extruder[extruder_nr_support_infill];
support_infill_config.smoothSpeed(first_layer_config_infill, std::max(0, layer_nr), initial_speedup_layer_count);
int extruder_nr_support_interface = storage.getSettingAsIndex("support_interface_extruder_nr");
GCodePathConfig::SpeedDerivatives& first_layer_config_interface = global_first_layer_config_per_extruder[extruder_nr_support_interface];
support_interface_config.smoothSpeed(first_layer_config_interface, std::max(0, layer_nr), initial_speedup_layer_count);
}
}
{ // extruder configs: travel, skirt/brim (= shield)
for (int extruder_nr = 0; extruder_nr < storage.meshgroup->getExtruderCount(); ++extruder_nr)
{
const ExtruderTrain* train = storage.meshgroup->getExtruderTrain(extruder_nr);
GCodePathConfig::SpeedDerivatives initial_layer_speed_config{
train->getSettingInMillimetersPerSecond("speed_travel_layer_0")
, train->getSettingInMillimetersPerSecond("acceleration_travel_layer_0")
, train->getSettingInMillimetersPerSecond("jerk_travel_layer_0")
};
GCodePathConfig& travel = travel_config_per_extruder[extruder_nr];
travel.smoothSpeed(initial_layer_speed_config, std::max(0, layer_nr), initial_speedup_layer_count);
// don't smooth speed for the skirt/brim!
// NOTE: not smoothing skirt/brim means the speeds are also not smoothed for the draft/ooze shield
GCodePathConfig& prime_tower = prime_tower_config_per_extruder[extruder_nr];
prime_tower.smoothSpeed(initial_layer_speed_config, std::max(0, layer_nr), initial_speedup_layer_count);
}
}
{ // meshes
for (unsigned int mesh_idx = 0; mesh_idx < storage.meshes.size(); mesh_idx++)
{
const SliceMeshStorage& mesh = storage.meshes[mesh_idx];
GCodePathConfig::SpeedDerivatives initial_layer_speed_config{
mesh.getSettingInMillimetersPerSecond("speed_print_layer_0")
, mesh.getSettingInMillimetersPerSecond("acceleration_print_layer_0")
, mesh.getSettingInMillimetersPerSecond("jerk_print_layer_0")
};
MeshPathConfigs& mesh_config = mesh_configs[mesh_idx];
//Outer wall speed (per mesh).
mesh_config.inset0_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layer_count);
//Inner wall speed (per mesh).
mesh_config.insetX_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layer_count);
//Skin speed (per mesh).
mesh_config.skin_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layer_count);
mesh_config.perimeter_gap_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layer_count);
for (unsigned int idx = 0; idx < MAX_INFILL_COMBINE; idx++)
{
//Infill speed (per combine part per mesh).
mesh_config.infill_config[idx].smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layer_count);
}
}
}
}
}//namespace cura
+63
Ver Arquivo
@@ -0,0 +1,63 @@
/** Copyright (C) 2017 Ultimaker - Released under terms of the AGPLv3 License */
#ifndef SETTINGS_PATH_CONFIGS_H
#define SETTINGS_PATH_CONFIGS_H
#include <vector>
#include "../utils/intpoint.h" // coord_t
#include "../GCodePathConfig.h"
namespace cura
{
class SliceDataStorage; // forward decl for SliceDataStorage
class SliceMeshStorage; // forward decl for SliceDataStorage
class ExtruderTrain; // forward decl for SliceDataStorage
/*!
* A class to represent all configurations for all features types of printed lines in a meshgroup.
*/
class PathConfigStorage
{
private:
const ExtruderTrain* adhesion_extruder_train;
const ExtruderTrain* support_infill_train;
const ExtruderTrain* support_interface_train;
public:
class MeshPathConfigs
{
public:
GCodePathConfig inset0_config;
GCodePathConfig insetX_config;
GCodePathConfig skin_config;
GCodePathConfig perimeter_gap_config;
std::vector<GCodePathConfig> infill_config;
MeshPathConfigs(const SliceMeshStorage& mesh, int layer_thickness);
};
GCodePathConfig raft_base_config;
GCodePathConfig raft_interface_config;
GCodePathConfig raft_surface_config;
std::vector<GCodePathConfig> travel_config_per_extruder; //!< The config used for travel moves (only speed is set!)
std::vector<GCodePathConfig> skirt_brim_config; //!< Configuration for skirt and brim per extruder.
std::vector<GCodePathConfig> prime_tower_config_per_extruder; //!< Configuration for the prime tower per extruder.
GCodePathConfig support_infill_config; //!< The config used to print the normal support, rather than the support interface
GCodePathConfig support_interface_config; //!< The config to use to print the dense roofs and bottoms of support
std::vector<MeshPathConfigs> mesh_configs; //!< For each meash the config for all its feature types
/*!
* \warning Note that the layer_nr might be below zero for raft (filler) layers
*/
PathConfigStorage(const SliceDataStorage& storage, int layer_nr, int layer_thickness);
private:
void handleInitialLayerSpeedup(const SliceDataStorage& storage, int layer_nr, int initial_speedup_layer_count);
};
}; // namespace cura
#endif // SETTINGS_PATH_CONFIGS_H
+4 -31
Ver Arquivo
@@ -35,7 +35,7 @@ void SliceLayer::getOutlines(Polygons& result, bool external_polys_only) const
{ {
if (external_polys_only) if (external_polys_only)
{ {
result.add(const_cast<SliceLayerPart&>(part).outline.outerPolygon()); // TODO: make a const version of outerPolygon() result.add(part.outline.outerPolygon());
} }
else else
{ {
@@ -57,12 +57,12 @@ void SliceLayer::getSecondOrInnermostWalls(Polygons& layer_walls) const
{ {
// we want the 2nd inner walls // we want the 2nd inner walls
if (part.insets.size() >= 2) { if (part.insets.size() >= 2) {
layer_walls.add(const_cast<SliceLayerPart&>(part).insets[1]); // TODO const cast! layer_walls.add(part.insets[1]);
continue; continue;
} }
// but we'll also take the inner wall if the 2nd doesn't exist // but we'll also take the inner wall if the 2nd doesn't exist
if (part.insets.size() == 1) { if (part.insets.size() == 1) {
layer_walls.add(const_cast<SliceLayerPart&>(part).insets[0]); // TODO const cast! layer_walls.add(part.insets[0]);
continue; continue;
} }
// offset_from_outlines was so large that it completely destroyed our isle, // offset_from_outlines was so large that it completely destroyed our isle,
@@ -87,38 +87,11 @@ std::vector<RetractionConfig> SliceDataStorage::initializeRetractionConfigs()
return ret; return ret;
} }
std::vector<GCodePathConfig> SliceDataStorage::initializeTravelConfigs()
{
std::vector<GCodePathConfig> ret;
for (int extruder = 0; extruder < meshgroup->getExtruderCount(); extruder++)
{
travel_config_per_extruder.emplace_back(PrintFeatureType::MoveCombing);
}
return ret;
}
std::vector<GCodePathConfig> SliceDataStorage::initializeSkirtBrimConfigs()
{
std::vector<GCodePathConfig> ret;
for (int extruder = 0; extruder < meshgroup->getExtruderCount(); extruder++)
{
skirt_brim_config.emplace_back(PrintFeatureType::SkirtBrim);
}
return ret;
}
SliceDataStorage::SliceDataStorage(MeshGroup* meshgroup) : SettingsMessenger(meshgroup), SliceDataStorage::SliceDataStorage(MeshGroup* meshgroup) : SettingsMessenger(meshgroup),
meshgroup(meshgroup != nullptr ? meshgroup : new MeshGroup(FffProcessor::getInstance())), //If no mesh group is provided, we roll our own. meshgroup(meshgroup != nullptr ? meshgroup : new MeshGroup(FffProcessor::getInstance())), //If no mesh group is provided, we roll our own.
print_layer_count(0), print_layer_count(0),
retraction_config_per_extruder(initializeRetractionConfigs()), retraction_config_per_extruder(initializeRetractionConfigs()),
extruder_switch_retraction_config_per_extruder(initializeRetractionConfigs()), extruder_switch_retraction_config_per_extruder(initializeRetractionConfigs()),
travel_config_per_extruder(initializeTravelConfigs()),
skirt_brim_config(initializeSkirtBrimConfigs()),
raft_base_config(PrintFeatureType::SupportInterface),
raft_interface_config(PrintFeatureType::Support),
raft_surface_config(PrintFeatureType::SupportInterface),
support_config(PrintFeatureType::Support),
support_skin_config(PrintFeatureType::SupportInterface),
max_print_height_second_to_last_extruder(-1), max_print_height_second_to_last_extruder(-1),
primeTower(*this) primeTower(*this)
{ {
@@ -163,7 +136,7 @@ Polygons SliceDataStorage::getLayerOutlines(int layer_nr, bool include_helper_pa
} }
const SliceLayer& layer = mesh.layers[layer_nr]; const SliceLayer& layer = mesh.layers[layer_nr];
layer.getOutlines(total, external_polys_only); layer.getOutlines(total, external_polys_only);
if (const_cast<SliceMeshStorage&>(mesh).getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL) // TODO: make all getSetting functions const?? if (mesh.getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL)
{ {
total = total.unionPolygons(layer.openPolyLines.offsetPolyLine(100)); total = total.unionPolygons(layer.openPolyLines.offsetPolyLine(100));
} }
+12 -41
Ver Arquivo
@@ -8,10 +8,9 @@
#include "utils/NoCopy.h" #include "utils/NoCopy.h"
#include "utils/AABB.h" #include "utils/AABB.h"
#include "mesh.h" #include "mesh.h"
#include "gcodePlanner.h"
#include "MeshGroup.h" #include "MeshGroup.h"
#include "PrimeTower.h" #include "PrimeTower.h"
#include "GCodePathConfig.h" #include "gcodeExport.h" // CoastingConfig
namespace cura namespace cura
{ {
@@ -138,7 +137,11 @@ public:
std::vector<SupportLayer> supportLayers; std::vector<SupportLayer> supportLayers;
SupportStorage() : generated(false), layer_nr_max_filled_layer(-1) { } SupportStorage()
: generated(false)
, layer_nr_max_filled_layer(-1)
{
}
~SupportStorage(){ supportLayers.clear(); } ~SupportStorage(){ supportLayers.clear(); }
}; };
/******************/ /******************/
@@ -152,27 +155,14 @@ public:
int layer_nr_max_filled_layer; //!< the layer number of the uppermost layer with content (modified while infill meshes are processed) int layer_nr_max_filled_layer; //!< the layer number of the uppermost layer with content (modified while infill meshes are processed)
GCodePathConfig inset0_config;
GCodePathConfig insetX_config;
GCodePathConfig skin_config;
GCodePathConfig perimeter_gap_config;
std::vector<GCodePathConfig> infill_config;
SubDivCube* base_subdiv_cube; SubDivCube* base_subdiv_cube;
SliceMeshStorage(SettingsBaseVirtual* settings, unsigned int slice_layer_count) SliceMeshStorage(SettingsBaseVirtual* settings, unsigned int slice_layer_count)
: SettingsMessenger(settings) : SettingsMessenger(settings)
, layer_nr_max_filled_layer(0) , layer_nr_max_filled_layer(0)
, inset0_config(PrintFeatureType::OuterWall)
, insetX_config(PrintFeatureType::InnerWall)
, skin_config(PrintFeatureType::Skin)
, perimeter_gap_config(PrintFeatureType::Skin)
, base_subdiv_cube(nullptr) , base_subdiv_cube(nullptr)
{ {
layers.resize(slice_layer_count); layers.resize(slice_layer_count);
infill_config.reserve(MAX_INFILL_COMBINE);
for(int n=0; n<MAX_INFILL_COMBINE; n++)
infill_config.emplace_back(PrintFeatureType::Infill);
} }
virtual ~SliceMeshStorage(); virtual ~SliceMeshStorage();
@@ -191,18 +181,8 @@ public:
std::vector<RetractionConfig> retraction_config_per_extruder; //!< Retraction config per extruder. std::vector<RetractionConfig> retraction_config_per_extruder; //!< Retraction config per extruder.
std::vector<RetractionConfig> extruder_switch_retraction_config_per_extruder; //!< Retraction config per extruder for when performing an extruder switch std::vector<RetractionConfig> extruder_switch_retraction_config_per_extruder; //!< Retraction config per extruder for when performing an extruder switch
std::vector<GCodePathConfig> travel_config_per_extruder; //!< The config used for travel moves (only speed is set!)
std::vector<GCodePathConfig> skirt_brim_config; //!< Configuration for skirt and brim per extruder.
std::vector<CoastingConfig> coasting_config; //!< coasting config per extruder std::vector<CoastingConfig> coasting_config; //!< coasting config per extruder
GCodePathConfig raft_base_config;
GCodePathConfig raft_interface_config;
GCodePathConfig raft_surface_config;
GCodePathConfig support_config;
GCodePathConfig support_skin_config; //!< The config to use to print the dense roofs and bottoms of support
SupportStorage support; SupportStorage support;
Polygons skirt_brim[MAX_EXTRUDERS]; //!< Skirt and brim polygons per extruder, ordered from inner to outer polygons. Polygons skirt_brim[MAX_EXTRUDERS]; //!< Skirt and brim polygons per extruder, ordered from inner to outer polygons.
@@ -217,21 +197,6 @@ public:
std::vector<Polygons> oozeShield; //oozeShield per layer std::vector<Polygons> oozeShield; //oozeShield per layer
Polygons draft_protection_shield; //!< The polygons for a heightened skirt which protects from warping by gusts of wind and acts as a heated chamber. Polygons draft_protection_shield; //!< The polygons for a heightened skirt which protects from warping by gusts of wind and acts as a heated chamber.
/*!
* Construct the initial retraction_config_per_extruder
*/
std::vector<RetractionConfig> initializeRetractionConfigs();
/*!
* Construct the initial travel_config_per_extruder
*/
std::vector<GCodePathConfig> initializeTravelConfigs();
/*!
* Construct the initial skirt & brim configurations for each extruder.
*/
std::vector<GCodePathConfig> initializeSkirtBrimConfigs();
/*! /*!
* \brief Creates a new slice data storage that stores the slice data of the * \brief Creates a new slice data storage that stores the slice data of the
* specified mesh group. * specified mesh group.
@@ -281,6 +246,12 @@ public:
* \return a vector of bools indicating whether the extruder with corresponding index is used in this layer. * \return a vector of bools indicating whether the extruder with corresponding index is used in this layer.
*/ */
std::vector<bool> getExtrudersUsed(int layer_nr) const; std::vector<bool> getExtrudersUsed(int layer_nr) const;
private:
/*!
* Construct the retraction_config_per_extruder
*/
std::vector<RetractionConfig> initializeRetractionConfigs();
}; };
}//namespace cura }//namespace cura
+3 -3
Ver Arquivo
@@ -216,7 +216,7 @@ SlicerLayer::findPossibleStitches(
// insert the starts of the polylines). // insert the starts of the polylines).
for(unsigned int polyline_0_idx = 0; polyline_0_idx < open_polylines.size(); polyline_0_idx++) for(unsigned int polyline_0_idx = 0; polyline_0_idx < open_polylines.size(); polyline_0_idx++)
{ {
const PolygonRef polyline_0 = open_polylines[polyline_0_idx]; ConstPolygonRef polyline_0 = open_polylines[polyline_0_idx];
if (polyline_0.size() < 1) continue; if (polyline_0.size() < 1) continue;
@@ -231,7 +231,7 @@ SlicerLayer::findPossibleStitches(
{ {
for(unsigned int polyline_0_idx = 0; polyline_0_idx < open_polylines.size(); polyline_0_idx++) for(unsigned int polyline_0_idx = 0; polyline_0_idx < open_polylines.size(); polyline_0_idx++)
{ {
const PolygonRef polyline_0 = open_polylines[polyline_0_idx]; ConstPolygonRef polyline_0 = open_polylines[polyline_0_idx];
if (polyline_0.size() < 1) continue; if (polyline_0.size() < 1) continue;
@@ -245,7 +245,7 @@ SlicerLayer::findPossibleStitches(
// search for nearby end points // search for nearby end points
for(unsigned int polyline_1_idx = 0; polyline_1_idx < open_polylines.size(); polyline_1_idx++) for(unsigned int polyline_1_idx = 0; polyline_1_idx < open_polylines.size(); polyline_1_idx++)
{ {
const PolygonRef polyline_1 = open_polylines[polyline_1_idx]; ConstPolygonRef polyline_1 = open_polylines[polyline_1_idx];
if (polyline_1.size() < 1) continue; if (polyline_1.size() < 1) continue;
+2 -2
Ver Arquivo
@@ -24,7 +24,7 @@ AABB::AABB(const Polygons& polys)
calculate(polys); calculate(polys);
} }
AABB::AABB(const PolygonRef poly) AABB::AABB(ConstPolygonRef poly)
: min(POINT_MAX, POINT_MAX), max(POINT_MIN, POINT_MIN) : min(POINT_MAX, POINT_MAX), max(POINT_MIN, POINT_MIN)
{ {
calculate(poly); calculate(poly);
@@ -43,7 +43,7 @@ void AABB::calculate(const Polygons& polys)
} }
} }
void AABB::calculate(const PolygonRef poly) void AABB::calculate(ConstPolygonRef poly)
{ {
min = Point(POINT_MAX, POINT_MAX); min = Point(POINT_MAX, POINT_MAX);
max = Point(POINT_MIN, POINT_MIN); max = Point(POINT_MIN, POINT_MIN);
+2 -2
Ver Arquivo
@@ -20,10 +20,10 @@ public:
AABB(); //!< initializes with invalid min and max AABB(); //!< initializes with invalid min and max
AABB(Point& min, Point& max); //!< initializes with given min and max AABB(Point& min, Point& max); //!< initializes with given min and max
AABB(const Polygons& polys); //!< Computes the boundary box for the given polygons AABB(const Polygons& polys); //!< Computes the boundary box for the given polygons
AABB(const PolygonRef poly); //!< Computes the boundary box for the given polygons AABB(ConstPolygonRef poly); //!< Computes the boundary box for the given polygons
void calculate(const Polygons& polys); //!< Calculates the aabb for the given polygons (throws away old min and max data of this aabb) void calculate(const Polygons& polys); //!< Calculates the aabb for the given polygons (throws away old min and max data of this aabb)
void calculate(const PolygonRef poly); //!< Calculates the aabb for the given polygon (throws away old min and max data of this aabb) void calculate(ConstPolygonRef poly); //!< Calculates the aabb for the given polygon (throws away old min and max data of this aabb)
/*! /*!
* Check whether this aabb overlaps with another. * Check whether this aabb overlaps with another.
+7 -7
Ver Arquivo
@@ -10,21 +10,21 @@ namespace cura
{ {
void ListPolyIt::convertPolygonsToLists(Polygons& polys, ListPolygons& result) void ListPolyIt::convertPolygonsToLists(const Polygons& polys, ListPolygons& result)
{ {
for (PolygonRef poly : polys) for (ConstPolygonRef poly : polys)
{ {
result.emplace_back(); result.emplace_back();
convertPolygonToList(poly, result.back()); convertPolygonToList(poly, result.back());
} }
} }
void ListPolyIt::convertPolygonToList(PolygonRef poly, ListPolygon& result) void ListPolyIt::convertPolygonToList(ConstPolygonRef poly, ListPolygon& result)
{ {
#ifdef DEBUG #ifdef DEBUG
Point last = poly.back(); Point last = poly.back();
#endif // DEBUG #endif // DEBUG
for (Point& p : poly) for (const Point& p : poly)
{ {
result.push_back(p); result.push_back(p);
#ifdef DEBUG #ifdef DEBUG
@@ -39,7 +39,7 @@ void ListPolyIt::convertPolygonToList(PolygonRef poly, ListPolygon& result)
} }
void ListPolyIt::convertListPolygonsToPolygons(ListPolygons& list_polygons, Polygons& polygons) void ListPolyIt::convertListPolygonsToPolygons(const ListPolygons& list_polygons, Polygons& polygons)
{ {
for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++) for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++)
{ {
@@ -48,9 +48,9 @@ void ListPolyIt::convertListPolygonsToPolygons(ListPolygons& list_polygons, Poly
} }
} }
void ListPolyIt::convertListPolygonToPolygon(ListPolygon& list_polygon, PolygonRef polygon) void ListPolyIt::convertListPolygonToPolygon(const ListPolygon& list_polygon, PolygonRef polygon)
{ {
for (Point& p : list_polygon) for (const Point& p : list_polygon)
{ {
polygon.add(p); polygon.add(p);
} }
+4 -4
Ver Arquivo
@@ -94,28 +94,28 @@ public:
* \param polys The polygons to convert * \param polys The polygons to convert
* \param result The converted polygons * \param result The converted polygons
*/ */
static void convertPolygonsToLists(Polygons& polys, ListPolygons& result); static void convertPolygonsToLists(const Polygons& polys, ListPolygons& result);
/*! /*!
* Convert Polygons to ListPolygons * Convert Polygons to ListPolygons
* *
* \param polys The polygons to convert * \param polys The polygons to convert
* \param result The converted polygons * \param result The converted polygons
*/ */
static void convertPolygonToList(PolygonRef poly, ListPolygon& result); static void convertPolygonToList(ConstPolygonRef poly, ListPolygon& result);
/*! /*!
* Convert ListPolygons to Polygons * Convert ListPolygons to Polygons
* *
* \param list_polygons The polygons to convert * \param list_polygons The polygons to convert
* \param polygons The converted polygons * \param polygons The converted polygons
*/ */
static void convertListPolygonsToPolygons(ListPolygons& list_polygons, Polygons& polygons); static void convertListPolygonsToPolygons(const ListPolygons& list_polygons, Polygons& polygons);
/*! /*!
* Convert ListPolygons to Polygons * Convert ListPolygons to Polygons
* *
* \param list_polygons The polygons to convert * \param list_polygons The polygons to convert
* \param polygons The converted polygons * \param polygons The converted polygons
*/ */
static void convertListPolygonToPolygon(ListPolygon& list_polygon, PolygonRef polygon); static void convertListPolygonToPolygon(const ListPolygon& list_polygon, PolygonRef polygon);
/*! /*!
* Insert a point into a ListPolygon if it's not a duplicate of the point before or the point after. * Insert a point into a ListPolygon if it's not a duplicate of the point before or the point after.
+1 -1
Ver Arquivo
@@ -46,7 +46,7 @@ public:
/*! /*!
* Get the polygon to which this PolygonsPointIndex refers * Get the polygon to which this PolygonsPointIndex refers
*/ */
const PolygonRef getPolygon() const ConstPolygonRef getPolygon() const
{ {
return (*polygons)[poly_idx]; return (*polygons)[poly_idx];
} }
+5 -6
Ver Arquivo
@@ -93,9 +93,8 @@ public:
{ {
for(unsigned int j=0;j<parts.size();j++) for(unsigned int j=0;j<parts.size();j++)
{ {
Polygon poly = parts[j];
fprintf(out, "<polygon points=\""); fprintf(out, "<polygon points=\"");
for(Point& p : poly) for (Point& p : parts[j])
{ {
Point fp = transform(p); Point fp = transform(p);
fprintf(out, "%lli,%lli ", fp.X, fp.Y); fprintf(out, "%lli,%lli ", fp.X, fp.Y);
@@ -130,9 +129,9 @@ public:
} }
} }
void writePoints(PolygonRef poly, bool write_coords=false, int size = 5, Color color = Color::BLACK) void writePoints(ConstPolygonRef poly, bool write_coords=false, int size = 5, Color color = Color::BLACK)
{ {
for (Point& p : poly) for (const Point& p : poly)
{ {
writePoint(p, write_coords, size, color); writePoint(p, write_coords, size, color);
} }
@@ -209,12 +208,12 @@ public:
} }
void writePolygons(const Polygons& polys, Color color = Color::BLACK) void writePolygons(const Polygons& polys, Color color = Color::BLACK)
{ {
for (const PolygonRef poly : const_cast<Polygons&>(polys)) for (ConstPolygonRef poly : polys)
{ {
writePolygon(poly, color); writePolygon(poly, color);
} }
} }
void writePolygon(const PolygonRef poly, Color color = Color::BLACK) void writePolygon(ConstPolygonRef poly, Color color = Color::BLACK)
{ {
Point p0 = poly.back(); Point p0 = poly.back();
for (Point p1 : poly) for (Point p1 : poly)
+32 -31
Ver Arquivo
@@ -8,9 +8,9 @@
namespace cura namespace cura
{ {
bool PolygonRef::shorterThan(int64_t check_length) const bool ConstPolygonRef::shorterThan(int64_t check_length) const
{ {
const PolygonRef& polygon = *this; const ConstPolygonRef& polygon = *this;
const Point* p0 = &polygon.back(); const Point* p0 = &polygon.back();
int64_t length = 0; int64_t length = 0;
for (const Point& p1 : polygon) for (const Point& p1 : polygon)
@@ -25,9 +25,9 @@ bool PolygonRef::shorterThan(int64_t check_length) const
return true; return true;
} }
bool PolygonRef::_inside(Point p, bool border_result) const bool ConstPolygonRef::_inside(Point p, bool border_result) const
{ {
PolygonRef thiss = *this; const ConstPolygonRef thiss = *this;
if (size() < 1) if (size() < 1)
{ {
return false; return false;
@@ -200,11 +200,11 @@ Polygons Polygons::offset(int distance, ClipperLib::JoinType join_type, double m
return ret; return ret;
} }
Polygons PolygonRef::offset(int distance, ClipperLib::JoinType joinType, double miter_limit) const Polygons ConstPolygonRef::offset(int distance, ClipperLib::JoinType join_type, double miter_limit) const
{ {
Polygons ret; Polygons ret;
ClipperLib::ClipperOffset clipper(miter_limit, 10.0); ClipperLib::ClipperOffset clipper(miter_limit, 10.0);
clipper.AddPath(*path, joinType, ClipperLib::etClosedPolygon); clipper.AddPath(*path, join_type, ClipperLib::etClosedPolygon);
clipper.MiterLimit = miter_limit; clipper.MiterLimit = miter_limit;
clipper.Execute(ret.paths, distance); clipper.Execute(ret.paths, distance);
return ret; return ret;
@@ -521,7 +521,7 @@ void Polygons::removeEmptyHoles_processPolyTreeNode(const ClipperLib::PolyNode&
} }
} }
bool PolygonRef::smooth_corner_complex(ListPolygon& poly, const Point p1, ListPolyIt& p0_it, ListPolyIt& p2_it, const int64_t shortcut_length) bool ConstPolygonRef::smooth_corner_complex(ListPolygon& poly, const Point p1, ListPolyIt& p0_it, ListPolyIt& p2_it, const int64_t shortcut_length)
{ {
// walk away from the corner until the shortcut > shortcut_length or it would smooth a piece inward // walk away from the corner until the shortcut > shortcut_length or it would smooth a piece inward
// - walk in both directions untill shortcut > shortcut_length // - walk in both directions untill shortcut > shortcut_length
@@ -703,7 +703,7 @@ bool PolygonRef::smooth_corner_complex(ListPolygon& poly, const Point p1, ListPo
return false; return false;
} }
void PolygonRef::smooth_outward_step(const Point p1, const int64_t shortcut_length2, ListPolyIt& p0_it, ListPolyIt& p2_it, bool& forward_is_blocked, bool& backward_is_blocked, bool& forward_is_too_far, bool& backward_is_too_far) void ConstPolygonRef::smooth_outward_step(const Point p1, const int64_t shortcut_length2, ListPolyIt& p0_it, ListPolyIt& p2_it, bool& forward_is_blocked, bool& backward_is_blocked, bool& forward_is_too_far, bool& backward_is_too_far)
{ {
const bool forward_has_converged = forward_is_blocked || forward_is_too_far; const bool forward_has_converged = forward_is_blocked || forward_is_too_far;
const bool backward_has_converged = backward_is_blocked || backward_is_too_far; const bool backward_has_converged = backward_is_blocked || backward_is_too_far;
@@ -759,7 +759,7 @@ void PolygonRef::smooth_outward_step(const Point p1, const int64_t shortcut_leng
} }
} }
void PolygonRef::smooth_corner_simple(ListPolygon& poly, const Point p0, const Point p1, const Point p2, const ListPolyIt p0_it, const ListPolyIt p1_it, const ListPolyIt p2_it, const Point v10, const Point v12, const Point v02, const int64_t shortcut_length, float cos_angle) void ConstPolygonRef::smooth_corner_simple(ListPolygon& poly, const Point p0, const Point p1, const Point p2, const ListPolyIt p0_it, const ListPolyIt p1_it, const ListPolyIt p2_it, const Point v10, const Point v12, const Point v02, const int64_t shortcut_length, float cos_angle)
{ {
// 1----b---->2 // 1----b---->2
// ^ / // ^ /
@@ -849,7 +849,7 @@ void PolygonRef::smooth_corner_simple(ListPolygon& poly, const Point p0, const P
} }
} }
void PolygonRef::smooth_outward(float min_angle, int shortcut_length, PolygonRef result) const void ConstPolygonRef::smooth_outward(float min_angle, int shortcut_length, PolygonRef result) const
{ {
// example of smoothed out corner: // example of smoothed out corner:
// //
@@ -952,7 +952,8 @@ Polygons Polygons::smooth_outward(float max_angle, int shortcut_length)
return ret; return ret;
} }
void PolygonRef::smooth(int remove_length, PolygonRef result)
void ConstPolygonRef::smooth(int remove_length, PolygonRef result) const
{ {
// a typical zigzag with the middle part to be removed by removing (1) : // a typical zigzag with the middle part to be removed by removing (1) :
// //
@@ -967,7 +968,7 @@ void PolygonRef::smooth(int remove_length, PolygonRef result)
// | // |
// | // |
// 0 // 0
PolygonRef& thiss = *this; const ConstPolygonRef& thiss = *path;
ClipperLib::Path* poly = result.path; ClipperLib::Path* poly = result.path;
if (size() > 0) if (size() > 0)
{ {
@@ -1036,12 +1037,12 @@ void PolygonRef::smooth(int remove_length, PolygonRef result)
} }
} }
Polygons Polygons::smooth(int remove_length) Polygons Polygons::smooth(int remove_length) const
{ {
Polygons ret; Polygons ret;
for (unsigned int p = 0; p < size(); p++) for (unsigned int p = 0; p < size(); p++)
{ {
PolygonRef poly(paths[p]); ConstPolygonRef poly(paths[p]);
if (poly.size() < 3) if (poly.size() < 3)
{ {
continue; continue;
@@ -1061,23 +1062,23 @@ Polygons Polygons::smooth(int remove_length)
return ret; return ret;
} }
void PolygonRef::smooth2(int remove_length, PolygonRef result) void ConstPolygonRef::smooth2(int remove_length, PolygonRef result) const
{ {
PolygonRef& thiss = *this; const ConstPolygonRef& thiss = *this;
ClipperLib::Path* poly = result.path; ClipperLib::Path* poly = result.path;
if (size() > 0) if (thiss.size() > 0)
{ {
poly->push_back(thiss[0]); poly->push_back(thiss[0]);
} }
for (unsigned int poly_idx = 1; poly_idx < size(); poly_idx++) for (unsigned int poly_idx = 1; poly_idx < thiss.size(); poly_idx++)
{ {
Point& last = thiss[poly_idx - 1]; const Point& last = thiss[poly_idx - 1];
Point& now = thiss[poly_idx]; const Point& now = thiss[poly_idx];
Point& next = thiss[(poly_idx + 1) % size()]; const Point& next = thiss[(poly_idx + 1) % thiss.size()];
if (shorterThen(last - now, remove_length) && shorterThen(now - next, remove_length)) if (shorterThen(last - now, remove_length) && shorterThen(now - next, remove_length))
{ {
poly_idx++; // skip the next line piece (dont escalate the removal of edges) poly_idx++; // skip the next line piece (dont escalate the removal of edges)
if (poly_idx < size()) if (poly_idx < thiss.size())
{ {
poly->push_back(thiss[poly_idx]); poly->push_back(thiss[poly_idx]);
} }
@@ -1089,12 +1090,12 @@ void PolygonRef::smooth2(int remove_length, PolygonRef result)
} }
} }
Polygons Polygons::smooth2(int remove_length, int min_area) Polygons Polygons::smooth2(int remove_length, int min_area) const
{ {
Polygons ret; Polygons ret;
for (unsigned int p = 0; p < size(); p++) for (unsigned int p = 0; p < size(); p++)
{ {
PolygonRef poly(paths[p]); ConstPolygonRef poly(paths[p]);
if (poly.size() == 0) if (poly.size() == 0)
{ {
continue; continue;
@@ -1147,14 +1148,14 @@ void Polygons::splitIntoParts_processPolyTreeNode(ClipperLib::PolyNode* node, st
} }
} }
unsigned int PartsView::getPartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx) unsigned int PartsView::getPartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx) const
{ {
PartsView& partsView = *this; const PartsView& partsView = *this;
for (unsigned int part_idx_now = 0; part_idx_now < partsView.size(); part_idx_now++) for (unsigned int part_idx_now = 0; part_idx_now < partsView.size(); part_idx_now++)
{ {
std::vector<unsigned int>& partView = partsView[part_idx_now]; const std::vector<unsigned int>& partView = partsView[part_idx_now];
if (partView.size() == 0) { continue; } if (partView.size() == 0) { continue; }
std::vector<unsigned int>::iterator result = std::find(partView.begin(), partView.end(), poly_idx); std::vector<unsigned int>::const_iterator result = std::find(partView.begin(), partView.end(), poly_idx);
if (result != partView.end()) if (result != partView.end())
{ {
if (boundary_poly_idx) { *boundary_poly_idx = partView[0]; } if (boundary_poly_idx) { *boundary_poly_idx = partView[0]; }
@@ -1178,7 +1179,7 @@ PolygonsPart PartsView::assemblePart(unsigned int part_idx) const
return ret; return ret;
} }
PolygonsPart PartsView::assemblePartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx) PolygonsPart PartsView::assemblePartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx) const
{ {
PolygonsPart ret; PolygonsPart ret;
unsigned int part_idx = getPartContaining(poly_idx, boundary_poly_idx); unsigned int part_idx = getPartContaining(poly_idx, boundary_poly_idx);
@@ -1215,7 +1216,7 @@ void Polygons::splitIntoPartsView_processPolyTreeNode(PartsView& partsView, Poly
partsView.emplace_back(); partsView.emplace_back();
unsigned int pos = partsView.size() - 1; unsigned int pos = partsView.size() - 1;
partsView[pos].push_back(reordered.size()); partsView[pos].push_back(reordered.size());
reordered.add(child->Contour); reordered.add(child->Contour); //TODO: should this steal the internal representation for speed?
for(int i = 0; i < child->ChildCount(); i++) for(int i = 0; i < child->ChildCount(); i++)
{ {
partsView[pos].push_back(reordered.size()); partsView[pos].push_back(reordered.size());
+184 -121
Ver Arquivo
@@ -27,6 +27,8 @@ namespace cura {
class PartsView; class PartsView;
class Polygons; class Polygons;
class Polygon;
class PolygonRef;
class ListPolyIt; class ListPolyIt;
@@ -36,31 +38,60 @@ typedef std::vector<ListPolygon> ListPolygons; //!< Polygons represented by a ve
const static int clipper_init = (0); const static int clipper_init = (0);
#define NO_INDEX (std::numeric_limits<unsigned int>::max()) #define NO_INDEX (std::numeric_limits<unsigned int>::max())
class PolygonRef class ConstPolygonRef
{ {
friend class Polygons;
friend class Polygon;
friend class PolygonRef;
protected:
ClipperLib::Path* path; ClipperLib::Path* path;
PolygonRef() ConstPolygonRef()
: path(nullptr) : path(nullptr)
{} {}
public: public:
PolygonRef(ClipperLib::Path& polygon) ConstPolygonRef(const ClipperLib::Path& polygon)
: path(&polygon) : path(const_cast<ClipperLib::Path*>(&polygon))
{} {}
bool operator==(ConstPolygonRef& other) const =delete;
// needed in std::optional<ConstPolygonRef>
// ConstPolygonRef& operator=(const ConstPolygonRef& other) =delete;
ConstPolygonRef& operator=(const ConstPolygonRef& other)
{
path = other.path;
return *this;
}
unsigned int size() const unsigned int size() const
{ {
return path->size(); return path->size();
} }
Point& operator[] (unsigned int index) const const Point& operator[] (unsigned int index) const
{ {
POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max()); POLY_ASSERT(index < size());
return (*path)[index]; return (*path)[index];
} }
void* data() const ClipperLib::Path& operator*() const
{ {
return path->data(); return *path;
}
ClipperLib::Path::const_iterator begin() const
{
return path->begin();
}
ClipperLib::Path::const_iterator end() const
{
return path->end();
}
ClipperLib::Path::const_reference back() const
{
return path->back();
} }
const void* data() const const void* data() const
@@ -68,37 +99,10 @@ public:
return path->data(); return path->data();
} }
void add(const Point p)
{
path->push_back(p);
}
PolygonRef& operator=(const PolygonRef& other) { path = other.path; return *this; }
bool operator==(const PolygonRef& other) const =delete;
ClipperLib::Path& operator*() { return *path; }
template <typename... Args>
void emplace_back(Args&&... args)
{
path->emplace_back(args...);
}
void remove(unsigned int index)
{
POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max());
path->erase(path->begin() + index);
}
void clear()
{
path->clear();
}
/*! /*!
* On Y-axis positive upward displays, Orientation will return true if the polygon's orientation is counter-clockwise. * On Y-axis positive upward displays, Orientation will return true if the polygon's orientation is counter-clockwise.
* *
* from http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Functions/Orientation.htm * from http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Functions/Orientation.htm
*/ */
bool orientation() const bool orientation() const
@@ -106,11 +110,6 @@ public:
return ClipperLib::Orientation(*path); return ClipperLib::Orientation(*path);
} }
void reverse()
{
ClipperLib::ReversePath(*path);
}
Polygons offset(int distance, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miter_limit = 1.2) const; Polygons offset(int distance, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miter_limit = 1.2) const;
int64_t polygonLength() const int64_t polygonLength() const
@@ -125,7 +124,7 @@ public:
} }
return length; return length;
} }
bool shorterThan(int64_t check_length) const; bool shorterThan(int64_t check_length) const;
Point min() const Point min() const
@@ -138,7 +137,7 @@ public:
} }
return ret; return ret;
} }
Point max() const Point max() const
{ {
Point ret = Point(POINT_MIN, POINT_MIN); Point ret = Point(POINT_MIN, POINT_MIN);
@@ -154,19 +153,6 @@ public:
{ {
return ClipperLib::Area(*path); return ClipperLib::Area(*path);
} }
/*!
* Translate the whole polygon in some direction.
*
* \param translation The direction in which to move the polygon
*/
void translate(Point translation)
{
for (Point& p : *this)
{
p += translation;
}
}
Point centerOfMass() const Point centerOfMass() const
{ {
@@ -183,14 +169,14 @@ public:
} }
double area = Area(*path); double area = Area(*path);
x = x / 6 / area; x = x / 6 / area;
y = y / 6 / area; y = y / 6 / area;
return Point(x, y); return Point(x, y);
} }
Point closestPointTo(Point p) Point closestPointTo(Point p) const
{ {
Point ret = p; Point ret = p;
float bestDist = FLT_MAX; float bestDist = FLT_MAX;
@@ -205,7 +191,7 @@ public:
} }
return ret; return ret;
} }
/*! /*!
* Check if we are inside the polygon. We do this by tracing from the point towards the positive X direction, * Check if we are inside the polygon. We do this by tracing from the point towards the positive X direction,
* every line we cross increments the crossings counter. If we have an even number of crossings then we are not inside the polygon. * every line we cross increments the crossings counter. If we have an even number of crossings then we are not inside the polygon.
@@ -241,7 +227,7 @@ public:
} }
return res == 1; return res == 1;
} }
/*! /*!
* Smooth out small perpendicular segments and store the result in \p result. * Smooth out small perpendicular segments and store the result in \p result.
* Smoothing is performed by removing the inner most vertex of a line segment smaller than \p remove_length * Smoothing is performed by removing the inner most vertex of a line segment smaller than \p remove_length
@@ -253,7 +239,7 @@ public:
* \param remove_length The length of the largest segment removed * \param remove_length The length of the largest segment removed
* \param result (output) The result polygon, assumed to be empty * \param result (output) The result polygon, assumed to be empty
*/ */
void smooth(int remove_length, PolygonRef result); void smooth(int remove_length, PolygonRef result) const;
/*! /*!
* Smooth out sharp inner corners, by taking a shortcut which bypasses the corner * Smooth out sharp inner corners, by taking a shortcut which bypasses the corner
@@ -271,51 +257,8 @@ public:
* \param remove_length The length of the largest segment removed * \param remove_length The length of the largest segment removed
* \param result (output) The result polygon, assumed to be empty * \param result (output) The result polygon, assumed to be empty
*/ */
void smooth2(int remove_length, PolygonRef result); void smooth2(int remove_length, PolygonRef result) const;
/*!
* Removes consecutive line segments with same orientation and changes this polygon.
*
* Removes verts which are connected to line segments which are both too small.
* Removes verts which detour from a direct line from the previous and next vert by a too small amount.
*
* \param smallest_line_segment_squared maximal squared length of removed line segments
* \param allowed_error_distance_squared The square of the distance of the middle point to the line segment of the consecutive and previous point for which the middle point is removed
*/
void simplify(int smallest_line_segment_squared = 100, int allowed_error_distance_squared = 25);
void pop_back()
{
path->pop_back();
}
ClipperLib::Path::reference back() const
{
return path->back();
}
ClipperLib::Path::iterator begin()
{
return path->begin();
}
ClipperLib::Path::iterator end()
{
return path->end();
}
ClipperLib::Path::const_iterator begin() const
{
return path->begin();
}
ClipperLib::Path::const_iterator end() const
{
return path->end();
}
friend class Polygons;
friend class Polygon;
private: private:
/*! /*!
@@ -375,6 +318,113 @@ private:
static void smooth_outward_step(const Point p1, const int64_t shortcut_length2, ListPolyIt& p0_it, ListPolyIt& p2_it, bool& forward_is_blocked, bool& backward_is_blocked, bool& forward_is_too_far, bool& backward_is_too_far); static void smooth_outward_step(const Point p1, const int64_t shortcut_length2, ListPolyIt& p0_it, ListPolyIt& p2_it, bool& forward_is_blocked, bool& backward_is_blocked, bool& forward_is_too_far, bool& backward_is_too_far);
}; };
class PolygonRef : public ConstPolygonRef
{
PolygonRef()
: ConstPolygonRef()
{}
public:
PolygonRef(ClipperLib::Path& polygon)
: ConstPolygonRef(polygon)
{}
PolygonRef& operator=(const PolygonRef& other)
{
path = other.path;
return *this;
}
Point& operator[] (unsigned int index)
{
POLY_ASSERT(index < size());
return (*path)[index];
}
ClipperLib::Path::iterator begin()
{
return path->begin();
}
ClipperLib::Path::iterator end()
{
return path->end();
}
ClipperLib::Path::reference back()
{
return path->back();
}
void* data()
{
return path->data();
}
void add(const Point p)
{
path->push_back(p);
}
PolygonRef& operator=(ConstPolygonRef& other) { path = other.path; return *this; }
ClipperLib::Path& operator*()
{
return *path;
}
template <typename... Args>
void emplace_back(Args&&... args)
{
path->emplace_back(args...);
}
void remove(unsigned int index)
{
POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max());
path->erase(path->begin() + index);
}
void clear()
{
path->clear();
}
void reverse()
{
ClipperLib::ReversePath(*path);
}
/*!
* Translate the whole polygon in some direction.
*
* \param translation The direction in which to move the polygon
*/
void translate(Point translation)
{
for (Point& p : *this)
{
p += translation;
}
}
/*!
* Removes consecutive line segments with same orientation and changes this polygon.
*
* Removes verts which are connected to line segments which are both too small.
* Removes verts which detour from a direct line from the previous and next vert by a too small amount.
*
* \param smallest_line_segment_squared maximal squared length of removed line segments
* \param allowed_error_distance_squared The square of the distance of the middle point to the line segment of the consecutive and previous point for which the middle point is removed
*/
void simplify(int smallest_line_segment_squared = 100, int allowed_error_distance_squared = 25);
void pop_back()
{
path->pop_back();
}
};
class Polygon : public PolygonRef class Polygon : public PolygonRef
{ {
ClipperLib::Path poly; ClipperLib::Path poly;
@@ -384,7 +434,7 @@ public:
{ {
} }
Polygon(const PolygonRef& other) Polygon(PolygonRef& other)
: PolygonRef(poly) : PolygonRef(poly)
{ {
poly = *other.path; poly = *other.path;
@@ -397,6 +447,7 @@ class Polygons
{ {
friend class Polygon; friend class Polygon;
friend class PolygonRef; friend class PolygonRef;
friend class ConstPolygonRef;
protected: protected:
ClipperLib::Paths paths; ClipperLib::Paths paths;
public: public:
@@ -410,11 +461,12 @@ public:
PolygonRef operator[] (unsigned int index) PolygonRef operator[] (unsigned int index)
{ {
POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max()); POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max());
return PolygonRef(paths[index]); return paths[index];
} }
const PolygonRef operator[] (unsigned int index) const ConstPolygonRef operator[] (unsigned int index) const
{ {
return const_cast<Polygons*>(this)->operator[](index); POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max());
return paths[index];
} }
ClipperLib::Paths::iterator begin() ClipperLib::Paths::iterator begin()
{ {
@@ -457,7 +509,11 @@ public:
{ {
paths.clear(); paths.clear();
} }
void add(const PolygonRef& poly) void add(ConstPolygonRef& poly)
{
paths.push_back(*poly.path);
}
void add(const ConstPolygonRef& poly)
{ {
paths.push_back(*poly.path); paths.push_back(*poly.path);
} }
@@ -493,6 +549,10 @@ public:
{ {
return PolygonRef(paths.back()); return PolygonRef(paths.back());
} }
ConstPolygonRef back() const
{
return ConstPolygonRef(paths.back());
}
Polygons() {} Polygons() {}
@@ -647,7 +707,7 @@ public:
* \param remove_length The length of the largest segment removed * \param remove_length The length of the largest segment removed
* \return The smoothed polygon * \return The smoothed polygon
*/ */
Polygons smooth(int remove_length); Polygons smooth(int remove_length) const;
/*! /*!
* Smooth out sharp inner corners, by taking a shortcut which bypasses the corner * Smooth out sharp inner corners, by taking a shortcut which bypasses the corner
@@ -658,7 +718,7 @@ public:
*/ */
Polygons smooth_outward(float angle, int shortcut_length); Polygons smooth_outward(float angle, int shortcut_length);
Polygons smooth2(int remove_length, int min_area); //!< removes points connected to small lines Polygons smooth2(int remove_length, int min_area) const; //!< removes points connected to small lines
/*! /*!
* removes points connected to similarly oriented lines * removes points connected to similarly oriented lines
@@ -798,16 +858,16 @@ public:
* Removes the same polygons from this set (and also empty polygons). * Removes the same polygons from this set (and also empty polygons).
* Polygons are considered the same if all points lie within [same_distance] of their counterparts. * Polygons are considered the same if all points lie within [same_distance] of their counterparts.
*/ */
Polygons remove(Polygons& to_be_removed, int same_distance = 0) Polygons remove(const Polygons& to_be_removed, int same_distance = 0) const
{ {
Polygons result; Polygons result;
for (unsigned int poly_keep_idx = 0; poly_keep_idx < size(); poly_keep_idx++) for (unsigned int poly_keep_idx = 0; poly_keep_idx < size(); poly_keep_idx++)
{ {
PolygonRef poly_keep = (*this)[poly_keep_idx]; ConstPolygonRef poly_keep = (*this)[poly_keep_idx];
bool should_be_removed = false; bool should_be_removed = false;
if (poly_keep.size() > 0) if (poly_keep.size() > 0)
// for (int hole_poly_idx = 0; hole_poly_idx < to_be_removed.size(); hole_poly_idx++) // for (int hole_poly_idx = 0; hole_poly_idx < to_be_removed.size(); hole_poly_idx++)
for (PolygonRef poly_rem : to_be_removed) for (ConstPolygonRef poly_rem : to_be_removed)
{ {
// PolygonRef poly_rem = to_be_removed[hole_poly_idx]; // PolygonRef poly_rem = to_be_removed[hole_poly_idx];
if (poly_rem.size() != poly_keep.size() || poly_rem.size() == 0) continue; if (poly_rem.size() != poly_keep.size() || poly_rem.size() == 0) continue;
@@ -923,10 +983,13 @@ public:
class PolygonsPart : public Polygons class PolygonsPart : public Polygons
{ {
public: public:
PolygonRef outerPolygon() PolygonRef outerPolygon()
{ {
Polygons& thiss = *this; return this->paths[0];
return thiss[0]; }
ConstPolygonRef outerPolygon() const
{
return this->paths[0];
} }
bool inside(Point p) bool inside(Point p)
@@ -959,7 +1022,7 @@ public:
* \param boundary_poly_idx Optional output parameter: The index of the boundary polygon of the part in \p polygons * \param boundary_poly_idx Optional output parameter: The index of the boundary polygon of the part in \p polygons
* \return The PolygonsPart containing the polygon with index \p poly_idx * \return The PolygonsPart containing the polygon with index \p poly_idx
*/ */
unsigned int getPartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx = nullptr); unsigned int getPartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx = nullptr) const;
/*! /*!
* Assemble the PolygonsPart of which the polygon with index \p poly_idx is part. * Assemble the PolygonsPart of which the polygon with index \p poly_idx is part.
* *
@@ -967,7 +1030,7 @@ public:
* \param boundary_poly_idx Optional output parameter: The index of the boundary polygon of the part in \p polygons * \param boundary_poly_idx Optional output parameter: The index of the boundary polygon of the part in \p polygons
* \return The PolygonsPart containing the polygon with index \p poly_idx * \return The PolygonsPart containing the polygon with index \p poly_idx
*/ */
PolygonsPart assemblePartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx = nullptr); PolygonsPart assemblePartContaining(unsigned int poly_idx, unsigned int* boundary_poly_idx = nullptr) const;
/*! /*!
* Assemble the PolygonsPart of which the polygon with index \p poly_idx is part. * Assemble the PolygonsPart of which the polygon with index \p poly_idx is part.
* *
+39 -39
Ver Arquivo
@@ -22,7 +22,7 @@ int64_t PolygonUtils::segmentLength(PolygonsPointIndex start, PolygonsPointIndex
assert(start.poly_idx == end.poly_idx); assert(start.poly_idx == end.poly_idx);
int64_t segment_length = 0; int64_t segment_length = 0;
Point prev_vert = start.p(); Point prev_vert = start.p();
const PolygonRef poly = (*start.polygons)[start.poly_idx]; ConstPolygonRef poly = (*start.polygons)[start.poly_idx];
for (unsigned int point_idx = 1; point_idx <= poly.size(); point_idx++) for (unsigned int point_idx = 1; point_idx <= poly.size(); point_idx++)
{ {
unsigned int vert_idx = (start.point_idx + point_idx) % poly.size(); unsigned int vert_idx = (start.point_idx + point_idx) % poly.size();
@@ -44,7 +44,7 @@ void PolygonUtils::spreadDots(PolygonsPointIndex start, PolygonsPointIndex end,
assert(start.poly_idx == end.poly_idx); assert(start.poly_idx == end.poly_idx);
int64_t segment_length = segmentLength(start, end); int64_t segment_length = segmentLength(start, end);
const PolygonRef poly = (*start.polygons)[start.poly_idx]; ConstPolygonRef poly = (*start.polygons)[start.poly_idx];
unsigned int n_dots_in_between = n_dots; unsigned int n_dots_in_between = n_dots;
if (start == end) if (start == end)
{ {
@@ -80,7 +80,7 @@ void PolygonUtils::spreadDots(PolygonsPointIndex start, PolygonsPointIndex end,
assert(result.size() == n_dots && "we didn't generate as many wipe locations as we asked for."); assert(result.size() == n_dots && "we didn't generate as many wipe locations as we asked for.");
} }
Point PolygonUtils::getVertexInwardNormal(PolygonRef poly, unsigned int point_idx) Point PolygonUtils::getVertexInwardNormal(ConstPolygonRef poly, unsigned int point_idx)
{ {
Point p1 = poly[point_idx]; Point p1 = poly[point_idx];
@@ -110,7 +110,7 @@ Point PolygonUtils::getVertexInwardNormal(PolygonRef poly, unsigned int point_id
break; break;
} }
} }
Point& p2 = poly[p2_idx]; const Point& p2 = poly[p2_idx];
Point off0 = turn90CCW(normal(p1 - p0, MM2INT(10.0))); // 10.0 for some precision Point off0 = turn90CCW(normal(p1 - p0, MM2INT(10.0))); // 10.0 for some precision
Point off1 = turn90CCW(normal(p2 - p1, MM2INT(10.0))); // 10.0 for some precision Point off1 = turn90CCW(normal(p2 - p1, MM2INT(10.0))); // 10.0 for some precision
@@ -119,7 +119,7 @@ Point PolygonUtils::getVertexInwardNormal(PolygonRef poly, unsigned int point_id
} }
Point PolygonUtils::getBoundaryPointWithOffset(PolygonRef poly, unsigned int point_idx, int64_t offset) Point PolygonUtils::getBoundaryPointWithOffset(ConstPolygonRef poly, unsigned int point_idx, int64_t offset)
{ {
return poly[point_idx] + normal(getVertexInwardNormal(poly, point_idx), -offset); return poly[point_idx] + normal(getVertexInwardNormal(poly, point_idx), -offset);
} }
@@ -130,7 +130,7 @@ Point PolygonUtils::moveInsideDiagonally(ClosestPolygonPoint point_on_boundary,
{ {
return no_point; return no_point;
} }
PolygonRef poly = *point_on_boundary.poly; ConstPolygonRef poly = *point_on_boundary.poly;
Point p0 = poly[point_on_boundary.point_idx]; Point p0 = poly[point_on_boundary.point_idx];
Point p1 = poly[(point_on_boundary.point_idx + 1) % poly.size()]; Point p1 = poly[(point_on_boundary.point_idx + 1) % poly.size()];
if (vSize2(p0 - point_on_boundary.location) < vSize2(p1 - point_on_boundary.location)) if (vSize2(p0 - point_on_boundary.location) < vSize2(p1 - point_on_boundary.location))
@@ -163,7 +163,7 @@ ClosestPolygonPoint PolygonUtils::moveInside2(const Polygons& polygons, Point& f
return _moveInside2(*closest_polygon_point, distance, from, max_dist2); return _moveInside2(*closest_polygon_point, distance, from, max_dist2);
} }
ClosestPolygonPoint PolygonUtils::moveInside2(const Polygons& loc_to_line_polygons, const PolygonRef polygon, Point& from, const int distance, const int64_t max_dist2, const LocToLineGrid* loc_to_line_grid, const std::function<int(Point)>& penalty_function) ClosestPolygonPoint PolygonUtils::moveInside2(const Polygons& loc_to_line_polygons, ConstPolygonRef polygon, Point& from, const int distance, const int64_t max_dist2, const LocToLineGrid* loc_to_line_grid, const std::function<int(Point)>& penalty_function)
{ {
std::optional<ClosestPolygonPoint> closest_polygon_point; std::optional<ClosestPolygonPoint> closest_polygon_point;
if (loc_to_line_grid) if (loc_to_line_grid)
@@ -225,7 +225,7 @@ unsigned int PolygonUtils::moveInside(const Polygons& polygons, Point& from, int
bool is_already_on_correct_side_of_boundary = false; // whether [from] is already on the right side of the boundary bool is_already_on_correct_side_of_boundary = false; // whether [from] is already on the right side of the boundary
for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++) for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++)
{ {
const PolygonRef poly = polygons[poly_idx]; ConstPolygonRef poly = polygons[poly_idx];
if (poly.size() < 2) if (poly.size() < 2)
continue; continue;
Point p0 = poly[poly.size()-2]; Point p0 = poly[poly.size()-2];
@@ -344,11 +344,11 @@ Point PolygonUtils::moveInside(const ClosestPolygonPoint& cpp, const int distanc
{ // the point which is assumed to be on the boundary doesn't have to be moved { // the point which is assumed to be on the boundary doesn't have to be moved
return cpp.location; return cpp.location;
} }
const PolygonRef poly = *cpp.poly; ConstPolygonRef poly = *cpp.poly;
unsigned int point_idx = cpp.point_idx; unsigned int point_idx = cpp.point_idx;
const Point& on_boundary = cpp.location; const Point& on_boundary = cpp.location;
Point& p1 = poly[point_idx]; const Point& p1 = poly[point_idx];
unsigned int p2_idx; unsigned int p2_idx;
for (p2_idx = point_idx + 1; p2_idx != point_idx; p2_idx = p2_idx + 1) for (p2_idx = point_idx + 1; p2_idx != point_idx; p2_idx = p2_idx + 1)
{ // find the next point different from p1 { // find the next point different from p1
@@ -361,7 +361,7 @@ Point PolygonUtils::moveInside(const ClosestPolygonPoint& cpp, const int distanc
break; break;
} }
} }
Point& p2 = poly[p2_idx]; const Point& p2 = poly[p2_idx];
if (on_boundary == p1) if (on_boundary == p1)
{ {
@@ -392,7 +392,7 @@ ClosestPolygonPoint PolygonUtils::ensureInsideOrOutside(const Polygons& polygons
{ {
return ClosestPolygonPoint(); // we couldn't move inside return ClosestPolygonPoint(); // we couldn't move inside
} }
PolygonRef closest_poly = *closest_polygon_point.poly; ConstPolygonRef closest_poly = *closest_polygon_point.poly;
bool is_outside_boundary = closest_poly.orientation(); bool is_outside_boundary = closest_poly.orientation();
{ {
@@ -481,8 +481,8 @@ void PolygonUtils::findSmallestConnection(ClosestPolygonPoint& poly1_result, Clo
{ {
return; return;
} }
PolygonRef poly1 = *poly1_result.poly; ConstPolygonRef poly1 = *poly1_result.poly;
PolygonRef poly2 = *poly2_result.poly; ConstPolygonRef poly2 = *poly2_result.poly;
if (poly1.size() == 0 || poly2.size() == 0) if (poly1.size() == 0 || poly2.size() == 0)
{ {
return; return;
@@ -515,8 +515,8 @@ void PolygonUtils::walkToNearestSmallestConnection(ClosestPolygonPoint& poly1_re
{ {
return; return;
} }
PolygonRef poly1 = *poly1_result.poly; ConstPolygonRef poly1 = *poly1_result.poly;
PolygonRef poly2 = *poly2_result.poly; ConstPolygonRef poly2 = *poly2_result.poly;
if (poly1_result.point_idx < 0 || poly2_result.point_idx < 0) if (poly1_result.point_idx < 0 || poly2_result.point_idx < 0)
{ {
return; return;
@@ -537,7 +537,7 @@ void PolygonUtils::walkToNearestSmallestConnection(ClosestPolygonPoint& poly1_re
} }
} }
ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, PolygonRef polygon, int start_idx) ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, ConstPolygonRef polygon, int start_idx)
{ {
ClosestPolygonPoint forth = findNearestClosest(from, polygon, start_idx, 1); ClosestPolygonPoint forth = findNearestClosest(from, polygon, start_idx, 1);
if (!forth.isValid()) if (!forth.isValid())
@@ -556,7 +556,7 @@ ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, PolygonRef poly
} }
} }
ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, PolygonRef polygon, int start_idx, int direction) ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, ConstPolygonRef polygon, int start_idx, int direction)
{ {
if (polygon.size() == 0) if (polygon.size() == 0)
{ {
@@ -572,8 +572,8 @@ ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, PolygonRef poly
{ {
int p1_idx = (polygon.size() + direction*p + start_idx) % polygon.size(); int p1_idx = (polygon.size() + direction*p + start_idx) % polygon.size();
int p2_idx = (polygon.size() + direction*(p+1) + start_idx) % polygon.size(); int p2_idx = (polygon.size() + direction*(p+1) + start_idx) % polygon.size();
Point& p1 = polygon[p1_idx]; const Point& p1 = polygon[p1_idx];
Point& p2 = polygon[p2_idx]; const Point& p2 = polygon[p2_idx];
Point closest_here = LinearAlg2D::getClosestOnLineSegment(from, p1 ,p2); Point closest_here = LinearAlg2D::getClosestOnLineSegment(from, p1 ,p2);
int64_t dist = vSize2(from - closest_here); int64_t dist = vSize2(from - closest_here);
@@ -600,7 +600,7 @@ ClosestPolygonPoint PolygonUtils::findClosest(Point from, const Polygons& polygo
{ {
return none; return none;
} }
PolygonRef any_polygon = polygons[0]; ConstPolygonRef any_polygon = polygons[0];
unsigned int any_poly_idx; unsigned int any_poly_idx;
for (any_poly_idx = 0; any_poly_idx < polygons.size(); any_poly_idx++) for (any_poly_idx = 0; any_poly_idx < polygons.size(); any_poly_idx++)
{ // find first point in all polygons { // find first point in all polygons
@@ -620,7 +620,7 @@ ClosestPolygonPoint PolygonUtils::findClosest(Point from, const Polygons& polygo
for (unsigned int ply = 0; ply < polygons.size(); ply++) for (unsigned int ply = 0; ply < polygons.size(); ply++)
{ {
const PolygonRef poly = polygons[ply]; ConstPolygonRef poly = polygons[ply];
if (poly.size() == 0) continue; if (poly.size() == 0) continue;
ClosestPolygonPoint closest_here = findClosest(from, poly, penalty_function); ClosestPolygonPoint closest_here = findClosest(from, poly, penalty_function);
if (!closest_here.isValid()) if (!closest_here.isValid())
@@ -639,7 +639,7 @@ ClosestPolygonPoint PolygonUtils::findClosest(Point from, const Polygons& polygo
return best; return best;
} }
ClosestPolygonPoint PolygonUtils::findClosest(Point from, const PolygonRef polygon, const std::function<int(Point)>& penalty_function) ClosestPolygonPoint PolygonUtils::findClosest(Point from, ConstPolygonRef polygon, const std::function<int(Point)>& penalty_function)
{ {
if (polygon.size() == 0) if (polygon.size() == 0)
{ {
@@ -653,11 +653,11 @@ ClosestPolygonPoint PolygonUtils::findClosest(Point from, const PolygonRef polyg
// //
for (unsigned int p = 0; p<polygon.size(); p++) for (unsigned int p = 0; p<polygon.size(); p++)
{ {
Point& p1 = polygon[p]; const Point& p1 = polygon[p];
unsigned int p2_idx = p+1; unsigned int p2_idx = p+1;
if (p2_idx >= polygon.size()) p2_idx = 0; if (p2_idx >= polygon.size()) p2_idx = 0;
Point& p2 = polygon[p2_idx]; const Point& p2 = polygon[p2_idx];
Point closest_here = LinearAlg2D::getClosestOnLineSegment(from, p1 ,p2); Point closest_here = LinearAlg2D::getClosestOnLineSegment(from, p1 ,p2);
int64_t dist2_score = vSize2(from - closest_here) + penalty_function(closest_here); int64_t dist2_score = vSize2(from - closest_here) + penalty_function(closest_here);
@@ -678,7 +678,7 @@ PolygonsPointIndex PolygonUtils::findNearestVert(const Point from, const Polygon
PolygonsPointIndex closest_vert; PolygonsPointIndex closest_vert;
for (unsigned int poly_idx = 0; poly_idx < polys.size(); poly_idx++) for (unsigned int poly_idx = 0; poly_idx < polys.size(); poly_idx++)
{ {
const PolygonRef poly = polys[poly_idx]; ConstPolygonRef poly = polys[poly_idx];
for (unsigned int point_idx = 0; point_idx < poly.size(); point_idx++) for (unsigned int point_idx = 0; point_idx < poly.size(); point_idx++)
{ {
int64_t dist2 = vSize2(poly[point_idx] - from); int64_t dist2 = vSize2(poly[point_idx] - from);
@@ -692,7 +692,7 @@ PolygonsPointIndex PolygonUtils::findNearestVert(const Point from, const Polygon
return closest_vert; return closest_vert;
} }
unsigned int PolygonUtils::findNearestVert(const Point from, const PolygonRef poly) unsigned int PolygonUtils::findNearestVert(const Point from, ConstPolygonRef poly)
{ {
int64_t best_dist2 = std::numeric_limits<int64_t>::max(); int64_t best_dist2 = std::numeric_limits<int64_t>::max();
unsigned int closest_vert_idx = -1; unsigned int closest_vert_idx = -1;
@@ -721,7 +721,7 @@ LocToLineGrid* PolygonUtils::createLocToLineGrid(const Polygons& polygons, int s
for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++) for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++)
{ {
const PolygonRef poly = polygons[poly_idx]; ConstPolygonRef poly = polygons[poly_idx];
for (unsigned int point_idx = 0; point_idx < poly.size(); point_idx++) for (unsigned int point_idx = 0; point_idx < poly.size(); point_idx++)
{ {
ret->insert(PolygonsPointIndex(&polygons, poly_idx, point_idx)); ret->insert(PolygonsPointIndex(&polygons, poly_idx, point_idx));
@@ -752,9 +752,9 @@ std::optional<ClosestPolygonPoint> PolygonUtils::findClose(
PolygonsPointIndex best_point_poly_idx(nullptr, NO_INDEX, NO_INDEX); PolygonsPointIndex best_point_poly_idx(nullptr, NO_INDEX, NO_INDEX);
for (PolygonsPointIndex& point_poly_index : near_lines) for (PolygonsPointIndex& point_poly_index : near_lines)
{ {
const PolygonRef poly = polygons[point_poly_index.poly_idx]; ConstPolygonRef poly = polygons[point_poly_index.poly_idx];
Point& p1 = poly[point_poly_index.point_idx]; const Point& p1 = poly[point_poly_index.point_idx];
Point& p2 = poly[(point_poly_index.point_idx + 1) % poly.size()]; const Point& p2 = poly[(point_poly_index.point_idx + 1) % poly.size()];
Point closest_here = LinearAlg2D::getClosestOnLineSegment(from, p1 ,p2); Point closest_here = LinearAlg2D::getClosestOnLineSegment(from, p1 ,p2);
int64_t dist2_score = vSize2(from - closest_here) + penalty_function(closest_here); int64_t dist2_score = vSize2(from - closest_here) + penalty_function(closest_here);
@@ -778,7 +778,7 @@ std::optional<ClosestPolygonPoint> PolygonUtils::findClose(
std::vector<std::pair<ClosestPolygonPoint, ClosestPolygonPoint>> PolygonUtils::findClose( std::vector<std::pair<ClosestPolygonPoint, ClosestPolygonPoint>> PolygonUtils::findClose(
const PolygonRef from, const Polygons& destination, ConstPolygonRef from, const Polygons& destination,
const LocToLineGrid& destination_loc_to_line, const LocToLineGrid& destination_loc_to_line,
const std::function<int(Point)>& penalty_function) const std::function<int(Point)>& penalty_function)
{ {
@@ -817,7 +817,7 @@ std::vector<std::pair<ClosestPolygonPoint, ClosestPolygonPoint>> PolygonUtils::f
bool PolygonUtils::getNextPointWithDistance(Point from, int64_t dist, const PolygonRef poly, int start_idx, int poly_start_idx, GivenDistPoint& result) bool PolygonUtils::getNextPointWithDistance(Point from, int64_t dist, ConstPolygonRef poly, int start_idx, int poly_start_idx, GivenDistPoint& result)
{ {
Point prev_poly_point = poly[(start_idx + poly_start_idx) % poly.size()]; Point prev_poly_point = poly[(start_idx + poly_start_idx) % poly.size()];
@@ -825,7 +825,7 @@ bool PolygonUtils::getNextPointWithDistance(Point from, int64_t dist, const Poly
for (unsigned int prev_idx = start_idx; prev_idx < poly.size(); prev_idx++) for (unsigned int prev_idx = start_idx; prev_idx < poly.size(); prev_idx++)
{ {
int next_idx = (prev_idx + 1 + poly_start_idx) % poly.size(); // last checked segment is between last point in poly and poly[0]... int next_idx = (prev_idx + 1 + poly_start_idx) % poly.size(); // last checked segment is between last point in poly and poly[0]...
Point& next_poly_point = poly[next_idx]; const Point& next_poly_point = poly[next_idx];
if ( !shorterThen(next_poly_point - from, dist) ) if ( !shorterThen(next_poly_point - from, dist) )
{ {
/* /*
@@ -932,7 +932,7 @@ bool PolygonUtils::polygonCollidesWithLineSegment(const Point from, const Point
return ret; return ret;
} }
bool PolygonUtils::polygonCollidesWithLineSegment(const PolygonRef poly, Point& transformed_startPoint, Point& transformed_endPoint, PointMatrix transformation_matrix) bool PolygonUtils::polygonCollidesWithLineSegment(ConstPolygonRef poly, const Point& transformed_startPoint, const Point& transformed_endPoint, PointMatrix transformation_matrix)
{ {
Point p0 = transformation_matrix.apply(poly.back()); Point p0 = transformation_matrix.apply(poly.back());
for(Point p1_ : poly) for(Point p1_ : poly)
@@ -947,7 +947,7 @@ bool PolygonUtils::polygonCollidesWithLineSegment(const PolygonRef poly, Point&
return false; return false;
} }
bool PolygonUtils::polygonCollidesWithLineSegment(const PolygonRef poly, Point& startPoint, Point& endPoint) bool PolygonUtils::polygonCollidesWithLineSegment(ConstPolygonRef poly, const Point& startPoint, const Point& endPoint)
{ {
Point diff = endPoint - startPoint; Point diff = endPoint - startPoint;
@@ -958,9 +958,9 @@ bool PolygonUtils::polygonCollidesWithLineSegment(const PolygonRef poly, Point&
return PolygonUtils::polygonCollidesWithLineSegment(poly, transformed_startPoint, transformed_endPoint, transformation_matrix); return PolygonUtils::polygonCollidesWithLineSegment(poly, transformed_startPoint, transformed_endPoint, transformation_matrix);
} }
bool PolygonUtils::polygonCollidesWithLineSegment(const Polygons& polys, Point& transformed_startPoint, Point& transformed_endPoint, PointMatrix transformation_matrix) bool PolygonUtils::polygonCollidesWithLineSegment(const Polygons& polys, const Point& transformed_startPoint, const Point& transformed_endPoint, PointMatrix transformation_matrix)
{ {
for (const PolygonRef poly : const_cast<Polygons&>(polys)) for (ConstPolygonRef poly : polys)
{ {
if (poly.size() == 0) { continue; } if (poly.size() == 0) { continue; }
if (PolygonUtils::polygonCollidesWithLineSegment(poly, transformed_startPoint, transformed_endPoint, transformation_matrix)) if (PolygonUtils::polygonCollidesWithLineSegment(poly, transformed_startPoint, transformed_endPoint, transformation_matrix))
@@ -973,7 +973,7 @@ bool PolygonUtils::polygonCollidesWithLineSegment(const Polygons& polys, Point&
} }
bool PolygonUtils::polygonCollidesWithLineSegment(const Polygons& polys, Point& startPoint, Point& endPoint) bool PolygonUtils::polygonCollidesWithLineSegment(const Polygons& polys, const Point& startPoint, const Point& endPoint)
{ {
Point diff = endPoint - startPoint; Point diff = endPoint - startPoint;
+18 -18
Ver Arquivo
@@ -20,12 +20,12 @@ namespace cura
struct ClosestPolygonPoint struct ClosestPolygonPoint
{ {
Point location; //!< Result location Point location; //!< Result location
std::optional<PolygonRef> poly; //!< Polygon in which the result was found (or none if no result was found) std::optional<ConstPolygonRef> poly; //!< Polygon in which the result was found (or none if no result was found)
unsigned int poly_idx; //!< The index of the polygon in some Polygons where ClosestPolygonPoint::poly can be found unsigned int poly_idx; //!< The index of the polygon in some Polygons where ClosestPolygonPoint::poly can be found
unsigned int point_idx; //!< Index to the first point in the polygon of the line segment on which the result was found unsigned int point_idx; //!< Index to the first point in the polygon of the line segment on which the result was found
ClosestPolygonPoint(Point p, int pos, PolygonRef poly) : location(p), poly(true, poly), poly_idx(NO_INDEX), point_idx(pos) {}; ClosestPolygonPoint(Point p, int pos, ConstPolygonRef poly) : location(p), poly(true, poly), poly_idx(NO_INDEX), point_idx(pos) {};
ClosestPolygonPoint(Point p, int pos, PolygonRef poly, int poly_idx) : location(p), poly(true, poly), poly_idx(poly_idx), point_idx(pos) {}; ClosestPolygonPoint(Point p, int pos, ConstPolygonRef poly, int poly_idx) : location(p), poly(true, poly), poly_idx(poly_idx), point_idx(pos) {};
ClosestPolygonPoint(PolygonRef poly) : poly(true, poly), poly_idx(NO_INDEX), point_idx(NO_INDEX) {}; ClosestPolygonPoint(ConstPolygonRef poly) : poly(true, poly), poly_idx(NO_INDEX), point_idx(NO_INDEX) {};
ClosestPolygonPoint() : poly_idx(NO_INDEX), point_idx(NO_INDEX) {}; ClosestPolygonPoint() : poly_idx(NO_INDEX), point_idx(NO_INDEX) {};
Point p() const Point p() const
{ // conformity with other classes { // conformity with other classes
@@ -53,7 +53,7 @@ struct PolygonsPointIndexSegmentLocator
{ {
std::pair<Point, Point> operator()(const PolygonsPointIndex& val) const std::pair<Point, Point> operator()(const PolygonsPointIndex& val) const
{ {
PolygonRef poly = (*val.polygons)[val.poly_idx]; ConstPolygonRef poly = (*val.polygons)[val.poly_idx];
Point start = poly[val.point_idx]; Point start = poly[val.point_idx];
unsigned int next_point_idx = (val.point_idx + 1) % poly.size(); unsigned int next_point_idx = (val.point_idx + 1) % poly.size();
Point end = poly[next_point_idx]; Point end = poly[next_point_idx];
@@ -104,7 +104,7 @@ public:
* \param poly The polygon. * \param poly The polygon.
* \param point_idx The index of the point in the polygon. * \param point_idx The index of the point in the polygon.
*/ */
static Point getVertexInwardNormal(PolygonRef poly, unsigned int point_idx); static Point getVertexInwardNormal(ConstPolygonRef poly, unsigned int point_idx);
/*! /*!
* Get a point from the \p poly with a given \p offset. * Get a point from the \p poly with a given \p offset.
@@ -114,7 +114,7 @@ public:
* \param offset The distance the point has to be moved outward from the polygon. * \param offset The distance the point has to be moved outward from the polygon.
* \return A point at the given distance inward from the point on the boundary polygon. * \return A point at the given distance inward from the point on the boundary polygon.
*/ */
static Point getBoundaryPointWithOffset(PolygonRef poly, unsigned int point_idx, int64_t offset); static Point getBoundaryPointWithOffset(ConstPolygonRef poly, unsigned int point_idx, int64_t offset);
/*! /*!
* Move a point away from the boundary by looking at the boundary normal of the nearest vert. * Move a point away from the boundary by looking at the boundary normal of the nearest vert.
@@ -178,7 +178,7 @@ public:
* \param penalty_function A function returning a penalty term on the squared distance score of a candidate point. * \param penalty_function A function returning a penalty term on the squared distance score of a candidate point.
* \return The point on the polygon closest to \p from * \return The point on the polygon closest to \p from
*/ */
static ClosestPolygonPoint moveInside2(const Polygons& loc_to_line_polygons, const PolygonRef polygon, Point& from, const int distance = 0, const int64_t max_dist2 = std::numeric_limits<int64_t>::max(), const LocToLineGrid* loc_to_line_grid = nullptr, const std::function<int(Point)>& penalty_function = no_penalty_function); static ClosestPolygonPoint moveInside2(const Polygons& loc_to_line_polygons, ConstPolygonRef polygon, Point& from, const int distance = 0, const int64_t max_dist2 = std::numeric_limits<int64_t>::max(), const LocToLineGrid* loc_to_line_grid = nullptr, const std::function<int(Point)>& penalty_function = no_penalty_function);
/*! /*!
* The opposite of moveInside. * The opposite of moveInside.
@@ -298,7 +298,7 @@ public:
* \param start_idx The index of the point in the polygon from which to start looking. * \param start_idx The index of the point in the polygon from which to start looking.
* \return The nearest point from \p start_idx going along the \p polygon (in both directions) with a locally minimal distance to \p from. * \return The nearest point from \p start_idx going along the \p polygon (in both directions) with a locally minimal distance to \p from.
*/ */
static ClosestPolygonPoint findNearestClosest(Point from, const PolygonRef polygon, int start_idx); static ClosestPolygonPoint findNearestClosest(Point from, ConstPolygonRef polygon, int start_idx);
/*! /*!
* Find the nearest closest point on a polygon from a given index walking in one direction along the polygon. * Find the nearest closest point on a polygon from a given index walking in one direction along the polygon.
@@ -309,7 +309,7 @@ public:
* \param direction The direction to walk: 1 for walking along the \p polygon, -1 for walking in opposite direction * \param direction The direction to walk: 1 for walking along the \p polygon, -1 for walking in opposite direction
* \return The nearest point from \p start_idx going along the \p polygon with a locally minimal distance to \p from. * \return The nearest point from \p start_idx going along the \p polygon with a locally minimal distance to \p from.
*/ */
static ClosestPolygonPoint findNearestClosest(const Point from, const PolygonRef polygon, int start_idx, int direction); static ClosestPolygonPoint findNearestClosest(const Point from, ConstPolygonRef polygon, int start_idx, int direction);
/*! /*!
* Find the point closest to \p from in all polygons in \p polygons. * Find the point closest to \p from in all polygons in \p polygons.
@@ -327,7 +327,7 @@ public:
* *
* \param penalty_function A function returning a penalty term on the squared distance score of a candidate point. * \param penalty_function A function returning a penalty term on the squared distance score of a candidate point.
*/ */
static ClosestPolygonPoint findClosest(Point from, const PolygonRef polygon, const std::function<int(Point)>& penalty_function = no_penalty_function); static ClosestPolygonPoint findClosest(Point from, ConstPolygonRef polygon, const std::function<int(Point)>& penalty_function = no_penalty_function);
/*! /*!
* Find the nearest vertex to \p from in \p polys * Find the nearest vertex to \p from in \p polys
@@ -343,7 +343,7 @@ public:
* \param poly The polygon in which to search * \param poly The polygon in which to search
* \return The index to the nearest vertex on the polygon * \return The index to the nearest vertex on the polygon
*/ */
static unsigned int findNearestVert(const Point from, const PolygonRef poly); static unsigned int findNearestVert(const Point from, ConstPolygonRef poly);
/*! /*!
* Create a SparsePointGridInclusive mapping from locations to line segments occurring in the \p polygons * Create a SparsePointGridInclusive mapping from locations to line segments occurring in the \p polygons
@@ -382,7 +382,7 @@ public:
* \param penalty_function A function returning a penalty term on the squared distance score of a candidate point. * \param penalty_function A function returning a penalty term on the squared distance score of a candidate point.
* \return A collection of near crossing from the \p from polygon to the \p destination polygon. Each element in the sollection is a pair with as first a cpp in the \p from polygon and as second a cpp in the \p destination polygon. * \return A collection of near crossing from the \p from polygon to the \p destination polygon. Each element in the sollection is a pair with as first a cpp in the \p from polygon and as second a cpp in the \p destination polygon.
*/ */
static std::vector<std::pair<ClosestPolygonPoint, ClosestPolygonPoint>> findClose(const PolygonRef from, const Polygons& destination, const LocToLineGrid& destination_loc_to_line, const std::function<int(Point)>& penalty_function = no_penalty_function); static std::vector<std::pair<ClosestPolygonPoint, ClosestPolygonPoint>> findClose(ConstPolygonRef from, const Polygons& destination, const LocToLineGrid& destination_loc_to_line, const std::function<int(Point)>& penalty_function = no_penalty_function);
/*! /*!
* Checks whether a given line segment collides with polygons as given in a loc_to_line grid. * Checks whether a given line segment collides with polygons as given in a loc_to_line grid.
@@ -409,7 +409,7 @@ public:
* \param start_idx the index of the prev poly point on the poly. * \param start_idx the index of the prev poly point on the poly.
* \param poly_start_idx The index of the point in the polygon which is to be handled as the start of the polygon. No point further than this point will be the result. * \param poly_start_idx The index of the point in the polygon which is to be handled as the start of the polygon. No point further than this point will be the result.
*/ */
static bool getNextPointWithDistance(Point from, int64_t dist, const PolygonRef poly, int start_idx, int poly_start_idx, GivenDistPoint& result); static bool getNextPointWithDistance(Point from, int64_t dist, ConstPolygonRef poly, int start_idx, int poly_start_idx, GivenDistPoint& result);
@@ -433,7 +433,7 @@ public:
* \return whether the line segment collides with the boundary of the * \return whether the line segment collides with the boundary of the
* polygon(s) * polygon(s)
*/ */
static bool polygonCollidesWithLineSegment(const PolygonRef poly, Point& transformed_startPoint, Point& transformed_endPoint, PointMatrix transformation_matrix); static bool polygonCollidesWithLineSegment(ConstPolygonRef poly, const Point& transformed_startPoint, const Point& transformed_endPoint, PointMatrix transformation_matrix);
/*! /*!
* Checks whether a given line segment collides with a given polygon(s). * Checks whether a given line segment collides with a given polygon(s).
@@ -449,7 +449,7 @@ public:
* \return whether the line segment collides with the boundary of the * \return whether the line segment collides with the boundary of the
* polygon(s) * polygon(s)
*/ */
static bool polygonCollidesWithLineSegment(const PolygonRef poly, Point& startPoint, Point& endPoint); static bool polygonCollidesWithLineSegment(ConstPolygonRef poly, const Point& startPoint, const Point& endPoint);
/*! /*!
* Checks whether a given line segment collides with a given polygon(s). * Checks whether a given line segment collides with a given polygon(s).
@@ -471,7 +471,7 @@ public:
* \return whether the line segment collides with the boundary of the * \return whether the line segment collides with the boundary of the
* polygon(s) * polygon(s)
*/ */
static bool polygonCollidesWithLineSegment(const Polygons& polys, Point& transformed_startPoint, Point& transformed_endPoint, PointMatrix transformation_matrix); static bool polygonCollidesWithLineSegment(const Polygons& polys, const Point& transformed_startPoint, const Point& transformed_endPoint, PointMatrix transformation_matrix);
/*! /*!
* Checks whether a given line segment collides with a given polygon(s). * Checks whether a given line segment collides with a given polygon(s).
@@ -487,7 +487,7 @@ public:
* \return whether the line segment collides with the boundary of the * \return whether the line segment collides with the boundary of the
* polygon(s) * polygon(s)
*/ */
static bool polygonCollidesWithLineSegment(const Polygons& polys, Point& startPoint, Point& endPoint); static bool polygonCollidesWithLineSegment(const Polygons& polys, const Point& startPoint, const Point& endPoint);
private: private:
/*! /*!
+1 -1
Ver Arquivo
@@ -18,7 +18,7 @@ WallOverlapComputation::WallOverlapComputation(Polygons& polygons, int line_widt
} }
float WallOverlapComputation::getFlow(Point& from, Point& to) float WallOverlapComputation::getFlow(const Point& from, const Point& to)
{ {
using Point2LinkIt = PolygonProximityLinker::Point2Link::iterator; using Point2LinkIt = PolygonProximityLinker::Point2Link::iterator;
+1 -1
Ver Arquivo
@@ -60,7 +60,7 @@ public:
* \param to The ending of the line segment * \param to The ending of the line segment
* \return a value between zero and one representing the reduced flow of the line segment * \return a value between zero and one representing the reduced flow of the line segment
*/ */
float getFlow(Point& from, Point& to); float getFlow(const Point& from, const Point& to);
/*! /*!
* Computes the neccesary priliminaries in order to efficiently compute the flow when generatign gcode paths. * Computes the neccesary priliminaries in order to efficiently compute the flow when generatign gcode paths.