Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions include/coordinates.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ class TileCoordinates_ {
return false;
return y == obj.y;
}

bool operator <(const TileCoordinates_ & obj) const
{
if (x != obj.x)
return x < obj.x;

return y < obj.y;
}

};
struct TileCoordinatesCompare {
bool operator()(const class TileCoordinates_& a, const class TileCoordinates_& b) const {
Expand Down
6 changes: 5 additions & 1 deletion include/tile_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ class TileDataSource {
TileCoordinates coordinates
);

Geometry buildWayGeometry(OutputGeometryType const geomType, NodeID const objectID, const TileBbox &bbox) const;
Geometry buildWayGeometry(OutputGeometryType const geomType, NodeID const objectID, const TileBbox &bbox);
LatpLon buildNodeGeometry(OutputGeometryType const geomType, NodeID const objectID, const TileBbox &bbox) const;

void open() {
Expand Down Expand Up @@ -427,6 +427,10 @@ class TileDataSource {


private:
std::vector<std::map<std::tuple<uint16_t, TileCoordinates, NodeID>, std::shared_ptr<MultiPolygon>>> clipCache;
std::vector<std::mutex> clipCacheMutex;
std::vector<size_t> clipCacheSize;
void cacheClippedGeometry(const TileBbox& box, const NodeID objectID, const MultiPolygon& mp);
};

TileCoordinatesSet getTilesAtZoom(
Expand Down
69 changes: 66 additions & 3 deletions src/tile_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ TileDataSource::TileDataSource(size_t threadNum, unsigned int baseZoom, bool inc
objectsMutex(threadNum * 4),
objects(CLUSTER_ZOOM_AREA),
objectsWithIds(CLUSTER_ZOOM_AREA),
baseZoom(baseZoom)
baseZoom(baseZoom),
clipCache(threadNum * 4),
clipCacheMutex(threadNum * 4),
clipCacheSize(threadNum * 4)
{
}

Expand Down Expand Up @@ -97,6 +100,10 @@ void TileDataSource::collectObjectsForTile(
TileCoordinate z6x = dstIndex.x / (1 << (zoom - CLUSTER_ZOOM));
TileCoordinate z6y = dstIndex.y / (1 << (zoom - CLUSTER_ZOOM));

if (z6x >= 64 || z6y >= 64) {
if (verbose) std::cerr << "collectObjectsForTile: invalid tile z" << zoom << "/" << dstIndex.x << "/" << dstIndex.y << std::endl;
return;
}
iStart = z6x * CLUSTER_ZOOM_WIDTH + z6y;
iEnd = iStart + 1;
}
Expand Down Expand Up @@ -129,7 +136,7 @@ void TileDataSource::collectLargeObjectsForTile(

// Build node and way geometries
Geometry TileDataSource::buildWayGeometry(OutputGeometryType const geomType,
NodeID const objectID, const TileBbox &bbox) const {
NodeID const objectID, const TileBbox &bbox) {
switch(geomType) {
case POINT_: {
auto p = retrieve_point(objectID);
Expand Down Expand Up @@ -175,7 +182,35 @@ Geometry TileDataSource::buildWayGeometry(OutputGeometryType const geomType,
}

case POLYGON_: {
auto const &input = retrieve_multi_polygon(objectID);
// Look for a previously clipped version at z-1, z-2, ...
std::shared_ptr<MultiPolygon> cachedClip;
{
size_t zoom = bbox.zoom;
size_t x = bbox.index.x;
size_t y = bbox.index.y;
std::lock_guard<std::mutex> lock(clipCacheMutex[objectID % clipCacheMutex.size()]);
while (zoom > 0) {
zoom--;
x /= 2;
y /= 2;
const auto& cache = clipCache[objectID % clipCache.size()];
const auto& rv = cache.find(std::make_tuple(zoom, TileCoordinates(x, y), objectID));
if (rv != cache.end()) {
cachedClip = rv->second;
break;
}
}
}

MultiPolygon uncached;

if (cachedClip == nullptr) {
// The cached multipolygon uses a non-standard allocator, so copy it
const auto &input = retrieve_multi_polygon(objectID);
boost::geometry::assign(uncached, input);
}

const auto &input = cachedClip == nullptr ? uncached : *cachedClip;

Box box = bbox.clippingBox;

Expand Down Expand Up @@ -235,11 +270,13 @@ Geometry TileDataSource::buildWayGeometry(OutputGeometryType const geomType,
MultiPolygon output;
geom::intersection(input, box, output);
geom::correct(output);
cacheClippedGeometry(bbox, objectID, output);
return output;
} else {
// occasionally also wrong_topological_dimension, disconnected_interior
}
}
cacheClippedGeometry(bbox, objectID, mp);
return mp;
}

Expand All @@ -248,6 +285,32 @@ Geometry TileDataSource::buildWayGeometry(OutputGeometryType const geomType,
}
}

void TileDataSource::cacheClippedGeometry(const TileBbox& box, const NodeID objectID, const MultiPolygon& mp) {
// The point of caching is to reuse the clip, so caching at the terminal zoom is
// pointless.
if (box.zoom == baseZoom)
return;

std::shared_ptr<MultiPolygon> copy = std::make_shared<MultiPolygon>();
boost::geometry::assign(*copy, mp);

size_t index = objectID % clipCacheMutex.size();
std::lock_guard<std::mutex> lock(clipCacheMutex[index]);
auto& cache = clipCache[index];
// In a perfect world, this would be an LRU cache and we'd evict old entries
// that are unlikely to be used again.
//
// But for now, just reset the cache every so often to prevent it growing
// without bound.
clipCacheSize[index]++;
if (clipCacheSize[index] > 5000) {
clipCacheSize[index] = 0;
cache.clear();
}

cache[std::make_tuple(box.zoom, box.index, objectID)] = copy;
}

LatpLon TileDataSource::buildNodeGeometry(OutputGeometryType const geomType,
NodeID const objectID, const TileBbox &bbox) const {
switch(geomType) {
Expand Down
4 changes: 2 additions & 2 deletions src/tile_worker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ void MergeIntersecting(MultiPolygon &input, MultiPolygon &to_merge) {

template <typename T>
void CheckNextObjectAndMerge(
const TileDataSource* source,
TileDataSource* source,
OutputObjectsConstIt& jt,
OutputObjectsConstIt ooSameLayerEnd,
const TileBbox& bbox,
Expand Down Expand Up @@ -147,7 +147,7 @@ void RemoveInnersBelowSize(MultiPolygon &g, double filterArea) {
}

void ProcessObjects(
const TileDataSource* source,
TileDataSource* source,
const AttributeStore& attributeStore,
OutputObjectsConstIt ooSameLayerBegin,
OutputObjectsConstIt ooSameLayerEnd,
Expand Down