36 #include <Structure.h>
42 #include <ServerFunctionsList.h>
54 #define UNWIND_BBOX_CODE 1
87 const string wrong_args =
"Wrong number of arguments to bbox(). Expected an Array and minimum and maximum values (3 arguments)";
91 throw Error(malformed_expr, wrong_args);
96 throw Error(malformed_expr, wrong_args);
99 if (argv[0] && argv[0]->type() != dods_array_c)
100 throw Error(
"In function bbox(): Expected argument 1 to be an Array.");
101 if (!argv[0]->var()->is_simple_type() || argv[0]->var()->type() == dods_str_c || argv[0]->var()->type() == dods_url_c)
102 throw Error(
"In function bbox(): Expected argument 1 to be an Array of numeric types.");
105 Array *the_array =
static_cast<Array*
>(argv[0]);
106 BESDEBUG(
"bbox",
"the_array: " << the_array->name() <<
": " << (
void*)the_array << endl);
110 the_array->set_read_p(
true);
113 vector<double> the_values;
114 extract_double_array(the_array, the_values);
116 double min_value = extract_double_value(argv[1]);
117 double max_value = extract_double_value(argv[2]);
120 unsigned int rank = the_array->dimensions();
127 unsigned int X = the_array->dimension_size(the_array->dim_begin());
129 bool found_start =
false;
130 unsigned int start = 0;
131 for (
unsigned int i = 0; i < X && !found_start; ++i) {
132 if (the_values[i] >= min_value && the_values[i] <= max_value) {
140 ostringstream oss(
"In function bbox(): No values between ", std::ios::ate);
141 oss << min_value <<
" and " << max_value <<
" were found in the array '" << the_array->name() <<
"'";
142 throw Error(oss.str());
145 bool found_stop =
false;
146 unsigned int stop = X-1;
147 for (
int i = X - 1; i >= 0 && !found_stop; --i) {
148 if (the_values[i] >= min_value && the_values[i] <= max_value) {
149 stop = (
unsigned int)i;
156 throw InternalErr(__FILE__, __LINE__,
"In BBoxFunction: Found start but not stop.");
159 response->set_vec_nocopy(0, slice);
167 Array::Dim_iter rows = the_array->dim_begin(), cols = the_array->dim_begin()+1;
168 unsigned int Y = the_array->dimension_size(rows);
169 unsigned int X = the_array->dimension_size(cols);
171 unsigned int x_start = X-1;
172 unsigned int y_start = 0;
173 bool found_y_start =
false;
175 for (
unsigned int j = 0; j < Y; ++j) {
176 bool found_x_start =
false;
178 for (
unsigned int i = 0; i < X && !found_x_start; ++i) {
179 unsigned int ind = j * X + i;
180 if (the_values[ind] >= min_value && the_values[ind] <= max_value) {
181 x_start =
min(i, x_start);
182 found_x_start =
true;
183 if (!found_y_start) {
185 found_y_start =
true;
192 if (!found_y_start) {
193 ostringstream oss(
"In function bbox(): No values between ", std::ios::ate);
194 oss << min_value <<
" and " << max_value <<
" were found in the array '" << the_array->name() <<
"'";
195 throw Error(oss.str());
198 unsigned int x_stop = 0;
199 unsigned int y_stop = 0;
200 bool found_y_stop =
false;
202 for (
int j = Y - 1; j >= (int)y_start; --j) {
203 bool found_x_stop =
false;
205 for (
int i = X - 1; i >= 0 && !found_x_stop; --i) {
206 unsigned int ind = j * X + i;
207 if (the_values[ind] >= min_value && the_values[ind] <= max_value) {
208 x_stop =
max((
unsigned int)i, x_stop);
220 throw InternalErr(__FILE__, __LINE__,
"In BBoxFunction: Found start but not stop.");
222 response->set_vec_nocopy(0,
roi_bbox_build_slice(y_start, y_stop, the_array->dimension_name(rows)));
223 response->set_vec_nocopy(1,
roi_bbox_build_slice(x_start, x_stop, the_array->dimension_name(cols)));
230 for (Array::Dim_iter i = the_array->dim_begin(), e = the_array->dim_end(); i != e; ++i) {
231 shape.at(j++) = the_array->dimension_size(i);
240 if (the_values[odometer.
offset()] >= min_value && the_values[odometer.
offset()] <= max_value) {
243 Odometer::shape::iterator m = min.begin();
244 Odometer::shape::iterator x = max.begin();
246 for (Odometer::shape::iterator i = indices.begin(), e = indices.end(); i != e; ++i, ++m, ++x) {
247 if (*i < *m) *m = *i;
248 if (*i > *x) *x = *i;
251 }
while (odometer.
next() != odometer.
end());
256 if (min[0] == shape[0]) {
257 ostringstream oss(
"In function bbox(): No values between ", std::ios::ate);
258 oss << min_value <<
" and " << max_value <<
" were found in the array '" << the_array->name() <<
"'";
259 throw Error(oss.str());
262 Odometer::shape::iterator m = min.begin();
263 Odometer::shape::iterator x = max.begin();
264 Array::Dim_iter d = the_array->dim_begin();
265 for (
unsigned int i = 0; i < rank; ++i, ++m, ++x, ++d) {
272 response->set_read_p(
true);
273 response->set_send_p(
true);
275 *btpp = response.release();
292 throw Error(malformed_expr,
"Not yet implemented for DAP4 functions.");
void indices(shape &indices)
Return the current set of indices.
std::vector< unsigned int > shape
unsigned int end()
Return the sentinel value that indicates that the offset (returned by offset()) is at the end of the ...
Structure * roi_bbox_build_slice(unsigned int start_value, unsigned int stop_value, const string &dim_name)
Build a single element of a bounding box.
static class NCMLUtil overview
BaseType * function_dap4_bbox(D4RValueList *, DMR &)
Return the bounding box for an array.
auto_ptr< Array > roi_bbox_build_empty_bbox(unsigned int num_dim, const string &bbox_name)
Build an empty Bounding Box using DAP variables.
void function_dap2_bbox(int argc, BaseType *argv[], DDS &, BaseType **btpp)
Return the bounding box for an array.
unsigned int offset()
The offset into memory for the current element.
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Map the indices of a N-dimensional array to the offset into memory that matches those indices...
unsigned int next()
Increment the Odometer to the next element and return the offset value.