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 26188 : bool operator()(const char *a, const char *b) const
36 : {
37 26188 : 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 62 : explicit OGROSMComputedAttribute(const char *pszName) : osName(pszName)
56 : {
57 62 : }
58 :
59 62 : 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 3040 : virtual OGRFeatureDefn *GetLayerDefn() override
137 : {
138 3040 : 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 GetExtent(OGREnvelope *psExtent, int bForce) override;
155 :
156 3 : virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
157 : int bForce) override
158 : {
159 3 : return OGRLayer::GetExtent(iGeomField, psExtent, bForce);
160 : }
161 :
162 : const OGREnvelope *GetSpatialFilterEnvelope();
163 :
164 : bool AddFeature(std::unique_ptr<OGRFeature> poFeature,
165 : bool bAttrFilterAlreadyEvaluated,
166 : bool *pbFilteredOut = nullptr,
167 : bool bCheckFeatureThreshold = true);
168 : void ForceResetReading();
169 :
170 : void AddField(const char *pszName, OGRFieldType eFieldType,
171 : OGRFieldSubType eSubType = OFSTNone);
172 : int GetFieldIndex(const char *pszName);
173 :
174 : bool HasOSMId() const
175 : {
176 : return m_bHasOSMId;
177 : }
178 :
179 155 : void SetHasOSMId(bool bIn)
180 : {
181 155 : m_bHasOSMId = bIn;
182 155 : }
183 :
184 32 : bool HasVersion() const
185 : {
186 32 : return m_bHasVersion;
187 : }
188 :
189 155 : void SetHasVersion(bool bIn)
190 : {
191 155 : m_bHasVersion = bIn;
192 155 : }
193 :
194 32 : bool HasTimestamp() const
195 : {
196 32 : return m_bHasTimestamp;
197 : }
198 :
199 155 : void SetHasTimestamp(bool bIn)
200 : {
201 155 : m_bHasTimestamp = bIn;
202 155 : }
203 :
204 32 : bool HasUID() const
205 : {
206 32 : return m_bHasUID;
207 : }
208 :
209 155 : void SetHasUID(bool bIn)
210 : {
211 155 : m_bHasUID = bIn;
212 155 : }
213 :
214 32 : bool HasUser() const
215 : {
216 32 : return m_bHasUser;
217 : }
218 :
219 155 : void SetHasUser(bool bIn)
220 : {
221 155 : m_bHasUser = bIn;
222 155 : }
223 :
224 32 : bool HasChangeset() const
225 : {
226 32 : return m_bHasChangeset;
227 : }
228 :
229 155 : void SetHasChangeset(bool bIn)
230 : {
231 155 : m_bHasChangeset = bIn;
232 155 : }
233 :
234 160 : bool HasOtherTags() const
235 : {
236 160 : return m_bHasOtherTags;
237 : }
238 :
239 2 : void SetHasOtherTags(bool bIn)
240 : {
241 2 : m_bHasOtherTags = bIn;
242 2 : }
243 :
244 160 : bool HasAllTags() const
245 : {
246 160 : return m_bHasAllTags;
247 : }
248 :
249 2 : void SetHasAllTags(bool bIn)
250 : {
251 2 : m_bHasAllTags = bIn;
252 2 : }
253 :
254 : void SetFieldsFromTags(OGRFeature *poFeature, GIntBig nID, bool bIsWayID,
255 : unsigned int nTags, const OSMTag *pasTags,
256 : const OSMInfo *psInfo);
257 :
258 192 : void SetDeclareInterest(bool bIn)
259 : {
260 192 : m_bUserInterested = bIn;
261 192 : }
262 :
263 4928 : bool IsUserInterested() const
264 : {
265 4928 : return m_bUserInterested;
266 : }
267 :
268 459 : int HasAttributeFilter() const
269 : {
270 459 : return m_poAttrQuery != nullptr;
271 : }
272 :
273 : int EvaluateAttributeFilter(OGRFeature *poFeature);
274 :
275 : void AddInsignificantKey(const char *pszK);
276 :
277 478 : int IsSignificantKey(const char *pszK) const
278 : {
279 478 : return aoSetInsignificantKeys.find(pszK) ==
280 956 : aoSetInsignificantKeys.end();
281 : }
282 :
283 : void AddIgnoreKey(const char *pszK);
284 : void AddWarnKey(const char *pszK);
285 :
286 : void AddComputedAttribute(const char *pszName, OGRFieldType eType,
287 : const char *pszSQL);
288 : };
289 :
290 : /************************************************************************/
291 : /* OGROSMDataSource */
292 : /************************************************************************/
293 :
294 : struct KeyDesc
295 : {
296 : char *pszK = nullptr;
297 : int nKeyIndex = 0;
298 : int nOccurrences = 0;
299 : std::vector<char *> apszValues{};
300 : //! map that is the reverse of apszValues
301 : std::map<const char *, int, OGROSMConstCharComp> anMapV{};
302 : };
303 :
304 : typedef struct
305 : {
306 : short bKIsIndex; /* whether we should use nKeyIndex or
307 : nOffsetInpabyNonRedundantKeys */
308 : short bVIsIndex; /* whether we should use nValueIndex or
309 : nOffsetInpabyNonRedundantValues */
310 :
311 : union
312 : {
313 : int nKeyIndex; /* index of OGROSMDataSource.asKeys */
314 : int nOffsetInpabyNonRedundantKeys; /* offset in
315 : OGROSMDataSource.pabyNonRedundantKeys
316 : */
317 : } uKey;
318 :
319 : union
320 : {
321 : int nValueIndex; /* index of KeyDesc.apszValues */
322 : int nOffsetInpabyNonRedundantValues; /* offset in
323 : OGROSMDataSource.pabyNonRedundantValues
324 : */
325 : } uVal;
326 : } IndexedKVP;
327 :
328 : typedef struct
329 : {
330 : GIntBig nOff;
331 :
332 : /* Note: only one of nth bucket pabyBitmap or panSectorSize must be free'd
333 : */
334 : union
335 : {
336 : GByte *pabyBitmap; /* array of BUCKET_BITMAP_SIZE bytes */
337 : GByte *panSectorSize; /* array of BUCKET_SECTOR_SIZE_ARRAY_SIZE bytes.
338 : Each values means (size in bytes - 8 ) / 2,
339 : minus 8. 252 means uncompressed */
340 : } u;
341 : } Bucket;
342 :
343 : typedef struct
344 : {
345 : int nLon;
346 : int nLat;
347 : } LonLat;
348 :
349 : struct WayFeaturePair
350 : {
351 : GIntBig nWayID = 0;
352 : /* point to a sub-array of OGROSMDataSource.anReqIds */
353 : GIntBig *panNodeRefs = nullptr;
354 : unsigned int nRefs = 0;
355 : unsigned int nTags = 0;
356 : IndexedKVP *pasTags = nullptr; /* point to a sub-array of
357 : OGROSMDataSource.pasAccumulatedTags */
358 : OSMInfo sInfo{};
359 : std::unique_ptr<OGRFeature> poFeature{};
360 : bool bIsArea = false;
361 : bool bAttrFilterAlreadyEvaluated = false;
362 : };
363 :
364 : #ifdef ENABLE_NODE_LOOKUP_BY_HASHING
365 : typedef struct
366 : {
367 : int nInd; /* values are indexes of panReqIds */
368 : int nNext; /* values are indexes of psCollisionBuckets, or -1 to stop the
369 : chain */
370 : } CollisionBucket;
371 : #endif
372 :
373 : class OGROSMDataSource final : public GDALDataset
374 : {
375 : friend class OGROSMLayer;
376 :
377 : std::vector<std::unique_ptr<OGROSMLayer>> m_apoLayers{};
378 :
379 : std::string m_osConfigFile{};
380 :
381 : OGREnvelope m_sExtent{};
382 : bool m_bExtentValid = false;
383 :
384 : // Starts off at -1 to indicate that we do not know.
385 : int m_bInterleavedReading = -1;
386 : OGROSMLayer *m_poCurrentLayer = nullptr;
387 :
388 : OSMContext *m_psParser = nullptr;
389 : bool m_bHasParsedFirstChunk = false;
390 : bool m_bStopParsing = false;
391 :
392 : sqlite3_vfs *m_pMyVFS = nullptr;
393 :
394 : sqlite3 *m_hDB = nullptr;
395 : sqlite3_stmt *m_hInsertNodeStmt = nullptr;
396 : sqlite3_stmt *m_hInsertWayStmt = nullptr;
397 : sqlite3_stmt **m_pahSelectNodeStmt = nullptr;
398 : sqlite3_stmt **m_pahSelectWayStmt = nullptr;
399 : sqlite3_stmt *m_hInsertPolygonsStandaloneStmt = nullptr;
400 : sqlite3_stmt *m_hDeletePolygonsStandaloneStmt = nullptr;
401 : sqlite3_stmt *m_hSelectPolygonsStandaloneStmt = nullptr;
402 : bool m_bHasRowInPolygonsStandalone = false;
403 :
404 : sqlite3 *m_hDBForComputedAttributes = nullptr;
405 :
406 : int m_nMaxSizeForInMemoryDBInMB = 0;
407 : bool m_bInMemoryTmpDB = false;
408 : bool m_bMustUnlink = true;
409 : CPLString m_osTmpDBName{};
410 :
411 : std::unordered_set<std::string> aoSetClosedWaysArePolygons{};
412 : int m_nMinSizeKeysInSetClosedWaysArePolygons = 0;
413 : int m_nMaxSizeKeysInSetClosedWaysArePolygons = 0;
414 :
415 : std::vector<LonLat> m_asLonLatCache{};
416 :
417 : std::array<const char *, 7> m_ignoredKeys = {{"area", "created_by",
418 : "converted_by", "note",
419 : "todo", "fixme", "FIXME"}};
420 :
421 : bool m_bReportAllNodes = false;
422 : bool m_bReportAllWays = false;
423 : bool m_bTagsAsHSTORE = true; // if false, as JSON
424 :
425 : bool m_bFeatureAdded = false;
426 :
427 : bool m_bInTransaction = false;
428 :
429 : bool m_bIndexPoints = true;
430 : bool m_bUsePointsIndex = true;
431 : bool m_bIndexWays = true;
432 : bool m_bUseWaysIndex = true;
433 :
434 : std::vector<bool> m_abSavedDeclaredInterest{};
435 : OGRLayer *m_poResultSetLayer = nullptr;
436 : bool m_bIndexPointsBackup = false;
437 : bool m_bUsePointsIndexBackup = false;
438 : bool m_bIndexWaysBackup = false;
439 : bool m_bUseWaysIndexBackup = false;
440 :
441 : bool m_bIsFeatureCountEnabled = false;
442 :
443 : bool m_bAttributeNameLaundering = true;
444 :
445 : std::vector<GByte> m_abyWayBuffer{};
446 :
447 : int m_nWaysProcessed = 0;
448 : int m_nRelationsProcessed = 0;
449 :
450 : bool m_bCustomIndexing = true;
451 : bool m_bCompressNodes = false;
452 :
453 : unsigned int m_nUnsortedReqIds = 0;
454 : GIntBig *m_panUnsortedReqIds = nullptr;
455 :
456 : unsigned int m_nReqIds = 0;
457 : GIntBig *m_panReqIds = nullptr;
458 :
459 : #ifdef ENABLE_NODE_LOOKUP_BY_HASHING
460 : bool m_bEnableHashedIndex = true;
461 : /* values >= 0 are indexes of panReqIds. */
462 : /* == -1 for unoccupied */
463 : /* < -1 are expressed as -nIndexToCollisionBuckets-2 where
464 : * nIndexToCollisionBuckets point to psCollisionBuckets */
465 : int *m_panHashedIndexes = nullptr;
466 : CollisionBucket *m_psCollisionBuckets = nullptr;
467 : bool m_bHashedIndexValid = false;
468 : #endif
469 :
470 : LonLat *m_pasLonLatArray = nullptr;
471 :
472 : IndexedKVP *m_pasAccumulatedTags =
473 : nullptr; /* points to content of pabyNonRedundantValues or
474 : aoMapIndexedKeys */
475 : int m_nAccumulatedTags = 0;
476 : unsigned int MAX_INDEXED_KEYS = 0;
477 : GByte *pabyNonRedundantKeys = nullptr;
478 : int nNonRedundantKeysLen = 0;
479 : unsigned int MAX_INDEXED_VALUES_PER_KEY = 0;
480 : GByte *pabyNonRedundantValues = nullptr;
481 : int nNonRedundantValuesLen = 0;
482 : std::vector<WayFeaturePair> m_asWayFeaturePairs{};
483 :
484 : std::vector<KeyDesc *> m_apsKeys{};
485 : std::map<const char *, KeyDesc *, OGROSMConstCharComp>
486 : m_aoMapIndexedKeys{}; /* map that is the reverse of asKeys */
487 :
488 : CPLString m_osNodesFilename{};
489 : bool m_bInMemoryNodesFile = false;
490 : bool m_bMustUnlinkNodesFile = true;
491 : GIntBig m_nNodesFileSize = 0;
492 : VSILFILE *m_fpNodes = nullptr;
493 :
494 : GIntBig m_nPrevNodeId = -INT_MAX;
495 : int m_nBucketOld = -1;
496 : int m_nOffInBucketReducedOld = -1;
497 : GByte *m_pabySector = nullptr;
498 : std::map<int, Bucket> m_oMapBuckets{};
499 : Bucket *GetBucket(int nBucketId);
500 :
501 : bool m_bNeedsToSaveWayInfo = false;
502 :
503 : static const GIntBig FILESIZE_NOT_INIT = -2;
504 : static const GIntBig FILESIZE_INVALID = -1;
505 : GIntBig m_nFileSize = FILESIZE_NOT_INIT;
506 :
507 : void CompressWay(bool bIsArea, unsigned int nTags,
508 : const IndexedKVP *pasTags, int nPoints,
509 : const LonLat *pasLonLatPairs, const OSMInfo *psInfo,
510 : std::vector<GByte> &abyCompressedWay);
511 : void UncompressWay(int nBytes, const GByte *pabyCompressedWay,
512 : bool *pbIsArea, std::vector<LonLat> &asCoords,
513 : unsigned int *pnTags, OSMTag *pasTags, OSMInfo *psInfo);
514 :
515 : bool ParseConf(CSLConstList papszOpenOptions);
516 : bool CreateTempDB();
517 : bool SetDBOptions();
518 : void SetCacheSize();
519 : bool CreatePreparedStatements();
520 : void CloseDB();
521 :
522 : bool IndexPoint(const OSMNode *psNode);
523 : bool IndexPointSQLite(const OSMNode *psNode);
524 : bool FlushCurrentSector();
525 : bool FlushCurrentSectorCompressedCase();
526 : bool FlushCurrentSectorNonCompressedCase();
527 : bool IndexPointCustom(const OSMNode *psNode);
528 :
529 : void IndexWay(GIntBig nWayID, bool bIsArea, unsigned int nTags,
530 : const IndexedKVP *pasTags, const LonLat *pasLonLatPairs,
531 : int nPairs, const OSMInfo *psInfo);
532 :
533 : bool StartTransactionCacheDB();
534 : bool CommitTransactionCacheDB();
535 :
536 : int FindNode(GIntBig nID);
537 : void ProcessWaysBatch();
538 :
539 : void ProcessPolygonsStandalone();
540 :
541 : void LookupNodes();
542 : void LookupNodesSQLite();
543 : void LookupNodesCustom();
544 : void LookupNodesCustomCompressedCase();
545 : void LookupNodesCustomNonCompressedCase();
546 :
547 : unsigned int
548 : LookupWays(std::map<GIntBig, std::pair<int, void *>> &aoMapWays,
549 : const OSMRelation *psRelation);
550 :
551 : OGRGeometry *BuildMultiPolygon(const OSMRelation *psRelation,
552 : unsigned int *pnTags, OSMTag *pasTags);
553 : OGRGeometry *BuildGeometryCollection(const OSMRelation *psRelation,
554 : bool bMultiLineString);
555 :
556 : bool TransferToDiskIfNecesserary();
557 :
558 : Bucket *AllocBucket(int iBucket);
559 :
560 : void AddComputedAttributes(
561 : int iCurLayer, const std::vector<OGROSMComputedAttribute> &oAttributes);
562 : bool IsClosedWayTaggedAsPolygon(unsigned int nTags, const OSMTag *pasTags);
563 :
564 : OGROSMDataSource(const OGROSMDataSource &) = delete;
565 : OGROSMDataSource &operator=(const OGROSMDataSource &) = delete;
566 :
567 : public:
568 : OGROSMDataSource();
569 : virtual ~OGROSMDataSource();
570 :
571 699 : virtual int GetLayerCount() override
572 : {
573 699 : return static_cast<int>(m_apoLayers.size());
574 : }
575 :
576 : virtual OGRLayer *GetLayer(int) override;
577 :
578 : virtual int TestCapability(const char *) override;
579 :
580 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
581 : OGRGeometry *poSpatialFilter,
582 : const char *pszDialect) override;
583 : virtual void ReleaseResultSet(OGRLayer *poLayer) override;
584 :
585 : virtual void ResetReading() override;
586 : virtual OGRFeature *GetNextFeature(OGRLayer **ppoBelongingLayer,
587 : double *pdfProgressPct,
588 : GDALProgressFunc pfnProgress,
589 : void *pProgressData) override;
590 :
591 : int Open(const char *pszFilename, CSLConstList papszOpenOptions);
592 :
593 : int MyResetReading();
594 : bool ParseNextChunk(int nIdxLayer, GDALProgressFunc pfnProgress,
595 : void *pProgressData);
596 : OGRErr GetExtent(OGREnvelope *psExtent);
597 : int IsInterleavedReading();
598 :
599 : void NotifyNodes(unsigned int nNodes, const OSMNode *pasNodes);
600 : void NotifyWay(const OSMWay *psWay);
601 : void NotifyRelation(const OSMRelation *psRelation);
602 : void NotifyBounds(double dfXMin, double dfYMin, double dfXMax,
603 : double dfYMax);
604 :
605 312 : OGROSMLayer *GetCurrentLayer()
606 : {
607 312 : return m_poCurrentLayer;
608 : }
609 :
610 237 : void SetCurrentLayer(OGROSMLayer *poLyr)
611 : {
612 237 : m_poCurrentLayer = poLyr;
613 237 : }
614 :
615 0 : bool IsFeatureCountEnabled() const
616 : {
617 0 : return m_bIsFeatureCountEnabled;
618 : }
619 :
620 1618 : bool DoesAttributeNameLaundering() const
621 : {
622 1618 : return m_bAttributeNameLaundering;
623 : }
624 : };
625 :
626 : #endif /* ndef OGR_OSM_H_INCLUDED */
|