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

Generated by: LCOV version 1.14