LCOV - code coverage report
Current view: top level - apps - gnmmanage.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 193 425 45.4 %
Date: 2024-11-21 22:18:42 Functions: 1 2 50.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * Project:  Geography Network utility
       3             :  * Purpose:  To manage GNM networks
       4             :  * Authors:  Mikhail Gusev, gusevmihs at gmail dot com
       5             :  *           Dmitry Baryshnikov, polimax@mail.ru
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2014, Mikhail Gusev
       9             :  * Copyright (c) 2014-2015, NextGIS <info@nextgis.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "commonutils.h"
      15             : #include "cpl_string.h"
      16             : #include "gdal_version.h"
      17             : #include "gdal.h"
      18             : #include "gnm.h"
      19             : #include "gnm_priv.h"
      20             : 
      21             : // #include "ogr_p.h"
      22             : // #include "gnm.h"
      23             : // #include "gnm_api.h"
      24             : 
      25             : enum operation
      26             : {
      27             :     op_unknown = 0, /** no operation */
      28             :     op_info,        /** print information about network */
      29             :     op_create,      /** create a new network */
      30             :     op_import,      /** add a OGR layer to the network */
      31             :     op_connect,     /** connect features from layers added to the network */
      32             :     op_disconnect,  /** disconnect features from layers added to the network */
      33             :     op_rule,        /** add connect rule */
      34             :     op_autoconnect, /** try to connect features base on their tolerance */
      35             :     op_delete,      /** delete network */
      36             :     op_change_st    /** change vertex or edge blocking state */
      37             : };
      38             : 
      39             : /************************************************************************/
      40             : /*                               Usage()                                */
      41             : /************************************************************************/
      42             : 
      43             : static void Usage(bool bIsError, const char *pszAdditionalMsg = nullptr,
      44             :                   bool bShort = true) CPL_NO_RETURN;
      45             : 
      46           0 : static void Usage(bool bIsError, const char *pszAdditionalMsg, bool bShort)
      47             : {
      48           0 :     fprintf(
      49             :         bIsError ? stderr : stdout,
      50             :         "Usage: gnmmanage [--help][--help-general][-q][-quiet][--long-usage]\n"
      51             :         "                 [info]\n"
      52             :         "                 [create [-f <format_name>] [-t_srs <srs_name>] "
      53             :         "[-dsco "
      54             :         "<NAME>=<VALUE>]... ]\n"
      55             :         "                 [import <src_dataset_name>] [-l <layer_name>]\n"
      56             :         "                 [connect <gfid_src> <gfid_tgt> <gfid_con> [-c "
      57             :         "<cost>] "
      58             :         "[-ic <inv_cost>] [-dir <dir>]]\n"
      59             :         "                 [disconnect <gfid_src> <gfid_tgt> <gfid_con>]\n"
      60             :         "                 [rule <rule_str>]\n"
      61             :         "                 [autoconnect <tolerance>]\n"
      62             :         "                 [delete]\n"
      63             :         "                 [change [-bl <gfid>][-unbl <gfid>][-unblall]]\n"
      64             :         "                 <gnm_name> [<layer> [<layer>]...]\n");
      65             : 
      66           0 :     if (bShort)
      67             :     {
      68           0 :         fprintf(bIsError ? stderr : stdout,
      69             :                 "\nNote: gnmmanage --long-usage for full help.\n");
      70           0 :         if (pszAdditionalMsg)
      71           0 :             fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
      72           0 :         exit(1);
      73             :     }
      74             : 
      75           0 :     fprintf(bIsError ? stderr : stdout,
      76             :             "\n   info: different information about network: system and class "
      77             :             "layers, network metadata, network spatial reference\n"
      78             :             "   create: create network\n"
      79             :             "      -f format_name: output file format name, possible values "
      80             :             "are:\n");
      81             : 
      82           0 :     int nGNMDriverCounter = 1;
      83           0 :     for (int iDr = 0; iDr < GDALGetDriverCount(); iDr++)
      84             :     {
      85           0 :         GDALDriverH hDriver = GDALGetDriver(iDr);
      86             : 
      87           0 :         const char *pszRFlag = "", *pszWFlag, *pszVirtualIO, *pszSubdatasets;
      88           0 :         char **papszMD = GDALGetMetadata(hDriver, nullptr);
      89             : 
      90           0 :         if (CPLFetchBool(papszMD, GDAL_DCAP_RASTER, false))
      91           0 :             continue;
      92           0 :         if (CPLFetchBool(papszMD, GDAL_DCAP_VECTOR, false))
      93           0 :             continue;
      94             : 
      95           0 :         if (CPLFetchBool(papszMD, GDAL_DCAP_OPEN, false))
      96           0 :             pszRFlag = "r";
      97             : 
      98           0 :         if (CPLFetchBool(papszMD, GDAL_DCAP_CREATE, false))
      99           0 :             pszWFlag = "w+";
     100           0 :         else if (CPLFetchBool(papszMD, GDAL_DCAP_CREATECOPY, false))
     101           0 :             pszWFlag = "w";
     102             :         else
     103           0 :             pszWFlag = "o";
     104             : 
     105           0 :         if (CPLFetchBool(papszMD, GDAL_DCAP_VIRTUALIO, false))
     106           0 :             pszVirtualIO = "v";
     107             :         else
     108           0 :             pszVirtualIO = "";
     109             : 
     110           0 :         if (CPLFetchBool(papszMD, GDAL_DMD_SUBDATASETS, false))
     111           0 :             pszSubdatasets = "s";
     112             :         else
     113           0 :             pszSubdatasets = "";
     114             : 
     115           0 :         fprintf(bIsError ? stderr : stdout, "          %d. %s (%s%s%s%s): %s\n",
     116             :                 nGNMDriverCounter++, GDALGetDriverShortName(hDriver), pszRFlag,
     117             :                 pszWFlag, pszVirtualIO, pszSubdatasets,
     118             :                 GDALGetDriverLongName(hDriver));
     119             :     }
     120             : 
     121           0 :     fprintf(
     122             :         bIsError ? stderr : stdout,
     123             :         "      -t_srs srs_name: spatial reference input\n"
     124             :         "      -dsco NAME=VALUE: network creation option set as pair=value\n"
     125             :         "   import src_dataset_name: import external layer where "
     126             :         "src_dataset_name is a dataset name to copy from\n"
     127             :         "      -l layer_name: layer name in dataset. If unset, 0 layer is "
     128             :         "copied\n"
     129             :         "   connect gfid_src gfid_tgt gfid_con: make a topological connection, "
     130             :         "where the gfid_src and gfid_tgt are vertices and gfid_con is edge "
     131             :         "(gfid_con can be -1, so the virtual connection will be created)\n"
     132             :         "      -c cost -ic inv_cost -dir dir: manually assign the following "
     133             :         "values: the cost (weight), inverse cost and direction of the edge "
     134             :         "(optional)\n"
     135             :         "   disconnect gfid_src gfid_tgt gfid_con: removes the connection from "
     136             :         "the graph\n"
     137             :         "   rule rule_str: creates a rule in the network by the given rule_str "
     138             :         "string\n"
     139             :         "   autoconnect tolerance: create topology automatically with the "
     140             :         "given double tolerance\n"
     141             :         "   delete: delete network\n"
     142             :         "   change: modify blocking state of vertices and edges ans save them "
     143             :         "in the network"
     144             :         "   -bl gfid: block feature before the main operation. Blocking "
     145             :         "features are saved in the special layer\n"
     146             :         "   -unbl gfid: unblock feature before the main operation\n"
     147             :         "   -unblall: unblock all blocked features before the main operation\n"
     148             :         "   gnm_name: the network to work with (path and name)\n");
     149             : 
     150           0 :     if (pszAdditionalMsg)
     151           0 :         fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
     152             : 
     153           0 :     exit(bIsError ? 1 : 0);
     154             : }
     155             : 
     156             : /************************************************************************/
     157             : /*                                main()                                */
     158             : /************************************************************************/
     159             : 
     160             : #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg)                            \
     161             :     do                                                                         \
     162             :     {                                                                          \
     163             :         if (iArg + nExtraArg >= nArgc)                                         \
     164             :             Usage(true, CPLSPrintf("%s option requires %d argument(s)",        \
     165             :                                    papszArgv[iArg], nExtraArg));               \
     166             :     } while (false)
     167             : 
     168           7 : MAIN_START(nArgc, papszArgv)
     169             : 
     170             : {
     171           7 :     int bQuiet = FALSE;
     172           7 :     const char *pszFormat = nullptr;
     173           7 :     const char *pszSRS = nullptr;
     174           7 :     GNMGFID nSrcFID = -1;
     175           7 :     GNMGFID nTgtFID = -1;
     176           7 :     GNMGFID nConFID = -1;
     177           7 :     double dfDirCost = 1.0;
     178           7 :     double dfInvCost = 1.0;
     179           7 :     GNMDirection eDir = GNM_EDGE_DIR_BOTH;
     180           7 :     const char *pszRuleStr = "";
     181           7 :     const char *pszDataSource = nullptr;
     182           7 :     char **papszDSCO = nullptr;
     183           7 :     const char *pszInputDataset = nullptr;
     184           7 :     const char *pszInputLayer = nullptr;
     185           7 :     double dfTolerance = 0.0001;
     186           7 :     operation stOper = op_unknown;
     187           7 :     char **papszLayers = nullptr;
     188           7 :     GNMNetwork *poDS = nullptr;
     189          14 :     std::vector<GNMGFID> anFIDsToBlock;
     190          14 :     std::vector<GNMGFID> anFIDsToUnblock;
     191           7 :     bool bUnblockAll = false;
     192           7 :     int nRet = 0;
     193             : 
     194             :     // Check strict compilation and runtime library version as we use C++ API
     195           7 :     if (!GDAL_CHECK_VERSION(papszArgv[0]))
     196           0 :         exit(1);
     197             : 
     198           7 :     EarlySetConfigOptions(nArgc, papszArgv);
     199             : 
     200             :     /* -------------------------------------------------------------------- */
     201             :     /*      Register format(s).                                             */
     202             :     /* -------------------------------------------------------------------- */
     203           7 :     GDALAllRegister();
     204             : 
     205             :     /* -------------------------------------------------------------------- */
     206             :     /*      Processing command line arguments.                              */
     207             :     /* -------------------------------------------------------------------- */
     208           7 :     nArgc = GDALGeneralCmdLineProcessor(nArgc, &papszArgv, GDAL_OF_GNM);
     209             : 
     210           7 :     if (nArgc < 1)
     211             :     {
     212           0 :         exit(-nArgc);
     213             :     }
     214             : 
     215          23 :     for (int iArg = 1; iArg < nArgc; iArg++)
     216             :     {
     217          17 :         if (EQUAL(papszArgv[1], "--utility_version"))
     218             :         {
     219           1 :             printf("%s was compiled against GDAL %s and is running against "
     220             :                    "GDAL %s\n",
     221             :                    papszArgv[0], GDAL_RELEASE_NAME,
     222             :                    GDALVersionInfo("RELEASE_NAME"));
     223           1 :             CSLDestroy(papszArgv);
     224           1 :             return 0;
     225             :         }
     226             : 
     227          16 :         else if (EQUAL(papszArgv[iArg], "--help"))
     228             :         {
     229           0 :             Usage(false);
     230             :         }
     231             : 
     232          16 :         else if (EQUAL(papszArgv[iArg], "--long-usage"))
     233             :         {
     234           0 :             Usage(false, nullptr, false);
     235             :         }
     236             : 
     237          16 :         else if (EQUAL(papszArgv[iArg], "-q") ||
     238          16 :                  EQUAL(papszArgv[iArg], "-quiet"))
     239             :         {
     240           0 :             bQuiet = TRUE;
     241             :         }
     242             : 
     243          16 :         else if (EQUAL(papszArgv[iArg], "info"))
     244             :         {
     245           1 :             stOper = op_info;
     246             :         }
     247             : 
     248          15 :         else if (EQUAL(papszArgv[iArg], "-f") || EQUAL(papszArgv[iArg], "-of"))
     249             :         {
     250           1 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     251             :             // coverity[tainted_data]
     252           1 :             pszFormat = papszArgv[++iArg];
     253             :         }
     254             : 
     255          14 :         else if (EQUAL(papszArgv[iArg], "-dsco"))
     256             :         {
     257           2 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     258             :             // coverity[tainted_data]
     259           2 :             papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg]);
     260             :         }
     261             : 
     262          12 :         else if (EQUAL(papszArgv[iArg], "create"))
     263             :         {
     264           1 :             stOper = op_create;
     265             :         }
     266             : 
     267          11 :         else if (EQUAL(papszArgv[iArg], "-t_srs"))
     268             :         {
     269           1 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     270             :             // coverity[tainted_data]
     271           1 :             pszSRS = papszArgv[++iArg];
     272             :         }
     273             : 
     274          10 :         else if (EQUAL(papszArgv[iArg], "import"))
     275             :         {
     276           2 :             stOper = op_import;
     277           2 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     278             :             // coverity[tainted_data]
     279           2 :             pszInputDataset = papszArgv[++iArg];
     280             :         }
     281             : 
     282           8 :         else if (EQUAL(papszArgv[iArg], "-l"))
     283             :         {
     284           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     285             :             // coverity[tainted_data]
     286           0 :             pszInputLayer = papszArgv[++iArg];
     287             :         }
     288             : 
     289           8 :         else if (EQUAL(papszArgv[iArg], "connect"))
     290             :         {
     291           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(3);
     292           0 :             stOper = op_connect;
     293             :             // coverity[tainted_data]
     294           0 :             nSrcFID = atoi(papszArgv[++iArg]);
     295             :             // coverity[tainted_data]
     296           0 :             nTgtFID = atoi(papszArgv[++iArg]);
     297             :             // coverity[tainted_data]
     298           0 :             nConFID = atoi(papszArgv[++iArg]);
     299             :         }
     300             : 
     301           8 :         else if (EQUAL(papszArgv[iArg], "-c"))
     302             :         {
     303           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     304             :             // coverity[tainted_data]
     305           0 :             dfDirCost = CPLAtofM(papszArgv[++iArg]);
     306             :         }
     307           8 :         else if (EQUAL(papszArgv[iArg], "-ic"))
     308             :         {
     309           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     310             :             // coverity[tainted_data]
     311           0 :             dfInvCost = CPLAtofM(papszArgv[++iArg]);
     312             :         }
     313           8 :         else if (EQUAL(papszArgv[iArg], "-dir"))
     314             :         {
     315           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     316             :             // coverity[tainted_data]
     317           0 :             eDir = atoi(papszArgv[++iArg]);
     318             :         }
     319             : 
     320           8 :         else if (EQUAL(papszArgv[iArg], "disconnect"))
     321             :         {
     322           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(3);
     323           0 :             stOper = op_disconnect;
     324             :             // coverity[tainted_data]
     325           0 :             nSrcFID = atoi(papszArgv[++iArg]);
     326             :             // coverity[tainted_data]
     327           0 :             nTgtFID = atoi(papszArgv[++iArg]);
     328             :             // coverity[tainted_data]
     329           0 :             nConFID = atoi(papszArgv[++iArg]);
     330             :         }
     331             : 
     332           8 :         else if (EQUAL(papszArgv[iArg], "autoconnect"))
     333             :         {
     334           1 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     335           1 :             stOper = op_autoconnect;
     336             :             // coverity[tainted_data]
     337           1 :             dfTolerance = CPLAtofM(papszArgv[++iArg]);
     338             :         }
     339             : 
     340           7 :         else if (EQUAL(papszArgv[iArg], "rule"))
     341             :         {
     342           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     343           0 :             stOper = op_rule;
     344             :             // coverity[tainted_data]
     345           0 :             pszRuleStr = papszArgv[++iArg];
     346             :         }
     347             : 
     348           7 :         else if (EQUAL(papszArgv[iArg], "delete"))
     349             :         {
     350           1 :             stOper = op_delete;
     351             :         }
     352             : 
     353           6 :         else if (EQUAL(papszArgv[iArg], "change"))
     354             :         {
     355           0 :             stOper = op_change_st;
     356             :         }
     357             : 
     358           6 :         else if (EQUAL(papszArgv[iArg], "-bl"))
     359             :         {
     360           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     361             :             // coverity[tainted_data]
     362           0 :             anFIDsToBlock.push_back(atoi(papszArgv[++iArg]));
     363             :         }
     364             : 
     365           6 :         else if (EQUAL(papszArgv[iArg], "-unbl"))
     366             :         {
     367           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     368             :             // coverity[tainted_data]
     369           0 :             anFIDsToUnblock.push_back(atoi(papszArgv[++iArg]));
     370             :         }
     371             : 
     372           6 :         else if (EQUAL(papszArgv[iArg], "-unblall"))
     373             :         {
     374           0 :             bUnblockAll = true;
     375             :         }
     376             : 
     377           6 :         else if (papszArgv[iArg][0] == '-')
     378             :         {
     379           0 :             Usage(true,
     380           0 :                   CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
     381             :         }
     382             : 
     383           6 :         else if (pszDataSource == nullptr)
     384           6 :             pszDataSource = papszArgv[iArg];
     385             :         else
     386           0 :             papszLayers = CSLAddString(papszLayers, papszArgv[iArg]);
     387             :     }
     388             : 
     389             :     // do the work
     390             :     // ////////////////////////////////////////////////////////////////
     391             : 
     392           6 :     if (stOper == op_info)
     393             :     {
     394           1 :         if (pszDataSource == nullptr)
     395           0 :             Usage(true, "No network dataset provided");
     396             : 
     397             :         // TODO for output:
     398             :         //  stats about graph and blocked features
     399             : 
     400             :         // open
     401             : 
     402           2 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     403           1 :             GDALOpenEx(pszDataSource, GDAL_OF_READONLY | GDAL_OF_GNM, nullptr,
     404             :                        nullptr, nullptr)));
     405             : 
     406           1 :         GDALDriver *poDriver = nullptr;
     407           1 :         if (poDS != nullptr)
     408           1 :             poDriver = poDS->GetDriver();
     409             : 
     410           1 :         if (poDS == nullptr)
     411             :         {
     412           0 :             fprintf(stderr, "FAILURE:\nUnable to open datasource `%s'.\n",
     413             :                     pszDataSource);
     414           0 :             exit(1);
     415             :         }
     416             : 
     417           1 :         if (poDriver == nullptr)
     418             :         {
     419           0 :             CPLAssert(false);
     420             :             exit(1);
     421             :         }
     422             : 
     423           1 :         printf("INFO: Open of `%s'\n      using driver `%s' successful.\n",
     424           1 :                pszDataSource, poDriver->GetDescription());
     425             : 
     426             :         // Report projection.
     427           1 :         int nMajor = poDS->GetVersion() / 100;
     428           1 :         printf("Network version: %d.%d.\n", nMajor,
     429           1 :                poDS->GetVersion() - nMajor * 100);
     430           1 :         const char *pszName = poDS->GetName();
     431           1 :         if (nullptr != pszName)
     432           1 :             printf("Network name: %s.\n", pszName);
     433           1 :         const char *pszDescript = poDS->GetDescription();
     434           1 :         if (nullptr != pszDescript)
     435           1 :             printf("Network description: %s.\n", pszDescript);
     436             : 
     437           1 :         char *pszProjection = const_cast<char *>(poDS->GetProjectionRef());
     438           1 :         OGRSpatialReferenceH hSRS = OSRNewSpatialReference(nullptr);
     439           1 :         if (OSRImportFromWkt(hSRS, &pszProjection) == CE_None)
     440             :         {
     441           0 :             char *pszPrettyWkt = nullptr;
     442           0 :             OSRExportToPrettyWkt(hSRS, &pszPrettyWkt, FALSE);
     443             : 
     444           0 :             printf("Coordinate System is:\n%s\n", pszPrettyWkt);
     445           0 :             CPLFree(pszPrettyWkt);
     446             :         }
     447             :         else
     448             :         {
     449           1 :             printf("Coordinate System is '%s'\n", pszProjection);
     450             :         }
     451           1 :         OSRDestroySpatialReference(hSRS);
     452             : 
     453             :         // report layers
     454           1 :         if (poDS->GetLayerCount() > 0)
     455             :         {
     456           1 :             printf("\nNetwork\'s layers: \n");
     457           3 :             for (int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++)
     458             :             {
     459           2 :                 OGRLayer *poLayer = poDS->GetLayer(iLayer);
     460             : 
     461           2 :                 if (poLayer != nullptr)
     462             :                 {
     463           2 :                     printf("  %d: %s", iLayer + 1, poLayer->GetName());
     464             : 
     465             :                     int nGeomFieldCount =
     466           2 :                         poLayer->GetLayerDefn()->GetGeomFieldCount();
     467           2 :                     if (nGeomFieldCount > 1)
     468             :                     {
     469           0 :                         printf(" (");
     470           0 :                         for (int iGeom = 0; iGeom < nGeomFieldCount; iGeom++)
     471             :                         {
     472           0 :                             if (iGeom > 0)
     473           0 :                                 printf(", ");
     474             :                             OGRGeomFieldDefn *poGFldDefn =
     475           0 :                                 poLayer->GetLayerDefn()->GetGeomFieldDefn(
     476           0 :                                     iGeom);
     477           0 :                             printf("%s", OGRGeometryTypeToName(
     478             :                                              poGFldDefn->GetType()));
     479             :                         }
     480           0 :                         printf(")");
     481             :                     }
     482           2 :                     else if (poLayer->GetGeomType() != wkbUnknown)
     483           2 :                         printf(" (%s)",
     484           2 :                                OGRGeometryTypeToName(poLayer->GetGeomType()));
     485             : 
     486           2 :                     printf("\n");
     487             :                 }
     488             :             }
     489             :         }
     490             : 
     491             :         // report rules
     492             :         GNMGenericNetwork *poGenericNetwork =
     493           1 :             dynamic_cast<GNMGenericNetwork *>(poDS);
     494             : 
     495           1 :         if (nullptr != poGenericNetwork)
     496             :         {
     497           2 :             CPLStringList oList(poGenericNetwork->GetRules());
     498           1 :             if (oList.Count() > 0)
     499             :             {
     500           1 :                 printf("\nNetwork\'s rules: \n");
     501           2 :                 for (int iRule = 0; iRule < oList.Count(); ++iRule)
     502             :                 {
     503           1 :                     printf("  %d: %s\n", iRule + 1, oList[iRule]);
     504             :                 }
     505             :             }
     506             :         }
     507             :     }
     508           5 :     else if (stOper == op_create)
     509             :     {
     510             :         const char *pszPath;
     511           1 :         const char *pszNetworkName = CSLFetchNameValue(papszDSCO, GNM_MD_NAME);
     512             : 
     513           1 :         if (pszDataSource == nullptr)
     514           0 :             Usage(true, "No network dataset provided");
     515             : 
     516             :         // the DSCO have priority on input keys
     517           1 :         if (nullptr == pszNetworkName)
     518             :         {
     519           0 :             pszPath = CPLGetPath(pszDataSource);
     520           0 :             pszNetworkName = CPLGetBasename(pszDataSource);
     521           0 :             papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_NAME, pszNetworkName);
     522             :         }
     523             :         else
     524             :         {
     525           1 :             pszPath = pszDataSource;
     526             :         }
     527             : 
     528           1 :         if (pszNetworkName == nullptr)
     529           0 :             Usage(true, "No dataset name provided");
     530             : 
     531           1 :         const char *pszFinalSRS = CSLFetchNameValue(papszDSCO, GNM_MD_SRS);
     532           1 :         if (nullptr == pszFinalSRS)
     533             :         {
     534           1 :             pszFinalSRS = pszSRS;
     535           1 :             papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_SRS, pszSRS);
     536             :         }
     537             : 
     538           1 :         if (nullptr == pszFinalSRS)
     539           0 :             Usage(true, "No spatial reference provided");
     540           1 :         if (pszFormat == nullptr)
     541           0 :             Usage(true, "No output format provided");
     542             : 
     543             :         GDALDriver *poDriver =
     544           1 :             GetGDALDriverManager()->GetDriverByName(pszFormat);
     545           1 :         if (poDriver == nullptr)
     546             :         {
     547           0 :             Usage(true, CPLSPrintf("%s driver not available", pszFormat));
     548             :         }
     549             :         else
     550             :         {
     551           1 :             char **papszMD = poDriver->GetMetadata();
     552             : 
     553           1 :             if (!CPLFetchBool(papszMD, GDAL_DCAP_GNM, false))
     554           0 :                 Usage(true, "not a GNM driver");
     555             : 
     556           1 :             poDS = cpl::down_cast<GNMNetwork *>(
     557             :                 poDriver->Create(pszPath, 0, 0, 0, GDT_Unknown, papszDSCO));
     558             : 
     559           1 :             if (nullptr == poDS)
     560             :             {
     561           0 :                 fprintf(
     562             :                     stderr,
     563             :                     "\nFAILURE: Failed to create network in a new dataset at "
     564             :                     "%s and with driver %s\n",
     565             :                     CPLFormFilename(pszPath, pszNetworkName, nullptr),
     566             :                     pszFormat);
     567           0 :                 nRet = 1;
     568             :             }
     569             :             else
     570             :             {
     571           1 :                 if (bQuiet == FALSE)
     572           1 :                     printf("\nNetwork created successfully in a "
     573             :                            "new dataset at %s\n",
     574             :                            CPLFormFilename(pszPath, pszNetworkName, nullptr));
     575             :             }
     576             :         }
     577             :     }
     578           4 :     else if (stOper == op_import)
     579             :     {
     580           2 :         if (pszDataSource == nullptr)
     581           0 :             Usage(true, "No network dataset provided");
     582             : 
     583           2 :         if (pszInputDataset == nullptr)
     584           0 :             Usage(true, "No input dataset name provided");
     585             : 
     586             :         // open
     587           4 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     588           2 :             GDALOpenEx(pszDataSource, GDAL_OF_READONLY | GDAL_OF_GNM, nullptr,
     589             :                        nullptr, nullptr)));
     590             : 
     591           2 :         if (nullptr == poDS)
     592             :         {
     593           0 :             printf("\nFailed to open network at %s\n", pszDataSource);
     594           0 :             goto exit;
     595             :         }
     596             : 
     597             :         GDALDataset *poSrcDS = static_cast<GDALDataset *>(
     598           2 :             GDALOpenEx(pszInputDataset, GDAL_OF_VECTOR | GDAL_OF_READONLY,
     599             :                        nullptr, nullptr, nullptr));
     600           2 :         if (nullptr == poSrcDS)
     601             :         {
     602           0 :             fprintf(stderr, "\nFAILURE: Can not open dataset at %s\n",
     603             :                     pszInputDataset);
     604             : 
     605           0 :             nRet = 1;
     606           0 :             goto exit;
     607             :         }
     608             : 
     609             :         OGRLayer *poSrcLayer;
     610           2 :         if (pszInputLayer != nullptr)
     611           0 :             poSrcLayer = poSrcDS->GetLayerByName(pszInputLayer);
     612             :         else
     613           2 :             poSrcLayer = poSrcDS->GetLayer(0);
     614             : 
     615           2 :         if (nullptr == poSrcLayer)
     616             :         {
     617           0 :             if (pszInputLayer != nullptr)
     618           0 :                 fprintf(stderr, "\nFAILURE: Can not open layer %s in %s\n",
     619             :                         pszInputLayer, pszInputDataset);
     620             :             else
     621           0 :                 fprintf(stderr, "\nFAILURE: Can not open layer in %s\n",
     622             :                         pszInputDataset);
     623             : 
     624           0 :             GDALClose(poSrcDS);
     625             : 
     626           0 :             nRet = 1;
     627           0 :             goto exit;
     628             :         }
     629             : 
     630           2 :         OGRLayer *poLayer = poDS->CopyLayer(poSrcLayer, poSrcLayer->GetName());
     631           2 :         if (nullptr == poLayer)
     632             :         {
     633           0 :             if (pszInputLayer != nullptr)
     634           0 :                 fprintf(stderr, "\nFAILURE: Can not copy layer %s from %s\n",
     635             :                         pszInputLayer, pszInputDataset);
     636             :             else
     637           0 :                 fprintf(stderr, "\nFAILURE: Can not copy layer from %s\n",
     638             :                         pszInputDataset);
     639           0 :             GDALClose(poSrcDS);
     640             : 
     641           0 :             nRet = 1;
     642           0 :             goto exit;
     643             :         }
     644             : 
     645           2 :         if (bQuiet == FALSE)
     646             :         {
     647           2 :             if (pszInputLayer != nullptr)
     648           0 :                 printf("\nLayer %s successfully copied from %s and added to "
     649             :                        "the network at %s\n",
     650             :                        pszInputLayer, pszInputDataset, pszDataSource);
     651             :             else
     652           2 :                 printf("\nLayer successfully copied from %s and added to the "
     653             :                        "network at %s\n",
     654             :                        pszInputDataset, pszDataSource);
     655             :         }
     656             : 
     657           2 :         GDALClose(poSrcDS);
     658             :     }
     659           2 :     else if (stOper == op_connect)
     660             :     {
     661           0 :         if (pszDataSource == nullptr)
     662           0 :             Usage(true, "No network dataset provided");
     663             : 
     664             :         // open
     665           0 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     666           0 :             GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
     667             :                        nullptr, nullptr)));
     668             : 
     669           0 :         if (nullptr == poDS)
     670             :         {
     671           0 :             fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
     672           0 :             nRet = 1;
     673           0 :             goto exit;
     674             :         }
     675             : 
     676             :         GNMGenericNetwork *poGenericNetwork =
     677           0 :             dynamic_cast<GNMGenericNetwork *>(poDS);
     678             : 
     679           0 :         if (nullptr == poGenericNetwork)
     680             :         {
     681           0 :             fprintf(stderr,
     682             :                     "\nUnsupported datasource type for this operation\n");
     683           0 :             nRet = 1;
     684           0 :             goto exit;
     685             :         }
     686             : 
     687           0 :         if (poGenericNetwork->ConnectFeatures(nSrcFID, nTgtFID, nConFID,
     688             :                                               dfDirCost, dfInvCost,
     689           0 :                                               eDir) != CE_None)
     690             :         {
     691           0 :             fprintf(stderr, "Failed to connect features\n");
     692           0 :             nRet = 1;
     693           0 :             goto exit;
     694             :         }
     695             : 
     696           0 :         if (bQuiet == FALSE)
     697             :         {
     698           0 :             printf("Features connected successfully\n");
     699             :         }
     700             :     }
     701           2 :     else if (stOper == op_disconnect)
     702             :     {
     703           0 :         if (pszDataSource == nullptr)
     704           0 :             Usage(true, "No network dataset provided");
     705             : 
     706             :         // open
     707           0 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     708           0 :             GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
     709             :                        nullptr, nullptr)));
     710             : 
     711           0 :         if (nullptr == poDS)
     712             :         {
     713           0 :             fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
     714           0 :             nRet = 1;
     715           0 :             goto exit;
     716             :         }
     717             : 
     718             :         GNMGenericNetwork *poGenericNetwork =
     719           0 :             dynamic_cast<GNMGenericNetwork *>(poDS);
     720             : 
     721           0 :         if (nullptr == poGenericNetwork)
     722             :         {
     723           0 :             fprintf(stderr,
     724             :                     "\nUnsupported datasource type for this operation\n");
     725           0 :             nRet = 1;
     726           0 :             goto exit;
     727             :         }
     728             : 
     729           0 :         if (poGenericNetwork->DisconnectFeatures(nSrcFID, nTgtFID, nConFID) !=
     730             :             CE_None)
     731             :         {
     732           0 :             fprintf(stderr, "Failed to disconnect features\n");
     733           0 :             nRet = 1;
     734           0 :             goto exit;
     735             :         }
     736             : 
     737           0 :         if (bQuiet == FALSE)
     738             :         {
     739           0 :             printf("Features disconnected successfully\n");
     740             :         }
     741             :     }
     742           2 :     else if (stOper == op_rule)
     743             :     {
     744           0 :         if (pszDataSource == nullptr)
     745           0 :             Usage(true, "No network dataset provided");
     746             : 
     747             :         // open
     748           0 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     749           0 :             GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
     750             :                        nullptr, nullptr)));
     751             : 
     752           0 :         if (nullptr == poDS)
     753             :         {
     754           0 :             fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
     755           0 :             nRet = 1;
     756           0 :             goto exit;
     757             :         }
     758             : 
     759             :         GNMGenericNetwork *poGenericNetwork =
     760           0 :             dynamic_cast<GNMGenericNetwork *>(poDS);
     761             : 
     762           0 :         if (nullptr == poGenericNetwork)
     763             :         {
     764           0 :             fprintf(stderr,
     765             :                     "\nUnsupported datasource type for this operation\n");
     766           0 :             nRet = 1;
     767           0 :             goto exit;
     768             :         }
     769             : 
     770           0 :         if (poGenericNetwork->CreateRule(pszRuleStr) != CE_None)
     771             :         {
     772           0 :             fprintf(stderr, "Failed to create rule %s\n", pszRuleStr);
     773           0 :             nRet = 1;
     774           0 :             goto exit;
     775             :         }
     776             : 
     777           0 :         if (bQuiet == FALSE)
     778             :         {
     779           0 :             printf("Create rule '%s' successfully\n", pszRuleStr);
     780             :         }
     781             :     }
     782           2 :     else if (stOper == op_autoconnect)
     783             :     {
     784           1 :         if (pszDataSource == nullptr)
     785           0 :             Usage(true, "No network dataset provided");
     786             : 
     787             :         // open
     788           2 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     789           1 :             GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
     790             :                        nullptr, nullptr)));
     791             : 
     792           1 :         if (nullptr == poDS)
     793             :         {
     794           0 :             fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
     795           0 :             nRet = 1;
     796           0 :             goto exit;
     797             :         }
     798             : 
     799             :         GNMGenericNetwork *poGenericNetwork =
     800           1 :             dynamic_cast<GNMGenericNetwork *>(poDS);
     801             : 
     802           1 :         if (nullptr == poGenericNetwork)
     803             :         {
     804           0 :             fprintf(stderr,
     805             :                     "\nUnsupported datasource type for this operation\n");
     806           0 :             nRet = 1;
     807           0 :             goto exit;
     808             :         }
     809             : 
     810           1 :         if (CSLCount(papszLayers) == 0 && poDS->GetLayerCount() > 1)
     811             :         {
     812           1 :             if (bQuiet == FALSE)
     813             :             {
     814           1 :                 printf("No layers provided. Use all layers of network:\n");
     815             :             }
     816             : 
     817           3 :             for (int i = 0; i < poDS->GetLayerCount(); ++i)
     818             :             {
     819           2 :                 OGRLayer *poLayer = poDS->GetLayer(i);
     820           2 :                 if (bQuiet == FALSE)
     821             :                 {
     822           2 :                     printf("%d. %s\n", i + 1, poLayer->GetName());
     823             :                 }
     824           2 :                 papszLayers = CSLAddString(papszLayers, poLayer->GetName());
     825             :             }
     826             :         }
     827             : 
     828           2 :         if (poGenericNetwork->ConnectPointsByLines(papszLayers, dfTolerance,
     829             :                                                    dfDirCost, dfInvCost,
     830           1 :                                                    eDir) != CE_None)
     831             :         {
     832           0 :             fprintf(stderr, "Failed to autoconnect features\n");
     833           0 :             nRet = 1;
     834           0 :             goto exit;
     835             :         }
     836             : 
     837           1 :         if (bQuiet == FALSE)
     838             :         {
     839           1 :             printf("Features connected successfully\n");
     840             :         }
     841             :     }
     842           1 :     else if (stOper == op_delete)
     843             :     {
     844           1 :         if (pszDataSource == nullptr)
     845           0 :             Usage(true, "No network dataset provided");
     846             : 
     847             :         // open
     848           2 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     849           1 :             GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
     850             :                        nullptr, nullptr)));
     851             : 
     852           1 :         if (nullptr == poDS)
     853             :         {
     854           0 :             fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
     855           0 :             nRet = 1;
     856           0 :             goto exit;
     857             :         }
     858             : 
     859           1 :         if (poDS->Delete() != CE_None)
     860             :         {
     861           0 :             fprintf(stderr, "Delete failed.\n");
     862           0 :             nRet = 1;
     863           0 :             goto exit;
     864             :         }
     865             : 
     866           1 :         if (bQuiet == FALSE)
     867             :         {
     868           1 :             printf("Delete successfully\n");
     869             :         }
     870             : 
     871             :         /** if hDriver == NULL this code delete everything in folder,
     872             :          *  not only GNM files
     873             : 
     874             :          GDALDriverH hDriver = NULL;
     875             :          if( pszFormat != NULL )
     876             :          {
     877             :              hDriver = GDALGetDriverByName( pszFormat );
     878             :              if( hDriver == NULL )
     879             :              {
     880             :                  fprintf( stderr, "Unable to find driver named '%s'.\n",
     881             :                           pszFormat );
     882             :                  exit( 1 );
     883             :              }
     884             :          }
     885             :          GDALDeleteDataset( hDriver, pszDataSource );
     886             :          */
     887             :     }
     888           0 :     else if (stOper == op_change_st)
     889             :     {
     890           0 :         if (pszDataSource == nullptr)
     891           0 :             Usage(true, "No dataset in input");
     892             : 
     893             :         // open
     894           0 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     895           0 :             GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
     896             :                        nullptr, nullptr)));
     897             : 
     898           0 :         if (nullptr == poDS)
     899             :         {
     900           0 :             fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
     901           0 :             nRet = 1;
     902           0 :             goto exit;
     903             :         }
     904             : 
     905             :         GNMGenericNetwork *poGenericNetwork =
     906           0 :             dynamic_cast<GNMGenericNetwork *>(poDS);
     907             : 
     908           0 :         if (nullptr == poGenericNetwork)
     909             :         {
     910           0 :             fprintf(stderr,
     911             :                     "\nUnsupported datasource type for this operation\n");
     912           0 :             nRet = 1;
     913           0 :             goto exit;
     914             :         }
     915             : 
     916           0 :         if (bUnblockAll)
     917             :         {
     918           0 :             if (poGenericNetwork->ChangeAllBlockState(false) != CE_None)
     919             :             {
     920           0 :                 fprintf(stderr, "\nChange all block state failed\n");
     921           0 :                 nRet = 1;
     922           0 :                 goto exit;
     923             :             }
     924             :         }
     925             :         else
     926             :         {
     927             :             size_t i;
     928           0 :             for (i = 0; i < anFIDsToBlock.size(); ++i)
     929             :             {
     930           0 :                 if (poGenericNetwork->ChangeBlockState(anFIDsToBlock[i],
     931           0 :                                                        true) != CE_None)
     932             :                 {
     933           0 :                     fprintf(stderr,
     934             :                             "\nChange block state of id " GNMGFIDFormat
     935             :                             " failed\n",
     936           0 :                             anFIDsToBlock[i]);
     937           0 :                     nRet = 1;
     938           0 :                     goto exit;
     939             :                 }
     940             :             }
     941             : 
     942           0 :             for (i = 0; i < anFIDsToUnblock.size(); ++i)
     943             :             {
     944           0 :                 if (poGenericNetwork->ChangeBlockState(anFIDsToUnblock[i],
     945           0 :                                                        false) != CE_None)
     946             :                 {
     947           0 :                     fprintf(stderr,
     948             :                             "\nChange block state of id " GNMGFIDFormat
     949             :                             " failed\n",
     950           0 :                             anFIDsToBlock[i]);
     951           0 :                     nRet = 1;
     952           0 :                     goto exit;
     953             :                 }
     954             :             }
     955             :         }
     956             : 
     957           0 :         if (bQuiet == FALSE)
     958             :         {
     959           0 :             printf("Change block state successfully\n");
     960             :         }
     961             :     }
     962             :     else
     963             :     {
     964           0 :         fprintf(
     965             :             stderr,
     966             :             "Need an operation. See help what you can do with gnmmanage:\n");
     967           0 :         Usage(true);
     968             :     }
     969             : 
     970           6 : exit:
     971           6 :     CSLDestroy(papszArgv);
     972           6 :     CSLDestroy(papszDSCO);
     973           6 :     CSLDestroy(papszLayers);
     974             : 
     975           6 :     if (poDS != nullptr)
     976             :     {
     977           6 :         if (GDALClose(poDS) != CE_None)
     978           0 :             nRet = 1;
     979             :     }
     980             : 
     981           6 :     GDALDestroyDriverManager();
     982             : 
     983           6 :     return nRet;
     984             : }
     985             : 
     986           0 : MAIN_END

Generated by: LCOV version 1.14