Fix aligning

- function belong
- Calculation of move distance on outline

Separate utils tests
This commit is contained in:
Filip Sykala 2021-05-10 20:47:41 +02:00 committed by Lukas Matena
parent 12b320624b
commit a3d17119f6
9 changed files with 122 additions and 108 deletions

View File

@ -285,9 +285,11 @@ bool LineUtils::belongs(const Line &line, const Point &point, double benevolence
const Point &b = line.b; const Point &b = line.b;
auto is_in_interval = [](coord_t value, coord_t from, coord_t to) -> bool auto is_in_interval = [](coord_t value, coord_t from, coord_t to) -> bool
{ {
if (from > to) { if (from < to) {
// from < value < to
if (from > value || to < value) return false; if (from > value || to < value) return false;
} else { } else {
// to < value < from
if (from < value || to > value) return false; if (from < value || to > value) return false;
} }
return true; return true;

View File

@ -28,7 +28,7 @@ public:
result.half_distance = result.max_distance / 2; result.half_distance = result.max_distance / 2;
result.head_radius = head_diameter / 2; result.head_radius = head_diameter / 2;
result.minimal_distance_from_outline = result.head_radius; result.minimal_distance_from_outline = result.head_radius;
result.maximal_distance_from_outline = result.half_distance; result.maximal_distance_from_outline = result.max_distance/4;
assert(result.minimal_distance_from_outline < result.maximal_distance_from_outline); assert(result.minimal_distance_from_outline < result.maximal_distance_from_outline);
result.minimal_support_distance = result.minimal_distance_from_outline + result.minimal_support_distance = result.minimal_distance_from_outline +
result.half_distance; result.half_distance;

View File

@ -20,10 +20,11 @@
// comment definition of NDEBUG to enable assert() // comment definition of NDEBUG to enable assert()
//#define NDEBUG //#define NDEBUG
#define SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG //#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
#define SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG //#define SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG
//#define SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG //#define SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG
//#define SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG
#include <cassert> #include <cassert>
@ -410,8 +411,18 @@ void SampleIslandUtils::align_samples(SupportIslandPoints &samples,
max_move = align_once(samples, island, config); max_move = align_once(samples, island, config);
if (max_move < config.minimal_move) break; if (max_move < config.minimal_move) break;
} }
//std::cout << "Align use " << config.count_iteration - count_iteration
// << " iteration and finish with precision " << max_move << "nano meters" << std::endl; #ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG
static int counter = 0;
SVG svg(("aligned_" + std::to_string(counter++) + ".svg").c_str(),BoundingBox(island));
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
} }
bool is_points_in_distance(const Slic3r::Point & p, bool is_points_in_distance(const Slic3r::Point & p,
@ -472,7 +483,10 @@ coord_t SampleIslandUtils::align_once(SupportIslandPoints &samples,
} }
} }
assert(island_cell != nullptr); assert(island_cell != nullptr);
Point center = island_cell->centroid(); Point center = island_cell->centroid();
/*
{ {
SVG cell_svg("island_cell.svg", island_cell->points); SVG cell_svg("island_cell.svg", island_cell->points);
cell_svg.draw(cell_polygon, "lightgray"); cell_svg.draw(cell_polygon, "lightgray");
@ -480,7 +494,7 @@ coord_t SampleIslandUtils::align_once(SupportIslandPoints &samples,
cell_svg.draw(*island_cell, "gray"); cell_svg.draw(*island_cell, "gray");
cell_svg.draw(sample->point, "green", config.head_radius); cell_svg.draw(sample->point, "green", config.head_radius);
cell_svg.draw(center, "black", config.head_radius); cell_svg.draw(center, "black", config.head_radius);
} }*/
assert(is_points_in_distance(center, island_cell->points, config.max_distance)); assert(is_points_in_distance(center, island_cell->points, config.max_distance));
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG #ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG
svg.draw(cell_polygon, color_point_cell); svg.draw(cell_polygon, color_point_cell);
@ -1115,7 +1129,7 @@ void SampleIslandUtils::create_sample_center_end(
Line edge(VoronoiGraphUtils::to_point(neighbor.edge->vertex0()), Line edge(VoronoiGraphUtils::to_point(neighbor.edge->vertex0()),
VoronoiGraphUtils::to_point(neighbor.edge->vertex1())); VoronoiGraphUtils::to_point(neighbor.edge->vertex1()));
for (const auto &support_point : near_no_move) { for (const auto &support_point : near_no_move) {
if (LineUtils::belongs(edge, support_point->point)) { if (LineUtils::belongs(edge, support_point->point, 10000)) {
exist_no_move = true; exist_no_move = true;
break; break;
} }
@ -1681,6 +1695,9 @@ bool SampleIslandUtils::is_visualization_disabled()
#endif #endif
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG #ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG
return false; return false;
#endif
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG
return false;
#endif #endif
return true; return true;
} }

View File

@ -128,9 +128,8 @@ coord_t SupportOutlineIslandPoint::move(const Point &destination)
} }
// apply closest result of move // apply closest result of move
this->point = closest.point;
this->position = closest.position; this->position = closest.position;
return closest.distance; return SupportIslandPoint::move(closest.point);
} }
Slic3r::Point SupportOutlineIslandPoint::calc_point(const Position &position, const Restriction &restriction) Slic3r::Point SupportOutlineIslandPoint::calc_point(const Position &position, const Restriction &restriction)

View File

@ -87,7 +87,7 @@ public:
--remaining; --remaining;
value_t temp = v[s]; value_t temp = v[s];
while (d = order_begin[d], d != s) { while (d = order_begin[d], d != s) {
swap(temp, v[d]); std::swap(temp, v[d]);
--remaining; --remaining;
} }
v[s] = temp; v[s] = temp;

View File

@ -6,6 +6,8 @@ add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp
sla_raycast_tests.cpp sla_raycast_tests.cpp
sla_parabola_tests.cpp sla_parabola_tests.cpp
sla_voronoi_graph_tests.cpp sla_voronoi_graph_tests.cpp
sla_vectorUtils_tests.cpp
sla_lineUtils_tests.cpp
sla_supptreeutils_tests.cpp sla_supptreeutils_tests.cpp
sla_archive_readwrite_tests.cpp sla_archive_readwrite_tests.cpp
sla_zcorrection_tests.cpp) sla_zcorrection_tests.cpp)

View File

@ -0,0 +1,59 @@
#include <catch2/catch.hpp>
#include <libslic3r/SLA/SupportIslands/LineUtils.hpp>
using namespace Slic3r;
using namespace Slic3r::sla;
TEST_CASE("Intersection point", "[Utils], [LineUtils]")
{
Point a1(0, 0);
Point b1(3, 6);
Line l1(a1, b1);
auto intersection = LineUtils::intersection(l1, Line(Point(0, 4),
Point(5, 4)));
CHECK(intersection.has_value());
Point i_point = intersection->cast<coord_t>();
CHECK(PointUtils::is_equal(i_point, Point(2, 4)));
// same line
auto bad_intersection = LineUtils::intersection(l1, l1);
CHECK(!bad_intersection.has_value());
// oposit direction
bad_intersection = LineUtils::intersection(l1, Line(b1, a1));
CHECK(!bad_intersection.has_value());
// parallel line
bad_intersection = LineUtils::intersection(l1, Line(a1 + Point(0, 1),
b1 + Point(0, 1)));
CHECK(!bad_intersection.has_value());
// out of line segment, but ray has intersection
Line l2(Point(0, 8), Point(6, 8));
intersection = LineUtils::intersection(l1, l2);
auto intersection2 = LineUtils::intersection(l2, l1);
CHECK(intersection.has_value());
CHECK(intersection2.has_value());
i_point = intersection->cast<coord_t>();
CHECK(PointUtils::is_equal(i_point, Point(4, 8)));
CHECK(PointUtils::is_equal(i_point, intersection2->cast<coord_t>()));
Line l3(Point(-2, -2), Point(1, -2));
intersection = LineUtils::intersection(l1, l3);
intersection2 = LineUtils::intersection(l3, l1);
CHECK(intersection.has_value());
CHECK(intersection2.has_value());
i_point = intersection->cast<coord_t>();
CHECK(PointUtils::is_equal(i_point, Point(-1, -2)));
CHECK(PointUtils::is_equal(i_point, intersection2->cast<coord_t>()));
}
TEST_CASE("Point belongs to line", "[Utils], [LineUtils]")
{
Line l(Point(10, 10), Point(50, 30));
CHECK(LineUtils::belongs(l, Point(30, 20)));
CHECK(!LineUtils::belongs(l, Point(30, 30)));
CHECK(LineUtils::belongs(l, Point(30, 30), 10.));
CHECK(!LineUtils::belongs(l, Point(30, 10)));
CHECK(!LineUtils::belongs(l, Point(70, 40)));
}

