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