+ support configurable vertex converter

This commit is contained in:
Artem Pavlenko 2012-04-03 19:49:57 +01:00
parent 6236a63156
commit e7f0e8aac0
4 changed files with 122 additions and 145 deletions

View file

@ -23,8 +23,9 @@
#ifndef MAPNIK_VERTEX_CONVERTERS_HPP #ifndef MAPNIK_VERTEX_CONVERTERS_HPP
#define MAPNIK_VERTEX_CONVERTERS_HPP #define MAPNIK_VERTEX_CONVERTERS_HPP
// boost
#include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_same.hpp>
// mpl
#include <boost/mpl/vector.hpp> #include <boost/mpl/vector.hpp>
#include <boost/mpl/push_back.hpp> #include <boost/mpl/push_back.hpp>
#include <boost/mpl/set.hpp> #include <boost/mpl/set.hpp>
@ -35,7 +36,6 @@
#include <boost/mpl/size.hpp> #include <boost/mpl/size.hpp>
#include <boost/mpl/at.hpp> #include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp> #include <boost/mpl/int.hpp>
// fusion // fusion
#include <boost/fusion/container/vector.hpp> #include <boost/fusion/container/vector.hpp>
#include <boost/fusion/include/at_c.hpp> #include <boost/fusion/include/at_c.hpp>
@ -46,11 +46,15 @@
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/array.hpp> #include <boost/array.hpp>
// mapnik
#include <mapnik/agg_helpers.hpp>
// agg // agg
#include "agg_conv_clip_polygon.h" #include "agg_conv_clip_polygon.h"
#include "agg_conv_clip_polyline.h" #include "agg_conv_clip_polyline.h"
#include "agg_conv_smooth_poly1.h" #include "agg_conv_smooth_poly1.h"
#include "agg_conv_stroke.h"
#include "agg_conv_dash.h"
namespace mapnik { namespace mapnik {
@ -58,6 +62,8 @@ struct transform_tag {};
struct clip_line_tag {}; struct clip_line_tag {};
struct clip_poly_tag {}; struct clip_poly_tag {};
struct smooth_tag {}; struct smooth_tag {};
struct stroke_tag {};
struct dash_tag {};
namespace detail { namespace detail {
@ -67,7 +73,7 @@ struct converter_traits
typedef T0 geometry_type; typedef T0 geometry_type;
typedef geometry_type conv_type; typedef geometry_type conv_type;
template <typename Args> template <typename Args>
static void setup(geometry_type & geom, Args & args) static void setup(geometry_type & geom, Args & args)
{ {
throw "BOOM!"; throw "BOOM!";
} }
@ -76,11 +82,11 @@ struct converter_traits
template <typename T> template <typename T>
struct converter_traits<T,mapnik::smooth_tag> struct converter_traits<T,mapnik::smooth_tag>
{ {
typedef T geometry_type; typedef T geometry_type;
typedef typename agg::conv_smooth_poly1_curve<geometry_type> conv_type; typedef typename agg::conv_smooth_poly1_curve<geometry_type> conv_type;
template <typename Args> template <typename Args>
static void setup(geometry_type & geom, Args & args) static void setup(geometry_type & geom, Args & args)
{ {
geom.smooth_value(boost::fusion::at_c<2>(args).smooth()); geom.smooth_value(boost::fusion::at_c<2>(args).smooth());
} }
@ -90,14 +96,57 @@ struct converter_traits<T,mapnik::smooth_tag>
template <typename T> template <typename T>
struct converter_traits<T, mapnik::clip_line_tag> struct converter_traits<T, mapnik::clip_line_tag>
{ {
typedef T geometry_type; typedef T geometry_type;
typedef typename agg::conv_clip_polyline<geometry_type> conv_type; typedef typename agg::conv_clip_polyline<geometry_type> conv_type;
template <typename Args> template <typename Args>
static void setup(geometry_type & geom, Args & args) static void setup(geometry_type & geom, Args & args)
{ {
typename boost::mpl::at<Args,boost::mpl::int_<0> >::type const& box = boost::fusion::at_c<0>(args); typename boost::mpl::at<Args,boost::mpl::int_<0> >::type const& box = boost::fusion::at_c<0>(args);
geom.clip_box(box.x0,box.y0,box.x1,box.y1); geom.clip_box(box.minx(),box.miny(),box.maxx(),box.maxy());
}
};
template <typename T>
struct converter_traits<T, mapnik::dash_tag>
{
typedef T geometry_type;
typedef typename agg::conv_dash<geometry_type> conv_type;
template <typename Args>
static void setup(geometry_type & geom, Args & args)
{
typename boost::mpl::at<Args,boost::mpl::int_<2> >::type const& sym = boost::fusion::at_c<2>(args);
double scale_factor = 1.0; //FIXME
stroke const& stroke_ = sym.get_stroke();
dash_array const& d = stroke_.get_dash_array();
dash_array::const_iterator itr = d.begin();
dash_array::const_iterator end = d.end();
for (;itr != end;++itr)
{
geom.add_dash(itr->first * scale_factor,
itr->second * scale_factor);
}
}
};
template <typename T>
struct converter_traits<T, mapnik::stroke_tag>
{
typedef T geometry_type;
typedef typename agg::conv_stroke<geometry_type> conv_type;
template <typename Args>
static void setup(geometry_type & geom, Args & args)
{
typename boost::mpl::at<Args,boost::mpl::int_<2> >::type const& sym = boost::fusion::at_c<2>(args);
stroke const& stroke_ = sym.get_stroke();
set_join_caps(stroke_,geom);
geom.generator().miter_limit(4.0); // FIXME : make configurable
double scale_factor = 1.0; //FIXME
geom.generator().width(stroke_.get_width() * scale_factor);
} }
}; };
@ -105,13 +154,13 @@ struct converter_traits<T, mapnik::clip_line_tag>
template <typename T> template <typename T>
struct converter_traits<T,mapnik::clip_poly_tag> struct converter_traits<T,mapnik::clip_poly_tag>
{ {
typedef T geometry_type; typedef T geometry_type;
typedef typename agg::conv_clip_polygon<geometry_type> conv_type; typedef typename agg::conv_clip_polygon<geometry_type> conv_type;
template <typename Args> template <typename Args>
static void setup(geometry_type & geom, Args & args) static void setup(geometry_type & geom, Args & args)
{ {
typename boost::mpl::at<Args,boost::mpl::int_<0> >::type const& box = boost::fusion::at_c<0>(args); typename boost::mpl::at<Args,boost::mpl::int_<0> >::type const& box = boost::fusion::at_c<0>(args);
geom.clip_box(box.minx(),box.miny(),box.maxx(),box.maxy()); geom.clip_box(box.minx(),box.miny(),box.maxx(),box.maxy());
} }
}; };
@ -120,11 +169,11 @@ struct converter_traits<T,mapnik::clip_poly_tag>
template <typename T> template <typename T>
struct converter_traits<T,mapnik::transform_tag> struct converter_traits<T,mapnik::transform_tag>
{ {
typedef T geometry_type; typedef T geometry_type;
typedef coord_transform2<CoordTransform, geometry_type> conv_type; typedef coord_transform2<CoordTransform, geometry_type> conv_type;
template <typename Args> template <typename Args>
static void setup(geometry_type & geom, Args & args) static void setup(geometry_type & geom, Args & args)
{ {
typename boost::mpl::at<Args,boost::mpl::int_<3> >::type const& tr = boost::fusion::at_c<3>(args); typename boost::mpl::at<Args,boost::mpl::int_<3> >::type const& tr = boost::fusion::at_c<3>(args);
typename boost::mpl::at<Args,boost::mpl::int_<4> >::type const& prj_trans = boost::fusion::at_c<4>(args); typename boost::mpl::at<Args,boost::mpl::int_<4> >::type const& prj_trans = boost::fusion::at_c<4>(args);
@ -137,65 +186,65 @@ template <bool>
struct converter_fwd struct converter_fwd
{ {
template <typename Base, typename T0,typename T1,typename T2, typename Iter,typename End> template <typename Base, typename T0,typename T1,typename T2, typename Iter,typename End>
static void forward(Base& base, T0 & geom,T1 & args) static void forward(Base& base, T0 & geom,T1 & args)
{ {
typedef T0 geometry_type; typedef T0 geometry_type;
typedef T2 conv_tag; typedef T2 conv_tag;
typedef typename detail::converter_traits<geometry_type,conv_tag>::conv_type conv_type; typedef typename detail::converter_traits<geometry_type,conv_tag>::conv_type conv_type;
conv_type conv(geom); conv_type conv(geom);
detail::converter_traits<conv_type,conv_tag>::setup(conv,args); detail::converter_traits<conv_type,conv_tag>::setup(conv,args);
base.template dispatch<Iter,End>(conv, typename boost::is_same<Iter,End>::type()); base.template dispatch<Iter,End>(conv, typename boost::is_same<Iter,End>::type());
} }
}; };
template <> template <>
struct converter_fwd<true> struct converter_fwd<true>
{ {
template <typename Base, typename T0,typename T1,typename T2, typename Iter,typename End> template <typename Base, typename T0,typename T1,typename T2, typename Iter,typename End>
static void forward(Base& base, T0 & geom,T1 & args) static void forward(Base& base, T0 & geom,T1 & args)
{ {
base.template dispatch<Iter,End>(geom, typename boost::is_same<Iter,End>::type()); base.template dispatch<Iter,End>(geom, typename boost::is_same<Iter,End>::type());
} }
}; };
template <typename A, typename C> template <typename A, typename C>
struct dispatcher struct dispatcher
{ {
typedef dispatcher this_type; typedef dispatcher this_type;
typedef A args_type; typedef A args_type;
typedef C conv_types; typedef C conv_types;
dispatcher(args_type args) dispatcher(args_type args)
: args_(args) : args_(args)
{ {
std::memset(&vec_[0], 0, sizeof(unsigned)*vec_.size()); std::memset(&vec_[0], 0, sizeof(unsigned)*vec_.size());
} }
template <typename Iter, typename End, typename Geometry> template <typename Iter, typename End, typename Geometry>
void dispatch(Geometry & geom, boost::mpl::true_) void dispatch(Geometry & geom, boost::mpl::true_)
{ {
boost::fusion::at_c<1>(args_).add_path(geom); boost::fusion::at_c<1>(args_).add_path(geom);
} }
template <typename Iter, typename End, typename Geometry> template <typename Iter, typename End, typename Geometry>
void dispatch(Geometry & geom, boost::mpl::false_) void dispatch(Geometry & geom, boost::mpl::false_)
{ {
typedef typename boost::mpl::deref<Iter>::type conv_tag; typedef typename boost::mpl::deref<Iter>::type conv_tag;
typedef typename detail::converter_traits<Geometry,conv_tag>::conv_type conv_type; typedef typename detail::converter_traits<Geometry,conv_tag>::conv_type conv_type;
typedef typename boost::mpl::next<Iter>::type Next; typedef typename boost::mpl::next<Iter>::type Next;
std::size_t index = boost::mpl::distance<Iter,End>::value - 1; std::size_t index = boost::mpl::distance<Iter,End>::value - 1;
if (vec_[index] == 1) if (vec_[index] == 1)
{ {
converter_fwd<boost::is_same<Geometry,conv_type>::value>:: converter_fwd<boost::is_same<Geometry,conv_type>::value>::
template forward<this_type,Geometry,args_type,conv_tag,Next,End>(*this,geom,args_); template forward<this_type,Geometry,args_type,conv_tag,Next,End>(*this,geom,args_);
} }
else else
{ {
converter_fwd<boost::mpl::true_::value>:: converter_fwd<boost::mpl::true_::value>::
template forward<this_type,Geometry,args_type,conv_tag,Next,End>(*this,geom,args_); template forward<this_type,Geometry,args_type,conv_tag,Next,End>(*this,geom,args_);
} }
} }
template <typename Geometry> template <typename Geometry>
@ -203,11 +252,11 @@ struct dispatcher
{ {
typedef typename boost::mpl::begin<conv_types>::type begin; typedef typename boost::mpl::begin<conv_types>::type begin;
typedef typename boost::mpl::end <conv_types>::type end; typedef typename boost::mpl::end <conv_types>::type end;
dispatch<begin,end,Geometry>(geom, boost::false_type()); dispatch<begin,end,Geometry>(geom, boost::false_type());
} }
boost::array<unsigned, boost::mpl::size<conv_types>::value> vec_; boost::array<unsigned, boost::mpl::size<conv_types>::value> vec_;
args_type args_; args_type args_;
}; };
} }
@ -215,7 +264,7 @@ struct dispatcher
template <typename B, typename R, typename S, typename P, typename T, typename C > template <typename B, typename R, typename S, typename P, typename T, typename C >
struct vertex_converter : private boost::noncopyable struct vertex_converter : private boost::noncopyable
{ {
typedef C conv_types; typedef C conv_types;
typedef B bbox_type; typedef B bbox_type;
typedef R rasterizer_type; typedef R rasterizer_type;
@ -224,29 +273,29 @@ struct vertex_converter : private boost::noncopyable
typedef T trans_type; typedef T trans_type;
typedef typename boost::fusion::vector typedef typename boost::fusion::vector
< <
bbox_type const&, bbox_type const&,
rasterizer_type&, rasterizer_type&,
symbolizer_type const&, symbolizer_type const&,
trans_type const&, trans_type const&,
proj_trans_type const& proj_trans_type const&
> args_type; > args_type;
vertex_converter(bbox_type const& b, rasterizer_type & ras, vertex_converter(bbox_type const& b, rasterizer_type & ras,
symbolizer_type const& sym, trans_type & tr, proj_trans_type const& prj_trans) symbolizer_type const& sym, trans_type & tr, proj_trans_type const& prj_trans)
: disp_(args_type(boost::cref(b),boost::ref(ras), : disp_(args_type(boost::cref(b),boost::ref(ras),
boost::cref(sym),boost::cref(tr), boost::cref(sym),boost::cref(tr),
boost::cref(prj_trans))) {} boost::cref(prj_trans))) {}
template <typename Geometry> template <typename Geometry>
void apply(Geometry & geom) void apply(Geometry & geom)
{ {
typedef Geometry geometry_type; typedef Geometry geometry_type;
//BOOST_FOREACH(geometry_type & geom, cont) //BOOST_FOREACH(geometry_type & geom, cont)
{ {
disp_.template apply<geometry_type>(geom); disp_.template apply<geometry_type>(geom);
} }
} }
template <typename Conv> template <typename Conv>
void set() void set()
{ {
@ -256,8 +305,8 @@ struct vertex_converter : private boost::noncopyable
if (index < disp_.vec_.size()) if (index < disp_.vec_.size())
disp_.vec_[index]=1; disp_.vec_[index]=1;
} }
detail::dispatcher<args_type,conv_types> disp_; detail::dispatcher<args_type,conv_types> disp_;
}; };

View file

@ -83,8 +83,7 @@ void agg_renderer<T>::process(line_pattern_symbolizer const& sym,
pattern_source source(*(*pat)); pattern_source source(*(*pat));
pattern_type pattern (filter,source); pattern_type pattern (filter,source);
renderer_type ren(ren_base, pattern); renderer_type ren(ren_base, pattern);
// TODO - should be sensitive to buffer size
ren.clip_box(0,0,width_,height_);
rasterizer_type ras(ren); rasterizer_type ras(ren);
//metawriter_with_properties writer = sym.get_metawriter(); //metawriter_with_properties writer = sym.get_metawriter();
for (unsigned i=0;i<feature->num_geometries();++i) for (unsigned i=0;i<feature->num_geometries();++i)

View file

@ -26,7 +26,7 @@
#include <mapnik/agg_helpers.hpp> #include <mapnik/agg_helpers.hpp>
#include <mapnik/agg_rasterizer.hpp> #include <mapnik/agg_rasterizer.hpp>
#include <mapnik/line_symbolizer.hpp> #include <mapnik/line_symbolizer.hpp>
#include <mapnik/vertex_converters.hpp>
// agg // agg
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_rendering_buffer.h" #include "agg_rendering_buffer.h"
@ -39,8 +39,6 @@
#include "agg_conv_dash.h" #include "agg_conv_dash.h"
#include "agg_renderer_outline_aa.h" #include "agg_renderer_outline_aa.h"
#include "agg_rasterizer_outline_aa.h" #include "agg_rasterizer_outline_aa.h"
#include "agg_conv_clip_polyline.h"
#include "agg_conv_smooth_poly1.h"
// stl // stl
#include <string> #include <string>
@ -65,13 +63,16 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
//agg::pixfmt_rgba32 pixf(buf); //agg::pixfmt_rgba32 pixf(buf);
aa_renderer::pixel_format_type pixf(buf); aa_renderer::pixel_format_type pixf(buf);
box2d<double> ext = query_extent_ * 1.1; box2d<double> ext = query_extent_ * 1.1;
if (sym.get_rasterizer() == RASTERIZER_FAST) if (sym.get_rasterizer() == RASTERIZER_FAST)
{ {
/*
typedef agg::renderer_base<aa_renderer::pixel_format_type> ren_base; typedef agg::renderer_base<aa_renderer::pixel_format_type> ren_base;
typedef agg::renderer_outline_aa<ren_base> renderer_type; typedef agg::renderer_outline_aa<ren_base> renderer_type;
typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type; typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type; //typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
//typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
agg::line_profile_aa profile; agg::line_profile_aa profile;
profile.width(stroke_.get_width() * scale_factor_); profile.width(stroke_.get_width() * scale_factor_);
@ -82,7 +83,7 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
rasterizer_type ras(ren); rasterizer_type ras(ren);
ras.line_join(agg::outline_miter_accurate_join); ras.line_join(agg::outline_miter_accurate_join);
ras.round_cap(true); ras.round_cap(true);
for (unsigned i=0;i<feature->num_geometries();++i) for (unsigned i=0;i<feature->num_geometries();++i)
{ {
geometry_type & geom = feature->get_geometry(i); geometry_type & geom = feature->get_geometry(i);
@ -94,6 +95,7 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
ras.add_path(path); ras.add_path(path);
} }
} }
*/
} }
else else
{ {
@ -103,96 +105,23 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
ren.attach(pixf); ren.attach(pixf);
//metawriter_with_properties writer = sym.get_metawriter(); //metawriter_with_properties writer = sym.get_metawriter();
typedef boost::mpl::vector<clip_line_tag,transform_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
vertex_converter<box2d<double>,rasterizer,line_symbolizer, proj_transform, CoordTransform,conv_types>
converter(ext,*ras_ptr,sym,t_,prj_trans);
//if (sym.clip())
converter.set<clip_line_tag>(); //FIXME make an optinal clip (default: true)
converter.set<transform_tag>(); //always transform
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
if (stroke_.has_dash()) converter.set<dash_tag>();
converter.set<stroke_tag>(); //always stroke
for (unsigned i=0;i<feature->num_geometries();++i) for (unsigned i=0;i<feature->num_geometries();++i)
{ {
geometry_type & geom = feature->get_geometry(i); geometry_type & geom = feature->get_geometry(i);
if (geom.num_points() > 1) if (geom.num_points() > 1)
{ {
if (stroke_.has_dash()) converter.apply(geom);
{
if (sym.smooth() > 0.0)
{
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
typedef agg::conv_smooth_poly1_curve<path_type> smooth_type;
clipped_geometry_type clipped(geom);
clipped.clip_box(ext.minx(),ext.miny(),ext.maxx(),ext.maxy());
path_type path(t_,clipped,prj_trans);
smooth_type smooth(path);
smooth.smooth_value(sym.smooth());
agg::conv_dash<smooth_type> dash(smooth);
dash_array const& d = stroke_.get_dash_array();
dash_array::const_iterator itr = d.begin();
dash_array::const_iterator end = d.end();
for (;itr != end;++itr)
{
dash.add_dash(itr->first * scale_factor_,
itr->second * scale_factor_);
}
agg::conv_stroke<agg::conv_dash<smooth_type > > stroke(dash);
set_join_caps(stroke_,stroke);
stroke.generator().miter_limit(4.0);
stroke.generator().width(stroke_.get_width() * scale_factor_);
ras_ptr->add_path(stroke);
}
else
{
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
clipped_geometry_type clipped(geom);
clipped.clip_box(ext.minx(),ext.miny(),ext.maxx(),ext.maxy());
path_type path(t_,clipped,prj_trans);
agg::conv_dash<path_type> dash(path);
dash_array const& d = stroke_.get_dash_array();
dash_array::const_iterator itr = d.begin();
dash_array::const_iterator end = d.end();
for (;itr != end;++itr)
{
dash.add_dash(itr->first * scale_factor_,
itr->second * scale_factor_);
}
agg::conv_stroke<agg::conv_dash<path_type > > stroke(dash);
set_join_caps(stroke_,stroke);
stroke.generator().miter_limit(4.0);
stroke.generator().width(stroke_.get_width() * scale_factor_);
ras_ptr->add_path(stroke);
}
}
else
{
if (sym.smooth() > 0.0)
{
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
typedef agg::conv_smooth_poly1_curve<path_type> smooth_type;
clipped_geometry_type clipped(geom);
clipped.clip_box(ext.minx(),ext.miny(),ext.maxx(),ext.maxy());
path_type path(t_,clipped,prj_trans);
smooth_type smooth(path);
smooth.smooth_value(sym.smooth());
agg::conv_stroke<smooth_type> stroke(smooth);
set_join_caps(stroke_,stroke);
stroke.generator().miter_limit(4.0);
stroke.generator().width(stroke_.get_width() * scale_factor_);
ras_ptr->add_path(stroke);
}
else
{
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
clipped_geometry_type clipped(geom);
clipped.clip_box(ext.minx(),ext.miny(),ext.maxx(),ext.maxy());
path_type path(t_,clipped,prj_trans);
agg::conv_stroke<path_type> stroke(path);
set_join_caps(stroke_,stroke);
stroke.generator().miter_limit(4.0);
stroke.generator().width(stroke_.get_width() * scale_factor_);
ras_ptr->add_path(stroke);
}
//if (writer.first) writer.first->add_line(path, *feature, t_, writer.second);
}
} }
} }

View file

@ -1326,8 +1326,8 @@ void map_parser::parse_polygon_symbolizer(rule & rule, xml_node const & sym)
if (smooth) poly_sym.set_smooth(*smooth); if (smooth) poly_sym.set_smooth(*smooth);
// to clip or not to clip value // to clip or not to clip value
optional<bool> clip = sym.get_opt_attr<bool>("clip"); //optional<bool> clip = sym.get_opt_attr<bool>("clip");
if (clip) poly_sym.set_clip(*clip); //if (clip) poly_sym.set_clip(*clip);
parse_metawriter_in_symbolizer(poly_sym, sym); parse_metawriter_in_symbolizer(poly_sym, sym);
rule.append(poly_sym); rule.append(poly_sym);