mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-22 08:11:11 -06:00
Finished porting LayerRegion to C++
This commit is contained in:
parent
5b8ed7367a
commit
9fcec10737
28 changed files with 319 additions and 203 deletions
|
@ -185,16 +185,12 @@ BridgeDetector::detect_angle()
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BridgeDetector::coverage(Polygons* coverage) const
|
||||
{
|
||||
if (this->angle == -1) return;
|
||||
return this->coverage(angle, coverage);
|
||||
}
|
||||
|
||||
void
|
||||
BridgeDetector::coverage(double angle, Polygons* coverage) const
|
||||
{
|
||||
if (angle == -1) angle = this->angle;
|
||||
if (angle == -1) return;
|
||||
|
||||
// Clone our expolygon and rotate it so that we work with vertical lines.
|
||||
ExPolygon expolygon = this->expolygon;
|
||||
expolygon.rotate(PI/2.0 - angle, Point(0,0));
|
||||
|
@ -263,19 +259,23 @@ BridgeDetector::coverage(double angle, Polygons* coverage) const
|
|||
*/
|
||||
}
|
||||
|
||||
Polygons
|
||||
BridgeDetector::coverage(double angle) const
|
||||
{
|
||||
Polygons pp;
|
||||
this->coverage(angle, &pp);
|
||||
return pp;
|
||||
}
|
||||
|
||||
/* This method returns the bridge edges (as polylines) that are not supported
|
||||
but would allow the entire bridge area to be bridged with detected angle
|
||||
if supported too */
|
||||
void
|
||||
BridgeDetector::unsupported_edges(Polylines* unsupported) const
|
||||
{
|
||||
if (this->angle == -1) return;
|
||||
return this->unsupported_edges(this->angle, unsupported);
|
||||
}
|
||||
|
||||
void
|
||||
BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const
|
||||
{
|
||||
if (angle == -1) angle = this->angle;
|
||||
if (angle == -1) return;
|
||||
|
||||
// get bridge edges (both contour and holes)
|
||||
Polylines bridge_edges;
|
||||
{
|
||||
|
@ -319,6 +319,14 @@ BridgeDetector::unsupported_edges(double angle, Polylines* unsupported) const
|
|||
*/
|
||||
}
|
||||
|
||||
Polylines
|
||||
BridgeDetector::unsupported_edges(double angle) const
|
||||
{
|
||||
Polylines pp;
|
||||
this->unsupported_edges(angle, &pp);
|
||||
return pp;
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(BridgeDetector, "BridgeDetector");
|
||||
#endif
|
||||
|
|
|
@ -18,10 +18,10 @@ class BridgeDetector {
|
|||
|
||||
BridgeDetector(const ExPolygon &_expolygon, const ExPolygonCollection &_lower_slices, coord_t _extrusion_width);
|
||||
bool detect_angle();
|
||||
void coverage(Polygons* coverage) const;
|
||||
void coverage(double angle, Polygons* coverage) const;
|
||||
void unsupported_edges(Polylines* unsupported) const;
|
||||
Polygons coverage(double angle = -1) const;
|
||||
void unsupported_edges(double angle, Polylines* unsupported) const;
|
||||
Polylines unsupported_edges(double angle = -1) const;
|
||||
|
||||
private:
|
||||
Polylines _edges; // representing the supporting edges
|
||||
|
|
|
@ -212,6 +212,15 @@ offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float
|
|||
ClipperPaths_to_Slic3rExPolygons(output, retval);
|
||||
}
|
||||
|
||||
Slic3r::ExPolygons
|
||||
offset_ex(const Slic3r::Polygons &polygons, const float delta,
|
||||
double scale, ClipperLib::JoinType joinType, double miterLimit)
|
||||
{
|
||||
Slic3r::ExPolygons expp;
|
||||
offset(polygons, &expp, delta, scale, joinType, miterLimit);
|
||||
return expp;
|
||||
}
|
||||
|
||||
void
|
||||
offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1,
|
||||
const float delta2, const double scale, const ClipperLib::JoinType joinType, const double miterLimit)
|
||||
|
@ -472,13 +481,16 @@ diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_
|
|||
return pp;
|
||||
}
|
||||
|
||||
template <class SubjectType, class ClipType>
|
||||
Slic3r::ExPolygons
|
||||
diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_)
|
||||
diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_)
|
||||
{
|
||||
Slic3r::ExPolygons expp;
|
||||
diff(subject, clip, &expp, safety_offset_);
|
||||
return expp;
|
||||
}
|
||||
template Slic3r::ExPolygons diff_ex<Slic3r::Polygons, Slic3r::Polygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_);
|
||||
template Slic3r::ExPolygons diff_ex<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_);
|
||||
|
||||
template <class SubjectType, class ResultType>
|
||||
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_)
|
||||
|
@ -507,6 +519,14 @@ intersection(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, boo
|
|||
return pp;
|
||||
}
|
||||
|
||||
Slic3r::ExPolygons
|
||||
intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_)
|
||||
{
|
||||
Slic3r::ExPolygons expp;
|
||||
intersection(subject, clip, &expp, safety_offset_);
|
||||
return expp;
|
||||
}
|
||||
|
||||
template <class SubjectType>
|
||||
bool intersects(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_)
|
||||
{
|
||||
|
|
|
@ -58,6 +58,9 @@ void offset(const Slic3r::Surface &surface, Slic3r::Surfaces* retval, const floa
|
|||
void offset(const Slic3r::Polygons &polygons, Slic3r::ExPolygons* retval, const float delta,
|
||||
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
||||
double miterLimit = 3);
|
||||
Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta,
|
||||
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
||||
double miterLimit = 3);
|
||||
|
||||
void offset2(const Slic3r::Polygons &polygons, ClipperLib::Paths* retval, const float delta1,
|
||||
const float delta2, double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
||||
|
@ -96,13 +99,16 @@ template <class SubjectType, class ResultType>
|
|||
void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_ = false);
|
||||
|
||||
Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
||||
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
||||
|
||||
template <class SubjectType, class ClipType>
|
||||
Slic3r::ExPolygons diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_ = false);
|
||||
|
||||
template <class SubjectType, class ResultType>
|
||||
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false);
|
||||
|
||||
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
||||
Slic3r::Polylines intersection(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
||||
Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
||||
|
||||
template <class SubjectType>
|
||||
bool intersects(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false);
|
||||
|
|
|
@ -122,6 +122,12 @@ ExPolygonCollection::contours() const
|
|||
return contours;
|
||||
}
|
||||
|
||||
void
|
||||
ExPolygonCollection::append(const ExPolygons &expp)
|
||||
{
|
||||
this->expolygons.insert(this->expolygons.end(), expp.begin(), expp.end());
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(ExPolygonCollection, "ExPolygon::Collection");
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,7 @@ class ExPolygonCollection
|
|||
Polygon convex_hull() const;
|
||||
Lines lines() const;
|
||||
Polygons contours() const;
|
||||
void append(const ExPolygons &expolygons);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -40,8 +40,7 @@ class LayerRegion
|
|||
|
||||
// collection of expolygons representing the bridged areas (thus not
|
||||
// needing support material)
|
||||
// (this could be just a Polygons object)
|
||||
ExPolygonCollection bridged;
|
||||
Polygons bridged;
|
||||
|
||||
// collection of polylines representing the unsupported bridge edges
|
||||
PolylineCollection unsupported_bridge_edges;
|
||||
|
@ -58,6 +57,8 @@ class LayerRegion
|
|||
void merge_slices();
|
||||
void prepare_fill_surfaces();
|
||||
void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces);
|
||||
void process_external_surfaces(const Layer* lower_layer);
|
||||
double infill_area_threshold() const;
|
||||
|
||||
private:
|
||||
Layer *_layer;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "Layer.hpp"
|
||||
#include "BridgeDetector.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "PerimeterGenerator.hpp"
|
||||
#include "Print.hpp"
|
||||
|
@ -86,6 +87,146 @@ LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection*
|
|||
g.process();
|
||||
}
|
||||
|
||||
void
|
||||
LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
{
|
||||
const Surfaces &surfaces = this->fill_surfaces.surfaces;
|
||||
const double margin = scale_(EXTERNAL_INFILL_MARGIN);
|
||||
|
||||
SurfaceCollection bottom;
|
||||
for (Surfaces::const_iterator surface = surfaces.begin(); surface != surfaces.end(); ++surface) {
|
||||
if (!surface->is_bottom()) continue;
|
||||
|
||||
ExPolygons grown = offset_ex(surface->expolygon, +margin);
|
||||
|
||||
/* detect bridge direction before merging grown surfaces otherwise adjacent bridges
|
||||
would get merged into a single one while they need different directions
|
||||
also, supply the original expolygon instead of the grown one, because in case
|
||||
of very thin (but still working) anchors, the grown expolygon would go beyond them */
|
||||
double angle = -1;
|
||||
if (lower_layer != NULL) {
|
||||
BridgeDetector bd(
|
||||
surface->expolygon,
|
||||
lower_layer->slices,
|
||||
this->flow(frInfill, this->layer()->height, true).scaled_width()
|
||||
);
|
||||
|
||||
#ifdef SLIC3R_DEBUG
|
||||
printf("Processing bridge at layer %zu:\n", this->layer()->id();
|
||||
#endif
|
||||
|
||||
if (bd.detect_angle() && this->layer()->object()->config.support_material) {
|
||||
angle = bd.angle;
|
||||
|
||||
Polygons coverage = bd.coverage();
|
||||
this->bridged.insert(this->bridged.end(), coverage.begin(), coverage.end());
|
||||
this->unsupported_bridge_edges.append(bd.unsupported_edges());
|
||||
}
|
||||
}
|
||||
|
||||
for (ExPolygons::const_iterator it = grown.begin(); it != grown.end(); ++it) {
|
||||
Surface s = *surface;
|
||||
s.expolygon = *it;
|
||||
s.bridge_angle = angle;
|
||||
bottom.surfaces.push_back(s);
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceCollection top;
|
||||
for (Surfaces::const_iterator surface = surfaces.begin(); surface != surfaces.end(); ++surface) {
|
||||
if (surface->surface_type != stTop) continue;
|
||||
|
||||
// give priority to bottom surfaces
|
||||
ExPolygons grown = diff_ex(
|
||||
offset(surface->expolygon, +margin),
|
||||
(Polygons)bottom
|
||||
);
|
||||
for (ExPolygons::const_iterator it = grown.begin(); it != grown.end(); ++it) {
|
||||
Surface s = *surface;
|
||||
s.expolygon = *it;
|
||||
top.surfaces.push_back(s);
|
||||
}
|
||||
}
|
||||
|
||||
/* if we're slicing with no infill, we can't extend external surfaces
|
||||
over non-existent infill */
|
||||
SurfaceCollection fill_boundaries;
|
||||
if (this->region()->config.fill_density.value > 0) {
|
||||
fill_boundaries = SurfaceCollection(surfaces);
|
||||
} else {
|
||||
for (Surfaces::const_iterator it = surfaces.begin(); it != surfaces.end(); ++it) {
|
||||
if (it->surface_type != stInternal)
|
||||
fill_boundaries.surfaces.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
// intersect the grown surfaces with the actual fill boundaries
|
||||
SurfaceCollection new_surfaces;
|
||||
{
|
||||
// merge top and bottom in a single collection
|
||||
SurfaceCollection tb = top;
|
||||
tb.surfaces.insert(tb.surfaces.end(), bottom.surfaces.begin(), bottom.surfaces.end());
|
||||
|
||||
// group surfaces
|
||||
std::vector<SurfacesPtr> groups;
|
||||
tb.group(&groups);
|
||||
|
||||
for (std::vector<SurfacesPtr>::const_iterator g = groups.begin(); g != groups.end(); ++g) {
|
||||
Polygons subject;
|
||||
for (SurfacesPtr::const_iterator s = g->begin(); s != g->end(); ++s) {
|
||||
Polygons pp = **s;
|
||||
subject.insert(subject.end(), pp.begin(), pp.end());
|
||||
}
|
||||
|
||||
ExPolygons expp = intersection_ex(
|
||||
subject,
|
||||
(Polygons)fill_boundaries,
|
||||
true // to ensure adjacent expolygons are unified
|
||||
);
|
||||
|
||||
for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) {
|
||||
Surface s = *g->front();
|
||||
s.expolygon = *ex;
|
||||
new_surfaces.surfaces.push_back(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* subtract the new top surfaces from the other non-top surfaces and re-add them */
|
||||
{
|
||||
SurfaceCollection other;
|
||||
for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
|
||||
if (s->surface_type != stTop && !s->is_bottom())
|
||||
other.surfaces.push_back(*s);
|
||||
}
|
||||
|
||||
// group surfaces
|
||||
std::vector<SurfacesPtr> groups;
|
||||
other.group(&groups);
|
||||
|
||||
for (std::vector<SurfacesPtr>::const_iterator g = groups.begin(); g != groups.end(); ++g) {
|
||||
Polygons subject;
|
||||
for (SurfacesPtr::const_iterator s = g->begin(); s != g->end(); ++s) {
|
||||
Polygons pp = **s;
|
||||
subject.insert(subject.end(), pp.begin(), pp.end());
|
||||
}
|
||||
|
||||
ExPolygons expp = diff_ex(
|
||||
subject,
|
||||
(Polygons)new_surfaces
|
||||
);
|
||||
|
||||
for (ExPolygons::const_iterator ex = expp.begin(); ex != expp.end(); ++ex) {
|
||||
Surface s = *g->front();
|
||||
s.expolygon = *ex;
|
||||
new_surfaces.surfaces.push_back(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->fill_surfaces = new_surfaces;
|
||||
}
|
||||
|
||||
void
|
||||
LayerRegion::prepare_fill_surfaces()
|
||||
{
|
||||
|
@ -123,6 +264,13 @@ LayerRegion::prepare_fill_surfaces()
|
|||
}
|
||||
}
|
||||
|
||||
double
|
||||
LayerRegion::infill_area_threshold() const
|
||||
{
|
||||
double ss = this->flow(frSolidInfill).scaled_spacing();
|
||||
return ss*ss;
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(LayerRegion, "Layer::Region");
|
||||
#endif
|
||||
|
|
|
@ -47,7 +47,7 @@ PerimeterGenerator::process()
|
|||
for (Surfaces::const_iterator surface = this->slices->surfaces.begin();
|
||||
surface != this->slices->surfaces.end(); ++surface) {
|
||||
// detect how many perimeters must be generated for this island
|
||||
short loop_number = this->config->perimeters + surface->extra_perimeters;
|
||||
signed short loop_number = this->config->perimeters + surface->extra_perimeters;
|
||||
loop_number--; // 0-indexed loops
|
||||
|
||||
Polygons gaps;
|
||||
|
@ -60,7 +60,7 @@ PerimeterGenerator::process()
|
|||
Polylines thin_walls;
|
||||
|
||||
// we loop one time more than needed in order to find gaps after the last perimeter was applied
|
||||
for (unsigned short i = 0; i <= loop_number+1; ++i) { // outer loop is 0
|
||||
for (signed short i = 0; i <= loop_number+1; ++i) { // outer loop is 0
|
||||
Polygons offsets;
|
||||
if (i == 0) {
|
||||
// the minimum thickness of a single loop is:
|
||||
|
@ -166,16 +166,16 @@ PerimeterGenerator::process()
|
|||
}
|
||||
|
||||
// nest loops: holes first
|
||||
for (unsigned short d = 0; d <= loop_number; ++d) {
|
||||
for (signed short d = 0; d <= loop_number; ++d) {
|
||||
PerimeterGeneratorLoops &holes_d = holes[d];
|
||||
|
||||
// loop through all holes having depth == d
|
||||
for (unsigned short i = 0; i < holes_d.size(); ++i) {
|
||||
for (signed short i = 0; i < holes_d.size(); ++i) {
|
||||
const PerimeterGeneratorLoop &loop = holes_d[i];
|
||||
|
||||
// find the hole loop that contains this one, if any
|
||||
for (unsigned short t = d+1; t <= loop_number; ++t) {
|
||||
for (unsigned short j = 0; j < holes[t].size(); ++j) {
|
||||
for (signed short t = d+1; t <= loop_number; ++t) {
|
||||
for (signed short j = 0; j < holes[t].size(); ++j) {
|
||||
PerimeterGeneratorLoop &candidate_parent = holes[t][j];
|
||||
if (candidate_parent.polygon.contains(loop.polygon.first_point())) {
|
||||
candidate_parent.children.push_back(loop);
|
||||
|
@ -187,8 +187,8 @@ PerimeterGenerator::process()
|
|||
}
|
||||
|
||||
// if no hole contains this hole, find the contour loop that contains it
|
||||
for (short t = loop_number; t >= 0; --t) {
|
||||
for (unsigned short j = 0; j < contours[t].size(); ++j) {
|
||||
for (signed short t = loop_number; t >= 0; --t) {
|
||||
for (signed short j = 0; j < contours[t].size(); ++j) {
|
||||
PerimeterGeneratorLoop &candidate_parent = contours[t][j];
|
||||
if (candidate_parent.polygon.contains(loop.polygon.first_point())) {
|
||||
candidate_parent.children.push_back(loop);
|
||||
|
@ -203,16 +203,16 @@ PerimeterGenerator::process()
|
|||
}
|
||||
|
||||
// nest contour loops
|
||||
for (short d = loop_number; d >= 1; --d) {
|
||||
for (signed short d = loop_number; d >= 1; --d) {
|
||||
PerimeterGeneratorLoops &contours_d = contours[d];
|
||||
|
||||
// loop through all contours having depth == d
|
||||
for (unsigned short i = 0; i < contours_d.size(); ++i) {
|
||||
for (signed short i = 0; i < contours_d.size(); ++i) {
|
||||
const PerimeterGeneratorLoop &loop = contours_d[i];
|
||||
|
||||
// find the contour loop that contains it
|
||||
for (short t = d-1; t >= 0; --t) {
|
||||
for (unsigned short j = 0; j < contours[t].size(); ++j) {
|
||||
for (signed short t = d-1; t >= 0; --t) {
|
||||
for (signed short j = 0; j < contours[t].size(); ++j) {
|
||||
PerimeterGeneratorLoop &candidate_parent = contours[t][j];
|
||||
if (candidate_parent.polygon.contains(loop.polygon.first_point())) {
|
||||
candidate_parent.children.push_back(loop);
|
||||
|
|
|
@ -50,6 +50,12 @@ PolylineCollection::leftmost_point() const
|
|||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
PolylineCollection::append(const Polylines &pp)
|
||||
{
|
||||
this->polylines.insert(this->polylines.end(), pp.begin(), pp.end());
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(PolylineCollection, "Polyline::Collection");
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,7 @@ class PolylineCollection
|
|||
void chained_path(PolylineCollection* retval, bool no_reverse = false) const;
|
||||
void chained_path_from(Point start_near, PolylineCollection* retval, bool no_reverse = false) const;
|
||||
Point leftmost_point() const;
|
||||
void append(const Polylines &polylines);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -135,6 +135,7 @@ class PrintObject
|
|||
bool invalidate_all_steps();
|
||||
|
||||
bool has_support_material() const;
|
||||
void process_external_surfaces();
|
||||
void bridge_over_infill();
|
||||
|
||||
private:
|
||||
|
|
|
@ -340,14 +340,32 @@ PrintObject::has_support_material() const
|
|||
|| this->config.support_material_enforce_layers > 0;
|
||||
}
|
||||
|
||||
void
|
||||
PrintObject::process_external_surfaces()
|
||||
{
|
||||
FOREACH_REGION(this->_print, region) {
|
||||
size_t region_id = region - this->_print->regions.begin();
|
||||
|
||||
FOREACH_LAYER(this, layer_it) {
|
||||
const Layer* lower_layer = (layer_it == this->layers.begin())
|
||||
? NULL
|
||||
: *(layer_it-1);
|
||||
|
||||
(*layer_it)->get_region(region_id)->process_external_surfaces(lower_layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This method applies bridge flow to the first internal solid layer above
|
||||
sparse infill */
|
||||
void
|
||||
PrintObject::bridge_over_infill()
|
||||
{
|
||||
FOREACH_REGION(this->_print, region) {
|
||||
size_t region_id = region - this->_print->regions.begin();
|
||||
|
||||
double fill_density = (*region)->config.fill_density.value;
|
||||
if (fill_density == 100) continue;
|
||||
// skip bridging in case there are no voids
|
||||
if ((*region)->config.fill_density.value == 100) continue;
|
||||
|
||||
// get bridge flow
|
||||
Flow bridge_flow = (*region)->flow(
|
||||
|
@ -360,6 +378,7 @@ PrintObject::bridge_over_infill()
|
|||
);
|
||||
|
||||
FOREACH_LAYER(this, layer_it) {
|
||||
// skip first layer
|
||||
if (layer_it == this->layers.begin()) continue;
|
||||
|
||||
Layer* layer = *layer_it;
|
||||
|
@ -379,7 +398,7 @@ PrintObject::bridge_over_infill()
|
|||
// iterate through lower layers spanned by bridge_flow
|
||||
double bottom_z = layer->print_z - bridge_flow.height;
|
||||
for (int i = (layer_it - this->layers.begin()) - 1; i >= 0; --i) {
|
||||
Layer* lower_layer = this->layers[i];
|
||||
const Layer* lower_layer = this->layers[i];
|
||||
|
||||
// stop iterating if layer is lower than bottom_z
|
||||
if (lower_layer->print_z < bottom_z) break;
|
||||
|
@ -390,19 +409,19 @@ PrintObject::bridge_over_infill()
|
|||
(*lower_layerm_it)->fill_surfaces.filter_by_type(stInternal, &lower_internal);
|
||||
|
||||
// intersect such lower internal surfaces with the candidate solid surfaces
|
||||
intersection(to_bridge_pp, lower_internal, &to_bridge_pp);
|
||||
to_bridge_pp = intersection(to_bridge_pp, lower_internal);
|
||||
}
|
||||
|
||||
// there's no point in bridging too thin/short regions
|
||||
{
|
||||
double min_width = bridge_flow.scaled_width() * 3;
|
||||
offset2(to_bridge_pp, &to_bridge_pp, -min_width, +min_width);
|
||||
to_bridge_pp = offset2(to_bridge_pp, -min_width, +min_width);
|
||||
}
|
||||
|
||||
if (to_bridge_pp.empty()) continue;
|
||||
|
||||
// convert into ExPolygons
|
||||
union_(to_bridge_pp, &to_bridge);
|
||||
to_bridge = union_ex(to_bridge_pp);
|
||||
}
|
||||
|
||||
#ifdef SLIC3R_DEBUG
|
||||
|
@ -410,8 +429,7 @@ PrintObject::bridge_over_infill()
|
|||
#endif
|
||||
|
||||
// compute the remaning internal solid surfaces as difference
|
||||
ExPolygons not_to_bridge;
|
||||
diff(internal_solid, to_bridge, ¬_to_bridge, true);
|
||||
ExPolygons not_to_bridge = diff_ex(internal_solid, to_bridge, true);
|
||||
|
||||
// build the new collection of fill_surfaces
|
||||
{
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
Surface::operator Polygons() const
|
||||
{
|
||||
return this->expolygon;
|
||||
}
|
||||
|
||||
double
|
||||
Surface::area() const
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@ class Surface
|
|||
: surface_type(_surface_type), expolygon(_expolygon),
|
||||
thickness(-1), thickness_layers(1), bridge_angle(-1), extra_perimeters(0)
|
||||
{};
|
||||
operator Polygons() const;
|
||||
double area() const;
|
||||
bool is_solid() const;
|
||||
bool is_external() const;
|
||||
|
|
|
@ -111,6 +111,12 @@ SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::append(const SurfaceCollection &coll)
|
||||
{
|
||||
this->surfaces.insert(this->surfaces.end(), coll.surfaces.begin(), coll.surfaces.end());
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(SurfaceCollection, "Surface::Collection");
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,9 @@ class SurfaceCollection
|
|||
public:
|
||||
Surfaces surfaces;
|
||||
|
||||
SurfaceCollection() {};
|
||||
SurfaceCollection(const Surfaces &_surfaces)
|
||||
: surfaces(_surfaces) {};
|
||||
operator Polygons() const;
|
||||
operator ExPolygons() const;
|
||||
void simplify(double tolerance);
|
||||
|
@ -19,6 +22,7 @@ class SurfaceCollection
|
|||
template <class T> bool any_bottom_contains(const T &item) const;
|
||||
SurfacesPtr filter_by_type(SurfaceType type);
|
||||
void filter_by_type(SurfaceType type, Polygons* polygons);
|
||||
void append(const SurfaceCollection &coll);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER 0.15
|
||||
#define SMALL_PERIMETER_LENGTH (6.5 / SCALING_FACTOR) * 2 * PI
|
||||
#define INSET_OVERLAP_TOLERANCE 0.4
|
||||
#define EXTERNAL_INFILL_MARGIN 3
|
||||
#define scale_(val) (val / SCALING_FACTOR)
|
||||
#define unscale(val) (val * SCALING_FACTOR)
|
||||
#define SCALED_EPSILON scale_(EPSILON)
|
||||
|
|
|
@ -9,14 +9,10 @@
|
|||
~BridgeDetector();
|
||||
|
||||
bool detect_angle();
|
||||
Polygons coverage()
|
||||
%code{% THIS->coverage(&RETVAL); %};
|
||||
Polygons coverage_by_angle(double angle)
|
||||
%code{% THIS->coverage(angle, &RETVAL); %};
|
||||
Polylines unsupported_edges()
|
||||
%code{% THIS->unsupported_edges(&RETVAL); %};
|
||||
Polylines unsupported_edges_by_angle(double angle)
|
||||
%code{% THIS->unsupported_edges(angle, &RETVAL); %};
|
||||
Polygons coverage();
|
||||
%name{coverage_by_angle} Polygons coverage(double angle);
|
||||
Polylines unsupported_edges();
|
||||
%name{unsupported_edges_by_angle} Polylines unsupported_edges(double angle);
|
||||
double angle()
|
||||
%code{% RETVAL = THIS->angle; %};
|
||||
double resolution()
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
%code%{ RETVAL = &THIS->thin_fills; %};
|
||||
Ref<SurfaceCollection> fill_surfaces()
|
||||
%code%{ RETVAL = &THIS->fill_surfaces; %};
|
||||
Ref<ExPolygonCollection> bridged()
|
||||
%code%{ RETVAL = &THIS->bridged; %};
|
||||
Polygons bridged()
|
||||
%code%{ RETVAL = THIS->bridged; %};
|
||||
Ref<PolylineCollection> unsupported_bridge_edges()
|
||||
%code%{ RETVAL = &THIS->unsupported_bridge_edges; %};
|
||||
Ref<ExtrusionEntityCollection> perimeters()
|
||||
|
@ -32,6 +32,7 @@
|
|||
void prepare_fill_surfaces();
|
||||
void make_perimeters(SurfaceCollection* slices, SurfaceCollection* fill_surfaces)
|
||||
%code%{ THIS->make_perimeters(*slices, fill_surfaces); %};
|
||||
double infill_area_threshold();
|
||||
};
|
||||
|
||||
%name{Slic3r::Layer} class Layer {
|
||||
|
|
|
@ -107,6 +107,7 @@ _constant()
|
|||
void set_step_started(PrintObjectStep step)
|
||||
%code%{ THIS->state.set_started(step); %};
|
||||
|
||||
void process_external_surfaces();
|
||||
void bridge_over_infill();
|
||||
|
||||
int ptr()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue