Comparar commits

...

63 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
Tim Kuipers bdb788e3c4 don't generate towers when support_use_towers is disabled (CURA-3288) 2017-02-15 12:48:46 +01:00
Tim Kuipers 5b00c21a5f Merge branch 'feature_omp_settings' 2017-02-15 12:19:21 +01:00
Tim Kuipers b546f66bbe Merge branch 'feature_omp_skin_infill' 2017-02-15 12:16:37 +01:00
Tim Kuipers 2af8320cc9 Merge branch 'feature_omp_slicing' 2017-02-15 12:16:11 +01:00
Tim Kuipers 5fa5c89935 fix: const correctness of getSetting functions (CURA-3372) 2017-02-15 12:05:14 +01:00
Tim Kuipers 5c40f74c68 feat: small optimization in setting value retrieval (CURA-3372) 2017-02-15 12:03:11 +01:00
Tim Kuipers 60cebc86eb fix: error on unknown unset setting, rather than warn (CURA-3372)
this als oremoves a const_cast :)
2017-02-15 12:02:36 +01:00
Tim Kuipers 1bb4e03b36 fix: remove superfluous const_cast (CURA-3372) 2017-02-15 11:46:01 +01:00
Tim Kuipers 677857a186 fix: lil (CURA-3331) 2017-02-09 21:13:26 +01:00
Tim Kuipers 156674e452 fix: bs include (CURA-3331) 2017-02-09 17:44:23 +01:00
Tim Kuipers 903b31d381 Merge branch 'feature_omp_skin_infill' of github.com:Ultimaker/CuraEngine into feature_omp_skin_infill 2017-02-09 17:41:49 +01:00
Tim Kuipers 734978230f lil (CURA-3330) 2017-02-09 17:41:45 +01:00
Tim Kuipers fa02006a5d fix: logging of OpenMP threads in main (CURA-3330) 2017-02-09 15:30:45 +01:00
Ghostkeeper 6861020c6b Remove irrelevant documentation of different function
This documentation of processInsets reports on one of the generateInsets functions. Probably a copy-paste mistake.

Contributes to issue CURA-3330.
2017-02-08 16:43:13 +01:00
Ghostkeeper 2d9a3c83ef Code style: Space after for keyword
Contributes to issue CURA-3330.
2017-02-08 16:29:02 +01:00
Ghostkeeper ab7e035f6e Don't continue with compiling when function has error
This would give an exception which breaks the script and makes a very unclear chained error message.

Contributes to issue CURA-2572.
2017-02-03 17:05:28 +01:00
Ghostkeeper d0a149cf26 Fix error handling when setting has a parse error
The code was an integer. It needs to be converted to a string in order to be added to other strings.

Contributes to issue CURA-2572.
2017-02-03 17:05:28 +01:00
Tim Kuipers 4d35735aa8 Merge pull request #451 from smartavionics/mb-spiralize-bug
Fix spiralize args bug - untested but this just looked wrong to me.
2017-02-02 13:12:49 +01:00
Mark Burton 5e831f99e9 Fix spiralize args bug - untested but this just looked wrong to me. 2017-02-02 08:08:50 +00:00
Tim Kuipers 04766f663b Add OpenMP parallel execution createLayerParts (CURA-3331) 2017-02-01 13:26:51 +01:00
Tim Kuipers 42684e6368 feat: Add OpenMP parallel execution of slice make polygons (CURA-3331) 2017-01-31 11:41:34 +01:00
Ghostkeeper aa14682087 Remove 'l' formatting character and simplify+speed-up int2mm formatting
The 'l' formatting character in combination with 'd' was not allowed with MinGW on Windows. Simply formatting with 'd' is sufficient since our coordinates are allowed to be cast to integers at this stage: We won't need to square them any more or anything.

Contributes to issue CURA-3274.
2017-01-31 10:35:28 +01:00
Tim Kuipers 4c5a959c4e fix: handle multithreaded progress messages (CURA-781) 2017-01-30 17:41:33 +01:00
Johan Kristensen 21746022c4 Add OpenMP parallel execution of processInsets
CURA-541
2017-01-30 17:36:12 +01:00
Johan Kristensen d6bf9be54e Add OpenMP parallel execution of processSkinsAndInfill
CURA-541
2017-01-30 17:35:59 +01:00
Johan K fff1164042 Add cmake option to enable OpenMP
CURA-541
2017-01-30 17:30:44 +01:00
Ghostkeeper c7e621eeb5 Merge branch '2.4' 2017-01-25 17:46:07 +01:00
Ghostkeeper 9c3170b277 Print debug message upon sending layer data
This should help a bit with debugging the slice loop. I hope.

Contributes to issue CURA-3274.
2017-01-25 17:45:34 +01:00
Ghostkeeper e2f89778e2 Remove p1 after inserting point next to it
Because this insertion requires dereferencing p1. If it has been removed from the list, dereferencing it would remove it from memory so that would be an invalid pointer reference.

Contributes to debugging issue CURA-3274.
2017-01-25 14:40:11 +01:00
Ghostkeeper 8f74952aca Replace last long in gcodeExport with int64_t
Previously we had a crash only on windows because the long was not long enough. Perhaps this fixes something with the slicing loop.

Contributes to issue CURA-3274.
2017-01-25 13:36:14 +01:00
Ghostkeeper 5b6f1db59d Merge branch 'mb-min-infill-area' of https://github.com/smartavionics/CuraEngine into smartavionics-mb-min-infill-area 2017-01-24 11:40:03 +01:00
Tim Kuipers 17463e1139 quick fix: accidental const (CURA-3309) 2017-01-23 17:37:17 +01:00
Tim Kuipers 8df26ae916 fix: equalize flow still equalizes after halving the line width for perimeter gaps (CURA-3309) 2017-01-23 17:36:24 +01:00
Tim Kuipers 9ac9d1dd59 Merge branch '2.4' 2017-01-23 14:54:16 +01:00
Tim Kuipers c2aa1d59bc fix: add perimeter_gaps config with line width of half the inner wall line width (CURA-3309)
also the perimeter gaps of the skin walls now have to be generated separately
2017-01-23 14:53:57 +01:00
Tim Kuipers 3d476f114b Merge branch '2.4' 2017-01-23 10:22:54 +01:00
Tim Kuipers 152f6e89a8 fix: more safety against empty layers (CURA-3290) 2017-01-20 16:56:01 +01:00
Tim Kuipers 113202cd34 fix: types in CubicSubdiv were wrong (CURA-3196)
the sphere_slice_radius2 was a long rather than a coord_t (long long)
2017-01-20 15:23:34 +01:00
Tim Kuipers 4bc706d618 fix: perimeter gaps were introduced for the overlap between infill and skin (CURA-3179)
this caused extra overextrusion where infill and skin meet
2017-01-20 15:01:51 +01:00
Tim Kuipers 5766e2db11 fix: don't fill gaps for outer wall when spiralize is enabled (CURA-3152) 2017-01-20 14:21:14 +01:00
Tim Kuipers 671ebccdbb fix: indentation only (CURA-3271) 2017-01-20 14:08:56 +01:00
Tim Kuipers 2516165c86 fix: there were no support bottoms on top of the first model in support of the second model (CURA-3271)
All support areas are now generated before generating the interface. They are stored in supportLayer.supportAreas right after generation of the areas.
generateSupportInterface then operates on the merged supportAreas.

Note that this has a performace impact: while evaluating support interface, the support of all models is considered, rather than only the support it introduced itself.
2017-01-20 14:08:29 +01:00
Tim Kuipers 0315aaf404 fix: support top distance was one layer too high (CURA-3269) 2017-01-20 13:26:39 +01:00
Mark Burton b43e4df3aa Remove areas of infill smaller than min_infill_area.
When you have a small feature above an outer layer (e.g. raised text), the
area under the feature will be infill rather than skin and so the skin is
composed of multiple segments around the feature. Better surface quality is
obtained if the area under the raised feature is treated as skin thus allowing
more of the outer layer to be printed as a single segment. This setting
specifies the minimum area (in mm^2) of a filled region. Areas smaller than
this will be filled with skin rather than infill.
2017-01-19 11:44:22 +00:00
Ghostkeeper 405c49133b Merge branch 'first-layer-skin-pattern' of https://github.com/14bitVoid/CuraEngine into 14bitVoid-first-layer-skin-pattern 2017-01-03 10:42:31 +01:00
Tim Kuipers 49f09ed204 fix: (anti) support meshes could f*ck up the printZ of each layer (CURA-3198)
those meshes didn't call createLayerParts and so their printZ was never set.
To determine the print height of a layer an arbitrary mesh was used to see the printZ.
2017-01-02 23:03:40 +01:00
14bitVoid e717404055 Use different skin pattern on first layer 2017-01-02 22:30:41 +01:00
Ghostkeeper 3e7d623c86 Make total bounding box use head coordinates
Instead of nozzle coordinates.
2016-12-20 15:49:37 +01:00
Ghostkeeper d694bff227 Remove superfluous comment
A bit witty, perhaps, but unnecessary.

