libdap  Updated for version 3.20.6
libdap4 is an implementation of OPeNDAP's DAP protocol.
GeoGridFunction.cc
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 using namespace libdap;
44 
45 namespace functions {
46 
81 void
82 function_geogrid(int argc, BaseType *argv[], DDS &, BaseType **btpp)
83 {
84  string info =
85  string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
86  "<function name=\"geogrid\" version=\"1.2\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#geogrid\">\n"+
87  "</function>";
88 
89  if (argc == 0) {
90  Str *response = new Str("version");
91  response->set_value(info);
92  *btpp = response;
93  return ;
94  }
95 
96  // There are two main forms of this function, one that takes a Grid and one
97  // that takes a Grid and two Arrays. The latter provides a way to explicitly
98  // tell the function which maps contain lat and lon data. The remaining
99  // arguments are the same for both versions, although that includes a
100  // varying argument list.
101 
102  // Look at the types of the first three arguments to determine which of the
103  // two forms were used to call this function.
104  Grid *l_grid = 0;
105  if (argc < 1 || !(l_grid = dynamic_cast < Grid * >(argv[0]->ptr_duplicate())))
106  throw Error(malformed_expr,"The first argument to geogrid() must be a Grid variable!");
107 
108  // Both forms require at least this many args
109  if (argc < 5)
110  throw Error(malformed_expr,"Wrong number of arguments to geogrid() (expected at least 5 args). See geogrid() for more information.");
111 
112  bool grid_lat_lon_form;
113  Array *l_lat = 0;
114  Array *l_lon = 0;
115  if (!(l_lat = dynamic_cast < Array * >(argv[1]))) //->ptr_duplicate())))
116  grid_lat_lon_form = false;
117  else if (!(l_lon = dynamic_cast < Array * >(argv[2]))) //->ptr_duplicate())))
118  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)!");
119  else
120  grid_lat_lon_form = true;
121 
122  if (grid_lat_lon_form && argc < 7)
123  throw Error(malformed_expr,"Wrong number of arguments to geogrid() (expected at least 7 args). See geogrid() for more information.");
124 
125 #if 0
126  Grid *l_grid = dynamic_cast < Grid * >(argv[0]->ptr_duplicate());
127  if (!l_grid)
128  throw Error(malformed_expr,"The first argument to geogrid() must be a Grid variable!");
129 #endif
130  // Read the maps. Do this before calling parse_gse_expression(). Avoid
131  // reading the array until the constraints have been applied because it
132  // might be really large.
133  //
134  // Trick: Some handlers build Grids from a combination of Array
135  // variables and attributes. Those handlers (e.g., hdf4) use the send_p
136  // property to determine which parts of the Grid to read *but they can
137  // only read the maps from within Grid::read(), not the map's read()*.
138  // Since the Grid's array does not have send_p set, it will not be read
139  // by the call below to Grid::read().
140  Grid::Map_iter i = l_grid->map_begin();
141  while (i != l_grid->map_end())
142  (*i++)->set_send_p(true);
143 
144  l_grid->read();
145  // Calling read() above sets the read_p flag for the entire grid; clear it
146  // for the grid's array so that later on the code will be sure to read it
147  // under all circumstances.
148  l_grid->get_array()->set_read_p(false);
149 
150  // Look for Grid Selection Expressions tacked onto the end of the BB
151  // specification. If there are any, evaluate them before evaluating the BB.
152  int min_arg_count = (grid_lat_lon_form) ? 7 : 5;
153  if (argc > min_arg_count) {
154  // argv[5..n] holds strings; each are little Grid Selection Expressions
155  // to be parsed and evaluated.
156  vector < GSEClause * > clauses;
157  gse_arg *arg = new gse_arg(l_grid);
158  for (int i = min_arg_count; i < argc; ++i) {
159  parse_gse_expression(arg, argv[i]);
160  clauses.push_back(arg->get_gsec());
161  }
162  delete arg;
163  arg = 0;
164 
165  apply_grid_selection_expressions(l_grid, clauses);
166  }
167 
168  try {
169  // Build a GeoConstraint object. If there are no longitude/latitude
170  // maps then this constructor throws Error.
171  GridGeoConstraint gc(l_grid);
172 
173  // This sets the bounding box and modifies the maps to match the
174  // notation of the box (0/359 or -180/179)
175  int box_index_offset = (grid_lat_lon_form) ? 3 : 1;
176  double top = extract_double_value(argv[box_index_offset]);
177  double left = extract_double_value(argv[box_index_offset + 1]);
178  double bottom = extract_double_value(argv[box_index_offset + 2]);
179  double right = extract_double_value(argv[box_index_offset + 3]);
180  gc.set_bounding_box(top, left, bottom, right);
181  DBG(cerr << "geogrid: past bounding box set" << endl);
182 
183  // This also reads all of the data into the grid variable
184  gc.apply_constraint_to_data();
185  DBG(cerr << "geogrid: past apply constraint" << endl);
186 
187  // In this function the l_grid pointer is the same as the pointer returned
188  // by this call. The caller of the function must free the pointer.
189  *btpp = gc.get_constrained_grid();
190  return;
191  }
192  catch (Error &e) {
193  throw e;
194  }
195  catch (exception & e) {
196  throw
197  InternalErr(string
198  ("A C++ exception was thrown from inside geogrid(): ")
199  + e.what());
200  }
201 }
202 
203 
210 bool GeoGridFunction::canOperateOn(DDS &dds)
211 {
212  bool usable = false;
213 
214  // Go find all the Grid variables.
215  //vector<Grid *> *grids = new vector<Grid *>();
216  vector<Grid*> grids;
217  get_grids(dds, &grids);
218 
219  // Were there any?
220  if(!grids.empty()){
221  // Apparently so...
222 
223  // See if any one of them looks like suitable GeoGrid
224  vector<Grid *>::iterator git;
225  for(git=grids.begin(); !usable && git!=grids.end() ; git++){
226  Grid *grid = *git;
227  usable = is_geo_grid(grid);
228  }
229  }
230  //delete grids;
231 
232  return usable;
233 }
234 
235 } // namesspace libdap
virtual void set_read_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:391
Map_iter map_end()
Definition: Grid.cc:537
top level DAP object to house generic methods
Definition: AISConnect.cc:30
A class for software fault reporting.
Definition: InternalErr.h:64
Holds character string data.
Definition: Str.h:62
Map_iter map_begin()
Returns an iterator referencing the first Map vector.
Definition: Grid.cc:525
virtual bool read()
simple implementation of read that iterates through vars and calls read on them
Definition: Constructor.cc:476
Holds the Grid data type.
Definition: Grid.h:122
virtual bool set_value(const string &value)
Definition: Str.cc:253
Array * get_array()
Returns the Grid Array. This method returns the array using an Array*, so no cast is required...
Definition: Grid.cc:518
double extract_double_value(BaseType *arg)
Definition: util.cc:402
virtual BaseType * ptr_duplicate()=0
The basic data type for the DODS DAP types.
Definition: BaseType.h:117
A class for error processing.
Definition: Error.h:92
A multidimensional array of identical data types.
Definition: Array.h:112