DGtal 1.4.0
Loading...
Searching...
No Matches
testNeighborhoodConfigurations.cpp
Go to the documentation of this file.
1
33#include "DGtalCatch.h"
34#include "DGtal/helpers/StdDefs.h"
35#include "DGtal/shapes/Shapes.h"
36#include "DGtal/base/Common.h"
37#include "DGtal/topology/NeighborhoodConfigurations.h"
38#include "DGtal/topology/tables/NeighborhoodTables.h"
39using namespace std;
40using namespace DGtal;
41using namespace DGtal::functions;
42
43template <typename TObject>
44TObject
45Object3D(const typename TObject::DigitalTopology &dt)
46{
47 using namespace DGtal;
48 using namespace Z3i;
49 Point p1( -10, -10, -10 );
50 Point p2( 10, 10, 10 );
51 Domain domain( p1, p2 );
52 Point c( 0, 0, 0 );
53 Point r( 3, 0, 0 );
54 DigitalSet diamond_set( domain );
55 for ( auto it = domain.begin(); it != domain.end(); ++it )
56 {
57 if ( (*it - c ).norm1() <= 3 ) diamond_set.insertNew( *it );
58 }
59 diamond_set.erase( c );
60 KSpace K;
62 domain.upperBound(), true);
63
64 return TObject(dt, diamond_set);
65}
66
67TEST_CASE("Check that each neighborhood point in 3D (26 points) has associated a bit in an unsigned integer (NeighborhoodConfiguration).", "[map][mask][3D]" )
68{
69 using namespace Z3i;
70 using Map = unordered_map<Point, NeighborhoodConfiguration>;
71 auto pointToMask3D =
73 Map truth3D;
74 truth3D[Point{ -1, -1, -1 }] = 1; // 0000 x x 0000 x x 0000 0001
75 truth3D[Point{ 0, -1, -1 }] = 2; // x x x x x x x 0010
76 truth3D[Point{ 1, -1, -1 }] = 4; // x x x x x x x 0100
77 truth3D[Point{ -1, 0, -1 }] = 8; // x x x x x x x 1000
78 truth3D[Point{ 0, 0, -1 }] = 16; // x x x x x x 0001 x
79 truth3D[Point{ 1, 0, -1 }] = 32; // x x x x x x 0010 x
80 truth3D[Point{ -1, 1, -1 }] = 64; // x x x x x x 0100 x
81 truth3D[Point{ 0, 1, -1 }] = 128; // x x x x x x 1000 x
82 truth3D[Point{ 1, 1, -1 }] = 256; // x x x x x 0001 x x
83 truth3D[Point{ -1, -1, 0 }] = 512; // x x x x x 0010 x x
84 truth3D[Point{ 0, -1, 0 }] = 1024; // x x x x x 0100 x x
85 truth3D[Point{ 1, -1, 0 }] = 2048; // x x x x x 1000 x x
86 truth3D[Point{ -1, 0, 0 }] = 4096; // x x x x 0001 x x x
87 truth3D[Point{ 1, 0, 0 }] = 8192; // x x x x 0010 x x x
88 truth3D[Point{ -1, 1, 0 }] = 16384; // x x x x 0100 x x x
89 truth3D[Point{ 0, 1, 0 }] = 32768; // x x x x 1000 x x x
90 truth3D[Point{ 1, 1, 0 }] = 65536; // x x x 0001 x x x x
91 truth3D[Point{ -1, -1, 1 }] = 131072; // x x x 0010 x x x x
92 truth3D[Point{ 0, -1, 1 }] = 262144; // x x x 0100 x x x x
93 truth3D[Point{ 1, -1, 1 }] = 524288; // x x x 1000 x x x x
94 truth3D[Point{ -1, 0, 1 }] = 1048576; // x x 0001 x x x x x
95 truth3D[Point{ 0, 0, 1 }] = 2097152; // x x 0010 x x x x x
96 truth3D[Point{ 1, 0, 1 }] = 4194304; // x x 0100 x x x x x
97 truth3D[Point{ -1, 1, 1 }] = 8388608; // x x 1000 x x x x x
98 truth3D[Point{ 0, 1, 1 }] = 16777216; // x 0001 x x x x x x
99 truth3D[Point{ 1, 1, 1 }] = 33554432; // x 0010 x x x x x x
100 CHECK(*pointToMask3D == truth3D);
101
102}
103SCENARIO("Simplicity tables match on-the-fly calculations for all 3D topologies", "[simple][object][diamond][3D]" )
104{
105 auto mapZeroNeighborhoodToMask = mapZeroPointNeighborhoodToConfigurationMask<Z3i::Point>();
106 using namespace Z3i;
107
108 SECTION("26_6 topology using loadTable from string and default table size (2^26)"){
109 auto obj = Object3D<Object26_6>(dt26_6);
110 const auto & filename = simplicity::tableSimple26_6;
111 auto ptable = loadTable( filename );
112 CHECK(ptable->size() == 67108864);
113 const auto & table = *ptable;
114 auto & objSet = obj.pointSet();
115 size_t nsimples{0};
116 size_t nsimples_tables{0};
117 for( const auto & p : objSet){
118 auto simple = obj.isSimple(p);
119 if( simple ) ++nsimples;
120 auto cfg = obj.getNeighborhoodConfigurationOccupancy(p, *mapZeroNeighborhoodToMask);
121 auto simple_from_table = table[cfg];
122 if( simple_from_table ) ++nsimples_tables;
123 INFO("Point: " << p << " cfg: " << cfg);
124 CHECK(simple == simple_from_table);
125 }
126 CHECK(nsimples == nsimples_tables);
127 auto border_size = obj.border().size();
128 CHECK(nsimples == border_size);
129 }
130 SECTION("18_6 topology using load table with explicit size (2^26)"){
131 auto obj = Object3D<Object18_6>(dt18_6);
132 const auto & filename = simplicity::tableSimple18_6;
133 // known_size is 2^26 (default)
134 auto ptable = loadTable(filename, 67108864);
135 const auto & table = *ptable;
136 auto & objSet = obj.pointSet();
137 size_t nsimples{0};
138 size_t nsimples_tables{0};
139 for( const auto & p : objSet){
140 auto simple = obj.isSimple(p);
141 if( simple ) ++nsimples;
142 auto cfg = obj.getNeighborhoodConfigurationOccupancy(p, *mapZeroNeighborhoodToMask);
143 auto simple_from_table = table[cfg];
144 if( simple_from_table ) ++nsimples_tables;
145 INFO("Point: " << p << " cfg: " << cfg);
146 CHECK(simple == simple_from_table);
147 }
148 CHECK(nsimples == nsimples_tables);
149 auto border_size = obj.border().size();
150 CHECK(nsimples == border_size);
151 }
152
153 SECTION("6_26 topology using loadTable with template parameter N=3 (dimension)"){
154 auto obj = Object3D<Object6_26>(dt6_26);
155 const auto & filename = simplicity::tableSimple6_26;
156 auto ptable = loadTable<3>(filename);
157 const auto & table = *ptable;
158 auto & objSet = obj.pointSet();
159 size_t nsimples{0};
160 size_t nsimples_tables{0};
161 for( const auto & p : objSet){
162 auto simple = obj.isSimple(p);
163 if( simple ) ++nsimples;
164 auto cfg = obj.getNeighborhoodConfigurationOccupancy(p, *mapZeroNeighborhoodToMask);
165 auto simple_from_table = table[cfg];
166 if( simple_from_table ) ++nsimples_tables;
167 INFO("Point: " << p << " cfg: " << cfg);
168 CHECK(simple == simple_from_table);
169 }
170 CHECK(nsimples == nsimples_tables);
171
172 auto border_size = obj.border().size();
173 CHECK(nsimples != border_size);
174 }
175
176 SECTION("6_18 topology"){
177 auto obj = Object3D<Object6_18>(dt6_18);
178 const auto & filename = simplicity::tableSimple6_18;
179 auto ptable = loadTable(filename);
180 const auto & table = *ptable;
181 auto & objSet = obj.pointSet();
182 size_t nsimples{0};
183 size_t nsimples_tables{0};
184 for( const auto & p : objSet){
185 auto simple = obj.isSimple(p);
186 if( simple ) ++nsimples;
187 auto cfg = obj.getNeighborhoodConfigurationOccupancy(p, *mapZeroNeighborhoodToMask);
188 auto simple_from_table = table[cfg];
189 if( simple_from_table ) ++nsimples_tables;
190 INFO("Point: " << p << " cfg: " << cfg);
191 CHECK(simple == simple_from_table);
192 }
193 CHECK(nsimples == nsimples_tables);
194
195 auto border_size = obj.border().size();
196 CHECK(nsimples != border_size);
197 }
198}
199
200
201struct Objects2D{
202 using Object8_4 = DGtal::Z2i::Object8_4;
203 using Object4_8 = DGtal::Z2i::Object4_8;
204 Object8_4 obj8_4;
205 Object4_8 obj4_8;
206
207 Objects2D()
208 {
209 using namespace DGtal;
210 using namespace Z2i;
211 Point p1( -17, -17 );
212 Point p2( 17, 17 );
213 Domain domain( p1, p2 );
214 DigitalSet shape_set( domain );
215 Shapes<Domain>::addNorm1Ball( shape_set, Point( -10, -8 ), 7 );
216 Shapes<Domain>::addNorm1Ball( shape_set, Point( 10, 8 ), 7 );
217 Shapes<Domain>::addNorm1Ball( shape_set, Point( 3, 0 ), 6 );
218 Shapes<Domain>::addNorm1Ball( shape_set, Point( 0, -3 ), 7 );
219 Shapes<Domain>::addNorm1Ball( shape_set, Point( -10, 0 ), 6 );
220 Shapes<Domain>::addNorm1Ball( shape_set, Point( -8, 8 ), 6 );
221 Shapes<Domain>::addNorm1Ball( shape_set, Point( 0, 9 ), 6 );
222 Shapes<Domain>::addNorm1Ball( shape_set, Point( 15, -2 ), 6 );
223 Shapes<Domain>::addNorm1Ball( shape_set, Point( 12, -10 ), 4 );
224 shape_set.erase( Point( 5, 0 ) );
225 shape_set.erase( Point( -1, -2 ) );
226 obj8_4 = Object8_4( dt8_4, shape_set );
227 obj4_8 = Object4_8( dt4_8, shape_set );
228 }
229
230};
231
232TEST_CASE("Check that each neighborhood point in 2D (8 points) has associated a bit in an unsigned integer (NeighborhoodConfiguration).", "[map][mask][2D]" )
233{
234 using namespace Z2i;
235 using Map = unordered_map<Point, NeighborhoodConfiguration>;
236 auto pointToMask2D =
238 Map truth2D;
239 truth2D[Point{ -1, -1 }] = 1; // 0000 x x 0000 x x 0000 0001
240 truth2D[Point{ 0, -1 }] = 2; // x x x x x x x 0010
241 truth2D[Point{ 1, -1 }] = 4; // x x x x x x x 0100
242 truth2D[Point{ -1, 0 }] = 8; // x x x x x x x 1000
243 truth2D[Point{ 1, 0 }] = 16; // x x x x x x 0001 x
244 truth2D[Point{ -1, 1 }] = 32; // x x x x x x 0010 x
245 truth2D[Point{ 0, 1 }] = 64; // x x x x x x 0100 x
246 truth2D[Point{ 1, 1 }] = 128; // x x x x x x 1000 x
247
248 CHECK(*pointToMask2D == truth2D);
249}
250
251TEST_CASE_METHOD(Objects2D, "Simplicity tables match on-the-fly calculations for all 2D topologies", "[simple][object][balls][2D]" )
252{
253 auto mapZeroNeighborhoodToMask = mapZeroPointNeighborhoodToConfigurationMask<Z2i::Point>();
254
255 SECTION("8_4 and 4_8 topologies using loadTable with specific table size (2^8) and with template parameter N=2 (dimension)"){
256 // 8_4
257 {
258 const auto & filename = simplicity::tableSimple8_4;
259 auto ptable = loadTable(filename, 256);
260 const auto & table = *ptable;
261 auto & obj = obj8_4;
262 auto & objSet = obj.pointSet();
263 size_t nsimples{0};
264 size_t nsimples_tables{0};
265 for( const auto & p : objSet){
266 auto simple = obj.isSimple(p);
267 if( simple ) ++nsimples;
268 auto cfg = obj.getNeighborhoodConfigurationOccupancy(p, *mapZeroNeighborhoodToMask);
269 auto simple_from_table = table[cfg];
270 if( simple_from_table ) ++nsimples_tables;
271 INFO("Point: " << p << " cfg: " << cfg);
272 CHECK(simple == simple_from_table);
273 }
274 CHECK(nsimples == nsimples_tables);
275 }
276
277 // 4_8
278 {
279 const auto & filename = simplicity::tableSimple4_8;
280 auto ptable = loadTable<2>(filename);
281 CHECK(ptable->size() == 256);
282 const auto & table = *ptable;
283 auto & obj = obj4_8;
284 auto & objSet = obj.pointSet();
285 size_t nsimples{0};
286 size_t nsimples_tables{0};
287 for( const auto & p : objSet){
288 auto simple = obj.isSimple(p);
289 if( simple ) ++nsimples;
290 auto cfg = obj.getNeighborhoodConfigurationOccupancy(p, *mapZeroNeighborhoodToMask);
291 auto simple_from_table = table[cfg];
292 if( simple_from_table ) ++nsimples_tables;
293 INFO("Point: " << p << " cfg: " << cfg);
294 CHECK(simple == simple_from_table);
295 }
296 CHECK(nsimples == nsimples_tables);
297 }
298 }
299}
300
301SCENARIO( "Load isthmus tables", "[isthmus]" ){
302 SECTION("isthmus"){
303 const auto & filename = isthmusicity::tableIsthmus;
304 auto ptable = loadTable(filename);
305 const auto & table = *ptable;
306 boost::ignore_unused_variable_warning(table);
307 }
308 SECTION("oneIsthmus"){
309 const auto & filename = isthmusicity::tableOneIsthmus;
310 auto ptable = loadTable(filename);
311 const auto & table = *ptable;
312 boost::ignore_unused_variable_warning(table);
313 }
314 SECTION("twoIsthmus"){
315 const auto & filename = isthmusicity::tableTwoIsthmus;
316 auto ptable = loadTable(filename);
317 const auto & table = *ptable;
318 boost::ignore_unused_variable_warning(table);
319 }
320}
Aim: A wrapper class around a STL associative container for storing sets of digital points within som...
const ConstIterator & begin() const
const Point & lowerBound() const
const Point & upperBound() const
const ConstIterator & end() const
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
static void addNorm1Ball(TDigitalSet &aSet, const Point &aCenter, UnsignedInteger aRadius)
Object< DT8_4, DigitalSet > Object8_4
Definition StdDefs.h:105
Object< DT4_8, DigitalSet > Object4_8
Definition StdDefs.h:101
functions namespace gathers all DGtal functionsxs.
DGtal::CountedPtr< std::unordered_map< TPoint, NeighborhoodConfiguration > > mapZeroPointNeighborhoodToConfigurationMask()
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.
STL namespace.
MyPointD Point
KSpace K
std::unordered_map< Cell, CubicalCellData > Map
TEST_CASE("Check that each neighborhood point in 3D (26 points) has associated a bit in an unsigned integer (NeighborhoodConfiguration).", "[map][mask][3D]")
TEST_CASE_METHOD(Objects2D, "Simplicity tables match on-the-fly calculations for all 2D topologies", "[simple][object][balls][2D]")
TObject Object3D(const typename TObject::DigitalTopology &dt)
Domain domain
SECTION("Testing constant forward iterators")
SCENARIO("UnorderedSetByBlock< PointVector< 2, int > unit tests with 32 bits blocks", "[unorderedsetbyblock][2d]")