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