Improve Lines Distancer quality, use it also in SeamPlacer
This commit is contained in:
parent
20bd7f9a26
commit
b49a2425ca
@ -1,6 +1,8 @@
|
|||||||
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
||||||
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
||||||
|
|
||||||
|
#include "Utils.hpp"
|
||||||
|
#include "libslic3r.h"
|
||||||
#include "libslic3r/AABBTreeIndirect.hpp"
|
#include "libslic3r/AABBTreeIndirect.hpp"
|
||||||
#include "libslic3r/Line.hpp"
|
#include "libslic3r/Line.hpp"
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@ -127,12 +129,26 @@ public:
|
|||||||
auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, nearest_line_index_out, nearest_point_out);
|
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}; }
|
if (distance < 0) { return {std::numeric_limits<Floating>::infinity(), nearest_line_index_out, nearest_point_out}; }
|
||||||
|
|
||||||
distance = sqrt(distance);
|
distance = sqrt(distance);
|
||||||
const LineType &line = lines[nearest_line_index_out];
|
const LineType &line = lines[nearest_line_index_out];
|
||||||
Vec<2, Floating> v1 = (line.b - line.a).template cast<Floating>();
|
Vec<2, Floating> v1 = (line.b - line.a).template cast<Floating>();
|
||||||
Vec<2, Floating> v2 = (point - 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; }
|
auto d1 = (v1.x() * v2.y()) - (v1.y() * v2.x());
|
||||||
|
|
||||||
|
LineType second_line = line;
|
||||||
|
if ((line.a.template cast<Floating>() - nearest_point_out).squaredNorm() < SCALED_EPSILON) {
|
||||||
|
second_line = lines[prev_idx_modulo(nearest_line_index_out, lines.size())];
|
||||||
|
} else {
|
||||||
|
second_line = lines[next_idx_modulo(nearest_line_index_out, lines.size())];
|
||||||
|
}
|
||||||
|
v1 = (second_line.b - second_line.a).template cast<Floating>();
|
||||||
|
v2 = (point - second_line.a).template cast<Floating>();
|
||||||
|
auto d2 = (v1.x() * v2.y()) - (v1.y() * v2.x());
|
||||||
|
|
||||||
|
auto d = abs(d1) > abs(d2) ? d1 : d2;
|
||||||
|
|
||||||
|
if (d > 0.0) { distance *= -1.0; }
|
||||||
|
|
||||||
return {distance, nearest_line_index_out, nearest_point_out};
|
return {distance, nearest_line_index_out, nearest_point_out};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef slic3r_ExPolygon_hpp_
|
#ifndef slic3r_ExPolygon_hpp_
|
||||||
#define slic3r_ExPolygon_hpp_
|
#define slic3r_ExPolygon_hpp_
|
||||||
|
|
||||||
|
#include "Point.hpp"
|
||||||
#include "libslic3r.h"
|
#include "libslic3r.h"
|
||||||
#include "Polygon.hpp"
|
#include "Polygon.hpp"
|
||||||
#include "Polyline.hpp"
|
#include "Polyline.hpp"
|
||||||
@ -124,6 +125,28 @@ inline Lines to_lines(const ExPolygons &src)
|
|||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::vector<Linef> to_linesf(const ExPolygons &src)
|
||||||
|
{
|
||||||
|
size_t n_lines = 0;
|
||||||
|
for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) {
|
||||||
|
n_lines += it_expoly->contour.points.size();
|
||||||
|
for (size_t i = 0; i < it_expoly->holes.size(); ++ i)
|
||||||
|
n_lines += it_expoly->holes[i].points.size();
|
||||||
|
}
|
||||||
|
std::vector<Linef> lines;
|
||||||
|
lines.reserve(n_lines);
|
||||||
|
for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) {
|
||||||
|
for (size_t i = 0; i <= it_expoly->holes.size(); ++ i) {
|
||||||
|
const Points &points = ((i == 0) ? it_expoly->contour : it_expoly->holes[i - 1]).points;
|
||||||
|
for (Points::const_iterator it = points.begin(); it != points.end()-1; ++it)
|
||||||
|
lines.push_back(Linef(unscaled(*it), unscaled(*(it + 1))));
|
||||||
|
lines.push_back(Linef(unscaled(points.back()), unscaled(points.front())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline Polylines to_polylines(const ExPolygon &src)
|
inline Polylines to_polylines(const ExPolygon &src)
|
||||||
{
|
{
|
||||||
Polylines polylines;
|
Polylines polylines;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "SeamPlacer.hpp"
|
#include "SeamPlacer.hpp"
|
||||||
|
|
||||||
#include "Color.hpp"
|
#include "Color.hpp"
|
||||||
|
#include "Polygon.hpp"
|
||||||
#include "PrintConfig.hpp"
|
#include "PrintConfig.hpp"
|
||||||
#include "tbb/parallel_for.h"
|
#include "tbb/parallel_for.h"
|
||||||
#include "tbb/blocked_range.h"
|
#include "tbb/blocked_range.h"
|
||||||
@ -995,49 +996,6 @@ void pick_random_seam_point(const std::vector<SeamCandidate> &perimeter_points,
|
|||||||
perimeter.finalized = true;
|
perimeter.finalized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PerimeterDistancer {
|
|
||||||
std::vector<Linef> lines;
|
|
||||||
AABBTreeIndirect::Tree<2, double> tree;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PerimeterDistancer(const Layer *layer) {
|
|
||||||
ExPolygons layer_outline = layer->lslices;
|
|
||||||
for (const ExPolygon &island : layer_outline) {
|
|
||||||
assert(island.contour.is_counter_clockwise());
|
|
||||||
for (const auto &line : island.contour.lines()) {
|
|
||||||
lines.emplace_back(unscale(line.a), unscale(line.b));
|
|
||||||
}
|
|
||||||
for (const Polygon &hole : island.holes) {
|
|
||||||
assert(hole.is_clockwise());
|
|
||||||
for (const auto &line : hole.lines()) {
|
|
||||||
lines.emplace_back(unscale(line.a), unscale(line.b));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
float distance_from_perimeter(const Vec2f &point) const {
|
|
||||||
Vec2d p = point.cast<double>();
|
|
||||||
size_t hit_idx_out { };
|
|
||||||
Vec2d hit_point_out = Vec2d::Zero();
|
|
||||||
auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, hit_idx_out, hit_point_out);
|
|
||||||
if (distance < 0) {
|
|
||||||
return std::numeric_limits<float>::max();
|
|
||||||
}
|
|
||||||
|
|
||||||
distance = sqrt(distance);
|
|
||||||
const Linef &line = lines[hit_idx_out];
|
|
||||||
Vec2d v1 = line.b - line.a;
|
|
||||||
Vec2d v2 = p - line.a;
|
|
||||||
if ((v1.x() * v2.y()) - (v1.y() * v2.x()) > 0.0) {
|
|
||||||
distance *= -1;
|
|
||||||
}
|
|
||||||
return distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
} // namespace SeamPlacerImpl
|
} // namespace SeamPlacerImpl
|
||||||
|
|
||||||
// Parallel process and extract each perimeter polygon of the given print object.
|
// Parallel process and extract each perimeter polygon of the given print object.
|
||||||
@ -1089,13 +1047,14 @@ void SeamPlacer::calculate_candidates_visibility(const PrintObject *po,
|
|||||||
|
|
||||||
void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) {
|
void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) {
|
||||||
using namespace SeamPlacerImpl;
|
using namespace SeamPlacerImpl;
|
||||||
|
using PerimeterDistancer = AABBTreeLines::LinesDistancer<Linef>;
|
||||||
|
|
||||||
std::vector<PrintObjectSeamData::LayerSeams> &layers = m_seam_per_object[po].layers;
|
std::vector<PrintObjectSeamData::LayerSeams> &layers = m_seam_per_object[po].layers;
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, layers.size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, layers.size()),
|
||||||
[po, &layers](tbb::blocked_range<size_t> r) {
|
[po, &layers](tbb::blocked_range<size_t> r) {
|
||||||
std::unique_ptr<PerimeterDistancer> prev_layer_distancer;
|
std::unique_ptr<PerimeterDistancer> prev_layer_distancer;
|
||||||
if (r.begin() > 0) { // previous layer exists
|
if (r.begin() > 0) { // previous layer exists
|
||||||
prev_layer_distancer = std::make_unique<PerimeterDistancer>(po->layers()[r.begin() - 1]);
|
prev_layer_distancer = std::make_unique<PerimeterDistancer>(to_linesf(po->layers()[r.begin() - 1]->lslices));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++layer_idx) {
|
for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++layer_idx) {
|
||||||
@ -1106,12 +1065,12 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
bool should_compute_layer_embedding = regions_with_perimeter > 1;
|
bool should_compute_layer_embedding = regions_with_perimeter > 1;
|
||||||
std::unique_ptr<PerimeterDistancer> current_layer_distancer = std::make_unique<PerimeterDistancer>(po->layers()[layer_idx]);
|
std::unique_ptr<PerimeterDistancer> current_layer_distancer = std::make_unique<PerimeterDistancer>(to_linesf(po->layers()[layer_idx]->lslices));
|
||||||
|
|
||||||
for (SeamCandidate &perimeter_point : layers[layer_idx].points) {
|
for (SeamCandidate &perimeter_point : layers[layer_idx].points) {
|
||||||
Vec2f point = Vec2f { perimeter_point.position.head<2>() };
|
Vec2f point = Vec2f { perimeter_point.position.head<2>() };
|
||||||
if (prev_layer_distancer.get() != nullptr) {
|
if (prev_layer_distancer.get() != nullptr) {
|
||||||
perimeter_point.overhang = prev_layer_distancer->distance_from_perimeter(point)
|
perimeter_point.overhang = prev_layer_distancer->signed_distance_from_lines(point.cast<double>())
|
||||||
+ 0.6f * perimeter_point.perimeter.flow_width
|
+ 0.6f * perimeter_point.perimeter.flow_width
|
||||||
- tan(SeamPlacer::overhang_angle_threshold)
|
- tan(SeamPlacer::overhang_angle_threshold)
|
||||||
* po->layers()[layer_idx]->height;
|
* po->layers()[layer_idx]->height;
|
||||||
@ -1120,7 +1079,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (should_compute_layer_embedding) { // search for embedded perimeter points (points hidden inside the print ,e.g. multimaterial join, best position for seam)
|
if (should_compute_layer_embedding) { // search for embedded perimeter points (points hidden inside the print ,e.g. multimaterial join, best position for seam)
|
||||||
perimeter_point.embedded_distance = current_layer_distancer->distance_from_perimeter(point)
|
perimeter_point.embedded_distance = current_layer_distancer->signed_distance_from_lines(point.cast<double>())
|
||||||
+ 0.6f * perimeter_point.perimeter.flow_width;
|
+ 0.6f * perimeter_point.perimeter.flow_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user