From 389d00d442f03136e315a4978f701f97472927dd Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 25 Mar 2015 12:55:37 +0100 Subject: [PATCH] make geometry methods templated to allow using modified geometry types ( e.g variant..> symbolizer_helper - store geometries in custom varaint using reference_wrapper --- include/mapnik/geometry_centroid.hpp | 45 +++++++++-- include/mapnik/geometry_envelope.hpp | 6 +- include/mapnik/geometry_type.hpp | 6 +- include/mapnik/text/symbolizer_helpers.hpp | 14 +++- include/mapnik/vertex_processor.hpp | 3 +- src/group/group_symbolizer_helper.cpp | 4 +- src/text/symbolizer_helpers.cpp | 93 +++++++++++++++++----- 7 files changed, 133 insertions(+), 38 deletions(-) diff --git a/include/mapnik/geometry_centroid.hpp b/include/mapnik/geometry_centroid.hpp index 8767395f4..4419e7a86 100644 --- a/include/mapnik/geometry_centroid.hpp +++ b/include/mapnik/geometry_centroid.hpp @@ -38,21 +38,53 @@ struct geometry_centroid geometry_centroid(point & pt) : pt_(pt) {} - result_type operator() (geometry const& geom) const + template + 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 - 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,9 +94,10 @@ struct geometry_centroid } -inline bool centroid(mapnik::geometry::geometry const& geom, point & pt) +template +inline bool centroid(T const& geom, point & pt) { - return detail::geometry_centroid(pt) (geom); + return detail::geometry_centroid(pt)(geom); } }} diff --git a/include/mapnik/geometry_envelope.hpp b/include/mapnik/geometry_envelope.hpp index 48ac55a1f..3857c7aad 100644 --- a/include/mapnik/geometry_envelope.hpp +++ b/include/mapnik/geometry_envelope.hpp @@ -34,7 +34,8 @@ struct geometry_envelope { using bbox_type = box2d; - bbox_type operator() (mapnik::geometry::geometry const& geom) const + template + bbox_type operator() (T const& geom) const { return mapnik::util::apply_visitor(*this, geom); } @@ -106,7 +107,8 @@ struct geometry_envelope } -inline mapnik::box2d envelope(mapnik::geometry::geometry const& geom) +template +inline mapnik::box2d envelope(T const& geom) { return detail::geometry_envelope() (geom); } diff --git a/include/mapnik/geometry_type.hpp b/include/mapnik/geometry_type.hpp index 60275016c..f34cc3927 100644 --- a/include/mapnik/geometry_type.hpp +++ b/include/mapnik/geometry_type.hpp @@ -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 + 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 +static inline mapnik::geometry::geometry_types geometry_type(T const& geom) { return detail::geometry_type()(geom); } diff --git a/include/mapnik/text/symbolizer_helpers.hpp b/include/mapnik/text/symbolizer_helpers.hpp index d24e84a05..1acda8a8a 100644 --- a/include/mapnik/text/symbolizer_helpers.hpp +++ b/include/mapnik/text/symbolizer_helpers.hpp @@ -61,6 +61,13 @@ using vertex_converter_type = vertex_converter; + using line_string_cref = std::reference_wrapper; + using polygon_cref = std::reference_wrapper; + using geometry_cref = util::variant; + // Using list instead of vector, because we delete random elements and need iterators to stay valid. + using geometry_container_type = std::list; 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 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 points_; - // Geometry currently being processed. - mutable std::list::iterator geo_itr_; // Point currently being processed. mutable std::list::iterator point_itr_; // Use point placement. Otherwise line placement is used. diff --git a/include/mapnik/vertex_processor.hpp b/include/mapnik/vertex_processor.hpp index a4b211e8c..6b5a774bc 100644 --- a/include/mapnik/vertex_processor.hpp +++ b/include/mapnik/vertex_processor.hpp @@ -34,7 +34,8 @@ struct vertex_processor vertex_processor(processor_type& proc) : proc_(proc) {} - void operator() (geometry const& geom) + template + void operator() (Geometry const& geom) { util::apply_visitor(*this, geom); } diff --git a/src/group/group_symbolizer_helper.cpp b/src/group/group_symbolizer_helper.cpp index b874e3921..338e5410e 100644 --- a/src/group/group_symbolizer_helper.cpp +++ b/src/group/group_symbolizer_helper.cpp @@ -87,12 +87,12 @@ pixel_position_list const& group_symbolizer_helper::get() else { using apply_find_line_placements = detail::apply_find_line_placements; - 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), *geom); + mapnik::util::apply_visitor(geometry::vertex_processor(apply), geom); } } diff --git a/src/text/symbolizer_helpers.cpp b/src/text/symbolizer_helpers.cpp index 7b31b6e15..855547cc3 100644 --- a/src/text/symbolizer_helpers.cpp +++ b/src/text/symbolizer_helpers.cpp @@ -74,6 +74,54 @@ struct apply_vertex_placement proj_transform const& prj_trans_; }; +template +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 + 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 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 b0 = geometry::envelope(g0); + box2d 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,24 +182,28 @@ void base_symbolizer_helper::initialize_geometries() const box2d gbox = t_.forward(geometry::envelope(geom), prj_trans_); if (gbox.width() >= minimum_path_length) { - geometries_to_process_.push_back(const_cast(&geom)); + //geometries_to_process_.push_back(const_cast(&geom)); + geometries_to_process_.push_back(std::move(geometry_cref(std::cref(geom.get())))); } } else { - geometries_to_process_.push_back(const_cast(&geom)); + //geometries_to_process_.push_back(const_cast(&geom)); + geometries_to_process_.push_back(std::move(geometry_cref(std::cref(geom.get())))); } } else { - geometries_to_process_.push_back(const_cast(&geom)); + //geometries_to_process_.push_back(const_cast(&geom)); + util::apply_visitor(detail::split_multi_geometries(geometries_to_process_), geom); } + // FIXME: return early if geometries_to_process_.empty() ? if (largest_box_only) { geometries_to_process_.sort(largest_bbox_first()); 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(); } @@ -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 >; apply_vertex_placement apply(points_, t_, prj_trans_); util::apply_visitor(geometry::vertex_processor(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()) // line_string { - auto const& line = util::get(**geo_itr_); + auto const& line = util::get(*geo_itr_); geometry::line_string_vertex_adapter va(line); converter_.apply(va); if (adapter_.status())