bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
gridfields_functions.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) 2002,2003,2011,2012 OPeNDAP, Inc.
7// Authors: James Gallagher <jgallagher@opendap.org>
8// Scott Moe <smeest1@gmail.com>
9// Bill Howe <billhowe@cs.washington.edu>
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// NOTE: This file is built only when the gridfields library is linked with
28// the netcdf_handler (i.e., the handler's build is configured using the
29// --with-gridfields=... option to the 'configure' script).
30
31#if 0 // Disabling cruft code from earlier ugrid work - ndp 03/25/2013
32
33#include "config.h"
34
35#include <limits.h>
36
37#include <cstdlib> // used by strtod()
38#include <cerrno>
39#include <cmath>
40#include <iostream>
41#include <sstream>
42
43//#define DODS_DEBUG
44
45#include <libdap/BaseType.h>
46#include <libdap/Byte.h>
47#include <libdap/Int16.h>
48#include <libdap/UInt16.h>
49#include <libdap/Int32.h>
50#include <libdap/UInt32.h>
51#include <libdap/Float32.h>
52#include <libdap/Float64.h>
53#include <libdap/Str.h>
54#include <libdap/Url.h>
55#include <libdap/Array.h>
56#include <libdap/Structure.h>
57#include <libdap/Sequence.h>
58#include <libdap/Grid.h>
59#include <libdap/Error.h>
60
61#include <libdap/debug.h>
62#include <libdap/util.h>
63
64#include <gridfields/restrict.h>
65#include <gridfields/gridfield.h>
66#include <gridfields/grid.h>
67#include <gridfields/cell.h>
68#include <gridfields/cellarray.h>
69#include <gridfields/array.h>
70#include <gridfields/implicit0cells.h>
71#include <gridfields/gridfieldoperator.h>
72
73// We wrapped VC++ 6.x strtod() to account for a short coming
74// in that function in regards to "NaN". I don't know if this
75// still applies in more recent versions of that product.
76// ROM - 12/2007
77#ifdef WIN32
78#include <limits>
79double w32strtod(const char *, char **);
80#endif
81
82using namespace std;
83using namespace libdap;
84
92static string extract_string_argument(BaseType * arg)
93{
94 if (arg->type() != dods_str_c)
95 throw Error(malformed_expr, "The function requires a DAP string argument.");
96
97 if (!arg->read_p())
98 throw InternalErr(__FILE__, __LINE__,
99 "The CE Evaluator built an argument list where some constants held no values.");
100
101 string s = dynamic_cast<Str&>(*arg).value();
102
103 DBG(cerr << "s: " << s << endl);
104
105 return s;
106}
107
108template<class T>
109static void set_array_using_double_helper(Array * a, double *src, int src_len)
110{
111 T *values = new T[src_len];
112 for (int i = 0; i < src_len; ++i)
113 values[i] = (T) src[i];
114
115 a->set_value(values, src_len);
116
117 delete[] values;
118}
119
120template<typename DODS, typename T>
121static T *extract_array_helper(Array *a)
122{
123 int length = a->size();
124
125 DBG(cerr << "Allocating..." << length << endl);
126 DODS *b = new DODS[length];
127
128 DBG(cerr << "Assigning value..." << endl);
129 a->value(b);
130
131 DBG(cerr << "array values extracted. Casting..." << endl);
132 T *dest = new T[length];
133
134 for (int i = 0; i < length; ++i)
135 dest[i] = (T) b[i];
136 delete[]b;
137
138 DBG(cerr << "Returning extracted values." << endl);
139
140 return dest;
141}
142
153static GF::Array *extract_gridfield_array(Array *a) {
154 if ((a->type() == dods_array_c && !a->var()->is_simple_type())
155 || a->var()->type() == dods_str_c || a->var()->type() == dods_url_c)
156 throw Error(malformed_expr,
157 "The function requires a DAP numeric-type array argument.");
158
159 a->set_send_p(true);
160 a->read();
161
162 // Construct a GridField array from a DODS array
163 GF::Array *gfa;
164
165 switch (a->var()->type()) {
166 case dods_byte_c:
167 gfa = new GF::Array(a->var()->name(), GF::INT);
168 gfa->shareIntData(extract_array_helper<dods_byte, int>(a), a->size());
169 break;
170 case dods_uint16_c:
171 gfa = new GF::Array(a->var()->name(), GF::INT);
172 gfa->shareIntData(extract_array_helper<dods_uint16, int>(a), a->size());
173 break;
174 case dods_int16_c:
175 gfa = new GF::Array(a->var()->name(), GF::INT);
176 gfa->shareIntData(extract_array_helper<dods_int16, int>(a), a->size());
177 break;
178 case dods_uint32_c:
179 gfa = new GF::Array(a->var()->name(), GF::INT);
180 gfa->shareIntData(extract_array_helper<dods_uint32, int>(a), a->size());
181 break;
182 case dods_int32_c:
183 gfa = new GF::Array(a->var()->name(), GF::INT);
184 gfa->shareIntData(extract_array_helper<dods_int32, int>(a), a->size());
185 break;
186 case dods_float32_c:
187 gfa = new GF::Array(a->var()->name(), GF::FLOAT);
188 gfa->shareFloatData(extract_array_helper<dods_float32, float>(a), a->size());
189 break;
190 case dods_float64_c:
191 gfa = new GF::Array(a->var()->name(), GF::FLOAT);
192 gfa->shareFloatData(extract_array_helper<dods_float64, float>(a), a->size());
193 break;
194 default:
195 throw InternalErr(__FILE__, __LINE__, "Unknown DDS type encountered when converting to gridfields array");
196 }
197 return gfa;
198};
199
200/*
201 If the array has the exact dimensions in the vector dims, in the same order,
202 return true. Otherwise return false.
203
204 */
205static bool same_dimensions(Array *arr, vector<Array::dimension> &dims) {
207 Array::Dim_iter ait;
208 DBG(cerr << "same_dimensions test for array " << arr->name() << endl);
209 DBG(cerr << " array dims: ");
210 for (ait = arr->dim_begin(); ait!=arr->dim_end(); ++ait) {
211 DBG(cerr << (*ait).name << ", ");
212 }
213 DBG(cerr << endl);
214 DBG(cerr << " rank dims: ");
215 for (dit = dims.begin(); dit!=dims.end(); ++dit) {
216 DBG(cerr << (*dit).name << ", " << endl);
217 for (ait = arr->dim_begin(); ait!=arr->dim_end(); ++ait) {
218 Array::dimension dd = *dit;
219 Array::dimension ad = *ait;
220 DBG(cout<<dd.name<<" "<<ad.name<<" "<<dd.size<<" "<<ad.size<<endl);
221 if (dd.name != ad.name
222 or dd.size != ad.size
223 or dd.stride != ad.stride
224 or dd.stop != ad.stop)
225 return false;
226 }
227 DBG(cerr << endl);
228 }
229 return true;
230}
231
236template<typename T>
237static T *extract_array(Array * a)
238{
239 // Simple types are Byte, ..., Float64, String and Url.
240 if ((a->type() == dods_array_c && !a->var()->is_simple_type())
241 || a->var()->type() == dods_str_c || a->var()->type() == dods_url_c)
242 throw Error(malformed_expr,
243 "The function requires a DAP numeric-type array argument.");
244
245 a->set_send_p(true);
246 a->read();
247 // This test should never pass due to the previous two lines;
248 // reading here seems to make
249 // sense rather than letting the caller forget to do so.
250 // is read() idemopotent?
251 if (!a->read_p())
252 throw InternalErr(__FILE__, __LINE__,
253 string("The Array '") + a->name() +
254 "'does not contain values. send_read_p() not called?");
255
256 // The types of arguments that the CE Parser will build for numeric
257 // constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
258 // Expanded to work for any numeric type so it can be used for more than
259 // just arguments.
260 switch (a->var()->type()) {
261 case dods_byte_c:
262 return extract_array_helper<dods_byte, T>(a);
263
264 case dods_uint16_c:
265 DBG(cerr << "dods_uint32_c" << endl);
266 return extract_array_helper<dods_uint16, T>(a);
267
268 case dods_int16_c:
269 DBG(cerr << "dods_int16_c" << endl);
270 return extract_array_helper<dods_int16, T>(a);
271
272 case dods_uint32_c:
273 DBG(cerr << "dods_uint32_c" << endl);
274 return extract_array_helper<dods_uint32, T>(a);
275
276 case dods_int32_c:
277 DBG(cerr << "dods_int32_c" << endl);
278 return extract_array_helper<dods_int32, T>(a);
279
280 case dods_float32_c:
281 DBG(cerr << "dods_float32_c" << endl);
282 // Added the following line. jhrg 8/7/12
283 return extract_array_helper<dods_float32, T>(a);
284
285 case dods_float64_c:
286 DBG(cerr << "dods_float64_c" << endl);
287 return extract_array_helper<dods_float64, T>(a);
288
289 default:
290 throw InternalErr(__FILE__, __LINE__,
291 "The argument list built by the CE parser contained an unsupported numeric type.");
292 }
293}
294
302static double extract_double_value(BaseType * arg)
303{
304 // Simple types are Byte, ..., Float64, String and Url.
305 if (!arg->is_simple_type() || arg->type() == dods_str_c || arg->type() == dods_url_c)
306 throw Error(malformed_expr, "The function requires a DAP numeric-type argument.");
307
308 if (!arg->read_p())
309 throw InternalErr(__FILE__, __LINE__,
310 "The CE Evaluator built an argument list where some constants held no values.");
311
312 // The types of arguments that the CE Parser will build for numeric
313 // constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
314 // Expanded to work for any numeric type so it can be used for more than
315 // just arguments.
316 switch (arg->type()) {
317 case dods_byte_c:
318 return (double) (dynamic_cast<Byte&>(*arg).value());
319 case dods_uint16_c:
320 return (double) (dynamic_cast<UInt16&>(*arg).value());
321 case dods_int16_c:
322 return (double) (dynamic_cast<Int16&>(*arg).value());
323 case dods_uint32_c:
324 return (double) (dynamic_cast<UInt32&>(*arg).value());
325 case dods_int32_c:
326 return (double) (dynamic_cast<Int32&>(*arg).value());
327 case dods_float32_c:
328 return (double) (dynamic_cast<Float32&>(*arg).value());
329 case dods_float64_c:
330 return dynamic_cast<Float64&>(*arg).value();
331 default:
332 throw InternalErr(__FILE__, __LINE__,
333 "The argument list built by the CE parser contained an unsupported numeric type.");
334 }
335}
336
337#if 0
338// These static functions could be moved to a class that provides a more
339// general interface for COARDS/CF someday. Assume each BaseType comes bundled
340// with an attribute table.
341
342// These are included here because the ugrid code might want to use attribute
343// values bound to various variables and this illustrates how that could be
344// done. jhrg 8/20/12
345
346// This was ripped from parser-util.cc
347static double string_to_double(const char *val)
348{
349 char *ptr;
350 errno = 0;
351 // Clear previous value. 5/21/2001 jhrg
352
353#ifdef WIN32
354 double v = w32strtod(val, &ptr);
355#else
356 double v = strtod(val, &ptr);
357#endif
358
359 if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE)) || *ptr != '\0') {
360 throw Error(malformed_expr, string("Could not convert the string '") + val + "' to a double.");
361 }
362
363 double abs_val = fabs(v);
364 if (abs_val > DODS_DBL_MAX || (abs_val != 0.0 && abs_val < DODS_DBL_MIN))
365 throw Error(malformed_expr, string("Could not convert the string '") + val + "' to a double.");
366
367 return v;
368}
369
379static double get_attribute_double_value(BaseType *var, vector<string> &attributes)
380{
381 // This code also builds a list of the attribute values that have been
382 // passed in but not found so that an informative message can be returned.
383 AttrTable &attr = var->get_attr_table();
384 string attribute_value = "";
385 string values = "";
386 vector<string>::iterator i = attributes.begin();
387 while (attribute_value == "" && i != attributes.end()) {
388 values += *i;
389 if (!values.empty())
390 values += ", ";
391 attribute_value = attr.get_attr(*i++);
392 }
393
394 // If the value string is empty, then look at the grid's array (if it's a
395 // grid) or throw an Error.
396 if (attribute_value.empty()) {
397 if (var->type() == dods_grid_c)
398 return get_attribute_double_value(dynamic_cast<Grid&>(*var).get_array(), attributes);
399 else
400 throw Error(malformed_expr,
401 string("No COARDS/CF '") + values.substr(0, values.size() - 2)
402 + "' attribute was found for the variable '" + var->name() + "'.");
403 }
404
405 return string_to_double(remove_quotes(attribute_value).c_str());
406}
407
408static double get_attribute_double_value(BaseType *var, const string &attribute)
409{
410 AttrTable &attr = var->get_attr_table();
411 string attribute_value = attr.get_attr(attribute);
412
413 // If the value string is empty, then look at the grid's array (if it's a
414 // grid or throw an Error.
415 if (attribute_value.empty()) {
416 if (var->type() == dods_grid_c)
417 return get_attribute_double_value(dynamic_cast<Grid&>(*var).get_array(), attribute);
418 else
419 throw Error(malformed_expr,
420 string("No COARDS '") + attribute + "' attribute was found for the variable '" + var->name()
421 + "'.");
422 }
423
424 return string_to_double(remove_quotes(attribute_value).c_str());
425}
426
427
428static double get_y_intercept(BaseType *var)
429{
430 vector<string> attributes;
431 attributes.push_back("add_offset");
432 attributes.push_back("add_off");
433 return get_attribute_double_value(var, attributes);
434}
435
436static double get_slope(BaseType *var)
437{
438 return get_attribute_double_value(var, "scale_factor");
439}
440
441static double get_missing_value(BaseType *var)
442{
443 return get_attribute_double_value(var, "missing_value");
444}
445#endif
446
469void
470function_ugrid_restrict(int argc, BaseType * argv[], DDS &dds, BaseType **btpp)
471{
472 static string info =
473 string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
474 "<function name=\"ugrid_demo\" version=\"0.1\">\n" +
475 "Fledgling code for Unstructured grid operations.\n" +
476 "</function>";
477
478 static string info2 =
479 string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
480 "<function name=\"ugrid_demo\" version=\"0.1\">\n" +
481 "code for Unstructured grid operations.\n" +
482 "</function>";
483 if (argc == 0) {
484 Str *response = new Str("info");
485 response->set_value(info);
486 *btpp = response;
487 return;
488 }
489
490 if (argc == 7) {
491 Str *response = new Str("info2");
492 response->set_value(info);
493 *btpp = response;
494 return;
495 }
496
497 // Check number of arguments; DBG is a macro. Use #define
498 // DODS_DEBUG to activate the debugging stuff.
499 if (argc != 2)
500 throw Error(malformed_expr,"Wrong number of arguments to ugrid_demo. ugrid_demo(dim:int32, condition:string); was passed " + long_to_string(argc) + " argument(s)");
501
502 if (argv[0]->type() != dods_int32_c)
503 throw Error(malformed_expr,"Wrong type for first argument. ugrid_demo(dim:int32, condition:string); was passed a/an " + argv[0]->type_name());
504
505 if (argv[1]->type() != dods_str_c)
506 throw Error(malformed_expr,"Wrong type for second argument. ugrid_demo(dim:int32, condition:string); was passed a/an " + argv[1]->type_name());
507
508 // keep track of which DDS dimensions correspond to GF dimensions
509
511
512 GF::Grid *G = new GF::Grid("result");
513
514 // 1) Find the nodes
515 DBG(cerr << "Reading 0-cells" << endl);
516 GF::AbstractCellArray *nodes = NULL;
517
518 for (DDS::Vars_iter vi = dds.var_begin(); vi != dds.var_end(); vi++) {
519
520 BaseType *bt = *vi;
521 // TODO allow variables that are not arrays; just ignore them
522 Array &arr = dynamic_cast<Array&>(*bt);
523 AttrTable &at = arr.get_attr_table();
524 DBG(cerr << "Array: " << arr.name() << endl);
525
526 int node_count = -1; //error condition
527 AttrTable::Attr_iter loc = at.simple_find("grid_location");
528
529 if (loc != at.attr_end()) {
530
531 if (at.get_attr(loc, 0) == "node") {
532 node_count = 1;
533 Array::Dim_iter di = arr.dim_begin();
534 DBG(cerr << "Interpreting 0-cells from dimensions: ");
535 rank_dimensions[0] = vector<Array::dimension>();
536 for (Array::Dim_iter di = arr.dim_begin(); di!= arr.dim_end(); di++) {
537 // These dimensions define the nodes.
538 DBG(cerr << di->name << ", ");
539 rank_dimensions[0].push_back(*di);
540 node_count *= di->c_size;
541 }
542 DBG(cerr << endl);
543
544 nodes = new GF::Implicit0Cells(node_count);
545 break;
546 } // Bound to nodes?
547 } // Has a "grid_location" attribute?
548 }
549
550 if (!nodes)
551 throw Error("Could not find a grid_location attribute and/or its node set.");
552
553 // Attach the nodes to the grid
554 G->setKCells(nodes, 0);
555
556 // 2) For each k, find the k-cells
557 // k = 2, for now
558 DBG(cerr << "Reading 2-cells" << endl);
559 GF::CellArray *twocells = NULL;
560
561 for (DDS::Vars_iter vi = dds.var_begin(); vi != dds.var_end(); vi++) {
562 BaseType *bt = *vi;
563 // TODO Allow variables that are note Arrays; ignore as above
564 Array &arr = dynamic_cast<Array&>(*bt);
565 DBG(cerr << "Array: " << arr.name() << endl);
566
567 AttrTable &at = arr.get_attr_table();
568
569 AttrTable::Attr_iter iter_cell_type = at.simple_find("cell_type");
570
571 if (iter_cell_type != at.attr_end()) {
572 string cell_type = at.get_attr(iter_cell_type, 0);
573 DBG(cerr << cell_type << endl);
574 if (cell_type == "tri_ccw") {
575 // Ok, we expect triangles
576 // which means a shape of 3xN
577 int twocell_count = -1, i=0;
578 int total_size = 1;
579 rank_dimensions[2] = vector<Array::dimension>();
580 for (Array::Dim_iter di = arr.dim_begin(); di!= arr.dim_end(); di++) {
581 total_size *= di->c_size;
582 rank_dimensions[2].push_back(*di);
583 if (i == 0) {
584 if (di->c_size != 3) {
585 DBG(cerr << "Cell array of type 'tri_ccw' must have a shape of 3xN, since triangles have three nodes." << endl);
586 throw Error(malformed_expr,"Cell array of type 'tri_ccw' must have a shape of 3xN, since triangles have three nodes.");
587 }
588 }
589 if (i == 1) {
590 twocell_count = di->c_size;
591 }
592 if (i>1) {
593 DBG(cerr << "Too many dimensions for a cell array of type 'tri_ccw'. Expected shape of 3XN" << endl);
594 throw Error(malformed_expr,"Too many dimensions for a cell array of type 'tri_ccw'. Expected shape of 3XN");
595 }
596 i++;
597 }
598
599 // interpret the array data as triangles
600 GF::Node *cellids = extract_array<GF::Node>(&arr);
601 GF::Node *cellids2 = extract_array<GF::Node>(&arr);
602 for (int j=0;j<twocell_count;j++)
603 { cellids[3*j]=cellids2[j];
604 cellids[3*j+1]=cellids2[j+twocell_count];
605 cellids[3*j+2]=cellids2[j+2*twocell_count];
606 }
607
608 // adjust for index origin
609 AttrTable::Attr_iter iter_index_origin = at.simple_find("index_origin");
610 if (iter_index_origin != at.attr_end()) {
611 DBG(cerr << "Found an index origin attribute." << endl);
612 AttrTable::entry *index_origin_entry = *iter_index_origin;
613 int index_origin;
614 if (index_origin_entry->attr->size() == 1) {
615 AttrTable::entry *index_origin_entry = *iter_index_origin;
616 string val = (*index_origin_entry->attr)[0];
617 DBG(cerr << "Value: " << val << endl);
618 stringstream buffer(val);
619 // what happens if string cannot be converted to an integer?
620 buffer >> index_origin;
621 DBG(cerr << "converted: " << index_origin << endl);
622 if (index_origin != 0) {
623 for (int j=0; j<total_size; j++) {
624 cellids[j] -= index_origin;
625 }
626 }
627 }
628 else {
629 throw Error(malformed_expr,"Index origin attribute exists, but either no value supplied, or more than one value supplied.");
630 }
631 }
632
633 // Create the cell array
634 twocells = new GF::CellArray(cellids, twocell_count, 3);
635
636 // Attach it to the grid
637 G->setKCells(twocells, 2);
638 }
639 }
640 }
641
642 if (!twocells)
643 throw Error("Could not find cell array of CCW triangles");
644
645 // 3) For each var, bind it to the appropriate dimension
646
647 // For each variable in the data source:
648 GF::GridField *input = new GF::GridField(G);
649
650 for (DDS::Vars_iter vi = dds.var_begin(); vi != dds.var_end(); vi++) {
651 BaseType *bt = *vi;
652
653 if (bt->type() == dods_array_c) {
654 Array *arr = (Array *)bt;
655 DBG(cerr << "Data Array: " << arr->name() << endl);
656 GF::Array *gfa = extract_gridfield_array(arr);
657
658 // Each rank is associated with a sequence of dimensions
659 // Vars that have the same dimensions should be bound to the grid at that rank
660 // (Note that in gridfields, Dimension and rank are synonyms. We
661 // use the latter here to avoid confusion).
663 for( iter = rank_dimensions.begin(); iter != rank_dimensions.end(); ++iter ) {
664 bool same = same_dimensions(arr, iter->second);
665 if (same) {
666 // This var should be bound to rank k
667 DBG(cerr << "Adding Attribute: " << gfa->sname() << endl);
668 input->AddAttribute(iter->first, gfa);
669 }
670 else {
671 // This array does not appear to be associated with any
672 // rank of the unstructured grid. Ignore for now.
673 // TODO Anything else we should do?
674 }
675 }
676 } // Ignore if not an array type. Anything else we should do?
677 }
678
679 int dim = extract_double_value(argv[0]);
680 string projection = extract_string_argument(argv[1]);
681 int nodenumber=input->Card(0);
682
683 GF::RestrictOp op = GF::RestrictOp(projection, dim, input);
684 GF::GridField *R = new GF::GridField(op.getResult());
685
686 // 4) Convert back to a DDS BaseType
687
688 // Create variables for each cell dimension
689 // Create variables for each attribute at each rank
690
691 R->GetGrid()->normalize();
692
693 Structure *construct = new Structure("construct");
694 for (DDS::Vars_iter vi = dds.var_begin(); vi != dds.var_end(); vi++) {
695 BaseType *bt = *vi;
696 if (bt->type() == dods_array_c) {
697 Array *arr = (Array *)bt;
699
700 AttrTable &arrattr2 = arr->get_attr_table();
701
702 if(arrattr2.simple_find("cell_type")!=arrattr2.attr_end())
703 {
704 GF::CellArray* Inb=(GF::CellArray*)(R->GetGrid()->getKCells(2));
705 Int32 *witnessn4 = new Int32(arr->name());
706 Array *Nodes = new Array(arr->name(),witnessn4);
707 vector< vector<int> > nodes2 = Inb->makeArrayInts();
708 vector<dods_int32> node1;
709 vector<dods_int32> node2;
710 vector<dods_int32> node3;
711 for (int j=0;j<nodes2.size();j++) {
712 node1.push_back(nodes2.at(j).at(0));
713 node2.push_back(nodes2.at(j).at(1));
714 node3.push_back(nodes2.at(j).at(2));
715 }
716 Int32 *witnessn1=new Int32("nodes1");
717 Int32 *witnessn2=new Int32("nodes2");
718 Int32 *witnessn3=new Int32("nodes3");
719 Array *Node1=new Array("trinode1",witnessn1);
720 Array *Node2=new Array("trinode2",witnessn2);
721 Array *Node3=new Array("trinode3",witnessn3);
722 Node1->append_dim(node1.size(),"dim-1");
723
724 Node2->append_dim(node2.size(),"dim-1");
725 Node3->append_dim(node3.size(),"dim-1");
726
727 Node1->set_value(node1,node1.size());
728 Node2->set_value(node2,node2.size());
729 Node3->set_value(node3,node3.size());
730
731 Nodes->append_dim(3,"three");
732 Nodes->append_dim(node1.size(),"tris");
733 Nodes->reserve_value_capacity(3*node1.size());
734 Nodes->set_value_slice_from_row_major_vector(*Node1,0);
735 Nodes->set_value_slice_from_row_major_vector(*Node2,Node1->size());
736 Nodes->set_value_slice_from_row_major_vector(*Node3,Node1->size()+Node2->size());
737 AttrTable &arrattr1 = arr->get_attr_table();
738 Nodes->set_attr_table(arrattr1);
739 construct->add_var_nocopy(Nodes);
740 }
741 else {
742 for( iter = rank_dimensions.begin(); iter != rank_dimensions.end(); ++iter ) {
743 bool same = same_dimensions(arr, iter->second);
744 if (same) {
745 // This var should be bound to rank k
746 Float64 *witness2=new Float64(arr->name());
747
748 GF::Array* gfa=R->GetAttribute(iter->first, arr->name());
749
750 vector<dods_float64> GFA = gfa->makeArrayf();
751
752 Array *Nodes = new Array(arr->name(), witness2);
753 Nodes->append_dim(GFA.size(), "nodes");
754 Nodes->set_value(GFA,GFA.size());
755
756 AttrTable &arrattr1 = arr->get_attr_table();
757 Nodes->set_attr_table(arrattr1);
758 // AttrTable &arrattr = Nodes->get_attr_table();
759 construct->add_var_nocopy(Nodes);
760 }
761 else {
762 // This array does not appear to be associated with
763 // any rank of the unstructured grid. Ignore for now.
764 // Anything else we should do?
765 }
766 }
767 }
768 }
769 }
770
771#if 0
772 for (DDS::Vars_iter vi = dds.var_begin(); vi != dds.var_end(); vi++) {
773 BaseType *bt = *vi;
774 if (bt->type() == dods_array_c) {
775 Array *arr = (Array *)bt;
777 for( iter = rank_dimensions.begin(); iter != rank_dimensions.end(); ++iter ) {
778 bool same = same_dimensions(arr, iter->second);
779 if (same) {
780 GF::Array* gfa = R->GetAttribute(iter->first, arr->name());
781 }
782 else {
783 //This array does not appear to be associated with any
784 // rank of the unstructured grid.Ignore for now.
785 // Anything else we should do?
786 }
787
788 }
789 }
790 }
791#endif
792 // TODO Needed?
793 //GF::Grid *newgrid = R->GetGrid();
794
795 *btpp = construct;
796
797 return;
798}
799
800//#endif
801
802
803#endif // Disabling cruft code from earlier ugrid work - ndp 03/25/2013
STL class.
STL class.
STL iterator class.
STL class.