Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/gnm/gnm.h
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
4
 * Purpose:  GNM general public declarations.
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
#ifndef GNM
32
#define GNM
33
34
#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
35
#include "ogrsf_frmts.h"
36
#endif
37
#include "gnmgraph.h"
38
39
// Direction of an edge.
40
typedef int GNMDirection;  // We use int values in order to save them to the
41
                           // network data.
42
43
// Network's metadata parameters names.
44
0
#define GNM_MD_NAME "net_name"
45
0
#define GNM_MD_DESCR "net_description"
46
0
#define GNM_MD_SRS "net_srs"
47
0
#define GNM_MD_VERSION "net_version"
48
0
#define GNM_MD_RULE "net_rule"
49
0
#define GNM_MD_FORMAT "FORMAT"
50
0
#define GNM_MD_FETCHEDGES "fetch_edge"
51
0
#define GNM_MD_FETCHVERTEX "fetch_vertex"
52
0
#define GNM_MD_NUM_PATHS "num_paths"
53
0
#define GNM_MD_EMITTER "emitter"
54
55
// TODO: Constants for capabilities.
56
// #define GNMCanChangeConnections "CanChangeConnections"
57
58
typedef enum
59
{
60
    /** Dijkstra shortest path */ GATDijkstraShortestPath = 1,
61
    /** KShortest Paths        */ GATKShortestPath,
62
    /** Recursive Breadth-first search */ GATConnectedComponents
63
} GNMGraphAlgorithmType;
64
65
#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
66
67
/**
68
 * General GNM class which represents a geography network of common format.
69
 *
70
 * @since GDAL 2.1
71
 */
72
73
class CPL_DLL GNMNetwork : public GDALDataset
74
{
75
  public:
76
    GNMNetwork();
77
    ~GNMNetwork() override;
78
79
    // GDALDataset Interface
80
    const OGRSpatialReference *GetSpatialRef() const override;
81
    char **GetFileList(void) override;
82
83
    // GNMNetwork Interface
84
85
    /**
86
     * @brief Create network system layers
87
     *
88
     * Creates the connectivity (the "network path" of data) over the dataset
89
     * and returns the resulting network.
90
     * NOTE: This method does not create any connections among features
91
     * but creates the necessary set of fields, layers, etc.
92
     * NOTE: After the successful creation the passed dataset must not be
93
     * modified outside (but can be read as usual).
94
     * NOTE: For the common network format the creation is forbidden if the
95
     * passed dataset already has network system layers and OVERWRITE creation
96
     * option is FALSE.
97
     *
98
     * @param pszFilename - A path there the network folder (schema, etc.) will
99
     *                      be created. The folder (schema, etc.) name get
100
     *                      options.
101
     * @param papszOptions - create network options. The create options
102
     *                       specific for gnm driver.
103
     * @return CE_None on success
104
     */
105
    virtual CPLErr Create(const char *pszFilename,
106
                          CSLConstList papszOptions) = 0;
107
108
    /**
109
     * @brief Open a network
110
     * @param poOpenInfo GDALOpenInfo pointer
111
     * @return CE_None on success
112
     */
113
    virtual CPLErr Open(GDALOpenInfo *poOpenInfo) = 0;
114
115
    /**
116
     * @brief Delete network. Delete all dependent layers
117
     * @return CE_None on success
118
     */
119
    virtual CPLErr Delete() = 0;
120
121
    /**
122
     * @brief GetName - a network name. The value provided to create function
123
     *        in GNM_MD_NAME key. While creation this value used to create the
124
     *        folder or db schema name. But can be changed after creation.
125
     * @return Network name string
126
     */
127
    virtual const char *GetName() const;
128
129
    /**
130
     * @brief GetVersion return the network version if applicable
131
     * @return version value
132
     */
133
    virtual int GetVersion() const
134
0
    {
135
0
        return 0;
136
0
    }
137
138
    /**
139
     * @brief DisconnectAll method clears the network graph
140
     * @return CE_None on success
141
     */
142
    virtual CPLErr DisconnectAll() = 0;
143
144
    /**
145
     * @brief GetFeatureByGlobalFID search all network layers for given feature
146
     *        identificator.
147
     * @param nGFID feature identificator.
148
     * @return OGRFeature pointer or NULL. The pointer should be freed via
149
     *         OGRFeature::DestroyFeature().
150
     */
151
    virtual OGRFeature *GetFeatureByGlobalFID(GNMGFID nGFID) = 0;
152
153
    /**
154
     * @brief Create path between start and end GFIDs.
155
     * @param nStartFID - start identificator
156
     * @param nEndFID - end identificator
157
     * @param eAlgorithm - The algorithm to get path
158
     * @param papszOptions - algorithm specific options
159
     * @return In memory OGRLayer pointer with features constituting
160
     *         the shortest path (or paths). The caller have to free
161
     *         the pointer via @see ReleaseResultSet().
162
     */
163
    virtual OGRLayer *GetPath(GNMGFID nStartFID, GNMGFID nEndFID,
164
                              GNMGraphAlgorithmType eAlgorithm,
165
                              CSLConstList papszOptions) = 0;
166
167
    /** Casts a handle to a pointer */
168
    static inline GNMNetwork *FromHandle(GNMGenericNetworkH hNet)
169
0
    {
170
0
        return static_cast<GNMNetwork *>(hNet);
171
0
    }
172
173
    /** Casts a pointer to a handle */
174
    static inline GNMGenericNetworkH ToHandle(GNMNetwork *poNetwork)
175
0
    {
176
0
        return static_cast<GNMGenericNetworkH>(poNetwork);
177
0
    }
178
179
  protected:
180
    /**
181
     * @brief Check if network already exist
182
     * @param pszFilename - path to network (folder or database
183
     * @param papszOptions - create options
184
     * @return TRUE if exist and not overwrite or FALSE
185
     */
186
    virtual int CheckNetworkExist(const char *pszFilename,
187
                                  CSLConstList papszOptions) = 0;
188
189
  protected:
190
    //! @cond Doxygen_Suppress
191
    CPLString m_soName{};
192
    OGRSpatialReference m_oSRS{};
193
    //! @endcond
194
};
195
196
class GNMRule;
197
class OGRGNMWrappedResultLayer;
198
199
/**
200
 * GNM class which represents a geography network of generic format.
201
 *
202
 * @since GDAL 2.1
203
 */
