1 : /******************************************************************************
2 : * $Id: usgsdemdataset.cpp 19291 2010-04-03 02:04:35Z warmerdam $
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 19291 2010-04-03 02:04:35Z warmerdam $");
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 24 : {
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 : CPLErr USGSDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
153 10 : 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 : 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( EQUALN(poGDS->pszProjection,"GEOGCS",6) )
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 : ((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 24 : USGSDEMDataset::~USGSDEMDataset()
279 :
280 : {
281 24 : FlushCache();
282 :
283 24 : CPLFree( pszProjection );
284 24 : if( fp != NULL )
285 24 : VSIFClose( fp );
286 24 : }
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 24 : int bNAD83 =TRUE;
399 :
400 : // OLD format header ends at byte 864
401 24 : if (bNewFormat)
402 : {
403 : char szHorzDatum[3];
404 :
405 : // year of data compilation
406 23 : VSIFSeek(InDem, 876, 0);
407 23 : fread(szDateBuffer, 4, 1, InDem);
408 23 : szDateBuffer[4] = 0;
409 :
410 : // Horizontal datum
411 : // 1=North American Datum 1927 (NAD 27)
412 : // 2=World Geodetic System 1972 (WGS 72)
413 : // 3=WGS 84
414 : // 4=NAD 83
415 : // 5=Old Hawaii Datum
416 : // 6=Puerto Rico Datum
417 : int datum;
418 23 : VSIFSeek(InDem, 890, 0);
419 23 : VSIFRead( szHorzDatum, 1, 2, InDem );
420 23 : szHorzDatum[2] = '\0';
421 23 : datum = atoi(szHorzDatum);
422 23 : switch (datum)
423 : {
424 : case 1:
425 1 : sr.SetWellKnownGeogCS( "NAD27" );
426 1 : bNAD83 = FALSE;
427 1 : break;
428 :
429 : case 2:
430 5 : sr.SetWellKnownGeogCS( "WGS72" );
431 5 : break;
432 :
433 : case 3:
434 14 : sr.SetWellKnownGeogCS( "WGS84" );
435 14 : break;
436 :
437 : case 4:
438 1 : sr.SetWellKnownGeogCS( "NAD83" );
439 1 : break;
440 :
441 : case -9:
442 0 : break;
443 :
444 : default:
445 2 : sr.SetWellKnownGeogCS( "NAD27" );
446 : break;
447 : }
448 : }
449 : else
450 : {
451 1 : sr.SetWellKnownGeogCS( "NAD27" );
452 1 : bNAD83 = FALSE;
453 : }
454 :
455 24 : if (nCoordSystem == 1) // UTM
456 6 : sr.SetUTM( iUTMZone, TRUE );
457 :
458 18 : else if (nCoordSystem == 2) // state plane
459 : {
460 0 : if( nGUnit == 1 )
461 : sr.SetStatePlane( iUTMZone, bNAD83,
462 0 : "Foot", CPLAtof(SRS_UL_US_FOOT_CONV) );
463 : else
464 0 : sr.SetStatePlane( iUTMZone, bNAD83 );
465 : }
466 :
467 24 : sr.exportToWkt( &pszProjection );
468 :
469 : /* -------------------------------------------------------------------- */
470 : /* For UTM we use the extents (really the UTM coordinates of */
471 : /* the lat/long corners of the quad) to determine the size in */
472 : /* pixels and lines, but we have to make the anchors be modulus */
473 : /* the pixel size which what really gets used. */
474 : /* -------------------------------------------------------------------- */
475 30 : if (nCoordSystem == 1 // UTM
476 : || nCoordSystem == 2 // State Plane
477 : || nCoordSystem == -9999 ) // unknown
478 : {
479 : int njunk;
480 : double dxStart;
481 :
482 : // expand extents modulus the pixel size.
483 6 : extent_min.y = floor(extent_min.y/dydelta) * dydelta;
484 6 : extent_max.y = ceil(extent_max.y/dydelta) * dydelta;
485 :
486 : // Forceably compute X extents based on first profile and pixelsize.
487 6 : VSIFSeek(InDem, nDataStartOffset, 0);
488 6 : fscanf(InDem, "%d", &njunk);
489 6 : fscanf(InDem, "%d", &njunk);
490 6 : fscanf(InDem, "%d", &njunk);
491 6 : fscanf(InDem, "%d", &njunk);
492 6 : dxStart = DConvert(InDem, 24);
493 :
494 6 : nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5);
495 6 : nRasterXSize = nProfiles;
496 :
497 6 : adfGeoTransform[0] = dxStart - dxdelta/2.0;
498 6 : adfGeoTransform[1] = dxdelta;
499 6 : adfGeoTransform[2] = 0.0;
500 6 : adfGeoTransform[3] = extent_max.y + dydelta/2.0;
501 6 : adfGeoTransform[4] = 0.0;
502 6 : adfGeoTransform[5] = -dydelta;
503 : }
504 : /* -------------------------------------------------------------------- */
505 : /* Geographic -- use corners directly. */
506 : /* -------------------------------------------------------------------- */
507 : else
508 : {
509 18 : nRasterYSize = (int) ((extent_max.y - extent_min.y)/dydelta + 1.5);
510 18 : nRasterXSize = nProfiles;
511 :
512 : // Translate extents from arc-seconds to decimal degrees.
513 18 : adfGeoTransform[0] = (extent_min.x - dxdelta/2.0) / 3600.0;
514 18 : adfGeoTransform[1] = dxdelta / 3600.0;
515 18 : adfGeoTransform[2] = 0.0;
516 18 : adfGeoTransform[3] = (extent_max.y + dydelta/2.0) / 3600.0;
517 18 : adfGeoTransform[4] = 0.0;
518 18 : adfGeoTransform[5] = (-dydelta) / 3600.0;
519 : }
520 :
521 24 : if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
522 : {
523 24 : return FALSE;
524 : }
525 :
526 24 : return TRUE;
527 : }
528 :
529 : /************************************************************************/
530 : /* GetGeoTransform() */
531 : /************************************************************************/
532 :
533 31 : CPLErr USGSDEMDataset::GetGeoTransform( double * padfTransform )
534 :
535 : {
536 31 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
537 31 : return CE_None;
538 : }
539 :
540 : /************************************************************************/
541 : /* GetProjectionRef() */
542 : /************************************************************************/
543 :
544 47 : const char *USGSDEMDataset::GetProjectionRef()
545 :
546 : {
547 47 : return pszProjection;
548 : }
549 :
550 :
551 : /************************************************************************/
552 : /* Identify() */
553 : /************************************************************************/
554 :
555 9615 : int USGSDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
556 :
557 : {
558 9615 : if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 200 )
559 9359 : return FALSE;
560 :
561 256 : if( !EQUALN((const char *) poOpenInfo->pabyHeader+156, " 0",6)
562 : && !EQUALN((const char *) poOpenInfo->pabyHeader+156, " 1",6)
563 : && !EQUALN((const char *) poOpenInfo->pabyHeader+156, " 2",6)
564 : && !EQUALN((const char *) poOpenInfo->pabyHeader+156, " 3",6)
565 : && !EQUALN((const char *) poOpenInfo->pabyHeader+156, " -9999",6) )
566 232 : return FALSE;
567 :
568 24 : if( !EQUALN((const char *) poOpenInfo->pabyHeader+150, " 1",6)
569 : && !EQUALN((const char *) poOpenInfo->pabyHeader+150, " 4",6))
570 0 : return FALSE;
571 :
572 24 : return TRUE;
573 : }
574 :
575 : /************************************************************************/
576 : /* Open() */
577 : /************************************************************************/
578 :
579 1370 : GDALDataset *USGSDEMDataset::Open( GDALOpenInfo * poOpenInfo )
580 :
581 : {
582 1370 : if( !Identify( poOpenInfo ) )
583 1346 : return NULL;
584 :
585 : /* -------------------------------------------------------------------- */
586 : /* Create a corresponding GDALDataset. */
587 : /* -------------------------------------------------------------------- */
588 : USGSDEMDataset *poDS;
589 :
590 24 : poDS = new USGSDEMDataset();
591 :
592 24 : poDS->fp = poOpenInfo->fp;
593 24 : poOpenInfo->fp = NULL;
594 :
595 : /* -------------------------------------------------------------------- */
596 : /* Read the file. */
597 : /* -------------------------------------------------------------------- */
598 24 : if( !poDS->LoadFromFile( poDS->fp ) )
599 : {
600 0 : delete poDS;
601 0 : return NULL;
602 : }
603 :
604 : /* -------------------------------------------------------------------- */
605 : /* Confirm the requested access is supported. */
606 : /* -------------------------------------------------------------------- */
607 24 : if( poOpenInfo->eAccess == GA_Update )
608 : {
609 0 : delete poDS;
610 : CPLError( CE_Failure, CPLE_NotSupported,
611 : "The USGSDEM driver does not support update access to existing"
612 0 : " datasets.\n" );
613 0 : return NULL;
614 : }
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* Create band information objects. */
618 : /* -------------------------------------------------------------------- */
619 24 : poDS->SetBand( 1, new USGSDEMRasterBand( poDS ));
620 :
621 24 : poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
622 :
623 : /* -------------------------------------------------------------------- */
624 : /* Initialize any PAM information. */
625 : /* -------------------------------------------------------------------- */
626 24 : poDS->SetDescription( poOpenInfo->pszFilename );
627 24 : poDS->TryLoadXML();
628 :
629 : /* -------------------------------------------------------------------- */
630 : /* Open overviews. */
631 : /* -------------------------------------------------------------------- */
632 24 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
633 :
634 24 : return( poDS );
635 : }
636 :
637 : /************************************************************************/
638 : /* GDALRegister_USGSDEM() */
639 : /************************************************************************/
640 :
641 409 : void GDALRegister_USGSDEM()
642 :
643 : {
644 : GDALDriver *poDriver;
645 :
646 409 : if( GDALGetDriverByName( "USGSDEM" ) == NULL )
647 : {
648 392 : poDriver = new GDALDriver();
649 :
650 392 : poDriver->SetDescription( "USGSDEM" );
651 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION,
652 392 : "dem" );
653 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
654 392 : "USGS Optional ASCII DEM (and CDED)" );
655 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
656 392 : "frmt_usgsdem.html" );
657 392 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Int16" );
658 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
659 : "<CreationOptionList>"
660 : " <Option name='PRODUCT' type='string-select' description='Specific Product Type'>"
661 : " <Value>DEFAULT</Value>"
662 : " <Value>CDED50K</Value>"
663 : " </Option>"
664 : " <Option name='TOPLEFT' type='string' description='Top left product corner (ie. 117d15w,52d30n'/>"
665 : " <Option name='RESAMPLE' type='string-select' description='Resampling kernel to use if resampled.'>"
666 : " <Value>Nearest</Value>"
667 : " <Value>Bilinear</Value>"
668 : " <Value>Cubic</Value>"
669 : " <Value>CubicSpline</Value>"
670 : " </Option>"
671 : " <Option name='TEMPLATE' type='string' description='File to default metadata from.'/>"
672 : " <Option name='DEMLevelCode' type='int' description='DEM Level (1, 2 or 3 if set)'/>"
673 : " <Option name='DataSpecVersion' type='int' description='Data and Specification version/revision (eg. 1020)'/>"
674 : " <Option name='PRODUCER' type='string' description='Producer Agency (up to 60 characters)'/>"
675 : " <Option name='OriginCode' type='string' description='Origin code (up to 4 characters, YT for Yukon)'/>"
676 : " <Option name='ProcessCode' type='string' description='Processing Code (8=ANUDEM, 9=FME, A=TopoGrid)'/>"
677 : " <Option name='ZRESOLUTION' type='float' description='Scaling factor for elevation values'/>"
678 : " <Option name='NTS' type='string' description='NTS Mapsheet name, used to derive TOPLEFT.'/>"
679 : " <Option name='INTERNALNAME' type='string' description='Dataset name written into file header.'/>"
680 392 : "</CreationOptionList>" );
681 :
682 392 : poDriver->pfnOpen = USGSDEMDataset::Open;
683 392 : poDriver->pfnCreateCopy = USGSDEMCreateCopy;
684 392 : poDriver->pfnIdentify = USGSDEMDataset::Identify;
685 :
686 392 : GetGDALDriverManager()->RegisterDriver( poDriver );
687 : }
688 409 : }
|