29#include "gdal/cpl_conv.h"
30#include "gdal/cpl_string.h"
31#include "gdal/ogr_api.h"
39S57Reader::S57Reader(
const char *pszFilename)
42 pszModuleName = CPLStrdup(pszFilename);
54 bFileIngested = FALSE;
67 nOptionFlags = S57M_UPDATES;
69 bMissingWarningIssued = FALSE;
70 bAttrWarningIssued = FALSE;
80S57Reader::~S57Reader()
85 CPLFree(pszModuleName);
86 CSLDestroy(papszOptions);
88 CPLFree(papoFDefnList);
95int S57Reader::Open(
int bTestOpen)
98 if (poModule != NULL) {
103 poModule =
new DDFModule();
104 if (!poModule->Open(pszModuleName)) {
112 if (poModule->FindFieldDefn(
"DSID") == NULL) {
114 CPLError(CE_Failure, CPLE_AppDefined,
115 "%s is an ISO8211 file, but not an S-57 data file.\n",
124 DDFFieldDefn *poFSPT = poModule->FindFieldDefn(
"FSPT");
125 if (poFSPT != NULL && !poFSPT->IsRepeating()) {
126 CPLDebug(
"S57",
"Forcing FSPT field to be repeating.");
127 poFSPT->SetRepeatingFlag(TRUE);
143void S57Reader::Close()
146 if (poModule != NULL) {
153 ClearPendingMultiPoint();
158 bFileIngested = FALSE;
171void S57Reader::ClearPendingMultiPoint()
174 if (poMultiPoint != NULL) {
184OGRFeature *S57Reader::NextPendingMultiPoint()
187 CPLAssert(poMultiPoint != NULL);
188 CPLAssert(wkbFlatten(poMultiPoint->GetGeometryRef()->getGeometryType()) ==
191 OGRFeatureDefn *poDefn = poMultiPoint->GetDefnRef();
192 OGRFeature *poPoint =
new OGRFeature(poDefn);
193 OGRMultiPoint *poMPGeom = (OGRMultiPoint *)poMultiPoint->GetGeometryRef();
194 OGRPoint *poSrcPoint;
196 poPoint->SetFID(poMultiPoint->GetFID());
198 for (
int i = 0; i < poDefn->GetFieldCount(); i++) {
199 poPoint->SetField(i, poMultiPoint->GetRawFieldRef(i));
202 poSrcPoint = (OGRPoint *)poMPGeom->getGeometryRef(iPointOffset++);
203 poPoint->SetGeometry(poSrcPoint);
205 poPoint->SetField(
"DEPTH", poSrcPoint->getZ());
207 if (iPointOffset >= poMPGeom->getNumGeometries()) ClearPendingMultiPoint();
216void S57Reader::SetOptions(
char **papszOptionsIn)
219 const char *pszOptionValue;
221 CSLDestroy(papszOptions);
222 papszOptions = CSLDuplicate(papszOptionsIn);
224 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_SPLIT_MULTIPOINT);
225 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
226 nOptionFlags |= S57M_SPLIT_MULTIPOINT;
228 nOptionFlags &= ~S57M_SPLIT_MULTIPOINT;
230 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_ADD_SOUNDG_DEPTH);
231 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
232 nOptionFlags |= S57M_ADD_SOUNDG_DEPTH;
234 nOptionFlags &= ~S57M_ADD_SOUNDG_DEPTH;
236 CPLAssert(!(nOptionFlags & S57M_ADD_SOUNDG_DEPTH) ||
237 (nOptionFlags & S57M_SPLIT_MULTIPOINT));
239 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_LNAM_REFS);
240 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
241 nOptionFlags |= S57M_LNAM_REFS;
243 nOptionFlags &= ~S57M_LNAM_REFS;
245 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_UPDATES);
246 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
247 nOptionFlags |= S57M_UPDATES;
249 nOptionFlags &= ~S57M_UPDATES;
251 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_PRESERVE_EMPTY_NUMBERS);
252 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
253 nOptionFlags |= S57M_PRESERVE_EMPTY_NUMBERS;
255 nOptionFlags &= ~S57M_PRESERVE_EMPTY_NUMBERS;
257 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_RETURN_PRIMITIVES);
258 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
259 nOptionFlags |= S57M_RETURN_PRIMITIVES;
261 nOptionFlags &= ~S57M_RETURN_PRIMITIVES;
263 pszOptionValue = CSLFetchNameValue(papszOptions, S57O_RETURN_LINKAGES);
264 if (pszOptionValue != NULL && !EQUAL(pszOptionValue,
"OFF"))
265 nOptionFlags |= S57M_RETURN_LINKAGES;
267 nOptionFlags &= ~S57M_RETURN_LINKAGES;
284void S57Reader::Rewind()
287 ClearPendingMultiPoint();
302int S57Reader::Ingest(CallBackFunction pcallback) {
307 if (poModule == NULL || bFileIngested)
return 0;
313 while ((poRecord = poModule->ReadRecord()) != NULL) {
315 if (!(*pcallback)())
return 0;
318 DDFField *poKeyField = poRecord->GetField(1);
319 const char *pszname = poKeyField->GetFieldDefn()->GetName();
321 if (EQUAL(pszname,
"VRID")) {
323 int nRCNM = poRecord->GetIntSubfield(
"VRID",0,
"RCNM",0);
324 int nRCID = poRecord->GetIntSubfield(
"VRID",0,
"RCID",0);
326 int nRCNM = 0, nRCID = 0;
327 DDFField *poField = poRecord->FindField(
"VRID", 0);
330 DDFSubfieldDefn *poSFDefn;
331 poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn(
"RCNM");
333 const char *pachData =
334 poField->GetSubfieldData(poSFDefn, &nBytesRemaining, 0);
335 nRCNM = poSFDefn->ExtractIntData(pachData, nBytesRemaining, NULL);
338 poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn(
"RCID");
340 const char *pachData =
341 poField->GetSubfieldData(poSFDefn, &nBytesRemaining, 0);
342 nRCID = poSFDefn->ExtractIntData(pachData, nBytesRemaining, NULL);
349 oVI_Index.AddRecord(nRCID, poRecord->Copy());
353 oVC_Index.AddRecord(nRCID, poRecord->Copy());
357 oVE_Index.AddRecord(nRCID, poRecord->Copy());
361 oVF_Index.AddRecord(nRCID, poRecord->Copy());
372 else if (EQUAL(pszname,
"FRID")) {
376 int nRCID = poRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0);
377 oFE_Index.AddRecord(nRCID, poRecord->Copy());
382 else if (EQUAL(pszname,
"DSPM")) {
383 nCOMF = MAX(1, poRecord->GetIntSubfield(
"DSPM", 0,
"COMF", 0));
384 nSOMF = MAX(1, poRecord->GetIntSubfield(
"DSPM", 0,
"SOMF", 0));
385 nCSCL = MAX(1, poRecord->GetIntSubfield(
"DSPM", 0,
"CSCL", 0));
389 else if (EQUAL(pszname,
"DSID")) {
391 pszDSNM = CPLStrdup(poRecord->GetStringSubfield(
"DSID", 0,
"DSNM", 0));
392 Nall = poRecord->GetIntSubfield(
"DSSI", 0,
"NALL", 0);
393 Aall = poRecord->GetIntSubfield(
"DSSI", 0,
"AALL", 0);
397 CPLDebug(
"S57",
"Skipping %s record in S57Reader::Ingest().\n",
398 poKeyField->GetFieldDefn()->GetName());
402 bFileIngested = TRUE;
407 int update_return = 0;
408 if (nOptionFlags & S57M_UPDATES) update_return = FindAndApplyUpdates();
410 return update_return;
417void S57Reader::SetNextFEIndex(
int nNewIndex,
int nRCNM)
420 if (nRCNM == RCNM_VI)
421 nNextVIIndex = nNewIndex;
422 else if (nRCNM == RCNM_VC)
423 nNextVCIndex = nNewIndex;
424 else if (nRCNM == RCNM_VE)
425 nNextVEIndex = nNewIndex;
426 else if (nRCNM == RCNM_VF)
427 nNextVFIndex = nNewIndex;
429 if (nNextFEIndex != nNewIndex) ClearPendingMultiPoint();
431 nNextFEIndex = nNewIndex;
439int S57Reader::GetNextFEIndex(
int nRCNM)
442 if (nRCNM == RCNM_VI)
444 else if (nRCNM == RCNM_VC)
446 else if (nRCNM == RCNM_VE)
448 else if (nRCNM == RCNM_VF)
458OGRFeature *S57Reader::ReadNextFeature(OGRFeatureDefn *poTarget)
461 if (!bFileIngested) Ingest();
466 if (poMultiPoint != NULL) {
467 if (poTarget == NULL || poTarget == poMultiPoint->GetDefnRef()) {
468 return NextPendingMultiPoint();
470 ClearPendingMultiPoint();
477 if (nOptionFlags & S57M_RETURN_PRIMITIVES) {
479 int *pnCounter = NULL;
481 if (poTarget == NULL) {
482 if (nNextVIIndex < oVI_Index.GetCount()) {
484 pnCounter = &nNextVIIndex;
485 }
else if (nNextVCIndex < oVC_Index.GetCount()) {
487 pnCounter = &nNextVCIndex;
488 }
else if (nNextVEIndex < oVE_Index.GetCount()) {
490 pnCounter = &nNextVEIndex;
491 }
else if (nNextVFIndex < oVF_Index.GetCount()) {
493 pnCounter = &nNextVFIndex;
496 if (EQUAL(poTarget->GetName(), OGRN_VI)) {
498 pnCounter = &nNextVIIndex;
499 }
else if (EQUAL(poTarget->GetName(), OGRN_VC)) {
501 pnCounter = &nNextVCIndex;
502 }
else if (EQUAL(poTarget->GetName(), OGRN_VE)) {
504 pnCounter = &nNextVEIndex;
505 }
else if (EQUAL(poTarget->GetName(), OGRN_VF)) {
507 pnCounter = &nNextVFIndex;
512 OGRFeature *poFeature = ReadVector(*pnCounter, nRCNM);
513 if (poFeature != NULL) {
523 while (nNextFEIndex < oFE_Index.GetCount()) {
524 OGRFeature *poFeature;
526 poFeature = ReadFeature(nNextFEIndex++, poTarget);
527 if (poFeature != NULL) {
528 if ((nOptionFlags & S57M_SPLIT_MULTIPOINT) &&
529 poFeature->GetGeometryRef() != NULL &&
530 wkbFlatten(poFeature->GetGeometryRef()->getGeometryType()) ==
532 poMultiPoint = poFeature;
534 return NextPendingMultiPoint();
574OGRFeature *S57Reader::ReadFeature(
int nFeatureId, OGRFeatureDefn *poTarget)
577 OGRFeature *poFeature;
579 if (nFeatureId < 0 || nFeatureId >= oFE_Index.GetCount())
return NULL;
581 DDFRecord *poRecord = oFE_Index.GetByIndex(nFeatureId);
584 int nRecord_OBJL = poRecord->GetIntSubfield(
"FRID", 0,
"OBJL", 0);
585 int nOBJL = poTarget->GetOBJL();
587 if (nRecord_OBJL == nOBJL)
589 poFeature = AssembleFeature(oFE_Index.GetByIndex(nFeatureId), poTarget);
591 if (poFeature != NULL) poFeature->SetFID(nFeatureId);
597 poFeature = AssembleFeature(oFE_Index.GetByIndex(nFeatureId), poTarget);
598 if (poFeature != NULL) poFeature->SetFID(nFeatureId);
610OGRFeature *S57Reader::AssembleFeature(DDFRecord *poRecord,
611 OGRFeatureDefn *poTarget)
615 OGRFeatureDefn *poFDefn;
623 poFDefn = FindFDefn(poRecord);
624 if (poFDefn == NULL) {
629 int nOBJL = poRecord->GetIntSubfield(
"FRID", 0,
"OBJL", 0);
631 S57GenerateObjectClassDefn(poRegistrar, nOBJL, this->GetOptionFlags());
633 AddFeatureDefn(poFDefn);
642 if (poTarget != NULL && poFDefn != poTarget)
return NULL;
647 OGRFeature *poFeature;
649 poFeature =
new OGRFeature(poFDefn);
654 nOBJL = poRecord->GetIntSubfield(
"FRID", 0,
"OBJL", 0);
655 poFeature->SetField(
"OBJL", nOBJL);
657 poFeature->SetField(
"RCID", poRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0));
658 poFeature->SetField(
"PRIM", poRecord->GetIntSubfield(
"FRID", 0,
"PRIM", 0));
659 poFeature->SetField(
"GRUP", poRecord->GetIntSubfield(
"FRID", 0,
"GRUP", 0));
660 poFeature->SetField(
"RVER", poRecord->GetIntSubfield(
"FRID", 0,
"RVER", 0));
661 poFeature->SetField(
"AGEN", poRecord->GetIntSubfield(
"FOID", 0,
"AGEN", 0));
662 poFeature->SetField(
"FIDN", poRecord->GetIntSubfield(
"FOID", 0,
"FIDN", 0));
663 poFeature->SetField(
"FIDS", poRecord->GetIntSubfield(
"FOID", 0,
"FIDS", 0));
668 if (nOptionFlags & S57M_LNAM_REFS) {
669 GenerateLNAMAndRefs(poRecord, poFeature);
675 if (nOptionFlags & S57M_RETURN_LINKAGES)
676 GenerateFSPTAttributes(poRecord, poFeature);
681 if (poRegistrar != NULL) ApplyObjectClassAttributes(poRecord, poFeature);
686 nPRIM = poRecord->GetIntSubfield(
"FRID", 0,
"PRIM", 0);
688 if (nPRIM == PRIM_P) {
690 AssembleSoundingGeometry(poRecord, poFeature);
692 AssemblePointGeometry(poRecord, poFeature);
693 }
else if (nPRIM == PRIM_L) {
694 AssembleLineGeometry(poRecord, poFeature);
695 }
else if (nPRIM == PRIM_A) {
696 AssembleAreaGeometry(poRecord, poFeature);
706void S57Reader::ApplyObjectClassAttributes(DDFRecord *poRecord,
707 OGRFeature *poFeature)
713 DDFField *poATTF = poRecord->FindField(
"ATTF");
714 int nAttrCount, iAttr;
716 if (poATTF == NULL)
return;
718 DDFFieldDefn *poDefn = poATTF->GetFieldDefn();
720 nAttrCount = poATTF->GetRepeatCount();
721 for (iAttr = 0; iAttr < nAttrCount; iAttr++) {
722 int nAttrId = poRecord->GetIntSubfield(
"ATTF", 0,
"ATTL", iAttr);
723 const char *pszAcronym;
725 if (nAttrId < 1 || nAttrId > poRegistrar->GetMaxAttrIndex() ||
726 (pszAcronym = poRegistrar->GetAttrAcronym(nAttrId)) == NULL) {
727 if (!bAttrWarningIssued) {
728 bAttrWarningIssued = TRUE;
729 CPLError(CE_Warning, CPLE_AppDefined,
730 "Illegal feature attribute id (ATTF:ATTL[%d]) of %d\n"
731 "on feature FIDN=%d, FIDS=%d.\n"
732 "Skipping attribute, no more warnings will be issued.",
733 iAttr, nAttrId, poFeature->GetFieldAsInteger(
"FIDN"),
734 poFeature->GetFieldAsInteger(
"FIDS"));
741 const char *pszValue;
742 pszValue = poRecord->GetStringSubfield(
"ATTF", 0,
"ATVL", iAttr);
746 OGRFieldDefn *poFldDefn;
748 iField = poFeature->GetDefnRef()->GetFieldIndex(pszAcronym);
750 if (!bMissingWarningIssued) {
751 bMissingWarningIssued = TRUE;
752 CPLError(CE_Warning, CPLE_AppDefined,
753 "For feature \"%s\", attribute \"%s\" ignored, not in "
754 "expected schema.\n",
755 poFeature->GetDefnRef()->GetName(), pszAcronym);
763 if (pszValue[0] == 0x7f) {
764 poFeature->UnsetField(iField);
768 poFldDefn = poFeature->GetDefnRef()->GetFieldDefn(iField);
769 if (poFldDefn->GetType() == OFTInteger || poFldDefn->GetType() == OFTReal) {
770 if (strlen(pszValue) == 0) {
771 if (nOptionFlags & S57M_PRESERVE_EMPTY_NUMBERS) {
772 poFeature->SetField(iField, EMPTY_NUMBER_MARKER);
777 poFeature->SetField(iField, pszValue);
780 poFeature->SetField(iField, pszValue);
787 DDFField *poNATF = poRecord->FindField(
"NATF");
789 if (poNATF == NULL)
return;
791 nAttrCount = poNATF->GetRepeatCount();
792 for (iAttr = 0; iAttr < nAttrCount; iAttr++) {
793 int nAttrId = poRecord->GetIntSubfield(
"NATF", 0,
"ATTL", iAttr);
794 const char *pszAcronym;
796 if (nAttrId < 1 || nAttrId >= poRegistrar->GetMaxAttrIndex() ||
797 (pszAcronym = poRegistrar->GetAttrAcronym(nAttrId)) == NULL) {
801 static int bAttrWarningIssued = FALSE;
803 if (!bAttrWarningIssued) {
804 bAttrWarningIssued = TRUE;
805 CPLError(CE_Warning, CPLE_AppDefined,
806 "Illegal feature attribute id (NATF:ATTL[%d]) of %d\n"
807 "on feature FIDN=%d, FIDS=%d.\n"
808 "Skipping attribute, no more warnings will be issued.",
809 iAttr, nAttrId, poFeature->GetFieldAsInteger(
"FIDN"),
810 poFeature->GetFieldAsInteger(
"FIDS"));
817 if (poFeature->GetFieldIndex(pszAcronym) < 0)
continue;
819 const char *pszValue =
820 poRecord->GetStringSubfield(
"NATF", 0,
"ATVL", iAttr);
821 if (pszValue != NULL) {
833 poField = poRecord->FindField(
"NATF", 0);
835 DDFSubfieldDefn *poSFDefn;
837 poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn(
"ATVL");
840 const char *pachData =
841 poField->GetSubfieldData(poSFDefn, &max_length, iAttr);
842 nLength = poSFDefn->GetDataLength(pachData, max_length, NULL);
850 int new_len = ((nLength / 2) + 2) * 2;
851 char *aa = (
char *)calloc(new_len, 1);
852 memcpy(aa, pszValue, nLength);
854 int index = poFeature->GetFieldIndex(pszAcronym);
855 OGRField *field = poFeature->GetRawFieldRef(index);
859 poFeature->SetField(pszAcronym, pszValue);
869void S57Reader::GenerateLNAMAndRefs(DDFRecord *poRecord, OGRFeature *poFeature)
877 sprintf(szLNAM,
"%04X%08X%04X", poFeature->GetFieldAsInteger(
"AGEN"),
878 poFeature->GetFieldAsInteger(
"FIDN"),
879 poFeature->GetFieldAsInteger(
"FIDS"));
880 poFeature->SetField(
"LNAM", szLNAM);
887 poFFPT = poRecord->FindField(
"FFPT");
889 if (poFFPT == NULL)
return;
894 int nRefCount = poFFPT->GetRepeatCount();
895 DDFSubfieldDefn *poLNAM;
896 char **papszRefs = NULL;
897 int *panRIND = (
int *)CPLMalloc(
sizeof(
int) * nRefCount);
899 poLNAM = poFFPT->GetFieldDefn()->FindSubfieldDefn(
"LNAM");
900 if (poLNAM == NULL)
return;
902 for (
int iRef = 0; iRef < nRefCount; iRef++) {
903 unsigned char *pabyData;
905 pabyData = (
unsigned char *)poFFPT->GetSubfieldData(poLNAM, NULL, iRef);
907 sprintf(szLNAM,
"%02X%02X%02X%02X%02X%02X%02X%02X", pabyData[1],
909 pabyData[5], pabyData[4], pabyData[3], pabyData[2],
910 pabyData[7], pabyData[6]);
912 papszRefs = CSLAddString(papszRefs, szLNAM);
914 panRIND[iRef] = pabyData[8];
917 poFeature->SetField(
"LNAM_REFS", papszRefs);
918 CSLDestroy(papszRefs);
920 poFeature->SetField(
"FFPT_RIND", nRefCount, panRIND);
928void S57Reader::GenerateFSPTAttributes(DDFRecord *poRecord,
929 OGRFeature *poFeature)
938 poFSPT = poRecord->FindField(
"FSPT");
939 if (poFSPT == NULL)
return;
941 nCount = poFSPT->GetRepeatCount();
946 int *panORNT, *panUSAG, *panMASK, *panRCNM, *panRCID;
948 panORNT = (
int *)CPLMalloc(
sizeof(
int) * nCount);
949 panUSAG = (
int *)CPLMalloc(
sizeof(
int) * nCount);
950 panMASK = (
int *)CPLMalloc(
sizeof(
int) * nCount);
951 panRCNM = (
int *)CPLMalloc(
sizeof(
int) * nCount);
952 panRCID = (
int *)CPLMalloc(
sizeof(
int) * nCount);
957 for (i = 0; i < nCount; i++) {
958 panRCID[i] = ParseName(poFSPT, i, panRCNM + i);
959 panORNT[i] = poRecord->GetIntSubfield(
"FSPT", 0,
"ORNT", i);
960 panUSAG[i] = poRecord->GetIntSubfield(
"FSPT", 0,
"USAG", i);
961 panMASK[i] = poRecord->GetIntSubfield(
"FSPT", 0,
"MASK", i);
967 poFeature->SetField(
"NAME_RCNM", nCount, panRCNM);
968 poFeature->SetField(
"NAME_RCID", nCount, panRCID);
969 poFeature->SetField(
"ORNT", nCount, panORNT);
970 poFeature->SetField(
"USAG", nCount, panUSAG);
971 poFeature->SetField(
"MASK", nCount, panMASK);
990OGRFeature *S57Reader::ReadVector(
int nFeatureId,
int nRCNM)
994 const char *pszFDName = NULL;
1001 poIndex = &oVI_Index;
1002 pszFDName = OGRN_VI;
1006 poIndex = &oVC_Index;
1007 pszFDName = OGRN_VC;
1011 poIndex = &oVE_Index;
1012 pszFDName = OGRN_VE;
1016 poIndex = &oVF_Index;
1017 pszFDName = OGRN_VF;
1025 if (nFeatureId < 0 || nFeatureId >= poIndex->GetCount())
return NULL;
1027 DDFRecord *poRecord = poIndex->GetByIndex(nFeatureId);
1032 OGRFeatureDefn *poFDefn = NULL;
1034 for (
int i = 0; i < nFDefnCount; i++) {
1035 if (EQUAL(papoFDefnList[i]->GetName(), pszFDName)) {
1036 poFDefn = papoFDefnList[i];
1041 if (poFDefn == NULL) {
1049 OGRFeature *poFeature =
new OGRFeature(poFDefn);
1051 poFeature->SetFID(nFeatureId);
1053 poFeature->SetField(
"RCNM", poRecord->GetIntSubfield(
"VRID", 0,
"RCNM", 0));
1054 poFeature->SetField(
"RCID", poRecord->GetIntSubfield(
"VRID", 0,
"RCID", 0));
1055 poFeature->SetField(
"RVER", poRecord->GetIntSubfield(
"VRID", 0,
"RVER", 0));
1056 poFeature->SetField(
"RUIN", poRecord->GetIntSubfield(
"VRID", 0,
"RUIN", 0));
1061 if (nRCNM == RCNM_VI || nRCNM == RCNM_VC) {
1062 double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
1064 if (poRecord->FindField(
"SG2D") != NULL) {
1065 dfX = poRecord->GetIntSubfield(
"SG2D", 0,
"XCOO", 0) / (double)nCOMF;
1066 dfY = poRecord->GetIntSubfield(
"SG2D", 0,
"YCOO", 0) / (double)nCOMF;
1067 poFeature->SetGeometryDirectly(
new OGRPoint(dfX, dfY));
1070 else if (poRecord->FindField(
"SG3D") != NULL)
1072 int i, nVCount = poRecord->FindField(
"SG3D")->GetRepeatCount();
1074 dfX = poRecord->GetIntSubfield(
"SG3D", 0,
"XCOO", 0) / (double)nCOMF;
1075 dfY = poRecord->GetIntSubfield(
"SG3D", 0,
"YCOO", 0) / (double)nCOMF;
1076 dfZ = poRecord->GetIntSubfield(
"SG3D", 0,
"VE3D", 0) / (double)nSOMF;
1077 poFeature->SetGeometryDirectly(
new OGRPoint(dfX, dfY, dfZ));
1079 OGRMultiPoint *poMP =
new OGRMultiPoint();
1081 for (i = 0; i < nVCount; i++) {
1082 dfX = poRecord->GetIntSubfield(
"SG3D", 0,
"XCOO", i) / (double)nCOMF;
1083 dfY = poRecord->GetIntSubfield(
"SG3D", 0,
"YCOO", i) / (double)nCOMF;
1084 dfZ = poRecord->GetIntSubfield(
"SG3D", 0,
"VE3D", i) / (double)nSOMF;
1086 poMP->addGeometryDirectly(
new OGRPoint(dfX, dfY, dfZ));
1089 poFeature->SetGeometryDirectly(poMP);
1098 else if (nRCNM == RCNM_VE && poRecord->FindField(
"SG2D") != NULL) {
1099 int i, nVCount = poRecord->FindField(
"SG2D")->GetRepeatCount();
1103 OGRLineString *poLine =
new OGRLineString();
1106 while (poRecord->FindField(
"SG2D", jpt) != NULL) {
1109 poRecord->GetIntSubfield(
"SG2D", jpt,
"XCOO", 0) / (
double)nCOMF,
1110 poRecord->GetIntSubfield(
"SG2D", jpt,
"YCOO", 0) / (
double)nCOMF);
1114 poLine->setNumPoints(jpt);
1116 poFeature->SetGeometryDirectly(poLine);
1119 OGRLineString *poLine =
new OGRLineString();
1127 poLine->setNumPoints(nVCount);
1129 for (i = 0; i < nVCount; i++) {
1131 i, poRecord->GetIntSubfield(
"SG2D", 0,
"XCOO", i) / (
double)nCOMF,
1132 poRecord->GetIntSubfield(
"SG2D", 0,
"YCOO", i) / (
double)nCOMF);
1134 poFeature->SetGeometryDirectly(poLine);
1143 if (nRCNM == RCNM_VE && (poVRPT = poRecord->FindField(
"VRPT")) != NULL) {
1144 poFeature->SetField(
"NAME_RCNM_0", RCNM_VC);
1145 poFeature->SetField(
"NAME_RCID_0", ParseName(poVRPT, 0));
1146 poFeature->SetField(
"ORNT_0",
1147 poRecord->GetIntSubfield(
"VRPT", 0,
"ORNT", 0));
1148 poFeature->SetField(
"USAG_0",
1149 poRecord->GetIntSubfield(
"VRPT", 0,
"USAG", 0));
1150 poFeature->SetField(
"TOPI_0",
1151 poRecord->GetIntSubfield(
"VRPT", 0,
"TOPI", 0));
1152 poFeature->SetField(
"MASK_0",
1153 poRecord->GetIntSubfield(
"VRPT", 0,
"MASK", 0));
1155 if (poVRPT->GetRepeatCount() > 1) {
1156 poFeature->SetField(
"NAME_RCNM_1", RCNM_VC);
1157 poFeature->SetField(
"NAME_RCID_1", ParseName(poVRPT, 1));
1158 poFeature->SetField(
"ORNT_1",
1159 poRecord->GetIntSubfield(
"VRPT", 0,
"ORNT", 1));
1160 poFeature->SetField(
"USAG_1",
1161 poRecord->GetIntSubfield(
"VRPT", 0,
"USAG", 1));
1162 poFeature->SetField(
"TOPI_1",
1163 poRecord->GetIntSubfield(
"VRPT", 0,
"TOPI", 1));
1164 poFeature->SetField(
"MASK_1",
1165 poRecord->GetIntSubfield(
"VRPT", 0,
"MASK", 1));
1167 DDFField *poVRPTEnd = poRecord->FindField(
"VRPT", 1);
1170 poFeature->SetField(
"NAME_RCNM_1", RCNM_VC);
1171 poFeature->SetField(
"NAME_RCID_1", ParseName(poVRPTEnd, 0));
1172 poFeature->SetField(
"ORNT_1",
1173 poRecord->GetIntSubfield(
"VRPT", 1,
"ORNT", 0));
1174 poFeature->SetField(
"USAG_1",
1175 poRecord->GetIntSubfield(
"VRPT", 1,
"USAG", 0));
1176 poFeature->SetField(
"TOPI_1",
1177 poRecord->GetIntSubfield(
"VRPT", 1,
"TOPI", 0));
1178 poFeature->SetField(
"MASK_1",
1179 poRecord->GetIntSubfield(
"VRPT", 1,
"MASK", 0));
1181 CPLDebug(
"S57",
"Vector End Point not found, edge omitted.");
1194int S57Reader::FetchPoint(
int nRCNM,
int nRCID,
double *pdfX,
double *pdfY,
1195 double *pdfZ,
int *pnquality)
1198 DDFRecord *poSRecord;
1200 if (nRCNM == RCNM_VI)
1201 poSRecord = oVI_Index.FindRecord(nRCID);
1203 poSRecord = oVC_Index.FindRecord(nRCID);
1205 if (poSRecord == NULL)
return FALSE;
1208 if (NULL != pnquality) {
1210 if ((f = poSRecord->FindField(
"ATTV")) != NULL) {
1211 DDFSubfieldDefn *sfd = (f->GetFieldDefn())->FindSubfieldDefn(
"ATVL");
1214 char *s = (
char *)poSRecord->GetStringSubfield(
"ATTV", 0,
"ATVL", 0,
1217 *pnquality = atoi(s);
1223 double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
1225 if (poSRecord->FindField(
"SG2D") != NULL) {
1226 dfX = poSRecord->GetIntSubfield(
"SG2D", 0,
"XCOO", 0) / (double)nCOMF;
1227 dfY = poSRecord->GetIntSubfield(
"SG2D", 0,
"YCOO", 0) / (double)nCOMF;
1228 }
else if (poSRecord->FindField(
"SG3D") != NULL) {
1229 dfX = poSRecord->GetIntSubfield(
"SG3D", 0,
"XCOO", 0) / (double)nCOMF;
1230 dfY = poSRecord->GetIntSubfield(
"SG3D", 0,
"YCOO", 0) / (double)nCOMF;
1231 dfZ = poSRecord->GetIntSubfield(
"SG3D", 0,
"VE3D", 0) / (double)nSOMF;
1235 if (pdfX != NULL) *pdfX = dfX;
1236 if (pdfY != NULL) *pdfY = dfY;
1237 if (pdfZ != NULL) *pdfZ = dfZ;
1246void S57Reader::AssemblePointGeometry(DDFRecord *poFRecord,
1247 OGRFeature *poFeature)
1256 poFSPT = poFRecord->FindField(
"FSPT");
1257 if (poFSPT == NULL)
return;
1259 if (poFSPT->GetRepeatCount() != 1) {
1261 fprintf(stderr,
"Point features with other than one spatial linkage.\n");
1262 poFRecord->Dump(stderr);
1265 "Point feature encountered with other than one spatial linkage.");
1268 nRCID = ParseName(poFSPT, 0, &nRCNM);
1270 double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
1273 if (!FetchPoint(nRCNM, nRCID, &dfX, &dfY, &dfZ, &nquality)) {
1278 poFeature->SetGeometryDirectly(
new OGRPoint(dfX, dfY, dfZ));
1279 OGRPoint *pp = (OGRPoint *)poFeature->GetGeometryRef();
1280 pp->setnQual(nquality);
1287void S57Reader::AssembleSoundingGeometry(DDFRecord *poFRecord,
1288 OGRFeature *poFeature)
1293 DDFRecord *poSRecord;
1298 poFSPT = poFRecord->FindField(
"FSPT");
1299 if (poFSPT == NULL)
return;
1301 CPLAssert(poFSPT->GetRepeatCount() == 1);
1303 nRCID = ParseName(poFSPT, 0, &nRCNM);
1305 if (nRCNM == RCNM_VI)
1306 poSRecord = oVI_Index.FindRecord(nRCID);
1308 poSRecord = oVC_Index.FindRecord(nRCID);
1310 if (poSRecord == NULL)
return;
1315 OGRMultiPoint *poMP =
new OGRMultiPoint();
1317 int nPointCount, i, nBytesLeft;
1318 DDFSubfieldDefn *poXCOO, *poYCOO, *poVE3D;
1319 const char *pachData;
1321 poField = poSRecord->FindField(
"SG2D");
1322 if (poField == NULL) poField = poSRecord->FindField(
"SG3D");
1323 if (poField == NULL)
return;
1325 poXCOO = poField->GetFieldDefn()->FindSubfieldDefn(
"XCOO");
1326 poYCOO = poField->GetFieldDefn()->FindSubfieldDefn(
"YCOO");
1327 poVE3D = poField->GetFieldDefn()->FindSubfieldDefn(
"VE3D");
1329 nPointCount = poField->GetRepeatCount();
1331 pachData = poField->GetData();
1332 nBytesLeft = poField->GetDataSize();
1334 for (i = 0; i < nPointCount; i++) {
1335 double dfX, dfY, dfZ = 0.0;
1338 dfY = poYCOO->ExtractIntData(pachData, nBytesLeft, &nBytesConsumed) /
1340 nBytesLeft -= nBytesConsumed;
1341 pachData += nBytesConsumed;
1343 dfX = poXCOO->ExtractIntData(pachData, nBytesLeft, &nBytesConsumed) /
1345 nBytesLeft -= nBytesConsumed;
1346 pachData += nBytesConsumed;
1348 if (poVE3D != NULL) {
1349 dfZ = poYCOO->ExtractIntData(pachData, nBytesLeft, &nBytesConsumed) /
1351 nBytesLeft -= nBytesConsumed;
1352 pachData += nBytesConsumed;
1355 poMP->addGeometryDirectly(
new OGRPoint(dfX, dfY, dfZ));
1358 poFeature->SetGeometryDirectly(poMP);
1365void S57Reader::AssembleLineGeometry(DDFRecord *poFRecord,
1366 OGRFeature *poFeature)
1371 OGRLineString *poLine =
new OGRLineString();
1376 poFSPT = poFRecord->FindField(
"FSPT");
1377 if (poFSPT == NULL)
return;
1379 nEdgeCount = poFSPT->GetRepeatCount();
1384 for (
int iEdge = 0; iEdge < nEdgeCount; iEdge++) {
1385 DDFRecord *poSRecord;
1391 nRCID = ParseName(poFSPT, iEdge);
1393 poSRecord = oVE_Index.FindRecord(nRCID);
1394 if (poSRecord == NULL) {
1395 CPLError(CE_Warning, CPLE_AppDefined,
1396 "Couldn't find spatial record %d.\n"
1397 "Feature OBJL=%s, RCID=%d may have corrupt or"
1398 "missing geometry.",
1399 nRCID, poFeature->GetDefnRef()->GetName(),
1400 poFRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0));
1409 int nStart, nEnd, nInc;
1410 DDFField *poSG2D = poSRecord->FindField(
"SG2D");
1411 DDFSubfieldDefn *poXCOO = NULL, *poYCOO = NULL;
1413 if (poSG2D != NULL) {
1414 poXCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn(
"XCOO");
1415 poYCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn(
"YCOO");
1417 nVCount = poSG2D->GetRepeatCount();
1421 DDFField *poField = poSRecord->FindField(
"VRPT");
1424 int nVC_RCIDStart, nVC_RCIDEnd;
1426 if (poField == NULL) {
1427 CPLError(CE_Warning, CPLE_AppDefined,
1428 "Couldn't find field VRPT in spatial record %d.\n"
1429 "Feature OBJL=%s, RCID=%d may have corrupt or"
1430 "missing geometry.",
1431 nRCID, poFeature->GetDefnRef()->GetName(),
1432 poFRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0));
1436 if (poField->GetRepeatCount() > 1) {
1437 nVC_RCID0 = ParseName(poField, 0);
1438 nVC_RCID1 = ParseName(poField, 1);
1440 nVC_RCID0 = ParseName(poField, 0);
1441 DDFField *poFieldEnd = poSRecord->FindField(
"VRPT", 1);
1442 if (poFieldEnd) nVC_RCID1 = ParseName(poFieldEnd, 0);
1445 if (poFRecord->GetIntSubfield(
"FSPT", 0,
"ORNT", iEdge) == 2) {
1446 nStart = nVCount - 1;
1449 nVC_RCIDStart = nVC_RCID1;
1450 nVC_RCIDEnd = nVC_RCID0;
1455 nVC_RCIDStart = nVC_RCID0;
1456 nVC_RCIDEnd = nVC_RCID1;
1475 if (FetchPoint(RCNM_VC, nVC_RCIDStart, &dfX, &dfY))
1476 poLine->addPoint(dfX, dfY);
1478 CPLError(CE_Warning, CPLE_AppDefined,
1479 "Unable to fetch start node RCID%d.\n"
1480 "Feature OBJL=%s, RCID=%d may have corrupt or"
1481 " missing geometry.",
1482 nVC_RCID, poFeature->GetDefnRef()->GetName(),
1483 poFRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0));
1489 int nVBase = poLine->getNumPoints();
1493 while (poSRecord->FindField(
"SG2D", jpt)) {
1495 poSRecord->GetIntSubfield(
"SG2D", jpt,
"XCOO", 0) / (
double)nCOMF,
1496 poSRecord->GetIntSubfield(
"SG2D", jpt,
"YCOO", 0) / (
double)nCOMF);
1500 poLine->setNumPoints(nVCount + nVBase);
1502 for (
int i = nStart; i != nEnd + nInc; i += nInc) {
1504 const char *pachData;
1505 int nBytesRemaining;
1507 pachData = poSG2D->GetSubfieldData(poXCOO, &nBytesRemaining, i);
1509 dfX = poXCOO->ExtractIntData(pachData, nBytesRemaining, NULL) /
1512 pachData = poSG2D->GetSubfieldData(poYCOO, &nBytesRemaining, i);
1514 dfY = poXCOO->ExtractIntData(pachData, nBytesRemaining, NULL) /
1517 poLine->setPoint(nVBase++, dfX, dfY);
1536 if (FetchPoint(RCNM_VC, nVC_RCIDEnd, &dfX, &dfY))
1537 poLine->addPoint(dfX, dfY);
1539 CPLError(CE_Warning, CPLE_AppDefined,
1540 "Unable to fetch end node RCID=%d.\n"
1541 "Feature OBJL=%s, RCID=%d may have corrupt or"
1542 " missing geometry.",
1543 nVC_RCID, poFeature->GetDefnRef()->GetName(),
1544 poFRecord->GetIntSubfield(
"FRID", 0,
"RCID", 0));
1548 if (poLine->getNumPoints() >= 2)
1549 poFeature->SetGeometryDirectly(poLine);
1558void S57Reader::AssembleAreaGeometry(DDFRecord *poFRecord,
1559 OGRFeature *poFeature)
1563 OGRGeometryCollection *poLines =
new OGRGeometryCollection();
1568 for (
int iFSPT = 0; (poFSPT = poFRecord->FindField(
"FSPT", iFSPT)) != NULL;
1572 nEdgeCount = poFSPT->GetRepeatCount();
1577 for (
int iEdge = 0; iEdge < nEdgeCount; iEdge++) {
1578 DDFRecord *poSRecord;
1584 nRCID = ParseName(poFSPT, iEdge);
1586 poSRecord = oVE_Index.FindRecord(nRCID);
1587 if (poSRecord == NULL) {
1588 CPLError(CE_Warning, CPLE_AppDefined,
1589 "Couldn't find spatial record %d.", nRCID);
1599 OGRLineString *poLine =
new OGRLineString();
1602 int nStart, nEnd, nInc;
1603 DDFField *poSG2D = poSRecord->FindField(
"SG2D");
1604 DDFSubfieldDefn *poXCOO = NULL, *poYCOO = NULL;
1606 if (poSG2D != NULL) {
1607 poXCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn(
"XCOO");
1608 poYCOO = poSG2D->GetFieldDefn()->FindSubfieldDefn(
"YCOO");
1610 nVCount = poSG2D->GetRepeatCount();
1614 DDFField *poField = poSRecord->FindField(
"VRPT");
1617 int nVC_RCIDStart, nVC_RCIDEnd;
1619 if (poField && poField->GetRepeatCount() > 1) {
1620 nVC_RCID0 = ParseName(poField, 0);
1621 nVC_RCID1 = ParseName(poField, 1);
1623 if (poField) nVC_RCID0 = ParseName(poField, 0);
1624 DDFField *poFieldEnd = poSRecord->FindField(
"VRPT", 1);
1625 if (poFieldEnd) nVC_RCID1 = ParseName(poFieldEnd, 0);
1628 if (poFRecord->GetIntSubfield(
"FSPT", 0,
"ORNT", iEdge) == 2) {
1629 nStart = nVCount - 1;
1632 nVC_RCIDStart = nVC_RCID1;
1633 nVC_RCIDEnd = nVC_RCID0;
1638 nVC_RCIDStart = nVC_RCID0;
1639 nVC_RCIDEnd = nVC_RCID1;
1648 if (FetchPoint(RCNM_VC, nVC_RCIDStart, &dfX, &dfY))
1649 poLine->addPoint(dfX, dfY);
1655 int nVBase = poLine->getNumPoints();
1659 while (poSRecord->FindField(
"SG2D", jpt)) {
1661 poSRecord->GetIntSubfield(
"SG2D", jpt,
"XCOO", 0) / (
double)nCOMF,
1662 poSRecord->GetIntSubfield(
"SG2D", jpt,
"YCOO", 0) /
1667 poLine->setNumPoints(nVCount + nVBase);
1669 for (
int i = nStart; i != nEnd + nInc; i += nInc) {
1671 const char *pachData;
1672 int nBytesRemaining;
1674 pachData = poSG2D->GetSubfieldData(poXCOO, &nBytesRemaining, i);
1676 dfX = poXCOO->ExtractIntData(pachData, nBytesRemaining, NULL) /
1679 pachData = poSG2D->GetSubfieldData(poYCOO, &nBytesRemaining, i);
1681 dfY = poXCOO->ExtractIntData(pachData, nBytesRemaining, NULL) /
1684 poLine->setPoint(nVBase++, dfX, dfY);
1693 if (FetchPoint(RCNM_VC, nVC_RCIDEnd, &dfX, &dfY))
1694 poLine->addPoint(dfX, dfY);
1697 poLines->addGeometryDirectly(poLine);
1704 OGRPolygon *poPolygon;
1707 poPolygon = (OGRPolygon *)OGRBuildPolygonFromEdges((OGRGeometryH)poLines,
1708 TRUE, FALSE, 0.0, &eErr);
1709 if (eErr != OGRERR_NONE) {
1710 CPLError(CE_Warning, CPLE_AppDefined,
1711 "Polygon assembly has failed for feature FIDN=%d,FIDS=%d.\n"
1712 "Geometry may be missing or incomplete.",
1713 poFeature->GetFieldAsInteger(
"FIDN"),
1714 poFeature->GetFieldAsInteger(
"FIDS"));
1719 if (poPolygon != NULL) poFeature->SetGeometryDirectly(poPolygon);
1730OGRFeatureDefn *S57Reader::FindFDefn(DDFRecord *poRecord)
1733 if (poRegistrar != NULL) {
1734 int nOBJL = poRecord->GetIntSubfield(
"FRID", 0,
"OBJL", 0);
1736 if (!poRegistrar->SelectClass(nOBJL)) {
1737 for (
int i = 0; i < nFDefnCount; i++) {
1738 if (EQUAL(papoFDefnList[i]->GetName(),
"Generic"))
1739 return papoFDefnList[i];
1744 for (
int i = 0; i < nFDefnCount; i++) {
1745 if (EQUAL(papoFDefnList[i]->GetName(), poRegistrar->GetAcronym()))
1746 return papoFDefnList[i];
1751 int nPRIM = poRecord->GetIntSubfield(
"FRID", 0,
"PRIM", 0);
1752 OGRwkbGeometryType eGType;
1754 if (nPRIM == PRIM_P)
1756 else if (nPRIM == PRIM_L)
1757 eGType = wkbLineString;
1758 else if (nPRIM == PRIM_A)
1759 eGType = wkbPolygon;
1763 for (
int i = 0; i < nFDefnCount; i++) {
1764 if (papoFDefnList[i]->GetGeomType() == eGType)
return papoFDefnList[i];
1778int S57Reader::ParseName(DDFField *poField,
int nIndex,
int *pnRCNM)
1781 unsigned char *pabyData;
1783 pabyData = (
unsigned char *)poField->GetSubfieldData(
1784 poField->GetFieldDefn()->FindSubfieldDefn(
"NAME"), NULL, nIndex);
1786 if (pnRCNM != NULL) *pnRCNM = pabyData[0];
1788 return pabyData[1] + pabyData[2] * 256 + pabyData[3] * 256 * 256 +
1789 pabyData[4] * 256 * 256 * 256;
1796void S57Reader::AddFeatureDefn(OGRFeatureDefn *poFDefn)
1800 papoFDefnList = (OGRFeatureDefn **)CPLRealloc(
1801 papoFDefnList,
sizeof(OGRFeatureDefn *) * nFDefnCount);
1803 papoFDefnList[nFDefnCount - 1] = poFDefn;
1813int S57Reader::CollectClassList(
int *panClassCount,
int nMaxClass)
1816 int bSuccess = TRUE;
1818 if (!bFileIngested) Ingest();
1820 for (
int iFEIndex = 0; iFEIndex < oFE_Index.GetCount(); iFEIndex++) {
1821 DDFRecord *poRecord = oFE_Index.GetByIndex(iFEIndex);
1822 int nOBJL = poRecord->GetIntSubfield(
"FRID", 0,
"OBJL", 0);
1824 if (nOBJL >= nMaxClass)
1827 panClassCount[nOBJL]++;
1840int S57Reader::ApplyRecordUpdate(DDFRecord *poTarget, DDFRecord *poUpdate)
1843 const char *pszKey = poUpdate->GetField(1)->GetFieldDefn()->GetName();
1848 if (poTarget->GetIntSubfield(pszKey, 0,
"RVER", 0) + 1 !=
1849 poUpdate->GetIntSubfield(pszKey, 0,
"RVER", 0)) {
1850 CPLError(CE_Warning, CPLE_AppDefined,
1851 "On RecordUpdate, mismatched RVER value for "
1852 "RCNM=%d,RCID=%d...update RVER is %d, target RVER is %d.",
1853 poTarget->GetIntSubfield(pszKey, 0,
"RCNM", 0),
1854 poTarget->GetIntSubfield(pszKey, 0,
"RCID", 0),
1855 poUpdate->GetIntSubfield(pszKey, 0,
"RVER", 0),
1856 poTarget->GetIntSubfield(pszKey, 0,
"RVER", 0));
1863 if (poUpdate->FindField(
"FRID") != NULL) {
1879 int up_PRIM = poUpdate->GetIntSubfield(
"FRID", 0,
"PRIM", 0);
1880 int tar_PRIM = poTarget->GetIntSubfield(
"FRID", 0,
"PRIM", 0);
1881 if (up_PRIM != tar_PRIM) {
1883 CE_Warning, CPLE_AppDefined,
1884 "On RecordUpdate, mismatched PRIM.... target PRIM=%d, update PRIM=%d",
1893 unsigned int *pnRVER;
1894 DDFField *poKey = poTarget->FindField(pszKey);
1895 DDFSubfieldDefn *poRVER_SFD;
1897 if (poKey == NULL) {
1902 poRVER_SFD = poKey->GetFieldDefn()->FindSubfieldDefn(
"RVER");
1903 if (poRVER_SFD == NULL)
return FALSE;
1905 pnRVER = (
unsigned int *)poKey->GetSubfieldData(poRVER_SFD, NULL, 0);
1913 if (poUpdate->FindField(
"FSPC") != NULL) {
1914 int nFSUI = poUpdate->GetIntSubfield(
"FSPC", 0,
"FSUI", 0);
1915 int nFSIX = poUpdate->GetIntSubfield(
"FSPC", 0,
"FSIX", 0);
1916 int nNSPT = poUpdate->GetIntSubfield(
"FSPC", 0,
"NSPT", 0);
1917 DDFField *poSrcFSPT = poUpdate->FindField(
"FSPT");
1918 DDFField *poDstFSPT = poTarget->FindField(
"FSPT");
1921 if ((poSrcFSPT == NULL && nFSUI != 2) || poDstFSPT == NULL) {
1926 nPtrSize = poDstFSPT->GetFieldDefn()->GetFixedWidth();
1930 char *pachInsertion;
1931 int nInsertionBytes = nPtrSize * nNSPT;
1933 pachInsertion = (
char *)CPLMalloc(nInsertionBytes + nPtrSize);
1934 memcpy(pachInsertion, poSrcFSPT->GetData(), nInsertionBytes);
1941 if (nFSIX <= poDstFSPT->GetRepeatCount()) {
1942 memcpy(pachInsertion + nInsertionBytes,
1943 poDstFSPT->GetData() + nPtrSize * (nFSIX - 1), nPtrSize);
1944 nInsertionBytes += nPtrSize;
1947 poTarget->SetFieldRaw(poDstFSPT, nFSIX - 1, pachInsertion,
1949 CPLFree(pachInsertion);
1950 }
else if (nFSUI == 2)
1953 for (
int i = nNSPT - 1; i >= 0; i--) {
1954 poTarget->SetFieldRaw(poDstFSPT, i + nFSIX - 1, NULL, 0);
1956 }
else if (nFSUI == 3)
1959 for (
int i = 0; i < nNSPT; i++) {
1960 const char *pachRawData;
1962 pachRawData = poSrcFSPT->GetData() + nPtrSize * i;
1964 poTarget->SetFieldRaw(poDstFSPT, i + nFSIX - 1, pachRawData, nPtrSize);
1973 if (poUpdate->FindField(
"VRPC") != NULL) {
1974 int nVPUI = poUpdate->GetIntSubfield(
"VRPC", 0,
"VPUI", 0);
1975 int nVPIX = poUpdate->GetIntSubfield(
"VRPC", 0,
"VPIX", 0);
1976 int nNVPT = poUpdate->GetIntSubfield(
"VRPC", 0,
"NVPT", 0);
1977 DDFField *poSrcVRPT = poUpdate->FindField(
"VRPT");
1978 DDFField *poDstVRPT = poTarget->FindField(
"VRPT");
1981 if ((poSrcVRPT == NULL && nVPUI != 2) || poDstVRPT == NULL) {
1986 nPtrSize = poDstVRPT->GetFieldDefn()->GetFixedWidth();
1990 char *pachInsertion;
1991 int nInsertionBytes = nPtrSize * nNVPT;
1993 pachInsertion = (
char *)CPLMalloc(nInsertionBytes + nPtrSize);
1994 memcpy(pachInsertion, poSrcVRPT->GetData(), nInsertionBytes);
2001 if (nVPIX <= poDstVRPT->GetRepeatCount()) {
2002 memcpy(pachInsertion + nInsertionBytes,
2003 poDstVRPT->GetData() + nPtrSize * (nVPIX - 1), nPtrSize);
2004 nInsertionBytes += nPtrSize;
2007 poTarget->SetFieldRaw(poDstVRPT, nVPIX - 1, pachInsertion,
2009 CPLFree(pachInsertion);
2010 }
else if (nVPUI == 2)
2013 for (
int i = nNVPT - 1; i >= 0; i--) {
2014 poTarget->SetFieldRaw(poDstVRPT, i + nVPIX - 1, NULL, 0);
2016 }
else if (nVPUI == 3)
2019 for (
int i = 0; i < nNVPT; i++) {
2020 const char *pachRawData;
2022 pachRawData = poSrcVRPT->GetData() + nPtrSize * i;
2024 poTarget->SetFieldRaw(poDstVRPT, i + nVPIX - 1, pachRawData, nPtrSize);
2032 if (poUpdate->FindField(
"SGCC") != NULL) {
2033 int nCCUI = poUpdate->GetIntSubfield(
"SGCC", 0,
"CCUI", 0);
2034 int nCCIX = poUpdate->GetIntSubfield(
"SGCC", 0,
"CCIX", 0);
2035 int nCCNC = poUpdate->GetIntSubfield(
"SGCC", 0,
"CCNC", 0);
2036 DDFField *poSrcSG2D = poUpdate->FindField(
"SG2D");
2037 DDFField *poDstSG2D = poTarget->FindField(
"SG2D");
2041 if (poDstSG2D == NULL) {
2042 poDstSG2D = poTarget->FindField(
"SG3D");
2043 if (poDstSG2D != NULL) {
2044 poSrcSG2D = poUpdate->FindField(
"SG3D");
2048 if (poDstSG2D == NULL && nCCUI == 2) {
2056 if ((poSrcSG2D == NULL && nCCUI != 2) ||
2057 (poDstSG2D == NULL && nCCUI != 1)) {
2062 if (poDstSG2D == NULL) {
2063 poTarget->AddField(poTarget->GetModule()->FindFieldDefn(
"SG2D"));
2064 poDstSG2D = poTarget->FindField(
"SG2D");
2065 if (poDstSG2D == NULL) {
2071 poTarget->SetFieldRaw(poDstSG2D, 0, NULL, 0);
2074 nCoordSize = poDstSG2D->GetFieldDefn()->GetFixedWidth();
2078 char *pachInsertion;
2079 int nInsertionBytes = nCoordSize * nCCNC;
2081 pachInsertion = (
char *)CPLMalloc(nInsertionBytes + nCoordSize);
2082 memcpy(pachInsertion, poSrcSG2D->GetData(), nInsertionBytes);
2089 if (nCCIX <= poDstSG2D->GetRepeatCount()) {
2090 memcpy(pachInsertion + nInsertionBytes,
2091 poDstSG2D->GetData() + nCoordSize * (nCCIX - 1), nCoordSize);
2092 nInsertionBytes += nCoordSize;
2095 poTarget->SetFieldRaw(poDstSG2D, nCCIX - 1, pachInsertion,
2097 CPLFree(pachInsertion);
2099 }
else if (nCCUI == 2)
2102 for (
int i = nCCNC - 1; i >= 0; i--) {
2103 poTarget->SetFieldRaw(poDstSG2D, i + nCCIX - 1, NULL, 0);
2105 }
else if (nCCUI == 3)
2108 for (
int i = 0; i < nCCNC; i++) {
2109 const char *pachRawData;
2111 pachRawData = poSrcSG2D->GetData() + nCoordSize * i;
2113 poTarget->SetFieldRaw(poDstSG2D, i + nCCIX - 1, pachRawData,
2132 if (poUpdate->FindField(
"ATTF") != NULL) {
2133 bool b_newField =
false;
2134 DDFSubfieldDefn *poSrcATVLDefn;
2135 DDFField *poSrcATTF = poUpdate->FindField(
"ATTF");
2136 DDFField *poDstATTF = poTarget->FindField(
"ATTF");
2138 if (NULL == poDstATTF) {
2143 DDFFieldDefn *poATTF = poTarget->GetModule()->FindFieldDefn(
"ATTF");
2144 poTarget->AddField(poATTF);
2145 poDstATTF = poTarget->FindField(
"ATTF");
2149 int nRepeatCount = poSrcATTF->GetRepeatCount();
2151 poSrcATVLDefn = poSrcATTF->GetFieldDefn()->FindSubfieldDefn(
"ATVL");
2153 for (
int iAtt = 0; iAtt < nRepeatCount; iAtt++) {
2154 int nATTL = poUpdate->GetIntSubfield(
"ATTF", 0,
"ATTL", iAtt);
2155 int iTAtt, nDataBytes;
2156 const char *pszRawData;
2158 for (iTAtt = poDstATTF->GetRepeatCount() - 1; iTAtt >= 0; iTAtt--) {
2159 if (poTarget->GetIntSubfield(
"ATTF", 0,
"ATTL", iTAtt) == nATTL)
break;
2161 if (iTAtt == -1) iTAtt = poDstATTF->GetRepeatCount();
2167 if (poTarget->GetIntSubfield(
"ATTF", 0,
"ATTL", 0) == 0) {
2173 pszRawData = poSrcATTF->GetInstanceData(iAtt, &nDataBytes);
2174 poTarget->SetFieldRaw(poDstATTF, iTAtt, pszRawData, nDataBytes);
2178 if (poUpdate->FindField(
"NATF") != NULL) {
2179 bool b_newField =
false;
2180 DDFSubfieldDefn *poSrcATVLDefn;
2181 DDFField *poSrcATTF = poUpdate->FindField(
"NATF");
2182 DDFField *poDstATTF = poTarget->FindField(
"NATF");
2189 if (NULL == poDstATTF) {
2194 DDFFieldDefn *poNATF = poTarget->GetModule()->FindFieldDefn(
"NATF");
2195 poTarget->AddField(poNATF);
2196 poDstATTF = poTarget->FindField(
"NATF");
2206 int nRepeatCount = poSrcATTF->GetRepeatCount();
2208 poSrcATVLDefn = poSrcATTF->GetFieldDefn()->FindSubfieldDefn(
"ATVL");
2210 for (
int iAtt = 0; iAtt < nRepeatCount; iAtt++) {
2211 int nATTL = poUpdate->GetIntSubfield(
"NATF", 0,
"ATTL", iAtt);
2212 int iTAtt, nDataBytes;
2213 const char *pszRawData;
2215 for (iTAtt = poDstATTF->GetRepeatCount() - 1; iTAtt >= 0; iTAtt--) {
2216 if (poTarget->GetIntSubfield(
"NATF", 0,
"ATTL", iTAtt) == nATTL)
break;
2218 if (iTAtt == -1) iTAtt = poDstATTF->GetRepeatCount();
2224 if (poTarget->GetIntSubfield(
"NATF", 0,
"ATTL", 0) == 0) {
2230 pszRawData = poSrcATTF->GetInstanceData(iAtt, &nDataBytes);
2233 poTarget->SetFieldRaw(poDstATTF, iTAtt, pszRawData, nDataBytes);
2248int S57Reader::ApplyUpdates(DDFModule *poUpdateModule,
int iUpdate)
2251 DDFRecord *poRecord;
2263 while ((poRecord = poUpdateModule->ReadRecord()) != NULL) {
2264 DDFField *poKeyField = poRecord->GetField(1);
2265 const char *pszKey = poKeyField->GetFieldDefn()->GetName();
2267 if (EQUAL(pszKey,
"VRID") || EQUAL(pszKey,
"FRID")) {
2268 int nRCNM = poRecord->GetIntSubfield(pszKey, 0,
"RCNM", 0);
2269 int nRCID = poRecord->GetIntSubfield(pszKey, 0,
"RCID", 0);
2270 int nRVER = poRecord->GetIntSubfield(pszKey, 0,
"RVER", 0);
2271 int nRUIN = poRecord->GetIntSubfield(pszKey, 0,
"RUIN", 0);
2274 if (EQUAL(poKeyField->GetFieldDefn()->GetName(),
"VRID")) {
2277 poIndex = &oVI_Index;
2281 poIndex = &oVC_Index;
2285 poIndex = &oVE_Index;
2289 poIndex = &oVF_Index;
2297 poIndex = &oFE_Index;
2300 if (poIndex != NULL) {
2305 poIndex->AddRecord(nRCID, poRecord->CloneOn(poModule));
2306 }
else if (nRUIN == 2)
2310 DDFRecord *poTarget;
2312 poTarget = poIndex->FindRecord(nRCID);
2313 if (poTarget == NULL) {
2314 CPLError(CE_Warning, CPLE_AppDefined,
2315 "While applying update %d, Can't find RCNM=%d,RCID=%d for "
2317 iUpdate, nRCNM, nRCID);
2318 ret_code = BAD_UPDATE;
2319 }
else if (poTarget->GetIntSubfield(pszKey, 0,
"RVER", 0) !=
2321 CPLError(CE_Warning, CPLE_AppDefined,
2322 "While applying update %d, On RecordRemove, mismatched "
2323 "RVER value for RCNM=%d,RCID=%d...update RVER is %d, "
2324 "target RVER is %d.",
2325 iUpdate, nRCNM, nRCID, nRVER,
2326 poTarget->GetIntSubfield(pszKey, 0,
"RVER", 0));
2328 CE_Warning, CPLE_AppDefined,
2329 "While applying update %d, Removal of RCNM=%d,RCID=%d failed.",
2330 iUpdate, nRCNM, nRCID);
2331 ret_code = BAD_UPDATE;
2334 poIndex->RemoveRecord(nRCID);
2338 else if (nRUIN == 3)
2342 DDFRecord *poTarget;
2344 poTarget = poIndex->FindRecord(nRCID);
2345 if (poTarget == NULL) {
2346 CPLError(CE_Warning, CPLE_AppDefined,
2347 "While applying update %d, Can't find RCNM=%d,RCID=%d for "
2349 iUpdate, nRCNM, nRCID);
2350 ret_code = BAD_UPDATE;
2353 if (!ApplyRecordUpdate(poTarget, poRecord)) {
2354 CPLError(CE_Warning, CPLE_AppDefined,
2355 "While applying update %d, an update to RCNM=%d,RCID=%d "
2357 iUpdate, nRCNM, nRCID);
2358 ret_code = BAD_UPDATE;
2365 else if (EQUAL(pszKey,
"DSID")) {
2367 char *u = (
char *)(poRecord->GetStringSubfield(
"DSID", 0,
"EDTN", 0));
2368 if (!strncmp(u,
"0", 1)) {
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);
2427 ret_code = update_ret;
2449#if defined(__clang__)
2451#elif defined(__GNUC__) || defined(__GNUG__)
2452#pragma GCC push_options
2453#pragma GCC optimize("O0")
2458OGRErr S57Reader::GetExtent(OGREnvelope *psExtent,
int bForce)
2461#define INDEX_COUNT 4
2469 if (!bForce && !bFileIngested)
return OGRERR_FAILURE;
2477 int bGotExtents = FALSE;
2478 double nXMin = 0, nXMax = 0, nYMin = 0, nYMax = 0;
2480 apoIndex[0] = &oVI_Index;
2481 apoIndex[1] = &oVC_Index;
2482 apoIndex[2] = &oVE_Index;
2483 apoIndex[3] = &oVF_Index;
2485 for (
int iIndex = 0; iIndex < INDEX_COUNT; iIndex++) {
2488 for (
int iVIndex = 0; iVIndex < poIndex->GetCount(); iVIndex++) {
2489 DDFRecord *poRecord = poIndex->GetByIndex(iVIndex);
2490 DDFField *poSG3D = poRecord->FindField(
"SG3D");
2491 DDFField *poSG2D = poRecord->FindField(
"SG2D");
2493 if (poSG3D != NULL) {
2494 int i, nVCount = poSG3D->GetRepeatCount();
2495 GInt32 *panData, nX, nY;
2497 panData = (GInt32 *)poSG3D->GetData();
2498 for (i = 0; i < nVCount; i++) {
2499 nX = CPL_LSBWORD32(panData[i * 3 + 1]);
2500 nY = CPL_LSBWORD32(panData[i * 3 + 0]);
2502 double dnX = nX / (double)nCOMF;
2503 double dnY = nY / (double)nCOMF;
2506 nXMin = MIN(nXMin, dnX);
2507 nXMax = MAX(nXMax, dnX);
2508 nYMin = MIN(nYMin, dnY);
2509 nYMax = MAX(nYMax, dnY);
2511 nXMin = nXMax = dnX;
2512 nYMin = nYMax = dnY;
2516 }
else if (poSG2D != NULL) {
2517 int i, nVCount = poSG2D->GetRepeatCount();
2518 GInt32 *panData, nX, nY;
2520 panData = (GInt32 *)poSG2D->GetData();
2521 for (i = 0; i < nVCount; i++) {
2522 nX = CPL_LSBWORD32(panData[i * 2 + 1]);
2523 nY = CPL_LSBWORD32(panData[i * 2 + 0]);
2525 double dnX = nX / (double)nCOMF;
2526 double dnY = nY / (double)nCOMF;
2529 nXMin = MIN(nXMin, dnX);
2530 nXMax = MAX(nXMax, dnX);
2531 nYMin = MIN(nYMin, dnY);
2532 nYMax = MAX(nYMax, dnY);
2534 nXMin = nXMax = dnX;
2535 nYMin = nYMax = dnY;
2544 return OGRERR_FAILURE;
2546 psExtent->MinX = nXMin;
2547 psExtent->MaxX = nXMax;
2548 psExtent->MinY = nYMin;
2549 psExtent->MaxY = nYMax;
2556#if defined(__GNUC__) || defined(__GNUG__)
2557#pragma GCC pop_options
Declarations for classes binding S57 support onto OGRLayer, OGRDataSource and OGRDriver.
Declarations for S-57 translator not including the binding onto OGRLayer/DataSource/Driver which are ...