1 /******************************************************************************
2  * $Id: s57.h 342855360b69569556916db63ea417dd3514f258 2020-06-14 15:44:48 +0200 Even Rouault $
3  *
4  * Project:  S-57 Translator
5  * Purpose:  Declarations for S-57 translator not including the
6  *           binding onto OGRLayer/DataSource/Driver which are found in
7  *           ogr_s57.h.
8  * Author:   Frank Warmerdam, warmerdam@pobox.com
9  *
10  ******************************************************************************
11  * Copyright (c) 1999, Frank Warmerdam
12  * Copyright (c) 2013, Even Rouault <even dot rouault at spatialys.com>
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the "Software"),
16  * to deal in the Software without restriction, including without limitation
17  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18  * and/or sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included
22  * in all copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30  * DEALINGS IN THE SOFTWARE.
31  ****************************************************************************/
32 
33 #ifndef S57_H_INCLUDED
34 #define S57_H_INCLUDED
35 
36 #include <string>
37 #include <vector>
38 #include "ogr_feature.h"
39 #include "iso8211.h"
40 
41 class S57Reader;
42 
43 char **S57FileCollector( const char * pszDataset );
44 
45 #define EMPTY_NUMBER_MARKER 2147483641  /* MAXINT-6 */
46 
47 /* -------------------------------------------------------------------- */
48 /*      Various option strings.                                         */
49 /* -------------------------------------------------------------------- */
50 #define S57O_UPDATES "UPDATES"
51 #define S57O_LNAM_REFS "LNAM_REFS"
52 #define S57O_SPLIT_MULTIPOINT "SPLIT_MULTIPOINT"
53 #define S57O_ADD_SOUNDG_DEPTH "ADD_SOUNDG_DEPTH"
54 #define S57O_PRESERVE_EMPTY_NUMBERS "PRESERVE_EMPTY_NUMBERS"
55 #define S57O_RETURN_PRIMITIVES "RETURN_PRIMITIVES"
56 #define S57O_RETURN_LINKAGES "RETURN_LINKAGES"
57 #define S57O_RETURN_DSID     "RETURN_DSID"
58 #define S57O_RECODE_BY_DSSI  "RECODE_BY_DSSI"
59 #define S57O_LIST_AS_STRING "LIST_AS_STRING"
60 
61 #define S57M_UPDATES                    0x01
62 #define S57M_LNAM_REFS                  0x02
63 #define S57M_SPLIT_MULTIPOINT           0x04
64 #define S57M_ADD_SOUNDG_DEPTH           0x08
65 #define S57M_PRESERVE_EMPTY_NUMBERS     0x10
66 #define S57M_RETURN_PRIMITIVES          0x20
67 #define S57M_RETURN_LINKAGES            0x40
68 #define S57M_RETURN_DSID                0x80
69 #define S57M_RECODE_BY_DSSI             0x100
70 #define S57M_LIST_AS_STRING             0x200
71 
72 /* -------------------------------------------------------------------- */
73 /*      RCNM values.                                                    */
74 /* -------------------------------------------------------------------- */
75 
76 #define RCNM_FE         100     /* Feature record */
77 
78 #define RCNM_VI         110     /* Isolated Node */
79 #define RCNM_VC         120     /* Connected Node */
80 #define RCNM_VE         130     /* Edge */
81 #define RCNM_VF         140     /* Face */
82 
83 #define RCNM_DSID       10
84 
85 #define OGRN_VI         "IsolatedNode"
86 #define OGRN_VC         "ConnectedNode"
87 #define OGRN_VE         "Edge"
88 #define OGRN_VF         "Face"
89 
90 /* -------------------------------------------------------------------- */
91 /*      FRID PRIM values.                                               */
92 /* -------------------------------------------------------------------- */
93 #define PRIM_P          1       /* point feature */
94 #define PRIM_L          2       /* line feature */
95 #define PRIM_A          3       /* area feature */
96 #define PRIM_N          4       /* non-spatial feature  */
97 
98 /************************************************************************/
99 /*                          S57ClassRegistrar                           */
100 /************************************************************************/
101 
102 class S57ClassContentExplorer;
103 
104 class CPL_DLL S57AttrInfo
105 {
106   public:
107     CPLString    osName;
108     CPLString    osAcronym;
109     char         chType;
110     char         chClass;
111 };
112 
113 class CPL_DLL S57ClassRegistrar
114 {
115     friend class S57ClassContentExplorer;
116 
117     // Class information:
118     int         nClasses;
119     CPLStringList apszClassesInfo;
120 
121     // Attribute Information:
122     int         nAttrCount;
123     std::vector<S57AttrInfo*> aoAttrInfos;
124     std::vector<int> anAttrIndex; // sorted by acronym.
125 
126     static bool        FindFile( const char *pszTarget, const char *pszDirectory,
127                           bool bReportErr, VSILFILE **fp );
128 
129     const char *ReadLine( VSILFILE * fp );
130     char      **papszNextLine;
131 
132 public:
133                 S57ClassRegistrar();
134                ~S57ClassRegistrar();
135 
136     bool        LoadInfo( const char *, const char *, bool );
137 
138     // attribute table methods.
139     //int         GetMaxAttrIndex() { return nAttrMax; }
140     const S57AttrInfo *GetAttrInfo( int i );
GetAttrName(int i)141     const char *GetAttrName( int i )
142     { return GetAttrInfo(i) == nullptr ? nullptr : aoAttrInfos[i]->osName.c_str(); }
GetAttrAcronym(int i)143     const char *GetAttrAcronym( int i )
144     { return GetAttrInfo(i) == nullptr ? nullptr : aoAttrInfos[i]->osAcronym.c_str(); }
GetAttrType(int i)145     char        GetAttrType( int i )
146     { return GetAttrInfo(i) == nullptr ? '\0' : aoAttrInfos[i]->chType; }
147 #define SAT_ENUM        'E'
148 #define SAT_LIST        'L'
149 #define SAT_FLOAT       'F'
150 #define SAT_INT         'I'
151 #define SAT_CODE_STRING 'A'
152 #define SAT_FREE_TEXT   'S'
153 
GetAttrClass(int i)154     char        GetAttrClass( int i )
155     { return GetAttrInfo(i) == nullptr ? '\0' : aoAttrInfos[i]->chClass; }
156     int         FindAttrByAcronym( const char * );
157 };
158 
159 /************************************************************************/
160 /*                       S57ClassContentExplorer                        */
161 /************************************************************************/
162 
163 class S57ClassContentExplorer
164 {
165     S57ClassRegistrar* poRegistrar;
166 
167     char     ***papapszClassesFields;
168 
169     int         iCurrentClass;
170 
171     char      **papszCurrentFields;
172 
173     char      **papszTempResult;
174 
175     public:
176     explicit    S57ClassContentExplorer(S57ClassRegistrar* poRegistrar);
177        ~S57ClassContentExplorer();
178 
179     bool        SelectClassByIndex( int );
180     bool        SelectClass( int );
181     bool        SelectClass( const char * );
182 
Rewind()183     bool        Rewind() { return SelectClassByIndex(0); }
NextClass()184     bool        NextClass() { return SelectClassByIndex(iCurrentClass+1); }
185 
186     int         GetOBJL();
187     const char *GetDescription() const;
188     const char *GetAcronym() const;
189 
190     char      **GetAttributeList( const char * = nullptr );
191 
192     char        GetClassCode() const;
193     char      **GetPrimitives();
194 };
195 
196 /************************************************************************/
197 /*                            DDFRecordIndex                            */
198 /*                                                                      */
199 /*      Maintain an index of DDF records based on an integer key.       */
200 /************************************************************************/
201 
202 typedef struct
203 {
204     int         nKey;
205     DDFRecord   *poRecord;
206     void        *pClientData;
207 } DDFIndexedRecord;
208 
209 class CPL_DLL DDFRecordIndex
210 {
211     bool        bSorted;
212 
213     int         nRecordCount;
214     int         nRecordMax;
215 
216     int         nLastObjlPos;  // Added for FindRecordByObjl().
217     int         nLastObjl;     // Added for FindRecordByObjl().
218 
219     DDFIndexedRecord *pasRecords;
220 
221     void        Sort();
222 
223 public:
224                 DDFRecordIndex();
225                ~DDFRecordIndex();
226 
227     void        AddRecord( int nKey, DDFRecord * );
228     bool        RemoveRecord( int nKey );
229 
230     DDFRecord  *FindRecord( int nKey );
231 
232     DDFRecord  *FindRecordByObjl( int nObjl );  // Added for FindRecordByObjl().
233 
234     void        Clear();
235 
GetCount()236     int         GetCount() { return nRecordCount; }
237 
238     DDFRecord  *GetByIndex( int i );
239     void        *GetClientInfoByIndex( int i );
240     void        SetClientInfoByIndex( int i, void *pClientInfo );
241 };
242 
243 /************************************************************************/
244 /*                              S57Reader                               */
245 /************************************************************************/
246 
247 class CPL_DLL S57Reader
248 {
249     S57ClassRegistrar  *poRegistrar;
250     S57ClassContentExplorer* poClassContentExplorer;
251 
252     int                 nFDefnCount;
253     OGRFeatureDefn      **papoFDefnList;
254 
255     std::vector<OGRFeatureDefn*> apoFDefnByOBJL;
256 
257     char                *pszModuleName;
258     char                *pszDSNM;
259 
260     DDFModule           *poModule;
261 
262     int                 nCOMF;  /* Coordinate multiplier */
263     int                 nSOMF;  /* Vertical (sounding) multiplier */
264 
265     bool                bFileIngested;
266     DDFRecordIndex      oVI_Index;
267     DDFRecordIndex      oVC_Index;
268     DDFRecordIndex      oVE_Index;
269     DDFRecordIndex      oVF_Index;
270 
271     int                 nNextVIIndex;
272     int                 nNextVCIndex;
273     int                 nNextVEIndex;
274     int                 nNextVFIndex;
275 
276     int                 nNextFEIndex;
277     DDFRecordIndex      oFE_Index;
278 
279     int                 nNextDSIDIndex;
280     DDFRecord           *poDSIDRecord;
281     DDFRecord           *poDSPMRecord;
282     std::string         m_osEDTNUpdate;
283     std::string         m_osUPDNUpdate;
284     std::string         m_osISDTUpdate;
285 
286     char                **papszOptions;
287 
288     int                 nOptionFlags;
289 
290     int                 iPointOffset;
291     OGRFeature          *poMultiPoint;
292 
293     int                 Aall;               // see RecodeByDSSI() function
294     int                 Nall;               // see RecodeByDSSI() function
295     bool                needAallNallSetup;  // see RecodeByDSSI() function
296 
297     void                ClearPendingMultiPoint();
298     OGRFeature         *NextPendingMultiPoint();
299 
300     OGRFeature         *AssembleFeature( DDFRecord  *, OGRFeatureDefn * );
301 
302     void                ApplyObjectClassAttributes( DDFRecord *, OGRFeature *);
303     // cppcheck-suppress functionStatic
304     void                GenerateLNAMAndRefs( DDFRecord *, OGRFeature * );
305     void                GenerateFSPTAttributes( DDFRecord *, OGRFeature * );
306 
307     void                AssembleSoundingGeometry( DDFRecord *, OGRFeature * );
308     // cppcheck-suppress functionStatic
309     void                AssemblePointGeometry( DDFRecord *, OGRFeature * );
310     void                AssembleLineGeometry( DDFRecord *, OGRFeature * );
311     void                AssembleAreaGeometry( DDFRecord *, OGRFeature * );
312 
313     bool                FetchPoint( int, int,
314                                     double *, double *, double * = nullptr );
315     bool                FetchLine( DDFRecord *, int, int, OGRLineString * );
316 
317     OGRFeatureDefn     *FindFDefn( DDFRecord * );
318     int                 ParseName( DDFField *, int = 0, int * = nullptr );
319 
320     // cppcheck-suppress functionStatic
321     bool                ApplyRecordUpdate( DDFRecord *, DDFRecord * );
322 
323     bool                bMissingWarningIssued;
324     bool                bAttrWarningIssued;
325 
326   public:
327     explicit            S57Reader( const char * );
328                        ~S57Reader();
329 
330     void                SetClassBased( S57ClassRegistrar *, S57ClassContentExplorer* );
331     bool                SetOptions( char ** );
GetOptionFlags()332     int                 GetOptionFlags() { return nOptionFlags; }
333 
334     int                 Open( int bTestOpen );
335     void                Close();
GetModule()336     DDFModule           *GetModule() { return poModule; }
GetDSNM()337     const char          *GetDSNM() { return pszDSNM; }
338 
339     bool                Ingest();
340     bool                ApplyUpdates( DDFModule * );
341     bool                FindAndApplyUpdates( const char *pszPath=nullptr );
342 
343     void                Rewind();
344     OGRFeature          *ReadNextFeature( OGRFeatureDefn * = nullptr );
345     OGRFeature          *ReadFeature( int nFID, OGRFeatureDefn * = nullptr );
346     OGRFeature          *ReadVector( int nFID, int nRCNM );
347     OGRFeature          *ReadDSID();
348 
349     int                 GetNextFEIndex( int nRCNM = 100 );
350     void                SetNextFEIndex( int nNewIndex, int nRCNM = 100 );
351 
352     void                AddFeatureDefn( OGRFeatureDefn * );
353 
354     bool                CollectClassList(std::vector<int> &anClassCount);
355 
356     OGRErr              GetExtent( OGREnvelope *psExtent, int bForce );
357 
358     char               *RecodeByDSSI(const char *SourceString, bool LookAtAALL_NALL);
359  };
360 
361 /************************************************************************/
362 /*                              S57Writer                               */
363 /************************************************************************/
364 
365 class CPL_DLL S57Writer
366 {
367 public:
368     static const int nDEFAULT_EXPP = 1;
369     static const int nDEFAULT_INTU = 4;
370     static const int nDEFAULT_AGEN = 540;
371 
372     static const int nDEFAULT_HDAT = 2;
373     static const int nDEFAULT_VDAT = 7;
374     static const int nDEFAULT_SDAT = 23;
375     static const int nDEFAULT_CSCL = 52000;
376     static const int nDEFAULT_COMF = 10000000;
377     static const int nDEFAULT_SOMF = 10;
378 
379                         S57Writer();
380                         ~S57Writer();
381 
382     void                SetClassBased( S57ClassRegistrar *, S57ClassContentExplorer* );
383     bool                CreateS57File( const char *pszFilename );
384     bool                Close();
385 
386     bool                WriteGeometry( DDFRecord *, int, double *, double *,
387                                        double * );
388     bool                WriteATTF( DDFRecord *, OGRFeature * );
389     bool                WritePrimitive( OGRFeature *poFeature );
390     bool                WriteCompleteFeature( OGRFeature *poFeature );
391     bool                WriteDSID( int nEXPP = nDEFAULT_EXPP,
392                                    int nINTU = nDEFAULT_INTU,
393                                    const char *pszDSNM = nullptr,
394                                    const char *pszEDTN = nullptr,
395                                    const char *pszUPDN = nullptr,
396                                    const char *pszUADT = nullptr,
397                                    const char *pszISDT = nullptr,
398                                    const char *pszSTED = nullptr,
399                                    int nAGEN = nDEFAULT_AGEN,
400                                    const char *pszCOMT = nullptr,
401                                    int nAALL = 0,
402                                    int nNALL = 0,
403                                    int nNOMR = 0, int nNOGR = 0,
404                                    int nNOLR = 0, int nNOIN = 0,
405                                    int nNOCN = 0, int nNOED = 0 );
406     bool                WriteDSPM( int nHDAT = nDEFAULT_HDAT,
407                                    int nVDAT = nDEFAULT_VDAT,
408                                    int nSDAT = nDEFAULT_SDAT,
409                                    int nCSCL = nDEFAULT_CSCL,
410                                    int nCOMF = nDEFAULT_COMF,
411                                    int nSOMF = nDEFAULT_SOMF);
412 
413 // semi-private - for sophisticated writers.
414     DDFRecord           *MakeRecord();
415     DDFModule           *poModule;
416 
417 private:
418     int                 nNext0001Index;
419     S57ClassRegistrar   *poRegistrar;
420     S57ClassContentExplorer* poClassContentExplorer;
421 
422     int                 m_nCOMF;  /* Coordinate multiplier */
423     int                 m_nSOMF;  /* Vertical (sounding) multiplier */
424 };
425 
426 /* -------------------------------------------------------------------- */
427 /*      Functions to create OGRFeatureDefns.                            */
428 /* -------------------------------------------------------------------- */
429 void           CPL_DLL  S57GenerateStandardAttributes( OGRFeatureDefn *, int );
430 OGRFeatureDefn CPL_DLL *S57GenerateGeomFeatureDefn( OGRwkbGeometryType, int );
431 OGRFeatureDefn CPL_DLL *S57GenerateObjectClassDefn( S57ClassRegistrar *,
432                                                     S57ClassContentExplorer* poClassContentExplorer,
433                                                     int, int );
434 OGRFeatureDefn CPL_DLL  *S57GenerateVectorPrimitiveFeatureDefn( int, int );
435 OGRFeatureDefn CPL_DLL  *S57GenerateDSIDFeatureDefn( void );
436 
437 #endif /* ndef S57_H_INCLUDED */
438