36 #include <Structure.h> 42 #include <ServerFunctionsList.h> 46 #include "BBoxFunction.h" 54 #define UNWIND_BBOX_CODE 1 57 using namespace libdap;
86 function_dap2_bbox(
int argc, BaseType *argv[], DDS &, BaseType **btpp)
88 const string wrong_args =
"Wrong number of arguments to bbox(). Expected an Array and minimum and maximum values (3 arguments)";
92 throw Error(malformed_expr, wrong_args);
97 throw Error(malformed_expr, wrong_args);
100 if (argv[0] && argv[0]->type() != dods_array_c)
101 throw Error(
"In function bbox(): Expected argument 1 to be an Array.");
102 if (!argv[0]->var()->is_simple_type() || argv[0]->var()->type() == dods_str_c || argv[0]->var()->type() == dods_url_c)
103 throw Error(
"In function bbox(): Expected argument 1 to be an Array of numeric types.");
106 Array *the_array = static_cast<Array*>(argv[0]);
107 BESDEBUG(
"bbox",
"the_array: " << the_array->name() <<
": " << (
void*)the_array << endl);
111 the_array->set_read_p(
true);
114 vector<double> the_values;
115 extract_double_array(the_array, the_values);
117 double min_value = extract_double_value(argv[1]);
118 double max_value = extract_double_value(argv[2]);
121 unsigned int rank = the_array->dimensions();
122 auto_ptr<Array> response = roi_bbox_build_empty_bbox(rank, the_array->name());
128 unsigned int X = the_array->dimension_size(the_array->dim_begin());
130 bool found_start =
false;
131 unsigned int start = 0;
132 for (
unsigned int i = 0; i < X && !found_start; ++i) {
133 if (the_values[i] >= min_value && the_values[i] <= max_value) {
141 ostringstream oss(
"In function bbox(): No values between ", std::ios::ate);
142 oss << min_value <<
" and " << max_value <<
" were found in the array '" << the_array->name() <<
"'";
143 throw Error(oss.str());
146 bool found_stop =
false;
147 unsigned int stop = X-1;
148 for (
int i = X - 1; i >= 0 && !found_stop; --i) {
149 if (the_values[i] >= min_value && the_values[i] <= max_value) {
150 stop = (
unsigned int)i;
157 throw InternalErr(__FILE__, __LINE__,
"In BBoxFunction: Found start but not stop.");
159 Structure *slice = roi_bbox_build_slice(start, stop, the_array->dimension_name(the_array->dim_begin()));
160 response->set_vec_nocopy(0, slice);
168 Array::Dim_iter rows = the_array->dim_begin(), cols = the_array->dim_begin()+1;
169 unsigned int Y = the_array->dimension_size(rows);
170 unsigned int X = the_array->dimension_size(cols);
172 unsigned int x_start = X-1;
173 unsigned int y_start = 0;
174 bool found_y_start =
false;
176 for (
unsigned int j = 0; j < Y; ++j) {
177 bool found_x_start =
false;
179 for (
unsigned int i = 0; i < X && !found_x_start; ++i) {
180 unsigned int ind = j * X + i;
181 if (the_values[ind] >= min_value && the_values[ind] <= max_value) {
182 x_start = min(i, x_start);
183 found_x_start =
true;
184 if (!found_y_start) {
186 found_y_start =
true;
193 if (!found_y_start) {
194 ostringstream oss(
"In function bbox(): No values between ", std::ios::ate);
195 oss << min_value <<
" and " << max_value <<
" were found in the array '" << the_array->name() <<
"'";
196 throw Error(oss.str());
199 unsigned int x_stop = 0;
200 unsigned int y_stop = 0;
201 bool found_y_stop =
false;
203 for (
int j = Y - 1; j >= (int)y_start; --j) {
204 bool found_x_stop =
false;
206 for (
int i = X - 1; i >= 0 && !found_x_stop; --i) {
207 unsigned int ind = j * X + i;
208 if (the_values[ind] >= min_value && the_values[ind] <= max_value) {
209 x_stop = max((
unsigned int)i, x_stop);
221 throw InternalErr(__FILE__, __LINE__,
"In BBoxFunction: Found start but not stop.");
223 response->set_vec_nocopy(0, roi_bbox_build_slice(y_start, y_stop, the_array->dimension_name(rows)));
224 response->set_vec_nocopy(1, roi_bbox_build_slice(x_start, x_stop, the_array->dimension_name(cols)));
229 Odometer::shape shape(rank);
231 for (Array::Dim_iter i = the_array->dim_begin(), e = the_array->dim_end(); i != e; ++i) {
232 shape.at(j++) = the_array->dimension_size(i);
234 Odometer odometer(shape);
236 Odometer::shape indices(rank);
237 Odometer::shape min = shape;
238 Odometer::shape max(rank, 0);
241 if (the_values[odometer.offset()] >= min_value && the_values[odometer.offset()] <= max_value) {
243 odometer.indices(indices);
244 Odometer::shape::iterator m = min.begin();
245 Odometer::shape::iterator x = max.begin();
247 for (Odometer::shape::iterator i = indices.begin(), e = indices.end(); i != e; ++i, ++m, ++x) {
248 if (*i < *m) *m = *i;
249 if (*i > *x) *x = *i;
252 }
while (odometer.next() != odometer.end());
257 if (min[0] == shape[0]) {
258 ostringstream oss(
"In function bbox(): No values between ", std::ios::ate);
259 oss << min_value <<
" and " << max_value <<
" were found in the array '" << the_array->name() <<
"'";
260 throw Error(oss.str());
263 Odometer::shape::iterator m = min.begin();
264 Odometer::shape::iterator x = max.begin();
265 Array::Dim_iter d = the_array->dim_begin();
266 for (
unsigned int i = 0; i < rank; ++i, ++m, ++x, ++d) {
267 response->set_vec_nocopy(i, roi_bbox_build_slice(*m, *x, the_array->dimension_name(d)));
273 response->set_read_p(
true);
274 response->set_send_p(
true);
276 *btpp = response.release();
291 BaseType *function_dap4_bbox(D4RValueList * , DMR & )
293 throw Error(malformed_expr,
"Not yet implemented for DAP4 functions.");