From 2dde0eb25711f41c92c632073785afdfb8f533f5 Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Sat, 9 Feb 2019 15:24:12 +0000 Subject: [PATCH] Adaptive smooth --- deps/agg/include/agg_array.h | 23 ++ deps/agg/include/agg_conv_adaptor_vcgen.h | 3 + deps/agg/include/agg_conv_curve.h | 3 + deps/agg/include/agg_conv_smooth_poly1.h | 59 +++-- deps/agg/include/agg_vcgen_smooth_poly1.h | 222 ++++++++++++++++-- deps/agg/src/agg_vcgen_smooth_poly1.cpp | 225 ------------------- include/mapnik/adaptive_smooth.hpp | 138 ++++++++++++ include/mapnik/symbolizer.hpp | 2 + include/mapnik/symbolizer_default_values.hpp | 6 + include/mapnik/symbolizer_enumerations.hpp | 9 + include/mapnik/symbolizer_keys.hpp | 1 + include/mapnik/vertex_converters.hpp | 4 +- src/load_map.cpp | 1 + src/symbolizer_enumerations.cpp | 8 + src/symbolizer_keys.cpp | 4 + test/data-visual | 2 +- 16 files changed, 440 insertions(+), 270 deletions(-) delete mode 100644 deps/agg/src/agg_vcgen_smooth_poly1.cpp create mode 100644 include/mapnik/adaptive_smooth.hpp diff --git a/deps/agg/include/agg_array.h b/deps/agg/include/agg_array.h index d07e46b0b..47bb2da53 100644 --- a/deps/agg/include/agg_array.h +++ b/deps/agg/include/agg_array.h @@ -124,6 +124,15 @@ namespace agg memcpy(m_array, v.m_array, sizeof(T) * m_size); } + pod_array(self_type && rhs) + { + pod_allocator::deallocate(m_array, m_size); + m_array = rhs.m_array; + m_size = rhs.m_size; + rhs.m_array = nullptr; + rhs.m_size = 0; + } + void resize(unsigned _size) { if(_size != m_size) @@ -172,6 +181,8 @@ namespace agg pod_vector(const pod_vector&); const pod_vector& operator = (const pod_vector&); + pod_vector(pod_vector && rhs); + // Set new capacity. All data is lost, size is set to zero. void capacity(unsigned cap, unsigned extra_tail=0); unsigned capacity() const { return m_capacity; } @@ -272,6 +283,18 @@ namespace agg memcpy(m_array, v.m_array, sizeof(T) * v.m_size); } + //------------------------------------------------------------------------ + template pod_vector::pod_vector(pod_vector && rhs) + { + pod_allocator::deallocate(m_array, m_capacity); + m_size = rhs.m_size; + m_capacity = rhs.m_capacity; + m_array = rhs.m_array; + rhs.m_size = 0; + rhs.m_capacity = 0; + rhs.m_array = nullptr; + } + //------------------------------------------------------------------------ template const pod_vector& pod_vector::operator = (const pod_vector&v) diff --git a/deps/agg/include/agg_conv_adaptor_vcgen.h b/deps/agg/include/agg_conv_adaptor_vcgen.h index ddbcef738..91a076e26 100644 --- a/deps/agg/include/agg_conv_adaptor_vcgen.h +++ b/deps/agg/include/agg_conv_adaptor_vcgen.h @@ -50,6 +50,9 @@ namespace agg m_source(&source), m_status(initial) {} + + conv_adaptor_vcgen(conv_adaptor_vcgen &&) = default; + void attach(VertexSource& source) { m_source = &source; } Generator& generator() { return m_generator; } diff --git a/deps/agg/include/agg_conv_curve.h b/deps/agg/include/agg_conv_curve.h index b75cfd522..c02b182b1 100644 --- a/deps/agg/include/agg_conv_curve.h +++ b/deps/agg/include/agg_conv_curve.h @@ -62,6 +62,9 @@ namespace agg explicit conv_curve(VertexSource& source) : m_source(&source), m_last_x(0.0), m_last_y(0.0) {} + + conv_curve(self_type &&) = default; + void attach(VertexSource& source) { m_source = &source; } void approximation_method(curve_approximation_method_e v) diff --git a/deps/agg/include/agg_conv_smooth_poly1.h b/deps/agg/include/agg_conv_smooth_poly1.h index 00ab6b6af..fd55085b5 100644 --- a/deps/agg/include/agg_conv_smooth_poly1.h +++ b/deps/agg/include/agg_conv_smooth_poly1.h @@ -28,53 +28,64 @@ namespace agg { - //-------------------------------------------------------conv_smooth_poly1 - template - struct conv_smooth_poly1 : - public conv_adaptor_vcgen + //-------------------------------------------------------conv_smooth + template + struct conv_smooth : + public conv_adaptor_vcgen { - typedef conv_adaptor_vcgen base_type; + typedef conv_adaptor_vcgen base_type; - conv_smooth_poly1(VertexSource& vs) : - conv_adaptor_vcgen(vs) + conv_smooth(VertexSource& vs) : + conv_adaptor_vcgen(vs) { } + conv_smooth(conv_smooth &&) = default; + + conv_smooth(const conv_smooth&) = delete; + const conv_smooth& + operator = (const conv_smooth&) = delete; + void smooth_value(double v) { base_type::generator().smooth_value(v); } double smooth_value() const { return base_type::generator().smooth_value(); } unsigned type() const { return base_type::type(); } - - private: - conv_smooth_poly1(const conv_smooth_poly1&); - const conv_smooth_poly1& - operator = (const conv_smooth_poly1&); }; + template + using conv_smooth_poly1 = conv_smooth; - - //-------------------------------------------------conv_smooth_poly1_curve - template - struct conv_smooth_poly1_curve : - public conv_curve > + //-------------------------------------------------conv_smooth_curve + template + struct conv_smooth_curve : + public conv_curve> { - conv_smooth_poly1_curve(VertexSource& vs) : - conv_curve >(m_smooth), + conv_smooth_curve(VertexSource& vs) : + conv_curve>(m_smooth), m_smooth(vs) { } + conv_smooth_curve(conv_smooth_curve && rhs) : + conv_curve>(std::move(rhs)), + m_smooth(std::move(rhs.m_smooth)) + { + this->attach(m_smooth); + } + + conv_smooth_curve(const conv_smooth_curve&) = delete; + const conv_smooth_curve& + operator = (const conv_smooth_curve&) = delete; + void smooth_value(double v) { m_smooth.generator().smooth_value(v); } double smooth_value() const { return m_smooth.generator().smooth_value(); } unsigned type() const { return m_smooth.type(); } private: - conv_smooth_poly1_curve(const conv_smooth_poly1_curve&); - const conv_smooth_poly1_curve& - operator = (const conv_smooth_poly1_curve&); - - conv_smooth_poly1 m_smooth; + conv_smooth m_smooth; }; + template + using conv_smooth_poly1_curve = conv_smooth_curve; } diff --git a/deps/agg/include/agg_vcgen_smooth_poly1.h b/deps/agg/include/agg_vcgen_smooth_poly1.h index 80fc0fb79..ad08a98de 100644 --- a/deps/agg/include/agg_vcgen_smooth_poly1.h +++ b/deps/agg/include/agg_vcgen_smooth_poly1.h @@ -23,13 +23,13 @@ namespace agg { - //======================================================vcgen_smooth_poly1 + //======================================================vcgen_smooth // - // See Implementation agg_vcgen_smooth_poly1.cpp // Smooth polygon generator // //------------------------------------------------------------------------ - class vcgen_smooth_poly1 + template + class vcgen_smooth { enum status_e { @@ -47,39 +47,223 @@ namespace agg public: typedef vertex_sequence vertex_storage; - vcgen_smooth_poly1(); + vcgen_smooth() : + m_src_vertices(), + m_smooth_value(0.5), + m_closed(0), + m_status(initial), + m_src_vertex(0) { } + + vcgen_smooth(vcgen_smooth &&) = default; void smooth_value(double v) { m_smooth_value = v * 0.5; } double smooth_value() const { return m_smooth_value * 2.0; } // Vertex Generator Interface - void remove_all(); - void add_vertex(double x, double y, unsigned cmd); + void remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_status = initial; + } + + void add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist(x, y)); + } + else + { + m_closed = get_close_flag(cmd); + } + } + } // Vertex Source Interface - void rewind(unsigned path_id); - unsigned vertex(double* x, double* y); + void rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(m_closed != 0); + } + m_status = ready; + m_src_vertex = 0; + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_src_vertices.size() < 2) + { + cmd = path_cmd_stop; + break; + } + + if(m_src_vertices.size() == 2) + { + *x = m_src_vertices[m_src_vertex].x; + *y = m_src_vertices[m_src_vertex].y; + m_src_vertex++; + if(m_src_vertex == 1) return path_cmd_move_to; + if(m_src_vertex == 2) return path_cmd_line_to; + cmd = path_cmd_stop; + break; + } + + cmd = path_cmd_move_to; + m_status = polygon; + m_src_vertex = 0; + + case polygon: + if(m_closed) + { + if(m_src_vertex >= m_src_vertices.size()) + { + *x = m_src_vertices[0].x; + *y = m_src_vertices[0].y; + m_status = end_poly; + return path_cmd_curve4; + } + } + else + { + if(m_src_vertex >= m_src_vertices.size() - 1) + { + *x = m_src_vertices[m_src_vertices.size() - 1].x; + *y = m_src_vertices[m_src_vertices.size() - 1].y; + m_status = end_poly; + return path_cmd_curve3; + } + } + + std::tie(m_ctrl1, m_ctrl2) = Calculate::apply( + m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.next(m_src_vertex), + m_src_vertices.next(m_src_vertex + 1), + m_smooth_value); + + *x = m_src_vertices[m_src_vertex].x; + *y = m_src_vertices[m_src_vertex].y; + m_src_vertex++; + + if(m_closed) + { + m_status = ctrl1; + return ((m_src_vertex == 1) ? + path_cmd_move_to : + path_cmd_curve4); + } + else + { + if(m_src_vertex == 1) + { + m_status = ctrl_b; + return path_cmd_move_to; + } + if(m_src_vertex >= m_src_vertices.size() - 1) + { + m_status = ctrl_e; + return path_cmd_curve3; + } + m_status = ctrl1; + return path_cmd_curve4; + } + break; + + case ctrl_b: + *x = m_ctrl2.x; + *y = m_ctrl2.y; + m_status = polygon; + return path_cmd_curve3; + + case ctrl_e: + *x = m_ctrl1.x; + *y = m_ctrl1.y; + m_status = polygon; + return path_cmd_curve3; + + case ctrl1: + *x = m_ctrl1.x; + *y = m_ctrl1.y; + m_status = ctrl2; + return path_cmd_curve4; + + case ctrl2: + *x = m_ctrl2.x; + *y = m_ctrl2.y; + m_status = polygon; + return path_cmd_curve4; + + case end_poly: + m_status = stop; + return path_cmd_end_poly | m_closed; + + case stop: + return path_cmd_stop; + } + } + return cmd; + } private: - vcgen_smooth_poly1(const vcgen_smooth_poly1&); - const vcgen_smooth_poly1& operator = (const vcgen_smooth_poly1&); - - void calculate(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2, - const vertex_dist& v3); + vcgen_smooth(const vcgen_smooth&); + const vcgen_smooth& operator = (const vcgen_smooth&); vertex_storage m_src_vertices; double m_smooth_value; unsigned m_closed; status_e m_status; unsigned m_src_vertex; - double m_ctrl1_x; - double m_ctrl1_y; - double m_ctrl2_x; - double m_ctrl2_y; + point_d m_ctrl1; + point_d m_ctrl2; }; + struct calculate_poly1 + { + using result_type = std::pair; + + static result_type apply(const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + const vertex_dist& v3, + double smooth_value) + { + double k1 = v0.dist / (v0.dist + v1.dist); + double k2 = v1.dist / (v1.dist + v2.dist); + + double xm1 = v0.x + (v2.x - v0.x) * k1; + double ym1 = v0.y + (v2.y - v0.y) * k1; + double xm2 = v1.x + (v3.x - v1.x) * k2; + double ym2 = v1.y + (v3.y - v1.y) * k2; + + return { + {v1.x + smooth_value * (v2.x - xm1), + v1.y + smooth_value * (v2.y - ym1)}, + {v2.x + smooth_value * (v1.x - xm2), + v2.y + smooth_value * (v1.y - ym2)} + }; + } + }; + + using vcgen_smooth_poly1 = vcgen_smooth; + } diff --git a/deps/agg/src/agg_vcgen_smooth_poly1.cpp b/deps/agg/src/agg_vcgen_smooth_poly1.cpp deleted file mode 100644 index eec9ca576..000000000 --- a/deps/agg/src/agg_vcgen_smooth_poly1.cpp +++ /dev/null @@ -1,225 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.4 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Smooth polygon generator -// -//---------------------------------------------------------------------------- - -#include "agg_vcgen_smooth_poly1.h" - -namespace agg -{ - -//------------------------------------------------------------------------ -vcgen_smooth_poly1::vcgen_smooth_poly1() : - m_src_vertices(), - m_smooth_value(0.5), - m_closed(0), - m_status(initial), - m_src_vertex(0) -{ -} - - -//------------------------------------------------------------------------ -void vcgen_smooth_poly1::remove_all() -{ - m_src_vertices.remove_all(); - m_closed = 0; - m_status = initial; -} - - -//------------------------------------------------------------------------ -void vcgen_smooth_poly1::add_vertex(double x, double y, unsigned cmd) -{ - m_status = initial; - if(is_move_to(cmd)) - { - m_src_vertices.modify_last(vertex_dist(x, y)); - } - else - { - if(is_vertex(cmd)) - { - m_src_vertices.add(vertex_dist(x, y)); - } - else - { - m_closed = get_close_flag(cmd); - } - } -} - - -//------------------------------------------------------------------------ -void vcgen_smooth_poly1::rewind(unsigned) -{ - if(m_status == initial) - { - m_src_vertices.close(m_closed != 0); - } - m_status = ready; - m_src_vertex = 0; -} - - -//------------------------------------------------------------------------ -void vcgen_smooth_poly1::calculate(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2, - const vertex_dist& v3) -{ - - double k1 = v0.dist / (v0.dist + v1.dist); - double k2 = v1.dist / (v1.dist + v2.dist); - - double xm1 = v0.x + (v2.x - v0.x) * k1; - double ym1 = v0.y + (v2.y - v0.y) * k1; - double xm2 = v1.x + (v3.x - v1.x) * k2; - double ym2 = v1.y + (v3.y - v1.y) * k2; - - m_ctrl1_x = v1.x + m_smooth_value * (v2.x - xm1); - m_ctrl1_y = v1.y + m_smooth_value * (v2.y - ym1); - m_ctrl2_x = v2.x + m_smooth_value * (v1.x - xm2); - m_ctrl2_y = v2.y + m_smooth_value * (v1.y - ym2); -} - - -//------------------------------------------------------------------------ -unsigned vcgen_smooth_poly1::vertex(double* x, double* y) -{ - unsigned cmd = path_cmd_line_to; - while(!is_stop(cmd)) - { - switch(m_status) - { - case initial: - rewind(0); - - case ready: - if(m_src_vertices.size() < 2) - { - cmd = path_cmd_stop; - break; - } - - if(m_src_vertices.size() == 2) - { - *x = m_src_vertices[m_src_vertex].x; - *y = m_src_vertices[m_src_vertex].y; - m_src_vertex++; - if(m_src_vertex == 1) return path_cmd_move_to; - if(m_src_vertex == 2) return path_cmd_line_to; - cmd = path_cmd_stop; - break; - } - - cmd = path_cmd_move_to; - m_status = polygon; - m_src_vertex = 0; - - case polygon: - if(m_closed) - { - if(m_src_vertex >= m_src_vertices.size()) - { - *x = m_src_vertices[0].x; - *y = m_src_vertices[0].y; - m_status = end_poly; - return path_cmd_curve4; - } - } - else - { - if(m_src_vertex >= m_src_vertices.size() - 1) - { - *x = m_src_vertices[m_src_vertices.size() - 1].x; - *y = m_src_vertices[m_src_vertices.size() - 1].y; - m_status = end_poly; - return path_cmd_curve3; - } - } - - calculate(m_src_vertices.prev(m_src_vertex), - m_src_vertices.curr(m_src_vertex), - m_src_vertices.next(m_src_vertex), - m_src_vertices.next(m_src_vertex + 1)); - - *x = m_src_vertices[m_src_vertex].x; - *y = m_src_vertices[m_src_vertex].y; - m_src_vertex++; - - if(m_closed) - { - m_status = ctrl1; - return ((m_src_vertex == 1) ? - path_cmd_move_to : - path_cmd_curve4); - } - else - { - if(m_src_vertex == 1) - { - m_status = ctrl_b; - return path_cmd_move_to; - } - if(m_src_vertex >= m_src_vertices.size() - 1) - { - m_status = ctrl_e; - return path_cmd_curve3; - } - m_status = ctrl1; - return path_cmd_curve4; - } - break; - - case ctrl_b: - *x = m_ctrl2_x; - *y = m_ctrl2_y; - m_status = polygon; - return path_cmd_curve3; - - case ctrl_e: - *x = m_ctrl1_x; - *y = m_ctrl1_y; - m_status = polygon; - return path_cmd_curve3; - - case ctrl1: - *x = m_ctrl1_x; - *y = m_ctrl1_y; - m_status = ctrl2; - return path_cmd_curve4; - - case ctrl2: - *x = m_ctrl2_x; - *y = m_ctrl2_y; - m_status = polygon; - return path_cmd_curve4; - - case end_poly: - m_status = stop; - return path_cmd_end_poly | m_closed; - - case stop: - return path_cmd_stop; - } - } - return cmd; -} - -} - diff --git a/include/mapnik/adaptive_smooth.hpp b/include/mapnik/adaptive_smooth.hpp new file mode 100644 index 000000000..e2d5004ef --- /dev/null +++ b/include/mapnik/adaptive_smooth.hpp @@ -0,0 +1,138 @@ +#ifndef MAPNIK_ADAPTIVE_SMOOTH_HPP +#define MAPNIK_ADAPTIVE_SMOOTH_HPP + +#include + +#pragma GCC diagnostic push +#include +#include "agg_conv_smooth_poly1.h" +#pragma GCC diagnostic pop + +namespace mapnik +{ + +struct vcgen_smooth_calucate_adaptive +{ + using result_type = std::pair; + using vertex_type = agg::vertex_dist; + + static result_type apply(vertex_type const& v0, + vertex_type const& v1, + vertex_type const& v2, + vertex_type const& v3, + double smooth_value) + { + double k1 = v0.dist / (v0.dist + v1.dist); + double k2 = v1.dist / (v1.dist + v2.dist); + + double xm1 = v0.x + (v2.x - v0.x) * k1; + double ym1 = v0.y + (v2.y - v0.y) * k1; + double xm2 = v1.x + (v3.x - v1.x) * k2; + double ym2 = v1.y + (v3.y - v1.y) * k2; + + double s1 = 0; + double s2 = 0; + + if (v1.dist > 0.0) + { + if (v0.dist > 0.0) + { + double dot1 = (v0.x - v1.x) * (v2.x - v1.x) + (v0.y - v1.y) * (v2.y - v1.y); + double a1 = std::acos(dot1 / (v0.dist * v1.dist)); + if (a1 >= util::pi * 0.5) + { + s1 = (a1 - util::pi * 0.5) / (util::pi * 0.5); + } + } + + if (v2.dist > 0.0) + { + double dot2 = (v1.x - v2.x) * (v3.x - v2.x) + (v1.y - v2.y) * (v3.y - v2.y); + double a2 = std::acos(dot2 / (v1.dist * v2.dist)); + if (a2 >= util::pi * 0.5) + { + s2 = (a2 - util::pi * 0.5) / (util::pi * 0.5); + } + } + } + + return { + {v1.x + s1 * smooth_value * (v2.x - xm1), + v1.y + s1 * smooth_value * (v2.y - ym1)}, + {v2.x + s2 * smooth_value * (v1.x - xm2), + v2.y + s2 * smooth_value * (v1.y - ym2)} + }; + } +}; + +using vcgen_smooth_adaptive = agg::vcgen_smooth; + +template +using conv_smooth_adaptive = agg::conv_smooth_curve; + +template +class smooth_converter +{ + Geometry geom_; + + using basic_impl_type = typename agg::conv_smooth_poly1_curve; + using adaptive_impl_type = conv_smooth_adaptive; + using impl_type = util::variant; + impl_type impl_; + + impl_type init_impl(smooth_algorithm_enum algo, Geometry & geom) const + { + switch(algo) + { + case SMOOTH_ALGORITHM_ADAPTIVE: + return adaptive_impl_type(geom); + case SMOOTH_ALGORITHM_BASIC: + default: + break; + } + return basic_impl_type(geom); + } + +public: + smooth_converter(Geometry & geom) : + geom_(geom), + impl_(std::move(init_impl(SMOOTH_ALGORITHM_BASIC, geom))) + {} + + void algorithm(smooth_algorithm_enum algo) + { + impl_ = init_impl(algo, geom_); + } + + void smooth_value(double v) + { + return util::apply_visitor([=](auto & impl) { + impl.smooth_value(v); + }, impl_); + } + + void rewind(unsigned path_id) + { + return util::apply_visitor([=](auto & impl) { + return impl.rewind(path_id); + }, impl_); + } + + unsigned vertex(double* x, double* y) + { + return util::apply_visitor([=](auto & impl) { + return impl.vertex(x, y); + }, impl_); + } + + unsigned type() const + { + return util::apply_visitor([](auto const& impl) { + return impl.type(); + }, impl_); + } +}; + +} + +#endif // MAPNIK_ADAPTIVE_SMOOTH_HPP diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index 1c9f7a23a..31e756b6d 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -96,6 +96,7 @@ enum class property_types : std::uint8_t target_direction, target_font_feature_settings, target_line_pattern, + target_smooth_algorithm, }; template @@ -191,6 +192,7 @@ ENUM_FROM_STRING( text_upright_enum ) ENUM_FROM_STRING( direction_enum ) ENUM_FROM_STRING( gamma_method_enum ) ENUM_FROM_STRING( line_pattern_enum ) +ENUM_FROM_STRING( smooth_algorithm_enum ) // enum template diff --git a/include/mapnik/symbolizer_default_values.hpp b/include/mapnik/symbolizer_default_values.hpp index e19b2b67a..4e7c7c06a 100644 --- a/include/mapnik/symbolizer_default_values.hpp +++ b/include/mapnik/symbolizer_default_values.hpp @@ -383,6 +383,12 @@ struct symbolizer_default static value_double value() { return 0.0; } }; +template <> +struct symbolizer_default +{ + static smooth_algorithm_enum value() { return SMOOTH_ALGORITHM_BASIC; } +}; + } // namespace mapnik #endif // MAPNIK_SYMBOLIZER_DEFAULT_VALUES_HPP diff --git a/include/mapnik/symbolizer_enumerations.hpp b/include/mapnik/symbolizer_enumerations.hpp index 53911ff9d..e7e3033c3 100644 --- a/include/mapnik/symbolizer_enumerations.hpp +++ b/include/mapnik/symbolizer_enumerations.hpp @@ -231,6 +231,15 @@ enum line_pattern_enum : std::uint8_t DEFINE_ENUM (line_pattern_e, line_pattern_enum ); +enum smooth_algorithm_enum : std::uint8_t +{ + SMOOTH_ALGORITHM_BASIC = 0, + SMOOTH_ALGORITHM_ADAPTIVE, + smooth_algorithm_enum_MAX +}; + +DEFINE_ENUM (smooth_algorithm_e, smooth_algorithm_enum ); + } #endif //MAPNIK_SYMBOLIZER_ENUMERATIONS_HPP diff --git a/include/mapnik/symbolizer_keys.hpp b/include/mapnik/symbolizer_keys.hpp index 1822be827..42200d6e5 100644 --- a/include/mapnik/symbolizer_keys.hpp +++ b/include/mapnik/symbolizer_keys.hpp @@ -67,6 +67,7 @@ enum class keys : std::uint8_t mesh_size, premultiplied, smooth, + smooth_algorithm, simplify_algorithm, simplify_tolerance, halo_rasterizer, diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index 73ef786e1..c0b2b03c2 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #pragma GCC diagnostic push #include @@ -77,11 +78,12 @@ template struct converter_traits { using geometry_type = T; - using conv_type = typename agg::conv_smooth_poly1_curve; + using conv_type = smooth_converter; template static void setup(geometry_type & geom, Args const& args) { + geom.algorithm(get(args.sym, args.feature, args.vars)); geom.smooth_value(get(args.sym, args.feature, args.vars)); } }; diff --git a/src/load_map.cpp b/src/load_map.cpp index 1b94bb2da..919971d45 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -1010,6 +1010,7 @@ void map_parser::parse_symbolizer_base(symbolizer_base &sym, xml_node const& nod set_symbolizer_property(sym, keys::comp_op, node); set_symbolizer_property(sym, keys::geometry_transform, node); set_symbolizer_property(sym, keys::simplify_algorithm, node); + set_symbolizer_property(sym, keys::smooth_algorithm, node); set_symbolizer_property(sym, keys::extend, node); } diff --git a/src/symbolizer_enumerations.cpp b/src/symbolizer_enumerations.cpp index 1eee34b9c..b8afc75a5 100644 --- a/src/symbolizer_enumerations.cpp +++ b/src/symbolizer_enumerations.cpp @@ -215,4 +215,12 @@ static const char * line_pattern_strings[] = { IMPLEMENT_ENUM( line_pattern_e, line_pattern_strings ) +static const char * smooth_algorithm_strings[] = { + "basic", + "adaptive", + "" +}; + +IMPLEMENT_ENUM( smooth_algorithm_e, smooth_algorithm_strings ) + } // namespace mapnik diff --git a/src/symbolizer_keys.cpp b/src/symbolizer_keys.cpp index 748b70392..b3b423850 100644 --- a/src/symbolizer_keys.cpp +++ b/src/symbolizer_keys.cpp @@ -95,6 +95,10 @@ static const property_meta_type key_meta[const_max_key] = property_meta_type{ "mesh-size", nullptr, property_types::target_double }, property_meta_type{ "premultiplied", nullptr, property_types::target_bool }, property_meta_type{ "smooth", nullptr, property_types::target_double }, + property_meta_type{ "smooth-algorithm", + [](enumeration_wrapper e) + {return enumeration(smooth_algorithm_enum(e.value)).as_string();}, + property_types::target_smooth_algorithm }, property_meta_type{ "simplify-algorithm", [](enumeration_wrapper e) { diff --git a/test/data-visual b/test/data-visual index b122c5b5b..1bccb46ba 160000 --- a/test/data-visual +++ b/test/data-visual @@ -1 +1 @@ -Subproject commit b122c5b5b072c2e13d23ad4df2d00d77f553c81a +Subproject commit 1bccb46badded81a9ccfb54851ece45df56c695c