1 /******************************************************************************
2  * $Id: sdts_al.h 2ace03ec48c36dae8ba74089d85617c095643428 2018-11-02 18:02:33 +0100 Even Rouault $
3  *
4  * Project:  SDTS Translator
5  * Purpose:  Include file for entire SDTS Abstraction Layer functions.
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 #ifndef SDTS_AL_H_INCLUDED
31 #define SDTS_AL_H_INCLUDED
32 
33 #include "cpl_conv.h"
34 #include "iso8211.h"
35 
36 class SDTS_IREF;
37 class SDTSModId;
38 class SDTSTransfer;
39 
40 #define SDTS_SIZEOF_SADR        8
41 
42 char **SDTSScanModuleReferences( DDFModule *, const char * );
43 
44 /************************************************************************/
45 /*                              SDTS_IREF                               */
46 /************************************************************************/
47 
48 /**
49   Class holding SDTS IREF (internal reference) information, internal
50   coordinate system format, scaling and resolution.  This object isn't
51   normally needed by applications.
52 */
53 class SDTS_IREF
54 {
55     int         nDefaultSADRFormat;
56 
57   public:
58                 SDTS_IREF();
59                 ~SDTS_IREF();
60 
61     int         Read( const char *pszFilename );
62 
63     char        *pszXAxisName;                  /* XLBL */
64     char        *pszYAxisName;                  /* YLBL */
65 
66     double      dfXScale;                       /* SFAX */
67     double      dfYScale;                       /* SFAY */
68 
69     double      dfXOffset;                      /* XORG */
70     double      dfYOffset;                      /* YORG */
71 
72     double      dfXRes;                         /* XHRS */
73     double      dfYRes;                         /* YHRS */
74 
75     char        *pszCoordinateFormat;           /* HFMT */
76 
77     int         GetSADRCount( DDFField * ) const;
78     int         GetSADR( DDFField *, int, double *, double *, double * );
79 };
80 
81 /************************************************************************/
82 /*                              SDTS_XREF                               */
83 /************************************************************************/
84 
85 /**
86   Class for reading the XREF (external reference) module containing the
87   data projection definition.
88 */
89 
90 class SDTS_XREF
91 {
92   public:
93                 SDTS_XREF();
94                 ~SDTS_XREF();
95 
96     int         Read( const char *pszFilename );
97 
98     /** Projection system name, from the RSNM field.  One of GEO, SPCS, UTM,
99         UPS, OTHR, UNSP. */
100     char        *pszSystemName;
101 
102     /** Horizontal datum name, from the HDAT field.  One of NAS, NAX, WGA,
103         WGB, WGC, WGE. */
104     char        *pszDatum;
105 
106     /** Zone number for UTM and SPCS projections, from the ZONE field. */
107     int         nZone;
108 };
109 
110 /************************************************************************/
111 /*                              SDTS_CATD                               */
112 /************************************************************************/
113 class SDTS_CATDEntry;
114 
115 /**
116   List of feature layer types.  See SDTSTransfer::GetLayerType().
117   */
118 
119 typedef enum {
120   SLTUnknown,
121   SLTPoint,
122   SLTLine,
123   SLTAttr,
124   SLTPoly,
125   SLTRaster
126 } SDTSLayerType;
127 
128 /**
129   Class for accessing the CATD (Catalog Directory) file containing a list of
130   all other files (modules) in the transfer.
131 */
132 class SDTS_CATD
133 {
134     char        *pszPrefixPath;
135 
136     int         nEntries;
137     SDTS_CATDEntry **papoEntries;
138 
139   public:
140                 SDTS_CATD();
141                 ~SDTS_CATD();
142 
143     int         Read( const char * pszFilename );
144 
145     const char  *GetModuleFilePath( const char * pszModule ) const;
146 
GetEntryCount()147     int         GetEntryCount() const { return nEntries; }
148     const char * GetEntryModule(int) const;
149     const char * GetEntryTypeDesc(int) const;
150     const char * GetEntryFilePath(int) const;
151     SDTSLayerType GetEntryType(int) const;
152     void          SetEntryTypeUnknown(int);
153 };
154 
155 /************************************************************************/
156 /*                              SDTSModId                               */
157 /************************************************************************/
158 
159 /**
160   Object representing a unique module/record identifier within an SDTS
161   transfer.
162 */
163 class SDTSModId
164 {
165   public:
SDTSModId()166                 SDTSModId() { szModule[0] = '\0';
167                               nRecord = -1;
168                               szOBRP[0] = '\0';
169                               szName[0] = '\0'; }
170 
171     int         Set( DDFField * );
172 
173     const char *GetName();
174 
175     /** The module name, such as PC01, containing the indicated record. */
176     char        szModule[8];
177 
178     /** The record within the module referred to.  This is -1 for unused
179         SDTSModIds. */
180     int         nRecord;
181 
182     /** The "role" of this record within the module.  This is normally empty
183         for references, but set in the oModId member of a feature.  */
184     char        szOBRP[8];
185 
186     /** String "szModule:nRecord" */
187     char        szName[20];
188 };
189 
190 /************************************************************************/
191 /*                             SDTSFeature                              */
192 /************************************************************************/
193 
194 /**
195   Base class for various SDTS features classes, providing a generic
196   module identifier, and list of attribute references.
197 */
198 class SDTSFeature
199 {
200 public:
201 
202                         SDTSFeature();
203     virtual            ~SDTSFeature();
204 
205     /** Unique identifier for this record/feature within transfer. */
206     SDTSModId           oModId;
207 
208     /** Number of attribute links (aoATID[]) on this feature. */
209     int         nAttributes;
210 
211     /** List of nAttributes attribute record identifiers related to this
212         feature.  */
213     SDTSModId   *paoATID;
214 
215     void        ApplyATID( DDFField * );
216 
217     /** Dump readable description of feature to indicated stream. */
218     virtual void Dump( FILE * ) = 0;
219 };
220 
221 /************************************************************************/
222 /*                          SDTSIndexedReader                           */
223 /************************************************************************/
224 
225 /**
226   Base class for all the SDTSFeature type readers.  Provides feature
227   caching semantics and fetching based on a record number.
228   */
229 
230 class SDTSIndexedReader
231 {
232     int                 nIndexSize;
233     SDTSFeature       **papoFeatures;
234 
235     int                 iCurrentFeature;
236 
237 protected:
238     DDFModule           oDDFModule;
239 
240 public:
241                         SDTSIndexedReader();
242     virtual            ~SDTSIndexedReader();
243 
244     virtual SDTSFeature  *GetNextRawFeature() = 0;
245 
246     SDTSFeature        *GetNextFeature();
247 
248     virtual void        Rewind();
249 
250     void                FillIndex();
251     void                ClearIndex();
252     int                 IsIndexed() const;
253 
254     SDTSFeature        *GetIndexedFeatureRef( int );
255     char **             ScanModuleReferences( const char * = "ATID" );
256 
GetModule()257     DDFModule          *GetModule() { return &oDDFModule; }
258 };
259 
260 /************************************************************************/
261 /*                             SDTSRawLine                              */
262 /************************************************************************/
263 
264 /** SDTS line feature, as read from LE* modules by SDTSLineReader. */
265 
266 class SDTSRawLine : public SDTSFeature
267 {
268   public:
269                 SDTSRawLine();
270     virtual    ~SDTSRawLine();
271 
272     int         Read( SDTS_IREF *, DDFRecord * );
273 
274     /** Number of vertices in the padfX, padfY and padfZ arrays. */
275     int         nVertices;
276 
277     /** List of nVertices X coordinates. */
278     double      *padfX;
279     /** List of nVertices Y coordinates. */
280     double      *padfY;
281     /** List of nVertices Z coordinates - currently always zero. */
282     double      *padfZ;
283 
284     /** Identifier of polygon to left of this line.  This is the SDTS PIDL
285         subfield. */
286     SDTSModId   oLeftPoly;
287 
288     /** Identifier of polygon to right of this line.  This is the SDTS PIDR
289         subfield. */
290     SDTSModId   oRightPoly;
291 
292     /** Identifier for the start node of this line.  This is the SDTS SNID
293         subfield. */
294     SDTSModId   oStartNode;             /* SNID */
295 
296     /** Identifier for the end node of this line.  This is the SDTS ENID
297         subfield. */
298     SDTSModId   oEndNode;               /* ENID */
299 
300     void        Dump( FILE * ) override;
301 };
302 
303 /************************************************************************/
304 /*                            SDTSLineReader                            */
305 /*                                                                      */
306 /*      Class for reading any of the files lines.                       */
307 /************************************************************************/
308 
309 /**
310   Reader for SDTS line modules.
311 
312   Returns SDTSRawLine features. Normally readers are instantiated with
313   the SDTSTransfer::GetIndexedReader() method.
314 
315   */
316 
317 class SDTSLineReader : public SDTSIndexedReader
318 {
319     SDTS_IREF   *poIREF;
320 
321   public:
322                 explicit SDTSLineReader( SDTS_IREF * );
323                 ~SDTSLineReader();
324 
325     int         Open( const char * );
326     SDTSRawLine *GetNextLine();
327     void        Close();
328 
GetNextRawFeature()329     SDTSFeature *GetNextRawFeature() override { return GetNextLine(); }
330 
331     void        AttachToPolygons( SDTSTransfer *, int iPolyLayer  );
332 };
333 
334 /************************************************************************/
335 /*                            SDTSAttrRecord                            */
336 /************************************************************************/
337 
338 /**
339   SDTS attribute record feature, as read from A* modules by
340   SDTSAttrReader.
341 
342   Note that even though SDTSAttrRecord is derived from SDTSFeature, there
343   are never any attribute records associated with attribute records using
344   the aoATID[] mechanism.  SDTSFeature::nAttributes will always be zero.
345   */
346 
347 class SDTSAttrRecord : public SDTSFeature
348 {
349   public:
350                 SDTSAttrRecord();
351     virtual    ~SDTSAttrRecord();
352 
353     /** The entire DDFRecord read from the file. */
354     DDFRecord   *poWholeRecord;
355 
356     /** The ATTR DDFField with the user attribute.  Each subfield is a
357         attribute value. */
358 
359     DDFField    *poATTR;
360 
361     virtual void Dump( FILE * ) override;
362 };
363 
364 /************************************************************************/
365 /*                            SDTSAttrReader                            */
366 /************************************************************************/
367 
368 /**
369   Class for reading SDTSAttrRecord features from a primary or secondary
370   attribute module.
371   */
372 
373 class SDTSAttrReader : public SDTSIndexedReader
374 {
375     int         bIsSecondary;
376 
377   public:
378                 SDTSAttrReader();
379    virtual     ~SDTSAttrReader();
380 
381     int         Open( const char * );
382     DDFField    *GetNextRecord( SDTSModId * = nullptr,
383                                 DDFRecord ** = nullptr,
384                                 int bDuplicate = FALSE );
385     SDTSAttrRecord *GetNextAttrRecord();
386     void        Close();
387 
388     /**
389       Returns TRUE if this is a Attribute Secondary layer rather than
390       an Attribute Primary layer.
391       */
IsSecondary()392     int         IsSecondary() const { return bIsSecondary; }
393 
GetNextRawFeature()394     SDTSFeature *GetNextRawFeature() override { return GetNextAttrRecord(); }
395 };
396 
397 /************************************************************************/
398 /*                             SDTSRawPoint                             */
399 /************************************************************************/
400 
401 /**
402   Object containing a point feature (type NA, NO or NP).
403   */
404 class SDTSRawPoint : public SDTSFeature
405 {
406   public:
407                 SDTSRawPoint();
408     virtual    ~SDTSRawPoint();
409 
410     int         Read( SDTS_IREF *, DDFRecord * );
411 
412     /** X coordinate of point. */
413     double      dfX;
414     /** Y coordinate of point. */
415     double      dfY;
416     /** Z coordinate of point. */
417     double      dfZ;
418 
419     /** Optional identifier of area marked by this point (i.e. PC01:27). */
420     SDTSModId   oAreaId;                /* ARID */
421 
422     virtual void Dump( FILE * ) override;
423 };
424 
425 /************************************************************************/
426 /*                           SDTSPointReader                            */
427 /************************************************************************/
428 
429 /**
430   Class for reading SDTSRawPoint features from a point module (type NA, NO
431   or NP).
432   */
433 
434 class SDTSPointReader : public SDTSIndexedReader
435 {
436     SDTS_IREF   *poIREF;
437 
438   public:
439                 explicit SDTSPointReader( SDTS_IREF * );
440     virtual    ~SDTSPointReader();
441 
442     int         Open( const char * );
443     SDTSRawPoint *GetNextPoint();
444     void        Close();
445 
GetNextRawFeature()446     SDTSFeature *GetNextRawFeature() override { return GetNextPoint(); }
447 };
448 
449 /************************************************************************/
450 /*                             SDTSRawPolygon                           */
451 /************************************************************************/
452 
453 /**
454   Class for holding information about a polygon feature.
455 
456   When directly read from a polygon module, the polygon has no concept
457   of its geometry.  Just its ID, and references to attribute records.
458   However, if the SDTSLineReader::AttachToPolygons() method is called on
459   the module containing the lines forming the polygon boundaries, then the
460   nEdges/papoEdges information on the SDTSRawPolygon will be filled in.
461 
462   Once this is complete the AssembleRings() method can be used to fill in the
463   nRings/nVertices/panRingStart/padfX/padfY/padfZ information defining the
464   ring geometry.
465 
466   Note that the rings may not appear in any particular order, nor with any
467   meaningful direction (clockwise or counterclockwise).
468   */
469 
470 class SDTSRawPolygon : public SDTSFeature
471 {
472     void        AddEdgeToRing( int, double *, double *, double *, int, int );
473 
474   public:
475                 SDTSRawPolygon();
476     virtual    ~SDTSRawPolygon();
477 
478     int         Read( DDFRecord * );
479 
480     int         nEdges;
481     SDTSRawLine **papoEdges;
482 
483     void        AddEdge( SDTSRawLine * );
484 
485     /** This method will assemble the edges associated with a polygon into
486       rings, returning FALSE if problems are encountered during assembly. */
487     int         AssembleRings();
488 
489     /** Number of rings in assembled polygon. */
490     int         nRings;
491     /** Total number of vertices in all rings of assembled polygon. */
492     int         nVertices;
493     /** Offsets into padfX/padfY/padfZ for the beginning of each ring in the
494       polygon.  This array is nRings long. */
495     int         *panRingStart;
496 
497     /** List of nVertices X coordinates for the polygon (split over multiple
498       rings via panRingStart. */
499     double      *padfX;
500     /** List of nVertices Y coordinates for the polygon (split over multiple
501       rings via panRingStart. */
502     double      *padfY;
503     /** List of nVertices Z coordinates for the polygon (split over multiple
504       rings via panRingStart.  The values are almost always zero. */
505     double      *padfZ;
506 
507     virtual void Dump( FILE * ) override;
508 };
509 
510 /************************************************************************/
511 /*                          SDTSPolygonReader                           */
512 /************************************************************************/
513 
514 /** Class for reading SDTSRawPolygon features from a polygon (PC*) module. */
515 
516 class SDTSPolygonReader : public SDTSIndexedReader
517 {
518     int         bRingsAssembled;
519 
520   public:
521                 SDTSPolygonReader();
522     virtual    ~SDTSPolygonReader();
523 
524     int         Open( const char * );
525     SDTSRawPolygon *GetNextPolygon();
526     void        Close();
527 
GetNextRawFeature()528     SDTSFeature *GetNextRawFeature() override { return GetNextPolygon(); }
529 
530     void        AssembleRings( SDTSTransfer *, int iPolyLayer );
531 };
532 
533 /************************************************************************/
534 /*                           SDTSRasterReader                           */
535 /************************************************************************/
536 
537 /**
538   Class for reading raster data from a raster layer.
539 
540   This class is somewhat unique among the reader classes in that it isn't
541   derived from SDTSIndexedFeature, and it doesn't return "features".  Instead
542   it is used to read raster blocks, in the natural block size of the dataset.
543   */
544 
545 class SDTSRasterReader
546 {
547     DDFModule   oDDFModule;
548 
549     char        szModule[20];
550 
551     int         nXSize;
552     int         nYSize;
553     int         nXBlockSize;
554     int         nYBlockSize;
555 
556     int         nXStart;                /* SOCI */
557     int         nYStart;                /* SORI */
558 
559     double      adfTransform[6];
560 
561   public:
562     char        szINTR[4];              /* CE is center, TL is top left */
563     char        szFMT[32];
564     char        szUNITS[64];
565     char        szLabel[64];
566 
567                 SDTSRasterReader();
568                 ~SDTSRasterReader();
569 
570     int         Open( SDTS_CATD * poCATD, SDTS_IREF *,
571                       const char * pszModule  );
572     void        Close();
573 
574     int         GetRasterType();        /* 1 = int16, see GDAL types */
575 #define SDTS_RT_INT16   1
576 #define SDTS_RT_FLOAT32 6
577 
578     int         GetTransform( double * );
579 
580     int         GetMinMax( double * pdfMin, double * pdfMax,
581                            double dfNoData );
582 
583     /**
584       Fetch the raster width.
585 
586       @return the width in pixels.
587       */
GetXSize()588     int         GetXSize() const { return nXSize; }
589     /**
590       Fetch the raster height.
591 
592       @return the height in pixels.
593       */
GetYSize()594     int         GetYSize() const { return nYSize; }
595 
596     /** Fetch the width of a source block (usually same as raster width). */
GetBlockXSize()597     int         GetBlockXSize() const { return nXBlockSize; }
598     /** Fetch the height of a source block (usually one). */
GetBlockYSize()599     int         GetBlockYSize() const { return nYBlockSize; }
600 
601     int         GetBlock( int nXOffset, int nYOffset, void * pData );
602 };
603 
604 /************************************************************************/
605 /*                             SDTSTransfer                             */
606 /************************************************************************/
607 
608 /**
609   Master class representing an entire SDTS transfer.
610 
611   This class is used to open the transfer, to get a list of available
612   feature layers, and to instantiate readers for those layers.
613 
614   */
615 
616 class SDTSTransfer
617 {
618   public:
619                 SDTSTransfer();
620                 ~SDTSTransfer();
621 
622     int         Open( const char * );
623     void        Close();
624 
625     int         FindLayer( const char * );
GetLayerCount()626     int         GetLayerCount() const { return nLayers; }
627     SDTSLayerType GetLayerType( int ) const;
628     int         GetLayerCATDEntry( int ) const;
629 
630     SDTSLineReader *GetLayerLineReader( int );
631     SDTSPointReader *GetLayerPointReader( int );
632     SDTSPolygonReader *GetLayerPolygonReader( int );
633     SDTSAttrReader *GetLayerAttrReader( int );
634     SDTSRasterReader *GetLayerRasterReader( int );
635     DDFModule   *GetLayerModuleReader( int );
636 
637     SDTSIndexedReader *GetLayerIndexedReader( int );
638 
639     /**
640       Fetch the catalog object for this transfer.
641 
642       @return pointer to the internally managed SDTS_CATD for the transfer.
643       */
GetCATD()644     SDTS_CATD   *GetCATD() { return &oCATD ; }
645 
GetIREF()646     SDTS_IREF   *GetIREF() { return &oIREF; }
647 
648     /**
649       Fetch the external reference object for this transfer.
650 
651       @return pointer to the internally managed SDTS_XREF for the transfer.
652       */
GetXREF()653     SDTS_XREF   *GetXREF() { return &oXREF; }
654 
655     SDTSFeature *GetIndexedFeatureRef( SDTSModId *,
656                                        SDTSLayerType *peType = nullptr);
657 
658     DDFField *GetAttr( SDTSModId * );
659 
660     int          GetBounds( double *pdfMinX, double *pdfMinY,
661                             double *pdfMaxX, double *pdfMaxY );
662 
663   private:
664 
665     SDTS_CATD   oCATD;
666     SDTS_IREF   oIREF;
667     SDTS_XREF   oXREF;
668 
669     int         nLayers;
670     int         *panLayerCATDEntry;
671     SDTSIndexedReader **papoLayerReader;
672 };
673 
674 #endif /* ifndef SDTS_AL_H_INCLUDED */
675