geometry_iterator code documentation.

This commit is contained in:
Carlos López 2011-02-07 01:45:29 +00:00
parent 4720303507
commit 6f6b161c7c
2 changed files with 69 additions and 7 deletions

View file

@ -33,6 +33,20 @@
namespace mapnik {
/*
* @brief Iterator class used to iterate over geometry vertexes.
* Since mapnik::geometry provides access to the components of
* a vertex only through variables passed by reference,
* geometry_iterator retrieves these components (command, x coord,
* and y coord) and makes them available inside tuples.
*
* This iterator exposes the behavior of a forward iterator and
* subclasses boost::iterator_adaptor, which already implements
* several iterator operations, such as dereferencing.
*
* @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>,
@ -44,14 +58,32 @@ public:
typedef Value value_type;
typedef Container container_type;
/*!
* @brief Constructor that initializes the reference to the current element to null.
* This constructor is suitable to mark the end of the iterator (analogous to
* calling end_iterator() in an STL container).
*
* @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))
{}
explicit geometry_iterator(Value* p, Container const& geometry)
: geometry_iterator::iterator_adaptor_(p),
/*!
* This constructor receives the first element of the sequence as a pointer.
* Since the container type will likely be a mapnik::geometry, this
* first element would need to be obtained in a similar way as the increment
* method below. For this reason, most of the time this constructor will
* be called with a null pointer. The body of the constructor makes a call
* to increment() in order to obtain this first element from the container.
*
* @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))
{
@ -60,6 +92,10 @@ public:
struct enabler {};
/*!
* @brief Constructor that enables operation between const and non-const iterators.
* @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,
typename boost::enable_if<boost::is_convertible<OtherValue*, Value*>,
@ -67,29 +103,55 @@ public:
: geometry_iterator::iterator_adaptor_(other.base()) {}
private:
// grant access to iterator_adaptor to handle iteration properly.
friend class boost::iterator_core_access;
/*!
* @brief Advance the iterator.
*/
void increment()
{
// variables used to extract vertex components.
geometry_type::value_type x;
geometry_type::value_type y;
// extract next vertex components.
unsigned cmd = geometry_.vertex(&x, &y);
if(cmd == SEG_END)
{
// if the end of the sequence is reached, set the reference
// to the current element to null, so it matches the value
// that marks the end of the sequence as defined in the
// "end_iterator" constructor.
this->base_reference() = 0;
}
else if(this->base_reference() == 0)
{
// the first element of the container is stored in the
// member variable 'first_value_' and later assigned
// to the reference that boost::iterator_adaptor stores
// to track the current element.
//
// '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);
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);
}
}
/*!
* @brief Test whether the current element is equal to 'other'.
* @tparam OtherValue the value type of the other iterator (it may be const or non-const).
* @param other iterator to compare to current element.
*/
template <typename OtherValue>
bool equal(geometry_iterator<OtherValue, Container> const& other) const
{
@ -100,6 +162,11 @@ private:
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.
*/
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;
}

View file

@ -102,18 +102,15 @@ namespace boost { namespace spirit { namespace traits {
template <>
struct container_iterator<mapnik::geometry_type const>
{
//typedef mapnik::geometry_type::iterator type;
typedef mapnik::geometry_iterator_type type;
};
template <>
struct begin_container<mapnik::geometry_type const>
{
//static mapnik::geometry_type::iterator
static mapnik::geometry_iterator_type
call(mapnik::geometry_type const& g)
{
//return g.begin();
return mapnik::geometry_iterator_type(0, g);
}
};
@ -121,11 +118,9 @@ namespace boost { namespace spirit { namespace traits {
template <>
struct end_container<mapnik::geometry_type const>
{
//static mapnik::geometry_type::iterator
static mapnik::geometry_iterator_type
call(mapnik::geometry_type const& g)
{
//return g.end();
return mapnik::geometry_iterator_type(g);
}
};