Add crop line and fix crop ray

This commit is contained in:
Filip Sykala - NTB T15p 2024-10-04 18:51:12 +02:00 committed by Lukas Matena
parent f9bc03fb6e
commit 537c5da543
3 changed files with 130 additions and 63 deletions

View File

@ -78,8 +78,9 @@ public:
// Align support points
// TODO: propagate print resolution
result.minimal_move = 10000.;// [in nanometers --> 0.01mm ], devide from print resolution to quater pixel
result.count_iteration = 100; // speed VS precission
result.minimal_move = scale_(0.1); // 0.1 mm is enough
// [in nanometers --> 0.01mm ], devide from print resolution to quater pixel is too strict
result.count_iteration = 50; // speed VS precission
result.max_align_distance = result.max_distance / 2;
return result;

View File

@ -23,9 +23,9 @@
//#define NDEBUG
//#define SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG
//#define SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG
//#define SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH "C:/data/temp/initial_sample_positions.svg"
//#define SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG
//#define SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG
#define SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG_PATH "C:/data/temp/align/island_<<COUNTER>>.svg"
//#define SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH "C:/data/temp/align_once/iter_<<COUNTER>>.svg"
//#define SLA_SAMPLE_ISLAND_UTILS_DEBUG_CELL_DISTANCE_PATH "C:/data/temp/island_cell.svg"
@ -36,6 +36,17 @@ using namespace Slic3r;
using namespace Slic3r::sla;
namespace {
std::string replace_first(
std::string s,
const std::string& toReplace,
const std::string& replaceWith
) {
std::size_t pos = s.find(toReplace);
if (pos == std::string::npos) return s;
s.replace(pos, toReplace.length(), replaceWith);
return s;
}
const ExPolygon &get_expolygon_with_biggest_contour(const ExPolygons &expolygons) {
assert(!expolygons.empty());
const ExPolygon *biggest = &expolygons.front();
@ -476,16 +487,17 @@ void SampleIslandUtils::align_samples(SupportIslandPoints &samples,
if (max_move < config.minimal_move) break;
}
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG_PATH
static int counter = 0;
SVG svg(("aligned_" + std::to_string(counter++) + ".svg").c_str(),BoundingBox(island.contour.points));
SVG svg(replace_first(SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG_PATH,
"<<COUNTER>>", std::to_string(counter++)).c_str(),BoundingBox(island.contour.points));
svg.draw(island);
draw(svg, samples, config.head_radius);
svg.Close();
std::cout << "Align use " << config.count_iteration - count_iteration
<< " iteration and finish with precision " << unscale(max_move,0)[0] <<
" mm" << std::endl;
#endif
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG_PATH
}
@ -501,17 +513,6 @@ Polygons create_voronoi_cells_boost(const Points &points, coord_t max_distance)
return cells;
}
std::string replace_first(
std::string s,
const std::string& toReplace,
const std::string& replaceWith
) {
std::size_t pos = s.find(toReplace);
if (pos == std::string::npos) return s;
s.replace(pos, toReplace.length(), replaceWith);
return s;
}
bool is_points_in_distance(const Slic3r::Point & p,
const Slic3r::Points &points,
double max_distance)
@ -989,15 +990,14 @@ SupportIslandPoints SampleIslandUtils::sample_voronoi_graph(
SupportIslandPoints points = sample_expath(longest_path, lines, config);
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH
{
static int counter = 0;
SVG svg("initial_sample_positions" + std::to_string(counter++) + ".svg",
SVG svg(SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH,
LineUtils::create_bounding_box(lines));
svg.draw(lines, "gray", config.head_radius/ 10);
draw(svg, points, config.head_radius, "black", true);
}
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH
return points;
}
@ -1935,7 +1935,7 @@ bool SampleIslandUtils::is_visualization_disabled()
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG
return false;
#endif
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH
return false;
#endif
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG
@ -1944,7 +1944,7 @@ bool SampleIslandUtils::is_visualization_disabled()
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
return false;
#endif
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG_PATH
return false;
#endif
return true;

View File

@ -50,9 +50,11 @@ Slic3r::Point to_point(const Site_2 &s) {
Slic3r::Line create_line_between_points(
const Point &point1, const Point &point2, double maximal_distance
) {
Point middle = (point1 + point2) / 2;
Point middle = point1/2 + point2/2;
Point diff = point1 - point2; // direction from point2 to point1
coord_t manhatn_distance = abs(diff.x()) + abs(diff.y());
// alligned points should not be too close
assert(manhatn_distance >= 1);
// it is not neccesary to know exact distance
// One need to know minimal distance between points.
// worst case is diagonal: sqrt(2*(0.5 * manhatn_distance)^2) =
@ -62,6 +64,60 @@ Slic3r::Line create_line_between_points(
return Line(middle - side_dir, middle + side_dir);
}
/// <summary>
/// Crop line which is no too far away(compare to maximal_distance) from v1(or v2)
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <param name="maximal_distance"></param>
/// <returns></returns>
std::optional<Slic3r::Line> crop_line(
const Point_2 &a, const Point_2 &b,
const Point &v1, const Point &v2, double maximal_distance
) {
Point diff = v1 - v2;
Point dir(-diff.y(), diff.x());
coord_t abs_x = abs(dir.x());
coord_t abs_y = abs(dir.y());
Point middle = v1 / 2 + v2 / 2;
double a_t, b_t; // [units is size of dir]
if (abs_x > abs_y) {
a_t = (a.x() - middle.x()) / (double) dir.x();
b_t = (b.x() - middle.x()) / (double) dir.x();
} else {
a_t = (a.y() - middle.y()) / (double) dir.y();
b_t = (b.y() - middle.y()) / (double) dir.y();
}
// calculate approx distance from middle point to detect too far from middle
coord_t manhatn_distance = abs_x + abs_y;
// alligned points should not be too close
assert(manhatn_distance >= 1);
double min_distance = manhatn_distance * .7;
double a_dist = a_t * min_distance;
double b_dist = b_t * min_distance;
double scale = maximal_distance / min_distance;
Line l(to_point(a), to_point(b));
if (a_dist > maximal_distance) {
if (b_dist > maximal_distance)
return {}; // out of range
l.a = middle + (scale * dir.cast<double>()).cast<coord_t>();
} else if (a_dist < -maximal_distance) {
if (b_dist < -maximal_distance)
return {}; // out of range
l.a = middle - (scale * dir.cast<double>()).cast<coord_t>();
}
if (b_dist > maximal_distance) {
l.b = middle + (scale * dir.cast<double>()).cast<coord_t>();
} else if (b_dist < -maximal_distance)
l.b = middle - (scale * dir.cast<double>()).cast<coord_t>();
return l;
}
/// <summary>
/// Crop ray to line which is no too far away(compare to maximal_distance) from v1(or v2)
/// </summary>
@ -70,41 +126,41 @@ Slic3r::Line create_line_between_points(
/// <param name="v2"></param>
/// <param name="maximal_distance">Limits for line</param>
/// <returns></returns>
std::optional<Slic3r::Line> crop_ray(const Point_2 &p, const Point_2 &v1, const Point_2 &v2, double maximal_distance) {
std::optional<Slic3r::Line> crop_ray(const Point_2 &ray_point, const Point &v1, const Point &v2, double maximal_distance) {
assert(maximal_distance > 0);
Vec2d ray_point = to_point_d(p);
Vec2d ray_dir(v1.y() - v2.y(), v2.x() - v1.x());
Point diff = v2 - v1;
Point ray_dir(-diff.y(), diff.x());
// bounds are similar as for line between points
Vec2d middle = (to_point_d(v1) + to_point_d(v2)) / 2;
double abs_x = abs(ray_dir.x());
double abs_y = abs(ray_dir.y());
double manhatn_dist = abs_x + abs_y; // maximal distance
Point middle = v1/2 + v2/2;
coord_t abs_x = abs(ray_dir.x());
coord_t abs_y = abs(ray_dir.y());
coord_t manhatn_dist = abs_x + abs_y; // maximal distance
// alligned points should not be too close
assert(manhatn_dist <= 1e-5);
assert(manhatn_dist >= 1);
double min_distance = manhatn_dist * .7;
assert(min_distance > 0);
double scale = maximal_distance / min_distance;
// count of dir from ray point to middle
double middle_t = (abs_x > abs_y) ?
// use x coor
(middle.x() - ray_point.x()) / ray_dir.x() :
(middle.x() - ray_point.x()) / (double) ray_dir.x() :
// use y coor
(middle.y() - ray_point.y()) / ray_dir.y();
(middle.y() - ray_point.y()) / (double) ray_dir.y();
// minimal distance from ray point to middle point
double min_middle_dist = middle_t * min_distance;
if (min_middle_dist < -2 * maximal_distance)
if (min_middle_dist < -maximal_distance)
// ray start out of area of interest
return {};
if (min_middle_dist > 2 * maximal_distance)
// move ray start close to middle
ray_point = middle - ray_dir * scale;
return Line(ray_point.cast<coord_t>(), (middle + ray_dir * scale).cast<coord_t>());
double scale = maximal_distance / min_distance;
Point side_dir = (ray_dir.cast<double>() * scale).cast<coord_t>();
return Line(min_middle_dist > maximal_distance?
(middle - side_dir) : to_point(ray_point),
middle + side_dir);
}
std::optional<Slic3r::Line> to_line(
@ -115,37 +171,31 @@ std::optional<Slic3r::Line> to_line(
if (!edge->is_valid())
return {};
auto crop_ray = [&maximal_distance](const Point_2 &p, const Point_2 &v1, const Point_2 &v2)
-> std::optional<Slic3r::Line> {
Vec2d ray_point = to_point_d(p);
Vec2d dir(v1.y() - v2.y(), v2.x() - v1.x());
Linef ray(ray_point, ray_point + dir);
auto seg_opt = LineUtils::crop_half_ray(ray, to_point(v1), maximal_distance);
if (!seg_opt.has_value())
return {};
return Line(seg_opt->a.cast<coord_t>(), seg_opt->b.cast<coord_t>());
};
if (edge->has_source()) {
// source point of edge
if (edge->has_target()) { // Line segment
assert(edge->is_segment());
return Line(
to_point(edge->source()->point()),
to_point(edge->target()->point()));
return crop_line(
edge->source()->point(),
edge->target()->point(),
to_point(edge->up()->point()),
to_point(edge->down()->point()),
maximal_distance);
} else { // ray from source
assert(edge->is_ray());
return crop_ray(
edge->source()->point(),
edge->up()->point(),
edge->down()->point());
to_point(edge->up()->point()),
to_point(edge->down()->point()),
maximal_distance);
}
} else if (edge->has_target()) { // ray from target
assert(edge->is_ray());
return crop_ray(
edge->target()->point(),
edge->down()->point(),
edge->up()->point());
to_point(edge->down()->point()),
to_point(edge->up()->point()),
maximal_distance);
}
// infinite line between points
assert(edge->is_bisector());
@ -156,7 +206,7 @@ std::optional<Slic3r::Line> to_line(
);
}
}
} // namespace
Polygons Slic3r::sla::create_voronoi_cells_cgal(const Points &points, coord_t max_distance) {
assert(points.size() > 1);
@ -217,6 +267,23 @@ Polygons Slic3r::sla::create_voronoi_cells_cgal(const Points &points, coord_t ma
if (lines.size() > 1)
LineUtils::sort_CCW(lines, origin);
//Slic3r::SVG
// svg("C:/data/temp/CGAL_VD_face.svg",
// {origin - Point(max_distance, max_distance),
// origin + Point(max_distance, max_distance)});
//svg.draw(lines, "green");
//do {
// if (ec->has_source())
// svg.draw(to_point(ec->source()->point()));
// if (ec->has_target())
// svg.draw(to_point(ec->target()->point()));
// if (ec->is_segment())
// svg.draw(Line(to_point(ec->source()->point()), to_point(ec->target()->point())));
//} while (++ec != ec_start);
//svg.draw(origin, "red");
//svg.Close();
// preccission to decide when not connect neighbor points
double min_distance = max_distance / 1000.;
size_t count_point = 6; // count added points
@ -224,7 +291,6 @@ Polygons Slic3r::sla::create_voronoi_cells_cgal(const Points &points, coord_t ma
cells[index] =
VoronoiGraphUtils::to_polygon(lines, origin, max_distance, min_distance, count_point);
}
// Point_2 p;
// Locate_result lr = vd.locate(p); // Could locate face of VD - potentionaly could iterate input points
return cells;