Skip to content

Commit ad1fcfb

Browse files
authored
Support osmium locations-on-ways format (#386)
1 parent 2b2ad07 commit ad1fcfb

9 files changed

Lines changed: 93 additions & 62 deletions

File tree

include/coordinates.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ struct LatpLon {
4949
int32_t latp;
5050
int32_t lon;
5151
};
52+
inline bool operator==(const LatpLon &a, const LatpLon &b) { return a.latp==b.latp && a.lon==b.lon; }
53+
namespace std {
54+
/// Hashing function so we can use an unordered_set
55+
template<>
56+
struct hash<LatpLon> {
57+
size_t operator()(const LatpLon &ll) const {
58+
return std::hash<int32_t>()(ll.latp) ^ std::hash<int32_t>()(ll.lon);
59+
}
60+
};
61+
}
62+
63+
typedef std::vector<LatpLon> LatpLonVec;
64+
typedef std::deque<LatpLon> LatpLonDeque;
5265

5366
double deg2rad(double deg);
5467
double rad2deg(double rad);

include/geom.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ typedef boost::geometry::index::rtree< IndexValue, boost::geometry::index::quadr
4343
typedef uint64_t NodeID;
4444
typedef uint64_t WayID;
4545

46-
typedef std::vector<NodeID> NodeVec;
4746
typedef std::vector<WayID> WayVec;
48-
typedef std::deque<NodeID> NodeDeque;
4947

5048
// Perform self-intersection aware simplification of geometry types
5149
Linestring simplify(Linestring const &ls, double max_distance);

include/osm_lua_processing.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class OsmLuaProcessing {
7575
void setNode(NodeID id, LatpLon node, const tag_map_t &tags);
7676

7777
/// \brief We are now processing a way
78-
void setWay(WayID wayId, NodeVec const &nodeVec, const tag_map_t &tags);
78+
void setWay(WayID wayId, LatpLonVec const &llVec, const tag_map_t &tags);
7979

8080
/** \brief We are now processing a relation
8181
* (note that we store relations as ways with artificial IDs, and that
@@ -194,7 +194,7 @@ class OsmLuaProcessing {
194194
/// Internal: clear current cached state
195195
inline void reset() {
196196
outputs.clear();
197-
nodeVecPtr = nullptr;
197+
llVecPtr = nullptr;
198198
outerWayVecPtr = nullptr;
199199
innerWayVecPtr = nullptr;
200200
linestringInited = false;
@@ -228,7 +228,7 @@ class OsmLuaProcessing {
228228
int relationSubscript = -1; // in processWay, position in the relation list
229229

230230
int32_t lon,latp; ///< Node coordinates
231-
NodeVec const *nodeVecPtr;
231+
LatpLonVec const *llVecPtr;
232232
WayVec const *outerWayVecPtr;
233233
WayVec const *innerWayVecPtr;
234234

include/osm_store.h

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -280,59 +280,59 @@ class RelationScanStore {
280280
class WayStore {
281281

282282
public:
283-
using nodeid_vector_t = std::vector<NodeID, mmap_allocator<NodeID>>;
284-
using element_t = std::pair<NodeID, nodeid_vector_t>;
283+
using latplon_vector_t = std::vector<LatpLon, mmap_allocator<LatpLon>>;
284+
using element_t = std::pair<WayID, latplon_vector_t>;
285285
using map_t = std::deque<element_t, mmap_allocator<element_t>>;
286286

287287
void reopen() {
288-
mNodeLists = std::make_unique<map_t>();
288+
mLatpLonLists = std::make_unique<map_t>();
289289
}
290290

291291
// @brief Lookup a node list
292292
// @param i OSM ID of a way
293293
// @return A node list
294294
// @exception NotFound
295-
nodeid_vector_t const &at(WayID wayid) const {
295+
latplon_vector_t const &at(WayID wayid) const {
296296
std::lock_guard<std::mutex> lock(mutex);
297297

298-
auto iter = std::lower_bound(mNodeLists->begin(), mNodeLists->end(), wayid, [](auto const &e, auto wayid) {
298+
auto iter = std::lower_bound(mLatpLonLists->begin(), mLatpLonLists->end(), wayid, [](auto const &e, auto wayid) {
299299
return e.first < wayid;
300300
});
301301

302-
if(iter == mNodeLists->end() || iter->first != wayid)
302+
if(iter == mLatpLonLists->end() || iter->first != wayid)
303303
throw std::out_of_range("Could not find way with id " + std::to_string(wayid));
304304

305305
return iter->second;
306306
}
307307

308308
// @brief Insert a node list.
309309
// @param i OSM ID of a way
310-
// @param nodeVec a node vector to be inserted
310+
// @param llVec a coordinate vector to be inserted
311311
// @invariant The OSM ID i must be larger than previously inserted OSM IDs of ways
312312
// (though unnecessarily for current impl, future impl may impose that)
313313
void insert_back(std::vector<element_t> &new_ways) {
314314
std::lock_guard<std::mutex> lock(mutex);
315-
auto i = mNodeLists->size();
316-
mNodeLists->resize(i + new_ways.size());
317-
std::copy(std::make_move_iterator(new_ways.begin()), std::make_move_iterator(new_ways.end()), mNodeLists->begin() + i);
315+
auto i = mLatpLonLists->size();
316+
mLatpLonLists->resize(i + new_ways.size());
317+
std::copy(std::make_move_iterator(new_ways.begin()), std::make_move_iterator(new_ways.end()), mLatpLonLists->begin() + i);
318318
}
319319

320320
// @brief Make the store empty
321321
void clear() {
322322
std::lock_guard<std::mutex> lock(mutex);
323-
mNodeLists->clear();
323+
mLatpLonLists->clear();
324324
}
325325

326326
std::size_t size() const {
327327
std::lock_guard<std::mutex> lock(mutex);
328-
return mNodeLists->size();
328+
return mLatpLonLists->size();
329329
}
330330

331331
void sort(unsigned int threadNum);
332332

333333
private:
334334
mutable std::mutex mutex;
335-
std::unique_ptr<map_t> mNodeLists;
335+
std::unique_ptr<map_t> mLatpLonLists;
336336
};
337337

338338
// relation store
@@ -624,7 +624,7 @@ class OSMStore
624624
// Relation -> MultiPolygon or MultiLinestring
625625
MultiPolygon wayListMultiPolygon(WayVec::const_iterator outerBegin, WayVec::const_iterator outerEnd, WayVec::const_iterator innerBegin, WayVec::const_iterator innerEnd) const;
626626
MultiLinestring wayListMultiLinestring(WayVec::const_iterator outerBegin, WayVec::const_iterator outerEnd) const;
627-
void mergeMultiPolygonWays(std::vector<NodeDeque> &results, std::map<WayID,bool> &done, WayVec::const_iterator itBegin, WayVec::const_iterator itEnd) const;
627+
void mergeMultiPolygonWays(std::vector<LatpLonDeque> &results, std::map<WayID,bool> &done, WayVec::const_iterator itBegin, WayVec::const_iterator itEnd) const;
628628

629629
///It is not really meaningful to try using a relation as a linestring. Not normally used but included
630630
///if Lua script attempts to do this.
@@ -640,7 +640,7 @@ class OSMStore
640640
}
641641

642642
template<class WayIt>
643-
Polygon nodeListPolygon(WayIt begin, WayIt end) const {
643+
Polygon llListPolygon(WayIt begin, WayIt end) const {
644644
Polygon poly;
645645
fillPoints(poly.outer(), begin, end);
646646
boost::geometry::correct(poly);
@@ -649,20 +649,19 @@ class OSMStore
649649

650650
// Way -> Linestring
651651
template<class WayIt>
652-
Linestring nodeListLinestring(WayIt begin, WayIt end) const {
652+
Linestring llListLinestring(WayIt begin, WayIt end) const {
653653
Linestring ls;
654654
fillPoints(ls, begin, end);
655655
return ls;
656656
}
657657

658658
private:
659659
// helper
660-
template<class PointRange, class NodeIt>
661-
void fillPoints(PointRange &points, NodeIt begin, NodeIt end) const {
660+
template<class PointRange, class LatpLonIt>
661+
void fillPoints(PointRange &points, LatpLonIt begin, LatpLonIt end) const {
662662
for (auto it = begin; it != end; ++it) {
663663
try {
664-
LatpLon ll = nodes_at(*it);
665-
boost::geometry::range::push_back(points, boost::geometry::make<Point>(ll.lon/10000000.0, ll.latp/10000000.0));
664+
boost::geometry::range::push_back(points, boost::geometry::make<Point>(it->lon/10000000.0, it->latp/10000000.0));
666665
} catch (std::out_of_range &err) {
667666
if (require_integrity) throw err;
668667
}

include/osmformat.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ message Way {
200200
optional Info info = 4;
201201

202202
repeated sint64 refs = 8 [packed = true]; // DELTA coded
203+
repeated sint64 lats = 9 [packed = true];
204+
repeated sint64 lons = 10 [packed = true];
203205
}
204206

205207
message Relation {

include/read_pbf.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ class PbfReader
4545
}
4646

4747
private:
48-
bool ReadBlock(std::istream &infile, OsmLuaProcessing &output, std::pair<std::size_t, std::size_t> progress, std::size_t datasize, std::unordered_set<std::string> const &nodeKeys, ReadPhase phase = ReadPhase::All);
48+
bool ReadBlock(std::istream &infile, OsmLuaProcessing &output, std::pair<std::size_t, std::size_t> progress, std::size_t datasize,
49+
std::unordered_set<std::string> const &nodeKeys, bool locationsOnWays, ReadPhase phase = ReadPhase::All);
4950
bool ReadNodes(OsmLuaProcessing &output, PrimitiveGroup &pg, PrimitiveBlock const &pb, const std::unordered_set<int> &nodeKeyPositions);
5051

51-
bool ReadWays(OsmLuaProcessing &output, PrimitiveGroup &pg, PrimitiveBlock const &pb);
52+
bool ReadWays(OsmLuaProcessing &output, PrimitiveGroup &pg, PrimitiveBlock const &pb, bool locationsOnWays);
5253
bool ScanRelations(OsmLuaProcessing &output, PrimitiveGroup &pg, PrimitiveBlock const &pb);
5354
bool ReadRelations(OsmLuaProcessing &output, PrimitiveGroup &pg, PrimitiveBlock const &pb);
5455

src/osm_lua_processing.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ double OsmLuaProcessing::Length() {
281281
const Linestring &OsmLuaProcessing::linestringCached() {
282282
if (!linestringInited) {
283283
linestringInited = true;
284-
linestringCache = osmStore.nodeListLinestring(nodeVecPtr->cbegin(),nodeVecPtr->cend());
284+
linestringCache = osmStore.llListLinestring(llVecPtr->cbegin(),llVecPtr->cend());
285285
}
286286
return linestringCache;
287287
}
@@ -297,7 +297,7 @@ const MultiLinestring &OsmLuaProcessing::multiLinestringCached() {
297297
const Polygon &OsmLuaProcessing::polygonCached() {
298298
if (!polygonInited) {
299299
polygonInited = true;
300-
polygonCache = osmStore.nodeListPolygon(nodeVecPtr->cbegin(), nodeVecPtr->cend());
300+
polygonCache = osmStore.llListPolygon(llVecPtr->cbegin(), llVecPtr->cend());
301301
}
302302
return polygonCache;
303303
}
@@ -561,13 +561,13 @@ void OsmLuaProcessing::setNode(NodeID id, LatpLon node, const tag_map_t &tags) {
561561
}
562562

563563
// We are now processing a way
564-
void OsmLuaProcessing::setWay(WayID wayId, NodeVec const &nodeVec, const tag_map_t &tags) {
564+
void OsmLuaProcessing::setWay(WayID wayId, LatpLonVec const &llVec, const tag_map_t &tags) {
565565
reset();
566566
osmID = (wayId & OSMID_MASK) | OSMID_WAY;
567567
originalOsmID = wayId;
568568
isWay = true;
569569
isRelation = false;
570-
nodeVecPtr = &nodeVec;
570+
llVecPtr = &llVec;
571571
outerWayVecPtr = nullptr;
572572
innerWayVecPtr = nullptr;
573573
linestringInited = polygonInited = multiPolygonInited = false;
@@ -579,7 +579,7 @@ void OsmLuaProcessing::setWay(WayID wayId, NodeVec const &nodeVec, const tag_map
579579
}
580580

581581
try {
582-
isClosed = nodeVecPtr->front()==nodeVecPtr->back();
582+
isClosed = llVecPtr->front()==llVecPtr->back();
583583

584584
} catch (std::out_of_range &err) {
585585
std::stringstream ss;
@@ -608,7 +608,7 @@ void OsmLuaProcessing::setWay(WayID wayId, NodeVec const &nodeVec, const tag_map
608608
// create a list of tiles this way passes through (tileSet)
609609
unordered_set<TileCoordinates> tileSet;
610610
try {
611-
insertIntermediateTiles(osmStore.nodeListLinestring(nodeVecPtr->cbegin(),nodeVecPtr->cend()), this->config.baseZoom, tileSet);
611+
insertIntermediateTiles(osmStore.llListLinestring(llVecPtr->cbegin(),llVecPtr->cend()), this->config.baseZoom, tileSet);
612612

613613
// then, for each tile, store the OutputObject for each layer
614614
bool polygonExists = false;
@@ -651,7 +651,7 @@ void OsmLuaProcessing::setRelation(int64_t relationId, WayVec const &outerWayVec
651651
isRelation = true;
652652
isClosed = isNativeMP;
653653

654-
nodeVecPtr = nullptr;
654+
llVecPtr = nullptr;
655655
outerWayVecPtr = &outerWayVec;
656656
innerWayVecPtr = &innerWayVec;
657657
currentTags = tags;

src/osm_store.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -270,12 +270,12 @@ void NodeStore::sort(unsigned int threadNum) {
270270
void WayStore::sort(unsigned int threadNum) {
271271
std::lock_guard<std::mutex> lock(mutex);
272272
boost::sort::block_indirect_sort(
273-
mNodeLists->begin(), mNodeLists->end(),
273+
mLatpLonLists->begin(), mLatpLonLists->end(),
274274
[](auto const &a, auto const &b) { return a.first < b.first; },
275275
threadNum);
276276
}
277277

278-
static inline bool isClosed(WayStore::nodeid_vector_t const &way) {
278+
static inline bool isClosed(WayStore::latplon_vector_t const &way) {
279279
return way.begin() == way.end();
280280
}
281281

@@ -345,8 +345,8 @@ MultiPolygon OSMStore::wayListMultiPolygon(WayVec::const_iterator outerBegin, Wa
345345
MultiPolygon mp;
346346
if (outerBegin == outerEnd) { return mp; } // no outers so quit
347347

348-
std::vector<NodeDeque> outers;
349-
std::vector<NodeDeque> inners;
348+
std::vector<LatpLonDeque> outers;
349+
std::vector<LatpLonDeque> inners;
350350
std::map<WayID,bool> done; // true=this way has already been added to outers/inners, don't reconsider
351351

352352
// merge constituent ways together
@@ -379,7 +379,7 @@ MultiLinestring OSMStore::wayListMultiLinestring(WayVec::const_iterator outerBeg
379379
MultiLinestring mls;
380380
if (outerBegin == outerEnd) { return mls; }
381381

382-
std::vector<NodeDeque> linestrings;
382+
std::vector<LatpLonDeque> linestrings;
383383
std::map<WayID,bool> done;
384384

385385
mergeMultiPolygonWays(linestrings, done, outerBegin, outerEnd);
@@ -399,11 +399,11 @@ MultiLinestring OSMStore::wayListMultiLinestring(WayVec::const_iterator outerBeg
399399
// - If no matches can be found, then one linestring is added (to 'attract' others)
400400
// - The process is rerun until no ways are left
401401
// There's quite a lot of copying going on here - could potentially be addressed
402-
void OSMStore::mergeMultiPolygonWays(std::vector<NodeDeque> &results, std::map<WayID,bool> &done, WayVec::const_iterator itBegin, WayVec::const_iterator itEnd) const {
402+
void OSMStore::mergeMultiPolygonWays(std::vector<LatpLonDeque> &results, std::map<WayID,bool> &done, WayVec::const_iterator itBegin, WayVec::const_iterator itEnd) const {
403403

404404
// Create maps of start/end nodes
405-
std::unordered_map<NodeID, std::vector<NodeID>> startNodes;
406-
std::unordered_map<NodeID, std::vector<NodeID>> endNodes;
405+
std::unordered_map<LatpLon, std::vector<WayID>> startNodes;
406+
std::unordered_map<LatpLon, std::vector<WayID>> endNodes;
407407
for (auto it = itBegin; it != itEnd; ++it) {
408408
if (done[*it]) { continue; }
409409
try {
@@ -422,16 +422,16 @@ void OSMStore::mergeMultiPolygonWays(std::vector<NodeDeque> &results, std::map<W
422422
}
423423
}
424424

425-
auto deleteFromWayList = [&](NodeID n, NodeID w, bool which) {
425+
auto deleteFromWayList = [&](LatpLon n, WayID w, bool which) {
426426
auto &nodemap = which ? startNodes : endNodes;
427-
std::vector<NodeID> &waylist = nodemap.find(n)->second;
427+
std::vector<WayID> &waylist = nodemap.find(n)->second;
428428
waylist.erase(std::remove(waylist.begin(), waylist.end(), w), waylist.end());
429429
if (waylist.empty()) { nodemap.erase(nodemap.find(n)); }
430430
};
431-
auto removeWay = [&](NodeID w) {
431+
auto removeWay = [&](WayID w) {
432432
auto const &way = ways.at(w);
433-
NodeID first = way.front();
434-
NodeID last = way.back();
433+
LatpLon first = way.front();
434+
LatpLon last = way.back();
435435
if (startNodes.find(first) != startNodes.end()) { deleteFromWayList(first, w, true ); }
436436
if (startNodes.find(last) != startNodes.end()) { deleteFromWayList(last, w, true ); }
437437
if (endNodes.find(first) != endNodes.end() ) { deleteFromWayList(first, w, false); }
@@ -446,8 +446,8 @@ void OSMStore::mergeMultiPolygonWays(std::vector<NodeDeque> &results, std::map<W
446446
for (auto rt = results.begin(); rt != results.end(); rt++) {
447447
bool working=true;
448448
do {
449-
NodeID rFirst = rt->front();
450-
NodeID rLast = rt->back();
449+
LatpLon rFirst = rt->front();
450+
LatpLon rLast = rt->back();
451451
if (rFirst==rLast) break;
452452
if (startNodes.find(rLast)!=startNodes.end()) {
453453
// append to the result
@@ -494,7 +494,7 @@ void OSMStore::mergeMultiPolygonWays(std::vector<NodeDeque> &results, std::map<W
494494
for (int i=0; i<=1; i++) {
495495
if (added>0) continue;
496496
for (auto nt : (i==0 ? startNodes : endNodes)) {
497-
NodeID w = nt.second.back();
497+
WayID w = nt.second.back();
498498
auto const &way = ways.at(w);
499499
results.emplace_back(way.begin(), way.end());
500500
added++;

0 commit comments

Comments
 (0)