Comparar commits
11 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 2926c2e06e | |||
| 7f9dd1cd81 | |||
| bfbfa5c47f | |||
| d887b50eed | |||
| 9712301aa8 | |||
| cdb0a41243 | |||
| 3235fc856d | |||
| d97f67967b | |||
| 64abe6b620 | |||
| cfc2dcb0ad | |||
| 43a40f86b7 |
@@ -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)
|
||||
@@ -79,6 +89,7 @@ set(engine_SRCS # Except main.cpp.
|
||||
src/wallOverlap.cpp
|
||||
src/Weaver.cpp
|
||||
src/Wireframe2gcode.cpp
|
||||
src/multithreadOpenMP.cpp
|
||||
|
||||
src/infill/NoZigZagConnectorProcessor.cpp
|
||||
src/infill/ZigzagConnectorProcessorConnectedEndPieces.cpp
|
||||
|
||||
+47
-30
@@ -91,9 +91,15 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int layer_nr=0; layer_nr<total_layers; layer_nr++)
|
||||
#pragma omp parallel default(none) shared(storage, total_layers)
|
||||
{
|
||||
processLayer(storage, layer_nr, total_layers);
|
||||
#pragma omp single nowait
|
||||
{
|
||||
for(unsigned int layer_nr=0; layer_nr<total_layers; layer_nr++)
|
||||
{
|
||||
processLayer(storage, layer_nr, total_layers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Progress::messageProgressStage(Progress::Stage::FINISH, &time_keeper);
|
||||
@@ -344,7 +350,10 @@ 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 = layer_plan_buffer.createPlanner(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"));
|
||||
// There should be a synchronization construct to make sure the writegcode task is complete before trimBuffer is called
|
||||
#pragma omp taskwait
|
||||
layer_plan_buffer.trimBuffer();
|
||||
gcode_layer.setIsInside(true);
|
||||
|
||||
gcode_layer.setExtruder(extruder_nr);
|
||||
@@ -381,7 +390,10 @@ 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 = layer_plan_buffer.createPlanner(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"));
|
||||
// There should be a synchronization construct to make sure the writegcode task is complete before trimBuffer is called
|
||||
#pragma omp taskwait
|
||||
layer_plan_buffer.trimBuffer();
|
||||
gcode_layer.setIsInside(true);
|
||||
|
||||
gcode_layer.setExtruder(extruder_nr); // reset to extruder number, because we might have primed in the last layer
|
||||
@@ -413,7 +425,10 @@ 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 = layer_plan_buffer.createPlanner(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"));
|
||||
// There should be a synchronization construct to make sure the writegcode task is complete before trimBuffer is called
|
||||
#pragma omp taskwait
|
||||
layer_plan_buffer.trimBuffer();
|
||||
gcode_layer.setIsInside(true);
|
||||
|
||||
if (CommandSocket::isInstantiated())
|
||||
@@ -497,7 +512,7 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
|
||||
|
||||
|
||||
|
||||
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 = layer_plan_buffer.createPlanner(storage, layer_nr, z, layer_thickness, last_position_planned, current_extruder_planned, is_inside_mesh_layer_part, fan_speed_layer_time_settings_per_extruder, getSettingAsCombingMode("retraction_combing"), comb_offset_from_outlines, avoid_other_parts, avoid_distance);
|
||||
|
||||
if (include_helper_parts && layer_nr == 0)
|
||||
{ // process the skirt or the brim of the starting extruder.
|
||||
@@ -586,7 +601,9 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
|
||||
last_position_planned = gcode_layer.getLastPosition();
|
||||
current_extruder_planned = gcode_layer.getExtruder();
|
||||
is_inside_mesh_layer_part = gcode_layer.getIsInsideMesh();
|
||||
|
||||
// There should be a synchronization construct to make sure the writegcode task is complete before trimBuffer is called
|
||||
#pragma omp taskwait
|
||||
layer_plan_buffer.trimBuffer();
|
||||
gcode_layer.processFanSpeedAndMinimalLayerTime();
|
||||
}
|
||||
|
||||
@@ -627,7 +644,7 @@ void FffGcodeWriter::processSkirtBrim(SliceDataStorage& storage, GCodePlanner& g
|
||||
{
|
||||
return;
|
||||
}
|
||||
gcode_layer.addTravel(skirt_brim.back().closestPointTo(gcode_layer.getLastPosition()));
|
||||
gcode_layer.addTravel(PolygonRef{skirt_brim.back()}.closestPointTo(gcode_layer.getLastPosition()));
|
||||
gcode_layer.addPolygonsByOptimizer(skirt_brim, &storage.skirt_brim_config[extruder_nr]);
|
||||
}
|
||||
|
||||
@@ -715,7 +732,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(SliceDataStorage& storage, const SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
|
||||
{
|
||||
if (layer_nr > mesh->layer_nr_max_filled_layer)
|
||||
{
|
||||
@@ -731,7 +748,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;
|
||||
@@ -747,12 +764,12 @@ void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& stora
|
||||
addMeshOpenPolyLinesToGCode(storage, mesh, gcode_layer, layer_nr);
|
||||
}
|
||||
|
||||
void FffGcodeWriter::addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
|
||||
void FffGcodeWriter::addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, const SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
@@ -766,7 +783,7 @@ void FffGcodeWriter::addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, Slic
|
||||
|
||||
}
|
||||
|
||||
void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
|
||||
void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, const SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
|
||||
{
|
||||
if (layer_nr > mesh->layer_nr_max_filled_layer)
|
||||
{
|
||||
@@ -780,7 +797,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)
|
||||
{
|
||||
@@ -790,7 +807,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)
|
||||
{
|
||||
@@ -822,7 +839,7 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshSto
|
||||
|
||||
for (int part_idx : part_order_optimizer.polyOrder)
|
||||
{
|
||||
SliceLayerPart& part = layer->parts[part_idx];
|
||||
const SliceLayerPart& part = layer->parts[part_idx];
|
||||
addMeshPartToGCode(storage, mesh, part, gcode_layer, layer_nr);
|
||||
}
|
||||
if (mesh->getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL)
|
||||
@@ -831,7 +848,7 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshSto
|
||||
}
|
||||
}
|
||||
|
||||
void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, SliceLayerPart& part, GCodePlanner& gcode_layer, int layer_nr)
|
||||
void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, const SliceMeshStorage* mesh, const SliceLayerPart& part, GCodePlanner& gcode_layer, int layer_nr)
|
||||
{
|
||||
bool skin_alternate_rotation = mesh->getSettingBoolean("skin_alternate_rotation") && ( mesh->getSettingAsCount("top_layers") >= 4 || mesh->getSettingAsCount("bottom_layers") >= 4 );
|
||||
|
||||
@@ -893,7 +910,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 SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int infill_angle)
|
||||
{
|
||||
int64_t z = layer_nr * getSettingInMicrons("layer_height");
|
||||
if (infill_line_distance > 0)
|
||||
@@ -924,7 +941,7 @@ void FffGcodeWriter::processMultiLayerInfill(GCodePlanner& gcode_layer, SliceMes
|
||||
}
|
||||
}
|
||||
|
||||
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 SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int infill_angle)
|
||||
{
|
||||
if (infill_line_distance == 0 || part.infill_area_per_combine_per_density[0].size() == 0)
|
||||
{
|
||||
@@ -985,7 +1002,7 @@ void FffGcodeWriter::processSingleLayerInfill(GCodePlanner& gcode_layer, SliceMe
|
||||
}
|
||||
}
|
||||
|
||||
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 SliceLayerPart& part, unsigned int layer_nr, EZSeamType z_seam_type, Point z_seam_pos)
|
||||
{
|
||||
bool compensate_overlap_0 = mesh->getSettingBoolean("travel_compensate_overlapping_walls_0_enabled");
|
||||
bool compensate_overlap_x = mesh->getSettingBoolean("travel_compensate_overlapping_walls_x_enabled");
|
||||
@@ -1022,7 +1039,7 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, SliceMeshStorage*
|
||||
}
|
||||
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);
|
||||
}
|
||||
@@ -1035,7 +1052,7 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, SliceMeshStorage*
|
||||
}
|
||||
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);
|
||||
}
|
||||
@@ -1045,7 +1062,7 @@ 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 SliceLayerPart& part, unsigned int layer_nr, int skin_overlap, int skin_angle)
|
||||
{
|
||||
int64_t z = layer_nr * getSettingInMicrons("layer_height");
|
||||
const unsigned int skin_line_width = mesh->skin_config.getLineWidth();
|
||||
@@ -1059,14 +1076,14 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
|
||||
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;
|
||||
@@ -1085,11 +1102,11 @@ 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
|
||||
}
|
||||
@@ -1168,7 +1185,7 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
|
||||
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);
|
||||
}
|
||||
@@ -1245,7 +1262,7 @@ bool FffGcodeWriter::addSupportInfillToGCode(SliceDataStorage& storage, GCodePla
|
||||
PathOrderOptimizer island_order_optimizer(gcode_layer.getLastPosition());
|
||||
for(unsigned int n=0; n<support_islands.size(); n++)
|
||||
{
|
||||
island_order_optimizer.addPolygon(support_islands[n][0]);
|
||||
island_order_optimizer.addPolygon(PolygonRef{support_islands[n][0]});
|
||||
}
|
||||
island_order_optimizer.optimize();
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ private:
|
||||
* \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(SliceDataStorage& storage, const SliceMeshStorage* mesh, GCodePlanner& gcodeLayer, int layer_nr);
|
||||
|
||||
/*!
|
||||
* Add the open polylines from a single layer from a single mesh-volume to the layer plan \p gcodeLayer for mesh the surface modes.
|
||||
@@ -312,7 +312,7 @@ private:
|
||||
* \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(SliceDataStorage& storage, const SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr);
|
||||
|
||||
/*!
|
||||
* Add a single layer from a single mesh-volume to the layer plan \p gcode_layer.
|
||||
@@ -323,7 +323,7 @@ private:
|
||||
* \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(SliceDataStorage& storage, const SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr);
|
||||
|
||||
/*!
|
||||
* Add a single part from a given layer of a mesh-volume to the layer plan \p gcode_layer.
|
||||
@@ -335,7 +335,7 @@ private:
|
||||
* \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(SliceDataStorage& storage, const SliceMeshStorage* mesh, const SliceLayerPart& part, GCodePlanner& gcode_layer, int layer_nr);
|
||||
|
||||
/*!
|
||||
* Add thicker (multiple layers) sparse infill for a given part in a layer plan.
|
||||
@@ -348,7 +348,7 @@ private:
|
||||
* \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 SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int fillAngle);
|
||||
|
||||
/*!
|
||||
* Add normal sparse infill for a given part in a layer.
|
||||
@@ -360,7 +360,7 @@ private:
|
||||
* \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 SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int fillAngle);
|
||||
|
||||
/*!
|
||||
* Generate the insets for the walls of a given layer part.
|
||||
@@ -371,7 +371,7 @@ private:
|
||||
* \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 SliceLayerPart& part, unsigned int layer_nr, EZSeamType z_seam_type, Point z_seam_pos);
|
||||
|
||||
|
||||
/*!
|
||||
@@ -387,7 +387,7 @@ private:
|
||||
* \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(cura::GCodePlanner& gcode_layer, const cura::SliceMeshStorage* mesh, const cura::SliceLayerPart& part, unsigned int layer_nr, int skin_overlap, int infill_angle);
|
||||
|
||||
/*!
|
||||
* Add the support to the layer plan \p gcodeLayer of the current layer for all support parts with the given \p extruder_nr.
|
||||
|
||||
@@ -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"
|
||||
@@ -23,7 +24,7 @@
|
||||
#include "progress/ProgressEstimator.h"
|
||||
#include "progress/ProgressStageEstimator.h"
|
||||
#include "progress/ProgressEstimatorLinear.h"
|
||||
|
||||
#include "multithreadOpenMP.h"
|
||||
|
||||
namespace cura
|
||||
{
|
||||
@@ -31,6 +32,17 @@ namespace cura
|
||||
|
||||
bool FffPolygonGenerator::generateAreas(SliceDataStorage& storage, MeshGroup* meshgroup, TimeKeeper& timeKeeper)
|
||||
{
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp master
|
||||
{
|
||||
#ifdef _OPENMP
|
||||
log("OpenMP enabled, number of threads used: %u\n", omp_get_num_threads());
|
||||
#else
|
||||
log("OpenMP disabled\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (!sliceModel(meshgroup, timeKeeper, storage))
|
||||
{
|
||||
return false;
|
||||
@@ -345,12 +357,24 @@ void FffPolygonGenerator::processBasicWallsSkinInfill(SliceDataStorage& storage,
|
||||
|
||||
|
||||
// walls
|
||||
for (unsigned int layer_number = 0; layer_number < mesh.layers.size(); layer_number++)
|
||||
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);
|
||||
@@ -381,15 +405,32 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,7 +470,7 @@ void FffPolygonGenerator::processInfillMesh(SliceDataStorage& storage, unsigned
|
||||
if (new_outline.size() == 1)
|
||||
{ // we don't have to call splitIntoParts, because a single polygon can only be a single part
|
||||
PolygonsPart outline_part_here;
|
||||
outline_part_here.add(new_outline[0]);
|
||||
outline_part_here.add(PolygonRef{new_outline[0]});
|
||||
new_parts.push_back(outline_part_here);
|
||||
}
|
||||
else if (new_outline.size() > 1)
|
||||
@@ -486,6 +527,14 @@ 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.
|
||||
*
|
||||
* generateInsets only reads and writes data for the current layer
|
||||
*
|
||||
* 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];
|
||||
@@ -567,8 +616,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)
|
||||
{
|
||||
|
||||
@@ -67,37 +67,37 @@ void GCodePathConfig::setSpeedIconic()
|
||||
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;
|
||||
}
|
||||
|
||||
double GCodePathConfig::getAcceleration()
|
||||
double GCodePathConfig::getAcceleration() const
|
||||
{
|
||||
return current_config.acceleration;
|
||||
}
|
||||
|
||||
double GCodePathConfig::getJerk()
|
||||
double GCodePathConfig::getJerk() const
|
||||
{
|
||||
return current_config.jerk;
|
||||
}
|
||||
|
||||
int GCodePathConfig::getLineWidth()
|
||||
int GCodePathConfig::getLineWidth() const
|
||||
{
|
||||
return current_config.line_width;
|
||||
}
|
||||
|
||||
bool GCodePathConfig::isTravelPath()
|
||||
bool GCodePathConfig::isTravelPath() const
|
||||
{
|
||||
return current_config.line_width == 0;
|
||||
}
|
||||
|
||||
double GCodePathConfig::getFlowPercentage()
|
||||
double GCodePathConfig::getFlowPercentage() const
|
||||
{
|
||||
return current_config.flow;
|
||||
}
|
||||
|
||||
@@ -79,28 +79,28 @@ public:
|
||||
/*!
|
||||
* 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();
|
||||
|
||||
@@ -7,6 +7,31 @@
|
||||
|
||||
namespace cura {
|
||||
|
||||
void issueWriteGCode_impl(
|
||||
GCodeExport* p_gcode,
|
||||
GCodePlanner* p_front_buffer
|
||||
){
|
||||
#pragma omp task default(none) firstprivate(p_gcode, p_front_buffer)
|
||||
{ MULTITHREAD_TASK_CATCH_EXCEPTION(
|
||||
GCodeExport& gcode_ref = *p_gcode;
|
||||
#ifdef _OPENMP
|
||||
omp_lock_guard_t<omp_nest_lock_type> gcode_output_lock_guard(gcode_ref.getOutputStreamLock());
|
||||
#endif
|
||||
p_front_buffer->writeGCode(gcode_ref);
|
||||
if (CommandSocket::isInstantiated())
|
||||
{
|
||||
CommandSocket::getInstance()->flushGcode();
|
||||
}
|
||||
)}
|
||||
}
|
||||
|
||||
void LayerPlanBuffer::issueWriteGCode()
|
||||
{
|
||||
assert(!(buffer.front().isGCodeWritten()) && "GCode shouldn't be written more than once");
|
||||
GCodeExport* p_gcode = &gcode;
|
||||
GCodePlanner* p_front_buffer = &buffer.front();
|
||||
issueWriteGCode_impl(p_gcode, p_front_buffer);
|
||||
}
|
||||
|
||||
|
||||
void LayerPlanBuffer::flush()
|
||||
@@ -15,6 +40,10 @@ void LayerPlanBuffer::flush()
|
||||
{
|
||||
insertTempCommands(); // insert preheat commands of the very last layer
|
||||
}
|
||||
|
||||
#ifdef _OPENMP
|
||||
omp_lock_guard_t<omp_nest_lock_type> gcode_output_lock_guard(gcode.getOutputStreamLock());
|
||||
#endif
|
||||
while (!buffer.empty())
|
||||
{
|
||||
buffer.front().writeGCode(gcode);
|
||||
@@ -30,9 +59,10 @@ void LayerPlanBuffer::flush()
|
||||
void LayerPlanBuffer::insertPreheatCommand(ExtruderPlan& extruder_plan_before, double time_after_extruder_plan_start, int extruder, double temp)
|
||||
{
|
||||
double acc_time = 0.0;
|
||||
for (unsigned int path_idx = extruder_plan_before.paths.size() - 1; int(path_idx) != -1 ; path_idx--)
|
||||
std::vector<GCodePath>& extruder_plan_before_paths = extruder_plan_before.getPaths();
|
||||
for (unsigned int path_idx = extruder_plan_before_paths.size() - 1; int(path_idx) != -1 ; path_idx--)
|
||||
{
|
||||
GCodePath& path = extruder_plan_before.paths[path_idx];
|
||||
GCodePath& path = extruder_plan_before_paths[path_idx];
|
||||
const double time_this_path = path.estimates.getTotalTime();
|
||||
acc_time += time_this_path;
|
||||
if (acc_time > time_after_extruder_plan_start)
|
||||
@@ -195,9 +225,9 @@ void LayerPlanBuffer::insertPrintTempCommand(ExtruderPlan& extruder_plan)
|
||||
if (preheat_config.getInitialPrintTemp(extruder) != 0)
|
||||
{ // handle heating from initial_print_temperature to printing_tempreature
|
||||
unsigned int path_idx;
|
||||
for (path_idx = 0; path_idx < extruder_plan.paths.size(); path_idx++)
|
||||
for (path_idx = 0; path_idx < extruder_plan.getPaths().size(); path_idx++)
|
||||
{
|
||||
GCodePath& path = extruder_plan.paths[path_idx];
|
||||
GCodePath& path = extruder_plan.getPaths()[path_idx];
|
||||
heated_pre_travel_time += path.estimates.getTotalTime();
|
||||
if (!path.isTravelPath())
|
||||
{
|
||||
@@ -224,9 +254,9 @@ void LayerPlanBuffer::insertFinalPrintTempCommand(std::vector<ExtruderPlan*>& ex
|
||||
double heated_post_travel_time = 0; // The time after the last extrude move toward the end of the extruder plan during which the nozzle is stable at the final print temperature
|
||||
{ // compute heated_post_travel_time
|
||||
unsigned int path_idx;
|
||||
for (path_idx = last_extruder_plan.paths.size() - 1; int(path_idx) >= 0; path_idx--)
|
||||
for (path_idx = last_extruder_plan.getPaths().size() - 1; int(path_idx) >= 0; path_idx--)
|
||||
{
|
||||
GCodePath& path = last_extruder_plan.paths[path_idx];
|
||||
GCodePath& path = last_extruder_plan.getPaths()[path_idx];
|
||||
if (!path.isTravelPath())
|
||||
{
|
||||
break;
|
||||
@@ -306,9 +336,9 @@ void LayerPlanBuffer::insertFinalPrintTempCommand(std::vector<ExtruderPlan*>& ex
|
||||
{ // insert temp command in precool_extruder_plan
|
||||
double extrusion_time_seen = 0;
|
||||
unsigned int path_idx;
|
||||
for (path_idx = precool_extruder_plan->paths.size() - 1; int(path_idx) >= 0; path_idx--)
|
||||
for (path_idx = precool_extruder_plan->getPaths().size() - 1; int(path_idx) >= 0; path_idx--)
|
||||
{
|
||||
GCodePath& path = precool_extruder_plan->paths[path_idx];
|
||||
GCodePath& path = precool_extruder_plan->getPaths()[path_idx];
|
||||
extrusion_time_seen += path.estimates.getTotalTime();
|
||||
if (extrusion_time_seen >= cool_down_time)
|
||||
{
|
||||
@@ -324,11 +354,16 @@ 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].getPathsList().empty()))
|
||||
{ // disregard empty layer
|
||||
buffer.pop_back();
|
||||
return;
|
||||
}
|
||||
for (ExtruderPlan& plan: buffer.back().extruder_plans)
|
||||
{
|
||||
plan.convertListToVector();
|
||||
}
|
||||
|
||||
|
||||
std::vector<ExtruderPlan*> extruder_plans;
|
||||
extruder_plans.reserve(buffer.size() * 2);
|
||||
|
||||
+20
-8
@@ -57,28 +57,40 @@ public:
|
||||
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
template<typename... Args>
|
||||
GCodePlanner& emplace_back(Args&&... constructor_args)
|
||||
GCodePlanner& createPlanner(Args&&... constructor_args)
|
||||
{
|
||||
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);
|
||||
if (CommandSocket::isInstantiated())
|
||||
{
|
||||
CommandSocket::getInstance()->flushGcode();
|
||||
}
|
||||
buffer.pop_front();
|
||||
issueWriteGCode();
|
||||
}
|
||||
return buffer.back();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write GCode for the oldest layer plan.
|
||||
*/
|
||||
void issueWriteGCode();
|
||||
|
||||
/*
|
||||
* Pop back the oldest layer plan if it exceeds the buffer size and it has been written to gcode.
|
||||
*/
|
||||
void trimBuffer()
|
||||
{
|
||||
if (buffer.size() > buffer_size)
|
||||
{
|
||||
assert(buffer.front().isGCodeWritten() && "GCode should be written before planner is discarded");
|
||||
buffer.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Write all remaining layer plans (GCodePlanner) to gcode and empty the buffer.
|
||||
*/
|
||||
|
||||
@@ -179,7 +179,6 @@ void PrimeTower::addToGcode_denseInfill(GCodePlanner& gcodeLayer, const int laye
|
||||
|
||||
gcodeLayer.addPolygonsByOptimizer(pattern.polygons, &config);
|
||||
gcodeLayer.addLinesByOptimizer(pattern.lines, &config, SpaceFillType::Lines);
|
||||
|
||||
last_prime_tower_poly_printed[extruder] = layer_nr;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ int SkirtBrim::generatePrimarySkirtBrimLines(SliceDataStorage& storage, int star
|
||||
//Remove small inner skirt and brim holes. Holes have a negative area, remove anything smaller then 100x extrusion "area"
|
||||
for (unsigned int n = 0; n < outer_skirt_brim_line.size(); n++)
|
||||
{
|
||||
double area = outer_skirt_brim_line[n].area();
|
||||
double area = PolygonRef{outer_skirt_brim_line[n]}.area();
|
||||
if (area < 0 && area > -primary_extruder_skirt_brim_line_width * primary_extruder_skirt_brim_line_width * 100)
|
||||
{
|
||||
outer_skirt_brim_line.remove(n--);
|
||||
|
||||
@@ -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++)
|
||||
|
||||
+6
-6
@@ -209,11 +209,11 @@ void Weaver::fillRoofs(Polygons& supporting, Polygons& to_be_supported, int dire
|
||||
std::vector<PolygonsPart> roof_parts = roofs.splitIntoParts();
|
||||
for (PolygonsPart& roof_part : roof_parts)
|
||||
{
|
||||
roof_outlines.add(roof_part[0]);
|
||||
roof_outlines.add(PolygonRef{roof_part[0]});
|
||||
for (unsigned int hole_idx = 1; hole_idx < roof_part.size(); hole_idx++)
|
||||
{
|
||||
roof_holes.add(roof_part[hole_idx]);
|
||||
roof_holes.back().reverse();
|
||||
roof_holes.add(PolygonRef{roof_part[hole_idx]});
|
||||
PolygonRef{roof_holes.back()}.reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,7 +223,7 @@ void Weaver::fillRoofs(Polygons& supporting, Polygons& to_be_supported, int dire
|
||||
|
||||
std::vector<PolygonsPart> supporting_parts = supporting.splitIntoParts();
|
||||
for (PolygonsPart& supporting_part : supporting_parts)
|
||||
supporting_outlines.add(supporting_part[0]); // only add outlines, not the holes
|
||||
supporting_outlines.add(PolygonRef{supporting_part[0]}); // only add outlines, not the holes
|
||||
|
||||
|
||||
|
||||
@@ -274,10 +274,10 @@ void Weaver::fillFloors(Polygons& supporting, Polygons& to_be_supported, int dir
|
||||
Polygons floor_holes;
|
||||
for (PolygonsPart& floor_part : floor_parts)
|
||||
{
|
||||
floor_outlines.add(floor_part[0]);
|
||||
floor_outlines.add(PolygonRef{floor_part[0]});
|
||||
for (unsigned int hole_idx = 1; hole_idx < floor_part.size(); hole_idx++)
|
||||
{
|
||||
floor_holes.add(floor_part[hole_idx]);
|
||||
floor_holes.add(PolygonRef{floor_part[hole_idx]});
|
||||
//floor_holes.back().reverse();
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -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.
|
||||
@@ -29,9 +29,9 @@ int bridgeAngle(Polygons outline, SliceLayer* prevLayer)
|
||||
for(unsigned int n=0; n<islands.size(); n++)
|
||||
{
|
||||
//Skip internal holes
|
||||
if (!islands[n].orientation())
|
||||
if (!PolygonRef{islands[n]}.orientation())
|
||||
continue;
|
||||
double area = fabs(islands[n].area());
|
||||
double area = fabs(PolygonRef{islands[n]}.area());
|
||||
if (area > area1)
|
||||
{
|
||||
if (area1 > area2)
|
||||
@@ -51,8 +51,8 @@ int bridgeAngle(Polygons outline, SliceLayer* prevLayer)
|
||||
if (idx1 < 0 || idx2 < 0)
|
||||
return -1;
|
||||
|
||||
Point center1 = islands[idx1].centerOfMass();
|
||||
Point center2 = islands[idx2].centerOfMass();
|
||||
Point center1 = PolygonRef{islands[idx1]}.centerOfMass();
|
||||
Point center2 = PolygonRef{islands[idx2]}.centerOfMass();
|
||||
|
||||
return angle(center2 - center1);
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
@@ -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())
|
||||
@@ -797,7 +797,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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -775,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
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "MeshGroup.h"
|
||||
#include "commandSocket.h"
|
||||
#include "RetractionConfig.h"
|
||||
#include "multithreadOpenMP.h"
|
||||
|
||||
namespace cura {
|
||||
|
||||
@@ -90,6 +91,9 @@ private:
|
||||
std::string machine_name;
|
||||
|
||||
std::ostream* output_stream;
|
||||
#ifdef _OPENMP
|
||||
omp_nest_lock_type output_stream_lock;
|
||||
#endif
|
||||
std::string new_line;
|
||||
|
||||
double current_e_value; //!< The last E value written to gcode (in mm or mm^3)
|
||||
@@ -177,6 +181,13 @@ public:
|
||||
|
||||
void setOutputStream(std::ostream* stream);
|
||||
|
||||
#ifdef _OPENMP
|
||||
omp_nest_lock_type& getOutputStreamLock()
|
||||
{
|
||||
return output_stream_lock;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool getExtruderIsUsed(const int extruder_nr) const; //!< Returns whether the extruder with the given index is used up until the current meshgroup
|
||||
|
||||
int getNozzleSize(const int extruder_nr) const;
|
||||
|
||||
+42
-24
@@ -11,7 +11,8 @@ 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)
|
||||
: extruder(extruder)
|
||||
: is_paths_vector_initialised(false)
|
||||
, extruder(extruder)
|
||||
, heated_pre_travel_time(0)
|
||||
, initial_printing_temperature(-1)
|
||||
, printing_temperature(-1)
|
||||
@@ -54,11 +55,24 @@ double ExtruderPlan::getFanSpeed()
|
||||
{
|
||||
return fan_speed;
|
||||
}
|
||||
|
||||
|
||||
GCodePath* GCodePlanner::getLatestPathWithConfig(GCodePathConfig* config, SpaceFillType space_fill_type, float flow, bool spiralize)
|
||||
void ExtruderPlan::convertListToVector()
|
||||
{
|
||||
std::vector<GCodePath>& paths = extruder_plans.back().paths;
|
||||
unsigned int number_of_paths = paths_list.size();
|
||||
paths_vector.reserve(number_of_paths);
|
||||
for (auto path : paths_list)
|
||||
{
|
||||
if (path.points.size())
|
||||
{
|
||||
paths_vector.emplace_back(std::move(path));
|
||||
}
|
||||
}
|
||||
is_paths_vector_initialised = true;
|
||||
}
|
||||
|
||||
|
||||
GCodePath* GCodePlanner::getLatestPathWithConfig(const GCodePathConfig* config, SpaceFillType space_fill_type, float flow, bool spiralize)
|
||||
{
|
||||
std::list<GCodePath>& paths = extruder_plans.back().getPathsList();
|
||||
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
|
||||
return &paths.back();
|
||||
paths.emplace_back();
|
||||
@@ -76,9 +90,9 @@ GCodePath* GCodePlanner::getLatestPathWithConfig(GCodePathConfig* config, SpaceF
|
||||
|
||||
void GCodePlanner::forceNewPathStart()
|
||||
{
|
||||
std::vector<GCodePath>& paths = extruder_plans.back().paths;
|
||||
std::list<GCodePath>& paths = extruder_plans.back().getPathsList();
|
||||
if (paths.size() > 0)
|
||||
paths[paths.size()-1].done = true;
|
||||
paths.back().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)
|
||||
@@ -93,6 +107,7 @@ GCodePlanner::GCodePlanner(SliceDataStorage& storage, int layer_nr, int z, int l
|
||||
, last_planned_extruder_setting_base(storage.meshgroup->getExtruderTrain(current_extruder))
|
||||
, comb_boundary_inside(computeCombBoundaryInside(combing_mode))
|
||||
, fan_speed_layer_time_settings_per_extruder(fan_speed_layer_time_settings_per_extruder)
|
||||
, gcode_written(0)
|
||||
{
|
||||
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]);
|
||||
@@ -189,7 +204,7 @@ bool GCodePlanner::setExtruder(int extruder)
|
||||
}
|
||||
addTravel(end_pos); // + extruder_offset cause it
|
||||
}
|
||||
if (extruder_plans.back().paths.empty() && extruder_plans.back().inserts.empty())
|
||||
if (extruder_plans.back().getPathsList().empty() && extruder_plans.back().inserts.empty())
|
||||
{ // first extruder plan in a layer might be empty, cause it is made with the last extruder planned in the previous layer
|
||||
extruder_plans.back().extruder = extruder;
|
||||
}
|
||||
@@ -250,7 +265,7 @@ GCodePath& GCodePlanner::addTravel(Point p)
|
||||
|
||||
const bool perform_z_hops = extr->getSettingBoolean("retraction_hop_enabled");
|
||||
|
||||
const bool is_first_travel_of_extruder_after_switch = extruder_plans.back().paths.size() == 0 && (extruder_plans.size() > 1 || last_extruder_previous_layer != getExtruder());
|
||||
const bool is_first_travel_of_extruder_after_switch = extruder_plans.back().getPathsList().size() == 0 && (extruder_plans.size() > 1 || last_extruder_previous_layer != getExtruder());
|
||||
const bool bypass_combing = is_first_travel_of_extruder_after_switch && extr->getSettingBoolean("retraction_hop_after_extruder_switch");
|
||||
|
||||
if (comb != nullptr && !bypass_combing && lastPosition != no_point)
|
||||
@@ -349,13 +364,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 +383,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 +418,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 +435,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 +445,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)
|
||||
{
|
||||
@@ -458,7 +473,7 @@ void ExtruderPlan::forceMinimalLayerTime(double minTime, double minimalSpeed, do
|
||||
if (minExtrudeTime < 1)
|
||||
minExtrudeTime = 1;
|
||||
double factor = extrudeTime / minExtrudeTime;
|
||||
for (GCodePath& path : paths)
|
||||
for (GCodePath& path : getPathsList())
|
||||
{
|
||||
if (path.isTravelPath())
|
||||
continue;
|
||||
@@ -482,7 +497,7 @@ void ExtruderPlan::forceMinimalLayerTime(double minTime, double minimalSpeed, do
|
||||
|
||||
// Adjust stored naive time estimates
|
||||
estimates.extrude_time *= inv_factor;
|
||||
for (GCodePath& path : paths)
|
||||
for (GCodePath& path : getPathsList())
|
||||
{
|
||||
path.estimates.extrude_time *= inv_factor;
|
||||
}
|
||||
@@ -500,7 +515,7 @@ TimeMaterialEstimates ExtruderPlan::computeNaiveTimeEstimates()
|
||||
Point p0 = start_position;
|
||||
|
||||
bool was_retracted = false; // wrong assumption; won't matter that much. (TODO)
|
||||
for (GCodePath& path : paths)
|
||||
for (GCodePath& path : getPathsList())
|
||||
{
|
||||
bool is_extrusion_path = false;
|
||||
double* path_time_estimate;
|
||||
@@ -653,7 +668,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");
|
||||
@@ -702,7 +717,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
|
||||
gcode.writeRetraction(retraction_config);
|
||||
}
|
||||
gcode.writeFanCommand(extruder_plan.getFanSpeed());
|
||||
std::vector<GCodePath>& paths = extruder_plan.paths;
|
||||
std::vector<GCodePath>& paths = extruder_plan.getPaths();
|
||||
|
||||
extruder_plan.inserts.sort([](const NozzleTempInsert& a, const NozzleTempInsert& b) -> bool {
|
||||
return a.path_idx < b.path_idx;
|
||||
@@ -875,6 +890,9 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
|
||||
} // extruder plans /\ .
|
||||
|
||||
gcode.updateTotalPrintTime();
|
||||
#pragma omp flush
|
||||
#pragma omp atomic update
|
||||
++gcode_written;
|
||||
}
|
||||
|
||||
void GCodePlanner::overrideFanSpeeds(double speed)
|
||||
@@ -991,7 +1009,7 @@ void GCodePlanner::processInitialLayersSpeedup()
|
||||
|
||||
bool GCodePlanner::makeRetractSwitchRetract(GCodeExport& gcode, unsigned int extruder_plan_idx, unsigned int path_idx)
|
||||
{
|
||||
std::vector<GCodePath>& paths = extruder_plans[extruder_plan_idx].paths;
|
||||
std::vector<GCodePath>& paths = extruder_plans[extruder_plan_idx].getPaths();
|
||||
for (unsigned int path_idx2 = path_idx + 1; path_idx2 < paths.size(); path_idx2++)
|
||||
{
|
||||
if (paths[path_idx2].getExtrusionMM3perMM() > 0)
|
||||
@@ -1022,7 +1040,7 @@ bool GCodePlanner::writePathWithCoasting(GCodeExport& gcode, unsigned int extrud
|
||||
return false;
|
||||
}
|
||||
ExtruderPlan& extruder_plan = extruder_plans[extruder_plan_idx];
|
||||
std::vector<GCodePath>& paths = extruder_plan.paths;
|
||||
std::vector<GCodePath>& paths = extruder_plan.getPaths();
|
||||
GCodePath& path = paths[path_idx];
|
||||
if (path_idx + 1 >= paths.size()
|
||||
||
|
||||
|
||||
+55
-8
@@ -37,9 +37,12 @@ class ExtruderPlan
|
||||
friend class GCodePlanner; // TODO: GCodePlanner still does a lot which should actually be handled in this class.
|
||||
friend class LayerPlanBuffer; // TODO: LayerPlanBuffer handles paths directly
|
||||
protected:
|
||||
std::vector<GCodePath> paths; //!< The paths planned for this extruder
|
||||
std::list<GCodePath> paths_list; //!< The paths planned for this extruder
|
||||
std::vector<GCodePath> paths_vector; //!< The paths planned for this extruder
|
||||
std::list<NozzleTempInsert> inserts; //!< The nozzle temperature command inserts, to be inserted in between paths
|
||||
|
||||
bool is_paths_vector_initialised; //!< Keeps information if content of \p paths_list has been copied to \p paths_vector
|
||||
|
||||
int extruder; //!< The extruder used for this paths in the current plan.
|
||||
double heated_pre_travel_time; //!< The time at the start of this ExtruderPlan during which the head travels and has a temperature of initial_print_temperature
|
||||
double initial_printing_temperature; //!< The required temperature at the start of this extruder plan.
|
||||
@@ -101,7 +104,7 @@ public:
|
||||
while ( ! inserts.empty() )
|
||||
{ // handle the Insert to be inserted before this path_idx (and all inserts not handled yet)
|
||||
NozzleTempInsert& insert = inserts.front();
|
||||
assert(insert.path_idx == paths.size());
|
||||
assert(insert.path_idx == getPaths().size());
|
||||
insert.write(gcode);
|
||||
inserts.pop_front();
|
||||
}
|
||||
@@ -156,6 +159,39 @@ public:
|
||||
* \return The fan speed computed in processFanSpeedAndMinimalLayerTime
|
||||
*/
|
||||
double getFanSpeed();
|
||||
|
||||
/*!
|
||||
* Move the paths data from the input list to the vector container
|
||||
*
|
||||
* \warning empties the \p paths_list which will no longer contain data. No references to the paths in \p paths_list should be kept.
|
||||
*/
|
||||
void convertListToVector();
|
||||
|
||||
/*!
|
||||
* Get the paths in a list container
|
||||
*
|
||||
* \warning should not be called after paths_list has been converted to paths variable
|
||||
*
|
||||
* \return The paths as a list
|
||||
*/
|
||||
std::list<GCodePath>& getPathsList()
|
||||
{
|
||||
assert(!is_paths_vector_initialised);
|
||||
return paths_list;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get the paths in a vector container
|
||||
*
|
||||
* \warning should not be called before paths_list has been converted to paths variable
|
||||
*
|
||||
* \return The paths as a vector
|
||||
*/
|
||||
std::vector<GCodePath>& getPaths()
|
||||
{
|
||||
assert(is_paths_vector_initialised);
|
||||
return paths_vector;
|
||||
}
|
||||
protected:
|
||||
|
||||
Point start_position; //!< The position the print head was at at the start of this extruder plan
|
||||
@@ -240,6 +276,8 @@ private:
|
||||
|
||||
std::vector<FanSpeedLayerTimeSettings>& fan_speed_layer_time_settings_per_extruder;
|
||||
|
||||
int gcode_written;
|
||||
|
||||
private:
|
||||
/*!
|
||||
* Either create a new path with the given config or return the last path if it already had that config.
|
||||
@@ -251,7 +289,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:
|
||||
/*!
|
||||
@@ -377,7 +415,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 +426,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 +445,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 +454,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,7 +472,16 @@ public:
|
||||
* \param gcode The gcode to write the planned paths to
|
||||
*/
|
||||
void writeGCode(GCodeExport& gcode);
|
||||
|
||||
/*!
|
||||
* Has the planned paths been written to gcode
|
||||
*/
|
||||
int isGCodeWritten()
|
||||
{
|
||||
int gcode_written_tmp;
|
||||
#pragma omp atomic read
|
||||
gcode_written_tmp = gcode_written;
|
||||
return gcode_written_tmp;
|
||||
}
|
||||
/*!
|
||||
* Complete all GcodePathConfigs by
|
||||
* - altering speeds to conform to speed_print_layer_0 and
|
||||
|
||||
+2
-2
@@ -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
@@ -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
|
||||
|
||||
+11
-5
@@ -3,6 +3,7 @@
|
||||
#include "layerPart.h"
|
||||
#include "settings/settings.h"
|
||||
#include "progress/Progress.h"
|
||||
#include "multithreadOpenMP.h"
|
||||
|
||||
#include "utils/SVG.h" // debug output
|
||||
|
||||
@@ -28,8 +29,8 @@ void createLayerWithParts(SliceLayer& storageLayer, SlicerLayer* layer, bool uni
|
||||
{
|
||||
for(unsigned int i=0; i<layer->polygons.size(); i++)
|
||||
{
|
||||
if (layer->polygons[i].orientation())
|
||||
layer->polygons[i].reverse();
|
||||
if (PolygonRef{layer->polygons[i]}.orientation())
|
||||
PolygonRef{layer->polygons[i]}.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,12 +45,17 @@ 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();
|
||||
// mesh.layers.resize(total_layers); TODO: put this back?
|
||||
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++)
|
||||
{ MULTITHREAD_FOR_CATCH_EXCEPTION(
|
||||
mesh.layers[layer_nr].sliceZ = slicer->layers[layer_nr].z;
|
||||
mesh.layers[layer_nr].printZ = slicer->layers[layer_nr].z;
|
||||
createLayerWithParts(mesh.layers[layer_nr], &slicer->layers[layer_nr], union_layers, union_all_remove_holes);
|
||||
}
|
||||
)}
|
||||
handleMultithreadAbort();
|
||||
}
|
||||
|
||||
void layerparts2HTML(SliceDataStorage& storage, const char* filename, bool all_layers, int layer_nr)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/** Copyright (C) 2016 Ultimaker - Released under terms of the AGPLv3 License */
|
||||
|
||||
#include "multithreadOpenMP.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace cura
|
||||
{
|
||||
|
||||
bool abort_execution = false;
|
||||
|
||||
#ifdef _OPENMP
|
||||
void handleMultithreadAbort()
|
||||
{
|
||||
if (checkMultithreadAbort())
|
||||
{
|
||||
std::exit(17);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}//namespace cura
|
||||
@@ -0,0 +1,182 @@
|
||||
/** Copyright (C) 2016 Ultimaker - Released under terms of the AGPLv3 License */
|
||||
|
||||
#ifndef MULTITHREAD_OPENMP_H
|
||||
#define MULTITHREAD_OPENMP_H
|
||||
|
||||
#include <omp.h>
|
||||
|
||||
namespace cura
|
||||
{
|
||||
|
||||
// TODO: remove
|
||||
extern bool abort_execution;
|
||||
|
||||
#ifdef _OPENMP
|
||||
|
||||
class omp_lock_type
|
||||
{
|
||||
public:
|
||||
omp_lock_type()
|
||||
{
|
||||
omp_init_lock(&lock_object);
|
||||
}
|
||||
~omp_lock_type()
|
||||
{
|
||||
omp_destroy_lock(&lock_object);
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
omp_set_lock(&lock_object);
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
omp_unset_lock(&lock_object);
|
||||
}
|
||||
int test_lock()
|
||||
{
|
||||
return omp_test_lock(&lock_object);
|
||||
}
|
||||
private:
|
||||
omp_lock_t lock_object;
|
||||
omp_lock_type( const omp_lock_type& ) = delete;
|
||||
omp_lock_type& operator=( const omp_lock_type& ) = delete;
|
||||
};
|
||||
|
||||
class omp_nest_lock_type
|
||||
{
|
||||
public:
|
||||
omp_nest_lock_type()
|
||||
{
|
||||
omp_init_nest_lock(&lock_object);
|
||||
}
|
||||
~omp_nest_lock_type()
|
||||
{
|
||||
omp_destroy_nest_lock(&lock_object);
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
omp_set_nest_lock(&lock_object);
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
omp_unset_nest_lock(&lock_object);
|
||||
}
|
||||
int test_lock()
|
||||
{
|
||||
return omp_test_nest_lock(&lock_object);
|
||||
}
|
||||
private:
|
||||
omp_nest_lock_t lock_object;
|
||||
omp_nest_lock_type( const omp_nest_lock_type& ) = delete;
|
||||
omp_nest_lock_type& operator=( const omp_nest_lock_type& ) = delete;
|
||||
};
|
||||
|
||||
template <typename LockType>
|
||||
class omp_try_lock_guard_t
|
||||
{
|
||||
public:
|
||||
omp_try_lock_guard_t( LockType& lock_)
|
||||
: lock(lock_)
|
||||
{
|
||||
has_lock = lock.test_lock();
|
||||
}
|
||||
~omp_try_lock_guard_t()
|
||||
{
|
||||
if (has_lock)
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
int isLocked()
|
||||
{
|
||||
return has_lock;
|
||||
}
|
||||
private:
|
||||
LockType& lock;
|
||||
int has_lock;
|
||||
omp_try_lock_guard_t( const omp_try_lock_guard_t& ) = delete;
|
||||
omp_try_lock_guard_t<LockType>& operator=( const omp_try_lock_guard_t& ) = delete;
|
||||
};
|
||||
|
||||
template <typename LockType>
|
||||
class omp_lock_guard_t
|
||||
{
|
||||
public:
|
||||
omp_lock_guard_t( LockType& lock_)
|
||||
: lock(lock_)
|
||||
{
|
||||
lock.lock();
|
||||
}
|
||||
~omp_lock_guard_t()
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
private:
|
||||
LockType& lock;
|
||||
omp_lock_guard_t( const omp_lock_guard_t& ) = delete;
|
||||
omp_lock_guard_t& operator=( const omp_lock_guard_t& ) = delete;
|
||||
};
|
||||
#endif
|
||||
|
||||
// TODO: remove
|
||||
inline bool checkMultithreadAbort()
|
||||
{
|
||||
bool tmp_abort_execution;
|
||||
#pragma omp atomic read
|
||||
tmp_abort_execution = abort_execution;
|
||||
return tmp_abort_execution;
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
inline void setMultithreadAbort()
|
||||
{
|
||||
#pragma omp atomic write
|
||||
abort_execution = true;
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
#ifdef _OPENMP
|
||||
void handleMultithreadAbort();
|
||||
#else
|
||||
inline void handleMultithreadAbort(){}
|
||||
#endif
|
||||
|
||||
// TODO: remove old code below
|
||||
#ifdef _OPENMP
|
||||
#define MULTITHREAD_FOR_CATCH_EXCEPTION(code) \
|
||||
if (checkMultithreadAbort()) \
|
||||
{ \
|
||||
continue; \
|
||||
} \
|
||||
try \
|
||||
{ \
|
||||
code \
|
||||
} \
|
||||
catch (...) \
|
||||
{ \
|
||||
setMultithreadAbort(); \
|
||||
}
|
||||
#else
|
||||
#define MULTITHREAD_FOR_CATCH_EXCEPTION(code) code
|
||||
#endif
|
||||
|
||||
#ifdef _OPENMP
|
||||
#define MULTITHREAD_TASK_CATCH_EXCEPTION(code) \
|
||||
if (!checkMultithreadAbort()) \
|
||||
{ \
|
||||
try \
|
||||
{ \
|
||||
code \
|
||||
} \
|
||||
catch (...) \
|
||||
{ \
|
||||
setMultithreadAbort(); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define MULTITHREAD_TASK_CATCH_EXCEPTION(code) code
|
||||
#endif
|
||||
|
||||
}//namespace cura
|
||||
|
||||
#endif // MULTITHREAD_OPENMP_H
|
||||
@@ -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
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -332,7 +332,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;
|
||||
|
||||
@@ -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,7 +97,7 @@ 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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
+28
-2
@@ -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];
|
||||
@@ -106,7 +121,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 +159,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];
|
||||
|
||||
@@ -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,
|
||||
@@ -163,7 +163,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 +207,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));
|
||||
}
|
||||
|
||||
+21
-15
@@ -8,6 +8,7 @@
|
||||
#include "utils/SparsePointGridInclusive.h"
|
||||
|
||||
#include "slicer.h"
|
||||
#include "multithreadOpenMP.h"
|
||||
|
||||
|
||||
namespace cura {
|
||||
@@ -216,7 +217,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 +232,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 +246,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;
|
||||
|
||||
@@ -589,7 +590,7 @@ void SlicerLayer::stitch_extensive(Polygons& open_polylines)
|
||||
{
|
||||
if (best_result.pointIdxA == best_result.pointIdxB)
|
||||
{
|
||||
polygons.add(open_polylines[best_polyline_1_idx]);
|
||||
polygons.add(PolygonRef{open_polylines[best_polyline_1_idx]});
|
||||
open_polylines[best_polyline_1_idx].clear();
|
||||
}
|
||||
else if (best_result.AtoB)
|
||||
@@ -604,9 +605,9 @@ void SlicerLayer::stitch_extensive(Polygons& open_polylines)
|
||||
else
|
||||
{
|
||||
unsigned int n = polygons.size();
|
||||
polygons.add(open_polylines[best_polyline_1_idx]);
|
||||
polygons.add(PolygonRef{open_polylines[best_polyline_1_idx]});
|
||||
for(unsigned int j = best_result.pointIdxB; j != best_result.pointIdxA; j = (j + 1) % polygons[best_result.polygonIdx].size())
|
||||
polygons[n].add(polygons[best_result.polygonIdx][j]);
|
||||
PolygonRef{polygons[n]}.add(polygons[best_result.polygonIdx][j]);
|
||||
open_polylines[best_polyline_1_idx].clear();
|
||||
}
|
||||
}
|
||||
@@ -615,7 +616,7 @@ void SlicerLayer::stitch_extensive(Polygons& open_polylines)
|
||||
if (best_result.pointIdxA == best_result.pointIdxB)
|
||||
{
|
||||
for(unsigned int n=0; n<open_polylines[best_polyline_1_idx].size(); n++)
|
||||
open_polylines[best_polyline_2_idx].add(open_polylines[best_polyline_1_idx][n]);
|
||||
PolygonRef{open_polylines[best_polyline_2_idx]}.add(open_polylines[best_polyline_1_idx][n]);
|
||||
open_polylines[best_polyline_1_idx].clear();
|
||||
}
|
||||
else if (best_result.AtoB)
|
||||
@@ -624,17 +625,17 @@ void SlicerLayer::stitch_extensive(Polygons& open_polylines)
|
||||
for(unsigned int n = best_result.pointIdxA; n != best_result.pointIdxB; n = (n + 1) % polygons[best_result.polygonIdx].size())
|
||||
poly.add(polygons[best_result.polygonIdx][n]);
|
||||
for(unsigned int n=poly.size()-1;int(n) >= 0; n--)
|
||||
open_polylines[best_polyline_2_idx].add(poly[n]);
|
||||
PolygonRef{open_polylines[best_polyline_2_idx]}.add(poly[n]);
|
||||
for(unsigned int n=0; n<open_polylines[best_polyline_1_idx].size(); n++)
|
||||
open_polylines[best_polyline_2_idx].add(open_polylines[best_polyline_1_idx][n]);
|
||||
PolygonRef{open_polylines[best_polyline_2_idx]}.add(open_polylines[best_polyline_1_idx][n]);
|
||||
open_polylines[best_polyline_1_idx].clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
for(unsigned int n = best_result.pointIdxB; n != best_result.pointIdxA; n = (n + 1) % polygons[best_result.polygonIdx].size())
|
||||
open_polylines[best_polyline_2_idx].add(polygons[best_result.polygonIdx][n]);
|
||||
PolygonRef{open_polylines[best_polyline_2_idx]}.add(polygons[best_result.polygonIdx][n]);
|
||||
for(unsigned int n = open_polylines[best_polyline_1_idx].size() - 1; int(n) >= 0; n--)
|
||||
open_polylines[best_polyline_2_idx].add(open_polylines[best_polyline_1_idx][n]);
|
||||
PolygonRef{open_polylines[best_polyline_2_idx]}.add(open_polylines[best_polyline_1_idx][n]);
|
||||
open_polylines[best_polyline_1_idx].clear();
|
||||
}
|
||||
}
|
||||
@@ -887,10 +888,15 @@ 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++)
|
||||
{
|
||||
layers[layer_nr].makePolygons(mesh, keep_none_closed, extensive_stitching);
|
||||
}
|
||||
|
||||
auto& layers_ref = layers;
|
||||
#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++)
|
||||
{ MULTITHREAD_FOR_CATCH_EXCEPTION(
|
||||
layers_ref[layer_nr].makePolygons(mesh, keep_none_closed, extensive_stitching);
|
||||
)}
|
||||
handleMultithreadAbort();
|
||||
|
||||
mesh->expandXY(mesh->getSettingInMicrons("xy_offset"));
|
||||
log("slice make polygons took %.3f seconds\n",slice_timer.restart());
|
||||
}
|
||||
|
||||
+1
-1
@@ -508,7 +508,7 @@ void AreaSupport::handleTowers(
|
||||
{
|
||||
supportLayer_this = supportLayer_this.unionPolygons(tower_roof);
|
||||
|
||||
if (tower_roof[0].area() < supportTowerDiameter * supportTowerDiameter)
|
||||
if (PolygonRef{tower_roof[0]}.area() < supportTowerDiameter * supportTowerDiameter)
|
||||
{
|
||||
tower_roof = tower_roof.offset(towerRoofExpansionDistance);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ AABB::AABB(const Polygons& polys)
|
||||
calculate(polys);
|
||||
}
|
||||
|
||||
AABB::AABB(const PolygonRef poly)
|
||||
AABB::AABB(const PolygonRef& 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(const PolygonRef& poly)
|
||||
{
|
||||
min = Point(POINT_MAX, POINT_MAX);
|
||||
max = Point(POINT_MIN, POINT_MIN);
|
||||
|
||||
+2
-2
@@ -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(const PolygonRef& 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(const PolygonRef& 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.
|
||||
|
||||
@@ -19,12 +19,12 @@ void ListPolyIt::convertPolygonsToLists(Polygons& polys, ListPolygons& result)
|
||||
}
|
||||
}
|
||||
|
||||
void ListPolyIt::convertPolygonToList(PolygonRef poly, ListPolygon& result)
|
||||
void ListPolyIt::convertPolygonToList(const PolygonRef& 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
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
* \param polys The polygons to convert
|
||||
* \param result The converted polygons
|
||||
*/
|
||||
static void convertPolygonToList(PolygonRef poly, ListPolygon& result);
|
||||
static void convertPolygonToList(const PolygonRef& poly, ListPolygon& result);
|
||||
/*!
|
||||
* Convert ListPolygons to Polygons
|
||||
*
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
/*!
|
||||
* Get the polygon to which this PolygonsPointIndex refers
|
||||
*/
|
||||
const PolygonRef getPolygon() const
|
||||
const ConstPolygonRef getPolygon() const
|
||||
{
|
||||
return (*polygons)[poly_idx];
|
||||
}
|
||||
|
||||
+5
-5
@@ -93,7 +93,7 @@ public:
|
||||
{
|
||||
for(unsigned int j=0;j<parts.size();j++)
|
||||
{
|
||||
Polygon poly = parts[j];
|
||||
Polygon poly = PolygonRef{parts[j]};
|
||||
fprintf(out, "<polygon points=\"");
|
||||
for(Point& p : poly)
|
||||
{
|
||||
@@ -130,9 +130,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 +209,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)
|
||||
|
||||
+68
-31
@@ -8,6 +8,23 @@
|
||||
namespace cura
|
||||
{
|
||||
|
||||
/*
|
||||
* Implementation of offset polygon used by PolygonRef and ConstPolygonRef
|
||||
*
|
||||
* \param ret_paths[out] where the offset polygon is stored.
|
||||
* \param path the path to be offset.
|
||||
* \param distance the distance to offset path.
|
||||
* \param joinType See ClipperLib documentation.
|
||||
* \param miter_limit See ClipperLib documentation.
|
||||
*/
|
||||
inline void PolygonRef_offset_impl(ClipperLib::Paths& ret_path, const ClipperLib::Path& path, int distance, ClipperLib::JoinType join_type, double miter_limit)
|
||||
{
|
||||
ClipperLib::ClipperOffset clipper(miter_limit, 10.0);
|
||||
clipper.AddPath(path, join_type, ClipperLib::etClosedPolygon);
|
||||
clipper.MiterLimit = miter_limit;
|
||||
clipper.Execute(ret_path, distance);
|
||||
}
|
||||
|
||||
bool PolygonRef::shorterThan(int64_t check_length) const
|
||||
{
|
||||
const PolygonRef& polygon = *this;
|
||||
@@ -27,7 +44,7 @@ bool PolygonRef::shorterThan(int64_t check_length) const
|
||||
|
||||
bool PolygonRef::_inside(Point p, bool border_result) const
|
||||
{
|
||||
PolygonRef thiss = *this;
|
||||
const PolygonRef& thiss = *this;
|
||||
if (size() < 1)
|
||||
{
|
||||
return false;
|
||||
@@ -203,10 +220,7 @@ Polygons Polygons::offset(int distance, ClipperLib::JoinType join_type, double m
|
||||
Polygons PolygonRef::offset(int distance, ClipperLib::JoinType joinType, double miter_limit) const
|
||||
{
|
||||
Polygons ret;
|
||||
ClipperLib::ClipperOffset clipper(miter_limit, 10.0);
|
||||
clipper.AddPath(*path, joinType, ClipperLib::etClosedPolygon);
|
||||
clipper.MiterLimit = miter_limit;
|
||||
clipper.Execute(ret.paths, distance);
|
||||
PolygonRef_offset_impl(ret.paths, *path, distance, joinType, miter_limit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -952,7 +966,7 @@ Polygons Polygons::smooth_outward(float max_angle, int shortcut_length)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PolygonRef::smooth(int remove_length, PolygonRef result)
|
||||
inline void PolygonRef_smooth_impl(const ClipperLib::Path& thiss, int remove_length, ClipperLib::Path* poly)
|
||||
{
|
||||
// a typical zigzag with the middle part to be removed by removing (1) :
|
||||
//
|
||||
@@ -967,9 +981,7 @@ void PolygonRef::smooth(int remove_length, PolygonRef result)
|
||||
// |
|
||||
// |
|
||||
// 0
|
||||
PolygonRef& thiss = *this;
|
||||
ClipperLib::Path* poly = result.path;
|
||||
if (size() > 0)
|
||||
if (thiss.size() > 0)
|
||||
{
|
||||
poly->push_back(thiss[0]);
|
||||
}
|
||||
@@ -1003,11 +1015,11 @@ void PolygonRef::smooth(int remove_length, PolygonRef result)
|
||||
Point v02T = turn90CCW(v02);
|
||||
int64_t v02_size = vSize(v02);
|
||||
bool force_push = false;
|
||||
for (unsigned int poly_idx = 1; poly_idx < size(); poly_idx++)
|
||||
for (unsigned int poly_idx = 1; poly_idx < thiss.size(); poly_idx++)
|
||||
{
|
||||
const Point& p1 = thiss[poly_idx];
|
||||
const Point& p2 = thiss[(poly_idx + 1) % size()];
|
||||
const Point& p3 = thiss[(poly_idx + 2) % size()];
|
||||
const Point& p2 = thiss[(poly_idx + 1) % thiss.size()];
|
||||
const Point& p3 = thiss[(poly_idx + 2) % thiss.size()];
|
||||
// v02 computed in last iteration
|
||||
// v02_size as well
|
||||
const Point v12 = p2 - p1;
|
||||
@@ -1036,12 +1048,22 @@ void PolygonRef::smooth(int remove_length, PolygonRef result)
|
||||
}
|
||||
}
|
||||
|
||||
Polygons Polygons::smooth(int remove_length)
|
||||
void PolygonRef::smooth(int remove_length, PolygonRef result) const
|
||||
{
|
||||
PolygonRef_smooth_impl(*path, remove_length, result.path);
|
||||
}
|
||||
|
||||
void ConstPolygonRef::smooth(int remove_length, PolygonRef result) const
|
||||
{
|
||||
PolygonRef_smooth_impl(*path, remove_length, &(*result));
|
||||
}
|
||||
|
||||
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 +1083,21 @@ Polygons Polygons::smooth(int remove_length)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PolygonRef::smooth2(int remove_length, PolygonRef result)
|
||||
inline void PolygonRef_smooth2_impl(const ClipperLib::Path& thiss, int remove_length, ClipperLib::Path* poly)
|
||||
{
|
||||
PolygonRef& 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 +1109,22 @@ void PolygonRef::smooth2(int remove_length, PolygonRef result)
|
||||
}
|
||||
}
|
||||
|
||||
Polygons Polygons::smooth2(int remove_length, int min_area)
|
||||
void PolygonRef::smooth2(int remove_length, PolygonRef result) const
|
||||
{
|
||||
PolygonRef_smooth2_impl(*path, remove_length, result.path);
|
||||
}
|
||||
|
||||
void ConstPolygonRef::smooth2(int remove_length, PolygonRef result) const
|
||||
{
|
||||
PolygonRef_smooth2_impl(*path, remove_length, &(*result));
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -1116,6 +1146,13 @@ Polygons Polygons::smooth2(int remove_length, int min_area)
|
||||
return ret;
|
||||
}
|
||||
|
||||
Polygons ConstPolygonRef::offset(int distance, ClipperLib::JoinType joinType, double miter_limit) const
|
||||
{
|
||||
Polygons ret;
|
||||
PolygonRef_offset_impl(ret.paths, *path, distance, joinType, miter_limit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<PolygonsPart> Polygons::splitIntoParts(bool unionAll) const
|
||||
{
|
||||
std::vector<PolygonsPart> ret;
|
||||
@@ -1137,10 +1174,10 @@ void Polygons::splitIntoParts_processPolyTreeNode(ClipperLib::PolyNode* node, st
|
||||
{
|
||||
ClipperLib::PolyNode* child = node->Childs[n];
|
||||
PolygonsPart part;
|
||||
part.add(child->Contour);
|
||||
part.add(ConstPolygonRef{child->Contour});
|
||||
for(int i=0; i<child->ChildCount(); i++)
|
||||
{
|
||||
part.add(child->Childs[i]->Contour);
|
||||
part.add(ConstPolygonRef{child->Childs[i]->Contour});
|
||||
splitIntoParts_processPolyTreeNode(child->Childs[i], ret);
|
||||
}
|
||||
ret.push_back(part);
|
||||
@@ -1172,7 +1209,7 @@ PolygonsPart PartsView::assemblePart(unsigned int part_idx) const
|
||||
{
|
||||
for (unsigned int poly_idx_ff : partsView[part_idx])
|
||||
{
|
||||
ret.add(polygons[poly_idx_ff]);
|
||||
ret.add(PolygonRef{polygons[poly_idx_ff]});
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -1215,11 +1252,11 @@ 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(ConstPolygonRef{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());
|
||||
reordered.add(child->Childs[i]->Contour);
|
||||
reordered.add(ConstPolygonRef{child->Childs[i]->Contour});
|
||||
splitIntoPartsView_processPolyTreeNode(partsView, reordered, child->Childs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
+227
-24
@@ -43,6 +43,12 @@ class PolygonRef
|
||||
: path(nullptr)
|
||||
{}
|
||||
public:
|
||||
PolygonRef(PolygonRef& polygon)
|
||||
:path{polygon.path}
|
||||
{}
|
||||
PolygonRef(PolygonRef&& polygon)
|
||||
:path{polygon.path}
|
||||
{}
|
||||
PolygonRef(ClipperLib::Path& polygon)
|
||||
: path(&polygon)
|
||||
{}
|
||||
@@ -78,7 +84,9 @@ public:
|
||||
bool operator==(const PolygonRef& other) const =delete;
|
||||
|
||||
ClipperLib::Path& operator*() { return *path; }
|
||||
|
||||
|
||||
const ClipperLib::Path& operator*() const { return *path; }
|
||||
|
||||
template <typename... Args>
|
||||
void emplace_back(Args&&... args)
|
||||
{
|
||||
@@ -190,7 +198,7 @@ public:
|
||||
return Point(x, y);
|
||||
}
|
||||
|
||||
Point closestPointTo(Point p)
|
||||
Point closestPointTo(Point p) const
|
||||
{
|
||||
Point ret = p;
|
||||
float bestDist = FLT_MAX;
|
||||
@@ -253,7 +261,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,7 +279,7 @@ 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.
|
||||
@@ -375,6 +383,193 @@ 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 ConstPolygonRef
|
||||
{
|
||||
const ClipperLib::Path* path;
|
||||
ConstPolygonRef()
|
||||
: path(nullptr)
|
||||
{}
|
||||
public:
|
||||
ConstPolygonRef(const ClipperLib::Path& polygon)
|
||||
: path(&polygon)
|
||||
{}
|
||||
ConstPolygonRef(const PolygonRef& polygon)
|
||||
: path(&(*polygon))
|
||||
{}
|
||||
|
||||
unsigned int size() const
|
||||
{
|
||||
return path->size();
|
||||
}
|
||||
|
||||
const Point& operator[] (unsigned int index) const
|
||||
{
|
||||
POLY_ASSERT(index < size());
|
||||
return (*path)[index];
|
||||
}
|
||||
|
||||
const void* data() const
|
||||
{
|
||||
return path->data();
|
||||
}
|
||||
|
||||
ConstPolygonRef& operator=(const ConstPolygonRef& other) { path = other.path; return *this; }
|
||||
|
||||
ConstPolygonRef& operator=(const PolygonRef& other) { path = &(*other); return *this; }
|
||||
|
||||
bool operator==(const ConstPolygonRef& other) const =delete;
|
||||
|
||||
const ClipperLib::Path& operator*() const { return *path; }
|
||||
|
||||
/*!
|
||||
* 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
|
||||
{
|
||||
return ClipperLib::Orientation(*path);
|
||||
}
|
||||
|
||||
Polygons offset(int distance, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miter_limit = 1.2) const;
|
||||
|
||||
int64_t polygonLength() const
|
||||
{
|
||||
int64_t length = 0;
|
||||
Point p0 = (*path)[path->size()-1];
|
||||
for(unsigned int n=0; n<path->size(); n++)
|
||||
{
|
||||
Point p1 = (*path)[n];
|
||||
length += vSize(p0 - p1);
|
||||
p0 = p1;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
bool shorterThan(int64_t check_length) const;
|
||||
|
||||
Point min() const
|
||||
{
|
||||
Point ret = Point(POINT_MAX, POINT_MAX);
|
||||
for(Point p : *path)
|
||||
{
|
||||
ret.X = std::min(ret.X, p.X);
|
||||
ret.Y = std::min(ret.Y, p.Y);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Point max() const
|
||||
{
|
||||
Point ret = Point(POINT_MIN, POINT_MIN);
|
||||
for(Point p : *path)
|
||||
{
|
||||
ret.X = std::max(ret.X, p.X);
|
||||
ret.Y = std::max(ret.Y, p.Y);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
double area() const
|
||||
{
|
||||
return ClipperLib::Area(*path);
|
||||
}
|
||||
|
||||
Point centerOfMass() const
|
||||
{
|
||||
double x = 0, y = 0;
|
||||
Point p0 = (*path)[path->size()-1];
|
||||
for(unsigned int n=0; n<path->size(); n++)
|
||||
{
|
||||
Point p1 = (*path)[n];
|
||||
double second_factor = (p0.X * p1.Y) - (p1.X * p0.Y);
|
||||
|
||||
x += double(p0.X + p1.X) * second_factor;
|
||||
y += double(p0.Y + p1.Y) * second_factor;
|
||||
p0 = p1;
|
||||
}
|
||||
|
||||
double area = Area(*path);
|
||||
|
||||
x = x / 6 / area;
|
||||
y = y / 6 / area;
|
||||
|
||||
return Point(x, y);
|
||||
}
|
||||
|
||||
Point closestPointTo(Point p) const
|
||||
{
|
||||
Point ret = p;
|
||||
float bestDist = FLT_MAX;
|
||||
for(unsigned int n=0; n<path->size(); n++)
|
||||
{
|
||||
float dist = vSize2f(p - (*path)[n]);
|
||||
if (dist < bestDist)
|
||||
{
|
||||
ret = (*path)[n];
|
||||
bestDist = dist;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Clipper function.
|
||||
* Returns false if outside, true if inside; if the point lies exactly on the border, will return 'border_result'.
|
||||
*
|
||||
* http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Functions/PointInPolygon.htm
|
||||
*/
|
||||
bool inside(Point p, bool border_result = false) const
|
||||
{
|
||||
int res = ClipperLib::PointInPolygon(p, *path);
|
||||
if (res == -1)
|
||||
{
|
||||
return border_result;
|
||||
}
|
||||
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
|
||||
* which has an angle with the next and previous line segment smaller than roughly 150*
|
||||
*
|
||||
* Note that in its current implementation this function doesn't remove line segments with an angle smaller than 30*
|
||||
* Such would be the case for an N shape.
|
||||
*
|
||||
* \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) const;
|
||||
|
||||
/*!
|
||||
* Smooth out the polygon and store the result in \p result.
|
||||
* Smoothing is performed by removing vertices for which both connected line segments are smaller than \p remove_length
|
||||
*
|
||||
* \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) const;
|
||||
|
||||
ClipperLib::Path::const_reference back() const
|
||||
{
|
||||
return path->back();
|
||||
}
|
||||
|
||||
ClipperLib::Path::const_iterator begin() const
|
||||
{
|
||||
return path->begin();
|
||||
}
|
||||
|
||||
ClipperLib::Path::const_iterator end() const
|
||||
{
|
||||
return path->end();
|
||||
}
|
||||
|
||||
friend class Polygons;
|
||||
friend class Polygon;
|
||||
};
|
||||
|
||||
class Polygon : public PolygonRef
|
||||
{
|
||||
ClipperLib::Path poly;
|
||||
@@ -397,6 +592,7 @@ class Polygons
|
||||
{
|
||||
friend class Polygon;
|
||||
friend class PolygonRef;
|
||||
friend class ConstPolygonRef;
|
||||
protected:
|
||||
ClipperLib::Paths paths;
|
||||
public:
|
||||
@@ -407,14 +603,14 @@ public:
|
||||
|
||||
unsigned int pointCount() const; //!< Return the amount of points in all polygons
|
||||
|
||||
PolygonRef operator[] (unsigned int index)
|
||||
ClipperLib::Path& 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);
|
||||
return paths[index];
|
||||
}
|
||||
ClipperLib::Paths::iterator begin()
|
||||
{
|
||||
@@ -461,6 +657,10 @@ public:
|
||||
{
|
||||
paths.push_back(*poly.path);
|
||||
}
|
||||
void add(const ConstPolygonRef& poly)
|
||||
{
|
||||
paths.push_back(*poly.path);
|
||||
}
|
||||
void add(Polygon&& other_poly)
|
||||
{
|
||||
paths.emplace_back(std::move(*other_poly));
|
||||
@@ -484,14 +684,14 @@ public:
|
||||
paths.emplace_back(args...);
|
||||
}
|
||||
|
||||
PolygonRef newPoly()
|
||||
ClipperLib::Path& newPoly()
|
||||
{
|
||||
paths.emplace_back();
|
||||
return PolygonRef(paths.back());
|
||||
return paths.back();
|
||||
}
|
||||
PolygonRef back()
|
||||
ClipperLib::Path& back()
|
||||
{
|
||||
return PolygonRef(paths.back());
|
||||
return paths.back();
|
||||
}
|
||||
|
||||
Polygons() {}
|
||||
@@ -647,7 +847,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 +858,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
|
||||
@@ -673,7 +873,7 @@ public:
|
||||
Polygons& thiss = *this;
|
||||
for (unsigned int p = 0; p < size(); p++)
|
||||
{
|
||||
thiss[p].simplify(smallest_line_segment_squared, allowed_error_distance_squared);
|
||||
PolygonRef{thiss[p]}.simplify(smallest_line_segment_squared, allowed_error_distance_squared);
|
||||
if (thiss[p].size() < 3)
|
||||
{
|
||||
remove(p);
|
||||
@@ -734,7 +934,7 @@ public:
|
||||
Polygons& thiss = *this;
|
||||
for(unsigned int i=0; i<size(); i++)
|
||||
{
|
||||
double area = INT2MM(INT2MM(fabs(thiss[i].area())));
|
||||
double area = INT2MM(INT2MM(fabs(PolygonRef{thiss[i]}.area())));
|
||||
if (area < minAreaSize) // Only create an up/down skin if the area is large enough. So you do not create tiny blobs of "trying to fill"
|
||||
{
|
||||
remove(i);
|
||||
@@ -798,16 +998,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,21 +1123,24 @@ 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)
|
||||
{
|
||||
if (size() < 1)
|
||||
return false;
|
||||
if (!(*this)[0].inside(p))
|
||||
if (!PolygonRef{(*this)[0]}.inside(p))
|
||||
return false;
|
||||
for(unsigned int n=1; n<paths.size(); n++)
|
||||
{
|
||||
if ((*this)[n].inside(p))
|
||||
if (PolygonRef{(*this)[n]}.inside(p))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -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);
|
||||
@@ -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(PolygonRef 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;
|
||||
|
||||
|
||||
+17
-17
@@ -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
|
||||
@@ -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(const PolygonRef 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:
|
||||
/*!
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário