IODA Bundle
test_functions.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 1996-2012 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
11 #include "eckit/testing/Test.h"
12 #include "eckit/types/FloatCompare.h"
13 
14 #include "odc/Writer.h"
15 #include "odc/Select.h"
16 
17 #include "TemporaryFiles.h"
18 
19 using namespace eckit::testing;
20 using eckit::types::is_approximately_equal;
21 
22 // ------------------------------------------------------------------------------------------------------
23 
24 CASE("Various distance measuring functions return sensible things") {
25 
27 
28  // Write some data with a latitude and longitude.
29 
30  {
31  odc::Writer<> oda(f.path());
32  odc::Writer<>::iterator row = oda.begin();
33 
34  row->setNumberOfColumns(2);
35 
36  row->setColumn(0, "lat", odc::api::REAL);
37  row->setColumn(1, "lon", odc::api::REAL);
38 
39  row->writeHeader();
40 
41  // Include some extreme values
42 
43  (*row)[0] = 45.0;
44  (*row)[1] = 0.0;
45  ++row;
46 
47  (*row)[0] = 90.0;
48  (*row)[1] = 180.0;
49  ++row;
50 
51  (*row)[0] = -90.0;
52  (*row)[1] = 360.0;
53  ++row;
54 
55  (*row)[0] = -45.0;
56  (*row)[1] = -90.0;
57  ++row;
58  }
59 
60  // And test that the SQL functions get the right data out!!!
61 
62  const std::string sql = std::string("select rad(45.0,0.0,1.0,lat,lon), ") +
63  "rad(10.0,0.0,0.0,lat,lon), " +
64  "distance(46.0,0.0,lat,lon), " +
65  "km(46.0,0.0,lat,lon), " +
66  "dist(100.,46.0,1.0,lat,lon), " +
67  "dist(40.0,5.0,1000.0,lat,lon) " +
68  "from \"" + f.path() + "\";";
69 
70  const double eps = 7.e-6;
71 
72  {
73  odc::Select oda(sql);
74  odc::Select::iterator it = oda.begin();
75 
76  EXPECT((*it)[0] == 1); // Inside relevant great-circle
77  EXPECT((*it)[1] == 0);
78  EXPECT(is_approximately_equal((*it)[2], 111120., eps)); // Surface distance to specified point
79  EXPECT(is_approximately_equal((*it)[3], 111.12, eps)); // In m
80  EXPECT((*it)[4] == 0); // Within specified distance of given point
81  EXPECT((*it)[5] == 1);
82  ++it;
83 
84  EXPECT((*it)[0] == 0); // Inside relevant great-circle
85  EXPECT((*it)[1] == 0);
86  // pi/4 * R
87  EXPECT(is_approximately_equal((*it)[2], 4889280., eps)); // Surface distance to specified point
88  EXPECT(is_approximately_equal((*it)[3], 4889.28, eps)); // In m
89  EXPECT((*it)[4] == 0); // Within specified distance of given point
90  EXPECT((*it)[5] == 0);
91  ++it;
92 
93  EXPECT((*it)[0] == 0); // Inside relevant great-circle
94  EXPECT((*it)[1] == 0);
95  // 3*pi/4 * R
96  EXPECT(is_approximately_equal((*it)[2], 15112320., eps)); // Surface distance to specified point
97  EXPECT(is_approximately_equal((*it)[3], 15112.32, eps)); // In m
98  EXPECT((*it)[4] == 0); // Within specified distance of given point
99  EXPECT((*it)[5] == 0);
100  ++it;
101 
102  EXPECT((*it)[0] == 0); // Inside relevant great-circle
103  EXPECT((*it)[1] == 0);
104  EXPECT(is_approximately_equal((*it)[2], 13398177.5541776344, eps)); // Surface distance to specified point
105  EXPECT(is_approximately_equal((*it)[3], 13398.1775541776344, eps)); // In m
106  EXPECT((*it)[4] == 0); // Within specified distance of given point
107  EXPECT((*it)[5] == 0);
108  ++it;
109  }
110 
111  // Test against things measured from the north and south poles
112 
113  const std::string sql2 = std::string("select "
114  "distance(90.0,0.0,lat,lon), "
115  "km(90.0,0.0,lat,lon), "
116  "distance(-90.0,0.0,lat,lon), "
117  "km(-90.0,0.0,lat,lon), "
118  "distance(0.0,180.0,lat,lon), "
119  "km(0.0,180.0,lat,lon), "
120  "from \"") + f.path() + "\";";
121 
122  {
123  odc::Select oda(sql2);
124  odc::Select::iterator it = oda.begin();
125 
126  // pi/4 * R_e
127  EXPECT(is_approximately_equal((*it)[0], 5000400., eps));
128  EXPECT(is_approximately_equal((*it)[1], 5000.4, eps));
129  // 3*pi/4 * R_e
130  EXPECT(is_approximately_equal((*it)[2], 15001200., eps));
131  EXPECT(is_approximately_equal((*it)[3], 15001.2, eps));
132  // 3*pi/4 * R_e
133  EXPECT(is_approximately_equal((*it)[4], 15001200., eps));
134  EXPECT(is_approximately_equal((*it)[5], 15001.2, eps));
135  ++it;
136 
137  EXPECT(is_approximately_equal((*it)[0], 0., eps));
138  EXPECT(is_approximately_equal((*it)[1], 0., eps));
139  // pi * R_e
140  EXPECT(is_approximately_equal((*it)[2], 20001600., eps));
141  EXPECT(is_approximately_equal((*it)[3], 20001.6, eps));
142  // pi / 2 * R_e
143  EXPECT(is_approximately_equal((*it)[4], 10000800., eps));
144  EXPECT(is_approximately_equal((*it)[5], 10000.8, eps));
145  ++it;
146 
147  EXPECT(is_approximately_equal((*it)[0], 20001600., eps));
148  EXPECT(is_approximately_equal((*it)[1], 20001.6, eps));
149  // pi * R_e
150  EXPECT(is_approximately_equal((*it)[2], 0., eps));
151  EXPECT(is_approximately_equal((*it)[3], 0., eps));
152  // pi / 2 * R_e
153  EXPECT(is_approximately_equal((*it)[4], 10000800., eps));
154  EXPECT(is_approximately_equal((*it)[5], 10000.8, eps));
155  ++it;
156 
157  // 3*pi/4 * R_e
158  EXPECT(is_approximately_equal((*it)[0], 15001200., eps));
159  EXPECT(is_approximately_equal((*it)[1], 15001.2, eps));
160  // pi/4 * R_e
161  EXPECT(is_approximately_equal((*it)[2], 5000400., eps));
162  EXPECT(is_approximately_equal((*it)[3], 5000.4, eps));
163  // pi / 2 * R_e
164  EXPECT(is_approximately_equal((*it)[4], 10000800., eps));
165  EXPECT(is_approximately_equal((*it)[5], 10000.8, eps));
166  ++it;
167  }
168 }
169 
170 
171 CASE("Inside or outside detection works for circles") {
172 
174 
175  {
176  odc::Writer<> oda(f.path());
177  odc::Writer<>::iterator row = oda.begin();
178 
179  row->setNumberOfColumns(2);
180  row->setColumn(0, "x", odc::api::REAL);
181  row->setColumn(1, "y", odc::api::REAL);
182  row->writeHeader();
183 
184  (*row)[0] = 45.0;
185  (*row)[1] = 10.0;
186  ++row;
187 
188  (*row)[0] = 0.0;
189  (*row)[1] = 0.0;
190  ++row;
191 
192  (*row)[0] = -45.5;
193  (*row)[1] = 37.4;
194  ++row;
195 
196  (*row)[0] = 45.5;
197  (*row)[1] = -37.4;
198  ++row;
199  }
200 
201  // And test that the SQL functions get the right data out!!!
202 
203  const std::string sql = std::string("select ") +
204  "circle(x, 46.0, y, 11.0, 1.0), "
205  "circle(x, 46.0, y, 11.0, 1.5), "
206  "circle(x, 0.0, y, 0.0, 1.0), "
207  "circle(x, 0.0, y, 0.0, -1.0), "
208  "circle(x, 0.0, y, 0.0, 0.0), " // If we are on a point, a radius of zero is OK!
209  "circle(x, 45.5, y, -37.4, 117.7966), "
210  "circle(x, 45.5, y, -37.4, 117.7967) "
211  "from \"" + f.path() + "\";";
212 
213  {
214  odc::Select oda(sql);
215  odc::Select::iterator it = oda.begin();
216 
217  EXPECT((*it)[0] == 0);
218  EXPECT((*it)[1] == 1);
219  EXPECT((*it)[2] == 0);
220  EXPECT((*it)[3] == 0);
221  EXPECT((*it)[4] == 0);
222  EXPECT((*it)[5] == 1);
223  EXPECT((*it)[6] == 1);
224  ++it;
225 
226  EXPECT((*it)[0] == 0);
227  EXPECT((*it)[1] == 0);
228  EXPECT((*it)[2] == 1);
229  EXPECT((*it)[3] == 1);
230  EXPECT((*it)[4] == 1);
231  EXPECT((*it)[5] == 1);
232  EXPECT((*it)[6] == 1);
233  ++it;
234 
235  EXPECT((*it)[0] == 0);
236  EXPECT((*it)[1] == 0);
237  EXPECT((*it)[2] == 0);
238  EXPECT((*it)[3] == 0);
239  EXPECT((*it)[4] == 0);
240  EXPECT((*it)[5] == 0);
241  EXPECT((*it)[6] == 1);
242  ++it;
243 
244  EXPECT((*it)[0] == 0);
245  EXPECT((*it)[1] == 0);
246  EXPECT((*it)[2] == 0);
247  EXPECT((*it)[3] == 0);
248  EXPECT((*it)[4] == 0);
249  EXPECT((*it)[5] == 1);
250  EXPECT((*it)[6] == 1);
251  }
252 }
253 
254 
255 CASE("Norms are correctly calculated") {
256 
258 
259  {
260  odc::Writer<> oda(f.path());
261  odc::Writer<>::iterator row = oda.begin();
262 
263  row->setNumberOfColumns(2);
264  row->setColumn(0, "x", odc::api::REAL);
265  row->setColumn(1, "y", odc::api::REAL);
266  row->writeHeader();
267 
268  (*row)[0] = 3.0;
269  (*row)[1] = 16.0;
270  ++row;
271 
272  (*row)[0] = 4.0;
273  (*row)[1] = 12.0;
274  ++row;
275 
276  (*row)[0] = 2.0;
277  (*row)[1] = 24.0;
278  ++row;
279  }
280 
281  // And test that the SQL functions get the right data out!!!
282 
283  // See ODB-382 for buggy behaviour.
284 
285  const std::string sql = std::string("select ") +
286  "norm(x, y) "
287  "from \"" + f.path() + "\";";
288 
289  {
290  odc::Select oda(sql);
291  odc::Select::iterator it = oda.begin();
292 
293  // Norm is an aggregate function that calculates sqrt(x . y) for the
294  // entire columns of data
295 
296  EXPECT(is_approximately_equal((*it)[0], 12.));
297  ++it;
298  }
299 }
300 
301 // ------------------------------------------------------------------------------------------------------
302 
303 int main(int argc, char* argv[]) {
304  return run_tests(argc, argv);
305 }
void oda
void writeHeader()
void setNumberOfColumns(size_t n)
Definition: IteratorProxy.h:95
int setColumn(size_t index, const std::string &name, api::ColumnType type)
int main(int argc, char *argv[])
CASE("Various distance measuring functions return sensible things")