1 /***************************************************************************
2  *
3  * Project:  OpenCPN
4  * Purpose:  S57 SENC File Object
5  * Author:   David Register
6  *
7  ***************************************************************************
8  *   Copyright (C) 2015 by David S. Register                               *
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  *   This program is distributed in the hope that it will be useful,       *
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  *   GNU General Public License for more details.                          *
19  *                                                                         *
20  *   You should have received a copy of the GNU General Public License     *
21  *   along with this program; if not, write to the                         *
22  *   Free Software Foundation, Inc.,                                       *
23  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
24  **************************************************************************/
25 
26 #ifndef OSENC_H
27 #define OSENC_H
28 
29 // For compilers that support precompilation, includes "wx.h".
30 #include "wx/wxprec.h"
31 
32 #ifndef  WX_PRECOMP
33   #include "wx/wx.h"
34 #endif //precompiled headers
35 
36 #include <wx/filename.h>
37 
38 #include "gdal/cpl_csv.h"
39 #include "ogr_s57.h"
40 #include "chartbase.h"
41 
42 #include <string.h>
43 #include <stdint.h>
44 #include <vector>
45 #include <mutex>
46 
47 WX_DEFINE_ARRAY_PTR(float *, SENCFloatPtrArray);
48 
49 //      Various error return enums
50 #define         SENC_NO_ERROR                           0
51 #define         ERROR_SENCFILE_NOT_FOUND                1
52 #define         ERROR_SENC_VERSION_MISMATCH             2
53 #define         ERROR_CANNOT_CREATE_SENC_DIR            3
54 #define         ERROR_CANNOT_CREATE_TEMP_SENC_FILE      4
55 #define         ERROR_INGESTING000                      5
56 #define         ERROR_REGISTRAR_NOT_SET                 6
57 #define         ERROR_BASEFILE_ATTRIBUTES               7
58 #define         ERROR_SENCFILE_ABORT                    8
59 
60 
61 //  OSENC V2 record definitions
62 #define HEADER_SENC_VERSION             1
63 #define HEADER_CELL_NAME                2
64 #define HEADER_CELL_PUBLISHDATE         3
65 #define HEADER_CELL_EDITION             4
66 #define HEADER_CELL_UPDATEDATE          5
67 #define HEADER_CELL_UPDATE              6
68 #define HEADER_CELL_NATIVESCALE         7
69 #define HEADER_CELL_SENCCREATEDATE      8
70 
71 #define FEATURE_ID_RECORD               64
72 #define FEATURE_ATTRIBUTE_RECORD        65
73 
74 #define FEATURE_GEOMETRY_RECORD_POINT           80
75 #define FEATURE_GEOMETRY_RECORD_LINE            81
76 #define FEATURE_GEOMETRY_RECORD_AREA            82
77 #define FEATURE_GEOMETRY_RECORD_MULTIPOINT      83
78 
79 #define VECTOR_EDGE_NODE_TABLE_RECORD             96
80 #define VECTOR_CONNECTED_NODE_TABLE_RECORD        97
81 
82 #define CELL_COVR_RECORD                        98
83 #define CELL_NOCOVR_RECORD                      99
84 #define CELL_EXTENT_RECORD                      100
85 
86 
87 //--------------------------------------------------------------------------
88 //      Utility Structures
89 //--------------------------------------------------------------------------
90 #pragma pack(push,1)
91 
92 typedef struct _OSENC_Record_Base{
93     uint16_t        record_type;
94     uint32_t        record_length;
95 }OSENC_Record_Base;
96 
97 typedef struct _OSENC_Record{
98     uint16_t        record_type;
99     uint32_t        record_length;
100     unsigned char   payload;
101 }OSENC_Record;
102 
103 
104 typedef struct _OSENC_Feature_Identification_Record_Base{
105     uint16_t        record_type;
106     uint32_t        record_length;
107     uint16_t        feature_type_code;
108     uint16_t        feature_ID;
109     uint8_t         feature_primitive;
110 }OSENC_Feature_Identification_Record_Base;
111 
112 
113 typedef struct _OSENC_Feature_Identification_Record_Payload{
114     uint16_t        feature_type_code;
115     uint16_t        feature_ID;
116     uint8_t         feature_primitive;
117 }OSENC_Feature_Identification_Record_Payload;
118 
119 typedef struct _OSENC_Attribute_Record_Base{
120     uint16_t        record_type;
121     uint32_t        record_length;
122     uint16_t        attribute_type;
123     unsigned char   attribute_value_type;
124 }OSENC_Attribute_Record_Base;
125 
126 typedef struct _OSENC_Attribute_Record{
127     uint16_t        record_type;
128     uint32_t        record_length;
129     uint16_t        attribute_type;
130     unsigned char   attribute_value_type;
131     void *          payload;
132 }OSENC_Attribute_Record;
133 
134 typedef struct _OSENC_Attribute_Record_Payload{
135     uint16_t        attribute_type_code;
136     unsigned char   attribute_value_type;
137 
138     union{
139         uint32_t        attribute_value_int;
140         double          attribute_value_double;
141         char *          attribute_value_char_ptr;
142     };
143 }OSENC_Attribute_Record_Payload;
144 
145 
146 typedef struct _OSENC_PointGeometry_Record{
147     uint16_t        record_type;
148     uint32_t        record_length;
149     double          lat;
150     double          lon;
151 }OSENC_PointGeometry_Record;
152 
153 typedef struct _OSENC_PointGeometry_Record_Payload{
154     double          lat;
155     double          lon;
156 }OSENC_PointGeometry_Record_Payload;
157 
158 
159 typedef struct _OSENC_MultipointGeometry_Record_Base{
160     uint16_t        record_type;
161     uint32_t        record_length;
162     double          extent_s_lat;
163     double          extent_n_lat;
164     double          extent_w_lon;
165     double          extent_e_lon;
166     uint32_t        point_count;
167 }OSENC_MultipointGeometry_Record_Base;
168 
169 typedef struct _OSENC_MultipointGeometry_Record_Payload{
170     double          extent_s_lat;
171     double          extent_n_lat;
172     double          extent_w_lon;
173     double          extent_e_lon;
174     uint32_t        point_count;
175     void *          payLoad;
176 }OSENC_MultipointGeometry_Record_Payload;
177 
178 
179 typedef struct _OSENC_LineGeometry_Record_Base{
180     uint16_t        record_type;
181     uint32_t        record_length;
182     double          extent_s_lat;
183     double          extent_n_lat;
184     double          extent_w_lon;
185     double          extent_e_lon;
186     uint32_t        edgeVector_count;
187 }OSENC_LineGeometry_Record_Base;
188 
189 typedef struct _OSENC_LineGeometry_Record_Payload{
190     double          extent_s_lat;
191     double          extent_n_lat;
192     double          extent_w_lon;
193     double          extent_e_lon;
194     uint32_t        edgeVector_count;
195     void *          payLoad;
196 }OSENC_LineGeometry_Record_Payload;
197 
198 
199 typedef struct _OSENC_AreaGeometry_Record_Base{
200     uint16_t        record_type;
201     uint32_t        record_length;
202     double          extent_s_lat;
203     double          extent_n_lat;
204     double          extent_w_lon;
205     double          extent_e_lon;
206     uint32_t        contour_count;
207     uint32_t        triprim_count;
208     uint32_t        edgeVector_count;
209 }OSENC_AreaGeometry_Record_Base;
210 
211 typedef struct _OSENC_AreaGeometry_Record_Payload{
212     double          extent_s_lat;
213     double          extent_n_lat;
214     double          extent_w_lon;
215     double          extent_e_lon;
216     uint32_t        contour_count;
217     uint32_t        triprim_count;
218     uint32_t        edgeVector_count;
219     void *          payLoad;
220 }OSENC_AreaGeometry_Record_Payload;
221 
222 typedef struct _OSENC_VET_Record{
223     uint16_t        record_type;
224     uint32_t        record_length;
225     unsigned char   payload;
226 }OSENC_VET_Record;
227 
228 typedef struct _OSENC_VET_Record_Base{
229     uint16_t        record_type;
230     uint32_t        record_length;
231 }OSENC_VET_Record_Base;
232 
233 typedef struct _OSENC_VCT_Record{
234     uint16_t        record_type;
235     uint32_t        record_length;
236     unsigned char   payload;
237 }OSENC_VCT_Record;
238 
239 typedef struct _OSENC_VCT_Record_Base{
240     uint16_t        record_type;
241     uint32_t        record_length;
242 }OSENC_VCT_Record_Base;
243 
244 typedef struct _OSENC_COVR_Record{
245     uint16_t        record_type;
246     uint32_t        record_length;
247     unsigned char   payload;
248 }_OSENC_COVR_Record;
249 
250 typedef struct _OSENC_COVR_Record_Base{
251     uint16_t        record_type;
252     uint32_t        record_length;
253 }_OSENC_COVR_Record_Base;
254 
255 typedef struct _OSENC_COVR_Record_Payload{
256     uint32_t        point_count;
257     float           point_array;
258 }_OSENC_COVR_Record_Payload;
259 
260 typedef struct _OSENC_NOCOVR_Record{
261     uint16_t        record_type;
262     uint32_t        record_length;
263     unsigned char   payload;
264 }_OSENC_NOCOVR_Record;
265 
266 typedef struct _OSENC_NOCOVR_Record_Base{
267     uint16_t        record_type;
268     uint32_t        record_length;
269 }_OSENC_NOCOVR_Record_Base;
270 
271 typedef struct _OSENC_NOCOVR_Record_Payload{
272     uint32_t        point_count;
273     float           point_array;
274 }_OSENC_NOCOVR_Record_Payload;
275 
276 
277 typedef struct _OSENC_EXTENT_Record{
278     uint16_t        record_type;
279     uint32_t        record_length;
280     double          extent_sw_lat;
281     double          extent_sw_lon;
282     double          extent_nw_lat;
283     double          extent_nw_lon;
284     double          extent_ne_lat;
285     double          extent_ne_lon;
286     double          extent_se_lat;
287     double          extent_se_lon;
288  }_OSENC_EXTENT_Record;
289 
290 typedef struct _OSENC_EXTENT_Record_Payload{
291      double          extent_sw_lat;
292      double          extent_sw_lon;
293      double          extent_nw_lat;
294      double          extent_nw_lon;
295      double          extent_ne_lat;
296      double          extent_ne_lon;
297      double          extent_se_lat;
298      double          extent_se_lon;
299  }_OSENC_EXTENT_Record_Payload;
300 
301  #pragma pack(pop)
302 
303 
304 
305 
306 
307 
308 
309 
310 
311 //  Some special defined attribute type codes
312 //  Should also be defined in a57attributes.csv
313 
314 #define ATTRIBUTE_ID_PRIM       50000
315 
316 
317 const char *MyCSVGetField( const char * pszFilename,
318                            const char * pszKeyFieldName,
319                            const char * pszKeyFieldValue,
320                            CSVCompareCriteria eCriteria,
321                            const char * pszTargetField ) ;
322 
323 
324 
325 
326 //      Fwd Definitions
327 class wxGenericProgressDialog;
328 class S57Obj;
329 class VE_Element;
330 class VC_Element;
331 class PolyTessGeo;
332 class LineGeometryDescriptor;
333 class wxFFileInputStream;
334 
335 typedef std::vector<S57Obj *> S57ObjVector;
336 typedef std::vector<VE_Element *> VE_ElementVector;
337 typedef std::vector<VC_Element *> VC_ElementVector;
338 
339 WX_DECLARE_HASH_MAP( int, int, wxIntegerHash, wxIntegerEqual, VectorHelperHash );
340 
341 //--------------------------------------------------------------------------
342 //      Osenc_instream definition
343 //--------------------------------------------------------------------------
344 class Osenc_instream
345 {
346 public:
Osenc_instream()347     Osenc_instream(){};
~Osenc_instream()348     virtual ~Osenc_instream(){};
349 
350     virtual bool Open( const wxString &senc_file_name ) = 0;
351     virtual void Close() = 0;
352 
353     virtual Osenc_instream &Read(void *buffer, size_t size) = 0;
354     virtual bool IsOk() = 0;
355     virtual bool isAvailable() = 0;
356     virtual void Shutdown() = 0;
357 
358 };
359 
360 
361 //--------------------------------------------------------------------------
362 //      Osenc_instreamFile definition
363 //      A simple file stream implementation based on wxFFileInputStream
364 //--------------------------------------------------------------------------
365 class Osenc_instreamFile : public Osenc_instream
366 {
367 public:
368     Osenc_instreamFile();
369     ~Osenc_instreamFile();
370 
371     bool Open( const wxString &senc_file_name );
372     void Close();
373 
374     Osenc_instream &Read(void *buffer, size_t size);
375     bool IsOk();
376     bool isAvailable();
377     void Shutdown();
378 
379 
380 private:
381     void Init();
382 
383     wxFFileInputStream  *m_instream;
384     bool                m_ok;
385 
386 };
387 
388 
389 
390 //--------------------------------------------------------------------------
391 //      Osenc_outstream definition
392 //--------------------------------------------------------------------------
393 class Osenc_outstream
394 {
395 public:
Osenc_outstream()396     Osenc_outstream(){};
~Osenc_outstream()397     virtual ~Osenc_outstream(){};
398 
399     virtual bool Open(const wxString& ofileName) = 0;
400 
401     virtual Osenc_outstream& Write(const void* buffer, size_t size) = 0;
402     virtual void Close() = 0;
403     virtual bool IsOk() = 0;
404 
405 
406 
407 };
408 
409 
410 //--------------------------------------------------------------------------
411 //      Osenc_outstreamFile definition
412 //      A simple file stream implementation based on wxFFileInputStream
413 //--------------------------------------------------------------------------
414 class Osenc_outstreamFile : public Osenc_outstream
415 {
416 public:
417     Osenc_outstreamFile();
418     ~Osenc_outstreamFile();
419 
420     bool Open(const wxString& ofileName);
421 
422     Osenc_outstream& Write(const void* buffer, size_t size);
423     void Close();
424     bool IsOk();
425 
426 private:
427     void Init();
428 
429     wxFFileOutputStream  *m_outstream;
430     bool                 m_ok;
431 
432 };
433 
434 
435 
436 
437 
438 //--------------------------------------------------------------------------
439 //      Osenc definition
440 //--------------------------------------------------------------------------
441 
442 class Osenc
443 {
444 public:
445     Osenc();
446     ~Osenc();
447 
getLastError()448     wxString getLastError(){ return errorMessage; }
449     void setVerbose(bool verbose );
setNoErrDialog(bool val)450     void setNoErrDialog( bool val ){ m_NoErrDialog = val; }
451 
452     int ingestHeader(const wxString &senc_file_name);
453     int ingest(const wxString &senc_file_name,
454                S57ObjVector *pObjectVector,
455                VE_ElementVector *pVEArray,
456                VC_ElementVector *pVCArray);
457 
458     int ingest200(const wxString &senc_file_name,
459                S57ObjVector *pObjectVector,
460                VE_ElementVector *pVEArray,
461                VC_ElementVector *pVCArray);
462 
463     //  SENC creation, by Version desired...
SetLODMeters(double meters)464     void SetLODMeters(double meters){ m_LOD_meters = meters;}
setRegistrar(S57ClassRegistrar * registrar)465     void setRegistrar( S57ClassRegistrar *registrar ){ m_poRegistrar = registrar; }
setRefLocn(double lat,double lon)466     void setRefLocn( double lat, double lon){ m_ref_lat = lat; m_ref_lon = lon; }
setOutstream(Osenc_outstream * stream)467     void setOutstream(Osenc_outstream *stream){ m_pauxOutstream = stream; }
setInstream(Osenc_instream * stream)468     void setInstream(Osenc_instream *stream){ m_pauxInstream = stream; }
469 
getUpdateDate()470     wxString getUpdateDate(){ return m_LastUpdateDate; }
getBaseDate()471     wxString getBaseDate(){ return m_sdate000; }
472 
getSENCFileCreateDate()473     wxString getSENCFileCreateDate(){ return m_readFileCreateDate; }
474 
getSencReadVersion()475     int getSencReadVersion(){ return m_senc_file_read_version; }
getSENCReadBaseEdition()476     wxString getSENCReadBaseEdition(){ return m_read_base_edtn; }
getSENCReadLastUpdate()477     int getSENCReadLastUpdate(){ return m_read_last_applied_update; }
getSENCReadScale()478     int getSENCReadScale(){ return m_Chart_Scale; }
getReadName()479     wxString getReadName(){ return m_Name; }
getReadID()480     wxString getReadID(){ return m_ID; }
getReadExtent()481     Extent &getReadExtent(){ return m_extent; }
482 
getSENCReadAuxPointArray()483     SENCFloatPtrArray &getSENCReadAuxPointArray(){ return m_AuxPtrArray;}
getSENCReadAuxPointCountArray()484     std::vector<int> &getSENCReadAuxPointCountArray(){ return m_AuxCntArray;}
getSENCReadNOCOVRPointArray()485     SENCFloatPtrArray &getSENCReadNOCOVRPointArray(){ return m_NoCovrPtrArray;}
getSENCReadNOCOVRPointCountArray()486     std::vector<int> &getSENCReadNOCOVRPointCountArray(){ return m_NoCovrCntArray;}
487 
488     int createSenc200(const wxString& FullPath000, const wxString& SENCFileName, bool b_showProg = true);
489 
490     void CreateSENCVectorEdgeTableRecord200( Osenc_outstream *stream, S57Reader *poReader );
491     void CreateSENCVectorConnectedTableRecord200( Osenc_outstream *stream, S57Reader *poReader );
492 
493     void InitializePersistentBuffer( void );
494     unsigned char *getBuffer( size_t length);
495 
getNativeScale()496     int getNativeScale(){ return m_native_scale; }
497     int GetBaseFileInfo(const wxString& FullPath000, const wxString& SENCFileName);
498 
499     std::unique_lock<std::mutex> lockCR;
500 
501 private:
502     void init();
503 
504     int ingestCell( OGRS57DataSource *poS57DS, const wxString &FullPath000, const wxString &working_dir );
505     int ValidateAndCountUpdates( const wxFileName file000, const wxString CopyDir,
506                                  wxString &LastUpdateDate, bool b_copyfiles);
507     int GetUpdateFileArray(const wxFileName file000, wxArrayString *UpFiles);
508     bool GetBaseFileAttr( const wxString &FullPath000 );
509     unsigned char *getObjectVectorIndexTable( S57Reader *poReader, OGRFeature *poFeature, int &nEntries );
510 
511     OGRFeature *GetChartFirstM_COVR( int &catcov, S57Reader *pENCReader, S57ClassRegistrar *poRegistrar );
512     OGRFeature *GetChartNextM_COVR( int &catcov, S57Reader *pENCReader );
513     bool CreateCOVRTables( S57Reader *pENCReader, S57ClassRegistrar *poRegistrar );
514     bool CreateCovrRecords(Osenc_outstream *stream);
515 
516     void CreateSENCRecord124( OGRFeature *pFeature, Osenc_outstream *stream, int mode, S57Reader *poReader );
517     void  CreateSENCVectorEdgeTable(Osenc_outstream *stream, S57Reader *poReader);
518     void  CreateSENCConnNodeTable(Osenc_outstream *stream, S57Reader *poReader);
519 
520     bool CreateSENCRecord200( OGRFeature *pFeature, Osenc_outstream *stream, int mode, S57Reader *poReader );
521     bool WriteFIDRecord200( Osenc_outstream *stream, int nOBJL, int featureID, int prim);
522     bool WriteHeaderRecord200( Osenc_outstream *stream, int recordType, std::string payload);
523     bool WriteHeaderRecord200( Osenc_outstream *stream, int recordType, uint16_t value);
524     bool WriteHeaderRecord200( Osenc_outstream *stream, int recordType, uint32_t value);
525     bool CreateAreaFeatureGeometryRecord200( S57Reader *poReader, OGRFeature *pFeature, Osenc_outstream *stream );
526     bool CreateLineFeatureGeometryRecord200( S57Reader *poReader, OGRFeature *pFeature, Osenc_outstream *stream );
527     bool CreateMultiPointFeatureGeometryRecord200( OGRFeature *pFeature, Osenc_outstream *stream);
528 
529     std::string GetFeatureAcronymFromTypecode( int typeCode );
530     std::string GetAttributeAcronymFromTypecode( int typeCode );
531 
532     PolyTessGeo *BuildPolyTessGeo(_OSENC_AreaGeometry_Record_Payload *record, unsigned char **bytes_consumed );
533     bool CalculateExtent( S57Reader *poReader, S57ClassRegistrar *poRegistrar );
534 
535     wxString            errorMessage;
536 
537     wxString            m_Name;
538     wxString m_ID;
539     wxString            m_FullPath000;
540 
541     int                 m_Chart_Scale;
542     int                 m_senc_file_read_version;
543     int                 m_senc_file_create_version;
544     wxString            m_read_base_edtn;
545     int                 m_read_last_applied_update;
546 
547     S57Reader           *poReader;
548 
549     wxDateTime          m_date000;
550     wxString            m_sdate000;
551 
552     wxString            m_edtn000;
553     int                 m_UPDN;
554 
555     int                 m_nGeoRecords;
556     int                 m_last_applied_update;
557     wxString            m_LastUpdateDate;
558     int                 m_native_scale;
559     wxString            m_readFileCreateDate;
560 
561     double              m_ref_lat, m_ref_lon;             // Common reference point, derived from FullExtent
562     VectorHelperHash    m_vector_helper_hash;
563     double              m_LOD_meters;
564     S57ClassRegistrar   *m_poRegistrar;
565     wxArrayString       m_tmpup_array;
566 
567     wxGenericProgressDialog    *m_ProgDialog;
568 
569 
570     unsigned char *     pBuffer;
571     size_t              bufferSize;
572 
573 
574     Extent              m_extent;
575 
576     //  Clone of Chartbase structures of the same name and purpose
577     //  Use mainly for SENC creation for ENC(.000) file
578     int         m_nCOVREntries;                       // number of coverage table entries
579     int         *m_pCOVRTablePoints;                  // int table of number of points in each coverage table entry
580     float       **m_pCOVRTable;                       // table of pointers to list of floats describing valid COVR
581 
582     int         m_nNoCOVREntries;                       // number of NoCoverage table entries
583     int         *m_pNoCOVRTablePoints;                  // int table of number of points in each NoCoverage table entry
584     float       **m_pNoCOVRTable;                       // table of pointers to list of floats describing valid NOCOVR
585 
586 
587     //  Arrays used to accumulate coverage regions on oSENC load
588     SENCFloatPtrArray     m_AuxPtrArray;
589     std::vector<int>            m_AuxCntArray;
590     SENCFloatPtrArray     m_NoCovrPtrArray;
591     std::vector<int>            m_NoCovrCntArray;
592 
593 
594     Osenc_outstream       *m_pauxOutstream;
595     Osenc_instream        *m_pauxInstream;
596 
597     Osenc_outstream       *m_pOutstream;
598     Osenc_instream        *m_pInstream;
599 
600     bool                  m_bVerbose;
601     wxArrayString         *m_UpFiles;
602     bool                  m_bPrivateRegistrar;
603     bool                  m_NoErrDialog;
604 };
605 
606 
607 #endif          // Guard
608