bes  Updated for version 3.20.6
BBoxUnionFunction.cc
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_util.h"
46 
47 using namespace std;
48 using namespace libdap;
49 
50 namespace functions {
51 
71 void
72 function_dap2_bbox_union(int argc, BaseType *argv[], DDS &, BaseType **btpp)
73 {
74  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)";
75 
76  unsigned int rank = 0;
77  string operation = "";
78 
79  switch (argc) {
80  case 0:
81  case 1:
82  // Must have 2 or more arguments
83  throw Error(malformed_expr, wrong_args);
84 
85  default:
86  // Vet the input: All bbox variables must be the same shape
87  rank = roi_valid_bbox(argv[0]); // throws if bbox is not valid
88 
89  // Actually, we could us names to form the unions - they don't
90  // really have to be the same shape, but this will do for now.
91  for (int i = 1; i < argc-1; ++i)
92  if (roi_valid_bbox(argv[0]) != rank)
93  throw Error(malformed_expr, "In function bbox_union(): All bounding boxes must be the same shape to form their union.");
94 
95  operation = extract_string_argument(argv[argc-1]);
96  downcase(operation);
97  break;
98  }
99 
100  // For each BBox, for each dimension, update the union,
101  // using the first BBox as a starting point.
102 
103  // Initialize a local data structure - used because it's much
104  // easier to read and write this than the DAP variables.
105  vector<slice> result(rank); // struct slice is defined in roi_utils.h
106 
107  for (unsigned int i = 0; i < rank; ++i) {
108  int start, stop;
109  string name;
110  // start, stop, name are value-result parameters; we know they are Array*
111  // because of the roi_valid_bbox() test.
112  roi_bbox_get_slice_data(static_cast<Array*>(argv[0]), i, start, stop, name);
113 
114  result.at(i).start = start;
115  result.at(i).stop = stop;
116  result.at(i).name = name;
117  }
118 
119  // For each BBox, for each dimension...
120  for (int i = 1; i < argc-1; ++i) {
121  // cast is safe given the tests above
122  Array *bbox = static_cast<Array*>(argv[i]);
123 
124  for (unsigned int i = 0; i < rank; ++i) {
125  int start, stop;
126  string name;
127  // start, stop, name are value-result parameters
128  roi_bbox_get_slice_data(bbox, i, start, stop, name);
129 
130  if (result.at(i).name != name)
131  throw Error("In function bbox_union(): named dimensions must match in the bounding boxes");
132 
133  if (operation == "union") {
134  result.at(i).start = min(result.at(i).start, start);
135  result.at(i).stop = max(result.at(i).stop, stop);
136  }
137  else if (operation == "inter" || operation == "intersection") {
138  result.at(i).start = max(result.at(i).start, start);
139  result.at(i).stop = min(result.at(i).stop, stop);
140 
141  if (result.at(i).stop < result.at(i).start)
142  throw Error("In bbox_union(): The intersection of the bounding boxes is empty (dimension " + long_to_string(i) + ").");
143  }
144  else {
145  throw Error(malformed_expr, "In bbox_union(): Unknown operator '" + operation + "'; expected 'union', 'intersection' or 'inter'.");
146  }
147  }
148  }
149 
150  // Build the response; name the result after the operation
151  unique_ptr<Array> response = roi_bbox_build_empty_bbox(rank, operation);
152  for (unsigned int i = 0; i < rank; ++i) {
153  Structure *slice = roi_bbox_build_slice(result.at(i).start, result.at(i).stop, result.at(i).name);
154  response->set_vec_nocopy(i, slice);
155  }
156 
157  // Return the result
158  *btpp = response.release();
159  return;
160 }
161 
173 BaseType *function_dap4_bbox_union(D4RValueList *, DMR &)
174 {
175  //auto_ptr<Array> response(new Array("bbox", new Structure("bbox")));
176 
177  throw Error(malformed_expr, "Not yet implemented for DAP4 functions.");
178 
179  return 0; //response.release();
180 }
181 
182 } // namesspace functions
libdap
Definition: BESDapFunctionResponseCache.h:35
Error