OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
GeoGridFunction.cc
Go to the documentation of this file.
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
5 // Access Protocol.
6 
7 // Copyright (c) 2003,2013 OPeNDAP, Inc.
8 // Authors: Nathan Potter <npotter@opendap.org>
9 // James Gallagher <jgallagher@opendap.org>
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26 
27 #include "config.h"
28 
29 #include <BaseType.h>
30 #include <Str.h>
31 #include <Array.h>
32 #include <Grid.h>
33 #include <Error.h>
34 #include <DDS.h>
35 #include <debug.h>
36 #include <util.h>
37 
38 #include "GeoGridFunction.h"
39 #include "GridGeoConstraint.h"
40 #include "gse_parser.h"
41 #include "grid_utils.h"
42 
43 namespace libdap {
44 
79 void
80 function_geogrid(int argc, BaseType *argv[], DDS &, BaseType **btpp)
81 {
82  string info =
83  string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
84  "<function name=\"geogrid\" version=\"1.2\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#geogrid\">\n"+
85  "</function>";
86 
87  if (argc == 0) {
88  Str *response = new Str("version");
89  response->set_value(info);
90  *btpp = response;
91  return ;
92  }
93 
94  // There are two main forms of this function, one that takes a Grid and one
95  // that takes a Grid and two Arrays. The latter provides a way to explicitly
96  // tell the function which maps contain lat and lon data. The remaining
97  // arguments are the same for both versions, although that includes a
98  // varying argument list.
99 
100  // Look at the types of the first three arguments to determine which of the
101  // two forms were used to call this function.
102  Grid *l_grid = 0;
103  if (argc < 1 || !(l_grid = dynamic_cast < Grid * >(argv[0]->ptr_duplicate())))
104  throw Error(malformed_expr,"The first argument to geogrid() must be a Grid variable!");
105 
106  // Both forms require at least this many args
107  if (argc < 5)
108  throw Error(malformed_expr,"Wrong number of arguments to geogrid() (expected at least 5 args). See geogrid() for more information.");
109 
110  bool grid_lat_lon_form;
111  Array *l_lat = 0;
112  Array *l_lon = 0;
113  if (!(l_lat = dynamic_cast < Array * >(argv[1]))) //->ptr_duplicate())))
114  grid_lat_lon_form = false;
115  else if (!(l_lon = dynamic_cast < Array * >(argv[2]))) //->ptr_duplicate())))
116  throw Error(malformed_expr,"When using the Grid, Lat, Lon form of geogrid() both the lat and lon maps must be given (lon map missing)!");
117  else
118  grid_lat_lon_form = true;
119 
120  if (grid_lat_lon_form && argc < 7)
121  throw Error(malformed_expr,"Wrong number of arguments to geogrid() (expected at least 7 args). See geogrid() for more information.");
122 
123 #if 0
124  Grid *l_grid = dynamic_cast < Grid * >(argv[0]->ptr_duplicate());
125  if (!l_grid)
126  throw Error(malformed_expr,"The first argument to geogrid() must be a Grid variable!");
127 #endif
128  // Read the maps. Do this before calling parse_gse_expression(). Avoid
129  // reading the array until the constraints have been applied because it
130  // might be really large.
131  //
132  // Trick: Some handlers build Grids from a combination of Array
133  // variables and attributes. Those handlers (e.g., hdf4) use the send_p
134  // property to determine which parts of the Grid to read *but they can
135  // only read the maps from within Grid::read(), not the map's read()*.
136  // Since the Grid's array does not have send_p set, it will not be read
137  // by the call below to Grid::read().
138  Grid::Map_iter i = l_grid->map_begin();
139  while (i != l_grid->map_end())
140  (*i++)->set_send_p(true);
141 
142  l_grid->read();
143  // Calling read() above sets the read_p flag for the entire grid; clear it
144  // for the grid's array so that later on the code will be sure to read it
145  // under all circumstances.
146  l_grid->get_array()->set_read_p(false);
147 
148  // Look for Grid Selection Expressions tacked onto the end of the BB
149  // specification. If there are any, evaluate them before evaluating the BB.
150  int min_arg_count = (grid_lat_lon_form) ? 7 : 5;
151  if (argc > min_arg_count) {
152  // argv[5..n] holds strings; each are little Grid Selection Expressions
153  // to be parsed and evaluated.
154  vector < GSEClause * > clauses;
155  gse_arg *arg = new gse_arg(l_grid);
156  for (int i = min_arg_count; i < argc; ++i) {
157  parse_gse_expression(arg, argv[i]);
158  clauses.push_back(arg->get_gsec());
159  }
160  delete arg;
161  arg = 0;
162 
163  apply_grid_selection_expressions(l_grid, clauses);
164  }
165 
166  try {
167  // Build a GeoConstraint object. If there are no longitude/latitude
168  // maps then this constructor throws Error.
169  GridGeoConstraint gc(l_grid);
170 
171  // This sets the bounding box and modifies the maps to match the
172  // notation of the box (0/359 or -180/179)
173  int box_index_offset = (grid_lat_lon_form) ? 3 : 1;
174  double top = extract_double_value(argv[box_index_offset]);
175  double left = extract_double_value(argv[box_index_offset + 1]);
176  double bottom = extract_double_value(argv[box_index_offset + 2]);
177  double right = extract_double_value(argv[box_index_offset + 3]);
178  gc.set_bounding_box(top, left, bottom, right);
179  DBG(cerr << "geogrid: past bounding box set" << endl);
180 
181  // This also reads all of the data into the grid variable
183  DBG(cerr << "geogrid: past apply constraint" << endl);
184 
185  // In this function the l_grid pointer is the same as the pointer returned
186  // by this call. The caller of the function must free the pointer.
187  *btpp = gc.get_constrained_grid();
188  return;
189  }
190  catch (Error &e) {
191  throw e;
192  }
193  catch (exception & e) {
194  throw
195  InternalErr(string
196  ("A C++ exception was thrown from inside geogrid(): ")
197  + e.what());
198  }
199 }
200 
201 
209 {
210  bool usable = false;
211 
212  // Go find all the Grid variables.
213  //vector<Grid *> *grids = new vector<Grid *>();
214  vector<Grid*> grids;
215  getGrids(dds, &grids);
216 
217  // Were there any?
218  if(!grids.empty()){
219  // Apparently so...
220 
221  // See if any one of them looks like suitable GeoGrid
222  vector<Grid *>::iterator git;
223  for(git=grids.begin(); !usable && git!=grids.end() ; git++){
224  Grid *grid = *git;
225  usable = isGeoGrid(grid);
226  }
227  }
228  //delete grids;
229 
230  return usable;
231 }
232 
233 } // namesspace libdap
void getGrids(BaseType *bt, vector< Grid * > *grids)
Recursively traverses the BaseType bt (if its a constructor type) and collects pointers to all of the...
Definition: grid_utils.cc:54
void apply_grid_selection_expressions(Grid *grid, vector< GSEClause * >clauses)
Definition: grid_utils.cc:166
GSEClause * get_gsec()
Definition: gse_parser.h:60
bool isGeoGrid(Grid *grid)
Evaluates a Grid to see if has suitable semantics for use with function_geogrid.
Definition: grid_utils.cc:104
void set_bounding_box(double top, double left, double bottom, double right)
Set the bounding box for this constraint.
virtual Grid * get_constrained_grid() const
Argument to the GSE parser.
Definition: gse_parser.h:43
bool canOperateOn(DDS &dds)
The passed DDS parameter dds is evaluated to see if it contains Grid objects whose semantics allow th...
#define gse_arg(arg)
Definition: gse.tab.cc:121
gse_arg * arg
Definition: gse.tab.cc:714
void parse_gse_expression(gse_arg *arg, BaseType *expr)
Definition: grid_utils.cc:116
void function_geogrid(int argc, BaseType *argv[], DDS &, BaseType **btpp)
The geogrid function returns the part of a Grid which includes a geographically specified rectangle...
Geographical constraint applied to a grid.
virtual void apply_constraint_to_data()
Once the bounding box is set use this method to apply the constraint.