1
0
Fork 0
mirror of https://github.com/mapnik/mapnik.git synced 2025-09-21 22:02:53 +02:00
mapnik/include/mapnik/adaptive_smooth.hpp
Mathis Logemann 64054fade4 compiler independent warning ignore
Signed-off-by: Mathis Logemann <mathisloge@gmail.com>
2020-11-19 17:25:10 +01:00

139 lines
3.8 KiB
C++

#ifndef MAPNIK_ADAPTIVE_SMOOTH_HPP
#define MAPNIK_ADAPTIVE_SMOOTH_HPP
#include <mapnik/util/math.hpp>
#include <mapnik/warning.hpp>
MAPNIK_DISABLE_WARNING_PUSH
#include <mapnik/warning_ignore_agg.hpp>
#include "agg_conv_smooth_poly1.h"
MAPNIK_DISABLE_WARNING_POP
namespace mapnik
{
struct vcgen_smooth_calucate_adaptive
{
using result_type = std::pair<agg::point_d, agg::point_d>;
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<vcgen_smooth_calucate_adaptive>;
template<class VertexSource>
using conv_smooth_adaptive = agg::conv_smooth_curve<VertexSource, vcgen_smooth_adaptive>;
template <typename Geometry>
class smooth_converter
{
Geometry geom_;
using basic_impl_type = typename agg::conv_smooth_poly1_curve<Geometry>;
using adaptive_impl_type = conv_smooth_adaptive<Geometry>;
using impl_type = util::variant<basic_impl_type, adaptive_impl_type>;
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