Change SurfaceType to flags

This commit is contained in:
supermerill 2018-11-27 14:05:26 +01:00
parent 450042a60c
commit 816bb1e546
8 changed files with 68 additions and 60 deletions

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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<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
{
@ -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;
};

View File

@ -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;