1 : /******************************************************************************
2 : * $Id: bagdataset.cpp 24084 2012-03-06 04:47:46Z warmerdam $
3 : *
4 : * Project: Hierarchical Data Format Release 5 (HDF5)
5 : * Purpose: Read BAG datasets.
6 : * Author: Frank Warmerdam <warmerdam@pobox.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
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 : #include "gh5_convenience.h"
31 :
32 : #include "gdal_pam.h"
33 : #include "gdal_priv.h"
34 : #include "ogr_spatialref.h"
35 : #include "cpl_string.h"
36 :
37 : CPL_CVSID("$Id: bagdataset.cpp 24084 2012-03-06 04:47:46Z warmerdam $");
38 :
39 : CPL_C_START
40 : void GDALRegister_BAG(void);
41 : CPL_C_END
42 :
43 : OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
44 : const char *pszISOXML );
45 :
46 : /************************************************************************/
47 : /* ==================================================================== */
48 : /* BAGDataset */
49 : /* ==================================================================== */
50 : /************************************************************************/
51 : class BAGDataset : public GDALPamDataset
52 : {
53 :
54 : friend class BAGRasterBand;
55 :
56 : hid_t hHDF5;
57 :
58 : char *pszProjection;
59 : double adfGeoTransform[6];
60 :
61 : void LoadMetadata();
62 :
63 : char *pszXMLMetadata;
64 : char *apszMDList[2];
65 :
66 : public:
67 : BAGDataset();
68 : ~BAGDataset();
69 :
70 : virtual CPLErr GetGeoTransform( double * );
71 : virtual const char *GetProjectionRef(void);
72 : virtual char **GetMetadata( const char * pszDomain = "" );
73 :
74 : static GDALDataset *Open( GDALOpenInfo * );
75 : static int Identify( GDALOpenInfo * );
76 : };
77 :
78 : /************************************************************************/
79 : /* ==================================================================== */
80 : /* BAGRasterBand */
81 : /* ==================================================================== */
82 : /************************************************************************/
83 : class BAGRasterBand : public GDALPamRasterBand
84 : {
85 : friend class BAGDataset;
86 :
87 : hid_t hDatasetID;
88 : hid_t native;
89 : hid_t dataspace;
90 :
91 : bool bMinMaxSet;
92 : double dfMinimum;
93 : double dfMaximum;
94 :
95 : public:
96 :
97 : BAGRasterBand( BAGDataset *, int );
98 : ~BAGRasterBand();
99 :
100 : bool Initialize( hid_t hDataset, const char *pszName );
101 :
102 : virtual CPLErr IReadBlock( int, int, void * );
103 : virtual double GetNoDataValue( int * );
104 :
105 : virtual double GetMinimum( int *pbSuccess = NULL );
106 : virtual double GetMaximum(int *pbSuccess = NULL );
107 : };
108 :
109 : /************************************************************************/
110 : /* BAGRasterBand() */
111 : /************************************************************************/
112 6 : BAGRasterBand::BAGRasterBand( BAGDataset *poDS, int nBand )
113 :
114 : {
115 6 : this->poDS = poDS;
116 6 : this->nBand = nBand;
117 :
118 6 : hDatasetID = -1;
119 6 : dataspace = -1;
120 6 : native = -1;
121 6 : bMinMaxSet = false;
122 6 : }
123 :
124 : /************************************************************************/
125 : /* ~BAGRasterBand() */
126 : /************************************************************************/
127 :
128 6 : BAGRasterBand::~BAGRasterBand()
129 : {
130 6 : if( dataspace > 0 )
131 6 : H5Sclose(dataspace);
132 :
133 6 : if( native > 0 )
134 6 : H5Tclose( native );
135 :
136 6 : if( hDatasetID > 0 )
137 6 : H5Dclose( hDatasetID );
138 6 : }
139 :
140 : /************************************************************************/
141 : /* Initialize() */
142 : /************************************************************************/
143 :
144 6 : bool BAGRasterBand::Initialize( hid_t hDatasetID, const char *pszName )
145 :
146 : {
147 6 : SetDescription( pszName );
148 :
149 6 : this->hDatasetID = hDatasetID;
150 :
151 6 : hid_t datatype = H5Dget_type( hDatasetID );
152 6 : dataspace = H5Dget_space( hDatasetID );
153 6 : hid_t n_dims = H5Sget_simple_extent_ndims( dataspace );
154 6 : native = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
155 : hsize_t dims[3], maxdims[3];
156 :
157 6 : eDataType = GH5_GetDataType( native );
158 :
159 6 : if( n_dims == 2 )
160 : {
161 6 : H5Sget_simple_extent_dims( dataspace, dims, maxdims );
162 :
163 6 : nRasterXSize = (int) dims[1];
164 6 : nRasterYSize = (int) dims[0];
165 : }
166 : else
167 : {
168 : CPLError( CE_Failure, CPLE_AppDefined,
169 0 : "Dataset not of rank 2." );
170 0 : return false;
171 : }
172 :
173 6 : nBlockXSize = nRasterXSize;
174 6 : nBlockYSize = 1;
175 :
176 : /* -------------------------------------------------------------------- */
177 : /* Check for chunksize, and use it as blocksize for optimized */
178 : /* reading. */
179 : /* -------------------------------------------------------------------- */
180 6 : hid_t listid = H5Dget_create_plist( hDatasetID );
181 6 : if (listid>0)
182 : {
183 6 : if(H5Pget_layout(listid) == H5D_CHUNKED)
184 : {
185 : hsize_t panChunkDims[3];
186 0 : int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
187 0 : nBlockXSize = (int) panChunkDims[nDimSize-1];
188 0 : nBlockYSize = (int) panChunkDims[nDimSize-2];
189 : }
190 6 : H5Pclose(listid);
191 : }
192 :
193 : /* -------------------------------------------------------------------- */
194 : /* Load min/max information. */
195 : /* -------------------------------------------------------------------- */
196 6 : if( EQUAL(pszName,"elevation")
197 : && GH5_FetchAttribute( hDatasetID, "Maximum Elevation Value",
198 : dfMaximum )
199 : && GH5_FetchAttribute( hDatasetID, "Minimum Elevation Value",
200 : dfMinimum ) )
201 2 : bMinMaxSet = true;
202 4 : else if( EQUAL(pszName,"uncertainty")
203 : && GH5_FetchAttribute( hDatasetID, "Maximum Uncertainty Value",
204 : dfMaximum )
205 : && GH5_FetchAttribute( hDatasetID, "Minimum Uncertainty Value",
206 : dfMinimum ) )
207 2 : bMinMaxSet = true;
208 2 : else if( EQUAL(pszName,"nominal_elevation")
209 : && GH5_FetchAttribute( hDatasetID, "max_value",
210 : dfMaximum )
211 : && GH5_FetchAttribute( hDatasetID, "min_value",
212 : dfMinimum ) )
213 2 : bMinMaxSet = true;
214 :
215 6 : return true;
216 : }
217 :
218 : /************************************************************************/
219 : /* GetMinimum() */
220 : /************************************************************************/
221 :
222 2 : double BAGRasterBand::GetMinimum( int * pbSuccess )
223 :
224 : {
225 2 : if( bMinMaxSet )
226 : {
227 2 : if( pbSuccess )
228 2 : *pbSuccess = TRUE;
229 2 : return dfMinimum;
230 : }
231 : else
232 0 : return GDALRasterBand::GetMinimum( pbSuccess );
233 : }
234 :
235 : /************************************************************************/
236 : /* GetMaximum() */
237 : /************************************************************************/
238 :
239 2 : double BAGRasterBand::GetMaximum( int * pbSuccess )
240 :
241 : {
242 2 : if( bMinMaxSet )
243 : {
244 2 : if( pbSuccess )
245 2 : *pbSuccess = TRUE;
246 2 : return dfMaximum;
247 : }
248 : else
249 0 : return GDALRasterBand::GetMaximum( pbSuccess );
250 : }
251 :
252 : /************************************************************************/
253 : /* GetNoDataValue() */
254 : /************************************************************************/
255 6 : double BAGRasterBand::GetNoDataValue( int * pbSuccess )
256 :
257 : {
258 6 : if( pbSuccess )
259 6 : *pbSuccess = TRUE;
260 :
261 6 : if( EQUAL(GetDescription(),"elevation") )
262 2 : return 1000000.0;
263 4 : else if( EQUAL(GetDescription(),"uncertainty") )
264 2 : return 0.0;
265 2 : else if( EQUAL(GetDescription(),"nominal_elevation") )
266 2 : return 1000000.0;
267 : else
268 0 : return GDALPamRasterBand::GetNoDataValue( pbSuccess );
269 : }
270 :
271 : /************************************************************************/
272 : /* IReadBlock() */
273 : /************************************************************************/
274 60 : CPLErr BAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
275 : void * pImage )
276 : {
277 : herr_t status;
278 : hsize_t count[3];
279 : H5OFFSET_TYPE offset[3];
280 : int nSizeOfData;
281 : hid_t memspace;
282 : hsize_t col_dims[3];
283 : hsize_t rank;
284 :
285 60 : rank=2;
286 :
287 60 : offset[0] = MAX(0,nRasterYSize - (nBlockYOff+1)*nBlockYSize);
288 60 : offset[1] = nBlockXOff*nBlockXSize;
289 60 : count[0] = nBlockYSize;
290 60 : count[1] = nBlockXSize;
291 :
292 60 : nSizeOfData = H5Tget_size( native );
293 60 : memset( pImage,0,nBlockXSize*nBlockYSize*nSizeOfData );
294 :
295 : /* blocksize may not be a multiple of imagesize */
296 60 : count[0] = MIN( size_t(nBlockYSize), GetYSize() - offset[0]);
297 60 : count[1] = MIN( size_t(nBlockXSize), GetXSize() - offset[1]);
298 :
299 60 : if( nRasterYSize - (nBlockYOff+1)*nBlockYSize < 0 )
300 : {
301 0 : count[0] += (nRasterYSize - (nBlockYOff+1)*nBlockYSize);
302 : }
303 :
304 : /* -------------------------------------------------------------------- */
305 : /* Select block from file space */
306 : /* -------------------------------------------------------------------- */
307 : status = H5Sselect_hyperslab( dataspace,
308 : H5S_SELECT_SET,
309 : offset, NULL,
310 60 : count, NULL );
311 :
312 : /* -------------------------------------------------------------------- */
313 : /* Create memory space to receive the data */
314 : /* -------------------------------------------------------------------- */
315 60 : col_dims[0]=nBlockYSize;
316 60 : col_dims[1]=nBlockXSize;
317 60 : memspace = H5Screate_simple( (int) rank, col_dims, NULL );
318 60 : H5OFFSET_TYPE mem_offset[3] = {0, 0, 0};
319 : status = H5Sselect_hyperslab(memspace,
320 : H5S_SELECT_SET,
321 : mem_offset, NULL,
322 60 : count, NULL);
323 :
324 : status = H5Dread ( hDatasetID,
325 : native,
326 : memspace,
327 : dataspace,
328 : H5P_DEFAULT,
329 60 : pImage );
330 :
331 60 : H5Sclose( memspace );
332 :
333 : /* -------------------------------------------------------------------- */
334 : /* Y flip the data. */
335 : /* -------------------------------------------------------------------- */
336 60 : int nLinesToFlip = count[0];
337 60 : int nLineSize = nSizeOfData * nBlockXSize;
338 60 : GByte *pabyTemp = (GByte *) CPLMalloc(nLineSize);
339 :
340 60 : for( int iY = 0; iY < nLinesToFlip/2; iY++ )
341 : {
342 : memcpy( pabyTemp,
343 : ((GByte *)pImage) + iY * nLineSize,
344 0 : nLineSize );
345 : memcpy( ((GByte *)pImage) + iY * nLineSize,
346 : ((GByte *)pImage) + (nLinesToFlip-iY-1) * nLineSize,
347 0 : nLineSize );
348 : memcpy( ((GByte *)pImage) + (nLinesToFlip-iY-1) * nLineSize,
349 : pabyTemp,
350 0 : nLineSize );
351 : }
352 :
353 60 : CPLFree( pabyTemp );
354 :
355 : /* -------------------------------------------------------------------- */
356 : /* Return success or failure. */
357 : /* -------------------------------------------------------------------- */
358 60 : if( status < 0 )
359 : {
360 : CPLError( CE_Failure, CPLE_AppDefined,
361 0 : "H5Dread() failed for block." );
362 0 : return CE_Failure;
363 : }
364 : else
365 60 : return CE_None;
366 : }
367 :
368 : /************************************************************************/
369 : /* ==================================================================== */
370 : /* BAGDataset */
371 : /* ==================================================================== */
372 : /************************************************************************/
373 :
374 : /************************************************************************/
375 : /* BAGDataset() */
376 : /************************************************************************/
377 :
378 2 : BAGDataset::BAGDataset()
379 : {
380 2 : hHDF5 = -1;
381 2 : pszXMLMetadata = NULL;
382 2 : pszProjection = NULL;
383 :
384 2 : adfGeoTransform[0] = 0.0;
385 2 : adfGeoTransform[1] = 1.0;
386 2 : adfGeoTransform[2] = 0.0;
387 2 : adfGeoTransform[3] = 0.0;
388 2 : adfGeoTransform[4] = 0.0;
389 2 : adfGeoTransform[5] = 1.0;
390 2 : }
391 :
392 : /************************************************************************/
393 : /* ~BAGDataset() */
394 : /************************************************************************/
395 2 : BAGDataset::~BAGDataset( )
396 : {
397 2 : FlushCache();
398 :
399 2 : if( hHDF5 >= 0 )
400 2 : H5Fclose( hHDF5 );
401 :
402 2 : CPLFree( pszXMLMetadata );
403 2 : CPLFree( pszProjection );
404 2 : }
405 :
406 : /************************************************************************/
407 : /* Identify() */
408 : /************************************************************************/
409 :
410 22270 : int BAGDataset::Identify( GDALOpenInfo * poOpenInfo )
411 :
412 : {
413 : /* -------------------------------------------------------------------- */
414 : /* Is it an HDF5 file? */
415 : /* -------------------------------------------------------------------- */
416 : static const char achSignature[] = "\211HDF\r\n\032\n";
417 :
418 22270 : if( poOpenInfo->pabyHeader == NULL
419 : || memcmp(poOpenInfo->pabyHeader,achSignature,8) != 0 )
420 22260 : return FALSE;
421 :
422 : /* -------------------------------------------------------------------- */
423 : /* Does it have the extension .bag? */
424 : /* -------------------------------------------------------------------- */
425 10 : if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"bag") )
426 8 : return FALSE;
427 :
428 2 : return TRUE;
429 : }
430 :
431 : /************************************************************************/
432 : /* Open() */
433 : /************************************************************************/
434 :
435 3362 : GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
436 :
437 : {
438 : /* -------------------------------------------------------------------- */
439 : /* Confirm that this appears to be a BAG file. */
440 : /* -------------------------------------------------------------------- */
441 3362 : if( !Identify( poOpenInfo ) )
442 3360 : return NULL;
443 :
444 : /* -------------------------------------------------------------------- */
445 : /* Confirm the requested access is supported. */
446 : /* -------------------------------------------------------------------- */
447 2 : if( poOpenInfo->eAccess == GA_Update )
448 : {
449 : CPLError( CE_Failure, CPLE_NotSupported,
450 0 : "The BAG driver does not support update access." );
451 0 : return NULL;
452 : }
453 :
454 : /* -------------------------------------------------------------------- */
455 : /* Open the file as an HDF5 file. */
456 : /* -------------------------------------------------------------------- */
457 : hid_t hHDF5 = H5Fopen( poOpenInfo->pszFilename,
458 2 : H5F_ACC_RDONLY, H5P_DEFAULT );
459 :
460 2 : if( hHDF5 < 0 )
461 0 : return NULL;
462 :
463 : /* -------------------------------------------------------------------- */
464 : /* Confirm it is a BAG dataset by checking for the */
465 : /* BAG_Root/Bag Version attribute. */
466 : /* -------------------------------------------------------------------- */
467 2 : hid_t hBagRoot = H5Gopen( hHDF5, "/BAG_root" );
468 2 : hid_t hVersion = -1;
469 :
470 2 : if( hBagRoot >= 0 )
471 2 : hVersion = H5Aopen_name( hBagRoot, "Bag Version" );
472 :
473 2 : if( hVersion < 0 )
474 : {
475 0 : H5Fclose( hHDF5 );
476 0 : return NULL;
477 : }
478 2 : H5Aclose( hVersion );
479 :
480 : /* -------------------------------------------------------------------- */
481 : /* Create a corresponding dataset. */
482 : /* -------------------------------------------------------------------- */
483 2 : BAGDataset *poDS = new BAGDataset();
484 :
485 2 : poDS->hHDF5 = hHDF5;
486 :
487 : /* -------------------------------------------------------------------- */
488 : /* Extract version as metadata. */
489 : /* -------------------------------------------------------------------- */
490 2 : CPLString osVersion;
491 :
492 4 : if( GH5_FetchAttribute( hBagRoot, "Bag Version", osVersion ) )
493 2 : poDS->SetMetadataItem( "BagVersion", osVersion );
494 :
495 2 : H5Gclose( hBagRoot );
496 :
497 : /* -------------------------------------------------------------------- */
498 : /* Fetch the elevation dataset and attach as a band. */
499 : /* -------------------------------------------------------------------- */
500 2 : int nNextBand = 1;
501 2 : hid_t hElevation = H5Dopen( hHDF5, "/BAG_root/elevation" );
502 2 : if( hElevation < 0 )
503 : {
504 0 : delete poDS;
505 0 : return NULL;
506 : }
507 :
508 2 : BAGRasterBand *poElevBand = new BAGRasterBand( poDS, nNextBand );
509 :
510 4 : if( !poElevBand->Initialize( hElevation, "elevation" ) )
511 : {
512 0 : delete poElevBand;
513 0 : delete poDS;
514 0 : return NULL;
515 : }
516 :
517 2 : poDS->nRasterXSize = poElevBand->nRasterXSize;
518 2 : poDS->nRasterYSize = poElevBand->nRasterYSize;
519 :
520 2 : poDS->SetBand( nNextBand++, poElevBand );
521 :
522 : /* -------------------------------------------------------------------- */
523 : /* Try to do the same for the uncertainty band. */
524 : /* -------------------------------------------------------------------- */
525 2 : hid_t hUncertainty = H5Dopen( hHDF5, "/BAG_root/uncertainty" );
526 2 : BAGRasterBand *poUBand = new BAGRasterBand( poDS, nNextBand );
527 :
528 4 : if( hUncertainty >= 0 && poUBand->Initialize( hUncertainty, "uncertainty") )
529 : {
530 2 : poDS->SetBand( nNextBand++, poUBand );
531 : }
532 : else
533 0 : delete poUBand;
534 :
535 : /* -------------------------------------------------------------------- */
536 : /* Try to do the same for the uncertainty band. */
537 : /* -------------------------------------------------------------------- */
538 2 : hid_t hNominal = -1;
539 :
540 2 : H5E_BEGIN_TRY {
541 2 : hNominal = H5Dopen( hHDF5, "/BAG_root/nominal_elevation" );
542 2 : } H5E_END_TRY;
543 :
544 2 : BAGRasterBand *poNBand = new BAGRasterBand( poDS, nNextBand );
545 4 : if( hNominal >= 0 && poNBand->Initialize( hNominal,
546 : "nominal_elevation" ) )
547 : {
548 2 : poDS->SetBand( nNextBand++, poNBand );
549 : }
550 : else
551 0 : delete poNBand;
552 :
553 : /* -------------------------------------------------------------------- */
554 : /* Load the XML metadata. */
555 : /* -------------------------------------------------------------------- */
556 2 : poDS->LoadMetadata();
557 :
558 : /* -------------------------------------------------------------------- */
559 : /* Setup/check for pam .aux.xml. */
560 : /* -------------------------------------------------------------------- */
561 2 : poDS->SetDescription( poOpenInfo->pszFilename );
562 2 : poDS->TryLoadXML();
563 :
564 : /* -------------------------------------------------------------------- */
565 : /* Setup overviews. */
566 : /* -------------------------------------------------------------------- */
567 2 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
568 :
569 2 : return( poDS );
570 : }
571 :
572 : /************************************************************************/
573 : /* LoadMetadata() */
574 : /************************************************************************/
575 :
576 2 : void BAGDataset::LoadMetadata()
577 :
578 : {
579 : /* -------------------------------------------------------------------- */
580 : /* Load the metadata from the file. */
581 : /* -------------------------------------------------------------------- */
582 2 : hid_t hMDDS = H5Dopen( hHDF5, "/BAG_root/metadata" );
583 2 : hid_t datatype = H5Dget_type( hMDDS );
584 2 : hid_t dataspace = H5Dget_space( hMDDS );
585 2 : hid_t native = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
586 : hsize_t dims[3], maxdims[3];
587 :
588 2 : H5Sget_simple_extent_dims( dataspace, dims, maxdims );
589 :
590 2 : pszXMLMetadata = (char *) CPLCalloc((int) (dims[0]+1),1);
591 :
592 2 : H5Dread( hMDDS, native, H5S_ALL, dataspace, H5P_DEFAULT, pszXMLMetadata );
593 :
594 2 : H5Tclose( native );
595 2 : H5Sclose( dataspace );
596 2 : H5Tclose( datatype );
597 2 : H5Dclose( hMDDS );
598 :
599 2 : if( strlen(pszXMLMetadata) == 0 )
600 0 : return;
601 :
602 : /* -------------------------------------------------------------------- */
603 : /* Try to get the geotransform. */
604 : /* -------------------------------------------------------------------- */
605 2 : CPLXMLNode *psRoot = CPLParseXMLString( pszXMLMetadata );
606 :
607 2 : if( psRoot == NULL )
608 0 : return;
609 :
610 2 : CPLStripXMLNamespace( psRoot, NULL, TRUE );
611 :
612 2 : CPLXMLNode *psGeo = CPLSearchXMLNode( psRoot, "=MD_Georectified" );
613 :
614 2 : if( psGeo != NULL )
615 : {
616 : char **papszCornerTokens =
617 : CSLTokenizeStringComplex(
618 : CPLGetXMLValue( psGeo, "cornerPoints.Point.coordinates", "" ),
619 2 : " ,", FALSE, FALSE );
620 :
621 2 : if( CSLCount(papszCornerTokens ) == 4 )
622 : {
623 2 : double dfLLX = atof( papszCornerTokens[0] );
624 2 : double dfLLY = atof( papszCornerTokens[1] );
625 2 : double dfURX = atof( papszCornerTokens[2] );
626 2 : double dfURY = atof( papszCornerTokens[3] );
627 :
628 2 : adfGeoTransform[0] = dfLLX;
629 2 : adfGeoTransform[1] = (dfURX - dfLLX) / (GetRasterXSize()-1);
630 2 : adfGeoTransform[3] = dfURY;
631 2 : adfGeoTransform[5] = (dfLLY - dfURY) / (GetRasterYSize()-1);
632 :
633 2 : adfGeoTransform[0] -= adfGeoTransform[1] * 0.5;
634 2 : adfGeoTransform[3] -= adfGeoTransform[5] * 0.5;
635 : }
636 2 : CSLDestroy( papszCornerTokens );
637 : }
638 :
639 : /* -------------------------------------------------------------------- */
640 : /* Try to get the coordinate system. */
641 : /* -------------------------------------------------------------------- */
642 2 : OGRSpatialReference oSRS;
643 :
644 2 : if( OGR_SRS_ImportFromISO19115( &oSRS, pszXMLMetadata )
645 : == OGRERR_NONE )
646 : {
647 0 : oSRS.exportToWkt( &pszProjection );
648 : }
649 :
650 : /* -------------------------------------------------------------------- */
651 : /* Fetch acquisition date. */
652 : /* -------------------------------------------------------------------- */
653 2 : CPLXMLNode *psDateTime = CPLSearchXMLNode( psRoot, "=dateTime" );
654 2 : if( psDateTime != NULL )
655 : {
656 2 : const char *pszDateTimeValue = CPLGetXMLValue( psDateTime, NULL, "" );
657 2 : if( pszDateTimeValue )
658 2 : SetMetadataItem( "BAG_DATETIME", pszDateTimeValue );
659 : }
660 :
661 2 : CPLDestroyXMLNode( psRoot );
662 : }
663 :
664 : /************************************************************************/
665 : /* GetGeoTransform() */
666 : /************************************************************************/
667 :
668 0 : CPLErr BAGDataset::GetGeoTransform( double *padfGeoTransform )
669 :
670 : {
671 0 : if( adfGeoTransform[0] != 0.0 || adfGeoTransform[3] != 0.0 )
672 : {
673 0 : memcpy( padfGeoTransform, adfGeoTransform, sizeof(double)*6 );
674 0 : return CE_None;
675 : }
676 : else
677 0 : return GDALPamDataset::GetGeoTransform( padfGeoTransform );
678 : }
679 :
680 : /************************************************************************/
681 : /* GetProjectionRef() */
682 : /************************************************************************/
683 :
684 0 : const char *BAGDataset::GetProjectionRef()
685 :
686 : {
687 0 : if( pszProjection )
688 0 : return pszProjection;
689 : else
690 0 : return GDALPamDataset::GetProjectionRef();
691 : }
692 :
693 : /************************************************************************/
694 : /* GetMetadata() */
695 : /************************************************************************/
696 :
697 2 : char **BAGDataset::GetMetadata( const char *pszDomain )
698 :
699 : {
700 2 : if( pszDomain != NULL && EQUAL(pszDomain,"xml:BAG") )
701 : {
702 2 : apszMDList[0] = pszXMLMetadata;
703 2 : apszMDList[1] = NULL;
704 :
705 2 : return apszMDList;
706 : }
707 : else
708 0 : return GDALPamDataset::GetMetadata( pszDomain );
709 : }
710 :
711 : /************************************************************************/
712 : /* GDALRegister_BAG() */
713 : /************************************************************************/
714 1135 : void GDALRegister_BAG( )
715 :
716 : {
717 : GDALDriver *poDriver;
718 :
719 1135 : if (! GDAL_CHECK_VERSION("BAG"))
720 0 : return;
721 :
722 1135 : if( GDALGetDriverByName( "BAG" ) == NULL )
723 : {
724 1093 : poDriver = new GDALDriver();
725 :
726 1093 : poDriver->SetDescription( "BAG" );
727 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
728 1093 : "Bathymetry Attributed Grid" );
729 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
730 1093 : "frmt_bag.html" );
731 1093 : poDriver->pfnOpen = BAGDataset::Open;
732 1093 : poDriver->pfnIdentify = BAGDataset::Identify;
733 :
734 1093 : GetGDALDriverManager( )->RegisterDriver( poDriver );
735 : }
736 : }
|