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