new feature: transform expressions are now dynamic
(cherry picked from commit 173c402b5c142310087246b0ea54dbec54edcac8) Conflicts: include/mapnik/vertex_converters.hpp src/agg/process_markers_symbolizer.cpp src/agg/process_point_symbolizer.cpp src/agg/process_polygon_pattern_symbolizer.cpp src/load_map.cpp
This commit is contained in:
parent
dad0bdacfc
commit
bd9609c370
30 changed files with 1071 additions and 163 deletions
|
@ -23,10 +23,14 @@
|
||||||
#define MAPNIK_PYTHON_BINDING_SVG_INCLUDED
|
#define MAPNIK_PYTHON_BINDING_SVG_INCLUDED
|
||||||
|
|
||||||
// mapnik
|
// mapnik
|
||||||
|
#include <mapnik/parse_transform.hpp>
|
||||||
#include <mapnik/symbolizer.hpp>
|
#include <mapnik/symbolizer.hpp>
|
||||||
#include <mapnik/svg/svg_path_parser.hpp>
|
#include <mapnik/svg/svg_path_parser.hpp>
|
||||||
#include <mapnik/value_error.hpp>
|
#include <mapnik/value_error.hpp>
|
||||||
|
|
||||||
|
// boost
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
// agg
|
// agg
|
||||||
#include "agg_trans_affine.h"
|
#include "agg_trans_affine.h"
|
||||||
|
|
||||||
|
@ -51,9 +55,9 @@ void set_svg_transform(T& symbolizer, std::string const& transform_wkt)
|
||||||
<< "', expected SVG transform attribute";
|
<< "', expected SVG transform attribute";
|
||||||
throw mapnik::value_error(ss.str());
|
throw mapnik::value_error(ss.str());
|
||||||
}
|
}
|
||||||
mapnik::transform_type matrix;
|
transform_list_ptr trans = boost::make_shared<transform_list>();
|
||||||
tr.store_to(&matrix[0]);
|
trans->push_back(matrix_node(tr));
|
||||||
symbolizer.set_image_transform(matrix);
|
symbolizer.set_image_transform(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace mapnik
|
} // end of namespace mapnik
|
||||||
|
|
|
@ -115,6 +115,13 @@ public:
|
||||||
|
|
||||||
void painted(bool painted);
|
void painted(bool painted);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
template <typename R>
|
||||||
|
void debug_draw_box(R& buf, box2d<double> const& extent,
|
||||||
|
double x, double y, double angle = 0.0);
|
||||||
|
void debug_draw_box(box2d<double> const& extent,
|
||||||
|
double x, double y, double angle = 0.0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
buffer_type & pixmap_;
|
buffer_type & pixmap_;
|
||||||
boost::shared_ptr<buffer_type> internal_buffer_;
|
boost::shared_ptr<buffer_type> internal_buffer_;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
// mapnik
|
// mapnik
|
||||||
#include <mapnik/rule.hpp>
|
#include <mapnik/rule.hpp>
|
||||||
|
#include <mapnik/parse_transform.hpp>
|
||||||
// boost
|
// boost
|
||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
|
@ -35,9 +36,10 @@
|
||||||
|
|
||||||
namespace mapnik {
|
namespace mapnik {
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
struct expression_attributes : boost::static_visitor<void>
|
struct expression_attributes : boost::static_visitor<void>
|
||||||
{
|
{
|
||||||
explicit expression_attributes(std::set<std::string> & names)
|
explicit expression_attributes(Container& names)
|
||||||
: names_(names) {}
|
: names_(names) {}
|
||||||
|
|
||||||
void operator() (value_type const& x) const
|
void operator() (value_type const& x) const
|
||||||
|
@ -53,35 +55,35 @@ struct expression_attributes : boost::static_visitor<void>
|
||||||
template <typename Tag>
|
template <typename Tag>
|
||||||
void operator() (binary_node<Tag> const& x) const
|
void operator() (binary_node<Tag> const& x) const
|
||||||
{
|
{
|
||||||
boost::apply_visitor(expression_attributes(names_),x.left);
|
boost::apply_visitor(*this, x.left);
|
||||||
boost::apply_visitor(expression_attributes(names_),x.right);
|
boost::apply_visitor(*this, x.right);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Tag>
|
template <typename Tag>
|
||||||
void operator() (unary_node<Tag> const& x) const
|
void operator() (unary_node<Tag> const& x) const
|
||||||
{
|
{
|
||||||
boost::apply_visitor(expression_attributes(names_),x.expr);
|
boost::apply_visitor(*this, x.expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator() (regex_match_node const& x) const
|
void operator() (regex_match_node const& x) const
|
||||||
{
|
{
|
||||||
boost::apply_visitor(expression_attributes(names_),x.expr);
|
boost::apply_visitor(*this, x.expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator() (regex_replace_node const& x) const
|
void operator() (regex_replace_node const& x) const
|
||||||
{
|
{
|
||||||
boost::apply_visitor(expression_attributes(names_),x.expr);
|
boost::apply_visitor(*this, x.expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::set<std::string>& names_;
|
Container& names_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct symbolizer_attributes : public boost::static_visitor<>
|
struct symbolizer_attributes : public boost::static_visitor<>
|
||||||
{
|
{
|
||||||
symbolizer_attributes(std::set<std::string>& names)
|
symbolizer_attributes(std::set<std::string>& names)
|
||||||
: names_(names) {}
|
: names_(names), f_attr(names) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void operator () (T const&) const {}
|
void operator () (T const&) const {}
|
||||||
|
@ -91,12 +93,12 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
||||||
expression_set::const_iterator it;
|
expression_set::const_iterator it;
|
||||||
expression_set expressions;
|
expression_set expressions;
|
||||||
sym.get_placement_options()->add_expressions(expressions);
|
sym.get_placement_options()->add_expressions(expressions);
|
||||||
expression_attributes f_attr(names_);
|
|
||||||
for (it=expressions.begin(); it != expressions.end(); it++)
|
for (it=expressions.begin(); it != expressions.end(); it++)
|
||||||
{
|
{
|
||||||
if (*it) boost::apply_visitor(f_attr, **it);
|
if (*it) boost::apply_visitor(f_attr, **it);
|
||||||
}
|
}
|
||||||
collect_metawriter(sym);
|
collect_metawriter(sym);
|
||||||
|
collect_transform(sym.get_transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator () (point_symbolizer const& sym)
|
void operator () (point_symbolizer const& sym)
|
||||||
|
@ -107,12 +109,14 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
||||||
path_processor_type::collect_attributes(*filename_expr,names_);
|
path_processor_type::collect_attributes(*filename_expr,names_);
|
||||||
}
|
}
|
||||||
collect_metawriter(sym);
|
collect_metawriter(sym);
|
||||||
|
collect_transform(sym.get_image_transform());
|
||||||
|
collect_transform(sym.get_transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator () (line_symbolizer const& sym)
|
void operator () (line_symbolizer const& sym)
|
||||||
{
|
{
|
||||||
collect_metawriter(sym);
|
collect_metawriter(sym);
|
||||||
|
collect_transform(sym.get_transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator () (line_pattern_symbolizer const& sym)
|
void operator () (line_pattern_symbolizer const& sym)
|
||||||
|
@ -123,11 +127,14 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
||||||
path_processor_type::collect_attributes(*filename_expr,names_);
|
path_processor_type::collect_attributes(*filename_expr,names_);
|
||||||
}
|
}
|
||||||
collect_metawriter(sym);
|
collect_metawriter(sym);
|
||||||
|
collect_transform(sym.get_image_transform());
|
||||||
|
collect_transform(sym.get_transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator () (polygon_symbolizer const& sym)
|
void operator () (polygon_symbolizer const& sym)
|
||||||
{
|
{
|
||||||
collect_metawriter(sym);
|
collect_metawriter(sym);
|
||||||
|
collect_transform(sym.get_transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator () (polygon_pattern_symbolizer const& sym)
|
void operator () (polygon_pattern_symbolizer const& sym)
|
||||||
|
@ -138,6 +145,8 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
||||||
path_processor_type::collect_attributes(*filename_expr,names_);
|
path_processor_type::collect_attributes(*filename_expr,names_);
|
||||||
}
|
}
|
||||||
collect_metawriter(sym);
|
collect_metawriter(sym);
|
||||||
|
collect_transform(sym.get_image_transform());
|
||||||
|
collect_transform(sym.get_transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator () (shield_symbolizer const& sym)
|
void operator () (shield_symbolizer const& sym)
|
||||||
|
@ -145,7 +154,6 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
||||||
expression_set::const_iterator it;
|
expression_set::const_iterator it;
|
||||||
expression_set expressions;
|
expression_set expressions;
|
||||||
sym.get_placement_options()->add_expressions(expressions);
|
sym.get_placement_options()->add_expressions(expressions);
|
||||||
expression_attributes f_attr(names_);
|
|
||||||
for (it=expressions.begin(); it != expressions.end(); it++)
|
for (it=expressions.begin(); it != expressions.end(); it++)
|
||||||
{
|
{
|
||||||
if (*it) boost::apply_visitor(f_attr, **it);
|
if (*it) boost::apply_visitor(f_attr, **it);
|
||||||
|
@ -157,11 +165,15 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
||||||
path_processor_type::collect_attributes(*filename_expr,names_);
|
path_processor_type::collect_attributes(*filename_expr,names_);
|
||||||
}
|
}
|
||||||
collect_metawriter(sym);
|
collect_metawriter(sym);
|
||||||
|
collect_transform(sym.get_image_transform());
|
||||||
|
collect_transform(sym.get_transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator () (markers_symbolizer const& sym)
|
void operator () (markers_symbolizer const& sym)
|
||||||
{
|
{
|
||||||
collect_metawriter(sym);
|
collect_metawriter(sym);
|
||||||
|
collect_transform(sym.get_image_transform());
|
||||||
|
collect_transform(sym.get_transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator () (building_symbolizer const& sym)
|
void operator () (building_symbolizer const& sym)
|
||||||
|
@ -169,20 +181,28 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
||||||
expression_ptr const& height_expr = sym.height();
|
expression_ptr const& height_expr = sym.height();
|
||||||
if (height_expr)
|
if (height_expr)
|
||||||
{
|
{
|
||||||
expression_attributes f_attr(names_);
|
|
||||||
boost::apply_visitor(f_attr,*height_expr);
|
boost::apply_visitor(f_attr,*height_expr);
|
||||||
}
|
}
|
||||||
collect_metawriter(sym);
|
collect_metawriter(sym);
|
||||||
|
collect_transform(sym.get_transform());
|
||||||
}
|
}
|
||||||
// TODO - support remaining syms
|
// TODO - support remaining syms
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::set<std::string>& names_;
|
std::set<std::string>& names_;
|
||||||
|
expression_attributes<std::set<std::string> > f_attr;
|
||||||
void collect_metawriter(symbolizer_base const& sym)
|
void collect_metawriter(symbolizer_base const& sym)
|
||||||
{
|
{
|
||||||
metawriter_properties const& properties = sym.get_metawriter_properties();
|
metawriter_properties const& properties = sym.get_metawriter_properties();
|
||||||
names_.insert(properties.begin(), properties.end());
|
names_.insert(properties.begin(), properties.end());
|
||||||
}
|
}
|
||||||
|
void collect_transform(transform_list_ptr const& trans_expr)
|
||||||
|
{
|
||||||
|
if (trans_expr)
|
||||||
|
{
|
||||||
|
transform_processor_type::collect_attributes(names_, *trans_expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,10 +210,11 @@ class attribute_collector : public boost::noncopyable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::set<std::string>& names_;
|
std::set<std::string>& names_;
|
||||||
|
expression_attributes<std::set<std::string> > f_attr;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
attribute_collector(std::set<std::string>& names)
|
attribute_collector(std::set<std::string>& names)
|
||||||
: names_(names) {}
|
: names_(names), f_attr(names) {}
|
||||||
|
|
||||||
template <typename RuleType>
|
template <typename RuleType>
|
||||||
void operator() (RuleType const& r)
|
void operator() (RuleType const& r)
|
||||||
|
@ -207,7 +228,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
expression_ptr const& expr = r.get_filter();
|
expression_ptr const& expr = r.get_filter();
|
||||||
expression_attributes f_attr(names_);
|
|
||||||
boost::apply_visitor(f_attr,*expr);
|
boost::apply_visitor(f_attr,*expr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -79,6 +79,21 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
box2d<double> bounding_box() const
|
||||||
|
{
|
||||||
|
if (is_vector())
|
||||||
|
{
|
||||||
|
return (*vector_data_)->bounding_box();
|
||||||
|
}
|
||||||
|
if (is_bitmap())
|
||||||
|
{
|
||||||
|
double width = (*bitmap_data_)->width();
|
||||||
|
double height = (*bitmap_data_)->height();
|
||||||
|
return box2d<double>(0, 0, width, height);
|
||||||
|
}
|
||||||
|
return box2d<double>();
|
||||||
|
}
|
||||||
|
|
||||||
inline double width() const
|
inline double width() const
|
||||||
{
|
{
|
||||||
if (is_bitmap())
|
if (is_bitmap())
|
||||||
|
|
243
include/mapnik/parse_transform.hpp
Normal file
243
include/mapnik/parse_transform.hpp
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAPNIK_PARSE_TRANSFORM_HPP
|
||||||
|
#define MAPNIK_PARSE_TRANSFORM_HPP
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/config.hpp>
|
||||||
|
#include <mapnik/debug.hpp>
|
||||||
|
#include <mapnik/attribute.hpp>
|
||||||
|
#include <mapnik/feature.hpp>
|
||||||
|
#include <mapnik/value.hpp>
|
||||||
|
#include <mapnik/transform_expression.hpp>
|
||||||
|
#include <mapnik/expression_evaluator.hpp>
|
||||||
|
|
||||||
|
// boost
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/variant.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
// agg
|
||||||
|
#include <agg_trans_affine.h>
|
||||||
|
|
||||||
|
namespace mapnik {
|
||||||
|
|
||||||
|
template <typename Container> struct expression_attributes;
|
||||||
|
template <typename Iterator> struct transform_expression_grammar;
|
||||||
|
|
||||||
|
MAPNIK_DECL transform_list_ptr parse_transform(std::string const & str);
|
||||||
|
MAPNIK_DECL bool parse_transform(transform_list& list,
|
||||||
|
std::string const & str,
|
||||||
|
transform_expression_grammar<std::string::const_iterator> const& g);
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct transform_processor
|
||||||
|
{
|
||||||
|
typedef T feature_type;
|
||||||
|
typedef agg::trans_affine transform_type;
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
struct attribute_collector : boost::static_visitor<void>
|
||||||
|
{
|
||||||
|
expression_attributes<Container> collect_;
|
||||||
|
|
||||||
|
attribute_collector(Container& names)
|
||||||
|
: collect_(names) {}
|
||||||
|
|
||||||
|
void operator() (identity_node const& node) const
|
||||||
|
{
|
||||||
|
boost::ignore_unused_variable_warning(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (matrix_node const& node) const
|
||||||
|
{
|
||||||
|
boost::apply_visitor(collect_, node.a_);
|
||||||
|
boost::apply_visitor(collect_, node.b_);
|
||||||
|
boost::apply_visitor(collect_, node.c_);
|
||||||
|
boost::apply_visitor(collect_, node.d_);
|
||||||
|
boost::apply_visitor(collect_, node.e_);
|
||||||
|
boost::apply_visitor(collect_, node.f_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (translate_node const& node) const
|
||||||
|
{
|
||||||
|
boost::apply_visitor(collect_, node.tx_);
|
||||||
|
boost::apply_visitor(collect_, node.ty_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (scale_node const& node) const
|
||||||
|
{
|
||||||
|
boost::apply_visitor(collect_, node.sx_);
|
||||||
|
boost::apply_visitor(collect_, node.sy_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (rotate_node const& node) const
|
||||||
|
{
|
||||||
|
boost::apply_visitor(collect_, node.angle_);
|
||||||
|
boost::apply_visitor(collect_, node.cx_);
|
||||||
|
boost::apply_visitor(collect_, node.cy_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (skewX_node const& node) const
|
||||||
|
{
|
||||||
|
boost::apply_visitor(collect_, node.angle_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (skewY_node const& node) const
|
||||||
|
{
|
||||||
|
boost::apply_visitor(collect_, node.angle_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct node_evaluator : boost::static_visitor<void>
|
||||||
|
{
|
||||||
|
node_evaluator(transform_type& tr, feature_type const& feat)
|
||||||
|
: transform_(tr), feature_(feat) {}
|
||||||
|
|
||||||
|
void operator() (identity_node const& node)
|
||||||
|
{
|
||||||
|
boost::ignore_unused_variable_warning(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (matrix_node const& node)
|
||||||
|
{
|
||||||
|
double a = eval(node.a_);
|
||||||
|
double b = eval(node.b_);
|
||||||
|
double c = eval(node.c_);
|
||||||
|
double d = eval(node.d_);
|
||||||
|
double e = eval(node.e_);
|
||||||
|
double f = eval(node.f_);
|
||||||
|
transform_.multiply(agg::trans_affine(a, b, c, d, e, f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (translate_node const& node)
|
||||||
|
{
|
||||||
|
double tx = eval(node.tx_);
|
||||||
|
double ty = eval(node.ty_, 0.0);
|
||||||
|
transform_.translate(tx, ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (scale_node const& node)
|
||||||
|
{
|
||||||
|
double sx = eval(node.sx_);
|
||||||
|
double sy = eval(node.sy_, sx);
|
||||||
|
transform_.scale(sx, sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (rotate_node const& node)
|
||||||
|
{
|
||||||
|
double angle = deg2rad(eval(node.angle_));
|
||||||
|
double cx = eval(node.cx_, 0.0);
|
||||||
|
double cy = eval(node.cy_, 0.0);
|
||||||
|
transform_.translate(-cx, -cy);
|
||||||
|
transform_.rotate(angle);
|
||||||
|
transform_.translate(cx, cy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (skewX_node const& node)
|
||||||
|
{
|
||||||
|
double angle = deg2rad(eval(node.angle_));
|
||||||
|
transform_.multiply(agg::trans_affine_skewing(angle, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (skewY_node const& node)
|
||||||
|
{
|
||||||
|
double angle = deg2rad(eval(node.angle_));
|
||||||
|
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> e(feature_);
|
||||||
|
return boost::apply_visitor(e, x).to_double();
|
||||||
|
}
|
||||||
|
|
||||||
|
double eval(expr_node const& x, double def) const
|
||||||
|
{
|
||||||
|
return is_null(x) ? def : eval(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
transform_type& transform_;
|
||||||
|
feature_type const& feature_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
static void collect_attributes(Container& names,
|
||||||
|
transform_list const& list)
|
||||||
|
{
|
||||||
|
attribute_collector<Container> collect(names);
|
||||||
|
|
||||||
|
BOOST_FOREACH (transform_node const& node, list)
|
||||||
|
{
|
||||||
|
boost::apply_visitor(collect, *node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void evaluate(transform_type& tr, feature_type const& feat,
|
||||||
|
transform_list const& list)
|
||||||
|
{
|
||||||
|
node_evaluator eval(tr, feat);
|
||||||
|
|
||||||
|
#ifdef MAPNIK_LOG
|
||||||
|
MAPNIK_LOG_DEBUG(transform) << "transform: begin with " << to_string(matrix_node(tr));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BOOST_REVERSE_FOREACH (transform_node const& node, list)
|
||||||
|
{
|
||||||
|
boost::apply_visitor(eval, *node);
|
||||||
|
#ifdef MAPNIK_LOG
|
||||||
|
MAPNIK_LOG_DEBUG(transform) << "transform: apply " << to_string(*node);
|
||||||
|
MAPNIK_LOG_DEBUG(transform) << "transform: result " << to_string(matrix_node(tr));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MAPNIK_LOG
|
||||||
|
MAPNIK_LOG_DEBUG(transform) << "transform: end";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string to_string(transform_node const& node)
|
||||||
|
{
|
||||||
|
return to_expression_string(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string to_string(transform_list const& list)
|
||||||
|
{
|
||||||
|
return to_expression_string(list);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef mapnik::transform_processor<Feature> transform_processor_type;
|
||||||
|
|
||||||
|
} // namespace mapnik
|
||||||
|
|
||||||
|
#endif // MAPNIK_PARSE_TRANSFORM_HPP
|
|
@ -28,6 +28,7 @@
|
||||||
#include <mapnik/parse_path.hpp>
|
#include <mapnik/parse_path.hpp>
|
||||||
#include <mapnik/metawriter.hpp>
|
#include <mapnik/metawriter.hpp>
|
||||||
#include <mapnik/image_compositing.hpp>
|
#include <mapnik/image_compositing.hpp>
|
||||||
|
#include <mapnik/transform_expression.hpp>
|
||||||
|
|
||||||
// boost
|
// boost
|
||||||
#include <boost/array.hpp>
|
#include <boost/array.hpp>
|
||||||
|
@ -36,7 +37,10 @@
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef boost::array<double,6> transform_type;
|
typedef transform_list_ptr transform_type;
|
||||||
|
|
||||||
|
MAPNIK_DECL void evaluate_transform(agg::trans_affine& tr, Feature const& feature,
|
||||||
|
transform_type const& trans_expr);
|
||||||
|
|
||||||
class Map;
|
class Map;
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,21 @@ public:
|
||||||
init_marker();
|
init_marker();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
box2d<double> const& get_marker_extent() const
|
||||||
|
{
|
||||||
|
return marker_ext_;
|
||||||
|
}
|
||||||
|
|
||||||
|
double get_marker_height() const
|
||||||
|
{
|
||||||
|
return marker_h_;
|
||||||
|
}
|
||||||
|
|
||||||
|
double get_marker_width() const
|
||||||
|
{
|
||||||
|
return marker_w_;
|
||||||
|
}
|
||||||
|
|
||||||
bool next();
|
bool next();
|
||||||
pixel_position get_marker_position(text_path const& p);
|
pixel_position get_marker_position(text_path const& p);
|
||||||
marker & get_marker() const;
|
marker & get_marker() const;
|
||||||
|
|
181
include/mapnik/transform_expression.hpp
Normal file
181
include/mapnik/transform_expression.hpp
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAPNIK_TRANSFORM_EXPRESSION_HPP
|
||||||
|
#define MAPNIK_TRANSFORM_EXPRESSION_HPP
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/expression_node.hpp>
|
||||||
|
|
||||||
|
// boost
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/variant.hpp>
|
||||||
|
|
||||||
|
// agg
|
||||||
|
#include <agg_trans_affine.h>
|
||||||
|
|
||||||
|
// stl
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace mapnik {
|
||||||
|
|
||||||
|
struct identity_node {};
|
||||||
|
|
||||||
|
struct matrix_node
|
||||||
|
{
|
||||||
|
expr_node a_;
|
||||||
|
expr_node b_;
|
||||||
|
expr_node c_;
|
||||||
|
expr_node d_;
|
||||||
|
expr_node e_;
|
||||||
|
expr_node f_;
|
||||||
|
|
||||||
|
explicit matrix_node(double const* m)
|
||||||
|
: a_(m[0]), b_(m[1]), c_(m[2]), d_(m[3]), e_(m[4]), f_(m[5]) {}
|
||||||
|
|
||||||
|
explicit matrix_node(agg::trans_affine const& m)
|
||||||
|
: a_(m.sx), b_(m.shy), c_(m.shx), d_(m.sy), e_(m.tx), f_(m.ty) {}
|
||||||
|
|
||||||
|
matrix_node(expr_node const& a, expr_node const& b, expr_node const& c,
|
||||||
|
expr_node const& d, expr_node const& e, expr_node const& f)
|
||||||
|
: a_(a), b_(b), c_(c), d_(d), e_(e), f_(f) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct translate_node
|
||||||
|
{
|
||||||
|
expr_node tx_;
|
||||||
|
expr_node ty_;
|
||||||
|
|
||||||
|
translate_node(expr_node const& tx,
|
||||||
|
boost::optional<expr_node> const& ty)
|
||||||
|
: tx_(tx)
|
||||||
|
, ty_(ty ? *ty : value_null()) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct scale_node
|
||||||
|
{
|
||||||
|
expr_node sx_;
|
||||||
|
expr_node sy_;
|
||||||
|
|
||||||
|
scale_node(expr_node const& sx,
|
||||||
|
boost::optional<expr_node> const& sy)
|
||||||
|
: sx_(sx)
|
||||||
|
, sy_(sy ? *sy : value_null()) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rotate_node
|
||||||
|
{
|
||||||
|
expr_node angle_;
|
||||||
|
expr_node cx_;
|
||||||
|
expr_node cy_;
|
||||||
|
|
||||||
|
rotate_node(expr_node const& angle,
|
||||||
|
boost::optional<expr_node> const& cx,
|
||||||
|
boost::optional<expr_node> const& cy)
|
||||||
|
: angle_(angle)
|
||||||
|
, cx_(cx ? *cx : value_null())
|
||||||
|
, cy_(cy ? *cy : value_null()) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skewX_node
|
||||||
|
{
|
||||||
|
expr_node angle_;
|
||||||
|
|
||||||
|
explicit skewX_node(expr_node const& angle)
|
||||||
|
: angle_(angle) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skewY_node
|
||||||
|
{
|
||||||
|
expr_node angle_;
|
||||||
|
|
||||||
|
explicit skewY_node(expr_node const& angle)
|
||||||
|
: angle_(angle) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// boost::spirit::traits::clear<T>(T& val) [with T = boost::variant<...>]
|
||||||
|
// attempts to assign to the variant's current value a default-constructed
|
||||||
|
// value ot the same type, which not only requires that each value-type is
|
||||||
|
// default-constructible, but also makes little sense with our variant of
|
||||||
|
// transform nodes...
|
||||||
|
|
||||||
|
typedef boost::variant< identity_node
|
||||||
|
, matrix_node
|
||||||
|
, translate_node
|
||||||
|
, scale_node
|
||||||
|
, rotate_node
|
||||||
|
, skewX_node
|
||||||
|
, skewY_node
|
||||||
|
> transform_variant;
|
||||||
|
|
||||||
|
// ... thus we wrap the variant-type in a distinct type and provide
|
||||||
|
// a custom clear overload, which resets the value to identity_node
|
||||||
|
|
||||||
|
struct transform_node
|
||||||
|
{
|
||||||
|
transform_variant base_;
|
||||||
|
|
||||||
|
transform_node()
|
||||||
|
: base_() {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
transform_node(T const& val)
|
||||||
|
: base_(val) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
transform_node& operator= (T const& val)
|
||||||
|
{
|
||||||
|
base_ = val;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform_variant const& operator* () const
|
||||||
|
{
|
||||||
|
return base_;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform_variant& operator* ()
|
||||||
|
{
|
||||||
|
return base_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void clear(transform_node& val)
|
||||||
|
{
|
||||||
|
val.base_ = identity_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
typedef detail::transform_node transform_node;
|
||||||
|
typedef std::vector<transform_node> transform_list;
|
||||||
|
typedef boost::shared_ptr<transform_list> transform_list_ptr;
|
||||||
|
|
||||||
|
MAPNIK_DECL std::string to_expression_string(transform_node const& node);
|
||||||
|
MAPNIK_DECL std::string to_expression_string(transform_list const& list);
|
||||||
|
|
||||||
|
} // namespace mapnik
|
||||||
|
|
||||||
|
#endif // MAPNIK_TRANSFORM_EXPRESSION_HPP
|
121
include/mapnik/transform_expression_grammar.hpp
Normal file
121
include/mapnik/transform_expression_grammar.hpp
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAPNIK_TRANSFORM_EXPRESSION_GRAMMAR_HPP
|
||||||
|
#define MAPNIK_TRANSFORM_EXPRESSION_GRAMMAR_HPP
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/expression_grammar.hpp>
|
||||||
|
#include <mapnik/transform_expression.hpp>
|
||||||
|
|
||||||
|
// spirit
|
||||||
|
#include <boost/spirit/home/phoenix/object/construct.hpp>
|
||||||
|
#include <boost/spirit/home/qi.hpp>
|
||||||
|
|
||||||
|
namespace mapnik {
|
||||||
|
|
||||||
|
namespace qi = boost::spirit::qi;
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
struct transform_expression_grammar
|
||||||
|
: qi::grammar<Iterator, transform_list(), space_type>
|
||||||
|
{
|
||||||
|
explicit transform_expression_grammar(expression_grammar<Iterator> const& g)
|
||||||
|
: transform_expression_grammar::base_type(start)
|
||||||
|
{
|
||||||
|
using boost::phoenix::construct;
|
||||||
|
using qi::_a; using qi::_1; using qi::_4;
|
||||||
|
using qi::_b; using qi::_2; using qi::_5;
|
||||||
|
using qi::_c; using qi::_3; using qi::_6;
|
||||||
|
using qi::_val;
|
||||||
|
using qi::char_;
|
||||||
|
using qi::lit;
|
||||||
|
using qi::no_case;
|
||||||
|
using qi::no_skip;
|
||||||
|
|
||||||
|
start = transform_ % no_skip[char_(", ")] ;
|
||||||
|
|
||||||
|
transform_ = matrix | translate | scale | rotate | skewX | skewY ;
|
||||||
|
|
||||||
|
matrix = no_case[lit("matrix")]
|
||||||
|
>> (lit('(')
|
||||||
|
>> expr >> -lit(',')
|
||||||
|
>> expr >> -lit(',')
|
||||||
|
>> expr >> -lit(',')
|
||||||
|
>> expr >> -lit(',')
|
||||||
|
>> expr >> -lit(',')
|
||||||
|
>> expr >> lit(')'))
|
||||||
|
[ _val = construct<matrix_node>(_1,_2,_3,_4,_5,_6) ];
|
||||||
|
|
||||||
|
translate = no_case[lit("translate")]
|
||||||
|
>> (lit('(')
|
||||||
|
>> expr >> -lit(',')
|
||||||
|
>> -expr >> lit(')'))
|
||||||
|
[ _val = construct<translate_node>(_1,_2) ];
|
||||||
|
|
||||||
|
scale = no_case[lit("scale")]
|
||||||
|
>> (lit('(')
|
||||||
|
>> expr >> -lit(',')
|
||||||
|
>> -expr >> lit(')'))
|
||||||
|
[ _val = construct<scale_node>(_1,_2) ];
|
||||||
|
|
||||||
|
rotate = no_case[lit("rotate")]
|
||||||
|
>> lit('(')
|
||||||
|
>> expr[_a = _1] >> -lit(',')
|
||||||
|
>> -(expr [_b = _1] >> -lit(',') >> expr[_c = _1])
|
||||||
|
>> lit(')')
|
||||||
|
[ _val = construct<rotate_node>(_a,_b,_c) ];
|
||||||
|
|
||||||
|
skewX = no_case[lit("skewX")]
|
||||||
|
>> lit('(')
|
||||||
|
>> expr [ _val = construct<skewX_node>(_1) ]
|
||||||
|
>> lit(')');
|
||||||
|
|
||||||
|
skewY = no_case[lit("skewY")]
|
||||||
|
>> lit('(')
|
||||||
|
>> expr [ _val = construct<skewY_node>(_1) ]
|
||||||
|
>> lit(')');
|
||||||
|
|
||||||
|
expr = g.expr.alias();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef qi::locals<expr_node, boost::optional<expr_node>,
|
||||||
|
boost::optional<expr_node>
|
||||||
|
> rotate_locals;
|
||||||
|
typedef qi::rule<Iterator, transform_node(), space_type> node_rule;
|
||||||
|
typedef qi::rule<Iterator, transform_list(), space_type> list_rule;
|
||||||
|
|
||||||
|
// rules
|
||||||
|
typename expression_grammar<Iterator>::rule_type expr;
|
||||||
|
qi::rule<Iterator, transform_list(), space_type> start;
|
||||||
|
qi::rule<Iterator, transform_node(), space_type> transform_;
|
||||||
|
qi::rule<Iterator, transform_node(), space_type> matrix;
|
||||||
|
qi::rule<Iterator, transform_node(), space_type> translate;
|
||||||
|
qi::rule<Iterator, transform_node(), space_type> scale;
|
||||||
|
qi::rule<Iterator, transform_node(), space_type, rotate_locals> rotate;
|
||||||
|
qi::rule<Iterator, transform_node(), space_type> skewX;
|
||||||
|
qi::rule<Iterator, transform_node(), space_type> skewY;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mapnik
|
||||||
|
|
||||||
|
#endif // MAPNIK_TRANSFORM_EXPRESSION_GRAMMAR_HPP
|
|
@ -120,9 +120,8 @@ struct converter_traits<T, mapnik::dash_tag>
|
||||||
template <typename Args>
|
template <typename Args>
|
||||||
static void setup(geometry_type & geom, Args const& args)
|
static void setup(geometry_type & geom, Args const& args)
|
||||||
{
|
{
|
||||||
|
|
||||||
typename boost::mpl::at<Args,boost::mpl::int_<2> >::type sym = boost::fusion::at_c<2>(args);
|
typename boost::mpl::at<Args,boost::mpl::int_<2> >::type sym = boost::fusion::at_c<2>(args);
|
||||||
double scale_factor = boost::fusion::at_c<5>(args);
|
double scale_factor = boost::fusion::at_c<6>(args);
|
||||||
stroke const& stroke_ = sym.get_stroke();
|
stroke const& stroke_ = sym.get_stroke();
|
||||||
dash_array const& d = stroke_.get_dash_array();
|
dash_array const& d = stroke_.get_dash_array();
|
||||||
dash_array::const_iterator itr = d.begin();
|
dash_array::const_iterator itr = d.begin();
|
||||||
|
@ -149,7 +148,7 @@ struct converter_traits<T, mapnik::stroke_tag>
|
||||||
stroke const& stroke_ = sym.get_stroke();
|
stroke const& stroke_ = sym.get_stroke();
|
||||||
set_join_caps(stroke_,geom);
|
set_join_caps(stroke_,geom);
|
||||||
geom.generator().miter_limit(stroke_.get_miterlimit());
|
geom.generator().miter_limit(stroke_.get_miterlimit());
|
||||||
double scale_factor = boost::fusion::at_c<5>(args);
|
double scale_factor = boost::fusion::at_c<6>(args);
|
||||||
geom.generator().width(stroke_.get_width() * scale_factor);
|
geom.generator().width(stroke_.get_width() * scale_factor);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -179,10 +178,8 @@ struct converter_traits<T,mapnik::transform_tag>
|
||||||
template <typename Args>
|
template <typename Args>
|
||||||
static void setup(geometry_type & geom, Args const& args)
|
static void setup(geometry_type & geom, Args const& args)
|
||||||
{
|
{
|
||||||
typename boost::mpl::at<Args,boost::mpl::int_<3> >::type tr = boost::fusion::at_c<3>(args);
|
geom.set_proj_trans(boost::fusion::at_c<4>(args));
|
||||||
typename boost::mpl::at<Args,boost::mpl::int_<4> >::type prj_trans = boost::fusion::at_c<4>(args);
|
geom.set_trans(boost::fusion::at_c<3>(args));
|
||||||
geom.set_proj_trans(prj_trans);
|
|
||||||
geom.set_trans(tr);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -191,21 +188,19 @@ template <typename T>
|
||||||
struct converter_traits<T,mapnik::affine_transform_tag>
|
struct converter_traits<T,mapnik::affine_transform_tag>
|
||||||
{
|
{
|
||||||
typedef T geometry_type;
|
typedef T geometry_type;
|
||||||
|
typedef agg::conv_transform<geometry_type, agg::trans_affine const>
|
||||||
|
conv_base_type;
|
||||||
|
|
||||||
struct conv_type : public agg::conv_transform<geometry_type>
|
struct conv_type : public conv_base_type
|
||||||
{
|
{
|
||||||
agg::trans_affine trans_;
|
|
||||||
|
|
||||||
conv_type(geometry_type& geom)
|
conv_type(geometry_type& geom)
|
||||||
: agg::conv_transform<geometry_type>(geom, trans_) {}
|
: conv_base_type(geom, agg::trans_affine::identity) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
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_<2> >::type sym = boost::fusion::at_c<2>(args);
|
geom.transformer(boost::fusion::at_c<5>(args));
|
||||||
boost::array<double,6> const& m = sym.get_transform();
|
|
||||||
geom.trans_.load_from(&m[0]);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -303,15 +298,16 @@ struct dispatcher
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename B, typename R, typename S, typename P, typename T, typename C >
|
template <typename B, typename R, typename S, typename T, typename P, typename A, 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;
|
||||||
typedef S symbolizer_type;
|
typedef S symbolizer_type;
|
||||||
typedef P proj_trans_type;
|
|
||||||
typedef T trans_type;
|
typedef T trans_type;
|
||||||
|
typedef P proj_trans_type;
|
||||||
|
typedef A affine_trans_type;
|
||||||
typedef typename boost::fusion::vector
|
typedef typename boost::fusion::vector
|
||||||
<
|
<
|
||||||
bbox_type const&,
|
bbox_type const&,
|
||||||
|
@ -319,16 +315,20 @@ struct vertex_converter : private boost::noncopyable
|
||||||
symbolizer_type const&,
|
symbolizer_type const&,
|
||||||
trans_type const&,
|
trans_type const&,
|
||||||
proj_trans_type const&,
|
proj_trans_type const&,
|
||||||
|
affine_trans_type const&,
|
||||||
double //scale-factor
|
double //scale-factor
|
||||||
> 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,
|
symbolizer_type const& sym, trans_type & tr,
|
||||||
proj_trans_type const& prj_trans,
|
proj_trans_type const& prj_trans,
|
||||||
|
affine_trans_type const& affine_trans,
|
||||||
double scale_factor)
|
double scale_factor)
|
||||||
: 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),scale_factor)) {}
|
boost::cref(prj_trans),
|
||||||
|
boost::cref(affine_trans),
|
||||||
|
scale_factor)) {}
|
||||||
|
|
||||||
template <typename Geometry>
|
template <typename Geometry>
|
||||||
void apply(Geometry & geom)
|
void apply(Geometry & geom)
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <mapnik/xml_node.hpp>
|
#include <mapnik/xml_node.hpp>
|
||||||
#include <mapnik/expression_grammar.hpp>
|
#include <mapnik/expression_grammar.hpp>
|
||||||
#include <mapnik/path_expression_grammar.hpp>
|
#include <mapnik/path_expression_grammar.hpp>
|
||||||
|
#include <mapnik/transform_expression_grammar.hpp>
|
||||||
|
|
||||||
// boost
|
// boost
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
@ -57,6 +58,7 @@ public:
|
||||||
mapnik::css_color_grammar<std::string::const_iterator> color_grammar;
|
mapnik::css_color_grammar<std::string::const_iterator> color_grammar;
|
||||||
mapnik::expression_grammar<std::string::const_iterator> expr_grammar;
|
mapnik::expression_grammar<std::string::const_iterator> expr_grammar;
|
||||||
path_expression_grammar<std::string::const_iterator> path_expr_grammar;
|
path_expression_grammar<std::string::const_iterator> path_expr_grammar;
|
||||||
|
transform_expression_grammar<std::string::const_iterator> transform_expr_grammar;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //ns mapnik
|
} //ns mapnik
|
||||||
|
|
|
@ -277,7 +277,7 @@ void agg_renderer<T>::render_marker(pixel_position const& pos, marker const& mar
|
||||||
mtx *= tr;
|
mtx *= tr;
|
||||||
mtx *= agg::trans_affine_scaling(scale_factor_);
|
mtx *= agg::trans_affine_scaling(scale_factor_);
|
||||||
// render the marker at the center of the marker box
|
// render the marker at the center of the marker box
|
||||||
mtx.translate(pos.x+0.5 * marker.width(), pos.y+0.5 * marker.height());
|
mtx.translate(pos.x, pos.y);
|
||||||
using namespace mapnik::svg;
|
using namespace mapnik::svg;
|
||||||
vertex_stl_adapter<svg_path_storage> stl_storage((*marker.get_vector_data())->source());
|
vertex_stl_adapter<svg_path_storage> stl_storage((*marker.get_vector_data())->source());
|
||||||
svg_path_adapter svg_path(stl_storage);
|
svg_path_adapter svg_path(stl_storage);
|
||||||
|
@ -291,10 +291,12 @@ void agg_renderer<T>::render_marker(pixel_position const& pos, marker const& mar
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
double cx = 0.5 * (*marker.get_bitmap_data())->width();
|
||||||
|
double cy = 0.5 * (*marker.get_bitmap_data())->height();
|
||||||
composite(current_buffer_->data(), **marker.get_bitmap_data(),
|
composite(current_buffer_->data(), **marker.get_bitmap_data(),
|
||||||
comp_op, opacity,
|
comp_op, opacity,
|
||||||
boost::math::iround(pos.x),
|
boost::math::iround(pos.x - cx),
|
||||||
boost::math::iround(pos.y),
|
boost::math::iround(pos.y - cy),
|
||||||
false, false);
|
false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,5 +307,57 @@ void agg_renderer<T>::painted(bool painted)
|
||||||
pixmap_.painted(painted);
|
pixmap_.painted(painted);
|
||||||
}
|
}
|
||||||
|
|
||||||
template class agg_renderer<image_32>;
|
template <typename T>
|
||||||
|
void agg_renderer<T>::debug_draw_box(box2d<double> const& box,
|
||||||
|
double x, double y, double angle)
|
||||||
|
{
|
||||||
|
agg::rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_ * 4);
|
||||||
|
debug_draw_box(buf, box, x, y, angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> template <typename R>
|
||||||
|
void agg_renderer<T>::debug_draw_box(R& buf, box2d<double> const& box,
|
||||||
|
double x, double y, double angle)
|
||||||
|
{
|
||||||
|
typedef agg::pixfmt_rgba32 pixfmt;
|
||||||
|
typedef agg::renderer_base<pixfmt> renderer_base;
|
||||||
|
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_type;
|
||||||
|
|
||||||
|
agg::scanline_p8 sl_line;
|
||||||
|
pixfmt pixf(buf);
|
||||||
|
renderer_base renb(pixf);
|
||||||
|
renderer_type ren(renb);
|
||||||
|
|
||||||
|
// compute tranformation matrix
|
||||||
|
agg::trans_affine_rotation tr(angle);
|
||||||
|
tr.translate(x, y);
|
||||||
|
|
||||||
|
// prepare path
|
||||||
|
agg::path_storage pbox;
|
||||||
|
pbox.start_new_path();
|
||||||
|
pbox.move_to(box.minx(), box.miny());
|
||||||
|
pbox.line_to(box.maxx(), box.miny());
|
||||||
|
pbox.line_to(box.maxx(), box.maxy());
|
||||||
|
pbox.line_to(box.minx(), box.maxy());
|
||||||
|
pbox.line_to(box.minx(), box.miny());
|
||||||
|
|
||||||
|
// prepare stroke with applied transformation
|
||||||
|
typedef agg::conv_transform<agg::path_storage> conv_transform;
|
||||||
|
typedef agg::conv_stroke<conv_transform> conv_stroke;
|
||||||
|
conv_transform tbox(pbox, tr);
|
||||||
|
conv_stroke sbox(tbox);
|
||||||
|
sbox.generator().width(1.0 * scale_factor_);
|
||||||
|
|
||||||
|
// render the outline
|
||||||
|
ras_ptr->reset();
|
||||||
|
ras_ptr->add_path(sbox);
|
||||||
|
ren.color(agg::rgba8(0x33, 0x33, 0xff, 0xcc)); // blue is fine
|
||||||
|
agg::render_scanlines(*ras_ptr, sl_line, ren);
|
||||||
|
}
|
||||||
|
|
||||||
|
template class agg_renderer<image_32>;
|
||||||
|
template void agg_renderer<image_32>::debug_draw_box<agg::rendering_buffer>(
|
||||||
|
agg::rendering_buffer& buf,
|
||||||
|
box2d<double> const& box,
|
||||||
|
double x, double y, double angle);
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,9 +94,13 @@ void agg_renderer<T>::process(line_pattern_symbolizer const& sym,
|
||||||
renderer_type ren(ren_base, pattern);
|
renderer_type ren(ren_base, pattern);
|
||||||
rasterizer_type ras(ren);
|
rasterizer_type ras(ren);
|
||||||
|
|
||||||
|
agg::trans_affine tr;
|
||||||
|
evaluate_transform(tr, *feature, sym.get_transform());
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_line_tag,transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_line_tag,transform_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>,rasterizer_type,line_pattern_symbolizer, proj_transform, CoordTransform, conv_types>
|
vertex_converter<box2d<double>, rasterizer_type, line_pattern_symbolizer,
|
||||||
converter(ext,ras,sym,t_,prj_trans,scale_factor_);
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
|
converter(ext,ras,sym,t_,prj_trans,tr,scale_factor_);
|
||||||
|
|
||||||
if (sym.clip()) converter.set<clip_line_tag>(); //optional clip (default: true)
|
if (sym.clip()) converter.set<clip_line_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
|
|
|
@ -76,6 +76,9 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
|
||||||
pixfmt_comp_type pixf(buf);
|
pixfmt_comp_type pixf(buf);
|
||||||
renderer_base renb(pixf);
|
renderer_base renb(pixf);
|
||||||
|
|
||||||
|
agg::trans_affine tr;
|
||||||
|
evaluate_transform(tr, *feature, sym.get_transform());
|
||||||
|
|
||||||
if (sym.get_rasterizer() == RASTERIZER_FAST)
|
if (sym.get_rasterizer() == RASTERIZER_FAST)
|
||||||
{
|
{
|
||||||
typedef agg::renderer_outline_aa<renderer_base> renderer_type;
|
typedef agg::renderer_outline_aa<renderer_base> renderer_type;
|
||||||
|
@ -89,8 +92,9 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
|
||||||
set_join_caps_aa(stroke_,ras);
|
set_join_caps_aa(stroke_,ras);
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_line_tag,transform_tag, offset_transform_tag, affine_transform_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
|
typedef boost::mpl::vector<clip_line_tag,transform_tag, offset_transform_tag, affine_transform_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
|
||||||
vertex_converter<box2d<double>,rasterizer_type,line_symbolizer, proj_transform, CoordTransform,conv_types>
|
vertex_converter<box2d<double>, rasterizer_type, line_symbolizer,
|
||||||
converter(query_extent_,ras,sym,t_,prj_trans,scaled);
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
|
converter(query_extent_,ras,sym,t_,prj_trans,tr,scaled);
|
||||||
|
|
||||||
if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
|
if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
|
||||||
converter.set<transform_tag>(); // always transform
|
converter.set<transform_tag>(); // always transform
|
||||||
|
@ -111,8 +115,9 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
typedef boost::mpl::vector<clip_line_tag,transform_tag, offset_transform_tag, affine_transform_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
|
typedef boost::mpl::vector<clip_line_tag,transform_tag, offset_transform_tag, affine_transform_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
|
||||||
vertex_converter<box2d<double>,rasterizer,line_symbolizer, proj_transform, CoordTransform,conv_types>
|
vertex_converter<box2d<double>, rasterizer, line_symbolizer,
|
||||||
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,scale_factor_);
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
|
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||||
|
|
||||||
if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
|
if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
|
||||||
converter.set<transform_tag>(); // always transform
|
converter.set<transform_tag>(); // always transform
|
||||||
|
|
|
@ -73,8 +73,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
||||||
renderer_base renb(pixf);
|
renderer_base renb(pixf);
|
||||||
renderer_type ren(renb);
|
renderer_type ren(renb);
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr;
|
||||||
boost::array<double,6> const& m = sym.get_image_transform();
|
evaluate_transform(tr, *feature, sym.get_image_transform());
|
||||||
tr.load_from(&m[0]);
|
|
||||||
tr = agg::trans_affine_scaling(scale_factor_) * tr;
|
tr = agg::trans_affine_scaling(scale_factor_) * tr;
|
||||||
std::string filename = path_processor_type::evaluate(*sym.get_filename(), *feature);
|
std::string filename = path_processor_type::evaluate(*sym.get_filename(), *feature);
|
||||||
marker_placement_e placement_method = sym.get_marker_placement();
|
marker_placement_e placement_method = sym.get_marker_placement();
|
||||||
|
@ -94,17 +93,12 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
||||||
}
|
}
|
||||||
boost::optional<path_ptr> marker = (*mark)->get_vector_data();
|
boost::optional<path_ptr> marker = (*mark)->get_vector_data();
|
||||||
box2d<double> const& bbox = (*marker)->bounding_box();
|
box2d<double> const& bbox = (*marker)->bounding_box();
|
||||||
double x1 = bbox.minx();
|
coord2d const center = bbox.center();
|
||||||
double y1 = bbox.miny();
|
|
||||||
double x2 = bbox.maxx();
|
agg::trans_affine_translation const recenter(-center.x, -center.y);
|
||||||
double y2 = bbox.maxy();
|
agg::trans_affine const recenter_tr = recenter * tr;
|
||||||
double w = (*mark)->width();
|
box2d<double> extent = bbox * recenter_tr;
|
||||||
double h = (*mark)->height();
|
|
||||||
|
|
||||||
agg::trans_affine recenter = agg::trans_affine_translation(-0.5*(x1+x2),-0.5*(y1+y2));
|
|
||||||
tr.transform(&x1,&y1);
|
|
||||||
tr.transform(&x2,&y2);
|
|
||||||
box2d<double> extent(x1,y1,x2,y2);
|
|
||||||
using namespace mapnik::svg;
|
using namespace mapnik::svg;
|
||||||
vertex_stl_adapter<svg_path_storage> stl_storage((*marker)->source());
|
vertex_stl_adapter<svg_path_storage> stl_storage((*marker)->source());
|
||||||
svg_path_adapter svg_path(stl_storage);
|
svg_path_adapter svg_path(stl_storage);
|
||||||
|
@ -132,7 +126,11 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
||||||
detector_->has_placement(extent))
|
detector_->has_placement(extent))
|
||||||
{
|
{
|
||||||
|
|
||||||
render_marker(pixel_position(x - 0.5 * w, y - 0.5 * h) ,**mark, tr, sym.get_opacity(), sym.comp_op());
|
render_marker(pixel_position(x, y), **mark, tr, sym.get_opacity(), sym.comp_op());
|
||||||
|
|
||||||
|
if (/* DEBUG */ 0) {
|
||||||
|
debug_draw_box(buf, extent, 0, 0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO - impl this for markers?
|
// TODO - impl this for markers?
|
||||||
//if (!sym.get_ignore_placement())
|
//if (!sym.get_ignore_placement())
|
||||||
|
@ -154,8 +152,22 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
||||||
|
|
||||||
while (placement.get_point(&x, &y, &angle))
|
while (placement.get_point(&x, &y, &angle))
|
||||||
{
|
{
|
||||||
agg::trans_affine matrix = recenter * tr *agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x, y);
|
agg::trans_affine matrix = recenter_tr;
|
||||||
|
matrix.rotate(angle);
|
||||||
|
matrix.translate(x, y);
|
||||||
svg_renderer.render(*ras_ptr, sl, renb, matrix, sym.get_opacity(),bbox);
|
svg_renderer.render(*ras_ptr, sl, renb, matrix, sym.get_opacity(),bbox);
|
||||||
|
|
||||||
|
if (/* DEBUG */ 0) {
|
||||||
|
agg::trans_affine_rotation r(angle);
|
||||||
|
debug_draw_box(buf, extent * r, x, y, 0.0);
|
||||||
|
// note: debug_draw_box(buf, extent, x, y, angle)
|
||||||
|
// would draw a rotated box showing the proper
|
||||||
|
// bounds of the marker, while the above will
|
||||||
|
// draw the box used for collision detection,
|
||||||
|
// which embraces the rotated extent but isn't
|
||||||
|
// rotated itself
|
||||||
|
}
|
||||||
|
|
||||||
if (writer.first)
|
if (writer.first)
|
||||||
{
|
{
|
||||||
//writer.first->add_box(label_ext, feature, t_, writer.second);
|
//writer.first->add_box(label_ext, feature, t_, writer.second);
|
||||||
|
|
|
@ -63,26 +63,15 @@ void agg_renderer<T>::process(point_symbolizer const& sym,
|
||||||
|
|
||||||
if (marker)
|
if (marker)
|
||||||
{
|
{
|
||||||
double w = (*marker)->width();
|
box2d<double> const& bbox = (*marker)->bounding_box();
|
||||||
double h = (*marker)->height();
|
coord2d const center = bbox.center();
|
||||||
|
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr;
|
||||||
boost::array<double,6> const& m = sym.get_image_transform();
|
evaluate_transform(tr, *feature, sym.get_image_transform());
|
||||||
tr.load_from(&m[0]);
|
|
||||||
double px0 = - 0.5 * w;
|
agg::trans_affine_translation const recenter(-center.x, -center.y);
|
||||||
double py0 = - 0.5 * h;
|
agg::trans_affine const recenter_tr = recenter * tr;
|
||||||
double px1 = 0.5 * w;
|
box2d<double> label_ext = bbox * recenter_tr;
|
||||||
double py1 = 0.5 * h;
|
|
||||||
double px2 = px1;
|
|
||||||
double py2 = py0;
|
|
||||||
double px3 = px0;
|
|
||||||
double py3 = py1;
|
|
||||||
tr.transform(&px0,&py0);
|
|
||||||
tr.transform(&px1,&py1);
|
|
||||||
tr.transform(&px2,&py2);
|
|
||||||
tr.transform(&px3,&py3);
|
|
||||||
box2d<double> label_ext (px0, py0, px1, py1);
|
|
||||||
label_ext.expand_to_include(px2, py2);
|
|
||||||
label_ext.expand_to_include(px3, py3);
|
|
||||||
|
|
||||||
for (unsigned i=0; i<feature->num_geometries(); ++i)
|
for (unsigned i=0; i<feature->num_geometries(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -103,7 +92,11 @@ void agg_renderer<T>::process(point_symbolizer const& sym,
|
||||||
detector_->has_placement(label_ext))
|
detector_->has_placement(label_ext))
|
||||||
{
|
{
|
||||||
|
|
||||||
render_marker(pixel_position(x - 0.5 * w, y - 0.5 * h) ,**marker,tr, sym.get_opacity(), sym.comp_op());
|
render_marker(pixel_position(x, y), **marker, tr, sym.get_opacity(), sym.comp_op());
|
||||||
|
|
||||||
|
if (/* DEBUG */ 0) {
|
||||||
|
debug_draw_box(label_ext, 0, 0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
if (!sym.get_ignore_placement())
|
if (!sym.get_ignore_placement())
|
||||||
detector_->insert(label_ext);
|
detector_->insert(label_ext);
|
||||||
|
|
|
@ -136,10 +136,14 @@ void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
|
||||||
agg::span_allocator<agg::rgba8> sa;
|
agg::span_allocator<agg::rgba8> sa;
|
||||||
renderer_type rp(renb,sa, sg);
|
renderer_type rp(renb,sa, sg);
|
||||||
|
|
||||||
|
agg::trans_affine tr;
|
||||||
|
evaluate_transform(tr, *feature, sym.get_transform());
|
||||||
|
|
||||||
box2d<double> inflated_extent = query_extent_ * 1.0;
|
box2d<double> inflated_extent = query_extent_ * 1.0;
|
||||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_poly_tag,transform_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>,rasterizer,polygon_pattern_symbolizer, proj_transform, CoordTransform,conv_types>
|
vertex_converter<box2d<double>, rasterizer, polygon_pattern_symbolizer,
|
||||||
converter(inflated_extent,*ras_ptr,sym,t_,prj_trans, scale_factor_);
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
|
converter(inflated_extent,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||||
|
|
||||||
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
|
|
|
@ -50,9 +50,13 @@ void agg_renderer<T>::process(polygon_symbolizer const& sym,
|
||||||
|
|
||||||
box2d<double> inflated_extent = query_extent_ * 1.0;
|
box2d<double> inflated_extent = query_extent_ * 1.0;
|
||||||
|
|
||||||
|
agg::trans_affine tr;
|
||||||
|
evaluate_transform(tr, *feature, sym.get_transform());
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>,rasterizer,polygon_symbolizer, proj_transform, CoordTransform,conv_types>
|
vertex_converter<box2d<double>, rasterizer, polygon_symbolizer,
|
||||||
converter(inflated_extent,*ras_ptr,sym,t_,prj_trans,scale_factor_);
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
|
converter(inflated_extent,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||||
|
|
||||||
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
|
|
|
@ -52,7 +52,15 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
|
||||||
placements_type &placements = helper.placements();
|
placements_type &placements = helper.placements();
|
||||||
for (unsigned int ii = 0; ii < placements.size(); ++ii)
|
for (unsigned int ii = 0; ii < placements.size(); ++ii)
|
||||||
{
|
{
|
||||||
render_marker(helper.get_marker_position(placements[ii]),
|
// get_marker_position returns (minx,miny) corner position,
|
||||||
|
// while (currently only) agg_renderer::render_marker newly
|
||||||
|
// expects center position;
|
||||||
|
// until all renderers and shield_symbolizer_helper are
|
||||||
|
// modified accordingly, we must adjust the position here
|
||||||
|
pixel_position pos = helper.get_marker_position(placements[ii]);
|
||||||
|
pos.x += 0.5 * helper.get_marker_width();
|
||||||
|
pos.y += 0.5 * helper.get_marker_height();
|
||||||
|
render_marker(pos,
|
||||||
helper.get_marker(),
|
helper.get_marker(),
|
||||||
helper.get_image_transform(),
|
helper.get_image_transform(),
|
||||||
sym.get_opacity(),
|
sym.get_opacity(),
|
||||||
|
|
|
@ -110,6 +110,7 @@ source = Split(
|
||||||
deepcopy.cpp
|
deepcopy.cpp
|
||||||
expression_string.cpp
|
expression_string.cpp
|
||||||
expression.cpp
|
expression.cpp
|
||||||
|
transform_expression.cpp
|
||||||
feature_kv_iterator.cpp
|
feature_kv_iterator.cpp
|
||||||
feature_type_style.cpp
|
feature_type_style.cpp
|
||||||
font_engine_freetype.cpp
|
font_engine_freetype.cpp
|
||||||
|
@ -126,6 +127,7 @@ source = Split(
|
||||||
load_map.cpp
|
load_map.cpp
|
||||||
memory.cpp
|
memory.cpp
|
||||||
parse_path.cpp
|
parse_path.cpp
|
||||||
|
parse_transform.cpp
|
||||||
palette.cpp
|
palette.cpp
|
||||||
placement_finder.cpp
|
placement_finder.cpp
|
||||||
plugin.cpp
|
plugin.cpp
|
||||||
|
|
|
@ -833,9 +833,13 @@ void cairo_renderer_base::start_map_processing(Map const& map)
|
||||||
context.set_operator(sym.comp_op());
|
context.set_operator(sym.comp_op());
|
||||||
context.set_color(sym.get_fill(), sym.get_opacity());
|
context.set_color(sym.get_fill(), sym.get_opacity());
|
||||||
|
|
||||||
|
agg::trans_affine tr;
|
||||||
|
evaluate_transform(tr, *feature, sym.get_transform());
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>,cairo_context,polygon_symbolizer, proj_transform, CoordTransform, conv_types>
|
vertex_converter<box2d<double>, cairo_context, polygon_symbolizer,
|
||||||
converter(query_extent_,context,sym,t_,prj_trans,1.0);
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
|
converter(query_extent_,context,sym,t_,prj_trans,tr,1.0);
|
||||||
|
|
||||||
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
|
@ -980,10 +984,13 @@ void cairo_renderer_base::start_map_processing(Map const& map)
|
||||||
context.set_dash(stroke_.get_dash_array());
|
context.set_dash(stroke_.get_dash_array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
agg::trans_affine tr;
|
||||||
|
evaluate_transform(tr, *feature, sym.get_transform());
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_line_tag,transform_tag, offset_transform_tag, affine_transform_tag, smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_line_tag,transform_tag, offset_transform_tag, affine_transform_tag, smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>,cairo_context,line_symbolizer, proj_transform, CoordTransform,conv_types>
|
vertex_converter<box2d<double>, cairo_context, line_symbolizer,
|
||||||
converter(query_extent_,context ,sym,t_,prj_trans,1.0);
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
|
converter(query_extent_,context,sym,t_,prj_trans,tr,1.0);
|
||||||
|
|
||||||
if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
|
if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
|
||||||
converter.set<transform_tag>(); // always transform
|
converter.set<transform_tag>(); // always transform
|
||||||
|
@ -1131,6 +1138,9 @@ void cairo_renderer_base::start_map_processing(Map const& map)
|
||||||
marker.reset(boost::make_shared<mapnik::marker>());
|
marker.reset(boost::make_shared<mapnik::marker>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
agg::trans_affine mtx;
|
||||||
|
evaluate_transform(mtx, *feature, sym.get_image_transform());
|
||||||
|
|
||||||
if (marker)
|
if (marker)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < feature->num_geometries(); ++i)
|
for (unsigned i = 0; i < feature->num_geometries(); ++i)
|
||||||
|
@ -1157,10 +1167,6 @@ void cairo_renderer_base::start_map_processing(Map const& map)
|
||||||
if (sym.get_allow_overlap() ||
|
if (sym.get_allow_overlap() ||
|
||||||
detector_.has_placement(label_ext))
|
detector_.has_placement(label_ext))
|
||||||
{
|
{
|
||||||
agg::trans_affine mtx;
|
|
||||||
boost::array<double,6> const& m = sym.get_image_transform();
|
|
||||||
mtx.load_from(&m[0]);
|
|
||||||
|
|
||||||
render_marker(pixel_position(px,py),**marker, mtx, sym.get_opacity());
|
render_marker(pixel_position(px,py),**marker, mtx, sym.get_opacity());
|
||||||
|
|
||||||
if (!sym.get_ignore_placement())
|
if (!sym.get_ignore_placement())
|
||||||
|
@ -1293,9 +1299,13 @@ void cairo_renderer_base::start_map_processing(Map const& map)
|
||||||
|
|
||||||
context.set_pattern(pattern);
|
context.set_pattern(pattern);
|
||||||
|
|
||||||
|
agg::trans_affine tr;
|
||||||
|
evaluate_transform(tr, *feature, sym.get_transform());
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>,cairo_context,polygon_pattern_symbolizer, proj_transform, CoordTransform, conv_types>
|
vertex_converter<box2d<double>, cairo_context, polygon_pattern_symbolizer,
|
||||||
converter(query_extent_,context,sym,t_,prj_trans,1.0);
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
|
converter(query_extent_,context,sym,t_,prj_trans,tr,1.0);
|
||||||
|
|
||||||
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
if (sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
|
@ -1371,8 +1381,8 @@ void cairo_renderer_base::start_map_processing(Map const& map)
|
||||||
typedef coord_transform<CoordTransform,clipped_geometry_type> path_type;
|
typedef coord_transform<CoordTransform,clipped_geometry_type> path_type;
|
||||||
|
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr;
|
||||||
boost::array<double,6> const& m = sym.get_image_transform();
|
evaluate_transform(tr, *feature, sym.get_image_transform());
|
||||||
tr.load_from(&m[0]);
|
|
||||||
// TODO - use this?
|
// TODO - use this?
|
||||||
//tr = agg::trans_affine_scaling(scale_factor_) * tr;
|
//tr = agg::trans_affine_scaling(scale_factor_) * tr;
|
||||||
std::string filename = path_processor_type::evaluate(*sym.get_filename(), *feature);
|
std::string filename = path_processor_type::evaluate(*sym.get_filename(), *feature);
|
||||||
|
|
|
@ -69,8 +69,7 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
|
||||||
ras_ptr->reset();
|
ras_ptr->reset();
|
||||||
|
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr;
|
||||||
boost::array<double,6> const& m = sym.get_image_transform();
|
evaluate_transform(tr, *feature, sym.get_image_transform());
|
||||||
tr.load_from(&m[0]);
|
|
||||||
unsigned int res = pixmap_.get_resolution();
|
unsigned int res = pixmap_.get_resolution();
|
||||||
tr = agg::trans_affine_scaling(scale_factor_*(1.0/res)) * tr;
|
tr = agg::trans_affine_scaling(scale_factor_*(1.0/res)) * tr;
|
||||||
std::string filename = path_processor_type::evaluate(*sym.get_filename(), *feature);
|
std::string filename = path_processor_type::evaluate(*sym.get_filename(), *feature);
|
||||||
|
|
|
@ -55,6 +55,9 @@ void grid_renderer<T>::process(point_symbolizer const& sym,
|
||||||
|
|
||||||
if (marker)
|
if (marker)
|
||||||
{
|
{
|
||||||
|
agg::trans_affine tr;
|
||||||
|
evaluate_transform(tr, *feature, sym.get_image_transform());
|
||||||
|
|
||||||
for (unsigned i=0; i<feature->num_geometries(); ++i)
|
for (unsigned i=0; i<feature->num_geometries(); ++i)
|
||||||
{
|
{
|
||||||
geometry_type const& geom = feature->get_geometry(i);
|
geometry_type const& geom = feature->get_geometry(i);
|
||||||
|
@ -78,10 +81,6 @@ void grid_renderer<T>::process(point_symbolizer const& sym,
|
||||||
if (sym.get_allow_overlap() ||
|
if (sym.get_allow_overlap() ||
|
||||||
detector_.has_placement(label_ext))
|
detector_.has_placement(label_ext))
|
||||||
{
|
{
|
||||||
agg::trans_affine tr;
|
|
||||||
boost::array<double,6> const& m = sym.get_image_transform();
|
|
||||||
tr.load_from(&m[0]);
|
|
||||||
|
|
||||||
render_marker(feature, pixmap_.get_resolution(),
|
render_marker(feature, pixmap_.get_resolution(),
|
||||||
pixel_position(px, py),
|
pixel_position(px, py),
|
||||||
**marker, tr,
|
**marker, tr,
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
#include <mapnik/expression.hpp>
|
#include <mapnik/expression.hpp>
|
||||||
#include <mapnik/parse_path.hpp>
|
#include <mapnik/parse_path.hpp>
|
||||||
|
#include <mapnik/parse_transform.hpp>
|
||||||
#include <mapnik/raster_colorizer.hpp>
|
#include <mapnik/raster_colorizer.hpp>
|
||||||
|
|
||||||
#include <mapnik/svg/svg_path_parser.hpp>
|
#include <mapnik/svg/svg_path_parser.hpp>
|
||||||
|
@ -838,8 +839,8 @@ void map_parser::parse_symbolizer_base(symbolizer_base &sym, xml_node const &pt)
|
||||||
optional<std::string> transform_wkt = pt.get_opt_attr<std::string>("transform");
|
optional<std::string> transform_wkt = pt.get_opt_attr<std::string>("transform");
|
||||||
if (transform_wkt)
|
if (transform_wkt)
|
||||||
{
|
{
|
||||||
agg::trans_affine tr;
|
mapnik::transform_list_ptr tl = boost::make_shared<mapnik::transform_list>();
|
||||||
if (!mapnik::svg::parse_transform((*transform_wkt).c_str(),tr))
|
if (!mapnik::parse_transform(*tl, *transform_wkt, pt.get_tree().transform_expr_grammar))
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Could not parse transform from '" << transform_wkt << "', expected SVG transform attribute";
|
ss << "Could not parse transform from '" << transform_wkt << "', expected SVG transform attribute";
|
||||||
|
@ -848,9 +849,7 @@ void map_parser::parse_symbolizer_base(symbolizer_base &sym, xml_node const &pt)
|
||||||
else
|
else
|
||||||
std::clog << "### WARNING: " << ss.str() << endl;
|
std::clog << "### WARNING: " << ss.str() << endl;
|
||||||
}
|
}
|
||||||
boost::array<double,6> matrix;
|
sym.set_transform(tl);
|
||||||
tr.store_to(&matrix[0]);
|
|
||||||
sym.set_transform(matrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<boolean> clip = pt.get_opt_attr<boolean>("clip");
|
optional<boolean> clip = pt.get_opt_attr<boolean>("clip");
|
||||||
|
@ -919,8 +918,8 @@ void map_parser::parse_point_symbolizer(rule & rule, xml_node const & sym)
|
||||||
optional<std::string> image_transform_wkt = sym.get_opt_attr<std::string>("image-transform");
|
optional<std::string> image_transform_wkt = sym.get_opt_attr<std::string>("image-transform");
|
||||||
if (image_transform_wkt)
|
if (image_transform_wkt)
|
||||||
{
|
{
|
||||||
agg::trans_affine tr;
|
mapnik::transform_list_ptr tl = boost::make_shared<mapnik::transform_list>();
|
||||||
if (!mapnik::svg::parse_transform((*image_transform_wkt).c_str(),tr))
|
if (!mapnik::parse_transform(*tl, *image_transform_wkt, sym.get_tree().transform_expr_grammar))
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Could not parse transform from '" << *image_transform_wkt
|
ss << "Could not parse transform from '" << *image_transform_wkt
|
||||||
|
@ -934,9 +933,7 @@ void map_parser::parse_point_symbolizer(rule & rule, xml_node const & sym)
|
||||||
MAPNIK_LOG_WARN(load_map) << "map_parser: " << ss;
|
MAPNIK_LOG_WARN(load_map) << "map_parser: " << ss;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boost::array<double,6> matrix;
|
symbol.set_image_transform(tl);
|
||||||
tr.store_to(&matrix[0]);
|
|
||||||
symbol.set_image_transform(matrix);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (image_reader_exception const & ex)
|
catch (image_reader_exception const & ex)
|
||||||
|
@ -1014,8 +1011,8 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& sym)
|
||||||
optional<std::string> image_transform_wkt = sym.get_opt_attr<std::string>("image-transform");
|
optional<std::string> image_transform_wkt = sym.get_opt_attr<std::string>("image-transform");
|
||||||
if (image_transform_wkt)
|
if (image_transform_wkt)
|
||||||
{
|
{
|
||||||
agg::trans_affine tr;
|
mapnik::transform_list_ptr tl = boost::make_shared<mapnik::transform_list>();
|
||||||
if (!mapnik::svg::parse_transform((*image_transform_wkt).c_str(),tr))
|
if (!mapnik::parse_transform(*tl, *image_transform_wkt, sym.get_tree().transform_expr_grammar))
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Could not parse transform from '" << *image_transform_wkt
|
ss << "Could not parse transform from '" << *image_transform_wkt
|
||||||
|
@ -1029,9 +1026,7 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& sym)
|
||||||
MAPNIK_LOG_WARN(load_map) << "map_parser: " << ss;
|
MAPNIK_LOG_WARN(load_map) << "map_parser: " << ss;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boost::array<double,6> matrix;
|
symbol.set_image_transform(tl);
|
||||||
tr.store_to(&matrix[0]);
|
|
||||||
symbol.set_image_transform(matrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<color> c = sym.get_opt_attr<color>("fill");
|
optional<color> c = sym.get_opt_attr<color>("fill");
|
||||||
|
@ -1257,8 +1252,8 @@ void map_parser::parse_shield_symbolizer(rule & rule, xml_node const& sym)
|
||||||
optional<std::string> image_transform_wkt = sym.get_opt_attr<std::string>("image-transform");
|
optional<std::string> image_transform_wkt = sym.get_opt_attr<std::string>("image-transform");
|
||||||
if (image_transform_wkt)
|
if (image_transform_wkt)
|
||||||
{
|
{
|
||||||
agg::trans_affine tr;
|
mapnik::transform_list_ptr tl = boost::make_shared<mapnik::transform_list>();
|
||||||
if (!mapnik::svg::parse_transform((*image_transform_wkt).c_str(),tr))
|
if (!mapnik::parse_transform(*tl, *image_transform_wkt, sym.get_tree().transform_expr_grammar))
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Could not parse transform from '" << *image_transform_wkt
|
ss << "Could not parse transform from '" << *image_transform_wkt
|
||||||
|
@ -1272,9 +1267,7 @@ void map_parser::parse_shield_symbolizer(rule & rule, xml_node const& sym)
|
||||||
MAPNIK_LOG_WARN(load_map) << "map_parser: " << ss;
|
MAPNIK_LOG_WARN(load_map) << "map_parser: " << ss;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boost::array<double,6> matrix;
|
shield_symbol.set_image_transform(tl);
|
||||||
tr.store_to(&matrix[0]);
|
|
||||||
shield_symbol.set_image_transform(matrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// shield displacement
|
// shield displacement
|
||||||
|
|
46
src/parse_transform.cpp
Normal file
46
src/parse_transform.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include <mapnik/parse_transform.hpp>
|
||||||
|
#include <mapnik/transform_expression_grammar.hpp>
|
||||||
|
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
|
namespace mapnik {
|
||||||
|
|
||||||
|
bool parse_transform(transform_list& transform,
|
||||||
|
std::string const & str,
|
||||||
|
transform_expression_grammar<std::string::const_iterator> const& g)
|
||||||
|
{
|
||||||
|
std::string::const_iterator itr = str.begin();
|
||||||
|
std::string::const_iterator end = str.end();
|
||||||
|
bool r = qi::phrase_parse(itr, end, g, space_type(), transform);
|
||||||
|
|
||||||
|
#ifdef MAPNIK_LOG
|
||||||
|
MAPNIK_LOG_DEBUG(load_map) << "map_parser: Parsed transform [ "
|
||||||
|
<< transform_processor_type::to_string(transform) << " ]";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (r && itr==end);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -244,8 +244,10 @@ public:
|
||||||
{
|
{
|
||||||
set_attr( sym_node, "fill-opacity", sym.get_opacity() );
|
set_attr( sym_node, "fill-opacity", sym.get_opacity() );
|
||||||
}
|
}
|
||||||
|
if (sym.height())
|
||||||
set_attr( sym_node, "height", to_expression_string(*sym.height()) );
|
{
|
||||||
|
set_attr( sym_node, "height", mapnik::to_expression_string(*sym.height()) );
|
||||||
|
}
|
||||||
|
|
||||||
add_metawriter_attributes(sym_node, sym);
|
add_metawriter_attributes(sym_node, sym);
|
||||||
}
|
}
|
||||||
|
@ -255,8 +257,9 @@ public:
|
||||||
ptree & sym_node = rule_.push_back(
|
ptree & sym_node = rule_.push_back(
|
||||||
ptree::value_type("MarkersSymbolizer", ptree()))->second;
|
ptree::value_type("MarkersSymbolizer", ptree()))->second;
|
||||||
markers_symbolizer dfl(parse_path("")); //TODO: Parameter?
|
markers_symbolizer dfl(parse_path("")); //TODO: Parameter?
|
||||||
std::string const& filename = path_processor_type::to_string( *sym.get_filename());
|
if (sym.get_filename())
|
||||||
if ( ! filename.empty() ) {
|
{
|
||||||
|
std::string filename = path_processor_type::to_string(*sym.get_filename());
|
||||||
set_attr( sym_node, "file", filename );
|
set_attr( sym_node, "file", filename );
|
||||||
}
|
}
|
||||||
if (sym.get_allow_overlap() != dfl.get_allow_overlap() || explicit_defaults_)
|
if (sym.get_allow_overlap() != dfl.get_allow_overlap() || explicit_defaults_)
|
||||||
|
@ -299,9 +302,9 @@ public:
|
||||||
{
|
{
|
||||||
set_attr( sym_node, "placement", sym.get_marker_placement() );
|
set_attr( sym_node, "placement", sym.get_marker_placement() );
|
||||||
}
|
}
|
||||||
std::string tr_str = sym.get_image_transform_string();
|
if (sym.get_image_transform())
|
||||||
if (tr_str != "matrix(1, 0, 0, 1, 0, 0)" || explicit_defaults_ )
|
|
||||||
{
|
{
|
||||||
|
std::string tr_str = sym.get_image_transform_string();
|
||||||
set_attr( sym_node, "image-transform", tr_str );
|
set_attr( sym_node, "image-transform", tr_str );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,8 +352,9 @@ private:
|
||||||
|
|
||||||
void add_image_attributes(ptree & node, const symbolizer_with_image & sym)
|
void add_image_attributes(ptree & node, const symbolizer_with_image & sym)
|
||||||
{
|
{
|
||||||
std::string const& filename = path_processor_type::to_string( *sym.get_filename());
|
if (sym.get_filename())
|
||||||
if ( ! filename.empty() ) {
|
{
|
||||||
|
std::string filename = path_processor_type::to_string( *sym.get_filename());
|
||||||
set_attr( node, "file", filename );
|
set_attr( node, "file", filename );
|
||||||
}
|
}
|
||||||
if (sym.get_opacity() != 1.0 || explicit_defaults_ )
|
if (sym.get_opacity() != 1.0 || explicit_defaults_ )
|
||||||
|
@ -358,6 +362,7 @@ private:
|
||||||
set_attr( node, "opacity", sym.get_opacity() );
|
set_attr( node, "opacity", sym.get_opacity() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_font_attributes(ptree & node, const text_symbolizer & sym)
|
void add_font_attributes(ptree & node, const text_symbolizer & sym)
|
||||||
{
|
{
|
||||||
text_placements_ptr p = sym.get_placement_options();
|
text_placements_ptr p = sym.get_placement_options();
|
||||||
|
@ -386,7 +391,6 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void add_stroke_attributes(ptree & node, const stroke & strk)
|
void add_stroke_attributes(ptree & node, const stroke & strk)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -434,8 +438,8 @@ private:
|
||||||
}
|
}
|
||||||
set_attr( node, "stroke-dasharray", os.str() );
|
set_attr( node, "stroke-dasharray", os.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_metawriter_attributes(ptree & node, symbolizer_base const& sym)
|
void add_metawriter_attributes(ptree & node, symbolizer_base const& sym)
|
||||||
{
|
{
|
||||||
if (!sym.get_metawriter_name().empty() || explicit_defaults_) {
|
if (!sym.get_metawriter_name().empty() || explicit_defaults_) {
|
||||||
|
@ -444,13 +448,11 @@ private:
|
||||||
if (!sym.get_metawriter_properties_overrides().empty() || explicit_defaults_) {
|
if (!sym.get_metawriter_properties_overrides().empty() || explicit_defaults_) {
|
||||||
set_attr(node, "meta-output", sym.get_metawriter_properties_overrides().to_string());
|
set_attr(node, "meta-output", sym.get_metawriter_properties_overrides().to_string());
|
||||||
}
|
}
|
||||||
|
if (sym.get_transform())
|
||||||
std::string tr_str = sym.get_transform_string();
|
|
||||||
if (tr_str != "matrix(1, 0, 0, 1, 0, 0)" || explicit_defaults_ ) // FIXME !!
|
|
||||||
{
|
{
|
||||||
|
std::string tr_str = sym.get_transform_string();
|
||||||
set_attr( node, "transform", tr_str );
|
set_attr( node, "transform", tr_str );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptree & rule_;
|
ptree & rule_;
|
||||||
|
|
|
@ -23,9 +23,26 @@
|
||||||
//mapnik
|
//mapnik
|
||||||
#include <mapnik/symbolizer.hpp>
|
#include <mapnik/symbolizer.hpp>
|
||||||
#include <mapnik/map.hpp>
|
#include <mapnik/map.hpp>
|
||||||
|
#include <mapnik/parse_transform.hpp>
|
||||||
|
|
||||||
namespace mapnik {
|
namespace mapnik {
|
||||||
|
|
||||||
|
void evaluate_transform(agg::trans_affine& tr, Feature const& feature,
|
||||||
|
transform_list_ptr const& trans_expr)
|
||||||
|
{
|
||||||
|
#ifdef MAPNIK_LOG
|
||||||
|
MAPNIK_LOG_DEBUG(transform) << "transform: evaluate "
|
||||||
|
<< (trans_expr
|
||||||
|
? transform_processor_type::to_string(*trans_expr)
|
||||||
|
: std::string("null"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (trans_expr)
|
||||||
|
{
|
||||||
|
transform_processor_type::evaluate(tr, feature, *trans_expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// default ctor
|
// default ctor
|
||||||
symbolizer_base::symbolizer_base()
|
symbolizer_base::symbolizer_base()
|
||||||
: properties_(),
|
: properties_(),
|
||||||
|
@ -36,12 +53,6 @@ symbolizer_base::symbolizer_base()
|
||||||
clip_(true),
|
clip_(true),
|
||||||
smooth_value_(0.0)
|
smooth_value_(0.0)
|
||||||
{
|
{
|
||||||
affine_transform_[0] = 1.0;
|
|
||||||
affine_transform_[1] = 0.0;
|
|
||||||
affine_transform_[2] = 0.0;
|
|
||||||
affine_transform_[3] = 1.0;
|
|
||||||
affine_transform_[4] = 0.0;
|
|
||||||
affine_transform_[5] = 0.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy ctor
|
// copy ctor
|
||||||
|
@ -107,6 +118,13 @@ composite_mode_e symbolizer_base::comp_op() const
|
||||||
void symbolizer_base::set_transform(transform_type const& affine_transform)
|
void symbolizer_base::set_transform(transform_type const& affine_transform)
|
||||||
{
|
{
|
||||||
affine_transform_ = affine_transform;
|
affine_transform_ = affine_transform;
|
||||||
|
|
||||||
|
#ifdef MAPNIK_LOG
|
||||||
|
MAPNIK_LOG_DEBUG(load_map) << "map_parser: set_transform: "
|
||||||
|
<< (affine_transform_
|
||||||
|
? transform_processor_type::to_string(*affine_transform_)
|
||||||
|
: std::string("null"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
transform_type const& symbolizer_base::get_transform() const
|
transform_type const& symbolizer_base::get_transform() const
|
||||||
|
@ -116,11 +134,10 @@ transform_type const& symbolizer_base::get_transform() const
|
||||||
|
|
||||||
std::string symbolizer_base::get_transform_string() const
|
std::string symbolizer_base::get_transform_string() const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
if (affine_transform_)
|
||||||
ss << "matrix(" << affine_transform_[0] << ", " << affine_transform_[1] << ", "
|
return transform_processor_type::to_string(*affine_transform_);
|
||||||
<< affine_transform_[2] << ", " << affine_transform_[3] << ", "
|
else
|
||||||
<< affine_transform_[4] << ", " << affine_transform_[5] << ")";
|
return std::string();
|
||||||
return ss.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void symbolizer_base::set_clip(bool clip)
|
void symbolizer_base::set_clip(bool clip)
|
||||||
|
@ -149,12 +166,6 @@ symbolizer_with_image::symbolizer_with_image(path_expression_ptr file)
|
||||||
: image_filename_( file ),
|
: image_filename_( file ),
|
||||||
image_opacity_(1.0f)
|
image_opacity_(1.0f)
|
||||||
{
|
{
|
||||||
image_transform_[0] = 1.0;
|
|
||||||
image_transform_[1] = 0.0;
|
|
||||||
image_transform_[2] = 0.0;
|
|
||||||
image_transform_[3] = 1.0;
|
|
||||||
image_transform_[4] = 0.0;
|
|
||||||
image_transform_[5] = 0.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
symbolizer_with_image::symbolizer_with_image( symbolizer_with_image const& rhs)
|
symbolizer_with_image::symbolizer_with_image( symbolizer_with_image const& rhs)
|
||||||
|
@ -187,6 +198,13 @@ float symbolizer_with_image::get_opacity() const
|
||||||
void symbolizer_with_image::set_image_transform(transform_type const& tr)
|
void symbolizer_with_image::set_image_transform(transform_type const& tr)
|
||||||
{
|
{
|
||||||
image_transform_ = tr;
|
image_transform_ = tr;
|
||||||
|
|
||||||
|
#ifdef MAPNIK_LOG
|
||||||
|
MAPNIK_LOG_DEBUG(load_map) << "map_parser: set_image_transform: "
|
||||||
|
<< (image_transform_
|
||||||
|
? transform_processor_type::to_string(*image_transform_)
|
||||||
|
: std::string("null"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
transform_type const& symbolizer_with_image::get_image_transform() const
|
transform_type const& symbolizer_with_image::get_image_transform() const
|
||||||
|
@ -196,11 +214,10 @@ transform_type const& symbolizer_with_image::get_image_transform() const
|
||||||
|
|
||||||
std::string symbolizer_with_image::get_image_transform_string() const
|
std::string symbolizer_with_image::get_image_transform_string() const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
if (image_transform_)
|
||||||
ss << "matrix(" << image_transform_[0] << ", " << image_transform_[1] << ", "
|
return transform_processor_type::to_string(*image_transform_);
|
||||||
<< image_transform_[2] << ", " << image_transform_[3] << ", "
|
else
|
||||||
<< image_transform_[4] << ", " << image_transform_[5] << ")";
|
return std::string();
|
||||||
return ss.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace mapnik
|
} // end of namespace mapnik
|
||||||
|
|
|
@ -350,8 +350,7 @@ template <typename FaceManagerT, typename DetectorT>
|
||||||
void shield_symbolizer_helper<FaceManagerT, DetectorT>::init_marker()
|
void shield_symbolizer_helper<FaceManagerT, DetectorT>::init_marker()
|
||||||
{
|
{
|
||||||
std::string filename = path_processor_type::evaluate(*sym_.get_filename(), this->feature_);
|
std::string filename = path_processor_type::evaluate(*sym_.get_filename(), this->feature_);
|
||||||
boost::array<double,6> const& m = sym_.get_image_transform();
|
evaluate_transform(image_transform_, feature_, sym_.get_image_transform());
|
||||||
image_transform_.load_from(&m[0]);
|
|
||||||
marker_.reset();
|
marker_.reset();
|
||||||
if (!filename.empty())
|
if (!filename.empty())
|
||||||
{
|
{
|
||||||
|
|
144
src/transform_expression.cpp
Normal file
144
src/transform_expression.cpp
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/expression_string.hpp>
|
||||||
|
#include <mapnik/transform_expression.hpp>
|
||||||
|
|
||||||
|
// boost
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
// stl
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace mapnik {
|
||||||
|
|
||||||
|
|
||||||
|
struct transform_node_to_expression_string
|
||||||
|
: public boost::static_visitor<void>
|
||||||
|
{
|
||||||
|
std::ostringstream& os_;
|
||||||
|
|
||||||
|
transform_node_to_expression_string(std::ostringstream& os)
|
||||||
|
: os_(os) {}
|
||||||
|
|
||||||
|
void operator() (identity_node const& node) const
|
||||||
|
{
|
||||||
|
boost::ignore_unused_variable_warning(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (matrix_node const& node)
|
||||||
|
{
|
||||||
|
os_ << "matrix("
|
||||||
|
<< to_expression_string(node.a_) << ", "
|
||||||
|
<< to_expression_string(node.b_) << ", "
|
||||||
|
<< to_expression_string(node.c_) << ", "
|
||||||
|
<< to_expression_string(node.d_) << ", "
|
||||||
|
<< to_expression_string(node.e_) << ", "
|
||||||
|
<< to_expression_string(node.f_) << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (translate_node const& node)
|
||||||
|
{
|
||||||
|
if (is_null(node.ty_))
|
||||||
|
{
|
||||||
|
os_ << "translate("
|
||||||
|
<< to_expression_string(node.tx_) << ")";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os_ << "translate("
|
||||||
|
<< to_expression_string(node.tx_) << ", "
|
||||||
|
<< to_expression_string(node.ty_) << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (scale_node const& node)
|
||||||
|
{
|
||||||
|
if (is_null(node.sy_))
|
||||||
|
{
|
||||||
|
os_ << "scale("
|
||||||
|
<< to_expression_string(node.sx_) << ")";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os_ << "scale("
|
||||||
|
<< to_expression_string(node.sx_) << ", "
|
||||||
|
<< to_expression_string(node.sy_) << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (rotate_node const& node)
|
||||||
|
{
|
||||||
|
if (is_null(node.cy_) || is_null(node.cy_))
|
||||||
|
{
|
||||||
|
os_ << "rotate("
|
||||||
|
<< to_expression_string(node.angle_) << ")";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os_ << "rotate("
|
||||||
|
<< to_expression_string(node.angle_) << ", "
|
||||||
|
<< to_expression_string(node.cx_) << ", "
|
||||||
|
<< to_expression_string(node.cy_) << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (skewX_node const& node)
|
||||||
|
{
|
||||||
|
os_ << "skewX("
|
||||||
|
<< to_expression_string(node.angle_) << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (skewY_node const& node)
|
||||||
|
{
|
||||||
|
os_ << "skewY("
|
||||||
|
<< to_expression_string(node.angle_) << ")";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::string to_expression_string(transform_node const& node)
|
||||||
|
{
|
||||||
|
std::ostringstream os; // FIXME set precision?
|
||||||
|
transform_node_to_expression_string to_string(os);
|
||||||
|
boost::apply_visitor(to_string, *node);
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string to_expression_string(transform_list const& list)
|
||||||
|
{
|
||||||
|
std::ostringstream os; // FIXME set precision?
|
||||||
|
std::streamsize first = 1;
|
||||||
|
transform_node_to_expression_string to_string(os);
|
||||||
|
|
||||||
|
BOOST_FOREACH (transform_node const& node, list)
|
||||||
|
{
|
||||||
|
os.write(" ", first ? (first = 0) : 1);
|
||||||
|
boost::apply_visitor(to_string, *node);
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace mapnik
|
|
@ -172,7 +172,8 @@ xml_tree::xml_tree(std::string const& encoding)
|
||||||
tr_(encoding),
|
tr_(encoding),
|
||||||
color_grammar(),
|
color_grammar(),
|
||||||
expr_grammar(tr_),
|
expr_grammar(tr_),
|
||||||
path_expr_grammar()
|
path_expr_grammar(),
|
||||||
|
transform_expr_grammar(expr_grammar)
|
||||||
{
|
{
|
||||||
node_.set_processed(true); //root node is always processed
|
node_.set_processed(true); //root node is always processed
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue