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;
|
CurvatureEstimator cestim;
|
||||||
auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast<double>(); };
|
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;
|
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>());
|
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.distance = distance + boundary_offset;
|
||||||
start_point.nearest_prev_layer_line = nearest_line;
|
start_point.nearest_prev_layer_line = nearest_line;
|
||||||
points.push_back(start_point);
|
points.push_back(start_point);
|
||||||
}
|
}
|
||||||
for (size_t i = 1; i < extrusion_points.size(); i++) {
|
for (size_t i = 1; i < input_points.size(); i++) {
|
||||||
ExtendedPoint next_point{maybe_unscale(extrusion_points[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>());
|
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.distance = distance + boundary_offset;
|
||||||
next_point.nearest_prev_layer_line = nearest_line;
|
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) {
|
if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) {
|
||||||
std::vector<ExtendedPoint> new_points;
|
std::vector<ExtendedPoint> new_points;
|
||||||
new_points.reserve(points.size() * 2);
|
new_points.reserve(points.size()*2);
|
||||||
new_points.push_back(points.front());
|
new_points.push_back(points.front());
|
||||||
for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) {
|
for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) {
|
||||||
const ExtendedPoint &curr = points[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);
|
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) {
|
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());
|
checked_lines_out.insert(checked_lines_out.end(), tmp.begin(), tmp.end());
|
||||||
}
|
}
|
||||||
return checked_lines_out;
|
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
|
} else { // single extrusion path, with possible varying parameters
|
||||||
if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) {
|
if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const float flow_width = get_flow_width(layer_region, entity->role());
|
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
|
// 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,
|
std::vector<ExtendedPoint> annotated_points = estimate_points_properties<true, true, false, false>(entity->as_polyline().points,
|
||||||
prev_layer_lines, flow_width,
|
prev_layer_lines, flow_width,
|
||||||
@ -268,13 +321,11 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
|
|||||||
curr_point.distance *= sign;
|
curr_point.distance *= sign;
|
||||||
|
|
||||||
SupportPointCause potential_cause = SupportPointCause::FloatingExtrusion;
|
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 /
|
float max_bridge_len = std::max(params.support_points_interface_radius * 2.0f,
|
||||||
((1.0f + std::abs(curr_point.curvature)) * (1.0f + std::abs(curr_point.curvature)) *
|
params.bridge_distance /
|
||||||
(1.0f + std::abs(curr_point.curvature)));
|
((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) {
|
if (curr_point.distance > 2.0f * flow_width) {
|
||||||
line_out.form_quality = 0.8f;
|
line_out.form_quality = 0.8f;
|
||||||
|
@ -68,7 +68,7 @@ enum class SupportPointCause {
|
|||||||
LongBridge, // point generated on bridge extrusion longer than the allowed length
|
LongBridge, // point generated on bridge extrusion longer than the allowed length
|
||||||
FloatingBridgeAnchor, // point generated on unsupported bridge endpoint
|
FloatingBridgeAnchor, // point generated on unsupported bridge endpoint
|
||||||
FloatingExtrusion, // point generated on extrusion that does not hold on its own - huge overhangs
|
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)
|
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)
|
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