Contributes to issue CURA-3137.
2016-12-15 12:03:28 +01:00
61 arquivos alterados com 1410 adições e 1078 exclusões
+6
Ver Arquivo
@@ -7,8 +7,14 @@
NUL
*.gcode
## Directories used for other stuff
Trash/*
output/*
callgrind/*
## Building result.
build/*
debug_build/*
*.pyc
*.exe
*.a
+11
Ver Arquivo
@@ -42,6 +42,16 @@ if(NOT APPLE AND NOT WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++")
endif()
option (ENABLE_OPENMP
"Use OpenMP for parallel code" ON)
if (ENABLE_OPENMP)
FIND_PACKAGE( OpenMP )
if( OPENMP_FOUND )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}" )
endif()
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR} libs)
add_library(clipper STATIC libs/clipper/clipper.cpp)
@@ -96,6 +106,7 @@ set(engine_SRCS # Except main.cpp.
src/progress/Progress.cpp
src/progress/ProgressStageEstimator.cpp
src/settings/PathConfigStorage.cpp
src/settings/SettingConfig.cpp
src/settings/SettingContainer.cpp
src/settings/SettingRegistry.cpp
+207 -215
Ver Arquivo
@@ -25,11 +25,11 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep
// set the initial extruder of this meshgroup
if (FffProcessor::getInstance()->getMeshgroupNr() == 0)
{ // first meshgroup
current_extruder_planned = getStartExtruder(storage);
planner_state.current_extruder = getStartExtruder(storage);
}
else
{
current_extruder_planned = gcode.getExtruderNr();
planner_state.current_extruder = gcode.getExtruderNr();
}
if (CommandSocket::isInstantiated())
@@ -42,12 +42,9 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep
setConfigCoasting(storage);
setConfigRetraction(storage);
initConfigs(storage);
for (int extruder = 0; extruder < storage.meshgroup->getExtruderCount(); extruder++)
{ //Skirt and brim.
storage.skirt_brim_config[extruder].setLayerHeight(getSettingInMicrons("layer_height_0"));
skirt_brim_is_processed[extruder] = false;
}
@@ -71,17 +68,6 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep
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
int extruder_count = storage.meshgroup->getExtruderCount();
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);
@@ -172,39 +175,7 @@ void FffGcodeWriter::setConfigRetraction(SliceDataStorage& storage)
}
}
void FffGcodeWriter::initConfigs(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"));
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)
unsigned int FffGcodeWriter::getStartExtruder(const SliceDataStorage& storage)
{
int start_extruder_nr = getSettingAsIndex("adhesion_extruder_nr");
if (getSettingAsPlatformAdhesion("adhesion_type") == EPlatformAdhesion::NONE)
@@ -223,7 +194,7 @@ unsigned int FffGcodeWriter::getStartExtruder(SliceDataStorage& storage)
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())
{
@@ -286,12 +257,12 @@ void FffGcodeWriter::processStartingCode(SliceDataStorage& storage, const unsign
gcode.writeTemperatureCommand(start_extruder_nr, print_temp_here, wait);
gcode.writePrimeTrain(train.getSettingInMillimetersPerSecond("speed_travel"));
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);
}
}
void FffGcodeWriter::processNextMeshGroupCode(SliceDataStorage& storage)
void FffGcodeWriter::processNextMeshGroupCode(const SliceDataStorage& storage)
{
gcode.writeFanCommand(0);
@@ -303,11 +274,11 @@ void FffGcodeWriter::processNextMeshGroupCode(SliceDataStorage& storage)
gcode.setZ(max_object_height + 5000);
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);
gcode.writeMove(last_position_planned, storage.meshgroup->getExtruderTrain(gcode.getExtruderNr())->getSettingInMillimetersPerSecond("speed_travel"), 0);
planner_state.last_position = Point(storage.model_min.x, storage.model_min.y);
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");
ExtruderTrain* train = storage.meshgroup->getExtruderTrain(extruder_nr);
@@ -316,16 +287,7 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
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);
@@ -341,7 +303,7 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
int layer_height = train->getSettingInMicrons("raft_base_thickness");
z += layer_height;
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.setExtruder(extruder_nr);
@@ -351,26 +313,31 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
CommandSocket::getInstance()->sendOptimizedLayerInfo(layer_nr, z, layer_height);
}
Polygons wall = storage.raftOutline.offset(-storage.raft_base_config.getLineWidth() / 2);
gcode_layer.addPolygonsByOptimizer(wall, &storage.raft_base_config);
Polygons wall = storage.raftOutline.offset(-gcode_layer.configs_storage.raft_base_config.getLineWidth() / 2);
gcode_layer.addPolygonsByOptimizer(wall, &gcode_layer.configs_storage.raft_base_config);
Polygons raftLines;
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);
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())
{
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.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
@@ -378,7 +345,7 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
int layer_height = train->getSettingInMicrons("raft_interface_thickness");
z += layer_height;
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.setExtruder(extruder_nr); // reset to extruder number, because we might have primed in the last layer
@@ -391,16 +358,21 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
Polygons raftLines;
int offset_from_poly_outline = 0;
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);
gcode_layer.addLinesByOptimizer(raftLines, &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.addLinesByOptimizer(raftLines, &gcode_layer.configs_storage.raft_interface_config, SpaceFillType::Lines);
gcode_layer.processFanSpeedAndMinimalLayerTime();
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");
@@ -410,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
z += layer_height;
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);
if (CommandSocket::isInstantiated())
@@ -421,20 +393,25 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
Polygons raft_lines;
int offset_from_poly_outline = 0;
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);
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.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);
logDebug("GcodeWriter processing layer %i of %i\n", layer_nr, total_layers);
@@ -486,15 +463,14 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
}
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"));
}
int64_t comb_offset_from_outlines = max_inner_wall_width * 2;
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);
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);
if (include_helper_parts && layer_nr == 0)
{ // process the skirt or the brim of the starting extruder.
@@ -525,10 +501,10 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
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;
{ // 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"))
{
layer_start_position = Point(storage.getSettingInMicrons("layer_start_x"), storage.getSettingInMicrons("layer_start_y"));
@@ -536,12 +512,12 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
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++)
{
unsigned int mesh_idx = mesh_order[mesh_order_idx];
SliceMeshStorage& mesh = storage.meshes[mesh_idx];
for (SliceLayerPart& part : mesh.layers[layer_nr].parts)
const unsigned int mesh_idx = mesh_order[mesh_order_idx];
const SliceMeshStorage& mesh = storage.meshes[mesh_idx];
for (const SliceLayerPart& part : mesh.layers[layer_nr].parts)
{
Point middle = (part.boundaryBox.min + part.boundaryBox.max) / 2;
coord_t dist2 = vSize2(middle - layer_start_position);
const Point middle = (part.boundaryBox.min + part.boundaryBox.max) / 2;
const coord_t dist2 = vSize2(middle - layer_start_position);
if (dist2 < best_dist2)
{
best_dist2 = dist2;
@@ -555,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_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)
{
addMeshLayerToGCode_meshSurfaceMode(storage, mesh, gcode_layer, layer_nr);
addMeshLayerToGCode_meshSurfaceMode(storage, mesh, mesh_config, gcode_layer, layer_nr);
}
else
{
addMeshLayerToGCode(storage, mesh, gcode_layer, layer_nr);
addMeshLayerToGCode(storage, mesh, mesh_config, gcode_layer, layer_nr);
}
}
}
@@ -579,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
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();
return gcode_layer;
}
bool FffGcodeWriter::getExtrudersNeedPrimeDuringFirstLayer()
bool FffGcodeWriter::getExtrudersNeedPrimeDuringFirstLayer() const
{
switch(gcode.getFlavor())
{
@@ -598,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.
@@ -612,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])
{
return;
}
Polygons& skirt_brim = storage.skirt_brim[extruder_nr];
skirt_brim_is_processed[extruder_nr] = true;
const Polygons& skirt_brim = storage.skirt_brim[extruder_nr];
const_cast<bool&>(skirt_brim_is_processed[extruder_nr]) = true; // TODO: resolve const cast!
if (skirt_brim.size() == 0)
{
return;
}
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)
{
@@ -636,11 +611,11 @@ void FffGcodeWriter::processOozeShield(SliceDataStorage& storage, GCodePlanner&
}
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)
{
@@ -667,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");
std::vector<int> ret;
@@ -687,17 +662,17 @@ std::vector<int> FffGcodeWriter::calculateExtruderOrder(SliceDataStorage& storag
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;
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)
{
Mesh& mesh_data = storage.meshgroup->meshes[mesh_idx];
Point3 middle = (mesh_data.getAABB().min + mesh_data.getAABB().max) / 2;
const Mesh& mesh_data = storage.meshgroup->meshes[mesh_idx];
const Point3 middle = (mesh_data.getAABB().min + mesh_data.getAABB().max) / 2;
mesh_idx_order_optimizer.addItem(Point(middle.x, middle.y), mesh_idx);
}
}
@@ -712,7 +687,7 @@ std::vector<unsigned int> FffGcodeWriter::calculateMeshOrder(SliceDataStorage& s
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)
{
@@ -728,7 +703,7 @@ void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& stora
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;
@@ -739,17 +714,17 @@ void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& stora
EZSeamType z_seam_type = mesh->getSettingAsZSeamType("z_seam_type");
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;
for(PolygonRef polyline : layer->openPolyLines)
for(ConstPolygonRef polyline : layer->openPolyLines)
{
for(unsigned int point_idx = 1; point_idx<polyline.size(); point_idx++)
{
@@ -759,11 +734,11 @@ void FffGcodeWriter::addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, Slic
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)
{
@@ -777,7 +752,7 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshSto
return;
}
SliceLayer* layer = &mesh->layers[layer_nr];
const SliceLayer* layer = &mesh->layers[layer_nr];
if (layer->parts.size() == 0)
{
@@ -787,7 +762,7 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshSto
if (mesh->getSettingAsCount("wall_line_count") > 0)
{ // don't switch extruder if there's nothing to print
bool empty = true;
for (SliceLayerPart& part : layer->parts)
for (const SliceLayerPart& part : layer->parts)
{
if (part.insets.size() > 0)
{
@@ -805,7 +780,7 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshSto
EZSeamType z_seam_type = mesh->getSettingAsZSeamType("z_seam_type");
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"))
{
layer_start_position = Point(storage.getSettingInMicrons("layer_start_x"), storage.getSettingInMicrons("layer_start_y"));
@@ -819,16 +794,16 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshSto
for (int part_idx : part_order_optimizer.polyOrder)
{
SliceLayerPart& part = layer->parts[part_idx];
addMeshPartToGCode(storage, mesh, part, gcode_layer, layer_nr);
const SliceLayerPart& part = layer->parts[part_idx];
addMeshPartToGCode(storage, mesh, mesh_config, part, gcode_layer, layer_nr);
}
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 );
@@ -850,21 +825,23 @@ void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, SliceMeshStor
if (mesh->getSettingBoolean("infill_before_walls"))
{
processMultiLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
processSingleLayerInfill(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, mesh_config, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
}
EZSeamType z_seam_type = mesh->getSettingAsZSeamType("z_seam_type");
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"))
{
processMultiLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
processSingleLayerInfill(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, mesh_config, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
}
EFillMethod skin_pattern = mesh->getSettingAsFillMethod("top_bottom_pattern");
EFillMethod skin_pattern = (layer_nr == 0)?
mesh->getSettingAsFillMethod("top_bottom_pattern_0") :
mesh->getSettingAsFillMethod("top_bottom_pattern");
int skin_angle = 45;
if ((skin_pattern == EFillMethod::LINES || skin_pattern == EFillMethod::ZIG_ZAG) && layer_nr & 1)
{
@@ -874,7 +851,7 @@ void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, SliceMeshStor
skin_angle -= 45;
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.
if (!mesh->getSettingBoolean("magic_spiralize") || static_cast<int>(layer_nr) < mesh->getSettingAsCount("bottom_layers"))
@@ -888,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");
if (infill_line_distance > 0)
@@ -896,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)
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");
Polygons infill_polygons;
Polygons infill_lines;
@@ -913,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_comp.generate(infill_polygons, infill_lines, mesh);
}
gcode_layer.addPolygonsByOptimizer(infill_polygons, &mesh->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.addPolygonsByOptimizer(infill_polygons, &mesh_config.infill_config[combine_idx]);
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)
{
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.
Polygons infill_polygons;
@@ -969,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_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)
{
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
{
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_x = mesh->getSettingBoolean("travel_compensate_overlapping_walls_x_enabled");
@@ -997,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
WallOverlapComputation* wall_overlap_computation(nullptr);
int wall_0_wipe_dist(0);
gcode_layer.addPolygonsByOptimizer(part.insets[0], &mesh->insetX_config, wall_overlap_computation, EZSeamType::SHORTEST, z_seam_pos, mesh->getSettingInMicrons("wall_0_wipe_dist"), wall_0_wipe_dist);
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;
@@ -1013,26 +990,26 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, SliceMeshStorage*
if (!compensate_overlap_0)
{
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
{
Polygons& outer_wall = part.insets[0];
Polygons outer_wall = part.insets[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
{
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
{
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"));
gcode_layer.addPolygonsByOptimizer(outer_wall, &mesh->insetX_config, &wall_overlap_computation);
gcode_layer.addPolygonsByOptimizer(outer_wall, &mesh_config.insetX_config, &wall_overlap_computation);
}
}
}
@@ -1040,31 +1017,35 @@ 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");
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_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
bool fill_perimeter_gaps = mesh->getSettingAsFillPerimeterGapMode("fill_perimeter_gaps") != FillPerimeterGapMode::NOWHERE;
bool fill_perimeter_gaps = mesh->getSettingAsFillPerimeterGapMode("fill_perimeter_gaps") != FillPerimeterGapMode::NOWHERE
&& !mesh->getSettingBoolean("magic_spiralize");
Point z_seam_pos(0, 0); // not used
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++)
{
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.optimize();
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_lines;
EFillMethod pattern = mesh->getSettingAsFillMethod("top_bottom_pattern");
EFillMethod pattern = (layer_nr == 0)?
mesh->getSettingAsFillMethod("top_bottom_pattern_0") :
mesh->getSettingAsFillMethod("top_bottom_pattern");
int bridge = -1;
if (layer_nr > 0)
bridge = bridgeAngle(skin_part.outline, &mesh->layers[layer_nr-1]);
@@ -1076,30 +1057,30 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
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;
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)
{
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)
{
// add perimeter gaps between the outer skin inset and the innermost wall
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));
for (unsigned int inset_idx = 1; inset_idx < skin_part.insets.size(); inset_idx++)
{ // 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 inner = skin_part.insets[inset_idx].offset(mesh->insetX_config.getLineWidth() / 2);
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_config.insetX_config.getLineWidth() / 2);
perimeter_gaps.add(outer.difference(inner));
}
}
@@ -1116,63 +1097,70 @@ 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_comp.generate(skin_polygons, skin_lines);
if (fill_perimeter_gaps)
{ // handle perimeter_gaps of skin insets
int offset = 0;
Infill infill_comp(EFillMethod::LINES, perimeter_gaps, offset, skin_line_width, skin_line_width, skin_overlap, skin_angle, z, extra_infill_shift);
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)
{
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
{
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)
{ // handle perimeter_gaps of skin insets
Polygons gap_polygons; // will remain empty
Polygons gap_lines;
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_comp.generate(gap_polygons, gap_lines);
gcode_layer.addLinesByOptimizer(gap_lines, &mesh_config.perimeter_gap_config, SpaceFillType::Lines);
}
}
if (fill_perimeter_gaps)
{ // handle perimeter gaps of normal insets
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++)
{
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);
perimeter_gaps.add(outer.difference(inner));
}
{ // gap between inner wall and skin/infill
if (mesh->getSettingInMicrons("infill_line_distance") > 0 && !mesh->getSettingBoolean("infill_hollow"))
if (mesh->getSettingInMicrons("infill_line_distance") > 0
&& !mesh->getSettingBoolean("infill_hollow")
&& mesh->getSettingInMicrons("infill_overlap_mm") >= 0
)
{
const Polygons outer = part.insets.back().offset(-1 * line_width / 2 - perimeter_gaps_extra_offset);
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 = inner.unionPolygons();
perimeter_gaps.add(outer.difference(inner));
}
}
Polygons skin_polygons; // unused
Polygons skin_lines; // soon to be generated gap filler lines
Polygons gap_polygons; // unused
Polygons gap_lines; // soon to be generated gap filler lines
int offset = 0;
int extra_infill_shift = 0;
Infill infill_comp(EFillMethod::LINES, perimeter_gaps, offset, skin_line_width, skin_line_width, skin_overlap, skin_angle, z, extra_infill_shift);
infill_comp.generate(skin_polygons, skin_lines);
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);
gcode_layer.addLinesByOptimizer(skin_lines, &mesh->skin_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;
if (!storage.support.generated || layer_nr > storage.support.layer_nr_max_filled_layer)
@@ -1183,7 +1171,7 @@ bool FffGcodeWriter::addSupportToGCode(SliceDataStorage& storage, GCodePlanner&
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");
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)
{
return support_added;
@@ -1201,12 +1189,14 @@ bool FffGcodeWriter::addSupportToGCode(SliceDataStorage& storage, GCodePlanner&
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;
if (!storage.support.generated
|| layer_nr > storage.support.layer_nr_max_filled_layer
|| storage.support.supportLayers[layer_nr].supportAreas.size() == 0)
|| support_layer.supportAreas.size() == 0)
{
return added;
}
@@ -1215,14 +1205,14 @@ bool FffGcodeWriter::addSupportInfillToGCode(SliceDataStorage& storage, GCodePla
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
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
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");
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();
@@ -1246,7 +1236,7 @@ bool FffGcodeWriter::addSupportInfillToGCode(SliceDataStorage& storage, GCodePla
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
gcode_layer.addPolygonsByOptimizer(boundary, &storage.support_config);
gcode_layer.addPolygonsByOptimizer(boundary, &gcode_layer.configs_storage.support_infill_config);
}
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
@@ -1263,20 +1253,22 @@ bool FffGcodeWriter::addSupportInfillToGCode(SliceDataStorage& storage, GCodePla
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
gcode_layer.addPolygonsByOptimizer(support_polygons, &storage.support_config);
gcode_layer.addLinesByOptimizer(support_lines, &storage.support_config, (support_pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
gcode_layer.addPolygonsByOptimizer(support_polygons, &gcode_layer.configs_storage.support_infill_config);
gcode_layer.addLinesByOptimizer(support_lines, &gcode_layer.configs_storage.support_infill_config, (support_pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
added = true;
}
}
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;
if (!storage.support.generated
|| 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;
}
@@ -1291,7 +1283,7 @@ bool FffGcodeWriter::addSupportRoofsToGCode(SliceDataStorage& storage, GCodePlan
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"))
{
@@ -1320,7 +1312,7 @@ bool FffGcodeWriter::addSupportRoofsToGCode(SliceDataStorage& storage, GCodePlan
Polygons* perimeter_gaps = nullptr;
bool use_endpieces = true;
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_lines;
infill_comp.generate(support_polygons, support_lines);
@@ -1328,14 +1320,14 @@ bool FffGcodeWriter::addSupportRoofsToGCode(SliceDataStorage& storage, GCodePlan
if (support_lines.size() > 0 || support_polygons.size() > 0)
{
setExtruder_addPrime(storage, gcode_layer, layer_nr, skin_extruder_nr);
gcode_layer.addPolygonsByOptimizer(support_polygons, &storage.support_skin_config);
gcode_layer.addLinesByOptimizer(support_lines, &storage.support_skin_config, (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
gcode_layer.addPolygonsByOptimizer(support_polygons, &gcode_layer.configs_storage.support_interface_config);
gcode_layer.addLinesByOptimizer(support_lines, &gcode_layer.configs_storage.support_interface_config, (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
added = true;
}
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
return;
@@ -1346,7 +1338,7 @@ void FffGcodeWriter::setExtruder_addPrime(SliceDataStorage& storage, GCodePlanne
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);
@@ -1357,7 +1349,7 @@ void FffGcodeWriter::setExtruder_addPrime(SliceDataStorage& storage, GCodePlanne
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!");
@@ -1372,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"))
{
+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.
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
bool is_inside_mesh_layer_part; //!< Whether the last position was inside a layer part (used in combing)
GCodePlanner::PlanningState planner_state;
public:
FffGcodeWriter(SettingsBase* settings_)
: SettingsMessenger(settings_)
, max_object_height(0)
, layer_plan_buffer(this, gcode)
, extruder_prime_is_planned {} // initialize all values in array with [false]
, last_position_planned(no_point)
, current_extruder_planned(0) // changed somewhere early in FffGcodeWriter::writeGCode
, is_inside_mesh_layer_part(false)
, planner_state{ no_point
, 0 // changed somewhere early in FffGcodeWriter::writeGCode
, false
}
{
}
@@ -172,17 +173,6 @@ private:
* \param[out] storage The data storage to which to save the configurations
*/
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.
@@ -192,7 +182,7 @@ private:
*
* \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.
@@ -202,14 +192,14 @@ private:
* \param[in] storage where the slice data is stored.
* \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.
*
* \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
@@ -217,7 +207,7 @@ private:
* \param[in,out] storage where the slice data is stored.
* \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
@@ -228,15 +218,16 @@ private:
* \param[in] storage where the slice data is stored.
* \param layer_nr The index of the layer to write the gcode of.
* \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.
*
* \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
@@ -244,7 +235,7 @@ private:
* \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.
*/
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.
@@ -254,7 +245,7 @@ private:
* \param extruder_nr The extruder train for which to process the skirt or
* 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.
@@ -263,7 +254,7 @@ private:
* \param gcodeLayer The initial planning of the gcode of the layer.
* \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.
@@ -272,7 +263,7 @@ private:
* \param gcodeLayer The initial planning of the gcode of the layer.
* \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
@@ -281,7 +272,7 @@ private:
* \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.
*/
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
@@ -290,88 +281,95 @@ private:
* \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.
*/
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.
*
* \param[in] storage where the slice data is stored.
* \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 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.
*
* \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_config the line config with which to print a print feature
* \param gcodeLayer The initial planning of the gcode of the layer.
* \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.
*
* \param[in] storage where the slice data is stored.
* \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 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.
*
* \param[in] storage where the slice data is stored.
* \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 gcode_layer The initial planning of the gcode of the layer.
* \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.
*
* \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_config the line config with which to print a print feature
* \param part The part for which to create gcode
* \param layer_nr The current layer number.
* \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 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.
* \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_config the line config with which to print a print feature
* \param part The part for which to create gcode
* \param layer_nr The current layer number.
* \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 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.
* \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_config the line config with which to print a print feature
* \param part The part for which to create gcode
* \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_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 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 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 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.
@@ -396,7 +395,7 @@ private:
* \param layer_nr The index of the layer to write the gcode of.
* \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.
* \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.
* \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.
* \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.
* \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.
@@ -424,7 +423,7 @@ private:
* \param layer_nr The index of the layer to write the gcode of.
* \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.
@@ -433,7 +432,7 @@ private:
* \param layer_nr The index of the layer to write the gcode of.
* \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.
+74 -12
Ver Arquivo
@@ -2,6 +2,7 @@
#include <algorithm>
#include <map> // multimap (ordered map allowing duplicate keys)
#include <omp.h>
#include "utils/math.h"
#include "utils/algorithm.h"
@@ -151,6 +152,10 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
SupportLayer& support_layer = storage.support.supportLayers[layer_nr];
SlicerLayer& slicer_layer = slicer->layers[layer_nr];
support_layer.anti_overhang = support_layer.anti_overhang.unionPolygons(slicer_layer.polygons);
meshStorage.layers[layer_nr].printZ =
slicer_layer.z
+ getSettingInMicrons("layer_height_0")
- initial_slice_z;
}
continue;
}
@@ -161,6 +166,10 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
SupportLayer& support_layer = storage.support.supportLayers[layer_nr];
SlicerLayer& slicer_layer = slicer->layers[layer_nr];
support_layer.support_mesh.add(slicer_layer.polygons);
meshStorage.layers[layer_nr].printZ =
slicer_layer.z
+ getSettingInMicrons("layer_height_0")
- initial_slice_z;
}
continue;
}
@@ -337,12 +346,24 @@ void FffPolygonGenerator::processBasicWallsSkinInfill(SliceDataStorage& storage,
// walls
unsigned int processed_layer_count = 0;
#pragma omp parallel for default(none) shared(mesh_layer_count, mesh, inset_skin_progress_estimate, processed_layer_count) schedule(dynamic)
for (unsigned int layer_number = 0; layer_number < mesh.layers.size(); layer_number++)
{
logDebug("Processing insets for layer %i of %i\n", layer_number, mesh_layer_count);
processInsets(mesh, layer_number);
double progress = inset_skin_progress_estimate.progress(layer_number);
Progress::messageProgress(Progress::Stage::INSET_SKIN, progress * 100, 100);
#ifdef _OPENMP
if (omp_get_thread_num() == 0)
#endif
{ // progress estimation is done only in one thread so that no two threads message progress at the same time
int _processed_layer_count;
#pragma omp atomic read
_processed_layer_count = processed_layer_count;
double progress = inset_skin_progress_estimate.progress(_processed_layer_count);
Progress::messageProgress(Progress::Stage::INSET_SKIN, progress * 100, 100);
}
#pragma omp atomic
processed_layer_count++;
}
ProgressEstimatorLinear* skin_estimator = new ProgressEstimatorLinear(mesh_layer_count);
@@ -373,16 +394,33 @@ void FffPolygonGenerator::processBasicWallsSkinInfill(SliceDataStorage& storage,
{
mesh_max_bottom_layer_count = std::max(mesh_max_bottom_layer_count, mesh.getSettingAsCount("bottom_layers"));
}
for (unsigned int layer_number = 0; layer_number < mesh.layers.size(); layer_number++)
processed_layer_count = 0;
#pragma omp parallel default(none) shared(mesh_layer_count, mesh, mesh_max_bottom_layer_count, process_infill, inset_skin_progress_estimate, processed_layer_count)
{
logDebug("Processing skins and infill layer %i of %i\n", layer_number, mesh_layer_count);
if (!mesh.getSettingBoolean("magic_spiralize") || static_cast<int>(layer_number) < mesh_max_bottom_layer_count) //Only generate up/downskin and infill for the first X layers when spiralize is choosen.
#pragma omp for schedule(dynamic)
for (unsigned int layer_number = 0; layer_number < mesh.layers.size(); layer_number++)
{
processSkinsAndInfill(mesh, layer_number, process_infill);
logDebug("Processing skins and infill layer %i of %i\n", layer_number, mesh_layer_count);
if (!mesh.getSettingBoolean("magic_spiralize") || static_cast<int>(layer_number) < mesh_max_bottom_layer_count) //Only generate up/downskin and infill for the first X layers when spiralize is choosen.
{
processSkinsAndInfill(mesh, layer_number, process_infill);
}
#ifdef _OPENMP
if (omp_get_thread_num() == 0)
#endif
{ // progress estimation is done only in one thread so that no two threads message progress at the same time
int _processed_layer_count;
#pragma omp atomic read
_processed_layer_count = processed_layer_count;
double progress = inset_skin_progress_estimate.progress(_processed_layer_count);
Progress::messageProgress(Progress::Stage::INSET_SKIN, progress * 100, 100);
}
#pragma omp atomic
processed_layer_count++;
}
}
double progress = inset_skin_progress_estimate.progress(layer_number);
Progress::messageProgress(Progress::Stage::INSET_SKIN, progress * 100, 100);
}
}
void FffPolygonGenerator::processInfillMesh(SliceDataStorage& storage, unsigned int mesh_order_idx, std::vector<unsigned int>& mesh_order)
@@ -478,6 +516,12 @@ void FffPolygonGenerator::processDerivedWallsSkinInfill(SliceMeshStorage& mesh)
}
}
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* processInsets only reads and writes data for the current layer
*/
void FffPolygonGenerator::processInsets(SliceMeshStorage& mesh, unsigned int layer_nr)
{
SliceLayer* layer = &mesh.layers[layer_nr];
@@ -516,11 +560,19 @@ void FffPolygonGenerator::removeEmptyFirstLayers(SliceDataStorage& storage, cons
for (SliceMeshStorage& mesh : storage.meshes)
{
SliceLayer& layer = mesh.layers[layer_idx];
if (layer.parts.size() > 0 || (mesh.getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL && layer.openPolyLines.size() > 0) )
if (mesh.getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL && layer.openPolyLines.size() > 0)
{
layer_is_empty = false;
break;
}
for (const SliceLayerPart& part : layer.parts)
{
if (part.print_outline.size() > 0)
{
layer_is_empty = false;
break;
}
}
}
if (layer_is_empty)
@@ -551,8 +603,18 @@ void FffPolygonGenerator::removeEmptyFirstLayers(SliceDataStorage& storage, cons
support_layers.erase(support_layers.begin(), support_layers.begin() + n_empty_first_layers);
}
}
void FffPolygonGenerator::processSkinsAndInfill(SliceMeshStorage& mesh, unsigned int layer_nr, bool process_infill)
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* generateSkins read (depend on) data from mesh.layers[*].parts[*].insets and write mesh.layers[n].parts[*].skin_parts
* generateInfill read mesh.layers[n].parts[*].{insets,skin_parts,boundingBox} and write mesh.layers[n].parts[*].infill_area
*
* processSkinsAndInfill read (depend on) mesh.layers[*].parts[*].{insets,boundingBox}.
* write mesh.layers[n].parts[*].{skin_parts,infill_area}.
*/
void FffPolygonGenerator::processSkinsAndInfill(SliceMeshStorage& mesh, unsigned int layer_nr, bool process_infill)
{
if (mesh.getSettingAsSurfaceMode("magic_mesh_surface_mode") == ESurfaceMode::SURFACE)
{
+33 -64
Ver Arquivo
@@ -6,105 +6,74 @@
namespace cura
{
GCodePathConfig::BasicConfig::BasicConfig()
: speed(0)
, acceleration(0)
, jerk(0)
, line_width(0)
, flow(100)
GCodePathConfig::GCodePathConfig(const GCodePathConfig& other)
: type(other.type)
, speed_derivatives(other.speed_derivatives)
, line_width(other.line_width)
, layer_thickness(other.layer_thickness)
, 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)
, acceleration(acceleration)
, jerk(jerk)
GCodePathConfig::GCodePathConfig(PrintFeatureType type, int line_width, int layer_height, double flow, GCodePathConfig::SpeedDerivatives speed_derivatives)
: type(type)
, speed_derivatives(speed_derivatives)
, line_width(line_width)
, layer_thickness(layer_height)
, 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;
this->acceleration = acceleration;
this->jerk = jerk;
this->line_width = line_width;
this->flow = flow;
double max_speed_layer = max_speed_layer_nr;
speed_derivatives.speed = (speed_derivatives.speed * layer_nr) / max_speed_layer + (first_layer_config.speed * (max_speed_layer - layer_nr) / max_speed_layer);
speed_derivatives.acceleration = (speed_derivatives.acceleration * layer_nr) / max_speed_layer + (first_layer_config.acceleration * (max_speed_layer - layer_nr) / max_speed_layer);
speed_derivatives.jerk = (speed_derivatives.jerk * layer_nr) / max_speed_layer + (first_layer_config.jerk * (max_speed_layer - layer_nr) / max_speed_layer);
}
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()
double GCodePathConfig::getExtrusionMM3perMM() const
{
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;
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 acceleration; //!< acceleration of head movement (mm/s^2)
double jerk; //!< jerk of the head movement (around stand still) (mm/s^3)
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
double jerk; //!< jerk of the head movement (around stand still) as instantaneous speed change (mm/s)
};
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
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);
/*!
* 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);
GCodePathConfig(const GCodePathConfig& other);
/*!
* 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 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 layer_nr The layer number
* \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);
/*!
* 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();
void smoothSpeed(SpeedDerivatives first_layer_config, int layer_nr, int max_speed_layer);
/*!
* 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
*/
double getSpeed();
double getSpeed() const;
/*!
* Get the current acceleration of this config
*/
double getAcceleration();
double getAcceleration() const;
/*!
* 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:
void calculateExtrusion();
double calculateExtrusion() const;
};
+5 -5
Ver Arquivo
@@ -17,7 +17,7 @@ void LayerPlanBuffer::flush()
}
while (!buffer.empty())
{
buffer.front().writeGCode(gcode);
buffer.front()->writeGCode(gcode);
if (CommandSocket::isInstantiated())
{
CommandSocket::getInstance()->flushGcode();
@@ -324,7 +324,7 @@ void LayerPlanBuffer::insertFinalPrintTempCommand(std::vector<ExtruderPlan*>& ex
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
buffer.pop_back();
return;
@@ -332,9 +332,9 @@ void LayerPlanBuffer::insertTempCommands()
std::vector<ExtruderPlan*> extruder_plans;
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);
}
@@ -342,7 +342,7 @@ void LayerPlanBuffer::insertTempCommands()
// 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++)
{
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
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)
: SettingsMessenger(settings)
@@ -54,29 +54,39 @@ public:
{
preheat_config.setConfig(settings);
}
/*!
* Place a new layer plan (GcodePlanner) by constructing it with the given arguments.
* Pop back the oldest layer plan is it exceeds the buffer size and write it to gcode.
* Push a new layer plan into the buffer
*/
template<typename... Args>
GCodePlanner& emplace_back(Args&&... constructor_args)
void push(GCodePlanner& layer_plan)
{
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)
{
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)
{
buffer.front().writeGCode(gcode);
GCodePlanner* ret = buffer.front();
if (CommandSocket::isInstantiated())
{
CommandSocket::getInstance()->flushGcode();
}
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
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
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
@@ -64,9 +64,18 @@ public:
/*!
* 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)
: 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) { }
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)
{
}
/*!
* 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.
+14 -52
Ver Arquivo
@@ -15,12 +15,7 @@ namespace cura
PrimeTower::PrimeTower(const SliceDataStorage& storage)
: is_hollow(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")
&& storage.getSettingInMicrons("prime_tower_wall_thickness") > 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)
{
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)
{
return;
}
bool prime_tower_added = false;
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)
if (gcodeLayer.getPrimeTowerIsPlanned())
{ // don't print the prime tower if it has been printed already
return;
}
@@ -159,7 +121,7 @@ void PrimeTower::addToGcode(const SliceDataStorage& storage, GCodePlanner& gcode
// pre-wipe:
if (pre_wipe)
{
preWipe(storage, gcodeLayer, new_extruder);
preWipe(storage, 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.
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);
gcodeLayer.addLinesByOptimizer(pattern.lines, &config, SpaceFillType::Lines);
last_prime_tower_poly_printed[extruder] = layer_nr;
gcode_layer.addPolygonsByOptimizer(pattern.polygons, &config);
gcode_layer.addLinesByOptimizer(pattern.lines, &config, SpaceFillType::Lines);
}
Point PrimeTower::getLocationBeforePrimeTower(const SliceDataStorage& storage)
Point PrimeTower::getLocationBeforePrimeTower(const SliceDataStorage& storage) const
{
Point ret(0, 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);
}
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];
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);
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);
}
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)
+5 -27
Ver Arquivo
@@ -34,7 +34,6 @@ private:
Polygons lines;
};
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
@@ -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 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
int current_pre_wipe_location_idx; //!< Index into \ref PrimeTower::wipe_locations of where to pre-wipe the nozzle
public:
bool enabled; //!< Whether the prime tower is enabled.
@@ -63,21 +61,6 @@ public:
*/
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
*
@@ -104,7 +87,7 @@ public:
* \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.
*/
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.
@@ -115,12 +98,6 @@ public:
void subtractFromSupport(SliceDataStorage& storage);
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
@@ -130,7 +107,7 @@ private:
* \param storage where to get settings from
* \return that location
*/
Point getLocationBeforePrimeTower(const SliceDataStorage& storage);
Point getLocationBeforePrimeTower(const SliceDataStorage& storage) const;
/*!
* \param storage where to get settings from
@@ -159,16 +136,17 @@ private:
* \param extruder The extruder we just switched to, with which the prime
* 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.
*
* \param storage where to get settings from
* \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
*/
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;
};
+4
Ver Arquivo
@@ -58,6 +58,10 @@ void SkirtBrim::getFirstLayerOutline(SliceDataStorage& storage, const unsigned i
constexpr int smallest_line_length = 200;
constexpr int largest_error_of_removed_point = 50;
first_layer_outline.simplify(smallest_line_length, largest_error_of_removed_point); // simplify for faster processing of the brim lines
if (first_layer_outline.size() == 0)
{
logError("Couldn't generate skirt / brim! No polygons on first layer.");
}
}
int SkirtBrim::generatePrimarySkirtBrimLines(SliceDataStorage& storage, int start_distance, unsigned int primary_line_count, const int primary_extruder_skirt_brim_line_width, const int64_t primary_extruder_minimal_length, const Polygons& first_layer_outline, Polygons& skirt_brim_primary_extruder)
+12
Ver Arquivo
@@ -12,6 +12,12 @@ WallsComputation::WallsComputation(int wall_0_inset, int line_width_0, int line_
{
}
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* generateInsets only reads and writes data for the current layer
*/
void WallsComputation::generateInsets(SliceLayerPart* part)
{
if (insetCount == 0)
@@ -58,6 +64,12 @@ void WallsComputation::generateInsets(SliceLayerPart* part)
}
}
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* generateInsets only reads and writes data for the current layer
*/
void WallsComputation::generateInsets(SliceLayer* layer)
{
for(unsigned int partNr = 0; partNr < layer->parts.size(); partNr++)
+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++)
{
const PolygonRef upperPart = parts1[prt];
ConstPolygonRef upperPart = parts1[prt];
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++)
{
const PolygonRef upperPart = supported[prt];
ConstPolygonRef upperPart(supported[prt]);
parts.emplace_back(prt);
+1 -1
Ver Arquivo
@@ -5,7 +5,7 @@
namespace cura {
int bridgeAngle(Polygons outline, SliceLayer* prevLayer)
int bridgeAngle(Polygons outline, const SliceLayer* prevLayer)
{
AABB boundaryBox(outline);
//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 SliceLayer;
int bridgeAngle(Polygons outline, SliceLayer* prevLayer);
int bridgeAngle(Polygons outline, const SliceLayer* prevLayer);
}//namespace cura
+5 -3
Ver Arquivo
@@ -215,7 +215,7 @@ public:
/*!
* 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:
/*!
* 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
}
void CommandSocket::sendPolygon(PrintFeatureType type, Polygon& polygon, int line_width)
void CommandSocket::sendPolygon(PrintFeatureType type, ConstPolygonRef polygon, int line_width)
{
#ifdef ARCUS
if (CommandSocket::isInstantiated())
@@ -642,6 +642,7 @@ void CommandSocket::sendLayerData()
{
for (std::pair<const int, std::shared_ptr<cura::proto::Layer>> entry : data.slice_data) //Note: This is in no particular order!
{
logDebug("Sending layer data for layer %i of %i.\n", entry.first, data.slice_data.size());
private_data->socket->sendMessage(entry.second); //Send the actual layers.
}
data.sliced_objects = 0;
@@ -667,6 +668,7 @@ void CommandSocket::sendOptimizedLayerData()
{
for (std::pair<const int, std::shared_ptr<cura::proto::LayerOptimized>> entry : data.slice_data) //Note: This is in no particular order!
{
logDebug("Sending layer data for layer %i of %i.\n", entry.first, data.slice_data.size());
private_data->socket->sendMessage(entry.second); //Send the actual layers.
}
data.sliced_objects = 0;
@@ -797,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)
{
+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
*/
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
+5 -6
Ver Arquivo
@@ -270,7 +270,7 @@ void GCodeExport::setFlavor(EGCodeFlavor flavor)
}
}
EGCodeFlavor GCodeExport::getFlavor()
EGCodeFlavor GCodeExport::getFlavor() const
{
return this->flavor;
}
@@ -556,8 +556,6 @@ void GCodeExport::writeMove(int x, int y, int z, double speed, double extrusion_
assert((Point3(x,y,z) - currentPosition).vSize() < MM2INT(300)); // no crazy positions (this code should not be compiled for release)
#endif //ASSERT_INSANE_OUTPUT
total_bounding_box.include(Point3(x, y, z));
if (extrusion_mm3_per_mm < 0)
logWarning("Warning! Negative extrusion move!");
@@ -570,6 +568,7 @@ void GCodeExport::writeMove(int x, int y, int z, double speed, double extrusion_
double extrusion_per_mm = mm3ToE(extrusion_mm3_per_mm);
Point gcode_pos = getGcodePos(x,y, current_extruder);
total_bounding_box.include(Point3(gcode_pos.X, gcode_pos.Y, z));
if (extrusion_mm3_per_mm > 0.000001)
{
@@ -729,7 +728,7 @@ void GCodeExport::writeZhopStart(int hop_height)
{
isZHopped = hop_height;
*output_stream << "G1 Z" << MMtoStream{currentPosition.z + isZHopped} << new_line;
total_bounding_box.include(currentPosition + Point3(0, 0, isZHopped));
total_bounding_box.includeZ(currentPosition.z + isZHopped);
}
}
@@ -776,7 +775,7 @@ void GCodeExport::switchExtruder(int new_extruder, const RetractionConfig& retra
bool force = 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
@@ -923,7 +922,7 @@ void GCodeExport::finalize(const char* endCode)
{
writeFanCommand(0);
writeCode(endCode);
long print_time = getTotalPrintTime();
int64_t print_time = getTotalPrintTime();
int mat_0 = getTotalFilamentUsed(0);
log("Print time: %d\n", print_time);
log("Print time (readable): %dh %dm %ds\n", print_time / 60 / 60, (print_time / 60) % 60, print_time % 60);
+1 -1
Ver Arquivo
@@ -188,7 +188,7 @@ public:
Point getGcodePos(const int64_t x, const int64_t y, const int extruder_train) const;
void setFlavor(EGCodeFlavor flavor);
EGCodeFlavor getFlavor();
EGCodeFlavor getFlavor() const;
void setZ(int z);
+34 -133
Ver Arquivo
@@ -10,7 +10,7 @@
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)
, heated_pre_travel_time(0)
, 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;
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;
}
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)
, configs_storage(storage, layer_nr, layer_thickness)
, layer_nr(layer_nr)
, is_initial_layer(layer_nr == 0 - Raft::getTotalExtraLayers(storage))
, z(z)
, layer_thickness(layer_thickness)
, start_position(last_position)
, lastPosition(last_position)
, last_extruder_previous_layer(current_extruder)
, last_planned_extruder_setting_base(storage.meshgroup->getExtruderTrain(current_extruder))
, start_position(last_planned_state.last_position)
, lastPosition(last_planned_state.last_position)
, has_prime_tower_planned(false)
, 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))
, 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.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;
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)
if (combing_mode != CombingMode::OFF)
{
@@ -139,12 +142,12 @@ Polygons GCodePlanner::computeCombBoundaryInside(CombingMode combing_mode)
else
{
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)
{
for (SliceLayerPart& part : layer.parts)
for (const SliceLayerPart& part : layer.parts)
{
comb_boundary.add(part.infill_area);
}
@@ -241,12 +244,12 @@ void GCodePlanner::moveInsideCombBoundary(int distance)
GCodePath& GCodePlanner::addTravel(Point p)
{
GCodePath* path = nullptr;
GCodePathConfig& travel_config = storage.travel_config_per_extruder[getExtruder()];
RetractionConfig& retraction_config = storage.retraction_config_per_extruder[getExtruder()];
const GCodePathConfig& travel_config = configs_storage.travel_config_per_extruder[getExtruder()];
const RetractionConfig& retraction_config = storage.retraction_config_per_extruder[getExtruder()];
bool combed = false;
SettingsBaseVirtual* extr = getLastPlannedExtruderTrainSettings();
const SettingsBaseVirtual* extr = getLastPlannedExtruderTrainSettings();
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)
{
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);
lastPosition = p;
@@ -349,13 +352,13 @@ void GCodePlanner::planPrime()
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);
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];
addTravel(p0);
@@ -368,7 +371,7 @@ void GCodePlanner::addPolygon(PolygonRef polygon, int start_idx, GCodePathConfig
}
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;
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)
{
@@ -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);
}
}
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);
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();
for (int poly_idx : orderOptimizer.polyOrder)
{
PolygonRef polygon = polygons[poly_idx];
ConstPolygonRef polygon = polygons[poly_idx];
int start = orderOptimizer.polyStart[poly_idx];
int end = 1 - start;
Point& p0 = polygon[start];
const Point& p0 = polygon[start];
addTravel(p0);
Point& p1 = polygon[end];
const Point& p1 = polygon[end];
addExtrusionMove(p1, config, space_fill_type);
if (wipe_dist != 0)
{
@@ -553,7 +556,7 @@ TimeMaterialEstimates ExtruderPlan::computeNaiveTimeEstimates()
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();
totalPrintTime = estimates.getTotalTime();
if (force_minimal_layer_time)
@@ -636,8 +639,6 @@ void GCodePlanner::processFanSpeedAndMinimalLayerTime()
void GCodePlanner::writeGCode(GCodeExport& gcode)
{
completeConfigs();
CommandSocket::setLayerForSend(layer_nr);
CommandSocket::setSendCurrentPosition( gcode.getPositionXY() );
gcode.setLayerNr(layer_nr);
@@ -653,7 +654,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
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();
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++)
{
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)
{
@@ -764,7 +765,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
else
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 !!
// works when path_idx is the index of the travel move BEFORE the infill lines to be merged
continue;
@@ -787,7 +788,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
bool spiralize = path.spiralize;
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;
if (coasting)
{
@@ -858,15 +859,15 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
if (train->getSettingBoolean("cool_lift_head") && extruder_plan.extraTime > 0.0)
{
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);
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
// or do it anyway when we switch extruder in-place
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?!
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);
}
@@ -886,106 +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);
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);
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();
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)
{
std::vector<GCodePath>& paths = extruder_plans[extruder_plan_idx].paths;
+57 -31
Ver Arquivo
@@ -16,6 +16,7 @@
#include "FanSpeedLayerTime.h"
#include "SpaceFillType.h"
#include "GCodePathConfig.h"
#include "settings/PathConfigStorage.h"
#include "utils/optional.h"
@@ -57,7 +58,7 @@ public:
* \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
*/
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
@@ -165,7 +166,7 @@ protected:
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
@@ -215,9 +216,25 @@ class GCodePlanner : public NoCopy
{
friend class LayerPlanBuffer;
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:
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 is_initial_layer; //!< Whether this is the first layer (which might be raft)
@@ -227,7 +244,9 @@ private:
Point start_position;
Point lastPosition;
bool has_prime_tower_planned;
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
@@ -238,7 +257,7 @@ private:
Comb* comb;
std::vector<FanSpeedLayerTimeSettings>& fan_speed_layer_time_settings_per_extruder;
const std::vector<FanSpeedLayerTimeSettings>& fan_speed_layer_time_settings_per_extruder;
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)
* \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:
/*!
@@ -274,7 +293,7 @@ public:
* \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.
*/
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();
void overrideFanSpeeds(double speed);
@@ -292,12 +311,21 @@ private:
Polygons computeCombBoundaryInside(CombingMode combing_mode);
public:
int getLayerNr()
int getLayerNr() const
{
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;
}
@@ -305,14 +333,25 @@ public:
/*!
* return whether the last position planned was inside the mesh (used in combing)
*/
bool getIsInsideMesh()
bool getIsInsideMesh() const
{
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
*/
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);
}
@@ -336,7 +375,7 @@ public:
/*!
* Get the last planned extruder.
*/
int getExtruder()
int getExtruder() const
{
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 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
@@ -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 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.
@@ -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 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.
@@ -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 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)
@@ -434,20 +473,7 @@ public:
* \param gcode The gcode to write the planned paths to
*/
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.
* 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;
}
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 (line_distance == 0) return;
@@ -144,7 +144,7 @@ void Infill::generateTriangleInfill(Polygons& result)
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;
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 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:
/*!
@@ -148,8 +148,8 @@ private:
* \param[out] result The resulting lines
* \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
* \param result (output) The resulting lines
+7 -7
Ver Arquivo
@@ -186,15 +186,15 @@ SubDivCube::SubDivCube(SliceMeshStorage& mesh, Point3& center, unsigned int dept
bool SubDivCube::isValidSubdivision(SliceMeshStorage& mesh, Point3& center, int64_t radius)
{
int64_t distance2;
long int sphere_slice_radius2;//!< squared radius of bounding sphere slice on target layer
coord_t sphere_slice_radius2;//!< squared radius of bounding sphere slice on target layer
bool inside_somewhere = false;
bool outside_somewhere = false;
int inside;
double part_dist;//what percentage of the radius the target layer is away from the center along the z axis. 0 - 1
const long int layer_height = mesh.getSettingInMicrons("layer_height");
long int bottom_layer = (center.z - radius) / layer_height;
long int top_layer = (center.z + radius) / layer_height;
for (long int test_layer = bottom_layer; test_layer <= top_layer; test_layer += 3) // steps of three. Low-hanging speed gain.
const coord_t layer_height = mesh.getSettingInMicrons("layer_height");
int bottom_layer = (center.z - radius) / layer_height;
int top_layer = (center.z + radius) / layer_height;
for (int test_layer = bottom_layer; test_layer <= top_layer; test_layer += 3) // steps of three. Low-hanging speed gain.
{
part_dist = (double)(test_layer * layer_height - center.z) / radius;
sphere_slice_radius2 = radius * radius * (1.0 - (part_dist * part_dist));
@@ -221,9 +221,9 @@ bool SubDivCube::isValidSubdivision(SliceMeshStorage& mesh, Point3& center, int6
return false;
}
int SubDivCube::distanceFromPointToMesh(SliceMeshStorage& mesh, long int layer_nr, Point& location, int64_t* distance2)
int SubDivCube::distanceFromPointToMesh(SliceMeshStorage& mesh, int layer_nr, Point& location, int64_t* distance2)
{
if (layer_nr < 0 || (unsigned long int)layer_nr >= mesh.layers.size()) //!< this layer is outside of valid range
if (layer_nr < 0 || (unsigned int)layer_nr >= mesh.layers.size()) //!< this layer is outside of valid range
{
return 2;
}
+1 -1
Ver Arquivo
@@ -74,7 +74,7 @@ private:
* \param[out] distance2 the squared distance to the infill border
* \return Code 0: outside, 1: inside, 2: boundary does not exist at specified layer
*/
static int distanceFromPointToMesh(SliceMeshStorage& mesh, long int layer_nr, Point& location, int64_t* distance2);
static int distanceFromPointToMesh(SliceMeshStorage& mesh, int layer_nr, Point& location, int64_t* distance2);
/*!
* Adds the defined line to the specified polygons. It assumes that the specified polygons are all parallel lines. Combines line segments with touching ends closer than epsilon.
+4 -1
Ver Arquivo
@@ -44,7 +44,10 @@ void createLayerWithParts(SliceLayer& storageLayer, SlicerLayer* layer, bool uni
}
void createLayerParts(SliceMeshStorage& mesh, Slicer* slicer, bool union_layers, bool union_all_remove_holes)
{
for(unsigned int layer_nr = 0; layer_nr < slicer->layers.size(); layer_nr++)
const auto total_layers = slicer->layers.size();
assert(mesh.layers.size() == total_layers);
#pragma omp parallel for default(none) shared(mesh,slicer) firstprivate(union_layers,union_all_remove_holes) schedule(dynamic)
for(unsigned int layer_nr = 0; layer_nr < total_layers; layer_nr++)
{
mesh.layers[layer_nr].sliceZ = slicer->layers[layer_nr].z;
mesh.layers[layer_nr].printZ = slicer->layers[layer_nr].z;
+15 -1
Ver Arquivo
@@ -20,6 +20,8 @@
#include "settings/SettingsToGV.h"
#include <omp.h> // omp_get_num_threads
namespace cura
{
@@ -328,7 +330,19 @@ int main(int argc, char **argv)
print_usage();
exit(1);
}
#pragma omp parallel
{
#pragma omp master
{
#ifdef _OPENMP
log("OpenMP multithreading enabled, likely number of threads to be used: %u\n", omp_get_num_threads());
#else
log("OpenMP multithreading disabled\n");
#endif
}
}
if (stringcasecompare(argv[1], "connect") == 0)
{
connect(argc, argv);
+10 -10
Ver Arquivo
@@ -16,7 +16,7 @@ void PathOrderOptimizer::optimize()
bool picked[polygons.size()];
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;
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)
{
PolygonRef poly = polygons[poly_idx];
ConstPolygonRef poly = polygons[poly_idx];
int best_point_idx = -1;
float best_point_score = std::numeric_limits<float>::infinity();
Point p0 = poly.back();
for (unsigned int point_idx = 0; point_idx < poly.size(); point_idx++)
{
Point& p1 = poly[point_idx];
Point& p2 = poly[(point_idx + 1) % poly.size()];
const Point& p1 = poly[point_idx];
const Point& p2 = poly[(point_idx + 1) % poly.size()];
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
// this score is in the order of 5 mm
@@ -143,7 +143,7 @@ void LineOrderOptimizer::optimize()
{
int best_point_idx = -1;
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
{
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
{
PolygonRef best_line = polygons[best_line_idx];
ConstPolygonRef best_line = polygons[best_line_idx];
assert(best_line.size() == 2);
int line_start_point_idx = polyStart[best_line_idx];
int line_end_point_idx = line_start_point_idx * -1 + 1; /// 1 -> 0 , 0 -> 1
Point& line_start = best_line[line_start_point_idx];
Point& line_end = best_line[line_end_point_idx];
const Point& line_start = best_line[line_start_point_idx];
const Point& line_end = best_line[line_end_point_idx];
prev_point = line_end;
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)
{
Point& p0 = polygons[poly_idx][0];
Point& p1 = polygons[poly_idx][1];
const Point& p0 = polygons[poly_idx][0];
const Point& p1 = polygons[poly_idx][1];
float dot_score = getAngleScore(incoming_perpundicular_normal, p0, p1);
{ /// check distance to first point on line (0)
float score = vSize2f(p0 - prev_point) + dot_score; // prefer 90 degree corners
+14 -4
Ver Arquivo
@@ -20,7 +20,7 @@ public:
EZSeamType type;
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')
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> polyOrder; //!< the optimized order as indices in #polygons
@@ -33,10 +33,15 @@ public:
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++)
this->polygons.push_back(polygons[i]);
@@ -66,7 +71,7 @@ class LineOrderOptimizer
{
public:
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> polyOrder; //!< the optimized order as indices in #polygons
@@ -80,6 +85,11 @@ public:
this->polygons.push_back(polygon);
}
void addPolygon(ConstPolygonRef polygon)
{
this->polygons.push_back(polygon);
}
void addPolygons(Polygons& polygons)
{
for(unsigned int i=0;i<polygons.size(); i++)
+5 -4
Ver Arquivo
@@ -6,6 +6,7 @@
#include <unordered_set>
#include "../utils/polygonUtils.h"
#include "../utils/linearAlg2D.h"
#include "../utils/PolygonsPointIndex.h"
#include "../sliceDataStorage.h"
#include "../utils/SVG.h"
@@ -22,7 +23,7 @@ Polygons& Comb::getBoundaryOutside()
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)
, layer_nr(layer_nr)
, 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)
, 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)
, 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 !!
, inside_loc_to_line(PolygonUtils::createLocToLineGrid(boundary_inside, comb_boundary_offset))
, boundary_outside(
@@ -213,7 +214,7 @@ Comb::Crossing::Crossing(const Point& dest_point, const bool dest_is_inside, con
{
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_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 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)
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 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.
* \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 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.
Polygons& boundary_inside; //!< The boundary within which to comb.
PartsView partsView_inside; //!< Structured indices onto boundary_inside which shows which polygons belong to which part.
Polygons boundary_inside; //!< The boundary within which to comb. (Will be reordered by the partsView_inside)
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.
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.
@@ -153,7 +153,7 @@ public:
* \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.
*/
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();
+1 -1
Ver Arquivo
@@ -23,7 +23,7 @@ namespace cura
class GCodePath
{
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
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.
+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
+1 -1
Ver Arquivo
@@ -125,7 +125,7 @@ bool SettingRegistry::getDefinitionFile(const std::string machine_id, std::strin
int SettingRegistry::loadExtruderJSONsettings(unsigned int extruder_nr, SettingsBase* settings_base)
{
if (extruder_train_ids.empty()) //... Tough luck, buddy.
if (extruder_train_ids.empty())
{
logError("Couldn't find any extruder trains!\n");
return -1;
+10 -8
Ver Arquivo
@@ -93,21 +93,23 @@ void SettingsBase::setSettingInheritBase(std::string key, const SettingsBaseVirt
std::string SettingsBase::getSettingString(std::string key) const
{
if (setting_values.find(key) != setting_values.end())
auto value_it = setting_values.find(key);
if (value_it != setting_values.end())
{
return setting_values.at(key);
return value_it->second;
}
if (setting_inherit_base.find(key) != setting_inherit_base.end())
auto inherit_override_it = setting_inherit_base.find(key);
if (inherit_override_it != setting_inherit_base.end())
{
return setting_inherit_base.at(key)->getSettingString(key);
return inherit_override_it->second->getSettingString(key);
}
if (parent)
{
return parent->getSettingString(key);
}
const_cast<SettingsBase&>(*this).setting_values[key] = "";
cura::logWarning("Unregistered setting %s\n", key.c_str());
cura::logError("Trying to retrieve unregistered setting with no value given: '%s'\n", key.c_str());
std::exit(-1);
return "";
}
@@ -426,7 +428,7 @@ FillPerimeterGapMode SettingsBaseVirtual::getSettingAsFillPerimeterGapMode(std::
return FillPerimeterGapMode::NOWHERE;
}
CombingMode SettingsBaseVirtual::getSettingAsCombingMode(std::string key)
CombingMode SettingsBaseVirtual::getSettingAsCombingMode(std::string key) const
{
std::string value = getSettingString(key);
if (value == "off")
@@ -444,7 +446,7 @@ CombingMode SettingsBaseVirtual::getSettingAsCombingMode(std::string key)
return CombingMode::ALL;
}
SupportDistPriority SettingsBaseVirtual::getSettingAsSupportDistPriority(std::string key)
SupportDistPriority SettingsBaseVirtual::getSettingAsSupportDistPriority(std::string key) const
{
std::string value = getSettingString(key);
if (value == "xy_overrides_z")
+2 -2
Ver Arquivo
@@ -251,8 +251,8 @@ public:
EZSeamType getSettingAsZSeamType(std::string key) const;
ESurfaceMode getSettingAsSurfaceMode(std::string key) const;
FillPerimeterGapMode getSettingAsFillPerimeterGapMode(std::string key) const;
CombingMode getSettingAsCombingMode(std::string key);
SupportDistPriority getSettingAsSupportDistPriority(std::string key);
CombingMode getSettingAsCombingMode(std::string key) const;
SupportDistPriority getSettingAsSupportDistPriority(std::string key) const;
};
class SettingRegistry;
+49 -5
Ver Arquivo
@@ -10,7 +10,16 @@
namespace cura
{
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* generateSkinAreas reads data from mesh.layers.parts[*].insets and writes to mesh.layers[n].parts[*].skin_parts
* generateSkinInsets only read/writes the skin_parts from the current layer.
*
* generateSkins therefore reads (depends on) data from mesh.layers[*].parts[*].insets and writes mesh.layers[n].parts[*].skin_parts
*/
void generateSkins(int layerNr, SliceMeshStorage& mesh, int downSkinCount, int upSkinCount, int wall_line_count, int innermost_wall_line_width, int insetCount, bool no_small_gaps_heuristic)
{
generateSkinAreas(layerNr, mesh, innermost_wall_line_width, downSkinCount, upSkinCount, wall_line_count, no_small_gaps_heuristic);
@@ -23,6 +32,12 @@ void generateSkins(int layerNr, SliceMeshStorage& mesh, int downSkinCount, int u
}
}
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* generateSkinAreas reads data from mesh.layers[*].parts[*].insets and writes to mesh.layers[n].parts[*].skin_parts
*/
void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost_wall_line_width, int downSkinCount, int upSkinCount, int wall_line_count, bool no_small_gaps_heuristic)
{
SliceLayer& layer = mesh.layers[layer_nr];
@@ -31,7 +46,7 @@ void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost
{
return;
}
int min_infill_area = mesh.getSettingInMillimeters("min_infill_area");
for(unsigned int partNr = 0; partNr < layer.parts.size(); partNr++)
{
SliceLayerPart& part = layer.parts[partNr];
@@ -63,12 +78,22 @@ void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost
{
if (static_cast<int>(layer_nr - downSkinCount) >= 0)
{
downskin = downskin.difference(getInsidePolygons(mesh.layers[layer_nr - downSkinCount])); // skin overlaps with the walls
Polygons not_air = getInsidePolygons(mesh.layers[layer_nr - downSkinCount]);
if (min_infill_area > 0)
{
not_air.removeSmallAreas(min_infill_area);
}
downskin = downskin.difference(not_air); // skin overlaps with the walls
}
if (static_cast<int>(layer_nr + upSkinCount) < static_cast<int>(mesh.layers.size()))
{
upskin = upskin.difference(getInsidePolygons(mesh.layers[layer_nr + upSkinCount])); // skin overlaps with the walls
Polygons not_air = getInsidePolygons(mesh.layers[layer_nr + upSkinCount]);
if (min_infill_area > 0)
{
not_air.removeSmallAreas(min_infill_area);
}
upskin = upskin.difference(not_air); // skin overlaps with the walls
}
}
else
@@ -80,6 +105,10 @@ void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost
{
not_air = not_air.intersection(getInsidePolygons(mesh.layers[downskin_layer_nr]));
}
if (min_infill_area > 0)
{
not_air.removeSmallAreas(min_infill_area);
}
downskin = downskin.difference(not_air); // skin overlaps with the walls
}
@@ -90,6 +119,10 @@ void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost
{
not_air = not_air.intersection(getInsidePolygons(mesh.layers[upskin_layer_nr]));
}
if (min_infill_area > 0)
{
not_air.removeSmallAreas(min_infill_area);
}
upskin = upskin.difference(not_air); // skin overlaps with the walls
}
}
@@ -106,7 +139,12 @@ void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost
}
}
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* generateSkinInsets only read/writes the skin_parts from the current layer.
*/
void generateSkinInsets(SliceLayerPart* part, const int wall_line_width, int insetCount)
{
if (insetCount == 0)
@@ -139,6 +177,12 @@ void generateSkinInsets(SliceLayerPart* part, const int wall_line_width, int ins
}
}
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* generateInfill read mesh.layers[n].parts[*].{insets,skin_parts,boundingBox} and write mesh.layers[n].parts[*].infill_area
*/
void generateInfill(int layerNr, SliceMeshStorage& mesh, const int innermost_wall_line_width, int infill_skin_overlap, int wall_line_count)
{
SliceLayer& layer = mesh.layers[layerNr];
+5 -32
Ver Arquivo
@@ -35,7 +35,7 @@ void SliceLayer::getOutlines(Polygons& result, bool external_polys_only) const
{
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
{
@@ -57,12 +57,12 @@ void SliceLayer::getSecondOrInnermostWalls(Polygons& layer_walls) const
{
// we want the 2nd inner walls
if (part.insets.size() >= 2) {
layer_walls.add(const_cast<SliceLayerPart&>(part).insets[1]); // TODO const cast!
layer_walls.add(part.insets[1]);
continue;
}
// but we'll also take the inner wall if the 2nd doesn't exist
if (part.insets.size() == 1) {
layer_walls.add(const_cast<SliceLayerPart&>(part).insets[0]); // TODO const cast!
layer_walls.add(part.insets[0]);
continue;
}
// offset_from_outlines was so large that it completely destroyed our isle,
@@ -87,38 +87,11 @@ std::vector<RetractionConfig> SliceDataStorage::initializeRetractionConfigs()
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),
meshgroup(meshgroup != nullptr ? meshgroup : new MeshGroup(FffProcessor::getInstance())), //If no mesh group is provided, we roll our own.
print_layer_count(0),
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),
primeTower(*this)
{
@@ -163,7 +136,7 @@ Polygons SliceDataStorage::getLayerOutlines(int layer_nr, bool include_helper_pa
}
const SliceLayer& layer = mesh.layers[layer_nr];
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));
}
@@ -207,7 +180,7 @@ Polygons SliceDataStorage::getLayerSecondOrInnermostWalls(int layer_nr, bool inc
{
const SliceLayer& layer = mesh.layers[layer_nr];
layer.getSecondOrInnermostWalls(total);
if (const_cast<SliceMeshStorage&>(mesh).getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL) // TODO: make getSetting const? make settings.setting_values mapping mutable??
if (mesh.getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL)
{
total = total.unionPolygons(layer.openPolyLines.offsetPolyLine(100));
}
+12 -39
Ver Arquivo
@@ -8,10 +8,9 @@
#include "utils/NoCopy.h"
#include "utils/AABB.h"
#include "mesh.h"
#include "gcodePlanner.h"
#include "MeshGroup.h"
#include "PrimeTower.h"
#include "GCodePathConfig.h"
#include "gcodeExport.h" // CoastingConfig
namespace cura
{
@@ -138,7 +137,11 @@ public:
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(); }
};
/******************/
@@ -152,25 +155,14 @@ public:
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;
std::vector<GCodePathConfig> infill_config;
SubDivCube* base_subdiv_cube;
SliceMeshStorage(SettingsBaseVirtual* settings, unsigned int slice_layer_count)
: SettingsMessenger(settings)
, layer_nr_max_filled_layer(0)
, inset0_config(PrintFeatureType::OuterWall)
, insetX_config(PrintFeatureType::InnerWall)
, skin_config(PrintFeatureType::Skin)
, base_subdiv_cube(nullptr)
{
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();
@@ -189,18 +181,8 @@ public:
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<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
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;
Polygons skirt_brim[MAX_EXTRUDERS]; //!< Skirt and brim polygons per extruder, ordered from inner to outer polygons.
@@ -215,21 +197,6 @@ public:
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.
/*!
* 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
* specified mesh group.
@@ -279,6 +246,12 @@ public:
* \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;
private:
/*!
* Construct the retraction_config_per_extruder
*/
std::vector<RetractionConfig> initializeRetractionConfigs();
};
}//namespace cura
+9 -5
Ver Arquivo
@@ -216,7 +216,7 @@ SlicerLayer::findPossibleStitches(
// insert the starts of the polylines).
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;
@@ -231,7 +231,7 @@ SlicerLayer::findPossibleStitches(
{
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;
@@ -245,7 +245,7 @@ SlicerLayer::findPossibleStitches(
// search for nearby end points
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;
@@ -887,10 +887,14 @@ Slicer::Slicer(Mesh* mesh, int initial, int thickness, int slice_layer_count, bo
}
}
log("slice of mesh took %.3f seconds\n",slice_timer.restart());
for(unsigned int layer_nr=0; layer_nr<layers.size(); layer_nr++)
std::vector<SlicerLayer>& layers_ref = layers; // force layers not to be copied into the threads
#pragma omp parallel for default(none) shared(mesh,layers_ref) firstprivate(keep_none_closed, extensive_stitching)
for(unsigned int layer_nr=0; layer_nr<layers_ref.size(); layer_nr++)
{
layers[layer_nr].makePolygons(mesh, keep_none_closed, extensive_stitching);
layers_ref[layer_nr].makePolygons(mesh, keep_none_closed, extensive_stitching);
}
mesh->expandXY(mesh->getSettingInMicrons("xy_offset"));
log("slice make polygons took %.3f seconds\n",slice_timer.restart());
}
+61 -51
Ver Arquivo
@@ -90,6 +90,7 @@ void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int l
storage.support.supportLayers.resize(layer_count);
}
// generate support areas
for (unsigned int mesh_idx = 0; mesh_idx < storage.meshes.size(); mesh_idx++)
{
SliceMeshStorage& mesh = storage.meshes[mesh_idx];
@@ -100,25 +101,33 @@ void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int l
std::vector<Polygons> supportAreas;
supportAreas.resize(layer_count, Polygons());
generateSupportAreas(storage, mesh_idx, layer_count, supportAreas);
if (mesh.getSettingBoolean("support_interface_enable"))
for (unsigned int layer_idx = 0; layer_idx < layer_count; layer_idx++)
{
generateSupportInterface(storage, mesh, supportAreas, layer_count);
}
else
{
for (unsigned int layer_idx = 0; layer_idx < layer_count ; layer_idx++)
{
storage.support.supportLayers[layer_idx].supportAreas.add(supportAreas[layer_idx]);
}
storage.support.supportLayers[layer_idx].supportAreas.add(supportAreas[layer_idx]);
}
}
for (unsigned int layer_idx = 0; layer_idx < layer_count ; layer_idx++)
{
Polygons& support_areas = storage.support.supportLayers[layer_idx].supportAreas;
support_areas = support_areas.unionPolygons();
}
// handle support interface
for (unsigned int mesh_idx = 0; mesh_idx < storage.meshes.size(); mesh_idx++)
{
SliceMeshStorage& mesh = storage.meshes[mesh_idx];
if (mesh.getSettingBoolean("infill_mesh") || mesh.getSettingBoolean("anti_overhang_mesh"))
{
continue;
}
if (mesh.getSettingBoolean("support_interface_enable"))
{
generateSupportInterface(storage, mesh, layer_count);
}
}
}
/*
@@ -156,6 +165,7 @@ void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int m
const int supportTowerDiameter = mesh.getSettingInMicrons("support_tower_diameter");
const int supportMinAreaSqrt = mesh.getSettingInMicrons("support_minimal_diameter");
const double supportTowerRoofAngle = mesh.getSettingInAngleRadians("support_tower_roof_angle");
const bool use_towers = mesh.getSettingBoolean("support_use_towers") && supportMinAreaSqrt > 0;
const int layerThickness = storage.getSettingInMicrons("layer_height");
const int supportXYDistance = mesh.getSettingInMicrons("support_xy_distance");
@@ -225,7 +235,10 @@ void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int m
std::vector<std::pair<int, std::vector<Polygons>>> overhang_points; // stores overhang_points along with the layer index at which the overhang point occurs
AreaSupport::detectOverhangPoints(storage, mesh, overhang_points, layer_count, supportMinAreaSqrt);
if (use_towers)
{
AreaSupport::detectOverhangPoints(storage, mesh, overhang_points, layer_count, supportMinAreaSqrt);
}
std::deque<std::pair<Polygons, Polygons>> basic_and_full_overhang_above;
for (unsigned int layer_idx = support_layer_count - 1; layer_idx != support_layer_count - 1 - layerZdistanceTop ; layer_idx--)
@@ -255,7 +268,7 @@ void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int m
supportLayer_this = supportLayer_this.offset(extension_offset);
}
if (supportMinAreaSqrt > 0)
if (use_towers)
{
// handle straight walls
AreaSupport::handleWallStruts(supportLayer_this, supportMinAreaSqrt, supportTowerDiameter);
@@ -342,14 +355,14 @@ void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int m
}
//Enforce top Z distance.
if (layerZdistanceTop > 0)
if (layerZdistanceTop > 1)
{
// this is performed after the main support generation loop above, because it affects the joining of polygons
// if this would be performed in the main loop then some support would not have been generated under the overhangs and consequently no support is generated for that,
// meaning almost no support would be generated in some cases which definitely need support.
for (size_t layer_idx = 0; layer_idx < storage.support.supportLayers.size() && layer_idx < support_layer_count - layerZdistanceTop; layer_idx++)
for (size_t layer_idx = 0; layer_idx < storage.support.supportLayers.size() && layer_idx < support_layer_count - (layerZdistanceTop - 1); layer_idx++)
{
supportAreas[layer_idx] = supportAreas[layer_idx].difference(storage.getLayerOutlines(layer_idx + layerZdistanceTop, false));
supportAreas[layer_idx] = supportAreas[layer_idx].difference(storage.getLayerOutlines(layer_idx + layerZdistanceTop - 1, false));
}
}
@@ -559,7 +572,7 @@ void AreaSupport::handleWallStruts(
}
void AreaSupport::generateSupportInterface(SliceDataStorage& storage, const SliceMeshStorage& mesh, std::vector<Polygons>& support_areas, const unsigned int layer_count)
void AreaSupport::generateSupportInterface(SliceDataStorage& storage, const SliceMeshStorage& mesh, const unsigned int layer_count)
{
const unsigned int roof_layer_count = round_divide(mesh.getSettingInMicrons("support_roof_height"), storage.getSettingInMicrons("layer_height"));
const unsigned int bottom_layer_count = round_divide(mesh.getSettingInMicrons("support_bottom_height"), storage.getSettingInMicrons("layer_height"));
@@ -576,44 +589,41 @@ void AreaSupport::generateSupportInterface(SliceDataStorage& storage, const Slic
const unsigned int top_layer_idx_above = layer_idx + roof_layer_count + z_distance_top;
const unsigned int bottom_layer_idx_below = std::max(0, int(layer_idx) - int(bottom_layer_count) - int(z_distance_bottom));
if (top_layer_idx_above < supportLayers.size())
if (top_layer_idx_above >= supportLayers.size())
{
Polygons roofs;
if (roof_layer_count > 0)
{
Polygons model;
const unsigned int n_scans = std::max(1u, (roof_layer_count - 1) / skip_layer_count);
const float z_skip = std::max(1.0f, float(roof_layer_count - 1) / float(n_scans));
for (float layer_idx_above = top_layer_idx_above; layer_idx_above > layer_idx + z_distance_top; layer_idx_above -= z_skip)
{
const Polygons outlines_above = mesh.layers[std::round(layer_idx_above)].getOutlines();
model = model.unionPolygons(outlines_above);
}
roofs = support_areas[layer_idx].intersection(model);
}
Polygons bottoms;
if (bottom_layer_count > 0)
{
Polygons model;
const unsigned int n_scans = std::max(1u, (bottom_layer_count - 1) / skip_layer_count);
const float z_skip = std::max(1.0f, float(bottom_layer_count - 1) / float(n_scans));
for (float layer_idx_below = bottom_layer_idx_below; std::round(layer_idx_below) < (int)(layer_idx - z_distance_bottom); layer_idx_below += z_skip)
{
const Polygons outlines_below = mesh.layers[std::round(layer_idx_below)].getOutlines();
model = model.unionPolygons(outlines_below);
}
bottoms = support_areas[layer_idx].intersection(model);
}
// expand skin a bit so that we're sure it's not too thin to be printed.
Polygons skin = roofs.unionPolygons(bottoms).offset(interface_line_width).intersection(support_areas[layer_idx]);
skin.removeSmallAreas(1.0);
layer.skin.add(skin);
layer.supportAreas.add(support_areas[layer_idx].difference(layer.skin));
continue;
}
else
Polygons roofs;
if (roof_layer_count > 0)
{
layer.skin.add(support_areas[layer_idx]);
Polygons model;
const unsigned int n_scans = std::max(1u, (roof_layer_count - 1) / skip_layer_count);
const float z_skip = std::max(1.0f, float(roof_layer_count - 1) / float(n_scans));
for (float layer_idx_above = top_layer_idx_above; layer_idx_above > layer_idx + z_distance_top; layer_idx_above -= z_skip)
{
const Polygons outlines_above = mesh.layers[std::round(layer_idx_above)].getOutlines();
model = model.unionPolygons(outlines_above);
}
roofs = layer.supportAreas.intersection(model);
}
Polygons bottoms;
if (bottom_layer_count > 0)
{
Polygons model;
const unsigned int n_scans = std::max(1u, (bottom_layer_count - 1) / skip_layer_count);
const float z_skip = std::max(1.0f, float(bottom_layer_count - 1) / float(n_scans));
for (float layer_idx_below = bottom_layer_idx_below; std::round(layer_idx_below) < (int)(layer_idx - z_distance_bottom); layer_idx_below += z_skip)
{
const Polygons outlines_below = mesh.layers[std::round(layer_idx_below)].getOutlines();
model = model.unionPolygons(outlines_below);
}
bottoms = layer.supportAreas.intersection(model);
}
// expand skin a bit so that we're sure it's not too thin to be printed.
Polygons skin = roofs.unionPolygons(bottoms).offset(interface_line_width).intersection(layer.supportAreas);
skin.removeSmallAreas(1.0);
layer.skin.add(skin);
layer.supportAreas = layer.supportAreas.difference(layer.skin);
}
}
+1 -2
Ver Arquivo
@@ -36,10 +36,9 @@ private:
*
* \param storage Output storage: support area + support skin area output
* \param mesh The mesh to generate support skins for.
* \param support_areas The basic support areas for the current mesh
* \param layer_count The number of layers in this mesh group.
*/
static void generateSupportInterface(SliceDataStorage& storage, const SliceMeshStorage& mesh, std::vector<Polygons>& support_areas, const unsigned int layer_count);
static void generateSupportInterface(SliceDataStorage& storage, const SliceMeshStorage& mesh, const unsigned int layer_count);
/*!
* Join current support layer with the support of the layer above, (make support conical) and perform smoothing etc operations.
+2 -2
Ver Arquivo
@@ -24,7 +24,7 @@ AABB::AABB(const Polygons& polys)
calculate(polys);
}
AABB::AABB(const PolygonRef poly)
AABB::AABB(ConstPolygonRef poly)
: min(POINT_MAX, POINT_MAX), max(POINT_MIN, POINT_MIN)
{
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);
max = Point(POINT_MIN, POINT_MIN);
+2 -2
Ver Arquivo
@@ -20,10 +20,10 @@ public:
AABB(); //!< initializes with invalid 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 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 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.
+6
Ver Arquivo
@@ -37,6 +37,12 @@ void AABB3D::include(Point3 p)
max.z = std::max(max.z, p.z);
}
void AABB3D::includeZ(int32_t z)
{
min.z = std::min(min.z, z);
max.z = std::max(max.z, z);
}
void AABB3D::offset(Point3 offset)
{
min += offset;
+8
Ver Arquivo
@@ -38,6 +38,14 @@ struct AABB3D
*/
void include(Point3 p);
/*!
* Expand the AABB3D to include a z-coordinate.
*
* This is for including a point of which the X and Y coordinates are
* unknown but known to already be included in the bounding box.
*/
void includeZ(int32_t z);
/*!
* Offset the coordinates of the bounding box.
* \param offset The offset with which to offset the AABB3D.
+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();
convertPolygonToList(poly, result.back());
}
}
void ListPolyIt::convertPolygonToList(PolygonRef poly, ListPolygon& result)
void ListPolyIt::convertPolygonToList(ConstPolygonRef poly, ListPolygon& result)
{
#ifdef DEBUG
Point last = poly.back();
#endif // DEBUG
for (Point& p : poly)
for (const Point& p : poly)
{
result.push_back(p);
#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++)
{
@@ -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);
}
+4 -4
Ver Arquivo
@@ -94,28 +94,28 @@ public:
* \param polys The polygons to convert
* \param result The converted polygons
*/
static void convertPolygonsToLists(Polygons& polys, ListPolygons& result);
static void convertPolygonsToLists(const Polygons& polys, ListPolygons& result);
/*!
* Convert Polygons to ListPolygons
*
* \param polys The polygons to convert
* \param result The converted polygons
*/
static void convertPolygonToList(PolygonRef poly, ListPolygon& result);
static void convertPolygonToList(ConstPolygonRef poly, ListPolygon& result);
/*!
* Convert ListPolygons to Polygons
*
* \param list_polygons The polygons to convert
* \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
*
* \param list_polygons The polygons to convert
* \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.
+1 -1
Ver Arquivo
@@ -46,7 +46,7 @@ public:
/*!
* Get the polygon to which this PolygonsPointIndex refers
*/
const PolygonRef getPolygon() const
ConstPolygonRef getPolygon() const
{
return (*polygons)[poly_idx];
}
+5 -6
Ver Arquivo
@@ -93,9 +93,8 @@ public:
{
for(unsigned int j=0;j<parts.size();j++)
{
Polygon poly = parts[j];
fprintf(out, "<polygon points=\"");
for(Point& p : poly)
for (Point& p : parts[j])
{
Point fp = transform(p);
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);
}
@@ -209,12 +208,12 @@ public:
}
void writePolygons(const Polygons& polys, Color color = Color::BLACK)
{
for (const PolygonRef poly : const_cast<Polygons&>(polys))
for (ConstPolygonRef poly : polys)
{
writePolygon(poly, color);
}
}
void writePolygon(const PolygonRef poly, Color color = Color::BLACK)
void writePolygon(ConstPolygonRef poly, Color color = Color::BLACK)
{
Point p0 = poly.back();
for (Point p1 : poly)
+33 -32
Ver Arquivo
@@ -8,9 +8,9 @@
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();
int64_t length = 0;
for (const Point& p1 : polygon)
@@ -25,9 +25,9 @@ bool PolygonRef::shorterThan(int64_t check_length) const
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)
{
return false;
@@ -200,11 +200,11 @@ Polygons Polygons::offset(int distance, ClipperLib::JoinType join_type, double m
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;
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.Execute(ret.paths, distance);
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 in both directions untill shortcut > shortcut_length
@@ -703,7 +703,7 @@ bool PolygonRef::smooth_corner_complex(ListPolygon& poly, const Point p1, ListPo
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 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
// ^ /
@@ -837,7 +837,6 @@ void PolygonRef::smooth_corner_simple(ListPolygon& poly, const Point p0, const P
Point b;
bool success = LinearAlg2D::getPointOnLineWithDist(a, p1, p2, shortcut_length, b);
// v02 has to be longer than ab!
p1_it.remove();
if (success)
{ // if not success then assume b is negligibly close to 2, but rounding errors caused a problem
#ifdef ASSERT_INSANE_OUTPUT
@@ -845,11 +844,12 @@ void PolygonRef::smooth_corner_simple(ListPolygon& poly, const Point p0, const P
#endif // #ifdef ASSERT_INSANE_OUTPUT
ListPolyIt::insertPointNonDuplicate(p1_it, p2_it, b);
}
p1_it.remove();
}
}
}
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:
//
@@ -952,7 +952,8 @@ Polygons Polygons::smooth_outward(float max_angle, int shortcut_length)
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) :
//
@@ -967,7 +968,7 @@ void PolygonRef::smooth(int remove_length, PolygonRef result)
// |
// |
// 0
PolygonRef& thiss = *this;
const ConstPolygonRef& thiss = *path;
ClipperLib::Path* poly = result.path;
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;
for (unsigned int p = 0; p < size(); p++)
{
PolygonRef poly(paths[p]);
ConstPolygonRef poly(paths[p]);
if (poly.size() < 3)
{
continue;
@@ -1061,23 +1062,23 @@ Polygons Polygons::smooth(int remove_length)
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;
if (size() > 0)
if (thiss.size() > 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];
Point& now = thiss[poly_idx];
Point& next = thiss[(poly_idx + 1) % size()];
if (shorterThen(last - now, remove_length) && shorterThen(now - next, remove_length))
const Point& last = thiss[poly_idx - 1];
const Point& now = thiss[poly_idx];
const Point& next = thiss[(poly_idx + 1) % thiss.size()];
if (shorterThen(last - now, remove_length) && shorterThen(now - next, remove_length))
{
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]);
}
@@ -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;
for (unsigned int p = 0; p < size(); p++)
{
PolygonRef poly(paths[p]);
ConstPolygonRef poly(paths[p]);
if (poly.size() == 0)
{
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++)
{
std::vector<unsigned int>& partView = partsView[part_idx_now];
const std::vector<unsigned int>& partView = partsView[part_idx_now];
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 (boundary_poly_idx) { *boundary_poly_idx = partView[0]; }
@@ -1178,7 +1179,7 @@ PolygonsPart PartsView::assemblePart(unsigned int part_idx) const
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;
unsigned int part_idx = getPartContaining(poly_idx, boundary_poly_idx);
@@ -1215,7 +1216,7 @@ void Polygons::splitIntoPartsView_processPolyTreeNode(PartsView& partsView, Poly
partsView.emplace_back();
unsigned int pos = partsView.size() - 1;
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++)
{
partsView[pos].push_back(reordered.size());
+184 -121
Ver Arquivo
@@ -27,6 +27,8 @@ namespace cura {
class PartsView;
class Polygons;
class Polygon;
class PolygonRef;
class ListPolyIt;
@@ -36,31 +38,60 @@ typedef std::vector<ListPolygon> ListPolygons; //!< Polygons represented by a ve
const static int clipper_init = (0);
#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;
PolygonRef()
ConstPolygonRef()
: path(nullptr)
{}
public:
PolygonRef(ClipperLib::Path& polygon)
: path(&polygon)
ConstPolygonRef(const ClipperLib::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
{
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];
}
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
@@ -68,37 +99,10 @@ public:
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.
*
*
* from http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Functions/Orientation.htm
*/
bool orientation() const
@@ -106,11 +110,6 @@ public:
return ClipperLib::Orientation(*path);
}
void reverse()
{
ClipperLib::ReversePath(*path);
}
Polygons offset(int distance, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miter_limit = 1.2) const;
int64_t polygonLength() const
@@ -125,7 +124,7 @@ public:
}
return length;
}
bool shorterThan(int64_t check_length) const;
Point min() const
@@ -138,7 +137,7 @@ public:
}
return ret;
}
Point max() const
{
Point ret = Point(POINT_MIN, POINT_MIN);
@@ -154,19 +153,6 @@ public:
{
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
{
@@ -183,14 +169,14 @@ public:
}
double area = Area(*path);
x = x / 6 / area;
y = y / 6 / area;
return Point(x, y);
}
Point closestPointTo(Point p)
Point closestPointTo(Point p) const
{
Point ret = p;
float bestDist = FLT_MAX;
@@ -205,7 +191,7 @@ public:
}
return ret;
}
/*!
* 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.
@@ -241,7 +227,7 @@ public:
}
return res == 1;
}
/*!
* 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
@@ -253,7 +239,7 @@ public:
* \param remove_length The length of the largest segment removed
* \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
@@ -271,51 +257,8 @@ public:
* \param remove_length The length of the largest segment removed
* \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:
/*!
@@ -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);
};
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
{
ClipperLib::Path poly;
@@ -384,7 +434,7 @@ public:
{
}
Polygon(const PolygonRef& other)
Polygon(PolygonRef& other)
: PolygonRef(poly)
{
poly = *other.path;
@@ -397,6 +447,7 @@ class Polygons
{
friend class Polygon;
friend class PolygonRef;
friend class ConstPolygonRef;
protected:
ClipperLib::Paths paths;
public:
@@ -410,11 +461,12 @@ public:
PolygonRef operator[] (unsigned int index)
{
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()
{
@@ -457,7 +509,11 @@ public:
{
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);
}
@@ -493,6 +549,10 @@ public:
{
return PolygonRef(paths.back());
}
ConstPolygonRef back() const
{
return ConstPolygonRef(paths.back());
}
Polygons() {}
@@ -647,7 +707,7 @@ public:
* \param remove_length The length of the largest segment removed
* \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
@@ -658,7 +718,7 @@ public:
*/
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
@@ -798,16 +858,16 @@ public:
* 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 remove(Polygons& to_be_removed, int same_distance = 0)
Polygons remove(const Polygons& to_be_removed, int same_distance = 0) const
{
Polygons result;
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;
if (poly_keep.size() > 0)
// 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];
if (poly_rem.size() != poly_keep.size() || poly_rem.size() == 0) continue;
@@ -923,10 +983,13 @@ public:
class PolygonsPart : public Polygons
{
public:
PolygonRef outerPolygon()
PolygonRef outerPolygon()
{
Polygons& thiss = *this;
return thiss[0];
return this->paths[0];
}
ConstPolygonRef outerPolygon() const
{
return this->paths[0];
}
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
* \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.
*
@@ -967,7 +1030,7 @@ public:
* \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
*/
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.
*
+39 -39
Ver Arquivo
@@ -22,7 +22,7 @@ int64_t PolygonUtils::segmentLength(PolygonsPointIndex start, PolygonsPointIndex
assert(start.poly_idx == end.poly_idx);
int64_t segment_length = 0;
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++)
{
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);
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;
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.");
}
Point PolygonUtils::getVertexInwardNormal(PolygonRef poly, unsigned int point_idx)
Point PolygonUtils::getVertexInwardNormal(ConstPolygonRef poly, unsigned int point_idx)
{
Point p1 = poly[point_idx];
@@ -110,7 +110,7 @@ Point PolygonUtils::getVertexInwardNormal(PolygonRef poly, unsigned int point_id
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 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);
}
@@ -130,7 +130,7 @@ Point PolygonUtils::moveInsideDiagonally(ClosestPolygonPoint point_on_boundary,
{
return no_point;
}
PolygonRef poly = *point_on_boundary.poly;
ConstPolygonRef poly = *point_on_boundary.poly;
Point p0 = poly[point_on_boundary.point_idx];
Point p1 = poly[(point_on_boundary.point_idx + 1) % poly.size()];
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);
}
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;
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
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)
continue;
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
return cpp.location;
}
const PolygonRef poly = *cpp.poly;
ConstPolygonRef poly = *cpp.poly;
unsigned int point_idx = cpp.point_idx;
const Point& on_boundary = cpp.location;
Point& p1 = poly[point_idx];
const Point& p1 = poly[point_idx];
unsigned int p2_idx;
for (p2_idx = point_idx + 1; p2_idx != point_idx; p2_idx = p2_idx + 1)
{ // find the next point different from p1
@@ -361,7 +361,7 @@ Point PolygonUtils::moveInside(const ClosestPolygonPoint& cpp, const int distanc
break;
}
}
Point& p2 = poly[p2_idx];
const Point& p2 = poly[p2_idx];
if (on_boundary == p1)
{
@@ -392,7 +392,7 @@ ClosestPolygonPoint PolygonUtils::ensureInsideOrOutside(const Polygons& polygons
{
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();
{
@@ -481,8 +481,8 @@ void PolygonUtils::findSmallestConnection(ClosestPolygonPoint& poly1_result, Clo
{
return;
}
PolygonRef poly1 = *poly1_result.poly;
PolygonRef poly2 = *poly2_result.poly;
ConstPolygonRef poly1 = *poly1_result.poly;
ConstPolygonRef poly2 = *poly2_result.poly;
if (poly1.size() == 0 || poly2.size() == 0)
{
return;
@@ -515,8 +515,8 @@ void PolygonUtils::walkToNearestSmallestConnection(ClosestPolygonPoint& poly1_re
{
return;
}
PolygonRef poly1 = *poly1_result.poly;
PolygonRef poly2 = *poly2_result.poly;
ConstPolygonRef poly1 = *poly1_result.poly;
ConstPolygonRef poly2 = *poly2_result.poly;
if (poly1_result.point_idx < 0 || poly2_result.point_idx < 0)
{
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);
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)
{
@@ -572,8 +572,8 @@ ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, PolygonRef poly
{
int p1_idx = (polygon.size() + direction*p + start_idx) % polygon.size();
int p2_idx = (polygon.size() + direction*(p+1) + start_idx) % polygon.size();
Point& p1 = polygon[p1_idx];
Point& p2 = polygon[p2_idx];
const Point& p1 = polygon[p1_idx];
const Point& p2 = polygon[p2_idx];
Point closest_here = LinearAlg2D::getClosestOnLineSegment(from, p1 ,p2);
int64_t dist = vSize2(from - closest_here);
@@ -600,7 +600,7 @@ ClosestPolygonPoint PolygonUtils::findClosest(Point from, const Polygons& polygo
{
return none;
}
PolygonRef any_polygon = polygons[0];
ConstPolygonRef any_polygon = polygons[0];
unsigned int any_poly_idx;
for (any_poly_idx = 0; any_poly_idx < polygons.size(); any_poly_idx++)
{ // 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++)
{
const PolygonRef poly = polygons[ply];
ConstPolygonRef poly = polygons[ply];
if (poly.size() == 0) continue;
ClosestPolygonPoint closest_here = findClosest(from, poly, penalty_function);
if (!closest_here.isValid())
@@ -639,7 +639,7 @@ ClosestPolygonPoint PolygonUtils::findClosest(Point from, const Polygons& polygo
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)
{
@@ -653,11 +653,11 @@ ClosestPolygonPoint PolygonUtils::findClosest(Point from, const PolygonRef polyg
//
for (unsigned int p = 0; p<polygon.size(); p++)
{
Point& p1 = polygon[p];
const Point& p1 = polygon[p];
unsigned int p2_idx = p+1;
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);
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;
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++)
{
int64_t dist2 = vSize2(poly[point_idx] - from);
@@ -692,7 +692,7 @@ PolygonsPointIndex PolygonUtils::findNearestVert(const Point from, const Polygon
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();
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++)
{
const PolygonRef poly = polygons[poly_idx];
ConstPolygonRef poly = polygons[poly_idx];
for (unsigned int point_idx = 0; point_idx < poly.size(); 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);
for (PolygonsPointIndex& point_poly_index : near_lines)
{
const PolygonRef poly = polygons[point_poly_index.poly_idx];
Point& p1 = poly[point_poly_index.point_idx];
Point& p2 = poly[(point_poly_index.point_idx + 1) % poly.size()];
ConstPolygonRef poly = polygons[point_poly_index.poly_idx];
const Point& p1 = poly[point_poly_index.point_idx];
const Point& p2 = poly[(point_poly_index.point_idx + 1) % poly.size()];
Point closest_here = LinearAlg2D::getClosestOnLineSegment(from, p1 ,p2);
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(
const PolygonRef from, const Polygons& destination,
ConstPolygonRef from, const Polygons& destination,
const LocToLineGrid& destination_loc_to_line,
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()];
@@ -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++)
{
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) )
{
/*
@@ -932,7 +932,7 @@ bool PolygonUtils::polygonCollidesWithLineSegment(const Point from, const Point
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());
for(Point p1_ : poly)
@@ -947,7 +947,7 @@ bool PolygonUtils::polygonCollidesWithLineSegment(const PolygonRef poly, Point&
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;
@@ -958,9 +958,9 @@ bool PolygonUtils::polygonCollidesWithLineSegment(const PolygonRef poly, Point&
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 (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;
+18 -18
Ver Arquivo
@@ -20,12 +20,12 @@ namespace cura
struct ClosestPolygonPoint
{
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 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, PolygonRef 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(Point p, int pos, ConstPolygonRef poly) : location(p), poly(true, poly), poly_idx(NO_INDEX), 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(ConstPolygonRef poly) : poly(true, poly), poly_idx(NO_INDEX), point_idx(NO_INDEX) {};
ClosestPolygonPoint() : poly_idx(NO_INDEX), point_idx(NO_INDEX) {};
Point p() const
{ // conformity with other classes
@@ -53,7 +53,7 @@ struct PolygonsPointIndexSegmentLocator
{
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];
unsigned int next_point_idx = (val.point_idx + 1) % poly.size();
Point end = poly[next_point_idx];
@@ -104,7 +104,7 @@ public:
* \param poly 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.
@@ -114,7 +114,7 @@ public:
* \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.
*/
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.
@@ -178,7 +178,7 @@ public:
* \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
*/
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.
@@ -298,7 +298,7 @@ public:
* \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.
*/
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.
@@ -309,7 +309,7 @@ public:
* \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.
*/
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.
@@ -327,7 +327,7 @@ public:
*
* \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
@@ -343,7 +343,7 @@ public:
* \param poly The polygon in which to search
* \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
@@ -382,7 +382,7 @@ public:
* \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.
*/
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.
@@ -409,7 +409,7 @@ public:
* \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.
*/
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
* 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).
@@ -449,7 +449,7 @@ public:
* \return whether the line segment collides with the boundary of the
* 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).
@@ -471,7 +471,7 @@ public:
* \return whether the line segment collides with the boundary of the
* 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).
@@ -487,7 +487,7 @@ public:
* \return whether the line segment collides with the boundary of the
* 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:
/*!
+4 -1
Ver Arquivo
@@ -1,3 +1,6 @@
//Copyright (c) 2017 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
#ifndef UTILS_STRING_H
#define UTILS_STRING_H
@@ -35,7 +38,7 @@ static inline void writeInt2mm(const int64_t coord, std::ostream& ss)
{
constexpr size_t buffer_size = 24;
char buffer[buffer_size];
int char_count = sprintf(buffer, "%" PRId64, coord); // convert int to string
int char_count = sprintf(buffer, "%d", int(coord)); // convert int to string
#ifdef DEBUG
if (char_count + 1 >= int(buffer_size)) // + 1 for the null character
{
+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;
+1 -1
Ver Arquivo
@@ -60,7 +60,7 @@ public:
* \param to The ending 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.
+4 -1
Ver Arquivo
@@ -235,11 +235,14 @@ class Setting:
tree = ast.parse(code, "eval")
compiled = compile(code, self._key, "eval")
except (SyntaxError, TypeError) as e:
print("Parse error in function (" + code + ") for setting", self._key + ":", str(e))
print("Parse error in function (" + str(code) + ") for setting", self._key + ":", str(e))
return None
except IllegalMethodError as e:
print("Use of illegal method", str(e), "in function (" + code + ") for setting", self._key)
return None
except Exception as e:
print("Exception in function (" + code + ") for setting", self._key + ":", str(e))
return None
return eval(compiled, globals(), locals)