Skip to content

Commit

Permalink
Prune polygon to area within tile bounding box
Browse files Browse the repository at this point in the history
  • Loading branch information
kleunen committed May 1, 2021
1 parent b9ce0c7 commit 18fab34
Showing 1 changed file with 73 additions and 9 deletions.
82 changes: 73 additions & 9 deletions src/output_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,11 @@ Geometry buildWayGeometry(OSMStore &osmStore, OutputObject const &oo, const Tile

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

MultiLinestring out;
auto const &ls = osmStore.retrieve<mmap::linestring_t>(oo.handle);

if(ls.empty())
return out;

Expand All @@ -95,7 +97,16 @@ Geometry buildWayGeometry(OSMStore &osmStore, OutputObject const &oo, const Tile
out.push_back(std::move(current_ls));
current_ls.clear();
}

geom::append(current_ls, ls[i]);

// Limit the extend of the linestring
if(current_ls.size() == linestring_ext_limit) {
out.push_back(std::move(current_ls));
current_ls.clear();
geom::append(current_ls, ls[i]);
}

}

if(current_ls.size() > 1)
Expand All @@ -109,23 +120,76 @@ Geometry buildWayGeometry(OSMStore &osmStore, OutputObject const &oo, const Tile
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;

MultiPolygon out;
for(auto const &p: mp) {
Polygon newp;
if(geom::within(p.outer, clippingPolygon)) {
boost::geometry::assign(newp, p);
out.push_back(newp);
continue;
}

for(auto const &inner: p.inners) {
if(!inner.empty()) {
Ring ring;
geom::append(ring, inner[0]);

for(std::size_t i = 1; i < inner.size(); ++i) {
if(geom::within(inner[i], bbox.clippingBox)) {
geom::append(ring, inner[i]);
continue;
}

std::size_t next_i = (i + 1) % inner.size();
if(geom::intersects(Linestring({ ring[i-1], inner[next_i] }), bbox.clippingBox)) {
geom::append(ring, inner[i]);
}
}

if(ring.size() >= 3) {
newp.inners().resize(newp.inners().size() + 1);
boost::geometry::assign(newp.inners().back(), ring);
}
}
}

Ring outer_ring;
geom::append(outer_ring, p.outer[0]);

for(std::size_t i = 1; i < p.outer.size(); ++i) {
if(geom::within(p.outer[i], bbox.clippingBox)) {
geom::append(outer_ring, p.outer[i]);
continue;
}

std::size_t next_i = (i + 1) % p.outer.size();
Linestring ls({ outer_ring[i-1], p.outer[next_i] });

bool intersects = geom::intersects(ls, bbox.clippingBox);
for(auto const &inner: newp.inners()) {
intersects |= geom::intersects(ls, inner);
}

if(intersects) {
geom::append(outer_ring, p.outer[i]);
}
}

boost::geometry::assign(newp.outer(), outer_ring);
out.push_back(newp);
}

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

default:
Expand Down

0 comments on commit 18fab34

Please sign in to comment.