35#include "DGtal/base/Common.h"
36#include "DGtal/kernel/SpaceND.h"
37#include "DGtal/kernel/domains/DomainPredicate.h"
38#include "DGtal/kernel/domains/HyperRectDomain.h"
39#include "DGtal/kernel/sets/DigitalSetSelector.h"
40#include "DGtal/kernel/sets/DigitalSetConverter.h"
41#include "DGtal/topology/MetricAdjacency.h"
42#include "DGtal/topology/DomainAdjacency.h"
43#include "DGtal/topology/DigitalTopology.h"
44#include "DGtal/topology/Object.h"
45#include "DGtal/graph/Expander.h"
46#include "DGtal/io/boards/Board2D.h"
47#include "DGtal/io/Color.h"
48#include "DGtal/io/colormaps/GradientColorMap.h"
49#include "DGtal/shapes/Shapes.h"
50#include "DGtal/helpers/StdDefs.h"
51#include "DGtal/topology/NeighborhoodConfigurations.h"
52#include "DGtal/topology/tables/NeighborhoodTables.h"
59#define INBLOCK_TEST(x) \
60 nbok += ( x ) ? 1 : 0; \
62 trace.info() << "(" << nbok << "/" << nb << ") " \
59#define INBLOCK_TEST(x) \ …
65#define INBLOCK_TEST2(x,y) \
66 nbok += ( x ) ? 1 : 0; \
68 trace.info() << "(" << nbok << "/" << nb << ") " \
65#define INBLOCK_TEST2(x,y) \ …
80 unsigned int nbok = 0;
87 Point p1( -449, -449 );
89 DomainType
domain( p1, p2 );
103 typedef ObjectType::SmallSet SmallSet;
105 typedef ObjectType::Size
Size;
116 double radius = (double) (r+1);
121 sstr <<
"Creating disk( r < " << radius <<
" ) ...";
122 trace.beginBlock ( sstr.str() );
123 for ( DomainType::ConstIterator it =
domain.begin();
127 if ( (*it - c ).norm() < radius )
129 disk.insertNew( *it );
133 trace.beginBlock (
"Testing Object instanciation and smart copy ..." );
134 ObjectType disk_object( dt48, disk );
135 nbok += disk_object.size() == 7825 ? 1 : 0;
137 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
138 <<
"Disk (r=450.0) " << disk_object << std::endl;
139 trace.info() <<
" size=" << disk_object.size() << std::endl;
140 ObjectType disk_object2( disk_object );
141 nbok += disk_object2.size() == 7825 ? 1 : 0;
143 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
144 <<
"Disk2 (r=450.0) " << disk_object2 << std::endl;
145 trace.info() <<
" size=" << disk_object2.size() << std::endl;
148 trace.beginBlock (
"Testing copy on write system ..." );
149 trace.info() <<
"Removing center point in Disk." << std::endl;
150 disk_object.pointSet().erase( c );
151 disk_object2.pointSet().insert( c );
152 nbok += disk_object.size() == 7824 ? 1 : 0;
154 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
155 <<
"Disk - c (r=450.0) " << disk_object << std::endl;
156 trace.info() <<
" size=" << disk_object.size() << std::endl;
157 nbok += disk_object2.size() == 7825 ? 1 : 0;
159 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
160 <<
"Disk2 + c (r=450.0) " << disk_object2 << std::endl;
161 trace.info() <<
" size=" << disk_object2.size() << std::endl;
164 trace.beginBlock (
"Testing neighborhoods ..." );
166 nbok += neigh.
size() == 4 ? 1 : 0;
168 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
169 <<
"N_4(Disk, c).size() = " << neigh.
size()
170 <<
" == 4" << std::endl;
172 nbok += neigh.
size() == 3 ? 1 : 0;
174 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
175 <<
"N*_4(Disk, " << l <<
").size() = " << neigh.
size()
176 <<
" == 3" << std::endl;
177 Size size = disk_object.properNeighborhoodSize( l );
178 nbok += size == 3 ? 1 : 0;
180 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
181 <<
"#N*_4(Disk, " << l <<
") = " << size
182 <<
" == 3" << std::endl;
185 nbok += neigh.
size() == 5 ? 1 : 0;
187 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
188 <<
"N_4(Disk2, c).size() = " << neigh.
size()
189 <<
" == 5" << std::endl;
192 trace.beginBlock (
"Testing set converters ..." );
194 ( neigh.
pointSet(), disk_object.pointSet() );
195 nbok += neigh.
size() == 7824 ? 1 : 0;
197 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
198 <<
"neigh = disk_object, size() = " << neigh.
size()
199 <<
" == 636100" << std::endl;
200 SmallObjectType neigh2 = disk_object2.neighborhood( c );
202 ( neigh.
pointSet(), neigh2.pointSet() );
203 nbok += neigh.
size() == 5 ? 1 : 0;
205 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
206 <<
"neigh = N_4(Disk2, c), size() = " << neigh.
size()
207 <<
" == 5" << std::endl;
210 trace.beginBlock (
"Testing border extraction ..." );
211 ObjectType bdisk = disk_object.border();
212 nbok += bdisk.size() == 400 ? 1 : 0;
214 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
215 <<
"Border(Disk, c), size() = " << bdisk.size()
216 <<
" == 3372" << std::endl;
217 ObjectType bdisk2 = disk_object2.border();
218 nbok += bdisk2.size() == 392 ? 1 : 0;
220 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
221 <<
"Border(Disk2, c), size() = " << bdisk2.size()
222 <<
" == 3364" << std::endl;
225 trace.beginBlock (
"Testing expansion by layers on the boundary ..." );
227 ObjectExpander expander( bdisk, *(bdisk.pointSet().begin()) );
228 while ( ! expander.finished() )
230 nbok += expander.layer().size() <= 2 ? 1 : 0;
232 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
233 <<
"expander.layer.size() <= 2 "
234 << expander << std::endl;
235 expander.nextLayer();
239 trace.beginBlock (
"Testing expansion by layers on the disk from center..." );
240 ObjectExpander expander2( disk_object2, c );
241 while ( ! expander2.finished() )
243 trace.info() << expander2 << std::endl;
244 expander2.nextLayer();
246 nbok += expander2.distance() <= sqrt(2.0)*radius ? 1 : 0;
248 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
249 <<
"expander.distance() = " << expander2.distance()
250 <<
" <= " << sqrt(2.0)*radius << std::endl;
262 unsigned int nbok = 0;
268 typedef Z3::Point
Point;
277 Point p1( -50, -50, -50 );
278 Point p2( 50, 50, 50 );
283 trace.beginBlock (
"Testing 3D Object instanciation and smart copy ..." );
284 trace.info() <<
"Creating diamond (r=15)" << endl;
287 for ( DomainConstIterator it =
domain.begin(); it !=
domain.end(); ++it )
289 if ( (*it - c ).norm1() <= 15 ) diamond_set.
insertNew( *it );
291 ObjectType diamond( dt6_18, diamond_set );
292 trace.info() <<
"Cloning diamond" << endl;
294 ObjectType diamond_clone( diamond );
296 trace.info() <<
"Removing two points " << c <<
" and " << d << endl;
297 diamond_clone.pointSet().erase( c );
298 diamond_clone.pointSet().erase( d );
300 trace.info() <<
"Inserting into vector<Object>" << endl;
301 vector<ObjectType> objects;
302 back_insert_iterator< vector< ObjectType > > inserter( objects );
303 *inserter++ = diamond;
304 *inserter++ = diamond_clone;
306 for ( vector<ObjectType>::const_iterator it = objects.begin();
309 trace.info() <<
"- objects[" << (it - objects.begin() ) <<
"]"
310 <<
" = " << *it << endl;
312 INBLOCK_TEST( objects[ 0 ].size() == ( objects[ 1 ].size() + 2 ) );
316 trace.beginBlock (
"Testing connected component extraction ..." );
322 trace.beginBlock (
"Components of diamond.border() ..." );
323 vector<ObjectType> objects2;
324 back_insert_iterator< vector< ObjectType > > inserter2( objects2 );
325 auto nbc0 = objects[ 0 ].border().writeComponents( inserter2 );
330 trace.beginBlock (
"Components of diamond_clone.border() ..." );
331 auto nbc1 = objects[ 1 ].border().writeComponents( inserter2 );
334 for ( vector<ObjectType>::const_iterator it = objects2.begin();
335 it != objects2.end();
337 trace.info() <<
"- objects2[" << (it - objects2.begin() ) <<
"]"
338 <<
" = " << *it << endl;
339 INBLOCK_TEST( objects2[ 0 ].size() == objects2[ 1 ].size() );
340 INBLOCK_TEST( objects2[ 2 ].size() == objects2[ 3 ].size() );
356 unsigned int nbok = 0;
362 typedef Z3::Point
Point;
373 Point p1( -10, -10, -10 );
374 Point p2( 10, 10, 10 );
379 trace.beginBlock (
"Creating Diamond (r=4)" );
382 for ( DomainConstIterator it =
domain.begin(); it !=
domain.end(); ++it )
384 if ( (*it - c ).norm1() <= 3 ) diamond_set.
insertNew( *it );
386 diamond_set.
erase( c );
387 ObjectType diamond( dt6_18, diamond_set );
390 trace.beginBlock (
"Geodesic neighborhoods ..." );
391 SmallObjectType geoN6_3 = diamond.geodesicNeighborhood( adj6, r, 3 );
392 SmallObjectType geoN18_2 = diamond.geodesicNeighborhood( adj18, r, 2 );
393 trace.info() <<
"geoN6_3 = " << geoN6_3 << endl;
394 trace.info() <<
"geoN18_2 = " << geoN18_2 << endl;
395 SmallComplementObjectType cgeoN6_3 = diamond.geodesicNeighborhoodInComplement( adj6, r, 3 );
396 SmallComplementObjectType cgeoN18_2 = diamond.geodesicNeighborhoodInComplement( adj18, r, 2 );
397 trace.info() <<
"cgeoN6_3 = " << cgeoN6_3 << endl;
398 trace.info() <<
"cgeoN18_2 = " << cgeoN18_2 << endl;
401 trace.beginBlock (
"Simple points ..." );
403 it != diamond.pointSet().end();
405 trace.info() <<
"- " << *it
406 <<
" " << ( diamond.isSimple( *it ) ?
"Simple" :
"Not simple" )
417 unsigned int nbok = 0;
420 trace.beginBlock (
"testDraw(): testing drawing commands." );
426 Point p1( -10, -10 );
428 DomainType
domain( p1, p2 );
459 double radius = (double) (r+1);
464 sstr <<
"Creating disk( r < " << radius <<
" ) ...";
465 trace.beginBlock ( sstr.str() );
466 for ( DomainType::ConstIterator it =
domain.begin();
470 if ( (*it - c ).norm() < radius )
472 disk.insertNew( *it );
476 trace.beginBlock (
"Testing Object instanciation and smart copy ..." );
477 ObjectType disk_object( dt48, disk );
478 ObjectType84 disk_object2( dt84, disk );
481 trace.beginBlock (
"Testing export as SVG with libboard." );
487 board << disk_object;
489 board.
saveSVG(
"disk-object.svg");
495 board2 <<
SetMode( disk_object.className(),
"DrawAdjacencies" ) << disk_object;
497 board2.
saveSVG(
"disk-object-adj.svg");
503 board3 <<
SetMode( disk_object2.className(),
"DrawAdjacencies" ) << disk_object2;
505 board3.
saveSVG(
"disk-object-adj-bis.svg");
548 unsigned int nbok = 0;
553 Point p1( -17, -17 );
586 trace.beginBlock (
"Greedy homotopic thinning ..." );
591 std::queue<DigitalSet::Iterator> Q;
596 while ( ! Q.empty() )
604 ( cmap_grad( layer ) ) )
611 }
while ( nb_simple != 0 );
615 trace.beginBlock (
"Greedy homotopic thinning ..." );
620 std::queue<DigitalSet::Iterator> Q;
625 while ( ! Q.empty() )
633 ( cmap_grad( layer ) ) )
640 }
while ( nb_simple != 0 );
645 board.
saveSVG(
"shape-thinning-4-8.svg");
650 board2.
saveSVG(
"shape-thinning-8-4.svg");
659 unsigned int nbok = 0;
662 using namespace DGtal;
668 trace.beginBlock (
"Create Diamond Object" );
669 Point p1( -10, -10, -10 );
670 Point p2( 10, 10, 10 );
677 for (
auto it =
domain.begin(); it !=
domain.end(); ++it )
679 if ( (*it - c ).norm1() <= 3 ) diamond_set.
insertNew( *it );
684 bool space_ok =
K.init(
domain.lowerBound(),
693 MyDigitalTopology::ForegroundAdjacency adjF;
694 MyDigitalTopology::BackgroundAdjacency adjB;
696 MyObject obj(topo,diamond_set);
700 trace.beginBlock(
"Check edges" );
702 std::set<Point> corner_points;
703 Point north( 0 , 0 , 3 );
704 corner_points.insert(north);
705 Point south( 0 , 0 , -3 );
706 corner_points.insert(south);
707 Point east( 3 , 0 , 0 );
708 corner_points.insert(east);
709 Point west( -3 , 0 , 0 );
710 corner_points.insert(west);
712 for(
auto && p : corner_points){
713 auto pit = obj.pointSet().find(p);
714 if(pit == obj.pointSet().end()){
715 trace.info() <<
"point not found" << std::endl;
718 auto edges = obj.outEdges(*pit);
721 Point center( 0 , 0 , 0 );
722 auto cpit = obj.pointSet().find(center);
723 auto cedges = obj.outEdges(*cpit);
727 for(
auto && e : cedges){
728 auto rev_e = obj.opposite(e);
730 (e.vertices[0] == rev_e.vertices[1]) &&
731 (e.vertices[1] == rev_e.vertices[0])
742 unsigned int nbok = 0;
747 Point p1( -17, -17 );
784 trace.beginBlock (
"Greedy homotopic thinning with table..." );
788 std::queue<DigitalSet::Iterator> Q;
793 while ( ! Q.empty() )
801 ( cmap_grad( layer ) ) )
808 }
while ( nb_simple != 0 );
817int main(
int argc,
char** argv )
819 trace.beginBlock (
"Testing class Object" );
820 trace.info() <<
"Args:";
821 for (
int i = 0; i < argc; ++i )
822 trace.info() <<
" " << argv[ i ];
823 trace.info() << endl;
832 trace.emphase() << ( res ?
"Passed." :
"Error." ) << endl;
817int main(
int argc,
char** argv ) {
…}
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)
ConstIterator end() const
Container::iterator Iterator
ConstIterator begin() const
Size erase(const Point &p)
Container::const_iterator ConstIterator
Aim: Given a domain and an adjacency, limits the given adjacency to the specified domain for all adja...
Aim: This class is useful to visit an object by adjacencies, layer by layer.
Aim: This class template may be used to (linearly) convert scalar values in a given range into a colo...
void addColor(const Color &color)
Aim: Parallelepidec region of a digital space, model of a 'CDomain'.
Aim: Describes digital adjacencies in digital spaces that are defined with the 1-norm and the infinit...
Aim: An object (or digital object) represents a set in some digital space associated with a digital t...
Object< ReverseTopology, SmallSet > SmallComplementObject
const DigitalSet & pointSet() const
std::string className() const
SmallObject properNeighborhood(const Point &p) const
SmallObject neighborhood(const Point &p) const
Object< DigitalTopology, SmallSet > SmallObject
void setTable(Alias< boost::dynamic_bitset<> >inputTable)
bool isSimple(const Point &v) const
static void addNorm1Ball(TDigitalSet &aSet, const Point &aCenter, UnsignedInteger aRadius)
PointVector< dim, Integer > Point
Board & setPenColorRGBi(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=255)
void clear(const DGtal::Color &color=DGtal::Color::None)
Board & setFillColor(const DGtal::Color &color)
Board & setLineWidth(double width)
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Board & setLineStyle(Shape::LineStyle style)
Z2i this namespace gathers the standard of types for 2D imagery.
Object< DT8_4, DigitalSet > Object8_4
MetricAdjacency< Space, 1 > Adj4
KhalimskySpaceND< 2, Integer > KSpace
Object< DT4_8, DigitalSet > Object4_8
MetricAdjacency< Space, 2 > Adj8
DigitalSetSelector< Domain, BIG_DS+HIGH_BEL_DS >::Type DigitalSet
Z3i this namespace gathers the standard of types for 3D imagery.
HyperRectDomain< Space > Domain
KhalimskySpaceND< 3, Integer > KSpace
DigitalSetSelector< Domain, BIG_DS+HIGH_BEL_DS >::Type DigitalSet
DigitalTopology< Adj26, Adj6 > DT26_6
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.
std::uint64_t uint64_t
unsigned 64-bit integer.
static void assign(OutputDigitalSet &output, const InputDigitalSet &input)
DigitalSetByAssociativeContainer< Domain, std::unordered_set< typename Domain::Point > > Type
Modifier class in a Board2D stream. Useful to choose your own mode for a given class....
Struct representing a 2D point.
virtual void setStyle(Board2D &aboard) const
MyDrawStyleCustomFillColor(const Color &c)
virtual void setStyle(Board2D &aboard) const
HalfEdgeDataStructure::Size Size
bool testSimplePoints3D()
#define INBLOCK_TEST2(x, y)
bool testSimplePoints2D()