Skip to content

Commit

Permalink
New parameter "Slicing Mode" for supporting 3DLabPrint airplane models.
Browse files Browse the repository at this point in the history
S3D's strategy for merging self intersecting models is "Even / Odd"
which PrusaSlicer now supports as an alternative to "Positive" rule.
Also added a "Close Holes" option to fill in all internal structures.
3D-Labprint Models aren't sliceable (till years) #3062 #3708
  • Loading branch information
bubnikv committed Jun 1, 2021
1 parent df87f1b commit 20ba7c0
Show file tree
Hide file tree
Showing 12 changed files with 96 additions and 33 deletions.
13 changes: 7 additions & 6 deletions src/libslic3r/ClipperUtils.cpp
Expand Up @@ -487,8 +487,8 @@ Slic3r::Polygons union_(const Slic3r::Polygons &subject, const Slic3r::Polygons
{ return _clipper(ClipperLib::ctUnion, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(subject2), ApplySafetyOffset::No); }

template <typename TSubject, typename TClip>
static ExPolygons _clipper_ex(ClipperLib::ClipType clipType, TSubject &&subject, TClip &&clip, ApplySafetyOffset do_safety_offset)
{ return PolyTreeToExPolygons(_clipper_do_polytree2(clipType, std::forward<TSubject>(subject), std::forward<TClip>(clip), ClipperLib::pftNonZero, do_safety_offset)); }
static ExPolygons _clipper_ex(ClipperLib::ClipType clipType, TSubject &&subject, TClip &&clip, ApplySafetyOffset do_safety_offset, ClipperLib::PolyFillType fill_type = ClipperLib::pftPositive)
{ return PolyTreeToExPolygons(_clipper_do_polytree2(clipType, std::forward<TSubject>(subject), std::forward<TClip>(clip), fill_type, do_safety_offset)); }

Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
{ return _clipper_ex(ClipperLib::ctDifference, ClipperUtils::PolygonsProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
Expand Down Expand Up @@ -531,11 +531,12 @@ Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesProvider(subject), ClipperUtils::SurfacesProvider(clip), do_safety_offset); }
Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset)
{ return _clipper_ex(ClipperLib::ctIntersection, ClipperUtils::SurfacesPtrProvider(subject), ClipperUtils::ExPolygonsProvider(clip), do_safety_offset); }
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject)
{ return _clipper_ex(ClipperLib::ctUnion, ClipperUtils::PolygonsProvider(subject), ClipperUtils::EmptyPathsProvider(), ApplySafetyOffset::No); }
Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons& subject)
// May be used to "heal" unusual models (3DLabPrints etc.) by providing fill_type (pftEvenOdd, pftNonZero, pftPositive, pftNegative).
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, ClipperLib::PolyFillType fill_type)
{ return _clipper_ex(ClipperLib::ctUnion, ClipperUtils::PolygonsProvider(subject), ClipperUtils::EmptyPathsProvider(), ApplySafetyOffset::No, fill_type); }
Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject)
{ return PolyTreeToExPolygons(_clipper_do_polytree2(ClipperLib::ctUnion, ClipperUtils::ExPolygonsProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); }
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces& subject)
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject)
{ return PolyTreeToExPolygons(_clipper_do_polytree2(ClipperLib::ctUnion, ClipperUtils::SurfacesProvider(subject), ClipperUtils::EmptyPathsProvider(), ClipperLib::pftNonZero)); }

template<typename PathsProvider1, typename PathsProvider2>
Expand Down
3 changes: 2 additions & 1 deletion src/libslic3r/ClipperUtils.hpp
Expand Up @@ -356,7 +356,8 @@ inline Slic3r::Lines intersection_ln(const Slic3r::Line &subject, const Slic3r::
Slic3r::Polygons union_(const Slic3r::Polygons &subject);
Slic3r::Polygons union_(const Slic3r::ExPolygons &subject);
Slic3r::Polygons union_(const Slic3r::Polygons &subject, const Slic3r::Polygons &subject2);
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject);
// May be used to "heal" unusual models (3DLabPrints etc.) by providing fill_type (pftEvenOdd, pftNonZero, pftPositive, pftNegative).
Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, ClipperLib::PolyFillType fill_type = ClipperLib::pftPositive);
Slic3r::ExPolygons union_ex(const Slic3r::ExPolygons &subject);
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject);

