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)
: 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
{
return false;
}
result_type operator() (geometry_collection const& collection) const
{
return false;
}
template <typename T>
result_type operator() (T const& geom) const
result_type operator() (point 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_);
return true;
@ -62,7 +94,8 @@ 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);
}

View file

@ -34,7 +34,8 @@ struct geometry_envelope
{
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);
}
@ -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);
}

View file

@ -31,7 +31,8 @@ namespace mapnik { namespace geometry { namespace detail {
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);
}
@ -78,7 +79,8 @@ struct geometry_type
};
} // 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);
}

View file

@ -61,6 +61,13 @@ using vertex_converter_type = vertex_converter<placement_finder_adapter<placemen
class base_symbolizer_helper
{
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,
feature_impl const& feature,
attributes const& vars,
@ -86,13 +93,12 @@ protected:
float scale_factor_;
//Processing
// Using list instead of vector, because we delete random elements and need iterators to stay valid.
// 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.
mutable std::list<pixel_position> points_;
// Geometry currently being processed.
mutable std::list<geometry::geometry*>::iterator geo_itr_;
// Point currently being processed.
mutable std::list<pixel_position>::iterator point_itr_;
// Use point placement. Otherwise line placement is used.

View file

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

View file

@ -87,12 +87,12 @@ pixel_position_list const& group_symbolizer_helper::get()
else
{
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
// vertex_converters
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_;
};
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
base_symbolizer_helper::base_symbolizer_helper(
@ -108,6 +156,13 @@ struct largest_bbox_first
box2d<double> b1 = geometry::envelope(*g1);
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
@ -117,7 +172,9 @@ void base_symbolizer_helper::initialize_geometries() const
geometry::geometry const& geom = feature_.get_geometry();
geometry::geometry_types type = geometry::geometry_type(geom);
// FIXME: how to handle MultiLinePolygon
if (type == geometry::geometry_types::Polygon)
{
if (minimum_path_length > 0)
@ -125,18 +182,22 @@ void base_symbolizer_helper::initialize_geometries() const
box2d<double> gbox = t_.forward(geometry::envelope(geom), prj_trans_);
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
{
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
{
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() ?
if (largest_box_only)
{
@ -164,24 +225,14 @@ void base_symbolizer_helper::initialize_points() const
double label_y=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)
{
using apply_vertex_placement = detail::apply_vertex_placement<std::list<pixel_position> >;
apply_vertex_placement apply(points_, t_, prj_trans_);
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
{
@ -204,8 +255,6 @@ void base_symbolizer_helper::initialize_points() const
label_x = pt.x;
label_y = pt.y;
success = true;
//success = label::centroid(va, label_x, label_y);
}
else if (how_placed == INTERIOR_PLACEMENT)
{
@ -282,10 +331,12 @@ bool text_symbolizer_helper::next_line_placement() const
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);
converter_.apply(va);
if (adapter_.status())