DGtal  1.2.0
testBoundedLatticePolytope.cpp
Go to the documentation of this file.
1 
31 #include <iostream>
32 #include <vector>
33 #include <algorithm>
34 #include "DGtal/base/Common.h"
35 #include "DGtal/kernel/SpaceND.h"
36 #include "DGtal/geometry/volumes/BoundedLatticePolytope.h"
37 #include "DGtalCatch.h"
39 
40 using namespace std;
41 using namespace DGtal;
42 
43 
45 // Functions for testing class BoundedLatticePolytope.
47 
48 SCENARIO( "BoundedLatticePolytope< Z2 > unit tests", "[lattice_polytope][2d]" )
49 {
50  typedef SpaceND<2,int> Space;
51  typedef Space::Point Point;
52  typedef Space::Vector Vector;
53  typedef BoundedLatticePolytope< Space > Polytope;
54 
55  GIVEN( "A triangle P at (0,0), (5,0), (0,7)" ) {
56  Point a( 0, 0 );
57  Point b( 5, 0 );
58  Point c( 0, 7 );
59  Polytope P { a, b, c };
60  THEN( "Its domain contains its vertices" ) {
61  REQUIRE( P.isDomainPointInside( a ) );
62  REQUIRE( P.isDomainPointInside( b ) );
63  REQUIRE( P.isDomainPointInside( c ) );
64  }
65  THEN( "Its vertices lie on its boundary" ) {
66  REQUIRE( P.isBoundary( a ) );
67  REQUIRE( P.isBoundary( b ) );
68  REQUIRE( P.isBoundary( c ) );
69  REQUIRE( ! P.isInterior( a ) );
70  REQUIRE( ! P.isInterior( b ) );
71  REQUIRE( ! P.isInterior( c ) );
72  }
73  THEN( "It contains more than 3 integer points" ) {
74  REQUIRE( P.count() > 3 );
75  }
76  THEN( "It contains more points than its area" ) {
77  REQUIRE( P.count() > (5*7/2) );
78  }
79  THEN( "It satisfies Pick's formula, ie 2*Area(P) = 2*#Int(P) + #Bd(P) - 2" ) {
80  Polytope IntP = P.interiorPolytope();
81  auto nb_int = IntP.count();
82  auto nb_bd = P.count() - IntP.count();
83  auto area2 = 5*7;
84  CAPTURE( nb_int );
85  CAPTURE( nb_bd );
86  CAPTURE( area2 );
87  REQUIRE( area2 == 2*nb_int + nb_bd - 2 );
88  }
89  THEN( "It satisfies #In(P) <= #Int(P) + #Bd(P)" ) {
90  auto nb = P.count();
91  auto nb_int = P.countInterior();
92  auto nb_bd = P.countBoundary();
93  CAPTURE( nb );
94  CAPTURE( nb_int );
95  CAPTURE( nb_bd );
96  REQUIRE( nb <= nb_int + nb_bd );
97  }
98  WHEN( "Cut by some half-space" ) {
99  Polytope Q = P;
100  Q.cut( Vector( -1, 1 ), 3 );
101  THEN( "It contains less points" ) {
102  REQUIRE( Q.count() < P.count() );
103  }
104  }
105  THEN( "Its boundary points and interior points are its inside points (closed polytope)" ) {
106  std::vector<Point> inside;
107  std::vector<Point> interior;
108  std::vector<Point> boundary;
109  std::vector<Point> all;
110  P.getPoints( inside );
111  P.getInteriorPoints( interior );
112  P.getBoundaryPoints( boundary );
113  std::sort( inside.begin(), inside.end() );
114  std::sort( interior.begin(), interior.end() );
115  std::sort( boundary.begin(), boundary.end() );
116  std::set_union( interior.cbegin(), interior.cend(), boundary.cbegin(), boundary.cend(),
117  std::back_inserter( all ) );
118  REQUIRE( std::equal( inside.cbegin(), inside.cend(), all.cbegin() ) );
119  }
120  }
121  GIVEN( "A closed segment S at (4,0), (-8,-4)" ) {
122  Point a( 4, 0 );
123  Point b( -8, -4 );
124  Polytope P { a, b };
125  THEN( "Its interior is empty #Int(P) == 0" ) {
126  auto nb_int = P.countInterior();
127  REQUIRE( nb_int == 0 );
128  }
129  THEN( "It satisfies #In(P) == #Int(P) + #Bd(P) == #Bd(P) == 5" ) {
130  auto nb = P.count();
131  auto nb_int = P.countInterior();
132  auto nb_bd = P.countBoundary();
133  CAPTURE( nb );
134  CAPTURE( nb_int );
135  CAPTURE( nb_bd );
136  std::vector<Point> Ppts;
137  P.getPoints( Ppts );
138  CAPTURE( Ppts );
139  REQUIRE( nb_bd == 5 );
140  REQUIRE( nb == nb_int + nb_bd );
141  }
142  }
143 }
144 
145 SCENARIO( "BoundedLatticePolytope< Z3 > unit tests", "[lattice_polytope][3d]" )
146 {
147  typedef SpaceND<3,int> Space;
148  typedef Space::Point Point;
149  typedef BoundedLatticePolytope< Space > Polytope;
150 
151  GIVEN( "A twisted simplex P at (0,0,0), (1,0,0), (0,1,0), (1,1,z)" ) {
152  Point a( 0, 0, 0 );
153  Point b( 1, 0, 0 );
154  Point c( 0, 1, 0 );
155  Point d( 1, 1, 8 );
156  Polytope P { a, b, c, d };
157  THEN( "Its domain contains its vertices" ) {
158  REQUIRE( P.isDomainPointInside( a ) );
159  REQUIRE( P.isDomainPointInside( b ) );
160  REQUIRE( P.isDomainPointInside( c ) );
161  REQUIRE( P.isDomainPointInside( d ) );
162  }
163  THEN( "Its vertices lie on its boundary" ) {
164  REQUIRE( P.isBoundary( a ) );
165  REQUIRE( P.isBoundary( b ) );
166  REQUIRE( P.isBoundary( c ) );
167  REQUIRE( P.isBoundary( d ) );
168  REQUIRE( ! P.isInterior( a ) );
169  REQUIRE( ! P.isInterior( b ) );
170  REQUIRE( ! P.isInterior( c ) );
171  REQUIRE( ! P.isInterior( d ) );
172  }
173  THEN( "It satisfies #In(P) <= #Int(P) + #Bd(P)" ) {
174  auto nb = P.count();
175  auto nb_int = P.countInterior();
176  auto nb_bd = P.countBoundary();
177  CAPTURE( nb );
178  CAPTURE( nb_int );
179  CAPTURE( nb_bd );
180  REQUIRE( nb <= nb_int + nb_bd );
181  }
182  THEN( "It contains only 4 integer points" ) {
183  REQUIRE( P.count() == 4 );
184  }
185 
186  }
187 
188  GIVEN( "A closed arbitrary simplex P at (0,0,0), (6,3,0), (0,5,10), (6,4,8)" ) {
189  Point a( 0, 0, 0 );
190  Point b( 6, 3, 0 );
191  Point c( 0, 5, 10 );
192  Point d( 6, 4, 8 );
193  Polytope P { a, b, c, d };
194 
195  THEN( "It satisfies #In(P) == #Int(P) + #Bd(P)" ) {
196  auto nb = P.count();
197  auto nb_int = P.countInterior();
198  auto nb_bd = P.countBoundary();
199  CAPTURE( nb );
200  CAPTURE( nb_int );
201  CAPTURE( nb_bd );
202  REQUIRE( nb == nb_int + nb_bd );
203  }
204  THEN( "Its boundary points and interior points are its inside points (closed polytope)" ) {
205  std::vector<Point> inside;
206  std::vector<Point> interior;
207  std::vector<Point> boundary;
208  std::vector<Point> all;
209  P.getPoints( inside );
210  P.getInteriorPoints( interior );
211  P.getBoundaryPoints( boundary );
212  std::sort( inside.begin(), inside.end() );
213  std::sort( interior.begin(), interior.end() );
214  std::sort( boundary.begin(), boundary.end() );
215  std::set_union( interior.cbegin(), interior.cend(), boundary.cbegin(), boundary.cend(),
216  std::back_inserter( all ) );
217  REQUIRE( std::equal( inside.cbegin(), inside.cend(), all.cbegin() ) );
218  }
219  WHEN( "Cut by some axis aligned half-space (1,0,0).x <= 3" ) {
220  Polytope Q = P;
221  Q.cut( 0, true, 3 );
222  THEN( "It contains less points" ) {
223  CAPTURE( P );
224  CAPTURE( P.getDomain() );
225  CAPTURE( Q );
226  CAPTURE( Q.getDomain() );
227  auto Pnb = P.count();
228  auto Pnb_int = P.countInterior();
229  auto Pnb_bd = P.countBoundary();
230  CAPTURE( Pnb );
231  CAPTURE( Pnb_int );
232  CAPTURE( Pnb_bd );
233  auto Qnb = Q.count();
234  auto Qnb_int = Q.countInterior();
235  auto Qnb_bd = Q.countBoundary();
236  CAPTURE( Qnb );
237  CAPTURE( Qnb_int );
238  CAPTURE( Qnb_bd );
239  std::vector<Point> Qpts;
240  Q.getPoints( Qpts );
241  CAPTURE( Qpts );
242  REQUIRE( Q.count() < P.count() );
243  }
244  }
245  }
246  GIVEN( "A closed triangle P at (0,0,0), (6,3,0), (2,5,10)" ) {
247  Point a( 0, 0, 0 );
248  Point b( 6, 3, 0 );
249  Point c( 2, 5, 10 );
250  Polytope P { a, b, c };
251  THEN( "Its interior is empty #Int(P) == 0" ) {
252  auto nb_int = P.countInterior();
253  REQUIRE( nb_int == 0 );
254  }
255  THEN( "It satisfies #In(P) == #Int(P) + #Bd(P)" ) {
256  auto nb = P.count();
257  auto nb_int = P.countInterior();
258  auto nb_bd = P.countBoundary();
259  CAPTURE( nb );
260  CAPTURE( nb_int );
261  CAPTURE( nb_bd );
262  std::vector<Point> Ppts;
263  P.getPoints( Ppts );
264  CAPTURE( Ppts );
265  REQUIRE( nb == nb_int + nb_bd );
266  }
267  }
268  GIVEN( "A closed triangle P with relatively prime coordinates (3,0,0), (0,4,0), (0,0,5)" ) {
269  Point a( 3, 0, 0 );
270  Point b( 0, 4, 0 );
271  Point c( 0, 0, 5 );
272  Polytope P { a, b, c };
273  THEN( "Its interior is empty #Int(P) == 0" ) {
274  auto nb_int = P.countInterior();
275  REQUIRE( nb_int == 0 );
276  }
277  THEN( "It satisfies #In(P) == #Int(P) + #Bd(P) == #Bd(P) == 3" ) {
278  auto nb = P.count();
279  auto nb_int = P.countInterior();
280  auto nb_bd = P.countBoundary();
281  CAPTURE( nb );
282  CAPTURE( nb_int );
283  CAPTURE( nb_bd );
284  std::vector<Point> Ppts;
285  P.getPoints( Ppts );
286  CAPTURE( Ppts );
287  REQUIRE( nb_bd == 3 );
288  REQUIRE( nb == nb_int + nb_bd );
289  }
290  }
291  GIVEN( "A closed segment S at (0,0,0), (8,-4,2)" ) {
292  Point a( 0, 0, 0 );
293  Point b( 8, -4, 2 );
294  Polytope P { a, b };
295  THEN( "Its interior is empty #Int(P) == 0" ) {
296  auto nb_int = P.countInterior();
297  REQUIRE( nb_int == 0 );
298  }
299  THEN( "It satisfies #In(P) == #Int(P) + #Bd(P) == #Bd(P) == 3" ) {
300  auto nb = P.count();
301  auto nb_int = P.countInterior();
302  auto nb_bd = P.countBoundary();
303  CAPTURE( nb );
304  CAPTURE( nb_int );
305  CAPTURE( nb_bd );
306  std::vector<Point> Ppts;
307  P.getPoints( Ppts );
308  CAPTURE( Ppts );
309  REQUIRE( nb_bd == 3 );
310  REQUIRE( nb == nb_int + nb_bd );
311  }
312  }
313 }
314 
315 // //
Aim: Represents an nD lattice polytope, i.e. a convex polyhedron bounded with vertices with integer c...
DGtal is the top-level namespace which contains all DGtal functions and types.
SCENARIO("BoundedLatticePolytope< Z2 > unit tests", "[lattice_polytope][2d]")
MyPointD Point
Definition: testClone2.cpp:383
FreemanChain< int >::Vector Vector
CAPTURE(thicknessHV)
GIVEN("A cubical complex with random 3-cells")
REQUIRE(domain.isInside(aPoint))