Merge some BS1.7 changes:
internal_solid_infill_pattern
This commit is contained in:
@@ -1634,25 +1634,28 @@ static inline ExPolygons detect_overhangs(
|
||||
//FIXME add user defined filtering here based on minimal area or minimum radius or whatever.
|
||||
|
||||
// BBS
|
||||
for (ExPolygon& expoly : layerm->raw_slices) {
|
||||
bool is_sharp_tail = false;
|
||||
float accum_height = layer.height;
|
||||
if (g_config_support_sharp_tails) {
|
||||
for (ExPolygon& expoly : layerm->raw_slices) {
|
||||
if (offset_ex(expoly, -0.5 * fw).empty()) continue;
|
||||
bool is_sharp_tail = false;
|
||||
float accum_height = layer.height;
|
||||
|
||||
// 1. nothing below
|
||||
// Check whether this is a sharp tail region.
|
||||
// Should use lower_layer_expolys without any offset. Otherwise, it may missing sharp tails near the main body.
|
||||
if (g_config_support_sharp_tails && !overlaps(offset_ex(expoly, 0.5 * fw), lower_layer_expolys)) {
|
||||
is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly,-0.1*fw).empty();
|
||||
}
|
||||
// 1. nothing below
|
||||
// Check whether this is a sharp tail region.
|
||||
// Should use lower_layer_expolys without any offset. Otherwise, it may missing sharp tails near the main body.
|
||||
if (!overlaps(offset_ex(expoly, 0.5 * fw), lower_layer_expolys)) {
|
||||
is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly, -0.1 * fw).empty();
|
||||
}
|
||||
|
||||
if (is_sharp_tail) {
|
||||
ExPolygons overhang = diff_ex({ expoly }, lower_layer_polygons);
|
||||
layer.sharp_tails.push_back(expoly);
|
||||
layer.sharp_tails_height.insert({ &expoly, accum_height });
|
||||
overhang = offset_ex(overhang, 0.05 * fw);
|
||||
polygons_append(diff_polygons, to_polygons(overhang));
|
||||
if (is_sharp_tail) {
|
||||
ExPolygons overhang = diff_ex({ expoly }, lower_layer_expolys);
|
||||
layer.sharp_tails.push_back(expoly);
|
||||
layer.sharp_tails_height.insert({ &expoly, accum_height });
|
||||
overhang = offset_ex(overhang, 0.05 * fw);
|
||||
polygons_append(diff_polygons, to_polygons(overhang));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (diff_polygons.empty())
|
||||
@@ -1790,13 +1793,21 @@ static inline std::tuple<Polygons, Polygons, double> detect_contacts(
|
||||
// For the same reason, the non-bridging support area may be smaller than the bridging support area!
|
||||
slices_margin_update(std::min(lower_layer_offset, float(scale_(gap_xy))), no_interface_offset);
|
||||
// Offset the contact polygons outside.
|
||||
|
||||
// BBS: already trim the support in trim_support_layers_by_object()
|
||||
#if 0
|
||||
for (size_t i = 0; i < NUM_MARGIN_STEPS; ++ i) {
|
||||
diff_polygons = diff(
|
||||
offset(
|
||||
diff_polygons,
|
||||
scaled<float>(SUPPORT_MATERIAL_MARGIN / NUM_MARGIN_STEPS),
|
||||
ClipperLib::jtRound,
|
||||
// round mitter limit
|
||||
scale_(0.05)),
|
||||
slices_margin.polygons);
|
||||
}
|
||||
#else
|
||||
diff_polygons = diff(diff_polygons, slices_margin.polygons);
|
||||
#endif
|
||||
}
|
||||
|
||||
polygons_append(contact_polygons, diff_polygons);
|
||||
} // for each layer.region
|
||||
|
||||
@@ -2255,21 +2266,18 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||
const coordf_t extrusion_width = m_object_config->line_width.get_abs_value(object.print()->config().nozzle_diameter.get_at(object.config().support_interface_filament-1));
|
||||
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
|
||||
if (is_auto(m_object_config->support_type.value) && g_config_support_sharp_tails && !detect_first_sharp_tail_only) {
|
||||
for (size_t layer_nr = 0; layer_nr < object.layer_count(); layer_nr++) {
|
||||
for (size_t layer_nr = layer_id_start; layer_nr < num_layers; layer_nr++) {
|
||||
if (object.print()->canceled())
|
||||
break;
|
||||
|
||||
const Layer* layer = object.get_layer(layer_nr);
|
||||
const Layer* lower_layer = layer->lower_layer;
|
||||
// skip if:
|
||||
// 1) if the current layer is already detected as sharp tails
|
||||
// 2) lower layer has no sharp tails
|
||||
if (!lower_layer || layer->sharp_tails.empty() == false || lower_layer->sharp_tails.empty() == true)
|
||||
if (!lower_layer)
|
||||
continue;
|
||||
|
||||
// BBS detect sharp tail
|
||||
const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails;
|
||||
auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height;
|
||||
const auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height;
|
||||
for (const ExPolygon& expoly : layer->lslices) {
|
||||
bool is_sharp_tail = false;
|
||||
float accum_height = layer->height;
|
||||
@@ -2300,13 +2308,13 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||
}
|
||||
|
||||
// 2.3 check whether sharp tail exceed the max height
|
||||
for (auto& lower_sharp_tail_height : lower_layer_sharptails_height) {
|
||||
for (const auto& lower_sharp_tail_height : lower_layer_sharptails_height) {
|
||||
if (lower_sharp_tail_height.first->overlaps(expoly)) {
|
||||
accum_height += lower_sharp_tail_height.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (accum_height >= sharp_tail_max_support_height) {
|
||||
if (accum_height > sharp_tail_max_support_height) {
|
||||
is_sharp_tail = false;
|
||||
break;
|
||||
}
|
||||
@@ -2343,7 +2351,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||
return MyLayersPtr();
|
||||
|
||||
// BBS group overhang clusters
|
||||
if (g_config_remove_small_overhangs) {
|
||||
const bool config_remove_small_overhangs = m_object_config->support_remove_small_overhang.value;
|
||||
if (config_remove_small_overhangs) {
|
||||
std::vector<OverhangCluster> clusters;
|
||||
double fw_scaled = scale_(extrusion_width);
|
||||
std::set<ExPolygon*> removed_overhang;
|
||||
@@ -2371,8 +2380,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||
if (!cluster.is_sharp_tail && !cluster.is_cantilever) {
|
||||
// 2. check overhang cluster size is small
|
||||
cluster.is_small_overhang = false;
|
||||
auto erode1 = offset_ex(cluster.merged_overhangs_dilated, -2.5 * fw_scaled);
|
||||
if (area(erode1) < SQ(scale_(0.1))) {
|
||||
auto erode1 = offset_ex(cluster.merged_overhangs_dilated, -1.0 * fw_scaled);
|
||||
Point bbox_sz = get_extents(erode1).size();
|
||||
if (bbox_sz.x() < 2 * fw_scaled || bbox_sz.y() < 2 * fw_scaled) {
|
||||
cluster.is_small_overhang = true;
|
||||
}
|
||||
}
|
||||
@@ -2824,41 +2834,10 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
||||
return bottom_contacts;
|
||||
}
|
||||
|
||||
// FN_HIGHER_EQUAL: the provided object pointer has a Z value >= of an internal threshold.
|
||||
// Find the first item with Z value >= of an internal threshold of fn_higher_equal.
|
||||
// If no vec item with Z value >= of an internal threshold of fn_higher_equal is found, return vec.size()
|
||||
// If the initial idx is size_t(-1), then use binary search.
|
||||
// Otherwise search linearly upwards.
|
||||
template<typename IteratorType, typename IndexType, typename FN_HIGHER_EQUAL>
|
||||
IndexType idx_higher_or_equal(IteratorType begin, IteratorType end, IndexType idx, FN_HIGHER_EQUAL fn_higher_equal)
|
||||
{
|
||||
auto size = int(end - begin);
|
||||
if (size == 0) {
|
||||
idx = 0;
|
||||
} else if (idx == IndexType(-1)) {
|
||||
// First of the batch of layers per thread pool invocation. Use binary search.
|
||||
int idx_low = 0;
|
||||
int idx_high = std::max(0, size - 1);
|
||||
while (idx_low + 1 < idx_high) {
|
||||
int idx_mid = (idx_low + idx_high) / 2;
|
||||
if (fn_higher_equal(begin[idx_mid]))
|
||||
idx_high = idx_mid;
|
||||
else
|
||||
idx_low = idx_mid;
|
||||
}
|
||||
idx = fn_higher_equal(begin[idx_low]) ? idx_low :
|
||||
(fn_higher_equal(begin[idx_high]) ? idx_high : size);
|
||||
} else {
|
||||
// For the other layers of this batch of layers, search incrementally, which is cheaper than the binary search.
|
||||
while (int(idx) < size && ! fn_higher_equal(begin[idx]))
|
||||
++ idx;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
template<typename T, typename IndexType, typename FN_HIGHER_EQUAL>
|
||||
IndexType idx_higher_or_equal(const std::vector<T>& vec, IndexType idx, FN_HIGHER_EQUAL fn_higher_equal)
|
||||
{
|
||||
return idx_higher_or_equal(vec.begin(), vec.end(), idx, fn_higher_equal);
|
||||
return Layer::idx_higher_or_equal(vec.begin(), vec.end(), idx, fn_higher_equal);
|
||||
}
|
||||
|
||||
// FN_LOWER_EQUAL: the provided object pointer has a Z value <= of an internal threshold.
|
||||
@@ -3343,7 +3322,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
||||
assert(! support_layer.polygons.empty() && support_layer.print_z >= m_slicing_params.raft_contact_top_z + EPSILON);
|
||||
// Find the overlapping object layers including the extra above / below gap.
|
||||
coordf_t z_threshold = support_layer.bottom_print_z() - gap_extra_below + EPSILON;
|
||||
idx_object_layer_overlapping = idx_higher_or_equal(
|
||||
idx_object_layer_overlapping = Layer::idx_higher_or_equal(
|
||||
object.layers().begin(), object.layers().end(), idx_object_layer_overlapping,
|
||||
[z_threshold](const Layer *layer){ return layer->print_z >= z_threshold; });
|
||||
// Collect all the object layers intersecting with this layer.
|
||||
@@ -4633,6 +4612,40 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
||||
}
|
||||
#endif
|
||||
|
||||
// Calculate top interface angle
|
||||
float angle_of_biggest_bridge = -1.f;
|
||||
do
|
||||
{
|
||||
// Currently only works when thick_bridges is off
|
||||
if (m_object->config().thick_bridges)
|
||||
break;
|
||||
|
||||
coordf_t object_layer_bottom_z = support_layer.print_z + m_slicing_params.gap_support_object;
|
||||
const Layer* object_layer = m_object->get_layer_at_bottomz(object_layer_bottom_z, 10.0 * EPSILON);
|
||||
if (object_layer == nullptr)
|
||||
break;
|
||||
|
||||
if (object_layer != nullptr) {
|
||||
float biggest_bridge_area = 0.f;
|
||||
const Polygons& top_contact_polys = top_contact_layer.polygons_to_extrude();
|
||||
for (auto layerm : object_layer->regions()) {
|
||||
for (auto bridge_surface : layerm->fill_surfaces.filter_by_type(stBottomBridge)) {
|
||||
float bs_area = bridge_surface->area();
|
||||
if (bs_area <= biggest_bridge_area || bridge_surface->bridge_angle < 0.f)
|
||||
continue;
|
||||
|
||||
angle_of_biggest_bridge = bridge_surface->bridge_angle;
|
||||
biggest_bridge_area = bs_area;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
auto calc_included_angle_degree = [](int degree_a, int degree_b) {
|
||||
int iad = std::abs(degree_b - degree_a);
|
||||
return std::min(iad, 180 - iad);
|
||||
};
|
||||
|
||||
// Top and bottom contacts, interface layers.
|
||||
for (size_t i = 0; i < 3; ++ i) {
|
||||
MyLayerExtruded &layer_ex = (i == 0) ? top_contact_layer : (i == 1 ? bottom_contact_layer : interface_layer);
|
||||
@@ -4655,6 +4668,22 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
||||
// Use interface angle for the interface layers.
|
||||
m_support_params.interface_angle + interface_angle_delta;
|
||||
|
||||
// BBS
|
||||
bool can_adjust_top_interface_angle = (m_object_config->support_interface_top_layers.value > 1 && &layer_ex == &top_contact_layer);
|
||||
if (can_adjust_top_interface_angle && angle_of_biggest_bridge >= 0.f) {
|
||||
int bridge_degree = (int)Geometry::rad2deg(angle_of_biggest_bridge);
|
||||
int support_intf_degree = (int)Geometry::rad2deg(filler_interface->angle);
|
||||
int max_included_degree = 0;
|
||||
int step = 90;
|
||||
for (int add_on_degree = 0; add_on_degree < 180; add_on_degree += step) {
|
||||
int degree_to_try = support_intf_degree + add_on_degree;
|
||||
int included_degree = calc_included_angle_degree(bridge_degree, degree_to_try);
|
||||
if (included_degree > max_included_degree) {
|
||||
max_included_degree = included_degree;
|
||||
filler_interface->angle = Geometry::deg2rad((float)degree_to_try);
|
||||
}
|
||||
}
|
||||
}
|
||||
double density = interface_as_base ? m_support_params.support_density : m_support_params.interface_density;
|
||||
filler_interface->spacing = interface_as_base ? m_support_params.support_material_flow.spacing() : m_support_params.support_material_interface_flow.spacing();
|
||||
filler_interface->link_max_length = coord_t(scale_(filler_interface->spacing * link_max_length_factor / density));
|
||||
|
||||
Reference in New Issue
Block a user