1 : /******************************************************************************
2 : * $Id: netcdfdataset.h 24073 2012-03-05 20:50:25Z etourigny $
3 : *
4 : * Project: netCDF read/write Driver
5 : * Purpose: GDAL bindings over netCDF library.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #ifndef _NETCDFDATASET_H_INCLUDED_
31 : #define _NETCDFATASET_H_INCLUDED_
32 :
33 : #include <float.h>
34 : #include "gdal_pam.h"
35 : #include "gdal_priv.h"
36 : #include "gdal_frmts.h"
37 : #include "cpl_string.h"
38 : #include "ogr_spatialref.h"
39 : #include "netcdf.h"
40 :
41 :
42 : /************************************************************************/
43 : /* ==================================================================== */
44 : /* defines */
45 : /* ==================================================================== */
46 : /************************************************************************/
47 :
48 : /* -------------------------------------------------------------------- */
49 : /* Creation and Configuration Options */
50 : /* -------------------------------------------------------------------- */
51 :
52 : /* Creation options
53 :
54 : FORMAT=NC/NC2/NC4/NC4C (COMPRESS=DEFLATE sets FORMAT=NC4C)
55 : COMPRESS=NONE/DEFLATE (default: NONE)
56 : ZLEVEL=[1-9] (default: 1)
57 : WRITE_BOTTOMUP=YES/NO (default: YES)
58 : WRITE_GDAL_TAGS=YES/NO (default: YES)
59 : WRITE_LONLAT=YES/NO/IF_NEEDED (default: YES for geographic, NO for projected)
60 : TYPE_LONLAT=float/double (default: double for geographic, float for projected)
61 : PIXELTYPE=DEFAULT/SIGNEDBYTE (use SIGNEDBYTE to get a signed Byte Band)
62 : */
63 :
64 : /* Config Options
65 :
66 : GDAL_NETCDF_BOTTOMUP=YES/NO overrides bottom-up value on import
67 : GDAL_NETCDF_CONVERT_LAT_180=YES/NO convert longitude values from ]180,360] to [-180,180]
68 : */
69 :
70 : /* -------------------------------------------------------------------- */
71 : /* Driver-specific defines */
72 : /* -------------------------------------------------------------------- */
73 :
74 : /* NETCDF driver defs */
75 : #define NCDF_MAX_STR_LEN 8192
76 : #define NCDF_CONVENTIONS_CF "CF-1.5"
77 : #define NCDF_GDAL GDALVersionInfo("--version")
78 : #define NCDF_SPATIAL_REF "spatial_ref"
79 : #define NCDF_GEOTRANSFORM "GeoTransform"
80 : #define NCDF_DIMNAME_X "x"
81 : #define NCDF_DIMNAME_Y "y"
82 : #define NCDF_DIMNAME_LON "lon"
83 : #define NCDF_DIMNAME_LAT "lat"
84 : #define NCDF_LONLAT "lon lat"
85 : #define NCDF_PI 3.14159265358979323846
86 :
87 : /* netcdf file types, as in libcdi/cdo and compat w/netcdf.h */
88 : #define NCDF_FORMAT_NONE 0 /* Not a netCDF file */
89 : #define NCDF_FORMAT_NC 1 /* netCDF classic format */
90 : #define NCDF_FORMAT_NC2 2 /* netCDF version 2 (64-bit) */
91 : #define NCDF_FORMAT_NC4 3 /* netCDF version 4 */
92 : #define NCDF_FORMAT_NC4C 4 /* netCDF version 4 (classic) */
93 : #define NCDF_FORMAT_UNKNOWN 10 /* Format not determined (yet) */
94 : /* HDF files (HDF5 or HDF4) not supported because of lack of support */
95 : /* in libnetcdf installation or conflict with other drivers */
96 : #define NCDF_FORMAT_HDF5 5 /* HDF4 file, not supported */
97 : #define NCDF_FORMAT_HDF4 6 /* HDF4 file, not supported */
98 :
99 : /* compression parameters */
100 : #define NCDF_COMPRESS_NONE 0
101 : /* TODO */
102 : /* http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html#Packed%20Data%20Values */
103 : #define NCDF_COMPRESS_PACKED 1
104 : #define NCDF_COMPRESS_DEFLATE 2
105 : #define NCDF_DEFLATE_LEVEL 1 /* best time/size ratio */
106 : #define NCDF_COMPRESS_SZIP 3 /* no support for writting */
107 :
108 : /* helper for libnetcdf errors */
109 : #define NCDF_ERR(status) if ( status != NC_NOERR ){ \
110 : CPLError( CE_Failure,CPLE_AppDefined, \
111 : "netcdf error #%d : %s .\nat (%s,%s,%d)\n",status, nc_strerror(status), \
112 : __FILE__, __FUNCTION__, __LINE__ ); }
113 :
114 : /* check for NC2 support in case it wasn't enabled at compile time */
115 : /* NC4 has to be detected at compile as it requires a special build of netcdf-4 */
116 : #ifndef NETCDF_HAS_NC2
117 : #ifdef NC_64BIT_OFFSET
118 : #define NETCDF_HAS_NC2 1
119 : #endif
120 : #endif
121 :
122 :
123 : /* -------------------------------------------------------------------- */
124 : /* CF-1 or NUG (NetCDF User's Guide) defs */
125 : /* -------------------------------------------------------------------- */
126 :
127 : /* CF: http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.5/cf-conventions.html */
128 : /* NUG: http://www.unidata.ucar.edu/software/netcdf/docs/netcdf.html#Variables */
129 : #define CF_STD_NAME "standard_name"
130 : #define CF_LNG_NAME "long_name"
131 : #define CF_UNITS "units"
132 : #define CF_ADD_OFFSET "add_offset"
133 : #define CF_SCALE_FACTOR "scale_factor"
134 : /* should be SRS_UL_METER but use meter now for compat with gtiff files */
135 : #define CF_UNITS_M "metre"
136 : #define CF_UNITS_D SRS_UA_DEGREE
137 : #define CF_PROJ_X_COORD "projection_x_coordinate"
138 : #define CF_PROJ_Y_COORD "projection_y_coordinate"
139 : #define CF_PROJ_X_COORD_LONG_NAME "x coordinate of projection"
140 : #define CF_PROJ_Y_COORD_LONG_NAME "y coordinate of projection"
141 : #define CF_GRD_MAPPING_NAME "grid_mapping_name"
142 : #define CF_GRD_MAPPING "grid_mapping"
143 : #define CF_COORDINATES "coordinates"
144 : /* #define CF_AXIS "axis" */
145 : /* #define CF_BOUNDS "bounds" */
146 : /* #define CF_ORIG_UNITS "original_units" */
147 :
148 :
149 : /* -------------------------------------------------------------------- */
150 : /* CF-1 convention standard variables related to */
151 : /* mapping & projection - see http://cf-pcmdi.llnl.gov/ */
152 : /* -------------------------------------------------------------------- */
153 :
154 : /* projection types */
155 : #define CF_PT_AEA "albers_conical_equal_area"
156 : #define CF_PT_AE "azimuthal_equidistant"
157 : #define CF_PT_CEA "cylindrical_equal_area"
158 : #define CF_PT_LAEA "lambert_azimuthal_equal_area"
159 : #define CF_PT_LCEA "lambert_cylindrical_equal_area"
160 : #define CF_PT_LCC "lambert_conformal_conic"
161 : #define CF_PT_TM "transverse_mercator"
162 : #define CF_PT_LATITUDE_LONGITUDE "latitude_longitude"
163 : #define CF_PT_MERCATOR "mercator"
164 : #define CF_PT_ORTHOGRAPHIC "orthographic"
165 : #define CF_PT_POLAR_STEREO "polar_stereographic"
166 : #define CF_PT_STEREO "stereographic"
167 :
168 : /* projection parameters */
169 : #define CF_PP_STD_PARALLEL "standard_parallel"
170 : /* CF uses only "standard_parallel" */
171 : #define CF_PP_STD_PARALLEL_1 "standard_parallel_1"
172 : #define CF_PP_STD_PARALLEL_2 "standard_parallel_2"
173 : #define CF_PP_CENTRAL_MERIDIAN "central_meridian"
174 : #define CF_PP_LONG_CENTRAL_MERIDIAN "longitude_of_central_meridian"
175 : #define CF_PP_LON_PROJ_ORIGIN "longitude_of_projection_origin"
176 : #define CF_PP_LAT_PROJ_ORIGIN "latitude_of_projection_origin"
177 : /* #define PROJ_X_ORIGIN "projection_x_coordinate_origin" */
178 : /* #define PROJ_Y_ORIGIN "projection_y_coordinate_origin" */
179 : #define CF_PP_EARTH_SHAPE "GRIB_earth_shape"
180 : #define CF_PP_EARTH_SHAPE_CODE "GRIB_earth_shape_code"
181 : /* scale_factor is not CF, there are two possible translations */
182 : /* for WKT scale_factor : SCALE_FACTOR_MERIDIAN and SCALE_FACTOR_ORIGIN */
183 : #define CF_PP_SCALE_FACTOR_MERIDIAN "scale_factor_at_central_meridian"
184 : #define CF_PP_SCALE_FACTOR_ORIGIN "scale_factor_at_projection_origin"
185 : #define CF_PP_VERT_LONG_FROM_POLE "straight_vertical_longitude_from_pole"
186 : #define CF_PP_FALSE_EASTING "false_easting"
187 : #define CF_PP_FALSE_NORTHING "false_northing"
188 : #define CF_PP_EARTH_RADIUS "earth_radius"
189 : #define CF_PP_EARTH_RADIUS_OLD "spherical_earth_radius_meters"
190 : #define CF_PP_INVERSE_FLATTENING "inverse_flattening"
191 : #define CF_PP_LONG_PRIME_MERIDIAN "longitude_of_prime_meridian"
192 : #define CF_PP_SEMI_MAJOR_AXIS "semi_major_axis"
193 : #define CF_PP_SEMI_MINOR_AXIS "semi_minor_axis"
194 : #define CF_PP_VERT_PERSP "vertical_perspective" /*not used yet */
195 :
196 :
197 : /* -------------------------------------------------------------------- */
198 : /* CF-1 Coordinate Type Naming (Chapter 4. Coordinate Types ) */
199 : /* -------------------------------------------------------------------- */
200 : static const char* papszCFLongitudeVarNames[] = { "lon", "longitude", NULL };
201 : static const char* papszCFLongitudeAttribNames[] = { "units", CF_STD_NAME, "axis", NULL };
202 : static const char* papszCFLongitudeAttribValues[] = { "degrees_east", "longitude", "X", NULL };
203 : static const char* papszCFLatitudeVarNames[] = { "lat", "latitude", NULL };
204 : static const char* papszCFLatitudeAttribNames[] = { "units", CF_STD_NAME, "axis", NULL };
205 : static const char* papszCFLatitudeAttribValues[] = { "degrees_north", "latitude", "Y", NULL };
206 :
207 : static const char* papszCFProjectionXVarNames[] = { "x", "xc", NULL };
208 : static const char* papszCFProjectionXAttribNames[] = { CF_STD_NAME, NULL };
209 : static const char* papszCFProjectionXAttribValues[] = { CF_PROJ_X_COORD, NULL };
210 : static const char* papszCFProjectionYVarNames[] = { "y", "yc", NULL };
211 : static const char* papszCFProjectionYAttribNames[] = { CF_STD_NAME, NULL };
212 : static const char* papszCFProjectionYAttribValues[] = { CF_PROJ_Y_COORD, NULL };
213 :
214 : static const char* papszCFVerticalAttribNames[] = { "axis", "positive", "positive", NULL };
215 : static const char* papszCFVerticalAttribValues[] = { "Z", "up", "down", NULL };
216 : static const char* papszCFVerticalUnitsValues[] = {
217 : /* units of pressure */
218 : "bar", "bars", "millibar", "millibars", "decibar", "decibars",
219 : "atmosphere", "atmospheres", "atm", "pascal", "pascals", "Pa", "hPa",
220 : /* units of length */
221 : "meter", "meters", "m", "kilometer", "kilometers", "km",
222 : /* dimensionless vertical coordinates */
223 : "level", "layer", "sigma_level",
224 : NULL };
225 : /* dimensionless vertical coordinates */
226 : static const char* papszCFVerticalStandardNameValues[] = {
227 : "atmosphere_ln_pressure_coordinate", "atmosphere_sigma_coordinate",
228 : "atmosphere_hybrid_sigma_pressure_coordinate",
229 : "atmosphere_hybrid_height_coordinate",
230 : "atmosphere_sleve_coordinate", "ocean_sigma_coordinate",
231 : "ocean_s_coordinate", "ocean_sigma_z_coordinate",
232 : "ocean_double_sigma_coordinate", "atmosphere_ln_pressure_coordinate",
233 : "atmosphere_sigma_coordinate",
234 : "atmosphere_hybrid_sigma_pressure_coordinate",
235 : "atmosphere_hybrid_height_coordinate",
236 : "atmosphere_sleve_coordinate", "ocean_sigma_coordinate",
237 : "ocean_s_coordinate", "ocean_sigma_z_coordinate",
238 : "ocean_double_sigma_coordinate", NULL };
239 :
240 : static const char* papszCFTimeAttribNames[] = { "axis", NULL };
241 : static const char* papszCFTimeAttribValues[] = { "T", NULL };
242 : static const char* papszCFTimeUnitsValues[] = {
243 : "days since", "day since", "d since",
244 : "hours since", "hour since", "h since", "hr since",
245 : "minutes since", "minute since", "min since",
246 : "seconds since", "second since", "sec since", "s since",
247 : NULL };
248 :
249 :
250 : /* -------------------------------------------------------------------- */
251 : /* CF-1 to GDAL mappings */
252 : /* -------------------------------------------------------------------- */
253 :
254 : /* Following are a series of mappings from CF-1 convention parameters
255 : * for each projection, to the equivalent in OGC WKT used internally by GDAL.
256 : * See: http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.5/apf.html
257 : */
258 :
259 : /* A struct allowing us to map between GDAL(OGC WKT) and CF-1 attributes */
260 : typedef struct {
261 : const char *CF_ATT;
262 : const char *WKT_ATT;
263 : // TODO: mappings may need default values, like scale factor?
264 : //double defval;
265 : } oNetcdfSRS_PP;
266 :
267 : // default mappings, for the generic case
268 : /* These 'generic' mappings are based on what was previously in the
269 : poNetCDFSRS struct. They will be used as a fallback in case none
270 : of the others match (ie you are exporting a projection that has
271 : no CF-1 equivalent).
272 : They are not used for known CF-1 projections since there is not a
273 : unique 2-way projection-independent
274 : mapping between OGC WKT params and CF-1 ones: it varies per-projection.
275 : */
276 :
277 : static const oNetcdfSRS_PP poGenericMappings[] = {
278 : /* scale_factor is handled as a special case, write 2 values */
279 : {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1 },
280 : {CF_PP_STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2 },
281 : {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN },
282 : {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER },
283 : {CF_PP_LON_PROJ_ORIGIN, SRS_PP_LONGITUDE_OF_ORIGIN },
284 : //Multiple mappings to LAT_PROJ_ORIGIN
285 : {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN },
286 : {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER },
287 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
288 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
289 : {NULL, NULL },
290 : };
291 :
292 : // Albers equal area
293 : //
294 : // grid_mapping_name = albers_conical_equal_area
295 : // WKT: Albers_Conic_Equal_Area
296 : // ESPG:9822
297 : //
298 : // Map parameters:
299 : //
300 : // * standard_parallel - There may be 1 or 2 values.
301 : // * longitude_of_central_meridian
302 : // * latitude_of_projection_origin
303 : // * false_easting
304 : // * false_northing
305 : //
306 : static const oNetcdfSRS_PP poAEAMappings[] = {
307 : {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
308 : {CF_PP_STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2},
309 : {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER},
310 : {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_LONGITUDE_OF_CENTER},
311 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
312 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
313 : {NULL, NULL}
314 : };
315 :
316 : // Azimuthal equidistant
317 : //
318 : // grid_mapping_name = azimuthal_equidistant
319 : // WKT: Azimuthal_Equidistant
320 : //
321 : // Map parameters:
322 : //
323 : // * longitude_of_projection_origin
324 : // * latitude_of_projection_origin
325 : // * false_easting
326 : // * false_northing
327 : //
328 : static const oNetcdfSRS_PP poAEMappings[] = {
329 : {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER},
330 : {CF_PP_LON_PROJ_ORIGIN, SRS_PP_LONGITUDE_OF_CENTER},
331 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
332 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
333 : {NULL, NULL}
334 : };
335 :
336 : // Lambert azimuthal equal area
337 : //
338 : // grid_mapping_name = lambert_azimuthal_equal_area
339 : // WKT: Lambert_Azimuthal_Equal_Area
340 : //
341 : // Map parameters:
342 : //
343 : // * longitude_of_projection_origin
344 : // * latitude_of_projection_origin
345 : // * false_easting
346 : // * false_northing
347 : //
348 : static const oNetcdfSRS_PP poLAEAMappings[] = {
349 : {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_CENTER},
350 : {CF_PP_LON_PROJ_ORIGIN, SRS_PP_LONGITUDE_OF_CENTER},
351 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
352 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
353 : {NULL, NULL}
354 : };
355 :
356 : // Lambert conformal
357 : //
358 : // grid_mapping_name = lambert_conformal_conic
359 : // WKT: Lambert_Conformal_Conic_1SP / Lambert_Conformal_Conic_2SP
360 : //
361 : // Map parameters:
362 : //
363 : // * standard_parallel - There may be 1 or 2 values.
364 : // * longitude_of_central_meridian
365 : // * latitude_of_projection_origin
366 : // * false_easting
367 : // * false_northing
368 : //
369 : // See http://www.remotesensing.org/geotiff/proj_list/lambert_conic_conformal_1sp.html
370 :
371 : // Lambert conformal conic - 1SP
372 : /* See bug # 3324
373 : It seems that the missing scale factor can be computed from standard_parallel1 and latitude_of_projection_origin.
374 : If both are equal (the common case) then scale factor=1, else use Snyder eq. 15-4.
375 : We save in the WKT standard_parallel1 for export to CF, but do not export scale factor.
376 : If a WKT has a scale factor != 1 and no standard_parallel1 then export is not CF, but we output scale factor for compat.
377 : is there a formula for that?
378 : */
379 : static const oNetcdfSRS_PP poLCC1SPMappings[] = {
380 : {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
381 : {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
382 : {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
383 : {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR}, /* special case */
384 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
385 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
386 : {NULL, NULL}
387 : };
388 :
389 : // Lambert conformal conic - 2SP
390 : static const oNetcdfSRS_PP poLCC2SPMappings[] = {
391 : {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
392 : {CF_PP_STD_PARALLEL_2, SRS_PP_STANDARD_PARALLEL_2},
393 : {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
394 : {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
395 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
396 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
397 : {NULL, NULL}
398 : };
399 :
400 : // Lambert cylindrical equal area
401 : //
402 : // grid_mapping_name = lambert_cylindrical_equal_area
403 : // WKT: Cylindrical_Equal_Area
404 : // EPSG:9834 (Spherical) and EPSG:9835
405 : //
406 : // Map parameters:
407 : //
408 : // * longitude_of_central_meridian
409 : // * either standard_parallel or scale_factor_at_projection_origin
410 : // * false_easting
411 : // * false_northing
412 : //
413 : // NB: CF-1 specifies a 'scale_factor_at_projection' alternative
414 : // to std_parallel ... but no reference to this in EPSG/remotesensing.org
415 : // ignore for now.
416 : //
417 : static const oNetcdfSRS_PP poLCEAMappings[] = {
418 : {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
419 : {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
420 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
421 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
422 : {NULL, NULL}
423 : };
424 :
425 : // Latitude-Longitude
426 : //
427 : // grid_mapping_name = latitude_longitude
428 : //
429 : // Map parameters:
430 : //
431 : // * None
432 : //
433 : // NB: handled as a special case - !isProjected()
434 :
435 :
436 : // Mercator
437 : //
438 : // grid_mapping_name = mercator
439 : // WKT: Mercator_1SP / Mercator_2SP
440 : //
441 : // Map parameters:
442 : //
443 : // * longitude_of_projection_origin
444 : // * either standard_parallel or scale_factor_at_projection_origin
445 : // * false_easting
446 : // * false_northing
447 :
448 : // Mercator 1 Standard Parallel (EPSG:9804)
449 : static const oNetcdfSRS_PP poM1SPMappings[] = {
450 : {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
451 : //LAT_PROJ_ORIGIN is always equator (0) in CF-1
452 : {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR},
453 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
454 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
455 : {NULL, NULL}
456 : };
457 :
458 : // Mercator 2 Standard Parallel
459 : static const oNetcdfSRS_PP poM2SPMappings[] = {
460 : {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
461 : {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
462 : //From best understanding of this projection, only
463 : // actually specify one SP - it is the same N/S of equator.
464 : //{CF_PP_STD_PARALLEL_2, SRS_PP_LATITUDE_OF_ORIGIN},
465 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
466 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
467 : {NULL, NULL}
468 : };
469 :
470 : // Orthographic
471 : // grid_mapping_name = orthographic
472 : // WKT: Orthographic
473 : //
474 : // Map parameters:
475 : //
476 : // * longitude_of_projection_origin
477 : // * latitude_of_projection_origin
478 : // * false_easting
479 : // * false_northing
480 : //
481 : static const oNetcdfSRS_PP poOrthoMappings[] = {
482 : {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
483 : {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
484 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
485 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
486 : {NULL, NULL}
487 : };
488 :
489 : // Polar stereographic
490 : //
491 : // grid_mapping_name = polar_stereographic
492 : // WKT: Polar_Stereographic
493 : //
494 : // Map parameters:
495 : //
496 : // * straight_vertical_longitude_from_pole
497 : // * latitude_of_projection_origin - Either +90. or -90.
498 : // * Either standard_parallel or scale_factor_at_projection_origin
499 : // * false_easting
500 : // * false_northing
501 :
502 : /*
503 : (http://www.remotesensing.org/geotiff/proj_list/polar_stereographic.html)
504 :
505 : Note: Projection parameters for this projection are quite different in CF-1 from
506 : OGC WKT/GeoTiff (for the latter, see above).
507 : From our best understanding, this projection requires more than a straight mapping:
508 : - As defined below, 'latitude_of_origin' (WKT) -> 'standard_parallel' (CF-1)
509 : and 'central_meridian' (WKT) -> 'straight_vertical_longitude_from_pole' (CF-1)
510 : - Then the 'latitude_of_projection_origin' in CF-1 must be set to either +90 or -90,
511 : depending on the sign of 'latitude_of_origin' in WKT.
512 : CF allows the use of standard_parallel (lat_ts in proj4) OR scale_factor (k0 in proj4).
513 : This is analogous to the B and A variants (resp.) in EPSG guidelines.
514 : When importing a CF file with scale_factor, we compute standard_parallel using
515 : Snyder eq. 22-7 with k=1 and lat=standard_parallel.
516 : Currently OGR does NOT relate the scale factor with the standard parallel, so we
517 : use the default. It seems that proj4 uses lat_ts (standard_parallel) and not k0.
518 : */
519 : static const oNetcdfSRS_PP poPSmappings[] = {
520 : {CF_PP_STD_PARALLEL_1, SRS_PP_LATITUDE_OF_ORIGIN},
521 : /* {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR}, */
522 : {CF_PP_VERT_LONG_FROM_POLE, SRS_PP_CENTRAL_MERIDIAN},
523 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
524 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
525 : {NULL, NULL}
526 : };
527 :
528 : // Rotated Pole
529 : //
530 : // grid_mapping_name = rotated_latitude_longitude
531 : // WKT: N/A
532 : //
533 : // Map parameters:
534 : //
535 : // * grid_north_pole_latitude
536 : // * grid_north_pole_longitude
537 : // * north_pole_grid_longitude - This parameter is optional (default is 0.).
538 :
539 : /* TODO: No GDAL equivalent of rotated pole? Doesn't seem to have an EPSG
540 : code or WKT ... so unless some advanced proj4 features can be used
541 : seems to rule out.
542 : see GDAL bug #4285 for a possible fix or workaround
543 : */
544 :
545 : // Stereographic
546 : //
547 : // grid_mapping_name = stereographic
548 : // WKT: Stereographic (and/or Oblique_Stereographic??)
549 : //
550 : // Map parameters:
551 : //
552 : // * longitude_of_projection_origin
553 : // * latitude_of_projection_origin
554 : // * scale_factor_at_projection_origin
555 : // * false_easting
556 : // * false_northing
557 : //
558 : // NB: see bug#4267 Stereographic vs. Oblique_Stereographic
559 : //
560 : static const oNetcdfSRS_PP poStMappings[] = {
561 : {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
562 : {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
563 : {CF_PP_SCALE_FACTOR_ORIGIN, SRS_PP_SCALE_FACTOR},
564 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
565 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
566 : {NULL, NULL}
567 : };
568 :
569 : // Transverse Mercator
570 : //
571 : // grid_mapping_name = transverse_mercator
572 : // WKT: Transverse_Mercator
573 : //
574 : // Map parameters:
575 : //
576 : // * scale_factor_at_central_meridian
577 : // * longitude_of_central_meridian
578 : // * latitude_of_projection_origin
579 : // * false_easting
580 : // * false_northing
581 : //
582 : static const oNetcdfSRS_PP poTMMappings[] = {
583 : {CF_PP_SCALE_FACTOR_MERIDIAN, SRS_PP_SCALE_FACTOR},
584 : {CF_PP_LONG_CENTRAL_MERIDIAN, SRS_PP_CENTRAL_MERIDIAN},
585 : {CF_PP_LAT_PROJ_ORIGIN, SRS_PP_LATITUDE_OF_ORIGIN},
586 : {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
587 : {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
588 : {NULL, NULL}
589 : };
590 :
591 : // Vertical perspective
592 : //
593 : // grid_mapping_name = vertical_perspective
594 : // WKT: ???
595 : //
596 : // Map parameters:
597 : //
598 : // * latitude_of_projection_origin
599 : // * longitude_of_projection_origin
600 : // * perspective_point_height
601 : // * false_easting
602 : // * false_northing
603 : //
604 : // TODO: see how to map this to OGR
605 :
606 :
607 : /* Mappings for various projections, including netcdf and GDAL projection names
608 : and corresponding oNetcdfSRS_PP mapping struct.
609 : A NULL mappings value means that the projection is not included in the CF
610 : standard and the generic mapping (poGenericMappings) will be used. */
611 : typedef struct {
612 : const char *CF_SRS;
613 : const char *WKT_SRS;
614 : const oNetcdfSRS_PP* mappings;
615 : } oNetcdfSRS_PT;
616 :
617 : static const oNetcdfSRS_PT poNetcdfSRS_PT[] = {
618 : {CF_PT_AEA, SRS_PT_ALBERS_CONIC_EQUAL_AREA, poAEAMappings },
619 : {CF_PT_AE, SRS_PT_AZIMUTHAL_EQUIDISTANT, poAEMappings },
620 : {"cassini_soldner", SRS_PT_CASSINI_SOLDNER, NULL },
621 : {CF_PT_LCEA, SRS_PT_CYLINDRICAL_EQUAL_AREA, poLCEAMappings },
622 : {"eckert_iv", SRS_PT_ECKERT_IV, NULL },
623 : {"eckert_vi", SRS_PT_ECKERT_VI, NULL },
624 : {"equidistant_conic", SRS_PT_EQUIDISTANT_CONIC, NULL },
625 : {"equirectangular", SRS_PT_EQUIRECTANGULAR, NULL },
626 : {"gall_stereographic", SRS_PT_GALL_STEREOGRAPHIC, NULL },
627 : {"geostationary_satellite", SRS_PT_GEOSTATIONARY_SATELLITE, NULL },
628 : {"goode_homolosine", SRS_PT_GOODE_HOMOLOSINE, NULL },
629 : {"gnomonic", SRS_PT_GNOMONIC, NULL },
630 : {"hotine_oblique_mercator", SRS_PT_HOTINE_OBLIQUE_MERCATOR, NULL },
631 : {"hotine_oblique_mercator_2P",
632 : SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN, NULL },
633 : {"laborde_oblique_mercator", SRS_PT_LABORDE_OBLIQUE_MERCATOR, NULL },
634 : {CF_PT_LCC, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP, poLCC1SPMappings },
635 : {CF_PT_LCC, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP, poLCC2SPMappings },
636 : {CF_PT_LAEA, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA, poLAEAMappings },
637 : {CF_PT_MERCATOR, SRS_PT_MERCATOR_1SP, poM1SPMappings },
638 : {CF_PT_MERCATOR, SRS_PT_MERCATOR_2SP, poM2SPMappings },
639 : {"miller_cylindrical", SRS_PT_MILLER_CYLINDRICAL, NULL },
640 : {"mollweide", SRS_PT_MOLLWEIDE, NULL },
641 : {"new_zealand_map_grid", SRS_PT_NEW_ZEALAND_MAP_GRID, NULL },
642 : /* for now map to STEREO, see bug #4267 */
643 : {"oblique_stereographic", SRS_PT_OBLIQUE_STEREOGRAPHIC, NULL },
644 : /* {STEREO, SRS_PT_OBLIQUE_STEREOGRAPHIC, poStMappings }, */
645 : {CF_PT_ORTHOGRAPHIC, SRS_PT_ORTHOGRAPHIC, poOrthoMappings },
646 : {CF_PT_POLAR_STEREO, SRS_PT_POLAR_STEREOGRAPHIC, poPSmappings },
647 : {"polyconic", SRS_PT_POLYCONIC, NULL },
648 : {"robinson", SRS_PT_ROBINSON, NULL },
649 : {"sinusoidal", SRS_PT_SINUSOIDAL, NULL },
650 : {CF_PT_STEREO, SRS_PT_STEREOGRAPHIC, poStMappings },
651 : {"swiss_oblique_cylindrical", SRS_PT_SWISS_OBLIQUE_CYLINDRICAL, NULL },
652 : {CF_PT_TM, SRS_PT_TRANSVERSE_MERCATOR, poTMMappings },
653 : {"TM_south_oriented", SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED, NULL },
654 : {NULL, NULL, NULL },
655 : };
656 :
657 : /************************************************************************/
658 : /* ==================================================================== */
659 : /* netCDFDataset */
660 : /* ==================================================================== */
661 : /************************************************************************/
662 :
663 : class netCDFRasterBand;
664 :
665 : class netCDFDataset : public GDALPamDataset
666 : {
667 : friend class netCDFRasterBand; //TMP
668 :
669 : /* basic dataset vars */
670 : CPLString osFilename;
671 : int cdfid;
672 : char **papszSubDatasets;
673 : char **papszMetadata;
674 : CPLStringList papszDimName;
675 : bool bBottomUp;
676 : int nFormat;
677 : int bIsGdalFile; /* was this file created by GDAL? */
678 : int bIsGdalCfFile; /* was this file created by the (new) CF-compliant driver? */
679 : char *pszCFProjection;
680 : char *pszCFCoordinates;
681 :
682 : /* projection/GT */
683 : double adfGeoTransform[6];
684 : char *pszProjection;
685 : int nXDimID;
686 : int nYDimID;
687 : int bIsProjected;
688 : int bIsGeographic;
689 :
690 : /* state vars */
691 : int status;
692 : int bDefineMode;
693 : int bSetProjection;
694 : int bSetGeoTransform;
695 : int bAddedProjectionVars;
696 : int bAddedGridMappingRef;
697 :
698 : /* create vars */
699 : char **papszCreationOptions;
700 : int nCompress;
701 : int nZLevel;
702 : int nCreateMode;
703 : int bSignedData;
704 :
705 : double rint( double );
706 :
707 : double FetchCopyParm( const char *pszGridMappingValue,
708 : const char *pszParm, double dfDefault );
709 :
710 : char ** FetchStandardParallels( const char *pszGridMappingValue );
711 :
712 : void ProcessCreationOptions( );
713 : int DefVarDeflate( int nVarId, int bChunking=TRUE );
714 : CPLErr AddProjectionVars( GDALProgressFunc pfnProgress=GDALDummyProgress,
715 : void * pProgressData=NULL );
716 : void AddGridMappingRef();
717 :
718 160 : int GetDefineMode() { return bDefineMode; }
719 : int SetDefineMode( int bNewDefineMode );
720 :
721 : CPLErr ReadAttributes( int, int );
722 :
723 : void CreateSubDatasetList( );
724 :
725 : void SetProjectionFromVar( int );
726 :
727 : int ProcessCFGeolocation( int );
728 : CPLErr Set1DGeolocation( int nVarId, const char *szDimName );
729 : double * Get1DGeolocation( const char *szDimName, int &nVarLen );
730 :
731 : protected:
732 :
733 : CPLXMLNode *SerializeToXML( const char *pszVRTPath );
734 :
735 : public:
736 :
737 : netCDFDataset( );
738 : ~netCDFDataset( );
739 :
740 : /* Projection/GT */
741 : CPLErr GetGeoTransform( double * );
742 : CPLErr SetGeoTransform (double *);
743 : const char * GetProjectionRef();
744 : CPLErr SetProjection (const char *);
745 :
746 : char ** GetMetadata( const char * );
747 :
748 836 : int GetCDFID() { return cdfid; }
749 :
750 : /* static functions */
751 : static int Identify( GDALOpenInfo * );
752 : static int IdentifyFormat( GDALOpenInfo *, bool );
753 : static GDALDataset *Open( GDALOpenInfo * );
754 :
755 : static netCDFDataset *CreateLL( const char * pszFilename,
756 : int nXSize, int nYSize, int nBands,
757 : char ** papszOptions );
758 : static GDALDataset *Create( const char * pszFilename,
759 : int nXSize, int nYSize, int nBands,
760 : GDALDataType eType,
761 : char ** papszOptions );
762 : static GDALDataset* CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
763 : int bStrict, char ** papszOptions,
764 : GDALProgressFunc pfnProgress, void * pProgressData );
765 :
766 : };
767 :
768 : #endif
|