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 <DGtal/topology/helpers/Surfaces.h>
54#include <DGtal/topology/LightImplicitDigitalSurface.h>
56#include "DGtalCatch.h"
70template <
typename KSpace >
76 INFO(
"Testing uNext & sNext with low = " << low <<
" & high = " << high );
90 refPoint[ i ] = t & (1u << i) ? 1 : 0;
92 INFO(
"Current topology is " << refPoint );
95 const auto refUCell = PK::uCell( refPoint );
96 auto currUCell =
K.
uCell( low, refUCell );
97 const auto lowUCell = currUCell;
98 const auto highUCell =
K.
uCell( high, refUCell );
102 const auto refSCell = PK::sCell( refPoint, PK::POS );
103 auto currSCell =
K.
sCell( low, refSCell );
104 const auto lowSCell = currSCell;
105 const auto highSCell =
K.
sCell( high, refSCell );
119 uCheck =
K.
uNext( currUCell, lowUCell, highUCell );
120 sCheck =
K.
sNext( currSCell, lowSCell, highSCell );
138template <
typename KSpace,
typename Cells >
144 REQUIRE( u.size() <= v.size() );
149 for(
auto const & cell : v )
154 REQUIRE( std::find( u.cbegin(), u.cend(),
K.
uCell( cell ) ) != u.cend() );
172template <
typename KSpace,
typename Cells >
178 REQUIRE( u.size() <= v.size() );
183 for(
auto const & cell : v )
188 REQUIRE( std::find( u.cbegin(), u.cend(),
K.
sCell( cell ) ) != u.cend() );
204template <
typename KSpace >
209 INFO(
"Testing (proper) neighborhood around point " <<
aPoint );
220 refPoint[ i ] = t & (1u << i) ? 1 : 0;
222 INFO(
"Current topology is " << refPoint );
225 const auto refUCell = PK::uCell( refPoint );
234 const auto refSCell = PK::sCell( refPoint, PK::NEG );
241 const auto refUCells = PK::uNeighborhood( currUCell );
243 const auto refSCells = PK::sNeighborhood( currSCell );
245 REQUIRE( currUCells.size() == currSCells.size() );
246 REQUIRE( refUCells.size() == refSCells.size() );
255 const auto refUCells = PK::uProperNeighborhood( currUCell );
257 const auto refSCells = PK::sProperNeighborhood( currSCell );
259 REQUIRE( currUCells.size() == currSCells.size() );
260 REQUIRE( refUCells.size() == refSCells.size() );
275template <
typename KSpace >
280 INFO(
"Testing faces and cofaces around point " <<
aPoint );
291 refPoint[ i ] = t & (1u << i) ? 1 : 0;
293 INFO(
"Current topology is " << refPoint );
296 const auto refUCell = PK::uCell( refPoint );
305 const auto refSCell = PK::sCell( refPoint, PK::NEG );
311 const auto currUCells =
K.
uFaces( currUCell );
312 const auto refUCells = PK::uFaces( currUCell );
314 REQUIRE( refUCells.size() == floor( std::pow( 3,
K.
uDim( currUCell ) ) - 1 ) );
320 const auto currUCells =
K.
uCoFaces( currUCell );
321 const auto refUCells = PK::uCoFaces( currUCell );
335template <
typename KSpace >
340 INFO(
"Testing block Incidence in KSpace..." );
347 for ( DirIterator q1 =
K.
sDirs( sspel ); q1 != 0; ++q1 )
348 for ( DirIterator q2 =
K.
sDirs( sspel ); q2 != 0; ++q2 )
356 INFO(
"D+_" << *q2 <<
"(D+_" << *q1 <<
"(V))=" << l10
357 <<
" D+_" << *q1 <<
"(D+_" << *q2 <<
"(V))=" << l01
371template <
typename KSpace >
376 INFO(
"Testing direct Incidence in KSpace..." );
383 for ( DirIterator q1 =
K.
sDirs( sspel ); q1 != 0; ++q1 )
384 for ( DirIterator q2 =
K.
sDirs( sspel ); q2 != 0; ++q2 )
392 INFO(
"Dd_" << *q2 <<
"(Dd_" << *q1 <<
"(V))=" << l10
393 <<
" Dd_" << *q1 <<
"(Dd_" << *q2 <<
"(V))=" << l01
415template <
typename KSpace>
422 INFO(
"Testing surfel adjacency ..." );
425 INFO(
"Testing surfel directness ..." );
432 INFO(
"spel=" << sspel <<
" surfel=" << surfel <<
" innerspel=" << innerspel );
437 INFO(
"spel=" << sspel <<
" surfel=" << surfel <<
" innerspel=" << innerspel );
441 INFO(
"Testing surfel neighborhood ..." );
444 SN.
init( &
K, &SAdj, surfel );
446 INFO(
"Testing surface tracking ..." );
451 const Point low = Point::diagonal(-3);
452 const Point high = Point::diagonal(3) + Point::base(0, 2);
459 const Point pcenter = Point::diagonal(0) + Point::base(0);
463 SCell other1, other2;
466 INFO(
"directNext = " << other1 );
469 INFO(
"indirectNext= " << other2 );
471 std::set<SCell> bdry;
475 std::set<SCell> bdry_direct;
481 INFO(
"Testing Board2D" );
485 for (
typename std::set<SCell>::const_iterator it = bdry_direct.begin(),
486 it_end = bdry_direct.end(); it != it_end; ++it )
488 board.
saveEPS(
"cells-2.eps" );
489 board.
saveSVG(
"cells-2.svg" );
498template <
typename KSpace>
510 INFO(
"Testing cell draw on digital board ..." );
512 const Point low( -3, -3 );
513 const Point high( 5, 3 );
530 Color( 255, 100, 100 ),
537 board.
saveEPS(
"cells-1.eps" );
538 board.
saveSVG(
"cells-1.svg" );
547 Color( 255, 100, 100 ) ) )
551 Color( 100, 255, 100 ) ) )
555 Color( 100, 100, 255 ) ) )
558 board.
saveEPS(
"cells-3.eps" );
559 board.
saveSVG(
"cells-3.svg" );
568template <
typename KSpace>
579 INFO(
"Test FindABel" );
581 const Point low = Point::diagonal(-3);
582 const Point high = Point::diagonal(3);
590 const Point p000 = Point::zero;
591 const Point p001 = Point::base(2);
592 const Point p010 = Point::base(1);
593 const Point p011 = p001 + p010;
594 const Point p100 = Point::base(0);
595 const Point p101 = p100 + p001;
596 const Point p110 = p100 + p010;
597 const Point p111 = Point::diagonal(1);
610 REQUIRE( s010 ==
K.
sCell( Point::diagonal(1) + Point::base(1),
true ) );
611 REQUIRE( s001 ==
K.
sCell( Point::diagonal(1) + Point::base(2),
false ) );
620template <
typename KSpace>
629 const Point low = Point::diagonal(-1);
630 const Point high = Point::diagonal(1);
635 const Cells faces =
K.
uFaces( vox );
638 INFO(
"Check CellularGridSpaceND::uFaces" );
645 for (
auto const & face : faces )
646 if (
K.
uDim( face ) == k )
665template <
typename KSpace>
674 const Point low = Point::diagonal(-1);
675 const Point high = Point::diagonal(1);
680 const Cells cofaces =
K.
uCoFaces( pointel );
683 INFO(
"Check CellularGridSpaceND::uCoFaces" );
690 for (
auto const & coface : cofaces )
692 if (
K.
uDim( coface ) == k )
726 INFO(
"Khalimsky space is " <<
K );
740 INFO(
"Khalimsky space is " <<
K );
754 INFO(
"Khalimsky space is " <<
K );
756 testScan(
K, {-1, -2, -3, -4}, {1, 0, 1, -1} );
765TEST_CASE(
"3D closed Khalimsky space",
"[KSpace][3D][closed]" )
768 const bool spaceOK =
K.
init( {-3, -3, -3}, {5, 3, 3},
K.
CLOSED );
769 INFO(
"Khalimsky space is " <<
K );
785TEST_CASE(
"2D closed Khalimsky space",
"[KSpace][2D][closed]" )
788 const bool spaceOK =
K.
init( {-3, -3}, {5, 3},
K.
CLOSED );
789 INFO(
"Khalimsky space is " <<
K );
805TEST_CASE(
"4D closed Khalimsky space",
"[KSpace][4D][closed]" )
808 const bool spaceOK =
K.
init( {-3, -3, -3, -3}, {5, 3, 3, 3},
K.
CLOSED );
809 INFO(
"Khalimsky space is " <<
K );
812 testScan(
K, {-1, -2, 0, 1}, {1, 2, 1, 2} );
825TEST_CASE(
"2D open Khalimsky space",
"[KSpace][2D][open]" )
828 const bool spaceOK =
K.
init( {-3, -3}, {5, 3},
K.
OPEN );
829 INFO(
"Khalimsky space is " <<
K );
845TEST_CASE(
"3D open Khalimsky space",
"[KSpace][3D][open]" )
848 const bool spaceOK =
K.
init( {-3, -3, -3}, {5, 3, 3},
K.
OPEN );
849 INFO(
"Khalimsky space is " <<
K );
865TEST_CASE(
"2D periodic Khalimsky space",
"[KSpace][2D][periodic]" )
869 INFO(
"Khalimsky space is " <<
K );
885TEST_CASE(
"3D periodic Khalimsky space",
"[KSpace][3D][periodic]" )
888 const bool spaceOK =
K.
init( {-3, -3, -3}, {2, 2, 3},
K.
PERIODIC );
889 INFO(
"Khalimsky space is " <<
K );
905TEST_CASE(
"2D mixed Khalimsky space",
"[KSpace][2D][closed][periodic]" )
909 INFO(
"Khalimsky space is " <<
K );
925TEST_CASE(
"3D mixed Khalimsky space",
"[KSpace][3D][closed][periodic][open]" )
929 INFO(
"Khalimsky space is " <<
K );
946TEST_CASE(
"3D test interior/exterior voxels to a digital surface")
951 for(
auto i=0; i < size*size*size; ++i)
953 INFO(
"Inserting " + std::to_string(set.
size())+
" voxels") ;
956 Point low( 0, 0, 0 );
957 Point high( 10, 10, 10 );
958 K.
init( low, high,
true );
961 for(
const auto &surfel: surface)
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...
void insertNew(const Point &p)
void insert(const Point &p)
std::string className() const
Aim: This class is a model of CPreCellularGridSpaceND. It represents the cubical grid as a cell compl...
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
Point interiorVoxel(const SCell &c) const
For a given surfel ((n-1)-signed cell), returns its interior voxel (point in Z^d given by the direct ...
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...
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).
Cell uPointel(Point p) const
From the digital coordinates of a point in Zn, builds the corresponding pointel (cell of dimension 0)...
KhalimskyPreSpaceND< dim, Integer > PreCellularGridSpace
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.
PointVector< dim, Integer > Point
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.
SignedKhalimskyCell< dim, Integer > SCell
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.
static const constexpr Sign POS
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.
SpaceND< dim, Integer > Space
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].
static const constexpr Dimension dimension
typename PreCellularGridSpace::DirIterator DirIterator
Point exteriorVoxel(const SCell &c) const
For a given surfel ((n-1)-signed cell), returns its exterior voxel (point in Z^d given by the indirec...
AnyCellCollection< Cell > Cells
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as the boundary of an impl...
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)
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
Aim: This helper class is useful to compute the neighboring surfels of a given surfel,...
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)
TEST_CASE("Checking concepts")
void testIncidence(KSpace const &K, typename KSpace::Point const &aPoint)
HyperRectDomain< Space > Domain
REQUIRE(domain.isInside(aPoint))
Z2i::DigitalSet DigitalSet