31#include "DGtal/base/SetFunctions.h"
32#include "DGtal/helpers/StdDefs.h"
33#include "DGtal/topology/CubicalComplexFunctions.h"
34#include "DGtal/topology/CubicalComplex.h"
35#include "DGtal/topology/KhalimskyCellHashFunctions.h"
36#include "DGtal/topology/VoxelComplex.h"
37#include "DGtal/topology/VoxelComplexFunctions.h"
38#include "DGtalCatch.h"
40#include <unordered_map>
42#include "DGtal/geometry/volumes/distance/DistanceTransformation.h"
43#include "DGtal/geometry/volumes/distance/ExactPredicateLpSeparableMetric.h"
44#include "DGtal/geometry/volumes/distance/VoronoiMap.h"
45#include "DGtal/images/SimpleThresholdForegroundPredicate.h"
46#include "DGtal/kernel/BasicPointPredicates.h"
47#include "DGtal/topology/NeighborhoodConfigurations.h"
48#include "DGtal/topology/tables/NeighborhoodTables.h"
58struct Fixture_complex_diamond {
69 std::unordered_set<typename DGtal::Z3i::Domain::Point>>;
76 Fixture_complex_diamond() :
77 complex_fixture(ks_fixture) {
78 create_complex_from_set(create_set());
83 FixtureComplex complex_fixture;
90 FixtureDigitalSet create_set() {
91 using namespace DGtal;
94 Point p1(-10, -10, -10);
100 FixtureDigitalSet set_fixture(
domain);
102 if ((*it - c).norm1() <= 3)
103 set_fixture.insertNew(*it);
105 set_fixture.erase(c);
110 FixtureComplex &create_complex_from_set(
const FixtureDigitalSet &input_set) {
112 ks_fixture.
init(input_set.domain().lowerBound(),
113 input_set.domain().upperBound(),
true);
114 complex_fixture = FixtureComplex(ks_fixture);
115 complex_fixture.construct(input_set);
116 return complex_fixture;
121 auto &vc = complex_fixture;
122 auto &ks = vc.space();
123 auto s3 = vc.nbCells(3);
124 auto s2 = vc.nbCells(2);
125 auto s1 = vc.nbCells(1);
126 auto s0 = vc.nbCells(0);
127 SECTION(
"insertVoxel in border") {
130 vc_new.insertVoxelPoint(p);
131 auto sa3 = vc_new.nbCells(3);
132 auto sa2 = vc_new.nbCells(2);
133 auto sa1 = vc_new.nbCells(1);
134 auto sa0 = vc_new.nbCells(0);
144 SECTION(
"insertVoxel isolated") {
147 vc_new.insertVoxelCell(ks.uSpel(p));
148 auto sa3 = vc_new.nbCells(3);
149 auto sa2 = vc_new.nbCells(2);
150 auto sa1 = vc_new.nbCells(1);
151 auto sa0 = vc_new.nbCells(0);
161 SECTION(
"insertVoxel interior") {
164 vc_new.insertVoxelCell(ks.uSpel(p));
165 auto sa3 = vc_new.nbCells(3);
166 auto sa2 = vc_new.nbCells(2);
167 auto sa1 = vc_new.nbCells(1);
168 auto sa0 = vc_new.nbCells(0);
181 "[neighborhood][faces]") {
182 auto &vc = complex_fixture;
183 auto &ks = vc.space();
185 bool no_hint =
false;
186 auto not_found = vc.end(3);
188 SECTION(
"Voxel is in the interior of the complex.") {
190 auto cellMapIt = vc.findCell(3, ks.uSpel(p));
191 CHECK(cellMapIt != not_found);
192 auto cell = cellMapIt->first;
193 auto kfaces = ks.uFaces(cell);
196 CHECK(kfaces.size() == 26);
197 auto vcBoundary_closed = vc.cellBoundary(cell, closed);
198 CHECK(vcBoundary_closed.size() == 26);
199 auto vcBoundary_no_hint = vc.cellBoundary(cell, no_hint);
200 CHECK(vcBoundary_no_hint.size() == 26);
202 SECTION(
"Voxel is in the exterior") {
204 auto cellMapIt = vc.findCell(3, ks.uSpel(p));
205 CHECK(cellMapIt == not_found);
206 auto cell = ks.uSpel(p);
207 auto kfaces = ks.uFaces(cell);
210 CHECK(kfaces.size() == 26);
212 auto vcBoundary_closed = vc.cellBoundary(cell, closed);
213 CHECK(vcBoundary_closed.size() == 26);
215 auto vcBoundary_no_hint = vc.cellBoundary(cell, no_hint);
216 CHECK(vcBoundary_no_hint.size() == 0);
218 SECTION(
"Voxel is out, but surrounded by in voxels") {
220 auto cellMapIt = vc.findCell(3, ks.uSpel(p));
221 CHECK(cellMapIt == not_found);
222 auto cell = ks.uSpel(p);
223 auto kfaces = ks.uFaces(cell);
226 CHECK(kfaces.size() == 26);
227 auto vcBoundary_closed = vc.cellBoundary(cell, closed);
228 CHECK(vcBoundary_closed.size() == 26);
229 auto vcBoundary_no_hint = vc.cellBoundary(cell, no_hint);
230 CHECK(vcBoundary_no_hint.size() == 26);
232 SECTION(
"Voxel is in the border") {
234 auto cellMapIt = vc.findCell(3, ks.uSpel(p));
235 CHECK(cellMapIt != not_found);
236 auto cell = cellMapIt->first;
237 auto kfaces = ks.uFaces(cell);
240 CHECK(kfaces.size() == 26);
241 auto vcBoundary_closed = vc.cellBoundary(cell, closed);
242 CHECK(vcBoundary_closed.size() == 26);
243 auto vcBoundary_no_hint = vc.cellBoundary(cell, no_hint);
244 CHECK(vcBoundary_no_hint.size() == 26);
250 auto &vc = complex_fixture;
251 SECTION(
" get neighbors from Kspace") {
253 size_t dim_voxel = 3;
254 auto it = vc.begin(dim_voxel);
255 for (std::size_t n = 0; n < 10; ++n)
257 auto cell = it->first;
258 auto point_from_kspace_1 = cell.preCell().coordinates;
259 size_t expected_num_adjacent_voxels = 12;
261 SECTION(
"properNeighborhood from KSpace"
262 "does not output all adjacent voxels.") {
264 size_t expected_kspace_neighborhood = 7;
265 auto neigh_k = vc.space().uNeighborhood(cell);
266 CHECK(neigh_k.size() == expected_kspace_neighborhood);
268 auto propN_k = vc.space().uProperNeighborhood(cell);
269 CHECK(propN_k.size() == expected_kspace_neighborhood - 1);
272 SECTION(
"Getting associated pointels and voxels from input_cell") {
273 std::set<FixtureComplex::Cell> pointel_set;
274 vc.pointelsFromCell(pointel_set, cell);
275 std::set<FixtureComplex::Cell> voxel_set;
276 for (
auto &&p : pointel_set)
277 vc.spelsFromCell(voxel_set, p);
278 SECTION(
"Gets desired full adjancency for voxels") {
279 CHECK(voxel_set.size() == expected_num_adjacent_voxels);
281 auto clique = vc.Kneighborhood(cell);
282 CHECK(clique.nbCells(3) == expected_num_adjacent_voxels);
289 auto &vc = complex_fixture;
290 size_t dim_voxel = 3;
291 auto cit = vc.begin(dim_voxel);
292 for (std::size_t n = 0; n < 10; ++n)
294 auto cell = cit->first;
296 SECTION(
"querying voxel simplicity") {
298 std::vector<FixtureComplex::Cell> non_simple_cells;
299 for (
auto it = vc.begin(dim_voxel); it != vc.end(dim_voxel); ++it) {
300 if (vc.isSimple(it->first))
303 non_simple_cells.emplace_back(it->first);
308 size_t border_size = 44;
309 REQUIRE(nsimples == border_size);
315 auto &vc = complex_fixture;
320 auto cit = vc.begin(dim_voxel);
321 for (std::size_t n = 0; n < 10; ++n)
323 auto cell = cit->first;
325 SECTION(
"querying voxel simplicity") {
327 std::vector<FixtureComplex::Cell> non_simple_cells;
328 for (
auto it = vc.begin(dim_voxel); it != vc.end(dim_voxel); ++it) {
329 if (vc.isSimple(it->first))
332 non_simple_cells.emplace_back(it->first);
336 size_t border_size = 44;
337 REQUIRE(nsimples == border_size);
342 auto &vc = complex_fixture;
343 auto itc = vc.begin(3);
344 for (std::size_t n = 0; n < 10; ++n)
346 auto cell = itc->first;
347 Point p_cell = vc.space().uCoords(cell);
348 auto neigh6 = vc.space().uProperNeighborhood(cell);
351 for(
auto & n : neigh6)
352 if(vc.belongs(n)) cells.push_back(n);
355 std::vector<std::pair<bool, FixtureComplex::Clique>> cliques_p;
357 for (
auto && cell_n : cells) {
358 auto cell_point = vc.space().uCoords(cell_n);
359 cliques_p.emplace_back(vc.K_2(p_cell, cell_point, verbose));
360 auto &is_critical = cliques_p.back().first;
361 auto &k2_clique = cliques_p.back().second;
362 CHECK(is_critical ==
true);
363 CHECK(k2_clique.nbCells(3) == 2);
366 SECTION(
" Check same results for different K_2 interfaces") {
367 for (
auto && cell_n : cells) {
368 auto co_face = vc.surfelBetweenAdjacentSpels(cell_n, cell);
370 auto cell_point = vc.space().uCoords(cell_n);
372 CHECK(
isEqual(vc.K_2(p_cell, cell_point,
false).second,
373 vc.K_2(cell, cell_n,
false).second) ==
true);
374 CHECK(
isEqual(vc.K_2(p_cell, cell_point,
false).second,
375 vc.K_2(co_face,
false).second) ==
true);
381 auto &vc = complex_fixture;
382 auto itc = vc.begin(3);
383 for (std::size_t n = 0; n < 10; ++n)
385 auto cell = itc->first;
386 Point p_cell = vc.space().uCoords(cell);
388 SECTION(
"K_1 mask from a linel") {
390 vc.space().uCell(cell.preCell().coordinates +
Point{0, 1, 1});
393 auto k1p = vc.K_1(linel,
true);
394 auto &is_critical = k1p.first;
395 CHECK(is_critical ==
true);
396 auto &k1_clique = k1p.second;
398 CHECK(k1_clique.nbCells(3) == 3);
403 auto &vc = complex_fixture;
404 auto itc = vc.begin(3);
405 for (std::size_t n = 0; n < 10; ++n)
407 auto cell = itc->first;
408 Point p_cell = vc.space().uCoords(cell);
410 SECTION(
"K_0 mask from a pointel") {
411 auto pointel = vc.space().uPointel(p_cell);
415 auto k0_mask = vc.K_0(pointel,
true);
417 auto &is_critical = k0_mask.first;
418 CHECK(is_critical ==
false);
419 auto &k0_clique = k0_mask.second;
421 CHECK(k0_clique.nbCells(3) == 1);
426 "[critical][clique]") {
427 auto &vc = complex_fixture;
429 SECTION(
" Get all criticalCliques() ") {
430 auto criticals = vc.criticalCliques();
431 CHECK(criticals.size() == 4);
433 CHECK(vc.nbCells(3) == 62);
434 CHECK(criticals[3].size() == 18);
435 CHECK(vc.nbCells(2) == 264);
436 CHECK(criticals[2].size() == 108);
437 CHECK(vc.nbCells(1) == 360);
438 CHECK(criticals[1].size() == 168);
439 CHECK(vc.nbCells(0) == 160);
440 CHECK(criticals[0].size() == 32);
448struct Fixture_complex_fig4 {
458 std::unordered_set<typename DGtal::Z3i::Domain::Point>>;
459 using FixtureMap = std::unordered_map<KSpace::Cell, CubicalCellData>;
464 FixtureComplex complex_fixture;
471 Fixture_complex_fig4() : complex_fixture(ks_fixture) {
472 create_complex_from_set(create_set());
478 FixtureDigitalSet create_set() {
479 using namespace DGtal;
481 Point p1(-10, -10, -10);
482 Point p2(10, 10, 10);
486 FixtureDigitalSet fig4_set(
domain);
488 fig4_set.insertNew(a1);
490 fig4_set.insertNew(a2);
492 fig4_set.insertNew(a3);
494 fig4_set.insertNew(c1);
496 fig4_set.insertNew(c2);
498 fig4_set.insertNew(c3);
500 fig4_set.insertNew(c4);
502 fig4_set.insertNew(b1);
504 fig4_set.insertNew(b2);
506 fig4_set.insertNew(l1);
508 fig4_set.insertNew(l2);
510 fig4_set.insertNew(r1);
515 FixtureComplex &create_complex_from_set(
const FixtureDigitalSet &input_set) {
517 ks_fixture.
init(input_set.domain().lowerBound(),
518 input_set.domain().upperBound(),
true);
519 complex_fixture = FixtureComplex(ks_fixture);
520 complex_fixture.construct(input_set);
521 return complex_fixture;
525 "[critical][clique]") {
526 auto &vc = complex_fixture;
528 SECTION(
" Get all criticalCliques() ") {
529 auto criticals = vc.criticalCliques(
true);
530 CHECK(criticals.size() == 4);
532 CHECK(vc.nbCells(3) == 12);
533 CHECK(criticals[3].size() == 1);
534 CHECK(vc.nbCells(2) == 64);
535 CHECK(criticals[2].size() == 3);
536 CHECK(vc.nbCells(1) == 109);
537 CHECK(criticals[1].size() == 2);
538 CHECK(vc.nbCells(0) == 58);
539 CHECK(criticals[0].size() == 6);
545 "[isSurface][function]") {
546 auto &vc = complex_fixture;
551 vc.insertCell(3, vc.space().uSpel(c));
555 vc.insertCell(3, vc.space().uSpel(r));
559 vc.insertCell(3, vc.space().uSpel(l));
565 std::unordered_set<typename DGtal::Z3i::Domain::Point>>;
573 SECTION(
"checking zero surfaces of original set") {
574 std::set<Point> zeroSurfacesCells;
576 vc.dumpVoxels(voxel_set);
577 Object object(topo, voxel_set);
578 for (
const auto &p : voxel_set) {
579 auto small_obj =
object.properNeighborhood(p);
580 if (isZeroSurface(small_obj))
581 zeroSurfacesCells.insert(p);
583 CHECK(zeroSurfacesCells.size() == 1);
586 SECTION(
"checking one surfaces of original set") {
589 vc.insertCell(3, vc.space().uSpel(u));
593 vc.insertCell(3, vc.space().uSpel(d));
596 std::set<Point> oneSurfacesCells;
598 vc.dumpVoxels(voxel_set);
599 Object object(topo, voxel_set);
601 for (
const auto &p : voxel_set) {
602 auto small_obj =
object.properNeighborhood(p);
603 if (isOneSurface(small_obj))
604 oneSurfacesCells.insert(p);
606 CHECK(oneSurfacesCells.size() == 1);
613struct Fixture_isthmus {
624 std::unordered_set<typename DGtal::Z3i::Domain::Point>>;
625 using FixtureMap = std::unordered_map<KSpace::Cell, CubicalCellData>;
630 FixtureComplex complex_fixture;
631 FixtureDigitalSet set_fixture;
638 Fixture_isthmus() : complex_fixture(ks_fixture), set_fixture(create_set()) {
639 create_complex_from_set(set_fixture);
645 FixtureDigitalSet create_set() {
646 using namespace DGtal;
648 Point p1(-10, -10, -10);
649 Point p2(10, 10, 10);
652 FixtureDigitalSet fig6_set(
domain);
655 fig6_set.insertNew(c00);
657 fig6_set.insertNew(c01);
659 fig6_set.insertNew(c02);
661 fig6_set.insertNew(c03);
664 fig6_set.insertNew(c10);
666 fig6_set.insertNew(y);
668 fig6_set.insertNew(c12);
670 fig6_set.insertNew(c13);
673 fig6_set.insertNew(c20);
675 fig6_set.insertNew(c21);
677 fig6_set.insertNew(c22);
678 Point c33(-1, 2, -1);
679 fig6_set.insertNew(c33);
682 fig6_set.insertNew(c30);
684 fig6_set.insertNew(c31);
687 fig6_set.insertNew(x);
690 fig6_set.insertNew(c50);
691 Point c51(-1, 5, -1);
692 fig6_set.insertNew(c51);
694 fig6_set.insertNew(c52);
697 fig6_set.insertNew(c60);
699 fig6_set.insertNew(c61);
700 Point c62(-2, 6, -1);
701 fig6_set.insertNew(c62);
706 FixtureComplex &create_complex_from_set(
const FixtureDigitalSet &input_set) {
708 ks_fixture.
init(input_set.domain().lowerBound(),
709 input_set.domain().upperBound(),
true);
710 complex_fixture = FixtureComplex(ks_fixture);
711 complex_fixture.construct(input_set);
712 return complex_fixture;
717 "[isthmus][thin][function]") {
719 auto &vc = complex_fixture;
720 auto &ks = vc.space();
721 boost::ignore_unused_variable_warning(ks);
723 set_fixture.erase(x);
727 vc.construct(set_fixture);
729 auto vc_new = asymetricThinningScheme<FixtureComplex>(
730 vc, selectFirst<FixtureComplex>, skelUltimate<FixtureComplex>);
731 CHECK(vc_new.nbCells(3) == 2);
737 auto &vc = complex_fixture;
739 auto &ks = vc.space();
743 SECTION(
"checking one isthmus") {
744 std::set<Point> isthmus;
745 for (
const auto &p : set_fixture) {
746 if (oneIsthmus(vc, ks.uSpel(p)))
749 CHECK(isthmus.size() == 1);
750 auto xit = isthmus.find(x);
754 SECTION(
"checking 2 isthmus") {
755 std::set<Point> isthmus;
756 for (
const auto &p : set_fixture) {
757 if (twoIsthmus(vc, ks.uSpel(p)))
760 CHECK(isthmus.size() == 1);
761 auto yit = isthmus.find(y);
765 SECTION(
"checking 1 and 2 isthmus") {
766 std::set<Point> isthmus;
767 for (
const auto &p : set_fixture) {
768 if (skelIsthmus(vc, ks.uSpel(p)))
771 CHECK(isthmus.size() == 2);
772 auto xit = isthmus.find(x);
773 auto yit = isthmus.find(y);
774 CHECK(xit != isthmus.end());
775 CHECK(yit != isthmus.end());
780 auto &vc = complex_fixture;
781 auto &ks = vc.space();
782 boost::ignore_unused_variable_warning(ks);
784 auto vc_new = asymetricThinningScheme<FixtureComplex>(
785 vc, selectFirst<FixtureComplex>, skelUltimate<FixtureComplex>);
786 CHECK(vc_new.nbCells(3) == 1);
789 auto vc_new = asymetricThinningScheme<FixtureComplex>(
790 vc, selectFirst<FixtureComplex>, skelEnd<FixtureComplex>);
791 CHECK(vc_new.nbCells(3) == 5);
794 auto vc_new = asymetricThinningScheme<FixtureComplex>(
795 vc, selectRandom<FixtureComplex>, oneIsthmus<FixtureComplex>);
796 CHECK(vc_new.nbCells(3) == 3);
799 auto vc_new = asymetricThinningScheme<FixtureComplex>(
800 vc, selectRandom<FixtureComplex>, twoIsthmus<FixtureComplex>);
801 CHECK(vc_new.nbCells(3) == 1);
804 auto vc_new = asymetricThinningScheme<FixtureComplex>(
805 vc, selectRandom<FixtureComplex>, skelIsthmus<FixtureComplex>);
806 CHECK(vc_new.nbCells(3) == 3);
811 "[persistence][isthmus][thin][function]") {
813 auto &vc = complex_fixture;
814 auto &ks = vc.space();
815 boost::ignore_unused_variable_warning(ks);
817 auto vc_new = persistenceAsymetricThinningScheme<FixtureComplex>(
818 vc, selectRandom<FixtureComplex>, skelUltimate<FixtureComplex>, 0);
819 CHECK(vc_new.nbCells(3) == 1);
822 auto vc_new = persistenceAsymetricThinningScheme<FixtureComplex>(
823 vc, selectRandom<FixtureComplex>, skelEnd<FixtureComplex>, 0);
824 CHECK(vc_new.nbCells(3) == 5);
833 auto pointToMaskMap =
834 *functions::mapZeroPointNeighborhoodToConfigurationMask<Point>();
835 auto oneIsthmusTable =
836 [&table, &pointToMaskMap](
const FixtureComplex &fc,
837 const FixtureComplex::Cell &c) {
838 return skelWithTable(table, pointToMaskMap, fc, c);
840 auto vc_new = persistenceAsymetricThinningScheme<FixtureComplex>(
841 vc, selectRandom<FixtureComplex>, oneIsthmusTable, 0);
842 CHECK(vc_new.nbCells(3) == 3);
851 auto pointToMaskMap =
852 *functions::mapZeroPointNeighborhoodToConfigurationMask<Point>();
853 auto twoIsthmusTable =
854 [&table, &pointToMaskMap](
const FixtureComplex &fc,
855 const FixtureComplex::Cell &c) {
856 return skelWithTable(table, pointToMaskMap, fc, c);
858 auto vc_new = persistenceAsymetricThinningScheme<FixtureComplex>(
859 vc, selectRandom<FixtureComplex>, twoIsthmusTable, 0);
860 CHECK(vc_new.nbCells(3) == 1);
869 auto pointToMaskMap =
870 *functions::mapZeroPointNeighborhoodToConfigurationMask<Point>();
871 auto isthmusTable = [&table,
872 &pointToMaskMap](
const FixtureComplex &fc,
873 const FixtureComplex::Cell &c) {
874 return skelWithTable(table, pointToMaskMap, fc, c);
876 auto vc_new = persistenceAsymetricThinningScheme<FixtureComplex>(
877 vc, selectRandom<FixtureComplex>, isthmusTable, 0);
878 CHECK(vc_new.nbCells(3) == 3);
895 std::unordered_set<typename DGtal::Z3i::Domain::Point>>;
896 using FixtureMap = std::unordered_map<KSpace::Cell, CubicalCellData>;
901 FixtureComplex complex_fixture;
902 FixtureDigitalSet set_fixture;
909 Fixture_X() : complex_fixture(ks_fixture), set_fixture(create_set()) {
910 create_complex_from_set(set_fixture);
916 FixtureDigitalSet create_set() {
917 using namespace DGtal;
919 Point p1(-16, -16, -16);
920 Point p2(16, 16, 16);
923 FixtureDigitalSet a_set(
domain);
924 std::vector<Point> center_set;
925 center_set.reserve(9);
928 center_set.push_back(c00);
929 Point c01x(-1, 0, 0);
930 center_set.push_back(c01x);
932 center_set.push_back(c10x);
933 Point c02x(-2, 0, 0);
934 center_set.push_back(c02x);
936 center_set.push_back(c20x);
938 Point c01y(0, -1, 0);
939 center_set.push_back(c01y);
941 center_set.push_back(c10y);
942 Point c02y(0, -2, 0);
943 center_set.push_back(c02y);
945 center_set.push_back(c20y);
947 Point z_pos(0, 0, 1);
948 int branch_length(4);
949 std::vector<Point> diagonals;
950 diagonals.reserve(6);
951 for (
const auto &p : center_set) {
953 for (
int l = 0; l <= branch_length; ++l) {
954 diagonals.push_back({l, l, 0});
955 diagonals.push_back({l, -l, 0});
956 diagonals.push_back({-l, l, 0});
957 diagonals.push_back({-l, -l, 0});
958 for (
int z = -1; z <= 1; ++z)
959 for (
const auto &d : diagonals)
960 a_set.insert(p + d + (z * z_pos));
967 FixtureComplex &create_complex_from_set(FixtureDigitalSet &input_set) {
969 ks_fixture.
init(input_set.domain().lowerBound(),
970 input_set.domain().upperBound(),
true);
971 complex_fixture = FixtureComplex(ks_fixture);
972 complex_fixture.construct(input_set);
973 return complex_fixture;
978 "[x][persistence][isthmus][thin][function]") {
980 auto &vc = complex_fixture;
981 auto &ks = vc.space();
982 boost::ignore_unused_variable_warning(ks);
985 "persistence value of 1 is equivalent to the assymetric algorithm") {
986 auto vc_new = persistenceAsymetricThinningScheme<FixtureComplex>(
987 vc, selectFirst<FixtureComplex>, skelEnd<FixtureComplex>, 1,
990 auto vc_assymetric = asymetricThinningScheme<FixtureComplex>(
991 vc, selectFirst<FixtureComplex>, skelEnd<FixtureComplex>,
true);
993 CHECK(vc_assymetric.nbCells(3) ==
994 Approx(vc_new.nbCells(3)).epsilon(0.1));
996 SECTION(
"persistence value: infinite is equivalent to ultimate skeleton") {
997 auto vc_new = persistenceAsymetricThinningScheme<FixtureComplex>(
998 vc, selectRandom<FixtureComplex>, skelEnd<FixtureComplex>, 100,
1000 REQUIRE(vc_new.nbCells(3) == 1);
1005 "[x][isthmus][thin][function][table]") {
1007 auto &vc = complex_fixture;
1008 auto &ks = vc.space();
1009 boost::ignore_unused_variable_warning(ks);
1010 bool verbose =
true;
1020 SECTION(
"Compute with skelWithTable (isIsthmus)") {
1023 auto pointToMaskMap =
1024 *functions::mapZeroPointNeighborhoodToConfigurationMask<Point>();
1025 auto skelWithTableIsthmus =
1026 [&table, &pointToMaskMap](
const FixtureComplex &fc,
1027 const FixtureComplex::Cell &c) {
1028 return skelWithTable(table, pointToMaskMap, fc, c);
1031 auto vc_new = asymetricThinningScheme<FixtureComplex>(
1032 vc, selectRandom<FixtureComplex>, skelWithTableIsthmus, verbose);
1037 SECTION(
"Compute with skelWithTable (isIsthmus) and empty Object") {
1038 trace.
beginBlock(
"Fixture_X skelIsthmus with table (empty objectSet)");
1039 vc.setSimplicityTable(
1043 auto pointToMaskMap =
1044 *functions::mapZeroPointNeighborhoodToConfigurationMask<Point>();
1045 auto skelWithTableIsthmus =
1046 [&table, &pointToMaskMap](
const FixtureComplex &fc,
1047 const FixtureComplex::Cell &c) {
1048 return skelWithTable(table, pointToMaskMap, fc, c);
1051 auto vc_new = asymetricThinningScheme<FixtureComplex>(
1052 vc, selectRandom<FixtureComplex>, skelWithTableIsthmus, verbose);
1061 auto &vc = complex_fixture;
1062 auto &ks = vc.space();
1063 boost::ignore_unused_variable_warning(ks);
1067 bool verbose =
true;
1068 SECTION(
"Fixture_X Distance Map") {
1071 DT dt(set_fixture.domain(), set_fixture, l3);
1073 auto selectDistMax = [&dt](
const FixtureComplex::Clique &clique) {
1074 return selectMaxValue<DT, FixtureComplex>(dt, clique);
1077 auto vc_new = asymetricThinningScheme<FixtureComplex>(
1078 vc, selectDistMax, skelEnd<FixtureComplex>, verbose);
1080 SECTION(
"persistenceThinning"){
1082 auto pointToMaskMap =
1083 *functions::mapZeroPointNeighborhoodToConfigurationMask<Point>();
1084 auto oneIsthmusTable =
1085 [&table, &pointToMaskMap](
const FixtureComplex &fc,
1086 const FixtureComplex::Cell &c) {
1087 return skelWithTable(table, pointToMaskMap, fc, c);
1089 int persistence = 3;
1090 auto vc_new = persistenceAsymetricThinningScheme<FixtureComplex>(
1091 vc, selectDistMax, oneIsthmusTable,
1092 persistence, verbose);
Aim: A wrapper class around a STL associative container for storing sets of digital points within som...
Aim: Represents a digital topology as a couple of adjacency relations.
TForegroundAdjacency ForegroundAdjacency
TBackgroundAdjacency BackgroundAdjacency
Aim: implements separable l_p metrics with exact predicates.
const ConstIterator & begin() const
const ConstIterator & end() const
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
const Point & lowerBound() const
Return the lower bound for digital points in this space.
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
const Point & upperBound() const
Return the upper bound for digital points in this space.
AnyCellCollection< Cell > Cells
Aim: An object (or digital object) represents a set in some digital space associated with a digital t...
void beginBlock(const std::string &keyword="")
This class represents a voxel complex living in some Khalimsky space. Voxel complexes are derived fro...
HyperRectDomain< Space > Domain
KhalimskySpaceND< 3, Integer > KSpace
DigitalSetSelector< Domain, BIG_DS+HIGH_BEL_DS >::Type DigitalSet
DigitalTopology< Adj26, Adj6 > DT26_6
functions namespace gathers all DGtal functionsxs.
DGtal::CountedPtr< boost::dynamic_bitset<> > loadTable(const std::string &input_filename, const unsigned int known_size, const bool compressed=true)
DGtal is the top-level namespace which contains all DGtal functions and types.
bool isEqual(Container1 &c1, Container2 &c2)
SECTION("Testing constant forward iterators")
REQUIRE(domain.isInside(aPoint))
TEST_CASE_METHOD(Fixture_complex_diamond, "insertVoxel", "[insert][close]")