From 05414e0e5678df7db3bebb1f0e71ca124a3d3a8f Mon Sep 17 00:00:00 2001 From: supermerill Date: Fri, 3 Aug 2018 16:53:48 +0200 Subject: [PATCH] overlap: now perimetergenerator store the not-overlap polygons in the layer region. fill smooth use it for the first layer fill_exactly use it, it's much more reliable now. --- xs/src/libslic3r/Fill/Fill.cpp | 25 +++-- xs/src/libslic3r/Fill/FillBase.cpp | 106 ++++++++++----------- xs/src/libslic3r/Fill/FillBase.hpp | 1 + xs/src/libslic3r/Fill/FillSmooth.cpp | 120 ++++++++++++++++-------- xs/src/libslic3r/Layer.hpp | 2 + xs/src/libslic3r/LayerRegion.cpp | 2 + xs/src/libslic3r/PerimeterGenerator.cpp | 18 +++- xs/src/libslic3r/PerimeterGenerator.hpp | 1 + xs/src/libslic3r/Surface.hpp | 1 + 9 files changed, 175 insertions(+), 101 deletions(-) diff --git a/xs/src/libslic3r/Fill/Fill.cpp b/xs/src/libslic3r/Fill/Fill.cpp index b690b9191..b0b806fd1 100644 --- a/xs/src/libslic3r/Fill/Fill.cpp +++ b/xs/src/libslic3r/Fill/Fill.cpp @@ -34,10 +34,11 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) { // Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id; - double fill_density = layerm.region()->config.fill_density; - Flow infill_flow = layerm.flow(frInfill); - Flow solid_infill_flow = layerm.flow(frSolidInfill); - Flow top_solid_infill_flow = layerm.flow(frTopSolidInfill); + double fill_density = layerm.region()->config.fill_density; + Flow infill_flow = layerm.flow(frInfill); + Flow solid_infill_flow = layerm.flow(frSolidInfill); + Flow top_solid_infill_flow = layerm.flow(frTopSolidInfill); + const float perimeter_spacing = layerm.flow(frPerimeter).spacing(); Surfaces surfaces; @@ -258,8 +259,20 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) f->link_max_length = scale_(link_max_length); // Used by the concentric infill pattern to clip the loops to create extrusion paths. f->loop_clipping = scale_(flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER; - //give the overlap size, it's not the real value (it can depend of the external_perimeter_extrusion_width) - f->overlap = layerm.region()->config.infill_overlap.get_abs_value(flow.nozzle_diameter); + //give the overlap size to let the infill do his overlap + //add overlap if at least one perimeter + if (layerm.region()->config.perimeters.getInt() > 0) { + f->overlap = layerm.region()->config.get_abs_value("infill_overlap", (perimeter_spacing + (f->spacing)) / 2); + if (f->overlap!=0) { + f->no_overlap_expolygons = intersection_ex(layerm.fill_no_overlap_expolygons, ExPolygons() = { surface.expolygon }); + } else { + f->no_overlap_expolygons.push_back(surface.expolygon); + } + } else { + f->overlap = 0; + f->no_overlap_expolygons.push_back(surface.expolygon); + } + // apply half spacing using this flow's own spacing and generate infill FillParams params; params.density = 0.01 * density; diff --git a/xs/src/libslic3r/Fill/FillBase.cpp b/xs/src/libslic3r/Fill/FillBase.cpp index f7db9cf72..fe7591494 100644 --- a/xs/src/libslic3r/Fill/FillBase.cpp +++ b/xs/src/libslic3r/Fill/FillBase.cpp @@ -35,10 +35,10 @@ Fill* Fill::new_from_type(const InfillPattern type) // case ipGrid: return new FillGrid(); case ipArchimedeanChords: return new FillArchimedeanChords(); case ipHilbertCurve: return new FillHilbertCurve(); - case ipOctagramSpiral: return new FillOctagramSpiral(); - case ipSmooth: return new FillSmooth(); - case ipSmoothTriple: return new FillSmoothTriple(); - case ipSmoothHilbert: return new FillSmoothHilbert(); + case ipOctagramSpiral: return new FillOctagramSpiral(); + case ipSmooth: return new FillSmooth(); + case ipSmoothTriple: return new FillSmoothTriple(); + case ipSmoothHilbert: return new FillSmoothHilbert(); default: CONFESS("unknown type"); return nullptr; } } @@ -76,10 +76,10 @@ coord_t Fill::_adjust_solid_spacing(const coord_t width, const coord_t distance) assert(width >= 0); assert(distance > 0); // floor(width / distance) - coord_t number_of_intervals = (width - EPSILON) / distance; + coord_t number_of_intervals = (coord_t)((width - EPSILON) / distance); coord_t distance_new = (number_of_intervals == 0) ? distance : - ((width - EPSILON) / number_of_intervals); + (coord_t)(((width - EPSILON) / number_of_intervals)); const coordf_t factor = coordf_t(distance_new) / coordf_t(distance); assert(factor > 1. - 1e-5); // How much could the extrusion width be increased? By 20%. @@ -96,8 +96,8 @@ std::pair Fill::_infill_direction(const Surface *surface) const // set infill angle float out_angle = this->angle; - if (out_angle == FLT_MAX) { - //FIXME Vojtech: Add a warning? + if (out_angle == FLT_MAX) { + //FIXME Vojtech: Add a warning? printf("Using undefined infill angle\n"); out_angle = 0.f; } @@ -105,7 +105,7 @@ std::pair Fill::_infill_direction(const Surface *surface) const // Bounding box is the bounding box of a perl object Slic3r::Print::Object (c++ object Slic3r::PrintObject) // The bounding box is only undefined in unit tests. Point out_shift = empty(this->bounding_box) ? - surface->expolygon.contour.bounding_box().center() : + surface->expolygon.contour.bounding_box().center() : this->bounding_box.center(); #if 0 @@ -117,73 +117,71 @@ std::pair Fill::_infill_direction(const Surface *surface) const #endif if (surface->bridge_angle >= 0) { - // use bridge angle - //FIXME Vojtech: Add a debugf? + // use bridge angle + //FIXME Vojtech: Add a debugf? // Slic3r::debugf "Filling bridge with angle %d\n", rad2deg($surface->bridge_angle); #ifdef SLIC3R_DEBUG printf("Filling bridge with angle %f\n", surface->bridge_angle); #endif /* SLIC3R_DEBUG */ - out_angle = surface->bridge_angle; + out_angle = (float)(surface->bridge_angle); } else if (this->layer_id != size_t(-1)) { // alternate fill direction out_angle += this->_layer_angle(this->layer_id / surface->thickness_layers); } else { -// printf("Layer_ID undefined!\n"); +// printf("Layer_ID undefined!\n"); } out_angle += float(M_PI/2.); return std::pair(out_angle, out_shift); } -void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, ExtrusionEntityCollection &out ){ +void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, ExtrusionEntityCollection &out) { + //add overlap & call fill_surface Polylines polylines = this->fill_surface(surface, params); if (polylines.empty()) return; - // ensure it doesn't over or under-extrude - double multFlow = 1; + // ensure it doesn't over or under-extrude + double multFlow = 1; if (!params.dont_adjust && params.full_infill() && !flow.bridge && params.fill_exactly){ - // compute the path of the nozzle -> extruded volume - double lengthTot = 0; - int nbLines = 0; - for (auto pline = polylines.begin(); pline != polylines.end(); ++pline){ - Lines lines = pline->lines(); - for (auto line = lines.begin(); line != lines.end(); ++line){ - lengthTot += unscale(line->length()); - nbLines++; - } - } - double extrudedVolume = flow.mm3_per_mm() * lengthTot; - // compute real volume - double poylineVolume = 0; - /// un-overlap the surface (it's done in perimeterGenerator, it just pass the surface polys a bit bigger to us, - /// so we have to shrink it, it's silly, it should be here we should decide how to use the overlap setting!) - ExPolygons noOffsetPolys = offset_ex(surface->expolygon, -scale_(this->overlap)); - for (auto poly = noOffsetPolys.begin(); poly != noOffsetPolys.end(); ++poly){ - poylineVolume += flow.height*unscale(unscale(poly->area())); - // add external "perimeter gap" - double perimeterRoundGap = unscale(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5; - // add holes "perimeter gaps" - double holesGaps = 0; - for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole){ - holesGaps += unscale(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5; - } - /*printf("process want %f mm3 extruded for a volume of %f (%f + %f + %f) space : we mult by %f \n", - extrudedVolume, - (poylineVolume + perimeterRoundGap + holesGaps), - poylineVolume, perimeterRoundGap, holesGaps, - (poylineVolume + perimeterRoundGap + holesGaps) / extrudedVolume);*/ - poylineVolume += perimeterRoundGap + holesGaps; - } - if (extrudedVolume != 0) multFlow = poylineVolume / extrudedVolume; - } + // compute the path of the nozzle -> extruded volume + double lengthTot = 0; + int nbLines = 0; + for (auto pline = polylines.begin(); pline != polylines.end(); ++pline){ + Lines lines = pline->lines(); + for (auto line = lines.begin(); line != lines.end(); ++line){ + lengthTot += unscale(line->length()); + nbLines++; + } + } + double extrudedVolume = flow.mm3_per_mm() * lengthTot; + // compute real volume + double poylineVolume = 0; + for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) { + poylineVolume += flow.height*unscale(unscale(poly->area())); + // add external "perimeter gap" + double perimeterRoundGap = unscale(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5; + // add holes "perimeter gaps" + double holesGaps = 0; + for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) { + holesGaps += unscale(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5; + } + poylineVolume += perimeterRoundGap + holesGaps; + } + //printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n", + // extrudedVolume, + // (poylineVolume), + // (poylineVolume) / extrudedVolume, + // this->no_overlap_expolygons.size()); + if (extrudedVolume != 0 && poylineVolume != 0) multFlow = poylineVolume / extrudedVolume; + } // Save into layer. auto *eec = new ExtrusionEntityCollection(); /// pass the no_sort attribute to the extrusion path eec->no_sort = this->no_sort(); - /// add it into the collection - out.entities.push_back(eec); - /// push the path + /// add it into the collection + out.entities.push_back(eec); + /// push the path extrusion_entities_append_paths( eec->entities, STDMOVE(polylines), flow.bridge ? @@ -191,7 +189,7 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ (surface->is_solid() ? ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : erInternalInfill), - flow.mm3_per_mm() * params.flow_mult * multFlow, flow.width * params.flow_mult, flow.height); + flow.mm3_per_mm() * params.flow_mult * multFlow, flow.width * params.flow_mult * multFlow, flow.height); } diff --git a/xs/src/libslic3r/Fill/FillBase.hpp b/xs/src/libslic3r/Fill/FillBase.hpp index 94213649e..e569a4773 100644 --- a/xs/src/libslic3r/Fill/FillBase.hpp +++ b/xs/src/libslic3r/Fill/FillBase.hpp @@ -59,6 +59,7 @@ public: coordf_t spacing; // infill / perimeter overlap, in unscaled coordinates coordf_t overlap; + ExPolygons no_overlap_expolygons; // in radians, ccw, 0 = East float angle; // In scaled coordinates. Maximum lenght of a perimeter segment connecting two infill lines. diff --git a/xs/src/libslic3r/Fill/FillSmooth.cpp b/xs/src/libslic3r/Fill/FillSmooth.cpp index d7572d7a5..3fc1d7d1c 100644 --- a/xs/src/libslic3r/Fill/FillSmooth.cpp +++ b/xs/src/libslic3r/Fill/FillSmooth.cpp @@ -32,18 +32,22 @@ namespace Slic3r { params2.density *= percentWidth[1]; params3.density *= percentWidth[2]; - //a small under-overlap to prevent over-extrudion on thin surfaces (i.e. remove the overlap) - Surface surfaceNoOverlap(*surface); - //remove the overlap (prevent over-extruding) if possible - ExPolygons noOffsetPolys = offset_ex(surfaceNoOverlap.expolygon, -scale_(this->overlap) * (flow.bridge?0:1)); - //printf("FillSmooth::fill_surface() : overlap=%f->%f.\n", overlap, -scale_(this->overlap)); - //printf("FillSmooth::polys : 1->%i.\n", noOffsetPolys.size()); - //printf("FillSmooth::polys : %f %f->%f.\n", surface->expolygon.area(), surfaceNoOverlap.expolygon.area(), noOffsetPolys[0].area()); - //if (offsetPolys.size() == 1) surfaceNoOverlap.expolygon = offsetPolys[0]; - - //TODO: recursive if multiple polys instead of failing - + // compute the volume to extrude + double volumeToOccupy = 0; + for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) { + // add external "perimeter gap" + double poylineVolume = flow.height*unscale(unscale(poly->area())); + double perimeterRoundGap = unscale(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5; + // add holes "perimeter gaps" + double holesGaps = 0; + for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) { + holesGaps += unscale(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5; + } + poylineVolume += perimeterRoundGap + holesGaps; + //extruded volume: see http://manual.slic3r.org/advanced/flow-math, and we need to remove a circle at an end (as the flow continue) + volumeToOccupy += poylineVolume; + } //if (polylines_layer1.empty() && polylines_layer2.empty() && polylines_layer3.empty()) // return; @@ -54,7 +58,6 @@ namespace Slic3r { ExtrusionEntityCollection *eec; - double volumeToOccupy = 0; // first infill std::unique_ptr f1 = std::unique_ptr(Fill::new_from_type(fillPattern[0])); @@ -67,34 +70,35 @@ namespace Slic3r { f1->link_max_length = this->link_max_length; // Used by the concentric infill pattern to clip the loops to create extrusion paths. f1->loop_clipping = this->loop_clipping; - for (auto poly = noOffsetPolys.begin(); poly != noOffsetPolys.end(); ++poly){ - surfaceNoOverlap.expolygon = *poly; - Polylines polylines_layer1 = f1->fill_surface(&surfaceNoOverlap, params1); - if (!polylines_layer1.empty()){ + Surface surfaceNoOverlap(*surface); + if (flow.bridge) { + Polylines polylines_layer1 = f1->fill_surface(surface, params1); + + if (!polylines_layer1.empty()) { + if (fillPattern[2] == InfillPattern::ipRectilinear && polylines_layer1[0].points.size() > 3) { + polylines_layer1[0].points.erase(polylines_layer1[0].points.begin()); + polylines_layer1[polylines_layer1.size() - 1].points.pop_back(); + } + + //compute the path of the nozzle double lengthTot = 0; int nbLines = 0; - 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(); - for (auto line = lines.begin(); line != lines.end(); ++line){ + for (auto line = lines.begin(); line != lines.end(); ++line) { lengthTot += unscale(line->length()); nbLines++; } } - - // add external "perimeter gap" - double poylineVolume = flow.height*unscale(unscale(poly->area())); - double perimeterRoundGap = unscale(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5; - // add holes "perimeter gaps" - double holesGaps = 0; - for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole){ - holesGaps += unscale(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5; - } - poylineVolume += perimeterRoundGap + holesGaps; - - //extruded volume: see http://manual.slic3r.org/advanced/flow-math, and we need to remove a circle at an end (as the flow continue) double extrudedVolume = flow.mm3_per_mm() * lengthTot; - volumeToOccupy += poylineVolume; + if (extrudedVolume == 0) extrudedVolume = 1; + + // Save into layer smoothing path. + eec = new ExtrusionEntityCollection(); + eecroot->entities.push_back(eec); + eec->no_sort = false; + // print thin eec = new ExtrusionEntityCollection(); eecroot->entities.push_back(eec); @@ -103,12 +107,54 @@ namespace Slic3r { eec->entities, STDMOVE(polylines_layer1), flow.bridge ? erBridgeInfill : rolePass[0], //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), - (float)(flow.width*percentFlow[0] * (params.fill_exactly ? poylineVolume / extrudedVolume : 1)), (float)flow.height*0.8); - } - else{ + params.flow_mult * flow.mm3_per_mm() * percentFlow[0] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1), + (float)(flow.width*percentFlow[0] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1)), (float)flow.height*0.8); + } else { return; } + + } else { + for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) { + surfaceNoOverlap.expolygon = *poly; + Polylines polylines_layer1 = f1->fill_surface(&surfaceNoOverlap, params1); + if (!polylines_layer1.empty()) { + + double lengthTot = 0; + int nbLines = 0; + for (auto pline = polylines_layer1.begin(); pline != polylines_layer1.end(); ++pline) { + Lines lines = pline->lines(); + for (auto line = lines.begin(); line != lines.end(); ++line) { + lengthTot += unscale(line->length()); + nbLines++; + } + } + + // add external "perimeter gap" + double poylineVolume = flow.height*unscale(unscale(poly->area())); + double perimeterRoundGap = unscale(poly->contour.length()) * flow.height * (1 - 0.25*PI) * 0.5; + // add holes "perimeter gaps" + double holesGaps = 0; + for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) { + holesGaps += unscale(hole->length()) * flow.height * (1 - 0.25*PI) * 0.5; + } + poylineVolume += perimeterRoundGap + holesGaps; + + //extruded volume: see http://manual.slic3r.org/advanced/flow-math, and we need to remove a circle at an end (as the flow continue) + double extrudedVolume = flow.mm3_per_mm() * lengthTot; + + eec = new ExtrusionEntityCollection(); + eecroot->entities.push_back(eec); + eec->no_sort = false; //can be sorted inside the pass + extrusion_entities_append_paths( + eec->entities, STDMOVE(polylines_layer1), + flow.bridge ? erBridgeInfill : rolePass[0], + //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), + (float)(flow.width*percentFlow[0] * (params.fill_exactly ? poylineVolume / extrudedVolume : 1)), (float)flow.height*0.8); + } else { + return; + } + } } //second infill @@ -154,8 +200,8 @@ namespace Slic3r { extrusion_entities_append_paths( eec->entities, STDMOVE(polylines_layer2), rolePass[1], - //reduced flow width for a better view (it's only a gui thing) - 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) (float)(flow.width*(percentFlow[1] < 0.1 ? 0.1 : percentFlow[1])), (float)flow.height); } else{ diff --git a/xs/src/libslic3r/Layer.hpp b/xs/src/libslic3r/Layer.hpp index f3b460443..84bb9cb9e 100644 --- a/xs/src/libslic3r/Layer.hpp +++ b/xs/src/libslic3r/Layer.hpp @@ -38,6 +38,8 @@ public: // Unspecified fill polygons, used for overhang detection ("ensure vertical wall thickness feature") // and for re-starting of infills. 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 SurfaceCollection fill_surfaces; diff --git a/xs/src/libslic3r/LayerRegion.cpp b/xs/src/libslic3r/LayerRegion.cpp index e29f5618a..a409f3885 100644 --- a/xs/src/libslic3r/LayerRegion.cpp +++ b/xs/src/libslic3r/LayerRegion.cpp @@ -84,6 +84,8 @@ LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* g.solid_infill_flow = this->flow(frSolidInfill); g.process(); + + this->fill_no_overlap_expolygons = g.fill_no_overlap; } //#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 3. diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/xs/src/libslic3r/PerimeterGenerator.cpp index f9a7652bf..31de8a8d3 100644 --- a/xs/src/libslic3r/PerimeterGenerator.cpp +++ b/xs/src/libslic3r/PerimeterGenerator.cpp @@ -425,8 +425,10 @@ void PerimeterGenerator::process() // two or more loops? perimeter_spacing / 2; // only apply infill overlap if we actually have one perimeter - if (inset > 0) - inset -= scale_(this->config->get_abs_value("infill_overlap", unscale(inset + solid_infill_spacing / 2))); + coord_t overlap = 0; + if (inset > 0) { + overlap = scale_(this->config->get_abs_value("infill_overlap", unscale(inset + solid_infill_spacing / 2))); + } // simplify infill contours according to resolution Polygons pp; for (ExPolygon &ex : last) @@ -434,12 +436,20 @@ void PerimeterGenerator::process() // collapse too narrow infill areas coord_t min_perimeter_infill_spacing = solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE); // append infill areas to fill_surfaces + //auto it_surf = this->fill_surfaces->surfaces.end(); this->fill_surfaces->append( offset2_ex( union_ex(pp), - -inset -min_perimeter_infill_spacing/2, + -inset - min_perimeter_infill_spacing / 2 + overlap, min_perimeter_infill_spacing / 2), - stInternal); + stInternal); + if (overlap != 0) { + ExPolygons polyWithoutOverlap = offset2_ex( + union_ex(pp), + -inset - min_perimeter_infill_spacing / 2, + min_perimeter_infill_spacing / 2); + this->fill_no_overlap.insert(this->fill_no_overlap.end(), polyWithoutOverlap.begin(), polyWithoutOverlap.end()); + } } // for each island } diff --git a/xs/src/libslic3r/PerimeterGenerator.hpp b/xs/src/libslic3r/PerimeterGenerator.hpp index 3c2288b0a..f89311c19 100644 --- a/xs/src/libslic3r/PerimeterGenerator.hpp +++ b/xs/src/libslic3r/PerimeterGenerator.hpp @@ -58,6 +58,7 @@ public: ExtrusionEntityCollection* loops; ExtrusionEntityCollection* gap_fill; SurfaceCollection* fill_surfaces; + ExPolygons fill_no_overlap; PerimeterGenerator( // Input: diff --git a/xs/src/libslic3r/Surface.hpp b/xs/src/libslic3r/Surface.hpp index 7d04a906d..f9bba7891 100644 --- a/xs/src/libslic3r/Surface.hpp +++ b/xs/src/libslic3r/Surface.hpp @@ -37,6 +37,7 @@ class Surface public: SurfaceType surface_type; ExPolygon expolygon; + ExPolygons notOverlaps; double thickness; // in mm unsigned short thickness_layers; // in layers double bridge_angle; // in radians, ccw, 0 = East, only 0+ (negative means undefined)