29#include <ogr_spatialref.h>
31#include <libdap/DDS.h>
32#include <libdap/Grid.h>
34#include <libdap/util.h>
36#include <BESInternalError.h>
39#include "GeoTiffTransmitter.h"
40#include "FONgTransform.h"
58 d_coards_lat_units.insert(
"degrees_north");
59 d_coards_lat_units.insert(
"degree_north");
60 d_coards_lat_units.insert(
"degree_N");
61 d_coards_lat_units.insert(
"degrees_N");
63 d_coards_lon_units.insert(
"degrees_east");
64 d_coards_lon_units.insert(
"degree_east");
65 d_coards_lon_units.insert(
"degrees_E");
66 d_coards_lon_units.insert(
"degree_E");
68 d_lat_names.insert(
"COADSY");
69 d_lat_names.insert(
"lat");
70 d_lat_names.insert(
"Lat");
71 d_lat_names.insert(
"LAT");
73 d_lon_names.insert(
"COADSX");
74 d_lon_names.insert(
"lon");
75 d_lon_names.insert(
"Lon");
76 d_lon_names.insert(
"LON");
96 is_prefix(
const string & in) :
101 bool operator()(
const string & prefix)
103 return s.find(prefix) == 0;
117bool FONgGrid::m_lat_unit_or_name_match(
const string &var_units,
const string &var_name,
const string &long_name)
119 return (long_name ==
"latitude" || d_coards_lat_units.find(var_units) != d_coards_lat_units.end()
120 || find_if(d_lat_names.begin(), d_lat_names.end(), is_prefix(var_name)) != d_lat_names.end());
123bool FONgGrid::m_lon_unit_or_name_match(
const string &var_units,
const string &var_name,
const string &long_name)
125 return (long_name ==
"longitude" || d_coards_lon_units.find(var_units) != d_coards_lon_units.end()
126 || find_if(d_lon_names.begin(), d_lon_names.end(), is_prefix(var_name)) != d_lon_names.end());
146 Grid::Map_iter m = d_grid->map_begin();
151 Array::Dim_iter d = d_grid->get_array()->dim_begin();
159 while (m != d_grid->map_end() && (!d_lat || !d_lon)) {
160 string units_value = (*m)->get_attr_table().get_attr(
"units");
161 units_value = remove_quotes(units_value);
162 string long_name = (*m)->get_attr_table().get_attr(
"long_name");
163 long_name = remove_quotes(long_name);
164 string map_name = (*m)->name();
168 if (!d_lat && m_lat_unit_or_name_match(units_value, map_name, long_name)) {
175 d_lat =
dynamic_cast<Array *
>(*m);
176 if (!d_lat)
throw InternalErr(__FILE__, __LINE__,
"Expected an array.");
178 if (!d_lat->read_p()) d_lat->read();
181 if (!d_lon && m_lon_unit_or_name_match(units_value, map_name, long_name)) {
182 d_lon =
dynamic_cast<Array *
>(*m);
183 if (!d_lon)
throw InternalErr(__FILE__, __LINE__,
"Expected an array.");
185 if (!d_lon->read_p()) d_lon->read();
192 return d_lat && d_lon;
205 BESDEBUG(
"fong3",
"Entering FONgGrid::extract_coordinates" << endl);
207 double *lat = 0, *lon = 0;
214 t.set_height(d_lat->length());
215 t.set_width(d_lon->length());
217 lat = extract_double_array(d_lat);
218 lon = extract_double_array(d_lon);
221 t.set_top(max (lat[0], lat[t.height()-1]));
224 t.set_bottom(min (lat[0], lat[t.height()-1]));
225 t.set_right(lon[t.width() - 1]);
228 string missing_value = d_grid->get_attr_table().get_attr(
"missing_value");
229 if (missing_value.empty()) missing_value = d_grid->get_array()->get_attr_table().get_attr(
"missing_value");
230 if (missing_value.empty()) missing_value = d_grid->get_attr_table().get_attr(
"_FillValue");
231 if (missing_value.empty()) missing_value = d_grid->get_array()->get_attr_table().get_attr(
"_FillValue");
233 BESDEBUG(
"fong3",
"missing_value attribute: " << missing_value << endl);
236 if (!missing_value.empty()) {
237 t.set_no_data(missing_value);
239 t.set_no_data_type(FONgTransform::negative);
241 t.set_no_data_type(FONgTransform::positive);
244 t.geo_transform_set(
true);
246 t.set_num_bands(t.num_bands() + 1);
261static bool is_spherical(BaseType *btp)
267 bool gmn = btp->get_attr_table().get_attr(
"grid_mapping_name") ==
"latitude_longitude";
268 bool sma = btp->get_attr_table().get_attr(
"semi_major_axis") ==
"6371000.0";
269 bool iflat = btp->get_attr_table().get_attr(
"inverse_flattening") ==
"0";
271 return gmn && sma && iflat;
275static bool is_wgs84(BaseType *btp)
282 bool gmn = btp->get_attr_table().get_attr(
"grid_mapping_name") ==
"latitude_longitude";
283 bool lpm = btp->get_attr_table().get_attr(
"longitude_of_prime_meridian") ==
"0.0";
284 bool sma = btp->get_attr_table().get_attr(
"semi_major_axis") ==
"6378137.0";
285 bool iflat = btp->get_attr_table().get_attr(
"inverse_flattening") ==
"298.257223563";
287 return gmn && lpm && sma && iflat;
304 string mapping_info = d_grid->get_attr_table().get_attr(
"grid_mapping");
305 if (mapping_info.empty()) mapping_info = d_grid->get_array()->get_attr_table().get_attr(
"grid_mapping");
307 string WK_GCS = GeoTiffTransmitter::default_gcs;
309 if (!mapping_info.empty()) {
317 BaseType *btp = dds->var(mapping_info);
318 if (btp && btp->name() ==
"crs") {
321 else if (is_spherical(btp)) WK_GCS =
"EPSG:4047";
325 OGRSpatialReference srs;
326 srs.SetWellKnownGeogCS(WK_GCS.c_str());
327 char *srs_wkt = NULL;
328 srs.exportToWkt(&srs_wkt);
330 string wkt = srs_wkt;
339 if (!d_grid->get_array()->read_p()) d_grid->get_array()->read();
342 return extract_double_array(d_grid->get_array());
string get_projection(libdap::DDS *dds)
Set the projection information For Grids, look for CF information. If it's not present,...
FONgGrid(libdap::Grid *g)
Constructor for FONgGrid that takes a DAP Grid.
virtual double * get_data()
Get the data values for the band(s). Call must delete.
virtual ~FONgGrid()
Destructor that cleans up the grid.
virtual void extract_coordinates(FONgTransform &t)
Get the GDAL/OGC WKT projection string.