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
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/parse_transform.hpp>
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
#include <mapnik/svg/svg_path_parser.hpp>
|
||||
#include <mapnik/value_error.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_trans_affine.h"
|
||||
|
||||
|
@ -51,9 +55,9 @@ void set_svg_transform(T& symbolizer, std::string const& transform_wkt)
|
|||
<< "', expected SVG transform attribute";
|
||||
throw mapnik::value_error(ss.str());
|
||||
}
|
||||
mapnik::transform_type matrix;
|
||||
tr.store_to(&matrix[0]);
|
||||
symbolizer.set_image_transform(matrix);
|
||||
transform_list_ptr trans = boost::make_shared<transform_list>();
|
||||
trans->push_back(matrix_node(tr));
|
||||
symbolizer.set_image_transform(trans);
|
||||
}
|
||||
|
||||
} // end of namespace mapnik
|
||||
|
|
|
@ -115,6 +115,13 @@ public:
|
|||
|
||||
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:
|
||||
buffer_type & pixmap_;
|
||||
boost::shared_ptr<buffer_type> internal_buffer_;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
// mapnik
|
||||
#include <mapnik/rule.hpp>
|
||||
#include <mapnik/parse_transform.hpp>
|
||||
// boost
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
@ -35,9 +36,10 @@
|
|||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename Container>
|
||||
struct expression_attributes : boost::static_visitor<void>
|
||||
{
|
||||
explicit expression_attributes(std::set<std::string> & names)
|
||||
explicit expression_attributes(Container& names)
|
||||
: names_(names) {}
|
||||
|
||||
void operator() (value_type const& x) const
|
||||
|
@ -53,35 +55,35 @@ struct expression_attributes : boost::static_visitor<void>
|
|||
template <typename Tag>
|
||||
void operator() (binary_node<Tag> const& x) const
|
||||
{
|
||||
boost::apply_visitor(expression_attributes(names_),x.left);
|
||||
boost::apply_visitor(expression_attributes(names_),x.right);
|
||||
boost::apply_visitor(*this, x.left);
|
||||
boost::apply_visitor(*this, x.right);
|
||||
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
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
|
||||
{
|
||||
boost::apply_visitor(expression_attributes(names_),x.expr);
|
||||
boost::apply_visitor(*this, x.expr);
|
||||
}
|
||||
|
||||
void operator() (regex_replace_node const& x) const
|
||||
{
|
||||
boost::apply_visitor(expression_attributes(names_),x.expr);
|
||||
boost::apply_visitor(*this, x.expr);
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<std::string>& names_;
|
||||
Container& names_;
|
||||
};
|
||||
|
||||
struct symbolizer_attributes : public boost::static_visitor<>
|
||||
{
|
||||
symbolizer_attributes(std::set<std::string>& names)
|
||||
: names_(names) {}
|
||||
: names_(names), f_attr(names) {}
|
||||
|
||||
template <typename T>
|
||||
void operator () (T const&) const {}
|
||||
|
@ -91,12 +93,12 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
|||
expression_set::const_iterator it;
|
||||
expression_set expressions;
|
||||
sym.get_placement_options()->add_expressions(expressions);
|
||||
expression_attributes f_attr(names_);
|
||||
for (it=expressions.begin(); it != expressions.end(); it++)
|
||||
{
|
||||
if (*it) boost::apply_visitor(f_attr, **it);
|
||||
}
|
||||
collect_metawriter(sym);
|
||||
collect_transform(sym.get_transform());
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
collect_metawriter(sym);
|
||||
|
||||
collect_transform(sym.get_image_transform());
|
||||
collect_transform(sym.get_transform());
|
||||
}
|
||||
|
||||
void operator () (line_symbolizer const& sym)
|
||||
{
|
||||
collect_metawriter(sym);
|
||||
collect_transform(sym.get_transform());
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
collect_metawriter(sym);
|
||||
collect_transform(sym.get_image_transform());
|
||||
collect_transform(sym.get_transform());
|
||||
}
|
||||
|
||||
void operator () (polygon_symbolizer const& sym)
|
||||
{
|
||||
collect_metawriter(sym);
|
||||
collect_transform(sym.get_transform());
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
collect_metawriter(sym);
|
||||
collect_transform(sym.get_image_transform());
|
||||
collect_transform(sym.get_transform());
|
||||
}
|
||||
|
||||
void operator () (shield_symbolizer const& sym)
|
||||
|
@ -145,7 +154,6 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
|||
expression_set::const_iterator it;
|
||||
expression_set expressions;
|
||||
sym.get_placement_options()->add_expressions(expressions);
|
||||
expression_attributes f_attr(names_);
|
||||
for (it=expressions.begin(); it != expressions.end(); 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_);
|
||||
}
|
||||
collect_metawriter(sym);
|
||||
collect_transform(sym.get_image_transform());
|
||||
collect_transform(sym.get_transform());
|
||||
}
|
||||
|
||||
void operator () (markers_symbolizer const& sym)
|
||||
{
|
||||
collect_metawriter(sym);
|
||||
collect_transform(sym.get_image_transform());
|
||||
collect_transform(sym.get_transform());
|
||||
}
|
||||
|
||||
void operator () (building_symbolizer const& sym)
|
||||
|
@ -169,20 +181,28 @@ struct symbolizer_attributes : public boost::static_visitor<>
|
|||
expression_ptr const& height_expr = sym.height();
|
||||
if (height_expr)
|
||||
{
|
||||
expression_attributes f_attr(names_);
|
||||
boost::apply_visitor(f_attr,*height_expr);
|
||||
}
|
||||
collect_metawriter(sym);
|
||||
collect_transform(sym.get_transform());
|
||||
}
|
||||
// TODO - support remaining syms
|
||||
|
||||
private:
|
||||
std::set<std::string>& names_;
|
||||
expression_attributes<std::set<std::string> > f_attr;
|
||||
void collect_metawriter(symbolizer_base const& sym)
|
||||
{
|
||||
metawriter_properties const& properties = sym.get_metawriter_properties();
|
||||
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:
|
||||
std::set<std::string>& names_;
|
||||
expression_attributes<std::set<std::string> > f_attr;
|
||||
public:
|
||||
|
||||
attribute_collector(std::set<std::string>& names)
|
||||
: names_(names) {}
|
||||
: names_(names), f_attr(names) {}
|
||||
|
||||
template <typename RuleType>
|
||||
void operator() (RuleType const& r)
|
||||
|
@ -207,7 +228,6 @@ public:
|
|||
}
|
||||
|
||||
expression_ptr const& expr = r.get_filter();
|
||||
expression_attributes f_attr(names_);
|
||||
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
|
||||
{
|
||||
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/metawriter.hpp>
|
||||
#include <mapnik/image_compositing.hpp>
|
||||
#include <mapnik/transform_expression.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/array.hpp>
|
||||
|
@ -36,7 +37,10 @@
|
|||
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;
|
||||
|
||||
|
|
|
@ -150,6 +150,21 @@ public:
|
|||
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();
|
||||
pixel_position get_marker_position(text_path const& p);
|
||||
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>
|
||||
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);
|
||||
double scale_factor = boost::fusion::at_c<5>(args);
|
||||
double scale_factor = boost::fusion::at_c<6>(args);
|
||||
stroke const& stroke_ = sym.get_stroke();
|
||||
dash_array const& d = stroke_.get_dash_array();
|
||||
dash_array::const_iterator itr = d.begin();
|
||||
|
@ -149,7 +148,7 @@ struct converter_traits<T, mapnik::stroke_tag>
|
|||
stroke const& stroke_ = sym.get_stroke();
|
||||
set_join_caps(stroke_,geom);
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
@ -179,10 +178,8 @@ struct converter_traits<T,mapnik::transform_tag>
|
|||
template <typename 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);
|
||||
typename boost::mpl::at<Args,boost::mpl::int_<4> >::type prj_trans = boost::fusion::at_c<4>(args);
|
||||
geom.set_proj_trans(prj_trans);
|
||||
geom.set_trans(tr);
|
||||
geom.set_proj_trans(boost::fusion::at_c<4>(args));
|
||||
geom.set_trans(boost::fusion::at_c<3>(args));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -191,21 +188,19 @@ template <typename T>
|
|||
struct converter_traits<T,mapnik::affine_transform_tag>
|
||||
{
|
||||
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)
|
||||
: agg::conv_transform<geometry_type>(geom, trans_) {}
|
||||
: conv_base_type(geom, agg::trans_affine::identity) {}
|
||||
};
|
||||
|
||||
template <typename 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);
|
||||
boost::array<double,6> const& m = sym.get_transform();
|
||||
geom.trans_.load_from(&m[0]);
|
||||
geom.transformer(boost::fusion::at_c<5>(args));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
typedef C conv_types;
|
||||
typedef B bbox_type;
|
||||
typedef R rasterizer_type;
|
||||
typedef S symbolizer_type;
|
||||
typedef P proj_trans_type;
|
||||
typedef T trans_type;
|
||||
typedef P proj_trans_type;
|
||||
typedef A affine_trans_type;
|
||||
typedef typename boost::fusion::vector
|
||||
<
|
||||
bbox_type const&,
|
||||
|
@ -319,16 +315,20 @@ struct vertex_converter : private boost::noncopyable
|
|||
symbolizer_type const&,
|
||||
trans_type const&,
|
||||
proj_trans_type const&,
|
||||
affine_trans_type const&,
|
||||
double //scale-factor
|
||||
> args_type;
|
||||
|
||||
vertex_converter(bbox_type const& b, rasterizer_type & ras,
|
||||
symbolizer_type const& sym, trans_type & tr,
|
||||
proj_trans_type const& prj_trans,
|
||||
affine_trans_type const& affine_trans,
|
||||
double scale_factor)
|
||||
: disp_(args_type(boost::cref(b), boost::ref(ras),
|
||||
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>
|
||||
void apply(Geometry & geom)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <mapnik/xml_node.hpp>
|
||||
#include <mapnik/expression_grammar.hpp>
|
||||
#include <mapnik/path_expression_grammar.hpp>
|
||||
#include <mapnik/transform_expression_grammar.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/format.hpp>
|
||||
|
@ -57,6 +58,7 @@ public:
|
|||
mapnik::css_color_grammar<std::string::const_iterator> color_grammar;
|
||||
mapnik::expression_grammar<std::string::const_iterator> expr_grammar;
|
||||
path_expression_grammar<std::string::const_iterator> path_expr_grammar;
|
||||
transform_expression_grammar<std::string::const_iterator> transform_expr_grammar;
|
||||
};
|
||||
|
||||
} //ns mapnik
|
||||
|
|
|
@ -277,7 +277,7 @@ void agg_renderer<T>::render_marker(pixel_position const& pos, marker const& mar
|
|||
mtx *= tr;
|
||||
mtx *= agg::trans_affine_scaling(scale_factor_);
|
||||
// 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;
|
||||
vertex_stl_adapter<svg_path_storage> stl_storage((*marker.get_vector_data())->source());
|
||||
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
|
||||
{
|
||||
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(),
|
||||
comp_op, opacity,
|
||||
boost::math::iround(pos.x),
|
||||
boost::math::iround(pos.y),
|
||||
boost::math::iround(pos.x - cx),
|
||||
boost::math::iround(pos.y - cy),
|
||||
false, false);
|
||||
}
|
||||
}
|
||||
|
@ -305,5 +307,57 @@ void agg_renderer<T>::painted(bool 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);
|
||||
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;
|
||||
vertex_converter<box2d<double>,rasterizer_type,line_pattern_symbolizer, proj_transform, CoordTransform, conv_types>
|
||||
converter(ext,ras,sym,t_,prj_trans,scale_factor_);
|
||||
vertex_converter<box2d<double>, rasterizer_type, line_pattern_symbolizer,
|
||||
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)
|
||||
converter.set<transform_tag>(); //always transform
|
||||
|
|
|
@ -76,6 +76,9 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
|
|||
pixfmt_comp_type pixf(buf);
|
||||
renderer_base renb(pixf);
|
||||
|
||||
agg::trans_affine tr;
|
||||
evaluate_transform(tr, *feature, sym.get_transform());
|
||||
|
||||
if (sym.get_rasterizer() == RASTERIZER_FAST)
|
||||
{
|
||||
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);
|
||||
|
||||
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>
|
||||
converter(query_extent_,ras,sym,t_,prj_trans,scaled);
|
||||
vertex_converter<box2d<double>, rasterizer_type, line_symbolizer,
|
||||
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)
|
||||
converter.set<transform_tag>(); // always transform
|
||||
|
@ -111,8 +115,9 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
|
|||
else
|
||||
{
|
||||
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>
|
||||
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,scale_factor_);
|
||||
vertex_converter<box2d<double>, rasterizer, line_symbolizer,
|
||||
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)
|
||||
converter.set<transform_tag>(); // always transform
|
||||
|
|
|
@ -73,8 +73,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
|||
renderer_base renb(pixf);
|
||||
renderer_type ren(renb);
|
||||
agg::trans_affine tr;
|
||||
boost::array<double,6> const& m = sym.get_image_transform();
|
||||
tr.load_from(&m[0]);
|
||||
evaluate_transform(tr, *feature, sym.get_image_transform());
|
||||
tr = agg::trans_affine_scaling(scale_factor_) * tr;
|
||||
std::string filename = path_processor_type::evaluate(*sym.get_filename(), *feature);
|
||||
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();
|
||||
box2d<double> const& bbox = (*marker)->bounding_box();
|
||||
double x1 = bbox.minx();
|
||||
double y1 = bbox.miny();
|
||||
double x2 = bbox.maxx();
|
||||
double y2 = bbox.maxy();
|
||||
double w = (*mark)->width();
|
||||
double h = (*mark)->height();
|
||||
coord2d const center = bbox.center();
|
||||
|
||||
agg::trans_affine_translation const recenter(-center.x, -center.y);
|
||||
agg::trans_affine const recenter_tr = recenter * tr;
|
||||
box2d<double> extent = bbox * recenter_tr;
|
||||
|
||||
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;
|
||||
vertex_stl_adapter<svg_path_storage> stl_storage((*marker)->source());
|
||||
svg_path_adapter svg_path(stl_storage);
|
||||
|
@ -132,7 +126,11 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
|||
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?
|
||||
//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))
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
//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)
|
||||
{
|
||||
double w = (*marker)->width();
|
||||
double h = (*marker)->height();
|
||||
box2d<double> const& bbox = (*marker)->bounding_box();
|
||||
coord2d const center = bbox.center();
|
||||
|
||||
agg::trans_affine tr;
|
||||
boost::array<double,6> const& m = sym.get_image_transform();
|
||||
tr.load_from(&m[0]);
|
||||
double px0 = - 0.5 * w;
|
||||
double py0 = - 0.5 * h;
|
||||
double px1 = 0.5 * w;
|
||||
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);
|
||||
evaluate_transform(tr, *feature, sym.get_image_transform());
|
||||
|
||||
agg::trans_affine_translation const recenter(-center.x, -center.y);
|
||||
agg::trans_affine const recenter_tr = recenter * tr;
|
||||
box2d<double> label_ext = bbox * recenter_tr;
|
||||
|
||||
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))
|
||||
{
|
||||
|
||||
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())
|
||||
detector_->insert(label_ext);
|
||||
|
|
|
@ -136,10 +136,14 @@ void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
|
|||
agg::span_allocator<agg::rgba8> sa;
|
||||
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;
|
||||
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>
|
||||
converter(inflated_extent,*ras_ptr,sym,t_,prj_trans, scale_factor_);
|
||||
vertex_converter<box2d<double>, rasterizer, polygon_pattern_symbolizer,
|
||||
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)
|
||||
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;
|
||||
|
||||
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;
|
||||
vertex_converter<box2d<double>,rasterizer,polygon_symbolizer, proj_transform, CoordTransform,conv_types>
|
||||
converter(inflated_extent,*ras_ptr,sym,t_,prj_trans,scale_factor_);
|
||||
vertex_converter<box2d<double>, rasterizer, polygon_symbolizer,
|
||||
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)
|
||||
converter.set<transform_tag>(); //always transform
|
||||
|
|
|
@ -52,7 +52,15 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
|
|||
placements_type &placements = helper.placements();
|
||||
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_image_transform(),
|
||||
sym.get_opacity(),
|
||||
|
|
|
@ -110,6 +110,7 @@ source = Split(
|
|||
deepcopy.cpp
|
||||
expression_string.cpp
|
||||
expression.cpp
|
||||
transform_expression.cpp
|
||||
feature_kv_iterator.cpp
|
||||
feature_type_style.cpp
|
||||
font_engine_freetype.cpp
|
||||
|
@ -126,6 +127,7 @@ source = Split(
|
|||
load_map.cpp
|
||||
memory.cpp
|
||||
parse_path.cpp
|
||||
parse_transform.cpp
|
||||
palette.cpp
|
||||
placement_finder.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_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;
|
||||
vertex_converter<box2d<double>,cairo_context,polygon_symbolizer, proj_transform, CoordTransform, conv_types>
|
||||
converter(query_extent_,context,sym,t_,prj_trans,1.0);
|
||||
vertex_converter<box2d<double>, cairo_context, polygon_symbolizer,
|
||||
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)
|
||||
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());
|
||||
}
|
||||
|
||||
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;
|
||||
vertex_converter<box2d<double>,cairo_context,line_symbolizer, proj_transform, CoordTransform,conv_types>
|
||||
converter(query_extent_,context ,sym,t_,prj_trans,1.0);
|
||||
vertex_converter<box2d<double>, cairo_context, line_symbolizer,
|
||||
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)
|
||||
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>());
|
||||
}
|
||||
|
||||
agg::trans_affine mtx;
|
||||
evaluate_transform(mtx, *feature, sym.get_image_transform());
|
||||
|
||||
if (marker)
|
||||
{
|
||||
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() ||
|
||||
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());
|
||||
|
||||
if (!sym.get_ignore_placement())
|
||||
|
@ -1293,9 +1299,13 @@ void cairo_renderer_base::start_map_processing(Map const& map)
|
|||
|
||||
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;
|
||||
vertex_converter<box2d<double>,cairo_context,polygon_pattern_symbolizer, proj_transform, CoordTransform, conv_types>
|
||||
converter(query_extent_,context,sym,t_,prj_trans,1.0);
|
||||
vertex_converter<box2d<double>, cairo_context, polygon_pattern_symbolizer,
|
||||
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)
|
||||
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;
|
||||
|
||||
agg::trans_affine tr;
|
||||
boost::array<double,6> const& m = sym.get_image_transform();
|
||||
tr.load_from(&m[0]);
|
||||
evaluate_transform(tr, *feature, sym.get_image_transform());
|
||||
|
||||
// TODO - use this?
|
||||
//tr = agg::trans_affine_scaling(scale_factor_) * tr;
|
||||
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();
|
||||
|
||||
agg::trans_affine tr;
|
||||
boost::array<double,6> const& m = sym.get_image_transform();
|
||||
tr.load_from(&m[0]);
|
||||
evaluate_transform(tr, *feature, sym.get_image_transform());
|
||||
unsigned int res = pixmap_.get_resolution();
|
||||
tr = agg::trans_affine_scaling(scale_factor_*(1.0/res)) * tr;
|
||||
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)
|
||||
{
|
||||
agg::trans_affine tr;
|
||||
evaluate_transform(tr, *feature, sym.get_image_transform());
|
||||
|
||||
for (unsigned i=0; i<feature->num_geometries(); ++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() ||
|
||||
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(),
|
||||
pixel_position(px, py),
|
||||
**marker, tr,
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include <mapnik/expression.hpp>
|
||||
#include <mapnik/parse_path.hpp>
|
||||
#include <mapnik/parse_transform.hpp>
|
||||
#include <mapnik/raster_colorizer.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");
|
||||
if (transform_wkt)
|
||||
{
|
||||
agg::trans_affine tr;
|
||||
if (!mapnik::svg::parse_transform((*transform_wkt).c_str(),tr))
|
||||
mapnik::transform_list_ptr tl = boost::make_shared<mapnik::transform_list>();
|
||||
if (!mapnik::parse_transform(*tl, *transform_wkt, pt.get_tree().transform_expr_grammar))
|
||||
{
|
||||
std::stringstream ss;
|
||||
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
|
||||
std::clog << "### WARNING: " << ss.str() << endl;
|
||||
}
|
||||
boost::array<double,6> matrix;
|
||||
tr.store_to(&matrix[0]);
|
||||
sym.set_transform(matrix);
|
||||
sym.set_transform(tl);
|
||||
}
|
||||
|
||||
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");
|
||||
if (image_transform_wkt)
|
||||
{
|
||||
agg::trans_affine tr;
|
||||
if (!mapnik::svg::parse_transform((*image_transform_wkt).c_str(),tr))
|
||||
mapnik::transform_list_ptr tl = boost::make_shared<mapnik::transform_list>();
|
||||
if (!mapnik::parse_transform(*tl, *image_transform_wkt, sym.get_tree().transform_expr_grammar))
|
||||
{
|
||||
std::stringstream ss;
|
||||
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;
|
||||
}
|
||||
}
|
||||
boost::array<double,6> matrix;
|
||||
tr.store_to(&matrix[0]);
|
||||
symbol.set_image_transform(matrix);
|
||||
symbol.set_image_transform(tl);
|
||||
}
|
||||
}
|
||||
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");
|
||||
if (image_transform_wkt)
|
||||
{
|
||||
agg::trans_affine tr;
|
||||
if (!mapnik::svg::parse_transform((*image_transform_wkt).c_str(),tr))
|
||||
mapnik::transform_list_ptr tl = boost::make_shared<mapnik::transform_list>();
|
||||
if (!mapnik::parse_transform(*tl, *image_transform_wkt, sym.get_tree().transform_expr_grammar))
|
||||
{
|
||||
std::stringstream ss;
|
||||
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;
|
||||
}
|
||||
}
|
||||
boost::array<double,6> matrix;
|
||||
tr.store_to(&matrix[0]);
|
||||
symbol.set_image_transform(matrix);
|
||||
symbol.set_image_transform(tl);
|
||||
}
|
||||
|
||||
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");
|
||||
if (image_transform_wkt)
|
||||
{
|
||||
agg::trans_affine tr;
|
||||
if (!mapnik::svg::parse_transform((*image_transform_wkt).c_str(),tr))
|
||||
mapnik::transform_list_ptr tl = boost::make_shared<mapnik::transform_list>();
|
||||
if (!mapnik::parse_transform(*tl, *image_transform_wkt, sym.get_tree().transform_expr_grammar))
|
||||
{
|
||||
std::stringstream ss;
|
||||
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;
|
||||
}
|
||||
}
|
||||
boost::array<double,6> matrix;
|
||||
tr.store_to(&matrix[0]);
|
||||
shield_symbol.set_image_transform(matrix);
|
||||
shield_symbol.set_image_transform(tl);
|
||||
}
|
||||
|
||||
// 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, "height", to_expression_string(*sym.height()) );
|
||||
if (sym.height())
|
||||
{
|
||||
set_attr( sym_node, "height", mapnik::to_expression_string(*sym.height()) );
|
||||
}
|
||||
|
||||
add_metawriter_attributes(sym_node, sym);
|
||||
}
|
||||
|
@ -255,8 +257,9 @@ public:
|
|||
ptree & sym_node = rule_.push_back(
|
||||
ptree::value_type("MarkersSymbolizer", ptree()))->second;
|
||||
markers_symbolizer dfl(parse_path("")); //TODO: Parameter?
|
||||
std::string const& filename = path_processor_type::to_string( *sym.get_filename());
|
||||
if ( ! filename.empty() ) {
|
||||
if (sym.get_filename())
|
||||
{
|
||||
std::string filename = path_processor_type::to_string(*sym.get_filename());
|
||||
set_attr( sym_node, "file", filename );
|
||||
}
|
||||
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() );
|
||||
}
|
||||
std::string tr_str = sym.get_image_transform_string();
|
||||
if (tr_str != "matrix(1, 0, 0, 1, 0, 0)" || explicit_defaults_ )
|
||||
if (sym.get_image_transform())
|
||||
{
|
||||
std::string tr_str = sym.get_image_transform_string();
|
||||
set_attr( sym_node, "image-transform", tr_str );
|
||||
}
|
||||
|
||||
|
@ -349,8 +352,9 @@ private:
|
|||
|
||||
void add_image_attributes(ptree & node, const symbolizer_with_image & sym)
|
||||
{
|
||||
std::string const& filename = path_processor_type::to_string( *sym.get_filename());
|
||||
if ( ! filename.empty() ) {
|
||||
if (sym.get_filename())
|
||||
{
|
||||
std::string filename = path_processor_type::to_string( *sym.get_filename());
|
||||
set_attr( node, "file", filename );
|
||||
}
|
||||
if (sym.get_opacity() != 1.0 || explicit_defaults_ )
|
||||
|
@ -358,6 +362,7 @@ private:
|
|||
set_attr( node, "opacity", sym.get_opacity() );
|
||||
}
|
||||
}
|
||||
|
||||
void add_font_attributes(ptree & node, const text_symbolizer & sym)
|
||||
{
|
||||
text_placements_ptr p = sym.get_placement_options();
|
||||
|
@ -386,7 +391,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void add_stroke_attributes(ptree & node, const stroke & strk)
|
||||
{
|
||||
|
||||
|
@ -434,8 +438,8 @@ private:
|
|||
}
|
||||
set_attr( node, "stroke-dasharray", os.str() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void add_metawriter_attributes(ptree & node, symbolizer_base const& sym)
|
||||
{
|
||||
if (!sym.get_metawriter_name().empty() || explicit_defaults_) {
|
||||
|
@ -444,13 +448,11 @@ private:
|
|||
if (!sym.get_metawriter_properties_overrides().empty() || explicit_defaults_) {
|
||||
set_attr(node, "meta-output", sym.get_metawriter_properties_overrides().to_string());
|
||||
}
|
||||
|
||||
std::string tr_str = sym.get_transform_string();
|
||||
if (tr_str != "matrix(1, 0, 0, 1, 0, 0)" || explicit_defaults_ ) // FIXME !!
|
||||
if (sym.get_transform())
|
||||
{
|
||||
std::string tr_str = sym.get_transform_string();
|
||||
set_attr( node, "transform", tr_str );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ptree & rule_;
|
||||
|
|
|
@ -23,9 +23,26 @@
|
|||
//mapnik
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
#include <mapnik/map.hpp>
|
||||
#include <mapnik/parse_transform.hpp>
|
||||
|
||||
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
|
||||
symbolizer_base::symbolizer_base()
|
||||
: properties_(),
|
||||
|
@ -36,12 +53,6 @@ symbolizer_base::symbolizer_base()
|
|||
clip_(true),
|
||||
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
|
||||
|
@ -107,6 +118,13 @@ composite_mode_e symbolizer_base::comp_op() const
|
|||
void symbolizer_base::set_transform(transform_type const& 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
|
||||
|
@ -116,11 +134,10 @@ transform_type const& symbolizer_base::get_transform() const
|
|||
|
||||
std::string symbolizer_base::get_transform_string() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "matrix(" << affine_transform_[0] << ", " << affine_transform_[1] << ", "
|
||||
<< affine_transform_[2] << ", " << affine_transform_[3] << ", "
|
||||
<< affine_transform_[4] << ", " << affine_transform_[5] << ")";
|
||||
return ss.str();
|
||||
if (affine_transform_)
|
||||
return transform_processor_type::to_string(*affine_transform_);
|
||||
else
|
||||
return std::string();
|
||||
}
|
||||
|
||||
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_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)
|
||||
|
@ -187,6 +198,13 @@ float symbolizer_with_image::get_opacity() const
|
|||
void symbolizer_with_image::set_image_transform(transform_type const& 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
|
||||
|
@ -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::stringstream ss;
|
||||
ss << "matrix(" << image_transform_[0] << ", " << image_transform_[1] << ", "
|
||||
<< image_transform_[2] << ", " << image_transform_[3] << ", "
|
||||
<< image_transform_[4] << ", " << image_transform_[5] << ")";
|
||||
return ss.str();
|
||||
if (image_transform_)
|
||||
return transform_processor_type::to_string(*image_transform_);
|
||||
else
|
||||
return std::string();
|
||||
}
|
||||
|
||||
} // end of namespace mapnik
|
||||
|
|
|
@ -350,8 +350,7 @@ template <typename FaceManagerT, typename DetectorT>
|
|||
void shield_symbolizer_helper<FaceManagerT, DetectorT>::init_marker()
|
||||
{
|
||||
std::string filename = path_processor_type::evaluate(*sym_.get_filename(), this->feature_);
|
||||
boost::array<double,6> const& m = sym_.get_image_transform();
|
||||
image_transform_.load_from(&m[0]);
|
||||
evaluate_transform(image_transform_, feature_, sym_.get_image_transform());
|
||||
marker_.reset();
|
||||
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),
|
||||
color_grammar(),
|
||||
expr_grammar(tr_),
|
||||
path_expr_grammar()
|
||||
path_expr_grammar(),
|
||||
transform_expr_grammar(expr_grammar)
|
||||
{
|
||||
node_.set_processed(true); //root node is always processed
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue