EVOLUTION-MANAGER
Edit File: ogredigeodatasource.cpp
/****************************************************************************** * * Project: EDIGEO Translator * Purpose: Implements OGREDIGEODataSource class * Author: Even Rouault, even dot rouault at mines dash paris dot org * ****************************************************************************** * Copyright (c) 2011, Even Rouault <even dot rouault at mines-paris dot org> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "ogr_edigeo.h" #include "cpl_conv.h" #include "cpl_string.h" CPL_CVSID("$Id: ogredigeodatasource.cpp 36981 2016-12-20 19:46:41Z rouault $"); /************************************************************************/ /* OGREDIGEODataSource() */ /************************************************************************/ OGREDIGEODataSource::OGREDIGEODataSource() : pszName(NULL), fpTHF(NULL), papoLayers(NULL), nLayers(0), poSRS(NULL), bExtentValid(FALSE), dfMinX(0), dfMinY(0), dfMaxX(0), dfMaxY(0), bRecodeToUTF8( CPLTestBool(CPLGetConfigOption("OGR_EDIGEO_RECODE_TO_UTF8", "YES"))), bHasUTF8ContentOnly(TRUE), iATR(-1), iDI3(-1), iDI4(-1), iHEI(-1), iFON(-1), iATR_VAL(-1), iANGLE(-1), iSIZE(-1), iOBJ_LNK(-1), iOBJ_LNK_LAYER(-1), dfSizeFactor(CPLAtof( CPLGetConfigOption("OGR_EDIGEO_FONT_SIZE_FACTOR", "2"))), bIncludeFontFamily(CPLTestBool( CPLGetConfigOption("OGR_EDIGEO_INCLUDE_FONT_FAMILY", "YES"))), bHasReadEDIGEO(FALSE) { if (dfSizeFactor <= 0 || dfSizeFactor >= 100) dfSizeFactor = 2; } /************************************************************************/ /* ~OGREDIGEODataSource() */ /************************************************************************/ OGREDIGEODataSource::~OGREDIGEODataSource() { for( int i = 0; i < nLayers; i++ ) delete papoLayers[i]; CPLFree( papoLayers ); CPLFree( pszName ); if (fpTHF) VSIFCloseL(fpTHF); if (poSRS) poSRS->Release(); } /************************************************************************/ /* TestCapability() */ /************************************************************************/ int OGREDIGEODataSource::TestCapability( CPL_UNUSED const char * pszCap ) { return FALSE; } /************************************************************************/ /* GetLayer() */ /************************************************************************/ OGRLayer *OGREDIGEODataSource::GetLayer( int iLayer ) { ReadEDIGEO(); if( iLayer < 0 || iLayer >= nLayers ) return NULL; else return papoLayers[iLayer]; } /************************************************************************/ /* GetLayerCount() */ /************************************************************************/ int OGREDIGEODataSource::GetLayerCount() { ReadEDIGEO(); return nLayers; } /************************************************************************/ /* ReadTHF() */ /************************************************************************/ int OGREDIGEODataSource::ReadTHF(VSILFILE* fp) { const char* pszLine = NULL; while((pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL) { if (strlen(pszLine) < 8 || pszLine[7] != ':') continue; /* Cf Z 52000 tableau 56 for field list*/ if (STARTS_WITH(pszLine, "LONSA")) { if (!osLON.empty()) { CPLDebug("EDIGEO", "We only handle one lot per THF file"); break; } osLON = pszLine + 8; } else if (STARTS_WITH(pszLine, "GNNSA")) osGNN = pszLine + 8; else if (STARTS_WITH(pszLine, "GONSA")) osGON = pszLine + 8; else if (STARTS_WITH(pszLine, "QANSA")) osQAN = pszLine + 8; else if (STARTS_WITH(pszLine, "DINSA")) osDIN = pszLine + 8; else if (STARTS_WITH(pszLine, "SCNSA")) osSCN = pszLine + 8; else if (STARTS_WITH(pszLine, "GDNSA")) aosGDN.push_back(pszLine + 8); } if (osLON.empty()) { CPLDebug("EDIGEO", "LON field missing"); return 0; } if (osGON.empty()) { CPLDebug("EDIGEO", "GON field missing"); return 0; } if (osDIN.empty()) { CPLDebug("EDIGEO", "DIN field missing"); return 0; } if (osSCN.empty()) { CPLDebug("EDIGEO", "SCN field missing"); return FALSE; } CPLDebug("EDIGEO", "LON = %s", osLON.c_str()); CPLDebug("EDIGEO", "GNN = %s", osGNN.c_str()); CPLDebug("EDIGEO", "GON = %s", osGON.c_str()); CPLDebug("EDIGEO", "QAN = %s", osQAN.c_str()); CPLDebug("EDIGEO", "DIN = %s", osDIN.c_str()); CPLDebug("EDIGEO", "SCN = %s", osSCN.c_str()); for(int i=0;i<(int)aosGDN.size();i++) CPLDebug("EDIGEO", "GDN[%d] = %s", i, aosGDN[i].c_str()); return TRUE; } /************************************************************************/ /* OpenFile() */ /************************************************************************/ VSILFILE* OGREDIGEODataSource::OpenFile(const char *pszType, const CPLString& osExt) { CPLString osTmp = osLON + pszType; CPLString osFilename = CPLFormCIFilename(CPLGetPath(pszName), osTmp.c_str(), osExt.c_str()); VSILFILE* fp = VSIFOpenL(osFilename, "rb"); if (fp == NULL) { CPLString osExtLower = osExt; for(int i=0;i<(int)osExt.size();i++) osExtLower[i] = (char)tolower(osExt[i]); CPLString osFilename2 = CPLFormCIFilename(CPLGetPath(pszName), osTmp.c_str(), osExtLower.c_str()); fp = VSIFOpenL(osFilename2, "rb"); if (fp == NULL) { CPLDebug("EDIGEO", "Cannot open %s", osFilename.c_str()); } } return fp; } /************************************************************************/ /* ReadGEO() */ /************************************************************************/ int OGREDIGEODataSource::ReadGEO() { VSILFILE* fp = OpenFile(osGON, "GEO"); if (fp == NULL) return FALSE; const char* pszLine = NULL; while( (pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL ) { if (strlen(pszLine) < 8 || pszLine[7] != ':') continue; if (STARTS_WITH(pszLine, "RELSA")) { osREL = pszLine + 8; CPLDebug("EDIGEO", "REL = %s", osREL.c_str()); break; } } VSIFCloseL(fp); if (osREL.empty()) { CPLDebug("EDIGEO", "REL field missing"); return FALSE; } /* All the SRS names mentioned in B.8.2.3 and B.8.3.1 are in the IGN file */ poSRS = new OGRSpatialReference(); CPLString osProj4Str = "+init=IGNF:" + osREL; if (poSRS->SetFromUserInput(osProj4Str.c_str()) != OGRERR_NONE) { /* Hard code a few common cases */ if (osREL == "LAMB1") poSRS->importFromProj4("+proj=lcc +lat_1=49.5 +lat_0=49.5 +lon_0=0 +k_0=0.99987734 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs"); else if (osREL == "LAMB2") poSRS->importFromProj4("+proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs"); else if (osREL == "LAMB3") poSRS->importFromProj4("+proj=lcc +lat_1=44.1 +lat_0=44.1 +lon_0=0 +k_0=0.9998775 +x_0=600000 +y_0=200000 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs"); else if (osREL == "LAMB4") poSRS->importFromProj4("+proj=lcc +lat_1=42.165 +lat_0=42.165 +lon_0=0 +k_0=0.99994471 +x_0=234.358 +y_0=185861.369 +a=6378249.2 +b=6356514.999978254 +nadgrids=ntf_r93.gsb,null +pm=paris +units=m +no_defs"); else if (osREL == "LAMB93") poSRS->importFromProj4("+proj=lcc +lat_1=44 +lat_2=49 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS81 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"); else { CPLDebug("EDIGEO", "Cannot resolve %s SRS. Check that the IGNF file is in the directory of PROJ.4 resource files", osREL.c_str()); delete poSRS; poSRS = NULL; } } return TRUE; } /************************************************************************/ /* ReadGEN() */ /************************************************************************/ int OGREDIGEODataSource::ReadGEN() { VSILFILE* fp = OpenFile(osGNN, "GEN"); if (fp == NULL) return FALSE; const char* pszLine = NULL; CPLString osCM1; CPLString osCM2; while( (pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL ) { if (strlen(pszLine) < 8 || pszLine[7] != ':') continue; if (STARTS_WITH(pszLine, "CM1CC")) { osCM1 = pszLine + 8; } else if (STARTS_WITH(pszLine, "CM2CC")) { osCM2 = pszLine + 8; } } VSIFCloseL(fp); if (osCM1.empty() || osCM2.empty()) return FALSE; char** papszTokens1 = CSLTokenizeString2(osCM1.c_str(), ";", 0); char** papszTokens2 = CSLTokenizeString2(osCM2.c_str(), ";", 0); if (CSLCount(papszTokens1) == 2 && CSLCount(papszTokens2) == 2) { bExtentValid = TRUE; dfMinX = CPLAtof(papszTokens1[0]); dfMinY = CPLAtof(papszTokens1[1]); dfMaxX = CPLAtof(papszTokens2[0]); dfMaxY = CPLAtof(papszTokens2[1]); } CSLDestroy(papszTokens1); CSLDestroy(papszTokens2); return bExtentValid; } /************************************************************************/ /* ReadDIC() */ /************************************************************************/ int OGREDIGEODataSource::ReadDIC() { VSILFILE* fp = OpenFile(osDIN, "DIC"); if (fp == NULL) return FALSE; const char* pszLine = NULL; CPLString osRTY; CPLString osRID; CPLString osLAB; CPLString osTYP; while( true ) { pszLine = CPLReadLine2L(fp, 81, NULL); if (pszLine != NULL) { if (strlen(pszLine) < 8 || pszLine[7] != ':') continue; } if (pszLine == NULL || STARTS_WITH(pszLine, "RTYSA")) { if (osRTY == "DID") { //CPLDebug("EDIGEO", "Object %s = %s", // osRID.c_str(), osLAB.c_str()); mapObjects[osRID] = osLAB; } else if (osRTY == "DIA") { //CPLDebug("EDIGEO", "Attribute %s = %s, %s", // osRID.c_str(), osLAB.c_str(), osTYP.c_str()); OGREDIGEOAttributeDef sAttributeDef; sAttributeDef.osLAB = osLAB; sAttributeDef.osTYP = osTYP; mapAttributes[osRID] = sAttributeDef; } if (pszLine == NULL) break; osRTY = pszLine + 8; osRID = ""; osLAB = ""; osTYP = ""; } if (STARTS_WITH(pszLine, "RIDSA")) osRID = pszLine + 8; else if (STARTS_WITH(pszLine, "LABSA")) osLAB = pszLine + 8; else if (STARTS_WITH(pszLine, "TYPSA")) osTYP = pszLine + 8; } VSIFCloseL(fp); return TRUE; } /************************************************************************/ /* ReadSCD() */ /************************************************************************/ int OGREDIGEODataSource::ReadSCD() { VSILFILE* fp = OpenFile(osSCN, "SCD"); if (fp == NULL) return FALSE; const char* pszLine = NULL; CPLString osRTY, osRID, osNameRID, osKND; strListType aosAttrRID; int nWidth = 0; while( true ) { pszLine = CPLReadLine2L(fp, 81, NULL); if (pszLine != NULL) { if (strlen(pszLine) < 8 || pszLine[7] != ':') continue; } if (pszLine == NULL || STARTS_WITH(pszLine, "RTYSA")) { if (osRTY == "OBJ") { if (mapObjects.find(osNameRID) == mapObjects.end()) { CPLDebug("EDIGEO", "Cannot find object %s", osNameRID.c_str()); } else { OGREDIGEOObjectDescriptor objDesc; objDesc.osRID = osRID; objDesc.osNameRID = osNameRID; objDesc.osKND = osKND; objDesc.aosAttrRID = aosAttrRID; /*CPLDebug("EDIGEO", "Object %s = %s, %s, %d attributes", osRID.c_str(), osNameRID.c_str(), osKND.c_str(), (int)aosAttrRID.size());*/ aoObjList.push_back(objDesc); } } else if (osRTY == "ATT") { if (mapAttributes.find(osNameRID) == mapAttributes.end()) { CPLDebug("EDIGEO", "Cannot find attribute %s", osNameRID.c_str()); } else { OGREDIGEOAttributeDescriptor attDesc; attDesc.osRID = osRID; attDesc.osNameRID = osNameRID; attDesc.nWidth = nWidth; /*CPLDebug("EDIGEO", "Attribute %s = %s, %d", osRID.c_str(), osNameRID.c_str(), nWidth);*/ mapAttributesSCD[osRID] = attDesc; } } if (pszLine == NULL) break; osRTY = pszLine + 8; osRID = ""; osNameRID = ""; osKND = ""; aosAttrRID.resize(0); nWidth = 0; } if (STARTS_WITH(pszLine, "RIDSA")) osRID = pszLine + 8; else if (STARTS_WITH(pszLine, "DIPCP")) { const char* pszDIP = pszLine + 8; char** papszTokens = CSLTokenizeString2(pszDIP, ";", 0); if (CSLCount(papszTokens) == 4) { osNameRID = papszTokens[3]; } CSLDestroy(papszTokens); } else if (STARTS_WITH(pszLine, "KNDSA")) osKND = pszLine + 8; else if (STARTS_WITH(pszLine, "AAPCP")) { const char* pszAAP = pszLine + 8; char** papszTokens = CSLTokenizeString2(pszAAP, ";", 0); if (CSLCount(papszTokens) == 4) { const char* pszAttRID = papszTokens[3]; aosAttrRID.push_back(pszAttRID); } CSLDestroy(papszTokens); } else if (STARTS_WITH(pszLine, "CANSN")) nWidth = atoi(pszLine + 8); } VSIFCloseL(fp); return TRUE; } /************************************************************************/ /* ReadQAL() */ /************************************************************************/ int OGREDIGEODataSource::ReadQAL() { VSILFILE* fp = OpenFile(osQAN, "QAL"); if (fp == NULL) return FALSE; const char* pszLine = NULL; CPLString osRTY; CPLString osRID; int nODA = 0; int nUDA = 0; while( true ) { pszLine = CPLReadLine2L(fp, 81, NULL); if (pszLine != NULL) { if (strlen(pszLine) < 8 || pszLine[7] != ':') continue; } if (pszLine == NULL || STARTS_WITH(pszLine, "RTYSA")) { if (osRTY == "QUP") { mapQAL[osRID] = intintType(nODA, nUDA); } if (pszLine == NULL) break; osRTY = pszLine + 8; osRID = ""; nODA = 0; nUDA = 0; } else if (STARTS_WITH(pszLine, "RIDSA")) osRID = pszLine + 8; else if (STARTS_WITH(pszLine, "ODASD")) nODA = atoi(pszLine + 8); else if (STARTS_WITH(pszLine, "UDASD")) nUDA = atoi(pszLine + 8); } VSIFCloseL(fp); return TRUE; } /************************************************************************/ /* CreateLayerFromObjectDesc() */ /************************************************************************/ int OGREDIGEODataSource::CreateLayerFromObjectDesc(const OGREDIGEOObjectDescriptor& objDesc) { OGRwkbGeometryType eType = wkbUnknown; if (objDesc.osKND == "ARE") eType = wkbPolygon; else if (objDesc.osKND == "LIN") eType = wkbLineString; else if (objDesc.osKND == "PCT") eType = wkbPoint; else { CPLDebug("EDIGEO", "Unknown KND : %s", objDesc.osKND.c_str()); return FALSE; } const char* pszLayerName = objDesc.osRID.c_str(); //mapObjects.find(objDesc.osNameRID)->second.c_str(); OGREDIGEOLayer* poLayer = new OGREDIGEOLayer(this, pszLayerName, eType, poSRS); poLayer->AddFieldDefn("OBJECT_RID", OFTString, ""); for(int j=0;j<(int)objDesc.aosAttrRID.size();j++) { std::map<CPLString,OGREDIGEOAttributeDescriptor>::iterator it = mapAttributesSCD.find(objDesc.aosAttrRID[j]); if (it != mapAttributesSCD.end()) { const OGREDIGEOAttributeDescriptor& attrDesc = it->second; const OGREDIGEOAttributeDef& attrDef = mapAttributes[attrDesc.osNameRID]; OGRFieldType eFieldType = OFTString; if (attrDef.osTYP == "R" || attrDef.osTYP == "E") eFieldType = OFTReal; else if (attrDef.osTYP == "I" || attrDef.osTYP == "N") eFieldType = OFTInteger; poLayer->AddFieldDefn(attrDef.osLAB, eFieldType, objDesc.aosAttrRID[j]); } } if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") == 0) { OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn(); iATR = poFDefn->GetFieldIndex("ATR"); iDI3 = poFDefn->GetFieldIndex("DI3"); iDI4 = poFDefn->GetFieldIndex("DI4"); iHEI = poFDefn->GetFieldIndex("HEI"); iFON = poFDefn->GetFieldIndex("FON"); poLayer->AddFieldDefn("OGR_OBJ_LNK", OFTString, ""); iOBJ_LNK = poFDefn->GetFieldIndex("OGR_OBJ_LNK"); poLayer->AddFieldDefn("OGR_OBJ_LNK_LAYER", OFTString, ""); iOBJ_LNK_LAYER = poFDefn->GetFieldIndex("OGR_OBJ_LNK_LAYER"); poLayer->AddFieldDefn("OGR_ATR_VAL", OFTString, ""); iATR_VAL = poFDefn->GetFieldIndex("OGR_ATR_VAL"); poLayer->AddFieldDefn("OGR_ANGLE", OFTReal, ""); iANGLE = poFDefn->GetFieldIndex("OGR_ANGLE"); poLayer->AddFieldDefn("OGR_FONT_SIZE", OFTReal, ""); iSIZE = poFDefn->GetFieldIndex("OGR_FONT_SIZE"); } else if (!mapQAL.empty()) { poLayer->AddFieldDefn("CREAT_DATE", OFTInteger, ""); poLayer->AddFieldDefn("UPDATE_DATE", OFTInteger, ""); } mapLayer[objDesc.osRID] = poLayer; papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*)); papoLayers[nLayers] = poLayer; nLayers ++; return TRUE; } /************************************************************************/ /* ReadVEC() */ /************************************************************************/ int OGREDIGEODataSource::ReadVEC(const char* pszVECName) { VSILFILE* fp = OpenFile(pszVECName, "VEC"); if (fp == NULL) return FALSE; const char* pszLine = NULL; CPLString osRTY, osRID; xyPairListType aXY; CPLString osLnkStartType, osLnkStartName, osLnkEndType, osLnkEndName; strListType osLnkEndNameList; CPLString osAttId; std::vector< strstrType > aosAttIdVal; CPLString osSCP; CPLString osQUP_RID; int bIso8859_1 = FALSE; while( true ) { pszLine = CPLReadLine2L(fp, 81, NULL); skip_read_next_line: if (pszLine != NULL) { if (strlen(pszLine) < 8 || pszLine[7] != ':') continue; } if (pszLine == NULL || STARTS_WITH(pszLine, "RTYSA")) { if (osRTY == "PAR") { if (aXY.size() < 2) CPLDebug("EDIGEO", "Error: ARC %s has not enough points", osRID.c_str()); else mapPAR[osRID] = aXY; } else if (osRTY == "LNK") { if (osLnkStartType == "PAR" && osLnkEndType == "PFE") { /*CPLDebug("EDIGEO", "PFE[%s] -> PAR[%s]", osLnkEndName.c_str(), osLnkStartName.c_str());*/ if (mapPFE_PAR.find(osLnkEndName) == mapPFE_PAR.end()) mapPFE_PAR[osLnkEndName].push_back(osLnkStartName); else { int bAlreadyExists = FALSE; strListType& osPARList = mapPFE_PAR[osLnkEndName]; for(int j=0;j<(int)osPARList.size();j++) { if (osPARList[j] == osLnkStartName) bAlreadyExists = TRUE; } if (!bAlreadyExists) osPARList.push_back(osLnkStartName); } } else if (osLnkStartType == "FEA" && osLnkEndType == "PFE") { /*CPLDebug("EDIGEO", "FEA[%s] -> PFE[%s]", osLnkStartName.c_str(), osLnkEndName.c_str());*/ listFEA_PFE.push_back(strstrType (osLnkStartName, osLnkEndName)); } else if (osLnkStartType == "FEA" && osLnkEndType == "PAR") { /*CPLDebug("EDIGEO", "FEA[%s] -> PAR[%s]", osLnkStartName.c_str(), osLnkEndName.c_str());*/ listFEA_PAR.push_back(std::pair<CPLString, strListType > (osLnkStartName, osLnkEndNameList)); } else if (osLnkStartType == "FEA" && osLnkEndType == "PNO") { /*CPLDebug("EDIGEO", "FEA[%s] -> PNO[%s]", osLnkStartName.c_str(), osLnkEndName.c_str());*/ listFEA_PNO.push_back(strstrType (osLnkStartName, osLnkEndName)); } else if (osLnkStartType == "FEA" && osLnkEndType == "FEA") { /*CPLDebug("EDIGEO", "FEA[%s] -> FEA[%s]", osLnkStartName.c_str(), osLnkEndName.c_str());*/ if (osSCP == "IS_S_REL_IWW") mapFEA_FEA[osLnkStartName] = osLnkEndName; } else if (osLnkStartType == "PAR" && osLnkEndType == "PNO") { } else { CPLDebug("EDIGEO", "Unhandled LNK(%s) %s=%s --> %s=%s", osRID.c_str(), osLnkStartType.c_str(), osLnkStartName.c_str(), osLnkEndType.c_str(), osLnkEndName.c_str()); } } else if (osRTY == "FEA") { OGREDIGEOFEADesc feaDesc; feaDesc.aosAttIdVal = aosAttIdVal; feaDesc.osSCP = osSCP; feaDesc.osQUP_RID = osQUP_RID; mapFEA[osRID] = feaDesc; } else if (osRTY == "PNO") { if (aXY.size() == 1) { /*CPLDebug("EDIGEO", "PNO[%s] = %f, %f", osRID.c_str(), aXY[0].first, aXY[0].second);*/ mapPNO[osRID] = aXY[0]; } } if (pszLine == NULL) break; osRTY = pszLine + 8; osRID = ""; aXY.resize(0); osLnkStartType = ""; osLnkStartName = ""; osLnkEndType = ""; osLnkEndName = ""; osAttId = ""; aosAttIdVal.resize(0); osLnkEndNameList.resize(0); osSCP = ""; osQUP_RID = ""; bIso8859_1 = FALSE; } else if (STARTS_WITH(pszLine, "RIDSA")) osRID = pszLine + 8; else if (STARTS_WITH(pszLine, "CORCC")) { const char* pszY = strchr(pszLine+8, ';'); if (pszY) { double dfX = CPLAtof(pszLine + 8); double dfY = CPLAtof(pszY + 1); aXY.push_back(xyPairType (dfX, dfY)); } } else if (STARTS_WITH(pszLine, "FTPCP")) { char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0); if (CSLCount(papszTokens) == 4) { if (osLnkStartType.empty()) { osLnkStartType = papszTokens[2]; osLnkStartName = papszTokens[3]; } else { osLnkEndType = papszTokens[2]; osLnkEndName = papszTokens[3]; osLnkEndNameList.push_back(osLnkEndName); } } CSLDestroy(papszTokens); } else if (STARTS_WITH(pszLine, "SCPCP")) { char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0); if (CSLCount(papszTokens) == 4) { if (osRTY == "LNK") { if (strcmp(papszTokens[2], "ASS") == 0) osSCP = papszTokens[3]; } else if (strcmp(papszTokens[2], "OBJ") == 0) osSCP = papszTokens[3]; } CSLDestroy(papszTokens); } else if (STARTS_WITH(pszLine, "ATPCP")) { char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0); if (CSLCount(papszTokens) == 4) { if (strcmp(papszTokens[2], "ATT") == 0) osAttId = papszTokens[3]; } CSLDestroy(papszTokens); } else if (strcmp(pszLine, "TEXT 06:8859-1") == 0) { bIso8859_1 = TRUE; } else if (STARTS_WITH(pszLine, "ATVS")) { CPLString osAttVal = pszLine + 8; while( true ) { pszLine = CPLReadLine2L(fp, 81, NULL); if (pszLine != NULL && strlen(pszLine) >= 8 && pszLine[7] == ':' && STARTS_WITH(pszLine, "NEXT ")) { osAttVal += pszLine + 8; } else { break; } } if (bIso8859_1 && bRecodeToUTF8) { char* pszNewVal = CPLRecode(osAttVal.c_str(), CPL_ENC_ISO8859_1, CPL_ENC_UTF8); osAttVal = pszNewVal; CPLFree(pszNewVal); } else if (bHasUTF8ContentOnly) { bHasUTF8ContentOnly = CPLIsUTF8(osAttVal.c_str(), -1); } if (!osAttId.empty()) aosAttIdVal.push_back( strstrType (osAttId, osAttVal) ); osAttId = ""; bIso8859_1 = FALSE; goto skip_read_next_line; } else if (STARTS_WITH(pszLine, "ATVCP")) { char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0); if (CSLCount(papszTokens) == 4) { if (strcmp(papszTokens[2], "ATT") == 0) { CPLString osAttVal = papszTokens[3]; if (!osAttId.empty()) aosAttIdVal.push_back( strstrType (osAttId, osAttVal) ); osAttId = ""; } } CSLDestroy(papszTokens); } else if (STARTS_WITH(pszLine, "QAPCP")) { char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0); if (CSLCount(papszTokens) == 4) { if (strcmp(papszTokens[2], "QUP") == 0) { osQUP_RID = papszTokens[3]; } } CSLDestroy(papszTokens); } } VSIFCloseL(fp); return TRUE; } /************************************************************************/ /* CreateFeature() */ /************************************************************************/ OGRFeature* OGREDIGEODataSource::CreateFeature(const CPLString& osFEA) { const std::map< CPLString, OGREDIGEOFEADesc >::iterator itFEA = mapFEA.find(osFEA); if (itFEA == mapFEA.end()) { CPLDebug("EDIGEO", "ERROR: Cannot find FEA %s", osFEA.c_str()); return NULL; } const OGREDIGEOFEADesc& fea = itFEA->second; const std::map<CPLString,OGREDIGEOLayer*>::iterator itLyr = mapLayer.find(fea.osSCP); if (itLyr != mapLayer.end()) { OGREDIGEOLayer* poLayer = itLyr->second; OGRFeature* poFeature = new OGRFeature(poLayer->GetLayerDefn()); poFeature->SetField(0, itFEA->first.c_str()); for(int i=0;i<(int)fea.aosAttIdVal.size();i++) { const CPLString& id = fea.aosAttIdVal[i].first; const CPLString& val = fea.aosAttIdVal[i].second; int iIndex = poLayer->GetAttributeIndex(id); if (iIndex != -1) poFeature->SetField(iIndex, val.c_str()); else CPLDebug("EDIGEO", "ERROR: Cannot find attribute %s", id.c_str()); } if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") != 0 && !mapQAL.empty() && !fea.osQUP_RID.empty()) { const std::map<CPLString, intintType>::iterator itQAL = mapQAL.find(fea.osQUP_RID); if (itQAL != mapQAL.end()) { const intintType& creationUpdateDate = itQAL->second; if (creationUpdateDate.first != 0) poFeature->SetField("CREAT_DATE", creationUpdateDate.first); if (creationUpdateDate.second != 0) poFeature->SetField("UPDATE_DATE", creationUpdateDate.second); } } poLayer->AddFeature(poFeature); return poFeature; } else { CPLDebug("EDIGEO", "ERROR: Cannot find layer %s", fea.osSCP.c_str()); return NULL; } } /************************************************************************/ /* SetStyle() */ /************************************************************************/ int OGREDIGEODataSource::SetStyle(const CPLString& osFEA, OGRFeature* poFeature) { /* EDIGEO PCI specific */ /* See EDIGeO_PCI.pdf, chapter 3 "Principes généraux de */ /* positionnement de la toponymie. */ const char* pszATR = NULL; if (strcmp(poFeature->GetDefnRef()->GetName(), "ID_S_OBJ_Z_1_2_2") == 0 && iATR != -1 && (pszATR = poFeature->GetFieldAsString(iATR)) != NULL) { const CPLString osATR = pszATR; std::map< CPLString, CPLString>::iterator itFEA_FEA = mapFEA_FEA.find(osFEA); if (itFEA_FEA != mapFEA_FEA.end()) { const CPLString& osOBJ_LNK = itFEA_FEA->second; std::map< CPLString, OGREDIGEOFEADesc >::iterator itFEA_LNK = mapFEA.find(osOBJ_LNK); if (itFEA_LNK != mapFEA.end()) { const OGREDIGEOFEADesc& fea_lnk = itFEA_LNK->second; for(int j=0;j<(int)fea_lnk.aosAttIdVal.size();j++) { if (fea_lnk.aosAttIdVal[j].first == osATR) { double dfAngle = 0; if (iDI3 != -1 && iDI4 != -1) { double dfBaseVectorX = poFeature->GetFieldAsDouble(iDI3); double dfBaseVectorY = poFeature->GetFieldAsDouble(iDI4); dfAngle = atan2(dfBaseVectorY, dfBaseVectorX) / M_PI * 180; if (dfAngle < 0) dfAngle += 360; } double dfSize = 1; if (iHEI != -1) dfSize = poFeature->GetFieldAsDouble(iHEI); if (dfSize <= 0 || dfSize >= 100) dfSize = 1; const char* pszFontFamily = NULL; if (iFON != -1) pszFontFamily = poFeature->GetFieldAsString(iFON); CPLString osStyle("LABEL(t:\""); osStyle += fea_lnk.aosAttIdVal[j].second; osStyle += "\""; if (dfAngle != 0) { osStyle += ",a:"; osStyle += CPLString().Printf("%.1f", dfAngle); } if (pszFontFamily != NULL && bIncludeFontFamily) { osStyle += ",f:\""; osStyle += pszFontFamily; osStyle += "\""; } osStyle += ",s:"; osStyle += CPLString().Printf("%.1f", dfSize); osStyle += ",c:#000000)"; poFeature->SetStyleString(osStyle); poFeature->SetField(iATR_VAL, fea_lnk.aosAttIdVal[j].second); poFeature->SetField(iANGLE, dfAngle); poFeature->SetField(iSIZE, dfSize * dfSizeFactor); poFeature->SetField(iOBJ_LNK, osOBJ_LNK); poFeature->SetField(iOBJ_LNK_LAYER, fea_lnk.osSCP); setLayersWithLabels.insert(fea_lnk.osSCP); break; } } } } } return TRUE; } /************************************************************************/ /* BuildPoints() */ /************************************************************************/ int OGREDIGEODataSource::BuildPoints() { for(int i=0;i<(int)listFEA_PNO.size();i++) { const CPLString& osFEA = listFEA_PNO[i].first; const CPLString& osPNO = listFEA_PNO[i].second; const std::map< CPLString, xyPairType >::iterator itPNO = mapPNO.find(osPNO); if (itPNO == mapPNO.end()) { CPLDebug("EDIGEO", "Cannot find PNO %s", osPNO.c_str()); } else { OGRFeature* poFeature = CreateFeature(osFEA); if (poFeature) { const xyPairType& pno = itPNO->second; OGRPoint* poPoint = new OGRPoint(pno.first, pno.second); if (poSRS) poPoint->assignSpatialReference(poSRS); poFeature->SetGeometryDirectly(poPoint); SetStyle(osFEA, poFeature); } } } return TRUE; } /************************************************************************/ /* BuildLineStrings() */ /************************************************************************/ int OGREDIGEODataSource::BuildLineStrings() { int i, iter; for(iter=0;iter<(int)listFEA_PAR.size();iter++) { const CPLString& osFEA = listFEA_PAR[iter].first; const strListType & aosPAR = listFEA_PAR[iter].second; OGRFeature* poFeature = CreateFeature(osFEA); if (poFeature) { OGRGeometry* poGeom = NULL; OGRMultiLineString* poMulti = NULL; for(int k=0;k<(int)aosPAR.size();k++) { const std::map< CPLString, xyPairListType >::iterator itPAR = mapPAR.find(aosPAR[k]); if (itPAR != mapPAR.end()) { const xyPairListType& arc = itPAR->second; OGRLineString* poLS = new OGRLineString(); poLS->setNumPoints((int)arc.size()); for(i=0;i<(int)arc.size();i++) { poLS->setPoint(i, arc[i].first, arc[i].second); } if (poGeom != NULL) { if (poMulti == NULL) { poMulti = new OGRMultiLineString(); poMulti->addGeometryDirectly(poGeom); poGeom = poMulti; } poMulti->addGeometryDirectly(poLS); } else poGeom = poLS; } else CPLDebug("EDIGEO", "ERROR: Cannot find ARC %s", aosPAR[k].c_str()); } if( poGeom != NULL ) { poGeom->assignSpatialReference(poSRS); poFeature->SetGeometryDirectly(poGeom); } } } return TRUE; } /************************************************************************/ /* BuildPolygon() */ /************************************************************************/ int OGREDIGEODataSource::BuildPolygon(const CPLString& osFEA, const CPLString& osPFE) { const std::map< CPLString, strListType >::iterator itPFE_PAR = mapPFE_PAR.find(osPFE); if (itPFE_PAR == mapPFE_PAR.end()) { CPLDebug("EDIGEO", "ERROR: Cannot find PFE %s", osPFE.c_str()); return FALSE; } const strListType & aosPARList = itPFE_PAR->second; /* -------------------------------------------------------------------- */ /* Resolve arc ids to arc coordinate lists. */ /* -------------------------------------------------------------------- */ std::vector< const xyPairListType *> aoPARPtrList; for( int i = 0; i < (int)aosPARList.size(); i++ ) { const std::map< CPLString, xyPairListType >::iterator itPAR = mapPAR.find(aosPARList[i]); if( itPAR != mapPAR.end() ) aoPARPtrList.push_back(&(itPAR->second)); else CPLDebug("EDIGEO", "ERROR: Cannot find ARC %s", aosPARList[i].c_str()); } if (aoPARPtrList.empty()) return FALSE; /* -------------------------------------------------------------------- */ /* Now try to chain all arcs together. */ /* -------------------------------------------------------------------- */ std::vector<xyPairListType> aoXYList; for( int j = 0; j < (int)aoPARPtrList.size(); j++ ) { if (aoPARPtrList[j] == NULL) continue; const xyPairListType& sFirstRing = *(aoPARPtrList[j]); const xyPairType* psNext = &(sFirstRing.back()); xyPairListType aoXY; for( int i = 0; i < (int)sFirstRing.size(); i++ ) aoXY.push_back(sFirstRing[i]); aoPARPtrList[j] = NULL; int nIter = 1; while(aoXY.back() != aoXY[0] && nIter < (int)aoPARPtrList.size()) { bool bFound = false; bool bReverseSecond = false; int i = 0; // Used after for. for( ; i < (int)aoPARPtrList.size(); i++ ) { if (aoPARPtrList[i] != NULL) { const xyPairListType& sSecondRing = *(aoPARPtrList[i]); if (*psNext == sSecondRing[0]) { bFound = true; bReverseSecond = false; break; } else if (*psNext == sSecondRing.back()) { bFound = true; bReverseSecond = true; break; } } } if( !bFound ) { CPLDebug("EDIGEO", "Cannot find ring for FEA %s / PFE %s", osFEA.c_str(), osPFE.c_str()); break; } else { const xyPairListType& secondRing = *(aoPARPtrList[i]); aoPARPtrList[i] = NULL; if( !bReverseSecond ) { for(i=1;i<(int)secondRing.size();i++) aoXY.push_back(secondRing[i]); psNext = &secondRing.back(); } else { for(i=1;i<(int)secondRing.size();i++) aoXY.push_back(secondRing[secondRing.size()-1-i]); psNext = &secondRing[0]; } } nIter ++; } aoXYList.push_back(aoXY); } /* -------------------------------------------------------------------- */ /* Create feature. */ /* -------------------------------------------------------------------- */ OGRFeature* poFeature = CreateFeature(osFEA); if( poFeature ) { std::vector<OGRGeometry*> aosPolygons; for( int j = 0; j < (int)aoXYList.size(); j++ ) { const xyPairListType& aoXY = aoXYList[j]; OGRLinearRing* poLS = new OGRLinearRing(); poLS->setNumPoints((int)aoXY.size()); for( int i = 0; i < (int)aoXY.size(); i++ ) poLS->setPoint(i, aoXY[i].first, aoXY[i].second); poLS->closeRings(); OGRPolygon* poPolygon = new OGRPolygon(); poPolygon->addRingDirectly(poLS); aosPolygons.push_back(poPolygon); } int bIsValidGeometry = FALSE; OGRGeometry* poGeom = OGRGeometryFactory::organizePolygons( &aosPolygons[0], (int)aosPolygons.size(), &bIsValidGeometry, NULL); if (poGeom) { if (poSRS) poGeom->assignSpatialReference(poSRS); poFeature->SetGeometryDirectly(poGeom); } } return TRUE; } /************************************************************************/ /* BuildPolygons() */ /************************************************************************/ int OGREDIGEODataSource::BuildPolygons() { for( int iter = 0; iter < (int)listFEA_PFE.size(); iter++ ) { const CPLString& osFEA = listFEA_PFE[iter].first; const CPLString& osPFE = listFEA_PFE[iter].second; BuildPolygon(osFEA, osPFE); } return TRUE; } /************************************************************************/ /* OGREDIGEOSortForQGIS() */ /************************************************************************/ static int OGREDIGEOSortForQGIS(const void* a, const void* b) { OGREDIGEOLayer* poLayerA = *((OGREDIGEOLayer**) a); OGREDIGEOLayer* poLayerB = *((OGREDIGEOLayer**) b); int nTypeA, nTypeB; switch (poLayerA->GetLayerDefn()->GetGeomType()) { case wkbPoint: nTypeA = 1; break; case wkbLineString: nTypeA = 2; break; case wkbPolygon: nTypeA = 3; break; default: nTypeA = 4; break; } switch (poLayerB->GetLayerDefn()->GetGeomType()) { case wkbPoint: nTypeB = 1; break; case wkbLineString: nTypeB = 2; break; case wkbPolygon: nTypeB = 3; break; default: nTypeB = 4; break; } if (nTypeA == nTypeB) { int nCmp = strcmp(poLayerA->GetName(), poLayerB->GetName()); if (nCmp == 0) return 0; static const char* const apszPolyOrder[] = { "COMMUNE_id", "LIEUDIT_id", "SECTION_id", "SUBDSECT_id", "SUBDFISC_id", "PARCELLE_id", "BATIMENT_id" }; for(int i=0;i<(int)(sizeof(apszPolyOrder)/sizeof(char*));i++) { if (strcmp(poLayerA->GetName(), apszPolyOrder[i]) == 0) return -1; if (strcmp(poLayerB->GetName(), apszPolyOrder[i]) == 0) return 1; } return nCmp; } else return nTypeB - nTypeA; } /************************************************************************/ /* Open() */ /************************************************************************/ int OGREDIGEODataSource::Open( const char * pszFilename ) { pszName = CPLStrdup( pszFilename ); fpTHF = VSIFOpenL(pszFilename, "rb"); if (fpTHF == NULL) return FALSE; const char* pszLine = NULL; int i = 0; bool bIsEDIGEO = false; while( i < 100 && (pszLine = CPLReadLine2L(fpTHF, 81, NULL)) != NULL ) { if (strcmp(pszLine, "RTYSA03:GTS") == 0) { bIsEDIGEO = true; break; } i++; } if( !bIsEDIGEO ) { VSIFCloseL(fpTHF); fpTHF = NULL; return FALSE; } return TRUE; } /************************************************************************/ /* ReadEDIGEO() */ /************************************************************************/ void OGREDIGEODataSource::ReadEDIGEO() { if (bHasReadEDIGEO) return; bHasReadEDIGEO = TRUE; /* -------------------------------------------------------------------- */ /* Read .THF file */ /* -------------------------------------------------------------------- */ VSIFSeekL(fpTHF, 0, SEEK_SET); if (!ReadTHF(fpTHF)) { VSIFCloseL(fpTHF); fpTHF = NULL; return; } VSIFCloseL(fpTHF); fpTHF = NULL; /* -------------------------------------------------------------------- */ /* Read .GEO file */ /* -------------------------------------------------------------------- */ if (!ReadGEO()) return; /* -------------------------------------------------------------------- */ /* Read .GEN file */ /* -------------------------------------------------------------------- */ if (!osGNN.empty()) ReadGEN(); /* -------------------------------------------------------------------- */ /* Read .DIC file */ /* -------------------------------------------------------------------- */ if (!ReadDIC()) return; /* -------------------------------------------------------------------- */ /* Read .SCD file */ /* -------------------------------------------------------------------- */ if (!ReadSCD()) return; /* -------------------------------------------------------------------- */ /* Read .QAL file */ /* -------------------------------------------------------------------- */ if (!osQAN.empty()) ReadQAL(); /* -------------------------------------------------------------------- */ /* Create layers from SCD definitions */ /* -------------------------------------------------------------------- */ for( int i = 0; i < (int)aoObjList.size(); i++ ) { CreateLayerFromObjectDesc(aoObjList[i]); } /* -------------------------------------------------------------------- */ /* Read .VEC files and create features */ /* -------------------------------------------------------------------- */ for( int i = 0; i < (int)aosGDN.size(); i++ ) { ReadVEC(aosGDN[i]); BuildPoints(); BuildLineStrings(); BuildPolygons(); mapPNO.clear(); mapPAR.clear(); mapFEA.clear(); mapPFE_PAR.clear(); listFEA_PFE.clear(); listFEA_PAR.clear(); listFEA_PNO.clear(); mapFEA_FEA.clear(); } mapObjects.clear(); mapAttributes.clear(); mapAttributesSCD.clear(); mapQAL.clear(); /* -------------------------------------------------------------------- */ /* Delete empty layers */ /* -------------------------------------------------------------------- */ for( int i = 0; i <nLayers; /*nothing*/ ) { if (papoLayers[i]->GetFeatureCount(TRUE) == 0) { delete papoLayers[i]; if (i < nLayers - 1) memmove(papoLayers + i, papoLayers + i + 1, (nLayers - i - 1) * sizeof(OGREDIGEOLayer*)); nLayers --; } else i++; } /* -------------------------------------------------------------------- */ /* When added from QGIS, the layers must be ordered from */ /* bottom (Polygon) to top (Point) to get nice visual effect */ /* -------------------------------------------------------------------- */ if (CPLTestBool(CPLGetConfigOption("OGR_EDIGEO_SORT_FOR_QGIS", "YES"))) qsort(papoLayers, nLayers, sizeof(OGREDIGEOLayer*), OGREDIGEOSortForQGIS); /* -------------------------------------------------------------------- */ /* Create a label layer for each feature layer */ /* -------------------------------------------------------------------- */ if (CPLTestBool(CPLGetConfigOption("OGR_EDIGEO_CREATE_LABEL_LAYERS", "YES"))) CreateLabelLayers(); return; } /************************************************************************/ /* CreateLabelLayers() */ /************************************************************************/ void OGREDIGEODataSource::CreateLabelLayers() { OGRLayer* poLayer = GetLayerByName("ID_S_OBJ_Z_1_2_2"); if (poLayer == NULL) return; std::map<CPLString, OGREDIGEOLayer*> mapLayerNameToLayer; OGRFeature* poFeature = NULL; OGRFeatureDefn* poFeatureDefn = poLayer->GetLayerDefn(); while( (poFeature = poLayer->GetNextFeature()) != NULL ) { const char* pszBelongingLayerName = poFeature->GetFieldAsString(iOBJ_LNK_LAYER); if (pszBelongingLayerName) { CPLString osBelongingLayerName = pszBelongingLayerName; std::map<CPLString, OGREDIGEOLayer*>::iterator it = mapLayerNameToLayer.find(osBelongingLayerName); OGREDIGEOLayer* poLabelLayer = NULL; if (it == mapLayerNameToLayer.end()) { /* Create label layer if it does not already exist */ CPLString osLayerLabelName = osBelongingLayerName + "_LABEL"; poLabelLayer = new OGREDIGEOLayer(this, osLayerLabelName.c_str(), wkbPoint, poSRS); OGRFeatureDefn* poLabelFeatureDefn = poLabelLayer->GetLayerDefn(); for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ ) poLabelFeatureDefn->AddFieldDefn(poFeatureDefn->GetFieldDefn(i)); mapLayerNameToLayer[osBelongingLayerName] = poLabelLayer; papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*)); papoLayers[nLayers] = poLabelLayer; nLayers ++; } else { poLabelLayer = mapLayerNameToLayer[osBelongingLayerName]; } OGRFeature* poNewFeature = new OGRFeature(poLabelLayer->GetLayerDefn()); poNewFeature->SetFrom(poFeature); poLabelLayer->AddFeature(poNewFeature); } delete poFeature; } poLayer->ResetReading(); }