123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- #include <algorithm>
- #include <catch2/catch.hpp>
- #include <test_utils.hpp>
- #include <libslic3r/TriangleMesh.hpp>
- #include <libslic3r/AABBTreeIndirect.hpp>
- #include <libslic3r/AABBTreeLines.hpp>
- using namespace Slic3r;
- TEST_CASE("Building a tree over a box, ray caster and closest query", "[AABBIndirect]")
- {
- TriangleMesh tmesh = make_cube(1., 1., 1.);
- auto tree = AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set(tmesh.its.vertices, tmesh.its.indices);
- REQUIRE(! tree.empty());
- igl::Hit hit;
- bool intersected = AABBTreeIndirect::intersect_ray_first_hit(
- tmesh.its.vertices, tmesh.its.indices,
- tree,
- Vec3d(0.5, 0.5, -5.),
- Vec3d(0., 0., 1.),
- hit);
- REQUIRE(intersected);
- REQUIRE(hit.t == Approx(5.));
- std::vector<igl::Hit> hits;
- bool intersected2 = AABBTreeIndirect::intersect_ray_all_hits(
- tmesh.its.vertices, tmesh.its.indices,
- tree,
- Vec3d(0.3, 0.5, -5.),
- Vec3d(0., 0., 1.),
- hits);
- REQUIRE(intersected2);
- REQUIRE(hits.size() == 2);
- REQUIRE(hits.front().t == Approx(5.));
- REQUIRE(hits.back().t == Approx(6.));
- size_t hit_idx;
- Vec3d closest_point;
- double squared_distance = AABBTreeIndirect::squared_distance_to_indexed_triangle_set(
- tmesh.its.vertices, tmesh.its.indices,
- tree,
- Vec3d(0.3, 0.5, -5.),
- hit_idx, closest_point);
- REQUIRE(squared_distance == Approx(5. * 5.));
- REQUIRE(closest_point.x() == Approx(0.3));
- REQUIRE(closest_point.y() == Approx(0.5));
- REQUIRE(closest_point.z() == Approx(0.));
- squared_distance = AABBTreeIndirect::squared_distance_to_indexed_triangle_set(
- tmesh.its.vertices, tmesh.its.indices,
- tree,
- Vec3d(0.3, 0.5, 5.),
- hit_idx, closest_point);
- REQUIRE(squared_distance == Approx(4. * 4.));
- REQUIRE(closest_point.x() == Approx(0.3));
- REQUIRE(closest_point.y() == Approx(0.5));
- REQUIRE(closest_point.z() == Approx(1.));
- }
- TEST_CASE("Creating a several 2d lines, testing closest point query", "[AABBIndirect]")
- {
- std::vector<Linef> lines { };
- lines.push_back(Linef(Vec2d(0.0, 0.0), Vec2d(1.0, 0.0)));
- lines.push_back(Linef(Vec2d(1.0, 0.0), Vec2d(1.0, 1.0)));
- lines.push_back(Linef(Vec2d(1.0, 1.0), Vec2d(0.0, 1.0)));
- lines.push_back(Linef(Vec2d(0.0, 1.0), Vec2d(0.0, 0.0)));
- auto tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines);
- size_t hit_idx_out;
- Vec2d hit_point_out;
- auto sqr_dist = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, Vec2d(0.0, 0.0), hit_idx_out,
- hit_point_out);
- REQUIRE(sqr_dist == Approx(0.0));
- REQUIRE((hit_idx_out == 0 || hit_idx_out == 3));
- REQUIRE(hit_point_out.x() == Approx(0.0));
- REQUIRE(hit_point_out.y() == Approx(0.0));
- sqr_dist = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, Vec2d(1.5, 0.5), hit_idx_out,
- hit_point_out);
- REQUIRE(sqr_dist == Approx(0.25));
- REQUIRE(hit_idx_out == 1);
- REQUIRE(hit_point_out.x() == Approx(1.0));
- REQUIRE(hit_point_out.y() == Approx(0.5));
- }
- TEST_CASE("Creating a several 2d lines, testing all lines in radius query", "[AABBIndirect]")
- {
- std::vector<Linef> lines { };
- lines.push_back(Linef(Vec2d(0.0, 0.0), Vec2d(10.0, 0.0)));
- lines.push_back(Linef(Vec2d(-10.0, 10.0), Vec2d(10.0, -10.0)));
- lines.push_back(Linef(Vec2d(-2.0, -1.0), Vec2d(-2.0, 1.0)));
- lines.push_back(Linef(Vec2d(-1.0, -1.0), Vec2d(-1.0, -1.0)));
- lines.push_back(Linef(Vec2d(1.0, 1.0), Vec2d(1.0, 1.0)));
- auto tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines);
- auto indices = AABBTreeLines::all_lines_in_radius(lines, tree, Vec2d{1.0,1.0}, 4.0);
- REQUIRE(std::find(indices.begin(),indices.end(), 0) != indices.end());
- REQUIRE(std::find(indices.begin(),indices.end(), 1) != indices.end());
- REQUIRE(std::find(indices.begin(),indices.end(), 4) != indices.end());
- REQUIRE(indices.size() == 3);
- }
- TEST_CASE("Find the closest point from ExPolys", "[ClosestPoint]") {
- //////////////////////////////
- // 0 - 3
- // |Ex0| 0 - 3
- // | |p |Ex1|
- // 1 - 2 | |
- // 1 - 2
- //[0,0]
- ///////////////////
- ExPolygons ex_polys{
- /*Ex0*/ {{0, 4}, {0, 1}, {2, 1}, {2, 4}},
- /*Ex1*/ {{4, 3}, {4, 0}, {6, 0}, {6, 3}}
- };
- Vec2d p{2.5, 3.5};
- std::vector<Linef> lines;
- auto add_lines = [&lines](const Polygon& poly) {
- for (const auto &line : poly.lines())
- lines.emplace_back(
- line.a.cast<double>(),
- line.b.cast<double>());
- };
- for (const ExPolygon &ex_poly : ex_polys) {
- add_lines(ex_poly.contour);
- for (const Polygon &hole : ex_poly.holes)
- add_lines(hole);
- }
- AABBTreeIndirect::Tree<2, double> tree =
- AABBTreeLines::build_aabb_tree_over_indexed_lines(lines);
- size_t hit_idx_out = std::numeric_limits<size_t>::max();
- Vec2d hit_point_out;
- [[maybe_unused]] double distance_sq =
- AABBTreeLines::squared_distance_to_indexed_lines(
- lines, tree, p, hit_idx_out, hit_point_out, 0.24/* < (0.5*0.5) */);
- CHECK(hit_idx_out == std::numeric_limits<size_t>::max());
- distance_sq = AABBTreeLines::squared_distance_to_indexed_lines(
- lines, tree, p, hit_idx_out, hit_point_out, 0.26);
- CHECK(hit_idx_out != std::numeric_limits<size_t>::max());
- //double distance = sqrt(distance_sq);
- //const Linef &line = lines[hit_idx_out];
- }
- #if 0
- #include "libslic3r/EdgeGrid.hpp"
- #include <iostream>
- #include <ctime>
- #include <ratio>
- #include <chrono>
- TEST_CASE("AABBTreeLines vs SignedDistanceGrid time Benchmark", "[AABBIndirect]")
- {
- std::vector<Points> lines { Points { } };
- std::vector<Linef> linesf { };
- Vec2d prevf { };
- // NOTE: max coord value of the lines is approx 83 mm
- for (int r = 1; r < 1000; ++r) {
- lines[0].push_back(Point::new_scale(Vec2d(exp(0.005f * r) * cos(r), exp(0.005f * r) * cos(r))));
- linesf.emplace_back(prevf, Vec2d(exp(0.005f * r) * cos(r), exp(0.005f * r) * cos(r)));
- prevf = linesf.back().b;
- }
- int build_num = 10000;
- using namespace std::chrono;
- {
- std::cout << "building the tree " << build_num << " times..." << std::endl;
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- for (int i = 0; i < build_num; ++i) {
- volatile auto tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(linesf);
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << "It took " << time_span.count() << " seconds." << std::endl << std::endl;
- }
- {
- std::cout << "building the grid res 1mm ONLY " << build_num/100 << " !!! times..." << std::endl;
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- for (int i = 0; i < build_num/100; ++i) {
- EdgeGrid::Grid grid { };
- grid.create(lines, scaled(1.0), true);
- grid.calculate_sdf();
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << "It took " << time_span.count() << " seconds." << std::endl << std::endl;
- }
- {
- std::cout << "building the grid res 10mm " << build_num << " times..." << std::endl;
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- for (int i = 0; i < build_num; ++i) {
- EdgeGrid::Grid grid { };
- grid.create(lines, scaled(10.0), true);
- grid.calculate_sdf();
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << "It took " << time_span.count() << " seconds." << std::endl << std::endl;
- }
- EdgeGrid::Grid grid10 { };
- grid10.create(lines, scaled(10.0), true);
- coord_t query10_res = scaled(10.0);
- grid10.calculate_sdf();
- EdgeGrid::Grid grid1 { };
- grid1.create(lines, scaled(1.0), true);
- coord_t query1_res = scaled(1.0);
- grid1.calculate_sdf();
- auto tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(linesf);
- int query_num = 10000;
- Points query_points { };
- std::vector<Vec2d> query_pointsf { };
- for (int x = 0; x < query_num; ++x) {
- Vec2d qp { rand() / (double(RAND_MAX) + 1.0f) * 200.0 - 100.0, rand() / (double(RAND_MAX) + 1.0f) * 200.0
- - 100.0 };
- query_pointsf.push_back(qp);
- query_points.push_back(Point::new_scale(qp));
- }
- {
- std::cout << "querying tree " << query_num << " times..." << std::endl;
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- for (const Vec2d &qp : query_pointsf) {
- size_t hit_idx_out;
- Vec2d hit_point_out;
- AABBTreeLines::squared_distance_to_indexed_lines(linesf, tree, qp, hit_idx_out, hit_point_out);
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << "It took " << time_span.count() << " seconds." << std::endl << std::endl;
- }
- {
- std::cout << "querying grid res 1mm " << query_num << " times..." << std::endl;
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- for (const Point &qp : query_points) {
- volatile auto dist = grid1.closest_point_signed_distance(qp, query1_res);
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << "It took " << time_span.count() << " seconds." << std::endl << std::endl;
- }
- {
- std::cout << "querying grid res 10mm " << query_num << " times..." << std::endl;
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- for (const Point &qp : query_points) {
- volatile auto dist = grid10.closest_point_signed_distance(qp, query10_res);
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << "It took " << time_span.count() << " seconds." << std::endl << std::endl;
- }
- std::cout << "Test build and queries together - same number of contour points and query points" << std::endl << std::endl;
- std::vector<int> point_counts { 100, 300, 500, 1000, 3000 };
- for (auto count : point_counts) {
- std::vector<Points> lines { Points { } };
- std::vector<Linef> linesf { };
- Vec2d prevf { };
- Points query_points { };
- std::vector<Vec2d> query_pointsf { };
- for (int x = 0; x < count; ++x) {
- Vec2d cp { rand() / (double(RAND_MAX) + 1.0f) * 200.0 - 100.0, rand() / (double(RAND_MAX) + 1.0f) * 200.0
- - 100.0 };
- lines[0].push_back(Point::new_scale(cp));
- linesf.emplace_back(prevf, cp);
- prevf = linesf.back().b;
- Vec2d qp { rand() / (double(RAND_MAX) + 1.0f) * 200.0 - 100.0, rand() / (double(RAND_MAX) + 1.0f) * 200.0
- - 100.0 };
- query_pointsf.push_back(qp);
- query_points.push_back(Point::new_scale(qp));
- }
- std::cout << "Test for point count: " << count << std::endl;
- {
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- auto tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(linesf);
- for (const Vec2d &qp : query_pointsf) {
- size_t hit_idx_out;
- Vec2d hit_point_out;
- AABBTreeLines::squared_distance_to_indexed_lines(linesf, tree, qp, hit_idx_out, hit_point_out);
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << " Tree took " << time_span.count() << " seconds." << std::endl;
- }
- {
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- EdgeGrid::Grid grid1 { };
- grid1.create(lines, scaled(1.0), true);
- coord_t query1_res = scaled(1.0);
- grid1.calculate_sdf();
- for (const Point &qp : query_points) {
- volatile auto dist = grid1.closest_point_signed_distance(qp, query1_res);
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << " Grid 1mm took " << time_span.count() << " seconds." << std::endl;
- }
- {
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- EdgeGrid::Grid grid10 { };
- grid10.create(lines, scaled(10.0), true);
- coord_t query10_res = scaled(10.0);
- grid10.calculate_sdf();
- for (const Point &qp : query_points) {
- volatile auto dist = grid10.closest_point_signed_distance(qp, query10_res);
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << " Grid 10mm took " << time_span.count() << " seconds." << std::endl;
- }
- }
- std::cout << "Test build and queries together - same number of contour points and query points" << std::endl <<
- "And with limited contour edge length to 4mm " << std::endl;
- for (auto count : point_counts) {
- std::vector<Points> lines { Points { } };
- std::vector<Linef> linesf { };
- Vec2d prevf { };
- Points query_points { };
- std::vector<Vec2d> query_pointsf { };
- for (int x = 0; x < count; ++x) {
- Vec2d cp { rand() / (double(RAND_MAX) + 1.0f) * 200.0 - 100.0, rand() / (double(RAND_MAX) + 1.0f) * 200.0
- - 100.0 };
- Vec2d contour = prevf + cp.normalized()*4.0; // limits the cnotour edge len to 4mm
- lines[0].push_back(Point::new_scale(contour));
- linesf.emplace_back(prevf, contour);
- prevf = linesf.back().b;
- Vec2d qp { rand() / (double(RAND_MAX) + 1.0f) * 200.0 - 100.0, rand() / (double(RAND_MAX) + 1.0f) * 200.0
- - 100.0 };
- query_pointsf.push_back(qp);
- query_points.push_back(Point::new_scale(qp));
- }
- std::cout << "Test for point count: " << count << std::endl;
- {
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- auto tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(linesf);
- for (const Vec2d &qp : query_pointsf) {
- size_t hit_idx_out;
- Vec2d hit_point_out;
- AABBTreeLines::squared_distance_to_indexed_lines(linesf, tree, qp, hit_idx_out, hit_point_out);
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << " Tree took " << time_span.count() << " seconds." << std::endl;
- }
- {
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- EdgeGrid::Grid grid1 { };
- grid1.create(lines, scaled(1.0), true);
- coord_t query1_res = scaled(1.0);
- grid1.calculate_sdf();
- for (const Point &qp : query_points) {
- volatile auto dist = grid1.closest_point_signed_distance(qp, query1_res);
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << " Grid 1mm took " << time_span.count() << " seconds." << std::endl;
- }
- {
- high_resolution_clock::time_point t1 = high_resolution_clock::now();
- EdgeGrid::Grid grid10 { };
- grid10.create(lines, scaled(10.0), true);
- coord_t query10_res = scaled(10.0);
- grid10.calculate_sdf();
- for (const Point &qp : query_points) {
- volatile auto dist = grid10.closest_point_signed_distance(qp, query10_res);
- }
- high_resolution_clock::time_point t2 = high_resolution_clock::now();
- duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
- std::cout << " Grid 10mm took " << time_span.count() << " seconds." << std::endl;
- }
- }
- }
- #endif
|