void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer, int nSurfaceFieldIndex ) { CPLDebug( "OGR_ILI", "Joining surface layer %s with geometries", GetLayerDefn()->GetName()); OGRwkbGeometryType geomType = GetLayerDefn()->GetGeomFieldDefn(nSurfaceFieldIndex)->GetType(); poSurfaceLineLayer->ResetReading(); while (OGRFeature *linefeature = poSurfaceLineLayer->GetNextFeatureRef()) { //OBJE entries with same _RefTID are polygon rings of same feature //TODO: non-numeric _RefTID/FID is not supported yet! GIntBig reftid = linefeature->GetFieldAsInteger64(1); //_RefTID OGRFeature *feature = GetFeatureRef((int)reftid); if (feature) { OGRCurvePolygon *poly; if (feature->GetGeomFieldRef(nSurfaceFieldIndex)) { CPLDebug( "OGR_ILI", "Adding ring to FID " CPL_FRMT_GIB, reftid ); poly = (OGRCurvePolygon *)feature->GetGeomFieldRef(nSurfaceFieldIndex); } else { poly = (geomType == wkbPolygon) ? new OGRPolygon() : new OGRCurvePolygon(); feature->SetGeomFieldDirectly(nSurfaceFieldIndex, poly); } OGRMultiCurve *lines = (OGRMultiCurve*)linefeature->GetGeomFieldRef(0); for( int i = 0; i < lines->getNumGeometries(); i++ ) { OGRCurve *line = (OGRCurve*)lines->getGeometryRef(i); OGRCurve *ring = (geomType == wkbPolygon) ? OGRCurve::CastToLinearRing((OGRCurve*)line->clone()) : (OGRCurve*)line->clone(); poly->addRingDirectly(ring); } } else { CPLError(CE_Warning, CPLE_AppDefined, "Couldn't join feature FID " CPL_FRMT_GIB, reftid ); } } ResetReading(); poSurfaceLineLayer = 0; }
/********************************************************************** * IMapInfoFile::GetNextFeature() * * Standard OGR GetNextFeature implementation. This method is used * to retreive the next OGRFeature. **********************************************************************/ OGRFeature *IMapInfoFile::GetNextFeature() { OGRFeature *poFeatureRef; OGRGeometry *poGeom; int nFeatureId; while( (nFeatureId = GetNextFeatureId(m_nCurFeatureId)) != -1 ) { poFeatureRef = GetFeatureRef(nFeatureId); if (poFeatureRef == NULL) return NULL; else if( (m_poFilterGeom == NULL || ((poGeom = poFeatureRef->GetGeometryRef()) != NULL && FilterGeometry( poGeom ))) && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeatureRef )) ) { // Avoid cloning feature... return the copy owned by the class CPLAssert(poFeatureRef == m_poCurFeature); m_poCurFeature = NULL; return poFeatureRef; } } return NULL; }
/********************************************************************** * IMapInfoFile::GetNextFeature() * * Standard OGR GetNextFeature implementation. This method is used * to retrieve the next OGRFeature. **********************************************************************/ OGRFeature *IMapInfoFile::GetNextFeature() { GIntBig nFeatureId = 0; while( (nFeatureId = GetNextFeatureId(m_nCurFeatureId)) != -1 ) { OGRGeometry *poGeom = nullptr; OGRFeature *poFeatureRef = GetFeatureRef(nFeatureId); if (poFeatureRef == nullptr) return nullptr; else if( (m_poFilterGeom == nullptr || ((poGeom = poFeatureRef->GetGeometryRef()) != nullptr && FilterGeometry( poGeom ))) && (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate( poFeatureRef )) ) { // Avoid cloning feature... return the copy owned by the class CPLAssert(poFeatureRef == m_poCurFeature); m_poCurFeature = nullptr; if( poFeatureRef->GetGeometryRef() != nullptr ) poFeatureRef->GetGeometryRef()->assignSpatialReference(GetSpatialRef()); return poFeatureRef; } } return nullptr; }
/********************************************************************** * IMapInfoFile::GetFeature() * * Standard OGR GetFeature implementation. This method is used * to get the wanted (nFeatureId) feature, a NULL value will be * returned on error. **********************************************************************/ OGRFeature *IMapInfoFile::GetFeature(long nFeatureId) { OGRFeature *poFeatureRef; poFeatureRef = GetFeatureRef(nFeatureId); if (poFeatureRef) { // Avoid cloning feature... return the copy owned by the class CPLAssert(poFeatureRef == m_poCurFeature); m_poCurFeature = NULL; return poFeatureRef; } else return NULL; }
/********************************************************************** * IMapInfoFile::GetFeature() * * Standard OGR GetFeature implementation. This method is used * to get the wanted (nFeatureId) feature, a NULL value will be * returned on error. **********************************************************************/ OGRFeature *IMapInfoFile::GetFeature(GIntBig nFeatureId) { /*fprintf(stderr, "GetFeature(%ld)\n", nFeatureId);*/ OGRFeature *poFeatureRef = GetFeatureRef(nFeatureId); if (poFeatureRef) { // Avoid cloning feature... return the copy owned by the class CPLAssert(poFeatureRef == m_poCurFeature); m_poCurFeature = nullptr; return poFeatureRef; } else return nullptr; }
void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfacePolyLayer, int nSurfaceFieldIndex ) { CPLDebug( "OGR_ILI", "Joining surface layer %s with geometries", GetLayerDefn()->GetName()); poSurfacePolyLayer->ResetReading(); while (OGRFeature *polyfeature = poSurfacePolyLayer->GetNextFeatureRef()) { int reftid = polyfeature->GetFieldAsInteger(1); OGRFeature *feature = GetFeatureRef(reftid); if (feature) { feature->SetGeomField(nSurfaceFieldIndex, polyfeature->GetGeomFieldRef(0)); } else { CPLDebug( "OGR_ILI", "Couldn't join feature FID %d", reftid ); } } ResetReading(); poSurfacePolyLayer = 0; }
/********************************************************************** * IMapInfoFile::GetNextFeature() * * Standard OGR GetNextFeature implementation. This methode is used * to retreive the next OGRFeature. **********************************************************************/ OGRFeature *IMapInfoFile::GetNextFeature() { OGRFeature *poFeatureRef; int nFeatureId; while( (nFeatureId = GetNextFeatureId(m_nCurFeatureId)) != -1 ) { poFeatureRef = GetFeatureRef(nFeatureId); if (poFeatureRef == NULL) return NULL; else if (m_poFilterGeom == NULL || m_poFilterGeom->Intersect( poFeatureRef->GetGeometryRef())) { // Avoid cloning feature... return the copy owned by the class CPLAssert(poFeatureRef == m_poCurFeature); m_poCurFeature = NULL; return poFeatureRef; } } return NULL; }
void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer, int nSurfaceFieldIndex ) { CPLDebug( "OGR_ILI", "Joining surface layer %s with geometries", GetLayerDefn()->GetName()); OGRwkbGeometryType geomType = GetLayerDefn()->GetGeomFieldDefn(nSurfaceFieldIndex)->GetType(); std::map<OGRFeature*, std::vector<OGRCurve*> > oMapFeatureToGeomSet; poSurfaceLineLayer->ResetReading(); // First map: for each target curvepolygon, find all belonging curves while (OGRFeature *linefeature = poSurfaceLineLayer->GetNextFeatureRef()) { //OBJE entries with same _RefTID are polygon rings of same feature OGRFeature *feature = nullptr; if (poFeatureDefn->GetFieldDefn(0)->GetType() == OFTString) { feature = GetFeatureRef(linefeature->GetFieldAsString(1)); } else { GIntBig reftid = linefeature->GetFieldAsInteger64(1); feature = GetFeatureRef(reftid); } if (feature) { OGRGeometry* poGeom = linefeature->GetGeomFieldRef(0); OGRMultiCurve *curves = dynamic_cast<OGRMultiCurve *>(poGeom); if( curves ) { for (auto&& curve: curves ) { if( !curve->IsEmpty() ) oMapFeatureToGeomSet[feature].push_back(curve); } } } else { CPLError( CE_Warning, CPLE_AppDefined, "Couldn't join feature FID " CPL_FRMT_GIB, linefeature->GetFieldAsInteger64(1) ); } } // Now for each target polygon, assemble the curves together. std::map<OGRFeature*, std::vector<OGRCurve*> >::const_iterator oIter = oMapFeatureToGeomSet.begin(); for( ; oIter != oMapFeatureToGeomSet.end(); ++oIter ) { OGRFeature* feature = oIter->first; std::vector<OGRCurve*> oCurves = oIter->second; std::vector<OGRCurve*> oSetDestCurves; double dfLargestArea = 0.0; OGRCurve* poLargestCurve = nullptr; while( true ) { std::vector<OGRCurve*>::iterator oIterCurves = oCurves.begin(); if( oIterCurves == oCurves.end() ) break; OGRPoint endPointCC; OGRCompoundCurve* poCC = new OGRCompoundCurve(); bool bFirst = true; while( true ) { bool bNewCurveAdded = false; const double dfEps = 1e-14; for(oIterCurves = oCurves.begin(); oIterCurves != oCurves.end(); ++oIterCurves ) { OGRCurve* curve = *oIterCurves; OGRPoint startPoint; OGRPoint endPoint; curve->StartPoint(&startPoint); curve->EndPoint(&endPoint); if( bFirst || (fabs(startPoint.getX() - endPointCC.getX()) < dfEps && fabs(startPoint.getY() - endPointCC.getY()) < dfEps) ) { bFirst = false; curve->EndPoint(&endPointCC); const OGRwkbGeometryType eCurveType = wkbFlatten(curve->getGeometryType()); if( eCurveType == wkbCompoundCurve ) { OGRCompoundCurve* poCCSub = curve->toCompoundCurve(); for( auto&& subCurve: poCCSub ) { poCC->addCurve(subCurve); } } else { poCC->addCurve( curve ); } oCurves.erase( oIterCurves ); bNewCurveAdded = true; break; } else if( fabs(endPoint.getX() - endPointCC.getX()) < dfEps && fabs(endPoint.getY() - endPointCC.getY()) < dfEps ) { curve->StartPoint(&endPointCC); const OGRwkbGeometryType eCurveType = wkbFlatten(curve->getGeometryType()); if( eCurveType == wkbLineString || eCurveType == wkbCircularString ) { OGRSimpleCurve* poSC = curve->clone()->toSimpleCurve(); poSC->reversePoints(); poCC->addCurveDirectly( poSC ); } else if( eCurveType == wkbCompoundCurve ) { // Reverse the order of the elements of the // compound curve OGRCompoundCurve* poCCSub = curve->toCompoundCurve(); for( int i=poCCSub->getNumCurves()-1; i >= 0; --i ) { OGRSimpleCurve* poSC = poCCSub->getCurve(i)-> clone()->toSimpleCurve(); poSC->reversePoints(); poCC->addCurveDirectly(poSC); } } oCurves.erase( oIterCurves ); bNewCurveAdded = true; break; } } if( !bNewCurveAdded || oCurves.empty() || poCC->get_IsClosed() ) break; } if( !poCC->get_IsClosed() ) { char* pszJSon = poCC->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "A ring %s for feature " CPL_FRMT_GIB " in layer %s " "was not closed. Dropping it", pszJSon, feature->GetFID(), GetName()); delete poCC; CPLFree(pszJSon); } else { double dfArea = poCC->get_Area(); if( dfArea >= dfLargestArea ) { dfLargestArea = dfArea; poLargestCurve = poCC; } oSetDestCurves.push_back(poCC); } } // Now build the final polygon by first inserting the largest ring. OGRCurvePolygon *poPoly = (geomType == wkbPolygon) ? new OGRPolygon() : new OGRCurvePolygon(); if( poLargestCurve ) { std::vector<OGRCurve*>::iterator oIterCurves = oSetDestCurves.begin(); for( ; oIterCurves != oSetDestCurves.end(); ++oIterCurves ) { OGRCurve* poCurve = *oIterCurves; if( poCurve == poLargestCurve ) { oSetDestCurves.erase( oIterCurves ); break; } } if (geomType == wkbPolygon) { poLargestCurve = OGRCurve::CastToLinearRing(poLargestCurve); } OGRErr error = poPoly->addRingDirectly(poLargestCurve); if (error != OGRERR_NONE) { char* pszJSon = poLargestCurve->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Cannot add ring %s to feature " CPL_FRMT_GIB " in layer %s", pszJSon, feature->GetFID(), GetName() ); CPLFree(pszJSon); } oIterCurves = oSetDestCurves.begin(); for( ; oIterCurves != oSetDestCurves.end(); ++oIterCurves ) { OGRCurve* poCurve = *oIterCurves; if (geomType == wkbPolygon) { poCurve = OGRCurve::CastToLinearRing(poCurve); } error = poPoly->addRingDirectly(poCurve); if (error != OGRERR_NONE) { char* pszJSon = poCurve->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Cannot add ring %s to feature " CPL_FRMT_GIB " in layer %s", pszJSon, feature->GetFID(), GetName() ); CPLFree(pszJSon); } } } feature->SetGeomFieldDirectly(nSurfaceFieldIndex, poPoly); } ResetReading(); }