View File

@ -456,12 +456,15 @@ SupportIslandPoints test_island_sampling(const ExPolygon & island,
} }
SampleConfig create_sample_config(double size) { SampleConfig create_sample_config(double size) {
//SupportPointGenerator::Config spg_config;
//return SampleConfigFactory::create(spg_config);
SampleConfig cfg; SampleConfig cfg;
cfg.max_distance = 3 * size + 0.1; cfg.max_distance = 3 * size + 0.1;
cfg.half_distance = cfg.max_distance/2; cfg.half_distance = cfg.max_distance/2;
cfg.head_radius = size / 4; cfg.head_radius = size / 4;
cfg.minimal_distance_from_outline = cfg.head_radius; cfg.minimal_distance_from_outline = cfg.head_radius;
cfg.maximal_distance_from_outline = cfg.half_distance; cfg.maximal_distance_from_outline = cfg.max_distance/4;
cfg.min_side_branch_length = 2 * cfg.minimal_distance_from_outline; cfg.min_side_branch_length = 2 * cfg.minimal_distance_from_outline;
cfg.minimal_support_distance = cfg.minimal_distance_from_outline + cfg.half_distance; cfg.minimal_support_distance = cfg.minimal_distance_from_outline + cfg.half_distance;
cfg.max_length_for_one_support_point = 2*size; cfg.max_length_for_one_support_point = 2*size;
@ -471,7 +474,7 @@ SampleConfig create_sample_config(double size) {
cfg.outline_sample_distance = cfg.max_distance; cfg.outline_sample_distance = cfg.max_distance;
cfg.minimal_move = std::max(10000., size/40); cfg.minimal_move = std::max(10000., size/40);
cfg.count_iteration = 100; cfg.count_iteration = 50;
cfg.max_align_distance = 0; cfg.max_align_distance = 0;
return cfg; return cfg;
} }
@ -587,8 +590,7 @@ TEST_CASE("Small islands should be supported in center", "[SupGen], [VoronoiSkel
double size = 3e7; double size = 3e7;
SampleConfig cfg = create_sample_config(size); SampleConfig cfg = create_sample_config(size);
ExPolygons islands = createTestIslands(size); ExPolygons islands = createTestIslands(size);
islands = { create_disc(3 * size, 2*size , 20)};
islands = {islands[16]};
for (ExPolygon &island : islands) { for (ExPolygon &island : islands) {
// information for debug which island cause problem // information for debug which island cause problem
[[maybe_unused]] size_t debug_index = &island - &islands.front(); [[maybe_unused]] size_t debug_index = &island - &islands.front();
@ -708,98 +710,6 @@ TEST_CASE("Compare sampling test", "[hide]")
} }
} }
// source: https://en.wikipedia.org/wiki/Centroid
Slic3r::Point centroid(const Slic3r::Polygon &polygon) {
double sum_x = 0.;
double sum_y = 0.;
double signed_area = 0.;
auto add = [&](const Point &p1, const Point &p2) {
Vec2d p1d = p1.cast<double>();
double area = p1d.x() * p2.y() - p1d.y() * p2.x();
sum_x += (p1d.x() + p2.x()) * area;
sum_y += (p1d.y() + p2.y()) * area;
signed_area += area;
};
const Points &points = polygon.points;
for (size_t i = 1; i < points.size(); i++) {
add(points[i - 1], points[i]);
}
add(points.back(), points.front());
double area6 = signed_area * 3;
return Point(sum_x / area6, sum_y / area6);
}
TEST_CASE("Trapezoid centroid should be inside of trapezoid", "[Utils]")
{
Slic3r::Polygon polygon({
Point(4702134, 1124765853),
Point(-4702134, 1124765853),
Point(-9404268, 1049531706),
Point(9404268, 1049531706)
});
Point my_centroid = centroid(polygon);
CHECK(polygon.contains(my_centroid));
Point centroid = polygon.centroid();
CHECK(polygon.contains(centroid));
}
#include <libslic3r/SLA/SupportIslands/VectorUtils.hpp>
TEST_CASE("Reorder destructive", "[Utils]"){
std::vector<int> data {0, 1, 3, 2, 4, 7, 6, 5, 8};
std::vector<int> order{0, 1, 3, 2, 4, 7, 6, 5, 8};
VectorUtils::reorder_destructive(order.begin(), order.end(), data.begin());
for (size_t i = 0; i < data.size() - 1;++i) {
CHECK(data[i] < data[i + 1]);
}
}
#include <libslic3r/SLA/SupportIslands/LineUtils.hpp>
TEST_CASE("Intersection point", "[Utils]")
{
Point a1(0, 0);
Point b1(3, 6);
Line l1(a1, b1);
auto intersection = LineUtils::intersection(l1, Line(Point(0, 4), Point(5, 4)));
CHECK(intersection.has_value());
Point i_point = intersection->cast<coord_t>();
CHECK(PointUtils::is_equal(i_point, Point(2, 4)));
// same line
auto bad_intersection = LineUtils::intersection(l1, l1);
CHECK(!bad_intersection.has_value());
// oposit direction
bad_intersection = LineUtils::intersection(l1, Line(b1,a1));
CHECK(!bad_intersection.has_value());
// parallel line
bad_intersection = LineUtils::intersection(l1, Line(a1 + Point(0, 1),
b1 + Point(0, 1)));
CHECK(!bad_intersection.has_value());
// out of line segment, but ray has intersection
Line l2(Point(0, 8), Point(6, 8));
intersection = LineUtils::intersection(l1, l2);
auto intersection2 = LineUtils::intersection(l2, l1);
CHECK(intersection.has_value());
CHECK(intersection2.has_value());
i_point = intersection->cast<coord_t>();
CHECK(PointUtils::is_equal(i_point, Point(4, 8)));
CHECK(PointUtils::is_equal(i_point, intersection2->cast<coord_t>()));
Line l3(Point(-2, -2), Point(1, -2));
intersection = LineUtils::intersection(l1, l3);
intersection2 = LineUtils::intersection(l3, l1);
CHECK(intersection.has_value());
CHECK(intersection2.has_value());
i_point = intersection->cast<coord_t>();
CHECK(PointUtils::is_equal(i_point, Point(-1, -2)));
CHECK(PointUtils::is_equal(i_point, intersection2->cast<coord_t>()));
}
TEST_CASE("Disable visualization", "[hide]") TEST_CASE("Disable visualization", "[hide]")
{ {
CHECK(true); CHECK(true);

View File

@ -0,0 +1,25 @@
#include <catch2/catch.hpp>
#include <libslic3r/SLA/SupportIslands/VectorUtils.hpp>
using namespace Slic3r::sla;
TEST_CASE("Reorder", "[Utils], [VectorUtils]")
{
std::vector<int> data{0, 1, 3, 2, 4, 7, 6, 5, 8};
std::vector<int> order{0, 1, 3, 2, 4, 7, 6, 5, 8};
VectorUtils::reorder(order.begin(), order.end(), data.begin());
for (size_t i = 0; i < data.size() - 1; ++i) {
CHECK(data[i] < data[i + 1]);
}
}
TEST_CASE("Reorder destructive", "[Utils], [VectorUtils]"){
std::vector<int> data {0, 1, 3, 2, 4, 7, 6, 5, 8};
std::vector<int> order{0, 1, 3, 2, 4, 7, 6, 5, 8};
VectorUtils::reorder_destructive(order.begin(), order.end(), data.begin());
for (size_t i = 0; i < data.size() - 1;++i) {
CHECK(data[i] < data[i + 1]);
}
}