diff --git a/src/output_object.cpp b/src/output_object.cpp index e70f87a2..21ff9f5e 100644 --- a/src/output_object.cpp +++ b/src/output_object.cpp @@ -108,12 +108,17 @@ Geometry buildWayGeometry(OSMStore &osmStore, OutputObject const &oo, const Tile case OutputGeometryType::POLYGON: { - auto const &mp = osmStore.retrieve(oo.handle); + auto const &input = osmStore.retrieve(oo.handle); Polygon clippingPolygon; geom::convert(bbox.clippingBox, clippingPolygon); - if (!geom::intersects(mp, clippingPolygon)) { return MultiPolygon(); } + if (!geom::intersects(input, clippingPolygon)) { return MultiPolygon(); } + MultiPolygon mp; + Polygon extendPolygon; + geom::convert(bbox.getExtendBox(), extendPolygon); + geom::intersection(input, extendPolygon, mp); + MultiPolygon out; for(auto const &p: mp) { Polygon newp; @@ -125,40 +130,49 @@ Geometry buildWayGeometry(OSMStore &osmStore, OutputObject const &oo, const Tile } std::size_t start_index = 0; + for(std::size_t j = 0; j < p.outer().size() - 1; ++j) { + if (geom::within(p.outer()[start_index], bbox.clippingBox)) { + start_index = j; + break; + } + } - geom::append(newp.outer(), p.outer[start_index]); - for(std::size_t j = 1; j < p.outer.size() - 1; ++j) { - std::size_t i = (start_index + j) % p.outer.size(); - std::size_t next_i = (i + 1) % p.outer.size(); - - bool keep_point = - geom::within(newp.outer().back(), bbox.clippingBox) || - geom::within(p.outer[i], bbox.clippingBox) || - geom::within(p.outer[next_i], bbox.clippingBox); - - if(!keep_point) { + geom::append(newp.outer(), p.outer()[start_index]); + geom::append(newp.outer(), p.outer()[start_index + 1]); + for(std::size_t j = 2; j < p.outer().size() - 1; ++j) { + std::size_t i = (start_index + j) % (p.outer().size() - 1); + auto prev_2 = newp.outer()[newp.outer().size() - 2]; + auto prev_1 = newp.outer()[newp.outer().size() - 1]; + + bool remove_point = + !geom::within(prev_2, bbox.clippingBox) && !geom::within(prev_1, bbox.clippingBox) && !geom::within(p.outer()[i], bbox.clippingBox); + + if(remove_point) { + // Check if 3 points are locally convex double det = - (p.outer[i].x() - newp.outer().back().x()) * (p.outer[next_i].y() * newp.outer().back().y()) - - (p.outer[next_i].x() - newp.outer().back().x()) * (p.outer[i].y() * newp.outer().back().y()); - - if(det < 0) { - Linestring ls({ newp.outer().back(), p.outer[next_i] }); + (p.outer()[i].x() - prev_2.x()) * (prev_1.y() - prev_2.y()) - + (prev_1.x() - prev_2.x()) * (p.outer()[i].y() - prev_2.y()); + + if(det <= 0) { + Linestring ls({ prev_2, p.outer()[i] }); bool intersects = geom::intersects(ls, bbox.clippingBox); - for(auto const &inner: p.inners) { + for(auto const &inner: p.inners()) { intersects |= geom::intersects(ls, inner); } - if(!intersects) + if(!intersects) { + newp.outer()[newp.outer().size() - 1] = p.outer()[i]; continue; - } + } + } } - geom::append(newp.outer(), p.outer[i]); - } - geom::append(newp.outer(), p.outer[start_index]); + geom::append(newp.outer(), p.outer()[i]); + } + geom::append(newp.outer(), p.outer()[start_index]); - newp.inners().reserve(p.inners.size()); - for(auto const &inner: p.inners) { + newp.inners().reserve(p.inners().size()); + for(auto const &inner: p.inners()) { if(geom::within(inner, newp.outer())) { newp.inners().resize(newp.inners().size() + 1); boost::geometry::assign(newp.inners().back(), inner);