File indexing completed on 2025-12-16 09:25:16
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/GenericCuboidVolumeBounds.hpp"
0013 #include "Acts/Geometry/Volume.hpp"
0014 #include "Acts/Utilities/BoundingBox.hpp"
0015 #include "Acts/Utilities/Frustum.hpp"
0016 #include "Acts/Utilities/Ray.hpp"
0017 #include "Acts/Visualization/IVisualization3D.hpp"
0018 #include "Acts/Visualization/PlyVisualization3D.hpp"
0019 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0020
0021 #include <algorithm>
0022 #include <array>
0023 #include <cmath>
0024 #include <cstdio>
0025 #include <filesystem>
0026 #include <fstream>
0027 #include <iostream>
0028 #include <memory>
0029 #include <numbers>
0030 #include <set>
0031 #include <sstream>
0032 #include <string>
0033 #include <utility>
0034 #include <vector>
0035
0036 using namespace Acts;
0037
0038 namespace ActsTests {
0039
0040 struct Object {};
0041
0042 using ObjectBBox = AxisAlignedBoundingBox<Object, double, 3>;
0043
0044 using Vector2F = Eigen::Matrix<double, 2, 1>;
0045 using Vector3F = Eigen::Matrix<double, 3, 1>;
0046 using AngleAxis3F = Eigen::AngleAxis<double>;
0047
0048 std::filesystem::path tmp_path = []() {
0049 auto tmpPath = std::filesystem::temp_directory_path() / "acts_unit_tests";
0050 std::filesystem::create_directory(tmpPath);
0051 std::cout << "Writing test output to: " << tmpPath << std::endl;
0052 return tmpPath;
0053 }();
0054
0055 std::ofstream tmp(const std::string& path) {
0056 return std::ofstream{(tmp_path / path).string()};
0057 }
0058
0059 BOOST_AUTO_TEST_SUITE(UtilitiesSuite)
0060
0061 BOOST_AUTO_TEST_CASE(box_construction) {
0062 BOOST_TEST_CONTEXT("2D") {
0063 Object o;
0064 using Box = AxisAlignedBoundingBox<Object, double, 2>;
0065 Box bb(&o, {-1, -1}, {2, 2});
0066
0067 typename Box::transform_type rot;
0068 rot = Eigen::Rotation2D<double>(std::numbers::pi / 7.);
0069 Box bb_rot = bb.transformed(rot);
0070
0071 CHECK_CLOSE_ABS(bb_rot.min(), Vector2F(-1.76874, -1.33485), 1e-4);
0072 CHECK_CLOSE_ABS(bb_rot.max(), Vector2F(2.23582, 2.66971), 1e-4);
0073 }
0074
0075 BOOST_TEST_CONTEXT("3D") {
0076 Object o;
0077 using Box = AxisAlignedBoundingBox<Object, double, 3>;
0078 Box bb(&o, {-1, -1, -1}, {2, 2, 2});
0079
0080 typename Box::transform_type rot;
0081 rot = AngleAxis3F(std::numbers::pi / 3., Vector3F::UnitZ());
0082 Box bb_rot = bb.transformed(rot);
0083
0084 CHECK_CLOSE_ABS(bb_rot.min(), Vector3F(-2.23205, -1.36603, -1), 1e-4);
0085 CHECK_CLOSE_ABS(bb_rot.max(), Vector3F(1.86603, 2.73205, 2), 1e-4);
0086
0087 rot *= AngleAxis3F(std::numbers::pi / 5., Vector3F(1, 1, 0).normalized());
0088 Box bb_rot2 = bb.transformed(rot);
0089
0090 CHECK_CLOSE_ABS(bb_rot2.min(), Vector3F(-2.40848, -1.51816, -2.0559), 1e-4);
0091 CHECK_CLOSE_ABS(bb_rot2.max(), Vector3F(2.61021, 3.03631, 2.86491), 1e-4);
0092 }
0093 }
0094
0095 BOOST_AUTO_TEST_CASE(intersect_points) {
0096 using VertexType = ObjectBBox::VertexType;
0097
0098 Object o;
0099 ObjectBBox bb(&o, {0, 0, 0}, {1, 1, 1});
0100 VertexType p;
0101
0102 p = {0.5, 0.5, 0.5};
0103 BOOST_CHECK(bb.intersect(p));
0104 p = {0.25, 0.25, 0.25};
0105 BOOST_CHECK(bb.intersect(p));
0106 p = {0.75, 0.75, 0.75};
0107 BOOST_CHECK(bb.intersect(p));
0108
0109
0110 p = {0, 0, 0};
0111 BOOST_CHECK(bb.intersect(p));
0112
0113 p = {1.0, 1.0, 1.0};
0114 BOOST_CHECK(!bb.intersect(p));
0115
0116
0117 p = {2, 0, 0};
0118 BOOST_CHECK(!bb.intersect(p));
0119 p = {0, 2, 0};
0120 BOOST_CHECK(!bb.intersect(p));
0121 p = {0, 0, 2};
0122 BOOST_CHECK(!bb.intersect(p));
0123 p = {2, 2, 0};
0124 BOOST_CHECK(!bb.intersect(p));
0125 p = {2, 0, 2};
0126 BOOST_CHECK(!bb.intersect(p));
0127 p = {2, 2, 2};
0128 BOOST_CHECK(!bb.intersect(p));
0129
0130 p = {-1, 0, 0};
0131 BOOST_CHECK(!bb.intersect(p));
0132 p = {0, -1, 0};
0133 BOOST_CHECK(!bb.intersect(p));
0134 p = {0, 0, -1};
0135 BOOST_CHECK(!bb.intersect(p));
0136 p = {-1, -1, 0};
0137 BOOST_CHECK(!bb.intersect(p));
0138 p = {-1, 0, -1};
0139 BOOST_CHECK(!bb.intersect(p));
0140 p = {-1, -1, -1};
0141 BOOST_CHECK(!bb.intersect(p));
0142 }
0143
0144 BOOST_AUTO_TEST_CASE(intersect_rays) {
0145 BOOST_TEST_CONTEXT("2D") {
0146 using Box = AxisAlignedBoundingBox<Object, double, 2>;
0147
0148 Object o;
0149 Box bb(&o, {-1, -1}, {1, 1});
0150
0151
0152
0153 Ray<double, 2> ray({-2, 0}, {1, 0});
0154 BOOST_CHECK(bb.intersect(ray));
0155
0156 ray = {{-2, 2}, {1, 0}};
0157 BOOST_CHECK(!bb.intersect(ray));
0158
0159 ray = {{-2, -2}, {1, 0}};
0160 BOOST_CHECK(!bb.intersect(ray));
0161
0162
0163 ray = {{-2, 1}, {1, 0}};
0164 BOOST_CHECK(!bb.intersect(ray));
0165
0166
0167
0168
0169
0170
0171 ray = {{2, 0}, {1, 0}};
0172 BOOST_CHECK(!bb.intersect(ray));
0173
0174
0175
0176 ray = {{2, 0}, {-1, 0}};
0177 BOOST_CHECK(bb.intersect(ray));
0178
0179 ray = {{2, 2}, {-1, 0}};
0180 BOOST_CHECK(!bb.intersect(ray));
0181
0182 ray = {{2, -2}, {-1, 0}};
0183 BOOST_CHECK(!bb.intersect(ray));
0184
0185
0186 ray = {{2, 1}, {-1, 0}};
0187 BOOST_CHECK(!bb.intersect(ray));
0188
0189
0190
0191
0192
0193
0194
0195 ray = {{0, -2}, {0, 1}};
0196 BOOST_CHECK(bb.intersect(ray));
0197
0198 ray = {{2, -2}, {0, 1}};
0199 BOOST_CHECK(!bb.intersect(ray));
0200
0201 ray = {{-2, -2}, {0, 1}};
0202 BOOST_CHECK(!bb.intersect(ray));
0203
0204
0205 ray = {{1, -2}, {0, 1}};
0206 BOOST_CHECK(!bb.intersect(ray));
0207
0208
0209 ray = {{-1, -2}, {0, 1}};
0210 BOOST_CHECK(!bb.intersect(ray));
0211
0212
0213 ray = {{0, -2}, {0, -1}};
0214 BOOST_CHECK(!bb.intersect(ray));
0215
0216
0217
0218 ray = {{0, 2}, {0, -1}};
0219 BOOST_CHECK(bb.intersect(ray));
0220
0221 ray = {{2, 2}, {0, -1}};
0222 BOOST_CHECK(!bb.intersect(ray));
0223
0224 ray = {{-2, 2}, {0, -1}};
0225 BOOST_CHECK(!bb.intersect(ray));
0226
0227
0228 ray = {{1, 2}, {0, -1}};
0229 BOOST_CHECK(!bb.intersect(ray));
0230
0231
0232 ray = {{-1, 2}, {0, -1}};
0233 BOOST_CHECK(!bb.intersect(ray));
0234
0235
0236 ray = {{0, 2}, {0, 1}};
0237 BOOST_CHECK(!bb.intersect(ray));
0238
0239
0240
0241 ray = {{-2, 0}, {0.5, 0.25}};
0242 BOOST_CHECK(bb.intersect(ray));
0243
0244 ray = {{-2, 0}, {0.5, 0.4}};
0245 BOOST_CHECK(bb.intersect(ray));
0246
0247 ray = {{-2, 0}, {0.5, 0.6}};
0248 BOOST_CHECK(!bb.intersect(ray));
0249
0250 ray = {{-2, 0}, {0.5, 0.1}};
0251 BOOST_CHECK(bb.intersect(ray));
0252
0253 ray = {{-2, 0}, {0.5, -0.4}};
0254 BOOST_CHECK(bb.intersect(ray));
0255
0256 ray = {{-2, 0}, {0.5, -0.6}};
0257 BOOST_CHECK(!bb.intersect(ray));
0258
0259 ray = {{-2, 0}, {0.1, 0.5}};
0260 BOOST_CHECK(!bb.intersect(ray));
0261
0262
0263 ray = {{0, 0}, {-1, 0}};
0264 BOOST_CHECK(bb.intersect(ray));
0265 ray = {{0, 0}, {1, 0}};
0266 BOOST_CHECK(bb.intersect(ray));
0267 ray = {{0, 0}, {0, -1}};
0268 BOOST_CHECK(bb.intersect(ray));
0269 ray = {{0, 0}, {0, 1}};
0270 BOOST_CHECK(bb.intersect(ray));
0271 }
0272
0273 BOOST_TEST_CONTEXT("3D visualize") {
0274 Object o;
0275
0276
0277 ObjectBBox bb3(&o, {-1, -1, -1}, {1, 1, 1});
0278 Ray<double, 3> ray3({0, 0, -2}, {0, 0, 1});
0279 BOOST_CHECK(bb3.intersect(ray3));
0280
0281 PlyVisualization3D<double> ply;
0282
0283 ray3.draw(ply);
0284 auto os = tmp("ray3d.ply");
0285 os << ply << std::flush;
0286 os.close();
0287 }
0288
0289 BOOST_TEST_CONTEXT("3D") {
0290 using VertexType3 = ObjectBBox::VertexType;
0291 Object o;
0292
0293
0294 ObjectBBox bb3(&o, {-1, -1, -1}, {1, 1, 1});
0295 Ray<double, 3> ray3({0, 0, -2}, {0, 0, 1});
0296 BOOST_CHECK(bb3.intersect(ray3));
0297
0298
0299 ray3 = {{0, 0, -2}, {0, 0, -1}};
0300 BOOST_CHECK(!bb3.intersect(ray3));
0301
0302 ray3 = {{0, 2, -2}, {0, 0, 1}};
0303 BOOST_CHECK(!bb3.intersect(ray3));
0304
0305 ray3 = {{0, -2, -2}, {0, 0, 1}};
0306 BOOST_CHECK(!bb3.intersect(ray3));
0307
0308
0309 ray3 = {{0, 1, -2}, {0, 0, 1}};
0310 BOOST_CHECK(!bb3.intersect(ray3));
0311
0312
0313
0314
0315
0316
0317 ray3 = {{-1, 0, -2}, {0, 0, 1}};
0318 BOOST_CHECK(!bb3.intersect(ray3));
0319
0320
0321 ray3 = {{1, 0, -2}, {0, 0, 1}};
0322 BOOST_CHECK(!bb3.intersect(ray3));
0323
0324 ray3 = {{-0.95, 0, -2}, {0, 0, 1}};
0325 BOOST_CHECK(bb3.intersect(ray3));
0326
0327
0328 ObjectBBox::VertexType p(0, 0, -2);
0329
0330 ray3 = {p, VertexType3(1, 1, 1) - p};
0331 BOOST_CHECK(bb3.intersect(ray3));
0332
0333 ray3 = {p, VertexType3(-1, 1, 1) - p};
0334 BOOST_CHECK(bb3.intersect(ray3));
0335
0336 ray3 = {p, VertexType3(-1, -1, 1) - p};
0337 BOOST_CHECK(bb3.intersect(ray3));
0338
0339 ray3 = {p, VertexType3(1, -1, 1) - p};
0340 BOOST_CHECK(bb3.intersect(ray3));
0341
0342 ray3 = {p, VertexType3(1.1, 0, -1) - p};
0343 BOOST_CHECK(!bb3.intersect(ray3));
0344
0345 ray3 = {p, VertexType3(-1.1, 0, -1) - p};
0346 BOOST_CHECK(!bb3.intersect(ray3));
0347
0348 ray3 = {p, VertexType3(0, 1.1, -1) - p};
0349 BOOST_CHECK(!bb3.intersect(ray3));
0350
0351 ray3 = {p, VertexType3(0, -1.1, -1) - p};
0352 BOOST_CHECK(!bb3.intersect(ray3));
0353
0354 ray3 = {p, VertexType3(0.9, 0, -1) - p};
0355 BOOST_CHECK(bb3.intersect(ray3));
0356
0357 ray3 = {p, VertexType3(-0.9, 0, -1) - p};
0358 BOOST_CHECK(bb3.intersect(ray3));
0359
0360 ray3 = {p, VertexType3(0, 0.9, -1) - p};
0361 BOOST_CHECK(bb3.intersect(ray3));
0362
0363 ray3 = {p, VertexType3(0, -0.9, -1) - p};
0364 BOOST_CHECK(bb3.intersect(ray3));
0365
0366 ray3 = {{0, 0, 0}, {1, 0, 0}};
0367 BOOST_CHECK(bb3.intersect(ray3));
0368 ray3 = {{0, 0, 0}, {0, 1, 0}};
0369 BOOST_CHECK(bb3.intersect(ray3));
0370 ray3 = {{0, 0, 0}, {0, 0, 1}};
0371 BOOST_CHECK(bb3.intersect(ray3));
0372
0373 ray3 = {{0, 0, 0}, {-1, 0, 0}};
0374 BOOST_CHECK(bb3.intersect(ray3));
0375 ray3 = {{0, 0, 0}, {0, -1, 0}};
0376 BOOST_CHECK(bb3.intersect(ray3));
0377 ray3 = {{0, 0, 0}, {0, 0, -1}};
0378 BOOST_CHECK(bb3.intersect(ray3));
0379 }
0380 }
0381
0382 BOOST_AUTO_TEST_CASE(ray_obb_intersect) {
0383 using Ray = Ray<double, 3>;
0384
0385 std::array<Vector3, 8> vertices{};
0386 vertices = {{{0, 0, 0},
0387 {2, 0, 0.4},
0388 {2, 1, 0.4},
0389 {0, 1, 0},
0390 {0, 0, 1},
0391 {1.8, 0, 1},
0392 {1.8, 1, 1},
0393 {0, 1, 1}}};
0394 auto cubo = std::make_shared<GenericCuboidVolumeBounds>(vertices);
0395 auto trf = Transform3(
0396 Translation3(Vector3(0, 8, -5)) *
0397 AngleAxis3(std::numbers::pi / 3., Vector3(1, -3, 9).normalized()));
0398
0399 Volume vol(trf, cubo);
0400
0401 PlyVisualization3D<double> ply;
0402
0403 Transform3 trl = Transform3::Identity();
0404 trl.translation() = trf.translation();
0405
0406 cubo->draw(ply);
0407
0408 auto obb = vol.orientedBoundingBox();
0409 obb.draw(ply, {200, 0, 0});
0410
0411 ply.clear();
0412
0413 Vector3 origin(10, -20, 6);
0414 Vector3 centroid(0., 0., 0.);
0415
0416 for (const auto& vtx_ : vertices) {
0417 Vector3 vtx = trf * vtx_;
0418 centroid += vtx;
0419 }
0420
0421
0422 centroid *= 0.125;
0423
0424
0425 for (const auto& vtx_ : vertices) {
0426 Vector3 vtx = trf * vtx_;
0427
0428
0429
0430 Ray ray(origin, (vtx - origin).normalized());
0431 ray = ray.transformed(trf.inverse());
0432 BOOST_CHECK(obb.intersect(ray));
0433 ray.draw(ply, (vtx - origin).norm());
0434
0435
0436
0437 vtx += (vtx - centroid);
0438 ray = Ray(origin, (vtx - origin).normalized());
0439 ray = ray.transformed(trf.inverse());
0440 BOOST_CHECK(!obb.intersect(ray));
0441 ray.draw(ply, (vtx - origin).norm());
0442 }
0443 }
0444
0445 BOOST_AUTO_TEST_CASE(frustum_intersect) {
0446 BOOST_TEST_CONTEXT("2D") {
0447 auto make_svg = [](const std::string& fname, std::size_t width,
0448 std::size_t height) {
0449 auto os = tmp(fname);
0450 os << "<?xml version=\"1.0\" standalone=\"no\"?>\n";
0451 os << "<svg width=\"" << width << "\" height=\"" << height
0452 << "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n";
0453 return os;
0454 };
0455
0456 using Frustum2 = Frustum<double, 2, 2>;
0457
0458 std::ofstream os;
0459
0460 const std::size_t svgWidth = 1000;
0461 const std::size_t svgHeight = svgWidth;
0462 const std::size_t nSteps = 10;
0463
0464
0465 const double min = -20;
0466 const double max = 20;
0467 os = make_svg("frust2d_parameters.svg", svgWidth, svgHeight);
0468
0469 const double step = (max - min) / nSteps;
0470 for (std::size_t i = 0; i <= nSteps; i++) {
0471 for (std::size_t j = 0; j <= nSteps; j++) {
0472 Vector2F dir(1, 0);
0473 Vector2F origin(min + step * i, min + step * j);
0474 origin.x() *= 1.10;
0475 Eigen::Rotation2D<double> rot(2 * std::numbers::pi / nSteps * i);
0476 double angle = std::numbers::pi / 2. / nSteps * j;
0477 Frustum2 fr(origin, rot * dir, angle);
0478 fr.svg(os, svgWidth, svgHeight, 2);
0479 }
0480 }
0481
0482 os << "</svg>";
0483 os.close();
0484
0485 const double unit = 20.;
0486
0487 using Box = AxisAlignedBoundingBox<Object, double, 2>;
0488 Object o;
0489 Box::Size size(Eigen::Matrix<double, 2, 1>(2, 2));
0490
0491 const double minX = -20.;
0492 const double minY = -20.;
0493 const double maxX = 20.;
0494 const double maxY = 20.;
0495 const double stepX = (maxX - minX) / nSteps;
0496 const double stepY = (maxY - minY) / nSteps;
0497
0498 std::set<std::size_t> idxsAct;
0499
0500
0501 std::vector<std::pair<Frustum2, std::set<std::size_t>>> frExp;
0502 frExp = {
0503 {Frustum2({0, 0}, {1, 0}, std::numbers::pi / 2.),
0504 {60, 70, 71, 72, 80, 81, 82, 83, 84, 90, 91, 92,
0505 93, 94, 95, 96, 100, 101, 102, 103, 104, 105, 106, 107,
0506 108, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120}
0507 },
0508 {Frustum2({0, 0}, {1, 0}, 0.5 * std::numbers::pi / 2.),
0509 {60, 71, 81, 82, 83, 92, 93, 94, 102,
0510 103, 104, 105, 106, 113, 114, 115, 116, 117}
0511 },
0512 {Frustum2({0, 0}, {1, 0}, 0.2 * std::numbers::pi / 2.),
0513 {60, 71, 82, 93, 104, 114, 115, 116}
0514 },
0515 {Frustum2({0, 0}, {1, 0}, 3 * std::numbers::pi / 4.),
0516 {60, 68, 69, 70, 71, 72, 73, 74, 77, 78, 79, 80, 81, 82, 83,
0517 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
0518 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
0519 112, 113, 114, 115, 116, 117, 118, 119, 120}
0520 },
0521 {Frustum2({0, 0}, {0, 1}, 0.5 * std::numbers::pi / 2.),
0522 {42, 43, 51, 52, 53, 54, 60, 61, 62, 63, 64, 65, 73, 74, 75, 76, 86, 87}
0523 },
0524 {Frustum2({0, 0}, {-1, 0}, 0.5 * std::numbers::pi / 2.),
0525 {3, 4, 5, 6, 7, 14, 15, 16, 17, 18, 26, 27, 28, 37, 38, 39, 49, 60}
0526 },
0527 {Frustum2({0, 0}, {0, -1}, 0.5 * std::numbers::pi / 2.),
0528 {33, 34, 44, 45, 46, 47, 55, 56, 57, 58, 59, 60, 66, 67, 68, 69, 77, 78}
0529 },
0530 {Frustum2({0, 0}, {1, 1}, 0.5 * std::numbers::pi / 2.),
0531 {60, 72, 73, 74, 83, 84, 85, 86, 87, 94, 95, 96, 97, 98, 106, 107,
0532 108, 109, 117, 118, 119, 120}
0533 },
0534 {Frustum2({0, 0}, {-1, 1}, 0.5 * std::numbers::pi / 2.),
0535 {7, 8, 9, 10, 18, 19, 20, 21, 28, 29, 30, 31, 32, 39, 40, 41, 42,
0536 43, 50, 51, 52, 60}
0537 },
0538 {Frustum2({0, 0}, {-1, -1}, 0.5 * std::numbers::pi / 2.),
0539 {0, 1, 2, 3, 11, 12, 13, 14, 22, 23, 24, 25, 26, 33, 34, 35, 36,
0540 37, 46, 47, 48, 60}
0541 },
0542 {Frustum2({0, 0}, {1, -1}, 0.5 * std::numbers::pi / 2.),
0543 {60, 68, 69, 70, 77, 78, 79, 80, 81, 88, 89, 90, 91, 92, 99, 100,
0544 101, 102, 110, 111, 112, 113}
0545 },
0546 {Frustum2({1, 1}, {1, -1}, std::numbers::pi / 2.),
0547 {55, 56, 57, 58, 59, 60, 66, 67, 68, 69, 70, 71, 77, 78, 79, 80,
0548 81, 82, 88, 89, 90, 91, 92, 93, 99, 100, 101, 102, 103, 104, 110, 111, 112, 113, 114, 115}
0549 },
0550 {Frustum2({-1, -1}, {1, -1}, std::numbers::pi / 2.),
0551 {55, 56, 57, 58, 59, 60, 66, 67, 68, 69, 70, 71, 77, 78, 79, 80,
0552 81, 82, 88, 89, 90, 91, 92, 93, 99, 100, 101, 102, 103, 104, 110, 111, 112, 113, 114, 115}
0553 },
0554 {Frustum2({10, -10}, {1, 1}, 0.5 * std::numbers::pi / 2.),
0555 {91, 92, 102, 103, 104, 105, 114, 115, 116, 117, 118, 119}
0556 },
0557 {Frustum2({-10.3, 12.8}, {0.3, -1}, 0.5 * std::numbers::pi / 2.),
0558 {22, 23, 24, 25, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 41,
0559 44, 45, 46, 47, 48, 49, 50, 55, 56, 57, 58, 59, 60, 66, 67, 68,
0560 69, 70, 77, 78, 79, 80, 88, 89, 99}
0561 },
0562 {Frustum2({17.2, 19.45}, {-1, -0.1}, 0.5 * std::numbers::pi / 2.),
0563 {5, 6, 7, 8, 9, 10, 17, 18, 19, 20, 21, 28, 29, 30, 31, 32, 40,
0564 41, 42, 43, 51, 52, 53, 54, 63, 64, 65, 74, 75, 76, 86, 87, 97,
0565 98, 109}
0566 },
0567 };
0568
0569
0570 for (std::size_t l = 0; l < frExp.size(); l++) {
0571 const Frustum2& fr = frExp.at(l).first;
0572 const std::set<std::size_t>& idxsExp = frExp.at(l).second;
0573 std::stringstream ss;
0574 ss << "frust2d_test_" << l << ".svg";
0575 os = make_svg(ss.str(), svgWidth, svgHeight);
0576
0577 idxsAct.clear();
0578
0579 std::vector<Box> boxes;
0580 boxes.reserve((nSteps + 1) * (nSteps + 1));
0581 for (std::size_t i = 0; i <= nSteps; i++) {
0582 for (std::size_t j = 0; j <= nSteps; j++) {
0583 boxes.emplace_back(
0584 &o,
0585 Eigen::Matrix<double, 2, 1>{minX + i * stepX, minY + j * stepY},
0586 size);
0587 std::stringstream st;
0588 st << boxes.size() - 1;
0589
0590 std::string color = "red";
0591 if (boxes.back().intersect(fr)) {
0592 color = "green";
0593 idxsAct.insert(boxes.size() - 1);
0594 }
0595
0596 boxes.back().svg(os, svgWidth, svgHeight, unit, st.str(), color);
0597 }
0598 }
0599
0600 BOOST_CHECK(idxsAct == idxsExp);
0601
0602 fr.svg(os, svgWidth, svgHeight, maxX, unit);
0603 os << "</svg>";
0604
0605 os.close();
0606 }
0607 }
0608
0609 PlyVisualization3D<double> helper;
0610 BOOST_TEST_CONTEXT("3D - 3 Sides") {
0611 using Frustum3 = Frustum<double, 3, 3>;
0612 std::ofstream os;
0613 std::size_t n = 10;
0614 const std::size_t nSteps = 5;
0615 double min = -10;
0616 double max = 10;
0617 double step = (max - min) / nSteps;
0618
0619
0620 auto make = [&](double angle, const Vector3F& origin,
0621 std::ofstream& osTmp) {
0622 helper.clear();
0623 double far = 1.;
0624 Frustum3 fr(origin, {0, 0, 1}, angle);
0625 fr.draw(helper, far);
0626 fr = Frustum3(origin, {0, 0, -1}, angle);
0627 fr.draw(helper, far);
0628 fr = Frustum3(origin, {1, 0, 0}, angle);
0629 fr.draw(helper, far);
0630 fr = Frustum3(origin, {-1, 0, 0}, angle);
0631 fr.draw(helper, far);
0632
0633 fr = Frustum3(origin, {0, 1, 0}, angle);
0634 fr.draw(helper, far);
0635 fr = Frustum3(origin, {0, -1, 0}, angle);
0636 fr.draw(helper, far);
0637
0638 osTmp << helper << std::flush;
0639
0640 helper.clear();
0641 };
0642
0643 os = std::ofstream("frust3d_dir.ply");
0644 for (std::size_t i = 0; i <= nSteps; i++) {
0645 for (std::size_t j = 0; j <= nSteps; j++) {
0646 for (std::size_t k = 0; k <= nSteps; k++) {
0647 Vector3F origin(min + i * step, min + j * step, min + k * step);
0648 make(std::numbers::pi / 4., origin, os);
0649 }
0650 }
0651 }
0652 os.close();
0653
0654 os = tmp("frust3D_angle.ply");
0655 helper.clear();
0656 for (std::size_t i = 0; i <= n; i++) {
0657 Vector3F origin(i * 4, 0, 0);
0658 AngleAxis3F rot(std::numbers::pi / n * i, Vector3F::UnitY());
0659 double angle = (std::numbers::pi / 2.) / n * (1 + i);
0660 Vector3F dir(1, 0, 0);
0661 Frustum3 fr(origin, rot * dir, angle);
0662 fr.draw(helper, 2);
0663 }
0664
0665 os << helper << std::flush;
0666 os.close();
0667
0668 std::set<std::size_t> idxsAct;
0669
0670 std::vector<std::pair<Frustum3, std::set<std::size_t>>> frExp;
0671 frExp = {
0672 {Frustum3({0, 0, 0}, {1, 0, 0}, std::numbers::pi / 2.),
0673 {
0674 665, 763, 774, 775, 785, 786, 787, 788, 796, 797, 807,
0675 872, 873, 883, 884, 885, 886, 894, 895, 896, 897, 898,
0676 905, 906, 907, 908, 909, 910, 911, 916, 917, 918, 919,
0677 920, 927, 928, 929, 930, 938, 939, 970, 971, 981, 982,
0678 983, 992, 993, 994, 995, 996, 1003, 1004, 1005, 1006, 1007,
0679 1008, 1009, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1025,
0680 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1036, 1037, 1038,
0681 1039, 1040, 1041, 1042, 1043, 1047, 1048, 1049, 1050, 1051, 1052,
0682 1053, 1058, 1059, 1060, 1061, 1062, 1069, 1070, 1071, 1080, 1081,
0683 1090, 1091, 1092, 1093, 1094, 1101, 1102, 1103, 1104, 1105, 1106,
0684 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1123, 1124, 1125,
0685 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1134, 1135, 1136, 1137,
0686 1138, 1139, 1140, 1141, 1142, 1143, 1145, 1146, 1147, 1148, 1149,
0687 1150, 1151, 1152, 1153, 1154, 1156, 1157, 1158, 1159, 1160, 1161,
0688 1162, 1163, 1164, 1165, 1167, 1168, 1169, 1170, 1171, 1172, 1173,
0689 1174, 1175, 1176, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185,
0690 1189, 1190, 1191, 1192, 1193, 1194, 1200, 1201, 1202, 1203, 1204,
0691 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1221, 1222, 1223,
0692 1224, 1225, 1226, 1227, 1228, 1229, 1232, 1233, 1234, 1235, 1236,
0693 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247,
0694 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258,
0695 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269,
0696 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280,
0697 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291,
0698 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302,
0699 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313,
0700 1314, 1315, 1316, 1317, 1320, 1321, 1322, 1323, 1324, 1325, 1326,
0701 1327,
0702 }},
0703 {Frustum3({0, 0, 0}, {0, 1, 0}, std::numbers::pi / 2.),
0704 {93, 102, 103, 104, 105, 106, 112, 113, 114, 115, 116,
0705 117, 118, 203, 213, 214, 215, 223, 224, 225, 226, 227,
0706 233, 234, 235, 236, 237, 238, 239, 324, 333, 334, 335,
0707 336, 337, 343, 344, 345, 346, 347, 348, 349, 353, 354,
0708 355, 356, 357, 358, 359, 360, 361, 434, 444, 445, 446,
0709 454, 455, 456, 457, 458, 464, 465, 466, 467, 468, 469,
0710 470, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482,
0711 483, 555, 564, 565, 566, 567, 568, 574, 575, 576, 577,
0712 578, 579, 580, 584, 585, 586, 587, 588, 589, 590, 591,
0713 592, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603,
0714 604, 665, 675, 676, 677, 685, 686, 687, 688, 689, 695,
0715 696, 697, 698, 699, 700, 701, 704, 705, 706, 707, 708,
0716 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719,
0717 720, 721, 722, 723, 724, 725, 795, 796, 797, 798, 799,
0718 805, 806, 807, 808, 809, 810, 811, 815, 816, 817, 818,
0719 819, 820, 821, 822, 823, 825, 826, 827, 828, 829, 830,
0720 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841,
0721 842, 843, 844, 845, 846, 926, 927, 928, 929, 930, 931,
0722 932, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944,
0723 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955,
0724 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966,
0725 967, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065,
0726 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076,
0727 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087,
0728 1088, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197,
0729 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208,
0730 1209, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329,
0731 1330}},
0732 {Frustum3({0, 0, 0}, {0, 0, 1}, std::numbers::pi / 2.),
0733 {32, 42, 43, 53, 54, 63, 64, 65, 75, 76, 86,
0734 87, 98, 153, 163, 164, 173, 174, 175, 183, 184, 185,
0735 186, 195, 196, 197, 207, 208, 219, 263, 273, 274, 283,
0736 284, 285, 294, 295, 296, 304, 305, 306, 307, 316, 317,
0737 318, 327, 328, 329, 339, 340, 351, 373, 384, 394, 395,
0738 404, 405, 406, 414, 415, 416, 417, 424, 425, 426, 427,
0739 428, 436, 437, 438, 439, 448, 449, 450, 460, 461, 472,
0740 483, 494, 504, 505, 514, 515, 516, 524, 525, 526, 527,
0741 535, 536, 537, 538, 545, 546, 547, 548, 549, 557, 558,
0742 559, 560, 568, 569, 570, 571, 580, 581, 582, 592, 593,
0743 604, 614, 615, 625, 626, 635, 636, 637, 645, 646, 647,
0744 648, 655, 656, 657, 658, 659, 665, 666, 667, 668, 669,
0745 670, 677, 678, 679, 680, 681, 689, 690, 691, 692, 701,
0746 702, 703, 713, 714, 724, 725, 735, 736, 745, 746, 747,
0747 755, 756, 757, 758, 765, 766, 767, 768, 769, 776, 777,
0748 778, 779, 780, 787, 788, 789, 790, 791, 798, 799, 800,
0749 801, 802, 809, 810, 811, 812, 813, 821, 822, 823, 824,
0750 833, 834, 835, 845, 846, 855, 856, 857, 866, 867, 868,
0751 876, 877, 878, 879, 887, 888, 889, 890, 898, 899, 900,
0752 901, 909, 910, 911, 912, 920, 921, 922, 923, 931, 932,
0753 933, 934, 942, 943, 944, 945, 954, 955, 956, 965, 966,
0754 967, 976, 977, 978, 987, 988, 989, 998, 999, 1000, 1009,
0755 1010, 1011, 1020, 1021, 1022, 1031, 1032, 1033, 1042, 1043, 1044,
0756 1053, 1054, 1055, 1064, 1065, 1066, 1075, 1076, 1077, 1086, 1087,
0757 1088, 1098, 1099, 1109, 1110, 1120, 1121, 1131, 1132, 1142, 1143,
0758 1153, 1154, 1164, 1165, 1175, 1176, 1186, 1187, 1197, 1198, 1208,
0759 1209, 1220, 1231, 1242, 1253, 1264, 1275, 1286, 1297, 1308, 1319,
0760 1330}},
0761 {Frustum3({0, 0, 0}, {0, 0, 1}, std::numbers::pi / 4.),
0762 {186, 305, 306, 307, 416, 417, 425, 426, 427, 428, 438, 439,
0763 527, 536, 537, 538, 545, 546, 547, 548, 549, 558, 559, 560,
0764 571, 647, 648, 656, 657, 658, 659, 665, 666, 667, 668, 669,
0765 670, 678, 679, 680, 681, 691, 692, 758, 767, 768, 769, 777,
0766 778, 779, 780, 788, 789, 790, 791, 799, 800, 801, 802, 811,
0767 812, 813, 824, 879, 890, 901, 912, 923, 934, 945}},
0768 {Frustum3({0, 0, 0}, {0, 0, 1}, std::numbers::pi / 8.),
0769 {427, 428, 546, 547, 548, 549, 658, 659, 665, 666, 667, 668, 669, 670,
0770 680, 681, 780, 791, 802}},
0771 {Frustum3({0, 0, 0}, {0, 0, 1}, std::numbers::pi * 3. / 4.),
0772 {8, 9, 10, 19, 20, 21, 29, 30, 31, 32, 40,
0773 41, 42, 43, 51, 52, 53, 54, 61, 62, 63, 64,
0774 65, 73, 74, 75, 76, 84, 85, 86, 87, 95, 96,
0775 97, 98, 107, 108, 109, 118, 119, 120, 129, 130, 131,
0776 140, 141, 142, 150, 151, 152, 153, 161, 162, 163, 164,
0777 171, 172, 173, 174, 175, 182, 183, 184, 185, 186, 193,
0778 194, 195, 196, 197, 205, 206, 207, 208, 216, 217, 218,
0779 219, 228, 229, 230, 239, 240, 241, 250, 251, 252, 260,
0780 261, 262, 263, 271, 272, 273, 274, 282, 283, 284, 285,
0781 292, 293, 294, 295, 296, 303, 304, 305, 306, 307, 314,
0782 315, 316, 317, 318, 326, 327, 328, 329, 337, 338, 339,
0783 340, 348, 349, 350, 351, 360, 361, 362, 370, 371, 372,
0784 373, 381, 382, 383, 384, 392, 393, 394, 395, 402, 403,
0785 404, 405, 406, 413, 414, 415, 416, 417, 424, 425, 426,
0786 427, 428, 435, 436, 437, 438, 439, 446, 447, 448, 449,
0787 450, 458, 459, 460, 461, 469, 470, 471, 472, 480, 481,
0788 482, 483, 491, 492, 493, 494, 502, 503, 504, 505, 513,
0789 514, 515, 516, 523, 524, 525, 526, 527, 534, 535, 536,
0790 537, 538, 544, 545, 546, 547, 548, 549, 556, 557, 558,
0791 559, 560, 567, 568, 569, 570, 571, 579, 580, 581, 582,
0792 590, 591, 592, 593, 601, 602, 603, 604, 612, 613, 614,
0793 615, 623, 624, 625, 626, 633, 634, 635, 636, 637, 644,
0794 645, 646, 647, 648, 655, 656, 657, 658, 659, 665, 666,
0795 667, 668, 669, 670, 677, 678, 679, 680, 681, 688, 689,
0796 690, 691, 692, 699, 700, 701, 702, 703, 711, 712, 713,
0797 714, 722, 723, 724, 725, 733, 734, 735, 736, 743, 744,
0798 745, 746, 747, 754, 755, 756, 757, 758, 765, 766, 767,
0799 768, 769, 776, 777, 778, 779, 780, 787, 788, 789, 790,
0800 791, 798, 799, 800, 801, 802, 809, 810, 811, 812, 813,
0801 820, 821, 822, 823, 824, 831, 832, 833, 834, 835, 843,
0802 844, 845, 846, 854, 855, 856, 857, 864, 865, 866, 867,
0803 868, 875, 876, 877, 878, 879, 886, 887, 888, 889, 890,
0804 897, 898, 899, 900, 901, 908, 909, 910, 911, 912, 919,
0805 920, 921, 922, 923, 930, 931, 932, 933, 934, 941, 942,
0806 943, 944, 945, 952, 953, 954, 955, 956, 964, 965, 966,
0807 967, 975, 976, 977, 978, 986, 987, 988, 989, 997, 998,
0808 999, 1000, 1008, 1009, 1010, 1011, 1019, 1020, 1021, 1022, 1030,
0809 1031, 1032, 1033, 1041, 1042, 1043, 1044, 1052, 1053, 1054, 1055,
0810 1063, 1064, 1065, 1066, 1074, 1075, 1076, 1077, 1085, 1086, 1087,
0811 1088, 1096, 1097, 1098, 1099, 1107, 1108, 1109, 1110, 1118, 1119,
0812 1120, 1121, 1129, 1130, 1131, 1132, 1140, 1141, 1142, 1143, 1151,
0813 1152, 1153, 1154, 1162, 1163, 1164, 1165, 1173, 1174, 1175, 1176,
0814 1184, 1185, 1186, 1187, 1195, 1196, 1197, 1198, 1206, 1207, 1208,
0815 1209, 1217, 1218, 1219, 1220, 1228, 1229, 1230, 1231, 1239, 1240,
0816 1241, 1242, 1250, 1251, 1252, 1253, 1261, 1262, 1263, 1264, 1272,
0817 1273, 1274, 1275, 1283, 1284, 1285, 1286, 1294, 1295, 1296, 1297,
0818 1305, 1306, 1307, 1308, 1316, 1317, 1318, 1319, 1327, 1328, 1329,
0819 1330}},
0820 {Frustum3({1.3, -5.9, 3.5}, {0.2, 0.4, 1}, std::numbers::pi / 3.),
0821 {318, 426, 427, 428, 438, 439, 450, 538, 546, 547, 548,
0822 549, 558, 559, 560, 570, 571, 582, 655, 656, 657, 658,
0823 659, 667, 668, 669, 670, 678, 679, 680, 681, 690, 691,
0824 692, 702, 703, 714, 768, 769, 777, 778, 779, 780, 787,
0825 788, 789, 790, 791, 799, 800, 801, 802, 810, 811, 812,
0826 813, 822, 823, 824, 834, 835, 846, 888, 889, 890, 899,
0827 900, 901, 910, 911, 912, 920, 921, 922, 923, 931, 932,
0828 933, 934, 942, 943, 944, 945, 954, 955, 956, 966, 967,
0829 1000, 1010, 1011, 1021, 1022, 1032, 1033, 1042, 1043, 1044, 1053,
0830 1054, 1055, 1064, 1065, 1066, 1074, 1075, 1076, 1077, 1086, 1087,
0831 1088, 1143, 1154, 1165, 1175, 1176, 1186, 1187, 1197, 1198, 1207,
0832 1208, 1209, 1308, 1319, 1330}}};
0833
0834 for (std::size_t l = 0; l < frExp.size(); l++) {
0835 const Frustum3& fr = frExp.at(l).first;
0836 const std::set<std::size_t>& idxsExp = frExp.at(l).second;
0837 std::stringstream ss;
0838 ss << "frust3d-3s_test_" << l << ".ply";
0839
0840 os = tmp(ss.str());
0841
0842 helper.clear();
0843
0844 idxsAct.clear();
0845
0846 fr.draw(helper, 50);
0847
0848 n = 10;
0849 min = -33;
0850 max = 33;
0851 step = (max - min) / n;
0852
0853 Object o;
0854 using Box = AxisAlignedBoundingBox<Object, double, 3>;
0855 Box::Size size(Eigen::Matrix<double, 3, 1>(2, 2, 2));
0856
0857 std::size_t idx = 0;
0858
0859 for (std::size_t i = 0; i <= n; i++) {
0860 for (std::size_t j = 0; j <= n; j++) {
0861 for (std::size_t k = 0; k <= n; k++) {
0862 Eigen::Matrix<double, 3, 1> pos(min + i * step, min + j * step,
0863 min + k * step);
0864 Box bb(&o, pos, size);
0865
0866 Color color = {255, 0, 0};
0867
0868 if (bb.intersect(fr)) {
0869 color = {0, 255, 0};
0870 idxsAct.insert(idx);
0871 }
0872
0873 bb.draw(helper, color);
0874 idx++;
0875 }
0876 }
0877 }
0878
0879 os << helper << std::flush;
0880 os.close();
0881
0882 BOOST_CHECK(idxsAct == idxsExp);
0883 }
0884 }
0885
0886 BOOST_TEST_CONTEXT("3D - 4 Sides") {
0887 using Frustum34 = Frustum<double, 3, 4>;
0888 const std::size_t n = 10;
0889 double min = -10;
0890 double max = 10;
0891 const std::size_t s = 5;
0892 double step = (max - min) / s;
0893 std::ofstream os;
0894
0895
0896 helper.clear();
0897 os = tmp("frust3d-4s_dir.ply");
0898
0899 const double constAngle = std::numbers::pi / 4.;
0900 for (std::size_t i = 0; i <= s; i++) {
0901 for (std::size_t j = 0; j <= s; j++) {
0902 for (std::size_t k = 0; k <= s; k++) {
0903 Vector3F origin(min + i * step, min + j * step, min + k * step);
0904 Vector3F dir(1, 0, 0);
0905
0906 double piOverS = std::numbers::pi / s;
0907 AngleAxis3F rot;
0908 rot = AngleAxis3F(piOverS * i, Vector3F::UnitX()) *
0909 AngleAxis3F(piOverS * j, Vector3F::UnitY()) *
0910 AngleAxis3F(piOverS * k, Vector3F::UnitZ());
0911
0912 Frustum34 fr(origin, rot * dir, constAngle);
0913 fr.draw(helper, 1);
0914 }
0915 }
0916 }
0917
0918 os << helper << std::flush;
0919 os.close();
0920
0921 os = tmp("frust3d-4s_angle.ply");
0922 helper.clear();
0923
0924 for (std::size_t i = 0; i <= n; i++) {
0925 Vector3F origin(i * 4, 0, 0);
0926 AngleAxis3F rot(std::numbers::pi / n * i, Vector3F::UnitY());
0927 const double angle = (std::numbers::pi / 2.) / n * (1 + i);
0928 Vector3F dir(1, 0, 0);
0929 Frustum34 fr(origin, rot * dir, angle);
0930 fr.draw(helper, 2);
0931 }
0932
0933 os << helper << std::flush;
0934 os.close();
0935
0936 std::set<std::size_t> idxsAct;
0937
0938 std::vector<std::pair<Frustum34, std::set<std::size_t>>> frExp;
0939 frExp = {
0940 {Frustum34({0, 0, 0}, {1, 0, 0}, std::numbers::pi / 2.),
0941 {665, 774, 775, 776, 785, 786, 787, 796, 797, 798, 883,
0942 884, 885, 886, 887, 894, 895, 896, 897, 898, 905, 906,
0943 907, 908, 909, 916, 917, 918, 919, 920, 927, 928, 929,
0944 930, 931, 992, 993, 994, 995, 996, 997, 998, 1003, 1004,
0945 1005, 1006, 1007, 1008, 1009, 1014, 1015, 1016, 1017, 1018, 1019,
0946 1020, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1036, 1037, 1038,
0947 1039, 1040, 1041, 1042, 1047, 1048, 1049, 1050, 1051, 1052, 1053,
0948 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1101, 1102, 1103, 1104,
0949 1105, 1106, 1107, 1108, 1109, 1112, 1113, 1114, 1115, 1116, 1117,
0950 1118, 1119, 1120, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130,
0951 1131, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1145,
0952 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1156, 1157, 1158,
0953 1159, 1160, 1161, 1162, 1163, 1164, 1167, 1168, 1169, 1170, 1171,
0954 1172, 1173, 1174, 1175, 1178, 1179, 1180, 1181, 1182, 1183, 1184,
0955 1185, 1186, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197,
0956 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220,
0957 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231,
0958 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242,
0959 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253,
0960 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264,
0961 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275,
0962 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286,
0963 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297,
0964 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308,
0965 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319,
0966 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330}},
0967 {Frustum34({0, 0, 0}, {0, 1, 0}, std::numbers::pi / 2.),
0968 {110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
0969 221, 222, 223, 224, 225, 226, 227, 228, 229, 231, 232,
0970 233, 234, 235, 236, 237, 238, 239, 240, 241, 332, 333,
0971 334, 335, 336, 337, 338, 342, 343, 344, 345, 346, 347,
0972 348, 349, 350, 352, 353, 354, 355, 356, 357, 358, 359,
0973 360, 361, 362, 443, 444, 445, 446, 447, 453, 454, 455,
0974 456, 457, 458, 459, 463, 464, 465, 466, 467, 468, 469,
0975 470, 471, 473, 474, 475, 476, 477, 478, 479, 480, 481,
0976 482, 483, 554, 555, 556, 564, 565, 566, 567, 568, 574,
0977 575, 576, 577, 578, 579, 580, 584, 585, 586, 587, 588,
0978 589, 590, 591, 592, 594, 595, 596, 597, 598, 599, 600,
0979 601, 602, 603, 604, 665, 675, 676, 677, 685, 686, 687,
0980 688, 689, 695, 696, 697, 698, 699, 700, 701, 705, 706,
0981 707, 708, 709, 710, 711, 712, 713, 715, 716, 717, 718,
0982 719, 720, 721, 722, 723, 724, 725, 796, 797, 798, 806,
0983 807, 808, 809, 810, 816, 817, 818, 819, 820, 821, 822,
0984 826, 827, 828, 829, 830, 831, 832, 833, 834, 836, 837,
0985 838, 839, 840, 841, 842, 843, 844, 845, 846, 927, 928,
0986 929, 930, 931, 937, 938, 939, 940, 941, 942, 943, 947,
0987 948, 949, 950, 951, 952, 953, 954, 955, 957, 958, 959,
0988 960, 961, 962, 963, 964, 965, 966, 967, 1058, 1059, 1060,
0989 1061, 1062, 1063, 1064, 1068, 1069, 1070, 1071, 1072, 1073, 1074,
0990 1075, 1076, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086,
0991 1087, 1088, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197,
0992 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209,
0993 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330}},
0994 {Frustum34({0, 0, 0}, {0, 0, 1}, std::numbers::pi / 2.),
0995 {10, 21, 32, 43, 54, 65, 76, 87, 98, 109, 120,
0996 131, 141, 142, 152, 153, 163, 164, 174, 175, 185, 186,
0997 196, 197, 207, 208, 218, 219, 229, 230, 241, 252, 262,
0998 263, 272, 273, 274, 283, 284, 285, 294, 295, 296, 305,
0999 306, 307, 316, 317, 318, 327, 328, 329, 338, 339, 340,
1000 350, 351, 362, 373, 383, 384, 393, 394, 395, 403, 404,
1001 405, 406, 414, 415, 416, 417, 425, 426, 427, 428, 436,
1002 437, 438, 439, 447, 448, 449, 450, 459, 460, 461, 471,
1003 472, 483, 494, 504, 505, 514, 515, 516, 524, 525, 526,
1004 527, 534, 535, 536, 537, 538, 545, 546, 547, 548, 549,
1005 556, 557, 558, 559, 560, 568, 569, 570, 571, 580, 581,
1006 582, 592, 593, 604, 615, 625, 626, 635, 636, 637, 645,
1007 646, 647, 648, 655, 656, 657, 658, 659, 665, 666, 667,
1008 668, 669, 670, 677, 678, 679, 680, 681, 689, 690, 691,
1009 692, 701, 702, 703, 713, 714, 725, 736, 746, 747, 756,
1010 757, 758, 766, 767, 768, 769, 776, 777, 778, 779, 780,
1011 787, 788, 789, 790, 791, 798, 799, 800, 801, 802, 810,
1012 811, 812, 813, 822, 823, 824, 834, 835, 846, 857, 867,
1013 868, 877, 878, 879, 887, 888, 889, 890, 898, 899, 900,
1014 901, 909, 910, 911, 912, 920, 921, 922, 923, 931, 932,
1015 933, 934, 943, 944, 945, 955, 956, 967, 978, 988, 989,
1016 998, 999, 1000, 1009, 1010, 1011, 1020, 1021, 1022, 1031, 1032,
1017 1033, 1042, 1043, 1044, 1053, 1054, 1055, 1064, 1065, 1066, 1076,
1018 1077, 1088, 1099, 1109, 1110, 1120, 1121, 1131, 1132, 1142, 1143,
1019 1153, 1154, 1164, 1165, 1175, 1176, 1186, 1187, 1197, 1198, 1209,
1020 1220, 1231, 1242, 1253, 1264, 1275, 1286, 1297, 1308, 1319, 1330}},
1021 {Frustum34({0, 0, 0}, {0, 0, 1}, std::numbers::pi / 4.),
1022 {406, 417, 428, 439, 450, 527, 535, 536, 537, 538, 546, 547, 548, 549,
1023 557, 558, 559, 560, 571, 648, 656, 657, 658, 659, 665, 666, 667, 668,
1024 669, 670, 678, 679, 680, 681, 692, 769, 777, 778, 779, 780, 788, 789,
1025 790, 791, 799, 800, 801, 802, 813, 890, 901, 912, 923, 934}},
1026 {Frustum34({0, 0, 0}, {0, 0, 1}, std::numbers::pi / 8.),
1027 {538, 549, 560, 659, 665, 666, 667, 668, 669, 670, 681, 780, 791,
1028 802}},
1029 {Frustum34({0, 0, 0}, {0, 0, 1}, std::numbers::pi * 3. / 4.),
1030 {7, 8, 9, 10, 18, 19, 20, 21, 29, 30, 31,
1031 32, 40, 41, 42, 43, 51, 52, 53, 54, 62, 63,
1032 64, 65, 73, 74, 75, 76, 84, 85, 86, 87, 95,
1033 96, 97, 98, 106, 107, 108, 109, 117, 118, 119, 120,
1034 128, 129, 130, 131, 139, 140, 141, 142, 150, 151, 152,
1035 153, 161, 162, 163, 164, 172, 173, 174, 175, 183, 184,
1036 185, 186, 194, 195, 196, 197, 205, 206, 207, 208, 216,
1037 217, 218, 219, 227, 228, 229, 230, 238, 239, 240, 241,
1038 249, 250, 251, 252, 260, 261, 262, 263, 271, 272, 273,
1039 274, 282, 283, 284, 285, 293, 294, 295, 296, 304, 305,
1040 306, 307, 315, 316, 317, 318, 326, 327, 328, 329, 337,
1041 338, 339, 340, 348, 349, 350, 351, 359, 360, 361, 362,
1042 370, 371, 372, 373, 381, 382, 383, 384, 392, 393, 394,
1043 395, 402, 403, 404, 405, 406, 413, 414, 415, 416, 417,
1044 424, 425, 426, 427, 428, 435, 436, 437, 438, 439, 446,
1045 447, 448, 449, 450, 458, 459, 460, 461, 469, 470, 471,
1046 472, 480, 481, 482, 483, 491, 492, 493, 494, 502, 503,
1047 504, 505, 513, 514, 515, 516, 523, 524, 525, 526, 527,
1048 534, 535, 536, 537, 538, 545, 546, 547, 548, 549, 556,
1049 557, 558, 559, 560, 567, 568, 569, 570, 571, 579, 580,
1050 581, 582, 590, 591, 592, 593, 601, 602, 603, 604, 612,
1051 613, 614, 615, 623, 624, 625, 626, 634, 635, 636, 637,
1052 644, 645, 646, 647, 648, 655, 656, 657, 658, 659, 665,
1053 666, 667, 668, 669, 670, 677, 678, 679, 680, 681, 688,
1054 689, 690, 691, 692, 700, 701, 702, 703, 711, 712, 713,
1055 714, 722, 723, 724, 725, 733, 734, 735, 736, 744, 745,
1056 746, 747, 755, 756, 757, 758, 765, 766, 767, 768, 769,
1057 776, 777, 778, 779, 780, 787, 788, 789, 790, 791, 798,
1058 799, 800, 801, 802, 809, 810, 811, 812, 813, 821, 822,
1059 823, 824, 832, 833, 834, 835, 843, 844, 845, 846, 854,
1060 855, 856, 857, 865, 866, 867, 868, 876, 877, 878, 879,
1061 886, 887, 888, 889, 890, 897, 898, 899, 900, 901, 908,
1062 909, 910, 911, 912, 919, 920, 921, 922, 923, 930, 931,
1063 932, 933, 934, 942, 943, 944, 945, 953, 954, 955, 956,
1064 964, 965, 966, 967, 975, 976, 977, 978, 986, 987, 988,
1065 989, 997, 998, 999, 1000, 1008, 1009, 1010, 1011, 1019, 1020,
1066 1021, 1022, 1030, 1031, 1032, 1033, 1041, 1042, 1043, 1044, 1052,
1067 1053, 1054, 1055, 1063, 1064, 1065, 1066, 1074, 1075, 1076, 1077,
1068 1085, 1086, 1087, 1088, 1096, 1097, 1098, 1099, 1107, 1108, 1109,
1069 1110, 1118, 1119, 1120, 1121, 1129, 1130, 1131, 1132, 1140, 1141,
1070 1142, 1143, 1151, 1152, 1153, 1154, 1162, 1163, 1164, 1165, 1173,
1071 1174, 1175, 1176, 1184, 1185, 1186, 1187, 1195, 1196, 1197, 1198,
1072 1206, 1207, 1208, 1209, 1217, 1218, 1219, 1220, 1228, 1229, 1230,
1073 1231, 1239, 1240, 1241, 1242, 1250, 1251, 1252, 1253, 1261, 1262,
1074 1263, 1264, 1272, 1273, 1274, 1275, 1283, 1284, 1285, 1286, 1294,
1075 1295, 1296, 1297, 1305, 1306, 1307, 1308, 1316, 1317, 1318, 1319,
1076 1327, 1328, 1329, 1330}},
1077 {Frustum34({1.3, -5.9, 3.5}, {0.2, 0.4, 1}, std::numbers::pi / 3.),
1078 {461, 472, 537, 538, 548, 549, 558, 559, 560, 569, 570,
1079 571, 581, 582, 593, 655, 656, 657, 658, 659, 666, 667,
1080 668, 669, 670, 678, 679, 680, 681, 690, 691, 692, 702,
1081 703, 714, 777, 778, 779, 780, 787, 788, 789, 790, 791,
1082 799, 800, 801, 802, 811, 812, 813, 823, 824, 835, 846,
1083 899, 900, 901, 910, 911, 912, 920, 921, 922, 923, 932,
1084 933, 934, 944, 945, 955, 956, 967, 1021, 1022, 1032, 1033,
1085 1042, 1043, 1044, 1053, 1054, 1055, 1064, 1065, 1066, 1076, 1077,
1086 1088, 1143, 1154, 1165, 1175, 1176, 1186, 1187, 1197, 1198, 1209,
1087 1308, 1319, 1330}}};
1088
1089 min = -33;
1090 max = 33;
1091 step = (max - min) / n;
1092
1093 for (std::size_t l = 0; l < frExp.size(); l++) {
1094 const Frustum34& fr = frExp.at(l).first;
1095 const std::set<std::size_t>& idxsExp = frExp.at(l).second;
1096 std::stringstream ss;
1097 ss << "frust3d-4s_test_" << l << ".ply";
1098
1099 os = tmp(ss.str());
1100
1101 helper.clear();
1102
1103 idxsAct.clear();
1104
1105 fr.draw(helper, 50);
1106
1107 Object o;
1108 using Box = AxisAlignedBoundingBox<Object, double, 3>;
1109 Box::Size size(Eigen::Matrix<double, 3, 1>(2, 2, 2));
1110
1111 std::size_t idx = 0;
1112 for (std::size_t i = 0; i <= n; i++) {
1113 for (std::size_t j = 0; j <= n; j++) {
1114 for (std::size_t k = 0; k <= n; k++) {
1115 Eigen::Matrix<double, 3, 1> pos(min + i * step, min + j * step,
1116 min + k * step);
1117 Box bb(&o, pos, size);
1118
1119 Color color = {255, 0, 0};
1120
1121 if (bb.intersect(fr)) {
1122 color = {0, 255, 0};
1123 idxsAct.insert(idx);
1124 }
1125
1126 bb.draw(helper, color);
1127 idx++;
1128 }
1129 }
1130 }
1131
1132 os << helper << std::flush;
1133 os.close();
1134
1135 BOOST_CHECK(idxsAct == idxsExp);
1136 }
1137 }
1138
1139 BOOST_TEST_CONTEXT("3D - 5 Sides") {
1140 using Frustum = Frustum<double, 3, 5>;
1141 using Box = AxisAlignedBoundingBox<Object, double, 3>;
1142 Box::Size size(Vector3(2, 2, 2));
1143
1144 Object o;
1145
1146 PlyVisualization3D<double> ply;
1147
1148 Frustum fr({0, 0, 0}, {0, 0, 1}, std::numbers::pi / 8.);
1149 fr.draw(ply, 10);
1150
1151 Box bb(&o, {0, 0, 10}, size);
1152 bb.draw(ply);
1153
1154 BOOST_CHECK(bb.intersect(fr));
1155
1156 auto os = tmp("frust3d-5s.ply");
1157 os << ply << std::flush;
1158 os.close();
1159 }
1160
1161 BOOST_TEST_CONTEXT("3D - 10 Sides") {
1162 using Frustum = Frustum<double, 3, 10>;
1163 using Box = AxisAlignedBoundingBox<Object, double, 3>;
1164 Box::Size size(Vector3(2, 2, 2));
1165
1166 Object o;
1167
1168 PlyVisualization3D<double> ply;
1169
1170 Vector3 pos = {-12.4205, 29.3578, 44.6207};
1171 Vector3 dir = {-0.656862, 0.48138, 0.58035};
1172 Frustum fr(pos, dir, 0.972419);
1173 fr.draw(ply, 10);
1174
1175 Box bb(&o, pos + dir * 10, size);
1176 bb.draw(ply);
1177
1178 BOOST_CHECK(bb.intersect(fr));
1179
1180 auto os = tmp("frust3d-10s.ply");
1181 os << ply << std::flush;
1182 os.close();
1183 }
1184
1185 BOOST_TEST_CONTEXT("3D - 4 Sides - Big box") {
1186 using Frustum = Frustum<double, 3, 4>;
1187 using Box = AxisAlignedBoundingBox<Object, double, 3>;
1188
1189 Object o;
1190
1191 PlyVisualization3D<double> ply;
1192
1193 Vector3 pos = {0, 0, 0};
1194 Vector3 dir = {0, 0, 1};
1195 Frustum fr(pos, dir, 0.972419);
1196 fr.draw(ply, 10);
1197
1198 Box::Size size(Vector3(100, 100, 2));
1199 Box bb(&o, pos + dir * 7, size);
1200 bb.draw(ply);
1201
1202 BOOST_CHECK(bb.intersect(fr));
1203
1204 auto os = tmp("frust3d-4s-bigbox.ply");
1205 os << ply << std::flush;
1206 os.close();
1207 }
1208 }
1209
1210 BOOST_AUTO_TEST_CASE(ostream_operator) {
1211 Object o;
1212 using Box = AxisAlignedBoundingBox<Object, double, 2>;
1213 Box bb(&o, {-1, -1}, {2, 2});
1214
1215 std::stringstream ss;
1216 ss << bb;
1217
1218 BOOST_CHECK(ss.str() == "AABB(ctr=(0.5, 0.5) vmin=(-1, -1) vmax=(2, 2))");
1219 }
1220
1221 BOOST_AUTO_TEST_SUITE_END()
1222
1223 }