void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType, OGRFeature *feature ) { #ifdef DEBUG_VERBOSE CPLDebug( "OGR_ILI", "ILI1Reader::ReadGeom geomIdx: %d OGRGeometryType: %s", geomIdx, OGRGeometryTypeToName(eType) ); #endif if (eType == wkbNone) { CPLError( CE_Warning, CPLE_AppDefined, "Calling ILI1Reader::ReadGeom with wkbNone" ); } // Initialize geometry. OGRCompoundCurve *ogrCurve = new OGRCompoundCurve(); OGRCurvePolygon *ogrPoly = NULL; //current polygon OGRMultiCurve *ogrMultiLine = NULL; //current multi line if (eType == wkbMultiCurve || eType == wkbMultiLineString) { ogrMultiLine = new OGRMultiCurve(); } else if (eType == wkbPolygon || eType == wkbCurvePolygon) { ogrPoly = new OGRCurvePolygon(); } OGRPoint ogrPoint; // Current point. ogrPoint.setX(CPLAtof(stgeom[1])); ogrPoint.setY(CPLAtof(stgeom[2])); OGRLineString *ogrLine = new OGRLineString(); ogrLine->addPoint(&ogrPoint); // Parse geometry. char **tokens = NULL; bool end = false; OGRCircularString *arc = NULL; //current arc while (!end && (tokens = ReadParseLine()) != NULL) { const char *firsttok = CSLGetField(tokens, 0); if( firsttok == NULL ) { // do nothing } else if (EQUAL(firsttok, "LIPT") && CSLCount(tokens) >= 3) { ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2])); if (arc) { arc->addPoint(&ogrPoint); OGRErr error = ogrCurve->addCurveDirectly(arc); if (error != OGRERR_NONE) { char* pszJSon = arc->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s", pszJSon ? pszJSon : "(null)" ); CPLFree(pszJSon); delete arc; } arc = NULL; } ogrLine->addPoint(&ogrPoint); } else if (EQUAL(firsttok, "ARCP") && CSLCount(tokens) >= 3) { //Finish line and start arc if (ogrLine->getNumPoints() > 1) { OGRErr error = ogrCurve->addCurveDirectly(ogrLine); if (error != OGRERR_NONE) { char* pszJSon = ogrLine->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s", pszJSon ? pszJSon : "(null)" ); CPLFree(pszJSon); delete ogrLine; } ogrLine = new OGRLineString(); } else { ogrLine->empty(); } delete arc; arc = new OGRCircularString(); arc->addPoint(&ogrPoint); ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2])); arc->addPoint(&ogrPoint); } else if (EQUAL(firsttok, "ELIN")) { if (ogrLine->getNumPoints() > 1) { // Ignore single LIPT after ARCP OGRErr error = ogrCurve->addCurveDirectly(ogrLine); if (error != OGRERR_NONE) { char* pszJSon = ogrLine->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s", pszJSon ? pszJSon : "(null)" ); CPLFree(pszJSon); delete ogrLine; } ogrLine = NULL; } if (!ogrCurve->IsEmpty()) { if (ogrMultiLine) { OGRErr error = ogrMultiLine->addGeometryDirectly(ogrCurve); if (error != OGRERR_NONE) { char* pszJSon = ogrCurve->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s", pszJSon ? pszJSon : "(null)" ); CPLFree(pszJSon); delete ogrCurve; } ogrCurve = NULL; } if (ogrPoly) { OGRErr error = ogrPoly->addRingDirectly(ogrCurve); if (error != OGRERR_NONE) { char* pszJSon = ogrCurve->exportToJson(); CPLError(CE_Warning, CPLE_AppDefined, "Could not add geometry: %s", pszJSon ? pszJSon : "(null)" ); CPLFree(pszJSon); delete ogrCurve; } ogrCurve = NULL; } } end = true; } else if (EQUAL(firsttok, "EEDG")) { end = true; } else if (EQUAL(firsttok, "LATT")) { //Line Attributes (ignored) } else if (EQUAL(firsttok, "EFLA")) { end = true; } else if (EQUAL(firsttok, "ETAB")) { end = true; } else { CPLError( CE_Warning, CPLE_AppDefined, "Unexpected token: %s", firsttok ); } CSLDestroy(tokens); } delete arc; delete ogrLine; //Set feature geometry if (eType == wkbMultiCurve) { feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine); delete ogrCurve; } else if (eType == wkbMultiLineString) { feature->SetGeomFieldDirectly(geomIdx, ogrMultiLine->getLinearGeometry()); delete ogrMultiLine; delete ogrCurve; } else if (eType == wkbCurvePolygon) { feature->SetGeomFieldDirectly(geomIdx, ogrPoly); delete ogrCurve; } else if (eType == wkbPolygon) { feature->SetGeomFieldDirectly(geomIdx, ogrPoly->getLinearGeometry()); delete ogrPoly; delete ogrCurve; } else { feature->SetGeomFieldDirectly(geomIdx, ogrCurve); } }
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(); }