Fixed a bug that caused half of the vertexes to disappear from the SVG path.

+ mapnik::geometry_iterator was replaced by mapnik::svg::path_iterator
+ svg::path_output_grammar was simplified
+ the container for this grammar is now coord_transform2, instead of geometry
+ added typedef size_type to coord_transform2 and removed it from geometry
This commit is contained in:
Carlos López 2011-02-14 03:40:25 +00:00
parent aabdeb1265
commit 83a7b4710e
6 changed files with 57 additions and 109 deletions

View File

@ -60,6 +60,9 @@ private:
template <typename Transform,typename Geometry>
struct MAPNIK_DECL coord_transform2
{
typedef std::size_t size_type;
typedef typename Geometry::value_type value_type;
coord_transform2(Transform const& t,
Geometry const& geom,
proj_transform const& prj_trans)

View File

@ -48,7 +48,6 @@ class geometry
{
public:
typedef T vertex_type;
typedef std::size_t size_type;
typedef typename vertex_type::type value_type;
typedef Container<vertex_type> container_type;
private:

View File

@ -25,9 +25,9 @@
// mapnik
#include <mapnik/vertex.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/geometry_iterator.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/svg/svg_path_iterator.hpp>
#include <mapnik/svg/svg_output_attributes.hpp>
// boost
@ -94,34 +94,36 @@ BOOST_FUSION_ADAPT_STRUCT(
*/
namespace boost { namespace spirit { namespace traits {
typedef mapnik::coord_transform2<mapnik::CoordTransform, mapnik::geometry_type> path_type;
template <>
struct is_container<mapnik::geometry_type const>
struct is_container<path_type const>
: mpl::true_
{};
template <>
struct container_iterator<mapnik::geometry_type const>
struct container_iterator<path_type const>
{
typedef mapnik::geometry_iterator_type type;
typedef mapnik::svg::path_iterator_type type;
};
template <>
struct begin_container<mapnik::geometry_type const>
struct begin_container<path_type const>
{
static mapnik::geometry_iterator_type
call(mapnik::geometry_type const& g)
static mapnik::svg::path_iterator_type
call(path_type const& path)
{
return mapnik::geometry_iterator_type(0, g);
return mapnik::svg::path_iterator_type(0, path);
}
};
template <>
struct end_container<mapnik::geometry_type const>
struct end_container<path_type const>
{
static mapnik::geometry_iterator_type
call(mapnik::geometry_type const& g)
static mapnik::svg::path_iterator_type
call(path_type const& path)
{
return mapnik::geometry_iterator_type(g);
return mapnik::svg::path_iterator_type(path);
}
};
}}}
@ -131,67 +133,17 @@ namespace mapnik { namespace svg {
using namespace boost::spirit;
using namespace boost::phoenix;
/*!
* @brief Structure that performs the conversion from map to user coordinates.
* It's methods and functions are meant to be used by svg_path_data_grammar as
* semantic actions to convert the value of vertex coordinates inside the grammar.
*
* It (kind of) works like a state machine, setting the value of x and y and then
* making the conversion just after y has been set.
*/
template <typename PathType>
struct path_coordinate_transformer
{
explicit path_coordinate_transformer(PathType const& path_type)
: path_type_(path_type),
current_x_(0.0),
current_y_(0.0)
{}
void set_current_x(double& x)
{
current_x_ = x;
}
void set_current_y(double& y)
{
current_y_ = y;
path_type_.vertex(&current_x_, &current_y_);
}
void current_x(double& x) const
{
x = current_x_;
}
void current_y(double& y) const
{
y = current_y_;
}
PathType const& path_type_;
double current_x_;
double current_y_;
};
template <typename OutputIterator, typename PathType>
struct svg_path_data_grammar : karma::grammar<OutputIterator, mapnik::geometry_type&()>
struct svg_path_data_grammar : karma::grammar<OutputIterator, PathType&()>
{
typedef path_coordinate_transformer<PathType> coordinate_transformer;
typedef mapnik::geometry_iterator_type::value_type vertex_type;
typedef mapnik::geometry_type::value_type& vertex_component_type;
typedef path_iterator_type::value_type vertex_type;
explicit svg_path_data_grammar(PathType const& path_type)
: svg_path_data_grammar::base_type(svg_path),
path_type_(path_type),
ct_(path_type)
path_type_(path_type)
{
using karma::int_;
using karma::double_;
using karma::_1;
using karma::_a;
using karma::eol;
using karma::omit;
using repository::confix;
svg_path =
@ -201,31 +153,18 @@ namespace mapnik { namespace svg {
path_vertex =
path_vertex_command
<< omit[path_vertex_component_x]
<< omit[path_vertex_component_y]
<< path_vertex_transformed_x
<< double_
<< lit(' ')
<< path_vertex_transformed_y;
<< double_;
path_vertex_command = &int_(1) << lit('M') | lit('L');
path_vertex_component_x = double_[_1 = _a][bind(&coordinate_transformer::set_current_x, &ct_, _a)][_a = _val];
path_vertex_component_y = double_[_1 = _a][bind(&coordinate_transformer::set_current_y, &ct_, _a)][_a = _val];
path_vertex_transformed_x = double_[_1 = _a][bind(&coordinate_transformer::current_x, &ct_, _a)];
path_vertex_transformed_y = double_[_1 = _a][bind(&coordinate_transformer::current_y, &ct_, _a)];
}
karma::rule<OutputIterator, mapnik::geometry_type&()> svg_path;
karma::rule<OutputIterator, PathType&()> svg_path;
karma::rule<OutputIterator, vertex_type()> path_vertex;
karma::rule<OutputIterator, int()> path_vertex_command;
karma::rule<OutputIterator, vertex_component_type(), karma::locals<double> > path_vertex_component_x, path_vertex_component_y;
karma::rule<OutputIterator, vertex_component_type(), karma::locals<double> > path_vertex_transformed_x, path_vertex_transformed_y;
PathType const& path_type_;
coordinate_transformer ct_;
};
template <typename OutputIterator>

View File

@ -20,11 +20,12 @@
*
*****************************************************************************/
#ifndef GEOMETRY_ITERATOR_HPP
#define GEOMETRY_ITERATOR_HPP
#ifndef SVG_PATH_ITERATOR_HPP
#define SVG_PATH_ITERATOR_HPP
// mapnik
#include <mapnik/geometry.hpp>
#include <mapnik/ctrans.hpp>
// boost
#include <boost/iterator/iterator_adaptor.hpp>
@ -32,6 +33,9 @@
#include <boost/shared_ptr.hpp>
namespace mapnik {
namespace svg {
using namespace mapnik;
/*
* @brief Iterator class used to iterate over geometry vertexes.
@ -47,9 +51,9 @@ namespace mapnik {
* @tparam Value the type of sequence element dereferenced.
* @tparam Container the sequence over which it iterates.
*/
template <typename Value, typename Container=geometry_type>
class geometry_iterator
: public boost::iterator_adaptor<geometry_iterator<Value, Container>,
template <typename Value, typename Container>
class path_iterator
: public boost::iterator_adaptor<path_iterator<Value, Container>,
Value*,
boost::use_default,
boost::forward_traversal_tag>
@ -57,6 +61,7 @@ class geometry_iterator
public:
typedef Value value_type;
typedef Container container_type;
typedef typename Container::value_type value_component_type;
/*!
* @brief Constructor that initializes the reference to the current element to null.
@ -65,10 +70,10 @@ public:
*
* @param geometry the geometry that handles the vector of vertexes.
*/
geometry_iterator(Container const& geometry)
: geometry_iterator::iterator_adaptor_(0),
geometry_(geometry),
first_value_(new Value(0,0,0,0,0))
path_iterator(Container const& path)
: path_iterator::iterator_adaptor_(0),
path_(path),
first_value_(new Value(0,0,0))
{}
/*!
@ -82,10 +87,10 @@ public:
* @param p pointer to the first element of the sequence.
* @param geometry the geometry that handles the vector of vertexes.
*/
explicit geometry_iterator(Value* first_element, Container const& geometry)
: geometry_iterator::iterator_adaptor_(first_element),
geometry_(geometry),
first_value_(new Value(0,0,0,0,0))
explicit path_iterator(Value* first_element, Container const& path)
: path_iterator::iterator_adaptor_(first_element),
path_(path),
first_value_(new Value(0,0,0))
{
this->increment();
}
@ -97,10 +102,10 @@ public:
* @sa http://www.boost.org/doc/libs/1_45_0/libs/iterator/doc/iterator_facade.html#interoperability
*/
template <typename OtherValue>
geometry_iterator(geometry_iterator<OtherValue> const& other,
path_iterator(path_iterator<OtherValue, Container> const& other,
typename boost::enable_if<boost::is_convertible<OtherValue*, Value*>,
enabler>::type = enabler())
: geometry_iterator::iterator_adaptor_(other.base()) {}
: path_iterator::iterator_adaptor_(other.base()) {}
private:
@ -117,7 +122,7 @@ private:
geometry_type::value_type y;
// extract next vertex components.
unsigned cmd = geometry_.vertex(&x, &y);
unsigned cmd = path_.vertex(&x, &y);
if(cmd == SEG_END)
{
@ -137,13 +142,13 @@ private:
// 'first_value_' is used as intermediate storage
// because the compiler prohibits the assignment of the
// address of a temporary object (&Value(...)).
*first_value_ = Value(cmd, x, y, x, y);
*first_value_ = Value(cmd, x, y);
this->base_reference() = first_value_.get();
}
else
{
// point the reference to the current element to the next.
*(this->base_reference()) = Value(cmd, x, y, x, y);
*(this->base_reference()) = Value(cmd, x, y);
}
}
@ -153,21 +158,23 @@ private:
* @param other iterator to compare to current element.
*/
template <typename OtherValue>
bool equal(geometry_iterator<OtherValue, Container> const& other) const
bool equal(path_iterator<OtherValue, Container> const& other) const
{
return this->base_reference() == other.base();
}
Container const& geometry_;
Container const& path_;
boost::shared_ptr<Value> first_value_;
};
/*!
* @brief Specialization of geometry_iterator, as needed by mapnik::svg::svg_path_data_grammar.
* The Value type is a boost::tuple that holds 5 elements, the command and the x and y coordinate.
* Each coordinate is stored twice to match the needs the grammar.
* Each coordinate is stored twice to match the needs of the grammar.
*/
typedef geometry_iterator<boost::tuple<unsigned, geometry_type::value_type, geometry_type::value_type, geometry_type::value_type, geometry_type::value_type>, geometry_type> geometry_iterator_type;
}
typedef path_iterator<boost::tuple<unsigned, geometry_type::value_type, geometry_type::value_type>,
coord_transform2<CoordTransform, geometry_type> > path_iterator_type;
#endif //GEOMETRY_ITERATOR_HPP
}}
#endif //SVG_PATH_ITERATOR_HPP

View File

@ -73,7 +73,7 @@ namespace mapnik { namespace svg {
path_attributes_grammar attributes_grammar;
path_dash_array_grammar dash_array_grammar;
karma::generate(output_iterator_, lit("<path ") << data_grammar, path.geom());
karma::generate(output_iterator_, lit("<path ") << data_grammar, path);
karma::generate(output_iterator_, lit(" ") << dash_array_grammar, path_attributes.stroke_dasharray());
karma::generate(output_iterator_, lit(" ") << attributes_grammar << lit("/>\n"), path_attributes);
}

View File

@ -172,7 +172,7 @@ void prepare_map(Map& m)
lyr.add_style("provlines");
m.addLayer(lyr);
}
// Roads
{
parameters p;