From 1cd5e69b3a740d37f4c713d27dfb24398c8423b9 Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Mon, 19 Jan 2015 13:47:46 +0000 Subject: [PATCH] add direction property for markers --- include/mapnik/marker_helpers.hpp | 6 ++-- include/mapnik/markers_placements/line.hpp | 4 +++ include/mapnik/markers_placements/point.hpp | 32 +++++++++++++++++++ .../markers_placements/vertext_first.hpp | 4 +++ .../markers_placements/vertext_last.hpp | 4 +++ include/mapnik/symbolizer.hpp | 2 ++ include/mapnik/symbolizer_default_values.hpp | 7 ++++ include/mapnik/symbolizer_enumerations.hpp | 15 +++++++++ include/mapnik/symbolizer_keys.hpp | 1 + src/load_map.cpp | 1 + src/symbolizer_enumerations.cpp | 13 ++++++++ src/symbolizer_keys.cpp | 3 ++ src/xml_tree.cpp | 1 + 13 files changed, 91 insertions(+), 2 deletions(-) diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index c7fd8becf..333b3650a 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -90,7 +90,8 @@ struct vector_markers_dispatch : util::noncopyable coord2d center = src_->bounding_box().center(); agg::trans_affine_translation recenter(-center.x, -center.y); agg::trans_affine tr = recenter * marker_trans_; - markers_placement_params params { src_->bounding_box(), tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; + direction_enum direction = get(sym_, feature_, vars_); + markers_placement_params params { src_->bounding_box(), tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges, direction }; markers_placement_finder placement_finder( placement_method, path, detector_, params); double x, y, angle = .0; @@ -147,7 +148,8 @@ struct raster_markers_dispatch : util::noncopyable value_double spacing = get(sym_, feature_, vars_); value_double max_error = get(sym_, feature_, vars_); box2d bbox(0,0, src_.width(),src_.height()); - markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; + direction_enum direction = get(sym_, feature_, vars_); + markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges, direction }; markers_placement_finder placement_finder( placement_method, path, detector_, params); double x, y, angle = .0; diff --git a/include/mapnik/markers_placements/line.hpp b/include/mapnik/markers_placements/line.hpp index 24bb229ec..9b9035e5c 100644 --- a/include/mapnik/markers_placements/line.hpp +++ b/include/mapnik/markers_placements/line.hpp @@ -97,6 +97,10 @@ public: x = pos.x; y = pos.y; angle = path_.current_segment_angle(); + if (!this->set_direction(angle)) + { + continue; + } box2d box = this->perform_transform(angle, x, y); if ((this->params_.avoid_edges && !this->detector_.extent().contains(box)) || (!this->params_.allow_overlap && !this->detector_.has_placement(box))) diff --git a/include/mapnik/markers_placements/point.hpp b/include/mapnik/markers_placements/point.hpp index 3ca1ce5c8..89bc005e5 100644 --- a/include/mapnik/markers_placements/point.hpp +++ b/include/mapnik/markers_placements/point.hpp @@ -24,6 +24,7 @@ #define MAPNIK_MARKERS_PLACEMENTS_POINT_HPP #include +#include #include "agg_basics.h" #include "agg_trans_affine.h" @@ -38,6 +39,7 @@ struct markers_placement_params double max_error; bool allow_overlap; bool avoid_edges; + direction_enum direction; }; template @@ -141,6 +143,36 @@ protected: result.expand_to_include(xD, yD); return result; } + + bool set_direction(double & angle) + { + switch (params_.direction) + { + case DIRECTION_UP: + angle = .0; + return true; + case DIRECTION_DOWN: + angle = M_PI; + return true; + case DIRECTION_AUTO: + angle = (std::fabs(util::normalize_angle(angle)) > 0.5 * M_PI) ? (angle + M_PI) : angle; + return true; + case DIRECTION_AUTO_DOWN: + angle = (std::fabs(util::normalize_angle(angle)) < 0.5 * M_PI) ? (angle + M_PI) : angle; + return true; + case DIRECTION_LEFT: + angle += M_PI; + return true; + case DIRECTION_LEFT_ONLY: + angle += M_PI; + return std::fabs(util::normalize_angle(angle)) < 0.5 * M_PI; + case DIRECTION_RIGHT_ONLY: + return std::fabs(util::normalize_angle(angle)) < 0.5 * M_PI; + case DIRECTION_RIGHT: + default: + return true; + } + } }; } diff --git a/include/mapnik/markers_placements/vertext_first.hpp b/include/mapnik/markers_placements/vertext_first.hpp index 9f142e160..7f6fada94 100644 --- a/include/mapnik/markers_placements/vertext_first.hpp +++ b/include/mapnik/markers_placements/vertext_first.hpp @@ -69,6 +69,10 @@ public: if (agg::is_line_to(this->locator_.vertex(&x1, &y1))) { angle = std::atan2(y1 - y0, x1 - x0); + if (!this->set_direction(angle)) + { + return false; + } } box2d box = this->perform_transform(angle, x, y); diff --git a/include/mapnik/markers_placements/vertext_last.hpp b/include/mapnik/markers_placements/vertext_last.hpp index 456687003..1c85c95b3 100644 --- a/include/mapnik/markers_placements/vertext_last.hpp +++ b/include/mapnik/markers_placements/vertext_last.hpp @@ -74,6 +74,10 @@ public: if (agg::is_line_to(command1)) { angle = std::atan2(y0 - y1, x0 - x1); + if (!this->set_direction(angle)) + { + return false; + } } box2d box = this->perform_transform(angle, x, y); diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index d15c1e10e..8a4745acd 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -91,6 +91,7 @@ enum class property_types : std::uint8_t target_justify_alignment, target_vertical_alignment, target_upright, + target_direction, target_font_feature_settings }; @@ -184,6 +185,7 @@ ENUM_FROM_STRING( horizontal_alignment_enum ) ENUM_FROM_STRING( justify_alignment_enum ) ENUM_FROM_STRING( text_transform_enum ) ENUM_FROM_STRING( text_upright_enum ) +ENUM_FROM_STRING( direction_enum ) ENUM_FROM_STRING( gamma_method_enum ) // enum diff --git a/include/mapnik/symbolizer_default_values.hpp b/include/mapnik/symbolizer_default_values.hpp index 8816d7c18..c793acbde 100644 --- a/include/mapnik/symbolizer_default_values.hpp +++ b/include/mapnik/symbolizer_default_values.hpp @@ -329,6 +329,13 @@ struct symbolizer_default static marker_multi_policy_enum value() { return MARKER_EACH_MULTI; } }; +// direction +template <> +struct symbolizer_default +{ + static direction_enum value() { return DIRECTION_RIGHT; } +}; + // placement // colorizer diff --git a/include/mapnik/symbolizer_enumerations.hpp b/include/mapnik/symbolizer_enumerations.hpp index 7f1c556c4..beca46835 100644 --- a/include/mapnik/symbolizer_enumerations.hpp +++ b/include/mapnik/symbolizer_enumerations.hpp @@ -189,6 +189,21 @@ enum text_upright_enum : std::uint8_t DEFINE_ENUM(text_upright_e, text_upright_enum); +enum direction_enum : std::uint8_t +{ + DIRECTION_LEFT, + DIRECTION_RIGHT, + DIRECTION_LEFT_ONLY, + DIRECTION_RIGHT_ONLY, + DIRECTION_AUTO, + DIRECTION_AUTO_DOWN, + DIRECTION_UP, + DIRECTION_DOWN, + direction_enum_MAX +}; + +DEFINE_ENUM(direction_e, direction_enum); + enum gamma_method_enum : std::uint8_t { GAMMA_POWER, //agg::gamma_power diff --git a/include/mapnik/symbolizer_keys.hpp b/include/mapnik/symbolizer_keys.hpp index 4867d3764..ec8649da5 100644 --- a/include/mapnik/symbolizer_keys.hpp +++ b/include/mapnik/symbolizer_keys.hpp @@ -89,6 +89,7 @@ enum class keys : std::uint8_t justify_alignment, vertical_alignment, upright, + direction, avoid_edges, ff_settings, MAX_SYMBOLIZER_KEY diff --git a/src/load_map.cpp b/src/load_map.cpp index c2d7fa4a1..370a0aca5 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -996,6 +996,7 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node) set_symbolizer_property(sym, keys::image_transform, node); set_symbolizer_property(sym, keys::markers_placement_type, node); set_symbolizer_property(sym, keys::markers_multipolicy, node); + set_symbolizer_property(sym, keys::direction, node); parse_stroke(sym,node); rule.append(std::move(sym)); } diff --git a/src/symbolizer_enumerations.cpp b/src/symbolizer_enumerations.cpp index dfa91860d..f2a580237 100644 --- a/src/symbolizer_enumerations.cpp +++ b/src/symbolizer_enumerations.cpp @@ -177,6 +177,19 @@ static const char * text_upright_strings[] = { }; IMPLEMENT_ENUM(text_upright_e, text_upright_strings) +static const char * direction_strings[] = { + "left", + "right", + "left-only", + "right-only", + "auto", + "auto-down", + "up", + "down", + "" +}; +IMPLEMENT_ENUM(direction_e, direction_strings) + static const char * gamma_method_strings[] = { "power", //agg::gamma_power "linear", //agg::gamma_linear diff --git a/src/symbolizer_keys.cpp b/src/symbolizer_keys.cpp index b22fa2ed0..8d46e1873 100644 --- a/src/symbolizer_keys.cpp +++ b/src/symbolizer_keys.cpp @@ -157,6 +157,9 @@ static const property_meta_type key_meta[const_max_key] = property_meta_type{ "upright", [](enumeration_wrapper e) {return enumeration(text_upright_enum(e.value)).as_string();}, property_types::target_upright}, + property_meta_type{ "direction", [](enumeration_wrapper e) + {return enumeration(direction_enum(e.value)).as_string();}, + property_types::target_direction}, property_meta_type{ "avoid-edges",nullptr, property_types::target_bool }, property_meta_type{ "font-feature-settings", nullptr, property_types::target_font_feature_settings }, diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index e46f6a4f2..410a2bcf0 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -427,6 +427,7 @@ compile_get_opt_attr(vertical_alignment_e); compile_get_opt_attr(horizontal_alignment_e); compile_get_opt_attr(justify_alignment_e); compile_get_opt_attr(text_upright_e); +compile_get_opt_attr(direction_e); compile_get_opt_attr(halo_rasterizer_e); compile_get_opt_attr(expression_ptr); compile_get_opt_attr(font_feature_settings);