204
205
class CPL_DLL GNMGenericNetwork : public GNMNetwork
206
{
207
  public:
208
    GNMGenericNetwork();
209
    ~GNMGenericNetwork() override;
210
211
    // GDALDataset Interface
212
213
    int GetLayerCount() const override;
214
    OGRLayer *GetLayer(int) const override;
215
    OGRErr DeleteLayer(int) override;
216
217
    int TestCapability(const char *) const override;
218
219
    virtual OGRLayer *CopyLayer(OGRLayer *poSrcLayer, const char *pszNewName,
220
                                CSLConstList papszOptions = nullptr) override;
221
222
    int CloseDependentDatasets() override;
223
    CPLErr FlushCache(bool bAtClosing) override;
224
225
    // GNMNetwork Interface
226
227
    virtual CPLErr Create(const char *pszFilename,
228
                          CSLConstList papszOptions) override = 0;
229
    CPLErr Delete() override;
230
231
    int GetVersion() const override;
232
    /**
233
     * @brief GetNewGlobalFID increase the global ID counter.
234
     * @return New global feature ID.
235
     */
236
    virtual GNMGFID GetNewGlobalFID();
237
238
    /**
239
     * @brief Get the algorithm name
240
     * @param eAlgorithm GNM algorithm type
241
     * @param bShortName Indicator which name to return - short or long
242
     * @return String with algorithm name
243
     */
244
    virtual CPLString GetAlgorithmName(GNMDirection eAlgorithm,
245
                                       bool bShortName);
246
247
    /**
248
     * @brief AddFeatureGlobalFID add the FID <-> Layer name link to fast access
249
     *        features by global FID.
250
     * @param nFID - global FID
251
     * @param pszLayerName - layer name
252
     * @return CE_None on success
253
     */
254
    virtual CPLErr AddFeatureGlobalFID(GNMGFID nFID, const char *pszLayerName);
255
256
    /**
257
     * @brief Connects two features via third feature (may be virtual, so the
258
     *        identificator should be -1). The features may be at the same layer
259
     *        or different layers.
260
     * @param nSrcFID - source feature identificator
261
     * @param nTgtFID - target feature identificator
262
     * @param nConFID - connection feature identificator (-1 for virtual
263
     * connection)
264
     * @param dfCost - cost moving from source to target (default 1)
265
     * @param dfInvCost - cost moving from target to source (default 1)
266
     * @param eDir - direction, may be source to target, target to source or
267
     * both. (default - both)
268
     * @return CE_None on success
269
     */
270
    virtual CPLErr ConnectFeatures(GNMGFID nSrcFID, GNMGFID nTgtFID,
271
                                   GNMGFID nConFID = -1, double dfCost = 1,
272
                                   double dfInvCost = 1,
273
                                   GNMDirection eDir = GNM_EDGE_DIR_BOTH);
274
275
    /**
276
     * @brief Remove features connection
277
     * @param nSrcFID - source feature identificator
278
     * @param nTgtFID - target feature identificator
279
     * @param nConFID - connection feature identificator
280
     * @return CE_None on success
281
     */
282
    virtual CPLErr DisconnectFeatures(GNMGFID nSrcFID, GNMGFID nTgtFID,
283
                                      GNMGFID nConFID);
284
285
    /**
286
     * @brief Find the corresponding identificator in graph (source, target,
287
     *        connector) and remove such connections.
288
     * @param nFID - identificator to find.
289
     * @return CE_None on success
290
     */
291
    virtual CPLErr DisconnectFeaturesWithId(GNMGFID nFID);
292
293
    /**
294
     * @brief Change connection attributes. Search the connection by source
295
     *        feature identificator, target feature identificator and connection
296
     *        identificator.
297
     * @param nSrcFID - source feature identificator
298
     * @param nTgtFID - target feature identificator
299
     * @param nConFID - connection feature identificator
300
     * @param dfCost - new cost moving from source to target
301
     * @param dfInvCost - new cost moving from target to source
302
     * @param eDir - new direction
303
     * @return CE_None on success
304
     */
305
    virtual CPLErr ReconnectFeatures(GNMGFID nSrcFID, GNMGFID nTgtFID,
306
                                     GNMGFID nConFID, double dfCost = 1,
307
                                     double dfInvCost = 1,
308
                                     GNMDirection eDir = GNM_EDGE_DIR_BOTH);
309
310
    CPLErr DisconnectAll() override;
311
312
    OGRFeature *GetFeatureByGlobalFID(GNMGFID nFID) override;
313
314
    /**
315
     * @brief Create network rule
316
     *
317
     * Creates the rule in the network according to the special syntax. These
318
     * rules are declarative and make an effect for the network when they exist.
319
     * Each rule for layer can be created only if the corresponding layer
320
     * existed and removed when the layer is being deleted.
321
     *
322
     * Rules syntax for the common network format in GNM contains the key words
323
     * (words in capital letters or signs) and the modifiers which refers to the
324
     * network objects. All the following combinations are available:
325
     *
326
     *  Notation:
327
     *  layer1, layer2, layer3 - a layer names (the corresponding layers must be
328
     *                           exist;
329
     *  field1 - a field name (field must be exist);
330
     *  constant1 - any double constant;
331
     *  string1 - any string;
332
     *
333
     *  Rules describing which layer can be connected or not connected with each
334
     *  other, and (optional) which layer must serve as a connector. By default
335
     *  all connections are forbidden. But while network creation process the
336
     *  rule to allow any connection added. During the connection process each
337
     *  rule tested if this connection can be created.
338
     *
339
     *    "ALLOW CONNECTS ANY"
340
     *    "DENY CONNECTS ANY"
341
     *    "DENY CONNECTS layer1 WITH layer2"
342
     *    "ALLOW CONNECTS layer1 WITH layer2 VIA layer3"
343
     *
344
     * @param pszRuleStr Rule string which will parsed. If the parsing was
345
     *        successful, the rule will start having effect immediately.
346
     * @return CE_None on success.
347
     */
348
    virtual CPLErr CreateRule(const char *pszRuleStr);
349
350
    /**
351
     * @brief Delete all rules from network
352
     * @return CE_None on success.
353
     */
354
    virtual CPLErr DeleteAllRules();
355
356
    /**
357
     * @brief Delete the specified rule
358
     * @param pszRuleStr - the rule to delete
359
     * @return CE_None on success.
360
     */
361
    virtual CPLErr DeleteRule(const char *pszRuleStr);
362
363
    /**
364
     * @brief Get the rule list
365
     * @return list of rule strings. The caller have to free the lis via
366
     * CPLDestroy.
367
     */
368
    virtual char **GetRules() const;
369
370
    /**
371
     * @brief Attempts to build the network topology automatically
372
     *
373
     * The method simply gets point and line or multiline layers from the
374
     * papszLayerList and searches for each line which connects two points:
375
     * start and end, so it can be not so effective in performance when it is
376
     * called on huge networks. Note, when passing your tolerance value: this
377
     * value will depend of spatial reference system of the network, and
378
     * especially of its 0,0 position because dfTolerance is just divided by 2
379
     * and added/subtracted to/from both sides of each line-feature end point
380
     * forming thus the square area around it. The first point-feature occurred
381
     * inside this area will be given as a start/end point for the current
382
     * connection. So it is also desirable that at least two layers are passed
383
     * in papszLayerList (one point and one line), and they are already
384
     * connected "visually" ("geometrically").
385
     *
386
     * @param papszLayerList A list of layers to connect. The list should be
387
     *                       freed via CSLDestroy.
388
     * @param dfTolerance Snapping tolerance.
389
     * @param dfCost Direct cost.
390
     * @param dfInvCost Inverse cost.
391
     * @param eDir Direction.
392
     * @return CE_None on success
393
     */
394
    virtual CPLErr ConnectPointsByLines(char **papszLayerList,
395
                                        double dfTolerance, double dfCost,
396
                                        double dfInvCost, GNMDirection eDir);
397
398
    /**
399
     * @brief Change the block state of edge or vertex
400
     * @param nFID Identificator
401
     * @param bIsBlock Block or unblock
402
     * @return CE_None on success
403
     */
404
    virtual CPLErr ChangeBlockState(GNMGFID nFID, bool bIsBlock);
405
406
    /**
407
     * @brief Change all vertices and edges block state.
408
     *
409
     * This is mainly use for unblock all vertices and edges.
410
     *
411
     * @param bIsBlock Block or unblock
412
     * @return CE_None on success
413
     */
414
    virtual CPLErr ChangeAllBlockState(bool bIsBlock = false);
415
416
    virtual OGRLayer *GetPath(GNMGFID nStartFID, GNMGFID nEndFID,
417
                              GNMGraphAlgorithmType eAlgorithm,
418
                              CSLConstList papszOptions) override;
419
420
    /** Casts a handle to a pointer */
421
    static inline GNMGenericNetwork *FromHandle(GNMGenericNetworkH hNet)
422
0
    {
423
0
        return static_cast<GNMGenericNetwork *>(hNet);
424
0
    }
425
426
    /** Casts a pointer to a handle */
427
    static inline GNMGenericNetworkH ToHandle(GNMGenericNetwork *poNetwork)
428
0
    {
429
0
        return static_cast<GNMGenericNetworkH>(poNetwork);
430
0
    }
431
432
  protected:
433
    /**
434
     * @brief Check or create layer OGR driver
435
     * @param pszDefaultDriverName - default driver name
436
     * @param papszOptions - create options
437
     * @return CE_None if driver is exist or CE_Failure
438
     */
439
    virtual CPLErr CheckLayerDriver(const char *pszDefaultDriverName,
440
                                    CSLConstList papszOptions);
441
    /**
442
     * @brief Check if provided OGR driver accepted as storage for network data
443
     * @param pszDriverName The driver name
444
     * @return true if supported, else false
445
     */
446
    virtual bool CheckStorageDriverSupport(const char *pszDriverName) = 0;
447
448
  protected:
449
    //! @cond Doxygen_Suppress
450
    virtual CPLErr CreateMetadataLayer(GDALDataset *const pDS, int nVersion,
451
                                       size_t nFieldSize = 1024);
452
    virtual CPLErr StoreNetworkSrs();
453
    virtual CPLErr LoadNetworkSrs();
454
    virtual CPLErr CreateGraphLayer(GDALDataset *const pDS);
455
    virtual CPLErr CreateFeaturesLayer(GDALDataset *const pDS);
456
    virtual CPLErr LoadMetadataLayer(GDALDataset *const pDS);
457
    virtual CPLErr LoadGraphLayer(GDALDataset *const pDS);
458
    virtual CPLErr LoadGraph();
459
    virtual CPLErr LoadFeaturesLayer(GDALDataset *const pDS);
460
    virtual CPLErr DeleteMetadataLayer() = 0;
461
    virtual CPLErr DeleteGraphLayer() = 0;
462
    virtual CPLErr DeleteFeaturesLayer() = 0;
463
    virtual CPLErr LoadNetworkLayer(const char *pszLayername) = 0;
464
    virtual CPLErr DeleteNetworkLayers() = 0;
465
    virtual void ConnectPointsByMultiline(
466
        GIntBig nFID, const OGRMultiLineString *poMultiLineString,
467
        const std::vector<OGRLayer *> &paPointLayers, double dfTolerance,
468
        double dfCost, double dfInvCost, GNMDirection eDir);
469
    virtual void
470
    ConnectPointsByLine(GIntBig nFID, const OGRLineString *poLineString,
471
                        const std::vector<OGRLayer *> &paPointLayers,
472
                        double dfTolerance, double dfCost, double dfInvCost,
473
                        GNMDirection eDir);
474
    virtual GNMGFID
475
    FindNearestPoint(const OGRPoint *poPoint,
476
                     const std::vector<OGRLayer *> &paPointLayers,
477
                     double dfTolerance);
478
    virtual OGRFeature *FindConnection(GNMGFID nSrcFID, GNMGFID nTgtFID,
479
                                       GNMGFID nConFID);
480
    virtual bool SaveRules();
481
    virtual GNMGFID GetNewVirtualFID();
482
    virtual void FillResultLayer(OGRGNMWrappedResultLayer *poResLayer,
483
                                 const GNMPATH &path, int nNoOfPath,
484
                                 bool bReturnVertices, bool bReturnEdges);
485
    //! @endcond
486
  protected:
487
    //! @cond Doxygen_Suppress
488
    int m_nVersion = 0;
489
    GNMGFID m_nGID = 0;
490
    GNMGFID m_nVirtualConnectionGID = -1;
491
    OGRLayer *m_poMetadataLayer = nullptr;
492
    OGRLayer *m_poGraphLayer = nullptr;
493
    OGRLayer *m_poFeaturesLayer = nullptr;
494
495
    GDALDriver *m_poLayerDriver = nullptr;
496
497
    std::map<GNMGFID, CPLString> m_moFeatureFIDMap{};
498
    std::vector<OGRLayer *> m_apoLayers{};
499
    std::vector<GNMRule> m_asRules;
500
    bool m_bIsRulesChanged = false;
501
502
    GNMGraph m_oGraph{};
503
    bool m_bIsGraphLoaded = false;
504
    //! @endcond
505
  private:
506
    CPL_DISALLOW_COPY_ASSIGN(GNMGenericNetwork)
507
};
508
509
/**
510
 * GNM layer which represents a geography network layer of generic format.
511
 * The class override some OGRLayer methods to fulfill the network requirements.
512
 *
513
 * @since GDAL 2.1
514
 */
515
516
class GNMGenericLayer final : public OGRLayer
517
{
518
  public:
519
    GNMGenericLayer(OGRLayer *poLayer, GNMGenericNetwork *poNetwork);
520
    ~GNMGenericLayer() override;
521
522
    // OGRLayer Interface
523
524
    OGRGeometry *GetSpatialFilter() override;
525
526
    virtual OGRErr ISetSpatialFilter(int iGeomField,
527
                                     const OGRGeometry *) override;
528
529
    OGRErr SetAttributeFilter(const char *) override;
530
531
    void ResetReading() override;
532
    OGRFeature *GetNextFeature() override;
533
    OGRErr SetNextByIndex(GIntBig nIndex) override;
534
535
    OGRErr DeleteFeature(GIntBig nFID) override;
536
537
    const char *GetName() const override;
538
    OGRwkbGeometryType GetGeomType() const override;
539
    const OGRFeatureDefn *GetLayerDefn() const override;
540
    virtual int FindFieldIndex(const char *pszFieldName,
541
                               int bExactMatch) override;
542
543
    const OGRSpatialReference *GetSpatialRef() const override;
544
545
    GIntBig GetFeatureCount(int bForce = TRUE) override;
546
547
    virtual OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
548
                              bool bForce = true) override;
549
550
    int TestCapability(const char *) const override;
