EVOLUTION-MANAGER
Edit File: ograeronavfaalayer.cpp
/****************************************************************************** * * Project: AeronavFAA Translator * Purpose: Implements OGRAeronavFAALayer class. * Author: Even Rouault, <even dot rouault at mines dash paris dot org> * ****************************************************************************** * Copyright (c) 2011-2013, 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_aeronavfaa.h" #include "cpl_conv.h" #include "cpl_string.h" #include "ogr_p.h" #include "ogr_srs_api.h" #include <algorithm> CPL_CVSID("$Id: ograeronavfaalayer.cpp 36981 2016-12-20 19:46:41Z rouault $"); /************************************************************************/ /* OGRAeronavFAALayer() */ /************************************************************************/ OGRAeronavFAALayer::OGRAeronavFAALayer( VSILFILE* fp, const char* pszLayerName ) : poFeatureDefn(new OGRFeatureDefn(pszLayerName)), poSRS(new OGRSpatialReference(SRS_WKT_WGS84)), fpAeronavFAA(fp), bEOF(false), nNextFID(0), psRecordDesc(NULL) { poFeatureDefn->Reference(); poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS); SetDescription( poFeatureDefn->GetName() ); } /************************************************************************/ /* ~OGRAeronavFAALayer() */ /************************************************************************/ OGRAeronavFAALayer::~OGRAeronavFAALayer() { if( poSRS != NULL ) poSRS->Release(); poFeatureDefn->Release(); VSIFCloseL( fpAeronavFAA ); } /************************************************************************/ /* ResetReading() */ /************************************************************************/ void OGRAeronavFAALayer::ResetReading() { nNextFID = 0; bEOF = false; VSIFSeekL( fpAeronavFAA, 0, SEEK_SET ); } /************************************************************************/ /* GetNextFeature() */ /************************************************************************/ OGRFeature *OGRAeronavFAALayer::GetNextFeature() { while( true ) { if( bEOF ) return NULL; OGRFeature *poFeature = GetNextRawFeature(); if (poFeature == NULL) return NULL; if((m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) ) { return poFeature; } else delete poFeature; } } /************************************************************************/ /* TestCapability() */ /************************************************************************/ int OGRAeronavFAALayer::TestCapability( CPL_UNUSED const char * pszCap ) { return FALSE; } static const RecordFieldDesc DOFFields [] = { { "ORS_CODE", 1, 2, OFTString }, { "NUMBER" , 4, 9, OFTInteger, }, { "VERIF_STATUS", 11, 11, OFTString }, { "COUNTRY", 13, 14, OFTString }, { "STATE", 16, 17, OFTString }, { "CITY", 19, 34, OFTString }, { "TYPE", 63, 74, OFTString }, { "QUANTITY", 76, 76, OFTInteger }, { "AGL_HT", 78, 82, OFTInteger }, { "AMSL_HT", 84, 88, OFTInteger }, { "LIGHTING", 90, 90, OFTString }, { "HOR_ACC", 92, 92, OFTString }, { "VER_ACC", 94, 94, OFTString }, { "MARK_INDIC", 96, 96, OFTString }, { "FAA_STUDY_NUMBER", 98, 111, OFTString }, { "ACTION", 113, 113, OFTString }, { "DATE", 115, 121, OFTString } }; static const RecordDesc DOF = { sizeof(DOFFields)/sizeof(DOFFields[0]), DOFFields, 36, 49 }; /************************************************************************/ /* OGRAeronavFAADOFLayer() */ /************************************************************************/ OGRAeronavFAADOFLayer::OGRAeronavFAADOFLayer( VSILFILE* fp, const char* pszLayerName ) : OGRAeronavFAALayer(fp, pszLayerName) { poFeatureDefn->SetGeomType( wkbPoint ); psRecordDesc = &DOF; for( int i = 0; i < psRecordDesc->nFields; i++ ) { OGRFieldDefn oField( psRecordDesc->pasFields[i].pszFieldName, psRecordDesc->pasFields[i].eType ); oField.SetWidth(psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1); poFeatureDefn->AddFieldDefn( &oField ); } } /************************************************************************/ /* GetLatLon() */ /************************************************************************/ static int GetLatLon(const char* pszLat, char chLatHemisphere, const char* pszLon, char chLonHemisphere, int nSecLen, double& dfLat, double& dfLon) { char szDeg[4] = { pszLat[0], pszLat[1], 0 }; char szMin[3] = { pszLat[3], pszLat[4], 0 }; char szSec[10]; memcpy(szSec, pszLat + 6, std::max((int)sizeof(szSec) - 1, nSecLen)); szSec[std::max((int)sizeof(szSec) - 1, nSecLen)] = 0; dfLat = atoi(szDeg) + atoi(szMin) / 60. + CPLAtof(szSec) / 3600.; if (chLatHemisphere == 'S') dfLat = -dfLat; szDeg[0] = pszLon[0]; szDeg[1] = pszLon[1]; szDeg[2] = pszLon[2]; szDeg[3] = 0; szMin[0] = pszLon[4]; szMin[1] = pszLon[5]; szMin[2] = 0; memcpy(szSec, pszLon + 7, std::max((int)sizeof(szSec) - 1, nSecLen)); szSec[std::max((int)sizeof(szSec) - 1, nSecLen)] = 0; dfLon = atoi(szDeg) + atoi(szMin) / 60. + CPLAtof(szSec) / 3600.; if (chLonHemisphere == ' ' || chLonHemisphere == 'W') dfLon = -dfLon; return TRUE; } /************************************************************************/ /* GetLatLon() */ /************************************************************************/ int OGRAeronavFAADOFLayer::GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon) { return ::GetLatLon(pszLat, pszLat[11], pszLon, pszLon[12], 5, dfLat, dfLon); } /************************************************************************/ /* GetNextRawFeature() */ /************************************************************************/ OGRFeature *OGRAeronavFAADOFLayer::GetNextRawFeature() { char szBuffer[130]; while( true ) { const char* pszLine = CPLReadLine2L(fpAeronavFAA, 130, NULL); if (pszLine == NULL) { bEOF = true; return NULL; } if (strlen(pszLine) != 128) continue; if ( ! (pszLine[psRecordDesc->nLatStartCol-1] >= '0' && pszLine[psRecordDesc->nLatStartCol-1] <= '9') ) continue; OGRFeature* poFeature = new OGRFeature(poFeatureDefn); poFeature->SetFID(nNextFID ++); for( int i=0; i < psRecordDesc->nFields; i++ ) { int nWidth = psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1; strncpy(szBuffer, pszLine + psRecordDesc->pasFields[i].nStartCol - 1, nWidth); szBuffer[nWidth] = 0; while(nWidth > 0 && szBuffer[nWidth - 1] == ' ') { szBuffer[nWidth - 1] = 0; nWidth --; } if (nWidth != 0) poFeature->SetField(i, szBuffer); } double dfLat = 0.0; double dfLon = 0.0; GetLatLon(pszLine + psRecordDesc->nLatStartCol - 1, pszLine + psRecordDesc->nLonStartCol - 1, dfLat, dfLon); OGRGeometry* poGeom = new OGRPoint(dfLon, dfLat); poGeom->assignSpatialReference(poSRS); poFeature->SetGeometryDirectly( poGeom ); return poFeature; } } static const RecordFieldDesc NAVAIDFields [] = { { "ID", 2, 6, OFTString }, { "NAVAID_TYPE", 8, 9, OFTString }, { "STATUS" , 11, 11, OFTString }, { "NAME" , 44, 68, OFTString }, { "CAN_ARTCC" , 69, 69, OFTString }, { "SERVICE" , 76, 76, OFTString }, { "FREQUENCY" , 78, 84, OFTString }, { "CHANNEL" , 86, 89, OFTString }, { "ELEVATION" , 92, 96, OFTString }, { "MAG_VAR" , 98, 100, OFTString }, { "ARTCC" , 102, 104, OFTString }, { "STATE" , 106, 107, OFTString }, }; static const RecordDesc NAVAID = { sizeof(NAVAIDFields)/sizeof(NAVAIDFields[0]), NAVAIDFields, 17, 30 }; /************************************************************************/ /* OGRAeronavFAANAVAIDLayer() */ /************************************************************************/ OGRAeronavFAANAVAIDLayer::OGRAeronavFAANAVAIDLayer( VSILFILE* fp, const char* pszLayerName ) : OGRAeronavFAALayer(fp, pszLayerName) { poFeatureDefn->SetGeomType( wkbPoint ); psRecordDesc = &NAVAID; for( int i=0; i < psRecordDesc->nFields; i++ ) { OGRFieldDefn oField( psRecordDesc->pasFields[i].pszFieldName, psRecordDesc->pasFields[i].eType ); oField.SetWidth( psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1 ); poFeatureDefn->AddFieldDefn( &oField ); } } /************************************************************************/ /* GetLatLon() */ /************************************************************************/ int OGRAeronavFAANAVAIDLayer::GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon) { return ::GetLatLon(pszLat + 2, pszLat[0], pszLon + 2, pszLon[0], 4, dfLat, dfLon); } /************************************************************************/ /* GetNextRawFeature() */ /************************************************************************/ OGRFeature *OGRAeronavFAANAVAIDLayer::GetNextRawFeature() { char szBuffer[134]; while( true ) { const char* pszLine = CPLReadLine2L(fpAeronavFAA, 134, NULL); if (pszLine == NULL) { bEOF = true; return NULL; } if (strlen(pszLine) != 132) continue; if ( !(pszLine[psRecordDesc->nLatStartCol-1] == 'N' || pszLine[psRecordDesc->nLatStartCol-1] == 'S') ) continue; if ( !(pszLine[psRecordDesc->nLonStartCol-1] == 'E' || pszLine[psRecordDesc->nLonStartCol-1] == 'W') ) continue; OGRFeature* poFeature = new OGRFeature(poFeatureDefn); poFeature->SetFID(nNextFID ++); for( int i=0; i < psRecordDesc->nFields; i++ ) { int nWidth = psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1; strncpy(szBuffer, pszLine + psRecordDesc->pasFields[i].nStartCol - 1, nWidth); szBuffer[nWidth] = 0; while(nWidth > 0 && szBuffer[nWidth - 1] == ' ') { szBuffer[nWidth - 1] = 0; nWidth --; } if (nWidth != 0) poFeature->SetField(i, szBuffer); } double dfLat = 0.0; double dfLon = 0.0; GetLatLon(pszLine + psRecordDesc->nLatStartCol - 1, pszLine + psRecordDesc->nLonStartCol - 1, dfLat, dfLon); OGRGeometry* poGeom = new OGRPoint(dfLon, dfLat); poGeom->assignSpatialReference(poSRS); poFeature->SetGeometryDirectly( poGeom ); return poFeature; } } /************************************************************************/ /* OGRAeronavFAARouteLayer() */ /************************************************************************/ OGRAeronavFAARouteLayer::OGRAeronavFAARouteLayer( VSILFILE* fp, const char* pszLayerName, int bIsDPOrSTARSIn ) : OGRAeronavFAALayer(fp, pszLayerName) { bIsDPOrSTARS = bIsDPOrSTARSIn; poFeatureDefn->SetGeomType( wkbLineString ); if (bIsDPOrSTARS) { { OGRFieldDefn oField( "APT_NAME", OFTString ); poFeatureDefn->AddFieldDefn( &oField ); } { OGRFieldDefn oField( "STATE", OFTString ); poFeatureDefn->AddFieldDefn( &oField ); } } { OGRFieldDefn oField( "NAME", OFTString ); poFeatureDefn->AddFieldDefn( &oField ); } } /************************************************************************/ /* GetLatLon() */ /************************************************************************/ int OGRAeronavFAARouteLayer::GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon) { return ::GetLatLon(pszLat, pszLat[10], pszLon, pszLon[11], 4, dfLat, dfLon); } /************************************************************************/ /* GetNextRawFeature() */ /************************************************************************/ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature() { OGRFeature* poFeature = NULL; OGRLineString* poLS = NULL; while( true ) { const char* pszLine = NULL; if (!osLastReadLine.empty()) pszLine = osLastReadLine.c_str(); else pszLine = CPLReadLine2L(fpAeronavFAA, 87, NULL); osLastReadLine = ""; if (pszLine == NULL) { bEOF = true; break; } if (strlen(pszLine) != 85) continue; if (bIsDPOrSTARS && STARTS_WITH(pszLine, "===") && pszLine[3] != '=') { osAPTName = pszLine + 3; const char* pszComma = strchr(pszLine + 3, ','); if (pszComma) { osAPTName.resize(pszComma - (pszLine + 3)); osStateName = pszComma + 2; const char* pszEqual = strchr(pszComma + 2, '='); if (pszEqual) osStateName.resize(pszEqual - (pszComma + 2)); } else { const char* pszEqual = strchr(pszLine + 3, '='); if (pszEqual) osAPTName.resize(pszEqual - (pszLine + 3)); osStateName = ""; } } if (STARTS_WITH(pszLine + 2, "FACILITY OR")) continue; if (STARTS_WITH(pszLine + 2, "INTERSECTION")) continue; if (strcmp(pszLine, "================================DELETIONS LIST=================================198326") == 0) { bEOF = true; break; } if (poFeature == NULL) { if (pszLine[2] == ' ' || pszLine[2] == '-' ) { continue; } if (STARTS_WITH(pszLine + 29, " ") || strchr(pszLine, '(') != NULL) { CPLString osName = pszLine + 2; osName.resize(60); while(!osName.empty() && osName.back() == ' ') { osName.resize(osName.size()-1); } if (strcmp(osName.c_str(), "(DELETIONS LIST)") == 0) { bEOF = true; return NULL; } poFeature = new OGRFeature(poFeatureDefn); poFeature->SetFID(nNextFID ++); if (bIsDPOrSTARS) { poFeature->SetField(0, osAPTName); poFeature->SetField(1, osStateName); poFeature->SetField(2, osName); } else poFeature->SetField(0, osName); poLS = new OGRLineString(); } continue; } if (STARTS_WITH(pszLine, " 0")) { if (poLS->getNumPoints() == 0) continue; else break; } if (pszLine[29 - 1] == ' ' && pszLine[42 - 1] == ' ') continue; if (strstr(pszLine, "RWY") || strchr(pszLine, '(')) { osLastReadLine = pszLine; break; } double dfLat = 0.0; double dfLon = 0.0; GetLatLon(pszLine + 29 - 1, pszLine + 42 - 1, dfLat, dfLon); poLS->addPoint(dfLon, dfLat); } if( poFeature != NULL ) poFeature->SetGeometryDirectly(poLS); return poFeature; } /************************************************************************/ /* ResetReading() */ /************************************************************************/ void OGRAeronavFAARouteLayer::ResetReading() { OGRAeronavFAALayer::ResetReading(); osLastReadLine = ""; osAPTName = ""; osStateName = ""; } static const RecordFieldDesc IAPFields [] = { { "LOC_ID", 4, 8, OFTString }, { "MAG_VAR" , 52, 54, OFTInteger, }, { "ELEVATION", 62, 67, OFTInteger }, { "TYPE", 71, 77, OFTString }, }; static const RecordDesc IAP = { sizeof(IAPFields)/sizeof(IAPFields[0]), IAPFields, -1, -1 }; /************************************************************************/ /* OGRAeronavFAAIAPLayer() */ /************************************************************************/ OGRAeronavFAAIAPLayer::OGRAeronavFAAIAPLayer( VSILFILE* fp, const char* pszLayerName ) : OGRAeronavFAALayer(fp, pszLayerName) { poFeatureDefn->SetGeomType( wkbPoint ); { OGRFieldDefn oField( "CITY", OFTString ); poFeatureDefn->AddFieldDefn( &oField ); } { OGRFieldDefn oField( "STATE", OFTString ); poFeatureDefn->AddFieldDefn( &oField ); } { OGRFieldDefn oField( "APT_NAME", OFTString ); poFeatureDefn->AddFieldDefn( &oField ); } { OGRFieldDefn oField( "APT_CODE", OFTString ); poFeatureDefn->AddFieldDefn( &oField ); } psRecordDesc = &IAP; for( int i=0; i < psRecordDesc->nFields; i++ ) { OGRFieldDefn oField( psRecordDesc->pasFields[i].pszFieldName, psRecordDesc->pasFields[i].eType ); oField.SetWidth(psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1); poFeatureDefn->AddFieldDefn( &oField ); } } /************************************************************************/ /* GetLatLon() */ /************************************************************************/ int OGRAeronavFAAIAPLayer::GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon) { return ::GetLatLon(pszLat, pszLat[11], pszLon, pszLon[12], 4, dfLat, dfLon); } /************************************************************************/ /* GetNextRawFeature() */ /************************************************************************/ OGRFeature *OGRAeronavFAAIAPLayer::GetNextRawFeature() { char szBuffer[87]; int nCountUnderscoreLines = 0; while( true ) { const char* pszLine = CPLReadLine2L(fpAeronavFAA, 87, NULL); if (pszLine == NULL) { bEOF = true; return NULL; } if (strlen(pszLine) != 85) continue; if (STARTS_WITH(pszLine, "DELETIONS")) { bEOF = true; return NULL; } if (nNextFID == 0 && nCountUnderscoreLines < 2) { if (strcmp(pszLine, "_____________________________________________________________________________ 285285") == 0) nCountUnderscoreLines ++; continue; } if (pszLine[1] != ' ') continue; if (STARTS_WITH(pszLine, " ")) continue; if (strstr(pszLine, "NAVIGATIONAL AIDS") != NULL) continue; if (strstr(pszLine, "TERMINAL INSTRUMENT FIXES") != NULL) continue; const char* pszComma = strchr(pszLine, ','); if (pszComma) { const char* pszBegin = pszLine; while( *pszBegin == ' ') pszBegin ++; osCityName = pszBegin; osCityName.resize(pszComma - pszBegin); osStateName = pszComma + 2; osStateName.resize(78 - (pszComma + 2 - pszLine)); while(!osStateName.empty() && osStateName.back() == ' ') { osStateName.resize(osStateName.size()-1); } osAPTName = ""; osAPTId = ""; continue; } const char* pszLeftParenthesis = strstr(pszLine, " ("); if (pszLeftParenthesis) { const char* pszRightParenthesis = strchr(pszLeftParenthesis, ')'); if (pszRightParenthesis) { const char* pszBegin = pszLine; while( *pszBegin == ' ') pszBegin ++; osAPTName = pszBegin; osAPTName.resize(pszLeftParenthesis - pszBegin); osAPTId = pszLeftParenthesis + 2; osAPTId.resize(pszRightParenthesis - (pszLeftParenthesis + 2)); } continue; } OGRFeature* poFeature = new OGRFeature(poFeatureDefn); poFeature->SetFID(nNextFID ++); poFeature->SetField(0, osCityName); poFeature->SetField(1, osStateName); poFeature->SetField(2, osAPTName); poFeature->SetField(3, osAPTId); for( int i=0; i<psRecordDesc->nFields; i++) { int nWidth = psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1; strncpy(szBuffer, pszLine + psRecordDesc->pasFields[i].nStartCol - 1, nWidth); szBuffer[nWidth] = 0; while(nWidth > 0 && szBuffer[nWidth - 1] == ' ') { szBuffer[nWidth - 1] = 0; nWidth --; } if (nWidth != 0) poFeature->SetField(i + 4, szBuffer); } double dfLat = 0.0; double dfLon = 0.0; GetLatLon(pszLine + 16 - 1, (pszLine[34 - 1] != ' ') ? pszLine + 34 - 1 : pszLine + 35 - 1, dfLat, dfLon); OGRGeometry* poGeom = new OGRPoint(dfLon, dfLat); poGeom->assignSpatialReference(poSRS); poFeature->SetGeometryDirectly( poGeom ); return poFeature; } } /************************************************************************/ /* ResetReading() */ /************************************************************************/ void OGRAeronavFAAIAPLayer::ResetReading() { OGRAeronavFAALayer::ResetReading(); osCityName = ""; osStateName = ""; osAPTName = ""; osAPTId = ""; }