mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 07:19:05 +08:00
improvements in islands recognition; LinesDistancer class for both Point based and Floating based lines
This commit is contained in:
parent
8a54f91548
commit
20bd7f9a26
@ -3,6 +3,7 @@
|
||||
|
||||
#include "libslic3r/AABBTreeIndirect.hpp"
|
||||
#include "libslic3r/Line.hpp"
|
||||
#include <type_traits>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -24,16 +25,16 @@ struct IndexedLinesDistancer {
|
||||
|
||||
inline VectorType closest_point_to_origin(size_t primitive_index,
|
||||
ScalarType &squared_distance) {
|
||||
VectorType nearest_point;
|
||||
Vec<LineType::Dim, typename LineType::Scalar> nearest_point;
|
||||
const LineType &line = lines[primitive_index];
|
||||
squared_distance = line_alg::distance_to_squared(line, origin, &nearest_point);
|
||||
return nearest_point;
|
||||
squared_distance = line_alg::distance_to_squared(line, origin.template cast<typename LineType::Scalar>(), &nearest_point);
|
||||
return nearest_point.template cast<ScalarType>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Build a balanced AABB Tree over a vector of float lines, balancing the tree
|
||||
// Build a balanced AABB Tree over a vector of lines, balancing the tree
|
||||
// on centroids of the lines.
|
||||
// Epsilon is applied to the bounding boxes of the AABB Tree to cope with numeric inaccuracies
|
||||
// during tree traversal.
|
||||
@ -41,7 +42,7 @@ template<typename LineType>
|
||||
inline AABBTreeIndirect::Tree<2, typename LineType::Scalar> build_aabb_tree_over_indexed_lines(
|
||||
const std::vector<LineType> &lines,
|
||||
//FIXME do we want to apply an epsilon?
|
||||
const float eps = 0)
|
||||
const double eps = 0)
|
||||
{
|
||||
using TreeType = AABBTreeIndirect::Tree<2, typename LineType::Scalar>;
|
||||
// using CoordType = typename TreeType::CoordType;
|
||||
@ -103,8 +104,49 @@ inline typename VectorType::Scalar squared_distance_to_indexed_lines(
|
||||
std::numeric_limits<Scalar>::infinity(), hit_idx_out, hit_point_out);
|
||||
}
|
||||
|
||||
}
|
||||
template<typename LineType> class LinesDistancer
|
||||
{
|
||||
private:
|
||||
std::vector<LineType> lines;
|
||||
using Scalar = typename LineType::Scalar;
|
||||
using Floating = typename std::conditional<std::is_floating_point<Scalar>::value, Scalar, double>::type;
|
||||
AABBTreeIndirect::Tree<2, Scalar> tree;
|
||||
|
||||
}
|
||||
public:
|
||||
explicit LinesDistancer(const std::vector<LineType> &lines) : lines(lines)
|
||||
{
|
||||
tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(this->lines);
|
||||
}
|
||||
|
||||
// negative sign means inside
|
||||
std::tuple<Floating, size_t, Vec<2, Floating>> signed_distance_from_lines_extra(const Vec<2, Scalar> &point) const
|
||||
{
|
||||
size_t nearest_line_index_out = size_t(-1);
|
||||
Vec<2, Floating> nearest_point_out = Vec<2, Floating>::Zero();
|
||||
Vec<2, Floating> p = point.template cast<Floating>();
|
||||
auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, nearest_line_index_out, nearest_point_out);
|
||||
|
||||
if (distance < 0) { return {std::numeric_limits<Floating>::infinity(), nearest_line_index_out, nearest_point_out}; }
|
||||
|
||||
distance = sqrt(distance);
|
||||
const LineType &line = lines[nearest_line_index_out];
|
||||
Vec<2, Floating> v1 = (line.b - line.a).template cast<Floating>();
|
||||
Vec<2, Floating> v2 = (point - line.a).template cast<Floating>();
|
||||
if ((v1.x() * v2.y()) - (v1.y() * v2.x()) > 0.0) { distance *= -1.0; }
|
||||
return {distance, nearest_line_index_out, nearest_point_out};
|
||||
}
|
||||
|
||||
Floating signed_distance_from_lines(const Vec<2, typename LineType::Scalar> &point) const
|
||||
{
|
||||
auto [dist, idx, np] = signed_distance_from_lines_extra(point);
|
||||
return dist;
|
||||
}
|
||||
|
||||
const LineType &get_line(size_t line_idx) const { return lines[line_idx]; }
|
||||
|
||||
const std::vector<LineType> &get_lines() const { return lines; }
|
||||
};
|
||||
|
||||
}} // namespace Slic3r::AABBTreeLines
|
||||
|
||||
#endif /* SRC_LIBSLIC3R_AABBTREELINES_HPP_ */
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "SupportSpotsGenerator.hpp"
|
||||
|
||||
#include "ExPolygon.hpp"
|
||||
#include "ExtrusionEntity.hpp"
|
||||
#include "Line.hpp"
|
||||
#include "Polygon.hpp"
|
||||
#include "tbb/parallel_for.h"
|
||||
#include "tbb/blocked_range.h"
|
||||
#include "tbb/blocked_range2d.h"
|
||||
@ -70,46 +73,10 @@ SupportPoint::SupportPoint(const Vec3f &position, float force, float spot_radius
|
||||
position(position), force(force), spot_radius(spot_radius), direction(direction) {
|
||||
}
|
||||
|
||||
class LinesDistancer {
|
||||
private:
|
||||
std::vector<ExtrusionLine> lines;
|
||||
AABBTreeIndirect::Tree<2, float> tree;
|
||||
|
||||
public:
|
||||
explicit LinesDistancer(const std::vector<ExtrusionLine> &lines) :
|
||||
lines(lines) {
|
||||
tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(this->lines);
|
||||
}
|
||||
|
||||
// negative sign means inside
|
||||
float signed_distance_from_lines(const Vec2f &point, size_t &nearest_line_index_out,
|
||||
Vec2f &nearest_point_out) const {
|
||||
auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, point, nearest_line_index_out,
|
||||
nearest_point_out);
|
||||
if (distance < 0)
|
||||
return std::numeric_limits<float>::infinity();
|
||||
|
||||
distance = sqrt(distance);
|
||||
const ExtrusionLine &line = lines[nearest_line_index_out];
|
||||
Vec2f v1 = line.b - line.a;
|
||||
Vec2f v2 = point - line.a;
|
||||
if ((v1.x() * v2.y()) - (v1.y() * v2.x()) > 0.0) {
|
||||
distance *= -1;
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
const ExtrusionLine& get_line(size_t line_idx) const {
|
||||
return lines[line_idx];
|
||||
}
|
||||
|
||||
const std::vector<ExtrusionLine>& get_lines() const {
|
||||
return lines;
|
||||
}
|
||||
};
|
||||
|
||||
static const size_t NULL_ISLAND = std::numeric_limits<size_t>::max();
|
||||
|
||||
using LD = AABBTreeLines::LinesDistancer<ExtrusionLine>;
|
||||
|
||||
class PixelGrid {
|
||||
Vec2f pixel_size;
|
||||
Vec2f origin;
|
||||
@ -387,7 +354,7 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity,
|
||||
std::vector<ExtrusionLine> &checked_lines_out,
|
||||
float layer_z,
|
||||
const LayerRegion *layer_region,
|
||||
const LinesDistancer &prev_layer_lines,
|
||||
const LD &prev_layer_lines,
|
||||
Issues &issues,
|
||||
const Params ¶ms) {
|
||||
|
||||
@ -429,11 +396,7 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity,
|
||||
// malformation in concave angles does not happen
|
||||
malformation_acc.add_angle(std::max(0.0f, curr_angle));
|
||||
|
||||
size_t nearest_line_idx;
|
||||
Vec2f nearest_point;
|
||||
float dist_from_prev_layer = prev_layer_lines.signed_distance_from_lines(current_line.b, nearest_line_idx,
|
||||
nearest_point);
|
||||
|
||||
auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.signed_distance_from_lines_extra(current_line.b);
|
||||
if (fabs(dist_from_prev_layer) < overhang_dist) {
|
||||
bridging_acc.reset();
|
||||
} else {
|
||||
@ -491,53 +454,18 @@ std::tuple<LayerIslands, PixelGrid> reckon_islands(
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LinesDistancer> islands; // these search trees will be used to determine to which island does the extrusion belong.
|
||||
std::vector<std::vector<size_t>> island_extrusions; //final assigment of each extrusion to an island.
|
||||
// initliaze the search from external perimeters - at the beginning, there is island candidate for each external perimeter.
|
||||
// some of them will disappear (e.g. holes)
|
||||
for (size_t e = 0; e < extrusions.size(); ++e) {
|
||||
if (layer_lines[extrusions[e].first].origin_entity->is_loop() &&
|
||||
layer_lines[extrusions[e].first].is_external_perimeter()) {
|
||||
std::vector<ExtrusionLine> copy(extrusions[e].second - extrusions[e].first);
|
||||
for (size_t ex_line_idx = extrusions[e].first; ex_line_idx < extrusions[e].second; ++ex_line_idx) {
|
||||
copy[ex_line_idx - extrusions[e].first] = layer_lines[ex_line_idx];
|
||||
}
|
||||
islands.emplace_back(copy);
|
||||
island_extrusions.push_back( { e });
|
||||
}
|
||||
std::vector<AABBTreeLines::LinesDistancer<Line>> islands; // these search trees will be used to determine to which island does the extrusion belong.
|
||||
for (const ExPolygon& island : layer->lslices) {
|
||||
islands.emplace_back(to_lines(island));
|
||||
}
|
||||
|
||||
// backup code if islands not found
|
||||
// If that happens, just make the first extrusion into island - it may be wrong, but it won't crash.
|
||||
if (islands.empty() && !extrusions.empty()) {
|
||||
std::vector<ExtrusionLine> copy(extrusions[0].second - extrusions[0].first);
|
||||
for (size_t ex_line_idx = extrusions[0].first; ex_line_idx < extrusions[0].second; ++ex_line_idx) {
|
||||
copy[ex_line_idx - extrusions[0].first] = layer_lines[ex_line_idx];
|
||||
}
|
||||
islands.emplace_back(copy);
|
||||
island_extrusions.push_back( { 0 });
|
||||
}
|
||||
|
||||
// assign non external extrusions to islands
|
||||
for (size_t e = 0; e < extrusions.size(); ++e) {
|
||||
if (!layer_lines[extrusions[e].first].origin_entity->is_loop() ||
|
||||
!layer_lines[extrusions[e].first].is_external_perimeter()) {
|
||||
bool island_assigned = false;
|
||||
for (size_t i = 0; i < islands.size(); ++i) {
|
||||
if (island_extrusions[i].empty()) {
|
||||
continue;
|
||||
}
|
||||
size_t idx = 0;
|
||||
Vec2f pt = Vec2f::Zero();
|
||||
if (islands[i].signed_distance_from_lines(layer_lines[extrusions[e].first].a, idx, pt) < 0) {
|
||||
island_extrusions[i].push_back(e);
|
||||
island_assigned = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!island_assigned) { // If extrusion is not assigned for some reason, push it into the first island. As with the previous backup code,
|
||||
// it may be wrong, but it won't crash
|
||||
island_extrusions[0].push_back(e);
|
||||
std::vector<std::vector<size_t>> island_extrusions(islands.size(),
|
||||
std::vector<size_t>{}); // final assigment of each extrusion to an island.
|
||||
for (size_t extrusion_idx = 0; extrusion_idx < extrusions.size(); extrusion_idx++) {
|
||||
Point second_point = Point::new_scale(layer_lines[extrusions[extrusion_idx].first].b);
|
||||
for (size_t island_idx = 0; island_idx < islands.size(); island_idx++) {
|
||||
if (islands[island_idx].signed_distance_from_lines(second_point) <= 0.0) {
|
||||
island_extrusions[island_idx].push_back(extrusion_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -553,10 +481,14 @@ std::tuple<LayerIslands, PixelGrid> reckon_islands(
|
||||
}
|
||||
|
||||
Island island { };
|
||||
island.external_lines.insert(island.external_lines.end(),
|
||||
layer_lines.begin() + extrusions[island_ex[0]].first,
|
||||
layer_lines.begin() + extrusions[island_ex[0]].second);
|
||||
for (size_t extrusion_idx : island_ex) {
|
||||
|
||||
if (layer_lines[extrusions[extrusion_idx].first].is_external_perimeter()) {
|
||||
island.external_lines.insert(island.external_lines.end(),
|
||||
layer_lines.begin() + extrusions[extrusion_idx].first,
|
||||
layer_lines.begin() + extrusions[extrusion_idx].second);
|
||||
}
|
||||
|
||||
for (size_t lidx = extrusions[extrusion_idx].first; lidx < extrusions[extrusion_idx].second; ++lidx) {
|
||||
line_to_island_mapping[lidx] = result.islands.size();
|
||||
const ExtrusionLine &line = layer_lines[lidx];
|
||||
@ -1050,7 +982,7 @@ Issues check_global_stability(SupportGridFilter supports_presence_grid,
|
||||
#ifdef DETAILED_DEBUG_LOGS
|
||||
weakest_conn.print_info("weakest connection info: ");
|
||||
#endif
|
||||
LinesDistancer island_lines_dist(island.external_lines);
|
||||
LD island_lines_dist(island.external_lines);
|
||||
float unchecked_dist = params.min_distance_between_support_points + 1.0f;
|
||||
|
||||
for (const ExtrusionLine &line : island.external_lines) {
|
||||
@ -1059,12 +991,9 @@ Issues check_global_stability(SupportGridFilter supports_presence_grid,
|
||||
unchecked_dist += line.len;
|
||||
} else {
|
||||
unchecked_dist = line.len;
|
||||
Vec2f target_point;
|
||||
size_t idx;
|
||||
Vec3f pivot_site_search_point = to_3d(Vec2f(line.b + (line.b - line.a).normalized() * 300.0f),
|
||||
layer_z);
|
||||
island_lines_dist.signed_distance_from_lines(pivot_site_search_point.head<2>(), idx,
|
||||
target_point);
|
||||
auto [dist, nidx, target_point] = island_lines_dist.signed_distance_from_lines_extra(pivot_site_search_point.head<2>());
|
||||
Vec3f support_point = to_3d(target_point, layer_z);
|
||||
auto force = part.is_stable_while_extruding(weakest_conn, line, support_point, layer_z, params);
|
||||
if (force > 0) {
|
||||
@ -1147,7 +1076,7 @@ std::tuple<Issues, std::vector<LayerIslands>> check_extrusions_and_build_graph(c
|
||||
}
|
||||
}
|
||||
#endif
|
||||
LinesDistancer external_lines(layer_lines);
|
||||
LD external_lines(layer_lines);
|
||||
layer_lines.clear();
|
||||
prev_layer_grid = layer_grid;
|
||||
|
||||
@ -1199,7 +1128,7 @@ std::tuple<Issues, std::vector<LayerIslands>> check_extrusions_and_build_graph(c
|
||||
}
|
||||
}
|
||||
#endif
|
||||
external_lines = LinesDistancer(layer_lines);
|
||||
external_lines = LD(layer_lines);
|
||||
layer_lines.clear();
|
||||
prev_layer_grid = layer_grid;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user