1 : /******************************************************************************
2 : * $Id: sdtstransfer.cpp 10645 2007-01-18 02:22:39Z warmerdam $
3 : *
4 : * Project: SDTS Translator
5 : * Purpose: Implementation of SDTSTransfer class.
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 :
32 : CPL_CVSID("$Id: sdtstransfer.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
33 :
34 : /************************************************************************/
35 : /* SDTSTransfer() */
36 : /************************************************************************/
37 :
38 12 : SDTSTransfer::SDTSTransfer()
39 :
40 : {
41 12 : nLayers = 0;
42 12 : panLayerCATDEntry = NULL;
43 12 : papoLayerReader = NULL;
44 12 : }
45 :
46 : /************************************************************************/
47 : /* ~SDTSTransfer() */
48 : /************************************************************************/
49 :
50 12 : SDTSTransfer::~SDTSTransfer()
51 :
52 : {
53 12 : Close();
54 12 : }
55 :
56 :
57 : /************************************************************************/
58 : /* Open() */
59 : /************************************************************************/
60 :
61 : /**
62 : * Open an SDTS transfer, and establish a list of data layers in the
63 : * transfer.
64 : *
65 : * @param pszFilename The name of the CATD file within the transfer.
66 : *
67 : * @return TRUE if the open success, or FALSE if it fails.
68 : */
69 :
70 12 : int SDTSTransfer::Open( const char * pszFilename )
71 :
72 : {
73 : /* -------------------------------------------------------------------- */
74 : /* Open the catalog. */
75 : /* -------------------------------------------------------------------- */
76 12 : if( !oCATD.Read( pszFilename ) )
77 9 : return FALSE;
78 :
79 :
80 : /* -------------------------------------------------------------------- */
81 : /* Read the IREF file. */
82 : /* -------------------------------------------------------------------- */
83 3 : if( oCATD.GetModuleFilePath( "IREF" ) == NULL )
84 : {
85 : CPLError( CE_Failure, CPLE_AppDefined,
86 : "Can't find IREF module in transfer `%s'.\n",
87 0 : pszFilename );
88 0 : return FALSE;
89 : }
90 :
91 3 : if( !oIREF.Read( oCATD.GetModuleFilePath( "IREF" ) ) )
92 0 : return FALSE;
93 :
94 : /* -------------------------------------------------------------------- */
95 : /* Read the XREF file. */
96 : /* -------------------------------------------------------------------- */
97 3 : if( oCATD.GetModuleFilePath( "XREF" ) == NULL )
98 : {
99 : CPLError( CE_Warning, CPLE_AppDefined,
100 : "Can't find XREF module in transfer `%s'.\n",
101 0 : pszFilename );
102 : }
103 3 : else if( !oXREF.Read( oCATD.GetModuleFilePath( "XREF" ) ) )
104 : {
105 : CPLError( CE_Warning, CPLE_AppDefined,
106 : "Can't read XREF module, even though found in transfer `%s'.\n",
107 0 : pszFilename );
108 : }
109 :
110 : /* -------------------------------------------------------------------- */
111 : /* Build an index of layer types we recognise and care about. */
112 : /* -------------------------------------------------------------------- */
113 : int iCATDLayer;
114 :
115 3 : panLayerCATDEntry = (int *) CPLMalloc(sizeof(int) * oCATD.GetEntryCount());
116 :
117 63 : for( iCATDLayer = 0; iCATDLayer < oCATD.GetEntryCount(); iCATDLayer++ )
118 : {
119 60 : switch( oCATD.GetEntryType(iCATDLayer) )
120 : {
121 : case SLTPoint:
122 : case SLTLine:
123 : case SLTAttr:
124 : case SLTPoly:
125 : case SLTRaster:
126 10 : panLayerCATDEntry[nLayers++] = iCATDLayer;
127 : break;
128 :
129 : default:
130 : /* ignore */
131 : break;
132 : }
133 : }
134 :
135 : /* -------------------------------------------------------------------- */
136 : /* Initialized the related indexed readers list. */
137 : /* -------------------------------------------------------------------- */
138 : papoLayerReader = (SDTSIndexedReader **)
139 3 : CPLCalloc(sizeof(SDTSIndexedReader*),oCATD.GetEntryCount());
140 :
141 3 : return TRUE;
142 : }
143 :
144 : /************************************************************************/
145 : /* Close() */
146 : /************************************************************************/
147 :
148 12 : void SDTSTransfer::Close()
149 :
150 : {
151 22 : for( int i = 0; i < nLayers; i++ )
152 : {
153 10 : if( papoLayerReader[i] != NULL )
154 8 : delete papoLayerReader[i];
155 : }
156 12 : CPLFree( papoLayerReader );
157 12 : papoLayerReader = NULL;
158 12 : CPLFree( panLayerCATDEntry );
159 12 : panLayerCATDEntry = NULL;
160 12 : nLayers = 0;
161 12 : }
162 :
163 : /************************************************************************/
164 : /* GetLayerType() */
165 : /************************************************************************/
166 :
167 : /**
168 : Fetch type of requested feature layer.
169 :
170 : @param iEntry the index of the layer to fetch information on. A value
171 : from zero to GetLayerCount()-1.
172 :
173 : @return the layer type.
174 :
175 : <ul>
176 : <li> SLTPoint: A point layer. An SDTSPointReader is returned by
177 : SDTSTransfer::GetLayerIndexedReader().
178 :
179 : <li> SLTLine: A line layer. An SDTSLineReader is returned by
180 : SDTSTransfer::GetLayerIndexedReader().
181 :
182 : <li> SLTAttr: An attribute primary or secondary layer. An SDTSAttrReader
183 : is returned by SDTSTransfer::GetLayerIndexedReader().
184 :
185 : <li> SLTPoly: A polygon layer. An SDTSPolygonReader is returned by
186 : SDTSTransfer::GetLayerIndexedReader().
187 :
188 : <li> SLTRaster: A raster layer. SDTSTransfer::GetLayerIndexedReader()
189 : is not implemented. Use SDTSTransfer::GetLayerRasterReader() instead.
190 : </ul>
191 :
192 : */
193 :
194 1200 : SDTSLayerType SDTSTransfer::GetLayerType( int iEntry )
195 :
196 : {
197 1200 : if( iEntry < 0 || iEntry >= nLayers )
198 0 : return SLTUnknown;
199 :
200 1200 : return oCATD.GetEntryType( panLayerCATDEntry[iEntry] );
201 : }
202 :
203 : /************************************************************************/
204 : /* GetLayerCATDEntry() */
205 : /************************************************************************/
206 :
207 : /**
208 : Fetch the CATD module index for a layer. This can be used to fetch
209 : details about the layer/module from the SDTS_CATD object, such as it's
210 : filename, and description.
211 :
212 : @param iEntry the layer index from 0 to GetLayerCount()-1.
213 :
214 : @return the module index suitable for use with the various SDTS_CATD
215 : methods.
216 : */
217 :
218 8 : int SDTSTransfer::GetLayerCATDEntry( int iEntry )
219 :
220 : {
221 8 : if( iEntry < 0 || iEntry >= nLayers )
222 0 : return -1;
223 :
224 8 : return panLayerCATDEntry[iEntry];
225 : }
226 :
227 : /************************************************************************/
228 : /* GetLayerLineReader() */
229 : /************************************************************************/
230 :
231 1 : SDTSLineReader *SDTSTransfer::GetLayerLineReader( int iEntry )
232 :
233 : {
234 : SDTSLineReader *poLineReader;
235 :
236 1 : if( iEntry < 0
237 : || iEntry >= nLayers
238 : || oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) != SLTLine )
239 : {
240 0 : return NULL;
241 : }
242 :
243 :
244 1 : poLineReader = new SDTSLineReader( &oIREF );
245 :
246 1 : if( !poLineReader->Open(
247 : oCATD.GetEntryFilePath( panLayerCATDEntry[iEntry] ) ) )
248 : {
249 0 : delete poLineReader;
250 0 : return NULL;
251 : }
252 : else
253 : {
254 1 : return poLineReader;
255 : }
256 : }
257 :
258 : /************************************************************************/
259 : /* GetLayerPointReader() */
260 : /************************************************************************/
261 :
262 3 : SDTSPointReader *SDTSTransfer::GetLayerPointReader( int iEntry )
263 :
264 : {
265 : SDTSPointReader *poPointReader;
266 :
267 3 : if( iEntry < 0
268 : || iEntry >= nLayers
269 : || oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) != SLTPoint )
270 : {
271 0 : return NULL;
272 : }
273 :
274 :
275 3 : poPointReader = new SDTSPointReader( &oIREF );
276 :
277 3 : if( !poPointReader->Open(
278 : oCATD.GetEntryFilePath( panLayerCATDEntry[iEntry] ) ) )
279 : {
280 0 : delete poPointReader;
281 0 : return NULL;
282 : }
283 : else
284 : {
285 3 : return poPointReader;
286 : }
287 : }
288 :
289 : /************************************************************************/
290 : /* GetLayerPolygonReader() */
291 : /************************************************************************/
292 :
293 1 : SDTSPolygonReader *SDTSTransfer::GetLayerPolygonReader( int iEntry )
294 :
295 : {
296 : SDTSPolygonReader *poPolyReader;
297 :
298 1 : if( iEntry < 0
299 : || iEntry >= nLayers
300 : || oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) != SLTPoly )
301 : {
302 0 : return NULL;
303 : }
304 :
305 :
306 1 : poPolyReader = new SDTSPolygonReader();
307 :
308 1 : if( !poPolyReader->Open(
309 : oCATD.GetEntryFilePath( panLayerCATDEntry[iEntry] ) ) )
310 : {
311 0 : delete poPolyReader;
312 0 : return NULL;
313 : }
314 : else
315 : {
316 1 : return poPolyReader;
317 : }
318 : }
319 :
320 : /************************************************************************/
321 : /* GetLayerAttrReader() */
322 : /************************************************************************/
323 :
324 3 : SDTSAttrReader *SDTSTransfer::GetLayerAttrReader( int iEntry )
325 :
326 : {
327 : SDTSAttrReader *poAttrReader;
328 :
329 3 : if( iEntry < 0
330 : || iEntry >= nLayers
331 : || oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) != SLTAttr )
332 : {
333 0 : return NULL;
334 : }
335 :
336 :
337 3 : poAttrReader = new SDTSAttrReader( &oIREF );
338 :
339 3 : if( !poAttrReader->Open(
340 : oCATD.GetEntryFilePath( panLayerCATDEntry[iEntry] ) ) )
341 : {
342 0 : delete poAttrReader;
343 0 : return NULL;
344 : }
345 : else
346 : {
347 3 : return poAttrReader;
348 : }
349 : }
350 :
351 : /************************************************************************/
352 : /* GetLayerRasterReader() */
353 : /************************************************************************/
354 :
355 : /**
356 : Instantiate an SDTSRasterReader for the indicated layer.
357 :
358 : @param iEntry the index of the layer to instantiate a reader for. A
359 : value between 0 and GetLayerCount()-1.
360 :
361 : @return a pointer to a new SDTSRasterReader object, or NULL if the method
362 : fails.
363 :
364 : NOTE: The reader returned from GetLayerRasterReader() becomes the
365 : responsibility of the caller to delete, and isn't automatically deleted
366 : when the SDTSTransfer is destroyed. This method is different from
367 : the GetLayerIndexedReader() method in this regard.
368 : */
369 :
370 2 : SDTSRasterReader *SDTSTransfer::GetLayerRasterReader( int iEntry )
371 :
372 : {
373 : SDTSRasterReader *poRasterReader;
374 :
375 2 : if( iEntry < 0
376 : || iEntry >= nLayers
377 : || oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) != SLTRaster )
378 : {
379 0 : return NULL;
380 : }
381 :
382 2 : poRasterReader = new SDTSRasterReader();
383 :
384 2 : if( !poRasterReader->Open( &oCATD, &oIREF,
385 : oCATD.GetEntryModule(panLayerCATDEntry[iEntry] ) ) )
386 : {
387 0 : delete poRasterReader;
388 0 : return NULL;
389 : }
390 : else
391 : {
392 2 : return poRasterReader;
393 : }
394 : }
395 :
396 : /************************************************************************/
397 : /* GetLayerModuleReader() */
398 : /************************************************************************/
399 :
400 0 : DDFModule *SDTSTransfer::GetLayerModuleReader( int iEntry )
401 :
402 : {
403 : DDFModule *poModuleReader;
404 :
405 0 : if( iEntry < 0 || iEntry >= nLayers )
406 : {
407 0 : return NULL;
408 : }
409 :
410 :
411 0 : poModuleReader = new DDFModule;
412 :
413 0 : if( !poModuleReader->Open(
414 : oCATD.GetEntryFilePath( panLayerCATDEntry[iEntry] ) ) )
415 : {
416 0 : delete poModuleReader;
417 0 : return NULL;
418 : }
419 : else
420 : {
421 0 : return poModuleReader;
422 : }
423 : }
424 :
425 : /************************************************************************/
426 : /* GetLayerIndexedReader() */
427 : /************************************************************************/
428 :
429 : /**
430 : Returns a pointer to a reader of the appropriate type to the requested
431 : layer.
432 :
433 : Notes:
434 : <ul>
435 : <li> The returned reader remains owned by the SDTSTransfer, and will be
436 : destroyed when the SDTSTransfer is destroyed. It should not be
437 : destroyed by the application.
438 :
439 : <li> If an indexed reader was already created for this layer using
440 : GetLayerIndexedReader(), it will be returned instead of creating a new
441 : reader. Amoung other things this means that the returned reader may not
442 : be positioned to read from the beginning of the module, and may already
443 : have it's index filled.
444 :
445 : <li> The returned reader will be of a type appropriate to the layer.
446 : See SDTSTransfer::GetLayerType() to see what reader classes correspond
447 : to what layer types, so it can be cast accordingly (if necessary).
448 :
449 : </ul>
450 :
451 : @param iEntry the index of the layer to instantiate a reader for. A
452 : value between 0 and GetLayerCount()-1.
453 :
454 : @return a pointer to an appropriate reader or NULL if the method fails.
455 : */
456 :
457 28 : SDTSIndexedReader *SDTSTransfer::GetLayerIndexedReader( int iEntry )
458 :
459 : {
460 28 : if( papoLayerReader[iEntry] == NULL )
461 : {
462 8 : switch( oCATD.GetEntryType( panLayerCATDEntry[iEntry] ) )
463 : {
464 : case SLTAttr:
465 3 : papoLayerReader[iEntry] = GetLayerAttrReader( iEntry );
466 3 : break;
467 :
468 : case SLTPoint:
469 3 : papoLayerReader[iEntry] = GetLayerPointReader( iEntry );
470 3 : break;
471 :
472 : case SLTLine:
473 1 : papoLayerReader[iEntry] = GetLayerLineReader( iEntry );
474 1 : break;
475 :
476 : case SLTPoly:
477 1 : papoLayerReader[iEntry] = GetLayerPolygonReader( iEntry );
478 : break;
479 :
480 : default:
481 : break;
482 : }
483 : }
484 :
485 28 : return papoLayerReader[iEntry];
486 : }
487 :
488 : /************************************************************************/
489 : /* FindLayer() */
490 : /************************************************************************/
491 :
492 : /**
493 : Fetch the SDTSTransfer layer number corresponding to a module name.
494 :
495 : @param pszModule the name of the module to search for, such as "PC01".
496 :
497 : @return the layer number (between 0 and GetLayerCount()-1 corresponding to
498 : the module, or -1 if it doesn't correspond to a layer.
499 : */
500 :
501 11 : int SDTSTransfer::FindLayer( const char * pszModule )
502 :
503 : {
504 : int iLayer;
505 :
506 21 : for( iLayer = 0; iLayer < nLayers; iLayer++ )
507 : {
508 21 : if( EQUAL(pszModule,
509 : oCATD.GetEntryModule( panLayerCATDEntry[iLayer] ) ) )
510 : {
511 11 : return iLayer;
512 : }
513 : }
514 :
515 0 : return -1;
516 : }
517 :
518 : /************************************************************************/
519 : /* GetIndexedFeatureRef() */
520 : /************************************************************************/
521 :
522 6 : SDTSFeature *SDTSTransfer::GetIndexedFeatureRef( SDTSModId *poModId,
523 : SDTSLayerType *peType )
524 :
525 : {
526 : /* -------------------------------------------------------------------- */
527 : /* Find the desired layer ... this is likely a significant slow */
528 : /* point in the whole process ... perhaps the last found could */
529 : /* be cached or something. */
530 : /* -------------------------------------------------------------------- */
531 6 : int iLayer = FindLayer( poModId->szModule );
532 6 : if( iLayer == -1 )
533 0 : return NULL;
534 :
535 : /* -------------------------------------------------------------------- */
536 : /* Get the reader, and read a feature from it. */
537 : /* -------------------------------------------------------------------- */
538 : SDTSIndexedReader *poReader;
539 :
540 6 : poReader = GetLayerIndexedReader( iLayer );
541 6 : if( poReader == NULL )
542 0 : return NULL;
543 :
544 : /* -------------------------------------------------------------------- */
545 : /* return type, if requested. */
546 : /* -------------------------------------------------------------------- */
547 6 : if( peType != NULL )
548 0 : *peType = GetLayerType(iLayer);
549 :
550 6 : return poReader->GetIndexedFeatureRef( poModId->nRecord );
551 : }
552 :
553 : /************************************************************************/
554 : /* GetAttr() */
555 : /* */
556 : /* Fetch the attribute information corresponding to a given */
557 : /* SDTSModId. */
558 : /************************************************************************/
559 :
560 : /**
561 : Fetch the attribute fields given a particular module/record id.
562 :
563 : @param poModId an attribute record identifer, normally taken from the
564 : aoATID[] array of an SDTSIndexedFeature.
565 :
566 : @return a pointer to the DDFField containing the user attribute values as
567 : subfields.
568 : */
569 :
570 6 : DDFField *SDTSTransfer::GetAttr( SDTSModId *poModId )
571 :
572 : {
573 : SDTSAttrRecord *poAttrRecord;
574 :
575 6 : poAttrRecord = (SDTSAttrRecord *) GetIndexedFeatureRef( poModId );
576 :
577 6 : if( poAttrRecord == NULL )
578 0 : return NULL;
579 :
580 6 : return poAttrRecord->poATTR;
581 : }
582 :
583 : /************************************************************************/
584 : /* GetBounds() */
585 : /************************************************************************/
586 :
587 : /**
588 : Fetch approximate bounds for a transfer by scanning all point layers
589 : and raster layers.
590 :
591 : For TVP datasets (where point layers are scanned) the results can, in
592 : theory miss some lines that go outside the bounds of the point layers.
593 : However, this isn't common since most TVP sets contain a bounding rectangle
594 : whose corners will define the most extreme extents.
595 :
596 : @param pdfMinX western edge of dataset
597 : @param pdfMinY southern edge of dataset
598 : @param pdfMaxX eastern edge of dataset
599 : @param pdfMaxY northern edge of dataset
600 :
601 : @return TRUE if success, or FALSE on a failure.
602 : */
603 :
604 0 : int SDTSTransfer::GetBounds( double *pdfMinX, double *pdfMinY,
605 : double *pdfMaxX, double *pdfMaxY )
606 :
607 : {
608 0 : int bFirst = TRUE;
609 :
610 0 : for( int iLayer = 0; iLayer < GetLayerCount(); iLayer++ )
611 : {
612 0 : if( GetLayerType( iLayer ) == SLTPoint )
613 : {
614 : SDTSPointReader *poLayer;
615 : SDTSRawPoint *poPoint;
616 :
617 0 : poLayer = (SDTSPointReader *) GetLayerIndexedReader( iLayer );
618 0 : if( poLayer == NULL )
619 0 : continue;
620 :
621 0 : poLayer->Rewind();
622 0 : while( (poPoint = (SDTSRawPoint*) poLayer->GetNextFeature()) )
623 : {
624 0 : if( bFirst )
625 : {
626 0 : *pdfMinX = *pdfMaxX = poPoint->dfX;
627 0 : *pdfMinY = *pdfMaxY = poPoint->dfY;
628 0 : bFirst = FALSE;
629 : }
630 : else
631 : {
632 0 : *pdfMinX = MIN(*pdfMinX,poPoint->dfX);
633 0 : *pdfMaxX = MAX(*pdfMaxX,poPoint->dfX);
634 0 : *pdfMinY = MIN(*pdfMinY,poPoint->dfY);
635 0 : *pdfMaxY = MAX(*pdfMaxY,poPoint->dfY);
636 : }
637 :
638 0 : if( !poLayer->IsIndexed() )
639 0 : delete poPoint;
640 : }
641 : }
642 :
643 0 : else if( GetLayerType( iLayer ) == SLTRaster )
644 : {
645 : SDTSRasterReader *poRL;
646 : double adfGeoTransform[6];
647 : double dfMinX, dfMaxX, dfMinY, dfMaxY;
648 :
649 0 : poRL = GetLayerRasterReader( iLayer );
650 0 : if( poRL == NULL )
651 0 : continue;
652 :
653 0 : poRL->GetTransform( adfGeoTransform );
654 :
655 0 : dfMinX = adfGeoTransform[0];
656 0 : dfMaxY = adfGeoTransform[3];
657 0 : dfMaxX = adfGeoTransform[0] + poRL->GetXSize()*adfGeoTransform[1];
658 0 : dfMinY = adfGeoTransform[3] + poRL->GetYSize()*adfGeoTransform[5];
659 :
660 0 : if( bFirst )
661 : {
662 0 : *pdfMinX = dfMinX;
663 0 : *pdfMaxX = dfMaxX;
664 0 : *pdfMinY = dfMinY;
665 0 : *pdfMaxY = dfMaxY;
666 0 : bFirst = FALSE;
667 : }
668 : else
669 : {
670 0 : *pdfMinX = MIN(dfMinX,*pdfMinX);
671 0 : *pdfMaxX = MAX(dfMaxX,*pdfMaxX);
672 0 : *pdfMinY = MIN(dfMinY,*pdfMinY);
673 0 : *pdfMaxY = MAX(dfMaxY,*pdfMaxY);
674 : }
675 :
676 0 : delete poRL;
677 : }
678 : }
679 :
680 0 : return !bFirst;
681 : }
682 :
|