1 // Some tests for vgl_oriented_box
2 // J.L. Mundy Dec. 2016
3 #include <iostream>
4 #include <sstream>
5 #include <cmath>
6 #include "testlib/testlib_test.h"
7 #include "vgl/vgl_oriented_box_2d.h"
8 #include "vgl/vgl_area.h"
9 #include "vgl/vgl_box_2d.h"
10 #ifdef _MSC_VER
11 # include "vcl_msvc_warnings.h"
12 #endif
13 #include "vgl/vgl_fit_oriented_box_2d.h"
14
15 static void
test_oriented_box_2d()16 test_oriented_box_2d()
17 {
18 std::cout << "***************************\n"
19 << " Testing vgl_oriented_box_2d\n"
20 << "***************************\n\n";
21 // test constructors and corner accessor
22 vgl_point_2d<double> pmaj1(0.0, 100.0), pmaj2(200.0, 100.0);
23 vgl_point_2d<double> pmin1(50.0, 150.0), pmin2(50.0, 0.0);
24 vgl_oriented_box_2d<double> ob(pmaj1, pmaj2, pmin1, pmin2);
25 std::vector<vgl_point_2d<double>> corns0 = ob.corners();
26 vgl_point_2d<double> pmaj11(50.0, 50.0), pmaj21(150.0, 50.0);
27 vgl_point_2d<double> pmin11(100.0, 75.0), pmin21(100.0, 25.0);
28 vgl_oriented_box_2d<double> ob1(pmaj11, pmaj21, pmin11, pmin21);
29 std::vector<vgl_point_2d<double>> corns1 = ob1.corners();
30
31 vgl_oriented_box_2d<double> tbox1 = ob1.translate(200.0, 50.0);
32 std::vector<vgl_point_2d<double>> trans_corns1 = tbox1.corners();
33 TEST("translate obox", trans_corns1[2].x() + trans_corns1[2].y(), 475.0);
34
35 vgl_point_2d<double> cent = tbox1.centroid();
36 TEST("centroid", cent.x() + cent.y(), 400.0);
37
38 vgl_oriented_box_2d<double> rtbox1 = tbox1.rotate(cent, 3.1415926535897 / 2.0);
39 std::vector<vgl_point_2d<double>> rot_trans_corns1 = rtbox1.corners();
40 TEST_NEAR("rotate box", rot_trans_corns1[2].x() + rot_trans_corns1[2].y(), 425.0, 0.000001);
41
42 vgl_box_2d<double> bb = rtbox1.enclosing_box();
43 double area = vgl_area(bb);
44 TEST_NEAR("bounding box", area, 5000.0, 0.000001);
45 std::stringstream ss;
46 ss << ob;
47 vgl_oriented_box_2d<double> ibox;
48 ss >> ibox;
49 bool eq = ibox == ob;
50 TEST("read/write equal", eq, true);
51 vgl_point_2d<float> pmaj1a(0.0f, 100.0f), pmaj2a(200.0f, 100.0f);
52
53 vgl_oriented_box_2d<float> ob0(pmaj1a, pmaj2a, 150.0f);
54 std::vector<vgl_point_2d<float>> corns = ob0.corners();
55 std::cout << "Corners" << std::endl;
56 for (auto & corn : corns)
57 std::cout << corn << std::endl;
58 float width = ob.width();
59 float height = ob.height();
60 vgl_point_2d<float> p(25.0, 25.0);
61 vgl_point_2d<float> uv = ob0.transform_to_obox(p);
62 std::cout << "width " << width << " height " << height << " uv " << uv << std::endl;
63 vgl_box_2d<float> box = ob0.enclosing_box();
64 std::cout << "axis_aligned box " << box << std::endl;
65 TEST("box size", width == 200.0f && height == 150.0f, true);
66 TEST("corners ", corns[2] == vgl_point_2d<float>(200.0f, 175.0f), true);
67 TEST("uv ", uv == vgl_point_2d<float>(-75.0f / 200.0f, -0.5f), true);
68 // test contains
69 vgl_point_2d<float> pin(199.0, 140.0);
70 vgl_point_2d<float> pout(175.0, 180.0);
71 bool good = ob0.contains(pin) && !ob0.contains(pout);
72 TEST("contains ", good, true);
73 vgl_point_2d<float> p0(0.0f, 25.0f), p1(200.0f, 25.0f), p2(0.0f, 175.0);
74 vgl_oriented_box_2d<float> ob1a(p0, p1, p2);
75 TEST("construct from 3 pts", ob1a == ob0, true);
76 vgl_box_2d<float> b, br;
77 b.add(vgl_point_2d<float>(0.0f, 0.0f));
78 b.add(vgl_point_2d<float>(100.0f, 150.0f));
79 br.add(vgl_point_2d<float>(-25.0f, 25.0f));
80 br.add(vgl_point_2d<float>(125.0f, 125.0f));
81 vgl_oriented_box_2d<float> ob2a(b, -3.1415926535897932384626433832795f / 2.0f);
82 vgl_oriented_box_2d<float> ob3(br, 0.0f);
83 TEST("test rotation constructors", ob2a == ob3, true);
84 vgl_point_2d<float> p0a(0.0f, 0.0f), p1a(100.0f, 57.73503f), p2a(-25.0f, 43.30127f);
85 vgl_oriented_box_2d<float> obang(p0a, p1a, p2a);
86 float ang = obang.angle_in_rad();
87 TEST_NEAR("orientation angle", ang, 0.523599f, 0.001);
88
89 // test fiting an oriented box to points
90 vgl_point_2d<double> p00(0.0, 0.0), p01(2.0, 0.0), p02(2.0, 1.0), p03(0.0, 1.0);
91 std::vector<vgl_point_2d<double>> verts;
92 verts.push_back(p00);
93 verts.push_back(p01);
94 verts.push_back(p02);
95 verts.push_back(p03);
96 vgl_polygon<double> poly(verts);
97 vgl_fit_oriented_box_2d<double> fob(poly);
98 vgl_oriented_box_2d<double> obf = fob.fitted_box();
99 double angf = obf.angle_in_rad(), wth = obf.width(), hht = obf.height();
100 double er = fabs(sin(angf)) + fabs(wth - 2) + fabs(hht - 1);
101 TEST_NEAR("fit oriented box to pts", er, 0.0, 0.001);
102
103 // test a real data case
104 vgl_point_2d<double> p0r(0.444941, -0.780737);
105 vgl_point_2d<double> p1r(-0.823115, -2.21685);
106 vgl_point_2d<double> p2r(-4.02411, -2.63267);
107 vgl_point_2d<double> p3(-4.06477, -4.40946);
108 vgl_point_2d<double> p4(-4.50972, -3.5838);
109 vgl_point_2d<double> p5(-4.58641, -4.70911);
110 vgl_point_2d<double> p6(-7.41408, -4.55561);
111 vgl_point_2d<double> p7(-7.75148, -5.77787);
112 vgl_point_2d<double> p8(-7.75148, -5.77787);
113 vgl_point_2d<double> p9(-7.41408, -4.55561);
114 vgl_point_2d<double> p10(-5.58869, -3.50253);
115 vgl_point_2d<double> p11(-5.66042, -2.23449);
116 vgl_point_2d<double> p12(-2.60774, -1.48014);
117 vgl_point_2d<double> p13(-1.6005, -0.199361);
118 vgl_point_2d<double> p14(3.20099, 0.40761);
119 vgl_point_2d<double> p15(3.91161, 2.23784);
120 vgl_point_2d<double> p16(6.18194, 2.47685);
121 vgl_point_2d<double> p17(6.40684, 3.30224);
122 vgl_point_2d<double> p18(12.0314, 6.14794);
123 vgl_point_2d<double> p19(12.8904, 7.66868);
124 vgl_point_2d<double> p20(12.8904, 7.66868);
125 vgl_point_2d<double> p21(9.05535, 6.53773);
126 vgl_point_2d<double> p22(9.23958, 5.59477);
127 vgl_point_2d<double> p23(8.12469, 6.34489);
128 vgl_point_2d<double> p24(6.33522, 4.64566);
129 vgl_point_2d<double> p25(4.43809, 4.91831);
130 vgl_point_2d<double> p26(3.17004, 3.52672);
131 vgl_point_2d<double> p27(3.46666, 2.9751);
132 vgl_point_2d<double> p28(2.12698, 2.94762);
133 vgl_point_2d<double> p29(2.42361, 2.42879);
134 vgl_point_2d<double> p30(0.59811, 1.39932);
135 std::vector<vgl_point_2d<double>> pts;
136 pts.push_back(p0r);
137 pts.push_back(p1r);
138 pts.push_back(p2r);
139 pts.push_back(p3);
140 pts.push_back(p4);
141 pts.push_back(p5);
142 pts.push_back(p6);
143 pts.push_back(p7);
144 pts.push_back(p8);
145 pts.push_back(p9);
146 pts.push_back(p10);
147 pts.push_back(p11);
148 pts.push_back(p12);
149 pts.push_back(p13);
150 pts.push_back(p14);
151 pts.push_back(p15);
152 pts.push_back(p16);
153 pts.push_back(p17);
154 pts.push_back(p18);
155 pts.push_back(p19);
156 pts.push_back(p20);
157 pts.push_back(p21);
158 pts.push_back(p22);
159 pts.push_back(p23);
160 pts.push_back(p24);
161 pts.push_back(p25);
162 pts.push_back(p26);
163 pts.push_back(p27);
164 pts.push_back(p28);
165 pts.push_back(p29);
166 pts.push_back(p30);
167 vgl_fit_oriented_box_2d<double> fob30(pts);
168 vgl_oriented_box_2d<double> obf30 = fob30.fitted_box();
169 std::vector<vgl_point_2d<double>> cns = obf30.corners();
170 for (auto & cn : cns)
171 std::cout << cn.x() << ' ' << cn.y() << std::endl;
172 double arear = vgl_area(obf30);
173 TEST_NEAR("real obox fit", arear, 78.59471308, 1e-04);
174 // second real fit
175 vgl_point_2d<double> q0(-6.70591, -2.28258);
176 vgl_point_2d<double> q1(-4.14291, -4.83427);
177 vgl_point_2d<double> q2(-0.631689, -4.85021);
178 vgl_point_2d<double> q3(0.176725, -6.1546);
179 vgl_point_2d<double> q4(-2.24703, -7.55325);
180 vgl_point_2d<double> q5(-0.0691315, -7.62193);
181 vgl_point_2d<double> q6(1.51102, -6.03368);
182 vgl_point_2d<double> q7(4.84672, -5.64279);
183 vgl_point_2d<double> q8(4.60103, -4.56791);
184 vgl_point_2d<double> q9(5.79494, -3.12394);
185 vgl_point_2d<double> q10(5.9711, 4.3438);
186 vgl_point_2d<double> q11(3.47803, 3.64558);
187 vgl_point_2d<double> q12(1.61627, 4.71676);
188 vgl_point_2d<double> q13(1.65141, 5.66017);
189 vgl_point_2d<double> q14(-0.59568, 6.50897);
190 vgl_point_2d<double> q15(-2.24605, 5.52854);
191 vgl_point_2d<double> q16(-3.1589, 6.50555);
192 vgl_point_2d<double> q17(-4.70391, 5.78521);
193 vgl_point_2d<double> q18(-4.77425, 3.85846);
194 vgl_point_2d<double> q19(-5.54678, 3.45917);
195 vgl_point_2d<double> q20(-4.77448, 1.23897);
196 std::vector<vgl_point_2d<double>> qpts;
197 qpts.push_back(q0);
198 qpts.push_back(q1);
199 qpts.push_back(q2);
200 qpts.push_back(q3);
201 qpts.push_back(q4);
202 qpts.push_back(q5);
203 qpts.push_back(q6);
204 qpts.push_back(q7);
205 qpts.push_back(q8);
206 qpts.push_back(q9);
207 qpts.push_back(q10);
208 qpts.push_back(q11);
209 qpts.push_back(q12);
210 qpts.push_back(q13);
211 qpts.push_back(q14);
212 qpts.push_back(q15);
213 qpts.push_back(q16);
214 qpts.push_back(q17);
215 qpts.push_back(q18);
216 qpts.push_back(q19);
217 qpts.push_back(q20);
218 vgl_fit_oriented_box_2d<double> q44(qpts);
219 double ang_rad = 1.378819939;
220 vgl_oriented_box_2d<double> ob44 = q44.fitted_box(ang_rad);
221 double angq = ob44.angle_in_rad();
222 double w44 = ob44.width();
223 double gtw = 14.11896874;
224 double er44 = fabs(w44 - gtw) + fabs(angq - ang_rad);
225 TEST_NEAR("specify_angle", er44, 0.0, 0.0001);
226 }
227
228 TESTMAIN(test_oriented_box_2d);
229