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