32 {
"$Id: GeoConstraint.cc 23563 2010-09-14 17:43:32Z jimg $" 67 is_prefix(
const string & in): s(in)
70 bool operator()(
const string & prefix)
72 return s.find(prefix) == 0;
88 const string & var_units,
const string & var_name)
90 return (units.find(var_units) != units.end()
91 || find_if(names.begin(), names.end(),
92 is_prefix(var_name)) != names.end());
110 GeoConstraint::categorize_notation(
const double left,
111 const double right)
const 113 return (left < 0 || right < 0) ? neg_pos : pos;
131 GeoConstraint::transform_constraint_to_pos_notation(
double &left,
149 void GeoConstraint::transform_longitude_to_pos_notation()
154 for (
int i = 0; i < d_lon_length; ++i)
168 void GeoConstraint::transform_longitude_to_neg_pos_notation()
170 for (
int i = 0; i < d_lon_length; ++i)
175 bool GeoConstraint::is_bounding_box_valid(
const double left,
const double top,
176 const double right,
const double bottom)
const 178 if ((left < d_lon[0] && right < d_lon[0])
179 || (left > d_lon[d_lon_length-1] && right > d_lon[d_lon_length-1]))
182 if (d_latitude_sense == normal) {
184 if ((top > d_lat[0] && bottom > d_lat[0])
185 || (top < d_lat[d_lat_length-1] && bottom < d_lat[d_lat_length-1]))
189 if ((top < d_lat[0] && bottom < d_lat[0])
190 || (top > d_lat[d_lat_length-1] && bottom > d_lat[d_lat_length-1]))
207 void GeoConstraint::find_longitude_indeces(
double left,
double right,
208 int &longitude_index_left,
int &longitude_index_right)
const 213 double t_left = fmod(left, 360.0);
214 double t_right = fmod(right, 360.0);
221 int lon_origin_index = 0;
222 double smallest_lon = fmod(d_lon[0], 360.0);
223 while (i < d_lon_length) {
224 double curent_lon_value = fmod(d_lon[i], 360.0);
225 if (smallest_lon > curent_lon_value) {
226 smallest_lon = curent_lon_value;
227 lon_origin_index = i;
232 DBG2(cerr <<
"lon_origin_index: " << lon_origin_index << endl);
237 i = lon_origin_index;
238 while (fmod(d_lon[i], 360.0) < t_left) {
240 i = i % d_lon_length;
243 if (i == lon_origin_index)
244 throw Error(
"geogrid: Could not find an index for the longitude value '" +
double_to_string(left) +
"'");
247 if (fmod(d_lon[i], 360.0) == t_left)
248 longitude_index_left = i;
250 longitude_index_left = (i - 1) > 0 ? i - 1 : 0;
252 DBG2(cerr <<
"longitude_index_left: " << longitude_index_left << endl);
256 int largest_lon_index = (lon_origin_index - 1 + d_lon_length) % d_lon_length;
257 i = largest_lon_index;
258 while (fmod(d_lon[i], 360.0) > t_right) {
260 i = (i == 0) ? d_lon_length - 1 : i - 1;
261 if (i == largest_lon_index)
262 throw Error(
"geogrid: Could not find an index for the longitude value '" +
double_to_string(right) +
"'");
265 if (fmod(d_lon[i], 360.0) == t_right)
266 longitude_index_right = i;
268 longitude_index_right = (i + 1) < d_lon_length - 1 ? i + 1 : d_lon_length - 1;
270 DBG2(cerr <<
"longitude_index_right: " << longitude_index_right << endl);
285 void GeoConstraint::find_latitude_indeces(
double top,
double bottom,
287 int &latitude_index_top,
288 int &latitude_index_bottom)
const 292 if (sense == normal) {
294 while (i < d_lat_length - 1 && top < d_lat[i])
297 j = d_lat_length - 1;
298 while (j > 0 && bottom > d_lat[j])
302 latitude_index_top = i;
304 latitude_index_top = (i - 1) > 0 ? i - 1 : 0;
306 if (d_lat[j] == bottom)
307 latitude_index_bottom = j;
309 latitude_index_bottom =
310 (j + 1) < d_lat_length - 1 ? j + 1 : d_lat_length - 1;
313 i = d_lat_length - 1;
314 while (i > 0 && d_lat[i] > top)
318 while (j < d_lat_length - 1 && d_lat[j] < bottom)
322 latitude_index_top = i;
324 latitude_index_top = (i + 1) < d_lat_length - 1 ? i + 1 : d_lat_length - 1;
326 if (d_lat[j] == bottom)
327 latitude_index_bottom = j;
329 latitude_index_bottom = (j - 1) > 0 ? j - 1 : 0;
338 return d_lat[0] >= d_lat[d_lat_length - 1] ? normal : inverted;
344 swap_vector_ends(
char *dest,
char *src,
int len,
int index,
int elem_sz)
346 memcpy(dest, src + index * elem_sz, (len - index) * elem_sz);
348 memcpy(dest + (len - index) * elem_sz, src, index * elem_sz);
352 static void transpose(std::vector<std::vector<T> > a,
353 std::vector<std::vector<T> > b,
int width,
int height)
355 for (
int i = 0; i < width; i++) {
356 for (
int j = 0; j < height; j++) {
369 void GeoConstraint::transpose_vector(
double *src,
const int length)
371 double *tmp =
new double[length];
373 int i = 0, j = length-1;
377 memcpy(src, tmp,length *
sizeof(
double));
383 count_size_except_latitude_and_longitude(
Array &a)
395 void GeoConstraint::flip_latitude_within_array(
Array &a,
int lat_length,
400 d_array_data =
static_cast<char*
>(a.
value());
401 d_array_data_size = a.
width();
404 int size = count_size_except_latitude_and_longitude(a);
405 char *tmp_data =
new char[d_array_data_size];
406 int array_elem_size = a.
var()->
width();
407 int lat_lon_size = (d_array_data_size / size);
409 DBG(cerr <<
"lat, lon_length: " << lat_length <<
", " << lon_length << endl);
410 DBG(cerr <<
"size: " << size << endl);
411 DBG(cerr <<
"d_array_data_size: " << d_array_data_size << endl);
412 DBG(cerr <<
"array_elem_size: " << array_elem_size<< endl);
413 DBG(cerr <<
"lat_lon_size: " << lat_lon_size<< endl);
415 for (
int i = 0; i < size; ++i) {
417 int s_lat = lat_length - 1;
419 int lon_size = array_elem_size * lon_length;
420 int offset = i * lat_lon_size;
422 memcpy(tmp_data + offset + (lat++ * lon_size),
423 d_array_data + offset + (s_lat-- * lon_size),
427 memcpy(d_array_data, tmp_data, d_array_data_size);
439 void GeoConstraint::reorder_longitude_map(
int longitude_index_left)
441 double *tmp_lon =
new double[d_lon_length];
443 swap_vector_ends((
char *) tmp_lon, (
char *) d_lon, d_lon_length,
444 longitude_index_left,
sizeof(
double));
446 memcpy(d_lon, tmp_lon, d_lon_length *
sizeof(
double));
452 count_dimensions_except_longitude(
Array &a)
481 if (!is_longitude_rightmost())
482 throw Error(
"This grid does not have Longitude as its rightmost dimension, the geogrid()\ndoes not support constraints that wrap around the edges of this type of grid.");
484 DBG(cerr <<
"Constraint for the left half: " << get_longitude_index_left()
485 <<
", " << get_lon_length() - 1 << endl);
489 get_lon_length() - 1);
495 int left_size = a.
width();
496 char *left_data = (
char*)a.
value();
504 DBG(cerr <<
"Constraint for the right half: " << 0
505 <<
", " << get_longitude_index_right() << endl);
512 char *right_data = (
char*)a.
value();
513 int right_size = a.
width();
516 d_array_data_size = left_size + right_size;
517 d_array_data =
new char[d_array_data_size];
523 int left_row_size = (get_lon_length() - get_longitude_index_left()) * elem_size;
524 int right_row_size = (get_longitude_index_right() + 1) * elem_size;
525 int total_bytes_per_row = left_row_size + right_row_size;
527 DBG2(cerr <<
"elem_size: " << elem_size <<
"; left & right size: " 528 << left_row_size <<
", " << right_row_size << endl);
532 int rows_to_copy = count_dimensions_except_longitude(a);
533 for (
int i = 0; i < rows_to_copy; ++i) {
534 DBG(cerr <<
"Copying " << i <<
"th row" << endl);
535 DBG(cerr <<
"left memcpy: " << *(
float *)(left_data + (left_row_size * i)) << endl);
537 memcpy(d_array_data + (total_bytes_per_row * i),
538 left_data + (left_row_size * i),
541 DBG(cerr <<
"right memcpy: " << *(
float *)(right_data + (right_row_size * i)) << endl);
543 memcpy(d_array_data + (total_bytes_per_row * i) + left_row_size,
544 right_data + (right_row_size * i),
554 GeoConstraint::GeoConstraint()
555 : d_array_data(0), d_array_data_size(0),
557 d_bounding_box_set(false),
558 d_longitude_rightmost(false),
559 d_longitude_notation(unknown_notation),
560 d_latitude_sense(unknown_sense)
563 d_coards_lat_units.insert(
"degrees_north");
564 d_coards_lat_units.insert(
"degree_north");
565 d_coards_lat_units.insert(
"degree_N");
566 d_coards_lat_units.insert(
"degrees_N");
568 d_coards_lon_units.insert(
"degrees_east");
569 d_coards_lon_units.insert(
"degree_east");
570 d_coards_lon_units.insert(
"degrees_E");
571 d_coards_lon_units.insert(
"degree_E");
573 d_lat_names.insert(
"COADSY");
574 d_lat_names.insert(
"lat");
575 d_lat_names.insert(
"Lat");
576 d_lat_names.insert(
"LAT");
578 d_lon_names.insert(
"COADSX");
579 d_lon_names.insert(
"lon");
580 d_lon_names.insert(
"Lon");
581 d_lon_names.insert(
"LON");
595 double bottom,
double right)
600 if (d_bounding_box_set)
601 throw Error(
"It is not possible to register more than one geographical constraint on a variable.");
607 throw Error(
"geogrid() does not currently work with inverted data (data where the north pole is at a negative latitude value).");
614 if (d_longitude_notation ==
neg_pos)
623 if (longitude_notation ==
neg_pos)
627 throw Error(
"The bounding box does not intersect any data within this Grid or Array. The\ngeographical extent of these data are from latitude " 632 +
" while the bounding box provided was latitude " 643 d_latitude_index_top, d_latitude_index_bottom);
648 d_longitude_index_right);
650 DBG(cerr <<
"Bounding box (tlbr): " << d_latitude_index_top <<
", " 651 << d_longitude_index_left <<
", " 652 << d_latitude_index_bottom <<
", " 653 << d_longitude_index_right << endl);
655 d_bounding_box_set =
true;
virtual bool read()
Read data into a local buffer.
virtual void add_constraint(Dim_iter i, int start, int stride, int stop)
Adds a constraint to an Array dimension.
void find_longitude_indeces(double left, double right, int &longitude_index_left, int &longitude_index_right) const
virtual void set_read_p(bool state)
Indicates that the data is ready to send.
virtual unsigned int width()=0
Returns the size of the class instance data.
void set_bounding_box(double top, double left, double bottom, double right)
bool unit_or_name_match(set< string > units, set< string > names, const string &var_units, const string &var_name)
Notation categorize_notation(const double left, const double right) const
virtual bool is_bounding_box_valid(const double left, const double top, const double right, const double bottom) const
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
virtual void transform_longitude_to_pos_notation()
virtual int dimension_size(Dim_iter i, bool constrained=false)
Returns the size of the dimension.
std::vector< dimension >::iterator Dim_iter
virtual void value(dods_byte *b) const
Get a copy of the data held by this variable. Read data from this variable's internal storage and loa...
void find_latitude_indeces(double top, double bottom, LatitudeSense sense, int &latitude_index_top, int &latitude_index_bottom) const
string double_to_string(const double &num)
void transform_constraint_to_pos_notation(double &left, double &right) const
virtual unsigned int width()
Returns the width of the data, in bytes.
virtual LatitudeSense categorize_latitude() const
A class for error processing.
A multidimensional array of identical data types.
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.