Support spot generator improvement - supporting bridges only in one direction

This commit is contained in:
PavelMikus 2023-01-23 13:00:36 +01:00 committed by Pavel Mikuš
parent 821d2391b4
commit f2deefd1de
3 changed files with 88 additions and 35 deletions

View File

@ -122,39 +122,18 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
CurvatureEstimator cestim;
auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast<double>(); };
std::vector<P> extrusion_points;
{
if (max_line_length <= 0) {
extrusion_points = input_points;
} else {
extrusion_points.reserve(input_points.size() * 2);
for (size_t i = 0; i + 1 < input_points.size(); i++) {
const P &curr = input_points[i];
const P &next = input_points[i + 1];
extrusion_points.push_back(curr);
auto len = maybe_unscale(next - curr).squaredNorm();
double t = sqrt((max_line_length * max_line_length) / len);
size_t new_point_count = 1.0 / (t + EPSILON);
for (size_t j = 1; j < new_point_count + 1; j++) {
extrusion_points.push_back(curr * (1.0 - j * t) + next * (j * t));
}
}
extrusion_points.push_back(input_points.back());
}
}
std::vector<ExtendedPoint> points;
points.reserve(extrusion_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1));
points.reserve(input_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1));
{
ExtendedPoint start_point{maybe_unscale(extrusion_points.front())};
ExtendedPoint start_point{maybe_unscale(input_points.front())};
auto [distance, nearest_line, x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(start_point.position.cast<AABBScalar>());
start_point.distance = distance + boundary_offset;
start_point.nearest_prev_layer_line = nearest_line;
points.push_back(start_point);
}
for (size_t i = 1; i < extrusion_points.size(); i++) {
ExtendedPoint next_point{maybe_unscale(extrusion_points[i])};
for (size_t i = 1; i < input_points.size(); i++) {
ExtendedPoint next_point{maybe_unscale(input_points[i])};
auto [distance, nearest_line, x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(next_point.position.cast<AABBScalar>());
next_point.distance = distance + boundary_offset;
next_point.nearest_prev_layer_line = nearest_line;
@ -172,7 +151,7 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) {
std::vector<ExtendedPoint> new_points;
new_points.reserve(points.size() * 2);
new_points.reserve(points.size()*2);
new_points.push_back(points.front());
for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) {
const ExtendedPoint &curr = points[point_idx];
@ -201,7 +180,30 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
}
new_points.push_back(next);
}
points = std::move(new_points);
points = new_points;
}
if (max_line_length > 0) {
std::vector<ExtendedPoint> new_points;
new_points.reserve(points.size()*2);
{
for (size_t i = 0; i + 1 < points.size(); i++) {
const ExtendedPoint &curr = points[i];
const ExtendedPoint &next = points[i + 1];
new_points.push_back(curr);
double len = (next.position - curr.position).squaredNorm();
double t = sqrt((max_line_length * max_line_length) / len);
size_t new_point_count = 1.0 / t;
for (size_t j = 1; j < new_point_count + 1; j++) {
Vec2d pos = curr.position * (1.0 - j * t) + next.position * (j * t);
auto [p_dist, p_near_l,
p_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(pos.cast<AABBScalar>());
new_points.push_back(ExtendedPoint{pos, float(p_dist + boundary_offset), p_near_l});
}
}
new_points.push_back(new_points.back());
}
points = new_points;
}
for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) {

View File

@ -237,13 +237,66 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
checked_lines_out.insert(checked_lines_out.end(), tmp.begin(), tmp.end());
}
return checked_lines_out;
} else if (entity->role().is_bridge() && !entity->role().is_perimeter()) {
// pure bridges are handled separately, beacuse we need to align the forward and backward direction support points
if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) {
return {};
}
const float flow_width = get_flow_width(layer_region, entity->role());
std::vector<ExtendedPoint> annotated_points = estimate_points_properties<true, true, true, true>(entity->as_polyline().points,
prev_layer_boundary, flow_width,
params.bridge_distance);
std::vector<ExtrusionLine> lines_out;
lines_out.reserve(annotated_points.size());
float bridged_distance = 0.0f;
std::optional<Vec2d> bridging_dir{};
for (size_t i = 0; i < annotated_points.size(); ++i) {
ExtendedPoint &curr_point = annotated_points[i];
ExtendedPoint &prev_point = i > 0 ? annotated_points[i - 1] : annotated_points[i - 1];
SupportPointCause potential_cause = std::abs(curr_point.curvature) > 0.1 ? SupportPointCause::FloatingBridgeAnchor :
SupportPointCause::LongBridge;
float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f;
Vec2d line_dir = (curr_point.position - prev_point.position).normalized();
ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast<float>() : curr_point.position.cast<float>(),
curr_point.position.cast<float>(), line_len, entity};
float max_bridge_len = std::max(params.support_points_interface_radius * 2.0f,
params.bridge_distance /
((1.0f + std::abs(curr_point.curvature)) * (1.0f + std::abs(curr_point.curvature)) *
(1.0f + std::abs(curr_point.curvature))));
if (!bridging_dir.has_value() && curr_point.distance > flow_width && line_len > params.bridge_distance * 0.6) {
bridging_dir = (prev_point.position - curr_point.position).normalized();
}
if (curr_point.distance > flow_width && potential_cause == SupportPointCause::LongBridge && bridging_dir.has_value() &&
bridging_dir->dot(line_dir) < 0.8) { // skip backward direction of bridge - supported by forward points enough
bridged_distance += line_len;
} else if (curr_point.distance > flow_width) {
bridged_distance += line_len;
if (bridged_distance > max_bridge_len) {
bridged_distance = 0.0f;
line_out.support_point_generated = potential_cause;
}
} else {
bridged_distance = 0.0f;
}
lines_out.push_back(line_out);
}
return lines_out;
} else { // single extrusion path, with possible varying parameters
if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) {
return {};
}
const float flow_width = get_flow_width(layer_region, entity->role());
// Compute only unsigned distance - prev_layer_lines can contain unconnected paths, thus the sign of the distance is unreliable
std::vector<ExtendedPoint> annotated_points = estimate_points_properties<true, true, false, false>(entity->as_polyline().points,
prev_layer_lines, flow_width,
@ -268,13 +321,11 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
curr_point.distance *= sign;
SupportPointCause potential_cause = SupportPointCause::FloatingExtrusion;
if (entity->role().is_bridge() && !entity->role().is_perimeter()) {
potential_cause = std::abs(curr_point.curvature) > 0.1 ? SupportPointCause::FloatingBridgeAnchor : SupportPointCause::LongBridge;
}
float max_bridge_len = params.bridge_distance /
((1.0f + std::abs(curr_point.curvature)) * (1.0f + std::abs(curr_point.curvature)) *
(1.0f + std::abs(curr_point.curvature)));
float max_bridge_len = std::max(params.support_points_interface_radius * 2.0f,
params.bridge_distance /
((1.0f + std::abs(curr_point.curvature)) * (1.0f + std::abs(curr_point.curvature)) *
(1.0f + std::abs(curr_point.curvature))));
if (curr_point.distance > 2.0f * flow_width) {
line_out.form_quality = 0.8f;

View File

@ -68,7 +68,7 @@ enum class SupportPointCause {
LongBridge, // point generated on bridge extrusion longer than the allowed length
FloatingBridgeAnchor, // point generated on unsupported bridge endpoint
FloatingExtrusion, // point generated on extrusion that does not hold on its own - huge overhangs
SeparationFromBed, // point generated for object parts that are connected to the bed, but the area is too low and there is risk of separation (brim may help)
SeparationFromBed, // point generated for object parts that are connected to the bed, but the area is too small and there is a risk of separation (brim may help)
UnstableFloatingPart, // point generated for object parts not connected to the bed, holded only by the other support points (brim will not help here)
WeakObjectPart // point generated when some part of the object is too weak to hold the upper part and may break (imagine hourglass)
};