From 2727eddf905ef43d47e0f4d3a1759026f12633d6 Mon Sep 17 00:00:00 2001 From: artemp Date: Fri, 5 Sep 2014 16:19:55 +0100 Subject: [PATCH] implement 'avoid-adges' for markers placements (point placement) (TODO: support all placement types) --- include/mapnik/grid/grid_marker_helpers.hpp | 6 ++++-- include/mapnik/marker_helpers.hpp | 6 ++++-- include/mapnik/markers_placements/point.hpp | 5 +++++ include/mapnik/symbolizer_keys.hpp | 1 + src/cairo/process_markers_symbolizer.cpp | 6 ++++-- src/load_map.cpp | 2 ++ src/symbolizer_keys.cpp | 5 +++-- 7 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/mapnik/grid/grid_marker_helpers.hpp b/include/mapnik/grid/grid_marker_helpers.hpp index 1bf04fc2e..b4d50dc3c 100644 --- a/include/mapnik/grid/grid_marker_helpers.hpp +++ b/include/mapnik/grid/grid_marker_helpers.hpp @@ -80,10 +80,11 @@ struct raster_markers_rasterizer_dispatch_grid : mapnik::noncopyable marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); box2d bbox(0,0, src_.width(), src_.height()); double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap }; + markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; markers_placement_finder placement_finder( placement_method, path, detector_, params); double x, y, angle = .0; @@ -190,11 +191,12 @@ struct vector_markers_rasterizer_dispatch_grid : mapnik::noncopyable bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); double opacity = get(sym_,keys::opacity, feature_, vars_, 1.0); bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); coord2d center = bbox_.center(); agg::trans_affine_translation recenter(-center.x, -center.y); double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap }; + markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; markers_placement_finder placement_finder( placement_method, path, detector_, params); double x, y, angle = .0; diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index b5d26bab4..35d16a1c4 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -111,13 +111,14 @@ struct vector_markers_rasterizer_dispatch : mapnik::noncopyable marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); double opacity = get(sym_,keys::opacity, feature_, vars_, 1.0); double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); coord2d center = bbox_.center(); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine tr = recenter * marker_trans_; - markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap }; + markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; markers_placement_finder placement_finder( placement_method, path, detector_, params); double x, y, angle = .0; @@ -195,12 +196,13 @@ struct raster_markers_rasterizer_dispatch : mapnik::noncopyable { marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); box2d bbox_(0,0, src_.width(),src_.height()); double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap }; + markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; markers_placement_finder placement_finder( placement_method, path, detector_, params); double x, y, angle = .0; diff --git a/include/mapnik/markers_placements/point.hpp b/include/mapnik/markers_placements/point.hpp index 8af6f8ca5..e9af96f8e 100644 --- a/include/mapnik/markers_placements/point.hpp +++ b/include/mapnik/markers_placements/point.hpp @@ -37,6 +37,7 @@ struct markers_placement_params double spacing; double max_error; bool allow_overlap; + bool avoid_edges; }; template @@ -87,6 +88,10 @@ public: angle = 0; box2d box = perform_transform(angle, x, y); + if (params_.avoid_edges && !detector_.extent().contains(box)) + { + return false; + } if (!params_.allow_overlap && !detector_.has_placement(box)) { return false; diff --git a/include/mapnik/symbolizer_keys.hpp b/include/mapnik/symbolizer_keys.hpp index 27b9bd0dd..b4442ed7c 100644 --- a/include/mapnik/symbolizer_keys.hpp +++ b/include/mapnik/symbolizer_keys.hpp @@ -90,6 +90,7 @@ enum class keys : std::uint8_t justify_alignment, vertical_alignment, upright, + avoid_edges, MAX_SYMBOLIZER_KEY }; diff --git a/src/cairo/process_markers_symbolizer.cpp b/src/cairo/process_markers_symbolizer.cpp index d782e499f..6f3464577 100644 --- a/src/cairo/process_markers_symbolizer.cpp +++ b/src/cairo/process_markers_symbolizer.cpp @@ -81,13 +81,14 @@ struct markers_dispatch : mapnik::noncopyable sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); coord2d center = bbox_.center(); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine tr = recenter * marker_trans_; - markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap }; + markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; markers_placement_finder placement_finder( placement_method, path, detector_, params); double x, y, angle = .0; @@ -148,9 +149,10 @@ struct raster_markers_dispatch : mapnik::noncopyable double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); box2d bbox_(0,0, src_.width(),src_.height()); - markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap }; + markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; markers_placement_finder placement_finder( placement_method, path, detector_, params); double x, y, angle = .0; diff --git a/src/load_map.cpp b/src/load_map.cpp index c44cc907c..eaf985ad2 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -957,6 +957,8 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node) set_symbolizer_property(sym, keys::max_error, node); // allow-overlap set_symbolizer_property(sym, keys::allow_overlap, node); + // avoid-edges + set_symbolizer_property(sym, keys::avoid_edges, node); // ignore-placement set_symbolizer_property(sym, keys::ignore_placement, node); // width diff --git a/src/symbolizer_keys.cpp b/src/symbolizer_keys.cpp index f6615c3e9..bb440e984 100644 --- a/src/symbolizer_keys.cpp +++ b/src/symbolizer_keys.cpp @@ -116,7 +116,8 @@ static const property_meta_type key_meta[const_max_key] = property_types::target_vertical_alignment}, property_meta_type{ "upright", enumeration_wrapper(UPRIGHT_AUTO), [](enumeration_wrapper e) {return enumeration(text_upright_enum(e.value)).as_string();}, - property_types::target_upright} + property_types::target_upright}, + property_meta_type{ "avoid-edges",false, nullptr, property_types::target_bool }, }; @@ -141,4 +142,4 @@ mapnik::keys get_key(std::string const& name) return static_cast(0); } -} \ No newline at end of file +}