1 // This is rpl/rsdl/tests/test_bins_2d.cxx
2 #include <vector>
3 #include <iostream>
4 #include <algorithm>
5 #ifdef _MSC_VER
6 #  include "vcl_msvc_warnings.h"
7 #endif
8 
9 #include "vnl/vnl_vector_fixed.h"
10 #include "vnl/vnl_double_2.h"
11 #include "vnl/vnl_math.h"
12 #include "vnl/vnl_random.h"
13 
14 #include "testlib/testlib_test.h"
15 
16 #include <rsdl/rsdl_bins_2d.h>
17 
test_bins_2d()18 static void test_bins_2d()
19 {
20   vnl_vector_fixed< double, 2 > min_pt, max_pt, bin_sizes;
21   min_pt[0] = 1.0;   min_pt[1] = -2.5;
22   max_pt[0] = 75.0;  max_pt[1] = 32;
23   bin_sizes[0] = 6; bin_sizes[1] = 4;
24 
25   rsdl_bins_2d< double, int > bins( min_pt, max_pt, bin_sizes );
26   double dist_tol = 0.0001;
27   bins.set_distance_tolerance( dist_tol );
28   vnl_vector_fixed< double, 2 >  pt( 12.5, 3 );
29   int value = 0;
30   bins.add_point( pt, value ); // should be 1, 0
31 
32   pt[0] += dist_tol / 4;
33   pt[1] -= dist_tol / 4;
34   int changed_value = -5;
35   TEST("add point and change point", bins.change_point( pt, changed_value ), true);
36 
37   int stored_value;
38   TEST("get value", bins.get_value( pt, stored_value ) &&
39                     stored_value == changed_value, true);
40 
41   vnl_vector_fixed< double, 2 > nearby( pt[0] + dist_tol, pt[1] - 2*dist_tol );
42 
43   TEST("change nearby, but not close enough",
44        !bins.change_point( nearby, 22 ) &&
45        bins.get_value( pt, stored_value ) &&
46        stored_value == changed_value, true);
47 
48   TEST("remove", bins.remove_point( pt ) &&
49                  ! bins.get_value( pt, stored_value ), true);
50 
51   pt[0] = 56.4; pt[1] = 31.0;
52   int added_value = 45;
53   bins.add_point( pt, added_value );
54   vnl_vector_fixed< double, 2 > pt2( 56.1, 30 );
55 
56   TEST("remove -- not there", !bins.remove_point( pt2 ) &&
57                               bins.get_value( pt, stored_value ) &&
58                               stored_value == added_value, true);
59   TEST("remove -- different stored value", !bins.remove_point( pt, 30 ) &&
60                                            bins.get_value( pt, stored_value ) &&
61                                            stored_value == added_value, true);
62 
63   TEST("remove with value", bins.remove_point( pt, added_value ) &&
64                             !bins.get_value( pt, stored_value ), true);
65 
66   pt[0] = 100; pt[1] = -30;
67   added_value = 24;
68   bins.add_point( pt, added_value );
69   TEST("adding point outside range", bins.get_value( pt, stored_value ) &&
70                                      stored_value == added_value, true);
71 
72   pt[0] = -50; pt[1] = 77.7;
73   added_value = 13;
74   bins.add_point( pt, added_value );
75   TEST("adding point outside range", bins.get_value( pt, stored_value ) &&
76                                      stored_value == added_value, true);
77 
78   //  Generate a bunch of points:
79   constexpr int M = 60;
80   std::vector< vnl_vector_fixed< double, 2 > > points( M );
81   std::vector< int > indices( M );
82   vnl_random mz_rand;
83   bins.reset( min_pt, max_pt, bin_sizes );
84 
85   for ( int i=0; i<M; ++i ) {
86     indices[ i ] = i;
87     points[ i ][0] = (max_pt[0] - min_pt[0]) * mz_rand.drand32() + min_pt[0];
88     points[ i ][1] = (max_pt[1] - min_pt[1]) * mz_rand.drand32() + min_pt[1];
89     bins.add_point( points[ i ], i );
90   }
91 
92   //  test  "is_any_point_within_radius" and "points_with_radius"
93 
94   constexpr int num_tests = 5;
95   for ( int t=0; t<num_tests; ++t ) {
96     vnl_vector_fixed< double, 2 > q;
97     q[0] = (max_pt[0] - min_pt[0]) * mz_rand.drand32() + min_pt[0];
98     q[1] = (max_pt[1] - min_pt[1]) * mz_rand.drand32() + min_pt[1];
99     double radius = (t+1) * bin_sizes[0] / 2;  // increasing size, starting smallest
100 
101     bool bin_answer = bins.is_any_point_within_radius( q, radius );
102 
103     std::vector< int > all_close_indices;
104     for ( int i=0; i<M; ++i ) {
105       if ( vnl_vector_ssd( points[ i ], q ) < vnl_math::sqr( radius ) )
106         all_close_indices.push_back( i );
107     }
108 
109     TEST("is_any_point_within_radius", bin_answer,
110          (!all_close_indices.empty()));
111 
112     std::vector< int > bin_close_indices;
113     bins.points_within_radius( q, radius, bin_close_indices );
114     bool correct = all_close_indices.size() ==  bin_close_indices.size();
115     std::sort( all_close_indices.begin(), all_close_indices.end() );
116     std::sort( bin_close_indices.begin(), bin_close_indices.end() );
117 
118     for ( unsigned int i=0; correct &&
119           i < std::min(all_close_indices.size(), bin_close_indices.size()); ++i )
120       correct = all_close_indices[ i ] == bin_close_indices[ i ];
121 
122     TEST("points_within_radius", correct, true);
123   }
124 
125   { //new test with bin size 5,5
126     vnl_double_2 a(0,0), b(100,100), c(5,5), d(4.9,0), e(8.8,0), f(1,0);
127     rsdl_bins_2d<double, int>  bins(a,b,c);//min, max, size
128 
129     bins.add_point(e, 1);
130     bins.add_point(f, 2);
131 
132     std::vector<int> answer;
133     bins.n_nearest(d, 1, answer);
134 
135     TEST("Second bin test bin size 5,5",
136          !answer.empty() && (answer[0] == 1 || answer[0] == 2), true);
137   }
138 
139   {//same as new test with bin size 2,2
140     vnl_double_2 a(0,0), b(100,100), c(2,2), d(4.9,0), e(8.8,0), f(1,0);
141     rsdl_bins_2d<double, int>  bins(a,b,c);//min, max, size
142 
143     bins.add_point(e, 1);
144     bins.add_point(f, 2);
145 
146     std::vector<int> answer;
147     bins.n_nearest(d, 1, answer);
148 
149     TEST("Second bin test bin size 2,2",
150          !answer.empty() && (answer[0] == 1 || answer[0] == 2), true);
151   }
152 }
153 
154 TESTMAIN(test_bins_2d);
155