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