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>
61#include <libdap/debug.h>
62#include <libdap/util.h>
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>
79double w32strtod(
const char *,
char **);
92static string extract_string_argument(BaseType * arg)
94 if (arg->type() != dods_str_c)
95 throw Error(malformed_expr,
"The function requires a DAP string argument.");
98 throw InternalErr(__FILE__, __LINE__,
99 "The CE Evaluator built an argument list where some constants held no values.");
101 string s =
dynamic_cast<Str&
>(*arg).value();
103 DBG(cerr <<
"s: " << s << endl);
109static void set_array_using_double_helper(Array * a,
double *src,
int src_len)
111 T *values =
new T[src_len];
112 for (
int i = 0; i < src_len; ++i)
113 values[i] = (T) src[i];
115 a->set_value(values, src_len);
120template<
typename DODS,
typename T>
121static T *extract_array_helper(Array *a)
123 int length = a->size();
125 DBG(cerr <<
"Allocating..." << length << endl);
126 DODS *b =
new DODS[length];
128 DBG(cerr <<
"Assigning value..." << endl);
131 DBG(cerr <<
"array values extracted. Casting..." << endl);
132 T *dest =
new T[length];
134 for (
int i = 0; i < length; ++i)
138 DBG(cerr <<
"Returning extracted values." << endl);
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.");
165 switch (a->var()->type()) {
167 gfa =
new GF::Array(a->var()->name(), GF::INT);
168 gfa->shareIntData(extract_array_helper<dods_byte, int>(a), a->size());
171 gfa =
new GF::Array(a->var()->name(), GF::INT);
172 gfa->shareIntData(extract_array_helper<dods_uint16, int>(a), a->size());
175 gfa =
new GF::Array(a->var()->name(), GF::INT);
176 gfa->shareIntData(extract_array_helper<dods_int16, int>(a), a->size());
179 gfa =
new GF::Array(a->var()->name(), GF::INT);
180 gfa->shareIntData(extract_array_helper<dods_uint32, int>(a), a->size());
183 gfa =
new GF::Array(a->var()->name(), GF::INT);
184 gfa->shareIntData(extract_array_helper<dods_int32, int>(a), a->size());
187 gfa =
new GF::Array(a->var()->name(), GF::FLOAT);
188 gfa->shareFloatData(extract_array_helper<dods_float32, float>(a), a->size());
191 gfa =
new GF::Array(a->var()->name(), GF::FLOAT);
192 gfa->shareFloatData(extract_array_helper<dods_float64, float>(a), a->size());
195 throw InternalErr(__FILE__, __LINE__,
"Unknown DDS type encountered when converting to gridfields array");
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 <<
", ");
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)
237static T *extract_array(Array * a)
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.");
252 throw InternalErr(__FILE__, __LINE__,
253 string(
"The Array '") + a->name() +
254 "'does not contain values. send_read_p() not called?");
260 switch (a->var()->type()) {
262 return extract_array_helper<dods_byte, T>(a);
265 DBG(cerr <<
"dods_uint32_c" << endl);
266 return extract_array_helper<dods_uint16, T>(a);
269 DBG(cerr <<
"dods_int16_c" << endl);
270 return extract_array_helper<dods_int16, T>(a);
273 DBG(cerr <<
"dods_uint32_c" << endl);
274 return extract_array_helper<dods_uint32, T>(a);
277 DBG(cerr <<
"dods_int32_c" << endl);
278 return extract_array_helper<dods_int32, T>(a);
281 DBG(cerr <<
"dods_float32_c" << endl);
283 return extract_array_helper<dods_float32, T>(a);
286 DBG(cerr <<
"dods_float64_c" << endl);
287 return extract_array_helper<dods_float64, T>(a);
290 throw InternalErr(__FILE__, __LINE__,
291 "The argument list built by the CE parser contained an unsupported numeric type.");
302static double extract_double_value(BaseType * arg)
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.");
309 throw InternalErr(__FILE__, __LINE__,
310 "The CE Evaluator built an argument list where some constants held no values.");
316 switch (arg->type()) {
318 return (
double) (
dynamic_cast<Byte&
>(*arg).value());
320 return (
double) (
dynamic_cast<UInt16&
>(*arg).value());
322 return (
double) (
dynamic_cast<Int16&
>(*arg).value());
324 return (
double) (
dynamic_cast<UInt32&
>(*arg).value());
326 return (
double) (
dynamic_cast<Int32&
>(*arg).value());
328 return (
double) (
dynamic_cast<Float32&
>(*arg).value());
330 return dynamic_cast<Float64&
>(*arg).value();
332 throw InternalErr(__FILE__, __LINE__,
333 "The argument list built by the CE parser contained an unsupported numeric type.");
347static double string_to_double(
const char *val)
354 double v = w32strtod(val, &ptr);
356 double v = strtod(val, &ptr);
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.");
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.");
379static double get_attribute_double_value(BaseType *var,
vector<string> &attributes)
383 AttrTable &attr = var->get_attr_table();
384 string attribute_value =
"";
387 while (attribute_value ==
"" && i != attributes.end()) {
391 attribute_value = attr.get_attr(*i++);
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);
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() +
"'.");
405 return string_to_double(remove_quotes(attribute_value).c_str());
408static double get_attribute_double_value(BaseType *var,
const string &attribute)
410 AttrTable &attr = var->get_attr_table();
411 string attribute_value = attr.get_attr(attribute);
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);
419 throw Error(malformed_expr,
420 string(
"No COARDS '") + attribute +
"' attribute was found for the variable '" + var->name()
424 return string_to_double(remove_quotes(attribute_value).c_str());
428static double get_y_intercept(BaseType *var)
431 attributes.push_back(
"add_offset");
432 attributes.push_back(
"add_off");
433 return get_attribute_double_value(var, attributes);
436static double get_slope(BaseType *var)
438 return get_attribute_double_value(var,
"scale_factor");
441static double get_missing_value(BaseType *var)
443 return get_attribute_double_value(var,
"missing_value");
470function_ugrid_restrict(
int argc, BaseType * argv[],
DDS &dds, BaseType **btpp)
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" +
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" +
484 Str *response =
new Str(
"info");
485 response->set_value(info);
491 Str *response =
new Str(
"info2");
492 response->set_value(info);
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)");
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());
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());
512 GF::Grid *G =
new GF::Grid(
"result");
515 DBG(cerr <<
"Reading 0-cells" << endl);
516 GF::AbstractCellArray *nodes = NULL;
518 for (DDS::Vars_iter vi = dds.var_begin(); vi != dds.var_end(); vi++) {
522 Array &arr =
dynamic_cast<Array&
>(*bt);
523 AttrTable &at = arr.get_attr_table();
524 DBG(cerr <<
"Array: " << arr.name() << endl);
527 AttrTable::Attr_iter loc = at.simple_find(
"grid_location");
529 if (loc != at.attr_end()) {
531 if (at.get_attr(loc, 0) ==
"node") {
533 Array::Dim_iter di = arr.dim_begin();
534 DBG(cerr <<
"Interpreting 0-cells from dimensions: ");
536 for (Array::Dim_iter di = arr.dim_begin(); di!= arr.dim_end(); di++) {
538 DBG(cerr << di->name <<
", ");
539 rank_dimensions[0].push_back(*di);
540 node_count *= di->c_size;
544 nodes =
new GF::Implicit0Cells(node_count);
551 throw Error(
"Could not find a grid_location attribute and/or its node set.");
554 G->setKCells(nodes, 0);
558 DBG(cerr <<
"Reading 2-cells" << endl);
559 GF::CellArray *twocells = NULL;
561 for (DDS::Vars_iter vi = dds.var_begin(); vi != dds.var_end(); vi++) {
564 Array &arr =
dynamic_cast<Array&
>(*bt);
565 DBG(cerr <<
"Array: " << arr.name() << endl);
567 AttrTable &at = arr.get_attr_table();
569 AttrTable::Attr_iter iter_cell_type = at.simple_find(
"cell_type");
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") {
577 int twocell_count = -1, i=0;
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);
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.");
590 twocell_count = di->c_size;
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");
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];
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;
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);
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;
629 throw Error(malformed_expr,
"Index origin attribute exists, but either no value supplied, or more than one value supplied.");
634 twocells =
new GF::CellArray(cellids, twocell_count, 3);
637 G->setKCells(twocells, 2);
643 throw Error(
"Could not find cell array of CCW triangles");
648 GF::GridField *input =
new GF::GridField(G);
650 for (DDS::Vars_iter vi = dds.var_begin(); vi != dds.var_end(); vi++) {
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);
663 for( iter = rank_dimensions.begin(); iter != rank_dimensions.end(); ++iter ) {
664 bool same = same_dimensions(arr, iter->second);
667 DBG(cerr <<
"Adding Attribute: " << gfa->sname() << endl);
668 input->AddAttribute(iter->first, gfa);
679 int dim = extract_double_value(argv[0]);
680 string projection = extract_string_argument(argv[1]);
681 int nodenumber=input->Card(0);
683 GF::RestrictOp op = GF::RestrictOp(projection, dim, input);
684 GF::GridField *R =
new GF::GridField(op.getResult());
691 R->GetGrid()->normalize();
693 Structure *construct =
new Structure(
"construct");
694 for (DDS::Vars_iter vi = dds.var_begin(); vi != dds.var_end(); vi++) {
696 if (bt->type() == dods_array_c) {
697 Array *arr = (Array *)bt;
700 AttrTable &arrattr2 = arr->get_attr_table();
702 if(arrattr2.simple_find(
"cell_type")!=arrattr2.attr_end())
704 GF::CellArray* Inb=(GF::CellArray*)(R->GetGrid()->getKCells(2));
706 Array *Nodes =
new Array(arr->name(),witnessn4);
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));
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");
724 Node2->append_dim(node2.size(),
"dim-1");
725 Node3->append_dim(node3.size(),
"dim-1");
727 Node1->set_value(node1,node1.size());
728 Node2->set_value(node2,node2.size());
729 Node3->set_value(node3,node3.size());
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);
742 for( iter = rank_dimensions.begin(); iter != rank_dimensions.end(); ++iter ) {
743 bool same = same_dimensions(arr, iter->second);
748 GF::Array* gfa=R->GetAttribute(iter->first, arr->name());
752 Array *Nodes =
new Array(arr->name(), witness2);
753 Nodes->append_dim(GFA.size(),
"nodes");
754 Nodes->set_value(GFA,GFA.size());
756 AttrTable &arrattr1 = arr->get_attr_table();
757 Nodes->set_attr_table(arrattr1);
759 construct->add_var_nocopy(Nodes);
772 for (DDS::Vars_iter vi = dds.var_begin(); vi != dds.var_end(); 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);
780 GF::Array* gfa = R->GetAttribute(iter->first, arr->name());