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