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