make geometry methods templated to allow using modified geometry types ( e.g variant<reference_wrapper<T>..>

symbolizer_helper - store geometries in custom varaint using reference_wrapper<T const>
This commit is contained in:
artemp 2015-03-25 12:55:37 +01:00
parent 22de30bb37
commit 389d00d442
7 changed files with 133 additions and 38 deletions

View file

@ -38,21 +38,53 @@ struct geometry_centroid
geometry_centroid(point & pt) geometry_centroid(point & pt)
: pt_(pt) {} : pt_(pt) {}
result_type operator() (geometry const& geom) const template <typename T>
result_type operator() (T const& geom) const
{ {
return mapnik::util::apply_visitor(*this, geom); return util::apply_visitor(*this, geom);
} }
result_type operator() (geometry_empty const&) const result_type operator() (geometry_empty const&) const
{ {
return false; return false;
} }
result_type operator() (geometry_collection const& collection) const result_type operator() (geometry_collection const& collection) const
{ {
return false; return false;
} }
template <typename T> result_type operator() (point const& geom) const
result_type operator() (T const& geom) const {
boost::geometry::centroid(geom, pt_);
return true;
}
result_type operator() (line_string const& geom) const
{
boost::geometry::centroid(geom, pt_);
return true;
}
result_type operator() (polygon const& geom) const
{
boost::geometry::centroid(geom, pt_);
return true;
}
result_type operator() (multi_point const& geom) const
{
boost::geometry::centroid(geom, pt_);
return true;
}
result_type operator() (multi_line_string const& geom) const
{
boost::geometry::centroid(geom, pt_);
return true;
}
result_type operator() (multi_polygon const& geom) const
{ {
boost::geometry::centroid(geom, pt_); boost::geometry::centroid(geom, pt_);
return true; return true;
@ -62,9 +94,10 @@ struct geometry_centroid
} }
inline bool centroid(mapnik::geometry::geometry const& geom, point & pt) template <typename T>
inline bool centroid(T const& geom, point & pt)
{ {
return detail::geometry_centroid(pt) (geom); return detail::geometry_centroid(pt)(geom);
} }
}} }}

View file

@ -34,7 +34,8 @@ struct geometry_envelope
{ {
using bbox_type = box2d<double>; using bbox_type = box2d<double>;
bbox_type operator() (mapnik::geometry::geometry const& geom) const template <typename T>
bbox_type operator() (T const& geom) const
{ {
return mapnik::util::apply_visitor(*this, geom); return mapnik::util::apply_visitor(*this, geom);
} }
@ -106,7 +107,8 @@ struct geometry_envelope
} }
inline mapnik::box2d<double> envelope(mapnik::geometry::geometry const& geom) template <typename T>
inline mapnik::box2d<double> envelope(T const& geom)
{ {
return detail::geometry_envelope() (geom); return detail::geometry_envelope() (geom);
} }

View file

