Skip to content

Commit a5f5d74

Browse files
authored
Speed up runtime by reducing allocation churn in tile generation (#902)
1 parent fff912e commit a5f5d74

20 files changed

Lines changed: 281 additions & 89 deletions

include/coordinates_geom.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ class TileBbox {
2323
TileBbox(TileCoordinates i, uint z, bool h, bool e);
2424

2525
std::pair<int,int> scaleLatpLon(double latp, double lon) const;
26-
std::vector<Point> scaleRing(Ring const &src) const;
26+
void scaleRing(Ring &dst, Ring const &src) const;
27+
Ring scaleRing(Ring const &src) const;
28+
void scaleGeometry(MultiPolygon &dst, MultiPolygon const &src) const;
2729
MultiPolygon scaleGeometry(MultiPolygon const &src) const;
2830
std::pair<double, double> floorLatpLon(double latp, double lon) const;
2931

include/geometry/correct.hpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* ----------------------------------------------------------------------------
1111
*/
1212

13+
#include <utility>
1314
#include <vector>
1415
#include <boost/geometry.hpp>
1516
#include <boost/geometry/geometries/point_xy.hpp>
@@ -25,7 +26,7 @@ namespace impl {
2526
template<typename C, typename T>
2627
static inline void result_combine(C &result, T &&new_element)
2728
{
28-
result.push_back(new_element);
29+
result.push_back(std::forward<T>(new_element));
2930

3031
for(std::size_t i = 0; i < result.size() - 1; ) {
3132
if(!boost::geometry::intersects(result[i], result.back())) {
@@ -96,6 +97,8 @@ static inline void dissolve_find_intersections(
9697
if(ring.empty()) return;
9798

9899
boost::geometry::index::rtree<std::pair< boost::geometry::model::segment<point_t>, std::size_t >, boost::geometry::index::quadratic<16>> index;
100+
std::vector<point_t> output;
101+
output.reserve(2);
99102

100103
// Generate all by-pass intersections in the graph
101104
// Generate a list of all by-pass intersections
@@ -112,7 +115,7 @@ static inline void dissolve_find_intersections(
112115
auto const &line_2 = iter.first;
113116
auto j = iter.second;
114117

115-
std::vector<point_t> output;
118+
output.clear();
116119
boost::geometry::intersection(line_1, line_2, output);
117120

118121
for(auto const &p: output) {
@@ -281,9 +284,11 @@ static inline std::vector<ring_t> correct(ring_t const &ring, boost::geometry::o
281284
dissolve_find_intersections(new_ring, pseudo_vertices, start_keys);
282285

283286
if(start_keys.empty()) {
284-
if(std::abs(boost::geometry::area(new_ring)) > remove_spike_min_area)
285-
return { new_ring };
286-
else
287+
if(std::abs(boost::geometry::area(new_ring)) > remove_spike_min_area) {
288+
std::vector<ring_t> result;
289+
result.push_back(std::move(new_ring));
290+
return result;
291+
} else
287292
return { };
288293
}
289294

include/osm_lua_processing.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ class OsmLuaProcessing {
276276
const inline Point getPoint() {
277277
return Point(lon/10000000.0,latp/10000000.0);
278278
}
279+
280+
double projectedPolygonArea(const Polygon &p);
279281

280282
OSMStore &osmStore; // global OSM store
281283

@@ -310,6 +312,7 @@ class OsmLuaProcessing {
310312
bool multiLinestringInited;
311313
MultiPolygon multiPolygonCache;
312314
bool multiPolygonInited;
315+
geom::model::polygon<DegPoint> areaPolygonCache;
313316

314317
NodeID lastStoredGeometryId;
315318
OutputGeometryType lastStoredGeometryType;

include/osm_store.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ class OSMStore
332332
template<class WayIt>
333333
Polygon llListPolygon(WayIt begin, WayIt end) const {
334334
Polygon poly;
335+
poly.outer().reserve(end - begin);
335336
fillPoints(poly.outer(), begin, end);
336337
boost::geometry::correct(poly);
337338
return poly;
@@ -341,6 +342,7 @@ class OSMStore
341342
template<class WayIt>
342343
Linestring llListLinestring(WayIt begin, WayIt end) const {
343344
Linestring ls;
345+
ls.reserve(end - begin);
344346
fillPoints(ls, begin, end);
345347
return ls;
346348
}

include/sharded_way_store.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class ShardedWayStore : public WayStore {
1414
void reopen() override;
1515
void batchStart() override;
1616
std::vector<LatpLon> at(WayID wayid) const override;
17+
void at(WayID wayid, std::vector<LatpLon>& output) const override;
1718
bool requiresNodes() const override;
1819
void insertLatpLons(std::vector<WayStore::ll_element_t> &newWays) override;
1920
void insertNodes(const std::vector<std::pair<WayID, std::vector<NodeID>>>& newWays) override;

include/sorted_way_store.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class SortedWayStore: public WayStore {
8888
void reopen() override;
8989
void batchStart() override;
9090
std::vector<LatpLon> at(WayID wayid) const override;
91+
void at(WayID wayid, std::vector<LatpLon>& output) const override;
9192
bool requiresNodes() const override { return true; }
9293
void insertLatpLons(std::vector<WayStore::ll_element_t> &newWays) override;
9394
void insertNodes(const std::vector<std::pair<WayID, std::vector<NodeID>>>& newWays) override;
@@ -107,6 +108,7 @@ class SortedWayStore: public WayStore {
107108
);
108109

109110
static std::vector<NodeID> decodeWay(uint16_t flags, const uint8_t* input);
111+
static void decodeWay(uint16_t flags, const uint8_t* input, std::vector<NodeID>& output);
110112

111113
private:
112114
bool compressWays;

include/tile_data.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ inline OutputObjectID outputObjectWithId<OutputObjectXYID>(const OutputObjectXYI
114114

115115
template<typename OO> void collectLowZoomObjectsForTile(
116116
const unsigned int& indexZoom,
117-
typename std::vector<std::vector<OO>> objects,
117+
const typename std::vector<std::vector<OO>>& objects,
118118
unsigned int zoom,
119119
const TileCoordinates& dstIndex,
120120
std::vector<OutputObjectID>& output

include/way_store.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class WayStore {
1515
// meaningful for SortedWayStore
1616
virtual void batchStart() = 0;
1717
virtual std::vector<LatpLon> at(WayID wayid) const = 0;
18+
virtual void at(WayID wayid, std::vector<LatpLon>& output) const = 0;
1819
virtual bool requiresNodes() const = 0;
1920
virtual void insertLatpLons(std::vector<ll_element_t>& newWays) = 0;
2021
virtual void insertNodes(const std::vector<std::pair<WayID, std::vector<NodeID>>>& newWays) = 0;

include/way_stores.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class BinarySearchWayStore: public WayStore {
1515
void reopen() override;
1616
void batchStart() override {}
1717
std::vector<LatpLon> at(WayID wayid) const override;
18+
void at(WayID wayid, std::vector<LatpLon>& output) const override;
1819
bool requiresNodes() const override { return false; }
1920
void insertLatpLons(std::vector<WayStore::ll_element_t> &newWays) override;
2021
void insertNodes(const std::vector<std::pair<WayID, std::vector<NodeID>>>& newWays) override;

src/coordinates_geom.cpp

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ pair<int,int> TileBbox::scaleLatpLon(double latp, double lon) const {
3333

3434
// Scaling with naive self-intersection check - if we've added the new point
3535
// within the last 5 points, then backtrack to the last time we added it
36-
std::vector<Point> TileBbox::scaleRing(Ring const &src) const {
37-
std::vector<Point> points;
36+
void TileBbox::scaleRing(Ring &points, Ring const &src) const {
37+
points.clear();
3838
points.reserve(src.size());
39-
for(auto &i: src) {
39+
for(auto const &i: src) {
4040
auto scaled = scaleLatpLon(i.y(), i.x()); // -> .first is x, .second is y
4141
bool found = false;
4242
for (size_t j=1; j<5; j++) {
@@ -48,36 +48,46 @@ std::vector<Point> TileBbox::scaleRing(Ring const &src) const {
4848
}
4949
if (!found) points.push_back(Point(scaled.first,scaled.second));
5050
}
51+
}
52+
53+
Ring TileBbox::scaleRing(Ring const &src) const {
54+
Ring points;
55+
scaleRing(points, src);
5156
return points;
5257
}
5358

54-
MultiPolygon TileBbox::scaleGeometry(MultiPolygon const &src) const {
55-
MultiPolygon dst;
56-
for(auto poly: src) {
57-
Polygon p;
59+
void TileBbox::scaleGeometry(MultiPolygon &dst, MultiPolygon const &src) const {
60+
if (dst.size() < src.size())
61+
dst.resize(src.size());
62+
63+
size_t polygonCount = 0;
64+
for(auto const &poly: src) {
65+
Polygon &p = dst[polygonCount];
5866

5967
// Copy the outer ring
60-
std::vector<Point> points = scaleRing(poly.outer());
61-
if (points.size()<4) continue;
62-
Ring outer;
63-
geom::append(outer,points);
64-
geom::append(p,outer);
68+
scaleRing(p.outer(), poly.outer());
69+
if (p.outer().size()<4)
70+
continue;
6571

6672
// Copy the inner rings
67-
int num_rings = 0;
68-
for(auto &r: poly.inners()) {
69-
points = scaleRing(r);
70-
if (points.size()<4) continue;
71-
Ring inner;
72-
geom::append(inner,points);
73-
num_rings++;
74-
geom::interior_rings(p).resize(num_rings);
75-
geom::append(p, inner, num_rings-1);
73+
if (p.inners().size() < poly.inners().size())
74+
p.inners().resize(poly.inners().size());
75+
size_t innerCount = 0;
76+
for(auto const &r: poly.inners()) {
77+
Ring &points = p.inners()[innerCount];
78+
scaleRing(points, r);
79+
if (points.size()>=4)
80+
innerCount++;
7681
}
77-
78-
// Add to multipolygon
79-
dst.push_back(p);
82+
p.inners().resize(innerCount);
83+
polygonCount++;
8084
}
85+
dst.resize(polygonCount);
86+
}
87+
88+
MultiPolygon TileBbox::scaleGeometry(MultiPolygon const &src) const {
89+
MultiPolygon dst;
90+
scaleGeometry(dst, src);
8191
return dst;
8292
}
8393

0 commit comments

Comments
 (0)