Coverage Report

Created: 2025-08-28 06:57

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