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