34 #include "DGtal/base/Common.h"
35 #include "DGtal/kernel/SpaceND.h"
36 #include "DGtal/geometry/volumes/BoundedLatticePolytope.h"
37 #include "DGtalCatch.h"
41 using namespace DGtal;
48 SCENARIO(
"BoundedLatticePolytope< Z2 > unit tests",
"[lattice_polytope][2d]" )
55 GIVEN(
"A triangle P at (0,0), (5,0), (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 ) );
65 THEN(
"Its vertices lie on its boundary" ) {
73 THEN(
"It contains more than 3 integer points" ) {
76 THEN(
"It contains more points than its area" ) {
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();
87 REQUIRE( area2 == 2*nb_int + nb_bd - 2 );
89 THEN(
"It satisfies #In(P) <= #Int(P) + #Bd(P)" ) {
91 auto nb_int = P.countInterior();
92 auto nb_bd = P.countBoundary();
96 REQUIRE( nb <= nb_int + nb_bd );
98 WHEN(
"Cut by some half-space" ) {
100 Q.cut(
Vector( -1, 1 ), 3 );
101 THEN(
"It contains less points" ) {
102 REQUIRE( Q.count() < P.count() );
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() );
119 std::set_union( interior.cbegin(), interior.cend(), boundary.cbegin(), boundary.cend(),
120 std::back_inserter( all ) );
121 REQUIRE( std::equal( inside.cbegin(), inside.cend(), all.cbegin() ) );
124 GIVEN(
"A closed segment S at (4,0), (-8,-4)" ) {
128 THEN(
"Its interior is empty #Int(P) == 0" ) {
129 auto nb_int = P.countInterior();
132 THEN(
"It satisfies #In(P) == #Int(P) + #Bd(P) == #Bd(P) == 5" ) {
134 auto nb_int = P.countInterior();
135 auto nb_bd = P.countBoundary();
139 std::vector<Point> Ppts;
143 REQUIRE( nb == nb_int + nb_bd );
148 SCENARIO(
"BoundedLatticePolytope< Z3 > unit tests",
"[lattice_polytope][3d]" )
154 GIVEN(
"A twisted simplex P at (0,0,0), (1,0,0), (0,1,0), (1,1,z)" ) {
159 Polytope P { a, b, c, d };
160 THEN(
"Its domain contains its vertices" ) {
161 REQUIRE( P.isDomainPointInside( a ) );
162 REQUIRE( P.isDomainPointInside( b ) );
163 REQUIRE( P.isDomainPointInside( c ) );
164 REQUIRE( P.isDomainPointInside( d ) );
166 THEN(
"Its vertices lie on its boundary" ) {
171 REQUIRE( ! P.isInterior( a ) );
172 REQUIRE( ! P.isInterior( b ) );
173 REQUIRE( ! P.isInterior( c ) );
174 REQUIRE( ! P.isInterior( d ) );
176 THEN(
"It satisfies #In(P) <= #Int(P) + #Bd(P)" ) {
178 auto nb_int = P.countInterior();
179 auto nb_bd = P.countBoundary();
183 REQUIRE( nb <= nb_int + nb_bd );
185 THEN(
"It contains only 4 integer points" ) {
191 GIVEN(
"A closed arbitrary simplex P at (0,0,0), (6,3,0), (0,5,10), (6,4,8)" ) {
196 Polytope P { a, b, c, d };
198 THEN(
"It satisfies #In(P) == #Int(P) + #Bd(P)" ) {
200 auto nb_int = P.countInterior();
201 auto nb_bd = P.countBoundary();
205 REQUIRE( nb == nb_int + nb_bd );
207 THEN(
"Its boundary points and interior points are its inside points (closed polytope)" ) {
208 std::vector<Point> inside;
209 std::vector<Point> interior;
210 std::vector<Point> boundary;
211 std::vector<Point> all;
212 P.getPoints( inside );
213 P.getInteriorPoints( interior );
214 P.getBoundaryPoints( boundary );
215 std::sort( inside.begin(), inside.end() );
216 std::sort( interior.begin(), interior.end() );
217 std::sort( boundary.begin(), boundary.end() );
221 std::set_union( interior.cbegin(), interior.cend(), boundary.cbegin(), boundary.cend(),
222 std::back_inserter( all ) );
223 REQUIRE( std::equal( inside.cbegin(), inside.cend(), all.cbegin() ) );
225 WHEN(
"Cut by some axis aligned half-space (1,0,0).x <= 3" ) {
228 THEN(
"It contains less points" ) {
233 auto Pnb = P.count();
234 auto Pnb_int = P.countInterior();
235 auto Pnb_bd = P.countBoundary();
239 auto Qnb = Q.count();
240 auto Qnb_int = Q.countInterior();
241 auto Qnb_bd = Q.countBoundary();
245 std::vector<Point> Qpts;
248 REQUIRE( Q.count() < P.count() );
252 GIVEN(
"A closed triangle P at (0,0,0), (6,3,0), (2,5,10)" ) {
256 Polytope P { a, b, c };
257 THEN(
"Its interior is empty #Int(P) == 0" ) {
258 auto nb_int = P.countInterior();
261 THEN(
"It satisfies #In(P) == #Int(P) + #Bd(P)" ) {
263 auto nb_int = P.countInterior();
264 auto nb_bd = P.countBoundary();
268 std::vector<Point> Ppts;
271 REQUIRE( nb == nb_int + nb_bd );
274 GIVEN(
"A closed triangle P with relatively prime coordinates (3,0,0), (0,4,0), (0,0,5)" ) {
278 Polytope P { a, b, c };
279 THEN(
"Its interior is empty #Int(P) == 0" ) {
280 auto nb_int = P.countInterior();
283 THEN(
"It satisfies #In(P) == #Int(P) + #Bd(P) == #Bd(P) == 3" ) {
285 auto nb_int = P.countInterior();
286 auto nb_bd = P.countBoundary();
290 std::vector<Point> Ppts;
294 REQUIRE( nb == nb_int + nb_bd );
297 GIVEN(
"A closed segment S at (0,0,0), (8,-4,2)" ) {
301 THEN(
"Its interior is empty #Int(P) == 0" ) {
302 auto nb_int = P.countInterior();
305 THEN(
"It satisfies #In(P) == #Int(P) + #Bd(P) == #Bd(P) == 3" ) {
307 auto nb_int = P.countInterior();
308 auto nb_bd = P.countBoundary();
312 std::vector<Point> Ppts;
316 REQUIRE( nb == nb_int + nb_bd );
Aim: Represents an nD lattice polytope, i.e. a convex polyhedron bounded with vertices with integer c...
DigitalPlane::Point Vector
DGtal is the top-level namespace which contains all DGtal functions and types.
SCENARIO("BoundedLatticePolytope< Z2 > unit tests", "[lattice_polytope][2d]")
GIVEN("A cubical complex with random 3-cells")
REQUIRE(domain.isInside(aPoint))