Comparar commits

..

28 Commits

Autor SHA1 Mensagem Data
Tim Kuipers e84ec85ca7 fix: spaghetti infill now uses connected zigzags to minimize non-extrusion moves (CURA-3238)
also note that due to the spaghetti_inset the zigzags are not connected to the walls (depending on user input)
2017-02-15 10:25:36 +01:00
Tim Kuipers 5f7ce40b89 fix: register layer as empty even if meshes don't have walls (CURA-3238) 2017-02-15 10:19:08 +01:00
Tim Kuipers c97097a7e2 indent only (CURA-3238) 2017-02-13 15:25:15 +01:00
Tim Kuipers 44612c2e71 fix: spaghetti infill now uses normal infill spacing and infill overlap settings (CURA-3238) 2017-02-13 15:24:52 +01:00
Tim Kuipers d1f64718ea feat: spaghetti_flow setting (CURA-3238) 2017-02-13 14:00:24 +01:00
Tim Kuipers a9390abd61 spaghetti infill: documentation (CURA-3238) 2017-02-13 13:54:17 +01:00
Tim Kuipers d3837f7efe feat: spaghetti_inset setting (CURA-3238) 2017-02-13 12:04:37 +01:00
Tim Kuipers 1890d51b03 fix: spaghetti infill: use infill line width rather than hardcoded value (CURA-3238) 2017-02-13 11:59:58 +01:00
Tim Kuipers 6d9eef9fa9 feat: spaghetti infill area inset (CURA-3238) 2017-02-13 11:40:11 +01:00
Tim Kuipers 76df240798 fix: forgot the actual SpaghettiInfill files (CURA-3238) 2017-02-13 11:40:11 +01:00
Tim Kuipers 0425676f13 feat: PolygonsPart::area() (CURA-3238) 2017-02-13 11:40:11 +01:00
Tim Kuipers ebd308f229 fix: small indent and const only (CURA-3238) 2017-02-13 11:40:11 +01:00
Tim Kuipers cad9a12ade feat: spaghetti infill (CURA-3238) 2017-02-13 11:40:11 +01:00
Tim Kuipers 95b2034739 feat: Polygon::polyLineLength() (CURA-3238) 2017-02-13 11:40:11 +01:00
Ghostkeeper ab7e035f6e Don't continue with compiling when function has error
This would give an exception which breaks the script and makes a very unclear chained error message.

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

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

Contributes to issue CURA-3274.
2017-01-31 10:35:28 +01:00
Johan K fff1164042 Add cmake option to enable OpenMP
CURA-541
2017-01-30 17:30:44 +01:00
Ghostkeeper c7e621eeb5 Merge branch '2.4' 2017-01-25 17:46:07 +01:00
Ghostkeeper 9c3170b277 Print debug message upon sending layer data
This should help a bit with debugging the slice loop. I hope.

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

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

