From 816bb1e546f325cd749a507afc3b9dbc617bac18 Mon Sep 17 00:00:00 2001 From: supermerill Date: Tue, 27 Nov 2018 14:05:26 +0100 Subject: [PATCH] Change SurfaceType to flags --- xs/src/libslic3r/Layer.cpp | 4 ++-- xs/src/libslic3r/LayerRegion.cpp | 14 +++++++------- xs/src/libslic3r/LayerRegionFill.cpp | 16 ++++++++-------- xs/src/libslic3r/PrintObject.cpp | 28 ++++++++++++++-------------- xs/src/libslic3r/SupportMaterial.cpp | 2 +- xs/src/libslic3r/Surface.cpp | 27 +++++++++++---------------- xs/src/libslic3r/Surface.hpp | 28 ++++++++++++++++++++-------- xs/xsp/Surface.xsp | 9 +++++---- 8 files changed, 68 insertions(+), 60 deletions(-) diff --git a/xs/src/libslic3r/Layer.cpp b/xs/src/libslic3r/Layer.cpp index cbbc6b3ee..26c766890 100644 --- a/xs/src/libslic3r/Layer.cpp +++ b/xs/src/libslic3r/Layer.cpp @@ -331,7 +331,7 @@ Layer::detect_surfaces_type() const SurfaceType surface_type_bottom = (object.config.support_material.value && object.config.support_material_contact_distance.value == 0) ? stBottom - : stBottomBridge; + : stBottom | stBridge; // Any surface lying on the void is a true bottom bridge (an overhang) bottom.append( @@ -370,7 +370,7 @@ Layer::detect_surfaces_type() // just like any other bottom surface lying on the void const SurfaceType surface_type_bottom = (object.config.raft_layers.value > 0 && object.config.support_material_contact_distance.value > 0) - ? stBottomBridge + ? stBottom | stBridge : stBottom; for (Surface &s : bottom.surfaces) s.surface_type = surface_type_bottom; } diff --git a/xs/src/libslic3r/LayerRegion.cpp b/xs/src/libslic3r/LayerRegion.cpp index 49e1775ea..750d86143 100644 --- a/xs/src/libslic3r/LayerRegion.cpp +++ b/xs/src/libslic3r/LayerRegion.cpp @@ -152,7 +152,7 @@ LayerRegion::process_external_surfaces() SurfaceCollection top; for (const Surface &surface : surfaces) { - if (surface.surface_type != stTop) continue; + if (!surface.is_top()) continue; // give priority to bottom surfaces ExPolygons grown = diff_ex( @@ -169,7 +169,7 @@ LayerRegion::process_external_surfaces() fill_boundaries = SurfaceCollection(surfaces); } else { for (const Surface &s : surfaces) - if (s.surface_type != stInternal) + if (s.is_external()) fill_boundaries.surfaces.push_back(s); } @@ -203,7 +203,7 @@ LayerRegion::process_external_surfaces() { SurfaceCollection other; for (const Surface &s : surfaces) - if (s.surface_type != stTop && !s.is_bottom()) + if (!s.is_top() && !s.is_bottom()) other.surfaces.push_back(s); // group surfaces @@ -241,7 +241,7 @@ LayerRegion::prepare_fill_surfaces() for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) { if (surface->surface_type == stTop) { if (this->layer()->object()->config.infill_only_where_needed) { - surface->surface_type = stInternalVoid; + surface->surface_type = stInternal | stVoid; } else { surface->surface_type = stInternal; } @@ -251,7 +251,7 @@ LayerRegion::prepare_fill_surfaces() if (this->region()->config.bottom_solid_layers == 0 && this->region()->config.min_top_bottom_shell_thickness <= 0) { for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) { - if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge) + if (surface->is_bottom()) surface->surface_type = stInternal; } } @@ -263,8 +263,8 @@ LayerRegion::prepare_fill_surfaces() // (we don't use scale_() because it would overflow the coord_t range const double min_area = this->region()->config.solid_infill_below_area.value / SCALING_FACTOR / SCALING_FACTOR; for (Surface &surface : this->fill_surfaces.surfaces) { - if (surface.surface_type == stInternal && surface.area() <= min_area) - surface.surface_type = stInternalSolid; + if (!surface.is_internal() && surface.area() <= min_area) + surface.surface_type = stInternal | stSolid; } } } diff --git a/xs/src/libslic3r/LayerRegionFill.cpp b/xs/src/libslic3r/LayerRegionFill.cpp index 3eb5e4a8d..55ca3e4d5 100644 --- a/xs/src/libslic3r/LayerRegionFill.cpp +++ b/xs/src/libslic3r/LayerRegionFill.cpp @@ -67,8 +67,8 @@ LayerRegion::make_fill() if (!surface.is_solid() || surface.is_bridge()) continue; group_attrib[i].is_solid = true; - group_attrib[i].fw = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width; - group_attrib[i].pattern = surface.surface_type == stTop ? this->region()->config.top_infill_pattern.value + group_attrib[i].fw = (surface.is_top()) ? top_solid_infill_flow.width : solid_infill_flow.width; + group_attrib[i].pattern = surface.is_top() ? this->region()->config.top_infill_pattern.value : surface.is_bottom() ? this->region()->config.bottom_infill_pattern.value : ipRectilinear; } @@ -137,7 +137,7 @@ LayerRegion::make_fill() ); Polygons to_subtract; - surfaces.filter_by_type(stInternalVoid, &to_subtract); + surfaces.filter_by_type(stInternal | stVoid, &to_subtract); append_to(to_subtract, collapsed); surfaces.append( @@ -146,7 +146,7 @@ LayerRegion::make_fill() to_subtract, true ), - stInternalSolid + stInternal | stSolid ); } @@ -162,19 +162,19 @@ LayerRegion::make_fill() surface_it != surfaces.surfaces.end(); ++surface_it) { const Surface &surface = *surface_it; - if (surface.surface_type == stInternalVoid) + if (surface.surface_type == (stInternal | stVoid)) continue; InfillPattern fill_pattern = this->region()->config.fill_pattern.value; double density = fill_density; - FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill + FlowRole role = (surface.is_top()) ? frTopSolidInfill : surface.is_solid() ? frSolidInfill : frInfill; const bool is_bridge = this->layer()->id() > 0 && surface.is_bridge(); if (surface.is_solid()) { density = 100.; - fill_pattern = (surface.surface_type == stTop) ? this->region()->config.top_infill_pattern.value + fill_pattern = (surface.is_top()) ? this->region()->config.top_infill_pattern.value : (surface.is_bottom() && !is_bridge) ? this->region()->config.bottom_infill_pattern.value : ipRectilinear; } else if (density <= 0) @@ -277,7 +277,7 @@ LayerRegion::make_fill() if (is_bridge) { role = erBridgeInfill; } else if (surface.is_solid()) { - role = (surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill; + role = (surface.is_top()) ? erTopSolidInfill : erSolidInfill; } else { role = erInternalInfill; } diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 74f36099e..5b7040192 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -392,7 +392,7 @@ 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(stInternal | stSolid, &internal_solid); if (internal_solid.empty()) continue; // check whether we should bridge or not according to density @@ -489,15 +489,15 @@ PrintObject::bridge_over_infill() { Surfaces new_surfaces; for (Surfaces::const_iterator surface = layerm->fill_surfaces.surfaces.begin(); surface != layerm->fill_surfaces.surfaces.end(); ++surface) { - if (surface->surface_type != stInternalSolid) + if (surface->surface_type != (stInternal | stSolid)) new_surfaces.push_back(*surface); } for (ExPolygons::const_iterator ex = to_bridge.begin(); ex != to_bridge.end(); ++ex) - new_surfaces.push_back(Surface(stInternalBridge, *ex)); + new_surfaces.push_back(Surface(stInternal | stBridge, *ex)); for (ExPolygons::const_iterator ex = not_to_bridge.begin(); ex != not_to_bridge.end(); ++ex) - new_surfaces.push_back(Surface(stInternalSolid, *ex)); + new_surfaces.push_back(Surface(stInternal | stSolid, *ex)); layerm->fill_surfaces.surfaces = new_surfaces; } @@ -1275,7 +1275,7 @@ PrintObject::combine_infill() // Save void surfaces. layerm->fill_surfaces.append( intersection_ex(internal, intersection_with_clearance, false), - stInternalVoid); + stInternal | stVoid); } } } @@ -1386,7 +1386,7 @@ PrintObject::discover_horizontal_shells() if (region_config.solid_infill_every_layers() > 0 && region_config.fill_density() > 0 && (i % region_config.solid_infill_every_layers()) == 0) { - const auto type = region_config.fill_density() == 100 ? stInternalSolid : stInternalBridge; + const auto type = region_config.fill_density() == 100 ? (stInternal | stSolid) : (stInternal | stBridge); for (auto* s : layerm->fill_surfaces.filter_by_type(stInternal)) s->surface_type = type; } @@ -1399,7 +1399,7 @@ void PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id) { const auto& region_config = layerm->region()->config; - for (auto& type : { stTop, stBottom, stBottomBridge }) { + for (auto& type : { stTop, stBottom, (stBottom | stBridge) }) { // 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 @@ -1451,7 +1451,7 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz // intersections have contours and holes Polygons new_internal_solid = intersection( solid, - to_polygons(neighbor_fill_surfaces.filter_by_type({stInternal, stInternalSolid})), + to_polygons(neighbor_fill_surfaces.filter_by_type({stInternal, stInternal | stSolid})), true ); if (new_internal_solid.empty()) { @@ -1529,7 +1529,7 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz // internal-solid are the union of the existing internal-solid surfaces // and new ones - Polygons tmp { to_polygons(neighbor_fill_surfaces.filter_by_type(stInternalSolid)) }; + Polygons tmp { to_polygons(neighbor_fill_surfaces.filter_by_type(stInternal | stSolid)) }; polygons_append(tmp, new_internal_solid); const auto internal_solid = union_ex(tmp); @@ -1542,7 +1542,7 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz neighbor_layerm->fill_surfaces.append(internal, stInternal); // assign new internal-solid surfaces to layer - neighbor_layerm->fill_surfaces.append(internal_solid, stInternalSolid); + neighbor_layerm->fill_surfaces.append(internal_solid, stInternal | stSolid); // assign top and bottom surfaces to layer SurfaceCollection tmp_coll; @@ -1624,7 +1624,7 @@ PrintObject::clip_fill_surfaces() // get our current internal fill boundaries Polygons lower_layer_internal_surfaces; for (const auto* layerm : lower_layer->regions) - for (const auto* s : layerm->fill_surfaces.filter_by_type({ stInternal, stInternalVoid })) + for (const auto* s : layerm->fill_surfaces.filter_by_type({ stInternal, stInternal | stVoid })) polygons_append(lower_layer_internal_surfaces, *s); upper_internal = intersection(overhangs, lower_layer_internal_surfaces); } @@ -1635,12 +1635,12 @@ PrintObject::clip_fill_surfaces() continue; Polygons internal; - for (const auto* s : layerm->fill_surfaces.filter_by_type({ stInternal, stInternalVoid })) + for (const auto* s : layerm->fill_surfaces.filter_by_type({ stInternal, stInternal | stVoid })) polygons_append(internal, *s); - layerm->fill_surfaces.remove_types({ stInternal, stInternalVoid }); + layerm->fill_surfaces.remove_types({ stInternal, stInternal | stVoid }); 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(diff_ex (internal, upper_internal, true), stInternal | stVoid); // 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 diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp index ce493e84d..556873297 100644 --- a/xs/src/libslic3r/SupportMaterial.cpp +++ b/xs/src/libslic3r/SupportMaterial.cpp @@ -409,7 +409,7 @@ SupportMaterial::contact_area(PrintObject *object) if (1) { // Remove the entire bridges and only support the unsupported edges. ExPolygons bridges; - for (auto surface : layer_m->fill_surfaces.filter_by_type(stBottomBridge)) { + for (auto surface : layer_m->fill_surfaces.filter_by_type(stBottom | stBridge)) { if (surface->bridge_angle != -1) { bridges.push_back(surface->expolygon); } diff --git a/xs/src/libslic3r/Surface.cpp b/xs/src/libslic3r/Surface.cpp index 4d2234e4d..061909d1d 100644 --- a/xs/src/libslic3r/Surface.cpp +++ b/xs/src/libslic3r/Surface.cpp @@ -16,42 +16,37 @@ 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; + return this->surface_type & (stTop | stBottom | stSolid | stBridge) != 0; } bool Surface::is_external() const { - return this->surface_type == stTop - || this->surface_type == stBottom - || this->surface_type == stBottomBridge; + return is_top() || is_bottom(); } bool Surface::is_internal() const { - return this->surface_type == stInternal - || this->surface_type == stInternalBridge - || this->surface_type == stInternalSolid - || this->surface_type == stInternalVoid; + return this->surface_type & stInternal != 0; } bool Surface::is_bottom() const { - return this->surface_type == stBottom - || this->surface_type == stBottomBridge; + return this->surface_type & stBottom != 0; +} + +bool +Surface::is_top() const +{ + return this->surface_type & stTop != 0; } bool Surface::is_bridge() const { - return this->surface_type == stBottomBridge - || this->surface_type == stInternalBridge; + return this->surface_type & stBridge != 0; } } diff --git a/xs/src/libslic3r/Surface.hpp b/xs/src/libslic3r/Surface.hpp index 17e232d7c..fdd827772 100644 --- a/xs/src/libslic3r/Surface.hpp +++ b/xs/src/libslic3r/Surface.hpp @@ -8,15 +8,26 @@ namespace Slic3r { /// Surface type enumerations. /// As it is very unlikely that there will be more than 32 or 64 of these surface types, pack into a flag -enum SurfaceType { - stTop = 0b1, - stBottom = 0b10, - stBottomBridge = 0b100, - stInternal = 0b1000, - stInternalSolid = 0b10000, - stInternalBridge = 0b100000, - stInternalVoid = 0b1000000 +enum SurfaceType : uint16_t { + stTop = 0b1, /// stTop: it has nothing just on top of it + stBottom = 0b10, /// stBottom: it's a surface with nothing just under it (or the base plate, or a support) + stInternal = 0b100, /// stInternal: not top nor bottom + stSolid = 0b1000, /// stSolid: modify the stInternal to say it should be at 100% infill + stBridge = 0b10000, /// stBridge: modify stBottom or stInternal to say it should be extruded as a bridge + stVoid = 0b100000 /// stVoid: modify stInternal to say it should be at 0% infill }; +inline SurfaceType operator|(SurfaceType a, SurfaceType b) +{return static_cast(static_cast(a) | static_cast(b));} +inline SurfaceType operator&(SurfaceType a, SurfaceType b) +{return static_cast(static_cast(a) & static_cast(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(a) ^ static_cast(b) == 0;} +inline bool operator!=(SurfaceType a, SurfaceType b) +{return static_cast(a) ^ static_cast(b) != 0;} class Surface { @@ -37,6 +48,7 @@ class Surface bool is_solid() const; bool is_external() const; bool is_internal() const; + bool is_top() const; bool is_bottom() const; bool is_bridge() const; }; diff --git a/xs/xsp/Surface.xsp b/xs/xsp/Surface.xsp index 021a8b7e4..d3fef5336 100644 --- a/xs/xsp/Surface.xsp +++ b/xs/xsp/Surface.xsp @@ -19,6 +19,7 @@ bool is_external() const; bool is_internal() const; bool is_bottom() const; + bool is_top() const; bool is_bridge() const; %{ @@ -104,11 +105,11 @@ _constant() ALIAS: S_TYPE_TOP = stTop S_TYPE_BOTTOM = stBottom - S_TYPE_BOTTOMBRIDGE = stBottomBridge + S_TYPE_BOTTOMBRIDGE = stBottom | stBridge S_TYPE_INTERNAL = stInternal - S_TYPE_INTERNALSOLID = stInternalSolid - S_TYPE_INTERNALBRIDGE = stInternalBridge - S_TYPE_INTERNALVOID = stInternalVoid + S_TYPE_INTERNALSOLID = stInternal | stSolid + S_TYPE_INTERNALBRIDGE = stInternal | stBridge + S_TYPE_INTERNALVOID = stInternal | stVoid PROTOTYPE: CODE: RETVAL = ix;