551
552
    virtual OGRErr CreateField(const OGRFieldDefn *poField,
553
                               int bApproxOK = TRUE) override;
554
    OGRErr DeleteField(int iField) override;
555
    OGRErr ReorderFields(int *panMap) override;
556
    virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
557
                                  int nFlagsIn) override;
558
559
    virtual OGRErr CreateGeomField(const OGRGeomFieldDefn *poField,
560
                                   int bApproxOK = TRUE) override;
561
562
    OGRErr SyncToDisk() override;
563
564
    OGRStyleTable *GetStyleTable() override;
565
    void SetStyleTableDirectly(OGRStyleTable *poStyleTable) override;
566
567
    void SetStyleTable(OGRStyleTable *poStyleTable) override;
568
569
    OGRErr StartTransaction() override;
570
    OGRErr CommitTransaction() override;
571
    OGRErr RollbackTransaction() override;
572
573
    const char *GetFIDColumn() const override;
574
    const char *GetGeometryColumn() const override;
575
576
    OGRErr SetIgnoredFields(CSLConstList papszFields) override;
577
578
    /** Intersection */
579
    OGRErr Intersection(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
580
                        CSLConstList papszOptions = nullptr,
581
                        GDALProgressFunc pfnProgress = nullptr,
582
                        void *pProgressArg = nullptr);
