forked from systemed/tilemaker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathosm_mem_tiles.cpp
More file actions
134 lines (108 loc) · 3.52 KB
/
osm_mem_tiles.cpp
File metadata and controls
134 lines (108 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "osm_mem_tiles.h"
#include "node_store.h"
#include "way_store.h"
using namespace std;
thread_local GeometryCache<Linestring> linestringCache;
OsmMemTiles::OsmMemTiles(
size_t threadNum,
uint indexZoom,
bool includeID,
const NodeStore& nodeStore,
const WayStore& wayStore
)
: TileDataSource(threadNum, indexZoom, includeID),
nodeStore(nodeStore),
wayStore(wayStore)
{
}
LatpLon OsmMemTiles::buildNodeGeometry(
NodeID const objectID,
const TileBbox &bbox
) const {
if (objectID < OSM_THRESHOLD) {
return TileDataSource::buildNodeGeometry(objectID, bbox);
}
if (IS_NODE(objectID))
return nodeStore.at(OSM_ID(objectID));
if (IS_WAY(objectID)) {
Linestring& ls = getOrBuildLinestring(objectID);
Point centroid;
Polygon p;
geom::assign_points(p, ls);
geom::centroid(p, centroid);
return LatpLon{(int32_t)(centroid.y()*10000000.0), (int32_t)(centroid.x()*10000000.0)};
}
throw std::runtime_error("OsmMemTiles::buildNodeGeometry: unsupported objectID");
}
Geometry OsmMemTiles::buildWayGeometry(
const OutputGeometryType geomType,
const NodeID objectID,
const TileBbox &bbox
) {
if (objectID < OSM_THRESHOLD || (geomType == POLYGON_ && IS_WAY(objectID))) {
return TileDataSource::buildWayGeometry(geomType, objectID, bbox);
}
if (geomType == LINESTRING_ && IS_WAY(objectID)) {
Linestring& ls = getOrBuildLinestring(objectID);
MultiLinestring out;
if(ls.empty())
return out;
Linestring current_ls;
geom::append(current_ls, ls[0]);
for(size_t i = 1; i < ls.size(); ++i) {
if(!geom::intersects(Linestring({ ls[i-1], ls[i] }), bbox.clippingBox)) {
if(current_ls.size() > 1)
out.push_back(std::move(current_ls));
current_ls.clear();
}
geom::append(current_ls, ls[i]);
}
if(current_ls.size() > 1)
out.push_back(std::move(current_ls));
MultiLinestring result;
geom::intersection(out, bbox.getExtendBox(), result);
return result;
}
throw std::runtime_error("buildWayGeometry: unexpected objectID: " + std::to_string(objectID));
}
void OsmMemTiles::populateLinestring(Linestring& ls, NodeID objectID) const {
std::vector<LatpLon> nodes = wayStore.at(OSM_ID(objectID));
for (const LatpLon& node : nodes) {
boost::geometry::range::push_back(ls, boost::geometry::make<Point>(node.lon/10000000.0, node.latp/10000000.0));
}
}
Linestring& OsmMemTiles::getOrBuildLinestring(NodeID objectID) const {
// Note: this function returns a reference, not a shared_ptr.
//
// This is safe, because this function is the only thing that can
// create/destroy entries in the cache, and the cache is thread-local.
Linestring* cachedEntry = linestringCache.get(objectID);
if (cachedEntry != nullptr)
return *cachedEntry;
std::shared_ptr<Linestring> rv = std::make_shared<Linestring>();
Linestring& ls = *rv;
populateLinestring(ls, objectID);
linestringCache.add(objectID, rv);
return *rv;
}
void OsmMemTiles::populateMultiPolygon(MultiPolygon& dst, NodeID objectID) {
if (objectID < OSM_THRESHOLD)
return TileDataSource::populateMultiPolygon(dst, objectID);
// We don't cache the linestrings used for polygons. Polygons from ways seem
// to be dominated by polygons with few points that only span a basezoom tile,
// e.g. building outlines.
//
// There are some exceptions, but some rough measurements showed caching
// hurt overall throughput.
Linestring ls;
populateLinestring(ls, objectID);
Polygon p;
geom::assign_points(p, ls);
dst.push_back(p);
}
void OsmMemTiles::Clear() {
for (auto& entry : objects)
entry.clear();
for (auto& entry : objectsWithIds)
entry.clear();
}