LCOV - code coverage report
Current view: top level - apps - gnmanalyse.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 118 266 44.4 %
Date: 2025-03-28 11:40:40 Functions: 2 5 40.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * Project:  geography network utility
       3             :  * Purpose:  Analyse 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 "gdal_version.h"
      16             : #include "gnm.h"
      17             : #include "gnm_priv.h"
      18             : #include "ogr_p.h"
      19             : 
      20             : enum operation
      21             : {
      22             :     op_unknown = 0, /** no operation */
      23             :     op_dijkstra,    /** create shortest path using Dijkstra algorithm */
      24             :     op_kpaths,      /** create k shortest paths using Yens algorithm */
      25             :     op_resource     /** create resource distribution layer */
      26             : };
      27             : 
      28             : /************************************************************************/
      29             : /*                               Usage()                                */
      30             : /************************************************************************/
      31           0 : static void Usage(bool bIsError, const char *pszAdditionalMsg = nullptr,
      32             :                   bool bShort = true, bool bHelpDoc = false)
      33             : {
      34           0 :     fprintf(
      35             :         bIsError ? stderr : stdout,
      36             :         "Usage: gnmanalyse [--help][--help-general][-q][-quiet][--long-usage]\n"
      37             :         "                  [dijkstra <start_gfid> <end_gfid "
      38             :         "[-alo <NAME>=<VALUE>]...]\n"
      39             :         "                  [kpaths <start_gfid> <end_gfid> <k> "
      40             :         "[-alo NAME=VALUE]...]\n"
      41             :         "                  [resource [-alo <NAME>=<VALUE>]...]\n"
      42             :         "                  [-ds <ds_name>][-f <ds_format>][-l <layer_name>]\n"
      43             :         "                  [-dsco <NAME>=<VALUE>]... [-lco <NAME>=<VALUE>]...\n"
      44             :         "                  <gnm_name>\n");
      45             : 
      46           0 :     if (bHelpDoc)
      47             :     {
      48           0 :         exit(0);
      49             :     }
      50             : 
      51           0 :     if (bShort)
      52             :     {
      53           0 :         printf("\nNote: gnmanalyse --long-usage for full help.\n");
      54           0 :         if (pszAdditionalMsg)
      55           0 :             fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
      56           0 :         exit(1);
      57             :     }
      58             : 
      59           0 :     fprintf(bIsError ? stderr : stdout,
      60             :             "\n   dijkstra start_gfid end_gfid: calculates the best path "
      61             :             "between two points using Dijkstra algorithm from start_gfid point "
      62             :             "to end_gfid point\n"
      63             :             "   kpaths start_gfid end_gfid k: calculates k (up to 10) best "
      64             :             "paths between two points using Yen\'s algorithm (which internally "
      65             :             "uses Dijkstra algorithm for single path calculating) from "
      66             :             "start_gfid point to end_gfid point\n"
      67             :             "   resource: calculates the \"resource distribution\". The "
      68             :             "connected components search is performed using breadth-first "
      69             :             "search and starting from that features which are marked by rules "
      70             :             "as \'EMITTERS\'\n"
      71             :             "   -ds ds_name: the name&path of the dataset to save the layer "
      72             :             "with resulting paths. Not need to be existed dataset\n"
      73             :             "   -f ds_format: define this to set the format of newly created "
      74             :             "dataset\n"
      75             :             "   -l layer_name: the name of the resulting layer. If the layer "
      76             :             "exists already - it will be rewritten. For K shortest paths "
      77             :             "several layers are created in format layer_nameN, where N - is "
      78             :             "number of the path (0 - is the most shortest one)\n"
      79             :             "   -dsco NAME=VALUE: Dataset creation option (format specific)\n"
      80             :             "   -lco  NAME=VALUE: Layer creation option (format specific)\n"
      81             :             "   -alo  NAME=VALUE: Algorithm option (format specific)\n"
      82             :             "   gnm_name: the network to work with (path and name)\n");
      83             : 
      84           0 :     if (pszAdditionalMsg)
      85           0 :         fprintf(stderr, "\nFAILURE: %s\n", pszAdditionalMsg);
      86             : 
      87           0 :     exit(bIsError ? 1 : 0);
      88             : }
      89             : 
      90             : /************************************************************************/
      91             : /*                   GetLayerAndOverwriteIfNecessary()                  */
      92             : /************************************************************************/
      93             : 
      94           0 : static OGRLayer *GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
      95             :                                                  const char *pszNewLayerName,
      96             :                                                  int bOverwrite,
      97             :                                                  int *pbErrorOccurred)
      98             : {
      99           0 :     if (pbErrorOccurred)
     100           0 :         *pbErrorOccurred = FALSE;
     101             : 
     102             :     /* GetLayerByName() can instantiate layers that would have been */
     103             :     /* 'hidden' otherwise, for example, non-spatial tables in a */
     104             :     /* PostGIS-enabled database, so this apparently useless command is */
     105             :     /* not useless... (#4012) */
     106           0 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     107           0 :     OGRLayer *poDstLayer = poDstDS->GetLayerByName(pszNewLayerName);
     108           0 :     CPLPopErrorHandler();
     109           0 :     CPLErrorReset();
     110             : 
     111           0 :     int iLayer = -1;
     112           0 :     if (poDstLayer != nullptr)
     113             :     {
     114           0 :         int nLayerCount = poDstDS->GetLayerCount();
     115           0 :         for (iLayer = 0; iLayer < nLayerCount; iLayer++)
     116             :         {
     117           0 :             OGRLayer *poLayer = poDstDS->GetLayer(iLayer);
     118           0 :             if (poLayer == poDstLayer)
     119           0 :                 break;
     120             :         }
     121             : 
     122           0 :         if (iLayer == nLayerCount)
     123             :             /* should not happen with an ideal driver */
     124           0 :             poDstLayer = nullptr;
     125             :     }
     126             : 
     127             :     /* -------------------------------------------------------------------- */
     128             :     /*      If the user requested overwrite, and we have the layer in       */
     129             :     /*      question we need to delete it now so it will get recreated      */
     130             :     /*      (overwritten).                                                  */
     131             :     /* -------------------------------------------------------------------- */
     132           0 :     if (poDstLayer != nullptr && bOverwrite)
     133             :     {
     134           0 :         if (poDstDS->DeleteLayer(iLayer) != OGRERR_NONE)
     135             :         {
     136           0 :             fprintf(stderr, "DeleteLayer() failed when overwrite requested.\n");
     137           0 :             if (pbErrorOccurred)
     138           0 :                 *pbErrorOccurred = TRUE;
     139             :         }
     140           0 :         poDstLayer = nullptr;
     141             :     }
     142             : 
     143           0 :     return poDstLayer;
     144             : }
     145             : 
     146             : /************************************************************************/
     147             : /*                     CreateAndFillOutputDataset                       */
     148             : /************************************************************************/
     149           0 : static OGRErr CreateAndFillOutputDataset(OGRLayer *poSrcLayer,
     150             :                                          const char *pszDestDataSource,
     151             :                                          const char *pszFormat,
     152             :                                          const char *pszLayer, char **papszDSCO,
     153             :                                          char **papszLCO, int bQuiet)
     154             : {
     155           0 :     GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
     156           0 :     if (poDriver == nullptr)
     157             :     {
     158           0 :         fprintf(stderr, "%s driver not available\n", pszFormat);
     159           0 :         return OGRERR_FAILURE;
     160             :     }
     161             : 
     162           0 :     if (!CPLTestBool(CSLFetchNameValueDef(poDriver->GetMetadata(),
     163             :                                           GDAL_DCAP_CREATE, "FALSE")))
     164             :     {
     165           0 :         fprintf(stderr, "%s driver does not support data source creation.\n",
     166             :                 pszFormat);
     167           0 :         return OGRERR_FAILURE;
     168             :     }
     169             : 
     170             :     GDALDataset *poODS =
     171           0 :         poDriver->Create(pszDestDataSource, 0, 0, 0, GDT_Unknown, papszDSCO);
     172           0 :     if (poODS == nullptr)
     173             :     {
     174           0 :         fprintf(stderr, "%s driver failed to create %s\n", pszFormat,
     175             :                 pszDestDataSource);
     176           0 :         return OGRERR_FAILURE;
     177             :     }
     178             : 
     179           0 :     if (nullptr == pszLayer)
     180           0 :         pszLayer = poSrcLayer->GetName();
     181             :     int nError;
     182           0 :     GetLayerAndOverwriteIfNecessary(poODS, pszLayer, TRUE, &nError);
     183           0 :     if (nError == TRUE)
     184             :     {
     185           0 :         return OGRERR_FAILURE;
     186             :     }
     187             : 
     188             :     // create layer
     189           0 :     OGRLayer *poLayer = poODS->CopyLayer(poSrcLayer, pszLayer, papszLCO);
     190           0 :     if (nullptr == poLayer)
     191             :     {
     192           0 :         fprintf(stderr, "\nFAILURE: Can not copy path to %s\n",
     193             :                 pszDestDataSource);
     194           0 :         GDALClose(poODS);
     195             : 
     196           0 :         return OGRERR_FAILURE;
     197             :     }
     198             : 
     199           0 :     if (bQuiet == FALSE)
     200             :     {
     201           0 :         printf("\nPath successfully copied and added to the network at %s\n",
     202             :                pszDestDataSource);
     203             :     }
     204             : 
     205           0 :     GDALClose(poODS);
     206             : 
     207           0 :     return OGRERR_NONE;
     208             : }
     209             : 
     210             : /************************************************************************/
     211             : /*                           ReportOnLayer()                            */
     212             : /************************************************************************/
     213             : 
     214           2 : static void ReportOnLayer(OGRLayer *poLayer, int bVerbose)
     215             : 
     216             : {
     217           2 :     OGRFeatureDefn *poDefn = poLayer->GetLayerDefn();
     218             : 
     219             :     /* -------------------------------------------------------------------- */
     220             :     /*      Report various overall information.                             */
     221             :     /* -------------------------------------------------------------------- */
     222           2 :     printf("\n");
     223             : 
     224           2 :     printf("Layer name: %s\n", poLayer->GetName());
     225             : 
     226           2 :     if (bVerbose)
     227             :     {
     228           2 :         int nGeomFieldCount = poLayer->GetLayerDefn()->GetGeomFieldCount();
     229           2 :         if (nGeomFieldCount > 1)
     230             :         {
     231           0 :             for (int iGeom = 0; iGeom < nGeomFieldCount; iGeom++)
     232             :             {
     233             :                 OGRGeomFieldDefn *poGFldDefn =
     234           0 :                     poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
     235           0 :                 printf("Geometry (%s): %s\n", poGFldDefn->GetNameRef(),
     236             :                        OGRGeometryTypeToName(poGFldDefn->GetType()));
     237             :             }
     238             :         }
     239             :         else
     240             :         {
     241           2 :             printf("Geometry: %s\n",
     242           2 :                    OGRGeometryTypeToName(poLayer->GetGeomType()));
     243             :         }
     244             : 
     245           2 :         printf("Feature Count: " CPL_FRMT_GIB "\n", poLayer->GetFeatureCount());
     246             : 
     247           2 :         OGREnvelope oExt;
     248           2 :         if (nGeomFieldCount > 1)
     249             :         {
     250           0 :             for (int iGeom = 0; iGeom < nGeomFieldCount; iGeom++)
     251             :             {
     252           0 :                 if (poLayer->GetExtent(iGeom, &oExt, TRUE) == OGRERR_NONE)
     253             :                 {
     254             :                     OGRGeomFieldDefn *poGFldDefn =
     255           0 :                         poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
     256           0 :                     CPLprintf("Extent (%s): (%f, %f) - (%f, %f)\n",
     257             :                               poGFldDefn->GetNameRef(), oExt.MinX, oExt.MinY,
     258             :                               oExt.MaxX, oExt.MaxY);
     259             :                 }
     260             :             }
     261             :         }
     262           2 :         else if (poLayer->GetExtent(&oExt, TRUE) == OGRERR_NONE)
     263             :         {
     264           2 :             CPLprintf("Extent: (%f, %f) - (%f, %f)\n", oExt.MinX, oExt.MinY,
     265             :                       oExt.MaxX, oExt.MaxY);
     266             :         }
     267             : 
     268             :         char *pszWKT;
     269             : 
     270           2 :         if (nGeomFieldCount > 1)
     271             :         {
     272           0 :             for (int iGeom = 0; iGeom < nGeomFieldCount; iGeom++)
     273             :             {
     274             :                 OGRGeomFieldDefn *poGFldDefn =
     275           0 :                     poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
     276           0 :                 const OGRSpatialReference *poSRS = poGFldDefn->GetSpatialRef();
     277           0 :                 if (poSRS == nullptr)
     278           0 :                     pszWKT = CPLStrdup("(unknown)");
     279             :                 else
     280             :                 {
     281           0 :                     poSRS->exportToPrettyWkt(&pszWKT);
     282             :                 }
     283             : 
     284           0 :                 printf("SRS WKT (%s):\n%s\n", poGFldDefn->GetNameRef(), pszWKT);
     285           0 :                 CPLFree(pszWKT);
     286             :             }
     287             :         }
     288             :         else
     289             :         {
     290           2 :             if (poLayer->GetSpatialRef() == nullptr)
     291           0 :                 pszWKT = CPLStrdup("(unknown)");
     292             :             else
     293             :             {
     294           2 :                 poLayer->GetSpatialRef()->exportToPrettyWkt(&pszWKT);
     295             :             }
     296             : 
     297           2 :             printf("Layer SRS WKT:\n%s\n", pszWKT);
     298           2 :             CPLFree(pszWKT);
     299             :         }
     300             : 
     301           2 :         if (strlen(poLayer->GetFIDColumn()) > 0)
     302           0 :             printf("FID Column = %s\n", poLayer->GetFIDColumn());
     303             : 
     304           2 :         for (int iGeom = 0; iGeom < nGeomFieldCount; iGeom++)
     305             :         {
     306             :             OGRGeomFieldDefn *poGFldDefn =
     307           2 :                 poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
     308           4 :             if (nGeomFieldCount == 1 && EQUAL(poGFldDefn->GetNameRef(), "") &&
     309           2 :                 poGFldDefn->IsNullable())
     310           2 :                 break;
     311           0 :             printf("Geometry Column ");
     312           0 :             if (nGeomFieldCount > 1)
     313           0 :                 printf("%d ", iGeom + 1);
     314           0 :             if (!poGFldDefn->IsNullable())
     315           0 :                 printf("NOT NULL ");
     316           0 :             printf("= %s\n", poGFldDefn->GetNameRef());
     317             :         }
     318             : 
     319          18 :         for (int iAttr = 0; iAttr < poDefn->GetFieldCount(); iAttr++)
     320             :         {
     321          16 :             OGRFieldDefn *poField = poDefn->GetFieldDefn(iAttr);
     322             :             const char *pszType =
     323          16 :                 (poField->GetSubType() != OFSTNone)
     324          16 :                     ? CPLSPrintf(
     325             :                           "%s(%s)",
     326             :                           poField->GetFieldTypeName(poField->GetType()),
     327             :                           poField->GetFieldSubTypeName(poField->GetSubType()))
     328          16 :                     : poField->GetFieldTypeName(poField->GetType());
     329          16 :             printf("%s: %s (%d.%d)", poField->GetNameRef(), pszType,
     330             :                    poField->GetWidth(), poField->GetPrecision());
     331          16 :             if (!poField->IsNullable())
     332           0 :                 printf(" NOT NULL");
     333          16 :             if (poField->GetDefault() != nullptr)
     334           0 :                 printf(" DEFAULT %s", poField->GetDefault());
     335          16 :             printf("\n");
     336             :         }
     337             :     }
     338             : 
     339             :     /* -------------------------------------------------------------------- */
     340             :     /*      Read, and dump features.                                        */
     341             :     /* -------------------------------------------------------------------- */
     342          82 :     for (auto &poFeature : poLayer)
     343             :     {
     344          80 :         poFeature->DumpReadable(nullptr);
     345             :     }
     346           2 : }
     347             : 
     348             : /************************************************************************/
     349             : /*                                main()                                */
     350             : /************************************************************************/
     351             : 
     352             : #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg)                            \
     353             :     do                                                                         \
     354             :     {                                                                          \
     355             :         if (iArg + nExtraArg >= nArgc)                                         \
     356             :             Usage(true, CPLSPrintf("%s option requires %d argument(s)",        \
     357             :                                    papszArgv[iArg], nExtraArg));               \
     358             :     } while (false)
     359             : 
     360           3 : MAIN_START(nArgc, papszArgv)
     361             : 
     362             : {
     363           3 :     int bQuiet = FALSE;
     364             : 
     365           3 :     const char *pszDataSource = nullptr;
     366             : 
     367           3 :     GNMGFID nFromFID = -1;
     368           3 :     GNMGFID nToFID = -1;
     369           3 :     int nK = 1;
     370           3 :     const char *pszDataset = nullptr;
     371           3 :     const char *pszFormat = "ESRI Shapefile";
     372           3 :     const char *pszLayer = nullptr;
     373           3 :     GNMNetwork *poDS = nullptr;
     374           3 :     OGRLayer *poResultLayer = nullptr;
     375           3 :     char **papszDSCO = nullptr, **papszLCO = nullptr, **papszALO = nullptr;
     376             : 
     377           3 :     operation stOper = op_unknown;
     378             : 
     379           3 :     int nRet = 0;
     380             : 
     381             :     // Check strict compilation and runtime library version as we use C++ API
     382           3 :     if (!GDAL_CHECK_VERSION(papszArgv[0]))
     383           0 :         exit(1);
     384             : 
     385           3 :     EarlySetConfigOptions(nArgc, papszArgv);
     386             : 
     387             :     /* -------------------------------------------------------------------- */
     388             :     /*      Register format(s).                                             */
     389             :     /* -------------------------------------------------------------------- */
     390           3 :     GDALAllRegister();
     391             : 
     392             :     /* -------------------------------------------------------------------- */
     393             :     /*      Processing command line arguments.                              */
     394             :     /* -------------------------------------------------------------------- */
     395           3 :     nArgc = GDALGeneralCmdLineProcessor(nArgc, &papszArgv, GDAL_OF_GNM);
     396             : 
     397           3 :     if (nArgc < 1)
     398             :     {
     399           1 :         exit(-nArgc);
     400             :     }
     401             : 
     402           6 :     for (int iArg = 1; iArg < nArgc; iArg++)
     403             :     {
     404           4 :         if (EQUAL(papszArgv[1], "--utility_version"))
     405             :         {
     406           0 :             printf("%s was compiled against GDAL %s and is running against "
     407             :                    "GDAL %s\n",
     408             :                    papszArgv[0], GDAL_RELEASE_NAME,
     409             :                    GDALVersionInfo("RELEASE_NAME"));
     410           0 :             CSLDestroy(papszArgv);
     411           0 :             return 0;
     412             :         }
     413             : 
     414           4 :         else if (EQUAL(papszArgv[iArg], "--help"))
     415             :         {
     416           0 :             Usage(false);
     417             :         }
     418             : 
     419           4 :         else if (EQUAL(papszArgv[iArg], "--help-doc"))
     420             :         {
     421           0 :             Usage(false, nullptr, true, true);
     422             :         }
     423             : 
     424           4 :         else if (EQUAL(papszArgv[iArg], "--long-usage"))
     425             :         {
     426           0 :             Usage(false, nullptr, false);
     427             :         }
     428             : 
     429           4 :         else if (EQUAL(papszArgv[iArg], "-q") ||
     430           4 :                  EQUAL(papszArgv[iArg], "-quiet"))
     431             :         {
     432           0 :             bQuiet = TRUE;
     433             :         }
     434             : 
     435           4 :         else if (EQUAL(papszArgv[iArg], "dijkstra"))
     436             :         {
     437           1 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
     438           1 :             stOper = op_dijkstra;
     439           1 :             nFromFID = atoi(papszArgv[++iArg]);
     440           1 :             nToFID = atoi(papszArgv[++iArg]);
     441             :         }
     442             : 
     443           3 :         else if (EQUAL(papszArgv[iArg], "kpaths"))
     444             :         {
     445           1 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(3);
     446           1 :             stOper = op_kpaths;
     447           1 :             nFromFID = atoi(papszArgv[++iArg]);
     448           1 :             nToFID = atoi(papszArgv[++iArg]);
     449           1 :             nK = atoi(papszArgv[++iArg]);
     450             :         }
     451             : 
     452           2 :         else if (EQUAL(papszArgv[iArg], "resource"))
     453             :         {
     454           0 :             stOper = op_resource;
     455             :         }
     456             : 
     457           2 :         else if (EQUAL(papszArgv[iArg], "-ds"))
     458             :         {
     459           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     460           0 :             pszDataset = papszArgv[++iArg];
     461             :         }
     462             : 
     463           2 :         else if ((EQUAL(papszArgv[iArg], "-f") ||
     464           2 :                   EQUAL(papszArgv[iArg], "-of")))
     465             :         {
     466           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     467           0 :             pszFormat = papszArgv[++iArg];
     468             :         }
     469             : 
     470           2 :         else if (EQUAL(papszArgv[iArg], "-l"))
     471             :         {
     472           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     473           0 :             pszLayer = papszArgv[++iArg];
     474             :         }
     475           2 :         else if (EQUAL(papszArgv[iArg], "-dsco"))
     476             :         {
     477           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     478           0 :             papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg]);
     479             :         }
     480           2 :         else if (EQUAL(papszArgv[iArg], "-lco"))
     481             :         {
     482           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     483           0 :             papszLCO = CSLAddString(papszLCO, papszArgv[++iArg]);
     484             :         }
     485           2 :         else if (EQUAL(papszArgv[iArg], "-alo"))
     486             :         {
     487           0 :             CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
     488           0 :             papszALO = CSLAddString(papszALO, papszArgv[++iArg]);
     489             :         }
     490           2 :         else if (papszArgv[iArg][0] == '-')
     491             :         {
     492           0 :             Usage(true,
     493           0 :                   CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
     494             :         }
     495             : 
     496           2 :         else if (pszDataSource == nullptr)
     497           2 :             pszDataSource = papszArgv[iArg];
     498             :     }
     499             : 
     500             :     // do the work
     501             :     // ////////////////////////////////////////////////////////////////
     502             : 
     503           2 :     if (stOper == op_dijkstra)
     504             :     {
     505           1 :         if (pszDataSource == nullptr)
     506           0 :             Usage(true, "No network dataset provided");
     507             : 
     508           1 :         if (nFromFID == -1 || nToFID == -1)
     509           0 :             Usage(true, "Invalid input from or to identificators");
     510             : 
     511             :         // open
     512           2 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     513           1 :             GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
     514             :                        nullptr, nullptr)));
     515           1 :         if (nullptr == poDS)
     516             :         {
     517           0 :             fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
     518           0 :             nRet = 1;
     519           0 :             goto exit;
     520             :         }
     521             : 
     522             :         poResultLayer =
     523           1 :             poDS->GetPath(nFromFID, nToFID, GATDijkstraShortestPath, papszALO);
     524           1 :         if (nullptr == pszDataset)
     525             :         {
     526           1 :             ReportOnLayer(poResultLayer, bQuiet == FALSE);
     527             :         }
     528             :         else
     529             :         {
     530           0 :             if (CreateAndFillOutputDataset(poResultLayer, pszDataset, pszFormat,
     531             :                                            pszLayer, papszDSCO, papszLCO,
     532           0 :                                            bQuiet) != OGRERR_NONE)
     533             :             {
     534           0 :                 nRet = 1;
     535           0 :                 goto exit;
     536             :             }
     537             :         }
     538             :     }
     539           1 :     else if (stOper == op_kpaths)
     540             :     {
     541           1 :         if (pszDataSource == nullptr)
     542           0 :             Usage(true, "No network dataset provided");
     543             : 
     544           1 :         if (nFromFID == -1 || nToFID == -1)
     545           0 :             Usage(true, "Invalid input from or to identificators");
     546             : 
     547             :         // open
     548           2 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     549           1 :             GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
     550             :                        nullptr, nullptr)));
     551           1 :         if (nullptr == poDS)
     552             :         {
     553           0 :             fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
     554           0 :             nRet = 1;
     555           0 :             goto exit;
     556             :         }
     557             : 
     558           1 :         if (CSLFindName(papszALO, GNM_MD_NUM_PATHS) == -1)
     559             :         {
     560           1 :             CPLDebug("GNM", "No K in options, add %d value", nK);
     561           1 :             papszALO = CSLAddNameValue(papszALO, GNM_MD_NUM_PATHS,
     562             :                                        CPLSPrintf("%d", nK));
     563             :         }
     564             : 
     565             :         poResultLayer =
     566           1 :             poDS->GetPath(nFromFID, nToFID, GATKShortestPath, papszALO);
     567             : 
     568           1 :         if (nullptr == pszDataset)
     569             :         {
     570           1 :             ReportOnLayer(poResultLayer, bQuiet == FALSE);
     571             :         }
     572             :         else
     573             :         {
     574           0 :             if (CreateAndFillOutputDataset(poResultLayer, pszDataset, pszFormat,
     575             :                                            pszLayer, papszDSCO, papszLCO,
     576           0 :                                            bQuiet) != OGRERR_NONE)
     577             :             {
     578           0 :                 nRet = 1;
     579           0 :                 goto exit;
     580             :             }
     581             :         }
     582             :     }
     583           0 :     else if (stOper == op_resource)
     584             :     {
     585           0 :         if (pszDataSource == nullptr)
     586           0 :             Usage(true, "No network dataset provided");
     587             : 
     588             :         // open
     589           0 :         poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
     590           0 :             GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
     591             :                        nullptr, nullptr)));
     592           0 :         if (nullptr == poDS)
     593             :         {
     594           0 :             fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
     595           0 :             nRet = 1;
     596           0 :             goto exit;
     597             :         }
     598             : 
     599             :         poResultLayer =
     600           0 :             poDS->GetPath(nFromFID, nToFID, GATConnectedComponents, papszALO);
     601             : 
     602           0 :         if (nullptr == pszDataset)
     603             :         {
     604           0 :             ReportOnLayer(poResultLayer, bQuiet == FALSE);
     605             :         }
     606             :         else
     607             :         {
     608           0 :             if (CreateAndFillOutputDataset(poResultLayer, pszDataset, pszFormat,
     609             :                                            pszLayer, papszDSCO, papszLCO,
     610           0 :                                            bQuiet) != OGRERR_NONE)
     611             :             {
     612           0 :                 nRet = 1;
     613           0 :                 goto exit;
     614             :             }
     615             :         }
     616             :     }
     617             :     else
     618             :     {
     619           0 :         fprintf(
     620             :             stderr,
     621             :             "Need an operation. See help what you can do with gnmanalyse:\n");
     622           0 :         Usage(true);
     623             :     }
     624             : 
     625           2 : exit:
     626           2 :     CSLDestroy(papszDSCO);
     627           2 :     CSLDestroy(papszLCO);
     628           2 :     CSLDestroy(papszALO);
     629           2 :     CSLDestroy(papszArgv);
     630             : 
     631           2 :     if (poResultLayer != nullptr)
     632           2 :         poDS->ReleaseResultSet(poResultLayer);
     633             : 
     634           2 :     if (poDS)
     635             :     {
     636           2 :         if (GDALClose(poDS) != CE_None)
     637           0 :             nRet = 1;
     638             :     }
     639             : 
     640           2 :     GDALDestroyDriverManager();
     641             : 
     642           2 :     return nRet;
     643             : }
     644             : 
     645           0 : MAIN_END

Generated by: LCOV version 1.14