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
|