Skip to content

Commit

Permalink
revert #91 for now / until further tested
Browse files Browse the repository at this point in the history
  • Loading branch information
Dane Springmeyer committed Dec 8, 2018
1 parent 227e987 commit 39c6d95
Showing 1 changed file with 54 additions and 94 deletions.
148 changes: 54 additions & 94 deletions src/feature_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,23 +98,24 @@ struct line_string_handler
bool first_ = true;
};

template <typename CoordinateType>
using annotated_ring = std::pair<mapbox::geometry::linear_ring<CoordinateType>, vtzero::ring_type>;

template <typename CoordinateType>
struct polygon_handler
{
polygon_handler(vtzero::polygon_feature_builder& builder, mapbox::geometry::box<CoordinateType> const& bbox, int dx, int dy, int zoom_factor)
: builder_(builder),
ring_{},
bbox_(bbox),
extent_({0, 0}, {0, 0}),
using geom_type = std::vector<annotated_ring<CoordinateType>>;
polygon_handler(geom_type& geom, int dx, int dy, int zoom_factor)
: geom_(geom),
dx_(dx),
dy_(dy),
zoom_factor_(zoom_factor) {}

void ring_begin(std::uint32_t count)
{
first_ = true;
ring_.clear();
ring_.reserve(count);
geom_.emplace_back();
geom_.back().first.reserve(count);
}

void ring_point(vtzero::point const& pt)
Expand All @@ -123,21 +124,7 @@ struct polygon_handler
{
CoordinateType x = pt.x * zoom_factor_ - dx_;
CoordinateType y = pt.y * zoom_factor_ - dy_;
ring_.emplace_back(x, y);
if (first_)
{
extent_.min.x = x;
extent_.max.x = x;
extent_.min.y = y;
extent_.max.y = y;
}
else
{
if (x < extent_.min.x) extent_.min.x = x;
if (x > extent_.max.x) extent_.max.x = x;
if (y < extent_.min.y) extent_.min.y = y;
if (y > extent_.max.y) extent_.max.y = y;
}
geom_.back().first.emplace_back(x, y);
cur_x_ = pt.x;
cur_y_ = pt.y;
first_ = false;
Expand All @@ -146,80 +133,16 @@ struct polygon_handler

void ring_end(vtzero::ring_type type)
{
if (type == vtzero::ring_type::outer)
{
if (!boost::geometry::intersects(extent_, bbox_))
{
skip_ = true;
}
else
{
skip_ = false;
valid_ = true;
}
}
if (!skip_ && ring_.size() > 3)
{
// only clip if not fully within bbox
if (bbox_.min.x >= extent_.min.x &&
bbox_.max.x <= extent_.max.x &&
bbox_.min.y >= extent_.min.y &&
bbox_.max.y <= extent_.max.y)
{
builder_.add_ring(static_cast<unsigned>(ring_.size()));
for (auto const& pt : ring_)
{
builder_.set_point(static_cast<int>(pt.x), static_cast<int>(pt.y));
};
}
else
{
// TODO: reuse this result memory?
std::vector<mapbox::geometry::polygon<CoordinateType>> result;
if (type == vtzero::ring_type::inner)
{
boost::geometry::reverse(ring_);
}
boost::geometry::intersection(ring_, bbox_, result);
for (auto&& geom : result)
{
if (type == vtzero::ring_type::inner)
{
boost::geometry::reverse(geom);
}
for (auto const& ring : geom)
{
if (ring.size() > 3)
{
builder_.add_ring(static_cast<unsigned>(ring.size()));
for (auto const& pt : ring)
{
builder_.set_point(static_cast<int>(pt.x), static_cast<int>(pt.y));
};
}
}
}
}
}
geom_.back().second = type;
}

bool valid() const
{
return valid_;
}

vtzero::polygon_feature_builder& builder_;
mapbox::geometry::linear_ring<CoordinateType> ring_;
mapbox::geometry::box<CoordinateType> const& bbox_;
mapbox::geometry::box<CoordinateType> extent_;
geom_type& geom_;
int const dx_;
int const dy_;
int const zoom_factor_;
CoordinateType cur_x_ = 0;
CoordinateType cur_y_ = 0;
bool first_ = true;
bool skip_ = false;
bool valid_ = false;
};

} // namespace detail
Expand Down Expand Up @@ -296,13 +219,50 @@ struct overzoomed_feature_builder
}
void apply_geometry_polygon(vtzero::feature const& feature)
{
vtzero::polygon_feature_builder feature_builder{layer_builder_};
feature_builder.copy_id(feature);
detail::polygon_handler<CoordinateType> handler(feature_builder, bbox_, dx_, dy_, zoom_factor_);
vtzero::decode_polygon_geometry(feature.geometry(), handler);
if (handler.valid())
std::vector<detail::annotated_ring<CoordinateType>> rings;
vtzero::decode_polygon_geometry(feature.geometry(), detail::polygon_handler<CoordinateType>(rings, dx_, dy_, zoom_factor_));
if (!rings.empty())
{
finalize(feature_builder, feature);
vtzero::polygon_feature_builder feature_builder{layer_builder_};
feature_builder.copy_id(feature);
bool valid = false;
bool process = false;
for (auto& r : rings)
{
if (r.second == vtzero::ring_type::outer)
{
auto extent = mapbox::geometry::envelope(r.first);
process = boost::geometry::intersects(extent, bbox_);
}
if (process)
{
std::vector<mapbox::geometry::polygon<coordinate_type>> result;
if (r.second == vtzero::ring_type::inner) boost::geometry::reverse(r.first);
// ^^ reverse inner rings before clipping as we're dealing with a disassembled polygon
boost::geometry::intersection(r.first, bbox_, result);
for (auto const& p : result)
{
for (auto const& ring : p)
{
if (ring.size() > 3)
{
valid = true;
feature_builder.add_ring(static_cast<unsigned>(ring.size()));
if (r.second == vtzero::ring_type::outer)
{
std::for_each(ring.begin(), ring.end(), [&feature_builder](auto const& pt) { feature_builder.set_point(static_cast<int>(pt.x), static_cast<int>(pt.y)); });
}
else
{
// apply points in reverse to preserve original winding order of inner rings
std::for_each(ring.rbegin(), ring.rend(), [&feature_builder](auto const& pt) { feature_builder.set_point(static_cast<int>(pt.x), static_cast<int>(pt.y)); });
}
}
}
}
}
}
if (valid) finalize(feature_builder, feature);
}
}

Expand Down

0 comments on commit 39c6d95

Please sign in to comment.