1 : /******************************************************************************
2 : * $Id: usgsdemdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
3 : *
4 : * Project: USGS DEM Driver
5 : * Purpose: All reader for USGS DEM Reader
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : * Portions of this module derived from the VTP USGS DEM driver by Ben
9 : * Discoe, see http://www.vterrain.org
10 : *
11 : ******************************************************************************
12 : * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
13 : *
14 : * Permission is hereby granted, free of charge, to any person obtaining a
15 : * copy of this software and associated documentation files (the "Software"),
16 : * to deal in the Software without restriction, including without limitation
17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 : * and/or sell copies of the Software, and to permit persons to whom the
19 : * Software is furnished to do so, subject to the following conditions:
20 : *
21 : * The above copyright notice and this permission notice shall be included
22 : * in all copies or substantial portions of the Software.
23 : *
24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 : * DEALINGS IN THE SOFTWARE.
31 : ****************************************************************************/
32 :
33 : #include "gdal_pam.h"
34 : #include "ogr_spatialref.h"
35 :
36 : CPL_CVSID("$Id: usgsdemdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
37 :
38 : CPL_C_START
39 : void GDALRegister_USGSDEM(void);
40 : CPL_C_END
41 :
42 : typedef struct {
43 : double x;
44 : double y;
45 : } DPoint2;
46 :
47 : #define USGSDEM_NODATA -32767
48 :
49 : GDALDataset *USGSDEMCreateCopy( const char *, GDALDataset *, int, char **,
50 : GDALProgressFunc pfnProgress,
51 : void * pProgressData );
52 :
53 : /************************************************************************/
54 : /* DConvert() */
55 : /************************************************************************/
56 :
57 1598 : static double DConvert( FILE *fp, int nCharCount )
58 :
59 : {
60 : char szBuffer[100];
61 : int i;
62 :
63 1598 : VSIFRead( szBuffer, nCharCount, 1, fp );
64 1598 : szBuffer[nCharCount] = '\0';
65 :
66 40238 : for( i = 0; i < nCharCount; i++ )
67 : {
68 38640 : if( szBuffer[i] == 'D' )
69 1575 : szBuffer[i] = 'E';
70 : }
71 :
72 1598 : return atof(szBuffer);
73 : }
74 :
75 : /************************************************************************/
76 : /* ==================================================================== */
77 : /* USGSDEMDataset */
78 : /* ==================================================================== */
79 : /************************************************************************/
80 :
81 : class USGSDEMRasterBand;
82 :
83 : class USGSDEMDataset : public GDALPamDataset
84 : {
85 : friend class USGSDEMRasterBand;
86 :
87 : int nDataStartOffset;
88 : GDALDataType eNaturalDataFormat;
89 :
90 : double adfGeoTransform[6];
91 : char *pszProjection;
92 :
93 : double fVRes;
94 :
95 : const char *pszUnits;
96 :
97 : int LoadFromFile( FILE * );
98 :
99 : FILE *fp;
100 :
101 : public:
102 : USGSDEMDataset();
103 : ~USGSDEMDataset();
104 :
105 : static int Identify( GDALOpenInfo * );
106 : static GDALDataset *Open( GDALOpenInfo * );
107 : CPLErr GetGeoTransform( double * padfTransform );
108 : const char *GetProjectionRef();
109 : };
110 :
111 : /************************************************************************/
112 : /* ==================================================================== */
113 : /* USGSDEMRasterBand */
114 : /* ==================================================================== */
115 : /************************************************************************/
116 :
117 : class USGSDEMRasterBand : public GDALPamRasterBand
118 48 : {
119 : friend class USGSDEMDataset;
120 :
121 : public:
122 :
123 : USGSDEMRasterBand( USGSDEMDataset * );
124 :
125 : virtual const char *GetUnitType();
126 : virtual double GetNoDataValue( int *pbSuccess = NULL );
127 : virtual CPLErr IReadBlock( int, int, void * );
128 : };
129 :
130 :
131 : /************************************************************************/
132 : /* USGSDEMRasterBand() */
133 : /************************************************************************/
134 :
135 24 : USGSDEMRasterBand::USGSDEMRasterBand( USGSDEMDataset *poDS )
136 :
137 : {
138 24 : this->poDS = poDS;
139 24 : this->nBand = 1;
140 :
141 24 : eDataType = poDS->eNaturalDataFormat;
142 :
143 24 : nBlockXSize = poDS->GetRasterXSize();
144 24 : nBlockYSize = poDS->GetRasterYSize();
145 :
146 24 : }
147 :
148 : /************************************************************************/
149 : /* IReadBlock() */
150 : /************************************************************************/
151 :
152 10 : CPLErr USGSDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
153 : void * pImage )
154 :
155 : {
156 : double dfYMin;
157 10 : int bad = FALSE;
158 10 : USGSDEMDataset *poGDS = (USGSDEMDataset *) poDS;
159 :
160 : /* -------------------------------------------------------------------- */
161 : /* Initialize image buffer to nodata value. */
162 : /* -------------------------------------------------------------------- */
163 40678 : for( int k = GetXSize() * GetYSize() - 1; k >= 0; k-- )
164 : {
165 40668 : if( GetRasterDataType() == GDT_Int16 )
166 37846 : ((GInt16 *) pImage)[k] = USGSDEM_NODATA;
167 : else
168 2822 : ((float *) pImage)[k] = USGSDEM_NODATA;
169 : }
170 :
171 : /* -------------------------------------------------------------------- */
172 : /* Seek to data. */
173 : /* -------------------------------------------------------------------- */
174 10 : VSIFSeek(poGDS->fp, poGDS->nDataStartOffset, 0);
175 :
176 10 : dfYMin = poGDS->adfGeoTransform[3]
177 10 : + (GetYSize()-0.5) * poGDS->adfGeoTransform[5];
178 :
179 : /* -------------------------------------------------------------------- */
180 : /* Read all the profiles into the image buffer. */
181 : /* -------------------------------------------------------------------- */
182 266 : for( int i = 0; i < GetXSize(); i++)
183 : {
184 : int njunk, nCPoints, lygap;
185 : double djunk, dxStart, dyStart, dfElevOffset;
186 :
187 256 : fscanf(poGDS->fp, "%d", &njunk);
188 256 : fscanf(poGDS->fp, "%d", &njunk);
189 256 : fscanf(poGDS->fp, "%d", &nCPoints);
190 256 : fscanf(poGDS->fp, "%d", &njunk);
191 :
192 256 : dxStart = DConvert(poGDS->fp, 24);
193 256 : dyStart = DConvert(poGDS->fp, 24);
194 256 : dfElevOffset = DConvert(poGDS->fp, 24);
195 256 : djunk = DConvert(poGDS->fp, 24);
196 256 : djunk = DConvert(poGDS->fp, 24);
197 :
198 256 : if( strstr(poGDS->pszProjection,"PROJCS") == NULL )
199 246 : dyStart = dyStart / 3600.0;
200 :
201 256 : lygap = (int)((dfYMin - dyStart)/poGDS->adfGeoTransform[5]+ 0.5);
202 :
203 39494 : for (int j=lygap; j < (nCPoints+(int)lygap); j++)
204 : {
205 39238 : int iY = GetYSize() - j - 1;
206 : int nElev;
207 :
208 39238 : fscanf(poGDS->fp, "%d", &nElev);
209 39238 : if (iY < 0 || iY >= GetYSize() )
210 0 : bad = TRUE;
211 39238 : else if( nElev == USGSDEM_NODATA )
212 : /* leave in output buffer as nodata */;
213 : else
214 : {
215 : float fComputedElev =
216 33846 : (float)(nElev * poGDS->fVRes + dfElevOffset);
217 :
218 33846 : if( GetRasterDataType() == GDT_Int16 )
219 : {
220 33785 : ((GInt16 *) pImage)[i + iY*GetXSize()] =
221 33785 : (GInt16) fComputedElev;
222 : }
223 : else
224 : {
225 61 : ((float *) pImage)[i + iY*GetXSize()] = fComputedElev;
226 : }
227 : }
228 : }
229 : }
230 :
231 10 : return CE_None;
232 : }
233 :
234 : /************************************************************************/
235 : /* GetNoDataValue() */
236 : /************************************************************************/
237 :
238 16 : double USGSDEMRasterBand::GetNoDataValue( int *pbSuccess )
239 :
240 : {
241 16 : if( pbSuccess != NULL )
242 14 : *pbSuccess = TRUE;
243 :
244 16 : return USGSDEM_NODATA;
245 : }
246 :
247 : /************************************************************************/
248 : /* GetUnitType() */
249 : /************************************************************************/
250 9 : const char *USGSDEMRasterBand::GetUnitType()
251 : {
252 9 : USGSDEMDataset *poGDS = (USGSDEMDataset *) poDS;
253 :
254 9 : return poGDS->pszUnits;
255 : }
256 :
257 : /************************************************************************/
258 : /* ==================================================================== */
259 : /* USGSDEMDataset */
260 : /* ==================================================================== */
261 : /************************************************************************/
262 :
263 : /************************************************************************/
264 : /* USGSDEMDataset() */
265 : /************************************************************************/
266 :
267 24 : USGSDEMDataset::USGSDEMDataset()
268 :
269 : {
270 24 : fp = NULL;
271 24 : pszProjection = NULL;
272 24 : }
273 :
274 : /************************************************************************/
275 : /* ~USGSDEMDataset() */
276 : /************************************************************************/
277 :
278 48 : USGSDEMDataset::~USGSDEMDataset()
279 :
280 : {
281 24 : FlushCache();
282 :
283 24 : CPLFree( pszProjection );
284 24 : if( fp != NULL )
285 24 : VSIFClose( fp );
286 48 : }
287 :
288 : /************************************************************************/
289 : /* LoadFromFile() */
290 : /* */
291 : /* If the data from DEM is in meters, then values are stored as */
292 : /* shorts. If DEM data is in feet, then height data will be */
293 : /* stored in float, to preserve the precision of the original */
294 : /* data. returns true if the file was successfully opened and */
295 : /* read. */
296 : /************************************************************************/
297 :
298 24 : int USGSDEMDataset::LoadFromFile(FILE *InDem)
299 : {
300 : int i, j;
301 : int nRow, nColumn;
302 : int nVUnit, nGUnit;
303 : double dxdelta, dydelta;
304 : double dElevMax, dElevMin;
305 : int bNewFormat;
306 : int nCoordSystem;
307 : int nProfiles;
308 : char szDateBuffer[5];
309 : DPoint2 corners[4]; // SW, NW, NE, SE
310 : DPoint2 extent_min, extent_max;
311 : int iUTMZone;
312 :
313 : // check for version of DEM format
314 24 : VSIFSeek(InDem, 864, 0);
315 :
316 : // Read DEM into matrix
317 24 : fscanf(InDem, "%d", &nRow);
318 24 : fscanf(InDem, "%d", &nColumn);
319 24 : bNewFormat = ((nRow!=1)||(nColumn!=1));
320 24 : if (bNewFormat)
321 : {
322 23 : VSIFSeek(InDem, 1024, 0); // New Format
323 23 : fscanf(InDem, "%d", &i);
324 23 : fscanf(InDem, "%d", &j);
325 24 : if ((i!=1)||(j!=1 && j != 0)) // File OK?
326 : {
327 1 : VSIFSeek(InDem, 893, 0); // Undocumented Format (39109h1.dem)
328 1 : fscanf(InDem, "%d", &i);
329 1 : fscanf(InDem, "%d", &j);
330 1 : if ((i!=1)||(j!=1)) // File OK?
331 : {
332 : CPLError( CE_Failure, CPLE_AppDefined,
333 0 : "Does not appear to be a USGS DEM file." );
334 0 : return FALSE;
335 : }
336 : else
337 1 : nDataStartOffset = 893;
338 : }
339 : else
340 22 : nDataStartOffset = 1024;
341 : }
342 : else
343 1 : nDataStartOffset = 864;
344 :
345 24 : VSIFSeek(InDem, 156, 0);
346 24 : fscanf(InDem, "%d", &nCoordSystem);
347 24 : fscanf(InDem, "%d", &iUTMZone);
348 :
349 24 : VSIFSeek(InDem, 528, 0);
350 24 : fscanf(InDem, "%d", &nGUnit);
351 24 : fscanf(InDem, "%d", &nVUnit);
352 :
353 : // Vertical Units in meters
354 24 : if (nVUnit==1)
355 0 : pszUnits = "ft";
356 : else
357 24 : pszUnits = "m";
358 :
359 24 : VSIFSeek(InDem, 816, 0);
360 24 : dxdelta = DConvert(InDem, 12);
361 24 : dydelta = DConvert(InDem, 12);
362 24 : fVRes = DConvert(InDem, 12);
363 :
364 : /* -------------------------------------------------------------------- */
365 : /* Should we treat this as floating point, or GInt16. */
366 : /* -------------------------------------------------------------------- */
367 25 : if (nVUnit==1 || fVRes < 1.0)
368 1 : eNaturalDataFormat = GDT_Float32;
369 : else
370 23 : eNaturalDataFormat = GDT_Int16;
371 :
372 : /* -------------------------------------------------------------------- */
373 : /* Read four corner coordinates. */
374 : /* -------------------------------------------------------------------- */
375 24 : VSIFSeek(InDem, 546, 0);
376 120 : for (i = 0; i < 4; i++)
377 : {
378 96 : corners[i].x = DConvert(InDem, 24);
379 96 : corners[i].y = DConvert(InDem, 24);
380 : }
381 :
382 : // find absolute extents of raw vales
383 24 : extent_min.x = MIN(corners[0].x, corners[1].x);
384 24 : extent_max.x = MAX(corners[2].x, corners[3].x);
385 24 : extent_min.y = MIN(corners[0].y, corners[3].y);
386 24 : extent_max.y = MAX(corners[1].y, corners[2].y);
387 :
388 24 : dElevMin = DConvert(InDem, 48);
389 24 : dElevMax = DConvert(InDem, 48);
390 :
391 24 : VSIFSeek(InDem, 858, 0);
392 24 : fscanf(InDem, "%d", &nProfiles);
393 :
394 : /* -------------------------------------------------------------------- */
395 : /* Collect the spatial reference system. */
396 : /* -------------------------------------------------------------------- */
397 24 : OGRSpatialReference sr;
398 :
399 : // OLD format header ends at byte 864
400 24 : if (bNewFormat)
401 : {
402 : char szHorzDatum[3];
403 :
404 : // year of data compilation
405 23 : VSIFSeek(InDem, 876, 0);
406 23 : fread(szDateBuffer, 4, 1, InDem);
407 23 : szDateBuffer[4] = 0;
408 :
409 : // Horizontal datum
410 : // 1=North American Datum 1927 (NAD 27)
411 : // 2=World Geodetic System 1972 (WGS 72)
412 : // 3=WGS 84
413 : // 4=NAD 83
414 : // 5=Old Hawaii Datum
415 : // 6=Puerto Rico Datum
416 : int datum;
417 23 : VSIFSeek(InDem, 890, 0);
418 23 : VSIFRead( szHorzDatum, 1, 2, InDem );
419 23 : szHorzDatum[2] = '\0';
420 23 : datum = atoi(szHorzDatum);
421 23 : switch (datum)
422 : {
423 : case 1:
424 1 : sr.SetWellKnownGeogCS( "NAD27" );
425 1 : break;
426 :
427 : case 2:
428 5 : sr.SetWellKnownGeogCS( "WGS72" );
429 5 : break;
430 :
431 : case 3:
432 14 : sr.SetWellKnownGeogCS( "WGS84" );
433 14 : break;
434 :
435 : case 4:
436 1 : sr.SetWellKnownGeogCS( "NAD83" );
437 1 : break;
438 :
439 : default:
440 2 : sr.SetWellKnownGeogCS( "NAD27" );
441 : break;
442 : }
443 : }
444 : else
445 1 : sr.SetWellKnownGeogCS( "NAD27" );
446 :
447 24 : if (nCoordSystem == 1) // UTM
448 6 : sr.SetUTM( iUTMZone, TRUE );
449 :
450 24 : sr.exportToWkt( &pszProjection );
451 :
452 : /* -------------------------------------------------------------------- */
453 : /* For UTM we use the extents (really the UTM coordinates of */
454 : /* the lat/long corners of the quad) to determine the size in */
455 : /* pixels and lines, but we have to make the anchors be modulus */
456 : /* the pixel size which what really gets used. */
457 : /* -------------------------------------------------------------------- */
458 24 : if (nCoordSystem == 1) // UTM
459 : {
460 : int njunk;
461 : double dxStart;
462 :
463 : // expand extents modulus the pixel size.
464 6 : extent_min.y = floor(extent_min.y/dydelta) * dydelta;
465 6 : extent_max.y = ceil(extent_max.y/dydelta) * dydelta;
466 :
467 : // Forceably compute X extents based on first profile and pixelsize.
468 6 : VSIFSeek(InDem, nDataStartOffset, 0);
469 6 : fscanf(InDem, "%d", &njunk);
470 6 : fscanf(InDem, "%d", &njunk);
471 6 : fscanf(InDem, "%d", &njunk);
472 6 : fscanf(InDem, "%d", &njunk);
473 6 : dxStart = DConvert(InDem, 24);
474 :
475 6 : nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5);
476 6 : nRasterXSize = nProfiles;
477 :
478 6 : adfGeoTransform[0] = dxStart - dxdelta/2.0;
479 6 : adfGeoTransform[1] = dxdelta;
480 6 : adfGeoTransform[2] = 0.0;
481 6 : adfGeoTransform[3] = extent_max.y + dydelta/2.0;
482 6 : adfGeoTransform[4] = 0.0;
483 6 : adfGeoTransform[5] = -dydelta;
484 : }
485 : /* -------------------------------------------------------------------- */
486 : /* Geographic -- use corners directly. */
487 : /* -------------------------------------------------------------------- */
488 : else
489 : {
490 18 : nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5);
491 18 : nRasterXSize = nProfiles;
492 :
493 : // Translate extents from arc-seconds to decimal degrees.
494 18 : adfGeoTransform[0] = (extent_min.x - dxdelta/2.0) / 3600.0;
495 18 : adfGeoTransform[1] = dxdelta / 3600.0;
496 18 : adfGeoTransform[2] = 0.0;
497 18 : adfGeoTransform[3] = (extent_max.y + dydelta/2.0) / 3600.0;
498 18 : adfGeoTransform[4] = 0.0;
499 18 : adfGeoTransform[5] = (-dydelta) / 3600.0;
500 : }
501 :
502 24 : if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
503 : {
504 0 : return FALSE;
505 : }
506 :
507 24 : return TRUE;
508 : }
509 :
510 : /************************************************************************/
511 : /* GetGeoTransform() */
512 : /************************************************************************/
513 :
514 31 : CPLErr USGSDEMDataset::GetGeoTransform( double * padfTransform )
515 :
516 : {
517 31 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
518 31 : return CE_None;
519 : }
520 :
521 : /************************************************************************/
522 : /* GetProjectionRef() */
523 : /************************************************************************/
524 :
525 47 : const char *USGSDEMDataset::GetProjectionRef()
526 :
527 : {
528 47 : return pszProjection;
529 : }
530 :
531 :
532 : /************************************************************************/
533 : /* Identify() */
534 : /************************************************************************/
535 :
536 8490 : int USGSDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
537 :
538 : {
539 8490 : if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 200 )
540 8343 : return FALSE;
541 :
542 147 : if( !EQUALN((const char *) poOpenInfo->pabyHeader+156, " 0",6)
543 : && !EQUALN((const char *) poOpenInfo->pabyHeader+156, " 1",6)
544 : && !EQUALN((const char *) poOpenInfo->pabyHeader+156, " 2",6)
545 : && !EQUALN((const char *) poOpenInfo->pabyHeader+156, " 3",6) )
546 123 : return FALSE;
547 :
548 24 : if( !EQUALN((const char *) poOpenInfo->pabyHeader+150, " 1",6)
549 : && !EQUALN((const char *) poOpenInfo->pabyHeader+150, " 4",6))
550 0 : return FALSE;
551 :
552 24 : return TRUE;
553 : }
554 :
555 : /************************************************************************/
556 : /* Open() */
557 : /************************************************************************/
558 :
559 763 : GDALDataset *USGSDEMDataset::Open( GDALOpenInfo * poOpenInfo )
560 :
561 : {
562 763 : if( !Identify( poOpenInfo ) )
563 739 : return NULL;
564 :
565 : /* -------------------------------------------------------------------- */
566 : /* Create a corresponding GDALDataset. */
567 : /* -------------------------------------------------------------------- */
568 : USGSDEMDataset *poDS;
569 :
570 24 : poDS = new USGSDEMDataset();
571 :
572 24 : poDS->fp = poOpenInfo->fp;
573 24 : poOpenInfo->fp = NULL;
574 :
575 : /* -------------------------------------------------------------------- */
576 : /* Read the file. */
577 : /* -------------------------------------------------------------------- */
578 24 : if( !poDS->LoadFromFile( poDS->fp ) )
579 : {
580 0 : delete poDS;
581 0 : return NULL;
582 : }
583 :
584 : /* -------------------------------------------------------------------- */
585 : /* Confirm the requested access is supported. */
586 : /* -------------------------------------------------------------------- */
587 24 : if( poOpenInfo->eAccess == GA_Update )
588 : {
589 0 : delete poDS;
590 : CPLError( CE_Failure, CPLE_NotSupported,
591 : "The USGSDEM driver does not support update access to existing"
592 0 : " datasets.\n" );
593 0 : return NULL;
594 : }
595 :
596 : /* -------------------------------------------------------------------- */
597 : /* Create band information objects. */
598 : /* -------------------------------------------------------------------- */
599 24 : poDS->SetBand( 1, new USGSDEMRasterBand( poDS ));
600 :
601 24 : poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
602 :
603 : /* -------------------------------------------------------------------- */
604 : /* Initialize any PAM information. */
605 : /* -------------------------------------------------------------------- */
606 24 : poDS->SetDescription( poOpenInfo->pszFilename );
607 24 : poDS->TryLoadXML();
608 :
609 : /* -------------------------------------------------------------------- */
610 : /* Open overviews. */
611 : /* -------------------------------------------------------------------- */
612 24 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
613 :
614 24 : return( poDS );
615 : }
616 :
617 : /************************************************************************/
618 : /* GDALRegister_USGSDEM() */
619 : /************************************************************************/
620 :
621 338 : void GDALRegister_USGSDEM()
622 :
623 : {
624 : GDALDriver *poDriver;
625 :
626 338 : if( GDALGetDriverByName( "USGSDEM" ) == NULL )
627 : {
628 336 : poDriver = new GDALDriver();
629 :
630 336 : poDriver->SetDescription( "USGSDEM" );
631 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION,
632 336 : "dem" );
633 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
634 336 : "USGS Optional ASCII DEM (and CDED)" );
635 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
636 336 : "frmt_usgsdem.html" );
637 336 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Int16" );
638 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
639 : "<CreationOptionList>"
640 : " <Option name='PRODUCT' type='string-select' description='Specific Product Type'>"
641 : " <Value>DEFAULT</Value>"
642 : " <Value>CDED50K</Value>"
643 : " </Option>"
644 : " <Option name='TOPLEFT' type='string' description='Top left product corner (ie. 117d15w,52d30n'/>"
645 : " <Option name='RESAMPLE' type='string-select' description='Resampling kernel to use if resampled.'>"
646 : " <Value>Nearest</Value>"
647 : " <Value>Bilinear</Value>"
648 : " <Value>Cubic</Value>"
649 : " <Value>CubicSpline</Value>"
650 : " </Option>"
651 : " <Option name='TEMPLATE' type='string' description='File to default metadata from.'/>"
652 : " <Option name='DEMLevelCode' type='int' description='DEM Level (1, 2 or 3 if set)'/>"
653 : " <Option name='DataSpecVersion' type='int' description='Data and Specification version/revision (eg. 1020)'/>"
654 : " <Option name='PRODUCER' type='string' description='Producer Agency (up to 60 characters)'/>"
655 : " <Option name='OriginCode' type='string' description='Origin code (up to 4 characters, YT for Yukon)'/>"
656 : " <Option name='ProcessCode' type='string' description='Processing Code (8=ANUDEM, 9=FME, A=TopoGrid)'/>"
657 : " <Option name='ZRESOLUTION' type='float' description='Scaling factor for elevation values'/>"
658 : " <Option name='NTS' type='string' description='NTS Mapsheet name, used to derive TOPLEFT.'/>"
659 : " <Option name='INTERNALNAME' type='string' description='Dataset name written into file header.'/>"
660 336 : "</CreationOptionList>" );
661 :
662 336 : poDriver->pfnOpen = USGSDEMDataset::Open;
663 336 : poDriver->pfnCreateCopy = USGSDEMCreateCopy;
664 336 : poDriver->pfnIdentify = USGSDEMDataset::Identify;
665 :
666 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
667 : }
668 338 : }
|