1 /****************************************************************************
2 **
3 ** Copyright (c) 2009-2019 C.B. Barber. All rights reserved.
4 ** $Id: //main/2019/qhull/src/qhulltest/PointCoordinates_test.cpp#1 $$Change: 2661 $
5 ** $DateTime: 2019/05/24 20:09:58 $$Author: bbarber $
6 **
7 ****************************************************************************/
8
9 //pre-compiled headers
10 #include <iostream>
11 #include "qhulltest/RoadTest.h" // QT_VERSION
12
13 #include "libqhullcpp/PointCoordinates.h"
14 #include "libqhullcpp/QhullError.h"
15 #include "libqhullcpp/RboxPoints.h"
16 #include "libqhullcpp/Qhull.h"
17
18 using std::cout;
19 using std::endl;
20 using std::ostringstream;
21 using std::ostream;
22 using std::string;
23 using std::stringstream;
24
25 namespace orgQhull {
26
27 class PointCoordinates_test : public RoadTest
28 {
29 Q_OBJECT
30
31 #//!\name Test slots
32 private slots:
33 void t_construct_q();
34 void t_construct_qh();
35 void t_convert();
36 void t_getset();
37 void t_element();
38 void t_foreach();
39 void t_search();
40 void t_modify();
41 void t_append_points();
42 void t_coord_iterator();
43 void t_io();
44 };//PointCoordinates_test
45
46 void
add_PointCoordinates_test()47 add_PointCoordinates_test()
48 {
49 new PointCoordinates_test(); // RoadTest::s_testcases
50 }
51
52 void PointCoordinates_test::
t_construct_q()53 t_construct_q()
54 {
55 Qhull q;
56 PointCoordinates pc(q);
57 QCOMPARE(pc.size(), 0U);
58 QCOMPARE(pc.coordinateCount(), 0);
59 QCOMPARE(pc.dimension(), 0);
60 QCOMPARE(pc.coordinates(), (coordT *)0);
61 QVERIFY(pc.isEmpty());
62 pc.checkValid();
63 PointCoordinates pc7(q, 2, "test explicit dimension");
64 QCOMPARE(pc7.dimension(), 2);
65 QCOMPARE(pc7.count(), 0);
66 QVERIFY(pc7.isEmpty());
67 QCOMPARE(pc7.comment(), std::string("test explicit dimension"));
68 pc7.checkValid();
69 PointCoordinates pc2(q, "Test pc2");
70 QCOMPARE(pc2.count(), 0);
71 QVERIFY(pc2.isEmpty());
72 QCOMPARE(pc2.comment(), std::string("Test pc2"));
73 pc2.checkValid();
74 PointCoordinates pc3(q, 3, "Test 3-d pc3");
75 QCOMPARE(pc3.dimension(), 3);
76 QVERIFY(pc3.isEmpty());
77 pc3.checkValid();
78 coordT c[]= { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 };
79 PointCoordinates pc4(q, 2, "Test 2-d pc4", 6, c);
80 QCOMPARE(pc4.dimension(), 2);
81 QCOMPARE(pc4.count(), 3);
82 QCOMPARE(pc4.size(), 3u);
83 QVERIFY(!pc4.isEmpty());
84 pc4.checkValid();
85 QhullPoint p= pc4[2];
86 QCOMPARE(p[1], 5.0);
87 // QhullPoint refers to PointCoordinates
88 p[1] += 1.0;
89 QCOMPARE(pc4[2][1], 6.0);
90 PointCoordinates pc5(q, 4, "Test 4-d pc5 with insufficient coordinates", 6, c);
91 QCOMPARE(pc5.dimension(), 4);
92 QCOMPARE(pc5.count(), 1);
93 QCOMPARE(pc5.extraCoordinatesCount(), 2);
94 QCOMPARE(pc5.extraCoordinates()[1], 5.0);
95 QVERIFY(!pc5.isEmpty());;
96 std::vector<coordT> vc;
97 vc.push_back(3.0);
98 vc.push_back(4.0);
99 vc.push_back(5.0);
100 vc.push_back(6.0);
101 vc.push_back(7.0);
102 vc.push_back(9.0);
103 pc5.append(2, &vc[3]); // Copy of vc[]
104 pc5.checkValid();
105 QhullPoint p5(q, 4, &vc[1]);
106 QCOMPARE(pc5[1], p5);
107 PointCoordinates pc6(pc5); // Makes copy of point_coordinates
108 QCOMPARE(pc6[1], p5);
109 QVERIFY(pc6==pc5);
110 QhullPoint p6= pc5[1]; // Refers to pc5.coordinates
111 pc5[1][0] += 1.0;
112 QCOMPARE(pc5[1], p6);
113 QVERIFY(pc5[1]!=p5);
114 QVERIFY(pc6!=pc5);
115 pc6= pc5;
116 QVERIFY(pc6==pc5);
117 PointCoordinates pc8(q);
118 pc6= pc8;
119 QVERIFY(pc6!=pc5);
120 QVERIFY(pc6.isEmpty());
121 }//t_construct_q
122
123 void PointCoordinates_test::
t_construct_qh()124 t_construct_qh()
125 {
126 QhullQh qh;
127 PointCoordinates pc(&qh);
128 QCOMPARE(pc.size(), 0U);
129 QCOMPARE(pc.coordinateCount(), 0);
130 QCOMPARE(pc.dimension(), 0);
131 QCOMPARE(pc.coordinates(), (coordT *)0);
132 QVERIFY(pc.isEmpty());
133 pc.checkValid();
134 PointCoordinates pc7(&qh, 2, "test explicit dimension");
135 QCOMPARE(pc7.dimension(), 2);
136 QCOMPARE(pc7.count(), 0);
137 QVERIFY(pc7.isEmpty());
138 QCOMPARE(pc7.comment(), std::string("test explicit dimension"));
139 pc7.checkValid();
140 PointCoordinates pc2(&qh, "Test pc2");
141 QCOMPARE(pc2.count(), 0);
142 QVERIFY(pc2.isEmpty());
143 QCOMPARE(pc2.comment(), std::string("Test pc2"));
144 pc2.checkValid();
145 PointCoordinates pc3(&qh, 3, "Test 3-d pc3");
146 QCOMPARE(pc3.dimension(), 3);
147 QVERIFY(pc3.isEmpty());
148 pc3.checkValid();
149 coordT c[]= { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 };
150 PointCoordinates pc4(&qh, 2, "Test 2-d pc4", 6, c);
151 QCOMPARE(pc4.dimension(), 2);
152 QCOMPARE(pc4.count(), 3);
153 QCOMPARE(pc4.size(), 3u);
154 QVERIFY(!pc4.isEmpty());
155 pc4.checkValid();
156 QhullPoint p= pc4[2];
157 QCOMPARE(p[1], 5.0);
158 // QhullPoint refers to PointCoordinates
159 p[1] += 1.0;
160 QCOMPARE(pc4[2][1], 6.0);
161 PointCoordinates pc5(&qh, 4, "Test 4-d pc5 with insufficient coordinates", 6, c);
162 QCOMPARE(pc5.dimension(), 4);
163 QCOMPARE(pc5.count(), 1);
164 QCOMPARE(pc5.extraCoordinatesCount(), 2);
165 QCOMPARE(pc5.extraCoordinates()[1], 5.0);
166 QVERIFY(!pc5.isEmpty());;
167 std::vector<coordT> vc;
168 vc.push_back(3.0);
169 vc.push_back(4.0);
170 vc.push_back(5.0);
171 vc.push_back(6.0);
172 vc.push_back(7.0);
173 vc.push_back(9.0);
174 pc5.append(2, &vc[3]); // Copy of vc[]
175 pc5.checkValid();
176 QhullPoint p5(&qh, 4, &vc[1]);
177 QCOMPARE(pc5[1], p5);
178 PointCoordinates pc6(pc5); // Makes copy of point_coordinates
179 QCOMPARE(pc6[1], p5);
180 QVERIFY(pc6==pc5);
181 QhullPoint p6= pc5[1]; // Refers to pc5.coordinates
182 pc5[1][0] += 1.0;
183 QCOMPARE(pc5[1], p6);
184 QVERIFY(pc5[1]!=p5);
185 QVERIFY(pc6!=pc5);
186 pc6= pc5;
187 QVERIFY(pc6==pc5);
188 PointCoordinates pc8(&qh);
189 pc6= pc8;
190 QVERIFY(pc6!=pc5);
191 QVERIFY(pc6.isEmpty());
192 }//t_construct_qh
193
194 void PointCoordinates_test::
t_convert()195 t_convert()
196 {
197 Qhull q;
198 //defineAs tested above
199 coordT c[]= {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
200 PointCoordinates ps(q, 3, "two 3-d points", 6, c);
201 QCOMPARE(ps.dimension(), 3);
202 QCOMPARE(ps.size(), 2u);
203 const coordT *c2= ps.constData();
204 QVERIFY(c!=c2);
205 QCOMPARE(c[0], c2[0]);
206 const coordT *c3= ps.data();
207 QCOMPARE(c3, c2);
208 coordT *c4= ps.data();
209 QCOMPARE(c4, c2);
210 std::vector<coordT> vs= ps.toStdVector();
211 QCOMPARE(vs.size(), 6u);
212 QCOMPARE(vs[5], 5.0);
213 QList<coordT> qs= ps.toQList();
214 QCOMPARE(qs.size(), 6);
215 QCOMPARE(qs[5], 5.0);
216 }//t_convert
217
218 void PointCoordinates_test::
t_getset()219 t_getset()
220 {
221 // See t_construct() for test of coordinates, coordinateCount, dimension, empty, isEmpty, ==, !=
222 // See t_construct() for test of checkValid, comment, setDimension
223 Qhull q;
224 PointCoordinates pc(q, "Coordinates c");
225 pc.setComment("New comment");
226 QCOMPARE(pc.comment(), std::string("New comment"));
227 pc.checkValid();
228 pc.makeValid(); // A no-op
229 pc.checkValid();
230 Coordinates cs= pc.getCoordinates();
231 QVERIFY(cs.isEmpty());
232 PointCoordinates pc2(pc);
233 pc.setDimension(3);
234 QVERIFY(pc2!=pc);
235 coordT c[]= {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
236 pc.append(6, c);
237 pc.checkValid();
238 pc.makeValid(); // A no-op
239 QhullPoint p= pc[0];
240 QCOMPARE(p[2], 2.0);
241 try{
242 pc.setDimension(2);
243 QFAIL("setDimension(2) did not fail for 3-d.");
244 }catch (const std::exception &e) {
245 const char *s= e.what();
246 cout << "INFO : Caught " << s;
247 }
248 }//t_getset
249
250 void PointCoordinates_test::
t_element()251 t_element()
252 {
253 Qhull q;
254 coordT c[]= {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
255 PointCoordinates pc(q, 2, "2-d points", 6, c);
256 QhullPoint p= pc.at(0);
257 QCOMPARE(p, pc[0]);
258 QCOMPARE(p, pc.first());
259 QCOMPARE(p, pc.value(0));
260 p= pc.back();
261 QCOMPARE(p, pc[2]);
262 QCOMPARE(p, pc.last());
263 QCOMPARE(p, pc.value(2));
264 QhullPoints ps= pc.mid(1, 2);
265 QCOMPARE(ps[1], p);
266 }//t_element
267
268 void PointCoordinates_test::
t_foreach()269 t_foreach()
270 {
271 Qhull q;
272 coordT c[]= {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
273 PointCoordinates pc(q, 2, "2-d points", 6, c);
274 QhullPoints::Iterator i= pc.begin();
275 QhullPoint p= pc[0];
276 QCOMPARE(*i, p);
277 QCOMPARE((*i)[0], 0.0);
278 QhullPoint p3= pc[2];
279 i= pc.end();
280 QCOMPARE(i[-1], p3);
281 const PointCoordinates pc2(q, 2, "2-d points", 6, c);
282 QhullPoints::ConstIterator i2= pc.begin();
283 const QhullPoint p0= pc2[0];
284 QCOMPARE(*i2, p0);
285 QCOMPARE((*i2)[0], 0.0);
286 QhullPoints::ConstIterator i3= i2;
287 QCOMPARE(i3, i2);
288 QCOMPARE((*i3)[0], 0.0);
289 i3= pc.constEnd();
290 --i3;
291 QhullPoint p2= pc2[2];
292 QCOMPARE(*i3, p2);
293 i= pc.end();
294 QVERIFY(i-1==i3);
295 i2= pc2.end();
296 QVERIFY(i2-1!=i3);
297 QCOMPARE(*(i2-1), *i3);
298 foreach(QhullPoint p3, pc){ //Qt only
299 QVERIFY(p3[0]>=0.0);
300 QVERIFY(p3[0]<=5.0);
301 }
302 Coordinates::ConstIterator i4= pc.beginCoordinates();
303 QCOMPARE(*i4, 0.0);
304 Coordinates::Iterator i5= pc.beginCoordinates();
305 QCOMPARE(*i5, 0.0);
306 i4= pc.beginCoordinates(1);
307 QCOMPARE(*i4, 2.0);
308 i5= pc.beginCoordinates(1);
309 QCOMPARE(*i5, 2.0);
310 i4= pc.endCoordinates();
311 QCOMPARE(*--i4, 5.0);
312 i5= pc.endCoordinates();
313 QCOMPARE(*--i5, 5.0);
314 }//t_foreach
315
316 void PointCoordinates_test::
t_search()317 t_search()
318 {
319 Qhull q;
320 coordT c[]= {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
321 PointCoordinates pc(q, 2, "2-d points", 6, c);
322 QhullPoint p0= pc[0];
323 QhullPoint p2= pc[2];
324 QVERIFY(pc.contains(p0));
325 QVERIFY(pc.contains(p2));
326 QCOMPARE(pc.count(p0), 1);
327 QCOMPARE(pc.indexOf(p2), 2);
328 QCOMPARE(pc.lastIndexOf(p0), 0);
329 }//t_search
330
331 void PointCoordinates_test::
t_modify()332 t_modify()
333 {
334 Qhull q;
335 coordT c[]= {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
336 PointCoordinates pc(q, 2, "2-d points", 6, c);
337 coordT c3[]= {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
338 PointCoordinates pc5(q, 2, "test explicit dimension");
339 pc5.append(6, c3); // 0-5
340 QVERIFY(pc5==pc);
341 PointCoordinates pc2(q, 2, "2-d");
342 coordT c2[]= {6.0, 7.0, 8.0, 9.0, 10.0, 11.0};
343 pc2.append(6, c2);
344 QCOMPARE(pc2.count(), 3);
345 pc2.append(14.0);
346 QCOMPARE(pc2.count(), 3);
347 QCOMPARE(pc2.extraCoordinatesCount(), 1);
348 pc2.append(15.0); // 6-11, 14,15
349 QCOMPARE(pc2.count(), 4);
350 QCOMPARE(pc2.extraCoordinatesCount(), 0);
351 QhullPoint p(pc[0]);
352 pc2.append(p); // 6-11, 14,15, 0,1
353 QCOMPARE(pc2.count(), 5);
354 QCOMPARE(pc2.extraCoordinatesCount(), 0);
355 QCOMPARE(pc2.lastIndexOf(p), 4);
356 pc.append(pc2); // Invalidates p
357 QCOMPARE(pc.count(), 8); // 0-11, 14,15, 0,1
358 QCOMPARE(pc.extraCoordinatesCount(), 0);
359 QCOMPARE(pc.lastIndexOf(pc[0]), 7);
360 pc.appendComment(" operators");
361 QCOMPARE(pc.comment(), std::string("2-d points operators"));
362 pc.checkValid();
363 // see t_append_points for appendPoints
364 PointCoordinates pc3= pc+pc2;
365 pc3.checkValid();
366 QCOMPARE(pc3.count(), 13);
367 QCOMPARE(pc3[6][0], 14.0);
368 QCOMPARE(pc3[8][0], 6.0);
369 pc3 += pc;
370 QCOMPARE(pc3.count(), 21);
371 QCOMPARE(pc3[14][0], 2.0);
372 pc3 += 12.0;
373 pc3 += 14.0;
374 QCOMPARE(pc3.count(), 22);
375 QCOMPARE(pc3.last()[0], 12.0);
376 // QhullPoint p3= pc3.first(); // += throws error because append may move the data
377 QhullPoint p3= pc2.first();
378 pc3 += p3;
379 QCOMPARE(pc3.count(), 23);
380 QCOMPARE(pc3.last()[0], 6.0);
381 pc3 << pc;
382 QCOMPARE(pc3.count(), 31);
383 QCOMPARE(pc3.last()[0], 0.0);
384 pc3 << 12.0 << 14.0;
385 QCOMPARE(pc3.count(), 32);
386 QCOMPARE(pc3.last()[0], 12.0);
387 PointCoordinates pc4(pc3);
388 pc4.reserveCoordinates(100);
389 QVERIFY(pc3==pc4);
390 }//t_modify
391
392 void PointCoordinates_test::
t_append_points()393 t_append_points()
394 {
395 Qhull q;
396 PointCoordinates pc(q, 2, "stringstream");
397 stringstream s("2 3 1 2 3 4 5 6");
398 pc.appendPoints(s);
399 QCOMPARE(pc.count(), 3);
400 }//t_append_points
401
402 void PointCoordinates_test::
t_coord_iterator()403 t_coord_iterator()
404 {
405 Qhull q;
406 PointCoordinates c(q, 2, "2-d");
407 c << 0.0 << 1.0 << 2.0 << 3.0 << 4.0 << 5.0;
408 PointCoordinatesIterator i(c);
409 QhullPoint p0(c[0]);
410 QhullPoint p1(c[1]);
411 QhullPoint p2(c[2]);
412 coordT c2[] = {-1.0, -2.0};
413 QhullPoint p3(q, 2, c2);
414 PointCoordinatesIterator i2= c;
415 QVERIFY(i.findNext(p1));
416 QVERIFY(!i.findNext(p1));
417 QVERIFY(!i.findNext(p2));
418 QVERIFY(!i.findNext(p3));
419 QVERIFY(i.findPrevious(p2));
420 QVERIFY(!i.findPrevious(p2));
421 QVERIFY(!i.findPrevious(p0));
422 QVERIFY(!i.findPrevious(p3));
423 QVERIFY(i2.findNext(p2));
424 QVERIFY(i2.findPrevious(p0));
425 QVERIFY(i2.findNext(p1));
426 QVERIFY(i2.findPrevious(p0));
427 QVERIFY(i2.hasNext());
428 QVERIFY(!i2.hasPrevious());
429 QVERIFY(i.hasNext());
430 QVERIFY(!i.hasPrevious());
431 i.toBack();
432 i2.toFront();
433 QVERIFY(!i.hasNext());
434 QVERIFY(i.hasPrevious());
435 QVERIFY(i2.hasNext());
436 QVERIFY(!i2.hasPrevious());
437 PointCoordinates c3(q);
438 PointCoordinatesIterator i3= c3;
439 QVERIFY(!i3.hasNext());
440 QVERIFY(!i3.hasPrevious());
441 i3.toBack();
442 QVERIFY(!i3.hasNext());
443 QVERIFY(!i3.hasPrevious());
444 QCOMPARE(i.peekPrevious(), p2);
445 QCOMPARE(i.previous(), p2);
446 QCOMPARE(i.previous(), p1);
447 QCOMPARE(i.previous(), p0);
448 QVERIFY(!i.hasPrevious());
449 QCOMPARE(i.peekNext(), p0);
450 // i.peekNext()= 1.0; // compiler error
451 QCOMPARE(i.next(), p0);
452 QCOMPARE(i.peekNext(), p1);
453 QCOMPARE(i.next(), p1);
454 QCOMPARE(i.next(), p2);
455 QVERIFY(!i.hasNext());
456 i.toFront();
457 QCOMPARE(i.next(), p0);
458 }//t_coord_iterator
459
460 void PointCoordinates_test::
t_io()461 t_io()
462 {
463 Qhull q;
464 PointCoordinates c(q);
465 ostringstream os;
466 os << "PointCoordinates 0-d\n" << c;
467 c.setDimension(2);
468 c << 1.0 << 2.0 << 3.0 << 1.0 << 2.0 << 3.0;
469 os << "PointCoordinates 1,2 3,1 2,3\n" << c;
470 cout << os.str();
471 QString s= QString::fromStdString(os.str());
472 QCOMPARE(s.count("0"), 3);
473 QCOMPARE(s.count("2"), 5);
474 }//t_io
475
476 }//orgQhull
477
478 #include "moc/PointCoordinates_test.moc"
479