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