583
    /** Union */
584
    OGRErr Union(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
585
                 CSLConstList papszOptions = nullptr,
586
                 GDALProgressFunc pfnProgress = nullptr,
587
                 void *pProgressArg = nullptr);
588
    /** SymDifference */
589
    OGRErr SymDifference(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
590
                         CSLConstList papszOptions,
591
                         GDALProgressFunc pfnProgress, void *pProgressArg);
592
    /** Identity */
593
    OGRErr Identity(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
594
                    CSLConstList papszOptions = nullptr,
595
                    GDALProgressFunc pfnProgress = nullptr,
596
                    void *pProgressArg = nullptr);
597
    /** Update */
598
    OGRErr Update(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
599
                  CSLConstList papszOptions = nullptr,
600
                  GDALProgressFunc pfnProgress = nullptr,
601
                  void *pProgressArg = nullptr);
602
    /** Clip */
603
    OGRErr Clip(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
604
                CSLConstList papszOptions = nullptr,
605
                GDALProgressFunc pfnProgress = nullptr,
606
                void *pProgressArg = nullptr);
607
    /** Erase */
608
    OGRErr Erase(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
609
                 CSLConstList papszOptions = nullptr,
610
                 GDALProgressFunc pfnProgress = nullptr,
611
                 void *pProgressArg = nullptr);
