36 #include "DGtal/base/Common.h"
37 #include "DGtal/kernel/SpaceND.h"
38 #include "DGtal/kernel/domains/HyperRectDomain.h"
40 #include "DGtal/topology/KhalimskySpaceND.h"
41 #include "DGtal/topology/KhalimskyPreSpaceND.h"
43 #include "DGtal/topology/CCellularGridSpaceND.h"
44 #include "DGtal/topology/CPreCellularGridSpaceND.h"
46 #include "DGtal/topology/SurfelAdjacency.h"
47 #include "DGtal/topology/SurfelNeighborhood.h"
48 #include "DGtal/shapes/Shapes.h"
49 #include "DGtal/topology/helpers/Surfaces.h"
50 #include "DGtal/io/boards/Board2D.h"
51 #include "DGtal/io/Color.h"
53 #include "DGtalCatch.h"
56 using namespace DGtal;
67 template <
typename KSpace >
73 INFO(
"Testing uNext & sNext with low = " << low <<
" & high = " << high );
82 for (
unsigned int t = 0; t < 1u << KSpace::dimension; ++t )
87 refPoint[ i ] = t & (1u << i) ? 1 : 0;
89 INFO(
"Current topology is " << refPoint );
92 const auto refUCell = PK::uCell( refPoint );
93 auto currUCell =
K.
uCell( low, refUCell );
94 const auto lowUCell = currUCell;
95 const auto highUCell =
K.
uCell( high, refUCell );
99 const auto refSCell = PK::sCell( refPoint, PK::POS );
100 auto currSCell =
K.
sCell( low, refSCell );
101 const auto lowSCell = currSCell;
102 const auto highSCell =
K.
sCell( high, refSCell );
116 uCheck =
K.
uNext( currUCell, lowUCell, highUCell );
117 sCheck =
K.
sNext( currSCell, lowSCell, highSCell );
135 template <
typename KSpace,
typename Cells >
141 REQUIRE( u.size() <= v.size() );
146 for(
auto const & cell : v )
151 REQUIRE( std::find( u.cbegin(), u.cend(),
K.
uCell( cell ) ) != u.cend() );
169 template <
typename KSpace,
typename Cells >
175 REQUIRE( u.size() <= v.size() );
180 for(
auto const & cell : v )
185 REQUIRE( std::find( u.cbegin(), u.cend(),
K.
sCell( cell ) ) != u.cend() );
201 template <
typename KSpace >
206 INFO(
"Testing (proper) neighborhood around point " <<
aPoint );
212 for (
unsigned int t = 0; t < 1u << KSpace::dimension; ++t )
217 refPoint[ i ] = t & (1u << i) ? 1 : 0;
219 INFO(
"Current topology is " << refPoint );
222 const auto refUCell = PK::uCell( refPoint );
231 const auto refSCell = PK::sCell( refPoint, PK::NEG );
238 const auto refUCells = PK::uNeighborhood( currUCell );
240 const auto refSCells = PK::sNeighborhood( currSCell );
242 REQUIRE( currUCells.size() == currSCells.size() );
243 REQUIRE( refUCells.size() == refSCells.size() );
252 const auto refUCells = PK::uProperNeighborhood( currUCell );
254 const auto refSCells = PK::sProperNeighborhood( currSCell );
256 REQUIRE( currUCells.size() == currSCells.size() );
257 REQUIRE( refUCells.size() == refSCells.size() );
272 template <
typename KSpace >
277 INFO(
"Testing faces and cofaces around point " <<
aPoint );
283 for (
unsigned int t = 0; t < 1u << KSpace::dimension; ++t )
288 refPoint[ i ] = t & (1u << i) ? 1 : 0;
290 INFO(
"Current topology is " << refPoint );
293 const auto refUCell = PK::uCell( refPoint );
302 const auto refSCell = PK::sCell( refPoint, PK::NEG );
308 const auto currUCells =
K.
uFaces( currUCell );
309 const auto refUCells = PK::uFaces( currUCell );
311 REQUIRE( refUCells.size() == floor( std::pow( 3,
K.
uDim( currUCell ) ) - 1 ) );
317 const auto currUCells =
K.
uCoFaces( currUCell );
318 const auto refUCells = PK::uCoFaces( currUCell );
332 template <
typename KSpace >
337 INFO(
"Testing block Incidence in KSpace..." );
344 for ( DirIterator q1 =
K.
sDirs( sspel ); q1 != 0; ++q1 )
345 for ( DirIterator q2 =
K.
sDirs( sspel ); q2 != 0; ++q2 )
353 INFO(
"D+_" << *q2 <<
"(D+_" << *q1 <<
"(V))=" << l10
354 <<
" D+_" << *q1 <<
"(D+_" << *q2 <<
"(V))=" << l01
368 template <
typename KSpace >
373 INFO(
"Testing direct Incidence in KSpace..." );
380 for ( DirIterator q1 =
K.
sDirs( sspel ); q1 != 0; ++q1 )
381 for ( DirIterator q2 =
K.
sDirs( sspel ); q2 != 0; ++q2 )
389 INFO(
"Dd_" << *q2 <<
"(Dd_" << *q1 <<
"(V))=" << l10
390 <<
" Dd_" << *q1 <<
"(Dd_" << *q2 <<
"(V))=" << l01
412 template <
typename KSpace>
419 INFO(
"Testing surfel adjacency ..." );
422 INFO(
"Testing surfel directness ..." );
429 INFO(
"spel=" << sspel <<
" surfel=" << surfel <<
" innerspel=" << innerspel );
434 INFO(
"spel=" << sspel <<
" surfel=" << surfel <<
" innerspel=" << innerspel );
438 INFO(
"Testing surfel neighborhood ..." );
441 SN.
init( &
K, &SAdj, surfel );
443 INFO(
"Testing surface tracking ..." );
448 const Point low = Point::diagonal(-3);
449 const Point high = Point::diagonal(3) + Point::base(0, 2);
454 DigitalSet shape_set(
domain );
456 const Point pcenter = Point::diagonal(0) + Point::base(0);
460 SCell other1, other2;
463 INFO(
"directNext = " << other1 );
466 INFO(
"indirectNext= " << other2 );
468 std::set<SCell> bdry;
472 std::set<SCell> bdry_direct;
478 INFO(
"Testing Board2D" );
482 for (
typename std::set<SCell>::const_iterator it = bdry_direct.begin(),
483 it_end = bdry_direct.end(); it != it_end; ++it )
485 board.
saveEPS(
"cells-2.eps" );
486 board.
saveSVG(
"cells-2.svg" );
495 template <
typename KSpace>
507 INFO(
"Testing cell draw on digital board ..." );
509 const Point low( -3, -3 );
510 const Point high( 5, 3 );
527 Color( 255, 100, 100 ),
534 board.
saveEPS(
"cells-1.eps" );
535 board.
saveSVG(
"cells-1.svg" );
544 Color( 255, 100, 100 ) ) )
548 Color( 100, 255, 100 ) ) )
552 Color( 100, 100, 255 ) ) )
555 board.
saveEPS(
"cells-3.eps" );
556 board.
saveSVG(
"cells-3.svg" );
565 template <
typename KSpace>
576 INFO(
"Test FindABel" );
578 const Point low = Point::diagonal(-3);
579 const Point high = Point::diagonal(3);
585 DigitalSet shape_set(
domain );
587 const Point p000 = Point::zero;
588 const Point p001 = Point::base(2);
589 const Point p010 = Point::base(1);
590 const Point p011 = p001 + p010;
591 const Point p100 = Point::base(0);
592 const Point p101 = p100 + p001;
593 const Point p110 = p100 + p010;
594 const Point p111 = Point::diagonal(1);
596 shape_set.insert( p000 );
597 shape_set.insert( p100 );
607 REQUIRE( s010 ==
K.
sCell( Point::diagonal(1) + Point::base(1),
true ) );
608 REQUIRE( s001 ==
K.
sCell( Point::diagonal(1) + Point::base(2),
false ) );
617 template <
typename KSpace>
626 const Point low = Point::diagonal(-1);
627 const Point high = Point::diagonal(1);
632 const Cells faces =
K.
uFaces( vox );
635 INFO(
"Check CellularGridSpaceND::uFaces" );
642 for (
auto const & face : faces )
643 if (
K.
uDim( face ) == k )
662 template <
typename KSpace>
671 const Point low = Point::diagonal(-1);
672 const Point high = Point::diagonal(1);
677 const Cells cofaces =
K.
uCoFaces( pointel );
680 INFO(
"Check CellularGridSpaceND::uCoFaces" );
687 for (
auto const & coface : cofaces )
689 if (
K.
uDim( coface ) == k )
720 TEST_CASE(
"2D Khalimsky pre-space",
"[KPreSpace][2D]" )
723 INFO(
"Khalimsky space is " <<
K );
734 TEST_CASE(
"3D Khalimsky pre-space",
"[KPreSpace][3D]" )
737 INFO(
"Khalimsky space is " <<
K );
748 TEST_CASE(
"4D Khalimsky pre-space",
"[KPreSpace][4D]" )
751 INFO(
"Khalimsky space is " <<
K );
753 testScan(
K, {-1, -2, -3, -4}, {1, 0, 1, -1} );
762 TEST_CASE(
"3D closed Khalimsky space",
"[KSpace][3D][closed]" )
765 const bool spaceOK =
K.
init( {-3, -3, -3}, {5, 3, 3},
K.
CLOSED );
766 INFO(
"Khalimsky space is " <<
K );
782 TEST_CASE(
"2D closed Khalimsky space",
"[KSpace][2D][closed]" )
785 const bool spaceOK =
K.
init( {-3, -3}, {5, 3},
K.
CLOSED );
786 INFO(
"Khalimsky space is " <<
K );
802 TEST_CASE(
"4D closed Khalimsky space",
"[KSpace][4D][closed]" )
805 const bool spaceOK =
K.
init( {-3, -3, -3, -3}, {5, 3, 3, 3},
K.
CLOSED );
806 INFO(
"Khalimsky space is " <<
K );
809 testScan(
K, {-1, -2, 0, 1}, {1, 2, 1, 2} );
822 TEST_CASE(
"2D open Khalimsky space",
"[KSpace][2D][open]" )
825 const bool spaceOK =
K.
init( {-3, -3}, {5, 3},
K.
OPEN );
826 INFO(
"Khalimsky space is " <<
K );
842 TEST_CASE(
"3D open Khalimsky space",
"[KSpace][3D][open]" )
845 const bool spaceOK =
K.
init( {-3, -3, -3}, {5, 3, 3},
K.
OPEN );
846 INFO(
"Khalimsky space is " <<
K );
862 TEST_CASE(
"2D periodic Khalimsky space",
"[KSpace][2D][periodic]" )
866 INFO(
"Khalimsky space is " <<
K );
882 TEST_CASE(
"3D periodic Khalimsky space",
"[KSpace][3D][periodic]" )
885 const bool spaceOK =
K.
init( {-3, -3, -3}, {2, 2, 3},
K.
PERIODIC );
886 INFO(
"Khalimsky space is " <<
K );
902 TEST_CASE(
"2D mixed Khalimsky space",
"[KSpace][2D][closed][periodic]" )
906 INFO(
"Khalimsky space is " <<
K );
922 TEST_CASE(
"3D mixed Khalimsky space",
"[KSpace][3D][closed][periodic][open]" )
926 INFO(
"Khalimsky space is " <<
K );
Aim: This class specializes a 'Board' class so as to display DGtal objects more naturally (with <<)....
Structure representing an RGB triple with alpha component.
Aim: A wrapper class around a STL associative container for storing sets of digital points within som...
std::string className() const
Aim: This class is a model of CPreCellularGridSpaceND. It represents the cubical grid as a cell compl...
static Cell uSpel(Point p)
From the digital coordinates of a point in Zn, builds the corresponding pre-spel (pre-cell of maximal...
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
bool sNext(SCell &p, const SCell &lower, const SCell &upper) const
Increment the cell [p] to its next position (as classically done in a scanning).
Cell uSpel(Point p) const
From the digital coordinates of a point in Zn, builds the corresponding spel (cell of maximal dimensi...
bool uIsInside(const PreCell &p, Dimension k) const
Useful to check if you are going out of the space.
Cell uIncident(const Cell &c, Dimension k, bool up) const
Return the forward or backward unsigned cell incident to [c] along axis [k], depending on [up].
Cells uCoFaces(const Cell &c) const
Return the proper cofaces of [c] (chain of upper incidence) that belong to the space.
TInteger Integer
Arithmetic ring induced by (+,-,*) and Integer numbers.
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
Dimension sOrthDir(const SCell &s) const
Given a signed surfel [s], returns its orthogonal direction (ie, the coordinate where the surfel is c...
static constexpr const Sign POS
DirIterator sDirs(const SCell &p) const
Given a signed cell [p], returns an iterator to iterate over each coordinate the cell spans.
Cells uFaces(const Cell &c) const
Return the proper faces of [c] (chain of lower incidence) that belong to the space.
Cells uNeighborhood(const Cell &cell) const
Computes the 1-neighborhood of the cell [c] and returns it.
SCell sOpp(const SCell &p) const
Creates the signed cell with the inverse sign of [p].
bool uNext(Cell &p, const Cell &lower, const Cell &upper) const
Increment the cell [p] to its next position (as classically done in a scanning).
static constexpr const Dimension dimension
Cell uPointel(Point p) const
From the digital coordinates of a point in Zn, builds the corresponding pointel (cell of dimension 0)...
bool sDirect(const SCell &p, Dimension k) const
Return 'true' if the direct orientation of [p] along [k] is in the positive coordinate direction.
Integer sTopology(const SCell &p) const
Return the topology word of [p].
SCell sCell(const SPreCell &c) const
From a signed cell, returns a signed cell lying into this Khalismky space.
SCells sProperNeighborhood(const SCell &cell) const
Computes the proper 1-neighborhood of the cell [c] and returns it.
Integer uTopology(const Cell &p) const
Return the topology word of [p].
Cells uProperNeighborhood(const Cell &cell) const
Computes the proper 1-neighborhood of the cell [c] and returns it.
SCell sSpel(Point p, Sign sign=POS) const
From the digital coordinates of a point in Zn, builds the corresponding spel (cell of maximal dimensi...
Cell uCell(const PreCell &c) const
From an unsigned cell, returns an unsigned cell lying into this Khalismky space.
SCell sDirectIncident(const SCell &p, Dimension k) const
Return the direct incident cell of [p] along [k] (the incident cell along [k])
@ CLOSED
The dimension is closed and non-periodic.
@ OPEN
The dimension is open.
@ PERIODIC
The dimension is periodic.
SCells sNeighborhood(const SCell &cell) const
Computes the 1-neighborhood of the cell [c] and returns it.
bool sIsInside(const SPreCell &p, Dimension k) const
Useful to check if you are going out of the space.
AnyCellCollection< SCell > SCells
Sign sSign(const SCell &c) const
Return its sign.
Dimension uDim(const Cell &p) const
Return the dimension of the cell [p].
SCell sIncident(const SCell &c, Dimension k, bool up) const
Return the forward or backward signed cell incident to [c] along axis [k], depending on [up].
typename PreCellularGridSpace::DirIterator DirIterator
AnyCellCollection< Cell > Cells
static void addNorm1Ball(TDigitalSet &aSet, const Point &aCenter, UnsignedInteger aRadius)
static void trackClosedBoundary(SCellSet &surface, const KSpace &K, const SurfelAdjacency< KSpace::dimension > &surfel_adj, const PointPredicate &pp, const SCell &start_surfel)
static void trackBoundary(SCellSet &surface, const KSpace &K, const SurfelAdjacency< KSpace::dimension > &surfel_adj, const PointPredicate &pp, const SCell &start_surfel)
static SCell findABel(const KSpace &K, const PointPredicate &pp, unsigned int nbtries=1000)
void init(const KSpace *space, const SurfelAdjacency< KSpace::dimension > *adj, const SCell &aSurfel)
unsigned int getAdjacentOnDigitalSet(SCell &adj_surfel, const DigitalSet &obj, Dimension track_dir, bool pos) const
void clear(const DGtal::Color &color=DGtal::Color::None)
void saveEPS(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Point::Coordinate Integer
DGtal is the top-level namespace which contains all DGtal functions and types.
boost::int64_t int64_t
signed 94-bit integer.
DGtal::uint32_t Dimension
Custom style class redefining the pen color and the fill color. You may use Board2D::Color::None for ...
Custom style class redefining the pen attributes. You may use Board2D::Color::None for transparent co...
Modifier class in a Board2D stream. Useful to choose your own mode for a given class....
Represents a signed cell in a cellular grid space by its Khalimsky coordinates and a boolean value.
std::string className() const
Return the style name used for drawing this object.
Aim: This concept describes a cellular grid space in nD. In these spaces obtained by cartesian produc...
Aim: This concept describes an unbounded cellular grid space in nD. In these spaces obtained by carte...
void testCellularGridSpaceNDCoFaces(KSpace const &K)
void testCellularGridSpaceNDFaces(KSpace const &K)
void cmpSCellsIfInside(KSpace const &K, typename KSpace::SCells const &u, Cells const &v)
void cmpUCellsIfInside(KSpace const &K, typename KSpace::Cells const &u, Cells const &v)
void testSurfelAdjacency(KSpace const &K)
void testScan(KSpace const &K, typename KSpace::Point const &low, typename KSpace::Point const &high)
void testCellDrawOnBoard(KSpace const &K)
void testDirectIncidence(KSpace const &K, typename KSpace::Point const &aPoint)
void testFaces(KSpace const &K, typename KSpace::Point const &aPoint)
void testNeighborhood(KSpace const &K, typename KSpace::Point const &aPoint)
void testFindABel(KSpace const &K)
TEST_CASE("Checking concepts")
void testIncidence(KSpace const &K, typename KSpace::Point const &aPoint)
HyperRectDomain< Space > Domain
REQUIRE(domain.isInside(aPoint))