@ -31,7 +31,8 @@ namespace mapnik { namespace geometry { namespace detail {
struct geometry_type struct geometry_type
{ {
mapnik::geometry::geometry_types operator () (mapnik::geometry::geometry const& geom) const template <typename T>
mapnik::geometry::geometry_types operator () (T const& geom) const
{ {
return mapnik::util::apply_visitor(*this, geom); return mapnik::util::apply_visitor(*this, geom);
} }
@ -78,7 +79,8 @@ struct geometry_type
}; };
} // detail } // detail
static inline mapnik::geometry::geometry_types geometry_type(mapnik::geometry::geometry const& geom) template <typename T>
static inline mapnik::geometry::geometry_types geometry_type(T const& geom)
{ {
return detail::geometry_type()(geom); return detail::geometry_type()(geom);
} }

View file

@ -61,6 +61,13 @@ using vertex_converter_type = vertex_converter<placement_finder_adapter<placemen
class base_symbolizer_helper class base_symbolizer_helper
{ {
public: public:
using point_cref = std::reference_wrapper<geometry::point const>;
using line_string_cref = std::reference_wrapper<geometry::line_string const>;
using polygon_cref = std::reference_wrapper<geometry::polygon const>;
using geometry_cref = util::variant<point_cref, line_string_cref, polygon_cref>;
// Using list instead of vector, because we delete random elements and need iterators to stay valid.
using geometry_container_type = std::list<geometry_cref>;
base_symbolizer_helper(symbolizer_base const& sym, base_symbolizer_helper(symbolizer_base const& sym,
feature_impl const& feature, feature_impl const& feature,
attributes const& vars, attributes const& vars,
@ -86,13 +93,12 @@ protected:
float scale_factor_; float scale_factor_;
//Processing //Processing
// Using list instead of vector, because we delete random elements and need iterators to stay valid.
// Remaining geometries to be processed. // Remaining geometries to be processed.
mutable std::list<geometry::geometry*> geometries_to_process_; mutable geometry_container_type geometries_to_process_;
// Geometry currently being processed.
mutable geometry_container_type::iterator geo_itr_;
// Remaining points to be processed. // Remaining points to be processed.
mutable std::list<pixel_position> points_; mutable std::list<pixel_position> points_;
// Geometry currently being processed.
mutable std::list<geometry::geometry*>::iterator geo_itr_;
// Point currently being processed. // Point currently being processed.
mutable std::list<pixel_position>::iterator point_itr_; mutable std::list<pixel_position>::iterator point_itr_;
// Use point placement. Otherwise line placement is used. // Use point placement. Otherwise line placement is used.

View file

@ -34,7 +34,8 @@ struct vertex_processor
vertex_processor(processor_type& proc) vertex_processor(processor_type& proc)
: proc_(proc) {} : proc_(proc) {}
void operator() (geometry const& geom) template <typename Geometry>
void operator() (Geometry const& geom)
{ {
util::apply_visitor(*this, geom); util::apply_visitor(*this, geom);
} }

View file

@ -87,12 +87,12 @@ pixel_position_list const& group_symbolizer_helper::get()
else else
{ {
using apply_find_line_placements = detail::apply_find_line_placements<group_symbolizer_helper>; using apply_find_line_placements = detail::apply_find_line_placements<group_symbolizer_helper>;
for (auto const* geom : geometries_to_process_) for (auto const& geom : geometries_to_process_)
{ {
// TODO to support clipped geometries this needs to use // TODO to support clipped geometries this needs to use
// vertex_converters // vertex_converters
apply_find_line_placements apply(t_, prj_trans_, *this); apply_find_line_placements apply(t_, prj_trans_, *this);
mapnik::util::apply_visitor(geometry::vertex_processor<apply_find_line_placements>(apply), *geom); mapnik::util::apply_visitor(geometry::vertex_processor<apply_find_line_placements>(apply), geom);
} }
} }

View file

@ -74,6 +74,54 @@ struct apply_vertex_placement
proj_transform const& prj_trans_; proj_transform const& prj_trans_;
}; };
template <typename T>
struct split_multi_geometries
{
using container_type = T;
split_multi_geometries(container_type & cont)
: cont_(cont) {}
void operator() (geometry::geometry_empty const&) const {}
void operator() (geometry::multi_point const& multi_pt) const
{
for ( auto const& pt : multi_pt )
{
cont_.push_back(std::move(base_symbolizer_helper::geometry_cref(std::cref(pt))));
}
}
void operator() (geometry::multi_line_string const& multi_line) const
{
for ( auto const& line : multi_line )
{
cont_.push_back(std::move(base_symbolizer_helper::geometry_cref(std::cref(line))));
}
}
void operator() (geometry::multi_polygon const& multi_poly) const
{
for ( auto const& poly : multi_poly )
{
cont_.push_back(std::move(base_symbolizer_helper::geometry_cref(std::cref(poly))));
}
}
void operator() (geometry::geometry_collection const& collection) const
{
#if 0
for ( auto const& geom : collection)
{
(*this)(geom);
}
#endif
}
template <typename Geometry>
void operator() (Geometry const& geom) const
{
cont_.push_back(std::move(base_symbolizer_helper::geometry_cref(std::cref(geom))));
}
container_type & cont_;
};
} // ns detail } // ns detail
base_symbolizer_helper::base_symbolizer_helper( base_symbolizer_helper::base_symbolizer_helper(
@ -108,6 +156,13 @@ struct largest_bbox_first
box2d<double> b1 = geometry::envelope(*g1); box2d<double> b1 = geometry::envelope(*g1);
return b0.width() * b0.height() > b1.width() * b1.height(); return b0.width() * b0.height() > b1.width() * b1.height();
} }
bool operator() (base_symbolizer_helper::geometry_cref const& g0,
base_symbolizer_helper::geometry_cref const& g1) const
{
box2d<double> b0 = geometry::envelope(g0);
box2d<double> b1 = geometry::envelope(g1);
return b0.width() * b0.height() > b1.width() * b1.height();
}
}; };
void base_symbolizer_helper::initialize_geometries() const void base_symbolizer_helper::initialize_geometries() const
@ -117,7 +172,9 @@ void base_symbolizer_helper::initialize_geometries() const
geometry::geometry const& geom = feature_.get_geometry(); geometry::geometry const& geom = feature_.get_geometry();
geometry::geometry_types type = geometry::geometry_type(geom); geometry::geometry_types type = geometry::geometry_type(geom);
// FIXME: how to handle MultiLinePolygon // FIXME: how to handle MultiLinePolygon
if (type == geometry::geometry_types::Polygon) if (type == geometry::geometry_types::Polygon)
{ {
if (minimum_path_length > 0) if (minimum_path_length > 0)
@ -125,24 +182,28 @@ void base_symbolizer_helper::initialize_geometries() const
box2d<double> gbox = t_.forward(geometry::envelope(geom), prj_trans_); box2d<double> gbox = t_.forward(geometry::envelope(geom), prj_trans_);
if (gbox.width() >= minimum_path_length) if (gbox.width() >= minimum_path_length)
{ {
geometries_to_process_.push_back(const_cast<geometry::geometry*>(&geom)); //geometries_to_process_.push_back(const_cast<geometry::geometry*>(&geom));
geometries_to_process_.push_back(std::move(geometry_cref(std::cref(geom.get<geometry::polygon>()))));
} }
} }
else else
{ {
geometries_to_process_.push_back(const_cast<geometry::geometry*>(&geom)); //geometries_to_process_.push_back(const_cast<geometry::geometry*>(&geom));
geometries_to_process_.push_back(std::move(geometry_cref(std::cref(geom.get<geometry::polygon>()))));
} }
} }
else else
{ {
geometries_to_process_.push_back(const_cast<geometry::geometry*>(&geom)); //geometries_to_process_.push_back(const_cast<geometry::geometry*>(&geom));
util::apply_visitor(detail::split_multi_geometries<geometry_container_type>(geometries_to_process_), geom);
} }
// FIXME: return early if geometries_to_process_.empty() ? // FIXME: return early if geometries_to_process_.empty() ?
if (largest_box_only) if (largest_box_only)
{ {
geometries_to_process_.sort(largest_bbox_first()); geometries_to_process_.sort(largest_bbox_first());
geo_itr_ = geometries_to_process_.begin(); geo_itr_ = geometries_to_process_.begin();
geometries_to_process_.erase(++geo_itr_,geometries_to_process_.end()); geometries_to_process_.erase(++geo_itr_, geometries_to_process_.end());
} }
geo_itr_ = geometries_to_process_.begin(); geo_itr_ = geometries_to_process_.begin();
} }
@ -164,24 +225,14 @@ void base_symbolizer_helper::initialize_points() const
double label_y=0.0; double label_y=0.0;
double z=0.0; double z=0.0;
for (auto * geom_ptr : geometries_to_process_) for (auto const& geom : geometries_to_process_)
{ {
geometry::geometry const& geom = *geom_ptr; //geometry::geometry const& geom = *geom_ptr;
if (how_placed == VERTEX_PLACEMENT) if (how_placed == VERTEX_PLACEMENT)
{ {
using apply_vertex_placement = detail::apply_vertex_placement<std::list<pixel_position> >; using apply_vertex_placement = detail::apply_vertex_placement<std::list<pixel_position> >;
apply_vertex_placement apply(points_, t_, prj_trans_); apply_vertex_placement apply(points_, t_, prj_trans_);
util::apply_visitor(geometry::vertex_processor<apply_vertex_placement>(apply), geom); util::apply_visitor(geometry::vertex_processor<apply_vertex_placement>(apply), geom);
#if 0
va.rewind(0);
for(unsigned i = 0; i < va.size(); ++i)
{
va.vertex(&label_x, &label_y);
prj_trans_.backward(label_x, label_y, z);
t_.forward(&label_x, &label_y);
points_.emplace_back(label_x, label_y);
}
#endif
} }
else else
{ {
@ -204,8 +255,6 @@ void base_symbolizer_helper::initialize_points() const
label_x = pt.x; label_x = pt.x;
label_y = pt.y; label_y = pt.y;
success = true; success = true;
//success = label::centroid(va, label_x, label_y);
} }
else if (how_placed == INTERIOR_PLACEMENT) else if (how_placed == INTERIOR_PLACEMENT)
{ {
@ -282,10 +331,12 @@ bool text_symbolizer_helper::next_line_placement() const
continue; //Reexecute size check continue; //Reexecute size check
} }
auto type = geometry::geometry_type(**geo_itr_);
if (type == geometry::LineString) // ?? //auto type = geometry::geometry_type(*geo_itr_.get());
if (geo_itr_->is<base_symbolizer_helper::line_string_cref>()) // line_string
{ {
auto const& line = util::get<geometry::line_string>(**geo_itr_); auto const& line = util::get<geometry::line_string const>(*geo_itr_);
geometry::line_string_vertex_adapter va(line); geometry::line_string_vertex_adapter va(line);
converter_.apply(va); converter_.apply(va);
if (adapter_.status()) if (adapter_.status())