util/math: clamp, degrees, radians

Use common functions for degrees <-> radians conversions, except when
dealing with agg, where it makes sense to use available deg2rad/rad2deg
functions instead of including another header.
This commit is contained in:
Mickey Rose 2018-07-13 12:34:25 +02:00
parent 0a6e82e555
commit a0a2c78950
9 changed files with 41 additions and 32 deletions

View file

@ -28,6 +28,7 @@
#endif
#include <mapnik/global.hpp>
#include <mapnik/config.hpp>
#include <mapnik/util/math.hpp>
#include <mapnik/vertex.hpp>
#include <mapnik/vertex_cache.hpp>
@ -572,14 +573,16 @@ private:
{
// inside turn (sharp/obtuse angle)
MAPNIK_LOG_DEBUG(ctrans) << "offset_converter:"
<< " Sharp joint [<< inside turn " << int(joint_angle*180/M_PI)
<< " Sharp joint [<< inside turn "
<< static_cast<int>(util::degrees(joint_angle))
<< " degrees >>]";
}
else
{
// outside turn (reflex angle)
MAPNIK_LOG_DEBUG(ctrans) << "offset_converter:"
<< " Bulge joint >)) outside turn " << int(joint_angle*180/M_PI)
<< " Bulge joint >)) outside turn "
<< static_cast<int>(util::degrees(joint_angle))
<< " degrees ((< with " << bulge_steps << " segments";
}
#endif

View file

@ -24,6 +24,7 @@
#define MAPNIK_SVG_GRAMMAR_CONFIG_X3_HPP
#include <mapnik/svg/svg_path_parser.hpp>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/spirit/home/x3.hpp>
@ -44,8 +45,6 @@ using svg_parse_context_type = x3::context<relative_tag, std::reference_wrapper<
x3::context<svg_path_tag,std::reference_wrapper<svg_converter_type> const,
phrase_parse_context_type>>;
inline double deg2rad(double deg) {return (M_PI * deg) / 180.0;}
}}}
#endif // MAPNIK_SVG_GRAMMAR_CONFIG_X3_HPP

View file

