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