1 // Some tests for vgl_plane_3d
2 // J.L. Mundy Sept. 17, 2010
3
4 #include <iostream>
5 #include <sstream>
6 #include <cmath>
7 #include "testlib/testlib_test.h"
8 #include "vgl/vgl_plane_3d.h"
9 #include "vgl/vgl_point_3d.h"
10 #include "vgl/vgl_point_2d.h"
11 #include "vgl/vgl_vector_3d.h"
12 #include "vgl/vgl_ray_3d.h"
13 #include "vgl/vgl_closest_point.h"
14 #ifdef _MSC_VER
15 # include "vcl_msvc_warnings.h"
16 #endif
17 static void
test_constructor()18 test_constructor()
19 {
20 double a = 0.0, b = 10.0, c = 0.0, d = 0.0;
21 vgl_plane_3d<double> plane_abcd(a, b, c, d);
22 vgl_vector_3d<double> n(0.0, 1.0, 0.0);
23 vgl_point_3d<double> p0(0.0, 0.0, 0.0);
24 vgl_plane_3d<double> plane_ptn(n, p0);
25 vgl_vector_3d<double> nabcd = plane_abcd.normal(), nptn = plane_ptn.normal();
26 double dist = std::fabs(1.0 - dot_product(nabcd, nptn));
27 TEST_NEAR("Constructors and Normal", dist, 0.0, 1e-5);
28 // case I coincident
29 vgl_vector_3d<double> dir0(-1.0, 0.0, 0.0), dir1(0.0, 0.0, 1.0);
30 vgl_ray_3d<double> r0(p0, dir0), r1(p0, dir1);
31 vgl_plane_3d<double> plane_coin_rays(r0, r1);
32 vgl_vector_3d<double> ncoin = plane_coin_rays.normal();
33 dist = std::fabs(1.0 - dot_product(ncoin, nptn));
34 TEST_NEAR("Coincident ray constructor", dist, 0.0, 1e-5);
35 vgl_point_3d<double> p0p(-1.0, 0.0, 0.0);
36 vgl_ray_3d<double> r0p(p0p, dir1);
37 vgl_plane_3d<double> plane_para_rays(r0p, r1);
38 vgl_vector_3d<double> npara = plane_para_rays.normal();
39 dist = std::fabs(1.0 - dot_product(npara, nptn));
40 TEST_NEAR("Parallel ray constructor", dist, 0.0, 1e-5);
41 }
42
43 static void
test_operations()44 test_operations()
45 {
46 // a plane rotated 45 degrees around the Y axis, i.e. normal is
47 // perpendicular to Y
48 double a = 1.0, b = 0.0, c = 1.0, d = 0.0;
49 vgl_plane_3d<double> plane(a, b, c, d);
50 vgl_point_3d<double> p3d(1.0, 1.0, -1.0);
51 vgl_point_2d<double> p2d, p2dy, p2dys;
52 bool good = plane.plane_coords(p3d, p2d, 1e-5);
53 double er = std::fabs(p2d.x() - std::sqrt(2.0));
54
55 // a plane with the Y axis as its normal
56 a = 0.0, b = 1.0, c = 0.0;
57 vgl_plane_3d<double> plane1(a, b, c, d);
58 vgl_point_3d<double> p3dy(1.0, 0.0, 1.0);
59 good = good && plane1.plane_coords(p3dy, p2dy, 1e-5);
60 er += std::fabs(p2dy.x() - 1.0) + std::fabs(p2dy.y() - 1.0);
61 // shift the plane along the y axis
62 d = -10.0;
63 vgl_plane_3d<double> plane1s(a, b, c, d);
64 vgl_point_3d<double> p3dys(1.0, 10.0, 1.0);
65 good = good && plane1s.plane_coords(p3dys, p2dys, 1e-5);
66 er += std::fabs(p2dys.x() - 1.0) + std::fabs(p2dys.y() - 1.0);
67 good = good && (er < 1e-5);
68 TEST("Plane Coordinate System: world -> plane", good, true);
69
70 vgl_point_3d<double> p3d1, p3d2, p3d3;
71 p3d1 = plane.world_coords(p2d);
72 p3d2 = plane1.world_coords(p2dy);
73 p3d3 = plane1s.world_coords(p2dys);
74 er = (p3d1 - p3d).length();
75 er += (p3d2 - p3dy).length();
76 er += (p3d3 - p3dys).length();
77 TEST_NEAR("Plane Coordinate System: plane -> world", er, 0.0, 1e-5);
78
79 // test with a realistic plane
80 vgl_point_3d<double> pt3d(-51.26, -7045.5, -50.0);
81 vgl_plane_3d<double> plane_real(-.162, 0.987, 0.0, 6943.55);
82 vgl_point_3d<double> pt3d_on = vgl_closest_point(pt3d, plane_real);
83 vgl_point_2d<double> pt2d;
84 good = plane_real.plane_coords(pt3d_on, pt2d, 1e-5);
85 TEST("Realistic plane test: world -> plane", good, true);
86 vgl_point_3d<double> prec_3d = plane_real.world_coords(pt2d);
87 er = (prec_3d - pt3d_on).length();
88 TEST_NEAR("Realistic plane test", er, 0.0, 1e-5);
89
90 // test stream operators
91 double as = 0.1, bs = 0.5, cs = 0.86, ds = -1.0;
92 vgl_plane_3d<double> pstr(as, bs, cs, ds);
93 std::stringstream ss;
94 ss << pstr;
95 vgl_plane_3d<double> prec;
96 ss >> prec;
97 TEST("plane stream ops", pstr == prec, true);
98 }
99
100 void
test_plane_3d()101 test_plane_3d()
102 {
103 std::cout << "**********************\n"
104 << " Testing vgl_plane_3d\n"
105 << "**********************\n\n";
106
107 test_constructor();
108 test_operations();
109 }
110
111
112 TESTMAIN(test_plane_3d);
113