mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 07:25:53 +08:00
Flags for surface_type
simplify the dense_infill algo. TODO: use a flag instead of the field. TODO: use the flags (without creating bugs)
This commit is contained in:
parent
b372e00464
commit
9454415e6d
@ -30,6 +30,9 @@ enum ExtrusionRole {
|
||||
// Extrusion role for a collection with multiple extrusion roles.
|
||||
erMixed,
|
||||
};
|
||||
// perimeter / infill / support / skirt / gapfill / wipetower / custom / mixed
|
||||
// side / internal / top / bottom
|
||||
// bridge
|
||||
|
||||
inline bool is_perimeter(ExtrusionRole role)
|
||||
{
|
||||
|
@ -66,7 +66,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||
for (uint32_t num_srf = 0; num_srf < groups[num_group].size(); ++num_srf) {
|
||||
Surface *srf = groups[num_group][num_srf];
|
||||
//if solid, wrong group
|
||||
if (srf->is_solid()) break;
|
||||
if (srf->has_fill_solid()) break;
|
||||
//find surface that can be used as dense infill
|
||||
if (srf->maxNbSolidLayersOnTop <= 1
|
||||
&& srf->maxNbSolidLayersOnTop > 0) {
|
||||
@ -100,11 +100,11 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||
// we can only merge solid non-bridge non-overextruded surfaces, so discard
|
||||
// non-solid surfaces
|
||||
const Surface &surface = *groups[i].front();
|
||||
if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0) && !surface.is_overBridge()) {
|
||||
if (surface.has_fill_solid() && (!surface.has_mod_bridge() || layerm.layer()->id() == 0) && !surface.has_mod_overBridge()) {
|
||||
group_attrib[i].is_solid = true;
|
||||
group_attrib[i].flow_width = (surface.is_top()) ? top_solid_infill_flow.width : solid_infill_flow.width;
|
||||
group_attrib[i].pattern = (surface.is_top() && surface.is_external()) ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().solid_fill_pattern.value;
|
||||
group_attrib[i].pattern = (surface.is_bottom() && surface.is_external()) ? layerm.region()->config().bottom_fill_pattern.value : layerm.region()->config().solid_fill_pattern.value;
|
||||
group_attrib[i].flow_width = (surface.has_pos_top()) ? top_solid_infill_flow.width : solid_infill_flow.width;
|
||||
group_attrib[i].pattern = surface.has_pos_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().solid_fill_pattern.value;
|
||||
group_attrib[i].pattern = surface.has_pos_bottom() ? layerm.region()->config().bottom_fill_pattern.value : layerm.region()->config().solid_fill_pattern.value;
|
||||
}
|
||||
}
|
||||
// Loop through solid groups, find compatible groups and append them to this one.
|
||||
@ -183,7 +183,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||
Polygons to_subtract;
|
||||
to_subtract.reserve(collapsed.size() + number_polygons(surfaces));
|
||||
for (Surfaces::const_iterator it_surface = surfaces.begin(); it_surface != surfaces.end(); ++ it_surface)
|
||||
if (it_surface->surface_type == stInternalVoid)
|
||||
if (it_surface->surface_type == (stPosInternal |stDensVoid) )
|
||||
polygons_append(to_subtract, *it_surface);
|
||||
polygons_append(to_subtract, collapsed);
|
||||
surfaces_append(
|
||||
@ -192,7 +192,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||
offset(collapsed, distance_between_surfaces),
|
||||
to_subtract,
|
||||
true),
|
||||
stInternalSolid);
|
||||
stPosInternal | stDensSolid);
|
||||
}*/
|
||||
|
||||
if (0) {
|
||||
@ -203,20 +203,20 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||
// );
|
||||
}
|
||||
for (const Surface &surface : surfaces) {
|
||||
if (surface.surface_type == stInternalVoid)
|
||||
if (surface.surface_type == (stPosInternal | stDensVoid))
|
||||
continue;
|
||||
InfillPattern fill_pattern = layerm.region()->config().fill_pattern.value;
|
||||
double density = fill_density;
|
||||
FlowRole role = (surface.is_top()) ? frTopSolidInfill :
|
||||
(surface.is_solid() ? frSolidInfill : frInfill);
|
||||
bool is_bridge = layerm.layer()->id() > 0 && surface.is_bridge();
|
||||
FlowRole role = (surface.has_pos_top()) ? frTopSolidInfill :
|
||||
(surface.has_fill_solid() ? frSolidInfill : frInfill);
|
||||
bool is_bridge = layerm.layer()->id() > 0 && surface.has_mod_bridge();
|
||||
bool is_denser = false;
|
||||
|
||||
if (surface.is_solid()) {
|
||||
if (surface.has_fill_solid()) {
|
||||
density = 100.;
|
||||
fill_pattern = ipRectilinear;
|
||||
if (surface.is_external() && !is_bridge)
|
||||
fill_pattern = surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value;
|
||||
if (surface.has_pos_external() && !is_bridge)
|
||||
fill_pattern = surface.has_pos_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value;
|
||||
else if (!is_bridge)
|
||||
fill_pattern = layerm.region()->config().solid_fill_pattern.value;
|
||||
} else {
|
||||
@ -249,7 +249,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||
|
||||
// calculate flow spacing for infill pattern generation
|
||||
bool using_internal_flow = false;
|
||||
if (! surface.is_solid() && ! is_bridge) {
|
||||
if (! surface.has_fill_solid() && ! is_bridge) {
|
||||
// it's internal infill, so we can calculate a generic flow spacing
|
||||
// for all layers, for avoiding the ugly effect of
|
||||
// misaligned infill on first layer because of different extrusion width and
|
||||
@ -314,7 +314,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||
}
|
||||
|
||||
float flow_percent = 1;
|
||||
if(surface.is_overBridge()){
|
||||
if (surface.has_mod_overBridge()){
|
||||
params.density = layerm.region()->config().over_bridge_flow_ratio;
|
||||
//params.flow_mult = layerm.region()->config().over_bridge_flow_ratio;
|
||||
}
|
||||
|
@ -189,13 +189,7 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶
|
||||
/// add it into the collection
|
||||
out.push_back(eec);
|
||||
//get the role
|
||||
ExtrusionRole good_role = params.role;
|
||||
if (good_role == erNone || good_role == erCustom) {
|
||||
good_role = (params.flow->bridge ? erBridgeInfill :
|
||||
(surface->is_solid() ?
|
||||
((surface->is_top()) ? erTopSolidInfill : erSolidInfill) :
|
||||
erInternalInfill));
|
||||
}
|
||||
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
|
||||
/// push the path
|
||||
extrusion_entities_append_paths(
|
||||
eec->entities, std::move(polylines),
|
||||
|
@ -132,6 +132,17 @@ protected:
|
||||
|
||||
void connect_infill(const Polylines &infill_ordered, const ExPolygon &boundary, Polylines &polylines_out);
|
||||
|
||||
ExtrusionRole getRoleFromSurfaceType(const FillParams ¶ms, const Surface *surface){
|
||||
if (params.role == erNone || params.role == erCustom) {
|
||||
return params.flow->bridge ?
|
||||
erBridgeInfill :
|
||||
(surface->has_fill_solid() ?
|
||||
((surface->has_pos_top()) ? erTopSolidInfill : erSolidInfill) :
|
||||
erInternalInfill);
|
||||
}
|
||||
return params.role;
|
||||
}
|
||||
|
||||
public:
|
||||
static coord_t _adjust_solid_spacing(const coord_t width, const coord_t distance);
|
||||
|
||||
|
@ -125,13 +125,7 @@ void FillConcentricWGapFill::fill_surface_extrusion(const Surface *surface, cons
|
||||
|
||||
|
||||
//get the role
|
||||
ExtrusionRole good_role = params.role;
|
||||
if (good_role == erNone || good_role == erCustom) {
|
||||
good_role = (params.flow->bridge ? erBridgeInfill :
|
||||
(surface->is_solid() ?
|
||||
((surface->is_top()) ? erTopSolidInfill : erSolidInfill) :
|
||||
erInternalInfill));
|
||||
}
|
||||
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
|
||||
|
||||
ExtrusionEntityCollection *coll_nosort = new ExtrusionEntityCollection();
|
||||
coll_nosort->no_sort = true; //can be sorted inside the pass
|
||||
|
@ -1537,14 +1537,7 @@ FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillP
|
||||
/// add it into the collection
|
||||
eecroot->entities.push_back(eec);
|
||||
//get the role
|
||||
ExtrusionRole good_role = params.role;
|
||||
if (good_role == erNone || good_role == erCustom) {
|
||||
good_role = params.flow->bridge ?
|
||||
erBridgeInfill :
|
||||
(surface->is_solid() ?
|
||||
((surface->is_top()) ? erTopSolidInfill : erSolidInfill) :
|
||||
erInternalInfill);
|
||||
}
|
||||
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
|
||||
/// push the path
|
||||
extrusion_entities_append_paths(
|
||||
eec->entities,
|
||||
@ -1576,14 +1569,7 @@ FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillP
|
||||
/// add it into the collection
|
||||
eecroot->entities.push_back(eec);
|
||||
//get the role
|
||||
ExtrusionRole good_role = params.role;
|
||||
if (good_role == erNone || good_role == erCustom) {
|
||||
good_role = params.flow->bridge ?
|
||||
erBridgeInfill :
|
||||
(surface->is_solid() ?
|
||||
((surface->is_top()) ? erTopSolidInfill : erSolidInfill) :
|
||||
erInternalInfill);
|
||||
}
|
||||
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
|
||||
/// push the path
|
||||
extrusion_entities_append_paths(
|
||||
eec->entities,
|
||||
@ -1683,14 +1669,8 @@ FillRectilinearSawtooth::fill_surface_extrusion(const Surface *surface, const Fi
|
||||
/// pass the no_sort attribute to the extrusion path
|
||||
eec->no_sort = this->no_sort();
|
||||
|
||||
ExtrusionRole good_role = params.role;
|
||||
if (good_role == erNone || good_role == erCustom) {
|
||||
good_role = params.flow->bridge ?
|
||||
erBridgeInfill :
|
||||
(surface->is_solid() ?
|
||||
((surface->is_top()) ? erTopSolidInfill : erSolidInfill) :
|
||||
erInternalInfill);
|
||||
}
|
||||
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
|
||||
|
||||
for (Polyline poly : polylines_out) {
|
||||
if (!poly.is_valid()) continue;
|
||||
|
||||
|
@ -70,11 +70,11 @@ void Layer::merge_slices()
|
||||
if (m_regions.size() == 1) {
|
||||
// Optimization, also more robust. Don't merge classified pieces of layerm->slices,
|
||||
// but use the non-split islands of a layer. For a single region print, these shall be equal.
|
||||
m_regions.front()->slices.set(this->slices.expolygons, stInternal);
|
||||
m_regions.front()->slices.set(this->slices.expolygons, stPosInternal | stDensSparse);
|
||||
} else {
|
||||
for (LayerRegion *layerm : m_regions)
|
||||
// without safety offset, artifacts are generated (GH #2494)
|
||||
layerm->slices.set(union_ex(to_polygons(std::move(layerm->slices.surfaces)), true), stInternal);
|
||||
layerm->slices.set(union_ex(to_polygons(std::move(layerm->slices.surfaces)), true), stPosInternal | stDensSparse);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,16 +37,15 @@ void LayerRegion::slices_to_fill_surfaces_clipped()
|
||||
// Polygons fill_boundaries = to_polygons(std::move(this->fill_surfaces));
|
||||
Polygons fill_boundaries = to_polygons(this->fill_expolygons);
|
||||
// Collect polygons per surface type.
|
||||
std::vector<Polygons> polygons_by_surface;
|
||||
polygons_by_surface.assign(size_t(stCount), Polygons());
|
||||
for (Surface &surface : this->slices.surfaces)
|
||||
polygons_append(polygons_by_surface[(size_t)surface.surface_type], surface.expolygon);
|
||||
std::map<SurfaceType, Polygons> polygons_by_surface;
|
||||
for (Surface &surface : this->slices.surfaces) {
|
||||
polygons_append(polygons_by_surface[surface.surface_type], surface.expolygon);
|
||||
}
|
||||
// Trim surfaces by the fill_boundaries.
|
||||
this->fill_surfaces.surfaces.clear();
|
||||
for (size_t surface_type = 0; surface_type < size_t(stCount); ++ surface_type) {
|
||||
const Polygons &polygons = polygons_by_surface[surface_type];
|
||||
if (! polygons.empty())
|
||||
this->fill_surfaces.append(intersection_ex(polygons, fill_boundaries), SurfaceType(surface_type));
|
||||
for (auto const& entry : polygons_by_surface) {
|
||||
if (!entry.second.empty())
|
||||
this->fill_surfaces.append(intersection_ex(entry.second, fill_boundaries), entry.first);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,24 +130,24 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
fill_boundaries.reserve(number_polygons(surfaces));
|
||||
bool has_infill = this->region()->config().fill_density.value > 0.;
|
||||
for (const Surface &surface : this->fill_surfaces.surfaces) {
|
||||
if (surface.is_top()) {
|
||||
if (surface.has_pos_top()) {
|
||||
// Collect the top surfaces, inflate them and trim them by the bottom surfaces.
|
||||
// This gives the priority to bottom surfaces.
|
||||
surfaces_append(top, offset_ex(surface.expolygon, float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
|
||||
} else if (surface.surface_type == stBottom || (surface.surface_type == stBottomBridge && lower_layer == NULL)) {
|
||||
} else if (surface.has_pos_bottom() && (!surface.has_mod_bridge() || lower_layer == NULL)) {
|
||||
// Grown by 3mm.
|
||||
surfaces_append(bottom, offset_ex(surface.expolygon, float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
|
||||
} else if (surface.surface_type == stBottomBridge) {
|
||||
} else if (surface.has_pos_bottom() && surface.has_mod_bridge()) {
|
||||
if (! surface.empty())
|
||||
bridges.push_back(surface);
|
||||
}
|
||||
if (has_infill || surface.surface_type != stInternal) {
|
||||
if (!surface.is_external())
|
||||
if (has_infill || !(surface.has_pos_internal() && surface.has_fill_sparse())) {
|
||||
if (!surface.has_pos_external())
|
||||
// Make a copy as the following line uses the move semantics.
|
||||
internal.push_back(surface);
|
||||
polygons_append(fill_boundaries, std::move(surface.expolygon));
|
||||
} else{
|
||||
if (!surface.is_external())
|
||||
if (!surface.has_pos_external())
|
||||
internal.push_back(std::move(surface));
|
||||
//push surface as perimeter-only inside the fill_boundaries
|
||||
if (margin_bridged > 0) {
|
||||
@ -324,7 +323,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||
s2.clear();
|
||||
}
|
||||
}
|
||||
if (s1.is_top())
|
||||
if (s1.has_pos_top())
|
||||
// Trim the top surfaces by the bottom surfaces. This gives the priority to the bottom surfaces.
|
||||
polys = diff(polys, bottom_polygons);
|
||||
surfaces_append(
|
||||
@ -376,14 +375,14 @@ void LayerRegion::prepare_fill_surfaces()
|
||||
// if no solid layers are requested, turn top/bottom surfaces to internal
|
||||
if (this->region()->config().top_solid_layers == 0) {
|
||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
|
||||
if (surface->is_top())
|
||||
if (surface->has_pos_top())
|
||||
surface->surface_type = (this->layer()->object()->config().infill_only_where_needed) ?
|
||||
stInternalVoid : stInternal;
|
||||
stPosInternal | stDensVoid : stPosInternal | stDensSparse;
|
||||
}
|
||||
if (this->region()->config().bottom_solid_layers == 0) {
|
||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
||||
if (surface->is_bottom())
|
||||
surface->surface_type = stInternal;
|
||||
if (surface->has_pos_bottom())
|
||||
surface->surface_type = stPosInternal | stDensSparse;
|
||||
}
|
||||
}
|
||||
|
||||
@ -392,8 +391,8 @@ void LayerRegion::prepare_fill_surfaces()
|
||||
// scaling an area requires two calls!
|
||||
double min_area = scale_(scale_(this->region()->config().solid_infill_below_area.value));
|
||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
||||
if (surface->surface_type == stInternal && surface->area() <= min_area)
|
||||
surface->surface_type = stInternalSolid;
|
||||
if (surface->has_fill_sparse() && surface->has_pos_internal() && surface->area() <= min_area)
|
||||
surface->surface_type = stPosInternal | stDensSolid;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ void PerimeterGenerator::process()
|
||||
// this will avoid to throw wrong offsets into a good polygons
|
||||
this->fill_surfaces->append(
|
||||
unsupported_filtered,
|
||||
stInternal);
|
||||
stPosInternal | stDensSparse);
|
||||
|
||||
// store the results
|
||||
last = diff_ex(last, unsupported_filtered, true);
|
||||
@ -204,7 +204,7 @@ void PerimeterGenerator::process()
|
||||
if (intersection_ex(support, ExPolygons() = { last[i] }).empty()) {
|
||||
this->fill_surfaces->append(
|
||||
ExPolygons() = { last[i] },
|
||||
stInternal);
|
||||
stPosInternal | stDensSparse);
|
||||
last.erase(last.begin() + i);
|
||||
i--;
|
||||
}
|
||||
@ -529,7 +529,7 @@ void PerimeterGenerator::process()
|
||||
ExPolygons infill_exp = offset2_ex(not_filled_exp,
|
||||
-inset - min_perimeter_infill_spacing / 2 + overlap,
|
||||
(float)min_perimeter_infill_spacing / 2);
|
||||
this->fill_surfaces->append(infill_exp, stInternal);
|
||||
this->fill_surfaces->append(infill_exp, stPosInternal | stDensSparse);
|
||||
|
||||
if (overlap != 0) {
|
||||
ExPolygons polyWithoutOverlap = offset2_ex(
|
||||
|
@ -183,7 +183,7 @@ private:
|
||||
void bridge_over_infill();
|
||||
void replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_replacement, SurfaceType st_under_it);
|
||||
void clip_fill_surfaces();
|
||||
void count_distance_solid();
|
||||
void tag_under_bridge();
|
||||
void discover_horizontal_shells();
|
||||
void combine_infill();
|
||||
void _generate_support_material();
|
||||
|
@ -332,13 +332,21 @@ void PrintObject::prepare_infill()
|
||||
//if (this->)
|
||||
this->bridge_over_infill();
|
||||
m_print->throw_if_canceled();
|
||||
this->replaceSurfaceType(stInternalSolid, stInternalOverBridge, stInternalBridge);
|
||||
this->replaceSurfaceType(stPosInternal | stDensSolid,
|
||||
stPosInternal | stDensSolid | stModOverBridge,
|
||||
stPosInternal | stDensSolid | stModBridge);
|
||||
m_print->throw_if_canceled();
|
||||
this->replaceSurfaceType(stInternalSolid, stInternalOverBridge, stBottomBridge);
|
||||
this->replaceSurfaceType(stPosTop | stDensSolid,
|
||||
stPosTop | stDensSolid | stModOverBridge,
|
||||
stPosInternal | stDensSolid | stModBridge);
|
||||
m_print->throw_if_canceled();
|
||||
this->replaceSurfaceType(stTop, stTopOverBridge, stInternalBridge);
|
||||
this->replaceSurfaceType(stPosInternal | stDensSolid,
|
||||
stPosInternal | stDensSolid | stModOverBridge,
|
||||
stPosBottom | stDensSolid | stModBridge);
|
||||
m_print->throw_if_canceled();
|
||||
this->replaceSurfaceType(stTop, stTopOverBridge, stBottomBridge);
|
||||
this->replaceSurfaceType(stPosTop | stDensSolid,
|
||||
stPosTop | stDensSolid | stModOverBridge,
|
||||
stPosBottom | stDensSolid | stModBridge);
|
||||
m_print->throw_if_canceled();
|
||||
|
||||
// combine fill surfaces to honor the "infill every N layers" option
|
||||
@ -347,7 +355,7 @@ void PrintObject::prepare_infill()
|
||||
|
||||
// count the distance from the nearest top surface, to allow to use denser infill
|
||||
// if needed and if infill_dense_layers is positive.
|
||||
this->count_distance_solid();
|
||||
this->tag_under_bridge();
|
||||
m_print->throw_if_canceled();
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
@ -710,17 +718,13 @@ ExPolygons fit_to_size(ExPolygon polygon_to_cover, ExPolygon polygon_to_check, c
|
||||
return intersection_ex(polygon_reduced, growing_area);
|
||||
}
|
||||
|
||||
//FIXME: cerify it works if the part is split in 2 in the Z axis
|
||||
void PrintObject::count_distance_solid() {
|
||||
//if dense area * COEFF_SPLIT > sparse area then fill all with dense
|
||||
// sparse area = layer's fill area - solid area
|
||||
const float COEFF_SPLIT = 2;
|
||||
const int NB_DENSE_LAYERS = 1;
|
||||
int idR = 0;
|
||||
void PrintObject::tag_under_bridge() {
|
||||
const float COEFF_SPLIT = 1.5;
|
||||
|
||||
for (const PrintRegion *region : this->m_print->regions()) {
|
||||
LayerRegion *previousOne = NULL;
|
||||
//count how many surface there are on each one
|
||||
if (region->config().infill_dense.getBool() && region->config().fill_density<40) {
|
||||
if (region->config().infill_dense.getBool() && region->config().fill_density < 40) {
|
||||
for (size_t idx_layer = this->layers().size() - 1; idx_layer < this->layers().size(); --idx_layer) {
|
||||
LayerRegion *layerm = NULL;
|
||||
for (LayerRegion * lregion : this->layers()[idx_layer]->regions()) {
|
||||
@ -734,131 +738,88 @@ void PrintObject::count_distance_solid() {
|
||||
continue;
|
||||
}
|
||||
if (previousOne == NULL) {
|
||||
for (Surface &surf : layerm->fill_surfaces.surfaces) {
|
||||
if (surf.is_solid()) {
|
||||
surf.maxNbSolidLayersOnTop = 0;
|
||||
}
|
||||
}
|
||||
previousOne = layerm;
|
||||
continue;
|
||||
}
|
||||
Surfaces surf_to_add;
|
||||
for (Surface &surf : layerm->fill_surfaces.surfaces) {
|
||||
if (!surf.is_solid()){
|
||||
surf.maxNbSolidLayersOnTop = 30000;
|
||||
uint16_t dense_dist = 30000;
|
||||
surf.maxNbSolidLayersOnTop = -1;
|
||||
if (!surf.has_fill_solid()){
|
||||
ExPolygons dense_polys;
|
||||
ExPolygons sparse_polys = { surf.expolygon };
|
||||
//find the surface which intersect with the smalle maxNb possible
|
||||
//find the surface which intersect with the smallest maxNb possible
|
||||
for (Surface &upp : previousOne->fill_surfaces.surfaces) {
|
||||
// i'm using intersection_ex because the result different than
|
||||
// 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);
|
||||
if (!intersect.empty()) {
|
||||
if (layerm->region()->config().infill_dense_algo == dfaEnlarged) {
|
||||
uint16_t dist = (uint16_t)(upp.maxNbSolidLayersOnTop + 1);
|
||||
const int nb_dense_layers = 1;
|
||||
if (dist <= nb_dense_layers) {
|
||||
// it will be a dense infill, split the surface if needed
|
||||
uint64_t area_intersect = 0;
|
||||
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 ((surf.area() > area_intersect * COEFF_SPLIT) &&
|
||||
surf.maxNbSolidLayersOnTop > nb_dense_layers) {
|
||||
//split in two
|
||||
if (dist == 1) {
|
||||
//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
|
||||
intersect = offset_ex(intersect, layerm->flow(frInfill).scaled_width() + scale_(layerm->region()->config().bridged_infill_margin));
|
||||
} else {
|
||||
//just remove too small sections
|
||||
intersect = offset_ex(intersect,
|
||||
layerm->flow(frInfill).scaled_width());
|
||||
}
|
||||
if (!intersect.empty()) {
|
||||
ExPolygons sparse_surfaces = offset2_ex(
|
||||
diff_ex(sparse_polys, intersect, true),
|
||||
-layerm->flow(frInfill).scaled_width(),
|
||||
layerm->flow(frInfill).scaled_width());
|
||||
ExPolygons dense_surfaces = diff_ex(sparse_polys, sparse_surfaces, true);
|
||||
//assign (copy)
|
||||
sparse_polys.clear();
|
||||
sparse_polys.insert(sparse_polys.begin(), sparse_surfaces.begin(), sparse_surfaces.end());
|
||||
dense_polys.insert(dense_polys.end(), dense_surfaces.begin(), dense_surfaces.end());
|
||||
dense_dist = std::min(dense_dist, dist);
|
||||
}
|
||||
} else {
|
||||
surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist);
|
||||
}
|
||||
} else {
|
||||
surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist);
|
||||
}
|
||||
} else if (layerm->region()->config().infill_dense_algo == dfaAutoNotFull || layerm->region()->config().infill_dense_algo == dfaAutomatic) {
|
||||
double area_intersect = 0;
|
||||
for (ExPolygon poly_inter : intersect) area_intersect += poly_inter.area();
|
||||
//like intersect.empty() but more resilient
|
||||
if (area_intersect > layerm->flow(frInfill).scaled_width() * layerm->flow(frInfill).scaled_width() * 2) {
|
||||
uint16_t dist = (uint16_t)(upp.maxNbSolidLayersOnTop + 1);
|
||||
if (dist <= NB_DENSE_LAYERS) {
|
||||
if (upp.has_fill_solid()){
|
||||
// i'm using intersection_ex because the result different than
|
||||
// upp.expolygon.overlaps(surf.expolygon) or surf.expolygon.overlaps(upp.expolygon)
|
||||
//and a little offset2 to remove the almost supported area
|
||||
ExPolygons intersect =
|
||||
offset2_ex(
|
||||
intersection_ex(sparse_polys, { upp.expolygon }, true)
|
||||
, -layerm->flow(frInfill).scaled_width(), layerm->flow(frInfill).scaled_width());
|
||||
if (!intersect.empty()) {
|
||||
|
||||
if (layerm->region()->config().infill_dense_algo == dfaEnlarged) {
|
||||
//expand the area a bit
|
||||
intersect = offset_ex(intersect, scale_(layerm->region()->config().bridged_infill_margin));
|
||||
} else if (layerm->region()->config().infill_dense_algo == dfaAutoNotFull
|
||||
|| layerm->region()->config().infill_dense_algo == dfaAutomatic){
|
||||
|
||||
//check if area isn't too big for autonotfull
|
||||
double area_intersect = 0;
|
||||
if (layerm->region()->config().infill_dense_algo == dfaAutoNotFull)
|
||||
for (ExPolygon poly_inter : intersect)
|
||||
area_intersect += poly_inter.area();
|
||||
//like intersect.empty() but more resilient
|
||||
if (layerm->region()->config().infill_dense_algo == dfaAutomatic
|
||||
|| surf.area() > area_intersect * COEFF_SPLIT) {
|
||||
|
||||
// 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 ((layerm->region()->config().infill_dense_algo == dfaAutomatic || surf.area() > area_intersect * COEFF_SPLIT) &&
|
||||
surf.maxNbSolidLayersOnTop > NB_DENSE_LAYERS) {
|
||||
//split in two
|
||||
if (dist == 1) {
|
||||
//if just under the solid area, we can expand a bit
|
||||
ExPolygons cover_intersect;
|
||||
for (ExPolygon &expoly_tocover : intersect) {
|
||||
ExPolygons temp = (fit_to_size(expoly_tocover, expoly_tocover,
|
||||
diff_ex(offset_ex(layerm->fill_no_overlap_expolygons, layerm->flow(frInfill).scaled_width()),
|
||||
offset_ex(layerm->fill_no_overlap_expolygons, -layerm->flow(frInfill).scaled_width())),
|
||||
surf.expolygon,
|
||||
4 * layerm->flow(frInfill).scaled_width(), 0.01));
|
||||
cover_intersect.insert(cover_intersect.end(), temp.begin(), temp.end());
|
||||
}
|
||||
intersect = offset_ex(cover_intersect,
|
||||
layerm->flow(frInfill).scaled_width());// +scale_(expandby));
|
||||
//layerm->region()->config().external_infill_margin));
|
||||
} else {
|
||||
//just remove too small sections
|
||||
intersect = offset_ex(intersect,
|
||||
layerm->flow(frInfill).scaled_width());
|
||||
}
|
||||
if (!intersect.empty()) {
|
||||
ExPolygons sparse_surfaces = offset2_ex(
|
||||
diff_ex(sparse_polys, intersect, true),
|
||||
-layerm->flow(frInfill).scaled_width(),
|
||||
layerm->flow(frInfill).scaled_width());
|
||||
ExPolygons dense_surfaces = diff_ex(sparse_polys, sparse_surfaces, true);
|
||||
//assign (copy)
|
||||
sparse_polys.clear();
|
||||
sparse_polys.insert(sparse_polys.begin(), sparse_surfaces.begin(), sparse_surfaces.end());
|
||||
dense_polys.insert(dense_polys.end(), dense_surfaces.begin(), dense_surfaces.end());
|
||||
dense_dist = std::min(dense_dist, dist);
|
||||
}
|
||||
} else {
|
||||
if (area_intersect < layerm->flow(frInfill).scaled_width() * layerm->flow(frInfill).scaled_width() * 2)
|
||||
surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist);
|
||||
ExPolygons cover_intersect;
|
||||
for (ExPolygon &expoly_tocover : intersect) {
|
||||
ExPolygons temp = (fit_to_size(expoly_tocover, expoly_tocover,
|
||||
diff_ex(offset_ex(layerm->fill_no_overlap_expolygons, layerm->flow(frInfill).scaled_width()),
|
||||
offset_ex(layerm->fill_no_overlap_expolygons, -layerm->flow(frInfill).scaled_width())),
|
||||
surf.expolygon,
|
||||
4 * layerm->flow(frInfill).scaled_width(), 0.01));
|
||||
cover_intersect.insert(cover_intersect.end(), temp.begin(), temp.end());
|
||||
}
|
||||
intersect = offset2_ex(cover_intersect,
|
||||
-layerm->flow(frInfill).scaled_width(),
|
||||
layerm->flow(frInfill).scaled_width() * 2);
|
||||
} else {
|
||||
surf.maxNbSolidLayersOnTop = std::min(surf.maxNbSolidLayersOnTop, dist);
|
||||
intersect.clear();
|
||||
}
|
||||
}
|
||||
if (!intersect.empty()) {
|
||||
ExPolygons sparse_surfaces = offset2_ex(
|
||||
diff_ex(sparse_polys, intersect, true),
|
||||
-layerm->flow(frInfill).scaled_width(),
|
||||
layerm->flow(frInfill).scaled_width());
|
||||
ExPolygons dense_surfaces = diff_ex(sparse_polys, sparse_surfaces, true);
|
||||
//assign (copy)
|
||||
sparse_polys = std::move(sparse_surfaces);
|
||||
dense_polys.insert(dense_polys.end(), dense_surfaces.begin(), dense_surfaces.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
//check if we are full-dense
|
||||
if (sparse_polys.empty()) break;
|
||||
}
|
||||
|
||||
//check if we need to split the surface
|
||||
if (dense_dist != 30000) {
|
||||
if (!dense_polys.empty()) {
|
||||
double area_dense = 0;
|
||||
for (ExPolygon poly_inter : dense_polys) area_dense += poly_inter.area();
|
||||
double area_sparse = 0;
|
||||
for (ExPolygon poly_inter : sparse_polys) area_sparse += poly_inter.area();
|
||||
std::cout << "need to split? " << area_sparse << " > " << area_dense << " * " << COEFF_SPLIT << "\n";
|
||||
if (area_sparse > area_dense * COEFF_SPLIT) {
|
||||
//split
|
||||
dense_polys = union_ex(dense_polys);
|
||||
for (ExPolygon dense_poly : dense_polys) {
|
||||
Surface dense_surf(surf, dense_poly);
|
||||
dense_surf.maxNbSolidLayersOnTop = dense_dist;
|
||||
dense_surf.maxNbSolidLayersOnTop = 1;
|
||||
surf_to_add.push_back(dense_surf);
|
||||
}
|
||||
sparse_polys = union_ex(sparse_polys);
|
||||
@ -868,29 +829,19 @@ void PrintObject::count_distance_solid() {
|
||||
}
|
||||
//layerm->fill_surfaces.surfaces.erase(it_surf);
|
||||
} else {
|
||||
surf.maxNbSolidLayersOnTop = dense_dist;
|
||||
surf.maxNbSolidLayersOnTop = 1;
|
||||
surf_to_add.push_back(surf);
|
||||
}
|
||||
} else {
|
||||
surf_to_add.push_back(surf);
|
||||
}
|
||||
} else {
|
||||
surf.maxNbSolidLayersOnTop = 0;
|
||||
surf_to_add.push_back(surf);
|
||||
}
|
||||
} else surf_to_add.emplace_back(std::move(surf));
|
||||
} else surf_to_add.emplace_back(std::move(surf));
|
||||
}
|
||||
//if (!surf_to_add.empty()) {
|
||||
// layerm->fill_surfaces.surfaces.insert(layerm->fill_surfaces.surfaces.begin(), surf_to_add.begin(), surf_to_add.end());
|
||||
//}
|
||||
layerm->fill_surfaces.surfaces.clear();
|
||||
layerm->fill_surfaces.surfaces.insert(layerm->fill_surfaces.surfaces.begin(), surf_to_add.begin(), surf_to_add.end());
|
||||
layerm->fill_surfaces.surfaces = std::move(surf_to_add);
|
||||
previousOne = layerm;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function analyzes slices of a region (SurfaceCollection slices).
|
||||
// Each region slice (instance of Surface) is analyzed, whether it is supported or whether it is the top surface.
|
||||
// Initially all slices are of type stInternal.
|
||||
@ -930,12 +881,12 @@ void PrintObject::detect_surfaces_type()
|
||||
// If we have raft layers, consider bottom layer as a bridge just like any other bottom surface lying on the void.
|
||||
SurfaceType surface_type_bottom_1st =
|
||||
(m_config.raft_layers.value > 0 && m_config.support_material_contact_distance_type.value != zdNone) ?
|
||||
stBottomBridge : stBottom;
|
||||
stPosBottom | stDensSolid | stModBridge : stPosBottom | stDensSolid;
|
||||
// If we have soluble support material, don't bridge. The overhang will be squished against a soluble layer separating
|
||||
// the support from the print.
|
||||
SurfaceType surface_type_bottom_other =
|
||||
(m_config.support_material.value && m_config.support_material_contact_distance_type.value == zdNone) ?
|
||||
stBottom : stBottomBridge;
|
||||
stPosBottom | stDensSolid : stPosBottom | stDensSolid | stModBridge;
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
m_print->throw_if_canceled();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "Detecting solid surfaces for region " << idx_region << " and layer " << layer->print_z;
|
||||
@ -961,13 +912,13 @@ void PrintObject::detect_surfaces_type()
|
||||
surfaces_append(top,
|
||||
//FIXME implement offset2_ex working over ExPolygons, that should be a bit more efficient than calling offset_ex twice.
|
||||
offset_ex(offset_ex(diff_ex(layerm_slices_surfaces, upper_slices, true), -offset), offset),
|
||||
stTop);
|
||||
stPosTop | stDensSolid);
|
||||
} else {
|
||||
// if no upper layer, all surfaces of this one are solid
|
||||
// we clone surfaces because we're going to clear the slices collection
|
||||
top = layerm->slices.surfaces;
|
||||
for (Surface &surface : top)
|
||||
surface.surface_type = stTop;
|
||||
surface.surface_type = stPosTop | stDensSolid;
|
||||
}
|
||||
|
||||
// Find bottom surfaces (difference between current surfaces of current layer and lower one).
|
||||
@ -1002,7 +953,7 @@ void PrintObject::detect_surfaces_type()
|
||||
to_polygons(lower_layer->get_region(idx_region)->slices.surfaces),
|
||||
true),
|
||||
-offset, offset),
|
||||
stBottom);
|
||||
stPosBottom | stDensSolid);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
@ -1024,7 +975,7 @@ void PrintObject::detect_surfaces_type()
|
||||
top.clear();
|
||||
surfaces_append(top,
|
||||
diff_ex(top_polygons, to_polygons(bottom), false),
|
||||
stTop);
|
||||
stPosTop | stDensSolid);
|
||||
}
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
@ -1049,7 +1000,7 @@ void PrintObject::detect_surfaces_type()
|
||||
polygons_append(topbottom, to_polygons(bottom));
|
||||
surfaces_append(surfaces_out,
|
||||
diff_ex(layerm_slices_surfaces, topbottom, false),
|
||||
stInternal);
|
||||
stPosInternal | stDensSparse);
|
||||
}
|
||||
|
||||
surfaces_append(surfaces_out, std::move(top));
|
||||
@ -1153,7 +1104,6 @@ void PrintObject::discover_vertical_shells()
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size(), grain_size),
|
||||
[this, &cache_top_botom_regions](const tbb::blocked_range<size_t>& range) {
|
||||
const SurfaceType surfaces_bottom[2] = { stBottom, stBottomBridge };
|
||||
const size_t num_regions = this->region_volumes.size();
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
m_print->throw_if_canceled();
|
||||
@ -1170,9 +1120,10 @@ void PrintObject::discover_vertical_shells()
|
||||
LayerRegion &layerm = *layer.m_regions[idx_region];
|
||||
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
|
||||
// Top surfaces.
|
||||
append(cache.top_surfaces, offset(to_expolygons(layerm.slices.filter_by_type(stTop)), min_perimeter_infill_spacing));
|
||||
append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stTop)), min_perimeter_infill_spacing));
|
||||
append(cache.top_surfaces, offset(to_expolygons(layerm.slices.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing));
|
||||
append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing));
|
||||
// Bottom surfaces.
|
||||
const SurfaceType surfaces_bottom[2] = { stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
|
||||
append(cache.bottom_surfaces, offset(to_expolygons(layerm.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
|
||||
append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
|
||||
// Calculate the maximum perimeter offset as if the slice was extruded with a single extruder only.
|
||||
@ -1238,7 +1189,6 @@ void PrintObject::discover_vertical_shells()
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size(), grain_size),
|
||||
[this, idx_region, &cache_top_botom_regions](const tbb::blocked_range<size_t>& range) {
|
||||
const SurfaceType surfaces_bottom[2] = { stBottom, stBottomBridge };
|
||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||
m_print->throw_if_canceled();
|
||||
Layer &layer = *m_layers[idx_layer];
|
||||
@ -1246,9 +1196,10 @@ void PrintObject::discover_vertical_shells()
|
||||
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
|
||||
// Top surfaces.
|
||||
auto &cache = cache_top_botom_regions[idx_layer];
|
||||
cache.top_surfaces = offset(to_expolygons(layerm.slices.filter_by_type(stTop)), min_perimeter_infill_spacing);
|
||||
append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stTop)), min_perimeter_infill_spacing));
|
||||
cache.top_surfaces = offset(to_expolygons(layerm.slices.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing);
|
||||
append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing));
|
||||
// Bottom surfaces.
|
||||
const SurfaceType surfaces_bottom[2] = { stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
|
||||
cache.bottom_surfaces = offset(to_expolygons(layerm.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing);
|
||||
append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
|
||||
// Holes over all regions. Only collect them once, they are valid for all idx_region iterations.
|
||||
@ -1402,7 +1353,7 @@ void PrintObject::discover_vertical_shells()
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
// Trim the shells region by the internal & internal void surfaces.
|
||||
const SurfaceType surfaceTypesInternal[] = { stInternal, stInternalVoid, stInternalSolid };
|
||||
const SurfaceType surfaceTypesInternal[] = { stPosInternal | stDensSparse, stPosInternal | stDensVoid, stPosInternal | stDensSolid };
|
||||
const Polygons polygonsInternal = to_polygons(layerm->fill_surfaces.filter_by_types(surfaceTypesInternal, 3));
|
||||
shell = intersection(shell, polygonsInternal, true);
|
||||
polygons_append(shell, diff(polygonsInternal, holes));
|
||||
@ -1410,7 +1361,7 @@ void PrintObject::discover_vertical_shells()
|
||||
continue;
|
||||
|
||||
// Append the internal solids, so they will be merged with the new ones.
|
||||
polygons_append(shell, to_polygons(layerm->fill_surfaces.filter_by_type(stInternalSolid)));
|
||||
polygons_append(shell, to_polygons(layerm->fill_surfaces.filter_by_type(stPosInternal | stDensSolid)));
|
||||
|
||||
// These regions will be filled by a rectilinear full infill. Currently this type of infill
|
||||
// only fills regions, which fit at least a single line. To avoid gaps in the sparse infill,
|
||||
@ -1458,12 +1409,12 @@ void PrintObject::discover_vertical_shells()
|
||||
|
||||
// Trim the internal & internalvoid by the shell.
|
||||
Slic3r::ExPolygons new_internal = diff_ex(
|
||||
to_polygons(layerm->fill_surfaces.filter_by_type(stInternal)),
|
||||
to_polygons(layerm->fill_surfaces.filter_by_type(stPosInternal | stDensSparse)),
|
||||
shell,
|
||||
false
|
||||
);
|
||||
Slic3r::ExPolygons new_internal_void = diff_ex(
|
||||
to_polygons(layerm->fill_surfaces.filter_by_type(stInternalVoid)),
|
||||
to_polygons(layerm->fill_surfaces.filter_by_type(stPosInternal | stDensVoid)),
|
||||
shell,
|
||||
false
|
||||
);
|
||||
@ -1477,11 +1428,12 @@ void PrintObject::discover_vertical_shells()
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
|
||||
// Assign resulting internal surfaces to layer.
|
||||
const SurfaceType surfaceTypesKeep[] = { stTop, stBottom, stBottomBridge };
|
||||
const SurfaceType surfaceTypesKeep[] = { stPosTop | stDensSolid, stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
|
||||
layerm->fill_surfaces.keep_types(surfaceTypesKeep, sizeof(surfaceTypesKeep)/sizeof(SurfaceType));
|
||||
layerm->fill_surfaces.append(new_internal, stInternal);
|
||||
layerm->fill_surfaces.append(new_internal_void, stInternalVoid);
|
||||
layerm->fill_surfaces.append(new_internal_solid, stInternalSolid);
|
||||
//layerm->fill_surfaces.keep_types_flag(stPosTop | stPosBottom);
|
||||
layerm->fill_surfaces.append(new_internal, stPosInternal | stDensSparse);
|
||||
layerm->fill_surfaces.append(new_internal_void, stPosInternal | stDensVoid);
|
||||
layerm->fill_surfaces.append(new_internal_solid, stPosInternal | stDensSolid);
|
||||
} // for each layer
|
||||
});
|
||||
m_print->throw_if_canceled();
|
||||
@ -1535,7 +1487,7 @@ void PrintObject::bridge_over_infill()
|
||||
|
||||
// extract the stInternalSolid surfaces that might be transformed into bridges
|
||||
Polygons internal_solid;
|
||||
layerm->fill_surfaces.filter_by_type(stInternalSolid, &internal_solid);
|
||||
layerm->fill_surfaces.filter_by_type(stPosInternal | stDensSolid, &internal_solid);
|
||||
|
||||
// check whether the lower area is deep enough for absorbing the extra flow
|
||||
// (for obvious physical reasons but also for preventing the bridge extrudates
|
||||
@ -1555,7 +1507,7 @@ void PrintObject::bridge_over_infill()
|
||||
// iterate through regions and collect internal surfaces
|
||||
Polygons lower_internal;
|
||||
for (LayerRegion *lower_layerm : lower_layer->m_regions)
|
||||
lower_layerm->fill_surfaces.filter_by_type(stInternal, &lower_internal);
|
||||
lower_layerm->fill_surfaces.filter_by_type(stPosInternal | stDensSparse, &lower_internal);
|
||||
|
||||
// intersect such lower internal surfaces with the candidate solid surfaces
|
||||
to_bridge_pp = intersection(to_bridge_pp, lower_internal);
|
||||
@ -1584,11 +1536,11 @@ void PrintObject::bridge_over_infill()
|
||||
ExPolygons not_to_bridge = diff_ex(internal_solid, to_polygons(to_bridge), true);
|
||||
to_bridge = intersection_ex(to_polygons(to_bridge), internal_solid, true);
|
||||
// build the new collection of fill_surfaces
|
||||
layerm->fill_surfaces.remove_type(stInternalSolid);
|
||||
layerm->fill_surfaces.remove_type(stPosInternal | stDensSolid);
|
||||
for (ExPolygon &ex : to_bridge)
|
||||
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalBridge, ex));
|
||||
layerm->fill_surfaces.surfaces.push_back(Surface(stPosInternal | stDensSolid | stModBridge, ex));
|
||||
for (ExPolygon &ex : not_to_bridge)
|
||||
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, ex));
|
||||
layerm->fill_surfaces.surfaces.push_back(Surface(stPosInternal | stDensSolid, ex));
|
||||
/*
|
||||
# exclude infill from the layers below if needed
|
||||
# see discussion at https://github.com/alexrj/Slic3r/issues/240
|
||||
@ -1636,7 +1588,8 @@ void PrintObject::bridge_over_infill()
|
||||
bridge (which is over sparse infill) note: it's almost complete copy/paste from the method behind,
|
||||
i think it should be merged before gitpull that.
|
||||
*/
|
||||
void PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_replacement, SurfaceType st_under_it)
|
||||
void
|
||||
PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_replacement, SurfaceType st_under_it)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "overextrude over Bridge...";
|
||||
|
||||
@ -1644,151 +1597,52 @@ void PrintObject::replaceSurfaceType(SurfaceType st_to_replace, SurfaceType st_r
|
||||
const PrintRegion ®ion = *m_print->regions()[region_id];
|
||||
|
||||
for (LayerPtrs::iterator layer_it = m_layers.begin(); layer_it != m_layers.end(); ++layer_it) {
|
||||
|
||||
// skip first layer
|
||||
if (layer_it == this->layers().begin()) continue;
|
||||
|
||||
Layer* layer = *layer_it;
|
||||
|
||||
Layer* layer = *layer_it;
|
||||
LayerRegion* layerm = layer->regions()[region_id];
|
||||
|
||||
// extract the stInternalSolid surfaces that might be transformed into bridges
|
||||
Polygons internal_solid;
|
||||
layerm->fill_surfaces.filter_by_type(st_to_replace, &internal_solid);
|
||||
|
||||
double internsolidareainit=0;
|
||||
for (ExPolygon &ex : union_ex(internal_solid)) internsolidareainit+=ex.area();
|
||||
|
||||
Polygons internal_over_tot_init;
|
||||
layerm->fill_surfaces.filter_by_type(st_replacement, &internal_over_tot_init);
|
||||
double totoverareaInit=0;
|
||||
for (ExPolygon &ex : union_ex(internal_over_tot_init)) totoverareaInit+=ex.area();
|
||||
|
||||
Polygons stBottom_init;
|
||||
layerm->fill_surfaces.filter_by_type(stBottom, &stBottom_init);
|
||||
double bottomeareainit=0;
|
||||
for (ExPolygon &ex : union_ex(stBottom_init)) bottomeareainit+=ex.area();
|
||||
Polygons poly_to_check;
|
||||
// extract the surfaces that might be transformed
|
||||
layerm->fill_surfaces.filter_by_type(st_to_replace, &poly_to_check);
|
||||
Polygons poly_to_replace = poly_to_check;
|
||||
|
||||
Polygons stBottomBridge_init;
|
||||
layerm->fill_surfaces.filter_by_type(stBottomBridge, &stBottomBridge_init);
|
||||
double bottombridgearea=0;
|
||||
for (ExPolygon &ex : union_ex(stBottomBridge_init)) bottombridgearea+=ex.area();
|
||||
|
||||
Polygons stIntBridge_init;
|
||||
layerm->fill_surfaces.filter_by_type(st_under_it, &stIntBridge_init);
|
||||
double intbridgeareainit=0;
|
||||
for (ExPolygon &ex : union_ex(stIntBridge_init)) intbridgeareainit+=ex.area();
|
||||
|
||||
// check whether the lower area is deep enough for absorbing the extra flow
|
||||
// (for obvious physical reasons but also for preventing the bridge extrudates
|
||||
// from overflowing in 3D preview)
|
||||
ExPolygons to_overextrude;
|
||||
{
|
||||
Polygons to_overextrude_pp = internal_solid;
|
||||
|
||||
// get previous layer
|
||||
if (int(layer_it - this->layers().begin()) - 1 >= 0) {
|
||||
const Layer* lower_layer = this->layers()[int(layer_it - this->layers().begin()) - 1];
|
||||
|
||||
// iterate through regions and collect internal surfaces
|
||||
Polygons lower_internal;
|
||||
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_Bridge;
|
||||
Polygons lower_internal_Over;
|
||||
lower_layerm->fill_surfaces.filter_by_type(st_replacement, &lower_internal_OK);
|
||||
lower_layerm->fill_surfaces.filter_by_type(st_under_it, &lower_internal_Bridge);
|
||||
lower_layerm->fill_surfaces.filter_by_type(st_to_replace, &lower_internal_Over);
|
||||
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_Bridge)) bridgearea+=ex.area();
|
||||
for (ExPolygon &ex : union_ex(lower_internal_Over)) overarea+=ex.area();
|
||||
// check the lower layer
|
||||
if (int(layer_it - this->layers().begin()) - 1 >= 0) {
|
||||
const Layer* lower_layer = this->layers()[int(layer_it - this->layers().begin()) - 1];
|
||||
|
||||
lower_layerm->fill_surfaces.filter_by_type(st_under_it, &lower_internal);
|
||||
}
|
||||
double sumarea=0;
|
||||
for (ExPolygon &ex : union_ex(lower_internal)) sumarea+=ex.area();
|
||||
|
||||
// intersect such lower internal surfaces with the candidate solid surfaces
|
||||
to_overextrude_pp = intersection(to_overextrude_pp, lower_internal);
|
||||
// iterate through regions and collect internal surfaces
|
||||
Polygons lower_internal;
|
||||
for (LayerRegion *lower_layerm : lower_layer->m_regions) {
|
||||
lower_layerm->fill_surfaces.filter_by_type(st_under_it, &lower_internal);
|
||||
}
|
||||
|
||||
// there's no point in overextruding too thin/short regions
|
||||
//FIXME Vojtech: The offset2 function is not a geometric offset,
|
||||
// therefore it may create 1) gaps, and 2) sharp corners, which are outside the original contour.
|
||||
// The gaps will be filled by a separate region, which makes the infill less stable and it takes longer.
|
||||
// {
|
||||
// float min_width = float(bridge_flow.scaled_width()) * 3.f;
|
||||
// to_overextrude_pp = offset2(to_overextrude_pp, -min_width, +min_width);
|
||||
// }
|
||||
|
||||
if (to_overextrude_pp.empty()) continue;
|
||||
|
||||
// convert into ExPolygons
|
||||
to_overextrude = union_ex(to_overextrude_pp);
|
||||
|
||||
// intersect such lower internal surfaces with the candidate solid surfaces
|
||||
poly_to_replace = intersection(poly_to_replace, lower_internal);
|
||||
}
|
||||
|
||||
#ifdef SLIC3R_DEBUG
|
||||
printf("Bridging " PRINTF_ZU " internal areas at layer " PRINTF_ZU "\n", to_overextrude.size(), layer->id());
|
||||
#endif
|
||||
|
||||
|
||||
if (poly_to_replace.empty()) continue;
|
||||
|
||||
// compute the remaning internal solid surfaces as difference
|
||||
ExPolygons not_to_overextrude = diff_ex(internal_solid, to_polygons(to_overextrude), true);
|
||||
to_overextrude = intersection_ex(to_polygons(to_overextrude), internal_solid, true);
|
||||
ExPolygons not_expoly_to_replace = diff_ex(poly_to_check, poly_to_replace, true);
|
||||
// build the new collection of fill_surfaces
|
||||
layerm->fill_surfaces.remove_type(st_to_replace);
|
||||
double overareafinal = 0, solidareafinal=0;
|
||||
for (ExPolygon &ex : to_overextrude){
|
||||
overareafinal += ex.area();
|
||||
layerm->fill_surfaces.surfaces.push_back(Surface(st_replacement, ex));
|
||||
}
|
||||
for (ExPolygon &ex : not_to_overextrude){
|
||||
solidareafinal += ex.area();
|
||||
layerm->fill_surfaces.surfaces.push_back(Surface(st_to_replace, ex));
|
||||
}
|
||||
Polygons internal_over_tot;
|
||||
layerm->fill_surfaces.filter_by_type(stInternalOverBridge, &internal_over_tot);
|
||||
double totoverarea=0;
|
||||
for (ExPolygon &ex : union_ex(internal_over_tot)) totoverarea+=ex.area();
|
||||
|
||||
/*
|
||||
# exclude infill from the layers below if needed
|
||||
# see discussion at https://github.com/alexrj/Slic3r/issues/240
|
||||
# Update: do not exclude any infill. Sparse infill is able to absorb the excess material.
|
||||
if (0) {
|
||||
my $excess = $layerm->extruders->{infill}->bridge_flow->width - $layerm->height;
|
||||
for (my $i = $layer_id-1; $excess >= $self->get_layer($i)->height; $i--) {
|
||||
Slic3r::debugf " skipping infill below those areas at layer %d\n", $i;
|
||||
foreach my $lower_layerm (@{$self->get_layer($i)->regions}) {
|
||||
my @new_surfaces = ();
|
||||
# subtract the area from all types of surfaces
|
||||
foreach my $group (@{$lower_layerm->fill_surfaces->group}) {
|
||||
push @new_surfaces, map $group->[0]->clone(expolygon => $_),
|
||||
@{diff_ex(
|
||||
[ map $_->p, @$group ],
|
||||
[ map @$_, @$to_overextrude ],
|
||||
)};
|
||||
push @new_surfaces, map Slic3r::Surface->new(
|
||||
expolygon => $_,
|
||||
surface_type => S_TYPE_INTERNALVOID,
|
||||
), @{intersection_ex(
|
||||
[ map $_->p, @$group ],
|
||||
[ map @$_, @$to_overextrude ],
|
||||
)};
|
||||
}
|
||||
$lower_layerm->fill_surfaces->clear;
|
||||
$lower_layerm->fill_surfaces->append($_) for @new_surfaces;
|
||||
}
|
||||
|
||||
$excess -= $self->get_layer($i)->height;
|
||||
{
|
||||
Surfaces new_surfaces;
|
||||
for (Surfaces::const_iterator surface = layerm->fill_surfaces.surfaces.begin(); surface != layerm->fill_surfaces.surfaces.end(); ++surface) {
|
||||
if (surface->surface_type != st_to_replace)
|
||||
new_surfaces.push_back(*surface);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
layerm->export_region_slices_to_svg_debug("7_overextrude_over_bridge");
|
||||
layerm->export_region_fill_surfaces_to_svg_debug("7_overextrude_over_bridge");
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
for (ExPolygon &ex : union_ex(poly_to_replace)) {
|
||||
new_surfaces.push_back(Surface(st_replacement, ex));
|
||||
}
|
||||
for (ExPolygon &ex : not_expoly_to_replace){
|
||||
new_surfaces.push_back(Surface(st_to_replace, ex));
|
||||
}
|
||||
|
||||
layerm->fill_surfaces.surfaces = new_surfaces;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1951,7 +1805,7 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start";
|
||||
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id)
|
||||
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stInternal);
|
||||
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stPosInternal | stDensSparse);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " end";
|
||||
}
|
||||
@ -1978,9 +1832,9 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||
if (my_parts.empty())
|
||||
continue;
|
||||
// Remove such parts from original region.
|
||||
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stInternal);
|
||||
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stPosInternal | stDensSparse);
|
||||
// Append new parts to our region.
|
||||
layerm->slices.append(std::move(my_parts), stInternal);
|
||||
layerm->slices.append(std::move(my_parts), stPosInternal | stDensSparse);
|
||||
}
|
||||
}
|
||||
m_print->throw_if_canceled();
|
||||
@ -2020,7 +1874,7 @@ end:
|
||||
if (scale) {
|
||||
// Single region, growing or shrinking.
|
||||
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), stPosInternal | stDensSparse);
|
||||
}
|
||||
_offsetHoles(hole_delta, layer->regions().front());
|
||||
} else if (scale || clip || hole_delta != 0.f) {
|
||||
@ -2038,7 +1892,7 @@ end:
|
||||
if (clip && region_id + 1 < layer->m_regions.size())
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
polygons_append(processed, slices);
|
||||
layerm->slices.set(std::move(slices), stInternal);
|
||||
layerm->slices.set(std::move(slices), stPosInternal | stDensSparse);
|
||||
_offsetHoles(hole_delta, layerm);
|
||||
}
|
||||
}
|
||||
@ -2085,7 +1939,7 @@ void PrintObject::_offsetHoles(float hole_delta, LayerRegion *layerm) {
|
||||
}
|
||||
new_polys.push_back(new_ex_poly);
|
||||
}
|
||||
layerm->slices.set(std::move(new_polys), stInternal);
|
||||
layerm->slices.set(std::move(new_polys), stPosInternal | stDensSparse);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2217,7 +2071,7 @@ std::string PrintObject::_fix_slicing_errors()
|
||||
if (lower_surfaces)
|
||||
for (const auto &surface : *lower_surfaces)
|
||||
polygons_append(holes, surface.expolygon.holes);
|
||||
layerm->slices.set(diff_ex(union_(outer), holes, false), stInternal);
|
||||
layerm->slices.set(diff_ex(union_(outer), holes, false), stPosInternal | stDensSparse);
|
||||
}
|
||||
// Update layer slices after repairing the single regions.
|
||||
layer->make_slices();
|
||||
@ -2397,7 +2251,7 @@ void PrintObject::clip_fill_surfaces()
|
||||
for (const LayerRegion *layerm : layer->m_regions)
|
||||
for (const Surface &surface : layerm->fill_surfaces.surfaces) {
|
||||
Polygons polygons = to_polygons(surface.expolygon);
|
||||
if (surface.is_solid())
|
||||
if (surface.has_fill_solid())
|
||||
polygons_append(overhangs, polygons);
|
||||
polygons_append(fill_surfaces, std::move(polygons));
|
||||
}
|
||||
@ -2406,7 +2260,7 @@ void PrintObject::clip_fill_surfaces()
|
||||
for (const LayerRegion *layerm : lower_layer->m_regions)
|
||||
for (const Surface &surface : layerm->fill_surfaces.surfaces) {
|
||||
Polygons polygons = to_polygons(surface.expolygon);
|
||||
if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
|
||||
if (surface.has_pos_internal() && (surface.has_fill_sparse() || surface.has_fill_void()) )
|
||||
polygons_append(lower_layer_internal_surfaces, polygons);
|
||||
polygons_append(lower_layer_fill_surfaces, std::move(polygons));
|
||||
}
|
||||
@ -2431,14 +2285,14 @@ void PrintObject::clip_fill_surfaces()
|
||||
for (LayerRegion *layerm : lower_layer->m_regions) {
|
||||
if (layerm->region()->config().fill_density.value == 0)
|
||||
continue;
|
||||
SurfaceType internal_surface_types[] = { stInternal, stInternalVoid };
|
||||
SurfaceType internal_surface_types[] = { stPosInternal | stDensSparse, stPosInternal | stDensVoid };
|
||||
Polygons internal;
|
||||
for (Surface &surface : layerm->fill_surfaces.surfaces)
|
||||
if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid)
|
||||
if (surface.has_pos_internal() && (surface.has_fill_sparse() || surface.has_fill_void()))
|
||||
polygons_append(internal, std::move(surface.expolygon));
|
||||
layerm->fill_surfaces.remove_types(internal_surface_types, 2);
|
||||
layerm->fill_surfaces.append(intersection_ex(internal, upper_internal, true), stInternal);
|
||||
layerm->fill_surfaces.append(diff_ex (internal, upper_internal, true), stInternalVoid);
|
||||
layerm->fill_surfaces.append(intersection_ex(internal, upper_internal, true), stPosInternal | stDensSparse);
|
||||
layerm->fill_surfaces.append(diff_ex (internal, upper_internal, true), stPosInternal | stDensVoid);
|
||||
// If there are voids it means that our internal infill is not adjacent to
|
||||
// perimeters. In this case it would be nice to add a loop around infill to
|
||||
// make it more robust and nicer. TODO.
|
||||
@ -2462,9 +2316,9 @@ void PrintObject::discover_horizontal_shells()
|
||||
if (region_config.solid_infill_every_layers.value > 0 && region_config.fill_density.value > 0 &&
|
||||
(i % region_config.solid_infill_every_layers) == 0) {
|
||||
// Insert a solid internal layer. Mark stInternal surfaces as stInternalSolid or stInternalBridge.
|
||||
SurfaceType type = (region_config.fill_density == 100) ? stInternalSolid : stInternalBridge;
|
||||
SurfaceType type = (region_config.fill_density == 100) ? (stPosInternal | stDensSolid) : (stPosInternal | stDensSolid | stModBridge);
|
||||
for (Surface &surface : layerm->fill_surfaces.surfaces)
|
||||
if (surface.surface_type == stInternal)
|
||||
if (surface.surface_type == stPosInternal | stDensSparse)
|
||||
surface.surface_type = type;
|
||||
}
|
||||
|
||||
@ -2474,7 +2328,8 @@ void PrintObject::discover_horizontal_shells()
|
||||
|
||||
for (int idx_surface_type = 0; idx_surface_type < 3; ++ idx_surface_type) {
|
||||
m_print->throw_if_canceled();
|
||||
SurfaceType type = (idx_surface_type == 0) ? stTop : (idx_surface_type == 1) ? stBottom : stBottomBridge;
|
||||
SurfaceType type = (idx_surface_type == 0) ? (stPosTop | stDensSolid) :
|
||||
( (idx_surface_type == 1) ? (stPosBottom | stDensSolid) : (stPosBottom | stDensSolid |stModBridge));
|
||||
// Find slices of current type for current layer.
|
||||
// Use slices instead of fill_surfaces, because they also include the perimeter area,
|
||||
// which needs to be propagated in shells; we need to grow slices like we did for
|
||||
@ -2500,8 +2355,8 @@ void PrintObject::discover_horizontal_shells()
|
||||
continue;
|
||||
// Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP) ? 'top' : 'bottom';
|
||||
|
||||
size_t solid_layers = (type == stTop || type == stTopOverBridge) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;
|
||||
for (int n = (type == stTop || type == stTopOverBridge) ? i-1 : i+1; std::abs(n - i) < solid_layers; (type == stTop || type == stTopOverBridge) ? -- n : ++ n) {
|
||||
size_t solid_layers = (type & stPosTop == stPosTop) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;
|
||||
for (int n = (type & stPosTop == stPosTop) ? i - 1 : i + 1; std::abs(n - i) < solid_layers; (type & stPosTop == stPosTop) ? --n : ++n) {
|
||||
if (n < 0 || n >= int(m_layers.size()))
|
||||
continue;
|
||||
// Slic3r::debugf " looking for neighbors on layer %d...\n", $n;
|
||||
@ -2522,7 +2377,7 @@ void PrintObject::discover_horizontal_shells()
|
||||
{
|
||||
Polygons internal;
|
||||
for (const Surface &surface : neighbor_layerm->fill_surfaces.surfaces)
|
||||
if (surface.surface_type == stInternal || surface.surface_type == stInternalSolid)
|
||||
if (surface.has_pos_internal() &&(surface.has_fill_sparse() || surface.has_fill_solid()))
|
||||
polygons_append(internal, to_polygons(surface.expolygon));
|
||||
new_internal_solid = intersection(solid, internal, true);
|
||||
}
|
||||
@ -2580,7 +2435,7 @@ void PrintObject::discover_horizontal_shells()
|
||||
// make sure our grown surfaces don't exceed the fill area
|
||||
Polygons internal;
|
||||
for (const Surface &surface : neighbor_layerm->fill_surfaces.surfaces)
|
||||
if (surface.is_internal() && !surface.is_bridge())
|
||||
if (surface.has_pos_internal() && !surface.has_mod_bridge())
|
||||
polygons_append(internal, to_polygons(surface.expolygon));
|
||||
polygons_append(new_internal_solid,
|
||||
intersection(
|
||||
@ -2598,22 +2453,23 @@ void PrintObject::discover_horizontal_shells()
|
||||
// internal-solid are the union of the existing internal-solid surfaces
|
||||
// and new ones
|
||||
SurfaceCollection backup = std::move(neighbor_layerm->fill_surfaces);
|
||||
polygons_append(new_internal_solid, to_polygons(backup.filter_by_type(stInternalSolid)));
|
||||
polygons_append(new_internal_solid, to_polygons(backup.filter_by_type(stPosInternal | stDensSolid)));
|
||||
ExPolygons internal_solid = union_ex(new_internal_solid, false);
|
||||
// assign new internal-solid surfaces to layer
|
||||
neighbor_layerm->fill_surfaces.set(internal_solid, stInternalSolid);
|
||||
neighbor_layerm->fill_surfaces.set(internal_solid, stPosInternal | stDensSolid);
|
||||
// subtract intersections from layer surfaces to get resulting internal surfaces
|
||||
Polygons polygons_internal = to_polygons(std::move(internal_solid));
|
||||
ExPolygons internal = diff_ex(
|
||||
to_polygons(backup.filter_by_type(stInternal)),
|
||||
to_polygons(backup.filter_by_type(stPosInternal | stDensSparse)),
|
||||
polygons_internal,
|
||||
true);
|
||||
// assign resulting internal surfaces to layer
|
||||
neighbor_layerm->fill_surfaces.append(internal, stInternal);
|
||||
neighbor_layerm->fill_surfaces.append(internal, stPosInternal | stDensSparse);
|
||||
polygons_append(polygons_internal, to_polygons(std::move(internal)));
|
||||
// assign top and bottom surfaces to layer
|
||||
SurfaceType surface_types_solid[] = { stTop, stBottom, stBottomBridge };
|
||||
SurfaceType surface_types_solid[] = { stPosTop | stDensSolid, stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
|
||||
backup.keep_types(surface_types_solid, 3);
|
||||
//backup.keep_types_flag(stPosTop | stPosBottom);
|
||||
std::vector<SurfacesPtr> top_bottom_groups;
|
||||
backup.group(&top_bottom_groups);
|
||||
for (SurfacesPtr &group : top_bottom_groups)
|
||||
@ -2694,12 +2550,12 @@ void PrintObject::combine_infill()
|
||||
layerms.emplace_back(m_layers[i]->regions()[region_id]);
|
||||
// We need to perform a multi-layer intersection, so let's split it in pairs.
|
||||
// Initialize the intersection with the candidates of the lowest layer.
|
||||
ExPolygons intersection = to_expolygons(layerms.front()->fill_surfaces.filter_by_type(stInternal));
|
||||
ExPolygons intersection = to_expolygons(layerms.front()->fill_surfaces.filter_by_type(stPosInternal | stDensSparse));
|
||||
// Start looping from the second layer and intersect the current intersection with it.
|
||||
for (size_t i = 1; i < layerms.size(); ++ i)
|
||||
intersection = intersection_ex(
|
||||
to_polygons(intersection),
|
||||
to_polygons(layerms[i]->fill_surfaces.filter_by_type(stInternal)),
|
||||
to_polygons(layerms[i]->fill_surfaces.filter_by_type(stPosInternal | stDensSparse)),
|
||||
false);
|
||||
double area_threshold = layerms.front()->infill_area_threshold();
|
||||
if (! intersection.empty() && area_threshold > 0.)
|
||||
@ -2730,12 +2586,12 @@ void PrintObject::combine_infill()
|
||||
for (ExPolygon &expoly : intersection)
|
||||
polygons_append(intersection_with_clearance, offset(expoly, clearance_offset));
|
||||
for (LayerRegion *layerm : layerms) {
|
||||
Polygons internal = to_polygons(layerm->fill_surfaces.filter_by_type(stInternal));
|
||||
layerm->fill_surfaces.remove_type(stInternal);
|
||||
layerm->fill_surfaces.append(diff_ex(internal, intersection_with_clearance, false), stInternal);
|
||||
Polygons internal = to_polygons(layerm->fill_surfaces.filter_by_type(stPosInternal | stDensSparse));
|
||||
layerm->fill_surfaces.remove_type(stPosInternal | stDensSparse);
|
||||
layerm->fill_surfaces.append(diff_ex(internal, intersection_with_clearance, false), stPosInternal | stDensSparse);
|
||||
if (layerm == layerms.back()) {
|
||||
// Apply surfaces back with adjusted depth to the uppermost layer.
|
||||
Surface templ(stInternal, ExPolygon());
|
||||
Surface templ(stPosInternal | stDensSparse, ExPolygon());
|
||||
templ.thickness = 0.;
|
||||
for (LayerRegion *layerm2 : layerms)
|
||||
templ.thickness += layerm2->layer()->height;
|
||||
@ -2745,7 +2601,7 @@ void PrintObject::combine_infill()
|
||||
// Save void surfaces.
|
||||
layerm->fill_surfaces.append(
|
||||
intersection_ex(internal, intersection_with_clearance, false),
|
||||
stInternalVoid);
|
||||
stPosInternal | stDensVoid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -824,7 +824,7 @@ namespace SupportMaterialInternal {
|
||||
for (const LayerRegion *region : layer.regions()) {
|
||||
if (SupportMaterialInternal::has_bridging_perimeters(region->perimeters))
|
||||
return true;
|
||||
if (region->fill_surfaces.has(stBottomBridge) && has_bridging_fills(region->fills))
|
||||
if (region->fill_surfaces.has(stPosBottom | stDensSolid | stModBridge) && has_bridging_fills(region->fills))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -922,7 +922,7 @@ namespace SupportMaterialInternal {
|
||||
// remove the entire bridges and only support the unsupported edges
|
||||
//FIXME the brided regions are already collected as layerm->bridged. Use it?
|
||||
for (const Surface &surface : layerm->fill_surfaces.surfaces)
|
||||
if (surface.surface_type == stBottomBridge && surface.bridge_angle != -1)
|
||||
if (surface.has_pos_bottom() && surface.has_mod_bridge() && surface.bridge_angle != -1)
|
||||
polygons_append(bridges, surface.expolygon);
|
||||
//FIXME add the gap filled areas. Extrude the gaps with a bridge flow?
|
||||
// Remove the unsupported ends of the bridges from the bridged areas.
|
||||
@ -1468,7 +1468,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
||||
if (! m_object_config->support_material_buildplate_only)
|
||||
// Find the bottom contact layers above the top surfaces of this layer.
|
||||
task_group.run([this, &object, &top_contacts, contact_idx, &layer, layer_id, &layer_storage, &layer_support_areas, &bottom_contacts, &projection_raw] {
|
||||
Polygons top = collect_region_slices_by_type(layer, stTop);
|
||||
Polygons top = collect_region_slices_by_type(layer, stPosTop| stDensSolid);
|
||||
#ifdef SLIC3R_DEBUG
|
||||
{
|
||||
BoundingBox bbox = get_extents(projection_raw);
|
||||
@ -2134,7 +2134,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
||||
break;
|
||||
some_region_overlaps = true;
|
||||
polygons_append(polygons_trimming,
|
||||
offset(to_expolygons(region->fill_surfaces.filter_by_type(stBottomBridge)),
|
||||
offset(to_expolygons(region->fill_surfaces.filter_by_type(stPosBottom | stDensSolid | stModBridge)),
|
||||
gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
if (region->region()->config().overhangs.value)
|
||||
SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters, gap_xy_scaled, polygons_trimming);
|
||||
@ -2335,7 +2335,7 @@ static inline void fill_expolygons_generate_paths(
|
||||
fill_params.flow = &flow;
|
||||
fill_params.role = role;
|
||||
for (const ExPolygon &expoly : expolygons) {
|
||||
Surface surface(stInternal, expoly);
|
||||
Surface surface(stPosInternal | stDensSparse, expoly);
|
||||
filler->fill_surface_extrusion(&surface, fill_params, dst);
|
||||
}
|
||||
}
|
||||
@ -2355,7 +2355,7 @@ static inline void fill_expolygons_generate_paths(
|
||||
fill_params.flow = &flow;
|
||||
fill_params.role = role;
|
||||
for (ExPolygon &expoly : expolygons) {
|
||||
Surface surface(stInternal, std::move(expoly));
|
||||
Surface surface(stPosInternal | stDensSparse, std::move(expoly));
|
||||
filler->fill_surface_extrusion(&surface, fill_params, dst);
|
||||
}
|
||||
}
|
||||
|
@ -16,61 +16,53 @@ Surface::area() const
|
||||
}
|
||||
|
||||
bool
|
||||
Surface::is_solid() const
|
||||
{
|
||||
return this->surface_type == stTop
|
||||
|| this->surface_type == stBottom
|
||||
|| this->surface_type == stBottomBridge
|
||||
|| this->surface_type == stInternalSolid
|
||||
|| this->surface_type == stInternalBridge
|
||||
|| this->surface_type == stInternalOverBridge
|
||||
|| this->surface_type == stTopOverBridge;
|
||||
Surface::has_fill_void() const {
|
||||
return (this->surface_type & stDensVoid) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Surface::is_external() const
|
||||
{
|
||||
return this->surface_type == stTop
|
||||
|| this->surface_type == stBottom
|
||||
|| this->surface_type == stBottomBridge
|
||||
|| this->surface_type == stTopOverBridge;
|
||||
Surface::has_fill_sparse() const {
|
||||
return (this->surface_type & stDensSparse) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Surface::is_top() const
|
||||
{
|
||||
return this->surface_type == stTop
|
||||
|| this->surface_type == stTopOverBridge;
|
||||
Surface::has_fill_solid() const {
|
||||
return (this->surface_type & stDensSolid) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Surface::is_internal() const
|
||||
Surface::has_pos_external() const
|
||||
{
|
||||
return this->surface_type == stInternal
|
||||
|| this->surface_type == stInternalBridge
|
||||
|| this->surface_type == stInternalOverBridge
|
||||
|| this->surface_type == stInternalSolid
|
||||
|| this->surface_type == stInternalVoid;
|
||||
return has_pos_top() || has_pos_bottom();
|
||||
}
|
||||
|
||||
bool
|
||||
Surface::is_bottom() const
|
||||
Surface::has_pos_top() const
|
||||
{
|
||||
return this->surface_type == stBottom
|
||||
|| this->surface_type == stBottomBridge;
|
||||
return (this->surface_type & stPosTop) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Surface::is_bridge() const
|
||||
Surface::has_pos_internal() const
|
||||
{
|
||||
return this->surface_type == stBottomBridge
|
||||
|| this->surface_type == stInternalBridge;
|
||||
return (this->surface_type & stPosInternal) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Surface::has_pos_bottom() const
|
||||
{
|
||||
return (this->surface_type & stPosBottom) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Surface::has_mod_bridge() const
|
||||
{
|
||||
return (this->surface_type & stModBridge) != 0;
|
||||
}
|
||||
bool
|
||||
Surface::is_overBridge() const
|
||||
Surface::has_mod_overBridge() const
|
||||
{
|
||||
return this->surface_type == stInternalOverBridge
|
||||
|| this->surface_type == stTopOverBridge;
|
||||
return (this->surface_type & stModOverBridge) != 0;
|
||||
}
|
||||
|
||||
BoundingBox get_extents(const Surface &surface)
|
||||
@ -102,18 +94,16 @@ BoundingBox get_extents(const SurfacesPtr &surfaces)
|
||||
|
||||
const char* surface_type_to_color_name(const SurfaceType surface_type)
|
||||
{
|
||||
switch (surface_type) {
|
||||
case stTop: return "rgb(255,0,0)"; // "red";
|
||||
case stBottom: return "rgb(0,255,0)"; // "green";
|
||||
case stBottomBridge: return "rgb(0,0,255)"; // "blue";
|
||||
case stInternal: return "rgb(255,255,128)"; // yellow
|
||||
case stInternalSolid: return "rgb(255,0,255)"; // magenta
|
||||
case stInternalBridge: return "rgb(0,255,255)"; // cyan
|
||||
case stInternalOverBridge: return "rgb(0,255,128)"; // green-cyan
|
||||
case stInternalVoid: return "rgb(128,128,128)";
|
||||
case stPerimeter: return "rgb(128,0,0)"; // maroon
|
||||
default: return "rgb(64,64,64)";
|
||||
};
|
||||
if ((surface_type & stPosTop) != 0) return "rgb(255,0,0)"; // "red";
|
||||
if (surface_type == stPosBottom | stDensSolid | stModBridge) return "rgb(0,0,255)"; // "blue";
|
||||
if ((surface_type & stPosBottom) != 0) return "rgb(0,255,0)"; // "green";
|
||||
if (surface_type == stPosInternal | stDensSolid | stModBridge) return "rgb(0,255,255)"; // cyan
|
||||
if (surface_type == stPosInternal | stDensSolid | stModOverBridge) return "rgb(0,255,128)"; // green-cyan
|
||||
if (surface_type == stPosInternal | stDensSolid) return "rgb(255,0,255)"; // magenta
|
||||
if (surface_type == stPosInternal | stDensVoid) return "rgb(128,128,128)"; // gray
|
||||
if (surface_type == stPosInternal | stDensSparse) return "rgb(255,255,128)"; // yellow
|
||||
if ((surface_type & stPosPerimeter) != 0) return "rgb(128,0,0)"; // maroon
|
||||
return "rgb(64,64,64)"; //dark gray
|
||||
}
|
||||
|
||||
Point export_surface_type_legend_to_svg_box_size()
|
||||
@ -128,27 +118,27 @@ void export_surface_type_legend_to_svg(SVG &svg, const Point &pos)
|
||||
coord_t pos_x = pos_x0;
|
||||
coord_t pos_y = pos(1) + scale_(1.5);
|
||||
coord_t step_x = scale_(10.);
|
||||
svg.draw_legend(Point(pos_x, pos_y), "perimeter" , surface_type_to_color_name(stPerimeter));
|
||||
svg.draw_legend(Point(pos_x, pos_y), "perimeter" , surface_type_to_color_name(stPosPerimeter));
|
||||
pos_x += step_x;
|
||||
svg.draw_legend(Point(pos_x, pos_y), "top" , surface_type_to_color_name(stTop));
|
||||
svg.draw_legend(Point(pos_x, pos_y), "top" , surface_type_to_color_name(stPosTop));
|
||||
pos_x += step_x;
|
||||
svg.draw_legend(Point(pos_x, pos_y), "bottom" , surface_type_to_color_name(stBottom));
|
||||
svg.draw_legend(Point(pos_x, pos_y), "bottom" , surface_type_to_color_name(stPosBottom));
|
||||
pos_x += step_x;
|
||||
svg.draw_legend(Point(pos_x, pos_y), "bottom bridge" , surface_type_to_color_name(stBottomBridge));
|
||||
svg.draw_legend(Point(pos_x, pos_y), "bottom bridge" , surface_type_to_color_name(stPosBottom | stModBridge));
|
||||
pos_x += step_x;
|
||||
svg.draw_legend(Point(pos_x, pos_y), "invalid" , surface_type_to_color_name(SurfaceType(-1)));
|
||||
// 2nd row
|
||||
pos_x = pos_x0;
|
||||
pos_y = pos(1)+scale_(2.8);
|
||||
svg.draw_legend(Point(pos_x, pos_y), "internal" , surface_type_to_color_name(stInternal));
|
||||
svg.draw_legend(Point(pos_x, pos_y), "internal" , surface_type_to_color_name(stPosInternal | stDensSparse));
|
||||
pos_x += step_x;
|
||||
svg.draw_legend(Point(pos_x, pos_y), "internal solid" , surface_type_to_color_name(stInternalSolid));
|
||||
svg.draw_legend(Point(pos_x, pos_y), "internal solid" , surface_type_to_color_name(stPosInternal | stDensSolid));
|
||||
pos_x += step_x;
|
||||
svg.draw_legend(Point(pos_x, pos_y), "internal bridge", surface_type_to_color_name(stInternalBridge));
|
||||
svg.draw_legend(Point(pos_x, pos_y), "internal bridge", surface_type_to_color_name(stPosInternal | stDensSolid | stModBridge));
|
||||
pos_x += step_x;
|
||||
svg.draw_legend(Point(pos_x, pos_y), "internal over bridge", surface_type_to_color_name(stInternalOverBridge));
|
||||
svg.draw_legend(Point(pos_x, pos_y), "internal over bridge", surface_type_to_color_name(stPosInternal| stDensSolid | stModOverBridge));
|
||||
pos_x += step_x;
|
||||
svg.draw_legend(Point(pos_x, pos_y), "internal void" , surface_type_to_color_name(stInternalVoid));
|
||||
svg.draw_legend(Point(pos_x, pos_y), "internal void" , surface_type_to_color_name(stPosInternal | stDensVoid));
|
||||
}
|
||||
|
||||
bool export_to_svg(const char *path, const Surfaces &surfaces, const float transparency)
|
||||
|
@ -6,31 +6,50 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum SurfaceType {
|
||||
// Top horizontal surface, visible from the top.
|
||||
stTop,
|
||||
// Bottom horizontal surface, visible from the bottom, printed with a normal extrusion flow.
|
||||
stBottom,
|
||||
// Bottom horizontal surface, visible from the bottom, unsupported, printed with a bridging extrusion flow.
|
||||
stBottomBridge,
|
||||
// Normal sparse infill.
|
||||
stInternal,
|
||||
// Full infill, supporting the top surfaces and/or defining the verticall wall thickness.
|
||||
stInternalSolid,
|
||||
// 1st layer of dense infill over sparse infill, printed with a bridging extrusion flow.
|
||||
stInternalBridge,
|
||||
// 2nd layer of dense infill over sparse infill/nothing, printed with an over-extruding flow.
|
||||
stInternalOverBridge,
|
||||
stTopOverBridge,
|
||||
// stInternal turns into void surfaces if the sparse infill is used for supports only,
|
||||
// or if sparse infill layers get combined into a single layer.
|
||||
stInternalVoid,
|
||||
// Inner/outer perimeters.
|
||||
stPerimeter,
|
||||
// Last surface type, if the SurfaceType is used as an index into a vector.
|
||||
stLast,
|
||||
stCount = stLast + 1
|
||||
/// a SurfaceType should be composed of a Position & density flag
|
||||
/// Position: top, bottom, internal
|
||||
/// Density: solid, sparse, void
|
||||
/// optinally, is can also have one bridge modifier (bridge, over-bridge).
|
||||
enum SurfaceType : uint16_t {
|
||||
stNone = 0,
|
||||
/// Position: Top horizontal surface, visible from the top.
|
||||
stPosTop = 1 << 0,
|
||||
/// Position: Bottom horizontal surface, visible from the bottom, printed with a normal extrusion flow.
|
||||
stPosBottom = 1 << 1,
|
||||
/// Position: Normal sparse infill.
|
||||
stPosInternal = 1 << 2,
|
||||
/// Position: Inner/outer perimeters. Mainly used for coloring
|
||||
stPosPerimeter = 1 << 3,
|
||||
/// Density: Solid infill (100%).
|
||||
stDensSolid = 1 << 4,
|
||||
/// Density: Sparse infill (>0% & <100%).
|
||||
stDensSparse = 1 << 5,
|
||||
/// Density: or if sparse infill layers get combined into a single layer.
|
||||
stDensVoid = 1 << 6,
|
||||
/// Bridge Modifier: 1st layer of dense infill over sparse infill, printed with a bridging extrusion flow.
|
||||
stModBridge = 1 << 7,
|
||||
/// Bridge Modifier: 2nd layer of dense infill over sparse infill/nothing, may be printed with an over-extruding flow.
|
||||
stModOverBridge = 1 << 8,
|
||||
};
|
||||
inline SurfaceType operator|(SurfaceType a, SurfaceType b) {
|
||||
return static_cast<SurfaceType>(static_cast<uint16_t>(a) | static_cast<uint16_t>(b));
|
||||
}
|
||||
inline SurfaceType operator&(SurfaceType a, SurfaceType b) {
|
||||
return static_cast<SurfaceType>(static_cast<uint16_t>(a)& static_cast<uint16_t>(b));
|
||||
}
|
||||
inline SurfaceType operator|=(SurfaceType& a, SurfaceType b) {
|
||||
a = a | b; return a;
|
||||
}
|
||||
inline SurfaceType operator&=(SurfaceType& a, SurfaceType b) {
|
||||
a = a & b; return a;
|
||||
}
|
||||
//inline bool operator==(SurfaceType a, SurfaceType b) {
|
||||
// return static_cast<uint16_t>(a) ^ static_cast<uint16_t>(b) == 0;
|
||||
//}
|
||||
//inline bool operator!=(SurfaceType a, SurfaceType b) {
|
||||
// return static_cast<uint16_t>(a) ^ static_cast<uint16_t>(b) != 0;
|
||||
//}
|
||||
|
||||
|
||||
class Surface
|
||||
{
|
||||
@ -108,13 +127,15 @@ public:
|
||||
double area() const;
|
||||
bool empty() const { return expolygon.empty(); }
|
||||
void clear() { expolygon.clear(); }
|
||||
bool is_solid() const;
|
||||
bool is_external() const;
|
||||
bool is_top() const;
|
||||
bool is_internal() const;
|
||||
bool is_bottom() const;
|
||||
bool is_bridge() const;
|
||||
bool is_overBridge() const;
|
||||
bool has_fill_solid() const;
|
||||
bool has_fill_sparse() const;
|
||||
bool has_fill_void() const;
|
||||
bool has_pos_external() const;
|
||||
bool has_pos_top() const;
|
||||
bool has_pos_internal() const;
|
||||
bool has_pos_bottom() const;
|
||||
bool has_mod_bridge() const;
|
||||
bool has_mod_overBridge() const;
|
||||
};
|
||||
|
||||
typedef std::vector<Surface> Surfaces;
|
||||
|
@ -64,6 +64,16 @@ SurfaceCollection::filter_by_type(const SurfaceType type)
|
||||
return ss;
|
||||
}
|
||||
|
||||
SurfacesPtr
|
||||
SurfaceCollection::filter_by_type_flag(const SurfaceType allowed, const SurfaceType not_allowed)
|
||||
{
|
||||
SurfacesPtr ss;
|
||||
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
|
||||
if (surface->surface_type & allowed == allowed && surface->surface_type & not_allowed == 0) ss.push_back(&*surface);
|
||||
}
|
||||
return ss;
|
||||
}
|
||||
|
||||
SurfacesPtr
|
||||
SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes)
|
||||
{
|
||||
@ -80,7 +90,7 @@ SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes)
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons)
|
||||
SurfaceCollection::filter_by_type(const SurfaceType type, Polygons* polygons)
|
||||
{
|
||||
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
|
||||
if (surface->surface_type == type) {
|
||||
@ -89,16 +99,41 @@ SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons)
|
||||
}
|
||||
}
|
||||
}
|
||||
void
|
||||
SurfaceCollection::filter_by_type_flag(Polygons* polygons, const SurfaceType flags_needed, const SurfaceType flags_not_allowed)
|
||||
{
|
||||
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
|
||||
if (surface->surface_type & flags_needed == flags_needed && surface->surface_type & flags_not_allowed) {
|
||||
Polygons pp = surface->expolygon;
|
||||
polygons->insert(polygons->end(), pp.begin(), pp.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::keep_type(const SurfaceType type)
|
||||
{
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < surfaces.size(); ++ i) {
|
||||
for (size_t i = 0; i < surfaces.size(); ++i) {
|
||||
if (surfaces[i].surface_type == type) {
|
||||
if (j < i)
|
||||
std::swap(surfaces[i], surfaces[j]);
|
||||
++ j;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
if (j < surfaces.size())
|
||||
surfaces.erase(surfaces.begin() + j, surfaces.end());
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::keep_type_flag(const SurfaceType type_to_keep, const SurfaceType type_to_remove)
|
||||
{
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < surfaces.size(); ++i) {
|
||||
if (surfaces[i].surface_type & type_to_keep == type_to_keep && surfaces[i].surface_type & type_to_remove == 0) {
|
||||
if (j < i)
|
||||
std::swap(surfaces[i], surfaces[j]);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
if (j < surfaces.size())
|
||||
@ -127,6 +162,21 @@ SurfaceCollection::keep_types(const SurfaceType *types, int ntypes)
|
||||
surfaces.erase(surfaces.begin() + j, surfaces.end());
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::keep_types_flag(const SurfaceType types_to_keep, const SurfaceType type_to_remove)
|
||||
{
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < surfaces.size(); ++i) {
|
||||
if (surfaces[i].surface_type & types_to_keep != 0 && surfaces[i].surface_type & type_to_remove == 0) {
|
||||
if (j < i)
|
||||
std::swap(surfaces[i], surfaces[j]);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
if (j < surfaces.size())
|
||||
surfaces.erase(surfaces.begin() + j, surfaces.end());
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceCollection::remove_type(const SurfaceType type)
|
||||
{
|
||||
|
@ -20,20 +20,24 @@ public:
|
||||
void simplify(double tolerance);
|
||||
void group(std::vector<SurfacesPtr> *retval);
|
||||
template <class T> bool any_internal_contains(const T &item) const {
|
||||
for (const Surface &surface : this->surfaces) if (surface.is_internal() && surface.expolygon.contains(item)) return true;
|
||||
for (const Surface &surface : this->surfaces) if (surface.has_pos_internal() && surface.expolygon.contains(item)) return true;
|
||||
return false;
|
||||
}
|
||||
template <class T> bool any_bottom_contains(const T &item) const {
|
||||
for (const Surface &surface : this->surfaces) if (surface.is_bottom() && surface.expolygon.contains(item)) return true;
|
||||
for (const Surface &surface : this->surfaces) if (surface.has_pos_bottom() && surface.expolygon.contains(item)) return true;
|
||||
return false;
|
||||
}
|
||||
SurfacesPtr filter_by_type(const SurfaceType type);
|
||||
SurfacesPtr filter_by_type_flag(const SurfaceType allowed, const SurfaceType not_allowed = stNone);
|
||||
SurfacesPtr filter_by_types(const SurfaceType *types, int ntypes);
|
||||
void keep_type(const SurfaceType type);
|
||||
void keep_type_flag(const SurfaceType flags_needed, const SurfaceType flags_to_remove = stNone);
|
||||
void keep_types(const SurfaceType *types, int ntypes);
|
||||
void keep_types_flag(const SurfaceType flags_to_keep, const SurfaceType flags_to_remove = stNone);
|
||||
void remove_type(const SurfaceType type);
|
||||
void remove_types(const SurfaceType *types, int ntypes);
|
||||
void filter_by_type(SurfaceType type, Polygons* polygons);
|
||||
void filter_by_type(const SurfaceType type, Polygons* polygons);
|
||||
void filter_by_type_flag(Polygons* polygons, const SurfaceType flags_needed, const SurfaceType flags_not_allowed = stNone);
|
||||
|
||||
void clear() { surfaces.clear(); }
|
||||
bool empty() const { return surfaces.empty(); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user