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

Generated by: LCOV version 1.14