mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-18 06:55:53 +08:00
#393 don't connect now differentiate with holes & outer perimeters
but it works only for half of rectilinear2: because it go over a new polyline start always from the same direction. So it needs a difficult to do change to rectilinear2. (TODO)
This commit is contained in:
parent
2022e3fbd6
commit
89ec89e682
@ -266,7 +266,7 @@ infill_dense_algo = autosmall
|
||||
infill_every_layers = 1
|
||||
infill_extruder = 1
|
||||
infill_first = 0
|
||||
infill_not_connected = 0
|
||||
infill_connection = connected
|
||||
infill_only_where_needed = 0
|
||||
infill_overlap = 20%
|
||||
interface_shells = 0
|
||||
|
@ -104,7 +104,7 @@ group:Infill
|
||||
end_line
|
||||
line:Pattern
|
||||
setting:label_width$5:label$_:fill_pattern
|
||||
setting:label$Don't connect:infill_not_connected
|
||||
setting:width$19:label$_:infill_connection
|
||||
end_line
|
||||
line:External patterns
|
||||
setting:label_width$5:top_fill_pattern
|
||||
|
@ -241,7 +241,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||
params.density = float(0.01 * density);
|
||||
params.dont_adjust = false;
|
||||
params.fill_exactly = layerm.region()->config().enforce_full_fill_volume.getBool();
|
||||
params.dont_connect = layerm.region()->config().infill_not_connected.getBool();
|
||||
params.connection = layerm.region()->config().infill_connection.value;
|
||||
//adjust flow (to over-extrude when needed)
|
||||
float flow_percent = 1;
|
||||
if (surface.has_pos_top()) flow_percent *= layerm.region()->config().fill_top_flow_ratio.get_abs_value(1);
|
||||
|
@ -168,7 +168,7 @@ void Fill3DHoneycomb::_fill_surface_single(
|
||||
|
||||
// connect lines if needed
|
||||
if (! polylines_chained.empty()) {
|
||||
if (params.dont_connect)
|
||||
if (params.connection == icNotConnected)
|
||||
append(polylines_out, std::move(polylines_chained));
|
||||
else
|
||||
this->connect_infill(std::move(polylines_chained), expolygon, polylines_out, this->spacing, params);
|
||||
|
@ -1011,6 +1011,7 @@ void Fill::connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary_
|
||||
[&boundary](const std::pair<size_t, size_t> &contour_point) {
|
||||
return contour_point.first < boundary.size() && contour_point.second < boundary[contour_point.first].size();
|
||||
}));
|
||||
assert(boundary_data.size() == boundary_src.holes.size() + 1);
|
||||
#endif /* NDEBUG */
|
||||
}
|
||||
|
||||
@ -1065,6 +1066,20 @@ void Fill::connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary_
|
||||
}
|
||||
std::sort(connections_sorted.begin(), connections_sorted.end(), [](const ConnectionCost& l, const ConnectionCost& r) { return l.cost < r.cost; });
|
||||
|
||||
//mark point as used depends of connection parameter
|
||||
if (params.connection == icOuterShell) {
|
||||
for (auto it = boundary_data.begin() + 1; it != boundary_data.end(); ++it) {
|
||||
for (ContourPointData& pt : *it) {
|
||||
pt.point_consumed = true;
|
||||
}
|
||||
}
|
||||
} else if (params.connection == icHoles) {
|
||||
for (ContourPointData& pt : boundary_data[0]) {
|
||||
pt.point_consumed = true;
|
||||
}
|
||||
}
|
||||
assert(boundary_data.size() == boundary_src.holes.size() + 1);
|
||||
|
||||
size_t idx_chain_last = 0;
|
||||
for (ConnectionCost &connection_cost : connections_sorted) {
|
||||
const std::pair<size_t, size_t> *cp1 = &map_infill_end_point_to_boundary[connection_cost.idx_first * 2 + 1];
|
||||
|
@ -38,7 +38,7 @@ struct FillParams
|
||||
float flow_mult { 1.0f };
|
||||
|
||||
// Don't connect the fill lines around the inner perimeter.
|
||||
bool dont_connect{ false };
|
||||
InfillConnection connection{ icConnected };
|
||||
|
||||
// Don't adjust spacing to fill the space evenly.
|
||||
bool dont_adjust { true };
|
||||
|
@ -193,10 +193,11 @@ void FillGyroid::_fill_surface_single(
|
||||
polylines = chain_polylines(polylines);
|
||||
// connect lines
|
||||
size_t polylines_out_first_idx = polylines_out.size();
|
||||
if (params.dont_connect)
|
||||
if (params.connection == icNotConnected){
|
||||
append(polylines_out, std::move(polylines));
|
||||
else
|
||||
} else {
|
||||
this->connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||
}
|
||||
// new paths must be rotated back
|
||||
if (abs(infill_angle) >= EPSILON) {
|
||||
for (auto it = polylines_out.begin() + polylines_out_first_idx; it != polylines_out.end(); ++ it)
|
||||
|
@ -89,16 +89,31 @@ void FillRectilinear::_fill_surface_single(
|
||||
// offset the expolygon by max(min_spacing/2, extra)
|
||||
ExPolygon expolygon_off;
|
||||
{
|
||||
if (params.connection == icConnected || params.connection == icHoles) {
|
||||
ExPolygons expolygons_off = offset_ex(expolygon, this->_min_spacing / 2);
|
||||
if (!expolygons_off.empty()) {
|
||||
// When expanding a polygon, the number of islands could only shrink. Therefore the offset_ex shall generate exactly one expanded island for one input island.
|
||||
assert(expolygons_off.size() == 1);
|
||||
std::swap(expolygon_off, expolygons_off.front());
|
||||
}
|
||||
//restore contour for hole-only.
|
||||
if (params.connection == icHoles) {
|
||||
expolygon_off.contour = expolygon.contour;
|
||||
}
|
||||
} else if (params.connection == icOuterShell) {
|
||||
// shrink only the contour
|
||||
expolygon_off = expolygon;
|
||||
Polygons bigcontour = offset(expolygon_off.contour, this->_min_spacing / 2);
|
||||
if (!bigcontour.empty()) {
|
||||
// When expanding a polygon, the number of islands could only shrink. Therefore the offset_ex shall generate exactly one expanded island for one input island.
|
||||
assert(bigcontour.size() == 1);
|
||||
std::swap(expolygon_off.contour, bigcontour.front());
|
||||
}
|
||||
}
|
||||
}
|
||||
bool first = true;
|
||||
for (Polyline &polyline : chain_polylines(std::move(polylines))) {
|
||||
if (!params.dont_connect && !first) {
|
||||
if (params.connection != icNotConnected && !first) {
|
||||
// Try to connect the lines.
|
||||
Points &pts_end = polylines_out.back().points;
|
||||
const Point &first_point = polyline.points.front();
|
||||
|
@ -123,6 +123,8 @@ struct SegmentIntersection
|
||||
int64_t pos_p{ 0 };
|
||||
uint32_t pos_q{ 1 };
|
||||
|
||||
bool is_hole{ false };
|
||||
|
||||
coord_t pos() const {
|
||||
// Division rounds both positive and negative down to zero.
|
||||
// Add half of q for an arithmetic rounding effect.
|
||||
@ -759,6 +761,7 @@ std::vector<SegmentedIntersectionLine> FillRectilinear2::_vert_lines_for_polygon
|
||||
}
|
||||
for (size_t iContour = 0; iContour < poly_with_offset.n_contours; ++ iContour) {
|
||||
const Points &contour = poly_with_offset.contour(iContour).points;
|
||||
bool is_hole = poly_with_offset.contour(iContour).is_clockwise();
|
||||
if (contour.size() < 2)
|
||||
continue;
|
||||
// For each segment
|
||||
@ -791,6 +794,7 @@ std::vector<SegmentedIntersectionLine> FillRectilinear2::_vert_lines_for_polygon
|
||||
SegmentIntersection is;
|
||||
is.iContour = iContour;
|
||||
is.iSegment = iSegment;
|
||||
is.is_hole = is_hole;
|
||||
assert(l <= this_x);
|
||||
assert(r >= this_x);
|
||||
// Calculate the intersection position in y axis. x is known.
|
||||
@ -1064,8 +1068,10 @@ static void connect_segment_intersections_by_contours(
|
||||
itsct.next_on_contour_quality = SegmentIntersection::LinkQuality::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
if (params.dont_connect) {
|
||||
if (params.connection == icNotConnected
|
||||
|| (params.connection == icOuterShell && itsct.is_hole) // not: don't work as expected because the algo only start from top and go bottom.
|
||||
|| (params.connection == icHoles && !itsct.is_hole)
|
||||
) {
|
||||
if (itsct.prev_on_contour_quality == SegmentIntersection::LinkQuality::Valid)
|
||||
itsct.prev_on_contour_quality = SegmentIntersection::LinkQuality::TooLong;
|
||||
if (itsct.next_on_contour_quality == SegmentIntersection::LinkQuality::Valid)
|
||||
@ -2704,7 +2710,7 @@ Polylines FillTriangles::fill_surface(const Surface *surface, const FillParams &
|
||||
FillParams params2 = params;
|
||||
params2.density *= 0.333333333f;
|
||||
FillParams params3 = params2;
|
||||
params3.dont_connect = true;
|
||||
params3.connection = icNotConnected;
|
||||
Polylines polylines_out;
|
||||
if (! fill_surface_by_lines(surface, params2, 0.f, 0., polylines_out) ||
|
||||
! fill_surface_by_lines(surface, params2, float(M_PI / 3.), 0., polylines_out) ||
|
||||
@ -2720,7 +2726,7 @@ Polylines FillStars::fill_surface(const Surface *surface, const FillParams ¶
|
||||
FillParams params2 = params;
|
||||
params2.density *= 0.333333333f;
|
||||
FillParams params3 = params2;
|
||||
params3.dont_connect = true;
|
||||
params3.connection = icNotConnected;
|
||||
Polylines polylines_out;
|
||||
if (! fill_surface_by_lines(surface, params2, 0.f, 0.f, polylines_out) ||
|
||||
! fill_surface_by_lines(surface, params2, float(M_PI / 3.), 0.f, polylines_out) ||
|
||||
@ -2736,7 +2742,7 @@ Polylines FillCubic::fill_surface(const Surface *surface, const FillParams ¶
|
||||
FillParams params2 = params;
|
||||
params2.density *= 0.333333333f;
|
||||
FillParams params3 = params2;
|
||||
params3.dont_connect = true;
|
||||
params3.connection = icNotConnected;
|
||||
Polylines polylines_out;
|
||||
coordf_t dx = sqrt(0.5) * z;
|
||||
if (! fill_surface_by_lines(surface, params2, 0.f, float(dx), polylines_out) ||
|
||||
|
@ -1361,7 +1361,7 @@ static bool fill_hatching_segments_legacy(
|
||||
(distNext < distPrev) :
|
||||
intrsctn_type_next == INTERSECTION_TYPE_OTHER_VLINE_OK;
|
||||
assert(intrsctn->is_inner());
|
||||
bool skip = params.dont_connect || (link_max_length > 0 && (take_next ? distNext : distPrev) > link_max_length);
|
||||
bool skip = params.connection == icNotConnected || (link_max_length > 0 && (take_next ? distNext : distPrev) > link_max_length);
|
||||
if (skip) {
|
||||
// Just skip the connecting contour and start a new path.
|
||||
goto dont_connect;
|
||||
@ -1423,7 +1423,7 @@ static bool fill_hatching_segments_legacy(
|
||||
distance_of_segmens(poly, intrsctn->iSegment, iSegNext, false)) :
|
||||
(vert_seg_dir_valid_mask == DIR_FORWARD);
|
||||
// Skip this perimeter line?
|
||||
bool skip = params.dont_connect;
|
||||
bool skip = params.connection == icNotConnected;
|
||||
if (! skip && link_max_length > 0) {
|
||||
coordf_t link_length = measure_perimeter_segment_on_vertical_line_length(
|
||||
poly_with_offset, segs, i_vline, intrsctn->iContour, i_intersection, iNext, dir_forward);
|
||||
|
@ -1763,12 +1763,23 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("infill_not_connected", coBool);
|
||||
def = this->add("infill_connection", coEnum);
|
||||
def->label = L("Do not connect infill lines to each other");
|
||||
def->category = OptionCategory::infill;
|
||||
def->tooltip = L("If checked, the infill algorithm will try to not connect the lines near the infill. Can be useful for art or with high infill/perimeter overlap.");
|
||||
def->tooltip = L("Give to the infill algorithm if the infill needs to be connected, and on which periemters"
|
||||
" Can be useful for art or with high infill/perimeter overlap."
|
||||
" The result amy varies between infill typers.");
|
||||
def->enum_keys_map = &ConfigOptionEnum<InfillConnection>::get_enum_values();
|
||||
def->enum_values.push_back("connected");
|
||||
def->enum_values.push_back("holes");
|
||||
def->enum_values.push_back("outershell");
|
||||
def->enum_values.push_back("notconnected");
|
||||
def->enum_labels.push_back(L("Connected"));
|
||||
def->enum_labels.push_back(L("Connected to hole perimeters"));
|
||||
def->enum_labels.push_back(L("Connected to outer perimeters"));
|
||||
def->enum_labels.push_back(L("Not connected"));
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
def->set_default_value(new ConfigOptionEnum<InfillConnection>(icConnected));
|
||||
|
||||
def = this->add("infill_dense_algo", coEnum);
|
||||
def->label = L("Algorithm");
|
||||
@ -4566,6 +4577,12 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
opt_key = "z_step";
|
||||
float v = boost::lexical_cast<float>(value);
|
||||
value = boost::lexical_cast<std::string>(1/v);
|
||||
} else if (opt_key == "infill_not_connected") {
|
||||
opt_key = "infill_connection";
|
||||
if (value == "1")
|
||||
value = "notconnected";
|
||||
else
|
||||
value = "connected";
|
||||
}
|
||||
|
||||
// Ignore the following obsolete configuration keys:
|
||||
@ -4575,10 +4592,11 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
"standby_temperature", "scale", "rotate", "duplicate", "duplicate_grid",
|
||||
"start_perimeters_at_concave_points", "start_perimeters_at_non_overhang", "randomize_start",
|
||||
"seal_position", "vibration_limit", "bed_size",
|
||||
"print_center", "g0", "threads", "pressure_advance", "wipe_tower_per_color_wipe"
|
||||
"print_center", "g0", "threads", "pressure_advance", "wipe_tower_per_color_wipe",
|
||||
#ifndef HAS_PRESSURE_EQUALIZER
|
||||
, "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative"
|
||||
"max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative",
|
||||
#endif /* HAS_PRESSURE_EQUALIZER */
|
||||
"cooling"
|
||||
};
|
||||
|
||||
if (ignore.find(opt_key) != ignore.end()) {
|
||||
|
@ -98,6 +98,10 @@ enum NoPerimeterUnsupportedAlgo {
|
||||
npuaNone, npuaNoPeri, npuaBridges, npuaBridgesOverhangs, npuaFilled,
|
||||
};
|
||||
|
||||
enum InfillConnection {
|
||||
icConnected, icHoles, icOuterShell, icNotConnected,
|
||||
};
|
||||
|
||||
enum SupportZDistanceType {
|
||||
zdFilament, zdPlane, zdNone,
|
||||
};
|
||||
@ -247,6 +251,16 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<NoPerimeterUnsupp
|
||||
return keys_map;
|
||||
}
|
||||
|
||||
template<> inline const t_config_enum_values& ConfigOptionEnum<InfillConnection>::get_enum_values() {
|
||||
static const t_config_enum_values keys_map = {
|
||||
{ "connected", icConnected },
|
||||
{ "holes", icHoles },
|
||||
{ "outershell", icOuterShell },
|
||||
{ "notconnected", icNotConnected }
|
||||
};
|
||||
return keys_map;
|
||||
}
|
||||
|
||||
template<> inline const t_config_enum_values& ConfigOptionEnum<SupportZDistanceType>::get_enum_values() {
|
||||
static const t_config_enum_values keys_map = {
|
||||
{ "filament", zdFilament },
|
||||
@ -672,7 +686,7 @@ public:
|
||||
ConfigOptionInt infill_every_layers;
|
||||
ConfigOptionFloatOrPercent infill_overlap;
|
||||
ConfigOptionFloat infill_speed;
|
||||
ConfigOptionBool infill_not_connected;
|
||||
ConfigOptionEnum<InfillConnection> infill_connection;
|
||||
ConfigOptionBool infill_dense;
|
||||
ConfigOptionEnum<DenseInfillAlgo> infill_dense_algo;
|
||||
ConfigOptionBool infill_first;
|
||||
@ -763,7 +777,7 @@ protected:
|
||||
OPT_PTR(infill_overlap);
|
||||
OPT_PTR(infill_speed);
|
||||
OPT_PTR(infill_dense);
|
||||
OPT_PTR(infill_not_connected);
|
||||
OPT_PTR(infill_connection);
|
||||
OPT_PTR(infill_dense_algo);
|
||||
OPT_PTR(infill_first);
|
||||
OPT_PTR(milling_after_z);
|
||||
|
@ -1004,6 +1004,8 @@ void Choice::set_value(const boost::any& value, bool change_event)
|
||||
val = idx_from_enum_value<DenseInfillAlgo>(val);
|
||||
else if (m_opt_id.compare("no_perimeter_unsupported_algo") == 0)
|
||||
val = idx_from_enum_value<NoPerimeterUnsupportedAlgo>(val);
|
||||
else if (m_opt_id.compare("infill_connection") == 0)
|
||||
val = idx_from_enum_value<InfillConnection>(val);
|
||||
else if (m_opt_id.compare("wipe_advanced_algo") == 0)
|
||||
val = idx_from_enum_value<WipeAlgo>(val);
|
||||
else if (m_opt_id.compare("support_material_contact_distance_type") == 0)
|
||||
@ -1089,6 +1091,8 @@ boost::any& Choice::get_value()
|
||||
convert_to_enum_value<DenseInfillAlgo>(ret_enum);
|
||||
else if (m_opt_id.compare("no_perimeter_unsupported_algo") == 0)
|
||||
convert_to_enum_value<NoPerimeterUnsupportedAlgo>(ret_enum);
|
||||
else if (m_opt_id.compare("infill_connection") == 0)
|
||||
convert_to_enum_value<InfillConnection>(ret_enum);
|
||||
else if (m_opt_id.compare("wipe_advanced_algo") == 0)
|
||||
convert_to_enum_value<WipeAlgo>(ret_enum);
|
||||
else if (m_opt_id.compare("support_material_contact_distance_type") == 0)
|
||||
|
@ -205,7 +205,9 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
||||
else if (opt_key.compare("infill_dense_algo") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<DenseInfillAlgo>(boost::any_cast<DenseInfillAlgo>(value)));
|
||||
else if (opt_key.compare("no_perimeter_unsupported_algo") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<NoPerimeterUnsupportedAlgo>(boost::any_cast<NoPerimeterUnsupportedAlgo>(value)));
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<DenseInfillAlgo>(boost::any_cast<DenseInfillAlgo>(value)));
|
||||
else if (opt_key.compare("infill_connection") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<InfillConnection>(boost::any_cast<InfillConnection>(value)));
|
||||
else if (opt_key.compare("wipe_advanced_algo") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<WipeAlgo>(boost::any_cast<WipeAlgo>(value)));
|
||||
else if (opt_key.compare("support_material_contact_distance_type") == 0)
|
||||
|
@ -774,6 +774,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
||||
else if (opt_key.compare("no_perimeter_unsupported_algo") == 0){
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<NoPerimeterUnsupportedAlgo>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("infill_connection") == 0) {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<InfillConnection>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("wipe_advanced_algo") == 0){
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<WipeAlgo>>(opt_key)->value);
|
||||
}
|
||||
|
@ -523,15 +523,15 @@ const std::vector<std::string>& Preset::print_options()
|
||||
"compatible_printers", "compatible_printers_condition", "inherits",
|
||||
"infill_dense", "infill_dense_algo",
|
||||
"no_perimeter_unsupported_algo",
|
||||
"support_material_solid_first_layer"
|
||||
, "exact_last_layer_height"
|
||||
, "perimeter_loop"
|
||||
, "perimeter_loop_seam"
|
||||
, "seam_travel"
|
||||
, "infill_not_connected"
|
||||
, "first_layer_infill_speed"
|
||||
, "thin_walls_min_width"
|
||||
, "thin_walls_overlap",
|
||||
"support_material_solid_first_layer",
|
||||
"exact_last_layer_height",
|
||||
"perimeter_loop",
|
||||
"perimeter_loop_seam",
|
||||
"seam_travel",
|
||||
"infill_connection",
|
||||
"first_layer_infill_speed",
|
||||
"thin_walls_min_width",
|
||||
"thin_walls_overlap",
|
||||
"thin_walls_speed"
|
||||
, "model_precision"
|
||||
, "curve_smoothing_precision"
|
||||
|
Loading…
x
Reference in New Issue
Block a user