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 13 : std::vector<GNMGFID> anFIDsToBlock;
190 13 : 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 1 : exit(-nArgc);
213 : }
214 :
215 22 : for (int iArg = 1; iArg < nArgc; iArg++)
216 : {
217 16 : if (EQUAL(papszArgv[1], "--utility_version"))
218 : {
219 0 : 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 0 : CSLDestroy(papszArgv);
224 0 : 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 2 : std::string osPath;
511 : std::string osNetworkName =
512 2 : CSLFetchNameValueDef(papszDSCO, GNM_MD_NAME, "");
513 :
514 1 : if (pszDataSource == nullptr)
515 0 : Usage(true, "No network dataset provided");
516 :
517 : // the DSCO have priority on input keys
518 1 : if (osNetworkName.empty())
519 : {
520 0 : osPath = CPLGetPathSafe(pszDataSource);
521 0 : osNetworkName = CPLGetBasenameSafe(pszDataSource);
522 : papszDSCO =
523 0 : CSLAddNameValue(papszDSCO, GNM_MD_NAME, osNetworkName.c_str());
524 : }
525 : else
526 : {
527 1 : osPath = pszDataSource;
528 : }
529 :
530 1 : if (osNetworkName.empty())
531 0 : Usage(true, "No dataset name provided");
532 :
533 1 : const char *pszFinalSRS = CSLFetchNameValue(papszDSCO, GNM_MD_SRS);
534 1 : if (nullptr == pszFinalSRS)
535 : {
536 1 : pszFinalSRS = pszSRS;
537 1 : papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_SRS, pszSRS);
538 : }
539 :
540 1 : if (nullptr == pszFinalSRS)
541 0 : Usage(true, "No spatial reference provided");
542 1 : if (pszFormat == nullptr)
543 0 : Usage(true, "No output format provided");
544 :
545 : GDALDriver *poDriver =
546 1 : GetGDALDriverManager()->GetDriverByName(pszFormat);
547 1 : if (poDriver == nullptr)
548 : {
549 0 : Usage(true, CPLSPrintf("%s driver not available", pszFormat));
550 : }
551 : else
552 : {
553 1 : char **papszMD = poDriver->GetMetadata();
554 :
555 1 : if (!CPLFetchBool(papszMD, GDAL_DCAP_GNM, false))
556 0 : Usage(true, "not a GNM driver");
557 :
558 1 : poDS = cpl::down_cast<GNMNetwork *>(poDriver->Create(
559 : osPath.c_str(), 0, 0, 0, GDT_Unknown, papszDSCO));
560 :
561 1 : if (nullptr == poDS)
562 : {
563 0 : fprintf(
564 : stderr,
565 : "\nFAILURE: Failed to create network in a new dataset at "
566 : "%s and with driver %s\n",
567 0 : CPLFormFilenameSafe(osPath.c_str(), osNetworkName.c_str(),
568 : nullptr)
569 : .c_str(),
570 : pszFormat);
571 0 : nRet = 1;
572 : }
573 : else
574 : {
575 1 : if (bQuiet == FALSE)
576 1 : printf("\nNetwork created successfully in a "
577 : "new dataset at %s\n",
578 2 : CPLFormFilenameSafe(osPath.c_str(),
579 : osNetworkName.c_str(), nullptr)
580 : .c_str());
581 : }
582 : }
583 : }
584 4 : else if (stOper == op_import)
585 : {
586 2 : if (pszDataSource == nullptr)
587 0 : Usage(true, "No network dataset provided");
588 :
589 2 : if (pszInputDataset == nullptr)
590 0 : Usage(true, "No input dataset name provided");
591 :
592 : // open
593 4 : poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
594 2 : GDALOpenEx(pszDataSource, GDAL_OF_READONLY | GDAL_OF_GNM, nullptr,
595 : nullptr, nullptr)));
596 :
597 2 : if (nullptr == poDS)
598 : {
599 0 : printf("\nFailed to open network at %s\n", pszDataSource);
600 0 : goto exit;
601 : }
602 :
603 : GDALDataset *poSrcDS = static_cast<GDALDataset *>(
604 2 : GDALOpenEx(pszInputDataset, GDAL_OF_VECTOR | GDAL_OF_READONLY,
605 : nullptr, nullptr, nullptr));
606 2 : if (nullptr == poSrcDS)
607 : {
608 0 : fprintf(stderr, "\nFAILURE: Can not open dataset at %s\n",
609 : pszInputDataset);
610 :
611 0 : nRet = 1;
612 0 : goto exit;
613 : }
614 :
615 : OGRLayer *poSrcLayer;
616 2 : if (pszInputLayer != nullptr)
617 0 : poSrcLayer = poSrcDS->GetLayerByName(pszInputLayer);
618 : else
619 2 : poSrcLayer = poSrcDS->GetLayer(0);
620 :
621 2 : if (nullptr == poSrcLayer)
622 : {
623 0 : if (pszInputLayer != nullptr)
624 0 : fprintf(stderr, "\nFAILURE: Can not open layer %s in %s\n",
625 : pszInputLayer, pszInputDataset);
626 : else
627 0 : fprintf(stderr, "\nFAILURE: Can not open layer in %s\n",
628 : pszInputDataset);
629 :
630 0 : GDALClose(poSrcDS);
631 :
632 0 : nRet = 1;
633 0 : goto exit;
634 : }
635 :
636 2 : OGRLayer *poLayer = poDS->CopyLayer(poSrcLayer, poSrcLayer->GetName());
637 2 : if (nullptr == poLayer)
638 : {
639 0 : if (pszInputLayer != nullptr)
640 0 : fprintf(stderr, "\nFAILURE: Can not copy layer %s from %s\n",
641 : pszInputLayer, pszInputDataset);
642 : else
643 0 : fprintf(stderr, "\nFAILURE: Can not copy layer from %s\n",
644 : pszInputDataset);
645 0 : GDALClose(poSrcDS);
646 :
647 0 : nRet = 1;
648 0 : goto exit;
649 : }
650 :
651 2 : if (bQuiet == FALSE)
652 : {
653 2 : if (pszInputLayer != nullptr)
654 0 : printf("\nLayer %s successfully copied from %s and added to "
655 : "the network at %s\n",
656 : pszInputLayer, pszInputDataset, pszDataSource);
657 : else
658 2 : printf("\nLayer successfully copied from %s and added to the "
659 : "network at %s\n",
660 : pszInputDataset, pszDataSource);
661 : }
662 :
663 2 : GDALClose(poSrcDS);
664 : }
665 2 : else if (stOper == op_connect)
666 : {
667 0 : if (pszDataSource == nullptr)
668 0 : Usage(true, "No network dataset provided");
669 :
670 : // open
671 0 : poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
672 0 : GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
673 : nullptr, nullptr)));
674 :
675 0 : if (nullptr == poDS)
676 : {
677 0 : fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
678 0 : nRet = 1;
679 0 : goto exit;
680 : }
681 :
682 : GNMGenericNetwork *poGenericNetwork =
683 0 : dynamic_cast<GNMGenericNetwork *>(poDS);
684 :
685 0 : if (nullptr == poGenericNetwork)
686 : {
687 0 : fprintf(stderr,
688 : "\nUnsupported datasource type for this operation\n");
689 0 : nRet = 1;
690 0 : goto exit;
691 : }
692 :
693 0 : if (poGenericNetwork->ConnectFeatures(nSrcFID, nTgtFID, nConFID,
694 : dfDirCost, dfInvCost,
695 0 : eDir) != CE_None)
696 : {
697 0 : fprintf(stderr, "Failed to connect features\n");
698 0 : nRet = 1;
699 0 : goto exit;
700 : }
701 :
702 0 : if (bQuiet == FALSE)
703 : {
704 0 : printf("Features connected successfully\n");
705 : }
706 : }
707 2 : else if (stOper == op_disconnect)
708 : {
709 0 : if (pszDataSource == nullptr)
710 0 : Usage(true, "No network dataset provided");
711 :
712 : // open
713 0 : poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
714 0 : GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
715 : nullptr, nullptr)));
716 :
717 0 : if (nullptr == poDS)
718 : {
719 0 : fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
720 0 : nRet = 1;
721 0 : goto exit;
722 : }
723 :
724 : GNMGenericNetwork *poGenericNetwork =
725 0 : dynamic_cast<GNMGenericNetwork *>(poDS);
726 :
727 0 : if (nullptr == poGenericNetwork)
728 : {
729 0 : fprintf(stderr,
730 : "\nUnsupported datasource type for this operation\n");
731 0 : nRet = 1;
732 0 : goto exit;
733 : }
734 :
735 0 : if (poGenericNetwork->DisconnectFeatures(nSrcFID, nTgtFID, nConFID) !=
736 : CE_None)
737 : {
738 0 : fprintf(stderr, "Failed to disconnect features\n");
739 0 : nRet = 1;
740 0 : goto exit;
741 : }
742 :
743 0 : if (bQuiet == FALSE)
744 : {
745 0 : printf("Features disconnected successfully\n");
746 : }
747 : }
748 2 : else if (stOper == op_rule)
749 : {
750 0 : if (pszDataSource == nullptr)
751 0 : Usage(true, "No network dataset provided");
752 :
753 : // open
754 0 : poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
755 0 : GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
756 : nullptr, nullptr)));
757 :
758 0 : if (nullptr == poDS)
759 : {
760 0 : fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
761 0 : nRet = 1;
762 0 : goto exit;
763 : }
764 :
765 : GNMGenericNetwork *poGenericNetwork =
766 0 : dynamic_cast<GNMGenericNetwork *>(poDS);
767 :
768 0 : if (nullptr == poGenericNetwork)
769 : {
770 0 : fprintf(stderr,
771 : "\nUnsupported datasource type for this operation\n");
772 0 : nRet = 1;
773 0 : goto exit;
774 : }
775 :
776 0 : if (poGenericNetwork->CreateRule(pszRuleStr) != CE_None)
777 : {
778 0 : fprintf(stderr, "Failed to create rule %s\n", pszRuleStr);
779 0 : nRet = 1;
780 0 : goto exit;
781 : }
782 :
783 0 : if (bQuiet == FALSE)
784 : {
785 0 : printf("Create rule '%s' successfully\n", pszRuleStr);
786 : }
787 : }
788 2 : else if (stOper == op_autoconnect)
789 : {
790 1 : if (pszDataSource == nullptr)
791 0 : Usage(true, "No network dataset provided");
792 :
793 : // open
794 2 : poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
795 1 : GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
796 : nullptr, nullptr)));
797 :
798 1 : if (nullptr == poDS)
799 : {
800 0 : fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
801 0 : nRet = 1;
802 0 : goto exit;
803 : }
804 :
805 : GNMGenericNetwork *poGenericNetwork =
806 1 : dynamic_cast<GNMGenericNetwork *>(poDS);
807 :
808 1 : if (nullptr == poGenericNetwork)
809 : {
810 0 : fprintf(stderr,
811 : "\nUnsupported datasource type for this operation\n");
812 0 : nRet = 1;
813 0 : goto exit;
814 : }
815 :
816 1 : if (CSLCount(papszLayers) == 0 && poDS->GetLayerCount() > 1)
817 : {
818 1 : if (bQuiet == FALSE)
819 : {
820 1 : printf("No layers provided. Use all layers of network:\n");
821 : }
822 :
823 3 : for (int i = 0; i < poDS->GetLayerCount(); ++i)
824 : {
825 2 : OGRLayer *poLayer = poDS->GetLayer(i);
826 2 : if (bQuiet == FALSE)
827 : {
828 2 : printf("%d. %s\n", i + 1, poLayer->GetName());
829 : }
830 2 : papszLayers = CSLAddString(papszLayers, poLayer->GetName());
831 : }
832 : }
833 :
834 2 : if (poGenericNetwork->ConnectPointsByLines(papszLayers, dfTolerance,
835 : dfDirCost, dfInvCost,
836 1 : eDir) != CE_None)
837 : {
838 0 : fprintf(stderr, "Failed to autoconnect features\n");
839 0 : nRet = 1;
840 0 : goto exit;
841 : }
842 :
843 1 : if (bQuiet == FALSE)
844 : {
845 1 : printf("Features connected successfully\n");
846 : }
847 : }
848 1 : else if (stOper == op_delete)
849 : {
850 1 : if (pszDataSource == nullptr)
851 0 : Usage(true, "No network dataset provided");
852 :
853 : // open
854 2 : poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
855 1 : GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
856 : nullptr, nullptr)));
857 :
858 1 : if (nullptr == poDS)
859 : {
860 0 : fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
861 0 : nRet = 1;
862 0 : goto exit;
863 : }
864 :
865 1 : if (poDS->Delete() != CE_None)
866 : {
867 0 : fprintf(stderr, "Delete failed.\n");
868 0 : nRet = 1;
869 0 : goto exit;
870 : }
871 :
872 1 : if (bQuiet == FALSE)
873 : {
874 1 : printf("Delete successfully\n");
875 : }
876 :
877 : /** if hDriver == NULL this code delete everything in folder,
878 : * not only GNM files
879 :
880 : GDALDriverH hDriver = NULL;
881 : if( pszFormat != NULL )
882 : {
883 : hDriver = GDALGetDriverByName( pszFormat );
884 : if( hDriver == NULL )
885 : {
886 : fprintf( stderr, "Unable to find driver named '%s'.\n",
887 : pszFormat );
888 : exit( 1 );
889 : }
890 : }
891 : GDALDeleteDataset( hDriver, pszDataSource );
892 : */
893 : }
894 0 : else if (stOper == op_change_st)
895 : {
896 0 : if (pszDataSource == nullptr)
897 0 : Usage(true, "No dataset in input");
898 :
899 : // open
900 0 : poDS = cpl::down_cast<GNMNetwork *>(static_cast<GDALDataset *>(
901 0 : GDALOpenEx(pszDataSource, GDAL_OF_UPDATE | GDAL_OF_GNM, nullptr,
902 : nullptr, nullptr)));
903 :
904 0 : if (nullptr == poDS)
905 : {
906 0 : fprintf(stderr, "\nFailed to open network at %s\n", pszDataSource);
907 0 : nRet = 1;
908 0 : goto exit;
909 : }
910 :
911 : GNMGenericNetwork *poGenericNetwork =
912 0 : dynamic_cast<GNMGenericNetwork *>(poDS);
913 :
914 0 : if (nullptr == poGenericNetwork)
915 : {
916 0 : fprintf(stderr,
917 : "\nUnsupported datasource type for this operation\n");
918 0 : nRet = 1;
919 0 : goto exit;
920 : }
921 :
922 0 : if (bUnblockAll)
923 : {
924 0 : if (poGenericNetwork->ChangeAllBlockState(false) != CE_None)
925 : {
926 0 : fprintf(stderr, "\nChange all block state failed\n");
927 0 : nRet = 1;
928 0 : goto exit;
929 : }
930 : }
931 : else
932 : {
933 : size_t i;
934 0 : for (i = 0; i < anFIDsToBlock.size(); ++i)
935 : {
936 0 : if (poGenericNetwork->ChangeBlockState(anFIDsToBlock[i],
937 0 : true) != CE_None)
938 : {
939 0 : fprintf(stderr,
940 : "\nChange block state of id " GNMGFIDFormat
941 : " failed\n",
942 0 : anFIDsToBlock[i]);
943 0 : nRet = 1;
944 0 : goto exit;
945 : }
946 : }
947 :
948 0 : for (i = 0; i < anFIDsToUnblock.size(); ++i)
949 : {
950 0 : if (poGenericNetwork->ChangeBlockState(anFIDsToUnblock[i],
951 0 : false) != CE_None)
952 : {
953 0 : fprintf(stderr,
954 : "\nChange block state of id " GNMGFIDFormat
955 : " failed\n",
956 0 : anFIDsToBlock[i]);
957 0 : nRet = 1;
958 0 : goto exit;
959 : }
960 : }
961 : }
962 :
963 0 : if (bQuiet == FALSE)
964 : {
965 0 : printf("Change block state successfully\n");
966 : }
967 : }
968 : else
969 : {
970 0 : fprintf(
971 : stderr,
972 : "Need an operation. See help what you can do with gnmmanage:\n");
973 0 : Usage(true);
974 : }
975 :
976 6 : exit:
977 6 : CSLDestroy(papszArgv);
978 6 : CSLDestroy(papszDSCO);
979 6 : CSLDestroy(papszLayers);
980 :
981 6 : if (poDS != nullptr)
982 : {
983 6 : if (GDALClose(poDS) != CE_None)
984 0 : nRet = 1;
985 : }
986 :
987 6 : GDALDestroyDriverManager();
988 :
989 6 : return nRet;
990 : }
991 :
992 0 : MAIN_END
|