OGRErr OGRCreateFromGeomedia( GByte *pabyGeom, OGRGeometry **ppoGeom, int nBytes ) { *ppoGeom = NULL; if( nBytes < 16 ) return OGRERR_FAILURE; if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) ) return OGRERR_FAILURE; int nGeomType = pabyGeom[0]; pabyGeom += 16; nBytes -= 16; if( nGeomType == GEOMEDIA_POINT || nGeomType == GEOMEDIA_ORIENTED_POINT ) { if (nBytes < 3 * 8) return OGRERR_FAILURE; double dfX, dfY, dfZ; memcpy(&dfX, pabyGeom, 8); CPL_LSBPTR64(&dfX); memcpy(&dfY, pabyGeom + 8, 8); CPL_LSBPTR64(&dfY); memcpy(&dfZ, pabyGeom + 16, 8); CPL_LSBPTR64(&dfZ); *ppoGeom = new OGRPoint( dfX, dfY, dfZ ); return OGRERR_NONE; } else if ( nGeomType == GEOMEDIA_POLYLINE ) { if (nBytes < 4) return OGRERR_FAILURE; int nPoints; memcpy(&nPoints, pabyGeom, 4); CPL_LSBPTR32(&nPoints); pabyGeom += 4; nBytes -= 4; if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24) return OGRERR_FAILURE; OGRLineString* poLS = new OGRLineString(); poLS->setNumPoints(nPoints); int i; for(i=0;i<nPoints;i++) { double dfX, dfY, dfZ; memcpy(&dfX, pabyGeom, 8); CPL_LSBPTR64(&dfX); memcpy(&dfY, pabyGeom + 8, 8); CPL_LSBPTR64(&dfY); memcpy(&dfZ, pabyGeom + 16, 8); CPL_LSBPTR64(&dfZ); poLS->setPoint(i, dfX, dfY, dfZ); pabyGeom += 24; } *ppoGeom = poLS; return OGRERR_NONE; } else if ( nGeomType == GEOMEDIA_POLYGON ) { if (nBytes < 4) return OGRERR_FAILURE; int nPoints; memcpy(&nPoints, pabyGeom, 4); CPL_LSBPTR32(&nPoints); pabyGeom += 4; nBytes -= 4; if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24) return OGRERR_FAILURE; OGRLinearRing* poRing = new OGRLinearRing(); poRing->setNumPoints(nPoints); int i; for(i=0;i<nPoints;i++) { double dfX, dfY, dfZ; memcpy(&dfX, pabyGeom, 8); CPL_LSBPTR64(&dfX); memcpy(&dfY, pabyGeom + 8, 8); CPL_LSBPTR64(&dfY); memcpy(&dfZ, pabyGeom + 16, 8); CPL_LSBPTR64(&dfZ); poRing->setPoint(i, dfX, dfY, dfZ); pabyGeom += 24; } OGRPolygon* poPoly = new OGRPolygon(); poPoly->addRingDirectly(poRing); *ppoGeom = poPoly; return OGRERR_NONE; } else if ( nGeomType == GEOMEDIA_BOUNDARY ) { if (nBytes < 4) return OGRERR_FAILURE; int nExteriorSize; memcpy(&nExteriorSize, pabyGeom, 4); CPL_LSBPTR32(&nExteriorSize); pabyGeom += 4; nBytes -= 4; if (nBytes < nExteriorSize) return OGRERR_FAILURE; OGRGeometry* poExteriorGeom = NULL; if (OGRCreateFromGeomedia( pabyGeom, &poExteriorGeom, nExteriorSize ) != OGRERR_NONE) return OGRERR_FAILURE; if ( wkbFlatten( poExteriorGeom->getGeometryType() ) != wkbPolygon ) { delete poExteriorGeom; return OGRERR_FAILURE; } pabyGeom += nExteriorSize; nBytes -= nExteriorSize; if (nBytes < 4) { delete poExteriorGeom; return OGRERR_FAILURE; } int nInteriorSize; memcpy(&nInteriorSize, pabyGeom, 4); CPL_LSBPTR32(&nInteriorSize); pabyGeom += 4; nBytes -= 4; if (nBytes < nInteriorSize) { delete poExteriorGeom; return OGRERR_FAILURE; } OGRGeometry* poInteriorGeom = NULL; if (OGRCreateFromGeomedia( pabyGeom, &poInteriorGeom, nInteriorSize ) != OGRERR_NONE) { delete poExteriorGeom; return OGRERR_FAILURE; } OGRwkbGeometryType interiorGeomType = wkbFlatten( poInteriorGeom->getGeometryType() ); if ( interiorGeomType == wkbPolygon ) { ((OGRPolygon*)poExteriorGeom)->addRing(((OGRPolygon*)poInteriorGeom)->getExteriorRing()); } else if ( interiorGeomType == wkbMultiPolygon ) { int numGeom = ((OGRMultiPolygon*)poInteriorGeom)->getNumGeometries(); for ( int i = 0; i < numGeom; ++i ) { OGRPolygon* poInteriorPolygon = (OGRPolygon*)((OGRMultiPolygon*)poInteriorGeom)->getGeometryRef(i); ((OGRPolygon*)poExteriorGeom)->addRing( poInteriorPolygon->getExteriorRing() ); } } else { delete poExteriorGeom; delete poInteriorGeom; return OGRERR_FAILURE; } delete poInteriorGeom; *ppoGeom = poExteriorGeom; return OGRERR_NONE; } else if ( nGeomType == GEOMEDIA_COLLECTION || nGeomType == GEOMEDIA_MULTILINE || nGeomType == GEOMEDIA_MULTIPOLYGON ) { if (nBytes < 4) return OGRERR_FAILURE; int i; int nParts; memcpy(&nParts, pabyGeom, 4); CPL_LSBPTR32(&nParts); pabyGeom += 4; nBytes -= 4; if (nParts < 0 || nParts > INT_MAX / (4 + 16) || nBytes < nParts * (4 + 16)) return OGRERR_FAILURE; /* Can this collection be considered as a multipolyline or multipolygon ? */ if ( nGeomType == GEOMEDIA_COLLECTION ) { GByte* pabyGeomBackup = pabyGeom; int nBytesBackup = nBytes; int bAllPolyline = TRUE; int bAllPolygon = TRUE; for(i=0;i<nParts;i++) { if (nBytes < 4) return OGRERR_FAILURE; int nSubBytes; memcpy(&nSubBytes, pabyGeom, 4); CPL_LSBPTR32(&nSubBytes); if (nSubBytes < 0) { return OGRERR_FAILURE; } pabyGeom += 4; nBytes -= 4; if (nBytes < nSubBytes) { return OGRERR_FAILURE; } if( nSubBytes < 16 ) return OGRERR_FAILURE; if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) ) return OGRERR_FAILURE; int nSubGeomType = pabyGeom[0]; if ( nSubGeomType != GEOMEDIA_POLYLINE ) bAllPolyline = FALSE; if ( nSubGeomType != GEOMEDIA_POLYGON ) bAllPolygon = FALSE; pabyGeom += nSubBytes; nBytes -= nSubBytes; } pabyGeom = pabyGeomBackup; nBytes = nBytesBackup; if (bAllPolyline) nGeomType = GEOMEDIA_MULTILINE; else if (bAllPolygon) nGeomType = GEOMEDIA_MULTIPOLYGON; } OGRGeometryCollection* poColl = (nGeomType == GEOMEDIA_MULTILINE) ? new OGRMultiLineString() : (nGeomType == GEOMEDIA_MULTIPOLYGON) ? new OGRMultiPolygon() : new OGRGeometryCollection(); for(i=0;i<nParts;i++) { if (nBytes < 4) return OGRERR_FAILURE; int nSubBytes; memcpy(&nSubBytes, pabyGeom, 4); CPL_LSBPTR32(&nSubBytes); if (nSubBytes < 0) { delete poColl; return OGRERR_FAILURE; } pabyGeom += 4; nBytes -= 4; if (nBytes < nSubBytes) { delete poColl; return OGRERR_FAILURE; } OGRGeometry* poSubGeom = NULL; if (OGRCreateFromGeomedia( pabyGeom, &poSubGeom, nSubBytes ) == OGRERR_NONE) { if (wkbFlatten(poColl->getGeometryType()) == wkbMultiPolygon && wkbFlatten(poSubGeom->getGeometryType()) == wkbLineString) { OGRPolygon* poPoly = new OGRPolygon(); OGRLinearRing* poRing = new OGRLinearRing(); poRing->addSubLineString((OGRLineString*)poSubGeom); poPoly->addRingDirectly(poRing); delete poSubGeom; poSubGeom = poPoly; } if (poColl->addGeometryDirectly(poSubGeom) != OGRERR_NONE) { //printf("%d %d\n", poColl->getGeometryType() & ~wkb25DBit, poSubGeom->getGeometryType() & ~wkb25DBit); delete poSubGeom; } } pabyGeom += nSubBytes; nBytes -= nSubBytes; } *ppoGeom = poColl; return OGRERR_NONE; } else { CPLDebug("GEOMEDIA", "Unhandled type %d", nGeomType); } return OGRERR_FAILURE; }
OGRFeature *OGRSOSILayer::GetNextFeature() { short nName, nNumLines; long nNumCoo; unsigned short nInfo; /* iterate through the SOSI groups*/ while (LC_NextBgr(poNextSerial,LC_FRAMGR)) { nName = LC_RxGr(&oNextSerial, LES_OPTIMALT, &nNumLines, &nNumCoo, &nInfo); S2S oHeaders; S2S::iterator iHeaders; /* extract reference strings from group header */ CPLString osKey, osValue; for (short i=1; i<=nNumLines; i++) { char *pszLine = LC_GetGi(i); if (pszLine[0] == '!') continue; /* If we have a comment line, skip it. */ if ((pszLine[0] == ':')||(pszLine[0] == '(')) { /* if we have a continued REF line... */ osValue.append(CPLString(pszLine)); /* append to previous line. */ oHeaders.insert(std::pair<CPLString,CPLString>(osKey,osValue)); continue; } while (pszLine[0] == '.') pszLine++; /* skipping the dots at the beginning of a SOSI line */ char *pszUTFLine = CPLRecode(pszLine, poParent->pszEncoding, CPL_ENC_UTF8); /* switch to UTF encoding here */ char *pszPos = strstr(pszUTFLine, " "); if (pszPos != NULL) { osKey = CPLString(std::string(pszUTFLine,pszPos)); osValue = CPLString(pszPos+1); oHeaders.insert(std::pair<CPLString,CPLString>(osKey,osValue)); } CPLFree(pszUTFLine); } /* get Feature from fyba, according to feature definition */ OGRGeometry *poGeom = NULL; OGRwkbGeometryType oGType = wkbUnknown; switch (nName) { case INGEN_GRUPPE: { /* No group */ CPLDebug( "[GetNextFeature]", "Could not load further groups - FYBA reported INGEN_GRUPPE."); break; } case L_FLATE: { /* Area */ oGType = wkbPolygon; OGRLinearRing *poOuter = new OGRLinearRing(); /* Initialize a new closed polygon */ long nRefNr; unsigned char nRefStatus; long nRefCount; bool correct = true; LC_GRF_STATUS oGrfStat; // Iterate through all objects that constitute this area. LC_InitGetRefFlate(&oGrfStat); nRefCount = LC_GetRefFlate(&oGrfStat, GRF_YTRE, &nRefNr, &nRefStatus, 1); while (nRefCount > 0) { if (poParent->papoBuiltGeometries[nRefNr] == NULL) { // This should not happen under normal operation. CPLError( CE_Warning, CPLE_AppDefined, "Feature %li referenced by %li, but it was not initialized. Geometry may be broken.", nRefNr, oNextSerial.lNr); correct = false; //return NULL; break; } OGRGeometry *geom = poParent->papoBuiltGeometries[nRefNr]; if (geom->getGeometryType() == wkbLineString) { OGRLineString *poCurve = (OGRLineString*)geom; if (nRefStatus == LC_MED_DIG) { /* clockwise */ poOuter->addSubLineString(poCurve); } else if (nRefStatus == LC_MOT_DIG) { /* counter-clockwise */ poOuter->addSubLineString(poCurve,poCurve->getNumPoints()-1,0); } else { CPLError( CE_Failure, CPLE_OpenFailed, "Internal error: GRF_*_OY encountered."); return NULL; } } else { CPLError( CE_Warning, CPLE_AppDefined, "Element %li composed of non-linestrings (REF %li of type %i). Ignored.", oNextSerial.lNr, nRefNr, geom->getGeometryType()); } nRefCount = LC_GetRefFlate(&oGrfStat, GRF_YTRE, &nRefNr, &nRefStatus, 1); } if (correct) { OGRPolygon *poLy = new OGRPolygon(); poOuter->closeRings(); poLy->addRingDirectly(poOuter); OGRLinearRing *poInner = 0; nRefCount = LC_GetRefFlate(&oGrfStat, GRF_INDRE, &nRefNr, &nRefStatus, 1); while (nRefCount > 0) { if (nRefNr == -1) { if (poInner && (poInner->getNumPoints()>2)) { /* If this is not the first polygon, terminate and add the last */ poInner->closeRings(); poLy->addRingDirectly(poInner); } poInner = new OGRLinearRing(); /* Initialize a new closed polygon */ } else { if (poParent->papoBuiltGeometries[nRefNr] == NULL) { /* this shouldn't happen under normal operation */ CPLError( CE_Fatal, CPLE_AppDefined, "Feature %li referenced by %li, but it was not initialized.", nRefNr, oNextSerial.lNr); return NULL; } OGRGeometry *geom = poParent->papoBuiltGeometries[nRefNr]; if (geom->getGeometryType() == wkbLineString) { OGRLineString *poCurve = (OGRLineString*)geom; if (nRefStatus == LC_MED_DIG) { /* clockwise */ poInner->addSubLineString(poCurve); } else if (nRefStatus == LC_MOT_DIG) { /* counter-clockwise */ poInner->addSubLineString(poCurve,poCurve->getNumPoints()-1,0); } else { CPLError( CE_Failure, CPLE_OpenFailed, "Internal error: GRF_*_OY encountered."); return NULL; } } else { CPLError( CE_Warning, CPLE_AppDefined, "Element %li composed of non-linestrings (REF %li of type %i). Ignored.", oNextSerial.lNr, nRefNr, geom->getGeometryType()); } } nRefCount = LC_GetRefFlate(&oGrfStat, GRF_INDRE, &nRefNr, &nRefStatus, 1); } poGeom = poLy; } break; } case L_KURVE: /* curve */ case L_LINJE: /* curve, not simplifyable */ case L_BUEP: { /* curve, interpolated from circular arc */ oGType = wkbLineString; OGRLineString *poCurve = (OGRLineString*)(poParent->papoBuiltGeometries[oNextSerial.lNr]); if (poCurve == NULL) { CPLError( CE_Fatal, CPLE_AppDefined, "Curve %li was not initialized.", oNextSerial.lNr); return NULL; } poGeom = poCurve->clone(); break; } case L_TEKST: { /* text */ oGType = wkbMultiPoint; OGRMultiPoint *poMP = (OGRMultiPoint*)(poParent->papoBuiltGeometries[oNextSerial.lNr]); if (poMP == NULL) { CPLError( CE_Fatal, CPLE_AppDefined, "Tekst %li was not initialized.", oNextSerial.lNr); return NULL; } poGeom = poMP->clone(); break; } case L_SYMBOL: { //CPLError( CE_Warning, CPLE_OpenFailed, "Geometry of type SYMBOL treated as point (PUNKT)."); } case L_PUNKT: { /* point */ oGType = wkbPoint; OGRPoint *poPoint = (OGRPoint*)(poParent->papoBuiltGeometries[oNextSerial.lNr]); if (poPoint == NULL) { CPLError( CE_Fatal, CPLE_AppDefined, "Point %li was not initialized.", oNextSerial.lNr); return NULL; } poGeom = poPoint->clone(); break; } case L_DEF: /* skip user definitions and headers here */ case L_HODE: { break; } default: { /* complain a bit about anything else that is not implemented */ CPLError( CE_Failure, CPLE_OpenFailed, "Unrecognized geometry of type %i.", nName); break; } } if (poGeom == NULL) continue; /* skipping L_HODE and unrecognized groups */ if (oGType != poFeatureDefn->GetGeomType()) { if (poGeom != NULL) delete poGeom; continue; /* skipping features that are not the correct geometry */ } OGRFeature *poFeature = new OGRFeature( poFeatureDefn ); /* set all headers found in this group - we export everything, just in case */ for (iHeaders = oHeaders.begin(); iHeaders != oHeaders.end(); iHeaders++) { OGRSOSIDataType *poType = SOSIGetType(iHeaders->first); OGRSOSISimpleDataType *poElements = poType->getElements(); const char *pszLine = iHeaders->second.c_str(); char** tokens = CSLTokenizeString(iHeaders->second.c_str()); for (int k=0; k<poType->getElementCount(); k++) { if (tokens[k] == 0) break; if (strcmp(poElements[k].GetName(),"")==0) continue; int iHNr = poHeaderDefn->find(poElements[k].GetName())->second; if (iHNr == -1) { CPLError( CE_Warning, CPLE_AppDefined, "Could not find field definition for %s.", poElements[k].GetName()); continue; } OGRFieldType nType = poElements[k].GetType(); switch (nType) { case OFTInteger: { poFeature->SetField( iHNr, SOSITypeToInt(tokens[k])); break; } case OFTDate: { int date[3]; SOSITypeToDate(tokens[k], date); poFeature->SetField( iHNr, date[0], date[1], date[2]); break; } case OFTDateTime: { int date[6]; SOSITypeToDateTime(tokens[k], date); if (date[0]>0) poFeature->SetField( iHNr, date[0], date[1], date[2], date[3], date[4], static_cast<float>(date[5]), 1); break; } case OFTReal: { poFeature->SetField( iHNr, SOSITypeToReal(tokens[k])); break; } default: { if ((k==0)&&((pszLine[0] == '\'')||(pszLine[0] == '\"'))) { /* If the value is quoted, ignore these */ int nLen = static_cast<int>(strlen(pszLine)); char *pszNline = (char*)CPLMalloc(nLen-1); strncpy(pszNline, pszLine+1, nLen-2); pszNline[nLen-2] = '\0'; poFeature->SetField( iHNr, pszNline); CPLFree(pszNline); } else { poFeature->SetField( iHNr, tokens[k]); } break; } } } CSLDestroy(tokens); } if( poGeom != NULL ) poGeom->assignSpatialReference(poParent->poSRS); poFeature->SetGeometryDirectly( poGeom ); poFeature->SetFID( nNextFID++ ); /* Loop until we have a feature that matches the definition */ if ( (m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) ) return poFeature; delete poFeature; } return NULL; }