Merge branch 'alexrj_flagssurfacetype'

Completes pr #4616
This commit is contained in:
Joseph Lenox 2018-12-02 17:00:40 -06:00
commit 802b1e1aa7
12 changed files with 107 additions and 92 deletions

View File

@ -269,7 +269,7 @@ sub contact_area {
# remove the entire bridges and only support the unsupported edges # remove the entire bridges and only support the unsupported edges
my @bridges = map $_->expolygon, my @bridges = map $_->expolygon,
grep $_->bridge_angle != -1, grep $_->bridge_angle != -1,
@{$layerm->fill_surfaces->filter_by_type(S_TYPE_BOTTOMBRIDGE)}; @{$layerm->fill_surfaces->filter_by_type(S_TYPE_BOTTOM + S_TYPE_BRIDGE)};
$diff = diff( $diff = diff(
$diff, $diff,

View File

@ -4,7 +4,7 @@ use warnings;
require Exporter; require Exporter;
our @ISA = qw(Exporter); our @ISA = qw(Exporter);
our @EXPORT_OK = qw(S_TYPE_TOP S_TYPE_BOTTOM S_TYPE_BOTTOMBRIDGE S_TYPE_INTERNAL S_TYPE_INTERNALSOLID S_TYPE_INTERNALBRIDGE S_TYPE_INTERNALVOID); our @EXPORT_OK = qw(S_TYPE_TOP S_TYPE_BOTTOM S_TYPE_INTERNAL S_TYPE_SOLID S_TYPE_BRIDGE S_TYPE_VOID);
our %EXPORT_TAGS = (types => \@EXPORT_OK); our %EXPORT_TAGS = (types => \@EXPORT_OK);
sub p { sub p {

View File

@ -82,7 +82,7 @@ plan tests => 8;
my $print = Slic3r::Test::init_print('20mm_cube', config => $config); my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
$print->process; $print->process;
ok defined(first { @{$_->get_region(0)->fill_surfaces->filter_by_type(S_TYPE_INTERNALVOID)} > 0 } ok defined(first { @{$_->get_region(0)->fill_surfaces->filter_by_type(S_TYPE_INTERNAL + S_TYPE_VOID)} > 0 }
@{$print->print->get_object(0)->layers}), @{$print->print->get_object(0)->layers}),
'infill combination produces internal void surfaces'; 'infill combination produces internal void surfaces';

View File

@ -267,7 +267,7 @@ Layer::make_fills()
/// Initially all slices are of type S_TYPE_INTERNAL. /// Initially all slices are of type S_TYPE_INTERNAL.
/// Slices are compared against the top / bottom slices and regions and classified to the following groups: /// Slices are compared against the top / bottom slices and regions and classified to the following groups:
/// S_TYPE_TOP - Part of a region, which is not covered by any upper layer. This surface will be filled with a top solid infill. /// S_TYPE_TOP - Part of a region, which is not covered by any upper layer. This surface will be filled with a top solid infill.
/// S_TYPE_BOTTOMBRIDGE - Part of a region, which is not fully supported, but it hangs in the air, or it hangs losely on a support or a raft. /// S_TYPE_BOTTOM | S_TYPE_BRIDGE - Part of a region, which is not fully supported, but it hangs in the air, or it hangs losely on a support or a raft.
/// S_TYPE_BOTTOM - Part of a region, which is not supported by the same region, but it is supported either by another region, or by a soluble interface layer. /// S_TYPE_BOTTOM - Part of a region, which is not supported by the same region, but it is supported either by another region, or by a soluble interface layer.
/// S_TYPE_INTERNAL - Part of a region, which is supported by the same region type. /// S_TYPE_INTERNAL - Part of a region, which is supported by the same region type.
/// If a part of a region is of S_TYPE_BOTTOM and S_TYPE_TOP, the S_TYPE_BOTTOM wins. /// If a part of a region is of S_TYPE_BOTTOM and S_TYPE_TOP, the S_TYPE_BOTTOM wins.
@ -331,7 +331,7 @@ Layer::detect_surfaces_type()
const SurfaceType surface_type_bottom = const SurfaceType surface_type_bottom =
(object.config.support_material.value && object.config.support_material_contact_distance.value == 0) (object.config.support_material.value && object.config.support_material_contact_distance.value == 0)
? stBottom ? stBottom
: stBottomBridge; : (stBottom | stBridge);
// Any surface lying on the void is a true bottom bridge (an overhang) // Any surface lying on the void is a true bottom bridge (an overhang)
bottom.append( bottom.append(
@ -370,7 +370,7 @@ Layer::detect_surfaces_type()
// just like any other bottom surface lying on the void // just like any other bottom surface lying on the void
const SurfaceType surface_type_bottom = const SurfaceType surface_type_bottom =
(object.config.raft_layers.value > 0 && object.config.support_material_contact_distance.value > 0) (object.config.raft_layers.value > 0 && object.config.support_material_contact_distance.value > 0)
? stBottomBridge ? (stBottom | stBridge)
: stBottom; : stBottom;
for (Surface &s : bottom.surfaces) s.surface_type = surface_type_bottom; for (Surface &s : bottom.surfaces) s.surface_type = surface_type_bottom;
} }

View File

@ -152,7 +152,7 @@ LayerRegion::process_external_surfaces()
SurfaceCollection top; SurfaceCollection top;
for (const Surface &surface : surfaces) { for (const Surface &surface : surfaces) {
if (surface.surface_type != stTop) continue; if (!surface.is_top()) continue;
// give priority to bottom surfaces // give priority to bottom surfaces
ExPolygons grown = diff_ex( ExPolygons grown = diff_ex(
@ -203,7 +203,7 @@ LayerRegion::process_external_surfaces()
{ {
SurfaceCollection other; SurfaceCollection other;
for (const Surface &s : surfaces) 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); other.surfaces.push_back(s);
// group surfaces // group surfaces
@ -238,21 +238,21 @@ LayerRegion::prepare_fill_surfaces()
// if no solid layers are requested, turn top/bottom surfaces to internal // if no solid layers are requested, turn top/bottom surfaces to internal
if (this->region()->config.top_solid_layers == 0 && this->region()->config.min_top_bottom_shell_thickness <= 0) { if (this->region()->config.top_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) { for (Surface &surface : this->fill_surfaces.surfaces) {
if (surface->surface_type == stTop) { if (surface.surface_type == stTop) {
if (this->layer()->object()->config.infill_only_where_needed) { if (this->layer()->object()->config.infill_only_where_needed) {
surface->surface_type = stInternalVoid; surface.surface_type = (stInternal | stVoid);
} else { } else {
surface->surface_type = stInternal; surface.surface_type = stInternal;
} }
} }
} }
} }
if (this->region()->config.bottom_solid_layers == 0 && this->region()->config.min_top_bottom_shell_thickness <= 0) { 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) { for (Surface &surface : this->fill_surfaces.surfaces) {
if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge) if (surface.is_bottom())
surface->surface_type = stInternal; surface.surface_type = stInternal;
} }
} }
@ -264,7 +264,7 @@ LayerRegion::prepare_fill_surfaces()
const double min_area = this->region()->config.solid_infill_below_area.value / SCALING_FACTOR / SCALING_FACTOR; const double min_area = this->region()->config.solid_infill_below_area.value / SCALING_FACTOR / SCALING_FACTOR;
for (Surface &surface : this->fill_surfaces.surfaces) { for (Surface &surface : this->fill_surfaces.surfaces) {
if (surface.surface_type == stInternal && surface.area() <= min_area) if (surface.surface_type == stInternal && surface.area() <= min_area)
surface.surface_type = stInternalSolid; surface.surface_type = (stInternal | stSolid);
} }
} }
} }

View File

@ -67,8 +67,8 @@ LayerRegion::make_fill()
if (!surface.is_solid() || surface.is_bridge()) continue; if (!surface.is_solid() || surface.is_bridge()) continue;
group_attrib[i].is_solid = true; 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].fw = (surface.is_top()) ? 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].pattern = surface.is_top() ? this->region()->config.top_infill_pattern.value
: surface.is_bottom() ? this->region()->config.bottom_infill_pattern.value : surface.is_bottom() ? this->region()->config.bottom_infill_pattern.value
: ipRectilinear; : ipRectilinear;
} }
@ -137,7 +137,7 @@ LayerRegion::make_fill()
); );
Polygons to_subtract; Polygons to_subtract;
surfaces.filter_by_type(stInternalVoid, &to_subtract); surfaces.filter_by_type((stInternal | stVoid), &to_subtract);
append_to(to_subtract, collapsed); append_to(to_subtract, collapsed);
surfaces.append( surfaces.append(
@ -146,7 +146,7 @@ LayerRegion::make_fill()
to_subtract, to_subtract,
true true
), ),
stInternalSolid (stInternal | stSolid)
); );
} }
@ -162,19 +162,19 @@ LayerRegion::make_fill()
surface_it != surfaces.surfaces.end(); ++surface_it) { surface_it != surfaces.surfaces.end(); ++surface_it) {
const Surface &surface = *surface_it; const Surface &surface = *surface_it;
if (surface.surface_type == stInternalVoid) if (surface.surface_type == (stInternal | stVoid))
continue; continue;
InfillPattern fill_pattern = this->region()->config.fill_pattern.value; InfillPattern fill_pattern = this->region()->config.fill_pattern.value;
double density = fill_density; double density = fill_density;
FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill FlowRole role = (surface.is_top()) ? frTopSolidInfill
: surface.is_solid() ? frSolidInfill : surface.is_solid() ? frSolidInfill
: frInfill; : frInfill;
const bool is_bridge = this->layer()->id() > 0 && surface.is_bridge(); const bool is_bridge = this->layer()->id() > 0 && surface.is_bridge();
if (surface.is_solid()) { if (surface.is_solid()) {
density = 100.; 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 : (surface.is_bottom() && !is_bridge) ? this->region()->config.bottom_infill_pattern.value
: ipRectilinear; : ipRectilinear;
} else if (density <= 0) } else if (density <= 0)
@ -277,7 +277,7 @@ LayerRegion::make_fill()
if (is_bridge) { if (is_bridge) {
role = erBridgeInfill; role = erBridgeInfill;
} else if (surface.is_solid()) { } else if (surface.is_solid()) {
role = (surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill; role = (surface.is_top()) ? erTopSolidInfill : erSolidInfill;
} else { } else {
role = erInternalInfill; role = erInternalInfill;
} }

View File

@ -395,7 +395,7 @@ PrintObject::bridge_over_infill()
// extract the stInternalSolid surfaces that might be transformed into bridges // extract the stInternalSolid surfaces that might be transformed into bridges
Polygons internal_solid; 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; if (internal_solid.empty()) continue;
// check whether we should bridge or not according to density // check whether we should bridge or not according to density
@ -492,15 +492,15 @@ PrintObject::bridge_over_infill()
{ {
Surfaces new_surfaces; Surfaces new_surfaces;
for (Surfaces::const_iterator surface = layerm->fill_surfaces.surfaces.begin(); surface != layerm->fill_surfaces.surfaces.end(); ++surface) { 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); new_surfaces.push_back(*surface);
} }
for (ExPolygons::const_iterator ex = to_bridge.begin(); ex != to_bridge.end(); ++ex) 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) 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; layerm->fill_surfaces.surfaces = new_surfaces;
} }
@ -524,7 +524,7 @@ PrintObject::bridge_over_infill()
)}; )};
push @new_surfaces, map Slic3r::Surface->new( push @new_surfaces, map Slic3r::Surface->new(
expolygon => $_, expolygon => $_,
surface_type => S_TYPE_INTERNALVOID, surface_type => S_TYPE_INTERNAL + S_TYPE_VOID,
), @{intersection_ex( ), @{intersection_ex(
[ map $_->p, @$group ], [ map $_->p, @$group ],
[ map @$_, @$to_bridge ], [ map @$_, @$to_bridge ],
@ -1376,8 +1376,7 @@ PrintObject::combine_infill()
// Save void surfaces. // Save void surfaces.
layerm->fill_surfaces.append( layerm->fill_surfaces.append(
intersection_ex(internal, intersection_with_clearance), intersection_ex(internal, intersection_with_clearance),
stInternalVoid (stInternal | stVoid));
);
} }
} }
} }
@ -1481,7 +1480,7 @@ PrintObject::discover_horizontal_shells()
if (region_config.solid_infill_every_layers() > 0 && region_config.fill_density() > 0 if (region_config.solid_infill_every_layers() > 0 && region_config.fill_density() > 0
&& (i % region_config.solid_infill_every_layers()) == 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)) for (auto* s : layerm->fill_surfaces.filter_by_type(stInternal))
s->surface_type = type; s->surface_type = type;
} }
@ -1494,7 +1493,7 @@ void
PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id) PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id)
{ {
const auto& region_config = layerm->region()->config; 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 // find slices of current type for current layer
// use slices instead of fill_surfaces because they also include the perimeter area // 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 // which needs to be propagated in shells; we need to grow slices like we did for
@ -1535,7 +1534,7 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz
{ {
const auto& region_config = layerm->region()->config; const auto& region_config = layerm->region()->config;
for (int n = (type == stTop ? i-1 : i+1); std::abs(n-int(i)) < solid_layers; (type == stTop ? n-- : n++)) { for (int n = ((type & stTop) != 0 ? i-1 : i+1); std::abs(n-int(i)) < solid_layers; ((type & stTop) != 0 ? n-- : n++)) {
if (n < 0 || static_cast<size_t>(n) >= this->layer_count()) continue; if (n < 0 || static_cast<size_t>(n) >= this->layer_count()) continue;
LayerRegion* neighbor_layerm { this->get_layer(n)->get_region(region_id) }; LayerRegion* neighbor_layerm { this->get_layer(n)->get_region(region_id) };
@ -1546,7 +1545,7 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz
// intersections have contours and holes // intersections have contours and holes
Polygons new_internal_solid = intersection( Polygons new_internal_solid = intersection(
solid, solid,
to_polygons(neighbor_fill_surfaces.filter_by_type({stInternal, stInternalSolid})), to_polygons(neighbor_fill_surfaces.filter_by_type({stInternal, (stInternal | stSolid)})),
true true
); );
if (new_internal_solid.empty()) { if (new_internal_solid.empty()) {
@ -1624,25 +1623,25 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz
// internal-solid are the union of the existing internal-solid surfaces // internal-solid are the union of the existing internal-solid surfaces
// and new ones // 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); polygons_append(tmp, new_internal_solid);
const auto internal_solid = union_ex(tmp); const ExPolygons internal_solid = union_ex(tmp);
// subtract intersections from layer surfaces to get resulting internal surfaces // subtract intersections from layer surfaces to get resulting internal surfaces
tmp = to_polygons(neighbor_fill_surfaces.filter_by_type(stInternal)); tmp = to_polygons(neighbor_fill_surfaces.filter_by_type(stInternal));
const auto internal = diff_ex(tmp, to_polygons(internal_solid), 1); const ExPolygons internal = diff_ex(tmp, to_polygons(internal_solid), 1);
// assign resulting internal surfaces to layer // assign resulting internal surfaces to layer
neighbor_layerm->fill_surfaces.clear(); neighbor_layerm->fill_surfaces.clear();
neighbor_layerm->fill_surfaces.append(internal, stInternal); neighbor_layerm->fill_surfaces.append(internal, stInternal);
// assign new internal-solid surfaces to layer // 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 // assign top and bottom surfaces to layer
SurfaceCollection tmp_coll; SurfaceCollection tmp_coll;
for (const auto& s : neighbor_fill_surfaces.surfaces) for (const Surface& s : neighbor_fill_surfaces.surfaces)
if (s.surface_type == stTop || s.is_bottom()) if (s.is_top() || s.is_bottom())
tmp_coll.append(s); tmp_coll.append(s);
for (auto s : tmp_coll.group()) { for (auto s : tmp_coll.group()) {
@ -1720,7 +1719,7 @@ PrintObject::clip_fill_surfaces()
Polygons lower_layer_internal_surfaces; Polygons lower_layer_internal_surfaces;
for (const auto* layerm : lower_layer->regions) for (const auto* layerm : lower_layer->regions)
polygons_append(lower_layer_internal_surfaces, to_polygons( polygons_append(lower_layer_internal_surfaces, to_polygons(
layerm->fill_surfaces.filter_by_type({ stInternal, stInternalVoid }) layerm->fill_surfaces.filter_by_type({ stInternal, (stInternal | stVoid) })
)); ));
upper_internal = intersection(overhangs, lower_layer_internal_surfaces); upper_internal = intersection(overhangs, lower_layer_internal_surfaces);
} }
@ -1730,10 +1729,10 @@ PrintObject::clip_fill_surfaces()
if (layerm->region()->config.fill_density.value == 0) if (layerm->region()->config.fill_density.value == 0)
continue; continue;
Polygons internal{ to_polygons(layerm->fill_surfaces.filter_by_type({ stInternal, stInternalVoid })) }; Polygons internal{ to_polygons(layerm->fill_surfaces.filter_by_type({ stInternal, (stInternal | stVoid) })) };
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(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 // 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 // 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) { if (1) {
// Remove the entire bridges and only support the unsupported edges. // Remove the entire bridges and only support the unsupported edges.
ExPolygons bridges; 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) { if (surface->bridge_angle != -1) {
bridges.push_back(surface->expolygon); bridges.push_back(surface->expolygon);
} }

View File

@ -16,42 +16,37 @@ Surface::area() const
bool bool
Surface::is_solid() const Surface::is_solid() const
{ {
return this->surface_type == stTop return (this->surface_type & (stTop | stBottom | stSolid | stBridge)) != 0;
|| this->surface_type == stBottom
|| this->surface_type == stBottomBridge
|| this->surface_type == stInternalSolid
|| this->surface_type == stInternalBridge;
} }
bool bool
Surface::is_external() const Surface::is_external() const
{ {
return this->surface_type == stTop return is_top() || is_bottom();
|| this->surface_type == stBottom
|| this->surface_type == stBottomBridge;
} }
bool bool
Surface::is_internal() const Surface::is_internal() const
{ {
return this->surface_type == stInternal return (this->surface_type & stInternal) != 0;
|| this->surface_type == stInternalBridge
|| this->surface_type == stInternalSolid
|| this->surface_type == stInternalVoid;
} }
bool bool
Surface::is_bottom() const Surface::is_bottom() const
{ {
return this->surface_type == stBottom return (this->surface_type & stBottom) != 0;
|| this->surface_type == stBottomBridge; }
bool
Surface::is_top() const
{
return (this->surface_type & stTop) != 0;
} }
bool bool
Surface::is_bridge() const Surface::is_bridge() const
{ {
return this->surface_type == stBottomBridge return (this->surface_type & stBridge) != 0;
|| this->surface_type == stInternalBridge;
} }
} }

View File

@ -8,15 +8,22 @@ namespace Slic3r {
/// Surface type enumerations. /// 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 /// As it is very unlikely that there will be more than 32 or 64 of these surface types, pack into a flag
enum SurfaceType { enum SurfaceType : uint16_t {
stTop = 0b1, stTop = 0b1, /// stTop: it has nothing just on top of it
stBottom = 0b10, stBottom = 0b10, /// stBottom: it's a surface with nothing just under it (or the base plate, or a support)
stBottomBridge = 0b100, stInternal = 0b100, /// stInternal: not top nor bottom
stInternal = 0b1000, stSolid = 0b1000, /// stSolid: modify the stInternal to say it should be at 100% infill
stInternalSolid = 0b10000, stBridge = 0b10000, /// stBridge: modify stBottom or stInternal to say it should be extruded as a bridge
stInternalBridge = 0b100000, stVoid = 0b100000 /// stVoid: modify stInternal to say it should be at 0% infill
stInternalVoid = 0b1000000
}; };
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;}
class Surface class Surface
{ {
@ -37,6 +44,7 @@ class Surface
bool is_solid() const; bool is_solid() const;
bool is_external() const; bool is_external() const;
bool is_internal() const; bool is_internal() const;
bool is_top() const;
bool is_bottom() const; bool is_bottom() const;
bool is_bridge() const; bool is_bridge() const;
}; };

View File

@ -93,24 +93,26 @@ template bool SurfaceCollection::any_bottom_contains<Polyline>(const Polyline &i
SurfacesPtr SurfacesPtr
SurfaceCollection::filter_by_type(std::initializer_list<SurfaceType> types) SurfaceCollection::filter_by_type(std::initializer_list<SurfaceType> types)
{ {
size_t n {0};
for (const auto& t : types)
n |= t;
SurfacesPtr ss; SurfacesPtr ss;
for (auto& s : this->surfaces) for (Surface& s : this->surfaces)
if ((s.surface_type & n) == s.surface_type) ss.push_back(&s); for (const SurfaceType& t : types)
if (s.surface_type == t) {
ss.push_back(&s);
break;
}
return ss; return ss;
} }
SurfacesConstPtr SurfacesConstPtr
SurfaceCollection::filter_by_type(std::initializer_list<SurfaceType> types) const SurfaceCollection::filter_by_type(std::initializer_list<SurfaceType> types) const
{ {
size_t n {0};
for (const auto& t : types)
n |= t;
SurfacesConstPtr ss; SurfacesConstPtr ss;
for (auto& s : this->surfaces) for (const Surface& s : this->surfaces)
if ((s.surface_type & n) == s.surface_type) ss.push_back(&s); for (const SurfaceType& t : types)
if (s.surface_type == t) {
ss.push_back(&s);
break;
}
return ss; return ss;
} }
@ -200,12 +202,23 @@ SurfaceCollection::keep_type(const SurfaceType type)
void void
SurfaceCollection::keep_types(const SurfaceType *types, size_t ntypes) SurfaceCollection::keep_types(const SurfaceType *types, size_t ntypes)
{ {
size_t n {0}; size_t j = 0;
for (size_t i = 0; i < ntypes; ++i) for (size_t i = 0; i < surfaces.size(); ++ i) {
n |= types[i]; // form bitmask. bool keep = false;
// Use stl remove_if to remove for (int k = 0; k < ntypes; ++ k) {
auto ptr = std::remove_if(surfaces.begin(), surfaces.end(),[n] (const Surface& s) { return (s.surface_type & n) != s.surface_type; }); if (surfaces[i].surface_type == types[k]) {
surfaces.erase(ptr, surfaces.cend()); keep = true;
break;
}
}
if (keep) {
if (j < i)
std::swap(surfaces[i], surfaces[j]);
++ j;
}
}
if (j < surfaces.size())
surfaces.erase(surfaces.begin() + j, surfaces.end());
} }
void void

View File

@ -19,6 +19,7 @@
bool is_external() const; bool is_external() const;
bool is_internal() const; bool is_internal() const;
bool is_bottom() const; bool is_bottom() const;
bool is_top() const;
bool is_bridge() const; bool is_bridge() const;
%{ %{
@ -104,11 +105,10 @@ _constant()
ALIAS: ALIAS:
S_TYPE_TOP = stTop S_TYPE_TOP = stTop
S_TYPE_BOTTOM = stBottom S_TYPE_BOTTOM = stBottom
S_TYPE_BOTTOMBRIDGE = stBottomBridge
S_TYPE_INTERNAL = stInternal S_TYPE_INTERNAL = stInternal
S_TYPE_INTERNALSOLID = stInternalSolid S_TYPE_SOLID = stSolid
S_TYPE_INTERNALBRIDGE = stInternalBridge S_TYPE_BRIDGE = stBridge
S_TYPE_INTERNALVOID = stInternalVoid S_TYPE_VOID = stVoid
PROTOTYPE: PROTOTYPE:
CODE: CODE:
RETVAL = ix; RETVAL = ix;