612
613
    /** GetFeaturesRead */
614
    GIntBig GetFeaturesRead();
615
616
    /** AttributeFilterEvaluationNeedsGeometry */
617
    int AttributeFilterEvaluationNeedsGeometry();
618
619
    //! @cond Doxygen_Suppress
620
    /* consider these private */
621
    OGRErr InitializeIndexSupport(const char *);
622
    OGRLayerAttrIndex *GetIndex();
623
    //! @endcond
624
625
  protected:
626
    //! @cond Doxygen_Suppress
627
    OGRErr ISetFeature(OGRFeature *poFeature) override;
628
    OGRErr ICreateFeature(OGRFeature *poFeature) override;
629
630
  protected:
631
    CPLString m_soLayerName{};
632
    OGRLayer *m_poLayer = nullptr;
633
    GNMGenericNetwork *m_poNetwork = nullptr;
634
    std::map<GNMGFID, GIntBig> m_mnFIDMap{};
635
    //! @endcond
636
637
  private:
638
    CPL_DISALLOW_COPY_ASSIGN(GNMGenericLayer)
639
};
640
641
typedef enum
642
{
643
    /** Rule for connect features */ GRTConnection = 0
644
} GNMRuleType;
645
646
/**
647
 * @brief The simple class for rules
648
 *
649
 * By now we have only connect rules, so the one class is enough. Maybe in
650
 * future the set of classes for different rule types will be needed.
651
 *
652
 * @since GDAL 2.1
653
 */
