Support spot generator improvement - supporting bridges only in one direction
This commit is contained in:
parent
821d2391b4
commit
f2deefd1de
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user