@ -24,8 +24,8 @@
#define MAPNIK_SVG_PATH_COMMANDS_HPP
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/config.hpp>
#include <mapnik/util/math.hpp>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
@ -35,12 +35,6 @@
namespace mapnik {
namespace svg {
inline double deg2rad(double deg)
{
return (M_PI * deg) / 180.0;
}
struct move_to
{
using result_type = void;
@ -137,7 +131,7 @@ struct arc_to
void operator()(PathType& path, T0 const& rv, T1 const& angle, T2 large_arc_flag, T3 sweep_flag, T4 const& v, T5 rel) const
{
path.arc_to(boost::fusion::at_c<0>(rv), boost::fusion::at_c<1>(rv),
deg2rad(angle), large_arc_flag, sweep_flag,
util::radians(angle), large_arc_flag, sweep_flag,
boost::fusion::at_c<0>(v), boost::fusion::at_c<1>(v),
rel);
}

View file

@ -24,9 +24,10 @@
#define MAPNIK_SVG_PATH_GRAMMAR_X3_DEF_HPP
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/config.hpp>
#include <mapnik/svg/svg_path_grammar_x3.hpp>
#include <mapnik/util/math.hpp>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
@ -112,7 +113,8 @@ auto const arc_to = [] (auto & ctx)
int sweep_flag = boost::fusion::at_c<3>(attr);
auto const& v = boost::fusion::at_c<4>(attr);
x3::get<svg_path_tag>(ctx).get().arc_to(std::get<0>(p),std::get<1>(p),
deg2rad(angle), large_arc_flag, sweep_flag,
util::radians(angle),
large_arc_flag, sweep_flag,
std::get<0>(v),std::get<1>(v),
x3::get<relative_tag>(ctx));
};

View file

@ -25,6 +25,7 @@
// mapnik
#include <mapnik/svg/svg_transform_grammar_x3.hpp>
// boost::fusion
#pragma GCC diagnostic push
#include <mapnik/warning_ignore.hpp>
@ -66,12 +67,12 @@ auto const rotate_action = [] (auto const& ctx)
auto cy = boost::fusion::at_c<2>(attr) ? *boost::fusion::at_c<2>(attr) : 0.0;
if (cx == 0.0 && cy == 0.0)
{
tr = agg::trans_affine_rotation(deg2rad(a)) * tr;
tr = agg::trans_affine_rotation(agg::deg2rad(a)) * tr;
}
else
{
agg::trans_affine t = agg::trans_affine_translation(-cx, -cy);
t *= agg::trans_affine_rotation(deg2rad(a));
t *= agg::trans_affine_rotation(agg::deg2rad(a));
t *= agg::trans_affine_translation(cx, cy);
tr = t * tr;
}
@ -101,14 +102,14 @@ auto const skewX_action = [] (auto const& ctx)
{
auto & tr = x3::get<svg_transform_tag>(ctx).get();
auto skew_x = _attr(ctx);
tr = agg::trans_affine_skewing(deg2rad(skew_x), 0.0) * tr;
tr = agg::trans_affine_skewing(agg::deg2rad(skew_x), 0.0) * tr;
};
auto const skewY_action = [] (auto const& ctx)
{
auto & tr = x3::get<svg_transform_tag>(ctx).get();
auto skew_y= _attr(ctx);
tr = agg::trans_affine_skewing(0.0, deg2rad(skew_y)) * tr;
tr = agg::trans_affine_skewing(0.0, agg::deg2rad(skew_y)) * tr;
};
//exported rule

View file

@ -28,6 +28,7 @@
#include <mapnik/value.hpp>
#include <mapnik/transform/transform_expression.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/util/math.hpp>
#include <mapnik/util/variant.hpp>
#pragma GCC diagnostic push
@ -145,7 +146,7 @@ struct transform_processor
void operator() (rotate_node const& node) const
{
double angle = deg2rad(eval(node.angle_));
double angle = agg::deg2rad(eval(node.angle_));
double cx = eval(node.cx_, 0.0);
double cy = eval(node.cy_, 0.0);
transform_.translate(-cx, -cy);
@ -156,28 +157,19 @@ struct transform_processor
void operator() (skewX_node const& node) const
{
auto degrees = std::fmod(eval(node.angle_),90.0);
if (degrees < -89.0) degrees = -89.0;
else if (degrees > 89.0) degrees = 89.0;
auto angle = deg2rad(degrees);
auto angle = agg::deg2rad(util::clamp(degrees, -89.0, 89.0));
transform_.multiply(agg::trans_affine_skewing(angle, 0.0));
}
void operator() (skewY_node const& node) const
{
auto degrees = std::fmod(eval(node.angle_),90.0);
if (degrees < -89.0) degrees = -89.0;
else if (degrees > 89.0) degrees = 89.0;
auto angle = deg2rad(degrees);
auto angle = agg::deg2rad(util::clamp(degrees, -89.0, 89.0));
transform_.multiply(agg::trans_affine_skewing(0.0, angle));
}
private:
static double deg2rad(double d)
{
return d * M_PI / 180.0;
}
double eval(expr_node const& x) const
{
mapnik::evaluate<feature_type, value_type, variable_type> e(feature_,vars_);

View file

@ -30,6 +30,22 @@ namespace mapnik { namespace util {
constexpr double pi = 3.1415926535897932384626433832795;
constexpr double tau = 6.283185307179586476925286766559;
template <typename T>
constexpr T const& clamp(T const& v, T const& lo, T const& hi)
{
return v < lo ? lo : hi < v ? hi : v;
}
constexpr double degrees(double rad)
{
return rad * (360 / tau);
}
constexpr double radians(double deg)
{
return deg * (tau / 360);
}
MAPNIK_DECL double normalize_angle(double angle);
}}

View file

@ -27,6 +27,7 @@
#include <mapnik/feature.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/text/harfbuzz_shaper.hpp>
#include <mapnik/util/math.hpp>
#include <mapnik/make_unique.hpp>
#pragma GCC diagnostic push
@ -117,7 +118,7 @@ text_layout::text_layout(face_manager_freetype & font_manager,
if (!wrap_str.empty()) wrap_char_ = wrap_str[0];
wrap_width_ = util::apply_visitor(extract_value<value_double>(feature,attrs), layout_properties_.wrap_width);
double angle = util::apply_visitor(extract_value<value_double>(feature,attrs), layout_properties_.orientation);
orientation_.init(angle * M_PI/ 180.0);
orientation_.init(util::radians(angle));
wrap_before_ = util::apply_visitor(extract_value<value_bool>(feature,attrs), layout_properties_.wrap_before);
repeat_wrap_char_ = util::apply_visitor(extract_value<value_bool>(feature,attrs), layout_properties_.repeat_wrap_char);
rotate_displacement_ = util::apply_visitor(extract_value<value_bool>(feature,attrs), layout_properties_.rotate_displacement);

View file

@ -22,6 +22,7 @@
// mapnik
#include <mapnik/text/text_properties.hpp>
#include <mapnik/text/text_layout.hpp>
#include <mapnik/util/math.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/symbolizer.hpp>
@ -59,7 +60,7 @@ evaluated_text_properties_ptr evaluate_text_properties(text_symbolizer_propertie
prop->minimum_distance = util::apply_visitor(extract_value<value_double>(feature,attrs), text_prop.expressions.minimum_distance);
prop->minimum_padding = util::apply_visitor(extract_value<value_double>(feature,attrs), text_prop.expressions.minimum_padding);
prop->minimum_path_length = util::apply_visitor(extract_value<value_double>(feature,attrs), text_prop.expressions.minimum_path_length);
prop->max_char_angle_delta = util::apply_visitor(extract_value<value_double>(feature,attrs), text_prop.expressions.max_char_angle_delta) * M_PI/180;
prop->max_char_angle_delta = util::radians(util::apply_visitor(extract_value<value_double>(feature,attrs), text_prop.expressions.max_char_angle_delta));
prop->allow_overlap = util::apply_visitor(extract_value<value_bool>(feature,attrs), text_prop.expressions.allow_overlap);
prop->largest_bbox_only = util::apply_visitor(extract_value<value_bool>(feature,attrs), text_prop.expressions.largest_bbox_only);
prop->upright = util::apply_visitor(extract_value<text_upright_enum>(feature,attrs), text_prop.expressions.upright);