1 /******************************************************************************
2 *
3 * Project: GDAL/OGR Geography Network support (Geographic Network Model)
4 * Purpose: GNM network class.
5 * Authors: Mikhail Gusev (gusevmihs at gmail dot com)
6 * Dmitry Baryshnikov, polimax@mail.ru
7 *
8 ******************************************************************************
9 * Copyright (c) 2014, Mikhail Gusev
10 * Copyright (c) 2014-2015, NextGIS <info@nextgis.com>
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 ****************************************************************************/
30
31 #include "gnm_api.h"
32 #include "gnm_priv.h"
33 #include "ogrsf_frmts.h"
34
35 #include <set>
36
37 CPL_CVSID("$Id: gnmgenericnetwork.cpp b878db8a22b3c59c80ab68c91b785227f347eced 2020-02-11 23:08:41 +0100 Even Rouault $")
38
39 //! @cond Doxygen_Suppress
GNMGenericNetwork()40 GNMGenericNetwork::GNMGenericNetwork() :
41 GNMNetwork(),
42 m_nVersion(0),
43 m_nGID(0),
44 m_nVirtualConnectionGID(-1),
45 m_poMetadataLayer(nullptr),
46 m_poGraphLayer(nullptr),
47 m_poFeaturesLayer(nullptr),
48 m_poLayerDriver(nullptr),
49 m_bIsRulesChanged(false),
50 m_bIsGraphLoaded(false)
51 {
52 }
53
~GNMGenericNetwork()54 GNMGenericNetwork::~GNMGenericNetwork()
55 {
56 for(size_t i = 0; i < m_apoLayers.size(); i++)
57 delete m_apoLayers[i];
58 }
59
GetLayerCount()60 int GNMGenericNetwork::GetLayerCount()
61 {
62 return (int)m_apoLayers.size();
63 }
64
GetLayer(int nIndex)65 OGRLayer *GNMGenericNetwork::GetLayer(int nIndex)
66 {
67 if(nIndex < 0 || nIndex >= (int)m_apoLayers.size())
68 return nullptr;
69 return m_apoLayers[nIndex];
70 }
71
DeleteLayer(int nIndex)72 OGRErr GNMGenericNetwork::DeleteLayer(int nIndex)
73 {
74 if(nIndex < 0 || nIndex >= (int)m_apoLayers.size())
75 return OGRERR_FAILURE;
76
77 const char* pszLayerName = m_apoLayers[nIndex]->GetName();
78 OGRFeature *poFeature;
79
80 std::set<GNMGFID> anGFIDs;
81 std::set<GNMGFID>::iterator it;
82 // remove layer GFID's from Features layer
83
84 m_poFeaturesLayer->ResetReading();
85 while ((poFeature = m_poFeaturesLayer->GetNextFeature()) != nullptr)
86 {
87 const char *pFeatureClass = poFeature->GetFieldAsString(
88 GNM_SYSFIELD_LAYERNAME);
89
90 if(EQUAL(pFeatureClass, pszLayerName))
91 {
92 anGFIDs.insert(poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_GFID));
93 CPL_IGNORE_RET_VAL(m_poFeaturesLayer->DeleteFeature(poFeature->GetFID()));
94 }
95 OGRFeature::DestroyFeature(poFeature);
96 }
97
98 // remove GFID's from graph layer
99
100 m_poGraphLayer->ResetReading();
101 while ((poFeature = m_poGraphLayer->GetNextFeature()) != nullptr)
102 {
103 GNMGFID nGFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_SOURCE);
104 it = anGFIDs.find(nGFID);
105 if( it != anGFIDs.end())
106 {
107 CPL_IGNORE_RET_VAL(m_poGraphLayer->DeleteFeature(poFeature->GetFID()));
108 OGRFeature::DestroyFeature(poFeature);
109 continue;
110 }
111
112 nGFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_TARGET);
113 it = anGFIDs.find(nGFID);
114 if( it != anGFIDs.end())
115 {
116 CPL_IGNORE_RET_VAL(m_poGraphLayer->DeleteFeature(poFeature->GetFID()));
117 OGRFeature::DestroyFeature(poFeature);
118 continue;
119 }
120
121 nGFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_CONNECTOR);
122 it = anGFIDs.find(nGFID);
123 if( it != anGFIDs.end())
124 {
125 CPL_IGNORE_RET_VAL(m_poGraphLayer->DeleteFeature(poFeature->GetFID()));
126 OGRFeature::DestroyFeature(poFeature);
127 continue;
128 }
129
130 OGRFeature::DestroyFeature(poFeature);
131 }
132
133 // remove connected rules
134 for(size_t i = m_asRules.size(); i > 0; --i)
135 {
136 if(EQUAL(m_asRules[i - 1].GetSourceLayerName(), pszLayerName))
137 {
138 m_asRules.erase(m_asRules.begin() + i - 1);
139 m_bIsRulesChanged = true;
140 }
141 else if(EQUAL(m_asRules[i - 1].GetTargetLayerName(), pszLayerName))
142 {
143 m_asRules.erase(m_asRules.begin() + i - 1);
144 m_bIsRulesChanged = true;
145 }
146 else if(EQUAL(m_asRules[i - 1].GetConnectorLayerName(), pszLayerName))
147 {
148 m_asRules.erase(m_asRules.begin() + i - 1);
149 m_bIsRulesChanged = true;
150 }
151 }
152
153 delete m_apoLayers[nIndex];
154 // remove from array
155 m_apoLayers.erase (m_apoLayers.begin() + nIndex);
156 return OGRERR_NONE;
157 }
158
Delete()159 CPLErr GNMGenericNetwork::Delete()
160 {
161 CPLErr eResult = DeleteNetworkLayers();
162 if(eResult != CE_None)
163 return eResult;
164 eResult = DeleteMetadataLayer();
165 if(eResult != CE_None)
166 return eResult;
167 eResult = DeleteGraphLayer();
168 if(eResult != CE_None)
169 return eResult;
170
171 return DeleteFeaturesLayer();
172 }
173
GetVersion() const174 int GNMGenericNetwork::GetVersion() const
175 {
176 return m_nVersion;
177 }
178
GetNewGlobalFID()179 GIntBig GNMGenericNetwork::GetNewGlobalFID()
180 {
181 return m_nGID++;
182 }
183
GetAlgorithmName(GNMDirection eAlgorithm,bool bShortName)184 CPLString GNMGenericNetwork::GetAlgorithmName(GNMDirection eAlgorithm,
185 bool bShortName)
186 {
187 switch(eAlgorithm)
188 {
189 case GATDijkstraShortestPath:
190 if(bShortName)
191 return CPLString("Dijkstra");
192 else
193 return CPLString("Dijkstra shortest path");
194 case GATKShortestPath:
195 if(bShortName)
196 return CPLString("Yens");
197 else
198 return CPLString("Yens shortest paths");
199 case GATConnectedComponents:
200 if(bShortName)
201 return CPLString("Connected");
202 else
203 return CPLString("Connected components");
204 }
205
206 return CPLString("Invalid");
207 }
208
AddFeatureGlobalFID(GNMGFID nFID,const char * pszLayerName)209 CPLErr GNMGenericNetwork::AddFeatureGlobalFID(GNMGFID nFID,
210 const char *pszLayerName)
211 {
212 OGRFeature *poFeature = OGRFeature::CreateFeature(
213 m_poFeaturesLayer->GetLayerDefn() );
214 poFeature->SetField( GNM_SYSFIELD_GFID, nFID );
215 poFeature->SetField( GNM_SYSFIELD_LAYERNAME, pszLayerName );
216
217 if( m_poFeaturesLayer->CreateFeature( poFeature ) != OGRERR_NONE )
218 {
219 OGRFeature::DestroyFeature( poFeature );
220 CPLError( CE_Failure, CPLE_AppDefined, "Failed to create feature." );
221 return CE_Failure;
222 }
223
224 OGRFeature::DestroyFeature( poFeature );
225
226 return CE_None;
227 }
228
ConnectFeatures(GNMGFID nSrcGFID,GNMGFID nTgtGFID,GNMGFID nConGFID,double dfCost,double dfInvCost,GNMDirection eDir)229 CPLErr GNMGenericNetwork::ConnectFeatures(GNMGFID nSrcGFID, GNMGFID nTgtGFID,
230 GNMGFID nConGFID, double dfCost,
231 double dfInvCost, GNMDirection eDir)
232 {
233 if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
234 {
235 return CE_Failure;
236 }
237
238 OGRFeature *poFeature = FindConnection(nSrcGFID, nTgtGFID, nConGFID);
239 if(poFeature != nullptr)
240 {
241 OGRFeature::DestroyFeature( poFeature );
242 CPLError( CE_Failure, CPLE_AppDefined, "The connection already created" );
243 return CE_Failure;
244 }
245
246 if(m_asRules.empty())
247 {
248 CPLError( CE_Failure, CPLE_AppDefined, "The connection forbidden" );
249 return CE_Failure;
250 }
251 else
252 {
253 CPLString soSrcLayerName = m_moFeatureFIDMap[nSrcGFID];
254 CPLString soTgtLayerName = m_moFeatureFIDMap[nTgtGFID];
255 CPLString soConnLayerName = m_moFeatureFIDMap[nConGFID];
256 for(size_t i = 0; i < m_asRules.size(); ++i)
257 {
258 if(!m_asRules[i].CanConnect(soSrcLayerName, soTgtLayerName,
259 soConnLayerName))
260 {
261 CPLError( CE_Failure, CPLE_AppDefined, "The connection forbidden" );
262 return CE_Failure;
263 }
264 }
265 }
266
267 // we support both vertices and edge to be virtual
268 if(nConGFID == -1)
269 nConGFID = GetNewVirtualFID();
270 if(nSrcGFID == -1)
271 nSrcGFID = GetNewVirtualFID();
272 if(nTgtGFID == -1)
273 nTgtGFID = GetNewVirtualFID();
274
275 poFeature = OGRFeature::CreateFeature( m_poGraphLayer->GetLayerDefn() );
276 poFeature->SetField( GNM_SYSFIELD_SOURCE, nSrcGFID );
277 poFeature->SetField( GNM_SYSFIELD_TARGET, nTgtGFID );
278 poFeature->SetField( GNM_SYSFIELD_CONNECTOR, nConGFID );
279 poFeature->SetField( GNM_SYSFIELD_COST, dfCost );
280 poFeature->SetField( GNM_SYSFIELD_INVCOST, dfInvCost );
281 poFeature->SetField( GNM_SYSFIELD_DIRECTION, eDir );
282 poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_NONE );
283
284 if( m_poGraphLayer->CreateFeature( poFeature ) != OGRERR_NONE )
285 {
286 OGRFeature::DestroyFeature( poFeature );
287 CPLError( CE_Failure, CPLE_AppDefined, "Failed to create feature." );
288 return CE_Failure;
289 }
290
291 OGRFeature::DestroyFeature( poFeature );
292
293 // update graph
294
295 m_oGraph.AddEdge(nConGFID, nSrcGFID, nTgtGFID, eDir == GNM_EDGE_DIR_BOTH,
296 dfCost, dfInvCost);
297
298 return CE_None;
299 }
300
DisconnectFeatures(GNMGFID nSrcGFID,GNMGFID nTgtGFID,GNMGFID nConGFID)301 CPLErr GNMGenericNetwork::DisconnectFeatures(GNMGFID nSrcGFID, GNMGFID nTgtGFID,
302 GNMGFID nConGFID)
303 {
304 if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
305 {
306 return CE_Failure;
307 }
308
309 OGRFeature *poFeature = FindConnection(nSrcGFID, nTgtGFID, nConGFID);
310 if (poFeature == nullptr)
311 {
312 CPLError( CE_Failure, CPLE_AppDefined, "The connection not exist" );
313 return CE_Failure;
314 }
315
316 if (m_poGraphLayer->DeleteFeature(poFeature->GetFID()) != OGRERR_NONE)
317 {
318 OGRFeature::DestroyFeature(poFeature);
319 return CE_Failure;
320 }
321
322 OGRFeature::DestroyFeature(poFeature);
323
324 // update graph
325
326 m_oGraph.DeleteEdge(nConGFID);
327
328 return CE_None;
329 }
330
DisconnectFeaturesWithId(GNMGFID nFID)331 CPLErr GNMGenericNetwork::DisconnectFeaturesWithId(GNMGFID nFID)
332 {
333 if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
334 {
335 return CE_Failure;
336 }
337
338 CPLString soFilter;
339 soFilter.Printf("%s = " GNMGFIDFormat " or %s = " GNMGFIDFormat " or %s = " GNMGFIDFormat,
340 GNM_SYSFIELD_SOURCE, nFID,
341 GNM_SYSFIELD_TARGET, nFID,
342 GNM_SYSFIELD_CONNECTOR, nFID);
343
344 CPLDebug("GNM", "Set attribute filter: %s", soFilter.c_str());
345
346 m_poGraphLayer->SetAttributeFilter(soFilter);
347 m_poGraphLayer->ResetReading();
348 OGRFeature* poFeature;
349 while ((poFeature = m_poGraphLayer->GetNextFeature()) != nullptr)
350 {
351 if(m_poGraphLayer->DeleteFeature(poFeature->GetFID()) != CE_None)
352 {
353 OGRFeature::DestroyFeature( poFeature );
354 CPLError( CE_Failure, CPLE_AppDefined,
355 "Failed to remove feature connection." );
356 return CE_Failure;
357 }
358 OGRFeature::DestroyFeature( poFeature );
359 }
360
361 m_poGraphLayer->SetAttributeFilter(nullptr);
362
363 m_oGraph.DeleteEdge(nFID);
364 m_oGraph.DeleteVertex(nFID);
365
366 return CE_None;
367 }
368
ReconnectFeatures(GNMGFID nSrcGFID,GNMGFID nTgtGFID,GNMGFID nConGFID,double dfCost,double dfInvCost,GNMDirection eDir)369 CPLErr GNMGenericNetwork::ReconnectFeatures(GNMGFID nSrcGFID, GNMGFID nTgtGFID,
370 GNMGFID nConGFID, double dfCost,
371 double dfInvCost, GNMDirection eDir)
372 {
373 if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
374 {
375 return CE_Failure;
376 }
377
378 OGRFeature *poFeature = FindConnection(nSrcGFID, nTgtGFID, nConGFID);
379 if (poFeature == nullptr)
380 {
381 CPLError( CE_Failure, CPLE_AppDefined, "The connection not exist" );
382 return CE_Failure;
383 }
384
385 poFeature->SetField( GNM_SYSFIELD_COST, dfCost );
386 poFeature->SetField( GNM_SYSFIELD_INVCOST, dfInvCost );
387 poFeature->SetField( GNM_SYSFIELD_DIRECTION, eDir );
388
389 if( m_poGraphLayer->SetFeature( poFeature ) != OGRERR_NONE )
390 {
391 OGRFeature::DestroyFeature( poFeature );
392 CPLError( CE_Failure, CPLE_AppDefined, "Failed to update feature." );
393 return CE_Failure;
394 }
395
396 OGRFeature::DestroyFeature( poFeature );
397
398 // update graph
399
400 m_oGraph.ChangeEdge(nConGFID, dfCost, dfInvCost);
401
402 return CE_None;
403 }
404
DisconnectAll()405 CPLErr GNMGenericNetwork::DisconnectAll()
406 {
407 if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
408 {
409 return CE_Failure;
410 }
411 // delete everything from m_pGraphLayer
412
413 OGRFeature *poFeature;
414 m_poGraphLayer->ResetReading();
415 while ((poFeature = m_poGraphLayer->GetNextFeature()) != nullptr)
416 {
417 CPL_IGNORE_RET_VAL(m_poGraphLayer->DeleteFeature(poFeature->GetFID()));
418 OGRFeature::DestroyFeature( poFeature );
419 }
420
421 m_oGraph.Clear();
422
423 return CE_None;
424 }
425
GetFeatureByGlobalFID(GNMGFID nFID)426 OGRFeature *GNMGenericNetwork::GetFeatureByGlobalFID(GNMGFID nFID)
427 {
428 CPLString soLayerName = m_moFeatureFIDMap[nFID];
429 for(size_t i = 0; i < m_apoLayers.size(); ++i)
430 {
431 if(EQUAL(soLayerName, m_apoLayers[i]->GetName()))
432 return m_apoLayers[i]->GetFeature(nFID);
433 }
434 return nullptr;
435 }
436
CreateRule(const char * pszRuleStr)437 CPLErr GNMGenericNetwork::CreateRule(const char *pszRuleStr)
438 {
439 CPLDebug("GNM", "Try to create rule '%s'", pszRuleStr);
440 GNMRule oRule(pszRuleStr);
441 if(!oRule.IsValid())
442 {
443 return CE_Failure;
444 }
445
446 if(!oRule.IsAcceptAny())
447 {
448 bool bSrcExist = false;
449 bool bTgtExist = false;
450 bool bConnExist = false;
451 // check layers exist
452 for(size_t i = 0; i < m_apoLayers.size(); ++i)
453 {
454 if(EQUAL(oRule.GetSourceLayerName(), m_apoLayers[i]->GetName()))
455 {
456 bSrcExist = true;
457 }
458 else if(EQUAL(oRule.GetTargetLayerName(), m_apoLayers[i]->GetName()))
459 {
460 bTgtExist = true;
461 }
462 else if(EQUAL(oRule.GetConnectorLayerName(), m_apoLayers[i]->GetName()))
463 {
464 bConnExist = true;
465 }
466 }
467
468 if(!bSrcExist || !bTgtExist)
469 {
470 CPLError( CE_Failure, CPLE_IllegalArg, "Layers '%s' or '%s' not exist",
471 oRule.GetSourceLayerName().c_str(),
472 oRule.GetTargetLayerName().c_str());
473 return CE_Failure;
474 }
475
476 if(!bConnExist && !oRule.GetConnectorLayerName().empty())
477 {
478 CPLError( CE_Failure, CPLE_IllegalArg, "Connector layer '%s' not exist",
479 oRule.GetConnectorLayerName().c_str());
480 return CE_Failure;
481 }
482 }
483
484 m_asRules.push_back(oRule);
485 m_bIsRulesChanged = true;
486
487 return CE_None;
488 }
489
DeleteAllRules()490 CPLErr GNMGenericNetwork::DeleteAllRules()
491 {
492 CPLString soFilter;
493 soFilter.Printf("%s LIKE '%s%%'", GNM_SYSFIELD_PARAMNAME, GNM_MD_RULE);
494 m_poMetadataLayer->SetAttributeFilter(soFilter);
495
496 m_poMetadataLayer->ResetReading();
497 OGRFeature *poFeature;
498 std::vector<GIntBig> aFIDs;
499 while((poFeature = m_poMetadataLayer->GetNextFeature()) != nullptr)
500 {
501 aFIDs.push_back(poFeature->GetFID());
502 OGRFeature::DestroyFeature(poFeature);
503 }
504
505 m_poMetadataLayer->SetAttributeFilter(nullptr);
506 for(size_t i = 0; i < aFIDs.size(); ++i)
507 {
508 CPL_IGNORE_RET_VAL(m_poMetadataLayer->DeleteFeature(aFIDs[i]));
509 }
510
511 return CE_None;
512 }
513
DeleteRule(const char * pszRuleStr)514 CPLErr GNMGenericNetwork::DeleteRule(const char *pszRuleStr)
515 {
516 for(size_t i = 0; i < m_asRules.size(); ++i)
517 {
518 if(EQUAL(pszRuleStr, m_asRules[i]))
519 {
520 m_asRules.erase(m_asRules.begin() + i);
521 m_bIsRulesChanged = true;
522 return CE_None;
523 }
524 }
525
526 return CE_Failure;
527 }
528
GetRules() const529 char **GNMGenericNetwork::GetRules() const
530 {
531 char** papszRules = nullptr;
532 for(size_t i = 0; i < m_asRules.size(); ++i)
533 {
534 papszRules = CSLAddString(papszRules, m_asRules[i]);
535 }
536 return papszRules;
537 }
538
ConnectPointsByLines(char ** papszLayerList,double dfTolerance,double dfCost,double dfInvCost,GNMDirection eDir)539 CPLErr GNMGenericNetwork::ConnectPointsByLines(char **papszLayerList,
540 double dfTolerance, double dfCost,
541 double dfInvCost, GNMDirection eDir)
542 {
543 if( CSLCount(papszLayerList) < 2 )
544 {
545 CPLError( CE_Failure, CPLE_IllegalArg, "Minimum 2 layers needed to connect" );
546 return CE_Failure;
547 }
548
549 std::vector<OGRLayer*> paLineLayers;
550 std::vector<OGRLayer*> paPointLayers;
551 int eType;
552 int iLayer;
553 OGRLayer* poLayer;
554
555 for(iLayer = 0; papszLayerList[iLayer] != nullptr; ++iLayer)
556 {
557 poLayer = GetLayerByName(papszLayerList[iLayer]);
558 if(nullptr == poLayer)
559 continue;
560
561 eType = wkbFlatten(poLayer->GetGeomType());
562 if(eType == wkbLineString || eType == wkbMultiLineString)
563 {
564 paLineLayers.push_back(poLayer);
565 }
566 else if(eType == wkbPoint)
567 {
568 paPointLayers.push_back(poLayer);
569 }
570 }
571
572 if (paLineLayers.empty() || paPointLayers.empty() )
573 {
574 CPLError( CE_Failure, CPLE_IllegalArg, "Need at least one line (or "
575 "multiline) layer and one point layer to connect" );
576 return CE_Failure;
577 }
578
579 // now walk through all lines and find nearest points for line start and end
580 OGRFeature* poFeature;
581 for(size_t i = 0; i < paLineLayers.size(); ++i)
582 {
583 poLayer = paLineLayers[i];
584
585 poLayer->ResetReading();
586 while((poFeature = poLayer->GetNextFeature()) != nullptr)
587 {
588 const OGRGeometry* poGeom = poFeature->GetGeometryRef();
589 if(nullptr != poGeom)
590 {
591 eType = wkbFlatten(poGeom->getGeometryType());
592 if(eType == wkbLineString)
593 {
594 const OGRLineString* poLineString =
595 (const OGRLineString*) poGeom;
596 ConnectPointsByLine(poFeature->GetFID(), poLineString,
597 paPointLayers, dfTolerance, dfCost,
598 dfInvCost, eDir);
599 }
600 else if( eType == wkbMultiLineString)
601 {
602 const OGRMultiLineString* poMultiLineString =
603 (const OGRMultiLineString*) poGeom;
604 ConnectPointsByMultiline(poFeature->GetFID(), poMultiLineString,
605 paPointLayers, dfTolerance, dfCost,
606 dfInvCost, eDir);
607 }
608 }
609 OGRFeature::DestroyFeature(poFeature);
610 }
611 }
612
613 return CE_None;
614 }
615
ChangeBlockState(GNMGFID nFID,bool bIsBlock)616 CPLErr GNMGenericNetwork::ChangeBlockState(GNMGFID nFID, bool bIsBlock)
617 {
618 if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
619 {
620 return CE_Failure;
621 }
622
623 // change block state in layer
624 OGRLayer* poLayer = GetLayerByName(m_moFeatureFIDMap[nFID]);
625 if(nullptr == poLayer)
626 {
627 CPLError( CE_Failure, CPLE_AppDefined, "Failed to get layer '%s'.",
628 m_moFeatureFIDMap[nFID].c_str() );
629 return CE_Failure;
630 }
631
632 OGRFeature* poFeature = poLayer->GetFeature(nFID);
633 if(nullptr == poFeature)
634 {
635 CPLError( CE_Failure, CPLE_AppDefined, "Failed to get feature '"
636 GNMGFIDFormat"'.", nFID );
637 return CE_Failure;
638 }
639
640 if(bIsBlock)
641 {
642 poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_ALL );
643 }
644 else
645 {
646 poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_NONE );
647 }
648
649 if( poLayer->SetFeature( poFeature ) != OGRERR_NONE )
650 {
651 OGRFeature::DestroyFeature( poFeature );
652 CPLError( CE_Failure, CPLE_AppDefined, "Failed to update feature." );
653 return CE_Failure;
654 }
655
656 OGRFeature::DestroyFeature( poFeature );
657
658 GNMGFID nSrcFID, nTgtFID, nConFID;
659
660 // change block state in graph layer
661 m_poGraphLayer->ResetReading();
662 while ((poFeature = m_poGraphLayer->GetNextFeature()) != nullptr)
663 {
664 nSrcFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_SOURCE);
665 nTgtFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_TARGET);
666 nConFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_CONNECTOR);
667 int nBlockState = poFeature->GetFieldAsInteger(GNM_SYSFIELD_BLOCKED);
668
669 if(bIsBlock)
670 {
671 if(nSrcFID == nFID)
672 nBlockState |= GNM_BLOCK_SRC;
673 else if(nTgtFID == nFID)
674 nBlockState |= GNM_BLOCK_TGT;
675 else if(nConFID == nFID)
676 nBlockState |= GNM_BLOCK_CONN;
677
678 poFeature->SetField( GNM_SYSFIELD_BLOCKED, nBlockState );
679 }
680 else
681 {
682 if(nSrcFID == nFID)
683 nBlockState &= ~GNM_BLOCK_SRC;
684 else if(nTgtFID == nFID)
685 nBlockState &= ~GNM_BLOCK_TGT;
686 else if(nConFID == nFID)
687 nBlockState &= ~GNM_BLOCK_CONN;
688
689 poFeature->SetField( GNM_SYSFIELD_BLOCKED, nBlockState );
690 }
691
692 if( m_poGraphLayer->SetFeature( poFeature ) != OGRERR_NONE )
693 {
694 OGRFeature::DestroyFeature( poFeature );
695 CPLError( CE_Failure, CPLE_AppDefined, "Failed to update feature." );
696 return CE_Failure;
697 }
698
699 OGRFeature::DestroyFeature( poFeature );
700 }
701
702 // change block state in graph
703 m_oGraph.ChangeBlockState(nFID, bIsBlock);
704
705 return CE_None;
706 }
707
ChangeAllBlockState(bool bIsBlock)708 CPLErr GNMGenericNetwork::ChangeAllBlockState(bool bIsBlock)
709 {
710 if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
711 {
712 return CE_Failure;
713 }
714
715 OGRFeature *poFeature;
716 m_poGraphLayer->ResetReading();
717 while ((poFeature = m_poGraphLayer->GetNextFeature()) != nullptr)
718 {
719 if(bIsBlock)
720 {
721 poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_ALL );
722 }
723 else
724 {
725 poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_NONE );
726 }
727
728 if( m_poGraphLayer->SetFeature( poFeature ) != OGRERR_NONE )
729 {
730 OGRFeature::DestroyFeature( poFeature );
731 CPLError( CE_Failure, CPLE_AppDefined, "Failed to update feature." );
732 return CE_Failure;
733 }
734
735 OGRFeature::DestroyFeature( poFeature );
736 }
737
738 // change all network layers
739
740 for(size_t i = 0; i < m_apoLayers.size(); ++i)
741 {
742 OGRLayer* poLayer = m_apoLayers[i];
743 if(nullptr == poLayer)
744 continue;
745 while ((poFeature = poLayer->GetNextFeature()) != nullptr)
746 {
747 if(bIsBlock)
748 {
749 poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_ALL );
750 }
751 else
752 {
753 poFeature->SetField( GNM_SYSFIELD_BLOCKED, GNM_BLOCK_NONE );
754 }
755
756 if( poLayer->SetFeature( poFeature ) != OGRERR_NONE )
757 {
758 OGRFeature::DestroyFeature( poFeature );
759 CPLError( CE_Failure, CPLE_AppDefined, "Failed to update feature." );
760 return CE_Failure;
761 }
762
763 OGRFeature::DestroyFeature( poFeature );
764 }
765 }
766
767 m_oGraph.ChangeAllBlockState(bIsBlock);
768
769 return CE_None;
770 }
771
GetPath(GNMGFID nStartFID,GNMGFID nEndFID,GNMGraphAlgorithmType eAlgorithm,char ** papszOptions)772 OGRLayer *GNMGenericNetwork::GetPath(GNMGFID nStartFID, GNMGFID nEndFID,
773 GNMGraphAlgorithmType eAlgorithm, char **papszOptions)
774 {
775
776 if(!m_bIsGraphLoaded && LoadGraph() != CE_None)
777 {
778 return nullptr;
779 }
780
781 GDALDriver* poMEMDrv =
782 OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("Memory");
783 if (poMEMDrv == nullptr)
784 {
785 CPLError(CE_Failure, CPLE_AppDefined, "Cannot load 'Memory' driver");
786 return nullptr;
787 }
788
789 GDALDataset* poMEMDS =
790 poMEMDrv->Create("dummy_name", 0, 0, 0, GDT_Unknown, nullptr);
791 OGRSpatialReference oDstSpaRef(GetProjectionRef());
792 OGRLayer* poMEMLayer = poMEMDS->CreateLayer(GetAlgorithmName(eAlgorithm,
793 true), &oDstSpaRef, wkbGeometryCollection, nullptr);
794
795 OGRGNMWrappedResultLayer* poResLayer =
796 new OGRGNMWrappedResultLayer(poMEMDS, poMEMLayer);
797
798 const bool bReturnEdges = CPLFetchBool(papszOptions, GNM_MD_FETCHEDGES, true);
799 const bool bReturnVertices = CPLFetchBool(papszOptions, GNM_MD_FETCHVERTEX, true);
800
801 switch (eAlgorithm)
802 {
803 case GATDijkstraShortestPath:
804 {
805 GNMPATH path = m_oGraph.DijkstraShortestPath(nStartFID, nEndFID);
806
807 // fill features in result layer
808 FillResultLayer(poResLayer, path, 1, bReturnVertices, bReturnEdges);
809 }
810 break;
811 case GATKShortestPath:
812 {
813 int nK = atoi(CSLFetchNameValueDef(papszOptions, GNM_MD_NUM_PATHS,
814 "1"));
815
816 CPLDebug("GNM", "Search %d path(s)", nK);
817
818 std::vector<GNMPATH> paths = m_oGraph.KShortestPaths(nStartFID,
819 nEndFID, nK);
820
821 // fill features in result layer
822 for(size_t i = 0; i < paths.size(); ++i)
823 {
824 FillResultLayer(poResLayer, paths[i], static_cast<int>(i + 1), bReturnVertices,
825 bReturnEdges);
826 }
827 }
828 break;
829 case GATConnectedComponents:
830 {
831 GNMVECTOR anEmitters;
832 if(nullptr != papszOptions)
833 {
834 char** papszEmitter = CSLFetchNameValueMultiple(papszOptions, GNM_MD_EMITTER);
835 for(int i = 0; papszEmitter[i] != nullptr; ++i)
836 {
837 GNMGFID nEmitter = atol(papszEmitter[i]);
838 anEmitters.push_back(nEmitter);
839 }
840 CSLDestroy(papszEmitter);
841 }
842
843 if(nStartFID != -1)
844 {
845 anEmitters.push_back(nStartFID);
846 }
847
848 if(nStartFID != -1)
849 {
850 anEmitters.push_back(nEndFID);
851 }
852
853 GNMPATH path = m_oGraph.ConnectedComponents(anEmitters);
854
855 // fill features in result layer
856 FillResultLayer(poResLayer, path, 1, bReturnVertices, bReturnEdges);
857 }
858 break;
859 }
860
861 return poResLayer;
862 }
863
ConnectPointsByMultiline(GIntBig nFID,const OGRMultiLineString * poMultiLineString,const std::vector<OGRLayer * > & paPointLayers,double dfTolerance,double dfCost,double dfInvCost,GNMDirection eDir)864 void GNMGenericNetwork::ConnectPointsByMultiline(GIntBig nFID,
865 const OGRMultiLineString* poMultiLineString,
866 const std::vector<OGRLayer*>& paPointLayers,
867 double dfTolerance, double dfCost,
868 double dfInvCost, GNMDirection eDir)
869 {
870 VALIDATE_POINTER0(poMultiLineString,
871 "GNMGenericNetwork::ConnectPointsByMultiline");
872 for(auto&& poLineString: poMultiLineString)
873 {
874 ConnectPointsByLine(nFID, poLineString, paPointLayers, dfTolerance,
875 dfCost, dfInvCost, eDir);
876 }
877 }
878
ConnectPointsByLine(GIntBig nFID,const OGRLineString * poLineString,const std::vector<OGRLayer * > & paPointLayers,double dfTolerance,double dfCost,double dfInvCost,GNMDirection eDir)879 void GNMGenericNetwork::ConnectPointsByLine(GIntBig nFID,
880 const OGRLineString* poLineString,
881 const std::vector<OGRLayer*>& paPointLayers,
882 double dfTolerance, double dfCost,
883 double dfInvCost, GNMDirection eDir)
884 {
885 VALIDATE_POINTER0(poLineString, "GNMGenericNetwork::ConnectPointsByLine");
886 OGRPoint oStartPoint, oEndPoint;
887 poLineString->StartPoint(&oStartPoint);
888 poLineString->EndPoint(&oEndPoint);
889 double dfHalfTolerance = dfTolerance / 2;
890
891 GNMGFID nSrcFID = FindNearestPoint(&oStartPoint, paPointLayers, dfHalfTolerance);
892 GNMGFID nTgtFID = FindNearestPoint(&oEndPoint, paPointLayers, dfHalfTolerance);
893
894 if(nSrcFID == -1 || nTgtFID == -1)
895 return;
896
897 // connect nSrcFID with nTgtFID via nFID
898 ConnectFeatures(nSrcFID, nTgtFID, (GNMGFID)nFID, dfCost, dfInvCost, eDir);
899 }
900
FindNearestPoint(const OGRPoint * poPoint,const std::vector<OGRLayer * > & paPointLayers,double dfTolerance)901 GNMGFID GNMGenericNetwork::FindNearestPoint(const OGRPoint* poPoint,
902 const std::vector<OGRLayer*>& paPointLayers,
903 double dfTolerance)
904 {
905 VALIDATE_POINTER1(poPoint, "GNMGenericNetwork::FindNearestPoint", -1);
906 double dfMinX = poPoint->getX() - dfTolerance;
907 double dfMinY = poPoint->getY() - dfTolerance;
908 double dfMaxX = poPoint->getX() + dfTolerance;
909 double dfMaxY = poPoint->getY() + dfTolerance;
910
911 OGRFeature *poFeature;
912
913 for(size_t i = 0; i < paPointLayers.size(); ++i)
914 {
915 OGRLayer *poLayer = paPointLayers[i];
916
917 poLayer->SetSpatialFilterRect(dfMinX, dfMinY,
918 dfMaxX, dfMaxY);
919 poLayer->ResetReading();
920 while((poFeature = poLayer->GetNextFeature()) != nullptr)
921 {
922 GNMGFID nRetFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_GFID);
923 OGRFeature::DestroyFeature(poFeature);
924 return nRetFID;
925 }
926 }
927
928 return -1;
929 }
930
FindConnection(GNMGFID nSrcFID,GNMGFID nTgtFID,GNMGFID nConFID)931 OGRFeature *GNMGenericNetwork::FindConnection(GNMGFID nSrcFID, GNMGFID nTgtFID,
932 GNMGFID nConFID)
933 {
934
935 CPLString soFilter;
936 soFilter.Printf("%s = " GNMGFIDFormat " and %s = " GNMGFIDFormat " and %s = " GNMGFIDFormat,
937 GNM_SYSFIELD_SOURCE, nSrcFID,
938 GNM_SYSFIELD_TARGET, nTgtFID,
939 GNM_SYSFIELD_CONNECTOR, nConFID);
940
941 CPLDebug("GNM", "Set attribute filter: %s", soFilter.c_str());
942
943 m_poGraphLayer->SetAttributeFilter(soFilter);
944 m_poGraphLayer->ResetReading();
945 OGRFeature *f = m_poGraphLayer->GetNextFeature();
946 m_poGraphLayer->SetAttributeFilter(nullptr);
947 return f;
948 }
949
SaveRules()950 void GNMGenericNetwork::SaveRules()
951 {
952 if(!m_bIsRulesChanged)
953 return;
954
955 if(DeleteAllRules() != CE_None)
956 return;
957
958 OGRFeature *poFeature;
959 for(int i = 0; i < (int)m_asRules.size(); ++i)
960 {
961 poFeature = OGRFeature::CreateFeature(m_poMetadataLayer->GetLayerDefn());
962 poFeature->SetField(GNM_SYSFIELD_PARAMNAME, CPLSPrintf("%s%d",
963 GNM_MD_RULE, i + 1));
964 poFeature->SetField(GNM_SYSFIELD_PARAMVALUE, m_asRules[i]);
965 if(m_poMetadataLayer->CreateFeature(poFeature) != OGRERR_NONE)
966 {
967 CPLError( CE_Failure, CPLE_AppDefined, "Write rule '%s' failed",
968 m_asRules[i].c_str());
969 // TODO: do we need interrupt here?
970 //OGRFeature::DestroyFeature( poFeature );
971 // return CE_Failure;
972 }
973 OGRFeature::DestroyFeature(poFeature);
974 }
975 }
976
GetNewVirtualFID()977 GNMGFID GNMGenericNetwork::GetNewVirtualFID()
978 {
979 return --m_nVirtualConnectionGID;
980 }
981
FillResultLayer(OGRGNMWrappedResultLayer * poResLayer,const GNMPATH & path,int nNoOfPath,bool bReturnVertices,bool bReturnEdges)982 void GNMGenericNetwork::FillResultLayer(OGRGNMWrappedResultLayer *poResLayer,
983 const GNMPATH &path, int nNoOfPath,
984 bool bReturnVertices, bool bReturnEdges)
985 {
986 for(size_t i = 0; i < path.size(); ++i)
987 {
988 if(bReturnVertices)
989 {
990 GNMGFID nGFID = path[i].first;
991
992 // TODO: create feature for virtual vertex
993 // if(nGFID < -1) {...}
994
995 CPLString soLayerName = m_moFeatureFIDMap[nGFID];
996 OGRFeature* poFeature = GetFeatureByGlobalFID(nGFID);
997 if(nullptr != poFeature)
998 {
999 poResLayer->InsertFeature(poFeature, soLayerName, nNoOfPath,
1000 false);
1001
1002 OGRFeature::DestroyFeature(poFeature);
1003 }
1004 }
1005
1006 if(bReturnEdges)
1007 {
1008 GNMGFID nGFID = path[i].second;
1009
1010 // TODO: create feature for virtual edge
1011 // if(nGFID < -1) {...}
1012
1013 CPLString soLayerName = m_moFeatureFIDMap[nGFID];
1014 OGRFeature* poFeature = GetFeatureByGlobalFID(nGFID);
1015 if(nullptr != poFeature)
1016 {
1017 poResLayer->InsertFeature(poFeature, soLayerName, nNoOfPath,
1018 true);
1019 OGRFeature::DestroyFeature(poFeature);
1020 }
1021 }
1022 }
1023 }
1024
CheckLayerDriver(const char * pszDefaultDriverName,char ** papszOptions)1025 CPLErr GNMGenericNetwork::CheckLayerDriver(const char* pszDefaultDriverName,
1026 char **papszOptions)
1027 {
1028 if(nullptr == m_poLayerDriver)
1029 {
1030 const char* pszDriverName = CSLFetchNameValueDef(papszOptions,
1031 GNM_MD_FORMAT,
1032 pszDefaultDriverName);
1033
1034 if(!CheckStorageDriverSupport(pszDriverName))
1035 {
1036 CPLError( CE_Failure, CPLE_IllegalArg, "%s driver not supported as network storage",
1037 pszDriverName );
1038 return CE_Failure;
1039 }
1040
1041 m_poLayerDriver = GetGDALDriverManager()->GetDriverByName(pszDriverName );
1042 if(nullptr == m_poLayerDriver)
1043 {
1044 CPLError( CE_Failure, CPLE_IllegalArg, "%s driver not available",
1045 pszDriverName );
1046 return CE_Failure;
1047 }
1048 }
1049 return CE_None;
1050 }
1051
CreateMetadataLayer(GDALDataset * const pDS,int nVersion,size_t nFieldSize)1052 CPLErr GNMGenericNetwork::CreateMetadataLayer(GDALDataset * const pDS, int nVersion,
1053 size_t nFieldSize)
1054 {
1055 OGRLayer* pMetadataLayer = pDS->CreateLayer(GNM_SYSLAYER_META, nullptr, wkbNone,
1056 nullptr);
1057 if (nullptr == pMetadataLayer)
1058 {
1059 CPLError( CE_Failure, CPLE_AppDefined, "Creation of '%s' layer failed",
1060 GNM_SYSLAYER_META );
1061 return CE_Failure;
1062 }
1063
1064 OGRFieldDefn oFieldKey(GNM_SYSFIELD_PARAMNAME, OFTString);
1065 oFieldKey.SetWidth(static_cast<int>(nFieldSize));
1066 OGRFieldDefn oFieldValue(GNM_SYSFIELD_PARAMVALUE, OFTString);
1067 oFieldValue.SetWidth(static_cast<int>(nFieldSize));
1068
1069 if(pMetadataLayer->CreateField(&oFieldKey) != OGRERR_NONE ||
1070 pMetadataLayer->CreateField(&oFieldValue) != OGRERR_NONE)
1071 {
1072 CPLError( CE_Failure, CPLE_AppDefined, "Creation of layer '%s' fields failed",
1073 GNM_SYSLAYER_META );
1074 return CE_Failure;
1075 }
1076
1077 OGRFeature *poFeature;
1078
1079 // write name
1080 poFeature = OGRFeature::CreateFeature(pMetadataLayer->GetLayerDefn());
1081 poFeature->SetField(GNM_SYSFIELD_PARAMNAME, GNM_MD_NAME);
1082 poFeature->SetField(GNM_SYSFIELD_PARAMVALUE, m_soName);
1083 if(pMetadataLayer->CreateFeature(poFeature) != OGRERR_NONE)
1084 {
1085 OGRFeature::DestroyFeature( poFeature );
1086 CPLError( CE_Failure, CPLE_AppDefined, "Write GNM name failed");
1087 return CE_Failure;
1088 }
1089 OGRFeature::DestroyFeature(poFeature);
1090
1091 // write version
1092 poFeature = OGRFeature::CreateFeature(pMetadataLayer->GetLayerDefn());
1093 poFeature->SetField(GNM_SYSFIELD_PARAMNAME, GNM_MD_VERSION);
1094 poFeature->SetField(GNM_SYSFIELD_PARAMVALUE, CPLSPrintf("%d", nVersion));
1095 if(pMetadataLayer->CreateFeature(poFeature) != OGRERR_NONE)
1096 {
1097 OGRFeature::DestroyFeature( poFeature );
1098 CPLError( CE_Failure, CPLE_AppDefined, "Write GNM version failed");
1099 return CE_Failure;
1100 }
1101 OGRFeature::DestroyFeature(poFeature);
1102
1103 // write description
1104 if(!sDescription.empty())
1105 {
1106 poFeature = OGRFeature::CreateFeature(pMetadataLayer->GetLayerDefn());
1107 poFeature->SetField(GNM_SYSFIELD_PARAMNAME, GNM_MD_DESCR);
1108 poFeature->SetField(GNM_SYSFIELD_PARAMVALUE, sDescription);
1109 if(pMetadataLayer->CreateFeature(poFeature) != OGRERR_NONE)
1110 {
1111 OGRFeature::DestroyFeature( poFeature );
1112 CPLError( CE_Failure, CPLE_AppDefined, "Write GNM description failed");
1113 return CE_Failure;
1114 }
1115 OGRFeature::DestroyFeature(poFeature);
1116 }
1117
1118 // write srs if < 254 or create file
1119 if(!m_soSRS.empty())
1120 {
1121 if(m_soSRS.size() >= nFieldSize)
1122 {
1123 // cppcheck-suppress knownConditionTrueFalse
1124 if(StoreNetworkSrs() != CE_None)
1125 return CE_Failure;
1126 }
1127 else
1128 {
1129 poFeature = OGRFeature::CreateFeature(pMetadataLayer->GetLayerDefn());
1130 poFeature->SetField(GNM_SYSFIELD_PARAMNAME, GNM_MD_SRS);
1131 poFeature->SetField(GNM_SYSFIELD_PARAMVALUE, m_soSRS);
1132 if(pMetadataLayer->CreateFeature(poFeature) != OGRERR_NONE)
1133 {
1134 OGRFeature::DestroyFeature( poFeature );
1135 CPLError( CE_Failure, CPLE_AppDefined, "Write GNM SRS failed");
1136 return CE_Failure;
1137 }
1138 OGRFeature::DestroyFeature(poFeature);
1139 }
1140 }
1141
1142 m_poMetadataLayer = pMetadataLayer;
1143
1144 m_nVersion = nVersion;
1145
1146 // create default rule
1147 return CreateRule("ALLOW CONNECTS ANY");
1148 }
1149
StoreNetworkSrs()1150 CPLErr GNMGenericNetwork::StoreNetworkSrs()
1151 {
1152 return CE_Failure;
1153 }
1154
LoadNetworkSrs()1155 CPLErr GNMGenericNetwork::LoadNetworkSrs()
1156 {
1157 return CE_Failure;
1158 }
1159
CreateGraphLayer(GDALDataset * const pDS)1160 CPLErr GNMGenericNetwork::CreateGraphLayer(GDALDataset * const pDS)
1161 {
1162 m_poGraphLayer = pDS->CreateLayer(GNM_SYSLAYER_GRAPH, nullptr, wkbNone, nullptr);
1163 if (nullptr == m_poGraphLayer)
1164 {
1165 CPLError( CE_Failure, CPLE_AppDefined, "Creation of '%s' layer failed",
1166 GNM_SYSLAYER_GRAPH );
1167 return CE_Failure;
1168 }
1169
1170 OGRFieldDefn oFieldSrc(GNM_SYSFIELD_SOURCE, GNMGFIDInt);
1171 OGRFieldDefn oFieldDst(GNM_SYSFIELD_TARGET, GNMGFIDInt);
1172 OGRFieldDefn oFieldConnector(GNM_SYSFIELD_CONNECTOR, GNMGFIDInt);
1173 OGRFieldDefn oFieldCost(GNM_SYSFIELD_COST, OFTReal);
1174 OGRFieldDefn oFieldInvCost(GNM_SYSFIELD_INVCOST, OFTReal);
1175 OGRFieldDefn oFieldDir(GNM_SYSFIELD_DIRECTION, OFTInteger);
1176 OGRFieldDefn oFieldBlock(GNM_SYSFIELD_BLOCKED, OFTInteger);
1177
1178 if(m_poGraphLayer->CreateField(&oFieldSrc) != OGRERR_NONE ||
1179 m_poGraphLayer->CreateField(&oFieldDst) != OGRERR_NONE ||
1180 m_poGraphLayer->CreateField(&oFieldConnector) != OGRERR_NONE ||
1181 m_poGraphLayer->CreateField(&oFieldCost) != OGRERR_NONE ||
1182 m_poGraphLayer->CreateField(&oFieldInvCost) != OGRERR_NONE ||
1183 m_poGraphLayer->CreateField(&oFieldDir) != OGRERR_NONE ||
1184 m_poGraphLayer->CreateField(&oFieldBlock) != OGRERR_NONE)
1185 {
1186 CPLError( CE_Failure, CPLE_AppDefined, "Creation of layer '%s' fields failed",
1187 GNM_SYSLAYER_GRAPH );
1188 return CE_Failure;
1189 }
1190
1191 return CE_None;
1192 }
1193
CreateFeaturesLayer(GDALDataset * const pDS)1194 CPLErr GNMGenericNetwork::CreateFeaturesLayer(GDALDataset * const pDS)
1195 {
1196 m_poFeaturesLayer = pDS->CreateLayer(GNM_SYSLAYER_FEATURES, nullptr, wkbNone, nullptr);
1197 if (nullptr == m_poFeaturesLayer)
1198 {
1199 CPLError( CE_Failure, CPLE_AppDefined, "Creation of '%s' layer failed",
1200 GNM_SYSLAYER_FEATURES );
1201 return CE_Failure;
1202 }
1203
1204 OGRFieldDefn oFieldGID(GNM_SYSFIELD_GFID, GNMGFIDInt);
1205 OGRFieldDefn oFieldLayerName(GNM_SYSFIELD_LAYERNAME, OFTString);
1206 oFieldLayerName.SetWidth(254);
1207
1208 if(m_poFeaturesLayer->CreateField(&oFieldGID) != OGRERR_NONE ||
1209 m_poFeaturesLayer->CreateField(&oFieldLayerName) != OGRERR_NONE)
1210 {
1211 CPLError( CE_Failure, CPLE_AppDefined, "Creation of layer '%s' fields failed",
1212 GNM_SYSLAYER_FEATURES );
1213 return CE_Failure;
1214 }
1215
1216 return CE_None;
1217 }
1218
LoadMetadataLayer(GDALDataset * const pDS)1219 CPLErr GNMGenericNetwork::LoadMetadataLayer(GDALDataset * const pDS)
1220 {
1221 // read version, description, SRS, classes, rules
1222 m_poMetadataLayer = pDS->GetLayerByName(GNM_SYSLAYER_META);
1223 if(nullptr == m_poMetadataLayer)
1224 {
1225 CPLError( CE_Failure, CPLE_AppDefined, "Loading of '%s' layer failed",
1226 GNM_SYSLAYER_META );
1227 return CE_Failure;
1228 }
1229
1230 std::map<int, GNMRule> moRules;
1231 int nRulePrefixLen = static_cast<int>(CPLStrnlen(GNM_MD_RULE, 255));
1232 OGRFeature *poFeature;
1233 m_poMetadataLayer->ResetReading();
1234 while ((poFeature = m_poMetadataLayer->GetNextFeature()) != nullptr)
1235 {
1236 const char *pKey = poFeature->GetFieldAsString(GNM_SYSFIELD_PARAMNAME);
1237 const char *pValue = poFeature->GetFieldAsString(GNM_SYSFIELD_PARAMVALUE);
1238
1239 CPLDebug("GNM", "Load metadata. Key: %s, value %s", pKey, pValue);
1240
1241 if(EQUAL(pKey, GNM_MD_NAME))
1242 {
1243 m_soName = pValue;
1244 }
1245 else if(EQUAL(pKey, GNM_MD_DESCR))
1246 {
1247 sDescription = pValue;
1248 }
1249 else if(EQUAL(pKey, GNM_MD_SRS))
1250 {
1251 m_soSRS = pValue;
1252 }
1253 else if(EQUAL(pKey, GNM_MD_VERSION))
1254 {
1255 m_nVersion = atoi(pValue);
1256 }
1257 else if(EQUALN(pKey, GNM_MD_RULE, nRulePrefixLen))
1258 {
1259 moRules[atoi(pKey + nRulePrefixLen)] = GNMRule(pValue);
1260 }
1261
1262 OGRFeature::DestroyFeature(poFeature);
1263 }
1264
1265 for(std::map<int, GNMRule>::iterator it = moRules.begin();
1266 it != moRules.end(); ++it)
1267 {
1268 if(it->second.IsValid())
1269 m_asRules.push_back(it->second);
1270 }
1271
1272 if(m_soSRS.empty())
1273 {
1274 // cppcheck-suppress knownConditionTrueFalse
1275 if(LoadNetworkSrs() != CE_None)
1276 return CE_Failure;
1277 }
1278
1279 return CE_None;
1280 }
1281
LoadGraphLayer(GDALDataset * const pDS)1282 CPLErr GNMGenericNetwork::LoadGraphLayer(GDALDataset * const pDS)
1283 {
1284 m_poGraphLayer = pDS->GetLayerByName(GNM_SYSLAYER_GRAPH);
1285 if(nullptr == m_poGraphLayer)
1286 {
1287 CPLError( CE_Failure, CPLE_AppDefined, "Loading of '%s' layer failed",
1288 GNM_SYSLAYER_GRAPH );
1289 return CE_Failure;
1290 }
1291
1292 return CE_None;
1293 }
1294
LoadGraph()1295 CPLErr GNMGenericNetwork::LoadGraph()
1296 {
1297 if(m_bIsGraphLoaded)
1298 return CE_None;
1299
1300 if(nullptr == m_poGraphLayer)
1301 {
1302 CPLError( CE_Failure, CPLE_AppDefined, "Loading of graph data failed");
1303 return CE_Failure;
1304 }
1305
1306 OGRFeature *poFeature;
1307 m_poGraphLayer->ResetReading();
1308 GNMGFID nSrcFID, nTgtFID, nConFID;
1309 double dfCost, dfInvCost;
1310 while ((poFeature = m_poGraphLayer->GetNextFeature()) != nullptr)
1311 {
1312 nSrcFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_SOURCE);
1313 nTgtFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_TARGET);
1314 nConFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_CONNECTOR);
1315 dfCost = poFeature->GetFieldAsDouble(GNM_SYSFIELD_COST);
1316 dfInvCost = poFeature->GetFieldAsDouble(GNM_SYSFIELD_INVCOST);
1317 GNMDirection eDir = poFeature->GetFieldAsInteger(GNM_SYSFIELD_DIRECTION);
1318
1319 int nBlockState = poFeature->GetFieldAsInteger(GNM_SYSFIELD_BLOCKED);
1320
1321 bool bIsBlock = GNM_BLOCK_NONE != nBlockState;
1322
1323 m_oGraph.AddEdge(nConFID, nSrcFID, nTgtFID, eDir == GNM_EDGE_DIR_BOTH,
1324 dfCost, dfInvCost);
1325
1326 if(bIsBlock)
1327 {
1328 if(nBlockState & GNM_BLOCK_SRC)
1329 m_oGraph.ChangeBlockState(nSrcFID, bIsBlock);
1330 if(nBlockState & GNM_BLOCK_TGT)
1331 m_oGraph.ChangeBlockState(nTgtFID, bIsBlock);
1332 if(nBlockState & GNM_BLOCK_CONN)
1333 m_oGraph.ChangeBlockState(nConFID, bIsBlock);
1334 }
1335
1336 if(nConFID < m_nVirtualConnectionGID)
1337 m_nVirtualConnectionGID = nConFID;
1338
1339 OGRFeature::DestroyFeature(poFeature);
1340 }
1341
1342 m_bIsGraphLoaded = true;
1343 return CE_None;
1344 }
1345
LoadFeaturesLayer(GDALDataset * const pDS)1346 CPLErr GNMGenericNetwork::LoadFeaturesLayer(GDALDataset * const pDS)
1347 {
1348 m_poFeaturesLayer = pDS->GetLayerByName(GNM_SYSLAYER_FEATURES);
1349 if(nullptr == m_poFeaturesLayer)
1350 {
1351 CPLError( CE_Failure, CPLE_AppDefined, "Loading of '%s' layer failed",
1352 GNM_SYSLAYER_FEATURES );
1353 return CE_Failure;
1354 }
1355
1356 OGRFeature *poFeature;
1357 m_poFeaturesLayer->ResetReading();
1358 while ((poFeature = m_poFeaturesLayer->GetNextFeature()) != nullptr)
1359 {
1360 GNMGFID nFID = poFeature->GetFieldAsGNMGFID(GNM_SYSFIELD_GFID);
1361 const char *pFeatureClass = poFeature->GetFieldAsString(
1362 GNM_SYSFIELD_LAYERNAME);
1363
1364 if(nFID >= m_nGID)
1365 m_nGID = nFID + 1;
1366
1367 m_moFeatureFIDMap[nFID] = pFeatureClass;
1368
1369 // Load network layer. No error handling as we want to load whole network
1370 LoadNetworkLayer(pFeatureClass);
1371
1372 OGRFeature::DestroyFeature(poFeature);
1373 }
1374 return CE_None;
1375 }
1376
TestCapability(const char * pszCap)1377 int GNMGenericNetwork::TestCapability( const char * pszCap )
1378
1379 {
1380 if( EQUAL(pszCap, ODsCCreateLayer) )
1381 return TRUE;
1382 else if( EQUAL(pszCap, ODsCDeleteLayer) )
1383 return TRUE;
1384 else
1385 return FALSE;
1386 }
1387
CopyLayer(OGRLayer * poSrcLayer,const char * pszNewName,char ** papszOptions)1388 OGRLayer *GNMGenericNetwork::CopyLayer(OGRLayer *poSrcLayer,
1389 const char *pszNewName, char **papszOptions)
1390 {
1391 CPLStringList aosOptions(CSLDuplicate(papszOptions));
1392 aosOptions.SetNameValue("DST_SRSWKT", GetProjectionRef());
1393 return GDALDataset::CopyLayer(poSrcLayer, pszNewName, aosOptions.List());
1394 }
1395
CloseDependentDatasets()1396 int GNMGenericNetwork::CloseDependentDatasets()
1397 {
1398 size_t nCount = m_apoLayers.size();
1399 for(size_t i = 0; i < nCount; ++i)
1400 {
1401 delete m_apoLayers[i];
1402 }
1403 m_apoLayers.clear();
1404
1405 GNMNetwork::CloseDependentDatasets();
1406
1407 return nCount > 0 ? TRUE : FALSE;
1408 }
1409
FlushCache()1410 void GNMGenericNetwork::FlushCache()
1411 {
1412 SaveRules();
1413
1414 GNMNetwork::FlushCache();
1415 }
1416
1417 //--- C API --------------------------------------------------------------------
1418
GNMConnectFeatures(GNMGenericNetworkH hNet,GNMGFID nSrcFID,GNMGFID nTgtFID,GNMGFID nConFID,double dfCost,double dfInvCost,GNMDirection eDir)1419 CPLErr CPL_STDCALL GNMConnectFeatures (GNMGenericNetworkH hNet,
1420 GNMGFID nSrcFID, GNMGFID nTgtFID,
1421 GNMGFID nConFID, double dfCost,
1422 double dfInvCost,
1423 GNMDirection eDir)
1424 {
1425 VALIDATE_POINTER1( hNet, "GNMConnectFeatures", CE_Failure );
1426
1427 return ((GNMGenericNetwork*)hNet)->ConnectFeatures(nSrcFID, nTgtFID,
1428 nConFID, dfCost,
1429 dfInvCost, eDir);
1430 }
1431
GNMDisconnectFeatures(GNMGenericNetworkH hNet,GNMGFID nSrcFID,GNMGFID nTgtFID,GNMGFID nConFID)1432 CPLErr CPL_STDCALL GNMDisconnectFeatures (GNMGenericNetworkH hNet, GNMGFID nSrcFID,
1433 GNMGFID nTgtFID, GNMGFID nConFID)
1434 {
1435 VALIDATE_POINTER1( hNet, "GNMDisconnectFeatures", CE_Failure );
1436
1437 return ((GNMGenericNetwork*)hNet)->DisconnectFeatures(nSrcFID, nTgtFID,
1438 nConFID);
1439 }
1440
GNMDisconnectFeaturesWithId(GNMGenericNetworkH hNet,GNMGFID nFID)1441 CPLErr CPL_STDCALL GNMDisconnectFeaturesWithId(GNMGenericNetworkH hNet,
1442 GNMGFID nFID)
1443 {
1444 VALIDATE_POINTER1( hNet, "GNMDisconnectFeaturesWithId", CE_Failure );
1445
1446 return ((GNMGenericNetwork*)hNet)->DisconnectFeaturesWithId(nFID);
1447 }
1448
GNMReconnectFeatures(GNMGenericNetworkH hNet,GNMGFID nSrcFID,GNMGFID nTgtFID,GNMGFID nConFID,double dfCost,double dfInvCost,GNMDirection eDir)1449 CPLErr CPL_STDCALL GNMReconnectFeatures (GNMGenericNetworkH hNet,
1450 GNMGFID nSrcFID, GNMGFID nTgtFID,
1451 GNMGFID nConFID, double dfCost,
1452 double dfInvCost, GNMDirection eDir)
1453 {
1454 VALIDATE_POINTER1( hNet, "GNMReconnectFeatures", CE_Failure );
1455
1456 return ((GNMGenericNetwork*)hNet)->ReconnectFeatures(nSrcFID, nTgtFID,
1457 nConFID, dfCost, dfInvCost, eDir);
1458 }
1459
GNMCreateRule(GNMGenericNetworkH hNet,const char * pszRuleStr)1460 CPLErr CPL_STDCALL GNMCreateRule (GNMGenericNetworkH hNet, const char *pszRuleStr)
1461 {
1462 VALIDATE_POINTER1( hNet, "GNMCreateRule", CE_Failure );
1463
1464 return ((GNMGenericNetwork*)hNet)->CreateRule(pszRuleStr);
1465 }
1466
GNMDeleteAllRules(GNMGenericNetworkH hNet)1467 CPLErr CPL_STDCALL GNMDeleteAllRules(GNMGenericNetworkH hNet)
1468 {
1469 VALIDATE_POINTER1( hNet, "GNMDeleteAllRules", CE_Failure );
1470
1471 return ((GNMGenericNetwork*)hNet)->DeleteAllRules();
1472 }
1473
GNMDeleteRule(GNMGenericNetworkH hNet,const char * pszRuleStr)1474 CPLErr CPL_STDCALL GNMDeleteRule(GNMGenericNetworkH hNet, const char *pszRuleStr)
1475 {
1476 VALIDATE_POINTER1( hNet, "GNMDeleteRule", CE_Failure );
1477
1478 return ((GNMGenericNetwork*)hNet)->DeleteRule(pszRuleStr);
1479 }
1480
GNMGetRules(GNMGenericNetworkH hNet)1481 char** CPL_STDCALL GNMGetRules(GNMGenericNetworkH hNet)
1482 {
1483 VALIDATE_POINTER1( hNet, "GNMDeleteRule", nullptr );
1484
1485 return ((GNMGenericNetwork*)hNet)->GetRules();
1486 }
1487
GNMConnectPointsByLines(GNMGenericNetworkH hNet,char ** papszLayerList,double dfTolerance,double dfCost,double dfInvCost,GNMDirection eDir)1488 CPLErr CPL_STDCALL GNMConnectPointsByLines (GNMGenericNetworkH hNet,
1489 char **papszLayerList,
1490 double dfTolerance,
1491 double dfCost,
1492 double dfInvCost,
1493 GNMDirection eDir)
1494 {
1495 VALIDATE_POINTER1( hNet, "GNMConnectPointsByLines", CE_Failure );
1496
1497 return ((GNMGenericNetwork*)hNet)->ConnectPointsByLines(papszLayerList,
1498 dfTolerance,
1499 dfCost,
1500 dfInvCost, eDir);
1501 }
1502
GNMChangeBlockState(GNMGenericNetworkH hNet,GNMGFID nFID,bool bIsBlock)1503 CPLErr CPL_STDCALL GNMChangeBlockState (GNMGenericNetworkH hNet,
1504 GNMGFID nFID, bool bIsBlock)
1505 {
1506 VALIDATE_POINTER1( hNet, "GNMChangeBlockState", CE_Failure );
1507
1508 return ((GNMGenericNetwork*)hNet)->ChangeBlockState(nFID, bIsBlock);
1509 }
1510
GNMChangeAllBlockState(GNMGenericNetworkH hNet,int bIsBlock)1511 CPLErr CPL_STDCALL GNMChangeAllBlockState (GNMGenericNetworkH hNet,
1512 int bIsBlock)
1513 {
1514 VALIDATE_POINTER1( hNet, "GNMChangeAllBlockState", CE_Failure );
1515
1516 return ((GNMGenericNetwork*)hNet)->ChangeAllBlockState(bIsBlock == TRUE);
1517 }
1518 //! @endcond
1519