|
|
|
|
@@ -2,6 +2,7 @@
|
|
|
|
|
#include "BoundingBox.hpp"
|
|
|
|
|
#include "ClipperUtils.hpp"
|
|
|
|
|
#include "Geometry.hpp"
|
|
|
|
|
#include "SVG.hpp"
|
|
|
|
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
|
|
|
|
|
|
@@ -358,6 +359,167 @@ PrintObject::process_external_surfaces()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PrintObject::discover_vertical_shells()
|
|
|
|
|
{
|
|
|
|
|
for (size_t idx_region = 0; idx_region < this->_print->regions.size(); ++ idx_region) {
|
|
|
|
|
for (size_t idx_layer = 0; idx_layer < this->layers.size(); ++ idx_layer) {
|
|
|
|
|
Layer* layer = this->layers[idx_layer];
|
|
|
|
|
LayerRegion* layerm = layer->get_region(idx_region);
|
|
|
|
|
// Find a union of perimeters below / above this surface to guarantee a minimum shell thickness.
|
|
|
|
|
Polygons shell;
|
|
|
|
|
ExPolygons shell_ex;
|
|
|
|
|
if (1)
|
|
|
|
|
{
|
|
|
|
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
|
|
|
|
{
|
|
|
|
|
static size_t idx = 0;
|
|
|
|
|
char path_cummulative[2048];
|
|
|
|
|
sprintf(path_cummulative, "out\\discover_vertical_shells-perimeters-before-union-run%d.svg", idx);
|
|
|
|
|
SVG svg_cummulative(path_cummulative, this->bounding_box());
|
|
|
|
|
for (int n = (int)idx_layer - layerm->region()->config.bottom_solid_layers + 1; n < (int)idx_layer + layerm->region()->config.top_solid_layers; ++ n) {
|
|
|
|
|
if (n < 0 || n >= (int)this->layers.size())
|
|
|
|
|
continue;
|
|
|
|
|
ExPolygons &expolys = this->layers[n]->perimeter_expolygons;
|
|
|
|
|
for (size_t i = 0; i < expolys.size(); ++ i) {
|
|
|
|
|
char path[2048];
|
|
|
|
|
sprintf(path, "out\\discover_vertical_shells-perimeters-before-union-run%d-layer%d-expoly%d.svg", idx, n, i);
|
|
|
|
|
SVG svg(path, get_extents(expolys[i]));
|
|
|
|
|
svg.draw(expolys[i]);
|
|
|
|
|
svg.draw_outline(expolys[i].contour, "black", scale_(0.05));
|
|
|
|
|
svg.draw_outline(expolys[i].holes, "blue", scale_(0.05));
|
|
|
|
|
svg.Close();
|
|
|
|
|
|
|
|
|
|
svg_cummulative.draw(expolys[i]);
|
|
|
|
|
svg_cummulative.draw_outline(expolys[i].contour, "black", scale_(0.05));
|
|
|
|
|
svg_cummulative.draw_outline(expolys[i].holes, "blue", scale_(0.05));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++ idx;
|
|
|
|
|
}
|
|
|
|
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
|
|
|
|
for (int n = (int)idx_layer - layerm->region()->config.bottom_solid_layers + 1; n < (int)idx_layer + layerm->region()->config.top_solid_layers; ++ n) {
|
|
|
|
|
if (n < 0 || n >= (int)this->layers.size())
|
|
|
|
|
continue;
|
|
|
|
|
ExPolygons &expolys = this->layers[n]->perimeter_expolygons;
|
|
|
|
|
for (size_t i = 0; i < expolys.size(); ++ i) {
|
|
|
|
|
shell.push_back(expolys[i].contour);
|
|
|
|
|
shell.insert(shell.end(), expolys[i].holes.begin(), expolys[i].holes.end());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
|
|
|
|
{
|
|
|
|
|
static size_t idx = 0;
|
|
|
|
|
char path[2048];
|
|
|
|
|
sprintf(path, "out\\discover_vertical_shells-perimeters-before-union-%d.svg", idx ++);
|
|
|
|
|
SVG svg(path, get_extents(shell));
|
|
|
|
|
svg.draw(shell);
|
|
|
|
|
svg.draw_outline(shell, "black", scale_(0.05));
|
|
|
|
|
svg.Close();
|
|
|
|
|
}
|
|
|
|
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
|
|
|
|
shell = union_(shell, true);
|
|
|
|
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
|
|
|
|
shell_ex = union_ex(shell, true);
|
|
|
|
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
|
|
|
|
{
|
|
|
|
|
static size_t idx = 0;
|
|
|
|
|
char path[2048];
|
|
|
|
|
sprintf(path, "out\\discover_vertical_shells-perimeters-after-union-%d.svg", idx ++);
|
|
|
|
|
SVG svg(path, get_extents(shell));
|
|
|
|
|
svg.draw(shell_ex);
|
|
|
|
|
svg.draw_outline(shell_ex, "black", "blue", scale_(0.05));
|
|
|
|
|
svg.Close();
|
|
|
|
|
}
|
|
|
|
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
|
|
|
|
|
|
|
|
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
|
|
|
|
{
|
|
|
|
|
static size_t idx = 0;
|
|
|
|
|
char path[2048];
|
|
|
|
|
sprintf(path, "out\\discover_vertical_shells-internal-wshell-%d.svg", idx ++);
|
|
|
|
|
SVG svg(path, get_extents(shell));
|
|
|
|
|
svg.draw(layerm->fill_surfaces.filter_by_type(stInternal), "yellow", 0.5);
|
|
|
|
|
svg.draw_outline(layerm->fill_surfaces.filter_by_type(stInternal), "black", "blue", scale_(0.05));
|
|
|
|
|
svg.draw(shell_ex, "blue", 0.5);
|
|
|
|
|
svg.draw_outline(shell_ex, "black", "blue", scale_(0.05));
|
|
|
|
|
svg.Close();
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
static size_t idx = 0;
|
|
|
|
|
char path[2048];
|
|
|
|
|
sprintf(path, "out\\discover_vertical_shells-internalvoid-wshell-%d.svg", idx ++);
|
|
|
|
|
SVG svg(path, get_extents(shell));
|
|
|
|
|
svg.draw(layerm->fill_surfaces.filter_by_type(stInternalVoid), "yellow", 0.5);
|
|
|
|
|
svg.draw_outline(layerm->fill_surfaces.filter_by_type(stInternalVoid), "black", "blue", scale_(0.05));
|
|
|
|
|
svg.draw(shell_ex, "blue", 0.5);
|
|
|
|
|
svg.draw_outline(shell_ex, "black", "blue", scale_(0.05));
|
|
|
|
|
svg.Close();
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
static size_t idx = 0;
|
|
|
|
|
char path[2048];
|
|
|
|
|
sprintf(path, "out\\discover_vertical_shells-internalvoid-wshell-%d.svg", idx ++);
|
|
|
|
|
SVG svg(path, get_extents(shell));
|
|
|
|
|
svg.draw(layerm->fill_surfaces.filter_by_type(stInternalVoid), "yellow", 0.5);
|
|
|
|
|
svg.draw_outline(layerm->fill_surfaces.filter_by_type(stInternalVoid), "black", "blue", scale_(0.05));
|
|
|
|
|
svg.draw(shell_ex, "blue", 0.5);
|
|
|
|
|
svg.draw_outline(shell_ex, "black", "blue", scale_(0.05));
|
|
|
|
|
svg.Close();
|
|
|
|
|
}
|
|
|
|
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
|
|
|
|
|
|
|
|
|
// Trim the internal & internalvoid by the $shell.
|
|
|
|
|
Slic3r::ExPolygons new_internal = diff_ex(
|
|
|
|
|
to_polygons(layerm->fill_surfaces.filter_by_type(stInternal)),
|
|
|
|
|
shell,
|
|
|
|
|
false
|
|
|
|
|
);
|
|
|
|
|
Slic3r::ExPolygons new_internal_void = diff_ex(
|
|
|
|
|
to_polygons(layerm->fill_surfaces.filter_by_type(stInternalVoid)),
|
|
|
|
|
shell,
|
|
|
|
|
false
|
|
|
|
|
);
|
|
|
|
|
// Add shells tstInternalVoido internal & internalvoid.
|
|
|
|
|
const SurfaceType surfaceTypesInternal[] = { stInternal, stInternalVoid };
|
|
|
|
|
Slic3r::ExPolygons new_internal_solid = intersection_ex(
|
|
|
|
|
to_polygons(layerm->fill_surfaces.filter_by_types(surfaceTypesInternal, 2)),
|
|
|
|
|
shell,
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
|
|
|
|
{
|
|
|
|
|
static size_t idx = 0;
|
|
|
|
|
char path[2048];
|
|
|
|
|
sprintf(path, "out\\discover_vertical_shells-new_internal-%d.svg", idx);
|
|
|
|
|
SVG::export_expolygons(path, get_extents(shell), new_internal, "black", "blue", scale_(0.05));
|
|
|
|
|
sprintf(path, "out\\discover_vertical_shells-new_internal_void-%d.svg", idx);
|
|
|
|
|
SVG::export_expolygons(path, get_extents(shell), new_internal_void, "black", "blue", scale_(0.05));
|
|
|
|
|
sprintf(path, "out\\discover_vertical_shells-new_internal_solid-%d.svg", idx);
|
|
|
|
|
SVG::export_expolygons(path, get_extents(shell), new_internal_solid, "black", "blue", scale_(0.05));
|
|
|
|
|
++ idx;
|
|
|
|
|
}
|
|
|
|
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
|
|
|
|
|
|
|
|
|
// Assign resulting internal surfaces to layer.
|
|
|
|
|
const SurfaceType surfaceTypesKeep[] = { stTop, stBottom, stBottomBridge, stInternalSolid };
|
|
|
|
|
layerm->fill_surfaces.keep_types(surfaceTypesKeep, sizeof(surfaceTypesKeep)/sizeof(SurfaceType));
|
|
|
|
|
layerm->fill_surfaces.append(stInternal , new_internal);
|
|
|
|
|
layerm->fill_surfaces.append(stInternalVoid , new_internal_void);
|
|
|
|
|
layerm->fill_surfaces.append(stInternalSolid, new_internal_solid);
|
|
|
|
|
|
|
|
|
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
|
|
|
|
layerm->export_region_slices_to_svg_debug("4_discover_vertical_shells");
|
|
|
|
|
layerm->export_region_fill_surfaces_to_svg_debug("4_discover_vertical_shells");
|
|
|
|
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
|
|
|
|
} // for each layer
|
|
|
|
|
} // for each region
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This method applies bridge flow to the first internal solid layer above
|
|
|
|
|
sparse infill */
|
|
|
|
|
void
|
|
|
|
|
@@ -415,6 +577,9 @@ PrintObject::bridge_over_infill()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// there's no point in bridging 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.
|
|
|
|
|
{
|
|
|
|
|
double min_width = bridge_flow.scaled_width() * 3;
|
|
|
|
|
to_bridge_pp = offset2(to_bridge_pp, -min_width, +min_width);
|
|
|
|
|
@@ -432,22 +597,17 @@ PrintObject::bridge_over_infill()
|
|
|
|
|
|
|
|
|
|
// compute the remaning internal solid surfaces as difference
|
|
|
|
|
ExPolygons not_to_bridge = diff_ex(internal_solid, to_bridge, true);
|
|
|
|
|
to_bridge = intersection_ex(to_polygons(to_bridge), internal_solid, true);
|
|
|
|
|
|
|
|
|
|
// build the new collection of fill_surfaces
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
new_surfaces.push_back(*surface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
layerm->fill_surfaces.remove_type(stInternalSolid);
|
|
|
|
|
|
|
|
|
|
for (ExPolygons::const_iterator ex = to_bridge.begin(); ex != to_bridge.end(); ++ex)
|
|
|
|
|
new_surfaces.push_back(Surface(stInternalBridge, *ex));
|
|
|
|
|
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalBridge, *ex));
|
|
|
|
|
|
|
|
|
|
for (ExPolygons::const_iterator ex = not_to_bridge.begin(); ex != not_to_bridge.end(); ++ex)
|
|
|
|
|
new_surfaces.push_back(Surface(stInternalSolid, *ex));
|
|
|
|
|
|
|
|
|
|
layerm->fill_surfaces.surfaces = new_surfaces;
|
|
|
|
|
layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, *ex));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@@ -483,6 +643,11 @@ PrintObject::bridge_over_infill()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
|
|
|
|
layerm->export_region_slices_to_svg_debug("7_bridge_over_infill");
|
|
|
|
|
layerm->export_region_fill_surfaces_to_svg_debug("7_bridge_over_infill");
|
|
|
|
|
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|