From c8c792277dc45c5bf47556b3ec1d85d19b18c137 Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Wed, 20 Aug 2014 19:43:36 -0400 Subject: [PATCH 1/5] Add attribute text-margin in place of minimum-distance. --- bindings/python/mapnik_text_placement.cpp | 3 ++- include/mapnik/text/text_properties.hpp | 2 ++ src/text/placement_finder.cpp | 29 ++++++++++------------- src/text/text_properties.cpp | 8 +++++++ 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/bindings/python/mapnik_text_placement.cpp b/bindings/python/mapnik_text_placement.cpp index 31bd30030..482385187 100644 --- a/bindings/python/mapnik_text_placement.cpp +++ b/bindings/python/mapnik_text_placement.cpp @@ -425,8 +425,9 @@ void export_text_placement() .def_readwrite("label_spacing", &text_symbolizer_properties::label_spacing) .def_readwrite("label_position_tolerance", &text_symbolizer_properties::label_position_tolerance) .def_readwrite("avoid_edges", &text_symbolizer_properties::avoid_edges) - .def_readwrite("minimum_distance", &text_symbolizer_properties::minimum_distance) + .def_readwrite("text_margin", &text_symbolizer_properties::text_margin) .def_readwrite("repeat_distance", &text_symbolizer_properties::repeat_distance) + .def_readwrite("minimum_distance", &text_symbolizer_properties::minimum_distance) .def_readwrite("minimum_padding", &text_symbolizer_properties::minimum_padding) .def_readwrite("minimum_path_length", &text_symbolizer_properties::minimum_path_length) .def_readwrite("maximum_angle_char_delta", &text_symbolizer_properties::max_char_angle_delta) diff --git a/include/mapnik/text/text_properties.hpp b/include/mapnik/text/text_properties.hpp index 9ccf00144..53fec57db 100644 --- a/include/mapnik/text/text_properties.hpp +++ b/include/mapnik/text/text_properties.hpp @@ -137,6 +137,7 @@ struct text_properties_expressions symbolizer_base::value_type label_spacing = 0.0; symbolizer_base::value_type label_position_tolerance = 0.0; symbolizer_base::value_type avoid_edges = false; + symbolizer_base::value_type text_margin = 0.0; symbolizer_base::value_type repeat_distance = 0.0; symbolizer_base::value_type minimum_distance = 0.0; symbolizer_base::value_type minimum_padding = 0.0; @@ -180,6 +181,7 @@ struct MAPNIK_DECL text_symbolizer_properties // distance the label can be moved on the line to fit, if 0 the default is used double label_position_tolerance; bool avoid_edges; + double text_margin; double repeat_distance; double minimum_distance; double minimum_padding; diff --git a/src/text/placement_finder.cpp b/src/text/placement_finder.cpp index 3bee0364d..13c36de93 100644 --- a/src/text/placement_finder.cpp +++ b/src/text/placement_finder.cpp @@ -313,23 +313,18 @@ double placement_finder::get_spacing(double path_length, double layout_width) co bool placement_finder::collision(const box2d &box, const value_unicode_string &repeat_key) const { - if (!detector_.extent().intersects(box) - || - (info_.properties.avoid_edges && !extent_.contains(box)) - || - (info_.properties.minimum_padding > 0 && - !extent_.contains(box + (scale_factor_ * info_.properties.minimum_padding))) - || - (!info_.properties.allow_overlap && - ((repeat_key.length() == 0 && !detector_.has_placement(box, info_.properties.minimum_distance * scale_factor_)) - || - (repeat_key.length() > 0 && !detector_.has_placement(box, info_.properties.minimum_distance * scale_factor_, - repeat_key, info_.properties.repeat_distance * scale_factor_)))) - ) - { - return true; - } - return false; + return !detector_.extent().intersects(box) + || + (info_.properties.avoid_edges && !extent_.contains(box)) + || + (info_.properties.minimum_padding > 0 && + !extent_.contains(box + (scale_factor_ * info_.properties.minimum_padding))) + || + (!info_.properties.allow_overlap && + ((repeat_key.length() == 0 && !detector_.has_placement(box, info_.properties.text_margin * scale_factor_)) + || + (repeat_key.length() > 0 && !detector_.has_placement(box, info_.properties.text_margin * scale_factor_, + repeat_key, info_.properties.repeat_distance * scale_factor_)))); } void placement_finder::set_marker(marker_info_ptr m, box2d box, bool marker_unlocked, pixel_position const& marker_displacement) diff --git a/src/text/text_properties.cpp b/src/text/text_properties.cpp index 9e98cf645..9b63e10d9 100644 --- a/src/text/text_properties.cpp +++ b/src/text/text_properties.cpp @@ -44,6 +44,7 @@ text_symbolizer_properties::text_symbolizer_properties() label_spacing(0.0), label_position_tolerance(0.0), avoid_edges(false), + text_margin(0.0), repeat_distance(0.0), minimum_distance(0.0), minimum_padding(0.0), @@ -115,6 +116,7 @@ void text_symbolizer_properties::text_properties_from_xml(xml_node const& node) set_property_from_xml(expressions.label_placement, "placement", node); set_property_from_xml(expressions.label_spacing, "spacing", node); set_property_from_xml(expressions.label_position_tolerance, "label-position-tolerance", node); + set_property_from_xml(expressions.text_margin, "text-margin", node); set_property_from_xml(expressions.repeat_distance, "repeat-distance", node); set_property_from_xml(expressions.minimum_distance, "minimum-distance", node); set_property_from_xml(expressions.minimum_padding, "minimum-padding", node); @@ -158,6 +160,10 @@ void text_symbolizer_properties::to_xml(boost::property_tree::ptree &node, { serialize_property("spacing", expressions.label_spacing, node); } + if (!(expressions.text_margin == dfl.expressions.text_margin) || explicit_defaults) + { + serialize_property("text-margin", expressions.text_margin, node); + } if (!(expressions.repeat_distance == dfl.expressions.repeat_distance) || explicit_defaults) { serialize_property("repeat-distance", expressions.repeat_distance, node); @@ -207,6 +213,8 @@ void text_symbolizer_properties::add_expressions(expression_set & output) const if (is_expression(expressions.label_spacing)) output.insert(util::get(expressions.label_spacing)); if (is_expression(expressions.label_position_tolerance)) output.insert(util::get(expressions.label_position_tolerance)); if (is_expression(expressions.avoid_edges)) output.insert(util::get(expressions.avoid_edges)); + if (is_expression(expressions.text_margin)) output.insert(util::get(expressions.text_margin)); + if (is_expression(expressions.repeat_distance)) output.insert(util::get(expressions.repeat_distance)); if (is_expression(expressions.minimum_distance)) output.insert(util::get(expressions.minimum_distance)); if (is_expression(expressions.minimum_padding)) output.insert(util::get(expressions.minimum_padding)); if (is_expression(expressions.minimum_path_length)) output.insert(util::get(expressions.minimum_path_length)); From a28d3dd99c406f35b94286333f0fd1c73ea3297a Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Thu, 21 Aug 2014 20:49:00 -0400 Subject: [PATCH 2/5] Handle text-margin, repeat-distance, and backward compatible minimum-distance in placement_finder. Update visual tests. --- include/mapnik/text/placement_finder.hpp | 2 +- src/text/placement_finder.cpp | 24 +++++++++++++------ src/text/text_properties.cpp | 1 + tests/visual_tests/styles/repeat-labels-1.xml | 4 ++-- tests/visual_tests/styles/repeat-labels-2.xml | 4 ++-- tests/visual_tests/styles/repeat-labels-3.xml | 4 ++-- tests/visual_tests/styles/repeat-labels-4.xml | 4 ++-- 7 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/mapnik/text/placement_finder.hpp b/include/mapnik/text/placement_finder.hpp index f7afd8979..bf7dc157c 100644 --- a/include/mapnik/text/placement_finder.hpp +++ b/include/mapnik/text/placement_finder.hpp @@ -72,7 +72,7 @@ private: // Adjusts user defined spacing to place an integer number of labels. double get_spacing(double path_length, double layout_width) const; // Checks for collision. - bool collision(box2d const& box, const value_unicode_string &repeat_key = "") const; + bool collision(box2d const& box, const value_unicode_string &repeat_key, bool line_placement) const; // Adds marker to glyph_positions and to collision detector. Returns false if there is a collision. bool add_marker(glyph_positions_ptr glyphs, pixel_position const& pos) const; // Maps upright==auto, left_only and right_only to left,right to simplify processing. diff --git a/src/text/placement_finder.cpp b/src/text/placement_finder.cpp index 13c36de93..1d7c7a1e1 100644 --- a/src/text/placement_finder.cpp +++ b/src/text/placement_finder.cpp @@ -121,7 +121,7 @@ bool placement_finder::find_point_placement(pixel_position const& pos) bbox.re_center(layout_center.x, layout_center.y); /* For point placements it is faster to just check the bounding box. */ - if (collision(bbox, layouts_.text())) return false; + if (collision(bbox, layouts_.text(), false)) return false; if (layout.num_lines()) bboxes.push_back(std::move(bbox)); @@ -244,7 +244,7 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or cluster_offset.y -= rot.sin * glyph.advance(); box2d bbox = get_bbox(layout, glyph, pos, rot); - if (collision(bbox, layouts_.text())) return false; + if (collision(bbox, layouts_.text(), true)) return false; bboxes.push_back(std::move(bbox)); glyphs->push_back(glyph, pos, rot); } @@ -311,8 +311,19 @@ double placement_finder::get_spacing(double path_length, double layout_width) co return path_length / num_labels; } -bool placement_finder::collision(const box2d &box, const value_unicode_string &repeat_key) const +bool placement_finder::collision(const box2d &box, const value_unicode_string &repeat_key, bool line_placement) const { + double text_margin, repeat_distance; + if (line_placement) + { + text_margin = info_.properties.text_margin * scale_factor_; + repeat_distance = (info_.properties.repeat_distance != 0 ? info_.properties.repeat_distance : info_.properties.minimum_distance) * scale_factor_; + } + else + { + text_margin = (info_.properties.text_margin != 0 ? info_.properties.text_margin : info_.properties.minimum_distance) * scale_factor_; + repeat_distance = info_.properties.repeat_distance * scale_factor_; + } return !detector_.extent().intersects(box) || (info_.properties.avoid_edges && !extent_.contains(box)) @@ -321,10 +332,9 @@ bool placement_finder::collision(const box2d &box, const value_unicode_s !extent_.contains(box + (scale_factor_ * info_.properties.minimum_padding))) || (!info_.properties.allow_overlap && - ((repeat_key.length() == 0 && !detector_.has_placement(box, info_.properties.text_margin * scale_factor_)) + ((repeat_key.length() == 0 && !detector_.has_placement(box, text_margin)) || - (repeat_key.length() > 0 && !detector_.has_placement(box, info_.properties.text_margin * scale_factor_, - repeat_key, info_.properties.repeat_distance * scale_factor_)))); + (repeat_key.length() > 0 && !detector_.has_placement(box, text_margin, repeat_key, repeat_distance)))); } void placement_finder::set_marker(marker_info_ptr m, box2d box, bool marker_unlocked, pixel_position const& marker_displacement) @@ -343,7 +353,7 @@ bool placement_finder::add_marker(glyph_positions_ptr glyphs, pixel_position con box2d bbox = marker_box_; bbox.move(real_pos.x, real_pos.y); glyphs->set_marker(marker_, real_pos); - if (collision(bbox, layouts_.text())) return false; + if (collision(bbox, layouts_.text(), false)) return false; detector_.insert(bbox); return true; } diff --git a/src/text/text_properties.cpp b/src/text/text_properties.cpp index 9b63e10d9..127b78777 100644 --- a/src/text/text_properties.cpp +++ b/src/text/text_properties.cpp @@ -64,6 +64,7 @@ void text_symbolizer_properties::evaluate_text_properties(feature_impl const& fe label_spacing = util::apply_visitor(extract_value(feature,attrs), expressions.label_spacing); label_position_tolerance = util::apply_visitor(extract_value(feature,attrs), expressions.label_position_tolerance); avoid_edges = util::apply_visitor(extract_value(feature,attrs), expressions.avoid_edges); + text_margin = util::apply_visitor(extract_value(feature,attrs), expressions.text_margin); repeat_distance = util::apply_visitor(extract_value(feature,attrs), expressions.repeat_distance); minimum_distance = util::apply_visitor(extract_value(feature,attrs), expressions.minimum_distance); minimum_padding = util::apply_visitor(extract_value(feature,attrs), expressions.minimum_padding); diff --git a/tests/visual_tests/styles/repeat-labels-1.xml b/tests/visual_tests/styles/repeat-labels-1.xml index e116f57a2..ca2b9f575 100644 --- a/tests/visual_tests/styles/repeat-labels-1.xml +++ b/tests/visual_tests/styles/repeat-labels-1.xml @@ -18,14 +18,14 @@ diff --git a/tests/visual_tests/styles/repeat-labels-2.xml b/tests/visual_tests/styles/repeat-labels-2.xml index b78dca811..07944c283 100644 --- a/tests/visual_tests/styles/repeat-labels-2.xml +++ b/tests/visual_tests/styles/repeat-labels-2.xml @@ -18,14 +18,14 @@ diff --git a/tests/visual_tests/styles/repeat-labels-3.xml b/tests/visual_tests/styles/repeat-labels-3.xml index fc24a2f38..cf8b31108 100644 --- a/tests/visual_tests/styles/repeat-labels-3.xml +++ b/tests/visual_tests/styles/repeat-labels-3.xml @@ -18,14 +18,14 @@ diff --git a/tests/visual_tests/styles/repeat-labels-4.xml b/tests/visual_tests/styles/repeat-labels-4.xml index 080c63e66..24db0f7ff 100644 --- a/tests/visual_tests/styles/repeat-labels-4.xml +++ b/tests/visual_tests/styles/repeat-labels-4.xml @@ -18,14 +18,14 @@ From 688dfcabc97fd7e7cd6c79fd4d0407f6797371ec Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Fri, 22 Aug 2014 08:52:45 -0400 Subject: [PATCH 3/5] Disallow use of minimum-distance with either repeat-distance or text-margin. --- src/text/text_properties.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/text/text_properties.cpp b/src/text/text_properties.cpp index 127b78777..ed4b461ca 100644 --- a/src/text/text_properties.cpp +++ b/src/text/text_properties.cpp @@ -114,12 +114,25 @@ formatting::node_ptr text_symbolizer_properties::format_tree() const void text_symbolizer_properties::text_properties_from_xml(xml_node const& node) { + // The options 'text-margin' and 'repeat-distance' replace 'minimum-distance'. + // Only allow one or the other to be defined here. + if (node.has_attribute("text-margin") || node.has_attribute("repeat-distance")) + { + if (node.has_attribute("minimum-distance")) + { + throw config_error(std::string("Cannot use deprecated option minimum-distance with " + "new options text-margin and repeat-distance.")); + } + set_property_from_xml(expressions.text_margin, "text-margin", node); + set_property_from_xml(expressions.repeat_distance, "repeat-distance", node); + } + else + { + set_property_from_xml(expressions.minimum_distance, "minimum-distance", node); + } set_property_from_xml(expressions.label_placement, "placement", node); set_property_from_xml(expressions.label_spacing, "spacing", node); set_property_from_xml(expressions.label_position_tolerance, "label-position-tolerance", node); - set_property_from_xml(expressions.text_margin, "text-margin", node); - set_property_from_xml(expressions.repeat_distance, "repeat-distance", node); - set_property_from_xml(expressions.minimum_distance, "minimum-distance", node); set_property_from_xml(expressions.minimum_padding, "minimum-padding", node); set_property_from_xml(expressions.minimum_path_length, "minimum-path-length", node); set_property_from_xml(expressions.avoid_edges, "avoid-edges", node); From cf8d1873bce2706b521fba4dbffef005611c1d90 Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Fri, 22 Aug 2014 10:48:02 -0400 Subject: [PATCH 4/5] Update visual test repeat-labels-1 to test minimum-distance functionality. --- ...t-labels-1-750-250-1.0-grid-reference.json | 6 +++--- ...eat-labels-1-750-250-1.0-agg-reference.png | Bin 9507 -> 7046 bytes ...t-labels-1-750-250-1.0-cairo-reference.png | Bin 5150 -> 4695 bytes ...eat-labels-1-750-250-2.0-agg-reference.png | Bin 13670 -> 7040 bytes ...t-labels-1-750-250-2.0-cairo-reference.png | Bin 7109 -> 5433 bytes tests/visual_tests/styles/repeat-labels-1.xml | 4 ++-- 6 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/visual_tests/grids/repeat-labels-1-750-250-1.0-grid-reference.json b/tests/visual_tests/grids/repeat-labels-1-750-250-1.0-grid-reference.json index 1ecbce60c..9cfaec02b 100644 --- a/tests/visual_tests/grids/repeat-labels-1-750-250-1.0-grid-reference.json +++ b/tests/visual_tests/grids/repeat-labels-1-750-250-1.0-grid-reference.json @@ -21,7 +21,7 @@ " ", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", - " !!!! ! !!!! ! !!!!! ! !!!! !!!! !!!!! ", + " ! ! ! ", " ", " ", " ", @@ -34,10 +34,10 @@ " ", " ", " ", - " $$$$ $$$$ $ $$$$$ $$$$ $ $$$$ $ $$$$ ", + " ", "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", - " $ $ $ $ ", + " ", " ", " ", " ", diff --git a/tests/visual_tests/images/repeat-labels-1-750-250-1.0-agg-reference.png b/tests/visual_tests/images/repeat-labels-1-750-250-1.0-agg-reference.png index 4d84c897261f7ed01d55ec3c288cda1adea10dd7..7d35d0c2c98f967755858ad0ace515bf082731f4 100644 GIT binary patch literal 7046 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 R!k->MTirmdR>djme*tk6TBQI0 literal 9507 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 u40X6cxc&_XprN9xT>av8=zjn!P1|Mw diff --git a/tests/visual_tests/images/repeat-labels-1-750-250-1.0-cairo-reference.png b/tests/visual_tests/images/repeat-labels-1-750-250-1.0-cairo-reference.png index b36b8dea22315a5c850adbcdd0e9602b62e6360c..84c041105d694cbad821eefcd36ab0258c566ad8 100644 GIT binary patch delta 4025 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 CQs3wR delta 4547 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 diff --git a/tests/visual_tests/images/repeat-labels-1-750-250-2.0-agg-reference.png b/tests/visual_tests/images/repeat-labels-1-750-250-2.0-agg-reference.png index 386be9e832e64f75d66410f679bad0404ac99467..17bdb7d05e4ca41fb13df2f540b762d975b006e8 100644 GIT binary patch literal 7040 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�%z3f zL>$r;Nd3@3AOGsV5^27m1!pJ)UAVp2RL=iXgjwhAX?`Qo86j+pB9iEiBBL>CfC2N= zzL2|adnSKeAuS=LeDFrUEOo_dWNmx5#{GS<07N#D{*fHE3mNaH6q=jab!h9r|kux%?LTQyKA`t(EmOhX-tu?5`8wb0S+lPPX}B}LRbD<+SmlE7L~A+f1FVIhlhZ3H zM;s>EBVubU+6|w$rgJikO}jC_cIK4xidXL6OdjOOaTtwI=A9==lj)iutyF2`yf(FQ zr-T8|p*Kf zQdwJv*mjr=BQ?kDLP>e1Twir~biBTjFJrS=VwolBz&UfkCwn!pQxgRuyM< zCw=XfU+EpY=oizqWlvYF1!$!Q$gh;9=R$hxSiq#6i-?nF1DXGm@&y!u;-IRr6H%{(}*Z zOdtwj9NT~3!I`@s1mi>Quf5-&8TL5i;T2!>C0CFq12>}|z!WQg$qV6Z-8+j~=+Irx zyQrnl?7Cse_O?Hx>4tYn39G4E@jd!&TN|W=PIqB!fxVLhwn8A`V|>kQ+fX?~e|Ijf zt@b95vyg9Ni2I1^q)%#)B#M{lz*DX-K{2?un}tp-XKne(pxLkiXQDTp*B4pcsy^?2 zu`D1LOnJqo;GHayENM#-EdHT>O&toIkEF#bP(y!KI9;bjfBkw@d_Wv9)uEOyUZ%89o@6vgu1Rh_zKd zt2;(-3;wMY@#qgDxsh2R`=ICb7+xyjmE^d;?ulDbRa!xR-`s|so8%U$;dlu4T zH)7Ki8NqfaKPlf-?1wl|ebF>}LR81-ZHnD+BWMv*j&$kKcRi}A2#@W=zO^|8F%0{y zNpkAG4J7j=BiQ7!*6NWzP425_=nh-Q^Xn-8;PVbX%b=^HQ_2X6K-m5fNmrm)I;>hSCRGhy8t~^s#yDupvf6^9 z*I2{LM7GO+>S7swrQ&_hfmeNaXD|7>vEmi~!_(L2l&Nl$AseeANKos<6mBwPKy`aE z=NYAgf+5_Ik;Db9y>bcwKB|!C-sF85Nu(!p#JK7~dMsSX42vyKbB|#?ZE|g-2~!{= zu{j2L-$ca*Co!}Bxdge}dS9hSo7RF>NWtNNh57VuZ{6L~gxQ#>9$>}@?Jh~R73y`; z$j(bn#SRIZ=;&`cP5(G@@C!%fcTWxl^y;JH%I_Czu@Y)lK~IDS^ohOC+B85&83VN| zT3!c14E^MJPQ>B6fI~-)B4~E;q?J{M)i_DI0o+TY@3KCf`8_F`gfbgw}0S9-nTz<2-UA>0A7}=`eA17{cB!uMr?7Hk^cyR*zM#~ zzZlcKbPrpklY0hsZ5-59Oo+d~ai_>jfLCCALyaJEG=G=F)@Ifwv5UlKgS`juSATAx zmA~Ni$mBL!Ur$bnFCc>e^t0|X{&;&9H^UXTpl!}^eB&Z zQM2W``J(j_n2toNl`ob0{r)n|POruwNN&$pOERKW_5P}~eb*JIJsjA{R7iB z!mUEu6_Qq}KtJgF)lpR)#R;onD0_DW#li7 z`c}>;+S{ft%f6uk8LrF2uol(pWnWKG>8Q(?vH376v=q=Eg|P2?gI!HZPw9~4@iSEz z_51E{$m&LpfLw(3-FrKeV4LqYn6-W6>VtXZ(|_iL+?lg4W_y0N<{Glr;7UN>|5j4N z4Lz+8f?YK~mw8J7y-qN)%Nap3Q@o~=pWUA|PtUt+xE@_x zIRj52h1wCOw+CO&g<2mf!?ZN-zm33JP<){XF(l{x_WP25PY!o>(T`iP!Igs#)*{Im zQH>DfwFL9;+^j7oQX9W1GQ%i~;8dJP7triKVTc`0GH7<=#CKJ1T1kZV#Jjniq3+`? z9lOKMf({4s)5x>SgVBJ-o|I)v`iAq%mYt-Yi%+14FVaaQ)%C(+=BB0g_V}S1V#3G) zZwF9%&)vTZ{#uXVxXfw~Z}A`)PVI~CL)quxeE_uN-&h_~wVgQ* zdKCT`ijgb8*Oml#g{d1LF@ZTMw&(`j{EhE$r4)OQ^Yl*?aeVA2iYL|OeOj|*t6YZlEzuLvxFpcPKYJ(9bBg~rfO3L11kgwh%@%LY}0Ih zVVz5|9EYfQGn#)GYWx0zK^<1-iEng5{Mkha-zKjxJLZ^NI*KH|YZ3n33uKT3c zSH|{=v0|X&lz{py<8ThQJZ2x<@C@u`pX`CG2D4BDcvIOHr`5>Wm^~teO9%h<1|~|5(TXFC8hQSUO-g-hD?$Z?9+f78pKp z${O4>24}?J)~fWe&7bZ%l^;A$CN03C`MZLFwi4XG)%Zoc0U$FqKb`_piL1=m=1?n` zUa)zI!v}fj{{v1Z0)+BoE*su0%WnVAbLmfe)`d z9UjzfH2_(XAsEoc3W3!=>zO_MA5n^g_* z<;(u+>?sOB+{FV%U^iDD*rGs8?*-m)XE7xbC@5nqj)4)IcN0n^Mzc>uM}p&cdJX@66Ei*a7UWh`u{bdOg{t7RTcOb7 z@p*KxsT0w)qUZ;?bQruHoROeb{er9~$))Cx0=MeB&RACwA$SbVYLz|~;CCAe#jDx0 z22ZNwW5cMRTcbi6ea~^A{@Q6rx~Y&*UktzC3@-0H;yxCLId2CspL3F2o$_O<9y#iZ zGIQ?HO**0hjOy^@pReJw)=vAwF5KW+#f2QPa7EshQ(Dv0hB0_Dd|lG4qT~e+w$Gp1 zSL1qE$#$XNBJ+m9lMZ+d?6s`bL8i^oXaosxej`vtZqPdC;rHWP55$U;$x89BPvi<^ zWc=GGxm1d;naWfIu7Tw>h-Xk| zXOdF)`^Ggt=dls0=pi~WYoyPr(lx3^8x|wji0SF*f*dkxPvMnArk>n{50P!t6)HI% zkd=uD$}>wv0fME^nw9AeBN(6Fz|jbEG?Glq!(?6!nCec{kwU^wed)2?3EBlWbsQr) z8sEXYF6a}r%odaAwwv+5l2>zMu*f{dH6dJGVyg6PT99OMj8 z#!`^tsoMihv$DZEyI~_E9prDnfaN_G&FZMtre@f+5IrOfXe7d!8e}?JXPHzGZ81ot z5xE4TJ4}xxvaT-oDYK@JAJ;8l=(Hyv=Xb;xtlr_E;WaX_i4>U96+t?oR zDJU&+Z9H(rG-VQrT(9_*hbBcBJv#0yS7!*8rLQJ;JpA+^by8Ruw#$R1NP4qKt)OvU5%Y58X>Ee9OYQmVck1a?G#D~p!{9~6Iwe`LytJi?*mAmBG(b^ z+$arwDwSRffu^wc7X3%r{VO9$QRiqMN-KA>^7~h+KZxBi(Qg>%YPoEnoz=vcIDQdSKXrr1HuJ+L9f(F5ih0PYg{^wGf1x zR}VDpCyEG5bpZ5TYX%B_8%)oeGlv6R;)*BAvXDwH_>RUw*HOT>8`6Q*I=J~6Y!@8e zJkUtLeSTdg4Vb({Y+!$Tk8^etJMLp=mQ)Z4bhkFn>2^1X0IT=X2$HZ8XGG8@5?HrgOg`A)@)U20+w(MR+hHTs$2>7 z&1r+bFMfenih!d$Dg2tQ2u$I36C78iQQ^3uH?ekuL7qpNMV|e%zTsV0lzd>%qf+Cr z{@Xuv3?H5R?gwYY25(Qh`Mtcte>9s@)8r~GMA3oPiUZGod@G_jl;!_@rI{6WeK$kB zrY<5>;@xkX+n4|HIQKkL^sDU8F9T@{hqUkSEsiR?7Bi;JsGwXhT%-$Q{-45aTd@((9Nq^Cs|MGmxI$r7eKdUHdQ|9V20>r?V>GxsKLY+QqWz*VHj{38vt4!$OR76t9q&0iZ{dwpiJ@6vE zIx2m6XpZ-qHk^Bdh(3qor(IlNhTV@BgSG504&Hsn<+ihuNuK>fr~OD?9hGN!j3L3X zK@|BRBlJ8~0@3H$LCb{o_vIYEWTfa*=!)(h0hDn{n7Ya;XTIXDXHoRc5g-ffE@?P7 zb;jzrotyr2yB>XAp<+WosX(8#_OqX}SoP-V`dao8fD-*Bv*7ea_lj<3A6Ne~;zO!p zxGip>sSH-oe5|TozCuYpJ27k(iRv{tF|Vrm6`$*lFxUFy8q;O79`flSn3?SI!OCG+ zg=-sVObPI-+o^9_d57AWmWG`UIy|xkY9anUiF!VT8{atQ=V#lUdzYXqGcGq6jAhB) zDY%(U+k5R`UtKh}{sv?fh@8ybDtUHdt&k<~n_vNe}`Oe{+(H=%?xCDN|_>7;Nwrc1>n|`4K@5>%__o=SltNamB zGBR=9Szi9UcYx0GRH?jg4|W-{;b97ORpgVULaZsU{X^zmw4lGg7)w^Y-7hZuV^S|8 z>WOLpq70>pXg=`SkDOHA+IVXwyM{wRZ!Y`DMB87(jgPmee9M2p$so#DyYQ8Gh6db996W;evgAh7qQ*g|M%rdi#jBPW zpR4%Ftbc%p_6*Ggr7I~vr^%{cw~XnzK+n|$b6_NztWHzbn1RgOEzDa8`U+iYg4Rr| zaaNbj8fDrH8H9uh{7l#b_QMj(va3Rtw_{stsrZ)zg<_e|HLl9F7v4_SG4>KWw>+d3 zo1m#P?hav9eAT0H7?1!LTb63&)Y?SHWqsM`MpG?kuu^>Iz4Z~jz>)mh7k9r!LcdoU zc!3b#xNw_T7{4eB1(tthZbcuZwbiq(Y*8zt5xfUY9#VnvIIv9~H*p^lL@!=3Sq5ka zI58o4OK3T3;|7NP+nfi-x!p>Jh+zzdp4X>8O(%B z2DO}{jV4uVLv_c&eXbcY?NGqxEm+w{f$obKi9vBi(du#ndpGGEoap6-#j>uO6P|$g z$ZsL>i*z^aHqKMg%d*%$)JYOJWql^X48U!d&W6kG8;9W*D}6_rzxSI~ZB8hQLT)D)bbyyVO_>Q<3bH~X`ul*qEOnj; z+jMX#*0w-77%@FlX@RpsHTm)oInPmpO8)g0OM%Rl2x+7~wL)OgN&P!DU|)N>bpu6k zE6cmBhkyr8QQ^kiPXry+OOzGhpiLo^z94CtF%2z**}8-dDQn}NQtTv?rKnx`eT5l! zn29ZQnxoSX&-$#}fg>VrDIyD?PZ>-Srv4lEXGvU5@!_c0zsxc!v&!LANRXp({Sw z&M_Il=zqh5T$&8HA)xQpzp?#orvP5JUp%@-(+7kR}Vz!apO8y-uDAHqX%+fy7cY$BGI2S`V(H3IXjg1&=pNt z`;$SBMD4$;?4AW=@%^Y%+1q^4234Ei!6Ekzla6Y9mkwU(zE``WH;7VWEKd| zhF|sWE$jCn>gAZlCFtW@8v;rz_xc{;v|e-Oc97Q=BS>y^Z{-K;K76kZ<1hPA8n~eC zJQ`>>))ET48FI{jx}z+g615=9irDZxr7vaPje=o@ckpHtca*b^31dRLdGdEO8UhM= z^PkD4yPkP1ON!GJzRN0f7xtfTqL(j`XqLp`Z!hQ0lL5jI4uZQIq2}6O?bwtNr!IYTHC<7)~q2ag}xdFYg_W zu!8k{>f}ndr|yb2oB5wCC7NE&N(nb=EB!rWNS)$M8pZX@ANMT)yt!aI{e6J__- zeQDMxzXqn4CxLxumrU1#^WOB!aF&PFn~xm+@P$cR{?k7K3}J(1*VW@0nZ>PbKYwsO zc)4U|`#H3*6!pJ(*?5)D8p4}86u6)3q)%=l7eyHd?@Jfcc=Br@$^kGb9iI@j>l_RYJ+(O1l}5}kOF zLC3$HtcZi+Y&yA$;f~vTKfQXF2B0%v6fhkWs!iY4cC#xO=x@!J-Rtchg5|XtAt1x% z$flyXQ+inQ`xpax9VqQpmK5wp?QlS^t&6`7aj{`C+`ob1)4Gv*_)fCb4oBQ_DraGu zoX0{YyNQsftaB-}g>TJX{bayn2@MTxDWV8=U^>EFi9C~$lE!|oxb77;eG#{-*}jJn zYhGz0q2oFxG}h1W=Wx#EPSoqQ?Zousl`8?`S8=Y8WsOdZre^1o##ZvCp8hXy$74cI z^-N5OILeV|-5u9FID)dzBq~8L_gh~W&ot&UzP)i^AU1mL@>$a;s#wyfp(=F+N}I{{ z1ltnUzK4?Z@`-((Aw_w^GzzL2ad5>u)f2ks6-8;M{M${NJch@lmaeo-LArX;Qipuc z)xygNxHFf?Ma4%uYFI}qMsdu%WHZ+oFw2+aRPu-dL`+eL$kh)ru!hqz(tXjxtq-m( z$xP-6zLfW^YH6hBc2YsZG|A>9-0dqCq1*lOXLVXEv2B0>otbP|uDuH;FRIVwp~V31 z#=`4j?pY)%4B91*#6ITO2(knbRcGn_l&=hvcMq-f;TEW0gjyxh$F)nPMOa)qn7k)U z)|%5IygS;oR;(LV;^@?Ch+DyV-@`>olAMkYa+xQ73(xLhWAg6*&?u$*+?x#YSyNTl zT{IT;g+(*ODc%%WH}{gQWFvG#6IVL(pe^dEE7c&$XMk4zex*s%x<*x6oyCR&<V{!O+^(K5{^bUv zQ@yy%7w;;TUnk+Q;)0{qbVICaQ4$tWcm0QCvc$E2ent9L&KH(S`Or-MMu9CrzJ(OB zVvkPMOmvj;!9bKmzW2#0xb|v?)1)(tV5j8%dG9qF^Y+4jo-^qrWFl!@6IRtY@*P}} zOk`fB6e1?)tD8S&RYHA9PpepjrXuwNQ2G>_iKHuUo5_BhwF-Tvx_PeFWz=H_z4VAL)^r4tU$E4Mf87Kw6NRN;%=da|Xky`Kqwi zj(%~);^1kgfAg!p?@$Oc%Yo!k&dC}ZrI;tV#Zc0Bfw{4qyuFLM@ z`{S3;Q$!6hI#hc|A*p1axZ0wB@p8^d&#QIuNKw;n#pheYR(NcSv7oNUf)m-~;tDQ!D`9gj;vojzT&^+Vyxyk#1^gpOt}Uj-y6a}EzHc{NNFOlDa) z?VmnTcjb^m_d8Gvrymw4#i@tMdB!AOI(kJmrS+fFtFgJ{<+&skP8HZJ#`nL+UB0U> zzfXO6MB`V;jdh6*O}@&Mx7?@72}7655Ras%FHi7t<{53>6#&sbyW;3L5R+;71E;VH zN0npF4^`q1@vH8q?jJcP4boUdZ1}y&rprkpB^RDC2?<-$$`Jja#iI z)ekrLwf?of8_rRADKPjOFPLgvm?1Ou%{P_{mt9C9?Y>Nr8C|;tCq6W2(mhw@$GRD_ zA_rUX%ir^(DaY#`sQMdQ8che@o+)X~&2x6oB5uYh_QJK^FEmav4E~rO)#rh17J4?O znEvD_=kB`Oj0lkne^&A_8=2)6BV_aJjbpNE%}Jifc9rQv!$m&|%)4x_HBu*BuA#qo z!w)@I2{^-Q$~*kYdToaKFv4%lPa1lD>2Jv+U7+w+wu1J= z)FhJPi&8;69K+#X?PBoB0VKl)0ts|?a=2N}ut{otnE6WobZ1r)EqX;3ElL8>&_`gn z^K&{ijd#8@W-e7el%(%xUyBq1R6R(06tf~r=XsGmo$kN3Ry|mvQ-@~A; zjlbWuXShjMP>SGIO}1c8{Qqs`La#vif;XF8=yv|K_M;V*sv{(N#U@q2x$8|5KX*3$ zp4CJgY?057^G1~luLw@fx_32-Hy?iDR^Q4kPy3)XQT=#H_x##<85c=xiV}$vN^0rr zT{X{T@EPR)u`Lf7{1NGbTHA-&AGG&*AG{Ge2@j)23U!%TAd9aT!uPx9zgIH;G@l_W z8e!DG#f8JDir}z)I~BMCvM^NkdMHHy`T`mlw<1eIqdxy&)VttvM_f9WgI@&SivHSQ r8*wxDoC=TBq2+8BpCSX6USoU@UC+5t3G^;BAv>|_5Mmr@xQ diff --git a/tests/visual_tests/images/repeat-labels-1-750-250-2.0-cairo-reference.png b/tests/visual_tests/images/repeat-labels-1-750-250-2.0-cairo-reference.png index 84a3bdcc8f0f1496448c0cc70f3518418343d7cc..215115d89cf79c48024e169b7e4de66bbf52de2c 100644 GIT binary patch literal 5433 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 Cw3>qe diff --git a/tests/visual_tests/styles/repeat-labels-1.xml b/tests/visual_tests/styles/repeat-labels-1.xml index ca2b9f575..1938a6a99 100644 --- a/tests/visual_tests/styles/repeat-labels-1.xml +++ b/tests/visual_tests/styles/repeat-labels-1.xml @@ -18,14 +18,14 @@ From 88782a85c8398f0c418c902a82f200ecd5d2d580 Mon Sep 17 00:00:00 2001 From: Jordan Hollinger Date: Fri, 22 Aug 2014 13:38:01 -0400 Subject: [PATCH 5/5] Minor improvement to repeat handling in collision detector. --- include/mapnik/label_collision_detector.hpp | 37 +++++++++++---------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/include/mapnik/label_collision_detector.hpp b/include/mapnik/label_collision_detector.hpp index 6d7796850..585be4f64 100644 --- a/include/mapnik/label_collision_detector.hpp +++ b/include/mapnik/label_collision_detector.hpp @@ -161,19 +161,19 @@ public: return true; } - bool has_placement(box2d const& box, double minimum_distance) + bool has_placement(box2d const& box, double margin) { - box2d const& minimum_box = (minimum_distance > 0 - ? box2d(box.minx() - minimum_distance, box.miny() - minimum_distance, - box.maxx() + minimum_distance, box.maxy() + minimum_distance) + box2d const& margin_box = (margin > 0 + ? box2d(box.minx() - margin, box.miny() - margin, + box.maxx() + margin, box.maxy() + margin) : box); - tree_t::query_iterator itr = tree_.query_in_box(minimum_box); + tree_t::query_iterator itr = tree_.query_in_box(margin_box); tree_t::query_iterator end = tree_.query_end(); for (;itr != end; ++itr) { - if (itr->box.intersects(minimum_box)) + if (itr->box.intersects(margin_box)) { return false; } @@ -181,24 +181,27 @@ public: return true; } - bool has_placement(box2d const& box, double minimum_distance, mapnik::value_unicode_string const& text, double repeat_distance) + bool has_placement(box2d const& box, double margin, mapnik::value_unicode_string const& text, double repeat_distance) { - box2d const& minimum_box = (minimum_distance > 0 - ? box2d(box.minx() - minimum_distance, box.miny() - minimum_distance, - box.maxx() + minimum_distance, box.maxy() + minimum_distance) + // Don't bother with any of the repeat checking unless the repeat distance is greater than the margin + if (repeat_distance <= margin) { + return has_placement(box, margin); + } + + box2d repeat_box(box.minx() - repeat_distance, box.miny() - repeat_distance, + box.maxx() + repeat_distance, box.maxy() + repeat_distance); + + box2d const& margin_box = (margin > 0 + ? box2d(box.minx() - margin, box.miny() - margin, + box.maxx() + margin, box.maxy() + margin) : box); - box2d const& repeat_box = (repeat_distance > 0 - ? box2d(box.minx() - repeat_distance, box.miny() - repeat_distance, - box.maxx() + repeat_distance, box.maxy() + repeat_distance) - : box); - - tree_t::query_iterator itr = tree_.query_in_box(repeat_distance > minimum_distance ? repeat_box : minimum_box); + tree_t::query_iterator itr = tree_.query_in_box(repeat_box); tree_t::query_iterator end = tree_.query_end(); for ( ;itr != end; ++itr) { - if (itr->box.intersects(minimum_box) || (text == itr->text && itr->box.intersects(repeat_box))) + if (itr->box.intersects(margin_box) || (text == itr->text && itr->box.intersects(repeat_box))) { return false; }