Contributes to issue CURA-3274.
2017-01-25 13:36:14 +01:00
Ghostkeeper 5b6f1db59d Merge branch 'mb-min-infill-area' of https://github.com/smartavionics/CuraEngine into smartavionics-mb-min-infill-area 2017-01-24 11:40:03 +01:00
Tim Kuipers 17463e1139 quick fix: accidental const (CURA-3309) 2017-01-23 17:37:17 +01:00
Tim Kuipers 8df26ae916 fix: equalize flow still equalizes after halving the line width for perimeter gaps (CURA-3309) 2017-01-23 17:36:24 +01:00
Mark Burton b43e4df3aa Remove areas of infill smaller than min_infill_area.
When you have a small feature above an outer layer (e.g. raised text), the
area under the feature will be infill rather than skin and so the skin is
composed of multiple segments around the feature. Better surface quality is
obtained if the area under the raised feature is treated as skin thus allowing
more of the outer layer to be printed as a single segment. This setting
specifies the minimum area (in mm^2) of a filled region. Areas smaller than
this will be filled with skin rather than infill.
2017-01-19 11:44:22 +00:00
51 arquivos alterados com 743 adições e 1037 exclusões
+1 -1
Ver Arquivo
@@ -89,9 +89,9 @@ set(engine_SRCS # Except main.cpp.
src/wallOverlap.cpp
src/Weaver.cpp
src/Wireframe2gcode.cpp
src/multithreadOpenMP.cpp
src/infill/NoZigZagConnectorProcessor.cpp
src/infill/SpaghettiInfill.cpp
src/infill/ZigzagConnectorProcessorConnectedEndPieces.cpp
src/infill/ZigzagConnectorProcessorDisconnectedEndPieces.cpp
src/infill/ZigzagConnectorProcessorEndPieces.cpp
+114 -56
Ver Arquivo
@@ -91,15 +91,9 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep
}
}
#pragma omp parallel default(none) shared(storage, total_layers)
for(unsigned int layer_nr=0; layer_nr<total_layers; layer_nr++)
{
#pragma omp single nowait
{
for(unsigned int layer_nr=0; layer_nr<total_layers; layer_nr++)
{
processLayer(storage, layer_nr, total_layers);
}
}
processLayer(storage, layer_nr, total_layers);
}
Progress::messageProgressStage(Progress::Stage::FINISH, &time_keeper);
@@ -200,9 +194,16 @@ void FffGcodeWriter::initConfigs(SliceDataStorage& storage)
mesh.inset0_config.init(mesh.getSettingInMillimetersPerSecond("speed_wall_0"), mesh.getSettingInMillimetersPerSecond("acceleration_wall_0"), mesh.getSettingInMillimetersPerSecond("jerk_wall_0"), mesh.getSettingInMicrons("wall_line_width_0"), mesh.getSettingInPercentage("material_flow"));
mesh.insetX_config.init(mesh.getSettingInMillimetersPerSecond("speed_wall_x"), mesh.getSettingInMillimetersPerSecond("acceleration_wall_x"), mesh.getSettingInMillimetersPerSecond("jerk_wall_x"), mesh.getSettingInMicrons("wall_line_width_x"), mesh.getSettingInPercentage("material_flow"));
mesh.skin_config.init(mesh.getSettingInMillimetersPerSecond("speed_topbottom"), mesh.getSettingInMillimetersPerSecond("acceleration_topbottom"), mesh.getSettingInMillimetersPerSecond("jerk_topbottom"), mesh.getSettingInMicrons("skin_line_width"), mesh.getSettingInPercentage("material_flow"));
mesh.perimeter_gap_config.init(mesh.getSettingInMillimetersPerSecond("speed_topbottom"), mesh.getSettingInMillimetersPerSecond("acceleration_topbottom"), mesh.getSettingInMillimetersPerSecond("jerk_topbottom"), mesh.getSettingInMicrons("wall_line_width_x") / 2, mesh.getSettingInPercentage("material_flow"));
// the perimeter gap config follows the skin config, but has a different line width:
// The perimeter gap config follows the skin config, but has a different line width:
// wall_line_width_x divided by two because the gaps are between 0 and 1 times the wall line width
const int perimeter_gaps_line_width = mesh.getSettingInMicrons("wall_line_width_x") / 2;
double perimeter_gaps_speed = mesh.getSettingInMillimetersPerSecond("speed_topbottom");
if (mesh.getSettingBoolean("speed_equalize_flow_enabled"))
{
perimeter_gaps_speed = perimeter_gaps_speed * mesh.getSettingInMicrons("skin_line_width") / perimeter_gaps_line_width;
}
mesh.perimeter_gap_config.init(perimeter_gaps_speed, mesh.getSettingInMillimetersPerSecond("acceleration_topbottom"), mesh.getSettingInMillimetersPerSecond("jerk_topbottom"), perimeter_gaps_line_width, mesh.getSettingInPercentage("material_flow"));
for (unsigned int idx = 0; idx < MAX_INFILL_COMBINE; idx++)
{
@@ -350,10 +351,7 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
int layer_height = train->getSettingInMicrons("raft_base_thickness");
z += layer_height;
int64_t comb_offset = train->getSettingInMicrons("raft_base_line_spacing");
GCodePlanner& gcode_layer = layer_plan_buffer.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();
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"));
gcode_layer.setIsInside(true);
gcode_layer.setExtruder(extruder_nr);
@@ -390,10 +388,7 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
int layer_height = train->getSettingInMicrons("raft_interface_thickness");
z += layer_height;
int64_t comb_offset = train->getSettingInMicrons("raft_interface_line_spacing");
GCodePlanner& gcode_layer = layer_plan_buffer.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();
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"));
gcode_layer.setIsInside(true);
gcode_layer.setExtruder(extruder_nr); // reset to extruder number, because we might have primed in the last layer
@@ -425,10 +420,7 @@ void FffGcodeWriter::processRaft(SliceDataStorage& storage, unsigned int total_l
const int layer_nr = initial_raft_layer_nr + 2 + raftSurfaceLayer - 1; // 2: 1 base layer, 1 interface layer
z += layer_height;
const int64_t comb_offset = train->getSettingInMicrons("raft_surface_line_spacing");
GCodePlanner& gcode_layer = layer_plan_buffer.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();
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"));
gcode_layer.setIsInside(true);
if (CommandSocket::isInstantiated())
@@ -512,7 +504,7 @@ void FffGcodeWriter::processLayer(SliceDataStorage& storage, int layer_nr, unsig
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);
GCodePlanner& gcode_layer = layer_plan_buffer.emplace_back(storage, layer_nr, z, layer_thickness, last_position_planned, current_extruder_planned, is_inside_mesh_layer_part, fan_speed_layer_time_settings_per_extruder, getSettingAsCombingMode("retraction_combing"), comb_offset_from_outlines, avoid_other_parts, avoid_distance);
if (include_helper_parts && layer_nr == 0)
{ // process the skirt or the brim of the starting extruder.
@@ -601,9 +593,7 @@ 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();
}
@@ -644,7 +634,7 @@ void FffGcodeWriter::processSkirtBrim(SliceDataStorage& storage, GCodePlanner& g
{
return;
}
gcode_layer.addTravel(PolygonRef{skirt_brim.back()}.closestPointTo(gcode_layer.getLastPosition()));
gcode_layer.addTravel(skirt_brim.back().closestPointTo(gcode_layer.getLastPosition()));
gcode_layer.addPolygonsByOptimizer(skirt_brim, &storage.skirt_brim_config[extruder_nr]);
}
@@ -732,7 +722,7 @@ std::vector<unsigned int> FffGcodeWriter::calculateMeshOrder(SliceDataStorage& s
return ret;
}
void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& storage, const SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
{
if (layer_nr > mesh->layer_nr_max_filled_layer)
{
@@ -748,7 +738,7 @@ void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& stora
setExtruder_addPrime(storage, gcode_layer, layer_nr, mesh->getSettingAsIndex("extruder_nr"));
const SliceLayer* layer = &mesh->layers[layer_nr];
SliceLayer* layer = &mesh->layers[layer_nr];
Polygons polygons;
@@ -764,12 +754,12 @@ void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& stora
addMeshOpenPolyLinesToGCode(storage, mesh, gcode_layer, layer_nr);
}
void FffGcodeWriter::addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, const SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
void FffGcodeWriter::addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
{
const SliceLayer* layer = &mesh->layers[layer_nr];
SliceLayer* layer = &mesh->layers[layer_nr];
Polygons lines;
for(ConstPolygonRef polyline : layer->openPolyLines)
for(PolygonRef polyline : layer->openPolyLines)
{
for(unsigned int point_idx = 1; point_idx<polyline.size(); point_idx++)
{
@@ -783,7 +773,7 @@ void FffGcodeWriter::addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, cons
}
void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, const SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr)
{
if (layer_nr > mesh->layer_nr_max_filled_layer)
{
@@ -797,19 +787,22 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, const SliceM
return;
}
const SliceLayer* layer = &mesh->layers[layer_nr];
SliceLayer* layer = &mesh->layers[layer_nr];
if (layer->parts.size() == 0)
{
return;
}
if (mesh->getSettingAsCount("wall_line_count") > 0)
{ // don't switch extruder if there's nothing to print
bool empty = true;
for (const SliceLayerPart& part : layer->parts)
const bool use_walls = mesh->getSettingAsCount("wall_line_count") > 0;
for (SliceLayerPart& part : layer->parts)
{
if (part.insets.size() > 0)
if (
(use_walls && part.insets.size() > 0)
|| (!use_walls && (part.getOwnInfillArea().size() > 0 || part.skin_parts.size() > 0))
)
{
empty = false;
break;
@@ -839,7 +832,7 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, const SliceM
for (int part_idx : part_order_optimizer.polyOrder)
{
const SliceLayerPart& part = layer->parts[part_idx];
SliceLayerPart& part = layer->parts[part_idx];
addMeshPartToGCode(storage, mesh, part, gcode_layer, layer_nr);
}
if (mesh->getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL)
@@ -848,7 +841,7 @@ void FffGcodeWriter::addMeshLayerToGCode(SliceDataStorage& storage, const SliceM
}
}
void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, const SliceMeshStorage* mesh, const SliceLayerPart& part, GCodePlanner& gcode_layer, int layer_nr)
void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, 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 );
@@ -870,8 +863,7 @@ void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, const SliceMe
if (mesh->getSettingBoolean("infill_before_walls"))
{
processMultiLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
processSingleLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
processInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
}
EZSeamType z_seam_type = mesh->getSettingAsZSeamType("z_seam_type");
@@ -880,8 +872,7 @@ void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, const SliceMe
if (!mesh->getSettingBoolean("infill_before_walls"))
{
processMultiLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
processSingleLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
processInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
}
EFillMethod skin_pattern = (layer_nr == 0)?
@@ -908,9 +899,76 @@ void FffGcodeWriter::addMeshPartToGCode(SliceDataStorage& storage, const SliceMe
}
void FffGcodeWriter::processInfill(GCodePlanner& gcode_layer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int infill_angle)
{
if (mesh->getSettingBoolean("spaghetti_infill_enabled"))
{
processSpaghettiInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
}
else
{
processMultiLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
processSingleLayerInfill(gcode_layer, mesh, part, layer_nr, infill_line_distance, infill_overlap, infill_angle);
}
}
void FffGcodeWriter::processSpaghettiInfill(GCodePlanner& gcode_layer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int infill_angle)
{
GCodePathConfig& config = mesh->infill_config[0];
const EFillMethod pattern = mesh->getSettingAsFillMethod("infill_pattern");
const unsigned int infill_line_width = config.getLineWidth();
const int64_t z = layer_nr * getSettingInMicrons("layer_height");
const int64_t infill_shift = 0;
const int64_t outline_offset = 0;
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)
for (std::pair<PolygonsPart, double>& filling_area : part.spaghetti_infill_volumes)
{
Polygons infill_lines;
Polygons infill_polygons;
const PolygonsPart& area = filling_area.first;
const double total_volume = filling_area.second * getSettingAsRatio("spaghetti_flow");
assert(total_volume > 0.0);
Polygons* perimeter_gaps_output = nullptr;
const bool connected_zigzags = true;
const bool use_endpieces = false;
Infill infill_comp(pattern, area, outline_offset, infill_line_width, infill_line_distance, infill_overlap, infill_angle, z, infill_shift, perimeter_gaps_output, connected_zigzags, use_endpieces);
infill_comp.generate(infill_polygons, infill_lines, mesh);
const coord_t total_length = infill_polygons.polygonLength() + infill_lines.polyLineLength();
if (total_length > 0)
{
const double normal_volume = INT2MM(INT2MM(total_length * infill_line_width)) * mesh->getSettingInMillimeters("layer_height");
const float flow_ratio = total_volume / normal_volume;
assert(flow_ratio >= 0.9);
gcode_layer.addPolygonsByOptimizer(infill_polygons, &config, nullptr, EZSeamType::SHORTEST, Point(0, 0), 0, false, flow_ratio);
if (pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES)
{
gcode_layer.addLinesByOptimizer(infill_lines, &config, SpaceFillType::Lines, mesh->getSettingInMicrons("infill_wipe_dist"), flow_ratio);
}
else
{
gcode_layer.addLinesByOptimizer(infill_lines, &config, (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines, 0, flow_ratio);
}
}
else
{
Point middle = const_cast<PolygonsPart&>(area).outerPolygon().centerOfMass();
if (!area.inside(middle))
{
PolygonUtils::ensureInsideOrOutside(area, middle, infill_line_width / 2);
}
const double normal_volume = INT2MM(INT2MM(10 * infill_line_width)) * mesh->getSettingInMillimeters("layer_height");
const float flow_ratio = total_volume / normal_volume;
gcode_layer.addTravel(middle);
gcode_layer.addExtrusionMove(middle + Point(0,10), &config, SpaceFillType::Lines, flow_ratio);
}
}
}
void FffGcodeWriter::processMultiLayerInfill(GCodePlanner& gcode_layer, SliceMeshStorage* mesh, 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)
@@ -941,7 +999,7 @@ void FffGcodeWriter::processMultiLayerInfill(GCodePlanner& gcode_layer, const Sl
}
}
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)
void FffGcodeWriter::processSingleLayerInfill(GCodePlanner& gcode_layer, SliceMeshStorage* mesh, 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)
{
@@ -1002,7 +1060,7 @@ void FffGcodeWriter::processSingleLayerInfill(GCodePlanner& gcode_layer, const S
}
}
void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, const SliceMeshStorage* mesh, const SliceLayerPart& part, unsigned int layer_nr, EZSeamType z_seam_type, Point z_seam_pos)
void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, SliceMeshStorage* mesh, 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");
@@ -1019,7 +1077,7 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, const SliceMeshSto
{ // on the last normal layer first make the outer wall normally and then start a second outer wall from the same hight, but gradually moving upward
WallOverlapComputation* wall_overlap_computation(nullptr);
int wall_0_wipe_dist(0);
gcode_layer.addPolygonsByOptimizer(part.insets[0], &mesh->insetX_config, wall_overlap_computation, EZSeamType::SHORTEST, z_seam_pos, mesh->getSettingInMicrons("wall_0_wipe_dist"), wall_0_wipe_dist);
gcode_layer.addPolygonsByOptimizer(part.insets[0], &mesh->insetX_config, wall_overlap_computation, EZSeamType::SHORTEST, z_seam_pos, wall_0_wipe_dist, spiralize);
}
}
int processed_inset_number = -1;
@@ -1039,7 +1097,7 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, const SliceMeshSto
}
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);
}
@@ -1052,7 +1110,7 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, const SliceMeshSto
}
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);
}
@@ -1062,7 +1120,7 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, const SliceMeshSto
}
void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, const SliceMeshStorage* mesh, const SliceLayerPart& part, unsigned int layer_nr, int skin_overlap, int skin_angle)
void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, SliceMeshStorage* mesh, 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();
@@ -1076,14 +1134,14 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, cons
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++)
{
const PolygonsPart& outline = part.skin_parts[skin_part_idx].outline;
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)
{
const SkinPart& skin_part = part.skin_parts[ordered_skin_part_idx];
SkinPart& skin_part = part.skin_parts[ordered_skin_part_idx];
Polygons skin_polygons;
Polygons skin_lines;
@@ -1102,11 +1160,11 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, cons
Polygons perimeter_gaps; // the perimeter gaps of the insets of this skin part
const Polygons* inner_skin_outline = nullptr;
Polygons* inner_skin_outline = nullptr;
int offset_from_inner_skin_outline = 0;
if (pattern != EFillMethod::CONCENTRIC)
{
for (const Polygons& skin_perimeter : skin_part.insets)
for (Polygons& skin_perimeter : skin_part.insets)
{
gcode_layer.addPolygonsByOptimizer(skin_perimeter, &mesh->insetX_config); // add polygons to gcode in inward order
}
@@ -1185,7 +1243,7 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, cons
const Polygons outer = part.insets.back().offset(-1 * line_width / 2 - perimeter_gaps_extra_offset);
Polygons inner = part.infill_area;
for (const SkinPart& skin_part : part.skin_parts)
for (SkinPart& skin_part : part.skin_parts)
{
inner.add(skin_part.outline);
}
@@ -1262,7 +1320,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(PolygonRef{support_islands[n][0]});
island_order_optimizer.addPolygon(support_islands[n][0]);
}
island_order_optimizer.optimize();
+35 -9
Ver Arquivo
@@ -301,7 +301,7 @@ private:
* \param layer_nr The index of the layer to write the gcode of.
*
*/
void addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& storage, const SliceMeshStorage* mesh, GCodePlanner& gcodeLayer, int layer_nr);
void addMeshLayerToGCode_meshSurfaceMode(SliceDataStorage& storage, 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, const SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr);
void addMeshOpenPolyLinesToGCode(SliceDataStorage& storage, 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, const SliceMeshStorage* mesh, GCodePlanner& gcode_layer, int layer_nr);
void addMeshLayerToGCode(SliceDataStorage& storage, 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,8 +335,34 @@ private:
* \param layer_nr The index of the layer to write the gcode of.
*
*/
void addMeshPartToGCode(SliceDataStorage& storage, const SliceMeshStorage* mesh, const SliceLayerPart& part, GCodePlanner& gcode_layer, int layer_nr);
void addMeshPartToGCode(SliceDataStorage& storage, SliceMeshStorage* mesh, SliceLayerPart& part, GCodePlanner& gcode_layer, int layer_nr);
/*!
* Add sparse infill for a given part in a layer plan.
*
* \param gcodeLayer The initial planning of the gcode of the layer.
* \param mesh The mesh for which to add to the layer plan \p gcodeLayer.
* \param part The part for which to create gcode
* \param layer_nr The current layer number.
* \param infill_line_distance The distance between the infill lines
* \param infill_overlap The distance by which the infill overlaps with the wall insets.
* \param fillAngle The angle in the XY plane at which the infill is generated.
*/
void processInfill(GCodePlanner& gcodeLayer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int fillAngle);
/*!
* Add spaghetti infill for a given part in a layer plan.
*
* \param gcodeLayer The initial planning of the gcode of the layer.
* \param mesh The mesh for which to add to the layer plan \p gcodeLayer.
* \param part The part for which to create gcode
* \param layer_nr The current layer number.
* \param infill_line_distance The distance between the infill lines
* \param infill_overlap The distance by which the infill overlaps with the wall insets.
* \param fillAngle The angle in the XY plane at which the infill is generated.
*/
void processSpaghettiInfill(GCodePlanner& gcodeLayer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int fillAngle);
/*!
* Add thicker (multiple layers) sparse infill for a given part in a layer plan.
*
@@ -348,7 +374,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, const SliceMeshStorage* mesh, const SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int fillAngle);
void processMultiLayerInfill(GCodePlanner& gcodeLayer, SliceMeshStorage* mesh, 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 +386,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, const SliceMeshStorage* mesh, const SliceLayerPart& part, unsigned int layer_nr, int infill_line_distance, int infill_overlap, int fillAngle);
void processSingleLayerInfill(GCodePlanner& gcodeLayer, SliceMeshStorage* mesh, 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 +397,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, const SliceMeshStorage* mesh, const SliceLayerPart& part, unsigned int layer_nr, EZSeamType z_seam_type, Point z_seam_pos);
void processInsets(GCodePlanner& gcodeLayer, SliceMeshStorage* mesh, SliceLayerPart& part, unsigned int layer_nr, EZSeamType z_seam_type, Point z_seam_pos);
/*!
@@ -387,7 +413,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, const cura::SliceMeshStorage* mesh, const cura::SliceLayerPart& part, unsigned int layer_nr, int skin_overlap, int infill_angle);
void processSkinAndPerimeterGaps(cura::GCodePlanner& gcode_layer, cura::SliceMeshStorage* mesh, 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.
+32 -81
Ver Arquivo
@@ -2,7 +2,6 @@
#include <algorithm>
#include <map> // multimap (ordered map allowing duplicate keys)
#include <omp.h>
#include "utils/math.h"
#include "utils/algorithm.h"
@@ -16,6 +15,7 @@
#include "WallsComputation.h"
#include "SkirtBrim.h"
#include "skin.h"
#include "infill/SpaghettiInfill.h"
#include "infill.h"
#include "raft.h"
#include "progress/Progress.h"
@@ -24,7 +24,7 @@
#include "progress/ProgressEstimator.h"
#include "progress/ProgressStageEstimator.h"
#include "progress/ProgressEstimatorLinear.h"
#include "multithreadOpenMP.h"
namespace cura
{
@@ -32,17 +32,6 @@ 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;
@@ -357,24 +346,12 @@ void FffPolygonGenerator::processBasicWallsSkinInfill(SliceDataStorage& storage,
// walls
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++)
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);
#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);
}
ProgressEstimatorLinear* skin_estimator = new ProgressEstimatorLinear(mesh_layer_count);
@@ -405,32 +382,15 @@ void FffPolygonGenerator::processBasicWallsSkinInfill(SliceDataStorage& storage,
{
mesh_max_bottom_layer_count = std::max(mesh_max_bottom_layer_count, mesh.getSettingAsCount("bottom_layers"));
}
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)
for (unsigned int layer_number = 0; layer_number < mesh.layers.size(); layer_number++)
{
#pragma omp for schedule(dynamic)
for (unsigned int layer_number = 0; layer_number < mesh.layers.size(); layer_number++)
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.
{
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++;
processSkinsAndInfill(mesh, layer_number, process_infill);
}
double progress = inset_skin_progress_estimate.progress(layer_number);
Progress::messageProgress(Progress::Stage::INSET_SKIN, progress * 100, 100);
}
}
@@ -470,7 +430,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(PolygonRef{new_outline[0]});
outline_part_here.add(new_outline[0]);
new_parts.push_back(outline_part_here);
}
else if (new_outline.size() > 1)
@@ -507,18 +467,27 @@ void FffPolygonGenerator::processInfillMesh(SliceDataStorage& storage, unsigned
void FffPolygonGenerator::processDerivedWallsSkinInfill(SliceMeshStorage& mesh)
{
// create gradual infill areas
SkinInfillAreaComputation::generateGradualInfill(mesh, mesh.getSettingInMicrons("gradual_infill_step_height"), mesh.getSettingAsCount("gradual_infill_steps"));
//SubDivCube Pre-compute Octree
if (mesh.getSettingAsFillMethod("infill_pattern") == EFillMethod::CUBICSUBDIV)
// generate spaghetti infill filling areas and volumes
if (mesh.getSettingBoolean("spaghetti_infill_enabled"))
{
SubDivCube::precomputeOctree(mesh);
SpaghettiInfill::generateSpaghettiInfill(mesh);
}
else
{
// combine infill
unsigned int combined_infill_layers = std::max(1U, round_divide(mesh.getSettingInMicrons("infill_sparse_thickness"), std::max(getSettingInMicrons("layer_height"), (coord_t)1))); //How many infill layers to combine to obtain the requested sparse thickness.
combineInfillLayers(mesh,combined_infill_layers);
// create gradual infill areas
SkinInfillAreaComputation::generateGradualInfill(mesh, mesh.getSettingInMicrons("gradual_infill_step_height"), mesh.getSettingAsCount("gradual_infill_steps"));
//SubDivCube Pre-compute Octree
if (mesh.getSettingAsFillMethod("infill_pattern") == EFillMethod::CUBICSUBDIV)
{
SubDivCube::precomputeOctree(mesh);
}
// combine infill
unsigned int combined_infill_layers = std::max(1U, round_divide(mesh.getSettingInMicrons("infill_sparse_thickness"), std::max(getSettingInMicrons("layer_height"), (coord_t)1))); //How many infill layers to combine to obtain the requested sparse thickness.
combineInfillLayers(mesh,combined_infill_layers);
}
// fuzzy skin
if (mesh.getSettingBoolean("magic_fuzzy_skin_enabled"))
@@ -527,14 +496,6 @@ 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];
@@ -616,18 +577,8 @@ void FffPolygonGenerator::removeEmptyFirstLayers(SliceDataStorage& storage, cons
support_layers.erase(support_layers.begin(), support_layers.begin() + n_empty_first_layers);
}
}
/*
* 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)
void FffPolygonGenerator::processSkinsAndInfill(SliceMeshStorage& mesh, unsigned int layer_nr, bool process_infill)
{
if (mesh.getSettingAsSurfaceMode("magic_mesh_surface_mode") == ESurfaceMode::SURFACE)
{
+7 -7
Ver Arquivo
@@ -67,37 +67,37 @@ void GCodePathConfig::setSpeedIconic()
current_config.jerk = iconic_config.jerk;
}
double GCodePathConfig::getExtrusionMM3perMM() const
double GCodePathConfig::getExtrusionMM3perMM()
{
return extrusion_mm3_per_mm;
}
double GCodePathConfig::getSpeed() const
double GCodePathConfig::getSpeed()
{
return current_config.speed;
}
double GCodePathConfig::getAcceleration() const
double GCodePathConfig::getAcceleration()
{
return current_config.acceleration;
}
double GCodePathConfig::getJerk() const
double GCodePathConfig::getJerk()
{
return current_config.jerk;
}
int GCodePathConfig::getLineWidth() const
int GCodePathConfig::getLineWidth()
{
return current_config.line_width;
}
bool GCodePathConfig::isTravelPath() const
bool GCodePathConfig::isTravelPath()
{
return current_config.line_width == 0;
}
double GCodePathConfig::getFlowPercentage() const
double GCodePathConfig::getFlowPercentage()
{
return current_config.flow;
}
+7 -7
Ver Arquivo
@@ -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() const;
double getExtrusionMM3perMM();
/*!
* Get the movement speed in mm/s
*/
double getSpeed() const;
double getSpeed();
/*!
* Get the current acceleration of this config
*/
double getAcceleration() const;
double getAcceleration();
/*!
* Get the current jerk of this config
*/
double getJerk() const;
double getJerk();
int getLineWidth() const;
int getLineWidth();
bool isTravelPath() const;
bool isTravelPath();
double getFlowPercentage() const;
double getFlowPercentage();
private:
void calculateExtrusion();
+9 -44
Ver Arquivo
@@ -7,31 +7,6 @@
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()
@@ -40,10 +15,6 @@ 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);
@@ -59,10 +30,9 @@ 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;
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--)
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)
@@ -225,9 +195,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.getPaths().size(); path_idx++)
for (path_idx = 0; path_idx < extruder_plan.paths.size(); path_idx++)
{
GCodePath& path = extruder_plan.getPaths()[path_idx];
GCodePath& path = extruder_plan.paths[path_idx];
heated_pre_travel_time += path.estimates.getTotalTime();
if (!path.isTravelPath())
{
@@ -254,9 +224,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.getPaths().size() - 1; int(path_idx) >= 0; path_idx--)
for (path_idx = last_extruder_plan.paths.size() - 1; int(path_idx) >= 0; path_idx--)
{
GCodePath& path = last_extruder_plan.getPaths()[path_idx];
GCodePath& path = last_extruder_plan.paths[path_idx];
if (!path.isTravelPath())
{
break;
@@ -336,9 +306,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->getPaths().size() - 1; int(path_idx) >= 0; path_idx--)
for (path_idx = precool_extruder_plan->paths.size() - 1; int(path_idx) >= 0; path_idx--)
{
GCodePath& path = precool_extruder_plan->getPaths()[path_idx];
GCodePath& path = precool_extruder_plan->paths[path_idx];
extrusion_time_seen += path.estimates.getTotalTime();
if (extrusion_time_seen >= cool_down_time)
{
@@ -354,16 +324,11 @@ 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].getPathsList().empty()))
if (buffer.back().extruder_plans.size() == 0 || (buffer.back().extruder_plans.size() == 1 && buffer.back().extruder_plans[0].paths.size() == 0))
{ // disregard empty layer
buffer.pop_back();
return;
}
for (ExtruderPlan& plan: buffer.back().extruder_plans)
{
plan.convertListToVector();
}
std::vector<ExtruderPlan*> extruder_plans;
extruder_plans.reserve(buffer.size() * 2);
+8 -20
Ver Arquivo
@@ -57,38 +57,26 @@ 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& createPlanner(Args&&... constructor_args)
GCodePlanner& emplace_back(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)
{
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.front().writeGCode(gcode);
if (CommandSocket::isInstantiated())
{
CommandSocket::getInstance()->flushGcode();
}
buffer.pop_front();
}
return buffer.back();
}
/*!
+1
Ver Arquivo
@@ -179,6 +179,7 @@ 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
Ver Arquivo
@@ -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 = PolygonRef{outer_skirt_brim_line[n]}.area();
double area = 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
Ver Arquivo
@@ -12,12 +12,6 @@ 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)
@@ -64,12 +58,6 @@ 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
Ver Arquivo
@@ -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(PolygonRef{roof_part[0]});
roof_outlines.add(roof_part[0]);
for (unsigned int hole_idx = 1; hole_idx < roof_part.size(); hole_idx++)
{
roof_holes.add(PolygonRef{roof_part[hole_idx]});
PolygonRef{roof_holes.back()}.reverse();
roof_holes.add(roof_part[hole_idx]);
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(PolygonRef{supporting_part[0]}); // only add outlines, not the holes
supporting_outlines.add(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(PolygonRef{floor_part[0]});
floor_outlines.add(floor_part[0]);
for (unsigned int hole_idx = 1; hole_idx < floor_part.size(); hole_idx++)
{
floor_holes.add(PolygonRef{floor_part[hole_idx]});
floor_holes.add(floor_part[hole_idx]);
//floor_holes.back().reverse();
}
}
+5 -5
Ver Arquivo
@@ -5,7 +5,7 @@
namespace cura {
int bridgeAngle(Polygons outline, const SliceLayer* prevLayer)
int bridgeAngle(Polygons outline, 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, const SliceLayer* prevLayer)
for(unsigned int n=0; n<islands.size(); n++)
{
//Skip internal holes
if (!PolygonRef{islands[n]}.orientation())
if (!islands[n].orientation())
continue;
double area = fabs(PolygonRef{islands[n]}.area());
double area = fabs(islands[n].area());
if (area > area1)
{
if (area1 > area2)
@@ -51,8 +51,8 @@ int bridgeAngle(Polygons outline, const SliceLayer* prevLayer)
if (idx1 < 0 || idx2 < 0)
return -1;
Point center1 = PolygonRef{islands[idx1]}.centerOfMass();
Point center2 = PolygonRef{islands[idx2]}.centerOfMass();
Point center1 = islands[idx1].centerOfMass();
Point center2 = islands[idx2].centerOfMass();
return angle(center2 - center1);
}
+1 -1
Ver Arquivo
@@ -6,7 +6,7 @@ namespace cura {
class Polygons;
class SliceLayer;
int bridgeAngle(Polygons outline, const SliceLayer* prevLayer);
int bridgeAngle(Polygons outline, SliceLayer* prevLayer);
}//namespace cura
+5 -3
Ver Arquivo
@@ -215,7 +215,7 @@ public:
/*!
* Adds closed polygon to the current path
*/
void sendPolygon(PrintFeatureType print_feature_type, ConstPolygonRef poly, int width);
void sendPolygon(PrintFeatureType print_feature_type, Polygon 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, ConstPolygonRef polygon, int line_width)
void CommandSocket::sendPolygon(PrintFeatureType type, Polygon& polygon, int line_width)
{
#ifdef ARCUS
if (CommandSocket::isInstantiated())
@@ -642,6 +642,7 @@ void CommandSocket::sendLayerData()
{
for (std::pair<const int, std::shared_ptr<cura::proto::Layer>> entry : data.slice_data) //Note: This is in no particular order!
{
logDebug("Sending layer data for layer %i of %i.\n", entry.first, data.slice_data.size());
private_data->socket->sendMessage(entry.second); //Send the actual layers.
}
data.sliced_objects = 0;
@@ -667,6 +668,7 @@ void CommandSocket::sendOptimizedLayerData()
{
for (std::pair<const int, std::shared_ptr<cura::proto::LayerOptimized>> entry : data.slice_data) //Note: This is in no particular order!
{
logDebug("Sending layer data for layer %i of %i.\n", entry.first, data.slice_data.size());
private_data->socket->sendMessage(entry.second); //Send the actual layers.
}
data.sliced_objects = 0;
@@ -797,7 +799,7 @@ void CommandSocket::PathCompiler::sendLineTo(PrintFeatureType print_feature_type
}
}
void CommandSocket::PathCompiler::sendPolygon(PrintFeatureType print_feature_type, ConstPolygonRef polygon, int width)
void CommandSocket::PathCompiler::sendPolygon(PrintFeatureType print_feature_type, Polygon polygon, int width)
{
if (polygon.size() < 2)
{
+1 -1
Ver Arquivo
@@ -64,7 +64,7 @@ public:
/*!
* Send a polygon to the front-end. This is used for the layerview in the GUI
*/
static void sendPolygon(cura::PrintFeatureType type, ConstPolygonRef polygon, int line_width);
static void sendPolygon(cura::PrintFeatureType type, Polygon& polygon, int line_width);
/*!
* Send a line to the front-end. This is used for the layerview in the GUI
+2 -2
Ver Arquivo
@@ -775,7 +775,7 @@ void GCodeExport::switchExtruder(int new_extruder, const RetractionConfig& retra
bool force = true;
bool extruder_switch = true;
writeRetraction(retraction_config_old_extruder, force, extruder_switch);
writeRetraction(const_cast<RetractionConfig&>(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
@@ -922,7 +922,7 @@ void GCodeExport::finalize(const char* endCode)
{
writeFanCommand(0);
writeCode(endCode);
long print_time = getTotalPrintTime();
int64_t print_time = getTotalPrintTime();
int mat_0 = getTotalFilamentUsed(0);
log("Print time: %d\n", print_time);
log("Print time (readable): %dh %dm %ds\n", print_time / 60 / 60, (print_time / 60) % 60, print_time % 60);
-11
Ver Arquivo
@@ -13,7 +13,6 @@
#include "MeshGroup.h"
#include "commandSocket.h"
#include "RetractionConfig.h"
#include "multithreadOpenMP.h"
namespace cura {
@@ -91,9 +90,6 @@ 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)
@@ -181,13 +177,6 @@ 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;
+26 -44
Ver Arquivo
@@ -11,8 +11,7 @@ namespace cura {
ExtruderPlan::ExtruderPlan(int extruder, Point start_position, int layer_nr, bool is_initial_layer, int layer_thickness, FanSpeedLayerTimeSettings& fan_speed_layer_time_settings, const RetractionConfig& retraction_config)
: is_paths_vector_initialised(false)
, extruder(extruder)
: extruder(extruder)
, heated_pre_travel_time(0)
, initial_printing_temperature(-1)
, printing_temperature(-1)
@@ -55,24 +54,11 @@ double ExtruderPlan::getFanSpeed()
{
return fan_speed;
}
void ExtruderPlan::convertListToVector()
{
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)
GCodePath* GCodePlanner::getLatestPathWithConfig(GCodePathConfig* config, SpaceFillType space_fill_type, float flow, bool spiralize)
{
std::list<GCodePath>& paths = extruder_plans.back().getPathsList();
std::vector<GCodePath>& paths = extruder_plans.back().paths;
if (paths.size() > 0 && paths.back().config == config && !paths.back().done && paths.back().flow == flow) // spiralize can only change when a travel path is in between
return &paths.back();
paths.emplace_back();
@@ -90,9 +76,9 @@ GCodePath* GCodePlanner::getLatestPathWithConfig(const GCodePathConfig* config,
void GCodePlanner::forceNewPathStart()
{
std::list<GCodePath>& paths = extruder_plans.back().getPathsList();
std::vector<GCodePath>& paths = extruder_plans.back().paths;
if (paths.size() > 0)
paths.back().done = true;
paths[paths.size()-1].done = true;
}
GCodePlanner::GCodePlanner(SliceDataStorage& storage, int layer_nr, int z, int layer_thickness, Point last_position, int current_extruder, bool is_inside_mesh, std::vector<FanSpeedLayerTimeSettings>& fan_speed_layer_time_settings_per_extruder, CombingMode combing_mode, int64_t comb_boundary_offset, bool travel_avoid_other_parts, int64_t travel_avoid_distance)
@@ -107,7 +93,6 @@ 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]);
@@ -204,7 +189,7 @@ bool GCodePlanner::setExtruder(int extruder)
}
addTravel(end_pos); // + extruder_offset cause it
}
if (extruder_plans.back().getPathsList().empty() && extruder_plans.back().inserts.empty())
if (extruder_plans.back().paths.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;
}
@@ -265,7 +250,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().getPathsList().size() == 0 && (extruder_plans.size() > 1 || last_extruder_previous_layer != getExtruder());
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 bypass_combing = is_first_travel_of_extruder_after_switch && extr->getSettingBoolean("retraction_hop_after_extruder_switch");
if (comb != nullptr && !bypass_combing && lastPosition != no_point)
@@ -364,27 +349,27 @@ void GCodePlanner::planPrime()
forceNewPathStart();
}
void GCodePlanner::addExtrusionMove(Point p, const GCodePathConfig* config, SpaceFillType space_fill_type, float flow, bool spiralize)
void GCodePlanner::addExtrusionMove(Point p, 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(ConstPolygonRef polygon, int start_idx, const GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation, coord_t wall_0_wipe_dist, bool spiralize)
void GCodePlanner::addPolygon(PolygonRef polygon, int start_idx, GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation, coord_t wall_0_wipe_dist, bool spiralize, float flow_ratio)
{
Point p0 = polygon[start_idx];
addTravel(p0);
for (unsigned int point_idx = 1; point_idx < polygon.size(); point_idx++)
{
Point p1 = polygon[(start_idx + point_idx) % polygon.size()];
float flow = (wall_overlap_computation)? wall_overlap_computation->getFlow(p0, p1) : 1.0;
float flow = (wall_overlap_computation)? flow_ratio * wall_overlap_computation->getFlow(p0, p1) : flow_ratio;
addExtrusionMove(p1, config, SpaceFillType::Polygons, flow, spiralize);
p0 = p1;
}
if (polygon.size() > 2)
{
const Point& p1 = polygon[start_idx];
float flow = (wall_overlap_computation)? wall_overlap_computation->getFlow(p0, p1) : 1.0;
Point& p1 = polygon[start_idx];
float flow = (wall_overlap_computation)? flow_ratio * wall_overlap_computation->getFlow(p0, p1) : flow_ratio;
addExtrusionMove(p1, config, SpaceFillType::Polygons, flow, spiralize);
if (wall_0_wipe_dist > 0)
@@ -418,7 +403,7 @@ void GCodePlanner::addPolygon(ConstPolygonRef polygon, int start_idx, const GCod
}
}
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)
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, float flow_ratio)
{
if (polygons.size() == 0)
{
@@ -432,10 +417,10 @@ void GCodePlanner::addPolygonsByOptimizer(const Polygons& polygons, const GCodeP
orderOptimizer.optimize();
for (unsigned int poly_idx : orderOptimizer.polyOrder)
{
addPolygon(polygons[poly_idx], orderOptimizer.polyStart[poly_idx], config, wall_overlap_computation, wall_0_wipe_dist, spiralize);
addPolygon(polygons[poly_idx], orderOptimizer.polyStart[poly_idx], config, wall_overlap_computation, wall_0_wipe_dist, spiralize, flow_ratio);
}
}
void GCodePlanner::addLinesByOptimizer(const Polygons& polygons, const GCodePathConfig* config, SpaceFillType space_fill_type, int wipe_dist)
void GCodePlanner::addLinesByOptimizer(Polygons& polygons, GCodePathConfig* config, SpaceFillType space_fill_type, int wipe_dist, float flow_ratio)
{
LineOrderOptimizer orderOptimizer(lastPosition);
for (unsigned int line_idx = 0; line_idx < polygons.size(); line_idx++)
@@ -445,13 +430,13 @@ void GCodePlanner::addLinesByOptimizer(const Polygons& polygons, const GCodePath
orderOptimizer.optimize();
for (int poly_idx : orderOptimizer.polyOrder)
{
ConstPolygonRef polygon = polygons[poly_idx];
PolygonRef polygon = polygons[poly_idx];
int start = orderOptimizer.polyStart[poly_idx];
int end = 1 - start;
const Point& p0 = polygon[start];
Point& p0 = polygon[start];
addTravel(p0);
const Point& p1 = polygon[end];
addExtrusionMove(p1, config, space_fill_type);
Point& p1 = polygon[end];
addExtrusionMove(p1, config, space_fill_type, flow_ratio);
if (wipe_dist != 0)
{
int line_width = config->getLineWidth();
@@ -473,7 +458,7 @@ void ExtruderPlan::forceMinimalLayerTime(double minTime, double minimalSpeed, do
if (minExtrudeTime < 1)
minExtrudeTime = 1;
double factor = extrudeTime / minExtrudeTime;
for (GCodePath& path : getPathsList())
for (GCodePath& path : paths)
{
if (path.isTravelPath())
continue;
@@ -497,7 +482,7 @@ void ExtruderPlan::forceMinimalLayerTime(double minTime, double minimalSpeed, do
// Adjust stored naive time estimates
estimates.extrude_time *= inv_factor;
for (GCodePath& path : getPathsList())
for (GCodePath& path : paths)
{
path.estimates.extrude_time *= inv_factor;
}
@@ -515,7 +500,7 @@ TimeMaterialEstimates ExtruderPlan::computeNaiveTimeEstimates()
Point p0 = start_position;
bool was_retracted = false; // wrong assumption; won't matter that much. (TODO)
for (GCodePath& path : getPathsList())
for (GCodePath& path : paths)
{
bool is_extrusion_path = false;
double* path_time_estimate;
@@ -668,7 +653,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
gcode.setZ(z);
const GCodePathConfig* last_extrusion_config = nullptr; // used to check whether we need to insert a TYPE comment in the gcode.
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");
@@ -717,7 +702,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
gcode.writeRetraction(retraction_config);
}
gcode.writeFanCommand(extruder_plan.getFanSpeed());
std::vector<GCodePath>& paths = extruder_plan.getPaths();
std::vector<GCodePath>& paths = extruder_plan.paths;
extruder_plan.inserts.sort([](const NozzleTempInsert& a, const NozzleTempInsert& b) -> bool {
return a.path_idx < b.path_idx;
@@ -890,9 +875,6 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
} // extruder plans /\ .
gcode.updateTotalPrintTime();
#pragma omp flush
#pragma omp atomic update
++gcode_written;
}
void GCodePlanner::overrideFanSpeeds(double speed)
@@ -1009,7 +991,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].getPaths();
std::vector<GCodePath>& paths = extruder_plans[extruder_plan_idx].paths;
for (unsigned int path_idx2 = path_idx + 1; path_idx2 < paths.size(); path_idx2++)
{
if (paths[path_idx2].getExtrusionMM3perMM() > 0)
@@ -1040,7 +1022,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.getPaths();
std::vector<GCodePath>& paths = extruder_plan.paths;
GCodePath& path = paths[path_idx];
if (path_idx + 1 >= paths.size()
||
+11 -55
Ver Arquivo
@@ -37,12 +37,9 @@ 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::list<GCodePath> paths_list; //!< The paths planned for this extruder
std::vector<GCodePath> paths_vector; //!< The paths planned for this extruder
std::vector<GCodePath> paths; //!< 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.
@@ -104,7 +101,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 == getPaths().size());
assert(insert.path_idx == paths.size());
insert.write(gcode);
inserts.pop_front();
}
@@ -159,39 +156,6 @@ 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
@@ -276,8 +240,6 @@ 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.
@@ -289,7 +251,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(const GCodePathConfig* config, SpaceFillType space_fill_type, float flow = 1.0, bool spiralize = false);
GCodePath* getLatestPathWithConfig(GCodePathConfig* config, SpaceFillType space_fill_type, float flow = 1.0, bool spiralize = false);
public:
/*!
@@ -415,7 +377,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, const GCodePathConfig* config, SpaceFillType space_fill_type, float flow = 1.0, bool spiralize = false);
void addExtrusionMove(Point p, GCodePathConfig* config, SpaceFillType space_fill_type, float flow = 1.0, bool spiralize = false);
/*!
* Add polygon to the gcode starting at vertex \p startIdx
@@ -425,8 +387,9 @@ public:
* \param wall_overlap_computation The wall overlap compensation calculator for each given segment (optionally nullptr)
* \param wall_0_wipe_dist The distance to travel along the polygon after it has been laid down, in order to wipe the start and end of the wall together
* \param spiralize Whether to gradually increase the z height from the normal layer height to the height of the next layer over this polygon
* \param flow_ratio The ratio with which to multiply the extrusion amount
*/
void addPolygon(ConstPolygonRef polygon, int startIdx, const GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation = nullptr, coord_t wall_0_wipe_dist = 0, bool spiralize = false);
void addPolygon(PolygonRef polygon, int startIdx, GCodePathConfig* config, WallOverlapComputation* wall_overlap_computation = nullptr, coord_t wall_0_wipe_dist = 0, bool spiralize = false, float flow_ratio = 1.0);
/*!
* Add polygons to the gcode with optimized order.
@@ -444,8 +407,9 @@ public:
* \param z_seam_pos The location near where to start each part in case \p z_seam_type is 'back'
* \param wall_0_wipe_dist The distance to travel along each polygon after it has been laid down, in order to wipe the start and end of the wall together
* \param spiralize Whether to gradually increase the z height from the normal layer height to the height of the next layer over each polygon printed
* \param flow_ratio The ratio with which to multiply the extrusion amount
*/
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);
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, float flow_ratio = 1.0);
/*!
* Add lines to the gcode with optimized order.
@@ -453,8 +417,9 @@ public:
* \param config The config of the lines
* \param space_fill_type The type of space filling used to generate the line segments (should be either Lines or PolyLines!)
* \param wipe_dist (optional) the distance wiped without extruding after laying down a line.
* \param flow_ratio The ratio with which to multiply the extrusion amount
*/
void addLinesByOptimizer(const Polygons& polygons, const GCodePathConfig* config, SpaceFillType space_fill_type, int wipe_dist = 0);
void addLinesByOptimizer(Polygons& polygons, GCodePathConfig* config, SpaceFillType space_fill_type, int wipe_dist = 0, float flow_ratio = 1.0);
/*!
* Compute naive time estimates (without accounting for slow down at corners etc.) and naive material estimates (without accounting for MergeInfillLines)
@@ -472,16 +437,7 @@ 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
Ver Arquivo
@@ -17,7 +17,7 @@ int Infill::computeScanSegmentIdx(int x, int line_width)
return x / line_width;
}
void Infill::generate(Polygons& result_polygons, Polygons& result_lines, const SliceMeshStorage* mesh)
void Infill::generate(Polygons& result_polygons, Polygons& result_lines, 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, const SliceMeshStorage& mesh)
void Infill::generateCubicSubDivInfill(Polygons& result, SliceMeshStorage& mesh)
{
Polygons uncropped;
mesh.base_subdiv_cube->generateSubdivisionLines(z, uncropped);
+3 -3
Ver Arquivo
@@ -80,7 +80,7 @@ public:
* \param result_lines (output) The resulting line segments (from linear infill types)
* \param mesh The mesh for which to geenrate infill (should only be used for non-helper objects)
*/
void generate(Polygons& result_polygons, Polygons& result_lines, const SliceMeshStorage* mesh = nullptr);
void generate(Polygons& result_polygons, Polygons& result_lines, 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, const SliceMeshStorage& mesh);
void generateCubicSubDivInfill(Polygons& result, 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
+139
Ver Arquivo
@@ -0,0 +1,139 @@
/** Copyright (C) 2017 Ultimaker - Released under terms of the AGPLv3 License */
#include "SpaghettiInfill.h"
namespace cura {
void SpaghettiInfill::generateSpaghettiInfill(SliceMeshStorage& mesh)
{
coord_t layer_height = mesh.getSettingInMicrons("layer_height");
coord_t line_width = mesh.getSettingInMicrons("infill_line_width");
double layer_height_mm = INT2MM(layer_height);
int spaghetti_max_layer_count = std::max(1, static_cast<int>(mesh.getSettingInMicrons("spaghetti_max_height") / layer_height));
// TODO: account for the initial layer height
coord_t filling_area_inset = mesh.getSettingInMicrons("spaghetti_inset");
if (mesh.getSettingInAngleDegrees("spaghetti_max_infill_angle") >= 90)
{
return; // infill cannot be combined into pillars
}
coord_t connection_inset_dist = tan(mesh.getSettingInAngleRadians("spaghetti_max_infill_angle")) * layer_height; // Horizontal component of the spaghetti_max_infill_angle
std::list<SpaghettiInfill::InfillPillar> pillar_base;
size_t min_layer = mesh.getSettingAsCount("bottom_layers") + 1;
size_t max_layer = mesh.layers.size() - 1 - mesh.getSettingAsCount("top_layers");
for (size_t layer_idx = min_layer; layer_idx <= max_layer; layer_idx++) //Skip every few layers, but extrude more.
{
SliceLayer& layer = mesh.layers[layer_idx];
// add infill parts to pillar_base
for (SliceLayerPart& slice_layer_part : layer.parts)
{
std::vector<PolygonsPart> part_infill_parts = slice_layer_part.getOwnInfillArea().splitIntoParts();
// add parts to pillar_base
for (PolygonsPart& infill_part : part_infill_parts)
{
SpaghettiInfill::InfillPillar& pillar = addPartToPillarBase(infill_part, pillar_base, connection_inset_dist);
pillar.top_slice_layer_part = &slice_layer_part;
pillar.last_layer_added = layer_idx;
pillar.layer_count++;
}
}
// handle finished pillars
for (auto it = pillar_base.begin(); it != pillar_base.end();)
{
InfillPillar& pillar = *it;
if (pillar.layer_count >= spaghetti_max_layer_count
|| pillar.last_layer_added < static_cast<int>(layer_idx)
)
{
pillar.addToTopSliceLayerPart(layer_height_mm, filling_area_inset, line_width);
auto to_be_erased = it;
++it;
pillar_base.erase(to_be_erased);
}
else
{
++it;
}
}
}
// handle unfinished pillars
for (auto it = pillar_base.begin(); it != pillar_base.end(); ++it)
{
it->addToTopSliceLayerPart(layer_height_mm, filling_area_inset, line_width);
}
}
void SpaghettiInfill::InfillPillar::addToTopSliceLayerPart(double layer_height_mm, coord_t filling_area_inset, coord_t line_width)
{
SliceLayerPart& slice_layer_part = *top_slice_layer_part;
double volume = total_area_mm2 * layer_height_mm;
assert(volume > 0.0);
// get filling area
Polygons filling_area = top_part.offset(-filling_area_inset);
assert(top_part.size() > 0 && top_part[0].size() > 0 && "the top part must be a non-zero area!");
if (filling_area.size() == 0)
{
AABB aabb(top_part);
Point inside = (aabb.min + aabb.max) / 2;
if (!top_part.inside(inside))
{
inside = top_part[0][0];
}
filling_area = PolygonsPart();
PolygonRef poly = filling_area.newPoly();
poly.emplace_back(inside + Point(-line_width / 2 - 10, line_width / 2 + 10));
poly.emplace_back(inside + Point(line_width / 2 + 10, line_width / 2 + 10));
poly.emplace_back(inside + Point(line_width / 2 + 10, -line_width / 2 - 10));
poly.emplace_back(inside + Point(-line_width / 2 - 10, -line_width / 2 - 10));
}
slice_layer_part.spaghetti_infill_volumes.emplace_back(top_part, volume);
}
bool SpaghettiInfill::InfillPillar::isConnected(const PolygonsPart& infill_part) const
{
Polygons insetted = infill_part.offset(-connection_inset_dist);
if (insetted.intersection(top_part).size() > 0)
{
return true;
}
else
{
return false;
}
}
SpaghettiInfill::InfillPillar& SpaghettiInfill::addPartToPillarBase(const PolygonsPart& infill_part, std::list<SpaghettiInfill::InfillPillar>& pillar_base, coord_t connection_inset_dist)
{
std::list<SpaghettiInfill::InfillPillar>::iterator ret = pillar_base.end();
for (auto it = pillar_base.begin(); it != pillar_base.end(); ++it)
{
InfillPillar& pillar = *it;
if (pillar.isConnected(infill_part))
{
pillar.total_area_mm2 += INT2MM(INT2MM(infill_part.area()));
pillar.top_part = infill_part;
if (ret != pillar_base.end())
{ // connecting two pillars of the layer below via one area on this layer
pillar.total_area_mm2 += ret->total_area_mm2;
pillar_base.erase(ret);
}
ret = it;
}
}
if (ret == pillar_base.end())
{ // couldn't connect to any existing pillar
pillar_base.emplace_back(infill_part, connection_inset_dist);
return pillar_base.back();
}
return *ret;
}
}//namespace cura
+95
Ver Arquivo
@@ -0,0 +1,95 @@
/** Copyright (C) 2017 Ultimaker - Released under terms of the AGPLv3 License */
#ifndef INFILL_SPAGHETTI_INFILL_H
#define INFILL_SPAGHETTI_INFILL_H
#include <list>
#include "../utils/intpoint.h"
#include "../utils/polygon.h"
#include "../sliceDataStorage.h"
namespace cura {
/*!
* Spaghetti infill is a type of infill which fills every so many layers, but extrudes as much filament corresponding to the total unfilled volume under the filling area.
*
* A filling layer is inserted when a a pillar of infill areas is becoming too high, or when the angle between the filling areas is too shallow.
*
* The filling area might be smaller than the actual infill area, so that we fill the pillar from a smaller top area.
*
* Infill pillars can join each other if they are connected on the top. The total volume will then be extruded from the top.
*
* Where the model spits into two from bottom to top, one of the top pieces will be connected to the lower part as one big pillar, while a new pillar will be generated for the other top part.
* Which part the base will be connected to is arbitrary.
*
*/
class SpaghettiInfill
{
public:
/*!
* Generate the filling areas and corresponding volume to extrude over such areas for spaghetti infill.
*/
static void generateSpaghettiInfill(SliceMeshStorage& mesh);
protected:
struct InfillPillar
{
SliceLayerPart* top_slice_layer_part = nullptr; //!< A reference to the slice_layer_part from which the top part is generated
PolygonsPart top_part; //!< The top area of this pillar
double total_area_mm2; //!< The total volume of the pillar divided by the layer height
coord_t connection_inset_dist; //!< Horizontal component of the spaghetti_max_infill_angle: the distance insetted corresponding to the maximum angle which can be filled by spaghetti infill.
int layer_count; //!< The height of the pillar in numer of layers
int last_layer_added = -1; //!< The last layer from which areas got added to this pillar
/*!
* Basic constructor of a pillar from a single area, which is to be the top of the new pillar
*
* \param _top_part The area which is the base and the top of the new pillar
* \param connection_inset_dist Horizontal component of the spaghetti_max_infill_angle
*/
InfillPillar(const PolygonsPart& _top_part, coord_t connection_inset_dist)
: top_part(_top_part) // TODO: prevent copy construction! Is that possible?
, total_area_mm2(INT2MM(INT2MM(top_part.area())))
, connection_inset_dist(connection_inset_dist)
, layer_count(1)
{
}
/*!
* Check whether the top of this pillar is connected (enough) to the given \p infill_part.
* It is assumed the infill_part is on the layer directly above the top part of this pillar.
*
* \param infill_part The part to check for connectivity
* \return Whether the infill part can be incorporated in this pillar
*/
bool isConnected(const PolygonsPart& infill_part) const;
/*!
* Register the volume of this infill pillar in the sliceDataStorage.
* The filling area and the volume are saved in \ref SliceLayerPart::spaghetti_infill_volumes
*
* Note that the filling area is different from the infill area, because the spaghetti can curl toward the sides.
*
* \param layer_height_mm The layer height in millimeters
* \param filling_area_inset The inset from the boundary of the walls to get from the infill area to the filling area
* \param line_width The line width used to generate an area just large enough for infill lines to be generated, when the infill area would otherwise be too small to get infill
*/
void addToTopSliceLayerPart(double layer_height_mm, coord_t filling_area_inset, coord_t line_width);
};
private:
/*!
* Add an area to the pillar base:
* - add it to an existing pillar if possible
* - otherwise create a new pillar for this area
* The pillar to which the area was added is returned
*
* \param infill_part The area to add to the base
* \param pillar_base The collection of pillars used up till the current layer
* \param connection_inset_dist The distance insetted corresponding to the maximum angle which can be filled by spaghetti infill
*/
static InfillPillar& addPartToPillarBase(const PolygonsPart& infill_part, std::list<InfillPillar>& pillar_base, coord_t connection_inset_dist);
};
}//namespace cura
#endif//INFILL_SPAGHETTI_INFILL_H
+5 -11
Ver Arquivo
@@ -3,7 +3,6 @@
#include "layerPart.h"
#include "settings/settings.h"
#include "progress/Progress.h"
#include "multithreadOpenMP.h"
#include "utils/SVG.h" // debug output
@@ -29,8 +28,8 @@ void createLayerWithParts(SliceLayer& storageLayer, SlicerLayer* layer, bool uni
{
for(unsigned int i=0; i<layer->polygons.size(); i++)
{
if (PolygonRef{layer->polygons[i]}.orientation())
PolygonRef{layer->polygons[i]}.reverse();
if (layer->polygons[i].orientation())
layer->polygons[i].reverse();
}
}
@@ -45,17 +44,12 @@ void createLayerWithParts(SliceLayer& storageLayer, SlicerLayer* layer, bool uni
}
void createLayerParts(SliceMeshStorage& mesh, Slicer* slicer, bool union_layers, bool union_all_remove_holes)
{
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(
for(unsigned int layer_nr = 0; layer_nr < slicer->layers.size(); layer_nr++)
{
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)
-21
Ver Arquivo
@@ -1,21 +0,0 @@
/** 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
-182
Ver Arquivo
@@ -1,182 +0,0 @@
/** 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
+10 -10
Ver Arquivo
@@ -16,7 +16,7 @@ void PathOrderOptimizer::optimize()
bool picked[polygons.size()];
memset(picked, false, sizeof(bool) * polygons.size());/// initialized as falses
for (ConstPolygonRef poly : polygons) /// find closest point to initial starting point within each polygon +initialize picked
for (PolygonRef 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)
{
ConstPolygonRef poly = polygons[poly_idx];
PolygonRef 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++)
{
const Point& p1 = poly[point_idx];
const Point& p2 = poly[(point_idx + 1) % poly.size()];
Point& p1 = poly[point_idx];
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();
ConstPolygonRef poly = polygons[poly_idx];
PolygonRef 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
{
ConstPolygonRef best_line = polygons[best_line_idx];
PolygonRef 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
const Point& line_start = best_line[line_start_point_idx];
const Point& line_end = best_line[line_end_point_idx];
Point& line_start = best_line[line_start_point_idx];
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)
{
const Point& p0 = polygons[poly_idx][0];
const Point& p1 = polygons[poly_idx][1];
Point& p0 = polygons[poly_idx][0];
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
+4 -14
Ver Arquivo
@@ -20,7 +20,7 @@ public:
EZSeamType type;
Point startPoint; //!< A location near the prefered start location
Point z_seam_pos; //!< The position near where to create the z_seam (if \ref PathOrderOptimizer::type == 'back')
std::vector<ConstPolygonRef> polygons; //!< the parts of the layer (in arbitrary order)
std::vector<PolygonRef> 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,15 +33,10 @@ public:
void addPolygon(PolygonRef polygon)
{
this->polygons.emplace_back(polygon);
this->polygons.push_back(polygon);
}
void addPolygon(ConstPolygonRef polygon)
{
this->polygons.emplace_back(polygon);
}
void addPolygons(const Polygons& polygons)
void addPolygons(Polygons& polygons)
{
for(unsigned int i=0;i<polygons.size(); i++)
this->polygons.push_back(polygons[i]);
@@ -71,7 +66,7 @@ class LineOrderOptimizer
{
public:
Point startPoint; //!< The location of the nozzle before starting to print the current layer
std::vector<ConstPolygonRef> polygons; //!< the parts of the layer (in arbitrary order)
std::vector<PolygonRef> 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
@@ -85,11 +80,6 @@ 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++)
+1 -1
Ver Arquivo
@@ -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, ConstPolygonRef from, const Point estimated_start, const Point estimated_end, Comb& comber)
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)
{
ClosestPolygonPoint* best_in = nullptr;
ClosestPolygonPoint* best_out = nullptr;
+2 -2
Ver Arquivo
@@ -48,7 +48,7 @@ private:
Point in_or_mid; //!< The point on the inside boundary, or in between the inside and outside boundary if the start/end point isn't inside the inside boudary
Point out; //!< The point on the outside boundary
PolygonsPart dest_part; //!< The assembled inside-boundary PolygonsPart in which the dest_point lies. (will only be initialized when Crossing::dest_is_inside holds)
std::optional<ConstPolygonRef> 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<PolygonRef> 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, ConstPolygonRef from, Point estimated_start, Point estimated_end, Comb& comber);
std::shared_ptr<std::pair<ClosestPolygonPoint, ClosestPolygonPoint>> findBestCrossing(const Polygons& outside, const PolygonRef from, Point estimated_start, Point estimated_end, Comb& comber);
};
+1 -1
Ver Arquivo
@@ -23,7 +23,7 @@ namespace cura
class GCodePath
{
public:
const GCodePathConfig* config; //!< The configuration settings of the path.
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.
+23 -31
Ver Arquivo
@@ -10,16 +10,7 @@
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);
@@ -32,12 +23,6 @@ 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];
@@ -46,7 +31,7 @@ void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost
{
return;
}
int min_infill_area = mesh.getSettingInMillimeters("min_infill_area");
for(unsigned int partNr = 0; partNr < layer.parts.size(); partNr++)
{
SliceLayerPart& part = layer.parts[partNr];
@@ -78,12 +63,22 @@ void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost
{
if (static_cast<int>(layer_nr - downSkinCount) >= 0)
{
downskin = downskin.difference(getInsidePolygons(mesh.layers[layer_nr - downSkinCount])); // skin overlaps with the walls
Polygons not_air = getInsidePolygons(mesh.layers[layer_nr - downSkinCount]);
if (min_infill_area > 0)
{
not_air.removeSmallAreas(min_infill_area);
}
downskin = downskin.difference(not_air); // skin overlaps with the walls
}
if (static_cast<int>(layer_nr + upSkinCount) < static_cast<int>(mesh.layers.size()))
{
upskin = upskin.difference(getInsidePolygons(mesh.layers[layer_nr + upSkinCount])); // skin overlaps with the walls
Polygons not_air = getInsidePolygons(mesh.layers[layer_nr + upSkinCount]);
if (min_infill_area > 0)
{
not_air.removeSmallAreas(min_infill_area);
}
upskin = upskin.difference(not_air); // skin overlaps with the walls
}
}
else
@@ -95,6 +90,10 @@ void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost
{
not_air = not_air.intersection(getInsidePolygons(mesh.layers[downskin_layer_nr]));
}
if (min_infill_area > 0)
{
not_air.removeSmallAreas(min_infill_area);
}
downskin = downskin.difference(not_air); // skin overlaps with the walls
}
@@ -105,6 +104,10 @@ void generateSkinAreas(int layer_nr, SliceMeshStorage& mesh, const int innermost
{
not_air = not_air.intersection(getInsidePolygons(mesh.layers[upskin_layer_nr]));
}
if (min_infill_area > 0)
{
not_air.removeSmallAreas(min_infill_area);
}
upskin = upskin.difference(not_air); // skin overlaps with the walls
}
}
@@ -121,12 +124,7 @@ 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)
@@ -159,12 +157,6 @@ void generateSkinInsets(SliceLayerPart* part, const int wall_line_width, int ins
}
}
/*
* This function is executed in a parallel region based on layer_nr.
* When modifying make sure any changes does not introduce data races.
*
* generateInfill read mesh.layers[n].parts[*].{insets,skin_parts,boundingBox} and write mesh.layers[n].parts[*].infill_area
*/
void generateInfill(int layerNr, SliceMeshStorage& mesh, const int innermost_wall_line_width, int infill_skin_overlap, int wall_line_count)
{
SliceLayer& layer = mesh.layers[layerNr];
+5 -5
Ver Arquivo
@@ -35,7 +35,7 @@ void SliceLayer::getOutlines(Polygons& result, bool external_polys_only) const
{
if (external_polys_only)
{
result.add(part.outline.outerPolygon());
result.add(const_cast<SliceLayerPart&>(part).outline.outerPolygon()); // TODO: make a const version of 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(part.insets[1]);
layer_walls.add(const_cast<SliceLayerPart&>(part).insets[1]); // TODO const cast!
continue;
}
// but we'll also take the inner wall if the 2nd doesn't exist
if (part.insets.size() == 1) {
layer_walls.add(part.insets[0]);
layer_walls.add(const_cast<SliceLayerPart&>(part).insets[0]); // TODO const cast!
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 (mesh.getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL)
if (const_cast<SliceMeshStorage&>(mesh).getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL) // TODO: make all getSetting functions const??
{
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 (mesh.getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL)
if (const_cast<SliceMeshStorage&>(mesh).getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL) // TODO: make getSetting const? make settings.setting_values mapping mutable??
{
total = total.unionPolygons(layer.openPolyLines.offsetPolyLine(100));
}
+2
Ver Arquivo
@@ -74,6 +74,8 @@ public:
* \return the own infill area
*/
Polygons& getOwnInfillArea();
std::vector<std::pair<PolygonsPart, double>> spaghetti_infill_volumes; //!< For each filling volume on this layer, the area within which to fill and the total volume to fill over the area
};
/*!
+15 -21
Ver Arquivo
@@ -8,7 +8,6 @@
#include "utils/SparsePointGridInclusive.h"
#include "slicer.h"
#include "multithreadOpenMP.h"
namespace cura {
@@ -217,7 +216,7 @@ SlicerLayer::findPossibleStitches(
// insert the starts of the polylines).
for(unsigned int polyline_0_idx = 0; polyline_0_idx < open_polylines.size(); polyline_0_idx++)
{
ConstPolygonRef polyline_0 = open_polylines[polyline_0_idx];
const PolygonRef polyline_0 = open_polylines[polyline_0_idx];
if (polyline_0.size() < 1) continue;
@@ -232,7 +231,7 @@ SlicerLayer::findPossibleStitches(
{
for(unsigned int polyline_0_idx = 0; polyline_0_idx < open_polylines.size(); polyline_0_idx++)
{
ConstPolygonRef polyline_0 = open_polylines[polyline_0_idx];
const PolygonRef polyline_0 = open_polylines[polyline_0_idx];
if (polyline_0.size() < 1) continue;
@@ -246,7 +245,7 @@ SlicerLayer::findPossibleStitches(
// search for nearby end points
for(unsigned int polyline_1_idx = 0; polyline_1_idx < open_polylines.size(); polyline_1_idx++)
{
ConstPolygonRef polyline_1 = open_polylines[polyline_1_idx];
const PolygonRef polyline_1 = open_polylines[polyline_1_idx];
if (polyline_1.size() < 1) continue;
@@ -590,7 +589,7 @@ void SlicerLayer::stitch_extensive(Polygons& open_polylines)
{
if (best_result.pointIdxA == best_result.pointIdxB)
{
polygons.add(PolygonRef{open_polylines[best_polyline_1_idx]});
polygons.add(open_polylines[best_polyline_1_idx]);
open_polylines[best_polyline_1_idx].clear();
}
else if (best_result.AtoB)
@@ -605,9 +604,9 @@ void SlicerLayer::stitch_extensive(Polygons& open_polylines)
else
{
unsigned int n = polygons.size();
polygons.add(PolygonRef{open_polylines[best_polyline_1_idx]});
polygons.add(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())
PolygonRef{polygons[n]}.add(polygons[best_result.polygonIdx][j]);
polygons[n].add(polygons[best_result.polygonIdx][j]);
open_polylines[best_polyline_1_idx].clear();
}
}
@@ -616,7 +615,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++)
PolygonRef{open_polylines[best_polyline_2_idx]}.add(open_polylines[best_polyline_1_idx][n]);
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)
@@ -625,17 +624,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--)
PolygonRef{open_polylines[best_polyline_2_idx]}.add(poly[n]);
open_polylines[best_polyline_2_idx].add(poly[n]);
for(unsigned int n=0; n<open_polylines[best_polyline_1_idx].size(); n++)
PolygonRef{open_polylines[best_polyline_2_idx]}.add(open_polylines[best_polyline_1_idx][n]);
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())
PolygonRef{open_polylines[best_polyline_2_idx]}.add(polygons[best_result.polygonIdx][n]);
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--)
PolygonRef{open_polylines[best_polyline_2_idx]}.add(open_polylines[best_polyline_1_idx][n]);
open_polylines[best_polyline_2_idx].add(open_polylines[best_polyline_1_idx][n]);
open_polylines[best_polyline_1_idx].clear();
}
}
@@ -888,15 +887,10 @@ Slicer::Slicer(Mesh* mesh, int initial, int thickness, int slice_layer_count, bo
}
}
log("slice of mesh took %.3f seconds\n",slice_timer.restart());
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();
for(unsigned int layer_nr=0; layer_nr<layers.size(); layer_nr++)
{
layers[layer_nr].makePolygons(mesh, keep_none_closed, extensive_stitching);
}
mesh->expandXY(mesh->getSettingInMicrons("xy_offset"));
log("slice make polygons took %.3f seconds\n",slice_timer.restart());
}
+1 -1
Ver Arquivo
@@ -508,7 +508,7 @@ void AreaSupport::handleTowers(
{
supportLayer_this = supportLayer_this.unionPolygons(tower_roof);
if (PolygonRef{tower_roof[0]}.area() < supportTowerDiameter * supportTowerDiameter)
if (tower_roof[0].area() < supportTowerDiameter * supportTowerDiameter)
{
tower_roof = tower_roof.offset(towerRoofExpansionDistance);
}
+2 -2
Ver Arquivo
@@ -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
Ver Arquivo
@@ -20,10 +20,10 @@ public:
AABB(); //!< initializes with invalid min and max
AABB(Point& min, Point& max); //!< initializes with given min and max
AABB(const Polygons& polys); //!< Computes the boundary box for the given polygons
AABB(const PolygonRef& poly); //!< Computes the boundary box for the given polygons
AABB(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.
+2 -2
Ver Arquivo
@@ -19,12 +19,12 @@ void ListPolyIt::convertPolygonsToLists(Polygons& polys, ListPolygons& result)
}
}
void ListPolyIt::convertPolygonToList(const PolygonRef& poly, ListPolygon& result)
void ListPolyIt::convertPolygonToList(PolygonRef poly, ListPolygon& result)
{
#ifdef DEBUG
Point last = poly.back();
#endif // DEBUG
for (const Point& p : poly)
for (Point& p : poly)
{
result.push_back(p);
#ifdef DEBUG
+1 -1
Ver Arquivo
@@ -101,7 +101,7 @@ public:
* \param polys The polygons to convert
* \param result The converted polygons
*/
static void convertPolygonToList(const PolygonRef& poly, ListPolygon& result);
static void convertPolygonToList(PolygonRef poly, ListPolygon& result);
/*!
* Convert ListPolygons to Polygons
*
+1 -1
Ver Arquivo
@@ -46,7 +46,7 @@ public:
/*!
* Get the polygon to which this PolygonsPointIndex refers
*/
const ConstPolygonRef getPolygon() const
const PolygonRef getPolygon() const
{
return (*polygons)[poly_idx];
}
+5 -5
Ver Arquivo
@@ -93,7 +93,7 @@ public:
{
for(unsigned int j=0;j<parts.size();j++)
{
Polygon poly = PolygonRef{parts[j]};
Polygon poly = parts[j];
fprintf(out, "<polygon points=\"");
for(Point& p : poly)
{
@@ -130,9 +130,9 @@ public:
}
}
void writePoints(ConstPolygonRef poly, bool write_coords=false, int size = 5, Color color = Color::BLACK)
void writePoints(PolygonRef poly, bool write_coords=false, int size = 5, Color color = Color::BLACK)
{
for (const Point& p : poly)
for (Point& p : poly)
{
writePoint(p, write_coords, size, color);
}
@@ -209,12 +209,12 @@ public:
}
void writePolygons(const Polygons& polys, Color color = Color::BLACK)
{
for (ConstPolygonRef poly : polys)
for (const PolygonRef poly : const_cast<Polygons&>(polys))
{
writePolygon(poly, color);
}
}
void writePolygon(ConstPolygonRef poly, Color color = Color::BLACK)
void writePolygon(const PolygonRef poly, Color color = Color::BLACK)
{
Point p0 = poly.back();
for (Point p1 : poly)
+56 -66
Ver Arquivo
@@ -8,23 +8,6 @@
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;
@@ -44,7 +27,7 @@ bool PolygonRef::shorterThan(int64_t check_length) const
bool PolygonRef::_inside(Point p, bool border_result) const
{
const PolygonRef& thiss = *this;
PolygonRef thiss = *this;
if (size() < 1)
{
return false;
@@ -207,6 +190,22 @@ unsigned int Polygons::findInside(Point p, bool border_result)
return ret;
}
int64_t Polygons::polyLineLength() const
{
int64_t length = 0;
for (unsigned int poly_idx = 0; poly_idx < paths.size(); poly_idx++)
{
Point p0 = paths[poly_idx][0];
for (unsigned int point_idx = 1; point_idx < paths[poly_idx].size(); point_idx++)
{
Point p1 = paths[poly_idx][point_idx];
length += vSize(p0 - p1);
p0 = p1;
}
}
return length;
}
Polygons Polygons::offset(int distance, ClipperLib::JoinType join_type, double miter_limit) const
{
Polygons ret;
@@ -220,7 +219,10 @@ 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;
PolygonRef_offset_impl(ret.paths, *path, distance, joinType, miter_limit);
ClipperLib::ClipperOffset clipper(miter_limit, 10.0);
clipper.AddPath(*path, joinType, ClipperLib::etClosedPolygon);
clipper.MiterLimit = miter_limit;
clipper.Execute(ret.paths, distance);
return ret;
}
@@ -851,7 +853,6 @@ void PolygonRef::smooth_corner_simple(ListPolygon& poly, const Point p0, const P
Point b;
bool success = LinearAlg2D::getPointOnLineWithDist(a, p1, p2, shortcut_length, b);
// v02 has to be longer than ab!
p1_it.remove();
if (success)
{ // if not success then assume b is negligibly close to 2, but rounding errors caused a problem
#ifdef ASSERT_INSANE_OUTPUT
@@ -859,6 +860,7 @@ void PolygonRef::smooth_corner_simple(ListPolygon& poly, const Point p0, const P
#endif // #ifdef ASSERT_INSANE_OUTPUT
ListPolyIt::insertPointNonDuplicate(p1_it, p2_it, b);
}
p1_it.remove();
}
}
}
@@ -966,7 +968,7 @@ Polygons Polygons::smooth_outward(float max_angle, int shortcut_length)
return ret;
}
inline void PolygonRef_smooth_impl(const ClipperLib::Path& thiss, int remove_length, ClipperLib::Path* poly)
void PolygonRef::smooth(int remove_length, PolygonRef result)
{
// a typical zigzag with the middle part to be removed by removing (1) :
//
@@ -981,7 +983,9 @@ inline void PolygonRef_smooth_impl(const ClipperLib::Path& thiss, int remove_len
// |
// |
// 0
if (thiss.size() > 0)
PolygonRef& thiss = *this;
ClipperLib::Path* poly = result.path;
if (size() > 0)
{
poly->push_back(thiss[0]);
}
@@ -1015,11 +1019,11 @@ inline void PolygonRef_smooth_impl(const ClipperLib::Path& thiss, int remove_len
Point v02T = turn90CCW(v02);
int64_t v02_size = vSize(v02);
bool force_push = false;
for (unsigned int poly_idx = 1; poly_idx < thiss.size(); poly_idx++)
for (unsigned int poly_idx = 1; poly_idx < size(); poly_idx++)
{
const Point& p1 = thiss[poly_idx];
const Point& p2 = thiss[(poly_idx + 1) % thiss.size()];
const Point& p3 = thiss[(poly_idx + 2) % thiss.size()];
const Point& p2 = thiss[(poly_idx + 1) % size()];
const Point& p3 = thiss[(poly_idx + 2) % size()];
// v02 computed in last iteration
// v02_size as well
const Point v12 = p2 - p1;
@@ -1048,22 +1052,12 @@ inline void PolygonRef_smooth_impl(const ClipperLib::Path& thiss, int remove_len
}
}
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 Polygons::smooth(int remove_length)
{
Polygons ret;
for (unsigned int p = 0; p < size(); p++)
{
ConstPolygonRef poly(paths[p]);
PolygonRef poly(paths[p]);
if (poly.size() < 3)
{
continue;
@@ -1083,21 +1077,23 @@ Polygons Polygons::smooth(int remove_length) const
return ret;
}
inline void PolygonRef_smooth2_impl(const ClipperLib::Path& thiss, int remove_length, ClipperLib::Path* poly)
void PolygonRef::smooth2(int remove_length, PolygonRef result)
{
if (thiss.size() > 0)
PolygonRef& thiss = *this;
ClipperLib::Path* poly = result.path;
if (size() > 0)
{
poly->push_back(thiss[0]);
}
for (unsigned int poly_idx = 1; poly_idx < thiss.size(); poly_idx++)
for (unsigned int poly_idx = 1; poly_idx < size(); poly_idx++)
{
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))
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))
{
poly_idx++; // skip the next line piece (dont escalate the removal of edges)
if (poly_idx < thiss.size())
if (poly_idx < size())
{
poly->push_back(thiss[poly_idx]);
}
@@ -1109,22 +1105,12 @@ inline void PolygonRef_smooth2_impl(const ClipperLib::Path& thiss, int remove_le
}
}
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 Polygons::smooth2(int remove_length, int min_area)
{
Polygons ret;
for (unsigned int p = 0; p < size(); p++)
{
ConstPolygonRef poly(paths[p]);
PolygonRef poly(paths[p]);
if (poly.size() == 0)
{
continue;
@@ -1146,11 +1132,15 @@ Polygons Polygons::smooth2(int remove_length, int min_area) const
return ret;
}
Polygons ConstPolygonRef::offset(int distance, ClipperLib::JoinType joinType, double miter_limit) const
double PolygonsPart::area() const
{
Polygons ret;
PolygonRef_offset_impl(ret.paths, *path, distance, joinType, miter_limit);
return ret;
double area = 0;
for (unsigned int poly_idx = 0; poly_idx < size(); poly_idx++)
{
area += operator[](poly_idx).area();
// note: holes have negative area
}
return area;
}
std::vector<PolygonsPart> Polygons::splitIntoParts(bool unionAll) const
@@ -1174,10 +1164,10 @@ void Polygons::splitIntoParts_processPolyTreeNode(ClipperLib::PolyNode* node, st
{
ClipperLib::PolyNode* child = node->Childs[n];
PolygonsPart part;
part.add(ConstPolygonRef{child->Contour});
part.add(child->Contour);
for(int i=0; i<child->ChildCount(); i++)
{
part.add(ConstPolygonRef{child->Childs[i]->Contour});
part.add(child->Childs[i]->Contour);
splitIntoParts_processPolyTreeNode(child->Childs[i], ret);
}
ret.push_back(part);
@@ -1209,7 +1199,7 @@ PolygonsPart PartsView::assemblePart(unsigned int part_idx) const
{
for (unsigned int poly_idx_ff : partsView[part_idx])
{
ret.add(PolygonRef{polygons[poly_idx_ff]});
ret.add(polygons[poly_idx_ff]);
}
}
return ret;
@@ -1252,11 +1242,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(ConstPolygonRef{child->Contour}); //TODO: should this steal the internal representation for speed?
reordered.add(child->Contour);
for(int i = 0; i < child->ChildCount(); i++)
{
partsView[pos].push_back(reordered.size());
reordered.add(ConstPolygonRef{child->Childs[i]->Contour});
reordered.add(child->Childs[i]->Contour);
splitIntoPartsView_processPolyTreeNode(partsView, reordered, child->Childs[i]);
}
}
+29 -228
Ver Arquivo
@@ -43,12 +43,6 @@ class PolygonRef
: path(nullptr)
{}
public:
PolygonRef(PolygonRef& polygon)
:path{polygon.path}
{}
PolygonRef(PolygonRef&& polygon)
:path{polygon.path}
{}
PolygonRef(ClipperLib::Path& polygon)
: path(&polygon)
{}
@@ -84,9 +78,7 @@ 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)
{
@@ -198,7 +190,7 @@ public:
return Point(x, y);
}
Point closestPointTo(Point p) const
Point closestPointTo(Point p)
{
Point ret = p;
float bestDist = FLT_MAX;
@@ -261,7 +253,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) const;
void smooth(int remove_length, PolygonRef result);
/*!
* Smooth out sharp inner corners, by taking a shortcut which bypasses the corner
@@ -279,7 +271,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) const;
void smooth2(int remove_length, PolygonRef result);
/*!
* Removes consecutive line segments with same orientation and changes this polygon.
@@ -383,193 +375,6 @@ 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;
@@ -592,7 +397,6 @@ class Polygons
{
friend class Polygon;
friend class PolygonRef;
friend class ConstPolygonRef;
protected:
ClipperLib::Paths paths;
public:
@@ -603,14 +407,14 @@ public:
unsigned int pointCount() const; //!< Return the amount of points in all polygons
ClipperLib::Path& operator[] (unsigned int index)
PolygonRef operator[] (unsigned int index)
{
POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max());
return paths[index];
return PolygonRef(paths[index]);
}
ConstPolygonRef operator[] (unsigned int index) const
const PolygonRef operator[] (unsigned int index) const
{
return paths[index];
return const_cast<Polygons*>(this)->operator[](index);
}
ClipperLib::Paths::iterator begin()
{
@@ -657,10 +461,6 @@ 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));
@@ -684,14 +484,14 @@ public:
paths.emplace_back(args...);
}
ClipperLib::Path& newPoly()
PolygonRef newPoly()
{
paths.emplace_back();
return paths.back();
return PolygonRef(paths.back());
}
ClipperLib::Path& back()
PolygonRef back()
{
return paths.back();
return PolygonRef(paths.back());
}
Polygons() {}
@@ -847,7 +647,7 @@ public:
* \param remove_length The length of the largest segment removed
* \return The smoothed polygon
*/
Polygons smooth(int remove_length) const;
Polygons smooth(int remove_length);
/*!
* Smooth out sharp inner corners, by taking a shortcut which bypasses the corner
@@ -858,7 +658,7 @@ public:
*/
Polygons smooth_outward(float angle, int shortcut_length);
Polygons smooth2(int remove_length, int min_area) const; //!< removes points connected to small lines
Polygons smooth2(int remove_length, int min_area); //!< removes points connected to small lines
/*!
* removes points connected to similarly oriented lines
@@ -873,7 +673,7 @@ public:
Polygons& thiss = *this;
for (unsigned int p = 0; p < size(); p++)
{
PolygonRef{thiss[p]}.simplify(smallest_line_segment_squared, allowed_error_distance_squared);
thiss[p].simplify(smallest_line_segment_squared, allowed_error_distance_squared);
if (thiss[p].size() < 3)
{
remove(p);
@@ -934,7 +734,7 @@ public:
Polygons& thiss = *this;
for(unsigned int i=0; i<size(); i++)
{
double area = INT2MM(INT2MM(fabs(PolygonRef{thiss[i]}.area())));
double area = INT2MM(INT2MM(fabs(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);
@@ -998,16 +798,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(const Polygons& to_be_removed, int same_distance = 0) const
Polygons remove(Polygons& to_be_removed, int same_distance = 0)
{
Polygons result;
for (unsigned int poly_keep_idx = 0; poly_keep_idx < size(); poly_keep_idx++)
{
ConstPolygonRef poly_keep = (*this)[poly_keep_idx];
PolygonRef 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 (ConstPolygonRef poly_rem : to_be_removed)
for (PolygonRef 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;
@@ -1074,6 +874,8 @@ public:
}
return length;
}
int64_t polyLineLength() const;
Point min() const
{
@@ -1123,28 +925,27 @@ public:
class PolygonsPart : public Polygons
{
public:
PolygonRef outerPolygon()
PolygonRef outerPolygon()
{
return this->paths[0];
}
ConstPolygonRef outerPolygon() const
{
return this->paths[0];
Polygons& thiss = *this;
return thiss[0];
}
bool inside(Point p)
bool inside(Point p) const
{
if (size() < 1)
return false;
if (!PolygonRef{(*this)[0]}.inside(p))
if (!(*this)[0].inside(p))
return false;
for(unsigned int n=1; n<paths.size(); n++)
{
if (PolygonRef{(*this)[n]}.inside(p))
if ((*this)[n].inside(p))
return false;
}
return true;
}
double area() const;
};
/*!
+38 -38
Ver Arquivo
@@ -22,7 +22,7 @@ int64_t PolygonUtils::segmentLength(PolygonsPointIndex start, PolygonsPointIndex
assert(start.poly_idx == end.poly_idx);
int64_t segment_length = 0;
Point prev_vert = start.p();
ConstPolygonRef poly = (*start.polygons)[start.poly_idx];
const PolygonRef 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);
ConstPolygonRef poly = (*start.polygons)[start.poly_idx];
const PolygonRef 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(ConstPolygonRef poly, unsigned int point_idx)
Point PolygonUtils::getVertexInwardNormal(PolygonRef poly, unsigned int point_idx)
{
Point p1 = poly[point_idx];
@@ -110,7 +110,7 @@ Point PolygonUtils::getVertexInwardNormal(ConstPolygonRef poly, unsigned int poi
break;
}
}
const Point& p2 = poly[p2_idx];
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(ConstPolygonRef poly, unsigned int poi
}
Point PolygonUtils::getBoundaryPointWithOffset(ConstPolygonRef poly, unsigned int point_idx, int64_t offset)
Point PolygonUtils::getBoundaryPointWithOffset(PolygonRef 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;
}
ConstPolygonRef poly = *point_on_boundary.poly;
PolygonRef 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, 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)
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)
{
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++)
{
ConstPolygonRef poly = polygons[poly_idx];
const PolygonRef 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;
}
ConstPolygonRef poly = *cpp.poly;
const PolygonRef poly = *cpp.poly;
unsigned int point_idx = cpp.point_idx;
const Point& on_boundary = cpp.location;
const Point& p1 = poly[point_idx];
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;
}
}
const Point& p2 = poly[p2_idx];
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
}
ConstPolygonRef closest_poly = *closest_polygon_point.poly;
PolygonRef 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;
}
ConstPolygonRef poly1 = *poly1_result.poly;
ConstPolygonRef poly2 = *poly2_result.poly;
PolygonRef poly1 = *poly1_result.poly;
PolygonRef poly2 = *poly2_result.poly;
if (poly1.size() == 0 || poly2.size() == 0)
{
return;
@@ -515,8 +515,8 @@ void PolygonUtils::walkToNearestSmallestConnection(ClosestPolygonPoint& poly1_re
{
return;
}
ConstPolygonRef poly1 = *poly1_result.poly;
ConstPolygonRef poly2 = *poly2_result.poly;
PolygonRef poly1 = *poly1_result.poly;
PolygonRef 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, ConstPolygonRef polygon, int start_idx)
ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, PolygonRef polygon, int start_idx)
{
ClosestPolygonPoint forth = findNearestClosest(from, polygon, start_idx, 1);
if (!forth.isValid())
@@ -556,7 +556,7 @@ ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, ConstPolygonRef
}
}
ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, ConstPolygonRef polygon, int start_idx, int direction)
ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, PolygonRef polygon, int start_idx, int direction)
{
if (polygon.size() == 0)
{
@@ -572,8 +572,8 @@ ClosestPolygonPoint PolygonUtils::findNearestClosest(Point from, ConstPolygonRef
{
int p1_idx = (polygon.size() + direction*p + start_idx) % polygon.size();
int p2_idx = (polygon.size() + direction*(p+1) + start_idx) % polygon.size();
const Point& p1 = polygon[p1_idx];
const Point& p2 = polygon[p2_idx];
Point& p1 = polygon[p1_idx];
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;
}
ConstPolygonRef any_polygon = polygons[0];
PolygonRef 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++)
{
ConstPolygonRef poly = polygons[ply];
const PolygonRef 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, ConstPolygonRef polygon, const std::function<int(Point)>& penalty_function)
ClosestPolygonPoint PolygonUtils::findClosest(Point from, const PolygonRef polygon, const std::function<int(Point)>& penalty_function)
{
if (polygon.size() == 0)
{
@@ -653,11 +653,11 @@ ClosestPolygonPoint PolygonUtils::findClosest(Point from, ConstPolygonRef polygo
//
for (unsigned int p = 0; p<polygon.size(); p++)
{
const Point& p1 = polygon[p];
Point& p1 = polygon[p];
unsigned int p2_idx = p+1;
if (p2_idx >= polygon.size()) p2_idx = 0;
const Point& p2 = polygon[p2_idx];
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++)
{
ConstPolygonRef poly = polys[poly_idx];
const PolygonRef 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++)
{
ConstPolygonRef poly = polygons[poly_idx];
const PolygonRef 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)
{
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()];
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()];
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(
ConstPolygonRef from, const Polygons& destination,
const PolygonRef 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, ConstPolygonRef poly, int start_idx, int poly_start_idx, GivenDistPoint& result)
bool PolygonUtils::getNextPointWithDistance(Point from, int64_t dist, const PolygonRef 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, ConstPolyg
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]...
const Point& next_poly_point = poly[next_idx];
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(ConstPolygonRef poly, const Point& transformed_startPoint, const Point& transformed_endPoint, PointMatrix transformation_matrix)
bool PolygonUtils::polygonCollidesWithLineSegment(const PolygonRef poly, Point& transformed_startPoint, Point& transformed_endPoint, PointMatrix transformation_matrix)
{
Point p0 = transformation_matrix.apply(poly.back());
for(Point p1_ : poly)
@@ -947,7 +947,7 @@ bool PolygonUtils::polygonCollidesWithLineSegment(ConstPolygonRef poly, const Po
return false;
}
bool PolygonUtils::polygonCollidesWithLineSegment(PolygonRef poly, const Point& startPoint, const Point& endPoint)
bool PolygonUtils::polygonCollidesWithLineSegment(const PolygonRef poly, Point& startPoint, Point& endPoint)
{
Point diff = endPoint - startPoint;
@@ -958,9 +958,9 @@ bool PolygonUtils::polygonCollidesWithLineSegment(PolygonRef poly, const Point&
return PolygonUtils::polygonCollidesWithLineSegment(poly, transformed_startPoint, transformed_endPoint, transformation_matrix);
}
bool PolygonUtils::polygonCollidesWithLineSegment(const Polygons& polys, const Point& transformed_startPoint, const Point& transformed_endPoint, PointMatrix transformation_matrix)
bool PolygonUtils::polygonCollidesWithLineSegment(const Polygons& polys, Point& transformed_startPoint, Point& transformed_endPoint, PointMatrix transformation_matrix)
{
for (ConstPolygonRef poly : polys)
for (const PolygonRef poly : const_cast<Polygons&>(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, const P
}
bool PolygonUtils::polygonCollidesWithLineSegment(const Polygons& polys, const Point& startPoint, const Point& endPoint)
bool PolygonUtils::polygonCollidesWithLineSegment(const Polygons& polys, Point& startPoint, Point& endPoint)
{
Point diff = endPoint - startPoint;
+17 -17
Ver Arquivo
@@ -20,12 +20,12 @@ namespace cura
struct ClosestPolygonPoint
{
Point location; //!< Result location
std::optional<ConstPolygonRef> poly; //!< Polygon in which the result was found (or none if no result was found)
std::optional<PolygonRef> 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, 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(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() : 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
{
ConstPolygonRef poly = (*val.polygons)[val.poly_idx];
PolygonRef 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(ConstPolygonRef poly, unsigned int point_idx);
static Point getVertexInwardNormal(PolygonRef 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(ConstPolygonRef poly, unsigned int point_idx, int64_t offset);
static Point getBoundaryPointWithOffset(PolygonRef 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, 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);
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);
/*!
* 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, ConstPolygonRef polygon, int start_idx);
static ClosestPolygonPoint findNearestClosest(Point from, const PolygonRef 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, ConstPolygonRef polygon, int start_idx, int direction);
static ClosestPolygonPoint findNearestClosest(const Point from, const PolygonRef 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, ConstPolygonRef polygon, const std::function<int(Point)>& penalty_function = no_penalty_function);
static ClosestPolygonPoint findClosest(Point from, const PolygonRef 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(ConstPolygonRef 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(const PolygonRef 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, ConstPolygonRef poly, int start_idx, int poly_start_idx, GivenDistPoint& result);
static bool getNextPointWithDistance(Point from, int64_t dist, const PolygonRef 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(ConstPolygonRef poly, const Point& transformed_startPoint, const Point& transformed_endPoint, PointMatrix transformation_matrix);
static bool polygonCollidesWithLineSegment(const PolygonRef poly, Point& transformed_startPoint, 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, const Point& startPoint, const Point& endPoint);
static bool polygonCollidesWithLineSegment(const PolygonRef poly, Point& startPoint, 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, const Point& transformed_startPoint, const Point& transformed_endPoint, PointMatrix transformation_matrix);
static bool polygonCollidesWithLineSegment(const Polygons& polys, Point& transformed_startPoint, 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, const Point& startPoint, const Point& endPoint);
static bool polygonCollidesWithLineSegment(const Polygons& polys, Point& startPoint, Point& endPoint);
private:
/*!
+4 -1
Ver Arquivo
@@ -1,3 +1,6 @@
//Copyright (c) 2017 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
#ifndef UTILS_STRING_H
#define UTILS_STRING_H
@@ -35,7 +38,7 @@ static inline void writeInt2mm(const int64_t coord, std::ostream& ss)
{
constexpr size_t buffer_size = 24;
char buffer[buffer_size];
int char_count = sprintf(buffer, "%" PRId64, coord); // convert int to string
int char_count = sprintf(buffer, "%d", int(coord)); // convert int to string
#ifdef DEBUG
if (char_count + 1 >= int(buffer_size)) // + 1 for the null character
{
+1 -1
Ver Arquivo
@@ -18,7 +18,7 @@ WallOverlapComputation::WallOverlapComputation(Polygons& polygons, int line_widt
}
float WallOverlapComputation::getFlow(const Point& from, const Point& to)
float WallOverlapComputation::getFlow(Point& from, Point& to)
{
using Point2LinkIt = PolygonProximityLinker::Point2Link::iterator;
+1 -1
Ver Arquivo
@@ -60,7 +60,7 @@ public:
* \param to The ending of the line segment
* \return a value between zero and one representing the reduced flow of the line segment
*/
float getFlow(const Point& from, const Point& to);
float getFlow(Point& from, Point& to);
/*!
* Computes the neccesary priliminaries in order to efficiently compute the flow when generatign gcode paths.
+4 -1
Ver Arquivo
@@ -235,11 +235,14 @@ class Setting:
tree = ast.parse(code, "eval")
compiled = compile(code, self._key, "eval")
except (SyntaxError, TypeError) as e:
print("Parse error in function (" + code + ") for setting", self._key + ":", str(e))
print("Parse error in function (" + str(code) + ") for setting", self._key + ":", str(e))
return None
except IllegalMethodError as e:
print("Use of illegal method", str(e), "in function (" + code + ") for setting", self._key)
return None
except Exception as e:
print("Exception in function (" + code + ") for setting", self._key + ":", str(e))
return None
return eval(compiled, globals(), locals)