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