mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-15 21:45:57 +08:00
merge complete
This commit is contained in:
parent
a4f9c28a9a
commit
a36142d258
@ -244,26 +244,26 @@ Polygons BridgeDetector::coverage(double angle, bool precise) const {
|
|||||||
if (n_supported >= 2) {
|
if (n_supported >= 2) {
|
||||||
// trim it to not allow to go outside of the intersections
|
// trim it to not allow to go outside of the intersections
|
||||||
BoundingBox center_bound = intersects[0].bounding_box();
|
BoundingBox center_bound = intersects[0].bounding_box();
|
||||||
coord_t min_y = center_bound.center().y, max_y = center_bound.center().y;
|
coord_t min_y = center_bound.center()(1), max_y = center_bound.center()(1);
|
||||||
for (Polygon &poly_bound : intersects) {
|
for (Polygon &poly_bound : intersects) {
|
||||||
center_bound = poly_bound.bounding_box();
|
center_bound = poly_bound.bounding_box();
|
||||||
if (min_y > center_bound.center().y) min_y = center_bound.center().y;
|
if (min_y > center_bound.center()(1)) min_y = center_bound.center()(1);
|
||||||
if (max_y < center_bound.center().y) max_y = center_bound.center().y;
|
if (max_y < center_bound.center()(1)) max_y = center_bound.center()(1);
|
||||||
}
|
}
|
||||||
coord_t min_x = trapezoid[0].x, max_x = trapezoid[0].x;
|
coord_t min_x = trapezoid[0](0), max_x = trapezoid[0](0);
|
||||||
for (Point &p : trapezoid.points) {
|
for (Point &p : trapezoid.points) {
|
||||||
if (min_x > p.x) min_x = p.x;
|
if (min_x > p(0)) min_x = p(0);
|
||||||
if (max_x < p.x) max_x = p.x;
|
if (max_x < p(0)) max_x = p(0);
|
||||||
}
|
}
|
||||||
//add what get_trapezoids3 has removed (+EPSILON)
|
//add what get_trapezoids3 has removed (+EPSILON)
|
||||||
min_x -= (this->spacing / 4 + 1);
|
min_x -= (this->spacing / 4 + 1);
|
||||||
max_x += (this->spacing / 4 + 1);
|
max_x += (this->spacing / 4 + 1);
|
||||||
coord_t mid_x = (min_x + max_x) / 2;
|
coord_t mid_x = (min_x + max_x) / 2;
|
||||||
for (Point &p : trapezoid.points) {
|
for (Point &p : trapezoid.points) {
|
||||||
if (p.y < min_y) p.y = min_y;
|
if (p(1) < min_y) p(1) = min_y;
|
||||||
if (p.y > max_y) p.y = max_y;
|
if (p(1) > max_y) p(1) = max_y;
|
||||||
if (p.x > min_x && p.x < mid_x) p.x = min_x;
|
if (p(0) > min_x && p(0) < mid_x) p(0) = min_x;
|
||||||
if (p.x < max_x && p.x > mid_x) p.x = max_x;
|
if (p(0) < max_x && p(0) > mid_x) p(0) = max_x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,11 +314,11 @@ ExPolygon::get_trapezoids3_half(Polygons* polygons, float spacing) const {
|
|||||||
BoundingBox bb(pp);
|
BoundingBox bb(pp);
|
||||||
|
|
||||||
// get all x coordinates
|
// get all x coordinates
|
||||||
int min_x = pp[0].x, max_x = pp[0].x;
|
int min_x = pp[0].x(), max_x = pp[0].x();
|
||||||
std::vector<coord_t> xx;
|
std::vector<coord_t> xx;
|
||||||
for (Points::const_iterator p = pp.begin(); p != pp.end(); ++p) {
|
for (Points::const_iterator p = pp.begin(); p != pp.end(); ++p) {
|
||||||
if (min_x > p->x) min_x = p->x;
|
if (min_x > p->x()) min_x = p->x();
|
||||||
if (max_x < p->x) max_x = p->x;
|
if (max_x < p->x()) max_x = p->x();
|
||||||
}
|
}
|
||||||
for (int x = min_x; x < max_x-spacing/2; x += spacing) {
|
for (int x = min_x; x < max_x-spacing/2; x += spacing) {
|
||||||
xx.push_back(x);
|
xx.push_back(x);
|
||||||
@ -334,14 +334,14 @@ ExPolygon::get_trapezoids3_half(Polygons* polygons, float spacing) const {
|
|||||||
// build rectangle
|
// build rectangle
|
||||||
Polygon poly;
|
Polygon poly;
|
||||||
poly.points.resize(4);
|
poly.points.resize(4);
|
||||||
poly[0].x = *x +spacing / 4;
|
poly[0].x() = *x + spacing / 4;
|
||||||
poly[0].y = bb.min.y;
|
poly[0].y() = bb.min(1);
|
||||||
poly[1].x = next_x -spacing / 4;
|
poly[1].x() = next_x - spacing / 4;
|
||||||
poly[1].y = bb.min.y;
|
poly[1].y() = bb.min(1);
|
||||||
poly[2].x = next_x -spacing / 4;
|
poly[2].x() = next_x - spacing / 4;
|
||||||
poly[2].y = bb.max.y;
|
poly[2].y() = bb.max(1);
|
||||||
poly[3].x = *x +spacing / 4;
|
poly[3].x() = *x + spacing / 4;
|
||||||
poly[3].y = bb.max.y;
|
poly[3].y() = bb.max(1);
|
||||||
|
|
||||||
// intersect with this expolygon
|
// intersect with this expolygon
|
||||||
// append results to return value
|
// append results to return value
|
||||||
|
@ -59,7 +59,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
layerm.fill_surfaces.group(&groups);
|
layerm.fill_surfaces.group(&groups);
|
||||||
|
|
||||||
//if internal infill can be dense, place it on his own group
|
//if internal infill can be dense, place it on his own group
|
||||||
if (layerm.region()->config.infill_dense.getBool() && layerm.region()->config.fill_density<40) {
|
if (layerm.region()->config().infill_dense.getBool() && layerm.region()->config().fill_density<40) {
|
||||||
SurfacesPtr *denseGroup = NULL;
|
SurfacesPtr *denseGroup = NULL;
|
||||||
const uint32_t nbGroups = groups.size();
|
const uint32_t nbGroups = groups.size();
|
||||||
for (uint32_t num_group = 0; num_group < nbGroups; ++num_group) {
|
for (uint32_t num_group = 0; num_group < nbGroups; ++num_group) {
|
||||||
@ -193,8 +193,8 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
(surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value) :
|
(surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value) :
|
||||||
ipRectilinear;
|
ipRectilinear;
|
||||||
} else {
|
} else {
|
||||||
if (layerm.region()->config.infill_dense.getBool()
|
if (layerm.region()->config().infill_dense.getBool()
|
||||||
&& layerm.region()->config.fill_density<40
|
&& layerm.region()->config().fill_density<40
|
||||||
&& surface.maxNbSolidLayersOnTop <= 1
|
&& surface.maxNbSolidLayersOnTop <= 1
|
||||||
&& surface.maxNbSolidLayersOnTop > 0) {
|
&& surface.maxNbSolidLayersOnTop > 0) {
|
||||||
density = 42;
|
density = 42;
|
||||||
@ -262,8 +262,8 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
f->loop_clipping = scale_(flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER;
|
f->loop_clipping = scale_(flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER;
|
||||||
//give the overlap size to let the infill do his overlap
|
//give the overlap size to let the infill do his overlap
|
||||||
//add overlap if at least one perimeter
|
//add overlap if at least one perimeter
|
||||||
if (layerm.region()->config.perimeters.getInt() > 0) {
|
if (layerm.region()->config().perimeters > 0) {
|
||||||
f->overlap = layerm.region()->config.get_abs_value("infill_overlap", (perimeter_spacing + (f->spacing)) / 2);
|
f->overlap = layerm.region()->config().get_abs_value("infill_overlap", (perimeter_spacing + (f->spacing)) / 2);
|
||||||
if (f->overlap!=0) {
|
if (f->overlap!=0) {
|
||||||
f->no_overlap_expolygons = intersection_ex(layerm.fill_no_overlap_expolygons, ExPolygons() = { surface.expolygon });
|
f->no_overlap_expolygons = intersection_ex(layerm.fill_no_overlap_expolygons, ExPolygons() = { surface.expolygon });
|
||||||
} else {
|
} else {
|
||||||
@ -278,8 +278,8 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
FillParams params;
|
FillParams params;
|
||||||
params.density = 0.01 * density;
|
params.density = 0.01 * density;
|
||||||
params.dont_adjust = false;
|
params.dont_adjust = false;
|
||||||
params.fill_exactly = layerm.region()->config.enforce_full_fill_volume.getBool();
|
params.fill_exactly = layerm.region()->config().enforce_full_fill_volume.getBool();
|
||||||
params.dont_connect = layerm.region()->config.infill_not_connected.getBool();
|
params.dont_connect = layerm.region()->config().infill_not_connected.getBool();
|
||||||
|
|
||||||
// calculate actual flow from spacing (which might have been adjusted by the infill
|
// calculate actual flow from spacing (which might have been adjusted by the infill
|
||||||
// pattern generator)
|
// pattern generator)
|
||||||
@ -293,8 +293,8 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||||||
|
|
||||||
float flow_percent = 1;
|
float flow_percent = 1;
|
||||||
if(surface.is_overBridge()){
|
if(surface.is_overBridge()){
|
||||||
params.density = layerm.region()->config.over_bridge_flow_ratio;
|
params.density = layerm.region()->config().over_bridge_flow_ratio;
|
||||||
//params.flow_mult = layerm.region()->config.over_bridge_flow_ratio;
|
//params.flow_mult = layerm.region()->config().over_bridge_flow_ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->fill_surface_extrusion(&surface, params, flow, erNone, out.entities);
|
f->fill_surface_extrusion(&surface, params, flow, erNone, out.entities);
|
||||||
|
@ -151,7 +151,7 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶
|
|||||||
for (auto pline = polylines.begin(); pline != polylines.end(); ++pline){
|
for (auto pline = polylines.begin(); pline != polylines.end(); ++pline){
|
||||||
Lines lines = pline->lines();
|
Lines lines = pline->lines();
|
||||||
for (auto line = lines.begin(); line != lines.end(); ++line){
|
for (auto line = lines.begin(); line != lines.end(); ++line){
|
||||||
lengthTot += unscale(line->length());
|
lengthTot += unscaled(line->length());
|
||||||
nbLines++;
|
nbLines++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,13 +159,13 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶
|
|||||||
// compute real volume
|
// compute real volume
|
||||||
double poylineVolume = 0;
|
double poylineVolume = 0;
|
||||||
for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) {
|
for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) {
|
||||||
poylineVolume += flow.height*unscale(unscale(poly->area()));
|
poylineVolume += flow.height*unscaled(unscaled(poly->area()));
|
||||||
// add external "perimeter gap"
|
// add external "perimeter gap"
|
||||||
double perimeterRoundGap = unscale(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
double perimeterRoundGap = unscaled(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
||||||
// add holes "perimeter gaps"
|
// add holes "perimeter gaps"
|
||||||
double holesGaps = 0;
|
double holesGaps = 0;
|
||||||
for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) {
|
for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) {
|
||||||
holesGaps += unscale(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
holesGaps += unscaled(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
||||||
}
|
}
|
||||||
poylineVolume += perimeterRoundGap + holesGaps;
|
poylineVolume += perimeterRoundGap + holesGaps;
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶
|
|||||||
}
|
}
|
||||||
/// push the path
|
/// push the path
|
||||||
extrusion_entities_append_paths(
|
extrusion_entities_append_paths(
|
||||||
eec->entities, STDMOVE(polylines),
|
eec->entities, std::move(polylines),
|
||||||
good_role,
|
good_role,
|
||||||
flow.mm3_per_mm() * params.flow_mult * multFlow,
|
flow.mm3_per_mm() * params.flow_mult * multFlow,
|
||||||
flow.width * params.flow_mult * multFlow,
|
flow.width * params.flow_mult * multFlow,
|
||||||
|
@ -89,8 +89,8 @@ void FillConcentricWGapFill::fill_surface_extrusion(const Surface *surface, cons
|
|||||||
coord_t distance = coord_t(min_spacing / params.density);
|
coord_t distance = coord_t(min_spacing / params.density);
|
||||||
|
|
||||||
if (params.density > 0.9999f && !params.dont_adjust) {
|
if (params.density > 0.9999f && !params.dont_adjust) {
|
||||||
distance = this->_adjust_solid_spacing(bounding_box.size().x, distance);
|
distance = this->_adjust_solid_spacing(bounding_box.size().x(), distance);
|
||||||
this->spacing = unscale(distance);
|
this->spacing = unscaled(distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons gaps;
|
ExPolygons gaps;
|
||||||
|
@ -37,12 +37,12 @@ namespace Slic3r {
|
|||||||
double volumeToOccupy = 0;
|
double volumeToOccupy = 0;
|
||||||
for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) {
|
for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) {
|
||||||
// add external "perimeter gap"
|
// add external "perimeter gap"
|
||||||
double poylineVolume = flow.height*unscale(unscale(poly->area()));
|
double poylineVolume = flow.height*unscaled(unscaled(poly->area()));
|
||||||
double perimeterRoundGap = unscale(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
double perimeterRoundGap = unscaled(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
||||||
// add holes "perimeter gaps"
|
// add holes "perimeter gaps"
|
||||||
double holesGaps = 0;
|
double holesGaps = 0;
|
||||||
for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) {
|
for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) {
|
||||||
holesGaps += unscale(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
holesGaps += unscaled(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
||||||
}
|
}
|
||||||
poylineVolume += perimeterRoundGap + holesGaps;
|
poylineVolume += perimeterRoundGap + holesGaps;
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ namespace Slic3r {
|
|||||||
for (auto pline = polylines_layer1.begin(); pline != polylines_layer1.end(); ++pline) {
|
for (auto pline = polylines_layer1.begin(); pline != polylines_layer1.end(); ++pline) {
|
||||||
Lines lines = pline->lines();
|
Lines lines = pline->lines();
|
||||||
for (auto line = lines.begin(); line != lines.end(); ++line) {
|
for (auto line = lines.begin(); line != lines.end(); ++line) {
|
||||||
lengthTot += unscale(line->length());
|
lengthTot += unscaled(line->length());
|
||||||
nbLines++;
|
nbLines++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ namespace Slic3r {
|
|||||||
eecroot->entities.push_back(eec);
|
eecroot->entities.push_back(eec);
|
||||||
eec->no_sort = false; //can be sorted inside the pass
|
eec->no_sort = false; //can be sorted inside the pass
|
||||||
extrusion_entities_append_paths(
|
extrusion_entities_append_paths(
|
||||||
eec->entities, STDMOVE(polylines_layer1),
|
eec->entities, std::move(polylines_layer1),
|
||||||
flow.bridge ? erBridgeInfill : rolePass[0],
|
flow.bridge ? erBridgeInfill : rolePass[0],
|
||||||
//reduced flow height for a better view (it's only a gui thing)
|
//reduced flow height for a better view (it's only a gui thing)
|
||||||
params.flow_mult * flow.mm3_per_mm() * percentFlow[0] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1),
|
params.flow_mult * flow.mm3_per_mm() * percentFlow[0] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1),
|
||||||
@ -122,18 +122,18 @@ namespace Slic3r {
|
|||||||
for (auto pline = polylines_layer1.begin(); pline != polylines_layer1.end(); ++pline) {
|
for (auto pline = polylines_layer1.begin(); pline != polylines_layer1.end(); ++pline) {
|
||||||
Lines lines = pline->lines();
|
Lines lines = pline->lines();
|
||||||
for (auto line = lines.begin(); line != lines.end(); ++line) {
|
for (auto line = lines.begin(); line != lines.end(); ++line) {
|
||||||
lengthTot += unscale(line->length());
|
lengthTot += unscaled(line->length());
|
||||||
nbLines++;
|
nbLines++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add external "perimeter gap"
|
// add external "perimeter gap"
|
||||||
double poylineVolume = flow.height*unscale(unscale(poly->area()));
|
double poylineVolume = flow.height*unscaled(unscaled(poly->area()));
|
||||||
double perimeterRoundGap = unscale(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
double perimeterRoundGap = unscaled(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
||||||
// add holes "perimeter gaps"
|
// add holes "perimeter gaps"
|
||||||
double holesGaps = 0;
|
double holesGaps = 0;
|
||||||
for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) {
|
for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) {
|
||||||
holesGaps += unscale(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
holesGaps += unscaled(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5;
|
||||||
}
|
}
|
||||||
poylineVolume += perimeterRoundGap + holesGaps;
|
poylineVolume += perimeterRoundGap + holesGaps;
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ namespace Slic3r {
|
|||||||
good_role = flow.bridge ? erBridgeInfill : rolePass[0];
|
good_role = flow.bridge ? erBridgeInfill : rolePass[0];
|
||||||
}
|
}
|
||||||
extrusion_entities_append_paths(
|
extrusion_entities_append_paths(
|
||||||
eec->entities, STDMOVE(polylines_layer1),
|
eec->entities, std::move(polylines_layer1),
|
||||||
good_role,
|
good_role,
|
||||||
//reduced flow height for a better view (it's only a gui thing)
|
//reduced flow height for a better view (it's only a gui thing)
|
||||||
params.flow_mult * flow.mm3_per_mm() * percentFlow[0] * (params.fill_exactly ? poylineVolume / extrudedVolume : 1),
|
params.flow_mult * flow.mm3_per_mm() * percentFlow[0] * (params.fill_exactly ? poylineVolume / extrudedVolume : 1),
|
||||||
@ -187,7 +187,7 @@ namespace Slic3r {
|
|||||||
for (auto pline = polylines_layer2.begin(); pline != polylines_layer2.end(); ++pline){
|
for (auto pline = polylines_layer2.begin(); pline != polylines_layer2.end(); ++pline){
|
||||||
Lines lines = pline->lines();
|
Lines lines = pline->lines();
|
||||||
for (auto line = lines.begin(); line != lines.end(); ++line){
|
for (auto line = lines.begin(); line != lines.end(); ++line){
|
||||||
lengthTot += unscale(line->length());
|
lengthTot += unscaled(line->length());
|
||||||
nbLines++;
|
nbLines++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,7 +205,7 @@ namespace Slic3r {
|
|||||||
}
|
}
|
||||||
// print thin
|
// print thin
|
||||||
extrusion_entities_append_paths(
|
extrusion_entities_append_paths(
|
||||||
eec->entities, STDMOVE(polylines_layer2),
|
eec->entities, std::move(polylines_layer2),
|
||||||
good_role,
|
good_role,
|
||||||
params.flow_mult * flow.mm3_per_mm() * percentFlow[1] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1),
|
params.flow_mult * flow.mm3_per_mm() * percentFlow[1] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1),
|
||||||
//min-reduced flow width for a better view (it's only a gui thing)
|
//min-reduced flow width for a better view (it's only a gui thing)
|
||||||
@ -244,7 +244,7 @@ namespace Slic3r {
|
|||||||
for (auto pline = polylines_layer3.begin(); pline != polylines_layer3.end(); ++pline){
|
for (auto pline = polylines_layer3.begin(); pline != polylines_layer3.end(); ++pline){
|
||||||
Lines lines = pline->lines();
|
Lines lines = pline->lines();
|
||||||
for (auto line = lines.begin(); line != lines.end(); ++line){
|
for (auto line = lines.begin(); line != lines.end(); ++line){
|
||||||
lengthTot += unscale(line->length());
|
lengthTot += unscaled(line->length());
|
||||||
nbLines++;
|
nbLines++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,7 +261,7 @@ namespace Slic3r {
|
|||||||
}
|
}
|
||||||
// print thin
|
// print thin
|
||||||
extrusion_entities_append_paths(
|
extrusion_entities_append_paths(
|
||||||
eec->entities, STDMOVE(polylines_layer3),
|
eec->entities, std::move(polylines_layer3),
|
||||||
good_role, //slow (if last)
|
good_role, //slow (if last)
|
||||||
//reduced flow width for a better view (it's only a gui thing)
|
//reduced flow width for a better view (it's only a gui thing)
|
||||||
params.flow_mult * flow.mm3_per_mm() * percentFlow[2] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1),
|
params.flow_mult * flow.mm3_per_mm() * percentFlow[2] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1),
|
||||||
|
@ -1502,7 +1502,7 @@ void GCode::process_layer(
|
|||||||
// fill->first_point fits inside ith slice
|
// fill->first_point fits inside ith slice
|
||||||
point_inside_surface(i, fill->first_point())) {
|
point_inside_surface(i, fill->first_point())) {
|
||||||
if (islands[i].by_region.empty()) {
|
if (islands[i].by_region.empty()) {
|
||||||
islands[i].by_region.assign(print.regions.size(), ObjectByExtruder::Island::Region());
|
islands[i].by_region.assign(print.regions().size(), ObjectByExtruder::Island::Region());
|
||||||
}
|
}
|
||||||
//don't do fill->entities because it will discard no_sort
|
//don't do fill->entities because it will discard no_sort
|
||||||
islands[i].by_region[region_id].append(entity_type, fill, entity_overrides, layer_to_print.object()->copies().size());
|
islands[i].by_region[region_id].append(entity_type, fill, entity_overrides, layer_to_print.object()->copies().size());
|
||||||
@ -2293,8 +2293,8 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
|
|||||||
{
|
{
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
for (const ObjectByExtruder::Island::Region ®ion : by_region) {
|
for (const ObjectByExtruder::Island::Region ®ion : by_region) {
|
||||||
if (print.regions[®ion - &by_region.front()]->config().infill_first == is_infill_first) {
|
if (print.regions()[®ion - &by_region.front()]->config().infill_first == is_infill_first) {
|
||||||
m_config.apply(print.regions[®ion - &by_region.front()]->config);
|
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||||
ExtrusionEntityCollection chained = region.infills.chained_path_from(m_last_pos, false);
|
ExtrusionEntityCollection chained = region.infills.chained_path_from(m_last_pos, false);
|
||||||
gcode += extrude_entity(chained, "infill");
|
gcode += extrude_entity(chained, "infill");
|
||||||
}
|
}
|
||||||
|
@ -375,6 +375,8 @@ std::string GCodePreviewData::get_legend_title() const
|
|||||||
return L("Volumetric flow rate (mm3/s)");
|
return L("Volumetric flow rate (mm3/s)");
|
||||||
case Extrusion::Tool:
|
case Extrusion::Tool:
|
||||||
return L("Tool");
|
return L("Tool");
|
||||||
|
case Extrusion::Filament:
|
||||||
|
return L("Filament");
|
||||||
case Extrusion::ColorPrint:
|
case Extrusion::ColorPrint:
|
||||||
return L("Color Print");
|
return L("Color Print");
|
||||||
}
|
}
|
||||||
@ -438,6 +440,7 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std::
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Extrusion::Tool:
|
case Extrusion::Tool:
|
||||||
|
case Extrusion::Filament:
|
||||||
{
|
{
|
||||||
unsigned int tools_colors_count = tool_colors.size() / 4;
|
unsigned int tools_colors_count = tool_colors.size() / 4;
|
||||||
items.reserve(tools_colors_count);
|
items.reserve(tools_colors_count);
|
||||||
|
@ -71,6 +71,7 @@ public:
|
|||||||
Feedrate,
|
Feedrate,
|
||||||
VolumetricRate,
|
VolumetricRate,
|
||||||
Tool,
|
Tool,
|
||||||
|
Filament,
|
||||||
ColorPrint,
|
ColorPrint,
|
||||||
Num_View_Types
|
Num_View_Types
|
||||||
};
|
};
|
||||||
|
@ -485,7 +485,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
if ((!print.config().infill_first ? perimeters_done : !perimeters_done) || (!object->config().wipe_into_objects && region.config().wipe_into_infill)) {
|
if ((!region.config().infill_first ? perimeters_done : !perimeters_done) || (!object->config().wipe_into_objects && region.config().wipe_into_infill)) {
|
||||||
for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->fills.entities) { // iterate through all infill Collections
|
for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->fills.entities) { // iterate through all infill Collections
|
||||||
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
||||||
|
|
||||||
@ -498,7 +498,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
|||||||
if (volume_to_wipe<=0)
|
if (volume_to_wipe<=0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!object->config().wipe_into_objects && !print.config().infill_first && region.config().wipe_into_infill)
|
if (!object->config().wipe_into_objects && !region.config().infill_first && region.config().wipe_into_infill)
|
||||||
// In this case we must check that the original extruder is used on this layer before the one we are overridding
|
// In this case we must check that the original extruder is used on this layer before the one we are overridding
|
||||||
// (and the perimeters will be finished before the infill is printed):
|
// (and the perimeters will be finished before the infill is printed):
|
||||||
if (!lt.is_extruder_order(region.config().perimeter_extruder - 1, new_extruder))
|
if (!lt.is_extruder_order(region.config().perimeter_extruder - 1, new_extruder))
|
||||||
@ -512,7 +512,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now the same for perimeters - see comments above for explanation:
|
// Now the same for perimeters - see comments above for explanation:
|
||||||
if (object->config().wipe_into_objects && (print.config().infill_first ? perimeters_done : !perimeters_done))
|
if (object->config().wipe_into_objects && (region.config().infill_first ? perimeters_done : !perimeters_done))
|
||||||
{
|
{
|
||||||
for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->perimeters.entities) {
|
for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->perimeters.entities) {
|
||||||
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
||||||
@ -572,12 +572,12 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
|
|||||||
// printed before its perimeter, or not be printed at all (in case its original extruder has
|
// printed before its perimeter, or not be printed at all (in case its original extruder has
|
||||||
// not been added to LayerTools
|
// not been added to LayerTools
|
||||||
// Either way, we will now force-override it with something suitable:
|
// Either way, we will now force-override it with something suitable:
|
||||||
if (print.config().infill_first
|
if (region.config().infill_first
|
||||||
|| object->config().wipe_into_objects // in this case the perimeter is overridden, so we can override by the last one safely
|
|| object->config().wipe_into_objects // in this case the perimeter is overridden, so we can override by the last one safely
|
||||||
|| lt.is_extruder_order(region.config().perimeter_extruder - 1, last_nonsoluble_extruder // !infill_first, but perimeter is already printed when last extruder prints
|
|| lt.is_extruder_order(region.config().perimeter_extruder - 1, last_nonsoluble_extruder // !infill_first, but perimeter is already printed when last extruder prints
|
||||||
|| std::find(lt.extruders.begin(), lt.extruders.end(), region.config().infill_extruder - 1) == lt.extruders.end()) // we have to force override - this could violate infill_first (FIXME)
|
|| std::find(lt.extruders.begin(), lt.extruders.end(), region.config().infill_extruder - 1) == lt.extruders.end()) // we have to force override - this could violate infill_first (FIXME)
|
||||||
)
|
)
|
||||||
set_extruder_override(fill, copy, (print.config().infill_first ? first_nonsoluble_extruder : last_nonsoluble_extruder), num_of_copies);
|
set_extruder_override(fill, copy, (region.config().infill_first ? first_nonsoluble_extruder : last_nonsoluble_extruder), num_of_copies);
|
||||||
else {
|
else {
|
||||||
// In this case we can (and should) leave it to be printed normally.
|
// In this case we can (and should) leave it to be printed normally.
|
||||||
// Force overriding would mean it gets printed before its perimeter.
|
// Force overriding would mean it gets printed before its perimeter.
|
||||||
@ -591,7 +591,7 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
|
|||||||
|| is_entity_overridden(fill, copy) )
|
|| is_entity_overridden(fill, copy) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
set_extruder_override(fill, copy, (print.config().infill_first ? last_nonsoluble_extruder : first_nonsoluble_extruder), num_of_copies);
|
set_extruder_override(fill, copy, (region.config().infill_first ? last_nonsoluble_extruder : first_nonsoluble_extruder), num_of_copies);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ public:
|
|||||||
// Unspecified fill polygons, used for overhang detection ("ensure vertical wall thickness feature")
|
// Unspecified fill polygons, used for overhang detection ("ensure vertical wall thickness feature")
|
||||||
// and for re-starting of infills.
|
// and for re-starting of infills.
|
||||||
ExPolygons fill_expolygons;
|
ExPolygons fill_expolygons;
|
||||||
|
// Unspecified fill polygons, used for interecting when we don't want the infill/perimeter overlap
|
||||||
|
ExPolygons fill_no_overlap_expolygons;
|
||||||
// collection of surfaces for infill generation
|
// collection of surfaces for infill generation
|
||||||
SurfaceCollection fill_surfaces;
|
SurfaceCollection fill_surfaces;
|
||||||
|
|
||||||
@ -110,8 +112,8 @@ public:
|
|||||||
ExPolygonCollection slices;
|
ExPolygonCollection slices;
|
||||||
|
|
||||||
size_t region_count() const { return m_regions.size(); }
|
size_t region_count() const { return m_regions.size(); }
|
||||||
const LayerRegion* get_region(int idx) const { return m_regions.at(idx); }
|
const LayerRegion* get_region(size_t idx) const { return m_regions.at(idx); }
|
||||||
LayerRegion* get_region(int idx) { return m_regions[idx]; }
|
LayerRegion* get_region(size_t idx) { return m_regions[idx]; }
|
||||||
LayerRegion* add_region(PrintRegion* print_region);
|
LayerRegion* add_region(PrintRegion* print_region);
|
||||||
const LayerRegionPtrs& regions() const { return m_regions; }
|
const LayerRegionPtrs& regions() const { return m_regions; }
|
||||||
// Test whether whether there are any slices assigned to this layer.
|
// Test whether whether there are any slices assigned to this layer.
|
||||||
|
@ -93,15 +93,15 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
|||||||
void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||||
{
|
{
|
||||||
const Surfaces &surfaces = this->fill_surfaces.surfaces;
|
const Surfaces &surfaces = this->fill_surfaces.surfaces;
|
||||||
const bool has_infill = this->region()->config.fill_density.value > 0.;
|
const bool has_infill = this->region()->config().fill_density.value > 0.;
|
||||||
coord_t margin = scale_(this->region()->config.external_infill_margin.getFloat());
|
coord_t margin = scale_(this->region()->config().external_infill_margin.getFloat());
|
||||||
coord_t margin_bridged = scale_(this->region()->config.bridged_infill_margin.getFloat());
|
coord_t margin_bridged = scale_(this->region()->config().bridged_infill_margin.getFloat());
|
||||||
//if no infill, reduce the margin for averythign to only the perimeter
|
//if no infill, reduce the margin for averythign to only the perimeter
|
||||||
if (!has_infill) {
|
if (!has_infill) {
|
||||||
if ((this->region()->config.perimeters.value > 0)) {
|
if ((this->region()->config().perimeters > 0)) {
|
||||||
const coord_t perimeter_width = scale_(this->region()->config.perimeter_extrusion_width.get_abs_value(this->layer()->object()->config.layer_height.value));
|
const coord_t perimeter_width = scale_(this->region()->config().perimeter_extrusion_width.get_abs_value(this->layer()->object()->config().layer_height.value));
|
||||||
const coord_t first_perimeter_width = scale_(this->region()->config.external_perimeter_extrusion_width.get_abs_value(this->layer()->object()->config.layer_height.value));
|
const coord_t first_perimeter_width = scale_(this->region()->config().external_perimeter_extrusion_width.get_abs_value(this->layer()->object()->config().layer_height.value));
|
||||||
margin = first_perimeter_width + perimeter_width * (this->region()->config.perimeters.value - 1);
|
margin = first_perimeter_width + perimeter_width * (this->region()->config().perimeters.value - 1);
|
||||||
} else margin = 0;
|
} else margin = 0;
|
||||||
margin_bridged = margin;
|
margin_bridged = margin;
|
||||||
}
|
}
|
||||||
|
@ -115,4 +115,15 @@ Vec3d Linef3::intersect_plane(double z) const
|
|||||||
return Vec3d(this->a(0) + v(0) * t, this->a(1) + v(1) * t, z);
|
return Vec3d(this->a(0) + v(0) * t, this->a(1) + v(1) * t, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point Line::point_at(double distance) const {
|
||||||
|
Point point;
|
||||||
|
double len = this->length();
|
||||||
|
point = this->a;
|
||||||
|
if (this->a.x() != this->b.x())
|
||||||
|
point.x() = this->a.x() + (this->b.x() - this->a.x()) * distance / len;
|
||||||
|
if (this->a.y() != this->b.y())
|
||||||
|
point.y() = this->a.y() + (this->b.y() - this->a.y()) * distance / len;
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,10 @@ public:
|
|||||||
|
|
||||||
static double distance_to_squared(const Point &point, const Point &a, const Point &b);
|
static double distance_to_squared(const Point &point, const Point &a, const Point &b);
|
||||||
static double distance_to(const Point &point, const Point &a, const Point &b) { return sqrt(distance_to_squared(point, a, b)); }
|
static double distance_to(const Point &point, const Point &a, const Point &b) { return sqrt(distance_to_squared(point, a, b)); }
|
||||||
|
Point point_at(double distance) const;
|
||||||
|
coord_t Line::dot(Line &l2) const { return vector().dot(l2.vector()); }
|
||||||
|
void extend_end(double distance) { Line line = *this; line.reverse(); this->b = line.point_at(-distance); }
|
||||||
|
void extend_start(double distance) { this->a = this->point_at(-distance); }
|
||||||
|
|
||||||
Point a;
|
Point a;
|
||||||
Point b;
|
Point b;
|
||||||
|
@ -344,10 +344,10 @@ add_point_same_percent(ThickPolyline* pattern, ThickPolyline* to_modify)
|
|||||||
coordf_t new_width = to_modify->width[idx_other - 1] * (1 - percent_dist);
|
coordf_t new_width = to_modify->width[idx_other - 1] * (1 - percent_dist);
|
||||||
new_width += to_modify->width[idx_other] * (percent_dist);
|
new_width += to_modify->width[idx_other] * (percent_dist);
|
||||||
Point new_point;
|
Point new_point;
|
||||||
new_point.x = (coord_t)((double)(to_modify->points[idx_other - 1].x) * (1 - percent_dist));
|
new_point.x() = (coord_t)((double)(to_modify->points[idx_other - 1].x()) * (1 - percent_dist));
|
||||||
new_point.x += (coord_t)((double)(to_modify->points[idx_other].x) * (percent_dist));
|
new_point.x() += (coord_t)((double)(to_modify->points[idx_other].x()) * (percent_dist));
|
||||||
new_point.y = (coord_t)((double)(to_modify->points[idx_other - 1].y) * (1 - percent_dist));
|
new_point.y() = (coord_t)((double)(to_modify->points[idx_other - 1].y()) * (1 - percent_dist));
|
||||||
new_point.y += (coord_t)((double)(to_modify->points[idx_other].y) * (percent_dist));
|
new_point.y() += (coord_t)((double)(to_modify->points[idx_other].y()) * (percent_dist));
|
||||||
to_modify->width.insert(to_modify->width.begin() + idx_other, new_width);
|
to_modify->width.insert(to_modify->width.begin() + idx_other, new_width);
|
||||||
to_modify->points.insert(to_modify->points.begin() + idx_other, new_point);
|
to_modify->points.insert(to_modify->points.begin() + idx_other, new_point);
|
||||||
}
|
}
|
||||||
@ -425,9 +425,11 @@ get_coeff_from_angle_countour(Point &point, const ExPolygon &contour, coord_t mi
|
|||||||
double
|
double
|
||||||
dot(Line l1, Line l2)
|
dot(Line l1, Line l2)
|
||||||
{
|
{
|
||||||
Vectorf v_1 = normalize(Vectorf(l1.b.x - l1.a.x, l1.b.y - l1.a.y));
|
Vec2d v_1(l1.b.x() - l1.a.x(), l1.b.y() - l1.a.y());
|
||||||
Vectorf v_2 = normalize(Vectorf(l2.b.x - l2.a.x, l2.b.y - l2.a.y));
|
v_1.normalize();
|
||||||
return v_1.x*v_2.x + v_1.y*v_2.y;
|
Vec2d v_2(l2.b.x() - l2.a.x(), l2.b.y() - l2.a.y());
|
||||||
|
v_2.normalize();
|
||||||
|
return v_1.x()*v_2.x() + v_1.y()*v_2.y();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -503,19 +505,19 @@ MedialAxis::fusion_curve(ThickPolylines &pp)
|
|||||||
//length_pull *= 0.144 * get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, min(min_width, polyline.length() / 2));
|
//length_pull *= 0.144 * get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, min(min_width, polyline.length() / 2));
|
||||||
|
|
||||||
////compute dir
|
////compute dir
|
||||||
//Vectorf pull_direction(polyline.points[1].x - polyline.points[0].x, polyline.points[1].y - polyline.points[0].y);
|
//Vectorf pull_direction(polyline.points[1].x() - polyline.points[0].x(), polyline.points[1].y() - polyline.points[0].y());
|
||||||
//pull_direction = normalize(pull_direction);
|
//pull_direction = normalize(pull_direction);
|
||||||
//pull_direction.x *= length_pull;
|
//pull_direction.x() *= length_pull;
|
||||||
//pull_direction.y *= length_pull;
|
//pull_direction.y() *= length_pull;
|
||||||
|
|
||||||
////pull the points
|
////pull the points
|
||||||
//Point &p1 = pp[crosspoint[0]].points[0];
|
//Point &p1 = pp[crosspoint[0]].points[0];
|
||||||
//p1.x = p1.x + (coord_t)pull_direction.x;
|
//p1.x() = p1.x() + (coord_t)pull_direction.x();
|
||||||
//p1.y = p1.y + (coord_t)pull_direction.y;
|
//p1.y() = p1.y() + (coord_t)pull_direction.y();
|
||||||
|
|
||||||
//Point &p2 = pp[crosspoint[1]].points[0];
|
//Point &p2 = pp[crosspoint[1]].points[0];
|
||||||
//p2.x = p2.x + (coord_t)pull_direction.x;
|
//p2.x() = p2.x() + (coord_t)pull_direction.x();
|
||||||
//p2.y = p2.y + (coord_t)pull_direction.y;
|
//p2.y() = p2.y() + (coord_t)pull_direction.y();
|
||||||
|
|
||||||
//delete the now unused polyline
|
//delete the now unused polyline
|
||||||
pp.erase(pp.begin() + i);
|
pp.erase(pp.begin() + i);
|
||||||
@ -579,19 +581,19 @@ MedialAxis::fusion_corners(ThickPolylines &pp)
|
|||||||
length_pull *= 0.144 * get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, min(min_width, polyline.length() / 2));
|
length_pull *= 0.144 * get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, min(min_width, polyline.length() / 2));
|
||||||
|
|
||||||
//compute dir
|
//compute dir
|
||||||
Vectorf pull_direction(polyline.points[1].x - polyline.points[0].x, polyline.points[1].y - polyline.points[0].y);
|
Vec2d pull_direction(polyline.points[1].x() - polyline.points[0].x(), polyline.points[1].y() - polyline.points[0].y());
|
||||||
pull_direction = normalize(pull_direction);
|
pull_direction.normalize();
|
||||||
pull_direction.x *= length_pull;
|
pull_direction.x() *= length_pull;
|
||||||
pull_direction.y *= length_pull;
|
pull_direction.y() *= length_pull;
|
||||||
|
|
||||||
//pull the points
|
//pull the points
|
||||||
Point &p1 = pp[crosspoint[0]].points[0];
|
Point &p1 = pp[crosspoint[0]].points[0];
|
||||||
p1.x = p1.x + pull_direction.x;
|
p1.x() = p1.x() + pull_direction.x();
|
||||||
p1.y = p1.y + pull_direction.y;
|
p1.y() = p1.y() + pull_direction.y();
|
||||||
|
|
||||||
Point &p2 = pp[crosspoint[1]].points[0];
|
Point &p2 = pp[crosspoint[1]].points[0];
|
||||||
p2.x = p2.x + pull_direction.x;
|
p2.x() = p2.x() + pull_direction.x();
|
||||||
p2.y = p2.y + pull_direction.y;
|
p2.y() = p2.y() + pull_direction.y();
|
||||||
|
|
||||||
//delete the now unused polyline
|
//delete the now unused polyline
|
||||||
pp.erase(pp.begin() + i);
|
pp.erase(pp.begin() + i);
|
||||||
@ -711,10 +713,10 @@ MedialAxis::extends_line(ThickPolyline& polyline, const ExPolygons& anchors, con
|
|||||||
best_anchor = p_maybe_inside;
|
best_anchor = p_maybe_inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (best_anchor.x != 0 && best_anchor.y != 0) {
|
if (best_anchor.x() != 0 && best_anchor.y() != 0) {
|
||||||
Point p_obj = best_anchor + new_bound;
|
Point p_obj = best_anchor + new_bound;
|
||||||
p_obj.x /= 2;
|
p_obj.x() /= 2;
|
||||||
p_obj.y /= 2;
|
p_obj.y() /= 2;
|
||||||
Line l2 = Line(new_back, p_obj);
|
Line l2 = Line(new_back, p_obj);
|
||||||
l2.extend_end(max_width);
|
l2.extend_end(max_width);
|
||||||
(void)bounds.contour.first_intersection(l2, &new_bound);
|
(void)bounds.contour.first_intersection(l2, &new_bound);
|
||||||
@ -937,8 +939,8 @@ MedialAxis::main_fusion(ThickPolylines& pp)
|
|||||||
size_t idx_point = 1;
|
size_t idx_point = 1;
|
||||||
while (idx_point < min(polyline.points.size(), best_candidate->points.size())) {
|
while (idx_point < min(polyline.points.size(), best_candidate->points.size())) {
|
||||||
//fusion
|
//fusion
|
||||||
polyline.points[idx_point].x = polyline.points[idx_point].x * coeff_poly + best_candidate->points[idx_point].x * coeff_candi;
|
polyline.points[idx_point].x() = polyline.points[idx_point].x() * coeff_poly + best_candidate->points[idx_point].x() * coeff_candi;
|
||||||
polyline.points[idx_point].y = polyline.points[idx_point].y * coeff_poly + best_candidate->points[idx_point].y * coeff_candi;
|
polyline.points[idx_point].y() = polyline.points[idx_point].y() * coeff_poly + best_candidate->points[idx_point].y() * coeff_candi;
|
||||||
|
|
||||||
// The width decrease with distance from the centerline.
|
// The width decrease with distance from the centerline.
|
||||||
// This formula is what works the best, even if it's not perfect (created empirically). 0->3% error on a gap fill on some tests.
|
// This formula is what works the best, even if it's not perfect (created empirically). 0->3% error on a gap fill on some tests.
|
||||||
@ -1048,10 +1050,10 @@ MedialAxis::remove_too_thin_extrusion(ThickPolylines& pp)
|
|||||||
if (polyline.points.front().distance_to(polyline.points[1]) * percent_can_keep > SCALED_RESOLUTION) {
|
if (polyline.points.front().distance_to(polyline.points[1]) * percent_can_keep > SCALED_RESOLUTION) {
|
||||||
//Can split => move the first point and assign a new weight.
|
//Can split => move the first point and assign a new weight.
|
||||||
//the update of endpoints wil be performed in concatThickPolylines
|
//the update of endpoints wil be performed in concatThickPolylines
|
||||||
polyline.points.front().x = polyline.points.front().x +
|
polyline.points.front().x() = polyline.points.front().x() +
|
||||||
(coord_t)((polyline.points[1].x - polyline.points.front().x) * (1 - percent_can_keep));
|
(coord_t)((polyline.points[1].x() - polyline.points.front().x()) * (1 - percent_can_keep));
|
||||||
polyline.points.front().y = polyline.points.front().y +
|
polyline.points.front().y() = polyline.points.front().y() +
|
||||||
(coord_t)((polyline.points[1].y - polyline.points.front().y) * (1 - percent_can_keep));
|
(coord_t)((polyline.points[1].y() - polyline.points.front().y()) * (1 - percent_can_keep));
|
||||||
polyline.width.front() = min_width;
|
polyline.width.front() = min_width;
|
||||||
} else {
|
} else {
|
||||||
/// almost 0-length, Remove
|
/// almost 0-length, Remove
|
||||||
@ -1072,10 +1074,10 @@ MedialAxis::remove_too_thin_extrusion(ThickPolylines& pp)
|
|||||||
if (polyline.points.back().distance_to(polyline.points[polyline.points.size() - 2]) * percent_can_keep > SCALED_RESOLUTION) {
|
if (polyline.points.back().distance_to(polyline.points[polyline.points.size() - 2]) * percent_can_keep > SCALED_RESOLUTION) {
|
||||||
//Can split => move the first point and assign a new weight.
|
//Can split => move the first point and assign a new weight.
|
||||||
//the update of endpoints wil be performed in concatThickPolylines
|
//the update of endpoints wil be performed in concatThickPolylines
|
||||||
polyline.points.back().x = polyline.points.back().x +
|
polyline.points.back().x() = polyline.points.back().x() +
|
||||||
(coord_t)((polyline.points[polyline.points.size() - 2].x - polyline.points.back().x) * (1 - percent_can_keep));
|
(coord_t)((polyline.points[polyline.points.size() - 2].x() - polyline.points.back().x()) * (1 - percent_can_keep));
|
||||||
polyline.points.back().y = polyline.points.back().y +
|
polyline.points.back().y() = polyline.points.back().y() +
|
||||||
(coord_t)((polyline.points[polyline.points.size() - 2].y - polyline.points.back().y) * (1 - percent_can_keep));
|
(coord_t)((polyline.points[polyline.points.size() - 2].y() - polyline.points.back().y()) * (1 - percent_can_keep));
|
||||||
polyline.width.back() = min_width;
|
polyline.width.back() = min_width;
|
||||||
} else {
|
} else {
|
||||||
/// almost 0-length, Remove
|
/// almost 0-length, Remove
|
||||||
@ -1139,11 +1141,11 @@ MedialAxis::concatenate_polylines_with_crossing(ThickPolylines& pp)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointf v_poly(polyline.lines().back().vector().x, polyline.lines().back().vector().y);
|
Vec2d v_poly(polyline.lines().back().vector().x(), polyline.lines().back().vector().y());
|
||||||
v_poly.scale(1 / std::sqrt(v_poly.x*v_poly.x + v_poly.y*v_poly.y));
|
v_poly *= (1 / std::sqrt(v_poly.x()*v_poly.x() + v_poly.y()*v_poly.y()));
|
||||||
Pointf v_other(other.lines().front().vector().x, other.lines().front().vector().y);
|
Vec2d v_other(other.lines().front().vector().x(), other.lines().front().vector().y());
|
||||||
v_other.scale(1 / std::sqrt(v_other.x*v_other.x + v_other.y*v_other.y));
|
v_other *= (1 / std::sqrt(v_other.x()*v_other.x() + v_other.y()*v_other.y()));
|
||||||
float other_dot = v_poly.x*v_other.x + v_poly.y*v_other.y;
|
float other_dot = v_poly.x()*v_other.x() + v_poly.y()*v_other.y();
|
||||||
if (other_dot > best_dot) {
|
if (other_dot > best_dot) {
|
||||||
best_candidate = &other;
|
best_candidate = &other;
|
||||||
best_idx = j;
|
best_idx = j;
|
||||||
@ -1306,8 +1308,8 @@ MedialAxis::simplify_polygon_frontier()
|
|||||||
const Point* closest = bounds.contour.closest_point(p_check);
|
const Point* closest = bounds.contour.closest_point(p_check);
|
||||||
if (closest != nullptr && closest->distance_to(p_check) + SCALED_EPSILON
|
if (closest != nullptr && closest->distance_to(p_check) + SCALED_EPSILON
|
||||||
< min(p_check.distance_to(simplified_poly.contour.points[prev_i]), p_check.distance_to(simplified_poly.contour.points[next_i])) / 2) {
|
< min(p_check.distance_to(simplified_poly.contour.points[prev_i]), p_check.distance_to(simplified_poly.contour.points[next_i])) / 2) {
|
||||||
p_check.x = closest->x;
|
p_check.x() = closest->x();
|
||||||
p_check.y = closest->y;
|
p_check.y() = closest->y();
|
||||||
need_intersect = true;
|
need_intersect = true;
|
||||||
} else {
|
} else {
|
||||||
simplified_poly.contour.points.erase(simplified_poly.contour.points.begin() + i);
|
simplified_poly.contour.points.erase(simplified_poly.contour.points.begin() + i);
|
||||||
@ -1553,7 +1555,7 @@ ExtrusionEntityCollection thin_variable_width(const ThickPolylines &polylines, E
|
|||||||
path.polyline.append(line.b);
|
path.polyline.append(line.b);
|
||||||
// Convert from spacing to extrusion width based on the extrusion model
|
// Convert from spacing to extrusion width based on the extrusion model
|
||||||
// of a square extrusion ended with semi circles.
|
// of a square extrusion ended with semi circles.
|
||||||
flow.width = unscale(w) + flow.height * (1. - 0.25 * PI);
|
flow.width = unscaled(w) + flow.height * (1. - 0.25 * PI);
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
printf(" filling %f gap\n", flow.width);
|
printf(" filling %f gap\n", flow.width);
|
||||||
#endif
|
#endif
|
||||||
|
@ -180,13 +180,13 @@ Point MultiPoint::point_projection(const Point &point) const {
|
|||||||
dmin = d;
|
dmin = d;
|
||||||
proj = pt1;
|
proj = pt1;
|
||||||
}
|
}
|
||||||
Pointf v1(coordf_t(pt1.x - pt0.x), coordf_t(pt1.y - pt0.y));
|
Vec2d v1(coordf_t(pt1(0) - pt0(0)), coordf_t(pt1(1) - pt0(1)));
|
||||||
coordf_t div = dot(v1);
|
coordf_t div = dot(v1);
|
||||||
if (div > 0.) {
|
if (div > 0.) {
|
||||||
Pointf v2(coordf_t(point.x - pt0.x), coordf_t(point.y - pt0.y));
|
Vec2d v2(coordf_t(point(0) - pt0(0)), coordf_t(point(1) - pt0(1)));
|
||||||
coordf_t t = dot(v1, v2) / div;
|
coordf_t t = dot(v1, v2) / div;
|
||||||
if (t > 0. && t < 1.) {
|
if (t > 0. && t < 1.) {
|
||||||
Point foot(coord_t(floor(coordf_t(pt0.x) + t * v1.x + 0.5)), coord_t(floor(coordf_t(pt0.y) + t * v1.y + 0.5)));
|
Point foot(coord_t(floor(coordf_t(pt0(0)) + t * v1(0) + 0.5)), coord_t(floor(coordf_t(pt0(1)) + t * v1(1) + 0.5)));
|
||||||
d = foot.distance_to(point);
|
d = foot.distance_to(point);
|
||||||
if (d < dmin) {
|
if (d < dmin) {
|
||||||
dmin = d;
|
dmin = d;
|
||||||
@ -199,8 +199,7 @@ Point MultiPoint::point_projection(const Point &point) const {
|
|||||||
return proj;
|
return proj;
|
||||||
}
|
}
|
||||||
|
|
||||||
Points
|
std::vector<Point> MultiPoint::_douglas_peucker(const std::vector<Point>& pts, const double tolerance)
|
||||||
MultiPoint::_douglas_peucker(const Points &points, const double tolerance)
|
|
||||||
{
|
{
|
||||||
std::vector<Point> result_pts;
|
std::vector<Point> result_pts;
|
||||||
if (! pts.empty()) {
|
if (! pts.empty()) {
|
||||||
|
@ -131,7 +131,7 @@ void PerimeterGenerator::process()
|
|||||||
//it's not dangerous as it will be intersected by 'unsupported' later
|
//it's not dangerous as it will be intersected by 'unsupported' later
|
||||||
//FIXME: add overlap in this->fill_surfaces->append
|
//FIXME: add overlap in this->fill_surfaces->append
|
||||||
// add overlap (perimeter_spacing/4 was good in test, ie 25%)
|
// add overlap (perimeter_spacing/4 was good in test, ie 25%)
|
||||||
coord_t overlap = scale_(this->config->get_abs_value("infill_overlap", unscale(perimeter_spacing)));
|
coord_t overlap = scale_(this->config->get_abs_value("infill_overlap", unscale<double>(perimeter_spacing)));
|
||||||
unsupported_filtered = intersection_ex(unsupported_filtered, offset_ex(bridgeable_simplified, overlap));
|
unsupported_filtered = intersection_ex(unsupported_filtered, offset_ex(bridgeable_simplified, overlap));
|
||||||
} else {
|
} else {
|
||||||
unsupported_filtered.clear();
|
unsupported_filtered.clear();
|
||||||
@ -675,7 +675,7 @@ PerimeterGenerator::_get_nearest_point(const PerimeterGeneratorLoops &children,
|
|||||||
const double dist = nearest_p.distance_to(p);
|
const double dist = nearest_p.distance_to(p);
|
||||||
//Try to find a point in the far side, aligning them
|
//Try to find a point in the far side, aligning them
|
||||||
if (dist + dist_cut / 20 < intersect.distance ||
|
if (dist + dist_cut / 20 < intersect.distance ||
|
||||||
(config->perimeter_loop_seam.value == spRear && (intersect.idx_polyline_outter <0 || p.y > intersect.outter_best.y)
|
(config->perimeter_loop_seam.value == spRear && (intersect.idx_polyline_outter <0 || p.y() > intersect.outter_best.y())
|
||||||
&& dist <= max_dist && intersect.distance + dist_cut / 20)) {
|
&& dist <= max_dist && intersect.distance + dist_cut / 20)) {
|
||||||
//ok, copy the idx
|
//ok, copy the idx
|
||||||
intersect.distance = (coord_t)nearest_p.distance_to(p);
|
intersect.distance = (coord_t)nearest_p.distance_to(p);
|
||||||
@ -692,7 +692,7 @@ PerimeterGenerator::_get_nearest_point(const PerimeterGeneratorLoops &children,
|
|||||||
const Point &nearest_p = *child.polygon.closest_point(p);
|
const Point &nearest_p = *child.polygon.closest_point(p);
|
||||||
const double dist = nearest_p.distance_to(p);
|
const double dist = nearest_p.distance_to(p);
|
||||||
if (dist + SCALED_EPSILON < intersect.distance ||
|
if (dist + SCALED_EPSILON < intersect.distance ||
|
||||||
(config->perimeter_loop_seam.value == spRear && (intersect.idx_polyline_outter<0 || p.y < intersect.outter_best.y)
|
(config->perimeter_loop_seam.value == spRear && (intersect.idx_polyline_outter<0 || p.y() < intersect.outter_best.y())
|
||||||
&& dist <= max_dist && intersect.distance + dist_cut / 20)) {
|
&& dist <= max_dist && intersect.distance + dist_cut / 20)) {
|
||||||
//ok, copy the idx
|
//ok, copy the idx
|
||||||
intersect.distance = (coord_t)nearest_p.distance_to(p);
|
intersect.distance = (coord_t)nearest_p.distance_to(p);
|
||||||
@ -1131,8 +1131,8 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop,
|
|||||||
travel_path_begin[2].extruder_id = -1;
|
travel_path_begin[2].extruder_id = -1;
|
||||||
Line line(outer_start->polyline.points.back(), inner_start->polyline.points.front());
|
Line line(outer_start->polyline.points.back(), inner_start->polyline.points.front());
|
||||||
Point p_dist_cut_extrude = (line.b - line.a);
|
Point p_dist_cut_extrude = (line.b - line.a);
|
||||||
p_dist_cut_extrude.x = (coord_t)(p_dist_cut_extrude.x * ((double)max_width_extrusion) / (line.length() * 2));
|
p_dist_cut_extrude.x() = (coord_t)(p_dist_cut_extrude.x() * ((double)max_width_extrusion) / (line.length() * 2));
|
||||||
p_dist_cut_extrude.y = (coord_t)(p_dist_cut_extrude.y * ((double)max_width_extrusion) / (line.length() * 2));
|
p_dist_cut_extrude.y() = (coord_t)(p_dist_cut_extrude.y() * ((double)max_width_extrusion) / (line.length() * 2));
|
||||||
//extrude a bit after the turn, to close the loop
|
//extrude a bit after the turn, to close the loop
|
||||||
Point p_start_travel = line.a;
|
Point p_start_travel = line.a;
|
||||||
p_start_travel += p_dist_cut_extrude;
|
p_start_travel += p_dist_cut_extrude;
|
||||||
@ -1168,8 +1168,8 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop,
|
|||||||
travel_path_end[2].extruder_id = -1;
|
travel_path_end[2].extruder_id = -1;
|
||||||
Line line(inner_end->polyline.points.back(), outer_end->polyline.points.front());
|
Line line(inner_end->polyline.points.back(), outer_end->polyline.points.front());
|
||||||
Point p_dist_cut_extrude = (line.b - line.a);
|
Point p_dist_cut_extrude = (line.b - line.a);
|
||||||
p_dist_cut_extrude.x = (coord_t)(p_dist_cut_extrude.x * ((double)max_width_extrusion) / (line.length() * 2));
|
p_dist_cut_extrude.x() = (coord_t)(p_dist_cut_extrude.x() * ((double)max_width_extrusion) / (line.length() * 2));
|
||||||
p_dist_cut_extrude.y = (coord_t)(p_dist_cut_extrude.y * ((double)max_width_extrusion) / (line.length() * 2));
|
p_dist_cut_extrude.y() = (coord_t)(p_dist_cut_extrude.y() * ((double)max_width_extrusion) / (line.length() * 2));
|
||||||
//extrude a bit after the turn, to close the loop
|
//extrude a bit after the turn, to close the loop
|
||||||
Point p_start_travel_2 = line.a;
|
Point p_start_travel_2 = line.a;
|
||||||
p_start_travel_2 += p_dist_cut_extrude;
|
p_start_travel_2 += p_dist_cut_extrude;
|
||||||
|
@ -100,6 +100,29 @@ int Point::nearest_point_index(const PointConstPtrs &points) const
|
|||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* distance to the closest point of line */
|
||||||
|
double
|
||||||
|
Point::distance_to(const Line &line) const {
|
||||||
|
const double dx = line.b.x() - line.a.x();
|
||||||
|
const double dy = line.b.y() - line.a.y();
|
||||||
|
|
||||||
|
const double l2 = dx*dx + dy*dy; // avoid a sqrt
|
||||||
|
if (l2 == 0.0) return this->distance_to(line.a); // line.a == line.b case
|
||||||
|
|
||||||
|
// Consider the line extending the segment, parameterized as line.a + t (line.b - line.a).
|
||||||
|
// We find projection of this point onto the line.
|
||||||
|
// It falls where t = [(this-line.a) . (line.b-line.a)] / |line.b-line.a|^2
|
||||||
|
const double t = ((this->x() - line.a.x()) * dx + (this->y() - line.a.y()) * dy) / l2;
|
||||||
|
if (t < 0.0) return this->distance_to(line.a); // beyond the 'a' end of the segment
|
||||||
|
else if (t > 1.0) return this->distance_to(line.b); // beyond the 'b' end of the segment
|
||||||
|
Point projection(
|
||||||
|
line.a.x() + t * dx,
|
||||||
|
line.a.y() + t * dy
|
||||||
|
);
|
||||||
|
return this->distance_to(projection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Point::nearest_point_index(const PointPtrs &points) const
|
int Point::nearest_point_index(const PointPtrs &points) const
|
||||||
{
|
{
|
||||||
PointConstPtrs p;
|
PointConstPtrs p;
|
||||||
|
@ -51,6 +51,9 @@ inline coord_t cross2(const Vec2crd &v1, const Vec2crd &v2) { return v1(0) * v2(
|
|||||||
inline float cross2(const Vec2f &v1, const Vec2f &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
|
inline float cross2(const Vec2f &v1, const Vec2f &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
|
||||||
inline double cross2(const Vec2d &v1, const Vec2d &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
|
inline double cross2(const Vec2d &v1, const Vec2d &v2) { return v1(0) * v2(1) - v1(1) * v2(0); }
|
||||||
|
|
||||||
|
inline coordf_t dot(const Vec2d &v1, const Vec2d &v2) { return v1.x() * v2.x() + v1.y() * v2.y(); }
|
||||||
|
inline coordf_t dot(const Vec2d &v) { return v.x() * v.x() + v.y() * v.y(); }
|
||||||
|
|
||||||
inline Vec2crd to_2d(const Vec3crd &pt3) { return Vec2crd(pt3(0), pt3(1)); }
|
inline Vec2crd to_2d(const Vec3crd &pt3) { return Vec2crd(pt3(0), pt3(1)); }
|
||||||
inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); }
|
inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); }
|
||||||
inline Vec2f to_2d(const Vec3f &pt3) { return Vec2f (pt3(0), pt3(1)); }
|
inline Vec2f to_2d(const Vec3f &pt3) { return Vec2f (pt3(0), pt3(1)); }
|
||||||
@ -118,6 +121,13 @@ public:
|
|||||||
double ccw_angle(const Point &p1, const Point &p2) const;
|
double ccw_angle(const Point &p1, const Point &p2) const;
|
||||||
Point projection_onto(const MultiPoint &poly) const;
|
Point projection_onto(const MultiPoint &poly) const;
|
||||||
Point projection_onto(const Line &line) const;
|
Point projection_onto(const Line &line) const;
|
||||||
|
|
||||||
|
double distance_to(const Point &point) const { return (point - *this).cast<double>().norm(); }
|
||||||
|
double distance_to(const Line &line) const;
|
||||||
|
bool coincides_with(const Point &point) const { return this->x() == point.x() && this->y() == point.y(); }
|
||||||
|
bool coincides_with_epsilon(const Point &point) const {
|
||||||
|
return std::abs(this->x() - point.x()) < SCALED_EPSILON && std::abs(this->y() - point.y()) < SCALED_EPSILON;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace int128 {
|
namespace int128 {
|
||||||
|
@ -138,6 +138,11 @@ bool remove_degenerate(Polylines &polylines);
|
|||||||
/// join something or is a dead-end.
|
/// join something or is a dead-end.
|
||||||
class ThickPolyline : public Polyline {
|
class ThickPolyline : public Polyline {
|
||||||
public:
|
public:
|
||||||
|
/// width size must be == point size
|
||||||
|
std::vector<coordf_t> width;
|
||||||
|
/// if true => it's an endpoint, if false it join an other ThickPolyline. first is at front(), second is at back()
|
||||||
|
std::pair<bool, bool> endpoints;
|
||||||
|
|
||||||
ThickPolyline() : endpoints(std::make_pair(false, false)) {}
|
ThickPolyline() : endpoints(std::make_pair(false, false)) {}
|
||||||
ThickLines thicklines() const;
|
ThickLines thicklines() const;
|
||||||
void reverse() {
|
void reverse() {
|
||||||
@ -145,14 +150,6 @@ public:
|
|||||||
std::reverse(this->width.begin(), this->width.end());
|
std::reverse(this->width.begin(), this->width.end());
|
||||||
std::swap(this->endpoints.first, this->endpoints.second);
|
std::swap(this->endpoints.first, this->endpoints.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// width size must be == point size
|
|
||||||
std::vector<coordf_t> width;
|
|
||||||
/// if true => it's an endpoint, if false it join an other ThickPolyline. first is at front(), second is at back()
|
|
||||||
std::pair<bool,bool> endpoints;
|
|
||||||
ThickPolyline() : endpoints(std::make_pair(false, false)) {};
|
|
||||||
ThickLines thicklines() const;
|
|
||||||
void reverse();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// concatenate poylines if possible and refresh the endpoints
|
/// concatenate poylines if possible and refresh the endpoints
|
||||||
|
@ -179,6 +179,7 @@ private:
|
|||||||
void generate_support_material();
|
void generate_support_material();
|
||||||
|
|
||||||
void _slice();
|
void _slice();
|
||||||
|
void _offsetHoles(float hole_delta, LayerRegion *layerm);
|
||||||
std::string _fix_slicing_errors();
|
std::string _fix_slicing_errors();
|
||||||
void _simplify_slices(double distance);
|
void _simplify_slices(double distance);
|
||||||
void _make_perimeters();
|
void _make_perimeters();
|
||||||
@ -187,7 +188,9 @@ private:
|
|||||||
void process_external_surfaces();
|
void process_external_surfaces();
|
||||||
void discover_vertical_shells();
|
void discover_vertical_shells();
|
||||||
void bridge_over_infill();
|
void bridge_over_infill();
|
||||||
|
void replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_replacement, SurfaceType st_under_it);
|
||||||
void clip_fill_surfaces();
|
void clip_fill_surfaces();
|
||||||
|
void count_distance_solid();
|
||||||
void discover_horizontal_shells();
|
void discover_horizontal_shells();
|
||||||
void combine_infill();
|
void combine_infill();
|
||||||
void _generate_support_material();
|
void _generate_support_material();
|
||||||
|
@ -84,12 +84,9 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"are very confident on your model, or you want to print an item with a geometry "
|
"are very confident on your model, or you want to print an item with a geometry "
|
||||||
"designed for vase mode.");
|
"designed for vase mode.");
|
||||||
def->cli = "remove-small-gaps!";
|
def->cli = "remove-small-gaps!";
|
||||||
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionBool(true);
|
def->default_value = new ConfigOptionBool(true);
|
||||||
|
|
||||||
def = this->add("bed_shape", coPoints);
|
|
||||||
def->label = L("Bed shape");
|
|
||||||
def->default_value = new ConfigOptionPoints { Pointf(0,0), Pointf(200,0), Pointf(200,200), Pointf(0,200) };
|
|
||||||
|
|
||||||
def = this->add("bed_temperature", coInts);
|
def = this->add("bed_temperature", coInts);
|
||||||
def->label = L("Other layers");
|
def->label = L("Other layers");
|
||||||
def->tooltip = L("Bed temperature for layers after the first one. "
|
def->tooltip = L("Bed temperature for layers after the first one. "
|
||||||
@ -170,6 +167,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->cli = "top-fan-speed=i@";
|
def->cli = "top-fan-speed=i@";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->max = 100;
|
def->max = 100;
|
||||||
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionInts{ 100 };
|
def->default_value = new ConfigOptionInts{ 100 };
|
||||||
|
|
||||||
def = this->add("bridge_flow_ratio", coFloat);
|
def = this->add("bridge_flow_ratio", coFloat);
|
||||||
@ -194,6 +192,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
"even if the bridged layer has fallen a bit.");
|
"even if the bridged layer has fallen a bit.");
|
||||||
def->cli = "over-bridge-flow-ratio=f";
|
def->cli = "over-bridge-flow-ratio=f";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionFloat(1);
|
def->default_value = new ConfigOptionFloat(1);
|
||||||
|
|
||||||
def = this->add("bridge_speed", coFloat);
|
def = this->add("bridge_speed", coFloat);
|
||||||
@ -439,6 +438,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->enum_labels.push_back(L("Hilbert Curve"));
|
def->enum_labels.push_back(L("Hilbert Curve"));
|
||||||
def->enum_labels.push_back(L("Archimedean Chords"));
|
def->enum_labels.push_back(L("Archimedean Chords"));
|
||||||
def->enum_labels.push_back(L("Octagram Spiral"));
|
def->enum_labels.push_back(L("Octagram Spiral"));
|
||||||
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionEnum<InfillPattern>(ipRectilinear);
|
def->default_value = new ConfigOptionEnum<InfillPattern>(ipRectilinear);
|
||||||
|
|
||||||
def = this->add("enforce_full_fill_volume", coBool);
|
def = this->add("enforce_full_fill_volume", coBool);
|
||||||
@ -446,6 +446,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->category = L("Infill");
|
def->category = L("Infill");
|
||||||
def->tooltip = L("Experimental option which modifies (top/bottom) fill flow to have the exact amount of plastic inside the volume to fill.");
|
def->tooltip = L("Experimental option which modifies (top/bottom) fill flow to have the exact amount of plastic inside the volume to fill.");
|
||||||
def->cli = "enforce-full-fill-volume!";
|
def->cli = "enforce-full-fill-volume!";
|
||||||
|
def->mode = comExpert;
|
||||||
def->default_value = new ConfigOptionBool(true);
|
def->default_value = new ConfigOptionBool(true);
|
||||||
|
|
||||||
def = this->add("external_infill_margin", coFloat);
|
def = this->add("external_infill_margin", coFloat);
|
||||||
@ -455,6 +456,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
def->cli = "top-layer-anchor=f";
|
def->cli = "top-layer-anchor=f";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
|
def->mode = comExpert;
|
||||||
def->default_value = new ConfigOptionFloat(1.5);
|
def->default_value = new ConfigOptionFloat(1.5);
|
||||||
|
|
||||||
def = this->add("bridged_infill_margin", coFloat);
|
def = this->add("bridged_infill_margin", coFloat);
|
||||||
@ -464,6 +466,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
def->cli = "top-layer-anchor=f";
|
def->cli = "top-layer-anchor=f";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
|
def->mode = comExpert;
|
||||||
def->default_value = new ConfigOptionFloat(2);
|
def->default_value = new ConfigOptionFloat(2);
|
||||||
|
|
||||||
def = this->add("external_perimeter_extrusion_width", coFloatOrPercent);
|
def = this->add("external_perimeter_extrusion_width", coFloatOrPercent);
|
||||||
@ -504,6 +507,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->tooltip = L("Join the perimeters to create only one continuous extrusion without any z-hop."
|
def->tooltip = L("Join the perimeters to create only one continuous extrusion without any z-hop."
|
||||||
" Long inside travel (from external to holes) are not extruded to give some space to the infill.");
|
" Long inside travel (from external to holes) are not extruded to give some space to the infill.");
|
||||||
def->cli = "loop-perimeter!";
|
def->cli = "loop-perimeter!";
|
||||||
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionBool(false);
|
def->default_value = new ConfigOptionBool(false);
|
||||||
|
|
||||||
def = this->add("perimeter_loop_seam", coEnum);
|
def = this->add("perimeter_loop_seam", coEnum);
|
||||||
@ -516,9 +520,10 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->enum_values.push_back("rear");
|
def->enum_values.push_back("rear");
|
||||||
def->enum_labels.push_back(L("Nearest"));
|
def->enum_labels.push_back(L("Nearest"));
|
||||||
def->enum_labels.push_back(L("Rear"));
|
def->enum_labels.push_back(L("Rear"));
|
||||||
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionEnum<SeamPosition>(spRear);
|
def->default_value = new ConfigOptionEnum<SeamPosition>(spRear);
|
||||||
|
|
||||||
def = this->add("extra_perimeters", coBool);
|
def = this->add("extra_perimeters", coBool);avoid
|
||||||
def->label = L("Extra perimeters if needed");
|
def->label = L("Extra perimeters if needed");
|
||||||
def->category = L("Layers and Perimeters");
|
def->category = L("Layers and Perimeters");
|
||||||
def->tooltip = L("Add more perimeters when needed for avoiding gaps in sloping walls. "
|
def->tooltip = L("Add more perimeters when needed for avoiding gaps in sloping walls. "
|
||||||
@ -903,7 +908,6 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->enum_values.push_back("cubic");
|
def->enum_values.push_back("cubic");
|
||||||
def->enum_values.push_back("line");
|
def->enum_values.push_back("line");
|
||||||
def->enum_values.push_back("concentric");
|
def->enum_values.push_back("concentric");
|
||||||
def->enum_values.push_back("concentricgapfill");
|
|
||||||
def->enum_values.push_back("honeycomb");
|
def->enum_values.push_back("honeycomb");
|
||||||
def->enum_values.push_back("3dhoneycomb");
|
def->enum_values.push_back("3dhoneycomb");
|
||||||
def->enum_values.push_back("gyroid");
|
def->enum_values.push_back("gyroid");
|
||||||
@ -917,7 +921,6 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->enum_labels.push_back(L("Cubic"));
|
def->enum_labels.push_back(L("Cubic"));
|
||||||
def->enum_labels.push_back(L("Line"));
|
def->enum_labels.push_back(L("Line"));
|
||||||
def->enum_labels.push_back(L("Concentric"));
|
def->enum_labels.push_back(L("Concentric"));
|
||||||
def->enum_labels.push_back(L("Concentric (filled)"));
|
|
||||||
def->enum_labels.push_back(L("Honeycomb"));
|
def->enum_labels.push_back(L("Honeycomb"));
|
||||||
def->enum_labels.push_back(L("3D Honeycomb"));
|
def->enum_labels.push_back(L("3D Honeycomb"));
|
||||||
def->enum_labels.push_back(L("Gyroid"));
|
def->enum_labels.push_back(L("Gyroid"));
|
||||||
@ -993,6 +996,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->sidetext = L("mm/s or %");
|
def->sidetext = L("mm/s or %");
|
||||||
def->cli = "first-layer-infill-speed=s";
|
def->cli = "first-layer-infill-speed=s";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
|
def->mode = comExpert;
|
||||||
def->default_value = new ConfigOptionFloatOrPercent(30, false);
|
def->default_value = new ConfigOptionFloatOrPercent(30, false);
|
||||||
|
|
||||||
def = this->add("first_layer_temperature", coInts);
|
def = this->add("first_layer_temperature", coInts);
|
||||||
@ -1090,6 +1094,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->tooltip = L("Enables the creation of a support layer under the first solid layer. This allows you to use a lower infill ratio without compromizing the top quality."
|
def->tooltip = L("Enables the creation of a support layer under the first solid layer. This allows you to use a lower infill ratio without compromizing the top quality."
|
||||||
" The dense infill is laid out with a 50% infill density.");
|
" The dense infill is laid out with a 50% infill density.");
|
||||||
def->cli = "infill-dense!";
|
def->cli = "infill-dense!";
|
||||||
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionBool(false);
|
def->default_value = new ConfigOptionBool(false);
|
||||||
|
|
||||||
def = this->add("infill_not_connected", coBool);
|
def = this->add("infill_not_connected", coBool);
|
||||||
@ -1097,6 +1102,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->category = L("Infill");
|
def->category = L("Infill");
|
||||||
def->tooltip = L("If checked, the infill algorithm will try to not connect the lines near the infill. Can be useful for art or with high infill/perimeter overlap.");
|
def->tooltip = L("If checked, the infill algorithm will try to not connect the lines near the infill. Can be useful for art or with high infill/perimeter overlap.");
|
||||||
def->cli = "infill-not-connected!";
|
def->cli = "infill-not-connected!";
|
||||||
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionBool(false);
|
def->default_value = new ConfigOptionBool(false);
|
||||||
|
|
||||||
def = this->add("infill_dense_algo", coEnum);
|
def = this->add("infill_dense_algo", coEnum);
|
||||||
@ -1112,6 +1118,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->enum_labels.push_back(L("Automatic"));
|
def->enum_labels.push_back(L("Automatic"));
|
||||||
def->enum_labels.push_back(L("Automatic, only for small areas"));
|
def->enum_labels.push_back(L("Automatic, only for small areas"));
|
||||||
def->enum_labels.push_back(L("Anchored"));
|
def->enum_labels.push_back(L("Anchored"));
|
||||||
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionEnum<DenseInfillAlgo>(dfaAutomatic);
|
def->default_value = new ConfigOptionEnum<DenseInfillAlgo>(dfaAutomatic);
|
||||||
|
|
||||||
def = this->add("infill_extruder", coInt);
|
def = this->add("infill_extruder", coInt);
|
||||||
@ -1522,6 +1529,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->category = L("Layers and Perimeters");
|
def->category = L("Layers and Perimeters");
|
||||||
def->tooltip = L("Experimental option to remove perimeters where there is nothing under it and a bridged infill should be better.");
|
def->tooltip = L("Experimental option to remove perimeters where there is nothing under it and a bridged infill should be better.");
|
||||||
def->cli = "no-perimeter-unsupported!";
|
def->cli = "no-perimeter-unsupported!";
|
||||||
|
def->mode = comExpert;
|
||||||
def->default_value = new ConfigOptionBool(false);
|
def->default_value = new ConfigOptionBool(false);
|
||||||
|
|
||||||
def = this->add("min_perimeter_unsupported", coInt);
|
def = this->add("min_perimeter_unsupported", coInt);
|
||||||
@ -1530,6 +1538,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->tooltip = L("Number of permieter exluded from this option.");
|
def->tooltip = L("Number of permieter exluded from this option.");
|
||||||
def->cli = "min-perimeter-unsupported=i";
|
def->cli = "min-perimeter-unsupported=i";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
|
def->mode = comExpert;
|
||||||
def->default_value = new ConfigOptionInt(0);
|
def->default_value = new ConfigOptionInt(0);
|
||||||
|
|
||||||
def = this->add("noperi_bridge_only", coBool);
|
def = this->add("noperi_bridge_only", coBool);
|
||||||
@ -1537,6 +1546,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->category = L("Layers and Perimeters");
|
def->category = L("Layers and Perimeters");
|
||||||
def->tooltip = L("Only remove perimeters over areas marked as 'bridge'. Can be useful to let perimeter run over overhangs, but it's not very reliable.");
|
def->tooltip = L("Only remove perimeters over areas marked as 'bridge'. Can be useful to let perimeter run over overhangs, but it's not very reliable.");
|
||||||
def->cli = "noperi-bridge-only!";
|
def->cli = "noperi-bridge-only!";
|
||||||
|
def->mode = comExpert;
|
||||||
def->default_value = new ConfigOptionBool(true);
|
def->default_value = new ConfigOptionBool(true);
|
||||||
|
|
||||||
def = this->add("parking_pos_retraction", coFloat);
|
def = this->add("parking_pos_retraction", coFloat);
|
||||||
@ -1665,6 +1675,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->category = L("Support material");
|
def->category = L("Support material");
|
||||||
def->tooltip = L("Use a solid layer instead of a raft for the layer that touch the build plate.");
|
def->tooltip = L("Use a solid layer instead of a raft for the layer that touch the build plate.");
|
||||||
def->cli = "support-material-solid-first-layer!";
|
def->cli = "support-material-solid-first-layer!";
|
||||||
|
def->mode = comAdvanced;
|
||||||
def->default_value = new ConfigOptionBool(false);
|
def->default_value = new ConfigOptionBool(false);
|
||||||
|
|
||||||
def = this->add("raft_layers", coInt);
|
def = this->add("raft_layers", coInt);
|
||||||
@ -1825,6 +1836,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->category = L("Layers and Perimeters");
|
def->category = L("Layers and Perimeters");
|
||||||
def->tooltip = L("Add a big cost to travel paths when possible (when going into a loop), so it will prefer a less optimal seam posistion if it's nearer.");
|
def->tooltip = L("Add a big cost to travel paths when possible (when going into a loop), so it will prefer a less optimal seam posistion if it's nearer.");
|
||||||
def->cli = "seam-travel!";
|
def->cli = "seam-travel!";
|
||||||
|
def->mode = comExpert;
|
||||||
def->default_value = new ConfigOptionBool(false);
|
def->default_value = new ConfigOptionBool(false);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -2509,6 +2521,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
" This might be useful for fine-tuning hole sizes.");
|
" This might be useful for fine-tuning hole sizes.");
|
||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
def->cli = "hole-size-compensation=f";
|
def->cli = "hole-size-compensation=f";
|
||||||
|
def->mode = comExpert;
|
||||||
def->default_value = new ConfigOptionFloat(0);
|
def->default_value = new ConfigOptionFloat(0);
|
||||||
|
|
||||||
def = this->add("z_offset", coFloat);
|
def = this->add("z_offset", coFloat);
|
||||||
|
@ -164,13 +164,12 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<FilamentType>::ge
|
|||||||
return keys_map;
|
return keys_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline t_config_enum_values& ConfigOptionEnum<DenseInfillAlgo>::get_enum_values() {
|
template<> inline const t_config_enum_values& ConfigOptionEnum<DenseInfillAlgo>::get_enum_values() {
|
||||||
static t_config_enum_values keys_map;
|
static const t_config_enum_values keys_map = {
|
||||||
if (keys_map.empty()) {
|
{ "automatic", dfaAutomatic },
|
||||||
keys_map["automatic"] = dfaAutomatic;
|
{ "autosmall", dfaAutoNotFull },
|
||||||
keys_map["autosmall"] = dfaAutoNotFull;
|
{ "enlarged", dfaEnlarged }
|
||||||
keys_map["enlarged"] = dfaEnlarged;
|
};
|
||||||
}
|
|
||||||
return keys_map;
|
return keys_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,18 +695,18 @@ void PrintObject::count_distance_solid() {
|
|||||||
// sparse area = layer's fill area - solid area
|
// sparse area = layer's fill area - solid area
|
||||||
const float COEFF_SPLIT = 2;
|
const float COEFF_SPLIT = 2;
|
||||||
const int NB_DENSE_LAYERS = 1;
|
const int NB_DENSE_LAYERS = 1;
|
||||||
for (int idx_region = 0; idx_region < this->_print->regions.size(); ++idx_region) {
|
for (size_t idx_region = 0; idx_region < this->m_print->regions().size(); ++idx_region) {
|
||||||
//count how many surface there are on each one
|
//count how many surface there are on each one
|
||||||
LayerRegion *previousOne = NULL;
|
LayerRegion *previousOne = NULL;
|
||||||
if (this->layers.size() > 1) previousOne = this->layers[this->layers.size() - 1]->get_region(idx_region);
|
if (this->layers().size() > 1) previousOne = this->layers()[this->layers().size() - 1]->get_region(idx_region);
|
||||||
if (previousOne != NULL && previousOne->region()->config.infill_dense.getBool() && previousOne->region()->config.fill_density<40) {
|
if (previousOne != NULL && previousOne->region()->config().infill_dense.getBool() && previousOne->region()->config().fill_density<40) {
|
||||||
for (Surface &surf : previousOne->fill_surfaces.surfaces) {
|
for (Surface &surf : previousOne->fill_surfaces.surfaces) {
|
||||||
if (surf.is_solid()) {
|
if (surf.is_solid()) {
|
||||||
surf.maxNbSolidLayersOnTop = 0;
|
surf.maxNbSolidLayersOnTop = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int idx_layer = this->layers.size() - 2; idx_layer >= 0; --idx_layer){
|
for (size_t idx_layer = this->layers().size() - 2; idx_layer >= 0; --idx_layer){
|
||||||
LayerRegion *layerm = this->layers[idx_layer]->get_region(idx_region);
|
LayerRegion *layerm = this->layers()[idx_layer]->get_region(idx_region);
|
||||||
Surfaces surf_to_add;
|
Surfaces surf_to_add;
|
||||||
for (auto it_surf = layerm->fill_surfaces.surfaces.begin(); it_surf != layerm->fill_surfaces.surfaces.end(); ++it_surf) {
|
for (auto it_surf = layerm->fill_surfaces.surfaces.begin(); it_surf != layerm->fill_surfaces.surfaces.end(); ++it_surf) {
|
||||||
Surface &surf = *it_surf;
|
Surface &surf = *it_surf;
|
||||||
@ -721,7 +721,7 @@ void PrintObject::count_distance_solid() {
|
|||||||
// upp.expolygon.overlaps(surf.expolygon) or surf.expolygon.overlaps(upp.expolygon)
|
// upp.expolygon.overlaps(surf.expolygon) or surf.expolygon.overlaps(upp.expolygon)
|
||||||
ExPolygons intersect = intersection_ex(sparse_polys, offset_ex(upp.expolygon, -layerm->flow(frInfill).scaled_width()), true);
|
ExPolygons intersect = intersection_ex(sparse_polys, offset_ex(upp.expolygon, -layerm->flow(frInfill).scaled_width()), true);
|
||||||
if (!intersect.empty()) {
|
if (!intersect.empty()) {
|
||||||
if (layerm->region()->config.infill_dense_algo == dfaEnlarged) {
|
if (layerm->region()->config().infill_dense_algo == dfaEnlarged) {
|
||||||
uint16_t dist = (uint16_t)(upp.maxNbSolidLayersOnTop + 1);
|
uint16_t dist = (uint16_t)(upp.maxNbSolidLayersOnTop + 1);
|
||||||
const int nb_dense_layers = 1;
|
const int nb_dense_layers = 1;
|
||||||
if (dist <= nb_dense_layers) {
|
if (dist <= nb_dense_layers) {
|
||||||
@ -729,11 +729,11 @@ void PrintObject::count_distance_solid() {
|
|||||||
uint64_t area_intersect = 0;
|
uint64_t area_intersect = 0;
|
||||||
for (ExPolygon poly_inter : intersect) area_intersect += poly_inter.area();
|
for (ExPolygon poly_inter : intersect) area_intersect += poly_inter.area();
|
||||||
//if it's in a dense area and the current surface isn't a dense one yet and the not-dense is too small.
|
//if it's in a dense area and the current surface isn't a dense one yet and the not-dense is too small.
|
||||||
std::cout << idx_layer << " dfaEnlarged: " << layerm->region()->config.infill_dense_algo << "\n";
|
std::cout << idx_layer << " dfaEnlarged: " << layerm->region()->config().infill_dense_algo << "\n";
|
||||||
std::cout << idx_layer << " dfaEnlarged: 1-" << (layerm->region()->config.infill_dense_algo == dfaEnlarged) << "\n";
|
std::cout << idx_layer << " dfaEnlarged: 1-" << (layerm->region()->config().infill_dense_algo == dfaEnlarged) << "\n";
|
||||||
std::cout << idx_layer << " dfaEnlarged: 2-" << (surf.area() > area_intersect * COEFF_SPLIT) << "\n";
|
std::cout << idx_layer << " dfaEnlarged: 2-" << (surf.area() > area_intersect * COEFF_SPLIT) << "\n";
|
||||||
std::cout << idx_layer << " dfaEnlarged: 3-" << (surf.maxNbSolidLayersOnTop > nb_dense_layers) << "\n";
|
std::cout << idx_layer << " dfaEnlarged: 3-" << (surf.maxNbSolidLayersOnTop > nb_dense_layers) << "\n";
|
||||||
std::cout << idx_layer << " dfaEnlarged: surf.area()=" << unscale(unscale(surf.area())) << ", area_intersect=" << unscale(unscale(area_intersect)) << "\n";
|
std::cout << idx_layer << " dfaEnlarged: surf.area()=" << unscale<double, double>(unscale<double, double>(surf.area())) << ", area_intersect=" << unscale<double, double>(unscale<double, double>(area_intersect)) << "\n";
|
||||||
std::cout << idx_layer << " dfaEnlarged: surf.maxNbSolidLayersOnTop=" << surf.maxNbSolidLayersOnTop << ", NB_DENSE_LAYERS=" << NB_DENSE_LAYERS << "\n";
|
std::cout << idx_layer << " dfaEnlarged: surf.maxNbSolidLayersOnTop=" << surf.maxNbSolidLayersOnTop << ", NB_DENSE_LAYERS=" << NB_DENSE_LAYERS << "\n";
|
||||||
if ((surf.area() > area_intersect * COEFF_SPLIT) &&
|
if ((surf.area() > area_intersect * COEFF_SPLIT) &&
|
||||||
surf.maxNbSolidLayersOnTop > nb_dense_layers) {
|
surf.maxNbSolidLayersOnTop > nb_dense_layers) {
|
||||||
@ -742,8 +742,7 @@ void PrintObject::count_distance_solid() {
|
|||||||
if (dist == 1) {
|
if (dist == 1) {
|
||||||
//if just under the solid area, we can expand a bit
|
//if just under the solid area, we can expand a bit
|
||||||
//remove too small sections and grew a bit to anchor it into the part
|
//remove too small sections and grew a bit to anchor it into the part
|
||||||
intersect = offset_ex(intersect,
|
intersect = offset_ex(intersect, layerm->flow(frInfill).scaled_width() + scale_(layerm->region()->config().bridged_infill_margin));
|
||||||
layerm->flow(frInfill).scaled_width() + scale_(layerm->region()->config.bridged_infill_margin));
|
|
||||||
} else {
|
} else {
|
||||||
//just remove too small sections
|
//just remove too small sections
|
||||||
intersect = offset_ex(intersect,
|
intersect = offset_ex(intersect,
|
||||||
@ -767,7 +766,7 @@ void PrintObject::count_distance_solid() {
|
|||||||
} else {
|
} else {
|
||||||
surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist);
|
surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist);
|
||||||
}
|
}
|
||||||
} else if (layerm->region()->config.infill_dense_algo == dfaAutoNotFull || layerm->region()->config.infill_dense_algo == dfaAutomatic) {
|
} else if (layerm->region()->config().infill_dense_algo == dfaAutoNotFull || layerm->region()->config().infill_dense_algo == dfaAutomatic) {
|
||||||
double area_intersect = 0;
|
double area_intersect = 0;
|
||||||
for (ExPolygon poly_inter : intersect) area_intersect += poly_inter.area();
|
for (ExPolygon poly_inter : intersect) area_intersect += poly_inter.area();
|
||||||
//like intersect.empty() but more resilient
|
//like intersect.empty() but more resilient
|
||||||
@ -776,7 +775,7 @@ void PrintObject::count_distance_solid() {
|
|||||||
if (dist <= NB_DENSE_LAYERS) {
|
if (dist <= NB_DENSE_LAYERS) {
|
||||||
// it will be a dense infill, split the surface if needed
|
// it will be a dense infill, split the surface if needed
|
||||||
//if the not-dense is too big to do a full dense and the current surface isn't a dense one yet.
|
//if the not-dense is too big to do a full dense and the current surface isn't a dense one yet.
|
||||||
if ((layerm->region()->config.infill_dense_algo == dfaAutomatic || surf.area() > area_intersect * COEFF_SPLIT) &&
|
if ((layerm->region()->config().infill_dense_algo == dfaAutomatic || surf.area() > area_intersect * COEFF_SPLIT) &&
|
||||||
surf.maxNbSolidLayersOnTop > NB_DENSE_LAYERS) {
|
surf.maxNbSolidLayersOnTop > NB_DENSE_LAYERS) {
|
||||||
//split in two
|
//split in two
|
||||||
if (dist == 1) {
|
if (dist == 1) {
|
||||||
@ -792,7 +791,7 @@ void PrintObject::count_distance_solid() {
|
|||||||
}
|
}
|
||||||
intersect = offset_ex(cover_intersect,
|
intersect = offset_ex(cover_intersect,
|
||||||
layerm->flow(frInfill).scaled_width());// +scale_(expandby));
|
layerm->flow(frInfill).scaled_width());// +scale_(expandby));
|
||||||
//layerm->region()->config.external_infill_margin));
|
//layerm->region()->config().external_infill_margin));
|
||||||
} else {
|
} else {
|
||||||
//just remove too small sections
|
//just remove too small sections
|
||||||
intersect = offset_ex(intersect,
|
intersect = offset_ex(intersect,
|
||||||
@ -818,10 +817,10 @@ void PrintObject::count_distance_solid() {
|
|||||||
surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist);
|
surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (layerm->region()->config.infill_dense_algo == dfaAutomatic) {
|
} else if (layerm->region()->config().infill_dense_algo == dfaAutomatic) {
|
||||||
double area_intersect = 0;
|
double area_intersect = 0;
|
||||||
for (ExPolygon poly_inter : intersect) area_intersect += poly_inter.area();
|
for (ExPolygon poly_inter : intersect) area_intersect += poly_inter.area();
|
||||||
std::cout << idx_layer << " dfaAutomatic: area_intersect=" << unscale(unscale(area_intersect)) << "\n";
|
std::cout << idx_layer << " dfaAutomatic: area_intersect=" << unscale<double, double>(unscale<double, double>(area_intersect)) << "\n";
|
||||||
//like intersect.empty() but more resilient
|
//like intersect.empty() but more resilient
|
||||||
if (area_intersect > layerm->flow(frInfill).scaled_width() * layerm->flow(frInfill).scaled_width() * 2) {
|
if (area_intersect > layerm->flow(frInfill).scaled_width() * layerm->flow(frInfill).scaled_width() * 2) {
|
||||||
std::cout << idx_layer << " dfaAutomatic: ok\n";
|
std::cout << idx_layer << " dfaAutomatic: ok\n";
|
||||||
@ -847,7 +846,7 @@ void PrintObject::count_distance_solid() {
|
|||||||
}
|
}
|
||||||
intersect = offset_ex(cover_intersect,
|
intersect = offset_ex(cover_intersect,
|
||||||
layerm->flow(frInfill).scaled_width());// +scale_(expandby));
|
layerm->flow(frInfill).scaled_width());// +scale_(expandby));
|
||||||
//layerm->region()->config.external_infill_margin));
|
//layerm->region()->config().external_infill_margin));
|
||||||
} else {
|
} else {
|
||||||
std::cout << "dfaAutomatic: remove too small sections\n";
|
std::cout << "dfaAutomatic: remove too small sections\n";
|
||||||
//just remove too small sections
|
//just remove too small sections
|
||||||
@ -978,7 +977,7 @@ void PrintObject::detect_surfaces_type()
|
|||||||
// unless internal shells are requested
|
// unless internal shells are requested
|
||||||
Layer *upper_layer = (idx_layer + 1 < this->layer_count()) ? m_layers[idx_layer + 1] : nullptr;
|
Layer *upper_layer = (idx_layer + 1 < this->layer_count()) ? m_layers[idx_layer + 1] : nullptr;
|
||||||
Layer *lower_layer = (idx_layer > 0) ? m_layers[idx_layer - 1] : nullptr;
|
Layer *lower_layer = (idx_layer > 0) ? m_layers[idx_layer - 1] : nullptr;
|
||||||
Layer *under_lower_layer = (idx_layer > 1) ? this->layers[idx_layer - 2] : nullptr;
|
Layer *under_lower_layer = (idx_layer > 1) ? this->layers()[idx_layer - 2] : nullptr;
|
||||||
// collapse very narrow parts (using the safety offset in the diff is not enough)
|
// collapse very narrow parts (using the safety offset in the diff is not enough)
|
||||||
float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
|
float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
|
||||||
|
|
||||||
@ -1672,15 +1671,16 @@ void PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_r
|
|||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "overextrude over Bridge...";
|
BOOST_LOG_TRIVIAL(info) << "overextrude over Bridge...";
|
||||||
|
|
||||||
FOREACH_REGION(this->_print, region) {
|
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++region_id) {
|
||||||
size_t region_id = region - this->_print->regions.begin();
|
const PrintRegion ®ion = *m_print->regions()[region_id];
|
||||||
|
|
||||||
|
for (LayerPtrs::iterator layer_it = m_layers.begin(); layer_it != m_layers.end(); ++layer_it) {
|
||||||
|
|
||||||
FOREACH_LAYER(this, layer_it) {
|
|
||||||
// skip first layer
|
// skip first layer
|
||||||
if (layer_it == this->layers.begin()) continue;
|
if (layer_it == this->layers().begin()) continue;
|
||||||
|
|
||||||
Layer* layer = *layer_it;
|
Layer* layer = *layer_it;
|
||||||
LayerRegion* layerm = layer->regions[region_id];
|
LayerRegion* layerm = layer->regions()[region_id];
|
||||||
|
|
||||||
// extract the stInternalSolid surfaces that might be transformed into bridges
|
// extract the stInternalSolid surfaces that might be transformed into bridges
|
||||||
Polygons internal_solid;
|
Polygons internal_solid;
|
||||||
@ -1717,24 +1717,25 @@ void PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_r
|
|||||||
Polygons to_overextrude_pp = internal_solid;
|
Polygons to_overextrude_pp = internal_solid;
|
||||||
|
|
||||||
// get previous layer
|
// get previous layer
|
||||||
if (int(layer_it - this->layers.begin()) - 1 >= 0) {
|
if (int(layer_it - this->layers().begin()) - 1 >= 0) {
|
||||||
const Layer* lower_layer = this->layers[int(layer_it - this->layers.begin()) - 1];
|
const Layer* lower_layer = this->layers()[int(layer_it - this->layers().begin()) - 1];
|
||||||
|
|
||||||
// iterate through regions and collect internal surfaces
|
// iterate through regions and collect internal surfaces
|
||||||
Polygons lower_internal;
|
Polygons lower_internal;
|
||||||
FOREACH_LAYERREGION(lower_layer, lower_layerm_it){
|
for (LayerRegion *lower_layerm : lower_layer->m_regions) {
|
||||||
|
lower_layerm->fill_surfaces.filter_by_type(stInternal, &lower_internal);
|
||||||
Polygons lower_internal_OK;
|
Polygons lower_internal_OK;
|
||||||
Polygons lower_internal_Bridge;
|
Polygons lower_internal_Bridge;
|
||||||
Polygons lower_internal_Over;
|
Polygons lower_internal_Over;
|
||||||
(*lower_layerm_it)->fill_surfaces.filter_by_type(st_replacement, &lower_internal_OK);
|
lower_layerm->fill_surfaces.filter_by_type(st_replacement, &lower_internal_OK);
|
||||||
(*lower_layerm_it)->fill_surfaces.filter_by_type(st_under_it, &lower_internal_Bridge);
|
lower_layerm->fill_surfaces.filter_by_type(st_under_it, &lower_internal_Bridge);
|
||||||
(*lower_layerm_it)->fill_surfaces.filter_by_type(st_to_replace, &lower_internal_Over);
|
lower_layerm->fill_surfaces.filter_by_type(st_to_replace, &lower_internal_Over);
|
||||||
double okarea =0, bridgearea=0, overarea=0;
|
double okarea =0, bridgearea=0, overarea=0;
|
||||||
for (ExPolygon &ex : union_ex(lower_internal_OK)) okarea+=ex.area();
|
for (ExPolygon &ex : union_ex(lower_internal_OK)) okarea+=ex.area();
|
||||||
for (ExPolygon &ex : union_ex(lower_internal_Bridge)) bridgearea+=ex.area();
|
for (ExPolygon &ex : union_ex(lower_internal_Bridge)) bridgearea+=ex.area();
|
||||||
for (ExPolygon &ex : union_ex(lower_internal_Over)) overarea+=ex.area();
|
for (ExPolygon &ex : union_ex(lower_internal_Over)) overarea+=ex.area();
|
||||||
|
|
||||||
(*lower_layerm_it)->fill_surfaces.filter_by_type(st_under_it, &lower_internal);
|
lower_layerm->fill_surfaces.filter_by_type(st_under_it, &lower_internal);
|
||||||
}
|
}
|
||||||
double sumarea=0;
|
double sumarea=0;
|
||||||
for (ExPolygon &ex : union_ex(lower_internal)) sumarea+=ex.area();
|
for (ExPolygon &ex : union_ex(lower_internal)) sumarea+=ex.area();
|
||||||
@ -1990,7 +1991,7 @@ end:
|
|||||||
Layer *layer = m_layers[layer_id];
|
Layer *layer = m_layers[layer_id];
|
||||||
// Apply size compensation and perform clipping of multi-part objects.
|
// Apply size compensation and perform clipping of multi-part objects.
|
||||||
float delta = float(scale_(m_config.xy_size_compensation.value));
|
float delta = float(scale_(m_config.xy_size_compensation.value));
|
||||||
float hole_delta = float(scale_(this->config.hole_size_compensation.value));
|
float hole_delta = float(scale_(this->config().hole_size_compensation.value));
|
||||||
if (layer_id == 0)
|
if (layer_id == 0)
|
||||||
delta -= float(scale_(m_config.elefant_foot_compensation.value));
|
delta -= float(scale_(m_config.elefant_foot_compensation.value));
|
||||||
bool scale = delta != 0.f;
|
bool scale = delta != 0.f;
|
||||||
@ -2001,7 +2002,7 @@ end:
|
|||||||
LayerRegion *layerm = layer->m_regions.front();
|
LayerRegion *layerm = layer->m_regions.front();
|
||||||
layerm->slices.set(offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta), stInternal);
|
layerm->slices.set(offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta), stInternal);
|
||||||
}
|
}
|
||||||
_offsetHoles(hole_delta, layer->regions.front());
|
_offsetHoles(hole_delta, layer->regions().front());
|
||||||
} else if (scale || clip || hole_delta != 0.f) {
|
} else if (scale || clip || hole_delta != 0.f) {
|
||||||
// Multiple regions, growing, shrinking or just clipping one region by the other.
|
// Multiple regions, growing, shrinking or just clipping one region by the other.
|
||||||
// When clipping the regions, priority is given to the first regions.
|
// When clipping the regions, priority is given to the first regions.
|
||||||
|
@ -1197,6 +1197,7 @@ static inline void remove_tangent_edges(std::vector<IntersectionLine> &lines)
|
|||||||
if (l1.edge_type == l2.edge_type) {
|
if (l1.edge_type == l2.edge_type) {
|
||||||
l1.set_skip();
|
l1.set_skip();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(l1.a_id == l2.b_id && l1.b_id == l2.a_id);
|
assert(l1.a_id == l2.b_id && l1.b_id == l2.a_id);
|
||||||
// If this edge joins two horizontal facets, remove both of them.
|
// If this edge joins two horizontal facets, remove both of them.
|
||||||
@ -1212,21 +1213,24 @@ static inline void remove_tangent_edges(std::vector<IntersectionLine> &lines)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct OpenPolyline {
|
struct OpenPolyline {
|
||||||
OpenPolyline() {};
|
OpenPolyline() {};
|
||||||
OpenPolyline(const IntersectionReference &start, const IntersectionReference &end, Points &&points) :
|
OpenPolyline(const IntersectionReference &start, const IntersectionReference &end, Points &&points) :
|
||||||
start(start), end(end), points(std::move(points)), consumed(false) {}
|
start(start), end(end), points(std::move(points)), consumed(false) { this->length = Slic3r::length(this->points); }
|
||||||
void reverse() {
|
void reverse() {
|
||||||
std::swap(start, end);
|
std::swap(start, end);
|
||||||
std::reverse(points.begin(), points.end());
|
std::reverse(points.begin(), points.end());
|
||||||
}
|
}
|
||||||
std::sort(out.begin(), out.end(), [](const OpenPolyline *lhs, const OpenPolyline *rhs){ return lhs->length > rhs->length; });
|
IntersectionReference start;
|
||||||
return out;
|
IntersectionReference end;
|
||||||
}
|
Points points;
|
||||||
|
double length;
|
||||||
|
bool consumed;
|
||||||
|
};
|
||||||
|
|
||||||
// called by TriangleMeshSlicer::make_loops() to connect remaining open polylines across shared triangle edges and vertices.
|
// called by TriangleMeshSlicer::make_loops() to connect sliced triangles into closed loops and open polylines by the triangle connectivity.
|
||||||
// Depending on "try_connect_reversed", it may or may not connect segments crossing triangles of opposite orientation.
|
// Only connects segments crossing triangles of the same orientation.
|
||||||
static void chain_open_polylines_exact(std::vector<OpenPolyline> &open_polylines, Polygons &loops, bool try_connect_reversed)
|
static void chain_lines_by_triangle_connectivity(std::vector<IntersectionLine> &lines, Polygons &loops, std::vector<OpenPolyline> &open_polylines)
|
||||||
{
|
{
|
||||||
// Build a map of lines by edge_a_id and a_id.
|
// Build a map of lines by edge_a_id and a_id.
|
||||||
std::vector<IntersectionLine*> by_edge_a_id;
|
std::vector<IntersectionLine*> by_edge_a_id;
|
||||||
@ -1256,13 +1260,20 @@ static void chain_open_polylines_exact(std::vector<OpenPolyline> &open_polylines
|
|||||||
first_line = &(*it_line_seed ++);
|
first_line = &(*it_line_seed ++);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
if (first_line == nullptr)
|
||||||
auto by_edge_lower = [](const IntersectionLine* il1, const IntersectionLine *il2) { return il1->edge_a_id < il2->edge_a_id; };
|
break;
|
||||||
auto by_vertex_lower = [](const IntersectionLine* il1, const IntersectionLine *il2) { return il1->a_id < il2->a_id; };
|
first_line->set_skip();
|
||||||
std::sort(by_edge_a_id.begin(), by_edge_a_id.end(), by_edge_lower);
|
Points loop_pts;
|
||||||
std::sort(by_a_id.begin(), by_a_id.end(), by_vertex_lower);
|
loop_pts.emplace_back(first_line->a);
|
||||||
// Chain the segments with a greedy algorithm, collect the loops and unclosed polylines.
|
IntersectionLine *last_line = first_line;
|
||||||
IntersectionLines::iterator it_line_seed = lines.begin();
|
|
||||||
|
/*
|
||||||
|
printf("first_line edge_a_id = %d, edge_b_id = %d, a_id = %d, b_id = %d, a = %d,%d, b = %d,%d\n",
|
||||||
|
first_line->edge_a_id, first_line->edge_b_id, first_line->a_id, first_line->b_id,
|
||||||
|
first_line->a.x, first_line->a.y, first_line->b.x, first_line->b.y);
|
||||||
|
*/
|
||||||
|
|
||||||
|
IntersectionLine key;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// find a line starting where last one finishes
|
// find a line starting where last one finishes
|
||||||
IntersectionLine* next_line = nullptr;
|
IntersectionLine* next_line = nullptr;
|
||||||
@ -1308,37 +1319,121 @@ static void chain_open_polylines_exact(std::vector<OpenPolyline> &open_polylines
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Continue with the current loop.
|
/*
|
||||||
|
printf("next_line edge_a_id = %d, edge_b_id = %d, a_id = %d, b_id = %d, a = %d,%d, b = %d,%d\n",
|
||||||
|
next_line->edge_a_id, next_line->edge_b_id, next_line->a_id, next_line->b_id,
|
||||||
|
next_line->a.x, next_line->a.y, next_line->b.x, next_line->b.y);
|
||||||
|
*/
|
||||||
|
loop_pts.emplace_back(next_line->a);
|
||||||
|
last_line = next_line;
|
||||||
|
next_line->set_skip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// called by TriangleMeshSlicer::make_loops() to connect remaining open polylines across shared triangle edges and vertices,
|
std::vector<OpenPolyline*> open_polylines_sorted(std::vector<OpenPolyline> &open_polylines, bool update_lengths)
|
||||||
// possibly closing small gaps.
|
|
||||||
// Depending on "try_connect_reversed", it may or may not connect segments crossing triangles of opposite orientation.
|
|
||||||
static void chain_open_polylines_close_gaps(std::vector<OpenPolyline> &open_polylines, Polygons &loops, double max_gap, bool try_connect_reversed)
|
|
||||||
{
|
{
|
||||||
const coord_t max_gap_scaled = (coord_t)scale_(max_gap);
|
std::vector<OpenPolyline*> out;
|
||||||
|
out.reserve(open_polylines.size());
|
||||||
|
for (OpenPolyline &opl : open_polylines)
|
||||||
|
if (! opl.consumed) {
|
||||||
|
if (update_lengths)
|
||||||
|
opl.length = Slic3r::length(opl.points);
|
||||||
|
out.emplace_back(&opl);
|
||||||
|
}
|
||||||
|
std::sort(out.begin(), out.end(), [](const OpenPolyline *lhs, const OpenPolyline *rhs){ return lhs->length > rhs->length; });
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
// Try to connect the loops.
|
// called by TriangleMeshSlicer::make_loops() to connect remaining open polylines across shared triangle edges and vertices.
|
||||||
|
// Depending on "try_connect_reversed", it may or may not connect segments crossing triangles of opposite orientation.
|
||||||
|
static void chain_open_polylines_exact(std::vector<OpenPolyline> &open_polylines, Polygons &loops, bool try_connect_reversed)
|
||||||
|
{
|
||||||
|
// Store the end points of open_polylines into vectors sorted
|
||||||
|
struct OpenPolylineEnd {
|
||||||
|
OpenPolylineEnd(OpenPolyline *polyline, bool start) : polyline(polyline), start(start) {}
|
||||||
|
OpenPolyline *polyline;
|
||||||
|
// Is it the start or end point?
|
||||||
|
bool start;
|
||||||
|
const IntersectionReference& ipref() const { return start ? polyline->start : polyline->end; }
|
||||||
|
// Return a unique ID for the intersection point.
|
||||||
|
// Return a positive id for a point, or a negative id for an edge.
|
||||||
|
int id() const { const IntersectionReference &r = ipref(); return (r.point_id >= 0) ? r.point_id : - r.edge_id; }
|
||||||
|
bool operator==(const OpenPolylineEnd &rhs) const { return this->polyline == rhs.polyline && this->start == rhs.start; }
|
||||||
|
};
|
||||||
|
auto by_id_lower = [](const OpenPolylineEnd &ope1, const OpenPolylineEnd &ope2) { return ope1.id() < ope2.id(); };
|
||||||
|
std::vector<OpenPolylineEnd> by_id;
|
||||||
|
by_id.reserve(2 * open_polylines.size());
|
||||||
for (OpenPolyline &opl : open_polylines) {
|
for (OpenPolyline &opl : open_polylines) {
|
||||||
if (opl.consumed)
|
if (opl.start.point_id != -1 || opl.start.edge_id != -1)
|
||||||
|
by_id.emplace_back(OpenPolylineEnd(&opl, true));
|
||||||
|
if (try_connect_reversed && (opl.end.point_id != -1 || opl.end.edge_id != -1))
|
||||||
|
by_id.emplace_back(OpenPolylineEnd(&opl, false));
|
||||||
|
}
|
||||||
|
std::sort(by_id.begin(), by_id.end(), by_id_lower);
|
||||||
|
// Find an iterator to by_id_lower for the particular end of OpenPolyline (by comparing the OpenPolyline pointer and the start attribute).
|
||||||
|
auto find_polyline_end = [&by_id, by_id_lower](const OpenPolylineEnd &end) -> std::vector<OpenPolylineEnd>::iterator {
|
||||||
|
for (auto it = std::lower_bound(by_id.begin(), by_id.end(), end, by_id_lower);
|
||||||
|
it != by_id.end() && it->id() == end.id(); ++ it)
|
||||||
|
if (*it == end)
|
||||||
|
return it;
|
||||||
|
return by_id.end();
|
||||||
|
};
|
||||||
|
// Try to connect the loops.
|
||||||
|
std::vector<OpenPolyline*> sorted_by_length = open_polylines_sorted(open_polylines, false);
|
||||||
|
for (OpenPolyline *opl : sorted_by_length) {
|
||||||
|
if (opl->consumed)
|
||||||
continue;
|
continue;
|
||||||
opl.consumed = true;
|
opl->consumed = true;
|
||||||
OpenPolylineEnd end(&opl, false);
|
OpenPolylineEnd end(opl, false);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// find a line starting where last one finishes
|
// find a line starting where last one finishes
|
||||||
OpenPolylineEnd* next_start = nullptr;
|
auto it_next_start = std::lower_bound(by_id.begin(), by_id.end(), end, by_id_lower);
|
||||||
if (end.edge_id() != -1) {
|
for (; it_next_start != by_id.end() && it_next_start->id() == end.id(); ++ it_next_start)
|
||||||
auto it_begin = std::lower_bound(by_edge_id.begin(), by_edge_id.end(), end, by_edge_lower);
|
if (! it_next_start->polyline->consumed)
|
||||||
if (it_begin != by_edge_id.end()) {
|
goto found;
|
||||||
auto it_end = std::upper_bound(it_begin, by_edge_id.end(), end, by_edge_lower);
|
// The current loop could not be closed. Unmark the segment.
|
||||||
for (auto it_edge = it_begin; it_edge != it_end; ++ it_edge)
|
opl->consumed = false;
|
||||||
if (! it_edge->polyline->consumed) {
|
|
||||||
next_start = &(*it_edge);
|
|
||||||
break;
|
break;
|
||||||
|
found:
|
||||||
|
// Attach this polyline to the end of the initial polyline.
|
||||||
|
if (it_next_start->start) {
|
||||||
|
auto it = it_next_start->polyline->points.begin();
|
||||||
|
std::copy(++ it, it_next_start->polyline->points.end(), back_inserter(opl->points));
|
||||||
|
} else {
|
||||||
|
auto it = it_next_start->polyline->points.rbegin();
|
||||||
|
std::copy(++ it, it_next_start->polyline->points.rend(), back_inserter(opl->points));
|
||||||
}
|
}
|
||||||
|
opl->length += it_next_start->polyline->length;
|
||||||
|
// Mark the next polyline as consumed.
|
||||||
|
it_next_start->polyline->points.clear();
|
||||||
|
it_next_start->polyline->length = 0.;
|
||||||
|
it_next_start->polyline->consumed = true;
|
||||||
|
if (try_connect_reversed) {
|
||||||
|
// Running in a mode, where the polylines may be connected by mixing their orientations.
|
||||||
|
// Update the end point lookup structure after the end point of the current polyline was extended.
|
||||||
|
auto it_end = find_polyline_end(end);
|
||||||
|
auto it_next_end = find_polyline_end(OpenPolylineEnd(it_next_start->polyline, !it_next_start->start));
|
||||||
|
// Swap the end points of the current and next polyline, but keep the polyline ptr and the start flag.
|
||||||
|
std::swap(opl->end, it_next_end->start ? it_next_end->polyline->start : it_next_end->polyline->end);
|
||||||
|
// Swap the positions of OpenPolylineEnd structures in the sorted array to match their respective end point positions.
|
||||||
|
std::swap(*it_end, *it_next_end);
|
||||||
}
|
}
|
||||||
|
// Check whether we closed this loop.
|
||||||
|
if ((opl->start.edge_id != -1 && opl->start.edge_id == opl->end.edge_id) ||
|
||||||
|
(opl->start.point_id != -1 && opl->start.point_id == opl->end.point_id)) {
|
||||||
|
// The current loop is complete. Add it to the output.
|
||||||
|
//assert(opl->points.front().point_id == opl->points.back().point_id);
|
||||||
|
//assert(opl->points.front().edge_id == opl->points.back().edge_id);
|
||||||
|
// Remove the duplicate last point.
|
||||||
|
opl->points.pop_back();
|
||||||
|
if (opl->points.size() >= 3) {
|
||||||
|
if (try_connect_reversed && area(opl->points) < 0)
|
||||||
|
// The closed polygon is patched from pieces with messed up orientation, therefore
|
||||||
|
// the orientation of the patched up polygon is not known.
|
||||||
|
// Orient the patched up polygons CCW. This heuristic may close some holes and cavities.
|
||||||
|
std::reverse(opl->points.begin(), opl->points.end());
|
||||||
|
loops.emplace_back(std::move(opl->points));
|
||||||
}
|
}
|
||||||
opl->points.clear();
|
opl->points.clear();
|
||||||
break;
|
break;
|
||||||
@ -1680,7 +1775,7 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic
|
|||||||
// 0.0499 comes from https://github.com/slic3r/Slic3r/issues/959
|
// 0.0499 comes from https://github.com/slic3r/Slic3r/issues/959
|
||||||
// double safety_offset = scale_(0.0499);
|
// double safety_offset = scale_(0.0499);
|
||||||
// 0.0001 is set to satisfy GH #520, #1029, #1364
|
// 0.0001 is set to satisfy GH #520, #1029, #1364
|
||||||
// double safety_offset = scale_(0.0001);
|
// double safety_offset = scale_(0.0001); // now a config value
|
||||||
|
|
||||||
/* The following line is commented out because it can generate wrong polygons,
|
/* The following line is commented out because it can generate wrong polygons,
|
||||||
see for example issue #661 */
|
see for example issue #661 */
|
||||||
|
@ -174,7 +174,7 @@ public:
|
|||||||
const float min_z, const float max_z, IntersectionLine *line_out) const;
|
const float min_z, const float max_z, IntersectionLine *line_out) const;
|
||||||
void cut(float z, TriangleMesh* upper, TriangleMesh* lower) const;
|
void cut(float z, TriangleMesh* upper, TriangleMesh* lower) const;
|
||||||
|
|
||||||
double safety_offset = scale_(0.0499);
|
double safety_offset = scale_(0.02);
|
||||||
private:
|
private:
|
||||||
const TriangleMesh *mesh;
|
const TriangleMesh *mesh;
|
||||||
// Map from a facet to an edge index.
|
// Map from a facet to an edge index.
|
||||||
|
@ -80,6 +80,8 @@ namespace Slic3r {
|
|||||||
template<typename T, typename Q>
|
template<typename T, typename Q>
|
||||||
inline T unscale(Q v) { return T(v) * T(SCALING_FACTOR); }
|
inline T unscale(Q v) { return T(v) * T(SCALING_FACTOR); }
|
||||||
|
|
||||||
|
inline double unscaled(double v) { return v * SCALING_FACTOR; }
|
||||||
|
|
||||||
enum Axis { X=0, Y, Z, E, F, NUM_AXES };
|
enum Axis { X=0, Y, Z, E, F, NUM_AXES };
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -930,7 +930,7 @@ void TabPrint::build()
|
|||||||
|
|
||||||
optgroup = page->new_optgroup(_(L("Advanced")));
|
optgroup = page->new_optgroup(_(L("Advanced")));
|
||||||
optgroup->append_single_option_line("remove_small_gaps");
|
optgroup->append_single_option_line("remove_small_gaps");
|
||||||
line = { _(L("Avoid unsupported perimeters")), "" };
|
line = { _(L("Seam")), "" };
|
||||||
line.append_option(optgroup->get_option("seam_position"));
|
line.append_option(optgroup->get_option("seam_position"));
|
||||||
line.append_option(optgroup->get_option("seam_travel"));
|
line.append_option(optgroup->get_option("seam_travel"));
|
||||||
optgroup->append_line(line);
|
optgroup->append_line(line);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user