bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
DilateArrayFunction.cc
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4// Access Protocol.
5
6// Copyright (c) 2015 OPeNDAP, Inc.
7// Authors:
8// James Gallagher <jgallagher@opendap.org>
9// Dan Holloway <dholloway@opendap.org>
10//
11// This library is free software; you can redistribute it and/or
12// modify it under the terms of the GNU Lesser General Public
13// License as published by the Free Software Foundation; either
14// version 2.1 of the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24//
25// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26
27#include "config.h"
28
29#include <cassert>
30
31#include <sstream>
32#include <vector>
33
34#include <libdap/Type.h>
35#include <libdap/BaseType.h>
36#include <libdap/Byte.h>
37#include <libdap/Int16.h>
38#include <libdap/UInt16.h>
39#include <libdap/Int32.h>
40#include <libdap/UInt32.h>
41#include <libdap/Float32.h>
42#include <libdap/Float64.h>
43#include <libdap/Str.h>
44#include <libdap/Url.h>
45#include <libdap/Array.h>
46#include <libdap/Error.h>
47#include <libdap/DDS.h>
48
49#include <libdap/DMR.h>
50#include <libdap/D4Group.h>
51#include <libdap/D4RValue.h>
52
53#include <libdap/debug.h>
54#include <libdap/util.h>
55
56#include <libdap/BaseTypeFactory.h>
57
58#include <BESDebug.h>
59
60#include "DilateArrayFunction.h"
61#include "functions_util.h"
62
63using namespace libdap;
64
65namespace functions {
66
67string dilate_array_info =
68 string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
69 + "<function name=\"dilate_array\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#dilate_array\">\n"
70 + "</function>";
71
83void function_dilate_dap2_array(int argc, BaseType * argv[], DDS &/*dds*/, BaseType **btpp)
84{
85 if (argc == 0) {
86 Str *response = new Str("info");
87 response->set_value(dilate_array_info);
88 *btpp = response;
89 return;
90 }
91
92 BESDEBUG("functions", "function_dilate_dap2_array() - argc: " << argc << endl);
93
94 BaseType *btp = argv[0];
95
96 if (btp->type() != dods_array_c)
97 throw Error(malformed_expr, "dilate_array(): first argument must point to a Array variable.");
98
99 Array *mask = static_cast<Array*>(btp);
100 if (mask->var()->type() != dods_byte_c && mask->dimensions() == 2)
101 throw Error(malformed_expr, "dilate_array(): first argument must point to a Two dimensional Byte Array variable.");
102
103 // OK, we've got a valid 2D mask, now get the bytes into a vector.
104 vector<dods_byte> mask_values(mask->length());
105 mask->value(mask_values.data());
106
107 // Now make a vector<> for the result; I'm not sure if we really need this... jhrg 5/26/15
108 vector<dods_byte> dest_values(mask->length());
109
110 // read argv[1], the number of dilation operations (size of the 'hot-dog') to perform.
111 if (!is_integer_type(argv[1]->type()))
112 throw Error(malformed_expr, "dilate_array(): Expected an integer for the second argument.");
113
114 unsigned int dSize = extract_uint_value(argv[1]);
115
116 Array::Dim_iter itr = mask->dim_begin();
117 int maxI = mask->dimension_size(itr++);
118 int maxJ = mask->dimension_size(itr);
119
120 // Dilate each mask location 'dSize' elements around it.
121 // NB: currently not handling mask edge.
122 for (unsigned int i=dSize; i<maxI-dSize; i++) {
123 for (unsigned int j=dSize; j<maxJ-dSize; j++ ) {
124 int mask_offset = j + i * maxI;
125 if ( mask_values.at(mask_offset) /*mask[i][j]*/ == 1 ) {
126 // I think this could be modified to handle the edge case by expanding the
127 // ranges above to be the whole image and then using max() and min() in the
128 // initialization and loop tests below. Not sure though. jhrg 5/16/15
129 for (unsigned int x=i-dSize; x<=i+dSize; x++) {
130 for (unsigned int y=j-dSize; y<=j+dSize; y++) {
131 int dest_offset = y + x * maxI;
132 dest_values.at(dest_offset) = 1; //dest.value[x][y] = 1;
133 }
134 }
135 }
136 }
137 }
138
139 // Create the 'dilated' array using the shape of the input 'mask' array variable.
140 Array *dest = new Array("dilated_mask", 0); // The ctor for Array copies the prototype pointer...
141
142 BaseTypeFactory btf;
143 dest->add_var_nocopy(btf.NewVariable(dods_byte_c)); // ... so use add_var_nocopy() to add it instead
144
145 dest->append_dim(maxI);
146 dest->append_dim(maxJ);
147
148 dest->set_value(dest_values, mask->length());
149 dest->set_send_p(true);
150 dest->set_read_p(true);
151
152 // return the array
153 *btpp = dest;
154
155 return;
156}
157
158
159} // namesspace functions