34#include "gdal/ogr_api.h"
35#include "gdal/cpl_conv.h"
36#include "gdal/cpl_string.h"
43S57Reader::S57Reader(
const char *pszFilename)
46 pszModuleName = CPLStrdup(pszFilename);
58 bFileIngested = FALSE;
71 nOptionFlags = S57M_UPDATES;
73 bMissingWarningIssued = FALSE;
74 bAttrWarningIssued = FALSE;
84S57Reader::~S57Reader()
89 CPLFree(pszModuleName);
90 CSLDestroy(papszOptions);
92 CPLFree(papoFDefnList);
99int S57Reader::Open(
int bTestOpen)
102 if (poModule != NULL) {
107 poModule =
new DDFModule();
108 if (!poModule->Open(pszModuleName)) {
116 if (poModule->FindFieldDefn(
"DSID") == NULL) {
118 CPLError(CE_Failure, CPLE_AppDefined,
119 "%s is an ISO8211 file, but not an S-57 data file.\n",
128 DDFFieldDefn *poFSPT = poModule->FindFieldDefn(
"FSPT");
129 if (poFSPT != NULL && !poFSPT->IsRepeating()) {
130 CPLDebug(
"S57",
"Forcing FSPT field to be repeating.");
131 poFSPT->SetRepeatingFlag(TRUE);
147void S57Reader::Close()
150 if (poModule != NULL) {
157 ClearPendingMultiPoint();
162 bFileIngested = FALSE;
175void S57Reader::ClearPendingMultiPoint()
178 if (poMultiPoint != NULL) {
188OGRFeature *S57Reader::NextPendingMultiPoint()
191 CPLAssert(poMultiPoint != NULL);
192 CPLAssert(wkbFlatten(poMultiPoint->GetGeometryRef()->getGeometryType()) ==
195 OGRFeatureDefn *poDefn = poMultiPoint->GetDefnRef();
196 OGRFeature *poPoint =
new OGRFeature(poDefn);
197 OGRMultiPoint *poMPGeom = (OGRMultiPoint *)poMultiPoint->GetGeometryRef();
198 OGRPoint *poSrcPoint;
200 poPoint->SetFID(poMultiPoint->GetFID());
202 for (
int i = 0; i < poDefn->GetFieldCount(); i++) {
203 poPoint->SetField(i, poMultiPoint->GetRawFieldRef(i));
206 poSrcPoint = (OGRPoint *)poMPGeom->getGeometryRef(iPointOffset++);
207 poPoint->SetGeometry(poSrcPoint);
209 poPoint->SetField(
"DEPTH", poSrcPoint->getZ());
211 if (iPointOffset >= poMPGeom->getNumGeometries()) ClearPendingMultiPoint();
220void S57Reader::SetOptions(
char **papszOptionsIn)
223 const char *pszOptionValue;
225 CSLDestroy(papszOptions);
226 papszOptions = CSLDuplicate(papszOptionsIn);
228 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_SPLIT_MULTIPOINT);
229 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
230 nOptionFlags |= S57M_SPLIT_MULTIPOINT;
232 nOptionFlags &= ~S57M_SPLIT_MULTIPOINT;
234 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_ADD_SOUNDG_DEPTH);
235 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
236 nOptionFlags |= S57M_ADD_SOUNDG_DEPTH;
238 nOptionFlags &= ~S57M_ADD_SOUNDG_DEPTH;
240 CPLAssert(!(nOptionFlags & S57M_ADD_SOUNDG_DEPTH) ||
241 (nOptionFlags & S57M_SPLIT_MULTIPOINT));
243 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_LNAM_REFS);
244 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
245 nOptionFlags |= S57M_LNAM_REFS;
247 nOptionFlags &= ~S57M_LNAM_REFS;
249 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_UPDATES);
250 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
251 nOptionFlags |= S57M_UPDATES;
253 nOptionFlags &= ~S57M_UPDATES;
255 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_PRESERVE_EMPTY_NUMBERS);
256 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
257 nOptionFlags |= S57M_PRESERVE_EMPTY_NUMBERS;
259 nOptionFlags &= ~S57M_PRESERVE_EMPTY_NUMBERS;
261 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_RETURN_PRIMITIVES);
262 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
263 nOptionFlags |= S57M_RETURN_PRIMITIVES;
265 nOptionFlags &= ~S57M_RETURN_PRIMITIVES;
267 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_RETURN_LINKAGES);
268 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
269 nOptionFlags |= S57M_RETURN_LINKAGES;
271 nOptionFlags &= ~S57M_RETURN_LINKAGES;
288void S57Reader::Rewind()
291 ClearPendingMultiPoint();
306int S57Reader::Ingest(CallBackFunction pcallback) {
309 CPLSetConfigOption(
"CPL_DEBUG",
"S57");
311 if (poModule == NULL || bFileIngested)
return 0;
317 while ((poRecord = poModule->ReadRecord()) != NULL) {
319 if (!(*pcallback)())
return 0;
322 DDFField *poKeyField = poRecord->GetField(1);
323 const char *pszname = poKeyField->GetFieldDefn()->GetName();
325 if (EQUAL(pszname,
"VRID")) {
327 int nRCNM = poRecord->GetIntSubfield(
"VRID",0,
"RCNM",0);
328 int nRCID = poRecord->GetIntSubfield(
"VRID",0,
"RCID",0);
330 int nRCNM = 0, nRCID = 0;
331 DDFField *poField = poRecord->FindField(
"VRID", 0);
334 DDFSubfieldDefn *poSFDefn;
335 poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn(
"RCNM");
337 const char *pachData =
338 poField->GetSubfieldData(poSFDefn, &nBytesRemaining, 0);
339 nRCNM = poSFDefn->ExtractIntData(pachData, nBytesRemaining, NULL);
342 poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn(
"RCID");
344 const char *pachData =
345 poField->GetSubfieldData(poSFDefn, &nBytesRemaining, 0);
346 nRCID = poSFDefn->ExtractIntData(pachData, nBytesRemaining, NULL);
353 oVI_Index.AddRecord(nRCID, poRecord->Copy());
357 oVC_Index.AddRecord(nRCID, poRecord->Copy());
361 oVE_Index.AddRecord(nRCID, poRecord->Copy());
365 oVF_Index.AddRecord(nRCID, poRecord->Copy());
376 else if (EQUAL(pszname,
"FRID")) {
380 int nRCID = poRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0);
381 oFE_Index.AddRecord(nRCID, poRecord->Copy());
386 else if (EQUAL(pszname,
"DSPM")) {
387 nCOMF = MAX(1, poRecord->GetIntSubfield(
"DSPM", 0,
"COMF", 0));
388 nSOMF = MAX(1, poRecord->GetIntSubfield(
"DSPM", 0,
"SOMF", 0));
389 nCSCL = MAX(1, poRecord->GetIntSubfield(
"DSPM", 0,
"CSCL", 0));
393 else if (EQUAL(pszname,
"DSID")) {
395 pszDSNM = CPLStrdup(poRecord->GetStringSubfield(
"DSID", 0,
"DSNM", 0));
396 Nall = poRecord->GetIntSubfield(
"DSSI", 0,
"NALL", 0);
397 Aall = poRecord->GetIntSubfield(
"DSSI", 0,
"AALL", 0);
401 CPLDebug(
"S57",
"Skipping %s record in S57Reader::Ingest().\n",
402 poKeyField->GetFieldDefn()->GetName());
406 bFileIngested = TRUE;
411 int update_return = 0;
412 if (nOptionFlags & S57M_UPDATES) update_return = FindAndApplyUpdates();
414 return update_return;
421void S57Reader::SetNextFEIndex(
int nNewIndex,
int nRCNM)
424 if (nRCNM == RCNM_VI)
425 nNextVIIndex = nNewIndex;
426 else if (nRCNM == RCNM_VC)
427 nNextVCIndex = nNewIndex;
428 else if (nRCNM == RCNM_VE)
429 nNextVEIndex = nNewIndex;
430 else if (nRCNM == RCNM_VF)
431 nNextVFIndex = nNewIndex;
433 if (nNextFEIndex != nNewIndex) ClearPendingMultiPoint();
435 nNextFEIndex = nNewIndex;
443int S57Reader::GetNextFEIndex(
int nRCNM)
446 if (nRCNM == RCNM_VI)
448 else if (nRCNM == RCNM_VC)
450 else if (nRCNM == RCNM_VE)
452 else if (nRCNM == RCNM_VF)
462OGRFeature *S57Reader::ReadNextFeature(OGRFeatureDefn *poTarget)
465 if (!bFileIngested) Ingest();
470 if (poMultiPoint != NULL) {
471 if (poTarget == NULL || poTarget == poMultiPoint->GetDefnRef()) {
472 return NextPendingMultiPoint();
474 ClearPendingMultiPoint();
481 if (nOptionFlags & S57M_RETURN_PRIMITIVES) {
483 int *pnCounter = NULL;
485 if (poTarget == NULL) {
486 if (nNextVIIndex < oVI_Index.GetCount()) {
488 pnCounter = &nNextVIIndex;
489 }
else if (nNextVCIndex < oVC_Index.GetCount()) {
491 pnCounter = &nNextVCIndex;
492 }
else if (nNextVEIndex < oVE_Index.GetCount()) {
494 pnCounter = &nNextVEIndex;
495 }
else if (nNextVFIndex < oVF_Index.GetCount()) {
497 pnCounter = &nNextVFIndex;
500 if (EQUAL(poTarget->GetName(), OGRN_VI)) {
502 pnCounter = &nNextVIIndex;
503 }
else if (EQUAL(poTarget->GetName(), OGRN_VC)) {
505 pnCounter = &nNextVCIndex;
506 }
else if (EQUAL(poTarget->GetName(), OGRN_VE)) {
508 pnCounter = &nNextVEIndex;
509 }
else if (EQUAL(poTarget->GetName(), OGRN_VF)) {
511 pnCounter = &nNextVFIndex;
516 OGRFeature *poFeature = ReadVector(*pnCounter, nRCNM);
517 if (poFeature != NULL) {
527 while (nNextFEIndex < oFE_Index.GetCount()) {
528 OGRFeature *poFeature;
530 poFeature = ReadFeature(nNextFEIndex++, poTarget);
531 if (poFeature != NULL) {
532 if ((nOptionFlags & S57M_SPLIT_MULTIPOINT) &&
533 poFeature->GetGeometryRef() != NULL &&
534 wkbFlatten(poFeature->GetGeometryRef()->getGeometryType()) ==
536 poMultiPoint = poFeature;
538 return NextPendingMultiPoint();
578OGRFeature *S57Reader::ReadFeature(
int nFeatureId, OGRFeatureDefn *poTarget)
581 OGRFeature *poFeature;
583 if (nFeatureId < 0 || nFeatureId >= oFE_Index.GetCount())
return NULL;
585 DDFRecord *poRecord = oFE_Index.GetByIndex(nFeatureId);
588 int nRecord_OBJL = poRecord->GetIntSubfield(
"FRID", 0,
"OBJL", 0);
589 int nOBJL = poTarget->GetOBJL();
591 if (nRecord_OBJL == nOBJL)
593 poFeature = AssembleFeature(oFE_Index.GetByIndex(nFeatureId), poTarget);
595 if (poFeature != NULL) poFeature->SetFID(nFeatureId);
601 poFeature = AssembleFeature(oFE_Index.GetByIndex(nFeatureId), poTarget);
602 if (poFeature != NULL) poFeature->SetFID(nFeatureId);
614OGRFeature *S57Reader::AssembleFeature(DDFRecord *poRecord,
615 OGRFeatureDefn *poTarget)
619 OGRFeatureDefn *poFDefn;
627 poFDefn = FindFDefn(poRecord);
628 if (poFDefn == NULL) {
633 int nOBJL = poRecord->GetIntSubfield(
"FRID", 0,
"OBJL", 0);
635 S57GenerateObjectClassDefn(poRegistrar, nOBJL, this->GetOptionFlags());
637 AddFeatureDefn(poFDefn);
646 if (poTarget != NULL && poFDefn != poTarget)
return NULL;
651 OGRFeature *poFeature;
653 poFeature =
new OGRFeature(poFDefn);
658 nOBJL = poRecord->GetIntSubfield(
"FRID", 0,
"OBJL", 0);
659 poFeature->SetField(
"OBJL", nOBJL);
661 poFeature->SetField(
"RCID", poRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0));
662 poFeature->SetField(
"PRIM", poRecord->GetIntSubfield(
"FRID", 0,
"PRIM", 0));
663 poFeature->SetField(
"GRUP", poRecord->GetIntSubfield(
"FRID", 0,
"GRUP", 0));
664 poFeature->SetField(
"RVER", poRecord->GetIntSubfield(
"FRID", 0,
"RVER", 0));
665 poFeature->SetField(
"AGEN", poRecord->GetIntSubfield(
"FOID", 0,
"AGEN", 0));
666 poFeature->SetField(
"FIDN", poRecord->GetIntSubfield(
"FOID", 0,
"FIDN", 0));
667 poFeature->SetField(
"FIDS", poRecord->GetIntSubfield(
"FOID", 0,
"FIDS", 0));
672 if (nOptionFlags & S57M_LNAM_REFS) {
673 GenerateLNAMAndRefs(poRecord, poFeature);
679 if (nOptionFlags & S57M_RETURN_LINKAGES)
680 GenerateFSPTAttributes(poRecord, poFeature);
685 if (poRegistrar != NULL) ApplyObjectClassAttributes(poRecord, poFeature);
690 nPRIM = poRecord->GetIntSubfield(
"FRID", 0,
"PRIM", 0);
692 if (nPRIM == PRIM_P) {
694 AssembleSoundingGeometry(poRecord, poFeature);
696 AssemblePointGeometry(poRecord, poFeature);
697 }
else if (nPRIM == PRIM_L) {
698 AssembleLineGeometry(poRecord, poFeature);
699 }
else if (nPRIM == PRIM_A) {
700 AssembleAreaGeometry(poRecord, poFeature);
710void S57Reader::ApplyObjectClassAttributes(DDFRecord *poRecord,
711 OGRFeature *poFeature)
717 DDFField *poATTF = poRecord->FindField(
"ATTF");
718 int nAttrCount, iAttr;
720 if (poATTF == NULL)
return;
722 DDFFieldDefn *poDefn = poATTF->GetFieldDefn();
724 nAttrCount = poATTF->GetRepeatCount();
725 for (iAttr = 0; iAttr < nAttrCount; iAttr++) {
726 int nAttrId = poRecord->GetIntSubfield(
"ATTF", 0,
"ATTL", iAttr);
727 const char *pszAcronym;
729 if (nAttrId < 1 || nAttrId > poRegistrar->GetMaxAttrIndex() ||
730 (pszAcronym = poRegistrar->GetAttrAcronym(nAttrId)) == NULL) {
731 if (!bAttrWarningIssued) {
732 bAttrWarningIssued = TRUE;
733 CPLError(CE_Warning, CPLE_AppDefined,
734 "Illegal feature attribute id (ATTF:ATTL[%d]) of %d\n"
735 "on feature FIDN=%d, FIDS=%d.\n"
736 "Skipping attribute, no more warnings will be issued.",
737 iAttr, nAttrId, poFeature->GetFieldAsInteger(
"FIDN"),
738 poFeature->GetFieldAsInteger(
"FIDS"));
745 const char *pszValue;
746 pszValue = poRecord->GetStringSubfield(
"ATTF", 0,
"ATVL", iAttr);
750 OGRFieldDefn *poFldDefn;
752 iField = poFeature->GetDefnRef()->GetFieldIndex(pszAcronym);
754 if (!bMissingWarningIssued) {
755 bMissingWarningIssued = TRUE;
756 CPLError(CE_Warning, CPLE_AppDefined,
757 "For feature \"%s\", attribute \"%s\" ignored, not in "
758 "expected schema.\n",
759 poFeature->GetDefnRef()->GetName(), pszAcronym);
767 if (pszValue[0] == 0x7f) {
768 poFeature->UnsetField(iField);
772 poFldDefn = poFeature->GetDefnRef()->GetFieldDefn(iField);
773 if (poFldDefn->GetType() == OFTInteger || poFldDefn->GetType() == OFTReal) {
774 if (strlen(pszValue) == 0) {
775 if (nOptionFlags & S57M_PRESERVE_EMPTY_NUMBERS) {
776 poFeature->SetField(iField, EMPTY_NUMBER_MARKER);
781 poFeature->SetField(iField, pszValue);
784 poFeature->SetField(iField, pszValue);
791 DDFField *poNATF = poRecord->FindField(
"NATF");
793 if (poNATF == NULL)
return;
795 nAttrCount = poNATF->GetRepeatCount();
796 for (iAttr = 0; iAttr < nAttrCount; iAttr++) {
797 int nAttrId = poRecord->GetIntSubfield(
"NATF", 0,
"ATTL", iAttr);
798 const char *pszAcronym;
800 if (nAttrId < 1 || nAttrId >= poRegistrar->GetMaxAttrIndex() ||
801 (pszAcronym = poRegistrar->GetAttrAcronym(nAttrId)) == NULL) {
805 static int bAttrWarningIssued = FALSE;
807 if (!bAttrWarningIssued) {
808 bAttrWarningIssued = TRUE;
809 CPLError(CE_Warning, CPLE_AppDefined,
810 "Illegal feature attribute id (NATF:ATTL[%d]) of %d\n"
811 "on feature FIDN=%d, FIDS=%d.\n"
812 "Skipping attribute, no more warnings will be issued.",
813 iAttr, nAttrId, poFeature->GetFieldAsInteger(
"FIDN"),
814 poFeature->GetFieldAsInteger(
"FIDS"));
821 if (poFeature->GetFieldIndex(pszAcronym) < 0)
continue;
823 const char *pszValue =
824 poRecord->GetStringSubfield(
"NATF", 0,
"ATVL", iAttr);
825 if (pszValue != NULL) {
837 poField = poRecord->FindField(
"NATF", 0);
839 DDFSubfieldDefn *poSFDefn;
841 poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn(
"ATVL");
844 const char *pachData =
845 poField->GetSubfieldData(poSFDefn, &max_length, iAttr);
846 nLength = poSFDefn->GetDataLength(pachData, max_length, NULL);
854 int new_len = ((nLength / 2) + 2) * 2;
855 char *aa = (
char *)calloc(new_len, 1);
856 memcpy(aa, pszValue, nLength);
858 int index = poFeature->GetFieldIndex(pszAcronym);
859 OGRField *field = poFeature->GetRawFieldRef(index);
863 poFeature->SetField(pszAcronym, pszValue);
873void S57Reader::GenerateLNAMAndRefs(DDFRecord *poRecord, OGRFeature *poFeature)
881 sprintf(szLNAM,
"%04X%08X%04X", poFeature->GetFieldAsInteger(
"AGEN"),
882 poFeature->GetFieldAsInteger(
"FIDN"),
883 poFeature->GetFieldAsInteger(
"FIDS"));
884 poFeature->SetField(
"LNAM", szLNAM);
891 poFFPT = poRecord->FindField(
"FFPT");
893 if (poFFPT == NULL)
return;
898 int nRefCount = poFFPT->GetRepeatCount();
899 DDFSubfieldDefn *poLNAM;
900 char **papszRefs = NULL;
901 int *panRIND = (
int *)CPLMalloc(
sizeof(
int) * nRefCount);
903 poLNAM = poFFPT->GetFieldDefn()->FindSubfieldDefn(
"LNAM");
904 if (poLNAM == NULL)
return;
906 for (
int iRef = 0; iRef < nRefCount; iRef++) {
907 unsigned char *pabyData;
909 pabyData = (
unsigned char *)poFFPT->GetSubfieldData(poLNAM, NULL, iRef);
911 sprintf(szLNAM,
"%02X%02X%02X%02X%02X%02X%02X%02X", pabyData[1],
913 pabyData[5], pabyData[4], pabyData[3], pabyData[2],
914 pabyData[7], pabyData[6]);
916 papszRefs = CSLAddString(papszRefs, szLNAM);
918 panRIND[iRef] = pabyData[8];
921 poFeature->SetField(
"LNAM_REFS", papszRefs);
922 CSLDestroy(papszRefs);
924 poFeature->SetField(
"FFPT_RIND", nRefCount, panRIND);
932void S57Reader::GenerateFSPTAttributes(DDFRecord *poRecord,
933 OGRFeature *poFeature)
942 poFSPT = poRecord->FindField(
"FSPT");
943 if (poFSPT == NULL)
return;
945 nCount = poFSPT->GetRepeatCount();
950 int *panORNT, *panUSAG, *panMASK, *panRCNM, *panRCID;
952 panORNT = (
int *)CPLMalloc(
sizeof(
int) * nCount);
953 panUSAG = (
int *)CPLMalloc(
sizeof(
int) * nCount);
954 panMASK = (
int *)CPLMalloc(
sizeof(
int) * nCount);
955 panRCNM = (
int *)CPLMalloc(
sizeof(
int) * nCount);
956 panRCID = (
int *)CPLMalloc(
sizeof(
int) * nCount);
961 for (i = 0; i < nCount; i++) {
962 panRCID[i] = ParseName(poFSPT, i, panRCNM + i);
963 panORNT[i] = poRecord->GetIntSubfield(
"FSPT", 0,
"ORNT", i);
964 panUSAG[i] = poRecord->GetIntSubfield(
"FSPT", 0,
"USAG", i);
965 panMASK[i] = poRecord->GetIntSubfield(
"FSPT", 0,
"MASK", i);
971 poFeature->SetField(
"NAME_RCNM", nCount, panRCNM);
972 poFeature->SetField(
"NAME_RCID", nCount, panRCID);
973 poFeature->SetField(
"ORNT", nCount, panORNT);
974 poFeature->SetField(
"USAG", nCount, panUSAG);
975 poFeature->SetField(
"MASK", nCount, panMASK);
994OGRFeature *S57Reader::ReadVector(
int nFeatureId,
int nRCNM)
998 const char *pszFDName = NULL;
1005 poIndex = &oVI_Index;
1006 pszFDName = OGRN_VI;
1010 poIndex = &oVC_Index;
1011 pszFDName = OGRN_VC;
1015 poIndex = &oVE_Index;
1016 pszFDName = OGRN_VE;
1020 poIndex = &oVF_Index;
1021 pszFDName = OGRN_VF;
1029 if (nFeatureId < 0 || nFeatureId >= poIndex->GetCount())
return NULL;
1031 DDFRecord *poRecord = poIndex->GetByIndex(nFeatureId);
1036 OGRFeatureDefn *poFDefn = NULL;
1038 for (
int i = 0; i < nFDefnCount; i++) {
1039 if (EQUAL(papoFDefnList[i]->GetName(), pszFDName)) {
1040 poFDefn = papoFDefnList[i];
1045 if (poFDefn == NULL) {
1053 OGRFeature *poFeature =
new OGRFeature(poFDefn);
1055 poFeature->SetFID(nFeatureId);
1057 poFeature->SetField(
"RCNM", poRecord->GetIntSubfield(
"VRID", 0,
"RCNM", 0));
1058 poFeature->SetField(
"RCID", poRecord->GetIntSubfield(
"VRID", 0,
"RCID", 0));
1059 poFeature->SetField(
"RVER", poRecord->GetIntSubfield(
"VRID", 0,
"RVER", 0));
1060 poFeature->SetField(
"RUIN", poRecord->GetIntSubfield(
"VRID", 0,
"RUIN", 0));
1065 if (nRCNM == RCNM_VI || nRCNM == RCNM_VC) {
1066 double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
1068 if (poRecord->FindField(
"SG2D") != NULL) {
1069 dfX = poRecord->GetIntSubfield(
"SG2D", 0,
"XCOO", 0) / (double)nCOMF;
1070 dfY = poRecord->GetIntSubfield(
"SG2D", 0,
"YCOO", 0) / (double)nCOMF;
1071 poFeature->SetGeometryDirectly(
new OGRPoint(dfX, dfY));
1074 else if (poRecord->FindField(
"SG3D") != NULL)
1076 int i, nVCount = poRecord->FindField(
"SG3D")->GetRepeatCount();
1078 dfX = poRecord->GetIntSubfield(
"SG3D", 0,
"XCOO", 0) / (double)nCOMF;
1079 dfY = poRecord->GetIntSubfield(
"SG3D", 0,
"YCOO", 0) / (double)nCOMF;
1080 dfZ = poRecord->GetIntSubfield(
"SG3D", 0,
"VE3D", 0) / (double)nSOMF;
1081 poFeature->SetGeometryDirectly(
new OGRPoint(dfX, dfY, dfZ));
1083 OGRMultiPoint *poMP =
new OGRMultiPoint();
1085 for (i = 0; i < nVCount; i++) {
1086 dfX = poRecord->GetIntSubfield(
"SG3D", 0,
"XCOO", i) / (double)nCOMF;
1087 dfY = poRecord->GetIntSubfield(
"SG3D", 0,
"YCOO", i) / (double)nCOMF;
1088 dfZ = poRecord->GetIntSubfield(
"SG3D", 0,
"VE3D", i) / (double)nSOMF;
1090 poMP->addGeometryDirectly(
new OGRPoint(dfX, dfY, dfZ));
1093 poFeature->SetGeometryDirectly(poMP);
1102 else if (nRCNM == RCNM_VE && poRecord->FindField(
"SG2D") != NULL) {
1103 int i, nVCount = poRecord->FindField(
"SG2D")->GetRepeatCount();
1107 OGRLineString *poLine =
new OGRLineString();
1110 while (poRecord->FindField(
"SG2D", jpt) != NULL) {
1113 poRecord->GetIntSubfield(
"SG2D", jpt,
"XCOO", 0) / (
double)nCOMF,
1114 poRecord->GetIntSubfield(
"SG2D", jpt,
"YCOO", 0) / (
double)nCOMF);
1118 poLine->setNumPoints(jpt);
1120 poFeature->SetGeometryDirectly(poLine);
1123 OGRLineString *poLine =
new OGRLineString();
1131 poLine->setNumPoints(nVCount);
1133 for (i = 0; i < nVCount; i++) {
1135 i, poRecord->GetIntSubfield(
"SG2D", 0,
"XCOO", i) / (
double)nCOMF,
1136 poRecord->GetIntSubfield(
"SG2D", 0,
"YCOO", i) / (
double)nCOMF);
1138 poFeature->SetGeometryDirectly(poLine);
1147 if (nRCNM == RCNM_VE && (poVRPT = poRecord->FindField(
"VRPT")) != NULL) {
1148 poFeature->SetField(
"NAME_RCNM_0", RCNM_VC);
1149 poFeature->SetField(
"NAME_RCID_0", ParseName(poVRPT, 0));
1150 poFeature->SetField(
"ORNT_0",
1151 poRecord->GetIntSubfield(
"VRPT", 0,
"ORNT", 0));
1152 poFeature->SetField(
"USAG_0",
1153 poRecord->GetIntSubfield(
"VRPT", 0,
"USAG", 0));
1154 poFeature->SetField(
"TOPI_0",
1155 poRecord->GetIntSubfield(
"VRPT", 0,
"TOPI", 0));
1156 poFeature->SetField(
"MASK_0",
1157 poRecord->GetIntSubfield(
"VRPT", 0,
"MASK", 0));
1159 if (poVRPT->GetRepeatCount() > 1) {
1160 poFeature->SetField(
"NAME_RCNM_1", RCNM_VC);
1161 poFeature->SetField(
"NAME_RCID_1", ParseName(poVRPT, 1));
1162 poFeature->SetField(
"ORNT_1",
1163 poRecord->GetIntSubfield(
"VRPT", 0,
"ORNT", 1));
1164 poFeature->SetField(
"USAG_1",
1165 poRecord->GetIntSubfield(
"VRPT", 0,
"USAG", 1));
1166 poFeature->SetField(
"TOPI_1",
1167 poRecord->GetIntSubfield(
"VRPT", 0,
"TOPI", 1));
1168 poFeature->SetField(
"MASK_1",
1169 poRecord->GetIntSubfield(
"VRPT", 0,
"MASK", 1));
1171 DDFField *poVRPTEnd = poRecord->FindField(
"VRPT", 1);
1174 poFeature->SetField(
"NAME_RCNM_1", RCNM_VC);
1175 poFeature->SetField(
"NAME_RCID_1", ParseName(poVRPTEnd, 0));
1176 poFeature->SetField(
"ORNT_1",
1177 poRecord->GetIntSubfield(
"VRPT", 1,
"ORNT", 0));
1178 poFeature->SetField(
"USAG_1",
1179 poRecord->GetIntSubfield(
"VRPT", 1,
"USAG", 0));
1180 poFeature->SetField(
"TOPI_1",
1181 poRecord->GetIntSubfield(
"VRPT", 1,
"TOPI", 0));
1182 poFeature->SetField(
"MASK_1",
1183 poRecord->GetIntSubfield(
"VRPT", 1,
"MASK", 0));
1185 CPLDebug(
"S57",
"Vector End Point not found, edge omitted.");
1198int S57Reader::FetchPoint(
int nRCNM,
int nRCID,
double *pdfX,
double *pdfY,
1199 double *pdfZ,
int *pnquality)
1202 DDFRecord *poSRecord;
1204 if (nRCNM == RCNM_VI)
1205 poSRecord = oVI_Index.FindRecord(nRCID);
1207 poSRecord = oVC_Index.FindRecord(nRCID);
1209 if (poSRecord == NULL)
return FALSE;
1212 if (NULL != pnquality) {
1214 if ((f = poSRecord->FindField(
"ATTV")) != NULL) {
1215 DDFSubfieldDefn *sfd = (f->GetFieldDefn())->FindSubfieldDefn(
"ATVL");
1218 char *s = (
char *)poSRecord->GetStringSubfield(
"ATTV", 0,
"ATVL", 0,
1221 *pnquality = atoi(s);
1227 double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
1229 if (poSRecord->FindField(
"SG2D") != NULL) {
1230 dfX = poSRecord->GetIntSubfield(
"SG2D", 0,
"XCOO", 0) / (double)nCOMF;
1231 dfY = poSRecord->GetIntSubfield(
"SG2D", 0,
"YCOO", 0) / (double)nCOMF;
1232 }
else if (poSRecord->FindField(
"SG3D") != NULL) {
1233 dfX = poSRecord->GetIntSubfield(
"SG3D", 0,
"XCOO", 0) / (double)nCOMF;
1234 dfY = poSRecord->GetIntSubfield(
"SG3D", 0,
"YCOO", 0) / (double)nCOMF;
1235 dfZ = poSRecord->GetIntSubfield(
"SG3D", 0,
"VE3D", 0) / (double)nSOMF;
1239 if (pdfX != NULL) *pdfX = dfX;
1240 if (pdfY != NULL) *pdfY = dfY;
1241 if (pdfZ != NULL) *pdfZ = dfZ;
1250void S57Reader::AssemblePointGeometry(DDFRecord *poFRecord,
1251 OGRFeature *poFeature)
1260 poFSPT = poFRecord->FindField(
"FSPT");
1261 if (poFSPT == NULL)
return;
1263 if (poFSPT->GetRepeatCount() != 1) {
1265 fprintf(stderr,
"Point features with other than one spatial linkage.\n");
1266 poFRecord->Dump(stderr);
1269 "Point feature encountered with other than one spatial linkage.");
1272 nRCID = ParseName(poFSPT, 0, &nRCNM);
1274 double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
1277 if (!FetchPoint(nRCNM, nRCID, &dfX, &dfY, &dfZ, &nquality)) {
1282 poFeature->SetGeometryDirectly(
new OGRPoint(dfX, dfY, dfZ));
1283 OGRPoint *pp = (OGRPoint *)poFeature->GetGeometryRef();
1284 pp->setnQual(nquality);
1291void S57Reader::AssembleSoundingGeometry(DDFRecord *poFRecord,
1292 OGRFeature *poFeature)
1297 DDFRecord *poSRecord;
1302 poFSPT = poFRecord->FindField(
"FSPT");
1303 if (poFSPT == NULL)
return;
1305 CPLAssert(poFSPT->GetRepeatCount() == 1);
1307 nRCID = ParseName(poFSPT, 0, &nRCNM);
1309 if (nRCNM == RCNM_VI)
1310 poSRecord = oVI_Index.FindRecord(nRCID);
1312 poSRecord = oVC_Index.FindRecord(nRCID);
1314 if (poSRecord == NULL)
return;
1319 OGRMultiPoint *poMP =
new OGRMultiPoint();
1321 int nPointCount, i, nBytesLeft;
1322 DDFSubfieldDefn *poXCOO, *poYCOO, *poVE3D;
1323 const char *pachData;
1325 poField = poSRecord->FindField(
"SG2D");
1326 if (poField == NULL) poField = poSRecord->FindField(
"SG3D");
1327 if (poField == NULL)
return;
1329 poXCOO = poField->GetFieldDefn()->FindSubfieldDefn(
"XCOO");
1330 poYCOO = poField->GetFieldDefn()->FindSubfieldDefn(
"YCOO");
1331 poVE3D = poField->GetFieldDefn()->FindSubfieldDefn(
"VE3D");
1333 nPointCount = poField->GetRepeatCount();
1335 pachData = poField->GetData();
1336 nBytesLeft = poField->GetDataSize();
1338 for (i = 0; i < nPointCount; i++) {
1339 double dfX, dfY, dfZ = 0.0;
1342 dfY = poYCOO->ExtractIntData(pachData, nBytesLeft, &nBytesConsumed) /
1344 nBytesLeft -= nBytesConsumed;
1345 pachData += nBytesConsumed;
1347 dfX = poXCOO->ExtractIntData(pachData, nBytesLeft, &nBytesConsumed) /
1349 nBytesLeft -= nBytesConsumed;
1350 pachData += nBytesConsumed;
1352 if (poVE3D != NULL) {
1353 dfZ = poYCOO->ExtractIntData(pachData, nBytesLeft, &nBytesConsumed) /
1355 nBytesLeft -= nBytesConsumed;
1356 pachData += nBytesConsumed;
1359 poMP->addGeometryDirectly(
new OGRPoint(dfX, dfY, dfZ));
1362 poFeature->SetGeometryDirectly(poMP);
1369void S57Reader::AssembleLineGeometry(DDFRecord *poFRecord,
1370 OGRFeature *poFeature)
1375 OGRLineString *poLine =
new OGRLineString();
1380 poFSPT = poFRecord->FindField(
"FSPT");
1381 if (poFSPT == NULL)
return;
1383 nEdgeCount = poFSPT->GetRepeatCount();
1388 for (
int iEdge = 0; iEdge < nEdgeCount; iEdge++) {
1389 DDFRecord *poSRecord;
1395 nRCID = ParseName(poFSPT, iEdge);
1397 poSRecord = oVE_Index.FindRecord(nRCID);
1398 if (poSRecord == NULL) {
1399 CPLError(CE_Warning, CPLE_AppDefined,
1400 "Couldn't find spatial record %d.\n"
1401 "Feature OBJL=%s, RCID=%d may have corrupt or"
1402 "missing geometry.",
1403 nRCID, poFeature->GetDefnRef()->GetName(),
1404 poFRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0));
1413 int nStart, nEnd, nInc;
1414 DDFField *poSG2D = poSRecord->FindField(
"SG2D");
1415 DDFSubfieldDefn *poXCOO = NULL, *poYCOO = NULL;
1417 if (poSG2D != NULL) {
1418 poXCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn(
"XCOO");
1419 poYCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn(
"YCOO");
1421 nVCount = poSG2D->GetRepeatCount();
1425 DDFField *poField = poSRecord->FindField(
"VRPT");
1428 int nVC_RCIDStart, nVC_RCIDEnd;
1430 if (poField == NULL) {
1431 CPLError(CE_Warning, CPLE_AppDefined,
1432 "Couldn't find field VRPT in spatial record %d.\n"
1433 "Feature OBJL=%s, RCID=%d may have corrupt or"
1434 "missing geometry.",
1435 nRCID, poFeature->GetDefnRef()->GetName(),
1436 poFRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0));
1440 if (poField->GetRepeatCount() > 1) {
1441 nVC_RCID0 = ParseName(poField, 0);
1442 nVC_RCID1 = ParseName(poField, 1);
1444 nVC_RCID0 = ParseName(poField, 0);
1445 DDFField *poFieldEnd = poSRecord->FindField(
"VRPT", 1);
1446 if (poFieldEnd) nVC_RCID1 = ParseName(poFieldEnd, 0);
1449 if (poFRecord->GetIntSubfield(
"FSPT", 0,
"ORNT", iEdge) == 2) {
1450 nStart = nVCount - 1;
1453 nVC_RCIDStart = nVC_RCID1;
1454 nVC_RCIDEnd = nVC_RCID0;
1459 nVC_RCIDStart = nVC_RCID0;
1460 nVC_RCIDEnd = nVC_RCID1;
1479 if (FetchPoint(RCNM_VC, nVC_RCIDStart, &dfX, &dfY))
1480 poLine->addPoint(dfX, dfY);
1482 CPLError(CE_Warning, CPLE_AppDefined,
1483 "Unable to fetch start node RCID%d.\n"
1484 "Feature OBJL=%s, RCID=%d may have corrupt or"
1485 " missing geometry.",
1486 nVC_RCID, poFeature->GetDefnRef()->GetName(),
1487 poFRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0));
1493 int nVBase = poLine->getNumPoints();
1497 while (poSRecord->FindField(
"SG2D", jpt)) {
1499 poSRecord->GetIntSubfield(
"SG2D", jpt,
"XCOO", 0) / (
double)nCOMF,
1500 poSRecord->GetIntSubfield(
"SG2D", jpt,
"YCOO", 0) / (
double)nCOMF);
1504 poLine->setNumPoints(nVCount + nVBase);
1506 for (
int i = nStart; i != nEnd + nInc; i += nInc) {
1508 const char *pachData;
1509 int nBytesRemaining;
1511 pachData = poSG2D->GetSubfieldData(poXCOO, &nBytesRemaining, i);
1513 dfX = poXCOO->ExtractIntData(pachData, nBytesRemaining, NULL) /
1516 pachData = poSG2D->GetSubfieldData(poYCOO, &nBytesRemaining, i);
1518 dfY = poXCOO->ExtractIntData(pachData, nBytesRemaining, NULL) /
1521 poLine->setPoint(nVBase++, dfX, dfY);
1540 if (FetchPoint(RCNM_VC, nVC_RCIDEnd, &dfX, &dfY))
1541 poLine->addPoint(dfX, dfY);
1543 CPLError(CE_Warning, CPLE_AppDefined,
1544 "Unable to fetch end node RCID=%d.\n"
1545 "Feature OBJL=%s, RCID=%d may have corrupt or"
1546 " missing geometry.",
1547 nVC_RCID, poFeature->GetDefnRef()->GetName(),
1548 poFRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0));
1552 if (poLine->getNumPoints() >= 2)
1553 poFeature->SetGeometryDirectly(poLine);
1562void S57Reader::AssembleAreaGeometry(DDFRecord *poFRecord,
1563 OGRFeature *poFeature)
1567 OGRGeometryCollection *poLines =
new OGRGeometryCollection();
1572 for (
int iFSPT = 0; (poFSPT = poFRecord->FindField(
"FSPT", iFSPT)) != NULL;
1576 nEdgeCount = poFSPT->GetRepeatCount();
1581 for (
int iEdge = 0; iEdge < nEdgeCount; iEdge++) {
1582 DDFRecord *poSRecord;
1588 nRCID = ParseName(poFSPT, iEdge);
1590 poSRecord = oVE_Index.FindRecord(nRCID);
1591 if (poSRecord == NULL) {
1592 CPLError(CE_Warning, CPLE_AppDefined,
1593 "Couldn't find spatial record %d.", nRCID);
1603 OGRLineString *poLine =
new OGRLineString();
1606 int nStart, nEnd, nInc;
1607 DDFField *poSG2D = poSRecord->FindField(
"SG2D");
1608 DDFSubfieldDefn *poXCOO = NULL, *poYCOO = NULL;
1610 if (poSG2D != NULL) {
1611 poXCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn(
"XCOO");
1612 poYCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn(
"YCOO");
1614 nVCount = poSG2D->GetRepeatCount();
1618 DDFField *poField = poSRecord->FindField(
"VRPT");
1621 int nVC_RCIDStart, nVC_RCIDEnd;
1623 if (poField && poField->GetRepeatCount() > 1) {
1624 nVC_RCID0 = ParseName(poField, 0);
1625 nVC_RCID1 = ParseName(poField, 1);
1627 if (poField) nVC_RCID0 = ParseName(poField, 0);
1628 DDFField *poFieldEnd = poSRecord->FindField(
"VRPT", 1);
1629 if (poFieldEnd) nVC_RCID1 = ParseName(poFieldEnd, 0);
1632 if (poFRecord->GetIntSubfield(
"FSPT", 0,
"ORNT", iEdge) == 2) {
1633 nStart = nVCount - 1;
1636 nVC_RCIDStart = nVC_RCID1;
1637 nVC_RCIDEnd = nVC_RCID0;
1642 nVC_RCIDStart = nVC_RCID0;
1643 nVC_RCIDEnd = nVC_RCID1;
1652 if (FetchPoint(RCNM_VC, nVC_RCIDStart, &dfX, &dfY))
1653 poLine->addPoint(dfX, dfY);
1659 int nVBase = poLine->getNumPoints();
1663 while (poSRecord->FindField(
"SG2D", jpt)) {
1665 poSRecord->GetIntSubfield(
"SG2D", jpt,
"XCOO", 0) / (
double)nCOMF,
1666 poSRecord->GetIntSubfield(
"SG2D", jpt,
"YCOO", 0) /
1671 poLine->setNumPoints(nVCount + nVBase);
1673 for (
int i = nStart; i != nEnd + nInc; i += nInc) {
1675 const char *pachData;
1676 int nBytesRemaining;
1678 pachData = poSG2D->GetSubfieldData(poXCOO, &nBytesRemaining, i);
1680 dfX = poXCOO->ExtractIntData(pachData, nBytesRemaining, NULL) /
1683 pachData = poSG2D->GetSubfieldData(poYCOO, &nBytesRemaining, i);
1685 dfY = poXCOO->ExtractIntData(pachData, nBytesRemaining, NULL) /
1688 poLine->setPoint(nVBase++, dfX, dfY);
1697 if (FetchPoint(RCNM_VC, nVC_RCIDEnd, &dfX, &dfY))
1698 poLine->addPoint(dfX, dfY);
1701 poLines->addGeometryDirectly(poLine);
1708 OGRPolygon *poPolygon;
1711 poPolygon = (OGRPolygon *)OGRBuildPolygonFromEdges((OGRGeometryH)poLines,
1712 TRUE, FALSE, 0.0, &eErr);
1713 if (eErr != OGRERR_NONE) {
1714 CPLError(CE_Warning, CPLE_AppDefined,
1715 "Polygon assembly has failed for feature FIDN=%d,FIDS=%d.\n"
1716 "Geometry may be missing or incomplete.",
1717 poFeature->GetFieldAsInteger(
"FIDN"),
1718 poFeature->GetFieldAsInteger(
"FIDS"));
1723 if (poPolygon != NULL) poFeature->SetGeometryDirectly(poPolygon);
1734OGRFeatureDefn *S57Reader::FindFDefn(DDFRecord *poRecord)
1737 if (poRegistrar != NULL) {
1738 int nOBJL = poRecord->GetIntSubfield(
"FRID", 0,
"OBJL", 0);
1740 if (!poRegistrar->SelectClass(nOBJL)) {
1741 for (
int i = 0; i < nFDefnCount; i++) {
1742 if (EQUAL(papoFDefnList[i]->GetName(),
"Generic"))
1743 return papoFDefnList[i];
1748 for (
int i = 0; i < nFDefnCount; i++) {
1749 if (EQUAL(papoFDefnList[i]->GetName(), poRegistrar->GetAcronym()))
1750 return papoFDefnList[i];
1755 int nPRIM = poRecord->GetIntSubfield(
"FRID", 0,
"PRIM", 0);
1756 OGRwkbGeometryType eGType;
1758 if (nPRIM == PRIM_P)
1760 else if (nPRIM == PRIM_L)
1761 eGType = wkbLineString;
1762 else if (nPRIM == PRIM_A)
1763 eGType = wkbPolygon;
1767 for (
int i = 0; i < nFDefnCount; i++) {
1768 if (papoFDefnList[i]->GetGeomType() == eGType)
return papoFDefnList[i];
1782int S57Reader::ParseName(DDFField *poField,
int nIndex,
int *pnRCNM)
1785 unsigned char *pabyData;
1787 pabyData = (
unsigned char *)poField->GetSubfieldData(
1788 poField->GetFieldDefn()->FindSubfieldDefn(
"NAME"), NULL, nIndex);
1790 if (pnRCNM != NULL) *pnRCNM = pabyData[0];
1792 return pabyData[1] + pabyData[2] * 256 + pabyData[3] * 256 * 256 +
1793 pabyData[4] * 256 * 256 * 256;
1800void S57Reader::AddFeatureDefn(OGRFeatureDefn *poFDefn)
1804 papoFDefnList = (OGRFeatureDefn **)CPLRealloc(
1805 papoFDefnList,
sizeof(OGRFeatureDefn *) * nFDefnCount);
1807 papoFDefnList[nFDefnCount - 1] = poFDefn;
1817int S57Reader::CollectClassList(
int *panClassCount,
int nMaxClass)
1820 int bSuccess = TRUE;
1822 if (!bFileIngested) Ingest();
1824 for (
int iFEIndex = 0; iFEIndex < oFE_Index.GetCount(); iFEIndex++) {
1825 DDFRecord *poRecord = oFE_Index.GetByIndex(iFEIndex);
1826 int nOBJL = poRecord->GetIntSubfield(
"FRID", 0,
"OBJL", 0);
1828 if (nOBJL >= nMaxClass)
1831 panClassCount[nOBJL]++;
1844int S57Reader::ApplyRecordUpdate(DDFRecord *poTarget, DDFRecord *poUpdate)
1847 const char *pszKey = poUpdate->GetField(1)->GetFieldDefn()->GetName();
1852 if (poTarget->GetIntSubfield(pszKey, 0,
"RVER", 0) + 1 !=
1853 poUpdate->GetIntSubfield(pszKey, 0,
"RVER", 0)) {
1854 CPLError(CE_Warning, CPLE_AppDefined,
1855 "On RecordUpdate, mismatched RVER value for "
1856 "RCNM=%d,RCID=%d...update RVER is %d, target RVER is %d.",
1857 poTarget->GetIntSubfield(pszKey, 0,
"RCNM", 0),
1858 poTarget->GetIntSubfield(pszKey, 0,
"RCID", 0),
1859 poUpdate->GetIntSubfield(pszKey, 0,
"RVER", 0),
1860 poTarget->GetIntSubfield(pszKey, 0,
"RVER", 0));
1867 if (poUpdate->FindField(
"FRID") != NULL) {
1883 int up_PRIM = poUpdate->GetIntSubfield(
"FRID", 0,
"PRIM", 0);
1884 int tar_PRIM = poTarget->GetIntSubfield(
"FRID", 0,
"PRIM", 0);
1885 if (up_PRIM != tar_PRIM) {
1887 CE_Warning, CPLE_AppDefined,
1888 "On RecordUpdate, mismatched PRIM.... target PRIM=%d, update PRIM=%d",
1897 unsigned int *pnRVER;
1898 DDFField *poKey = poTarget->FindField(pszKey);
1899 DDFSubfieldDefn *poRVER_SFD;
1901 if (poKey == NULL) {
1906 poRVER_SFD = poKey->GetFieldDefn()->FindSubfieldDefn(
"RVER");
1907 if (poRVER_SFD == NULL)
return FALSE;
1909 pnRVER = (
unsigned int *)poKey->GetSubfieldData(poRVER_SFD, NULL, 0);
1917 if (poUpdate->FindField(
"FSPC") != NULL) {
1918 int nFSUI = poUpdate->GetIntSubfield(
"FSPC", 0,
"FSUI", 0);
1919 int nFSIX = poUpdate->GetIntSubfield(
"FSPC", 0,
"FSIX", 0);
1920 int nNSPT = poUpdate->GetIntSubfield(
"FSPC", 0,
"NSPT", 0);
1921 DDFField *poSrcFSPT = poUpdate->FindField(
"FSPT");
1922 DDFField *poDstFSPT = poTarget->FindField(
"FSPT");
1925 if ((poSrcFSPT == NULL && nFSUI != 2) || poDstFSPT == NULL) {
1930 nPtrSize = poDstFSPT->GetFieldDefn()->GetFixedWidth();
1934 char *pachInsertion;
1935 int nInsertionBytes = nPtrSize * nNSPT;
1937 pachInsertion = (
char *)CPLMalloc(nInsertionBytes + nPtrSize);
1938 memcpy(pachInsertion, poSrcFSPT->GetData(), nInsertionBytes);
1945 if (nFSIX <= poDstFSPT->GetRepeatCount()) {
1946 memcpy(pachInsertion + nInsertionBytes,
1947 poDstFSPT->GetData() + nPtrSize * (nFSIX - 1), nPtrSize);
1948 nInsertionBytes += nPtrSize;
1951 poTarget->SetFieldRaw(poDstFSPT, nFSIX - 1, pachInsertion,
1953 CPLFree(pachInsertion);
1954 }
else if (nFSUI == 2)
1957 for (
int i = nNSPT - 1; i >= 0; i--) {
1958 poTarget->SetFieldRaw(poDstFSPT, i + nFSIX - 1, NULL, 0);
1960 }
else if (nFSUI == 3)
1963 for (
int i = 0; i < nNSPT; i++) {
1964 const char *pachRawData;
1966 pachRawData = poSrcFSPT->GetData() + nPtrSize * i;
1968 poTarget->SetFieldRaw(poDstFSPT, i + nFSIX - 1, pachRawData, nPtrSize);
1977 if (poUpdate->FindField(
"VRPC") != NULL) {
1978 int nVPUI = poUpdate->GetIntSubfield(
"VRPC", 0,
"VPUI", 0);
1979 int nVPIX = poUpdate->GetIntSubfield(
"VRPC", 0,
"VPIX", 0);
1980 int nNVPT = poUpdate->GetIntSubfield(
"VRPC", 0,
"NVPT", 0);
1981 DDFField *poSrcVRPT = poUpdate->FindField(
"VRPT");
1982 DDFField *poDstVRPT = poTarget->FindField(
"VRPT");
1985 if ((poSrcVRPT == NULL && nVPUI != 2) || poDstVRPT == NULL) {
1990 nPtrSize = poDstVRPT->GetFieldDefn()->GetFixedWidth();
1994 char *pachInsertion;
1995 int nInsertionBytes = nPtrSize * nNVPT;
1997 pachInsertion = (
char *)CPLMalloc(nInsertionBytes + nPtrSize);
1998 memcpy(pachInsertion, poSrcVRPT->GetData(), nInsertionBytes);
2005 if (nVPIX <= poDstVRPT->GetRepeatCount()) {
2006 memcpy(pachInsertion + nInsertionBytes,
2007 poDstVRPT->GetData() + nPtrSize * (nVPIX - 1), nPtrSize);
2008 nInsertionBytes += nPtrSize;
2011 poTarget->SetFieldRaw(poDstVRPT, nVPIX - 1, pachInsertion,
2013 CPLFree(pachInsertion);
2014 }
else if (nVPUI == 2)
2017 for (
int i = nNVPT - 1; i >= 0; i--) {
2018 poTarget->SetFieldRaw(poDstVRPT, i + nVPIX - 1, NULL, 0);
2020 }
else if (nVPUI == 3)
2023 for (
int i = 0; i < nNVPT; i++) {
2024 const char *pachRawData;
2026 pachRawData = poSrcVRPT->GetData() + nPtrSize * i;
2028 poTarget->SetFieldRaw(poDstVRPT, i + nVPIX - 1, pachRawData, nPtrSize);
2036 if (poUpdate->FindField(
"SGCC") != NULL) {
2037 int nCCUI = poUpdate->GetIntSubfield(
"SGCC", 0,
"CCUI", 0);
2038 int nCCIX = poUpdate->GetIntSubfield(
"SGCC", 0,
"CCIX", 0);
2039 int nCCNC = poUpdate->GetIntSubfield(
"SGCC", 0,
"CCNC", 0);
2040 DDFField *poSrcSG2D = poUpdate->FindField(
"SG2D");
2041 DDFField *poDstSG2D = poTarget->FindField(
"SG2D");
2045 if (poDstSG2D == NULL) {
2046 poDstSG2D = poTarget->FindField(
"SG3D");
2047 if (poDstSG2D != NULL) {
2048 poSrcSG2D = poUpdate->FindField(
"SG3D");
2052 if (poDstSG2D == NULL && nCCUI == 2) {
2060 if ((poSrcSG2D == NULL && nCCUI != 2) ||
2061 (poDstSG2D == NULL && nCCUI != 1)) {
2066 if (poDstSG2D == NULL) {
2067 poTarget->AddField(poTarget->GetModule()->FindFieldDefn(
"SG2D"));
2068 poDstSG2D = poTarget->FindField(
"SG2D");
2069 if (poDstSG2D == NULL) {
2075 poTarget->SetFieldRaw(poDstSG2D, 0, NULL, 0);
2078 nCoordSize = poDstSG2D->GetFieldDefn()->GetFixedWidth();
2082 char *pachInsertion;
2083 int nInsertionBytes = nCoordSize * nCCNC;
2085 pachInsertion = (
char *)CPLMalloc(nInsertionBytes + nCoordSize);
2086 memcpy(pachInsertion, poSrcSG2D->GetData(), nInsertionBytes);
2093 if (nCCIX <= poDstSG2D->GetRepeatCount()) {
2094 memcpy(pachInsertion + nInsertionBytes,
2095 poDstSG2D->GetData() + nCoordSize * (nCCIX - 1), nCoordSize);
2096 nInsertionBytes += nCoordSize;
2099 poTarget->SetFieldRaw(poDstSG2D, nCCIX - 1, pachInsertion,
2101 CPLFree(pachInsertion);
2103 }
else if (nCCUI == 2)
2106 for (
int i = nCCNC - 1; i >= 0; i--) {
2107 poTarget->SetFieldRaw(poDstSG2D, i + nCCIX - 1, NULL, 0);
2109 }
else if (nCCUI == 3)
2112 for (
int i = 0; i < nCCNC; i++) {
2113 const char *pachRawData;
2115 pachRawData = poSrcSG2D->GetData() + nCoordSize * i;
2117 poTarget->SetFieldRaw(poDstSG2D, i + nCCIX - 1, pachRawData,
2136 if (poUpdate->FindField(
"ATTF") != NULL) {
2137 bool b_newField =
false;
2138 DDFSubfieldDefn *poSrcATVLDefn;
2139 DDFField *poSrcATTF = poUpdate->FindField(
"ATTF");
2140 DDFField *poDstATTF = poTarget->FindField(
"ATTF");
2142 if (NULL == poDstATTF) {
2147 DDFFieldDefn *poATTF = poTarget->GetModule()->FindFieldDefn(
"ATTF");
2148 poTarget->AddField(poATTF);
2149 poDstATTF = poTarget->FindField(
"ATTF");
2153 int nRepeatCount = poSrcATTF->GetRepeatCount();
2155 poSrcATVLDefn = poSrcATTF->GetFieldDefn()->FindSubfieldDefn(
"ATVL");
2157 for (
int iAtt = 0; iAtt < nRepeatCount; iAtt++) {
2158 int nATTL = poUpdate->GetIntSubfield(
"ATTF", 0,
"ATTL", iAtt);
2159 int iTAtt, nDataBytes;
2160 const char *pszRawData;
2162 for (iTAtt = poDstATTF->GetRepeatCount() - 1; iTAtt >= 0; iTAtt--) {
2163 if (poTarget->GetIntSubfield(
"ATTF", 0,
"ATTL", iTAtt) == nATTL)
break;
2165 if (iTAtt == -1) iTAtt = poDstATTF->GetRepeatCount();
2171 if (poTarget->GetIntSubfield(
"ATTF", 0,
"ATTL", 0) == 0) {
2177 pszRawData = poSrcATTF->GetInstanceData(iAtt, &nDataBytes);
2178 poTarget->SetFieldRaw(poDstATTF, iTAtt, pszRawData, nDataBytes);
2182 if (poUpdate->FindField(
"NATF") != NULL) {
2183 bool b_newField =
false;
2184 DDFSubfieldDefn *poSrcATVLDefn;
2185 DDFField *poSrcATTF = poUpdate->FindField(
"NATF");
2186 DDFField *poDstATTF = poTarget->FindField(
"NATF");
2193 if (NULL == poDstATTF) {
2198 DDFFieldDefn *poNATF = poTarget->GetModule()->FindFieldDefn(
"NATF");
2199 poTarget->AddField(poNATF);
2200 poDstATTF = poTarget->FindField(
"NATF");
2210 int nRepeatCount = poSrcATTF->GetRepeatCount();
2212 poSrcATVLDefn = poSrcATTF->GetFieldDefn()->FindSubfieldDefn(
"ATVL");
2214 for (
int iAtt = 0; iAtt < nRepeatCount; iAtt++) {
2215 int nATTL = poUpdate->GetIntSubfield(
"NATF", 0,
"ATTL", iAtt);
2216 int iTAtt, nDataBytes;
2217 const char *pszRawData;
2219 for (iTAtt = poDstATTF->GetRepeatCount() - 1; iTAtt >= 0; iTAtt--) {
2220 if (poTarget->GetIntSubfield(
"NATF", 0,
"ATTL", iTAtt) == nATTL)
break;
2222 if (iTAtt == -1) iTAtt = poDstATTF->GetRepeatCount();
2228 if (poTarget->GetIntSubfield(
"NATF", 0,
"ATTL", 0) == 0) {
2234 pszRawData = poSrcATTF->GetInstanceData(iAtt, &nDataBytes);
2237 poTarget->SetFieldRaw(poDstATTF, iTAtt, pszRawData, nDataBytes);
2252int S57Reader::ApplyUpdates(DDFModule *poUpdateModule,
int iUpdate)
2255 DDFRecord *poRecord;
2267 while ((poRecord = poUpdateModule->ReadRecord()) != NULL) {
2268 DDFField *poKeyField = poRecord->GetField(1);
2269 const char *pszKey = poKeyField->GetFieldDefn()->GetName();
2271 if (EQUAL(pszKey,
"VRID") || EQUAL(pszKey,
"FRID")) {
2272 int nRCNM = poRecord->GetIntSubfield(pszKey, 0,
"RCNM", 0);
2273 int nRCID = poRecord->GetIntSubfield(pszKey, 0,
"RCID", 0);
2274 int nRVER = poRecord->GetIntSubfield(pszKey, 0,
"RVER", 0);
2275 int nRUIN = poRecord->GetIntSubfield(pszKey, 0,
"RUIN", 0);
2278 if (EQUAL(poKeyField->GetFieldDefn()->GetName(),
"VRID")) {
2281 poIndex = &oVI_Index;
2285 poIndex = &oVC_Index;
2289 poIndex = &oVE_Index;
2293 poIndex = &oVF_Index;
2301 poIndex = &oFE_Index;
2304 if (poIndex != NULL) {
2309 poIndex->AddRecord(nRCID, poRecord->CloneOn(poModule));
2310 }
else if (nRUIN == 2)
2314 DDFRecord *poTarget;
2316 poTarget = poIndex->FindRecord(nRCID);
2317 if (poTarget == NULL) {
2318 CPLError(CE_Warning, CPLE_AppDefined,
2319 "While applying update %d, Can't find RCNM=%d,RCID=%d for "
2321 iUpdate, nRCNM, nRCID);
2322 ret_code = BAD_UPDATE;
2323 }
else if (poTarget->GetIntSubfield(pszKey, 0,
"RVER", 0) !=
2325 CPLError(CE_Warning, CPLE_AppDefined,
2326 "While applying update %d, On RecordRemove, mismatched "
2327 "RVER value for RCNM=%d,RCID=%d...update RVER is %d, "
2328 "target RVER is %d.",
2329 iUpdate, nRCNM, nRCID, nRVER,
2330 poTarget->GetIntSubfield(pszKey, 0,
"RVER", 0));
2332 CE_Warning, CPLE_AppDefined,
2333 "While applying update %d, Removal of RCNM=%d,RCID=%d failed.",
2334 iUpdate, nRCNM, nRCID);
2335 ret_code = BAD_UPDATE;
2338 poIndex->RemoveRecord(nRCID);
2342 else if (nRUIN == 3)
2346 DDFRecord *poTarget;
2348 poTarget = poIndex->FindRecord(nRCID);
2349 if (poTarget == NULL) {
2350 CPLError(CE_Warning, CPLE_AppDefined,
2351 "While applying update %d, Can't find RCNM=%d,RCID=%d for "
2353 iUpdate, nRCNM, nRCID);
2354 ret_code = BAD_UPDATE;
2357 if (!ApplyRecordUpdate(poTarget, poRecord)) {
2358 CPLError(CE_Warning, CPLE_AppDefined,
2359 "While applying update %d, an update to RCNM=%d,RCID=%d "
2361 iUpdate, nRCNM, nRCID);
2362 ret_code = BAD_UPDATE;
2369 else if (EQUAL(pszKey,
"DSID")) {
2375 "While applying update %d, Skipping %s record in "
2376 "S57Reader::ApplyUpdates().",
2378 ret_code = BAD_UPDATE;
2392int S57Reader::FindAndApplyUpdates(
const char *pszPath)
2396 int bSuccess = TRUE;
2399 if (pszPath == NULL) pszPath = pszModuleName;
2401 if (!EQUAL(CPLGetExtension(pszPath),
"000")) {
2402 CPLError(CE_Failure, CPLE_AppDefined,
2403 "Can't apply updates to a base file with a different\n"
2404 "extension than .000.");
2408 for (iUpdate = 1; bSuccess; iUpdate++) {
2409 char szExtension[16];
2410 char *pszUpdateFilename;
2411 DDFModule oUpdateModule;
2413 assert(iUpdate <= 999);
2414 sprintf(szExtension,
"%03d", iUpdate);
2416 pszUpdateFilename = CPLStrdup(CPLResetExtension(pszPath, szExtension));
2418 bSuccess = oUpdateModule.Open(pszUpdateFilename, TRUE);
2421 CPLDebug(
"S57",
"Applying feature updates from %s.", pszUpdateFilename);
2422 CPLFree(pszUpdateFilename);
2425 int update_ret = ApplyUpdates(&oUpdateModule, iUpdate);
2426 if (update_ret) ret_code = update_ret;
2446#if defined(__clang__)
2448#elif defined(__GNUC__) || defined(__GNUG__)
2449#pragma GCC push_options
2450#pragma GCC optimize("O0")
2456S57Reader::GetExtent(OGREnvelope *psExtent,
int bForce)
2459#define INDEX_COUNT 4
2467 if (!bForce && !bFileIngested)
return OGRERR_FAILURE;
2475 int bGotExtents = FALSE;
2476 double nXMin = 0, nXMax = 0, nYMin = 0, nYMax = 0;
2478 apoIndex[0] = &oVI_Index;
2479 apoIndex[1] = &oVC_Index;
2480 apoIndex[2] = &oVE_Index;
2481 apoIndex[3] = &oVF_Index;
2483 for (
int iIndex = 0; iIndex < INDEX_COUNT; iIndex++) {
2486 for (
int iVIndex = 0; iVIndex < poIndex->GetCount(); iVIndex++) {
2487 DDFRecord *poRecord = poIndex->GetByIndex(iVIndex);
2488 DDFField *poSG3D = poRecord->FindField(
"SG3D");
2489 DDFField *poSG2D = poRecord->FindField(
"SG2D");
2491 if (poSG3D != NULL) {
2492 int i, nVCount = poSG3D->GetRepeatCount();
2493 GInt32 *panData, nX, nY;
2495 panData = (GInt32 *)poSG3D->GetData();
2496 for (i = 0; i < nVCount; i++) {
2497 nX = CPL_LSBWORD32(panData[i * 3 + 1]);
2498 nY = CPL_LSBWORD32(panData[i * 3 + 0]);
2500 double dnX = nX / (double)nCOMF;
2501 double dnY = nY / (double)nCOMF;
2504 nXMin = MIN(nXMin, dnX);
2505 nXMax = MAX(nXMax, dnX);
2506 nYMin = MIN(nYMin, dnY);
2507 nYMax = MAX(nYMax, dnY);
2509 nXMin = nXMax = dnX;
2510 nYMin = nYMax = dnY;
2514 }
else if (poSG2D != NULL) {
2515 int i, nVCount = poSG2D->GetRepeatCount();
2516 GInt32 *panData, nX, nY;
2518 panData = (GInt32 *)poSG2D->GetData();
2519 for (i = 0; i < nVCount; i++) {
2520 nX = CPL_LSBWORD32(panData[i * 2 + 1]);
2521 nY = CPL_LSBWORD32(panData[i * 2 + 0]);
2523 double dnX = nX / (double)nCOMF;
2524 double dnY = nY / (double)nCOMF;
2527 nXMin = MIN(nXMin, dnX);
2528 nXMax = MAX(nXMax, dnX);
2529 nYMin = MIN(nYMin, dnY);
2530 nYMax = MAX(nYMax, dnY);
2532 nXMin = nXMax = dnX;
2533 nYMin = nYMax = dnY;
2542 return OGRERR_FAILURE;
2544 psExtent->MinX = nXMin;
2545 psExtent->MaxX = nXMax;
2546 psExtent->MinY = nYMin;
2547 psExtent->MaxY = nYMax;
2554#if defined(__GNUC__) || defined(__GNUG__)
2555#pragma GCC pop_options