1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: UnitTestPlanesIntersection.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 #include "vtkSmartPointer.h"
17 #include "vtkPlanesIntersection.h"
18
19 #include "vtkTetra.h"
20 #include "vtkPoints.h"
21 #include "vtkBoundingBox.h"
22 #include "vtkRegularPolygonSource.h"
23 #include "vtkDoubleArray.h"
24 #include "vtkMath.h"
25 #include "vtkTestErrorObserver.h"
26
27 #include <sstream>
28 static vtkSmartPointer<vtkTetra> MakeTetra();
29
UnitTestPlanesIntersection(int,char * [])30 int UnitTestPlanesIntersection(int, char*[])
31 {
32 int status = 0;
33 {
34 vtkSmartPointer<vtkPlanesIntersection> aPlanes =
35 vtkSmartPointer<vtkPlanesIntersection>::New();
36 std::cout << " Testing Print of an PlanesIntersection...";
37 std::ostringstream planesPrint;
38 aPlanes->Print(planesPrint);
39 std::cout << "PASSED" << std::endl;
40 }
41
42 {
43 std::cout << " Testing Convert3DCell...";
44 vtkSmartPointer<vtkTetra> aTetra = MakeTetra();
45 vtkPlanesIntersection *aPlanes =
46 vtkPlanesIntersection::Convert3DCell(aTetra);
47 if (aTetra->GetNumberOfFaces() != aPlanes->GetNumberOfPlanes())
48 {
49 status++;
50 std::cout << "FAILED" << std::endl;
51 }
52 else
53 {
54 std::cout << "PASSED" << std::endl;
55 }
56 aPlanes->Delete();
57 }
58
59 {
60 std::cout << " Testing Region Vertices...";
61 vtkSmartPointer<vtkTetra> aTetra = MakeTetra();
62 vtkPlanesIntersection *aPlanes =
63 vtkPlanesIntersection::Convert3DCell(aTetra);
64 int numVertices = aPlanes->GetNumberOfRegionVertices();
65 if (numVertices != 4)
66 {
67 std::cout << " GetNumberOfRegionVertices() got " << numVertices
68 << " but expected 4 ";
69 std::cout << "FAILED" << std::endl;
70 ++status;
71 }
72 else
73 {
74 std::cout << "PASSED" << std::endl;
75 }
76 aPlanes->Delete();
77 }
78
79 {
80 std::cout << " Testing PolygonIntersectsBBox...";
81 int status4 = 0;
82 vtkBoundingBox bbox1(-10, 10, -10, 10, -10, 10);
83
84 // create a polygon
85 vtkSmartPointer<vtkRegularPolygonSource> polygon =
86 vtkSmartPointer<vtkRegularPolygonSource>::New();
87 polygon->SetNumberOfSides(15);
88 double center[3] = {0.0, 0.0, 0.0};
89 double radius = 10.0;
90 polygon->SetCenter(center);
91 polygon->SetRadius(radius);
92 polygon->Update();
93 double bounds[6];
94 bbox1.GetBounds(bounds);
95
96 int result = vtkPlanesIntersection::PolygonIntersectsBBox(
97 bounds,
98 polygon->GetOutput()->GetPoints());
99 if (result == 0)
100 {
101 ++status4;
102 std::cout << " PolygonIntersectsBBox() fails bbox contains ";
103 }
104
105 // bbox outside
106 vtkBoundingBox bbox3(100, 200, 100, 200, 100, 200);
107 bbox3.GetBounds(bounds);
108
109 result = vtkPlanesIntersection::PolygonIntersectsBBox(
110 bounds,
111 polygon->GetOutput()->GetPoints());
112 if (result != 0)
113 {
114 ++status4;
115 std::cout << " PolygonIntersectsBBox() fils bbox outside ";
116 }
117
118 // bbox straddles
119 vtkBoundingBox bbox2(0, 200, 0, 200, 0, 200);
120 bbox2.GetBounds(bounds);
121
122 result = vtkPlanesIntersection::PolygonIntersectsBBox(
123 bounds,
124 polygon->GetOutput()->GetPoints());
125 if (result != 0)
126 {
127 ++status4;
128 std::cout << " PolygonIntersectsBBox() fils bbox outside ";
129 }
130
131 if (status4)
132 {
133 std::cout << "FAILED" << std::endl;
134 }
135 else
136 {
137 std::cout << "PASSED" << std::endl;
138 }
139 }
140
141 {
142 std::cout << " Testing IntersectsRegion...";
143 int status2 = 0;
144 vtkBoundingBox bbox(-10, 10, -10, 10, -10, 10);
145 double xmin, xmax, ymin, ymax, zmin, zmax;
146 bbox.GetMinPoint(xmin, ymin, zmin);
147 bbox.GetMaxPoint(xmax, ymax, zmax);
148
149 vtkSmartPointer<vtkPoints> points =
150 vtkSmartPointer<vtkPoints>::New();
151
152 points->InsertNextPoint(xmin, ymin, zmin);
153 points->InsertNextPoint(xmax, ymin, zmin);
154 points->InsertNextPoint(xmax, ymax, zmin);
155 points->InsertNextPoint(xmin, ymax, zmin);
156
157 points->InsertNextPoint(xmin, ymin, zmax);
158 points->InsertNextPoint(xmax, ymin, zmax);
159 points->InsertNextPoint(xmax, ymax, zmax);
160 points->InsertNextPoint(xmin, ymax, zmax);
161
162 vtkSmartPointer<vtkTetra> aTetra = MakeTetra();
163 vtkPlanesIntersection *aPlanes =
164 vtkPlanesIntersection::Convert3DCell(aTetra);
165 std::ostringstream planesPrint;
166 aPlanes->Print(planesPrint);
167
168 if (aPlanes->IntersectsRegion(points) == 0)
169 {
170 ++status2;
171 }
172 points->SetPoint(0, -.01, -.01, -.01);
173 points->SetPoint(1, .01, -.01, -.01);
174 points->SetPoint(2, .01, .01, -.01);
175 points->SetPoint(3, -.01, .01, -.01);
176
177 points->SetPoint(4, -.01, -.01, .01);
178 points->SetPoint(5, .01, -.01, .01);
179 points->SetPoint(6, .01, .01, .01);
180 points->SetPoint(7, -.01, .01, .01);
181 points->Modified();
182 // box is entirely inside
183 if (aPlanes->IntersectsRegion(points) != 1)
184 {
185 ++status2;
186 }
187
188 points->SetPoint(0, 1000.0, 1000.0, 1000.0);
189 points->SetPoint(1, 2000.0, 1000.0, 1000.0);
190 points->SetPoint(2, 2000.0, 2000.0, 1000.0);
191 points->SetPoint(3, 1000.0, 2000.0, 1000.0);
192
193 points->SetPoint(4, 1000.0, 1000.0, 2000.0);
194 points->SetPoint(5, 2000.0, 1000.0, 2000.0);
195 points->SetPoint(6, 2000.0, 2000.0, 2000.0);
196 points->SetPoint(7, 1000.0, 2000.0, 2000.0);
197 points->Modified();
198
199 // box is entirely outside
200 if (aPlanes->IntersectsRegion(points) != 0)
201 {
202 std::cout << "Box entirely outside failed ";
203 ++status2;
204 }
205 points->SetPoint(0, 0.0, 0.0, 0.0);
206 points->SetPoint(1, 10.0, 0.0, 0.0);
207 points->SetPoint(2, 10.0, 10.0, 0.0);
208 points->SetPoint(3, 0.0, 10.0, 0.0);
209
210 points->SetPoint(4, 0.0, 0.0, 10.0);
211 points->SetPoint(5, 10.0, 0.0, 10.0);
212 points->SetPoint(6, 10.0, 10.0, 10.0);
213 points->SetPoint(7, 0.0, 10.0, 10.0);
214 points->Modified();
215
216 // box straddles region
217 if (aPlanes->IntersectsRegion(points) != 1)
218 {
219 std::cout << "Box straddling region failed ";
220 ++status2;
221 }
222
223 aPlanes->Delete();
224 if (status2)
225 {
226 std::cout << "FAILED" << std::endl;
227 ++status;
228 }
229 else
230 {
231 std::cout << "PASSED" << std::endl;
232 }
233 }
234
235 {
236 std::cout << " Testing Set/GetRegionVertices...";
237 int status3 = 0;
238
239 vtkSmartPointer<vtkTetra> aTetra = MakeTetra();
240 vtkPlanesIntersection *aPlanes =
241 vtkPlanesIntersection::Convert3DCell(aTetra);
242 int numberOfRegionVertices = aPlanes->GetNumRegionVertices();
243 std::vector<double> regionVertices(numberOfRegionVertices * 3);
244
245 int got = aPlanes->GetRegionVertices(
246 &(*regionVertices.begin()),
247 numberOfRegionVertices);
248 if (got != numberOfRegionVertices)
249 {
250 ++status3;
251 std::cout << " GetRegionVertices() got " << got
252 << " but expected " << numberOfRegionVertices << " ";
253 }
254 aPlanes->SetRegionVertices(
255 &(*regionVertices.begin()),
256 numberOfRegionVertices);
257 // Repeat to exercise Delete()
258 aPlanes->SetRegionVertices(
259 &(*regionVertices.begin()),
260 numberOfRegionVertices);
261
262 // Ask for fewer region vertices
263 got = aPlanes->GetRegionVertices(
264 &(*regionVertices.begin()),
265 1);
266 if (got != 1)
267 {
268 ++status3;
269 std::cout << " GetRegionVertices() got " << got
270 << " but expected 1 ";
271 }
272
273 vtkSmartPointer<vtkPlanesIntersection> regionPlane =
274 vtkSmartPointer<vtkPlanesIntersection>::New();
275 vtkSmartPointer<vtkPoints> rpoints =
276 vtkSmartPointer<vtkPoints>::New();
277 rpoints->InsertNextPoint (-1.0, 0.0, 0.0);
278 rpoints->InsertNextPoint (1.0, 0.0, 0.0);
279 rpoints->InsertNextPoint (0.0, -1.0, 0.0);
280 rpoints->InsertNextPoint (0.0, 1.0, 0.0);
281 rpoints->InsertNextPoint (0.0, 0.0, -1.0);
282 rpoints->InsertNextPoint (0.0, 0.0, 1.0);
283 regionPlane->SetRegionVertices(rpoints);
284
285 // Repeat to test Delete()
286 regionPlane->SetRegionVertices(rpoints);
287
288 vtkSmartPointer<vtkTest::ErrorObserver> errorObserver =
289 vtkSmartPointer<vtkTest::ErrorObserver>::New();
290 double v;
291 vtkSmartPointer<vtkPlanesIntersection> empty =
292 vtkSmartPointer<vtkPlanesIntersection>::New();
293 empty->AddObserver(vtkCommand::ErrorEvent, errorObserver);
294 empty->GetRegionVertices(&v, 0);
295 status3 += errorObserver->CheckErrorMessage("invalid region");
296
297 if (status3)
298 {
299 ++status;
300 std::cout << "FAILED" << std::endl;
301 }
302 else
303 {
304 std::cout << "PASSED" << std::endl;
305 }
306 aPlanes->Delete();
307 }
308
309 {
310 std::cout << " Testing SetRegionVertices...";
311 int status5 = 0;
312 vtkSmartPointer<vtkPlanesIntersection> aPlanes =
313 vtkSmartPointer<vtkPlanesIntersection>::New();
314 vtkSmartPointer<vtkPoints> points =
315 vtkSmartPointer<vtkPoints>::New();
316 vtkSmartPointer<vtkDoubleArray> normals =
317 vtkSmartPointer<vtkDoubleArray>::New();
318 normals->SetNumberOfComponents(3);
319
320 points->InsertNextPoint (-1.0, 0.0, 0.0);
321 normals->InsertNextTuple3(-1.0, 0.0, 0.0);
322 points->InsertNextPoint (1.0, 0.0, 0.0);
323 normals->InsertNextTuple3(1.0, 0.0, 0.0);
324 points->InsertNextPoint (0.0, -1.0, 0.0);
325 normals->InsertNextTuple3(0.0, -1.0, 0.0);
326 points->InsertNextPoint (0.0, 1.0, 0.0);
327 normals->InsertNextTuple3(0.0, 1.0, 0.0);
328 points->InsertNextPoint (0.0, 0.0, -1.0);
329 normals->InsertNextTuple3(0.0, 0.0, -1.0);
330 points->InsertNextPoint (0.0, 0.0, 1.0);
331 normals->InsertNextTuple3(0.0, 0.0, 1.0);
332 aPlanes->SetPoints(points);
333 aPlanes->SetNormals(normals);
334
335 int numberOfRegionVertices = aPlanes->GetNumRegionVertices();
336 if (numberOfRegionVertices != 8)
337 {
338 ++status5;
339 std::cout << " GetNumRegionVertices() got " << numberOfRegionVertices
340 << " but expected 8 ";
341 }
342 std::vector<double> regionVertices(numberOfRegionVertices * 3);
343
344 aPlanes->GetRegionVertices(
345 &(*regionVertices.begin()),
346 numberOfRegionVertices);
347 aPlanes->SetRegionVertices(
348 &(*regionVertices.begin()),
349 numberOfRegionVertices);
350
351 if (status5)
352 {
353 ++status;
354 std::cout << "FAILED" << std::endl;
355 }
356 else
357 {
358 std::cout << "PASSED" << std::endl;
359 }
360 }
361
362 {
363 std::cout << " Testing IntersectsRegion Errors...";
364 vtkSmartPointer<vtkTest::ErrorObserver> errorObserver =
365 vtkSmartPointer<vtkTest::ErrorObserver>::New();
366
367 vtkBoundingBox bbox(-10, 10, -10, 10, -10, 10);
368 double xmin, xmax, ymin, ymax, zmin, zmax;
369 bbox.GetMinPoint(xmin, ymin, zmin);
370 bbox.GetMaxPoint(xmax, ymax, zmax);
371
372 vtkSmartPointer<vtkPoints> points =
373 vtkSmartPointer<vtkPoints>::New();
374
375 points->InsertNextPoint(xmin, ymin, zmin);
376 points->InsertNextPoint(xmax, ymin, zmin);
377 points->InsertNextPoint(xmax, ymax, zmin);
378 points->InsertNextPoint(xmin, ymax, zmin);
379
380 points->InsertNextPoint(xmin, ymin, zmax);
381 points->InsertNextPoint(xmax, ymin, zmax);
382 points->InsertNextPoint(xmax, ymax, zmax);
383 points->InsertNextPoint(xmin, ymax, zmax);
384
385 // empty planes
386 vtkSmartPointer<vtkPlanesIntersection> empty =
387 vtkSmartPointer<vtkPlanesIntersection>::New();
388 empty->AddObserver(vtkCommand::ErrorEvent, errorObserver);
389
390 int status1 = 0;
391 if (empty->IntersectsRegion(points) != 0)
392 {
393 ++status1;
394 std::cout << "FAILED" << std::endl;
395 }
396 else
397 {
398 status1 += errorObserver->CheckErrorMessage("invalid region - less than 4 planes");
399 }
400
401 // Invalid Region
402 vtkSmartPointer<vtkPlanesIntersection> invalidRegion =
403 vtkSmartPointer<vtkPlanesIntersection>::New();
404 invalidRegion->AddObserver(vtkCommand::ErrorEvent, errorObserver);
405
406 vtkSmartPointer<vtkPoints> npoints =
407 vtkSmartPointer<vtkPoints>::New();
408 vtkSmartPointer<vtkDoubleArray> normals =
409 vtkSmartPointer<vtkDoubleArray>::New();
410 normals->SetNumberOfComponents(3);
411
412 npoints->InsertNextPoint (-1.0, 0.0, 0.0);
413 normals->InsertNextTuple3(-1.0, 0.0, 0.0);
414 npoints->InsertNextPoint (-1.0, 0.0, 0.0);
415 normals->InsertNextTuple3(-1.0, 0.0, 0.0);
416 npoints->InsertNextPoint (-1.0, 0.0, 0.0);
417 normals->InsertNextTuple3(-1.0, 0.0, 0.0);
418 npoints->InsertNextPoint (-1.0, 0.0, 0.0);
419 normals->InsertNextTuple3(-1.0, 0.0, 0.0);
420 invalidRegion->SetPoints(npoints);
421 invalidRegion->SetNormals(normals);
422
423 if (invalidRegion->IntersectsRegion(points) != 0)
424 {
425 ++status1;
426 std::cout << "FAILED" << std::endl;
427 }
428 else
429 {
430 status1 += errorObserver->CheckErrorMessage("Invalid region: zero-volume intersection");
431 }
432 vtkSmartPointer<vtkPlanesIntersection> invalidBox =
433 vtkSmartPointer<vtkPlanesIntersection>::New();
434 invalidBox->AddObserver(vtkCommand::ErrorEvent, errorObserver);
435
436 vtkSmartPointer<vtkPoints> points2 =
437 vtkSmartPointer<vtkPoints>::New();
438 vtkSmartPointer<vtkDoubleArray> normals2 =
439 vtkSmartPointer<vtkDoubleArray>::New();
440 normals2->SetNumberOfComponents(3);
441
442 points2->InsertNextPoint (-1.0, 0.0, 0.0);
443 normals2->InsertNextTuple3(-1.0, 0.0, 0.0);
444 points2->InsertNextPoint (1.0, 0.0, 0.0);
445 normals2->InsertNextTuple3(1.0, 0.0, 0.0);
446 points2->InsertNextPoint (0.0, -1.0, 0.0);
447 normals2->InsertNextTuple3(0.0, -1.0, 0.0);
448 points2->InsertNextPoint (0.0, 1.0, 0.0);
449 normals2->InsertNextTuple3(0.0, 1.0, 0.0);
450 points2->InsertNextPoint (0.0, 0.0, -1.0);
451 normals2->InsertNextTuple3(0.0, 0.0, -1.0);
452 points2->InsertNextPoint (0.0, 0.0, 1.0);
453 normals2->InsertNextTuple3(0.0, 0.0, 1.0);
454 invalidBox->SetPoints(points2);
455 invalidBox->SetNormals(normals2);
456
457 vtkSmartPointer<vtkPoints> badBox =
458 vtkSmartPointer<vtkPoints>::New();
459
460 badBox->InsertNextPoint(xmin, ymin, zmin);
461 badBox->InsertNextPoint(xmax, ymin, zmin);
462 badBox->InsertNextPoint(xmax, ymax, zmin);
463 badBox->InsertNextPoint(xmin, ymax, zmin);
464
465 badBox->InsertNextPoint(xmin, ymin, zmax);
466 badBox->InsertNextPoint(xmax, ymin, zmax);
467 badBox->InsertNextPoint(xmax, ymax, zmax);
468
469 if (invalidBox->IntersectsRegion(badBox) != 0)
470 {
471 ++status1;
472 std::cout << "FAILED" << std::endl;
473 }
474 else
475 {
476 status1 += errorObserver->CheckErrorMessage("invalid box");
477 }
478
479 if (status1)
480 {
481 ++status;
482 std::cout << "FAILED" << std::endl;
483 }
484 else
485 {
486 std::cout << "PASSED" << std::endl;
487 }
488 }
489
490 if (status)
491 {
492 return EXIT_FAILURE;
493 }
494 else
495 {
496 return EXIT_SUCCESS;
497 }
498 }
499
500
MakeTetra()501 vtkSmartPointer<vtkTetra> MakeTetra()
502 {
503 vtkSmartPointer<vtkTetra> aTetra =
504 vtkSmartPointer<vtkTetra>::New();
505 aTetra->GetPointIds()->SetId(0,0);
506 aTetra->GetPointIds()->SetId(1,1);
507 aTetra->GetPointIds()->SetId(2,2);
508 aTetra->GetPointIds()->SetId(3,3);
509 aTetra->GetPoints()->SetPoint(0, -1.0, -1.0, -1.0);
510 aTetra->GetPoints()->SetPoint(1, 1.0, -1.0, -1.0);
511 aTetra->GetPoints()->SetPoint(2, 0.0, 1.0, -1.0);
512 aTetra->GetPoints()->SetPoint(3, 0.5, 0.5, 1.0);
513 return aTetra;
514 }
515