Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Private definitions for OGR/OpenStreeMap driver.
5 : * Author: Even Rouault, <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2012-2014, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef OGR_OSM_H_INCLUDED
14 : #define OGR_OSM_H_INCLUDED
15 :
16 : // replace O(log2(N)) complexity of FindNode() by O(1)
17 : #define ENABLE_NODE_LOOKUP_BY_HASHING 1
18 :
19 : #include "ogrsf_frmts.h"
20 : #include "cpl_string.h"
21 :
22 : #include <array>
23 : #include <set>
24 : #include <unordered_set>
25 : #include <map>
26 : #include <vector>
27 :
28 : #include "osm_parser.h"
29 :
30 : #include "ogrsqlitevfs.h"
31 :
32 : class OGROSMConstCharComp
33 : {
34 : public:
35 30416 : bool operator()(const char *a, const char *b) const
36 : {
37 30416 : return strcmp(a, b) < 0;
38 : }
39 : };
40 :
41 : class OGROSMComputedAttribute
42 : {
43 : public:
44 : CPLString osName{};
45 : int nIndex = -1;
46 : OGRFieldType eType = OFTString;
47 : CPLString osSQL{};
48 : sqlite3_stmt *hStmt = nullptr;
49 : std::vector<CPLString> aosAttrToBind{};
50 : std::vector<int> anIndexToBind{};
51 : bool bHardcodedZOrder = false;
52 :
53 0 : OGROSMComputedAttribute() = default;
54 :
55 74 : explicit OGROSMComputedAttribute(const char *pszName) : osName(pszName)
56 : {
57 74 : }
58 :
59 74 : OGROSMComputedAttribute(OGROSMComputedAttribute &&) = default;
60 : OGROSMComputedAttribute &operator=(OGROSMComputedAttribute &&) = default;
61 :
62 : private:
63 : OGROSMComputedAttribute(const OGROSMComputedAttribute &) = delete;
64 : OGROSMComputedAttribute &
65 : operator=(const OGROSMComputedAttribute &) = delete;
66 : };
67 :
68 : /************************************************************************/
69 : /* OGROSMLayer */
70 : /************************************************************************/
71 :
72 : class OGROSMDataSource;
73 :
74 : class OGROSMLayer final : public OGRLayer
75 : {
76 : friend class OGROSMDataSource;
77 :
78 : OGROSMDataSource *m_poDS = nullptr;
79 : int m_nIdxLayer = 0;
80 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
81 : OGRSpatialReference *m_poSRS = nullptr;
82 :
83 : std::vector<char *>
84 : m_apszNames{}; /* Needed to keep a "reference" to the string inserted
85 : into oMapFieldNameToIndex */
86 : std::map<const char *, int, OGROSMConstCharComp> m_oMapFieldNameToIndex{};
87 :
88 : std::vector<OGROSMComputedAttribute> m_oComputedAttributes{};
89 :
90 : bool m_bResetReadingAllowed = false;
91 :
92 : size_t m_nFeatureArrayIndex = 0;
93 : std::vector<std::unique_ptr<OGRFeature>> m_apoFeatures{};
94 :
95 : bool m_bHasOSMId = false;
96 : int m_nIndexOSMId = -1;
97 : int m_nIndexOSMWayId = -1;
98 : bool m_bHasVersion = false;
99 : bool m_bHasTimestamp = false;
100 : bool m_bHasUID = false;
101 : bool m_bHasUser = false;
102 : bool m_bHasChangeset = false;
103 : bool m_bHasOtherTags = true;
104 : int m_nIndexOtherTags = -1;
105 : bool m_bHasAllTags = false;
106 : int m_nIndexAllTags = -1;
107 :
108 : bool m_bHasWarnedTooManyFeatures = false;
109 :
110 : std::string m_osAllTagsBuffer{};
111 :
112 : bool m_bUserInterested = true;
113 :
114 : bool AddToArray(std::unique_ptr<OGRFeature>, bool bCheckFeatureThreshold);
115 :
116 : int AddInOtherOrAllTags(const char *pszK);
117 :
118 : char szLaunderedFieldName[256];
119 : const char *GetLaunderedFieldName(const char *pszName);
120 :
121 : std::vector<char *> apszInsignificantKeys{};
122 : std::map<const char *, int, OGROSMConstCharComp> aoSetInsignificantKeys{};
123 :
124 : std::vector<char *> apszIgnoreKeys{};
125 : std::map<const char *, int, OGROSMConstCharComp> aoSetIgnoreKeys{};
126 :
127 : std::set<std::string> aoSetWarnKeys{};
128 :
129 : OGROSMLayer(const OGROSMLayer &) = delete;
130 : OGROSMLayer &operator=(const OGROSMLayer &) = delete;
131 :
132 : public:
133 : OGROSMLayer(OGROSMDataSource *m_poDS, int m_nIdxLayer, const char *pszName);
134 : virtual ~OGROSMLayer();
135 :
136 3342 : virtual OGRFeatureDefn *GetLayerDefn() override
137 : {
138 3342 : return m_poFeatureDefn;
139 : }
140 :
141 : virtual void ResetReading() override;
142 : virtual int TestCapability(const char *) override;
143 :
144 : virtual OGRFeature *GetNextFeature() override;
145 :
146 : OGRFeature *MyGetNextFeature(OGROSMLayer **ppoNewCurLayer,
147 : GDALProgressFunc pfnProgress,
148 : void *pProgressData);
149 :
150 : virtual GIntBig GetFeatureCount(int bForce) override;
151 :
152 : virtual OGRErr SetAttributeFilter(const char *pszAttrQuery) override;
153 :
154 : virtual OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent,
155 : bool bForce) override;
156 :
157 : const OGREnvelope *GetSpatialFilterEnvelope();
158 :
159 : bool AddFeature(std::unique_ptr<OGRFeature> poFeature,
160 : bool bAttrFilterAlreadyEvaluated,
161 : bool *pbFilteredOut = nullptr,
162 : bool bCheckFeatureThreshold = true);
163 : void ForceResetReading();
164 :
165 : void AddField(const char *pszName, OGRFieldType eFieldType,
166 : OGRFieldSubType eSubType = OFSTNone);
167 : int GetFieldIndex(const char *pszName);
168 :
169 : bool HasOSMId() const
170 : {
171 : return m_bHasOSMId;
172 : }
173 :
174 185 : void SetHasOSMId(bool bIn)
175 : {
176 185 : m_bHasOSMId = bIn;
177 185 : }
178 :
179 38 : bool HasVersion() const
180 : {
181 38 : return m_bHasVersion;
182 : }
183 :
184 185 : void SetHasVersion(bool bIn)
185 : {
186 185 : m_bHasVersion = bIn;
187 185 : }
188 :
189 38 : bool HasTimestamp() const
190 : {
191 38 : return m_bHasTimestamp;
192 : }
193 :
194 185 : void SetHasTimestamp(bool bIn)
195 : {
196 185 : m_bHasTimestamp = bIn;
197 185 : }
198 :
199 38 : bool HasUID() const
200 : {
201 38 : return m_bHasUID;
202 : }
203 :
204 185 : void SetHasUID(bool bIn)
205 : {
206 185 : m_bHasUID = bIn;
207 185 : }
208 :
209 38 : bool HasUser() const
210 : {
211 38 : return m_bHasUser;
212 : }
213 :
214 185 : void SetHasUser(bool bIn)
215 : {
216 185 : m_bHasUser = bIn;
217 185 : }
218 :
219 38 : bool HasChangeset() const
220 : {
221 38 : return m_bHasChangeset;
222 : }
223 :
224 185 : void SetHasChangeset(bool bIn)
225 : {
226 185 : m_bHasChangeset = bIn;
227 185 : }
228 :
229 190 : bool HasOtherTags() const
230 : {
231 190 : return m_bHasOtherTags;
232 : }
233 :
234 2 : void SetHasOtherTags(bool bIn)
235 : {
236 2 : m_bHasOtherTags = bIn;
237 2 : }
238 :
239 190 : bool HasAllTags() const
240 : {
241 190 : return m_bHasAllTags;
242 : }
243 :
244 2 : void SetHasAllTags(bool bIn)
245 : {
246 2 : m_bHasAllTags = bIn;
247 2 : }
248 :
249 : void SetFieldsFromTags(OGRFeature *poFeature, GIntBig nID, bool bIsWayID,
250 : unsigned int nTags, const OSMTag *pasTags,
251 : const OSMInfo *psInfo);
252 :
253 192 : void SetDeclareInterest(bool bIn)
254 : {
255 192 : m_bUserInterested = bIn;
256 192 : }
257 :
258 5128 : bool IsUserInterested() const
259 : {
260 5128 : return m_bUserInterested;
261 : }
262 :
263 507 : int HasAttributeFilter() const
264 : {
265 507 : return m_poAttrQuery != nullptr;
266 : }
267 :
268 : int EvaluateAttributeFilter(OGRFeature *poFeature);
269 :
270 : void AddInsignificantKey(const char *pszK);
271 :
272 510 : int IsSignificantKey(const char *pszK) const
273 : {
274 510 : return aoSetInsignificantKeys.find(pszK) ==
275 1020 : aoSetInsignificantKeys.end();
276 : }
277 :
278 : void AddIgnoreKey(const char *pszK);
279 : void AddWarnKey(const char *pszK);
280 :
281 : void AddComputedAttribute(const char *pszName, OGRFieldType eType,
282 : const char *pszSQL);
283 : };
284 :
285 : /************************************************************************/
286 : /* OGROSMDataSource */
287 : /************************************************************************/
288 :
289 : struct KeyDesc
290 : {
291 : char *pszK = nullptr;
292 : int nKeyIndex = 0;
293 : int nOccurrences = 0;
294 : std::vector<char *> apszValues{};
295 : //! map that is the reverse of apszValues
296 : std::map<const char *, int, OGROSMConstCharComp> anMapV{};
297 : };
298 :
299 : typedef struct
300 : {
301 : short bKIsIndex; /* whether we should use nKeyIndex or
302 : nOffsetInpabyNonRedundantKeys */
303 : short bVIsIndex; /* whether we should use nValueIndex or
304 : nOffsetInpabyNonRedundantValues */
305 :
306 : union
307 : {
308 : int nKeyIndex; /* index of OGROSMDataSource.asKeys */
309 : int nOffsetInpabyNonRedundantKeys; /* offset in
310 : OGROSMDataSource.pabyNonRedundantKeys
311 : */
312 : } uKey;
313 :
314 : union
315 : {
316 : int nValueIndex; /* index of KeyDesc.apszValues */
317 : int nOffsetInpabyNonRedundantValues; /* offset in
318 : OGROSMDataSource.pabyNonRedundantValues
319 : */
320 : } uVal;
321 : } IndexedKVP;
322 :
323 : typedef struct
324 : {
325 : GIntBig nOff;
326 :
327 : /* Note: only one of nth bucket pabyBitmap or panSectorSize must be free'd
328 : */
329 : union
330 : {
331 : GByte *pabyBitmap; /* array of BUCKET_BITMAP_SIZE bytes */
332 : GByte *panSectorSize; /* array of BUCKET_SECTOR_SIZE_ARRAY_SIZE bytes.
333 : Each values means (size in bytes - 8 ) / 2,
334 : minus 8. 252 means uncompressed */
335 : } u;
336 : } Bucket;
337 :
338 : typedef struct
339 : {
340 : int nLon;
341 : int nLat;
342 : } LonLat;
343 :
344 : struct WayFeaturePair
345 : {
346 : GIntBig nWayID = 0;
347 : /* point to a sub-array of OGROSMDataSource.anReqIds */
348 : GIntBig *panNodeRefs = nullptr;
349 : unsigned int nRefs = 0;
350 : unsigned int nTags = 0;
351 : IndexedKVP *pasTags = nullptr; /* point to a sub-array of
352 : OGROSMDataSource.pasAccumulatedTags */
353 : OSMInfo sInfo{};
354 : std::unique_ptr<OGRFeature> poFeature{};
355 : bool bIsArea = false;
356 : bool bAttrFilterAlreadyEvaluated = false;
357 : };
358 :
359 : #ifdef ENABLE_NODE_LOOKUP_BY_HASHING
360 : typedef struct
361 : {
362 : int nInd; /* values are indexes of panReqIds */
363 : int nNext; /* values are indexes of psCollisionBuckets, or -1 to stop the
364 : chain */
365 : } CollisionBucket;
366 : #endif
367 :
368 : class OGROSMDataSource final : public GDALDataset
369 : {
370 : friend class OGROSMLayer;
371 :
372 : std::vector<std::unique_ptr<OGROSMLayer>> m_apoLayers{};
373 :
374 : std::string m_osConfigFile{};
375 :
376 : OGREnvelope m_sExtent{};
377 : bool m_bExtentValid = false;
378 :
379 : // Starts off at -1 to indicate that we do not know.
380 : int m_bInterleavedReading = -1;
381 : OGROSMLayer *m_poCurrentLayer = nullptr;
382 :
383 : OSMContext *m_psParser = nullptr;
384 : bool m_bHasParsedFirstChunk = false;
385 : bool m_bStopParsing = false;
386 :
387 : sqlite3_vfs *m_pMyVFS = nullptr;
388 :
389 : sqlite3 *m_hDB = nullptr;
390 : sqlite3_stmt *m_hInsertNodeStmt = nullptr;
391 : sqlite3_stmt *m_hInsertWayStmt = nullptr;
392 : sqlite3_stmt **m_pahSelectNodeStmt = nullptr;
393 : sqlite3_stmt **m_pahSelectWayStmt = nullptr;
394 : sqlite3_stmt *m_hInsertPolygonsStandaloneStmt = nullptr;
395 : sqlite3_stmt *m_hDeletePolygonsStandaloneStmt = nullptr;
396 : sqlite3_stmt *m_hSelectPolygonsStandaloneStmt = nullptr;
397 : bool m_bHasRowInPolygonsStandalone = false;
398 :
399 : sqlite3 *m_hDBForComputedAttributes = nullptr;
400 :
401 : int m_nMaxSizeForInMemoryDBInMB = 0;
402 : bool m_bInMemoryTmpDB = false;
403 : bool m_bMustUnlink = true;
404 : CPLString m_osTmpDBName{};
405 :
406 : std::unordered_set<std::string> aoSetClosedWaysArePolygons{};
407 : int m_nMinSizeKeysInSetClosedWaysArePolygons = 0;
408 : int m_nMaxSizeKeysInSetClosedWaysArePolygons = 0;
409 :
410 : std::vector<LonLat> m_asLonLatCache{};
411 :
412 : std::array<const char *, 7> m_ignoredKeys = {{"area", "created_by",
413 : "converted_by", "note",
414 : "todo", "fixme", "FIXME"}};
415 :
416 : bool m_bReportAllNodes = false;
417 : bool m_bReportAllWays = false;
418 : bool m_bTagsAsHSTORE = true; // if false, as JSON
419 :
420 : bool m_bFeatureAdded = false;
421 :
422 : bool m_bInTransaction = false;
423 :
424 : bool m_bIndexPoints = true;
425 : bool m_bUsePointsIndex = true;
426 : bool m_bIndexWays = true;
427 : bool m_bUseWaysIndex = true;
428 :
429 : std::vector<bool> m_abSavedDeclaredInterest{};
430 : OGRLayer *m_poResultSetLayer = nullptr;
431 : bool m_bIndexPointsBackup = false;
432 : bool m_bUsePointsIndexBackup = false;
433 : bool m_bIndexWaysBackup = false;
434 : bool m_bUseWaysIndexBackup = false;
435 :
436 : bool m_bIsFeatureCountEnabled = false;
437 :
438 : bool m_bAttributeNameLaundering = true;
439 :
440 : std::vector<GByte> m_abyWayBuffer{};
441 :
442 : int m_nWaysProcessed = 0;
443 : int m_nRelationsProcessed = 0;
444 :
445 : bool m_bCustomIndexing = true;
446 : bool m_bCompressNodes = false;
447 :
448 : unsigned int m_nUnsortedReqIds = 0;
449 : GIntBig *m_panUnsortedReqIds = nullptr;
450 :
451 : unsigned int m_nReqIds = 0;
452 : GIntBig *m_panReqIds = nullptr;
453 :
454 : #ifdef ENABLE_NODE_LOOKUP_BY_HASHING
455 : bool m_bEnableHashedIndex = true;
456 : /* values >= 0 are indexes of panReqIds. */
457 : /* == -1 for unoccupied */
458 : /* < -1 are expressed as -nIndexToCollisionBuckets-2 where
459 : * nIndexToCollisionBuckets point to psCollisionBuckets */
460 : int *m_panHashedIndexes = nullptr;
461 : CollisionBucket *m_psCollisionBuckets = nullptr;
462 : bool m_bHashedIndexValid = false;
463 : #endif
464 :
465 : LonLat *m_pasLonLatArray = nullptr;
466 :
467 : IndexedKVP *m_pasAccumulatedTags =
468 : nullptr; /* points to content of pabyNonRedundantValues or
469 : aoMapIndexedKeys */
470 : int m_nAccumulatedTags = 0;
471 : unsigned int MAX_INDEXED_KEYS = 0;
472 : GByte *pabyNonRedundantKeys = nullptr;
473 : int nNonRedundantKeysLen = 0;
474 : unsigned int MAX_INDEXED_VALUES_PER_KEY = 0;
475 : GByte *pabyNonRedundantValues = nullptr;
476 : int nNonRedundantValuesLen = 0;
477 : std::vector<WayFeaturePair> m_asWayFeaturePairs{};
478 :
479 : std::vector<KeyDesc *> m_apsKeys{};
480 : std::map<const char *, KeyDesc *, OGROSMConstCharComp>
481 : m_aoMapIndexedKeys{}; /* map that is the reverse of asKeys */
482 :
483 : CPLString m_osNodesFilename{};
484 : bool m_bInMemoryNodesFile = false;
485 : bool m_bMustUnlinkNodesFile = true;
486 : GIntBig m_nNodesFileSize = 0;
487 : VSILFILE *m_fpNodes = nullptr;
488 :
489 : GIntBig m_nPrevNodeId = -INT_MAX;
490 : int m_nBucketOld = -1;
491 : int m_nOffInBucketReducedOld = -1;
492 : GByte *m_pabySector = nullptr;
493 : std::map<int, Bucket> m_oMapBuckets{};
494 : Bucket *GetBucket(int nBucketId);
495 :
496 : bool m_bNeedsToSaveWayInfo = false;
497 :
498 : static const GIntBig FILESIZE_NOT_INIT = -2;
499 : static const GIntBig FILESIZE_INVALID = -1;
500 : GIntBig m_nFileSize = FILESIZE_NOT_INIT;
501 :
502 : void CompressWay(bool bIsArea, unsigned int nTags,
503 : const IndexedKVP *pasTags, int nPoints,
504 : const LonLat *pasLonLatPairs, const OSMInfo *psInfo,
505 : std::vector<GByte> &abyCompressedWay);
506 : void UncompressWay(int nBytes, const GByte *pabyCompressedWay,
507 : bool *pbIsArea, std::vector<LonLat> &asCoords,
508 : unsigned int *pnTags, OSMTag *pasTags, OSMInfo *psInfo);
509 :
510 : bool ParseConf(CSLConstList papszOpenOptions);
511 : bool CreateTempDB();
512 : bool SetDBOptions();
513 : void SetCacheSize();
514 : bool CreatePreparedStatements();
515 : void CloseDB();
516 :
517 : bool IndexPoint(const OSMNode *psNode);
518 : bool IndexPointSQLite(const OSMNode *psNode);
519 : bool FlushCurrentSector();
520 : bool FlushCurrentSectorCompressedCase();
521 : bool FlushCurrentSectorNonCompressedCase();
522 : bool IndexPointCustom(const OSMNode *psNode);
523 :
524 : void IndexWay(GIntBig nWayID, bool bIsArea, unsigned int nTags,
525 : const IndexedKVP *pasTags, const LonLat *pasLonLatPairs,
526 : int nPairs, const OSMInfo *psInfo);
527 :
528 : bool StartTransactionCacheDB();
529 : bool CommitTransactionCacheDB();
530 :
531 : int FindNode(GIntBig nID);
532 : void ProcessWaysBatch();
533 :
534 : void ProcessPolygonsStandalone();
535 :
536 : void LookupNodes();
537 : void LookupNodesSQLite();
538 : void LookupNodesCustom();
539 : void LookupNodesCustomCompressedCase();
540 : void LookupNodesCustomNonCompressedCase();
541 :
542 : unsigned int
543 : LookupWays(std::map<GIntBig, std::pair<int, void *>> &aoMapWays,
544 : const OSMRelation *psRelation);
545 :
546 : OGRGeometry *BuildMultiPolygon(const OSMRelation *psRelation,
547 : unsigned int *pnTags, OSMTag *pasTags);
548 : OGRGeometry *BuildGeometryCollection(const OSMRelation *psRelation,
549 : bool bMultiLineString);
550 :
551 : bool TransferToDiskIfNecesserary();
552 :
553 : Bucket *AllocBucket(int iBucket);
554 :
555 : void AddComputedAttributes(
556 : int iCurLayer, const std::vector<OGROSMComputedAttribute> &oAttributes);
557 : bool IsClosedWayTaggedAsPolygon(unsigned int nTags, const OSMTag *pasTags);
558 :
559 : OGROSMDataSource(const OGROSMDataSource &) = delete;
560 : OGROSMDataSource &operator=(const OGROSMDataSource &) = delete;
561 :
562 : public:
563 : OGROSMDataSource();
564 : virtual ~OGROSMDataSource();
565 :
566 1154 : virtual int GetLayerCount() override
567 : {
568 1154 : return static_cast<int>(m_apoLayers.size());
569 : }
570 :
571 : virtual OGRLayer *GetLayer(int) override;
572 :
573 : virtual int TestCapability(const char *) override;
574 :
575 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
576 : OGRGeometry *poSpatialFilter,
577 : const char *pszDialect) override;
578 : virtual void ReleaseResultSet(OGRLayer *poLayer) override;
579 :
580 : virtual void ResetReading() override;
581 : virtual OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer,
582 : double *pdfProgressPct,
583 : GDALProgressFunc pfnProgress,
584 : void *pProgressData) override;
585 :
586 : int Open(const char *pszFilename, CSLConstList papszOpenOptions);
587 :
588 : int MyResetReading();
589 : bool ParseNextChunk(int nIdxLayer, GDALProgressFunc pfnProgress,
590 : void *pProgressData);
591 : OGRErr GetExtent(OGREnvelope *psExtent);
592 : int IsInterleavedReading();
593 :
594 : void NotifyNodes(unsigned int nNodes, const OSMNode *pasNodes);
595 : void NotifyWay(const OSMWay *psWay);
596 : void NotifyRelation(const OSMRelation *psRelation);
597 : void NotifyBounds(double dfXMin, double dfYMin, double dfXMax,
598 : double dfYMax);
599 :
600 416 : OGROSMLayer *GetCurrentLayer()
601 : {
602 416 : return m_poCurrentLayer;
603 : }
604 :
605 237 : void SetCurrentLayer(OGROSMLayer *poLyr)
606 : {
607 237 : m_poCurrentLayer = poLyr;
608 237 : }
609 :
610 0 : bool IsFeatureCountEnabled() const
611 : {
612 0 : return m_bIsFeatureCountEnabled;
613 : }
614 :
615 1930 : bool DoesAttributeNameLaundering() const
616 : {
617 1930 : return m_bAttributeNameLaundering;
618 : }
619 : };
620 :
621 : #endif /* ndef OGR_OSM_H_INCLUDED */
|