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