mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-11 22:38:58 +08:00
Support island points are generated as unique ptr for option to move with them
+ add fix for cell 2 polygon transformation
This commit is contained in:
parent
942443429e
commit
85984ca189
@ -314,11 +314,11 @@ bool liang_barsky_line_clipping(
|
||||
template<typename T>
|
||||
int ray_circle_intersections_r2_lv2_c(T r2, T a, T b, T lv2, T c, std::pair<Eigen::Matrix<T, 2, 1, Eigen::DontAlign>, Eigen::Matrix<T, 2, 1, Eigen::DontAlign>> &out)
|
||||
{
|
||||
T x0 = - a * c / lv2;
|
||||
T y0 = - b * c / lv2;
|
||||
T d = r2 - c * c / lv2;
|
||||
if (d < T(0))
|
||||
return 0;
|
||||
T x0 = - a * c / lv2;
|
||||
T y0 = - b * c / lv2;
|
||||
T mult = sqrt(d / lv2);
|
||||
out.first.x() = x0 + b * mult;
|
||||
out.first.y() = y0 - a * mult;
|
||||
|
@ -59,7 +59,7 @@ std::optional<Slic3r::Linef> LineUtils::crop_ray(const Linef &ray,
|
||||
Vec2d center_d = center.cast<double>();
|
||||
if (is_parallel_y(ray)) {
|
||||
double x = ray.a.x();
|
||||
double diff = x - center.x();
|
||||
double diff = x - center_d.x();
|
||||
double abs_diff = fabs(diff);
|
||||
if (abs_diff > radius) return {};
|
||||
// create cross points
|
||||
@ -247,6 +247,13 @@ void LineUtils::draw(SVG & svg,
|
||||
}
|
||||
}
|
||||
|
||||
double LineUtils::perp_distance(const Linef &line, Vec2d p)
|
||||
{
|
||||
Vec2d v = line.b - line.a; // direction
|
||||
Vec2d va = p - line.a;
|
||||
return std::abs(cross2(v, va)) / v.norm();
|
||||
}
|
||||
|
||||
void LineUtils::draw(SVG & svg,
|
||||
const Lines &lines,
|
||||
const char * color,
|
||||
|
@ -84,6 +84,14 @@ public:
|
||||
static std::tuple<double, double, double> get_param(const Line &line);
|
||||
static std::tuple<double, double, double> get_param(const Linef &line);
|
||||
|
||||
/// <summary>
|
||||
/// Calculate distance between point and ray
|
||||
/// </summary>
|
||||
/// <param name="line">a and b are only for direction, not limit</param>
|
||||
/// <param name="p">Point in space</param>
|
||||
/// <returns>Euclid perpedicular distance</returns>
|
||||
static double perp_distance(const Linef &line, Vec2d p);
|
||||
|
||||
static void draw(SVG & svg,
|
||||
const Line &line,
|
||||
const char *color = "gray",
|
||||
|
@ -19,18 +19,17 @@
|
||||
|
||||
using namespace Slic3r::sla;
|
||||
|
||||
|
||||
SupportIslandPoint SampleIslandUtils::create_point(
|
||||
std::unique_ptr<SupportIslandPoint> SampleIslandUtils::create_point(
|
||||
const VoronoiGraph::Node::Neighbor *neighbor,
|
||||
double ratio,
|
||||
SupportIslandPoint::Type type)
|
||||
{
|
||||
VoronoiGraph::Position position(neighbor, ratio);
|
||||
Slic3r::Point p = VoronoiGraphUtils::create_edge_point(position);
|
||||
return SupportIslandPoint(p, type, position);
|
||||
return std::make_unique<SupportCenterIslandPoint>(p, position, type);
|
||||
}
|
||||
|
||||
SupportIslandPoint SampleIslandUtils::create_point_on_path(
|
||||
std::unique_ptr<SupportIslandPoint> SampleIslandUtils::create_point_on_path(
|
||||
const VoronoiGraph::Nodes &path,
|
||||
double distance,
|
||||
SupportIslandPoint::Type type)
|
||||
@ -57,12 +56,10 @@ SupportIslandPoint SampleIslandUtils::create_point_on_path(
|
||||
// distance must be inside path
|
||||
// this means bad input params
|
||||
assert(false);
|
||||
return SupportIslandPoint(Point(0, 0),
|
||||
SupportIslandPoint::Type::undefined,
|
||||
VoronoiGraph::Position(nullptr,0.));
|
||||
return nullptr; // unreachable
|
||||
}
|
||||
|
||||
SupportIslandPoint SampleIslandUtils::create_middle_path_point(
|
||||
SupportIslandPointPtr SampleIslandUtils::create_middle_path_point(
|
||||
const VoronoiGraph::Path &path, SupportIslandPoint::Type type)
|
||||
{
|
||||
return create_point_on_path(path.nodes, path.length / 2, type);
|
||||
@ -73,10 +70,11 @@ SupportIslandPoints SampleIslandUtils::create_side_points(
|
||||
{
|
||||
VoronoiGraph::Nodes reverse_path = path; // copy
|
||||
std::reverse(reverse_path.begin(), reverse_path.end());
|
||||
return {
|
||||
create_point_on_path(path, side_distance, SupportIslandPoint::Type::two_points),
|
||||
create_point_on_path(reverse_path, side_distance, SupportIslandPoint::Type::two_points)
|
||||
};
|
||||
SupportIslandPoints result;
|
||||
result.reserve(2);
|
||||
result.push_back(create_point_on_path(path, side_distance, SupportIslandPoint::Type::two_points));
|
||||
result.push_back(create_point_on_path(reverse_path, side_distance, SupportIslandPoint::Type::two_points));
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
SupportIslandPoints SampleIslandUtils::sample_side_branch(
|
||||
@ -92,7 +90,11 @@ SupportIslandPoints SampleIslandUtils::sample_side_branch(
|
||||
VoronoiGraph::Nodes reverse_path = side_path.nodes;
|
||||
std::reverse(reverse_path.begin(), reverse_path.end());
|
||||
reverse_path.push_back(first_node);
|
||||
return {create_point_on_path(reverse_path, cfg.side_distance, SupportIslandPoint::Type::center_line_end)};
|
||||
SupportIslandPoints result;
|
||||
result.push_back(
|
||||
create_point_on_path(reverse_path, cfg.side_distance,
|
||||
SupportIslandPoint::Type::center_line_end));
|
||||
return std::move(result);
|
||||
}
|
||||
// count of segment between points on main path
|
||||
size_t segment_count = static_cast<size_t>(
|
||||
@ -113,13 +115,13 @@ SupportIslandPoints SampleIslandUtils::sample_side_branch(
|
||||
if (side_item->second.top().length > cfg.min_length) {
|
||||
auto side_samples = sample_side_branches(side_item,
|
||||
start_offset, cfg);
|
||||
result.insert(result.end(), side_samples.begin(),
|
||||
side_samples.end());
|
||||
result.insert(result.end(), std::move_iterator(side_samples.begin()),
|
||||
std::move_iterator(side_samples.end()));
|
||||
}
|
||||
}
|
||||
while (distance < neighbor->edge_length) {
|
||||
double edge_ratio = distance / neighbor->edge_length;
|
||||
result.emplace_back(
|
||||
result.push_back(
|
||||
create_point(neighbor, edge_ratio, SupportIslandPoint::Type::center_line)
|
||||
);
|
||||
distance += sample_distance;
|
||||
@ -128,8 +130,8 @@ SupportIslandPoints SampleIslandUtils::sample_side_branch(
|
||||
prev_node = node;
|
||||
}
|
||||
assert(fabs(distance - (sample_distance - cfg.side_distance)) < 1e-5);
|
||||
result.back().type = SupportIslandPoint::Type::center_line_end;
|
||||
return result;
|
||||
result.back()->type = SupportIslandPoint::Type::center_line_end;
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
SupportIslandPoints SampleIslandUtils::sample_side_branches(
|
||||
@ -150,10 +152,12 @@ SupportIslandPoints SampleIslandUtils::sample_side_branches(
|
||||
while (side_branches_cpy.top().length > cfg.min_length) {
|
||||
auto samples = sample_side_branch(first_node, side_branches_cpy.top(),
|
||||
start_offset, cfg);
|
||||
result.insert(result.end(), samples.begin(), samples.end());
|
||||
result.insert(result.end(),
|
||||
std::move_iterator(samples.begin()),
|
||||
std::move_iterator(samples.end()));
|
||||
side_branches_cpy.pop();
|
||||
}
|
||||
return result;
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
std::vector<std::set<const VoronoiGraph::Node *>> create_circles_sets(
|
||||
@ -187,14 +191,16 @@ std::vector<std::set<const VoronoiGraph::Node *>> create_circles_sets(
|
||||
|
||||
Slic3r::Points SampleIslandUtils::to_points(const SupportIslandPoints &support_points)
|
||||
{
|
||||
std::function<Point(const SupportIslandPoint &)> transform_func = &SupportIslandPoint::point;
|
||||
std::function<Point(const std::unique_ptr<SupportIslandPoint> &)> transform_func = &SupportIslandPoint::point;
|
||||
return VectorUtils::transform(support_points, transform_func);
|
||||
}
|
||||
|
||||
std::vector<Slic3r::Vec2f> SampleIslandUtils::to_points_f(const SupportIslandPoints &support_points)
|
||||
{
|
||||
std::function<Vec2f(const SupportIslandPoint &p)> transform_func =
|
||||
[](const SupportIslandPoint &p) { return p.point.cast<float>(); };
|
||||
std::function<Vec2f(const std::unique_ptr<SupportIslandPoint> &)> transform_func =
|
||||
[](const std::unique_ptr<SupportIslandPoint> &p) {
|
||||
return p->point.cast<float>();
|
||||
};
|
||||
return VectorUtils::transform(support_points, transform_func);
|
||||
}
|
||||
|
||||
@ -246,13 +252,13 @@ coord_t SampleIslandUtils::align_once(SupportIslandPoints &samples,
|
||||
construct_voronoi(points.begin(), points.end(), &vd);
|
||||
coord_t max_move = 0;
|
||||
for (const VD::cell_type &cell : vd.cells()) {
|
||||
SupportIslandPoint &sample = samples[cell.source_index()];
|
||||
if (!sample.can_move()) continue;
|
||||
SupportIslandPointPtr &sample = samples[cell.source_index()];
|
||||
if (!sample->can_move()) continue;
|
||||
Polygon polygon = VoronoiGraphUtils::to_polygon(cell, points, config.max_distance);
|
||||
Polygons intersections = Slic3r::intersection(island, ExPolygon(polygon));
|
||||
const Polygon *island_cell = nullptr;
|
||||
for (const Polygon &intersection : intersections) {
|
||||
if (intersection.contains(sample.point)) {
|
||||
if (intersection.contains(sample->point)) {
|
||||
island_cell = &intersection;
|
||||
break;
|
||||
}
|
||||
@ -265,27 +271,13 @@ coord_t SampleIslandUtils::align_once(SupportIslandPoints &samples,
|
||||
svg.draw(*island_cell, "gray");
|
||||
svg.draw(sample.point, "black", config.head_radius);
|
||||
svg.draw(Line(sample.point, center), "blue", config.head_radius / 5);
|
||||
#endif // VISUALIZE_SAMPLE_ISLAND_UTILS_ALIGN_ONCE
|
||||
coord_t act_move = align_support(sample, center, config.max_align_distance);
|
||||
#endif // VISUALIZE_SAMPLE_ISLAND_UTILS_ALIGN_ONCE
|
||||
coord_t act_move = sample->move(center);
|
||||
if (max_move < act_move) max_move = act_move;
|
||||
}
|
||||
return max_move;
|
||||
}
|
||||
|
||||
coord_t SampleIslandUtils::align_support(SupportIslandPoint &support,
|
||||
const Point & wanted,
|
||||
double max_distance)
|
||||
{
|
||||
//move only along VD
|
||||
VoronoiGraph::Position position =
|
||||
VoronoiGraphUtils::align(support.position, wanted, max_distance);
|
||||
Point new_point = VoronoiGraphUtils::create_edge_point(position);
|
||||
Point move = new_point - support.point;
|
||||
support.position= position;
|
||||
support.point = new_point;
|
||||
return abs(move.x()) + abs(move.y());
|
||||
}
|
||||
|
||||
SupportIslandPoints SampleIslandUtils::sample_center_line(
|
||||
const VoronoiGraph::ExPath &path, const CenterLineConfiguration &cfg)
|
||||
{
|
||||
@ -300,7 +292,7 @@ SupportIslandPoints SampleIslandUtils::sample_center_line(
|
||||
if (path.circles.empty()) return result;
|
||||
sample_center_circles(path, cfg, result);
|
||||
|
||||
return result;
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
void SampleIslandUtils::sample_center_circle_end(
|
||||
@ -325,7 +317,7 @@ void SampleIslandUtils::sample_center_circle_end(
|
||||
double distance_between = distance / (count_supports + 1);
|
||||
if (distance_between < neighbor_distance) {
|
||||
// point is calculated to be in done path, SP will be on edge point
|
||||
result.emplace_back(create_point(&neighbor, 1., SupportIslandPoint::Type::center_circle_end));
|
||||
result.push_back(create_point(&neighbor, 1., SupportIslandPoint::Type::center_circle_end));
|
||||
neighbor_distance = 0.;
|
||||
count_supports -= 1;
|
||||
if (count_supports == 0) {
|
||||
@ -340,7 +332,7 @@ void SampleIslandUtils::sample_center_circle_end(
|
||||
nodes.insert(nodes.begin(), neighbor.node);
|
||||
for (int i = 1; i <= count_supports; ++i) {
|
||||
double distance_from_neighbor = i * (distance_between) - neighbor_distance;
|
||||
result.emplace_back(
|
||||
result.push_back(
|
||||
create_point_on_path(nodes, distance_from_neighbor, SupportIslandPoint::Type::center_circle_end2));
|
||||
double distance_support_to_node = fabs(neighbor.edge_length -
|
||||
distance_from_neighbor);
|
||||
@ -435,11 +427,13 @@ SupportDistanceMap create_path_distances(
|
||||
return path_distances;
|
||||
}
|
||||
|
||||
// do not use
|
||||
SupportDistanceMap create_support_distance_map(const SupportIslandPoints &support_points)
|
||||
{
|
||||
SupportDistanceMap support_distance_map;
|
||||
for (const SupportIslandPoint &support_point : support_points) {
|
||||
const VoronoiGraph::Position &position = support_point.position;
|
||||
for (const SupportIslandPointPtr &support_point : support_points) {
|
||||
auto ptr = dynamic_cast<SupportCenterIslandPoint*>(support_point.get()); // bad use
|
||||
const VoronoiGraph::Position &position = ptr->position;
|
||||
const VoronoiGraph::Node *node = position.neighbor->node;
|
||||
const VoronoiGraph::Node *twin_node = VoronoiGraphUtils::get_twin_node(position.neighbor);
|
||||
double distance = (1 - position.ratio) * position.neighbor->edge_length;
|
||||
@ -516,7 +510,9 @@ void SampleIslandUtils::sample_center_circles(
|
||||
for (const auto &circle_set : circles_sets) {
|
||||
SupportDistanceMap path_distances = create_path_distances(circle_set, path_set, support_distance_map, cfg.max_sample_distance/2);
|
||||
SupportIslandPoints circle_result = sample_center_circle(circle_set, path_distances, cfg);
|
||||
result.insert(result.end(), circle_result.begin(), circle_result.end());
|
||||
result.insert(result.end(),
|
||||
std::make_move_iterator(circle_result.begin()),
|
||||
std::make_move_iterator(circle_result.end()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -589,7 +585,7 @@ SupportIslandPoints SampleIslandUtils::sample_center_circle(
|
||||
.distance_from_support_point -
|
||||
nd.distance_from_support_point;
|
||||
double ratio = distance_from_node / neighbor.edge_length;
|
||||
result.emplace_back(
|
||||
result.push_back(
|
||||
create_point(&neighbor, ratio, SupportIslandPoint::Type::center_circle));
|
||||
next_nd.distance_from_support_point -= cfg.max_sample_distance;
|
||||
}
|
||||
@ -605,9 +601,10 @@ SupportIslandPoints SampleIslandUtils::sample_expath(
|
||||
// 1) One support point
|
||||
if (path.length < config.max_length_for_one_support_point) {
|
||||
// create only one point in center
|
||||
return {
|
||||
create_middle_path_point(path, SupportIslandPoint::Type::one_center_point)
|
||||
};
|
||||
SupportIslandPoints result;
|
||||
result.push_back(create_middle_path_point(
|
||||
path, SupportIslandPoint::Type::one_center_point));
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
double max_width = VoronoiGraphUtils::get_max_width(path);
|
||||
@ -624,8 +621,8 @@ SupportIslandPoints SampleIslandUtils::sample_expath(
|
||||
config.max_distance,
|
||||
config.minimal_distance_from_outline);
|
||||
SupportIslandPoints samples = sample_center_line(path, centerLineConfiguration);
|
||||
samples.front().type = SupportIslandPoint::Type::center_line_end2;
|
||||
return samples;
|
||||
samples.front()->type = SupportIslandPoint::Type::center_line_end2;
|
||||
return std::move(samples);
|
||||
}
|
||||
|
||||
// line of zig zag points
|
||||
@ -641,7 +638,7 @@ SupportIslandPoints SampleIslandUtils::sample_expath(
|
||||
SupportIslandPoints points;
|
||||
points.emplace_back(create_point_on_path(path.nodes, config.minimal_distance_from_outline));
|
||||
|
||||
return points;
|
||||
return std::move(points);
|
||||
}
|
||||
|
||||
SupportIslandPoints SampleIslandUtils::sample_voronoi_graph(
|
||||
@ -665,10 +662,10 @@ void SampleIslandUtils::draw(SVG & svg,
|
||||
bool write_type)
|
||||
{
|
||||
for (const auto &p : supportIslandPoints) {
|
||||
svg.draw(p.point, color, size);
|
||||
if (write_type && p.type != SupportIslandPoint::Type::undefined) {
|
||||
auto type_name = magic_enum::enum_name(p.type);
|
||||
Point start = p.point + Point(size, 0.);
|
||||
svg.draw(p->point, color, size);
|
||||
if (write_type && p->type != SupportIslandPoint::Type::undefined) {
|
||||
auto type_name = magic_enum::enum_name(p->type);
|
||||
Point start = p->point + Point(size, 0.);
|
||||
svg.draw_text(start, std::string(type_name).c_str(), color);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
/// <param name="ratio">Source distance ratio for position on edge</param>
|
||||
/// <param name="type">Type of point</param>
|
||||
/// <returns>created support island point</returns>
|
||||
static SupportIslandPoint create_point(
|
||||
static SupportIslandPointPtr create_point(
|
||||
const VoronoiGraph::Node::Neighbor *neighbor,
|
||||
double ratio,
|
||||
SupportIslandPoint::Type type = SupportIslandPoint::Type::undefined);
|
||||
@ -39,7 +39,7 @@ public:
|
||||
/// <param name="path">Neighbor connected Nodes</param>
|
||||
/// <param name="distance">Distance to final point</param>
|
||||
/// <returns>Points with distance to first node</returns>
|
||||
static SupportIslandPoint create_point_on_path(
|
||||
static SupportIslandPointPtr create_point_on_path(
|
||||
const VoronoiGraph::Nodes &path,
|
||||
double distance,
|
||||
SupportIslandPoint::Type type = SupportIslandPoint::Type::undefined);
|
||||
@ -52,7 +52,7 @@ public:
|
||||
/// <param name="path">Queue of neighbor nodes.(must be neighbor)</param>
|
||||
/// <param name="path_length">length of path</param>
|
||||
/// <returns>Point laying on voronoi diagram</returns>
|
||||
static SupportIslandPoint create_middle_path_point(
|
||||
static SupportIslandPointPtr create_middle_path_point(
|
||||
const VoronoiGraph::Path &path,
|
||||
SupportIslandPoint::Type type = SupportIslandPoint::Type::undefined);
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define slic3r_SLA_SuppotstIslands_SupportIslandPoint_hpp_
|
||||
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <libslic3r/Point.hpp>
|
||||
#include "VoronoiGraph.hpp"
|
||||
|
||||
@ -12,59 +13,106 @@ namespace Slic3r::sla {
|
||||
/// </summary>
|
||||
struct SupportIslandPoint
|
||||
{
|
||||
enum class Type : unsigned char {
|
||||
enum class Type: unsigned char {
|
||||
one_center_point,
|
||||
two_points,
|
||||
center_line,
|
||||
center_line_end, // end of branch
|
||||
center_line_end, // end of branch
|
||||
center_line_end2, // start of main path(only one per VD)
|
||||
center_circle,
|
||||
center_circle_end, // circle finish by one point (one end per circle - need allign)
|
||||
center_circle_end2, // circle finish by multi points (one end per circle - need allign)
|
||||
center_circle_end, // circle finish by one point (one end per circle -
|
||||
// need allign)
|
||||
center_circle_end2, // circle finish by multi points (one end per
|
||||
// circle - need allign)
|
||||
|
||||
outline, // keep position align with island outline
|
||||
undefined
|
||||
};
|
||||
|
||||
Slic3r::Point point; // 2 point in layer coordinate
|
||||
Type type;
|
||||
Slic3r::Point point; // 2 coordinate point in a layer (in one slice)
|
||||
|
||||
//SupportIslandPoint() : point(0, 0), type(Type::undefined) {}
|
||||
SupportIslandPoint(Slic3r::Point point, Type type = Type::undefined);
|
||||
virtual ~SupportIslandPoint() = default;
|
||||
|
||||
static bool can_move(const Type &type)
|
||||
{
|
||||
// use shorter list
|
||||
/*
|
||||
static const std::set<Type> can_move({
|
||||
Type::center_line,
|
||||
Type::center_circle,
|
||||
Type::center_circle_end,
|
||||
Type::center_circle_end2});
|
||||
return can_move.find(type) != can_move.end();
|
||||
/*/ // switch comment center
|
||||
static const std::set<Type> cant_move({
|
||||
Type::one_center_point,
|
||||
Type::two_points,
|
||||
Type::center_line_end,
|
||||
Type::center_line_end2});
|
||||
return cant_move.find(type) == cant_move.end();
|
||||
//*/
|
||||
}
|
||||
|
||||
virtual bool can_move() const { return can_move(type); }
|
||||
|
||||
/// <summary>
|
||||
/// Move position of support point close to destination
|
||||
/// with support point restrictions
|
||||
/// </summary>
|
||||
/// <param name="destination">Wanted position</param>
|
||||
/// <returns>Move distance</returns>
|
||||
virtual coord_t move(const Point &destination);
|
||||
};
|
||||
|
||||
using SupportIslandPointPtr = std::unique_ptr<SupportIslandPoint>;
|
||||
using SupportIslandPoints = std::vector<SupportIslandPointPtr>;
|
||||
|
||||
struct SupportCenterIslandPoint : public SupportIslandPoint
|
||||
{
|
||||
// Define position on voronoi graph
|
||||
// Lose data when voronoi graph does NOT exist
|
||||
VoronoiGraph::Position position;
|
||||
// IMPROVE: not need ratio, only neighbor
|
||||
// const VoronoiGraph::Node::Neighbor* neighbor;
|
||||
|
||||
Type type;
|
||||
// TODO: should earn when created
|
||||
const double max_distance = 1e6; // [in nm] --> 1 mm
|
||||
|
||||
SupportIslandPoint(Slic3r::Point point,
|
||||
Type type,
|
||||
VoronoiGraph::Position position)
|
||||
: point(std::move(point)), type(type), position(position)
|
||||
SupportCenterIslandPoint(Slic3r::Point point,
|
||||
VoronoiGraph::Position position,
|
||||
Type type = Type::center_line)
|
||||
: SupportIslandPoint(point, type), position(position)
|
||||
{}
|
||||
|
||||
bool can_move() const{
|
||||
// use shorter list
|
||||
/*
|
||||
|
||||
static const std::set<Type> can_move({
|
||||
Type::center_line,
|
||||
Type::center_circle,
|
||||
Type::center_circle_end,
|
||||
Type::center_circle_end2
|
||||
});
|
||||
return can_move.find(type) != can_move.end();
|
||||
|
||||
/*/
|
||||
|
||||
static const std::set<Type> cant_move({
|
||||
Type::one_center_point,
|
||||
Type::two_points,
|
||||
Type::center_line_end,
|
||||
Type::center_line_end2
|
||||
});
|
||||
return cant_move.find(type) == cant_move.end();
|
||||
|
||||
//*/
|
||||
bool can_move() const override{ return true; }
|
||||
coord_t move(const Point &destination) override;
|
||||
};
|
||||
|
||||
struct SupportOutlineIslandPoint : public SupportIslandPoint
|
||||
{
|
||||
// index of line form island outline
|
||||
size_t index;
|
||||
SupportOutlineIslandPoint(Slic3r::Point point,
|
||||
size_t index,
|
||||
Type type = Type::outline)
|
||||
: SupportIslandPoint(point, type), index(index)
|
||||
{}
|
||||
|
||||
bool can_move() const override { return true; }
|
||||
|
||||
coord_t move(const Point &destination) override
|
||||
{
|
||||
// TODO: For decide of move need information about
|
||||
// + island outlines \ May be
|
||||
// + distance from outline / offseted outlines
|
||||
// + search distance for allowed move over outlines(count, distance)
|
||||
assert(false); // Not implemented
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
using SupportIslandPoints = std::vector<SupportIslandPoint>;
|
||||
|
||||
} // namespace Slic3r::sla
|
||||
#endif // slic3r_SLA_SuppotstIslands_SupportIslandPoint_hpp_
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
template<typename T1, typename T2>
|
||||
static void sort_by(std::vector<T1> &data, std::function<T2(const T1 &)> &calc)
|
||||
{
|
||||
assert(!data.empty());
|
||||
// initialize original index locations
|
||||
std::vector<size_t> idx(data.size());
|
||||
iota(idx.begin(), idx.end(), 0);
|
||||
|
@ -13,10 +13,10 @@
|
||||
#include <libslic3r/VoronoiVisualUtils.hpp>
|
||||
|
||||
// comment definition of NDEBUG to enable assert()
|
||||
// #define NDEBUG
|
||||
//#define NDEBUG
|
||||
#include <cassert>
|
||||
|
||||
//#define SLA_CELL_2_POLYGON_DEBUG
|
||||
//#define SLA_SVG_VISUALIZATION_CELL_2_POLYGON
|
||||
|
||||
using namespace Slic3r::sla;
|
||||
|
||||
@ -38,7 +38,7 @@ Slic3r::Point VoronoiGraphUtils::to_point(const VD::vertex_type *vertex)
|
||||
|
||||
Slic3r::Vec2d VoronoiGraphUtils::to_point_d(const VD::vertex_type *vertex)
|
||||
{
|
||||
return Vec2d(to_coord(vertex->x()), to_coord(vertex->y()));
|
||||
return Vec2d(vertex->x(), vertex->y());
|
||||
}
|
||||
|
||||
bool VoronoiGraphUtils::is_coord_in_limits(const VD::coordinate_type &coord,
|
||||
@ -78,13 +78,6 @@ Slic3r::Line VoronoiGraphUtils::create_line_between_source_points(
|
||||
return Line(middle - side_dir, middle + side_dir);
|
||||
}
|
||||
|
||||
bool is_oposit_direction(const Slic3r::Point &p1, const Slic3r::Point &p2) {
|
||||
if (abs(p1.x()) > abs(p1.y())) {
|
||||
return (p1.x() > 0) != (p2.x() > 0);
|
||||
}
|
||||
return (p1.y() > 0) != (p2.y() > 0);
|
||||
}
|
||||
|
||||
std::optional<Slic3r::Line> VoronoiGraphUtils::to_line(
|
||||
const VD::edge_type &edge, const Points &points, double maximal_distance)
|
||||
{
|
||||
@ -137,12 +130,22 @@ std::optional<Slic3r::Line> VoronoiGraphUtils::to_line(
|
||||
}
|
||||
std::optional<Linef> segment;
|
||||
if (use_both) {
|
||||
Linef edge_segment(Vec2d(v0->x(), v0->y()), Vec2d(v1->x(), v1->y()));
|
||||
Linef edge_segment(to_point_d(v0), to_point_d(v1));
|
||||
segment = LineUtils::crop_line(edge_segment, p1, maximal_distance);
|
||||
} else {
|
||||
Vec2d ray_point(edge_vertex->x(), edge_vertex->y());
|
||||
Linef ray(ray_point, ray_point + direction.cast<double>());
|
||||
segment = LineUtils::crop_half_ray(ray, p1, maximal_distance);
|
||||
// Vertex can't be used as start point because data type limitation
|
||||
// Explanation for shortening line is in Test::bad_vertex
|
||||
Vec2d middle = (p1.cast<double>() + p2.cast<double>()) / 2.;
|
||||
Vec2d vertex = to_point_d(edge_vertex);
|
||||
Vec2d vertex_direction = (vertex - middle);
|
||||
Vec2d vertex_dir_abs(fabs(vertex_direction.x()), fabs(vertex_direction.y()));
|
||||
double divider = (vertex_dir_abs.x() > vertex_dir_abs.y()) ?
|
||||
vertex_dir_abs.x() / maximal_distance :
|
||||
vertex_dir_abs.y() / maximal_distance;
|
||||
Vec2d vertex_dir_short = vertex_direction / divider;
|
||||
Vec2d start_point = middle + vertex_dir_short;
|
||||
Linef line_short(start_point, start_point + direction.cast<double>());
|
||||
segment = LineUtils::crop_half_ray(line_short, p1, maximal_distance);
|
||||
}
|
||||
if (!segment.has_value()) return {};
|
||||
return Line(segment->a.cast<coord_t>(), segment->b.cast<coord_t>());
|
||||
@ -218,32 +221,24 @@ Slic3r::Polygon VoronoiGraphUtils::to_polygon(const VD::cell_type & cell,
|
||||
const VD::edge_type *edge = cell.incident_edge();
|
||||
do {
|
||||
assert(edge->is_linear());
|
||||
if (!edge->is_primary()) {
|
||||
edge = edge->next();
|
||||
continue;
|
||||
}
|
||||
if (!edge->is_primary()) continue;
|
||||
std::optional<Line> line = to_line(*edge, points, maximal_distance);
|
||||
if (!line.has_value()) {
|
||||
edge = edge->next();
|
||||
continue;
|
||||
}
|
||||
if (!line.has_value()) continue;
|
||||
Geometry::Orientation orientation = Geometry::orient(center, line->a, line->b);
|
||||
if (orientation == Geometry::Orientation::ORIENTATION_COLINEAR)
|
||||
{ // on circle over source point edge
|
||||
edge = edge->next();
|
||||
// Can be rich on circle over source point edge
|
||||
if (orientation == Geometry::Orientation::ORIENTATION_COLINEAR)
|
||||
continue;
|
||||
}
|
||||
if (orientation == Geometry::Orientation::ORIENTATION_CW)
|
||||
std::swap(line->a, line->b);
|
||||
lines.push_back(line.value());
|
||||
edge = edge->next();
|
||||
} while (edge != cell.incident_edge());
|
||||
} while ((edge = edge->next()) && edge != cell.incident_edge());
|
||||
assert(!lines.empty());
|
||||
LineUtils::sort_CCW(lines, center);
|
||||
// preccission to decide when not connect neighbor points
|
||||
double min_distance = maximal_distance / 1000.;
|
||||
size_t count_point = 6; // count added points
|
||||
Slic3r::Polygon polygon = to_polygon(lines, center, maximal_distance, min_distance, count_point);
|
||||
#ifdef SLA_CELL_2_POLYGON_DEBUG
|
||||
#ifdef SLA_SVG_VISUALIZATION_CELL_2_POLYGON
|
||||
{
|
||||
std::cout << "cell " << cell.source_index() << " has " << lines.size() << "edges" << std::endl;
|
||||
BoundingBox bbox(center - Point(maximal_distance, maximal_distance),
|
||||
@ -261,7 +256,7 @@ Slic3r::Polygon VoronoiGraphUtils::to_polygon(const VD::cell_type & cell,
|
||||
}
|
||||
svg.draw(center, "red", maximal_distance / 100);
|
||||
}
|
||||
#endif /* SLA_CELL_2_POLYGON_DEBUG */
|
||||
#endif /* SLA_SVG_VISUALIZATION_CELL_2_POLYGON */
|
||||
return polygon;
|
||||
}
|
||||
|
||||
|
@ -2284,3 +2284,79 @@ TEST_CASE("Voronoi cell doesn't contain a source point - SPE-2298", "[VoronoiCel
|
||||
REQUIRE(vd.is_valid());
|
||||
}
|
||||
// */
|
||||
|
||||
//#include <libslic3r/SLA/SupportIslands/LineUtils.hpp>
|
||||
TEST_CASE("bad vertex cause overflow of data type precisin when use VD result", "[VoronoiDiagram]")
|
||||
{
|
||||
// Points are almost in line
|
||||
Points points = {
|
||||
{-106641371, 61644934},
|
||||
{-56376476, 32588892},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
//auto perp_distance = sla::LineUtils::perp_distance;
|
||||
auto perp_distance = [](const Linef &line, Vec2d p) {
|
||||
Vec2d v = line.b - line.a; // direction
|
||||
Vec2d va = p - line.a;
|
||||
return std::abs(cross2(v, va)) / v.norm();
|
||||
};
|
||||
|
||||
using VD = Slic3r::Geometry::VoronoiDiagram;
|
||||
VD vd;
|
||||
construct_voronoi(points.begin(), points.end(), &vd);
|
||||
|
||||
// edge between source index 0 and 1 has bad vertex
|
||||
size_t bad_index0 = 0;
|
||||
size_t bad_index1 = 1;
|
||||
for (auto &edge : vd.edges()) {
|
||||
size_t i1 = edge.cell()->source_index();
|
||||
size_t i2 = edge.twin()->cell()->source_index();
|
||||
if (i1 == bad_index0 && i2 == bad_index1 ||
|
||||
i1 == bad_index1 && i2 == bad_index0) {
|
||||
Vec2d p1 = points[bad_index0].cast<double>();
|
||||
Vec2d p2 = points[bad_index1].cast<double>();
|
||||
Vec2d middle = (p1 + p2) / 2;
|
||||
// direction for edge is perpendicular point connection
|
||||
Vec2d direction(p2.y() - p1.y(), p1.x() - p2.x());
|
||||
const VD::vertex_type *vrtx = (edge.vertex0() == nullptr) ?
|
||||
edge.vertex1() :
|
||||
edge.vertex0();
|
||||
if (vrtx == nullptr) continue;
|
||||
Vec2d vertex(vrtx->x(), vrtx->y());
|
||||
|
||||
double point_distance = (p1 - p2).norm();
|
||||
double half_point_distance = point_distance/2;
|
||||
|
||||
Linef line_from_middle(middle, middle + direction); // line between source points
|
||||
double distance_vertex = perp_distance(line_from_middle, vertex);
|
||||
double distance_p1 = perp_distance(line_from_middle, p1);
|
||||
double distance_p2 = perp_distance(line_from_middle, p2);
|
||||
|
||||
Linef line_from_vertex(vertex, vertex + direction);
|
||||
double distance_middle = perp_distance(line_from_vertex, middle);
|
||||
double distance_p1_ = perp_distance(line_from_vertex, p1);
|
||||
double distance_p2_ = perp_distance(line_from_vertex, p2);
|
||||
|
||||
double maximal_distance = 9e6;
|
||||
Vec2d vertex_direction = (vertex - middle);
|
||||
Vec2d vertex_dir_abs(fabs(vertex_direction.x()),
|
||||
fabs(vertex_direction.y()));
|
||||
double divider = (vertex_dir_abs.x() > vertex_dir_abs.y()) ?
|
||||
vertex_dir_abs.x() / maximal_distance :
|
||||
vertex_dir_abs.y() / maximal_distance;
|
||||
Vec2d vertex_dir_short = vertex_direction / divider;
|
||||
Vec2d start_point = middle + vertex_dir_short;
|
||||
Linef line_short(start_point, start_point + direction);
|
||||
double distance_short_vertex = perp_distance(line_short, vertex);
|
||||
double distance_short_middle = perp_distance(line_short, middle);
|
||||
double distance_p1_short = perp_distance(line_short, p1);
|
||||
double distance_p2_short = perp_distance(line_short, p2);
|
||||
|
||||
CHECK(distance_vertex < 10);
|
||||
//CHECK(distance_middle < 10); // This is bad
|
||||
CHECK(distance_short_vertex < 10);
|
||||
CHECK(distance_short_middle < 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,8 +331,8 @@ SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
||||
const Point &chck_point = chck_points[index];
|
||||
double &min_distance = point_distances[index];
|
||||
bool exist_close_support_point = false;
|
||||
for (auto &island_point : points) {
|
||||
Point& p = island_point.point;
|
||||
for (const auto &island_point : points) {
|
||||
const Point& p = island_point->point;
|
||||
Point abs_diff(fabs(p.x() - chck_point.x()),
|
||||
fabs(p.y() - chck_point.y()));
|
||||
if (abs_diff.x() < min_distance && abs_diff.y() < min_distance) {
|
||||
@ -354,7 +354,7 @@ SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
||||
SVG svg("Error" + std::to_string(++counter) + ".svg", bb);
|
||||
svg.draw(island, "blue", 0.5f);
|
||||
for (auto& p : points)
|
||||
svg.draw(p.point, "lightgreen", config.head_radius);
|
||||
svg.draw(p->point, "lightgreen", config.head_radius);
|
||||
for (size_t index = 0; index < chck_points.size(); ++index) {
|
||||
const Point &chck_point = chck_points[index];
|
||||
double distance = point_distances[index];
|
||||
@ -367,7 +367,7 @@ SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
||||
//CHECK(is_ok);
|
||||
|
||||
// all points must be inside of island
|
||||
for (const auto &point : points) { CHECK(island.contains(point.point)); }
|
||||
for (const auto &point : points) { CHECK(island.contains(point->point)); }
|
||||
return points;
|
||||
}
|
||||
|
||||
@ -428,10 +428,10 @@ TEST_CASE("Speed align", "[VoronoiSkeleton]")
|
||||
Slic3r::Voronoi::annotate_inside_outside(vd, lines);
|
||||
VoronoiGraph::ExPath longest_path;
|
||||
VoronoiGraph skeleton = VoronoiGraphUtils::create_skeleton(vd, lines);
|
||||
auto samples = SampleIslandUtils::sample_voronoi_graph(skeleton, cfg, longest_path);
|
||||
|
||||
for (int i = 0; i < 100; ++i) { auto sample_copy = samples; // copy
|
||||
SampleIslandUtils::align_samples(sample_copy, island, cfg);
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
auto samples = SampleIslandUtils::sample_voronoi_graph(skeleton, cfg, longest_path);
|
||||
SampleIslandUtils::align_samples(samples, island, cfg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ void check(Slic3r::Points points, double max_distance) {
|
||||
|
||||
TEST_CASE("Polygon from cell", "[Voronoi]")
|
||||
{
|
||||
// for debug #define SLA_CELL_2_POLYGON_DEBUG in VoronoiGraphUtils
|
||||
// for debug #define SLA_SVG_VISUALIZATION_CELL_2_POLYGON in VoronoiGraphUtils
|
||||
double max_distance = 1e7;
|
||||
coord_t size = (int) (4e6);
|
||||
coord_t half_size = size/2;
|
||||
|
Loading…
x
Reference in New Issue
Block a user