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