diff --git a/CHANGELOG b/CHANGELOG index 4532039d9..eebfb533f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,8 @@ For a complete change history, see the SVN log. Mapnik Trunk ------------ +- Add minimum-path-length property to text_symbolizer to allow labels to be placed only on lines of a certain length (#865) + - Add support for png quantization using fixed palettes (#843) - Add AlsoFilter functionality - http://trac.mapnik.org/wiki/AlsoFilter diff --git a/bindings/python/mapnik_text_symbolizer.cpp b/bindings/python/mapnik_text_symbolizer.cpp index ccd5b51a2..2f844a062 100644 --- a/bindings/python/mapnik_text_symbolizer.cpp +++ b/bindings/python/mapnik_text_symbolizer.cpp @@ -90,6 +90,7 @@ struct text_symbolizer_pickle_suite : boost::python::pickle_suite extras.append(t.get_justify_alignment()); extras.append(t.get_text_opacity()); extras.append(t.get_minimum_padding()); + extras.append(t.get_minimum_path_length()); return boost::python::make_tuple(disp,t.get_label_placement(), t.get_vertical_alignment(),t.get_halo_radius(),t.get_halo_fill(),t.get_text_ratio(), @@ -153,6 +154,7 @@ struct text_symbolizer_pickle_suite : boost::python::pickle_suite t.set_justify_alignment(extract(extras[6])); t.set_text_opacity(extract(extras[7])); t.set_minimum_padding(extract(extras[8])); + t.set_minimum_path_length(extract(extras[9])); } }; @@ -276,6 +278,9 @@ void export_text_symbolizer() .add_property("minimum_padding", &text_symbolizer::get_minimum_padding, &text_symbolizer::set_minimum_padding) + .add_property("minimum_path_length", + &text_symbolizer::get_minimum_path_length, + &text_symbolizer::set_minimum_path_length) .add_property("name",&text_symbolizer::get_name, &text_symbolizer::set_name) .add_property("opacity", diff --git a/include/mapnik/placement_finder.hpp b/include/mapnik/placement_finder.hpp index 86f2b0d5c..a2368ed93 100644 --- a/include/mapnik/placement_finder.hpp +++ b/include/mapnik/placement_finder.hpp @@ -70,6 +70,7 @@ struct placement : boost::noncopyable double max_char_angle_delta; double minimum_distance; double minimum_padding; + double minimum_path_length; bool avoid_edges; bool has_dimensions; bool allow_overlap; diff --git a/include/mapnik/text_symbolizer.hpp b/include/mapnik/text_symbolizer.hpp index 71bbf142e..f3556cb2a 100644 --- a/include/mapnik/text_symbolizer.hpp +++ b/include/mapnik/text_symbolizer.hpp @@ -110,6 +110,8 @@ struct MAPNIK_DECL text_symbolizer : public symbolizer_base double get_minimum_distance() const; void set_minimum_padding(double distance); double get_minimum_padding() const; + void set_minimum_path_length(double size); + double get_minimum_path_length() const; void set_allow_overlap(bool overlap); bool get_allow_overlap() const; void set_text_opacity(double opacity); @@ -146,6 +148,7 @@ private: bool avoid_edges_; double minimum_distance_; double minimum_padding_; + double minimum_path_length_; bool overlap_; double text_opacity_; bool wrap_before_; diff --git a/src/load_map.cpp b/src/load_map.cpp index eede49323..4995c1760 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -1204,7 +1204,7 @@ void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym ) << "halo-radius,text-ratio,wrap-width,wrap-before," << "wrap-character,text-transform,line-spacing," << "label-position-tolerance,character-spacing," - << "spacing,minimum-distance,minimum-padding," + << "spacing,minimum-distance,minimum-padding,minimum-path-length," << "avoid-edges,allow-overlap,opacity,max-char-angle-delta," << "horizontal-alignment,justify-alignment," << "placements,placement-type," @@ -1381,6 +1381,13 @@ void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym ) text_symbol.set_minimum_padding(*min_padding); } + // minimum path length + optional min_path_length = get_opt_attr(sym, "minimum-path-length"); + if (min_path_length) + { + text_symbol.set_minimum_path_length(*min_path_length); + } + // do not render labels around edges optional avoid_edges = get_opt_attr(sym, "avoid-edges"); diff --git a/src/placement_finder.cpp b/src/placement_finder.cpp index 9f25fb1cf..88a3f48d0 100644 --- a/src/placement_finder.cpp +++ b/src/placement_finder.cpp @@ -66,6 +66,7 @@ placement::placement(string_info & info_, max_char_angle_delta(sym.get_max_char_angle_delta()), minimum_distance(scale_factor_ * sym.get_minimum_distance()), minimum_padding(scale_factor_ * sym.get_minimum_padding()), + minimum_path_length(0), avoid_edges(sym.get_avoid_edges()), has_dimensions(has_dimensions_), allow_overlap(false), @@ -90,6 +91,7 @@ placement::placement(string_info & info_, max_char_angle_delta(sym.get_max_char_angle_delta()), minimum_distance(scale_factor_ * sym.get_minimum_distance()), minimum_padding(scale_factor_ * sym.get_minimum_padding()), + minimum_path_length(scale_factor_ * sym.get_minimum_path_length()), avoid_edges(sym.get_avoid_edges()), has_dimensions(false), allow_overlap(sym.get_allow_overlap()), @@ -517,6 +519,10 @@ void placement_finder::find_line_placements(placement & p, text_place //Now path_positions is full and total_distance is correct //shape_path shouldn't be used from here + // Ensure lines have a minimum length. + if (total_distance < p.minimum_path_length) + return; + double distance = 0.0; std::pair string_dimensions = p.info.get_dimensions(); diff --git a/src/save_map.cpp b/src/save_map.cpp index 17d2cfd05..339250c43 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -532,6 +532,10 @@ private: { set_attr( node, "minimum-padding", sym.get_minimum_padding() ); } + if (sym.get_minimum_path_length() != dfl.get_minimum_path_length() || explicit_defaults_ ) + { + set_attr( node, "minimum-path-length", sym.get_minimum_path_length() ); + } if (sym.get_allow_overlap() != dfl.get_allow_overlap() || explicit_defaults_ ) { set_attr( node, "allow-overlap", sym.get_allow_overlap() ); diff --git a/src/text_symbolizer.cpp b/src/text_symbolizer.cpp index 2a03c642b..dd6953d6e 100644 --- a/src/text_symbolizer.cpp +++ b/src/text_symbolizer.cpp @@ -111,6 +111,7 @@ text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_na avoid_edges_(false), minimum_distance_(0.0), minimum_padding_(0.0), + minimum_path_length_(0.0), overlap_(false), text_opacity_(1.0), wrap_before_(false), @@ -143,6 +144,7 @@ text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const avoid_edges_(false), minimum_distance_(0.0), minimum_padding_(0.0), + minimum_path_length_(0.0), overlap_(false), text_opacity_(1.0), wrap_before_(false), @@ -175,6 +177,7 @@ text_symbolizer::text_symbolizer(text_symbolizer const& rhs) avoid_edges_(rhs.avoid_edges_), minimum_distance_(rhs.minimum_distance_), minimum_padding_(rhs.minimum_padding_), + minimum_path_length_(rhs.minimum_path_length_), overlap_(rhs.overlap_), text_opacity_(rhs.text_opacity_), wrap_before_(rhs.wrap_before_), @@ -206,6 +209,7 @@ text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other) avoid_edges_ = other.avoid_edges_; minimum_distance_ = other.minimum_distance_; minimum_padding_ = other.minimum_padding_; + minimum_path_length_ = other.minimum_path_length_; overlap_ = other.overlap_; text_opacity_ = other.text_opacity_; wrap_before_ = other.wrap_before_; @@ -473,7 +477,17 @@ void text_symbolizer::set_minimum_padding(double distance) { minimum_padding_ = distance; } - + +double text_symbolizer::get_minimum_path_length() const +{ + return minimum_path_length_; +} + +void text_symbolizer::set_minimum_path_length(double size) +{ + minimum_path_length_ = size; +} + void text_symbolizer::set_allow_overlap(bool overlap) { overlap_ = overlap;