Expand Down
3 changes: 2 additions & 1 deletion src/libslic3r/Preset.cpp
Expand Up @@ -416,7 +416,7 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config)
const std::vector<std::string>& Preset::print_options()
{
static std::vector<std::string> s_opts {
"layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius",
"layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "slicing_mode",
"top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness",
"extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs",
"seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern",
Expand Down Expand Up @@ -543,6 +543,7 @@ const std::vector<std::string>& Preset::sla_print_options()
"support_points_density_relative",
"support_points_minimal_distance",
"slice_closing_radius",
"slicing_mode",
"pad_enable",
"pad_wall_thickness",
"pad_wall_height",
Expand Down
41 changes: 31 additions & 10 deletions src/libslic3r/PrintConfig.cpp
Expand Up @@ -116,6 +116,13 @@ static t_config_enum_values s_keys_map_IroningType {
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(IroningType)

static t_config_enum_values s_keys_map_SlicingMode {
{ "regular", int(SlicingMode::Regular) },
{ "even_odd", int(SlicingMode::EvenOdd) },
{ "close_holes", int(SlicingMode::CloseHoles) }
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SlicingMode)

static t_config_enum_values s_keys_map_SupportMaterialPattern {
{ "rectilinear", smpRectilinear },
{ "rectilinear-grid", smpRectilinearGrid },
Expand Down Expand Up @@ -235,16 +242,6 @@ void PrintConfigDef::init_common_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(200.0));

def = this->add("slice_closing_radius", coFloat);
def->label = L("Slice gap closing radius");
def->category = L("Advanced");
def->tooltip = L("Cracks smaller than 2x gap closing radius are being filled during the triangle mesh slicing. "
"The gap closing operation may reduce the final print resolution, therefore it is advisable to keep the value reasonably low.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0.049));

def = this->add("print_host", coString);
def->label = L("Hostname, IP or URL");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
Expand Down Expand Up @@ -2359,6 +2356,30 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));

def = this->add("slice_closing_radius", coFloat);
def->label = L("Slice gap closing radius");
def->category = L("Advanced");
def->tooltip = L("Cracks smaller than 2x gap closing radius are being filled during the triangle mesh slicing. "
"The gap closing operation may reduce the final print resolution, therefore it is advisable to keep the value reasonably low.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0.049));

def = this->add("slicing_mode", coEnum);
def->label = L("Slicing Mode");
def->category = L("Advanced");
def->tooltip = L("Use \"Even / Odd\" for 3DLabPrint airplane models. Use \"Close holes\" to close all holes in the model.");
def->enum_keys_map = &ConfigOptionEnum<SlicingMode>::get_enum_values();
def->enum_values.push_back("regular");
def->enum_values.push_back("even_odd");
def->enum_values.push_back("close_holes");
def->enum_labels.push_back(L("Regular"));
def->enum_labels.push_back(L("Even / Odd"));
def->enum_labels.push_back(L("Close holes"));
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<SlicingMode>(SlicingMode::Regular));

def = this->add("support_material", coBool);
def->label = L("Generate support material");
def->category = L("Support material");
Expand Down
13 changes: 13 additions & 0 deletions src/libslic3r/PrintConfig.hpp
Expand Up @@ -69,6 +69,16 @@ enum class IroningType {
Count,
};

enum class SlicingMode
{
// Regular, applying ClipperLib::pftPositive rule when creating ExPolygons.
Regular,
// Compatible with 3DLabPrint models, applying ClipperLib::pftEvenOdd rule when creating ExPolygons.
EvenOdd,
// Orienting all contours CCW, thus closing all holes.
CloseHoles,
};

enum SupportMaterialPattern {
smpRectilinear, smpRectilinearGrid, smpHoneycomb,
};
Expand Down Expand Up @@ -123,6 +133,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(FuzzySkinType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(InfillPattern)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(IroningType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SlicingMode)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SupportMaterialPattern)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SupportMaterialStyle)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SupportMaterialInterfacePattern)
Expand Down Expand Up @@ -453,6 +464,7 @@ PRINT_CONFIG_CLASS_DEFINE(
// ((ConfigOptionFloat, seam_preferred_direction))
// ((ConfigOptionFloat, seam_preferred_direction_jitter))
((ConfigOptionFloat, slice_closing_radius))
((ConfigOptionEnum<SlicingMode>, slicing_mode))
((ConfigOptionBool, support_material))
// Automatic supports (generated based on support_material_threshold).
((ConfigOptionBool, support_material_auto))
Expand Down Expand Up @@ -758,6 +770,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, faded_layers))/*= 10*/

((ConfigOptionFloat, slice_closing_radius))
((ConfigOptionEnum<SlicingMode>, slicing_mode))

