27 #include "wx/wxprec.h"
35 #include <wx/wfstream.h>
36 #include <wx/filename.h>
37 #include <wx/progdlg.h>
42 #include "model/cutil.h"
43 #include "s57RegistrarMgr.h"
44 #include "gdal/cpl_csv.h"
46 #include "gdal/cpl_string.h"
47 #include "LOD_reduce.h"
50 #include "model/georef.h"
54 extern s57RegistrarMgr *m_pRegistrarMan;
55 extern wxString g_csv_locn;
56 extern bool g_bGDAL_Debug;
58 bool chain_broken_mssage_shown =
false;
62 #include <wx/arrimpl.cpp>
63 WX_DEFINE_ARRAY(
float *, MyFloatPtrArray);
65 #define MAX_VECTOR_POINTS 1000
68 sigjmp_buf env_osenc_ogrf;
79 void OpenCPN_OGR_OSENC_ErrorHandler(CPLErr eErrClass,
int nError,
80 const char *pszErrorMsg) {
81 #define ERR_BUF_LEN 2000
83 char buf[ERR_BUF_LEN + 1];
85 if (eErrClass == CE_Debug) {
86 if (g_OsencVerbose) sprintf(buf,
" %s", pszErrorMsg);
87 }
else if (eErrClass == CE_Warning)
88 sprintf(buf,
" Warning %d: %s\n", nError, pszErrorMsg);
90 sprintf(buf,
" ERROR %d: %s\n", nError, pszErrorMsg);
92 if (g_bGDAL_Debug || (CE_Debug != eErrClass)) {
93 wxString msg(buf, wxConvUTF8);
100 if (eErrClass == CE_Fatal) {
101 longjmp(env_osenc_ogrf, 1);
110 Osenc_instreamFile::Osenc_instreamFile() { Init(); }
112 Osenc_instreamFile::~Osenc_instreamFile() {
delete m_instream; }
114 bool Osenc_instreamFile::Open(
const wxString &senc_file_name) {
115 m_instream =
new wxFFileInputStream(senc_file_name);
116 return m_instream->IsOk();
119 void Osenc_instreamFile::Close() {}
121 Osenc_instream &Osenc_instreamFile::Read(
void *buffer,
size_t size) {
122 if (m_instream) m_ok = m_instream->Read(buffer, size).IsOk();
127 bool Osenc_instreamFile::IsOk() {
128 if (m_instream) m_ok = m_instream->IsOk();
133 bool Osenc_instreamFile::isAvailable() {
return true; }
135 void Osenc_instreamFile::Shutdown() {}
137 void Osenc_instreamFile::Init() {
146 Osenc_outstreamFile::Osenc_outstreamFile() { Init(); }
148 Osenc_outstreamFile::~Osenc_outstreamFile() {
delete m_outstream; }
150 bool Osenc_outstreamFile::Open(
const wxString &file) {
152 m_outstream =
new wxFFileOutputStream(file);
153 if (m_outstream) m_ok = m_outstream->IsOk();
158 void Osenc_outstreamFile::Close() {
159 if (m_outstream) m_ok = m_outstream->Close();
162 Osenc_outstream &Osenc_outstreamFile::Write(
const void *buffer,
size_t size) {
163 if (m_outstream) m_ok = m_outstream->Write(buffer, size).IsOk();
168 bool Osenc_outstreamFile::IsOk() {
169 if (m_outstream) m_ok = m_outstream->IsOk();
174 void Osenc_outstreamFile::Init() {
183 Osenc::Osenc() { init(); }
186 if (m_bPrivateRegistrar)
delete m_poRegistrar;
189 SENCFloatPtrArray &AuxPtrArray = getSENCReadAuxPointArray();
190 std::vector<int> &AuxCntArray = getSENCReadAuxPointCountArray();
191 int nCOVREntries = AuxCntArray.size();
192 for (
unsigned int j = 0; j < (
unsigned int)nCOVREntries; j++) {
193 free(AuxPtrArray[j]);
196 SENCFloatPtrArray &AuxNoPtrArray = getSENCReadNOCOVRPointArray();
197 std::vector<int> &AuxNoCntArray = getSENCReadNOCOVRPointCountArray();
198 int nNoCOVREntries = AuxNoCntArray.size();
199 for (
unsigned int j = 0; j < (
unsigned int)nNoCOVREntries; j++) {
200 free(AuxNoPtrArray[j]);
205 for (
unsigned int j = 0; j < (
unsigned int)m_nNoCOVREntries; j++)
206 free(m_pNoCOVRTable[j]);
208 for (
unsigned int j = 0; j < (
unsigned int)m_nCOVREntries; j++)
209 free(m_pCOVRTable[j]);
211 free(m_pCOVRTablePoints);
213 free(m_pNoCOVRTablePoints);
214 free(m_pNoCOVRTable);
216 CPLPopErrorHandler();
219 void Osenc::init(
void) {
221 m_poRegistrar = NULL;
222 m_bPrivateRegistrar =
false;
223 m_senc_file_read_version = 0;
225 InitializePersistentBuffer();
230 m_read_base_edtn = _T(
"-1");
232 m_nNoCOVREntries = 0;
234 m_pCOVRTablePoints = NULL;
236 m_pNoCOVRTablePoints = NULL;
237 m_pNoCOVRTable = NULL;
239 m_pauxOutstream = NULL;
240 m_pauxInstream = NULL;
246 g_OsencVerbose =
true;
247 m_NoErrDialog =
false;
252 CPLPushErrorHandler(OpenCPN_OGR_OSENC_ErrorHandler);
254 lockCR = std::unique_lock<std::mutex>(m, std::defer_lock);
257 void Osenc::setVerbose(
bool verbose) {
258 m_bVerbose = verbose;
259 g_OsencVerbose = verbose;
262 int Osenc::ingestHeader(
const wxString &senc_file_name) {
266 int ret_val = SENC_NO_ERROR;
268 wxFileName fn(senc_file_name);
284 fpx.Open(senc_file_name);
285 if (!fpx.IsOk())
return ERROR_SENCFILE_NOT_FOUND;
293 return ERROR_SENCFILE_NOT_FOUND;
297 if (HEADER_SENC_VERSION != record.record_type) {
298 return ERROR_SENCFILE_NOT_FOUND;
305 return ERROR_SENCFILE_NOT_FOUND;
307 uint16_t *pint = (uint16_t *)buf;
308 m_senc_file_read_version = *pint;
326 switch (record.record_type) {
327 case HEADER_SENC_VERSION: {
335 uint16_t *pint = (uint16_t *)buf;
336 m_senc_file_read_version = *pint;
339 case HEADER_CELL_NAME: {
347 m_Name = wxString(buf, wxConvUTF8);
350 case HEADER_CELL_PUBLISHDATE: {
361 case HEADER_CELL_EDITION: {
369 uint16_t *pint = (uint16_t *)buf;
370 m_read_base_edtn.Printf(_T(
"%d"), *pint);
374 case HEADER_CELL_UPDATEDATE: {
385 case HEADER_CELL_UPDATE: {
394 uint16_t *pint = (uint16_t *)buf;
395 m_read_last_applied_update = *pint;
399 case HEADER_CELL_NATIVESCALE: {
407 uint32_t *pint = (uint32_t *)buf;
408 m_Chart_Scale = *pint;
413 case HEADER_CELL_SENCCREATEDATE: {
421 m_readFileCreateDate = wxString(buf, wxConvUTF8);
426 case CELL_EXTENT_RECORD: {
436 m_extent.NLAT = pPayload->extent_nw_lat;
437 m_extent.SLAT = pPayload->extent_se_lat;
438 m_extent.WLON = pPayload->extent_nw_lon;
439 m_extent.ELON = pPayload->extent_se_lon;
444 case CELL_COVR_RECORD: {
456 int point_count = pPayload->point_count;
457 m_AuxCntArray.push_back(point_count);
459 float *pf = (
float *)malloc(point_count * 2 *
sizeof(
float));
460 memcpy(pf, &pPayload->point_array, point_count * 2 *
sizeof(
float));
461 m_AuxPtrArray.Add(pf);
466 case CELL_NOCOVR_RECORD: {
478 int point_count = pPayload->point_count;
479 m_NoCovrCntArray.push_back(point_count);
481 float *pf = (
float *)malloc(point_count * 2 *
sizeof(
float));
482 memcpy(pf, &pPayload->point_array, point_count * 2 *
sizeof(
float));
483 m_NoCovrPtrArray.Add(pf);
488 case FEATURE_ID_RECORD: {
505 std::string Osenc::GetFeatureAcronymFromTypecode(
int typeCode) {
506 if (m_pRegistrarMan) {
507 std::string acronym = m_pRegistrarMan->getFeatureAcronym(typeCode);
508 return acronym.c_str();
513 std::string Osenc::GetAttributeAcronymFromTypecode(
int typeCode) {
515 return m_pRegistrarMan->getAttributeAcronym(typeCode);
520 int Osenc::ingest200(
const wxString &senc_file_name,
521 S57ObjVector *pObjectVector, VE_ElementVector *pVEArray,
522 VC_ElementVector *pVCArray) {
523 int ret_val = SENC_NO_ERROR;
541 fpx.Open(senc_file_name);
542 if (!fpx.IsOk())
return ERROR_SENCFILE_NOT_FOUND;
562 switch (record.record_type) {
563 case HEADER_SENC_VERSION: {
571 uint16_t *pint = (uint16_t *)buf;
572 m_senc_file_read_version = *pint;
575 case HEADER_CELL_NAME: {
583 m_Name = wxString(buf, wxConvUTF8);
586 case HEADER_CELL_PUBLISHDATE: {
594 m_sdate000 = wxString(buf, wxConvUTF8);
598 case HEADER_CELL_EDITION: {
606 uint16_t *pint = (uint16_t *)buf;
607 m_read_base_edtn.Printf(_T(
"%d"), *pint);
612 case HEADER_CELL_UPDATEDATE: {
620 m_LastUpdateDate = wxString(buf, wxConvUTF8);
624 case HEADER_CELL_UPDATE: {
632 uint16_t *pint = (uint16_t *)buf;
633 m_read_last_applied_update = *pint;
638 case HEADER_CELL_NATIVESCALE: {
646 uint32_t *pint = (uint32_t *)buf;
647 m_Chart_Scale = *pint;
651 case HEADER_CELL_SENCCREATEDATE: {
662 case CELL_EXTENT_RECORD: {
672 m_extent.NLAT = pPayload->extent_nw_lat;
673 m_extent.SLAT = pPayload->extent_se_lat;
674 m_extent.WLON = pPayload->extent_nw_lon;
675 m_extent.ELON = pPayload->extent_se_lon;
679 m_ref_lat = (m_extent.NLAT + m_extent.SLAT) / 2.;
680 m_ref_lon = (m_extent.ELON + m_extent.WLON) / 2.;
685 case CELL_COVR_RECORD: {
697 case CELL_NOCOVR_RECORD: {
709 case FEATURE_ID_RECORD: {
723 int featureTypeCode = pPayload->feature_type_code;
724 featureID = pPayload->feature_ID;
732 std::string acronym = GetFeatureAcronymFromTypecode(featureTypeCode);
739 if (acronym.length()) {
740 obj =
new S57Obj(acronym.c_str());
741 obj->Index = featureID;
743 pObjectVector->push_back(obj);
749 case FEATURE_ATTRIBUTE_RECORD: {
762 int attributeTypeCode = pPayload->attribute_type_code;
773 std::string acronym =
774 GetAttributeAcronymFromTypecode(attributeTypeCode);
776 int attributeValueType = pPayload->attribute_value_type;
778 if (acronym.length()) {
779 switch (attributeValueType) {
781 uint32_t val = pPayload->attribute_value_int;
783 obj->AddIntegerAttribute(acronym.c_str(), val);
798 double val = pPayload->attribute_value_double;
799 if (obj) obj->AddDoubleAttribute(acronym.c_str(), val);
811 char *val = (
char *)&pPayload->attribute_value_char_ptr;
812 if (obj) obj->AddStringAttribute(acronym.c_str(), val);
825 case FEATURE_GEOMETRY_RECORD_POINT: {
839 obj->SetPointGeometry(pPayload->lat, pPayload->lon, m_ref_lat,
846 case FEATURE_GEOMETRY_RECORD_AREA: {
860 unsigned char *next_byte;
861 PolyTessGeo *pPTG = BuildPolyTessGeo(pPayload, &next_byte);
863 obj->SetAreaGeometry(pPTG, m_ref_lat, m_ref_lon);
866 LineGeometryDescriptor Descriptor;
869 Descriptor.extent_e_lon = pPayload->extent_e_lon;
870 Descriptor.extent_w_lon = pPayload->extent_w_lon;
871 Descriptor.extent_s_lat = pPayload->extent_s_lat;
872 Descriptor.extent_n_lat = pPayload->extent_n_lat;
874 Descriptor.indexCount = pPayload->edgeVector_count;
878 Descriptor.indexTable =
879 (
int *)malloc(pPayload->edgeVector_count * 3 *
sizeof(
int));
880 memcpy(Descriptor.indexTable, next_byte,
881 pPayload->edgeVector_count * 3 *
sizeof(
int));
883 obj->SetLineGeometry(&Descriptor, GEO_AREA, m_ref_lat, m_ref_lon);
889 case FEATURE_GEOMETRY_RECORD_LINE: {
901 LineGeometryDescriptor lD;
904 lD.extent_e_lon = pPayload->extent_e_lon;
905 lD.extent_w_lon = pPayload->extent_w_lon;
906 lD.extent_s_lat = pPayload->extent_s_lat;
907 lD.extent_n_lat = pPayload->extent_n_lat;
909 lD.indexCount = pPayload->edgeVector_count;
913 (
int *)malloc(pPayload->edgeVector_count * 3 *
sizeof(
int));
914 memcpy(lD.indexTable, &pPayload->payLoad,
915 pPayload->edgeVector_count * 3 *
sizeof(
int));
917 if (obj) obj->SetLineGeometry(&lD, GEO_LINE, m_ref_lat, m_ref_lon);
922 case FEATURE_GEOMETRY_RECORD_MULTIPOINT: {
936 MultipointGeometryDescriptor Descriptor;
939 Descriptor.extent_e_lon = pPayload->extent_e_lon;
940 Descriptor.extent_w_lon = pPayload->extent_w_lon;
941 Descriptor.extent_s_lat = pPayload->extent_s_lat;
942 Descriptor.extent_n_lat = pPayload->extent_n_lat;
944 Descriptor.pointCount = pPayload->point_count;
945 Descriptor.pointTable = &pPayload->payLoad;
947 if (obj) obj->SetMultipointGeometry(&Descriptor, m_ref_lat, m_ref_lon);
952 case VECTOR_EDGE_NODE_TABLE_RECORD: {
962 uint8_t *pRun = (uint8_t *)buf;
965 int nCount = *(
int *)pRun;
969 for (
int i = 0; i < nCount; i++) {
970 int featureIndex = *(
int *)pRun;
973 int pointCount = *(
int *)pRun;
976 float *pPoints = NULL;
978 pPoints = (
float *)malloc(pointCount * 2 *
sizeof(
float));
979 memcpy(pPoints, pRun, pointCount * 2 *
sizeof(
float));
981 pRun += pointCount * 2 *
sizeof(float);
983 VE_Element *pvee =
new VE_Element;
984 pvee->index = featureIndex;
985 pvee->nCount = pointCount;
986 pvee->pPoints = pPoints;
987 pvee->max_priority = 0;
989 pVEArray->push_back(pvee);
995 case VECTOR_CONNECTED_NODE_TABLE_RECORD: {
1005 uint8_t *pRun = (uint8_t *)buf;
1008 int nCount = *(
int *)pRun;
1009 pRun +=
sizeof(int);
1011 for (
int i = 0; i < nCount; i++) {
1012 int featureIndex = *(
int *)pRun;
1013 pRun +=
sizeof(int);
1015 float *pPoint = (
float *)malloc(2 *
sizeof(
float));
1016 memcpy(pPoint, pRun, 2 *
sizeof(
float));
1017 pRun += 2 *
sizeof(float);
1019 VC_Element *pvce =
new VC_Element;
1020 pvce->index = featureIndex;
1021 pvce->pPoint = pPoint;
1023 pVCArray->push_back(pvce);
1038 int Osenc::ingestCell(OGRS57DataSource *poS57DS,
const wxString &FullPath000,
1039 const wxString &working_dir) {
1046 wxString LastUpdateDate = m_date000.Format(_T(
"%Y%m%d"));
1048 int available_updates =
1049 ValidateAndCountUpdates(FullPath000, working_dir, LastUpdateDate,
true);
1053 if (m_bVerbose && (available_updates > m_UPDN)) {
1056 _T(
"Preparing to apply ENC updates, target final update is %3d."),
1066 char **papszReaderOptions = NULL;
1071 papszReaderOptions =
1072 CSLSetNameValue(papszReaderOptions, S57O_RETURN_LINKAGES,
"ON");
1073 papszReaderOptions =
1074 CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
"ON");
1075 poS57DS->SetOptionList(papszReaderOptions);
1080 bool b_current_debug = g_bGDAL_Debug;
1081 g_bGDAL_Debug = m_bVerbose;
1084 wxString s0_file = working_dir;
1085 if (s0_file.Last() != wxFileName::GetPathSeparator())
1086 s0_file.Append(wxFileName::GetPathSeparator());
1087 wxFileName f000(FullPath000);
1089 s0_file.Append(f000.GetFullName());
1091 if (poS57DS->Open(s0_file.mb_str(), TRUE, NULL))
return 1;
1094 S57Reader *poReader = poS57DS->GetModule(0);
1096 m_last_applied_update = m_UPDN;
1097 wxString last_successful_update_file;
1100 for (
unsigned int i_up = 0; i_up < m_tmpup_array.GetCount(); i_up++) {
1101 wxFileName fn(m_tmpup_array[i_up]);
1102 wxString ext = fn.GetExt();
1107 DDFModule oUpdateModule;
1108 if (!oUpdateModule.Open(m_tmpup_array[i_up].mb_str(), FALSE)) {
1111 int upResult = poReader->ApplyUpdates(&oUpdateModule, n_upd);
1115 m_last_applied_update = n_upd;
1116 last_successful_update_file = m_tmpup_array[i_up];
1131 if ((available_updates > 0) && (m_last_applied_update != available_updates)) {
1132 if (last_successful_update_file.Length()) {
1135 DDFModule oUpdateModule;
1136 wxString LastGoodUpdateDate;
1137 wxDateTime now = wxDateTime::Now();
1138 LastGoodUpdateDate = now.Format(_T(
"%Y%m%d"));
1141 oUpdateModule.Open(last_successful_update_file.mb_str(), TRUE) == 0);
1145 oUpdateModule.Rewind();
1146 DDFRecord *pr = oUpdateModule.ReadRecord();
1152 u = (
char *)(pr->GetStringSubfield(
"DSID", 0,
"ISDT", 0, &nSuccess));
1156 LastGoodUpdateDate = wxString(u, wxConvUTF8);
1159 m_LastUpdateDate = LastGoodUpdateDate;
1164 _T(
"WARNING---ENC Update failed. Last valid update file is:"));
1165 msg += last_successful_update_file.mb_str();
1168 _T(
" This ENC exchange set should be updated and SENCs rebuilt."));
1170 if (!m_NoErrDialog) {
1173 _(
"S57 Cell Update failed.\nENC features may be incomplete or "
1174 "inaccurate.\n\nCheck the logfile for details."),
1175 _(
"OpenCPN Create SENC Warning"), wxOK | wxICON_EXCLAMATION, 5);
1179 OCPNMessageBox(NULL,
1180 _(
"S57 Cell Update failed.\nNo updates could be "
1181 "applied.\nENC features may be incomplete or "
1182 "inaccurate.\n\nCheck the logfile for details."),
1183 _(
"OpenCPN Create SENC Warning"),
1184 wxOK | wxICON_EXCLAMATION, 5);
1189 g_bGDAL_Debug = b_current_debug;
1195 papszReaderOptions =
1196 CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
"OFF");
1197 poReader->SetOptions(papszReaderOptions);
1198 CSLDestroy(papszReaderOptions);
1200 wxRemoveFile(s0_file);
1205 int Osenc::ValidateAndCountUpdates(
const wxFileName file000,
1206 const wxString CopyDir,
1207 wxString &LastUpdateDate,
bool b_copyfiles) {
1209 wxFileName last_up_added;
1213 m_UpFiles =
new wxArrayString;
1215 s57chart::GetUpdateFileArray(file000, m_UpFiles, m_date000, m_edtn000);
1218 if (m_UpFiles->GetCount()) {
1235 unsigned int jup = 0;
1236 for (
int iff = 0; iff < retval + 1; iff++) {
1238 wxString targetFile;
1240 if (jup < m_UpFiles->GetCount()) upFile = m_UpFiles->Item(jup);
1241 wxFileName upCheck(upFile);
1243 wxString text = upCheck.GetExt();
1246 targetFile = upFile;
1249 targetFile = file000.GetFullName();
1252 wxFileName ufile(targetFile);
1254 sext.Printf(_T(
"%03d"), iff);
1258 wxString cp_ufile = CopyDir;
1259 if (cp_ufile.Last() != ufile.GetPathSeparator())
1260 cp_ufile.Append(ufile.GetPathSeparator());
1262 cp_ufile.Append(ufile.GetFullName());
1264 wxString tfile = ufile.GetFullPath();
1269 if (ufile.FileExists()) {
1270 wxFile uf(ufile.GetFullPath());
1271 if (uf.IsOpened()) {
1277 if (ufile.FileExists() &&
1281 bool cpok = wxCopyFile(ufile.GetFullPath(), cp_ufile);
1283 wxString msg(_T(
" Cannot copy temporary working ENC file "));
1284 msg.Append(ufile.GetFullPath());
1285 msg.Append(_T(
" to "));
1286 msg.Append(cp_ufile);
1316 _T(
"WARNING---ENC Update chain incomplete. Substituting NULL ")
1317 _T(
"update file: "));
1318 msg += ufile.GetFullName();
1320 wxLogMessage(_T(
" Subsequent ENC updates may produce errors."));
1322 _T(
" This ENC exchange set should be updated and SENCs ")
1327 dupdate.Initialize(
'3',
'L',
'E',
'1',
'0',
"!!!", 3, 4, 4);
1328 bstat = !(dupdate.Create(cp_ufile.mb_str()) == 0);
1332 wxString msg(_T(
" Error creating dummy update file: "));
1333 msg.Append(cp_ufile);
1338 m_tmpup_array.Add(cp_ufile);
1339 last_up_added = cp_ufile;
1346 wxFileName lastfile(last_up_added);
1348 last_sext.Printf(_T(
"%03d"), upmax);
1349 lastfile.SetExt(last_sext);
1352 DDFModule oUpdateModule;
1355 !(oUpdateModule.Open(lastfile.GetFullPath().mb_str(), TRUE) == 0);
1359 oUpdateModule.Rewind();
1360 DDFRecord *pr = oUpdateModule.ReadRecord();
1366 u = (
char *)(pr->GetStringSubfield(
"DSID", 0,
"ISDT", 0, &nSuccess));
1370 LastUpdateDate = wxString(u, wxConvUTF8);
1373 wxDateTime now = wxDateTime::Now();
1374 LastUpdateDate = now.Format(_T(
"%Y%m%d"));
1382 bool Osenc::GetBaseFileAttr(
const wxString &FullPath000) {
1384 if (!oModule.Open(FullPath000.mb_str())) {
1394 DDFRecord *pr = oModule.ReadRecord();
1398 m_nGeoRecords = pr->GetIntSubfield(
"DSSI", 0,
"NOGR", 0);
1399 if (!m_nGeoRecords) {
1401 _T(
"GetBaseFileAttr: DDFRecord 0 does not contain DSSI:NOGR ");
1409 char *u = (
char *)(pr->GetStringSubfield(
"DSID", 0,
"ISDT", 0));
1411 date000 = wxString(u, wxConvUTF8);
1414 _T(
"GetBaseFileAttr: DDFRecord 0 does not contain DSID:ISDT ");
1419 m_date000.ParseFormat(date000, _T(
"%Y%m%d"));
1420 if (!m_date000.IsValid()) m_date000.ParseFormat(_T(
"20000101"), _T(
"%Y%m%d"));
1422 m_date000.ResetTime();
1425 u = (
char *)(pr->GetStringSubfield(
"DSID", 0,
"EDTN", 0));
1427 m_edtn000 = wxString(u, wxConvUTF8);
1430 _T(
"GetBaseFileAttr: DDFRecord 0 does not contain DSID:EDTN ");
1432 m_edtn000 = _T(
"1");
1438 u = (
char *)(pr->GetStringSubfield(
"DSID", 0,
"UPDN", 0));
1441 wxString tmp_updn = wxString(u, wxConvUTF8);
1442 if (tmp_updn.ToLong(&updn)) m_UPDN = updn;
1446 _T(
"GetBaseFileAttr: DDFRecord 0 does not contain DSID:UPDN ");
1453 for (; pr != NULL; pr = oModule.ReadRecord()) {
1454 if (pr->FindField(
"DSPM") != NULL) {
1455 m_native_scale = pr->GetIntSubfield(
"DSPM", 0,
"CSCL", 0);
1459 if (!m_native_scale) {
1460 errorMessage = _T(
"GetBaseFileAttr: ENC not contain DSPM:CSCL ");
1462 m_native_scale = 1000;
1474 int Osenc::createSenc200(
const wxString &FullPath000,
1475 const wxString &SENCFileName,
bool b_showProg) {
1478 m_FullPath000 = FullPath000;
1480 m_senc_file_create_version = 201;
1482 if (!m_poRegistrar) {
1483 m_poRegistrar =
new S57ClassRegistrar();
1484 m_poRegistrar->LoadInfo(g_csv_locn.mb_str(), FALSE);
1485 m_bPrivateRegistrar =
true;
1490 wxFileName SENCfile = wxFileName(SENCFileName);
1491 wxFileName file000 = wxFileName(FullPath000);
1494 if (
true != SENCfile.DirExists(SENCfile.GetPath())) {
1495 if (!SENCfile.Mkdir(SENCfile.GetPath())) {
1497 _T(
"Cannot create SENC file directory for ") + SENCfile.GetFullPath();
1499 return ERROR_CANNOT_CREATE_SENC_DIR;
1505 wxString tmp_file = tfn.CreateTempFileName(_T(
""));
1517 if (m_pauxOutstream) {
1518 m_pOutstream = m_pauxOutstream;
1525 if (!stream->Open(tmp_file)) {
1526 errorMessage = _T(
"Unable to create temp SENC file: ");
1527 errorMessage += tmp_file;
1528 delete m_pOutstream;
1530 return ERROR_CANNOT_CREATE_TEMP_SENC_FILE;
1535 if (!GetBaseFileAttr(FullPath000)) {
1536 delete m_pOutstream;
1538 return ERROR_BASEFILE_ATTRIBUTES;
1541 OGRS57DataSource S57DS;
1542 OGRS57DataSource *poS57DS = &S57DS;
1543 poS57DS->SetS57Registrar(m_poRegistrar);
1547 if (ingestCell(poS57DS, FullPath000, SENCfile.GetPath())) {
1548 errorMessage = _T(
"Error ingesting: ") + FullPath000;
1549 delete m_pOutstream;
1551 return ERROR_INGESTING000;
1554 S57Reader *poReader = poS57DS->GetModule(0);
1557 if (!CreateCOVRTables(poReader, m_poRegistrar)) {
1558 delete m_pOutstream;
1560 return ERROR_SENCFILE_ABORT;
1564 m_ref_lat = (m_extent.NLAT + m_extent.SLAT) / 2.;
1565 m_ref_lon = (m_extent.WLON + m_extent.ELON) / 2.;
1577 s57chart::GetChartNameFromTXT(FullPath000, nice_name);
1579 string sname =
"UTF8Error";
1580 wxCharBuffer buffer = nice_name.ToUTF8();
1581 if (buffer.data()) sname = buffer.data();
1583 if (!WriteHeaderRecord200(stream, HEADER_SENC_VERSION,
1584 (uint16_t)m_senc_file_create_version)) {
1586 delete m_pOutstream;
1588 return ERROR_SENCFILE_ABORT;
1591 if (!WriteHeaderRecord200(stream, HEADER_CELL_NAME, sname)) {
1593 delete m_pOutstream;
1595 return ERROR_SENCFILE_ABORT;
1598 wxString date000 = m_date000.Format(_T(
"%Y%m%d"));
1599 string sdata = date000.ToStdString();
1600 if (!WriteHeaderRecord200(stream, HEADER_CELL_PUBLISHDATE, sdata)) {
1602 delete m_pOutstream;
1604 return ERROR_SENCFILE_ABORT;
1608 m_edtn000.ToLong(&n000);
1609 if (!WriteHeaderRecord200(stream, HEADER_CELL_EDITION, (uint16_t)n000)) {
1611 delete m_pOutstream;
1613 return ERROR_SENCFILE_ABORT;
1616 sdata = m_LastUpdateDate.ToStdString();
1617 if (!WriteHeaderRecord200(stream, HEADER_CELL_UPDATEDATE, sdata)) {
1619 delete m_pOutstream;
1621 return ERROR_SENCFILE_ABORT;
1624 if (!WriteHeaderRecord200(stream, HEADER_CELL_UPDATE,
1625 (uint16_t)m_last_applied_update)) {
1627 delete m_pOutstream;
1629 return ERROR_SENCFILE_ABORT;
1632 if (!WriteHeaderRecord200(stream, HEADER_CELL_NATIVESCALE,
1633 (uint32_t)m_native_scale)) {
1635 delete m_pOutstream;
1637 return ERROR_SENCFILE_ABORT;
1640 wxDateTime now = wxDateTime::Now();
1641 wxString dateNow = now.Format(_T(
"%Y%m%d"));
1642 sdata = dateNow.ToStdString();
1643 if (!WriteHeaderRecord200(stream, HEADER_CELL_SENCCREATEDATE, sdata)) {
1645 delete m_pOutstream;
1647 return ERROR_SENCFILE_ABORT;
1651 if (!CreateCovrRecords(stream)) {
1653 delete m_pOutstream;
1655 return ERROR_SENCFILE_ABORT;
1663 OGRFeature *pEdgeVectorRecordFeature = poReader->ReadVector(feid, RCNM_VE);
1664 while (NULL != pEdgeVectorRecordFeature) {
1665 int record_id = pEdgeVectorRecordFeature->GetFieldAsInteger(
"RCID");
1667 m_vector_helper_hash[record_id] = feid;
1670 delete pEdgeVectorRecordFeature;
1671 pEdgeVectorRecordFeature = poReader->ReadVector(feid, RCNM_VE);
1674 wxString Message = SENCfile.GetFullPath();
1675 Message.Append(_T(
"...Ingesting"));
1677 wxString Title(_(
"OpenCPN S57 SENC File Create..."));
1678 Title.append(SENCfile.GetFullPath());
1680 #if wxUSE_PROGRESSDLG
1683 int nProg = poReader->GetFeatureCount();
1685 if (wxThread::IsMain() && b_showProg) {
1686 m_ProgDialog =
new wxGenericProgressDialog();
1688 wxFont *qFont = GetOCPNScaledFont(_(
"Dialog"));
1689 m_ProgDialog->SetFont(*qFont);
1691 m_ProgDialog->Create(Title, Message, nProg, NULL,
1692 wxPD_AUTO_HIDE | wxPD_SMOOTH);
1697 OGRFeature *objectDef;
1702 objectDef = poReader->ReadNextFeature();
1704 if (objectDef != NULL) {
1707 #if wxUSE_PROGRESSDLG
1713 if (m_ProgDialog && progsw.Time() > 200) {
1717 wxString(objectDef->GetDefnRef()->GetName(), wxConvUTF8);
1718 sobj.Append(wxString::Format(_T(
" %d/%d "), iObj, nProg));
1720 bcont = m_ProgDialog->Update(iObj, sobj);
1721 #if defined(__WXMSW__) || defined(__WXOSX__)
1727 OGRwkbGeometryType geoType = wkbUnknown;
1734 if (objectDef->GetGeometryRef() != NULL)
1735 geoType = objectDef->GetGeometryRef()->getGeometryType();
1738 if (geoType != wkbUnknown) {
1739 CreateSENCRecord200(objectDef, stream, 1, poReader);
1750 CreateSENCVectorEdgeTableRecord200(stream, poReader);
1753 CreateSENCVectorConnectedTableRecord200(stream, poReader);
1758 delete m_pOutstream;
1762 for (
unsigned int iff = 0; iff < m_tmpup_array.GetCount(); iff++)
1763 remove(m_tmpup_array[iff].mb_str());
1769 wxRemoveFile(tmp_file);
1770 ret_code = ERROR_SENCFILE_ABORT;
1774 bool cpok = wxRenameFile(tmp_file, SENCfile.GetFullPath());
1776 errorMessage = _T(
" Cannot rename temporary SENC file ");
1777 errorMessage.Append(tmp_file);
1778 errorMessage.Append(_T(
" to "));
1779 errorMessage.Append(SENCfile.GetFullPath());
1780 ret_code = ERROR_SENCFILE_ABORT;
1782 ret_code = SENC_NO_ERROR;
1785 #if wxUSE_PROGRESSDLG
1786 delete m_ProgDialog;
1797 record.record_type = CELL_EXTENT_RECORD;
1799 record.extent_sw_lat = m_extent.SLAT;
1800 record.extent_sw_lon = m_extent.WLON;
1801 record.extent_nw_lat = m_extent.NLAT;
1802 record.extent_nw_lon = m_extent.WLON;
1803 record.extent_ne_lat = m_extent.NLAT;
1804 record.extent_ne_lon = m_extent.ELON;
1805 record.extent_se_lat = m_extent.SLAT;
1806 record.extent_se_lon = m_extent.ELON;
1808 size_t targetCount =
sizeof(record);
1809 if (!stream->Write(&record, targetCount).IsOk())
return false;
1811 for (
int i = 0; i < m_nCOVREntries; i++) {
1812 int nPoints = m_pCOVRTablePoints[i];
1814 float *fpbuf = m_pCOVRTable[i];
1818 record.record_type = CELL_COVR_RECORD;
1820 (nPoints * 2 *
sizeof(float));
1823 size_t targetCount =
sizeof(record);
1824 if (!stream->Write(&record, targetCount).IsOk())
return false;
1827 targetCount =
sizeof(uint32_t);
1828 if (!stream->Write(&nPoints, targetCount).IsOk())
return false;
1831 targetCount = nPoints * 2 *
sizeof(float);
1832 if (!stream->Write(fpbuf, targetCount).IsOk())
return false;
1835 for (
int i = 0; i < m_nNoCOVREntries; i++) {
1836 int nPoints = m_pNoCOVRTablePoints[i];
1838 float *fpbuf = m_pNoCOVRTable[i];
1842 record.record_type = CELL_NOCOVR_RECORD;
1844 sizeof(uint32_t) + (nPoints * 2 *
sizeof(float));
1847 size_t targetCount =
sizeof(record);
1848 if (!stream->Write(&record, targetCount).IsOk())
return false;
1851 targetCount =
sizeof(uint32_t);
1852 if (!stream->Write(&nPoints, targetCount).IsOk())
return false;
1855 targetCount = nPoints * 2 *
sizeof(float);
1856 if (!stream->Write(fpbuf, targetCount).IsOk())
return false;
1862 bool Osenc::WriteHeaderRecord200(
Osenc_outstream *stream,
int recordType,
1863 std::string payload) {
1864 int payloadLength = payload.length() + 1;
1868 unsigned char *pBuffer = getBuffer(recordLength);
1871 memset(pRecord, 0, recordLength);
1872 pRecord->record_type = recordType;
1873 pRecord->record_length = recordLength;
1874 memcpy(&pRecord->payload, payload.c_str(), payloadLength);
1876 size_t targetCount = recordLength;
1877 if (!stream->Write(pBuffer, targetCount).IsOk())
1883 bool Osenc::WriteHeaderRecord200(
Osenc_outstream *stream,
int recordType,
1885 int payloadLength =
sizeof(uint16_t);
1889 unsigned char *pBuffer = getBuffer(recordLength);
1892 memset(pRecord, 0, recordLength);
1893 pRecord->record_type = recordType;
1894 pRecord->record_length = recordLength;
1895 memcpy(&pRecord->payload, &val, payloadLength);
1897 size_t targetCount = recordLength;
1898 if (!stream->Write(pBuffer, targetCount).IsOk())
1904 bool Osenc::WriteHeaderRecord200(
Osenc_outstream *stream,
int recordType,
1906 int payloadLength =
sizeof(uint32_t);
1910 unsigned char *pBuffer = getBuffer(recordLength);
1913 memset(pRecord, 0, recordLength);
1914 pRecord->record_type = recordType;
1915 pRecord->record_length = recordLength;
1916 memcpy(&pRecord->payload, &val, payloadLength);
1918 size_t targetCount = recordLength;
1919 if (!stream->Write(pBuffer, targetCount).IsOk())
1925 bool Osenc::WriteFIDRecord200(
Osenc_outstream *stream,
int nOBJL,
int featureID,
1928 memset(&record, 0,
sizeof(record));
1930 record.record_type = FEATURE_ID_RECORD;
1931 record.record_length =
sizeof(record);
1933 record.feature_ID = featureID;
1934 record.feature_type_code = nOBJL;
1935 record.feature_primitive = prim;
1937 size_t targetCount =
sizeof(record);
1938 if (!stream->Write(&record, targetCount).IsOk())
1944 bool Osenc::CreateMultiPointFeatureGeometryRecord200(OGRFeature *pFeature,
1946 OGRGeometry *pGeo = pFeature->GetGeometryRef();
1948 int wkb_len = pGeo->WkbSize();
1949 unsigned char *pwkb_buffer = (
unsigned char *)malloc(wkb_len);
1952 pGeo->exportToWkb(wkbNDR, pwkb_buffer);
1956 unsigned char *ps = pwkb_buffer;
1958 int nPoints = *((
int *)ps);
1960 int sb_len = (nPoints * 3 *
sizeof(float));
1962 unsigned char *psb_buffer = (
unsigned char *)malloc(sb_len);
1963 unsigned char *pd = psb_buffer;
1968 float *pdf = (
float *)pd;
1971 float lonmax = -1000;
1972 float lonmin = 1000;
1973 float latmax = -1000;
1974 float latmin = 1000;
1976 for (
int ip = 0; ip < nPoints; ip++) {
1984 OGRGeometryCollection *temp_geometry_collection =
1985 (OGRGeometryCollection *)pGeo;
1986 OGRGeometry *temp_geometry = temp_geometry_collection->getGeometryRef(ip);
1987 OGRPoint *pt_geom = (OGRPoint *)temp_geometry;
1989 double lon = pt_geom->getX();
1990 double lat = pt_geom->getY();
1991 double depth = pt_geom->getZ();
1994 double easting, northing;
1995 toSM(lat, lon, m_ref_lat, m_ref_lon, &easting, &northing);
1998 float __attribute__((aligned(16))) east = easting;
1999 float __attribute__((aligned(16))) north = northing;
2000 float __attribute__((aligned(16))) deep = depth;
2001 unsigned char *puceast = (
unsigned char *)&east;
2002 unsigned char *pucnorth = (
unsigned char *)&north;
2003 unsigned char *pucdeep = (
unsigned char *)&deep;
2005 memcpy(pdf++, puceast, sizeof(
float));
2006 memcpy(pdf++, pucnorth, sizeof(
float));
2007 memcpy(pdf++, pucdeep, sizeof(
float));
2012 *pdf++ = (float)depth;
2016 lonmax = fmax(lon, lonmax);
2017 lonmin = fmin(lon, lonmin);
2018 latmax = fmax(lat, latmax);
2019 latmin = fmin(lat, latmin);
2024 record.record_type = FEATURE_GEOMETRY_RECORD_MULTIPOINT;
2026 (nPoints * 3 *
sizeof(
float));
2027 record.extent_e_lon = lonmax;
2028 record.extent_w_lon = lonmin;
2029 record.extent_n_lat = latmax;
2030 record.extent_s_lat = latmin;
2031 record.point_count = nPoints;
2034 size_t targetCount =
sizeof(record);
2035 if (!stream->Write(&record, targetCount).IsOk())
goto failure;
2037 targetCount = nPoints * 3 *
sizeof(float);
2038 if (!stream->Write(psb_buffer, targetCount).IsOk())
goto failure;
2051 bool Osenc::CreateLineFeatureGeometryRecord200(S57Reader *poReader,
2052 OGRFeature *pFeature,
2054 OGRGeometry *pGeo = pFeature->GetGeometryRef();
2056 int wkb_len = pGeo->WkbSize();
2057 unsigned char *pwkb_buffer = (
unsigned char *)malloc(wkb_len);
2060 pGeo->exportToWkb(wkbNDR, pwkb_buffer);
2065 ((wkb_len - 9) / 2) + 9 + 16;
2067 unsigned char *psb_buffer = (
unsigned char *)malloc(sb_len);
2068 unsigned char *pd = psb_buffer;
2069 unsigned char *ps = pwkb_buffer;
2073 int ip = *((
int *)(ps + 5));
2077 double *psd = (
double *)ps;
2078 float *pdf = (
float *)pd;
2081 float lonmax = -1000;
2082 float lonmin = 1000;
2083 float latmax = -1000;
2084 float latmin = 1000;
2086 for (
int i = 0; i < ip; i++) {
2089 double easting, northing;
2091 double __attribute__((aligned(16))) east_d, north_d;
2092 unsigned char *pucd = (
unsigned char *)psd;
2094 memcpy(&east_d, pucd, sizeof(
double));
2096 pucd += sizeof(
double);
2097 memcpy(&north_d, pucd, sizeof(
double));
2103 toSM(lat, lon, m_ref_lat, m_ref_lon, &easting, &northing);
2104 unsigned char *puceasting = (
unsigned char *)&easting;
2105 unsigned char *pucnorthing = (
unsigned char *)&northing;
2107 memcpy(pdf++, puceasting, sizeof(
float));
2108 memcpy(pdf++, pucnorthing, sizeof(
float));
2111 lon = (float)*psd++;
2112 lat = (float)*psd++;
2115 toSM(lat, lon, m_ref_lat, m_ref_lon, &easting, &northing);
2121 lonmax = fmax(lon, lonmax);
2122 lonmin = fmin(lon, lonmin);
2123 latmax = fmax(lat, latmax);
2124 latmin = fmin(lat, latmin);
2127 int nEdgeVectorRecords = 0;
2128 unsigned char *pvec_buffer =
2129 getObjectVectorIndexTable(poReader, pFeature, nEdgeVectorRecords);
2136 int nEdgeVectorRecords;
2137 OGRFeature *pEdgeVectorRecordFeature;
2139 pNAME_RCID = (
int *) pFeature->GetFieldAsIntegerList(
"NAME_RCID", &nEdgeVectorRecords );
2140 pORNT = (
int *) pFeature->GetFieldAsIntegerList(
"ORNT", NULL );
2147 unsigned char *pvec_buffer = (
unsigned char *)malloc(nEdgeVectorRecords * 3 *
sizeof(
int));
2148 unsigned char *pvRun = pvec_buffer;
2151 char ** papszReaderOptions = NULL;
2152 papszReaderOptions = CSLSetNameValue( papszReaderOptions, S57O_UPDATES,
"ON" );
2153 papszReaderOptions = CSLSetNameValue( papszReaderOptions, S57O_RETURN_LINKAGES,
"ON" );
2154 papszReaderOptions = CSLSetNameValue( papszReaderOptions, S57O_RETURN_PRIMITIVES,
"ON" );
2155 poReader->SetOptions( papszReaderOptions );
2158 for(
int i = 0; i < nEdgeVectorRecords; i++ ) {
2160 int *pI = (
int *)pvRun;
2162 int edge_rcid = pNAME_RCID[i];
2164 int start_rcid, end_rcid;
2165 int target_record_feid = m_vector_helper_hash[pNAME_RCID[i]];
2166 pEdgeVectorRecordFeature = poReader->ReadVector( target_record_feid, RCNM_VE );
2168 if( NULL != pEdgeVectorRecordFeature ) {
2169 start_rcid = pEdgeVectorRecordFeature->GetFieldAsInteger(
"NAME_RCID_0" );
2170 end_rcid = pEdgeVectorRecordFeature->GetFieldAsInteger(
"NAME_RCID_1" );
2176 if( !poReader->FetchPoint( RCNM_VC, start_rcid, NULL, NULL, NULL, NULL ) )
2178 if( !poReader->FetchPoint( RCNM_VC, end_rcid, NULL, NULL, NULL, NULL ) )
2181 OGRLineString *poLS = (OGRLineString *)pEdgeVectorRecordFeature->GetGeometryRef();
2185 if( edge_ornt == 1 ){
2195 delete pEdgeVectorRecordFeature;
2205 pvRun += 3 *
sizeof(int);
2210 papszReaderOptions = CSLSetNameValue( papszReaderOptions, S57O_RETURN_PRIMITIVES,
"OFF" );
2211 poReader->SetOptions( papszReaderOptions );
2212 CSLDestroy( papszReaderOptions );
2217 record.record_type = FEATURE_GEOMETRY_RECORD_LINE;
2219 (nEdgeVectorRecords * 3 *
sizeof(
int));
2220 record.extent_e_lon = lonmax;
2221 record.extent_w_lon = lonmin;
2222 record.extent_n_lat = latmax;
2223 record.extent_s_lat = latmin;
2224 record.edgeVector_count = nEdgeVectorRecords;
2227 size_t targetCount =
sizeof(record);
2228 if (!stream->Write(&record, targetCount).IsOk())
return false;
2231 targetCount = nEdgeVectorRecords * 3 *
sizeof(int);
2232 if (!stream->Write(pvec_buffer, targetCount).IsOk())
return false;
2242 bool Osenc::CreateAreaFeatureGeometryRecord200(S57Reader *poReader,
2243 OGRFeature *pFeature,
2247 PolyTessGeo *ppg = NULL;
2249 OGRGeometry *pGeo = pFeature->GetGeometryRef();
2250 OGRPolygon *poly = (OGRPolygon *)(pGeo);
2252 if (!poly->getExteriorRing())
return false;
2255 ppg =
new PolyTessGeo(poly,
true, m_ref_lat, m_ref_lon, m_LOD_meters);
2258 error_code = ppg->ErrorCode;
2262 _T(
" Warning: S57 SENC Geometry Error %d, Some Features ignored."),
2273 memset(&baseRecord, 0,
sizeof(baseRecord));
2275 baseRecord.record_type = FEATURE_GEOMETRY_RECORD_AREA;
2279 baseRecord.extent_s_lat = ppg->Get_ymin();
2280 baseRecord.extent_n_lat = ppg->Get_ymax();
2281 baseRecord.extent_e_lon = ppg->Get_xmax();
2282 baseRecord.extent_w_lon = ppg->Get_xmin();
2284 baseRecord.contour_count = ppg->GetnContours();
2288 int contourPointCountArraySize = ppg->GetnContours() *
sizeof(uint32_t);
2289 uint32_t *contourPointCountArray =
2290 (uint32_t *)malloc(contourPointCountArraySize);
2292 uint32_t *pr = contourPointCountArray;
2294 for (
int i = 0; i < ppg->GetnContours(); i++) {
2295 *pr++ = ppg->Get_PolyTriGroup_head()->pn_vertex[i];
2311 TriPrim *pTP = ppg->Get_PolyTriGroup_head()
2316 geoLength +=
sizeof(uint8_t) +
sizeof(uint32_t);
2317 geoLength += pTP->nVert * 2 *
sizeof(float);
2318 geoLength += 4 *
sizeof(double);
2324 baseRecord.triprim_count = n_TriPrims;
2326 int nEdgeVectorRecords = 0;
2327 unsigned char *pvec_buffer =
2328 getObjectVectorIndexTable(poReader, pFeature, nEdgeVectorRecords);
2335 int nEdgeVectorRecords;
2336 OGRFeature *pEdgeVectorRecordFeature;
2338 pNAME_RCID = (
int *) pFeature->GetFieldAsIntegerList(
"NAME_RCID", &nEdgeVectorRecords );
2339 pORNT = (
int *) pFeature->GetFieldAsIntegerList(
"ORNT", NULL );
2341 baseRecord.edgeVector_count = nEdgeVectorRecords;
2343 unsigned char *pvec_buffer = (
unsigned char *)malloc(nEdgeVectorRecords * 3 *
sizeof(
int));
2344 unsigned char *pvRun = pvec_buffer;
2347 char ** papszReaderOptions = NULL;
2348 papszReaderOptions = CSLSetNameValue( papszReaderOptions, S57O_UPDATES,
"ON" );
2349 papszReaderOptions = CSLSetNameValue( papszReaderOptions, S57O_RETURN_LINKAGES,
"ON" );
2350 papszReaderOptions = CSLSetNameValue( papszReaderOptions, S57O_RETURN_PRIMITIVES,
"ON" );
2351 poReader->SetOptions( papszReaderOptions );
2354 for(
int i = 0; i < nEdgeVectorRecords; i++ ) {
2356 int *pI = (
int *)pvRun;
2358 int start_rcid, end_rcid;
2359 int target_record_feid = m_vector_helper_hash[pNAME_RCID[i]];
2360 pEdgeVectorRecordFeature = poReader->ReadVector( target_record_feid, RCNM_VE );
2362 int edge_rcid = pNAME_RCID[i];
2364 if( NULL != pEdgeVectorRecordFeature ) {
2365 start_rcid = pEdgeVectorRecordFeature->GetFieldAsInteger(
"NAME_RCID_0" );
2366 end_rcid = pEdgeVectorRecordFeature->GetFieldAsInteger(
"NAME_RCID_1" );
2371 if( !poReader->FetchPoint( RCNM_VC, start_rcid, NULL, NULL, NULL, NULL ) )
2373 if( !poReader->FetchPoint( RCNM_VC, end_rcid, NULL, NULL, NULL, NULL ) )
2379 if( edge_ornt == 1 ){
2389 delete pEdgeVectorRecordFeature;
2399 pvRun += 3 *
sizeof(int);
2404 papszReaderOptions = CSLSetNameValue( papszReaderOptions, S57O_RETURN_PRIMITIVES,
"OFF" );
2405 poReader->SetOptions( papszReaderOptions );
2406 CSLDestroy( papszReaderOptions );
2410 baseRecord.edgeVector_count = nEdgeVectorRecords;
2414 recordLength += contourPointCountArraySize;
2415 recordLength += geoLength;
2416 recordLength += nEdgeVectorRecords * 3 *
sizeof(int);
2417 baseRecord.record_length = recordLength;
2420 size_t targetCount =
sizeof(baseRecord);
2421 if (!stream->Write(&baseRecord, targetCount).IsOk())
return false;
2424 targetCount = contourPointCountArraySize;
2425 if (!stream->Write(contourPointCountArray, targetCount).IsOk())
return false;
2428 pTP = ppg->Get_PolyTriGroup_head()
2431 if (!stream->Write(&pTP->type,
sizeof(uint8_t)).IsOk())
return false;
2432 if (!stream->Write(&pTP->nVert,
sizeof(uint32_t)).IsOk())
return false;
2439 double minlat, minlon, maxlat, maxlon;
2440 minlat = pTP->tri_box.GetMinLat();
2441 minlon = pTP->tri_box.GetMinLon();
2442 maxlat = pTP->tri_box.GetMaxLat();
2443 maxlon = pTP->tri_box.GetMaxLon();
2445 if (!stream->Write(&minlon,
sizeof(
double)).IsOk())
return false;
2446 if (!stream->Write(&maxlon,
sizeof(
double)).IsOk())
return false;
2447 if (!stream->Write(&minlat,
sizeof(
double)).IsOk())
return false;
2448 if (!stream->Write(&maxlat,
sizeof(
double)).IsOk())
return false;
2455 if (!stream->Write(pTP->p_vertex, pTP->nVert * 2 *
sizeof(
float)).IsOk())
2462 targetCount = nEdgeVectorRecords * 3 *
sizeof(int);
2463 if (!stream->Write(pvec_buffer, targetCount).IsOk())
return false;
2466 free(contourPointCountArray);
2472 unsigned char *Osenc::getObjectVectorIndexTable(S57Reader *poReader,
2473 OGRFeature *pFeature,
2479 int nEdgeVectorRecords;
2480 OGRFeature *pEdgeVectorRecordFeature;
2483 (
int *)pFeature->GetFieldAsIntegerList(
"NAME_RCID", &nEdgeVectorRecords);
2484 pORNT = (
int *)pFeature->GetFieldAsIntegerList(
"ORNT", NULL);
2486 nEntries = nEdgeVectorRecords;
2488 unsigned char *pvec_buffer =
2489 (
unsigned char *)malloc(nEdgeVectorRecords * 3 *
sizeof(
int));
2490 unsigned char *pvRun = pvec_buffer;
2493 char **papszReaderOptions = NULL;
2494 papszReaderOptions = CSLSetNameValue(papszReaderOptions, S57O_UPDATES,
"ON");
2495 papszReaderOptions =
2496 CSLSetNameValue(papszReaderOptions, S57O_RETURN_LINKAGES,
"ON");
2497 papszReaderOptions =
2498 CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
"ON");
2499 poReader->SetOptions(papszReaderOptions);
2503 for (
int i = 0; i < nEdgeVectorRecords; i++) {
2504 int *pI = (
int *)pvRun;
2506 int edge_rcid = pNAME_RCID[i];
2508 int start_rcid, end_rcid;
2509 int target_record_feid = m_vector_helper_hash[pNAME_RCID[i]];
2510 pEdgeVectorRecordFeature =
2511 poReader->ReadVector(target_record_feid, RCNM_VE);
2513 if (NULL != pEdgeVectorRecordFeature) {
2514 start_rcid = pEdgeVectorRecordFeature->GetFieldAsInteger(
"NAME_RCID_0");
2515 end_rcid = pEdgeVectorRecordFeature->GetFieldAsInteger(
"NAME_RCID_1");
2521 if (!poReader->FetchPoint(RCNM_VC, start_rcid, NULL, NULL, NULL, NULL))
2523 if (!poReader->FetchPoint(RCNM_VC, end_rcid, NULL, NULL, NULL, NULL))
2526 OGRLineString *poLS =
2527 (OGRLineString *)pEdgeVectorRecordFeature->GetGeometryRef();
2530 else if (poLS->getNumPoints() < 1)
2533 int edge_ornt = pORNT[i];
2535 if (edge_ornt == 1) {
2545 delete pEdgeVectorRecordFeature;
2555 pvRun += 3 *
sizeof(int);
2559 papszReaderOptions =
2560 CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
"OFF");
2561 poReader->SetOptions(papszReaderOptions);
2562 CSLDestroy(papszReaderOptions);
2567 void Osenc::CreateSENCVectorEdgeTableRecord200(
Osenc_outstream *stream,
2568 S57Reader *poReader) {
2570 uint8_t *pPayload = NULL;
2571 int payloadSize = 0;
2572 uint8_t *pRun = pPayload;
2575 char **papszReaderOptions = NULL;
2576 papszReaderOptions = CSLSetNameValue(papszReaderOptions, S57O_UPDATES,
"ON");
2577 papszReaderOptions =
2578 CSLSetNameValue(papszReaderOptions, S57O_RETURN_LINKAGES,
"ON");
2579 papszReaderOptions =
2580 CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
"ON");
2581 poReader->SetOptions(papszReaderOptions);
2584 OGRLineString *pLS = NULL;
2586 OGRFeature *pEdgeVectorRecordFeature = poReader->ReadVector(feid, RCNM_VE);
2591 while (NULL != pEdgeVectorRecordFeature) {
2596 if (pEdgeVectorRecordFeature->GetGeometryRef() != NULL) {
2597 pGeo = pEdgeVectorRecordFeature->GetGeometryRef();
2598 if (pGeo->getGeometryType() == wkbLineString) {
2599 pLS = (OGRLineString *)pGeo;
2600 nPoints = pLS->getNumPoints();
2606 int new_size = payloadSize + (2 *
sizeof(int));
2607 pPayload = (uint8_t *)realloc(pPayload, new_size);
2608 pRun = pPayload + payloadSize;
2610 payloadSize = new_size;
2613 int record_id = pEdgeVectorRecordFeature->GetFieldAsInteger(
"RCID");
2614 *(
int *)pRun = record_id;
2615 pRun +=
sizeof(int);
2622 int reduction_ratio = nPoints / MAX_VECTOR_POINTS + 1;
2623 int reduced_points = 0;
2625 double *ppd = (
double *)malloc((nPoints / reduction_ratio + 1) * 2 *
2629 for (
int i = 0; i < nPoints; i++) {
2630 if (i % reduction_ratio == 0) {
2632 pLS->getPoint(i, &p);
2635 double easting, northing;
2636 toSM(p.getY(), p.getX(), m_ref_lat, m_ref_lon, &easting, &northing);
2643 nPoints = reduced_points;
2646 std::vector<int> index_keep;
2647 if (nPoints > 5 && (m_LOD_meters > .01)) {
2648 index_keep.push_back(0);
2649 index_keep.push_back(nPoints - 1);
2651 DouglasPeucker(ppd, 0, nPoints - 1, m_LOD_meters, &index_keep);
2656 index_keep.resize(nPoints);
2657 for (
int i = 0; i < nPoints; i++) index_keep[i] = i;
2661 int nPointReduced = index_keep.size();
2662 *(
int *)pRun = nPointReduced;
2663 pRun +=
sizeof(int);
2668 int new_size_red = payloadSize + (nPointReduced * 2 *
sizeof(float));
2669 pPayload = (uint8_t *)realloc(pPayload, new_size_red);
2670 pRun = pPayload + payloadSize;
2672 payloadSize = new_size_red;
2674 float *npp = (
float *)pRun;
2675 float *npp_run = npp;
2677 for (
int ip = 0; ip < nPoints; ip++) {
2681 for (
unsigned int j = 0; j < index_keep.size(); j++) {
2682 if (index_keep[j] == ip) {
2685 pRun += 2 *
sizeof(float);
2698 delete pEdgeVectorRecordFeature;
2699 pEdgeVectorRecordFeature = poReader->ReadVector(feid, RCNM_VE);
2708 record.record_type = VECTOR_EDGE_NODE_TABLE_RECORD;
2709 record.record_length =
2716 stream->Write(&nFeatures,
sizeof(uint32_t));
2719 stream->Write(pPayload, payloadSize);
2725 papszReaderOptions =
2726 CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
"OFF");
2727 poReader->SetOptions(papszReaderOptions);
2728 CSLDestroy(papszReaderOptions);
2731 void Osenc::CreateSENCVectorConnectedTableRecord200(
Osenc_outstream *stream,
2732 S57Reader *poReader) {
2734 uint8_t *pPayload = NULL;
2735 int payloadSize = 0;
2736 uint8_t *pRun = pPayload;
2739 char **papszReaderOptions = NULL;
2740 papszReaderOptions = CSLSetNameValue(papszReaderOptions, S57O_UPDATES,
"ON");
2741 papszReaderOptions =
2742 CSLSetNameValue(papszReaderOptions, S57O_RETURN_LINKAGES,
"ON");
2743 papszReaderOptions =
2744 CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
"ON");
2745 poReader->SetOptions(papszReaderOptions);
2750 OGRFeature *pConnNodeRecordFeature = poReader->ReadVector(feid, RCNM_VC);
2751 int featureCount = 0;
2754 while (NULL != pConnNodeRecordFeature) {
2755 if (pConnNodeRecordFeature->GetGeometryRef() != NULL) {
2756 pGeo = pConnNodeRecordFeature->GetGeometryRef();
2757 if (pGeo->getGeometryType() == wkbPoint) {
2758 int new_size = payloadSize +
sizeof(int) + (2 *
sizeof(
float));
2759 pPayload = (uint8_t *)realloc(pPayload, new_size);
2760 pRun = pPayload + payloadSize;
2762 payloadSize = new_size;
2765 int record_id = pConnNodeRecordFeature->GetFieldAsInteger(
"RCID");
2766 *(
int *)pRun = record_id;
2767 pRun +=
sizeof(int);
2769 pP = (OGRPoint *)pGeo;
2772 double easting, northing;
2773 toSM(pP->getY(), pP->getX(), m_ref_lat, m_ref_lon, &easting, &northing);
2779 float *ps = (
float *)pRun;
2789 delete pConnNodeRecordFeature;
2790 pConnNodeRecordFeature = poReader->ReadVector(feid, RCNM_VC);
2799 record.record_type = VECTOR_CONNECTED_NODE_TABLE_RECORD;
2800 record.record_length =
2807 stream->Write(&featureCount,
sizeof(uint32_t));
2810 stream->Write(pPayload, payloadSize);
2817 papszReaderOptions =
2818 CSLSetNameValue(papszReaderOptions, S57O_RETURN_PRIMITIVES,
"OFF");
2819 poReader->SetOptions(papszReaderOptions);
2820 CSLDestroy(papszReaderOptions);
2823 bool Osenc::CreateSENCRecord200(OGRFeature *pFeature,
Osenc_outstream *stream,
2824 int mode, S57Reader *poReader) {
2832 OGRFeatureDefn *pFD = pFeature->GetDefnRef();
2833 int nOBJL = pFD->GetOBJL();
2835 OGRGeometry *pGeo = pFeature->GetGeometryRef();
2836 OGRwkbGeometryType gType = pGeo->getGeometryType();
2841 primitive = GEO_LINE;
2844 primitive = GEO_POINT;
2847 primitive = GEO_AREA;
2853 if (!WriteFIDRecord200(stream, nOBJL, pFeature->GetFID(), primitive))
2856 #define MAX_HDR_LINE 400
2872 if (pFeature->GetFID() == 290)
int yyp = 4;
2874 int payloadLength = 0;
2875 void *payloadBuffer = NULL;
2876 unsigned int payloadBufferLength = 0;
2878 for (
int iField = 0; iField < pFeature->GetFieldCount(); iField++) {
2879 if (pFeature->IsFieldSet(iField)) {
2880 if ((iField == 1) || (iField > 7)) {
2881 OGRFieldDefn *poFDefn = pFeature->GetDefnRef()->GetFieldDefn(iField);
2884 const char *pAttrName = poFDefn->GetNameRef();
2885 const char *pAttrVal = pFeature->GetFieldAsString(iField);
2890 int attributeID = m_pRegistrarMan->getAttributeID(pAttrName);
2893 int OGRvalueType = (int)poFDefn->GetType();
2897 if (-1 == attributeID) {
2898 if (!strncmp(pAttrName,
"PRIM", 4)) {
2899 attributeID = ATTRIBUTE_ID_PRIM;
2903 #if 0 OFTInteger = 0, OFTIntegerList = 1, OFTReal = 2, OFTRealList = 3, OFTString = 4, OFTStringList = 5, OFTWideString = 6, OFTWideStringList = 7, OFTBinary = 8
2914 switch (OGRvalueType) {
2917 valueType = OGRvalueType;
2919 if (payloadBufferLength < 4) {
2920 payloadBuffer = realloc(payloadBuffer, 4);
2921 payloadBufferLength = 4;
2924 int aValue = pFeature->GetFieldAsInteger(iField);
2925 memcpy(payloadBuffer, &aValue,
sizeof(
int));
2926 payloadLength =
sizeof(int);
2932 valueType = OGRvalueType;
2935 const int *aValueList =
2936 pFeature->GetFieldAsIntegerList(iField, &nCount);
2938 if (payloadBufferLength < nCount *
sizeof(
int)) {
2939 payloadBuffer = realloc(payloadBuffer, nCount *
sizeof(
int));
2940 payloadBufferLength = nCount *
sizeof(int);
2943 int *pBuffRun = (
int *)payloadBuffer;
2944 for (
int i = 0; i < nCount; i++) {
2945 *pBuffRun++ = aValueList[i];
2947 payloadLength = nCount *
sizeof(int);
2953 valueType = OGRvalueType;
2955 if (payloadBufferLength <
sizeof(
double)) {
2956 payloadBuffer = realloc(payloadBuffer,
sizeof(
double));
2957 payloadBufferLength =
sizeof(double);
2960 double aValue = pFeature->GetFieldAsDouble(iField);
2961 memcpy(payloadBuffer, &aValue,
sizeof(
double));
2962 payloadLength =
sizeof(double);
2969 valueType = OGRvalueType;
2972 const double *aValueList =
2973 pFeature->GetFieldAsDoubleList(iField, &nCount);
2975 if (payloadBufferLength < nCount *
sizeof(
double)) {
2976 payloadBuffer = realloc(payloadBuffer, nCount *
sizeof(
double));
2977 payloadBufferLength = nCount *
sizeof(double);
2980 double *pBuffRun = (
double *)payloadBuffer;
2981 for (
int i = 0; i < nCount; i++) {
2982 *pBuffRun++ = aValueList[i];
2984 payloadLength = nCount *
sizeof(double);
2991 valueType = OGRvalueType;
2992 const char *pAttrVal = pFeature->GetFieldAsString(iField);
2994 wxString wxAttrValue;
2996 if ((0 == strncmp(
"NOBJNM", pAttrName, 6)) ||
2997 (0 == strncmp(
"NINFOM", pAttrName, 6)) ||
2998 (0 == strncmp(
"NPLDST", pAttrName, 6)) ||
2999 (0 == strncmp(
"NTXTDS", pAttrName, 6))) {
3000 if (poReader->GetNall() ==
3003 wxString att_conv(pAttrVal, conv);
3004 att_conv.RemoveLast();
3006 att_conv.Replace(_T(
"\n"),
3009 wxAttrValue = att_conv;
3010 }
else if (poReader->GetNall() ==
3012 wxCSConv conv(_T(
"iso8859-1"));
3013 wxString att_conv(pAttrVal, conv);
3014 wxAttrValue = att_conv;
3017 if (poReader->GetAall() ==
3020 wxCSConv conv(_T(
"iso8859-1"));
3021 wxString att_conv(pAttrVal, conv);
3022 wxAttrValue = att_conv;
3029 unsigned int stringPayloadLength = 0;
3031 wxCharBuffer buffer;
3032 if (wxAttrValue.Length()) {
3033 buffer = wxAttrValue.ToUTF8();
3034 pAttrVal = buffer.data();
3035 stringPayloadLength = strlen(buffer.data());
3038 if (stringPayloadLength) {
3039 if (payloadBufferLength < stringPayloadLength + 1) {
3040 payloadBuffer = realloc(payloadBuffer, stringPayloadLength + 1);
3041 payloadBufferLength = stringPayloadLength + 1;
3044 strcpy((
char *)payloadBuffer, pAttrVal);
3045 payloadLength = stringPayloadLength + 1;
3057 if (-1 != attributeID) {
3063 unsigned char *pBuffer = getBuffer(recordLength);
3067 pRecord->record_type = FEATURE_ATTRIBUTE_RECORD;
3068 pRecord->record_length = recordLength;
3069 pRecord->attribute_type = attributeID;
3070 pRecord->attribute_value_type = valueType;
3071 memcpy(&pRecord->payload, payloadBuffer, payloadLength);
3074 size_t targetCount = recordLength;
3075 if (!stream->Write(pBuffer, targetCount).IsOk()) {
3076 free(payloadBuffer);
3083 if (wkbPoint == pGeo->getGeometryType()) {
3084 OGRPoint *pp = (OGRPoint *)pGeo;
3085 int nqual = pp->getnQual();
3088 int attributeID = m_pRegistrarMan->getAttributeID(
"QUAPOS");
3090 if (-1 != attributeID) {
3091 if (payloadBufferLength < 4) {
3092 payloadBuffer = realloc(payloadBuffer, 4);
3093 payloadBufferLength = 4;
3096 memcpy(payloadBuffer, &nqual,
sizeof(
int));
3097 payloadLength =
sizeof(int);
3102 unsigned char *pBuffer = getBuffer(recordLength);
3106 pRecord->record_type = FEATURE_ATTRIBUTE_RECORD;
3107 pRecord->record_length = recordLength;
3108 pRecord->attribute_type = attributeID;
3109 pRecord->attribute_value_type = valueType;
3110 memcpy(&pRecord->payload, payloadBuffer, payloadLength);
3113 size_t targetCount = recordLength;
3114 if (!stream->Write(pBuffer, targetCount).IsOk()) {
3115 free(payloadBuffer);
3122 free(payloadBuffer);
3127 if( wkbPoint == pGeo->getGeometryType() ) {
3128 OGRPoint *pp = (OGRPoint *) pGeo;
3129 int nqual = pp->getnQual();
3132 snprintf( line, MAX_HDR_LINE - 2,
" %s (%c) = %d",
"QUALTY",
'I', nqual );
3133 sheader += wxString( line, wxConvUTF8 );
3140 sprintf( line,
" %s %f %f\n", pGeo->getGeometryName(), m_ref_lat, m_ref_lon );
3141 sheader += wxString( line, wxConvUTF8 );
3144 wxCharBuffer buffer=sheader.ToUTF8();
3145 fprintf( fpOut,
"HDRLEN=%lu\n", (
unsigned long) strlen(buffer) );
3146 fwrite( buffer.data(), 1, strlen(buffer), fpOut );
3150 if ((pGeo != NULL)) {
3153 OGRwkbGeometryType gType = pGeo->getGeometryType();
3155 case wkbLineString: {
3156 if (!CreateLineFeatureGeometryRecord200(poReader, pFeature, stream))
3164 record.record_type = FEATURE_GEOMETRY_RECORD_POINT;
3165 record.record_length =
sizeof(record);
3167 int wkb_len = pGeo->WkbSize();
3168 unsigned char *pwkb_buffer = (
unsigned char *)malloc(wkb_len);
3171 pGeo->exportToWkb(wkbNDR, pwkb_buffer);
3174 unsigned char *ps = pwkb_buffer;
3177 double *psd = (
double *)ps;
3181 __attribute__((aligned(16))) double lata, lona;
3182 unsigned char *pucsd = (
unsigned char *)psd;
3184 memcpy(&lona, pucsd, sizeof(
double));
3185 pucsd += sizeof(
double);
3186 memcpy(&lata, pucsd, sizeof(
double));
3200 size_t targetCount = record.record_length;
3201 if (!stream->Write(&record, targetCount).IsOk())
return false;
3207 case wkbMultiPoint25D: {
3208 if (!CreateMultiPointFeatureGeometryRecord200(pFeature, stream))
3216 if (!CreateAreaFeatureGeometryRecord200(poReader, pFeature, stream))
3224 msg = _T(
" Warning: Unimplemented ogr geotype record ");
3237 unsigned char **next_byte) {
3238 PolyTessGeo *pPTG =
new PolyTessGeo();
3240 pPTG->SetExtents(record->extent_w_lon, record->extent_s_lat,
3241 record->extent_e_lon, record->extent_n_lat);
3243 unsigned int n_TriPrim = record->triprim_count;
3244 int nContours = record->contour_count;
3247 void *payLoad = &record->payLoad;
3253 PolyTriGroup *ppg =
new PolyTriGroup;
3254 ppg->m_bSMSENC =
true;
3255 ppg->data_type = DATA_TYPE_DOUBLE;
3257 ppg->nContours = nContours;
3259 ppg->pn_vertex = (
int *)malloc(nContours *
sizeof(
int));
3260 int *pctr = ppg->pn_vertex;
3263 int *contour_pointcount_array_run = (
int *)payLoad;
3264 for (
int i = 0; i < nContours; i++) {
3265 *pctr++ = *contour_pointcount_array_run++;
3269 ppg->pgroup_geom = NULL;
3273 TriPrim **p_prev_triprim = &(ppg->tri_prim_head);
3276 unsigned int tri_type;
3279 int total_byte_size = 2 *
sizeof(float);
3281 uint8_t *pPayloadRun =
3282 (uint8_t *)contour_pointcount_array_run;
3285 for (
unsigned int i = 0; i < n_TriPrim; i++) {
3286 tri_type = *pPayloadRun++;
3287 nvert = *(uint32_t *)pPayloadRun;
3288 pPayloadRun +=
sizeof(uint32_t);
3290 TriPrim *tp =
new TriPrim;
3291 *p_prev_triprim = tp;
3292 p_prev_triprim = &(tp->p_next);
3295 tp->type = tri_type;
3299 wxMax(nvert_max, nvert);
3302 double *pbb = (
double *)pPayloadRun;
3304 double minxt, minyt, maxxt, maxyt;
3307 double __attribute__((aligned(16))) abox[4];
3308 unsigned char *pucbb = (
unsigned char *)pPayloadRun;
3309 memcpy(&abox[0], pucbb, 4 * sizeof(
double));
3322 tp->tri_box.Set(minyt, minxt, maxyt, maxxt);
3324 pPayloadRun += 4 *
sizeof(double);
3326 int byte_size = nvert * 2 *
sizeof(float);
3327 total_byte_size += byte_size;
3329 tp->p_vertex = (
double *)pPayloadRun;
3331 pPayloadRun += byte_size;
3334 if (next_byte) *next_byte = pPayloadRun;
3338 unsigned char *vbuf = (
unsigned char *)malloc(total_byte_size);
3340 TriPrim *p_tp = ppg->tri_prim_head;
3341 unsigned char *p_run = vbuf;
3343 memcpy(p_run, p_tp->p_vertex, p_tp->nVert * 2 *
sizeof(
float));
3344 p_tp->p_vertex = (
double *)p_run;
3345 p_run += p_tp->nVert * 2 *
sizeof(float);
3346 p_tp = p_tp->p_next;
3348 ppg->bsingle_alloc =
true;
3349 ppg->single_buffer = vbuf;
3350 ppg->single_buffer_size = total_byte_size;
3351 ppg->data_type = DATA_TYPE_FLOAT;
3353 pPTG->SetPPGHead(ppg);
3354 pPTG->SetnVertexMax(nvert_max);
3361 bool Osenc::CreateCOVRTables(S57Reader *poReader,
3362 S57ClassRegistrar *poRegistrar) {
3367 float LatMax, LatMin, LonMax, LonMin;
3373 m_pCOVRTablePoints = NULL;
3374 m_pCOVRTable = NULL;
3377 MyFloatPtrArray *pAuxPtrArray =
new MyFloatPtrArray;
3378 std::vector<int> auxCntArray, noCovrCntArray;
3380 MyFloatPtrArray *pNoCovrPtrArray =
new MyFloatPtrArray;
3383 pFeat = GetChartFirstM_COVR(catcov, poReader, poRegistrar);
3388 OGRPolygon *poly = (OGRPolygon *)(pFeat->GetGeometryRef());
3389 OGRLinearRing *xring = poly->getExteriorRing();
3391 int npt = xring->getNumPoints();
3396 pf = (
float *)malloc(2 * npt *
sizeof(
float));
3399 for (
int i = 0; i < npt; i++) {
3401 xring->getPoint(i, &p);
3404 LatMax = fmax(LatMax, p.getY());
3405 LatMin = fmin(LatMin, p.getY());
3406 LonMax = fmax(LonMax, p.getX());
3407 LonMin = fmin(LonMin, p.getX());
3417 pAuxPtrArray->Add(pf);
3418 auxCntArray.push_back(npt);
3419 }
else if (catcov == 2) {
3420 pNoCovrPtrArray->Add(pf);
3421 noCovrCntArray.push_back(npt);
3427 pFeat = GetChartNextM_COVR(catcov, poReader);
3432 m_nCOVREntries = auxCntArray.size();
3437 if (m_nCOVREntries == 1) {
3438 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
3439 *m_pCOVRTablePoints = auxCntArray[0];
3440 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
3441 *m_pCOVRTable = (
float *)malloc(auxCntArray[0] * 2 *
sizeof(
float));
3442 memcpy(*m_pCOVRTable, pAuxPtrArray->Item(0),
3443 auxCntArray[0] * 2 *
sizeof(
float));
3446 else if (m_nCOVREntries > 1) {
3448 m_pCOVRTablePoints = (
int *)malloc(m_nCOVREntries *
sizeof(
int));
3449 m_pCOVRTable = (
float **)malloc(m_nCOVREntries *
sizeof(
float *));
3451 for (
unsigned int j = 0; j < (
unsigned int)m_nCOVREntries; j++) {
3452 m_pCOVRTablePoints[j] = auxCntArray[j];
3453 m_pCOVRTable[j] = (
float *)malloc(auxCntArray[j] * 2 *
sizeof(
float));
3454 memcpy(m_pCOVRTable[j], pAuxPtrArray->Item(j),
3455 auxCntArray[j] * 2 *
sizeof(
float));
3461 wxString msg(_T(
" ENC contains no useable M_COVR, CATCOV=1 features: "));
3462 msg.Append(m_FullPath000);
3467 m_nNoCOVREntries = noCovrCntArray.size();
3469 if (m_nNoCOVREntries) {
3471 m_pNoCOVRTablePoints = (
int *)malloc(m_nNoCOVREntries *
sizeof(
int));
3472 m_pNoCOVRTable = (
float **)malloc(m_nNoCOVREntries *
sizeof(
float *));
3474 for (
unsigned int j = 0; j < (
unsigned int)m_nNoCOVREntries; j++) {
3475 int npoints = noCovrCntArray[j];
3476 m_pNoCOVRTablePoints[j] = npoints;
3477 m_pNoCOVRTable[j] = (
float *)malloc(npoints * 2 *
sizeof(
float));
3478 memcpy(m_pNoCOVRTable[j], pNoCovrPtrArray->Item(j),
3479 npoints * 2 *
sizeof(
float));
3482 m_pNoCOVRTablePoints = NULL;
3483 m_pNoCOVRTable = NULL;
3486 for (
unsigned int j = 0; j < (
unsigned int)m_nNoCOVREntries; j++)
3487 free(pNoCovrPtrArray->Item(j));
3488 for (
unsigned int j = 0; j < (
unsigned int)m_nCOVREntries; j++)
3489 free(pAuxPtrArray->Item(j));
3491 delete pAuxPtrArray;
3492 delete pNoCovrPtrArray;
3494 if (0 == m_nCOVREntries) {
3495 wxString msg(_T(
" ENC contains no M_COVR features: "));
3496 msg.Append(m_FullPath000);
3499 msg = _T(
" Calculating Chart Extents as fallback.");
3504 if (poReader->GetExtent(&Env,
true) == OGRERR_NONE) {
3511 m_pCOVRTablePoints = (
int *)malloc(
sizeof(
int));
3512 *m_pCOVRTablePoints = 4;
3513 m_pCOVRTable = (
float **)malloc(
sizeof(
float *));
3514 float *pf = (
float *)malloc(2 * 4 *
sizeof(
float));
3531 wxString msg(_T(
" Cannot calculate Extents for ENC: "));
3532 msg.Append(m_FullPath000);
3540 m_extent.NLAT = LatMax;
3541 m_extent.SLAT = LatMin;
3542 m_extent.ELON = LonMax;
3543 m_extent.WLON = LonMin;
3548 OGRFeature *Osenc::GetChartFirstM_COVR(
int &catcov, S57Reader *pENCReader,
3549 S57ClassRegistrar *poRegistrar) {
3550 OGRFeature *rv = NULL;
3552 if ((NULL != pENCReader) && (NULL != poRegistrar)) {
3554 poRegistrar->SelectClass(
"M_COVR");
3560 bool bFound =
false;
3561 OGRFeature *pobjectDef = pENCReader->ReadNextFeature();
3564 OGRFeatureDefn *poDefn = pobjectDef->GetDefnRef();
3565 if (poDefn && (poDefn->GetOBJL() == 302 )) {
3567 catcov = pobjectDef->GetFieldAsInteger(
"CATCOV");
3575 pobjectDef = pENCReader->ReadNextFeature();
3582 OGRFeature *Osenc::GetChartNextM_COVR(
int &catcov, S57Reader *pENCReader) {
3586 bool bFound =
false;
3587 OGRFeature *pobjectDef = pENCReader->ReadNextFeature();
3591 OGRFeatureDefn *poDefn = pobjectDef->GetDefnRef();
3592 if (poDefn && (poDefn->GetOBJL() == 302)) {
3594 catcov = pobjectDef->GetFieldAsInteger(
"CATCOV");
3602 pobjectDef = pENCReader->ReadNextFeature();
3609 int Osenc::GetBaseFileInfo(
const wxString &FullPath000,
3610 const wxString &SENCFileName) {
3611 wxFileName SENCfile = wxFileName(SENCFileName);
3615 if (!GetBaseFileAttr(FullPath000)) {
3616 return ERROR_BASEFILE_ATTRIBUTES;
3619 OGRS57DataSource oS57DS;
3620 oS57DS.SetS57Registrar(m_poRegistrar);
3622 bool b_current_debug = g_bGDAL_Debug;
3623 g_bGDAL_Debug =
false;
3627 if (ingestCell(&oS57DS, FullPath000, SENCfile.GetPath())) {
3628 errorMessage = _T(
"Error ingesting: ") + FullPath000;
3629 return ERROR_INGESTING000;
3632 S57Reader *poReader = oS57DS.GetModule(0);
3634 CalculateExtent(poReader, m_poRegistrar);
3636 g_bGDAL_Debug = b_current_debug;
3640 return SENC_NO_ERROR;
3643 bool Osenc::CalculateExtent(S57Reader *poReader,
3644 S57ClassRegistrar *poRegistrar) {
3649 float LatMax, LatMin, LonMax, LonMin;
3655 m_pCOVRTablePoints = NULL;
3656 m_pCOVRTable = NULL;
3666 pFeat = GetChartFirstM_COVR(catcov, poReader, poRegistrar);
3671 OGRPolygon *poly = (OGRPolygon *)(pFeat->GetGeometryRef());
3672 OGRLinearRing *xring = poly->getExteriorRing();
3674 int npt = xring->getNumPoints();
3677 for (
int i = 0; i < npt; i++) {
3679 xring->getPoint(i, &p);
3682 LatMax = fmax(LatMax, p.getY());
3683 LatMin = fmin(LatMin, p.getY());
3684 LonMax = fmax(LonMax, p.getX());
3685 LonMin = fmin(LonMin, p.getX());
3691 pFeat = GetChartNextM_COVR(catcov, poReader);
3695 m_extent.NLAT = LatMax;
3696 m_extent.SLAT = LatMin;
3697 m_extent.ELON = LonMax;
3698 m_extent.WLON = LonMin;
3703 void Osenc::InitializePersistentBuffer(
void) {
3704 pBuffer = (
unsigned char *)malloc(1024);
3708 unsigned char *Osenc::getBuffer(
size_t length) {
3709 if (length > bufferSize) {
3710 pBuffer = (
unsigned char *)realloc(pBuffer, length * 2);
3711 bufferSize = length * 2;
General purpose GUI support.