Skip to content

Commit

Permalink
Use dynamic bbox to prevent clipping of edges passing tile border (#234)
Browse files Browse the repository at this point in the history
  • Loading branch information
kleunen authored May 5, 2021
1 parent 9afb9f1 commit 12b34fe
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 15 deletions.
1 change: 1 addition & 0 deletions include/coordinates.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ class TileBbox {

std::pair<int,int> scaleLatpLon(double latp, double lon) const;
Box getTileBox() const;
Box getExtendBox() const;
};

#endif //_COORDINATES_H
Expand Down
6 changes: 6 additions & 0 deletions src/coordinates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,9 @@ Box TileBbox::getTileBox() const {
return Box(geom::make<Point>(minLon+xmargin, minLatp+ymargin), geom::make<Point>(maxLon-xmargin, maxLatp-ymargin));
}

Box TileBbox::getExtendBox() const {
return Box(
geom::make<Point>( minLon-(maxLon-minLon)*2.0, minLatp-(maxLatp-minLatp)*(8191.0/8192.0)),
geom::make<Point>( maxLon+(maxLon-minLon)*(8191.0/8192.0), maxLatp+(maxLatp-minLatp)*2.0));
}

87 changes: 72 additions & 15 deletions src/output_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,29 +80,86 @@ Geometry buildWayGeometry(OSMStore &osmStore, OutputObject const &oo, const Tile

case OutputGeometryType::LINESTRING:
{
auto const &ls = osmStore.retrieve<mmap::linestring_t>(oo.handle);

MultiLinestring out;
geom::intersection(osmStore.retrieve<mmap::linestring_t>(oo.handle), bbox.clippingBox, out);
return 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;
}

case OutputGeometryType::POLYGON:
{
auto const &mp = osmStore.retrieve<mmap::multi_polygon_t>(oo.handle);

Polygon clippingPolygon;

geom::convert(bbox.clippingBox, clippingPolygon);
if (!geom::intersects(mp, clippingPolygon)) { return MultiPolygon(); }
if (geom::within(mp, clippingPolygon)) {
MultiPolygon out;
boost::geometry::assign(out, mp);
return out;
auto const &input = osmStore.retrieve<mmap::multi_polygon_t>(oo.handle);

Box box = bbox.clippingBox;

for(auto const &p: input) {
for(auto const &inner: p.inners) {
for(std::size_t i = 0; i < inner.size() - 1; ++i)
{
Point p1 = inner[i];
Point p2 = inner[i + 1];

if(geom::within(p1, bbox.clippingBox) != geom::within(p2, bbox.clippingBox)) {
box.min_corner() = Point(
std::min(box.min_corner().x(), std::min(p1.x(), p2.x())),
std::min(box.min_corner().y(), std::min(p1.y(), p2.y())));
box.max_corner() = Point(
std::max(box.max_corner().x(), std::max(p1.x(), p2.x())),
std::max(box.max_corner().y(), std::max(p1.y(), p2.y())));
}
}
}

for(std::size_t i = 0; i < p.outer.size() - 1; ++i) {
Point p1 = p.outer[i];
Point p2 = p.outer[i + 1];

if(geom::within(p1, bbox.clippingBox) != geom::within(p2, bbox.clippingBox)) {
box.min_corner() = Point(
std::min(box.min_corner().x(), std::min(p1.x(), p2.x())),
std::min(box.min_corner().y(), std::min(p1.y(), p2.y())));
box.max_corner() = Point(
std::max(box.max_corner().x(), std::max(p1.x(), p2.x())),
std::max(box.max_corner().y(), std::max(p1.y(), p2.y())));
}
}
}

Box extBox = bbox.getExtendBox();
box.min_corner() = Point(
std::max(box.min_corner().x(), extBox.min_corner().x()),
std::max(box.min_corner().y(), extBox.min_corner().y()));
box.max_corner() = Point(
std::min(box.max_corner().x(), extBox.max_corner().x()),
std::min(box.max_corner().y(), extBox.max_corner().y()));

Polygon clippingPolygon;
geom::convert(box, clippingPolygon);

try {
MultiPolygon out;
geom::intersection(mp, clippingPolygon, out);
return out;
MultiPolygon mp;
geom::intersection(input, clippingPolygon, mp);
return mp;
} catch (geom::overlay_invalid_input_exception &err) {
std::cout << "Couldn't clip polygon (self-intersection)" << std::endl;
return MultiPolygon(); // blank
Expand Down

0 comments on commit 12b34fe

Please sign in to comment.