bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
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 <libdap/BaseType.h>
33#include <libdap/Int32.h>
34#include <libdap/Str.h>
35#include <libdap/Array.h>
36#include <libdap/Structure.h>
37
38#include <libdap/D4RValue.h>
39#include <libdap/Error.h>
40#include <libdap/debug.h>
41#include <libdap/util.h>
42#include <libdap/ServerFunctionsList.h>
43
44#include "BBoxUnionFunction.h"
45#include "roi_util.h"
46
47using namespace std;
48using namespace libdap;
49
50namespace functions {
51
71void
72function_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
173BaseType *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