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