OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BBoxUnionFunction.cc
Go to the documentation of this file.
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of bes, A C++ implementation of the OPeNDAP
5 // Hyrax data server
6 
7 // Copyright (c) 2015 OPeNDAP, Inc.
8 // Authors: James Gallagher <jgallagher@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 #include "config.h"
27 
28 #include <cassert>
29 #include <sstream>
30 #include <memory>
31 
32 #include <BaseType.h>
33 #include <Int32.h>
34 #include <Str.h>
35 #include <Array.h>
36 #include <Structure.h>
37 
38 #include <D4RValue.h>
39 #include <Error.h>
40 #include <debug.h>
41 #include <util.h>
42 #include <ServerFunctionsList.h>
43 
44 #include "BBoxUnionFunction.h"
45 #include "roi_utils.h"
46 
47 using namespace std;
48 
49 namespace libdap {
50 
70 void
71 function_dap2_bbox_union(int argc, BaseType *argv[], DDS &, BaseType **btpp)
72 {
73  const string wrong_args = "Wrong number of arguments to bbox_union(). Expected one or more bounding boxes and a string naming the operation (2+ arguments)";
74 
75  unsigned int rank = 0;
76  string operation = "";
77 
78  switch (argc) {
79  case 0:
80  case 1:
81  // Must have 2 or more arguments
82  throw Error(malformed_expr, wrong_args);
83 
84  default:
85  // Vet the input: All bbox variables must be the same shape
86  rank = roi_valid_bbox(argv[0]); // throws if bbox is not valid
87 
88  // Actually, we could us names to form the unions - they don't
89  // really have to be the same shape, but this will do for now.
90  for (int i = 1; i < argc-1; ++i)
91  if (roi_valid_bbox(argv[0]) != rank)
92  throw Error(malformed_expr, "In function bbox_union(): All bounding boxes must be the same shape to form their union.");
93 
94  operation = extract_string_argument(argv[argc-1]);
95  downcase(operation);
96  break;
97  }
98 
99  // For each BBox, for each dimension, update the union,
100  // using the first BBox as a starting point.
101 
102  // Initialize a local data structure - used because it's much
103  // easier to read and write this than the DAP variables.
104  vector<slice> result(rank); // struct slice is defined in roi_utils.h
105 
106  for (unsigned int i = 0; i < rank; ++i) {
107  int start, stop;
108  string name;
109  // start, stop, name are value-result parameters; we know they are Array*
110  // because of the roi_valid_bbox() test.
111  roi_bbox_get_slice_data(static_cast<Array*>(argv[0]), i, start, stop, name);
112 
113  result.at(i).start = start;
114  result.at(i).stop = stop;
115  result.at(i).name = name;
116  }
117 
118  // For each BBox, for each dimension...
119  for (int i = 1; i < argc-1; ++i) {
120  // cast is safe given the tests above
121  Array *bbox = static_cast<Array*>(argv[i]);
122 
123  for (unsigned int i = 0; i < rank; ++i) {
124  int start, stop;
125  string name;
126  // start, stop, name are value-result parameters
127  roi_bbox_get_slice_data(bbox, i, start, stop, name);
128 
129  if (result.at(i).name != name)
130  throw Error("In function bbox_union(): named dimensions must match in the bounding boxes");
131 
132  if (operation == "union") {
133  result.at(i).start = min(result.at(i).start, start);
134  result.at(i).stop = max(result.at(i).stop, stop);
135  }
136  else if (operation == "inter" || operation == "intersection") {
137  result.at(i).start = max(result.at(i).start, start);
138  result.at(i).stop = min(result.at(i).stop, stop);
139 
140  if (result.at(i).stop < result.at(i).start)
141  throw Error("In bbox_union(): The intersection of the bounding boxes is empty (dimension " + long_to_string(i) + ").");
142  }
143  else {
144  throw Error(malformed_expr, "In bbox_union(): Unknown operator '" + operation + "'; expected 'union', 'intersection' or 'inter'.");
145  }
146  }
147  }
148 
149  // Build the response; name the result after the operation
150  auto_ptr<Array> response = roi_bbox_build_empty_bbox(rank, operation);
151  for (unsigned int i = 0; i < rank; ++i) {
152  Structure *slice = roi_bbox_build_slice(result.at(i).start, result.at(i).stop, result.at(i).name);
153  response->set_vec_nocopy(i, slice);
154  }
155 
156  // Return the result
157  *btpp = response.release();
158  return;
159 }
160 
172 BaseType *function_dap4_bbox_union(D4RValueList *, DMR &)
173 {
174  //auto_ptr<Array> response(new Array("bbox", new Structure("bbox")));
175 
176  throw Error(malformed_expr, "Not yet implemented for DAP4 functions.");
177 
178  return 0; //response.release();
179 }
180 
181 } // namesspace libdap
void roi_bbox_get_slice_data(Array *slices, unsigned int i, int &start, int &stop, string &name)
This method extracts values from one element of the Bounding Box (i.e., Array of Structures).
Definition: roi_utils.cc:122
STL namespace.
BaseType * function_dap4_bbox_union(D4RValueList *, DMR &)
Combine several bounding boxes, forming their union.
unsigned int roi_valid_bbox(BaseType *btp)
Is the bound box valid?
Definition: roi_utils.cc:90
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.
Definition: roi_utils.cc:153
static class NCMLUtil overview
auto_ptr< Array > roi_bbox_build_empty_bbox(unsigned int num_dim, const string &bbox_name)
Build an empty Bounding Box using DAP variables.
Definition: roi_utils.cc:192
#define min(a, b)
Definition: os_utils.h:71
void function_dap2_bbox_union(int argc, BaseType *argv[], DDS &, BaseType **btpp)
Combine several bounding boxes, forming their union.
#define max(a, b)
Definition: os_utils.h:67