/****************************************************************************** * Project: Geography Network utility * Purpose: To manage GNM networks * Authors: Mikhail Gusev, gusevmihs at gmail dot com * Dmitry Baryshnikov, polimax@mail.ru * ****************************************************************************** * Copyright (c) 2014, Mikhail Gusev * Copyright (c) 2014-2015, NextGIS * * 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 "commonutils.h" #include "cpl_string.h" #include "gdal_version.h" #include "gdal.h" #include "gnm.h" #include "gnm_priv.h" //#include "ogr_p.h" //#include "gnm.h" //#include "gnm_api.h" CPL_CVSID("$Id: gnmmanage.cpp 8c3e4ef55212f20eec95aa7e12ba5d48dacfdc47 2020-10-01 21:20:51 +0200 Even Rouault $") enum operation { op_unknown = 0, /** no operation */ op_info, /** print information about network */ op_create, /** create a new network */ op_import, /** add a OGR layer to the network */ op_connect, /** connect features from layers added to the network */ op_disconnect, /** disconnect features from layers added to the network */ op_rule, /** add connect rule */ op_autoconnect, /** try to connect features base on their tolerance */ op_delete, /** delete network */ op_change_st /** change vertex or edge blocking state */ }; /************************************************************************/ /* Usage() */ /************************************************************************/ static void Usage(const char* pszAdditionalMsg, int bShort = TRUE) CPL_NO_RETURN; static void Usage(const char* pszAdditionalMsg, int bShort) { printf("Usage: gnmmanage [--help][-q][-quiet][--long-usage]\n" " [info]\n" " [create [-f format_name] [-t_srs srs_name] [-dsco NAME=VALUE]... ]\n" " [import src_dataset_name] [-l layer_name]\n" " [connect gfid_src gfid_tgt gfid_con [-c cost] [-ic inv_cost] [-dir dir]]\n" " [disconnect gfid_src gfid_tgt gfid_con]\n" " [rule rule_str]\n" " [autoconnect tolerance]\n" " [delete]\n" " [change [-bl gfid][-unbl gfid][-unblall]]\n" " gnm_name [layer [layer ...]]\n"); if (bShort) { printf("\nNote: gnmmanage --long-usage for full help.\n"); if (pszAdditionalMsg) fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg); exit(1); } printf("\n info: different information about network: system and class " "layers, network metadata, network spatial reference\n" " create: create network\n" " -f format_name: output file format name, possible values are:\n"); int nGNMDriverCounter = 1; for(int iDr = 0; iDr < GDALGetDriverCount(); iDr++ ) { GDALDriverH hDriver = GDALGetDriver(iDr); const char *pszRFlag = "", *pszWFlag, *pszVirtualIO, *pszSubdatasets; char** papszMD = GDALGetMetadata( hDriver, nullptr ); if( CPLFetchBool( papszMD, GDAL_DCAP_RASTER, false ) ) continue; if( CPLFetchBool( papszMD, GDAL_DCAP_VECTOR, false ) ) continue; if( CPLFetchBool( papszMD, GDAL_DCAP_OPEN, false ) ) pszRFlag = "r"; if( CPLFetchBool( papszMD, GDAL_DCAP_CREATE, false ) ) pszWFlag = "w+"; else if( CPLFetchBool( papszMD, GDAL_DCAP_CREATECOPY, false ) ) pszWFlag = "w"; else pszWFlag = "o"; if( CPLFetchBool( papszMD, GDAL_DCAP_VIRTUALIO, false ) ) pszVirtualIO = "v"; else pszVirtualIO = ""; if( CPLFetchBool( papszMD, GDAL_DMD_SUBDATASETS, false ) ) pszSubdatasets = "s"; else pszSubdatasets = ""; printf( " %d. %s (%s%s%s%s): %s\n", nGNMDriverCounter++, GDALGetDriverShortName( hDriver ), pszRFlag, pszWFlag, pszVirtualIO, pszSubdatasets, GDALGetDriverLongName( hDriver ) ); } printf(" -t_srs srs_name: spatial reference input\n" " -dsco NAME=VALUE: network creation option set as pair=value\n" " import src_dataset_name: import external layer where src_dataset_name is a dataset name to copy from\n" " -l layer_name: layer name in dataset. If unset, 0 layer is copied\n" " connect gfid_src gfid_tgt gfid_con: make a topological connection, where the gfid_src and gfid_tgt are vertices and gfid_con is edge (gfid_con can be -1, so the virtual connection will be created)\n" " -c cost -ic inv_cost -dir dir: manually assign the following values: the cost (weight), inverse cost and direction of the edge (optional)\n" " disconnect gfid_src gfid_tgt gfid_con: removes the connection from the graph\n" " rule rule_str: creates a rule in the network by the given rule_str string\n" " autoconnect tolerance: create topology automatically with the given double tolerance\n" " delete: delete network\n" " change: modify blocking state of vertices and edges ans save them in the network" " -bl gfid: block feature before the main operation. Blocking features are saved in the special layer\n" " -unbl gfid: unblock feature before the main operation\n" " -unblall: unblock all blocked features before the main operation\n" " gnm_name: the network to work with (path and name)\n" ); if (pszAdditionalMsg) fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg); exit(1); } static void Usage(int bShort = TRUE) { Usage(nullptr, bShort); } /************************************************************************/ /* main() */ /************************************************************************/ #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \ do { if (iArg + nExtraArg >= nArgc) \ Usage(CPLSPrintf("%s option requires %d argument(s)", \ papszArgv[iArg], nExtraArg)); } while( false ) MAIN_START(nArgc, papszArgv) { int bQuiet = FALSE; const char *pszFormat = nullptr; const char *pszSRS = nullptr; GNMGFID nSrcFID = -1; GNMGFID nTgtFID = -1; GNMGFID nConFID = -1; double dfDirCost = 1.0; double dfInvCost = 1.0; GNMDirection eDir = GNM_EDGE_DIR_BOTH; const char *pszRuleStr = ""; const char *pszDataSource = nullptr; char **papszDSCO = nullptr; const char *pszInputDataset = nullptr; const char *pszInputLayer = nullptr; double dfTolerance = 0.0001; operation stOper = op_unknown; char **papszLayers = nullptr; GNMNetwork *poDS = nullptr; std::vector anFIDsToBlock; std::vector anFIDsToUnblock; bool bUnblockAll = false; int nRet = 0; // Check strict compilation and runtime library version as we use C++ API if (! GDAL_CHECK_VERSION(papszArgv[0])) exit(1); EarlySetConfigOptions(nArgc, papszArgv); /* -------------------------------------------------------------------- */ /* Register format(s). */ /* -------------------------------------------------------------------- */ GDALAllRegister(); /* -------------------------------------------------------------------- */ /* Processing command line arguments. */ /* -------------------------------------------------------------------- */ nArgc = GDALGeneralCmdLineProcessor( nArgc, &papszArgv, GDAL_OF_GNM ); if( nArgc < 1 ) { exit( -nArgc ); } for( int iArg = 1; iArg < nArgc; iArg++ ) { if( EQUAL(papszArgv[1], "--utility_version") ) { printf("%s was compiled against GDAL %s and is running against GDAL %s\n", papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME")); CSLDestroy( papszArgv ); return 0; } else if( EQUAL(papszArgv[iArg],"--help") ) { Usage(); } else if ( EQUAL(papszArgv[iArg], "--long-usage") ) { Usage(FALSE); } else if( EQUAL(papszArgv[iArg],"-q") || EQUAL(papszArgv[iArg],"-quiet") ) { bQuiet = TRUE; } else if ( EQUAL(papszArgv[iArg],"info") ) { stOper = op_info; } else if( EQUAL(papszArgv[iArg],"-f") || EQUAL(papszArgv[iArg],"-of") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); // coverity[tainted_data] pszFormat = papszArgv[++iArg]; } else if( EQUAL(papszArgv[iArg],"-dsco") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); // coverity[tainted_data] papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] ); } else if( EQUAL(papszArgv[iArg],"create") ) { stOper = op_create; } else if( EQUAL(papszArgv[iArg],"-t_srs") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); // coverity[tainted_data] pszSRS = papszArgv[++iArg]; } else if( EQUAL(papszArgv[iArg],"import") ) { stOper = op_import; CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); // coverity[tainted_data] pszInputDataset = papszArgv[++iArg]; } else if( EQUAL(papszArgv[iArg],"-l") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); // coverity[tainted_data] pszInputLayer = papszArgv[++iArg]; } else if( EQUAL(papszArgv[iArg],"connect") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(3); stOper = op_connect; // coverity[tainted_data] nSrcFID = atoi(papszArgv[++iArg]); // coverity[tainted_data] nTgtFID = atoi(papszArgv[++iArg]); // coverity[tainted_data] nConFID = atoi(papszArgv[++iArg]); } else if( EQUAL(papszArgv[iArg],"-c") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); // coverity[tainted_data] dfDirCost = CPLAtofM(papszArgv[++iArg]); } else if( EQUAL(papszArgv[iArg],"-ic") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); // coverity[tainted_data] dfInvCost = CPLAtofM(papszArgv[++iArg]); } else if( EQUAL(papszArgv[iArg],"-dir") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); // coverity[tainted_data] eDir = atoi(papszArgv[++iArg]); } else if( EQUAL(papszArgv[iArg],"disconnect") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(3); stOper = op_disconnect; // coverity[tainted_data] nSrcFID = atoi(papszArgv[++iArg]); // coverity[tainted_data] nTgtFID = atoi(papszArgv[++iArg]); // coverity[tainted_data] nConFID = atoi(papszArgv[++iArg]); } else if ( EQUAL(papszArgv[iArg],"autoconnect") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); stOper = op_autoconnect; // coverity[tainted_data] dfTolerance = CPLAtofM(papszArgv[++iArg]); } else if ( EQUAL(papszArgv[iArg],"rule") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); stOper = op_rule; // coverity[tainted_data] pszRuleStr = papszArgv[++iArg]; } else if ( EQUAL(papszArgv[iArg],"delete") ) { stOper = op_delete; } else if( EQUAL(papszArgv[iArg],"change") ) { stOper = op_change_st; } else if( EQUAL(papszArgv[iArg],"-bl") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); // coverity[tainted_data] anFIDsToBlock.push_back(atoi(papszArgv[++iArg])); } else if( EQUAL(papszArgv[iArg],"-unbl") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); // coverity[tainted_data] anFIDsToUnblock.push_back(atoi(papszArgv[++iArg])); } else if( EQUAL(papszArgv[iArg],"-unblall") ) { bUnblockAll = true; } else if( papszArgv[iArg][0] == '-' ) { Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg])); } else if( pszDataSource == nullptr ) pszDataSource = papszArgv[iArg]; else papszLayers = CSLAddString( papszLayers, papszArgv[iArg] ); } // do the work //////////////////////////////////////////////////////////////// if(stOper == op_info) { if(pszDataSource == nullptr) Usage("No network dataset provided"); //TODO for output: // stats about graph and blocked features // open poDS = cpl::down_cast(static_cast( GDALOpenEx( pszDataSource, GDAL_OF_READONLY | GDAL_OF_GNM, nullptr, nullptr, nullptr ))); GDALDriver *poDriver = nullptr; if( poDS != nullptr ) poDriver = poDS->GetDriver(); if( poDS == nullptr ) { fprintf(stderr, "FAILURE:\nUnable to open datasource `%s'.\n", pszDataSource); exit(1); } if( poDriver == nullptr ) { CPLAssert( false ); exit(1); } printf( "INFO: Open of `%s'\n using driver `%s' successful.\n", pszDataSource, poDriver->GetDescription() ); // Report projection. int nMajor = poDS->GetVersion() / 100; printf( "Network version: %d.%d.\n", nMajor, poDS->GetVersion() - nMajor * 100 ); const char* pszName = poDS->GetName(); if(nullptr != pszName) printf( "Network name: %s.\n", pszName ); const char* pszDescript = poDS->GetDescription(); if(nullptr != pszDescript) printf( "Network description: %s.\n", pszDescript ); char *pszProjection = const_cast(poDS->GetProjectionRef()); OGRSpatialReferenceH hSRS = OSRNewSpatialReference(nullptr); if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None ) { char *pszPrettyWkt = nullptr; OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE ); printf( "Coordinate System is:\n%s\n", pszPrettyWkt ); CPLFree( pszPrettyWkt ); } else { printf( "Coordinate System is '%s'\n", pszProjection ); } OSRDestroySpatialReference(hSRS); // report layers if(poDS->GetLayerCount() > 0) { printf("\nNetwork\'s layers: \n"); for (int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++) { OGRLayer *poLayer = poDS->GetLayer(iLayer); if (poLayer != nullptr) { printf(" %d: %s", iLayer + 1, poLayer->GetName()); int nGeomFieldCount = poLayer->GetLayerDefn()->GetGeomFieldCount(); if (nGeomFieldCount > 1) { printf(" ("); for (int iGeom = 0; iGeom < nGeomFieldCount; iGeom++) { if (iGeom > 0) printf(", "); OGRGeomFieldDefn* poGFldDefn = poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom); printf("%s", OGRGeometryTypeToName( poGFldDefn->GetType()) ); } printf(")"); } else if (poLayer->GetGeomType() != wkbUnknown) printf(" (%s)", OGRGeometryTypeToName( poLayer->GetGeomType()) ); printf("\n"); } } } // report rules GNMGenericNetwork* poGenericNetwork = dynamic_cast(poDS); if(nullptr != poGenericNetwork) { CPLStringList oList(poGenericNetwork->GetRules()); if(oList.Count() > 0) { printf("\nNetwork\'s rules: \n"); for(int iRule = 0; iRule < oList.Count(); ++iRule) { printf(" %d: %s\n", iRule + 1, oList[iRule]); } } } } else if(stOper == op_create) { const char* pszPath; const char* pszNetworkName = CSLFetchNameValue(papszDSCO, GNM_MD_NAME); if(pszDataSource == nullptr) Usage("No network dataset provided"); //the DSCO have priority on input keys if(nullptr == pszNetworkName) { pszPath = CPLGetPath(pszDataSource); pszNetworkName = CPLGetBasename(pszDataSource); papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_NAME, pszNetworkName); } else { pszPath = pszDataSource; } if( pszNetworkName == nullptr) Usage("No dataset name provided"); const char* pszFinalSRS = CSLFetchNameValue(papszDSCO, GNM_MD_SRS); if(nullptr == pszFinalSRS) { pszFinalSRS = pszSRS; papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_SRS, pszSRS); } if(nullptr == pszFinalSRS) Usage("No spatial reference provided"); if( pszFormat == nullptr ) Usage("No output format provided"); GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat); if( poDriver == nullptr ) { Usage( CPLSPrintf("%s driver not available", pszFormat) ); } else { char** papszMD = poDriver->GetMetadata(); if( !CPLFetchBool( papszMD, GDAL_DCAP_GNM, false ) ) Usage("not a GNM driver"); poDS = cpl::down_cast(poDriver->Create( pszPath, 0, 0, 0, GDT_Unknown, papszDSCO )); if (nullptr == poDS) { fprintf(stderr, "\nFAILURE: Failed to create network in a new dataset at " "%s and with driver %s\n", CPLFormFilename(pszPath, pszNetworkName, nullptr) ,pszFormat); nRet = 1; } else { if (bQuiet == FALSE) printf("\nNetwork created successfully in a " "new dataset at %s\n", CPLFormFilename(pszPath, pszNetworkName, nullptr)); } } } else if(stOper == op_import) { if(pszDataSource == nullptr) Usage("No network dataset provided"); if(pszInputDataset == nullptr) Usage("No input dataset name provided"); // open poDS = cpl::down_cast(static_cast(GDALOpenEx( pszDataSource, GDAL_OF_READONLY | GDAL_OF_GNM, nullptr, nullptr, nullptr ))); if(nullptr == poDS) { printf("\nFailed to open network at %s\n",pszDataSource); goto exit; } GDALDataset *poSrcDS = static_cast(GDALOpenEx(pszInputDataset, GDAL_OF_VECTOR | GDAL_OF_READONLY, nullptr, nullptr, nullptr )); if(nullptr == poSrcDS) { fprintf(stderr, "\nFAILURE: Can not open dataset at %s\n", pszInputDataset); nRet = 1; goto exit; } OGRLayer *poSrcLayer; if (pszInputLayer != nullptr) poSrcLayer = poSrcDS->GetLayerByName(pszInputLayer); else poSrcLayer = poSrcDS->GetLayer(0); if (nullptr == poSrcLayer) { if (pszInputLayer != nullptr) fprintf(stderr, "\nFAILURE: Can not open layer %s in %s\n", pszInputLayer,pszInputDataset); else fprintf(stderr, "\nFAILURE: Can not open layer in %s\n", pszInputDataset); GDALClose(poSrcDS); nRet = 1; goto exit; } OGRLayer * poLayer = poDS->CopyLayer(poSrcLayer, poSrcLayer->GetName()); if (nullptr == poLayer) { if (pszInputLayer != nullptr) fprintf(stderr, "\nFAILURE: Can not copy layer %s from %s\n", pszInputLayer,pszInputDataset); else fprintf(stderr, "\nFAILURE: Can not copy layer from %s\n", pszInputDataset); GDALClose(poSrcDS); nRet = 1; goto exit; } if (bQuiet == FALSE) { if (pszInputLayer != nullptr) printf("\nLayer %s successfully copied from %s and added to the network at %s\n", pszInputLayer, pszInputDataset, pszDataSource); else printf("\nLayer successfully copied from %s and added to the network at %s\n", pszInputDataset, pszDataSource); } GDALClose(poSrcDS); } else if (stOper == op_connect) { if(pszDataSource == nullptr) Usage("No network dataset provided"); // open poDS = cpl::down_cast(static_cast(GDALOpenEx( pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr, nullptr, nullptr ))); if(nullptr == poDS) { fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource); nRet = 1; goto exit; } GNMGenericNetwork* poGenericNetwork = dynamic_cast(poDS); if(nullptr == poGenericNetwork) { fprintf( stderr, "\nUnsupported datasource type for this operation\n"); nRet = 1; goto exit; } if(poGenericNetwork->ConnectFeatures(nSrcFID, nTgtFID, nConFID, dfDirCost, dfInvCost, eDir) != CE_None ) { fprintf( stderr, "Failed to connect features\n" ); nRet = 1; goto exit; } if (bQuiet == FALSE) { printf("Features connected successfully\n"); } } else if (stOper == op_disconnect) { if(pszDataSource == nullptr) Usage("No network dataset provided"); // open poDS = cpl::down_cast(static_cast(GDALOpenEx( pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr, nullptr, nullptr ))); if(nullptr == poDS) { fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource); nRet = 1; goto exit; } GNMGenericNetwork* poGenericNetwork = dynamic_cast(poDS); if(nullptr == poGenericNetwork) { fprintf( stderr, "\nUnsupported datasource type for this operation\n"); nRet = 1; goto exit; } if(poGenericNetwork->DisconnectFeatures(nSrcFID, nTgtFID, nConFID) != CE_None ) { fprintf( stderr, "Failed to disconnect features\n" ); nRet = 1; goto exit; } if (bQuiet == FALSE) { printf("Features disconnected successfully\n"); } } else if (stOper == op_rule) { if(pszDataSource == nullptr) Usage("No network dataset provided"); // open poDS = cpl::down_cast(static_cast(GDALOpenEx( pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr, nullptr, nullptr ))); if(nullptr == poDS) { fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource); nRet = 1; goto exit; } GNMGenericNetwork* poGenericNetwork = dynamic_cast(poDS); if(nullptr == poGenericNetwork) { fprintf( stderr, "\nUnsupported datasource type for this operation\n"); nRet = 1; goto exit; } if(poGenericNetwork->CreateRule(pszRuleStr) != CE_None ) { fprintf( stderr, "Failed to create rule %s\n", pszRuleStr ); nRet = 1; goto exit; } if (bQuiet == FALSE) { printf("Create rule '%s' successfully\n", pszRuleStr); } } else if (stOper == op_autoconnect) { if(pszDataSource == nullptr) Usage("No network dataset provided"); // open poDS = cpl::down_cast(static_cast(GDALOpenEx( pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr, nullptr, nullptr ))); if(nullptr == poDS) { fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource); nRet = 1; goto exit; } GNMGenericNetwork* poGenericNetwork = dynamic_cast(poDS); if(nullptr == poGenericNetwork) { fprintf( stderr, "\nUnsupported datasource type for this operation\n"); nRet = 1; goto exit; } if(CSLCount(papszLayers) == 0 && poDS->GetLayerCount() > 1) { if(bQuiet == FALSE) { printf("No layers provided. Use all layers of network:\n"); } for(int i = 0; i < poDS->GetLayerCount(); ++i) { OGRLayer* poLayer = poDS->GetLayer(i); if(bQuiet == FALSE) { printf("%d. %s\n", i + 1, poLayer->GetName()); } papszLayers = CSLAddString(papszLayers, poLayer->GetName() ); } } if(poGenericNetwork->ConnectPointsByLines(papszLayers, dfTolerance, dfDirCost, dfInvCost, eDir) != CE_None ) { fprintf( stderr, "Failed to autoconnect features\n" ); nRet = 1; goto exit; } if (bQuiet == FALSE) { printf("Features connected successfully\n"); } } else if(stOper == op_delete) { if(pszDataSource == nullptr) Usage("No network dataset provided"); // open poDS = cpl::down_cast(static_cast(GDALOpenEx( pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr, nullptr, nullptr ))); if(nullptr == poDS) { fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource); nRet = 1; goto exit; } if( poDS->Delete() != CE_None ) { fprintf( stderr, "Delete failed.\n" ); nRet = 1; goto exit; } if (bQuiet == FALSE) { printf("Delete successfully\n"); } /** if hDriver == NULL this code delete everything in folder, * not only GNM files GDALDriverH hDriver = NULL; if( pszFormat != NULL ) { hDriver = GDALGetDriverByName( pszFormat ); if( hDriver == NULL ) { fprintf( stderr, "Unable to find driver named '%s'.\n", pszFormat ); exit( 1 ); } } GDALDeleteDataset( hDriver, pszDataSource ); */ } else if(stOper == op_change_st) { if(pszDataSource == nullptr) Usage("No dataset in input"); // open poDS = cpl::down_cast(static_cast(GDALOpenEx( pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr, nullptr, nullptr ))); if(nullptr == poDS) { fprintf( stderr, "\nFailed to open network at %s\n", pszDataSource); nRet = 1; goto exit; } GNMGenericNetwork* poGenericNetwork = dynamic_cast(poDS); if(nullptr == poGenericNetwork) { fprintf( stderr, "\nUnsupported datasource type for this operation\n"); nRet = 1; goto exit; } if(bUnblockAll) { if(poGenericNetwork->ChangeAllBlockState(false) != CE_None) { fprintf( stderr, "\nChange all block state failed\n"); nRet = 1; goto exit; } } else { size_t i; for(i = 0; i < anFIDsToBlock.size(); ++i) { if(poGenericNetwork->ChangeBlockState(anFIDsToBlock[i], true) != CE_None) { fprintf( stderr, "\nChange block state of id " GNMGFIDFormat " failed\n", anFIDsToBlock[i]); nRet = 1; goto exit; } } for(i = 0; i < anFIDsToUnblock.size(); ++i) { if(poGenericNetwork->ChangeBlockState(anFIDsToUnblock[i], false) != CE_None) { fprintf( stderr, "\nChange block state of id " GNMGFIDFormat " failed\n", anFIDsToBlock[i]); nRet = 1; goto exit; } } } if (bQuiet == FALSE) { printf("Change block state successfully\n"); } } else { printf("\nNeed an operation. See help what you can do with gnmmanage:\n"); Usage(); } exit: CSLDestroy( papszArgv ); CSLDestroy( papszDSCO ); CSLDestroy( papszLayers ); if( poDS != nullptr ) GDALClose(poDS); GDALDestroyDriverManager(); return nRet; } MAIN_END