bes Updated for version 3.20.13
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 <libdap/BaseType.h>
30#include <libdap/Str.h>
31#include <libdap/Array.h>
32#include <libdap/Grid.h>
33#include <libdap/Error.h>
34#include <libdap/DDS.h>
35#include <libdap/debug.h>
36#include <libdap/util.h>
37
38#include "GeoGridFunction.h"
39#include "GridGeoConstraint.h"
40#include "gse_parser.h"
41#include "grid_utils.h"
42
43using namespace libdap;
44
45namespace functions {
46
81void
82function_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
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
bool canOperateOn(libdap::DDS &dds)