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