654
655
class CPL_DLL GNMRule /* non final */
656
{
657
  public:
658
    /** Constructor */
659
    GNMRule();
660
    /** Constructor */
661
    explicit GNMRule(const std::string &oRule);
662
    /** Constructor */
663
    explicit GNMRule(const char *pszRule);
664
665
    /** Copy constructor */
666
0
    GNMRule(const GNMRule &) = default;
667
668
    /** Move constructor */
669
0
    GNMRule(GNMRule &&) = default;
670
671
    /** Assignment operator */
672
    GNMRule &operator=(const GNMRule &) = default;
673
674
    /** Move assignment operator */
675
0
    GNMRule &operator=(GNMRule &&) = default;
676
677
    /** Destructor */
678
    virtual ~GNMRule();
679
680
    /**
681
     * @brief  This function indicate if rule string was parsed successfully
682
     * @return true if rule is valid
683
     */
684
    virtual bool IsValid() const;
685
    /**
686
     * @brief Indicator of any layer state
687
     * @return true if accept any layer
688
     */
689
    virtual bool IsAcceptAny() const;
690
    /**
691
     * @brief This is for future use to indicate the rule type/ Now return only
692
     * GRTConnection type.
693
     * @return the rule type
694
     */
695
    virtual GNMRuleType GetType() const;
696
    /**
697
     * @brief Check if connection can take place.
698
     * @param soSrcLayerName - the layer name
699
     * @param soTgtLayerName - the layer name
700
     * @param soConnLayerName - the layer name
701
     * @return true if can connect features from soSrcLayerName and
702
     * soTgtLayerName via soConnLayerName
703
     */
704
    virtual bool CanConnect(const CPLString &soSrcLayerName,
705
                            const CPLString &soTgtLayerName,
706
                            const CPLString &soConnLayerName = "");
707
    /** Return source layer name */
708
    virtual CPLString GetSourceLayerName() const;
709
    /** Return target layer name */
710
    virtual CPLString GetTargetLayerName() const;
711
    /** Return connector layer name */
712
    virtual CPLString GetConnectorLayerName() const;
713
    /** Return rule as a string */
714
    const char *c_str() const;
715
    /** Return rule as a string */
716
    operator const char *(void) const;
717
718
  protected:
719
    //! @cond Doxygen_Suppress
720
    virtual bool ParseRuleString();
721
722
  protected:
723
    CPLString m_soSrcLayerName{};
724
    CPLString m_soTgtLayerName{};
725
    CPLString m_soConnLayerName{};
726
    bool m_bAllow = false;
727
    bool m_bValid = false;
728
    bool m_bAny = false;
729
    CPLString m_soRuleString{};
730
    //! @endcond
731
};
732
733
/**
734
 * @brief The OGRGNMWrappedResultLayer class for search paths queries results.
735
 *
736
 * @since GDAL 2.1
737
 */
738
739
class OGRGNMWrappedResultLayer final : public OGRLayer
740
{
741
  public:
742
    OGRGNMWrappedResultLayer(GDALDataset *poDS, OGRLayer *poLayer);
743
    ~OGRGNMWrappedResultLayer() override;
744
745
    // OGRLayer
746
    void ResetReading() override;
747
    OGRFeature *GetNextFeature() override;
748
    OGRErr SetNextByIndex(GIntBig nIndex) override;
749
    OGRFeature *GetFeature(GIntBig nFID) override;
750
    const OGRFeatureDefn *GetLayerDefn() const override;
751
    GIntBig GetFeatureCount(int bForce = TRUE) override;
752
    int TestCapability(const char *pszCap) const override;
753
    virtual OGRErr CreateField(const OGRFieldDefn *poField,
754
                               int bApproxOK = TRUE) override;
755
    virtual OGRErr CreateGeomField(const OGRGeomFieldDefn *poField,
756
                                   int bApproxOK = TRUE) override;
757
    const char *GetFIDColumn() const override;
758
    const char *GetGeometryColumn() const override;
759
    const OGRSpatialReference *GetSpatialRef() const override;
760
761
    // OGRGNMWrappedResultLayer
762
    OGRErr InsertFeature(OGRFeature *poFeature, const CPLString &soLayerName,
763
                         int nPathNo, bool bIsEdge);
764
765
  protected:
766
    OGRErr ISetFeature(OGRFeature *poFeature) override;
767
    OGRErr ICreateFeature(OGRFeature *poFeature) override;
768
769
  protected:
770
    //! @cond Doxygen_Suppress
771
    GDALDataset *poDS = nullptr;
772
    OGRLayer *poLayer = nullptr;
773
    //! @endcond
774
775
  private:
776
    CPL_DISALLOW_COPY_ASSIGN(OGRGNMWrappedResultLayer)
777
};
778
779
#endif  // __cplusplus
780
781
#endif  // GNM