1 : /******************************************************************************
2 : * $Id: sdtsdataset.cpp 17664 2009-09-21 21:16:45Z rouault $
3 : *
4 : * Project: SDTS Translator
5 : * Purpose: GDALDataset driver for SDTS Raster translator.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, 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 : #include "sdts_al.h"
31 : #include "gdal_pam.h"
32 : #include "ogr_spatialref.h"
33 :
34 : CPL_CVSID("$Id: sdtsdataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
35 :
36 : /**
37 : \file sdtsdataset.cpp
38 :
39 : exclude
40 : */
41 :
42 : CPL_C_START
43 : void GDALRegister_SDTS(void);
44 : CPL_C_END
45 :
46 : /************************************************************************/
47 : /* ==================================================================== */
48 : /* SDTSDataset */
49 : /* ==================================================================== */
50 : /************************************************************************/
51 :
52 : class SDTSRasterBand;
53 :
54 : class SDTSDataset : public GDALPamDataset
55 2 : {
56 : friend class SDTSRasterBand;
57 :
58 : SDTSTransfer *poTransfer;
59 : SDTSRasterReader *poRL;
60 :
61 : char *pszProjection;
62 :
63 : public:
64 : virtual ~SDTSDataset();
65 :
66 : static GDALDataset *Open( GDALOpenInfo * );
67 :
68 : virtual const char *GetProjectionRef(void);
69 : virtual CPLErr GetGeoTransform( double * );
70 : };
71 :
72 : class SDTSRasterBand : public GDALPamRasterBand
73 4 : {
74 : friend class SDTSDataset;
75 :
76 : SDTSRasterReader *poRL;
77 :
78 : public:
79 :
80 : SDTSRasterBand( SDTSDataset *, int, SDTSRasterReader * );
81 :
82 : virtual CPLErr IReadBlock( int, int, void * );
83 :
84 : virtual double GetNoDataValue( int *pbSuccess );
85 : virtual const char *GetUnitType();
86 : };
87 :
88 :
89 : /************************************************************************/
90 : /* ~SDTSDataset() */
91 : /************************************************************************/
92 :
93 4 : SDTSDataset::~SDTSDataset()
94 :
95 : {
96 2 : FlushCache();
97 :
98 2 : if( poTransfer != NULL )
99 2 : delete poTransfer;
100 :
101 2 : if( poRL != NULL )
102 2 : delete poRL;
103 :
104 2 : if( pszProjection != NULL )
105 2 : CPLFree( pszProjection );
106 4 : }
107 :
108 : /************************************************************************/
109 : /* Open() */
110 : /************************************************************************/
111 :
112 9861 : GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
113 :
114 : {
115 : int i;
116 :
117 : /* -------------------------------------------------------------------- */
118 : /* Before trying SDTSOpen() we first verify that the first */
119 : /* record is in fact a SDTS file descriptor record. */
120 : /* -------------------------------------------------------------------- */
121 9861 : char *pachLeader = (char *) poOpenInfo->pabyHeader;
122 :
123 9861 : if( poOpenInfo->nHeaderBytes < 24 )
124 8725 : return NULL;
125 :
126 1136 : if( pachLeader[5] != '1' && pachLeader[5] != '2' && pachLeader[5] != '3' )
127 1122 : return NULL;
128 :
129 14 : if( pachLeader[6] != 'L' )
130 3 : return NULL;
131 :
132 11 : if( pachLeader[8] != '1' && pachLeader[8] != ' ' )
133 0 : return NULL;
134 :
135 : /* -------------------------------------------------------------------- */
136 : /* Try opening the dataset. */
137 : /* -------------------------------------------------------------------- */
138 11 : SDTSTransfer *poTransfer = new SDTSTransfer;
139 :
140 11 : if( !poTransfer->Open( poOpenInfo->pszFilename ) )
141 : {
142 9 : delete poTransfer;
143 9 : return NULL;
144 : }
145 :
146 : /* -------------------------------------------------------------------- */
147 : /* Confirm the requested access is supported. */
148 : /* -------------------------------------------------------------------- */
149 2 : if( poOpenInfo->eAccess == GA_Update )
150 : {
151 0 : delete poTransfer;
152 : CPLError( CE_Failure, CPLE_NotSupported,
153 : "The SDTS driver does not support update access to existing"
154 0 : " datasets.\n" );
155 0 : return NULL;
156 : }
157 :
158 : /* -------------------------------------------------------------------- */
159 : /* Find the first raster layer. If there are none, abort */
160 : /* returning an error. */
161 : /* -------------------------------------------------------------------- */
162 2 : SDTSRasterReader *poRL = NULL;
163 :
164 2 : for( i = 0; i < poTransfer->GetLayerCount(); i++ )
165 : {
166 2 : if( poTransfer->GetLayerType( i ) == SLTRaster )
167 : {
168 2 : poRL = poTransfer->GetLayerRasterReader( i );
169 2 : break;
170 : }
171 : }
172 :
173 2 : if( poRL == NULL )
174 : {
175 0 : delete poTransfer;
176 :
177 : CPLError( CE_Warning, CPLE_AppDefined,
178 : "%s is an SDTS transfer, but has no raster cell layers.\n"
179 : "Perhaps it is a vector transfer?\n",
180 0 : poOpenInfo->pszFilename );
181 0 : return NULL;
182 : }
183 :
184 : /* -------------------------------------------------------------------- */
185 : /* Initialize a corresponding GDALDataset. */
186 : /* -------------------------------------------------------------------- */
187 2 : SDTSDataset *poDS = new SDTSDataset();
188 :
189 2 : poDS->poTransfer = poTransfer;
190 2 : poDS->poRL = poRL;
191 :
192 : /* -------------------------------------------------------------------- */
193 : /* Capture some information from the file that is of interest. */
194 : /* -------------------------------------------------------------------- */
195 2 : poDS->nRasterXSize = poRL->GetXSize();
196 2 : poDS->nRasterYSize = poRL->GetYSize();
197 :
198 : /* -------------------------------------------------------------------- */
199 : /* Create band information objects. */
200 : /* -------------------------------------------------------------------- */
201 2 : poDS->nBands = 1;
202 : poDS->papoBands = (GDALRasterBand **)
203 2 : VSICalloc(sizeof(GDALRasterBand *),poDS->nBands);
204 :
205 8 : for( i = 0; i < poDS->nBands; i++ )
206 2 : poDS->SetBand( i+1, new SDTSRasterBand( poDS, i+1, poRL ) );
207 :
208 : /* -------------------------------------------------------------------- */
209 : /* Try to establish the projection string. For now we only */
210 : /* support UTM and GEO. */
211 : /* -------------------------------------------------------------------- */
212 2 : OGRSpatialReference oSRS;
213 2 : SDTS_XREF *poXREF = poTransfer->GetXREF();
214 :
215 2 : if( EQUAL(poXREF->pszSystemName,"UTM") )
216 : {
217 2 : oSRS.SetUTM( poXREF->nZone );
218 : }
219 0 : else if( EQUAL(poXREF->pszSystemName,"GEO") )
220 : {
221 : /* we set datum later */
222 : }
223 : else
224 0 : oSRS.SetLocalCS( poXREF->pszSystemName );
225 :
226 2 : if( oSRS.IsLocal() )
227 : /* don't try to set datum. */;
228 2 : else if( EQUAL(poXREF->pszDatum,"NAS") )
229 2 : oSRS.SetWellKnownGeogCS( "NAD27" );
230 0 : else if( EQUAL(poXREF->pszDatum, "NAX") )
231 0 : oSRS.SetWellKnownGeogCS( "NAD83" );
232 0 : else if( EQUAL(poXREF->pszDatum, "WGC") )
233 0 : oSRS.SetWellKnownGeogCS( "WGS72" );
234 0 : else if( EQUAL(poXREF->pszDatum, "WGE") )
235 0 : oSRS.SetWellKnownGeogCS( "WGS84" );
236 : else
237 0 : oSRS.SetWellKnownGeogCS( "WGS84" );
238 :
239 2 : oSRS.Fixup();
240 :
241 2 : poDS->pszProjection = NULL;
242 2 : if( oSRS.exportToWkt( &poDS->pszProjection ) != OGRERR_NONE )
243 0 : poDS->pszProjection = CPLStrdup("");
244 :
245 :
246 : /* -------------------------------------------------------------------- */
247 : /* Get metadata from the IDEN file. */
248 : /* -------------------------------------------------------------------- */
249 2 : const char* pszIDENFilePath = poTransfer->GetCATD()->GetModuleFilePath("IDEN");
250 2 : if (pszIDENFilePath)
251 : {
252 2 : DDFModule oIDENFile;
253 2 : if( oIDENFile.Open( pszIDENFilePath ) )
254 : {
255 : DDFRecord* poRecord;
256 :
257 4 : while( (poRecord = oIDENFile.ReadRecord()) != NULL )
258 : {
259 :
260 2 : if( poRecord->GetStringSubfield( "IDEN", 0, "MODN", 0 ) == NULL )
261 0 : continue;
262 :
263 : static const char* fields[][2] = { { "TITL", "TITLE" },
264 : { "DAID", "DATASET_ID" },
265 : { "DAST", "DATA_STRUCTURE" },
266 : { "MPDT", "MAP_DATE" },
267 : { "DCDT", "DATASET_CREATION_DATE" } };
268 :
269 12 : for (i = 0; i < (int)sizeof(fields) / (int)sizeof(fields[0]) ; i++)
270 : {
271 : const char* pszFieldValue =
272 10 : poRecord->GetStringSubfield( "IDEN", 0, fields[i][0], 0 );
273 10 : if ( pszFieldValue )
274 10 : poDS->SetMetadataItem(fields[i][1], pszFieldValue);
275 : }
276 :
277 2 : break;
278 : }
279 2 : }
280 : }
281 :
282 : /* -------------------------------------------------------------------- */
283 : /* Initialize any PAM information. */
284 : /* -------------------------------------------------------------------- */
285 2 : poDS->SetDescription( poOpenInfo->pszFilename );
286 2 : poDS->TryLoadXML();
287 :
288 2 : return( poDS );
289 : }
290 :
291 : /************************************************************************/
292 : /* GetGeoTransform() */
293 : /************************************************************************/
294 :
295 1 : CPLErr SDTSDataset::GetGeoTransform( double * padfTransform )
296 :
297 : {
298 1 : if( poRL->GetTransform( padfTransform ) )
299 1 : return CE_None;
300 : else
301 0 : return CE_Failure;
302 : }
303 :
304 : /************************************************************************/
305 : /* GetProjectionRef() */
306 : /************************************************************************/
307 :
308 1 : const char *SDTSDataset::GetProjectionRef()
309 :
310 : {
311 1 : return pszProjection;
312 : }
313 :
314 : /************************************************************************/
315 : /* ==================================================================== */
316 : /* SDTSRasterBand */
317 : /* ==================================================================== */
318 : /************************************************************************/
319 :
320 : /************************************************************************/
321 : /* SDTSRasterBand() */
322 : /************************************************************************/
323 :
324 2 : SDTSRasterBand::SDTSRasterBand( SDTSDataset *poDS, int nBand,
325 2 : SDTSRasterReader * poRL )
326 :
327 : {
328 2 : this->poDS = poDS;
329 2 : this->nBand = nBand;
330 2 : this->poRL = poRL;
331 :
332 2 : if( poRL->GetRasterType() == SDTS_RT_INT16 )
333 2 : eDataType = GDT_Int16;
334 : else
335 0 : eDataType = GDT_Float32;
336 :
337 2 : nBlockXSize = poRL->GetBlockXSize();
338 2 : nBlockYSize = poRL->GetBlockYSize();
339 2 : }
340 :
341 : /************************************************************************/
342 : /* IReadBlock() */
343 : /************************************************************************/
344 :
345 25 : CPLErr SDTSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
346 : void * pImage )
347 :
348 : {
349 25 : if( poRL->GetBlock( nBlockXOff, nBlockYOff, pImage ) )
350 25 : return CE_None;
351 : else
352 0 : return CE_Failure;
353 : }
354 :
355 : /************************************************************************/
356 : /* GetNoDataValue() */
357 : /************************************************************************/
358 :
359 0 : double SDTSRasterBand::GetNoDataValue( int *pbSuccess )
360 :
361 : {
362 0 : if( pbSuccess != NULL )
363 0 : *pbSuccess = TRUE;
364 :
365 0 : return -32766.0;
366 : }
367 :
368 : /************************************************************************/
369 : /* GetUnitType() */
370 : /************************************************************************/
371 :
372 0 : const char *SDTSRasterBand::GetUnitType()
373 :
374 : {
375 0 : if( EQUAL(poRL->szUNITS,"FEET") )
376 0 : return "ft";
377 0 : else if( EQUALN(poRL->szUNITS,"MET",3) )
378 0 : return "m";
379 : else
380 0 : return poRL->szUNITS;
381 : }
382 :
383 : /************************************************************************/
384 : /* GDALRegister_SDTS() */
385 : /************************************************************************/
386 :
387 338 : void GDALRegister_SDTS()
388 :
389 : {
390 : GDALDriver *poDriver;
391 :
392 338 : if( GDALGetDriverByName( "SDTS" ) == NULL )
393 : {
394 336 : poDriver = new GDALDriver();
395 :
396 336 : poDriver->SetDescription( "SDTS" );
397 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
398 336 : "SDTS Raster" );
399 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
400 336 : "frmt_various.html#SDTS" );
401 336 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ddf" );
402 :
403 336 : poDriver->pfnOpen = SDTSDataset::Open;
404 :
405 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
406 : }
407 338 : }
408 :
|