// Enabling or disabling support creation
((ConfigOptionBool, supports_enable))
Expand Down
3 changes: 2 additions & 1 deletion src/libslic3r/PrintObject.cpp
Expand Up @@ -525,7 +525,8 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "mmu_segmented_region_max_width"
|| opt_key == "raft_layers"
|| opt_key == "raft_contact_distance"
|| opt_key == "slice_closing_radius") {
|| opt_key == "slice_closing_radius"
|| opt_key == "slicing_mode") {
steps.emplace_back(posSlice);
} else if (
opt_key == "clip_multipart_objects"
Expand Down
9 changes: 8 additions & 1 deletion src/libslic3r/PrintObjectSlice.cpp
Expand Up @@ -169,6 +169,14 @@ static std::vector<VolumeSlices> slice_volumes_inner(
params_base.trafo = object_trafo;
params_base.resolution = print_config.resolution.value;

switch (print_object_config.slicing_mode.value) {
case SlicingMode::Regular: params_base.mode = MeshSlicingParams::SlicingMode::Regular; break;
case SlicingMode::EvenOdd: params_base.mode = MeshSlicingParams::SlicingMode::EvenOdd; break;
case SlicingMode::CloseHoles: params_base.mode = MeshSlicingParams::SlicingMode::Positive; break;
}

params_base.mode_below = params_base.mode;

const auto extra_offset = std::max(0.f, float(print_object_config.xy_size_compensation.value));

for (const ModelVolume *model_volume : model_volumes)
Expand All @@ -184,7 +192,6 @@ static std::vector<VolumeSlices> slice_volumes_inner(
params.mode = MeshSlicingParams::SlicingMode::PositiveLargestContour;
// Slice the bottom layers with SlicingMode::Regular.
// This needs to be in sync with LayerRegion::make_perimeters() spiral_vase!
params.mode_below = MeshSlicingParams::SlicingMode::Regular;
const PrintRegionConfig &region_config = it->region->config();
params.slicing_mode_normal_below_layer = size_t(region_config.bottom_solid_layers.value);
for (; params.slicing_mode_normal_below_layer < zs.size() && zs[params.slicing_mode_normal_below_layer] < region_config.bottom_solid_min_thickness - EPSILON;
Expand Down
4 changes: 2 additions & 2 deletions src/libslic3r/SLAPrint.cpp
Expand Up @@ -930,10 +930,10 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|| opt_key == "support_object_elevation"
|| opt_key == "pad_around_object"
|| opt_key == "pad_around_object_everywhere"
|| opt_key == "slice_closing_radius") {
|| opt_key == "slice_closing_radius"
|| opt_key == "slicing_mode") {
steps.emplace_back(slaposObjectSlice);
} else if (

opt_key == "support_points_density_relative"
|| opt_key == "support_points_minimal_distance") {
steps.emplace_back(slaposSupportPoints);
Expand Down
13 changes: 10 additions & 3 deletions src/libslic3r/SLAPrintSteps.cpp
Expand Up @@ -472,11 +472,17 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
po.m_model_height_levels.emplace_back(it->slice_level());

po.m_model_slices.clear();
float closing_r = float(po.config().slice_closing_radius.value);
MeshSlicingParamsEx params;
params.closing_radius = float(po.config().slice_closing_radius.value);
switch (po.config().slicing_mode.value) {
case SlicingMode::Regular: params.mode = MeshSlicingParams::SlicingMode::Regular; break;
case SlicingMode::EvenOdd: params.mode = MeshSlicingParams::SlicingMode::EvenOdd; break;
case SlicingMode::CloseHoles: params.mode = MeshSlicingParams::SlicingMode::Positive; break;
}
auto thr = [this]() { m_print->throw_if_canceled(); };
auto &slice_grid = po.m_model_height_levels;
assert(mesh.has_shared_vertices());
po.m_model_slices = slice_mesh_ex(mesh.its, slice_grid, closing_r, thr);
po.m_model_slices = slice_mesh_ex(mesh.its, slice_grid, params, thr);

sla::Interior *interior = po.m_hollowing_data ?
po.m_hollowing_data->interior.get() :
Expand All @@ -486,7 +492,8 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
TriangleMesh interiormesh = sla::get_mesh(*interior);
interiormesh.repaired = false;
interiormesh.repair(true);
std::vector<ExPolygons> interior_slices = slice_mesh_ex(interiormesh.its, slice_grid, closing_r, thr);
params.mode = MeshSlicingParams::SlicingMode::Regular;
std::vector<ExPolygons> interior_slices = slice_mesh_ex(interiormesh.its, slice_grid, params, thr);

sla::ccr::for_each(size_t(0), interior_slices.size(),
[&po, &interior_slices] (size_t i) {
Expand Down
18 changes: 11 additions & 7 deletions src/libslic3r/TriangleMeshSlicer.cpp
Expand Up @@ -967,7 +967,7 @@ static ExPolygons make_expolygons_simple(std::vector<IntersectionLine> &lines)
return slices;
}

static void make_expolygons(const Polygons &loops, const float closing_radius, const float extra_offset, ExPolygons* slices)
static void make_expolygons(const Polygons &loops, const float closing_radius, const float extra_offset, ClipperLib::PolyFillType fill_type, ExPolygons* slices)
{
/*
Input loops are not suitable for evenodd nor nonzero fill types, as we might get
Expand Down Expand Up @@ -1049,10 +1049,10 @@ static void make_expolygons(const Polygons &loops, const float closing_radius, c

// append to the supplied collection
expolygons_append(*slices,
offset_out > 0 && offset_in < 0 ? offset2_ex(union_ex(loops), offset_out, offset_in) :
offset_out > 0 ? offset_ex(union_ex(loops), offset_out) :
offset_in < 0 ? offset_ex(union_ex(loops), offset_in) :
union_ex(loops));
offset_out > 0 && offset_in < 0 ? offset2_ex(union_ex(loops, fill_type), offset_out, offset_in) :
offset_out > 0 ? offset_ex(union_ex(loops, fill_type), offset_out) :
offset_in < 0 ? offset_ex(union_ex(loops, fill_type), offset_in) :
union_ex(loops, fill_type));
}

std::vector<Polygons> slice_mesh(
Expand Down Expand Up @@ -1175,9 +1175,13 @@ std::vector<ExPolygons> slice_mesh_ex(
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
throw_on_cancel();
ExPolygons &expolygons = layers[layer_id];
Slic3r::make_expolygons(layers_p[layer_id], params.closing_radius, params.extra_offset, &expolygons);
//FIXME simplify
const auto this_mode = layer_id < params.slicing_mode_normal_below_layer ? params.mode_below : params.mode;
Slic3r::make_expolygons(
layers_p[layer_id], params.closing_radius, params.extra_offset,
this_mode == MeshSlicingParams::SlicingMode::EvenOdd ? ClipperLib::pftEvenOdd :
this_mode == MeshSlicingParams::SlicingMode::PositiveLargestContour ? ClipperLib::pftNonZero : ClipperLib::pftPositive,
&expolygons);
//FIXME simplify
if (this_mode == MeshSlicingParams::SlicingMode::PositiveLargestContour)
keep_largest_contour_only(expolygons);
if (resolution != 0.)
Expand Down
7 changes: 6 additions & 1 deletion src/libslic3r/TriangleMeshSlicer.hpp
Expand Up @@ -12,8 +12,13 @@ struct MeshSlicingParams
{
enum class SlicingMode : uint32_t {
// Regular slicing, maintain all contours and their orientation.
// slice_mesh_ex() applies ClipperLib::pftPositive rule to the result of slice_mesh().
Regular,
// Maintain all contours, orient all contours CCW, therefore all holes are being closed.
// For slicing 3DLabPrints plane models (aka to be compatible with S3D default strategy).
// slice_mesh_ex() applies ClipperLib::pftEvenOdd rule. slice_mesh() slices EvenOdd as Regular.
EvenOdd,
// Maintain all contours, orient all contours CCW.
// slice_mesh_ex() applies ClipperLib::pftPositive rule, thus holes will be closed.
Positive,
// Orient all contours CCW and keep only the contour with the largest area.
// This mode is useful for slicing complex objects in vase mode.
Expand Down
2 changes: 2 additions & 0 deletions src/slic3r/GUI/Tab.cpp
Expand Up @@ -1610,6 +1610,7 @@ void TabPrint::build()

optgroup = page->new_optgroup(L("Slicing"));
optgroup->append_single_option_line("slice_closing_radius");
optgroup->append_single_option_line("slicing_mode");
optgroup->append_single_option_line("resolution");
optgroup->append_single_option_line("xy_size_compensation");
optgroup->append_single_option_line("elefant_foot_compensation", "elephant-foot-compensation_114487");
Expand Down Expand Up @@ -4318,6 +4319,7 @@ void TabSLAPrint::build()
page = add_options_page(L("Advanced"), "wrench");
optgroup = page->new_optgroup(L("Slicing"));
optgroup->append_single_option_line("slice_closing_radius");
optgroup->append_single_option_line("slicing_mode");

page = add_options_page(L("Output options"), "output+page_white");
optgroup = page->new_optgroup(L("Output file"));
Expand Down

0 comments on commit 20ba7c0

Please sign in to comment.