#include <boost/geometry.hpp>
namespace boost
{
namespace geometry
{
namespace traits
{
template<> struct tag<QPoint>
{ typedef point_tag type; };
template<> struct coordinate_type<QPoint>
{ typedef double type; };
template<> struct coordinate_system<QPoint>
{ typedef cs::cartesian type; };
template<> struct dimension<QPoint> : boost::mpl::int_<2> {};
template<>
struct access<QPoint, 0>
{
static QPoint::double get(QPoint const& p)
{
return p.x;
}
static void set(QPoint& p, QPoint::double const& value)
{
p.x = value;
}
};
template<>
struct access<QPoint, 1>
{
static QPoint::double get(QPoint const& p)
{
return p.y;
}
static void set(QPoint& p, QPoint::double const& value)
{
p.y = value;
}
};
}
}
}
namespace boost
{
namespace geometry
{
namespace traits
{
template<>
struct tag<QLineString>
{
typedef linestring_tag type;
};
}
}
}
#include <boost/range.hpp>
namespace boost
{
template <>
struct range_iterator<QLineString>
{ typedef std::vector<QPoint*>::iterator type; };
template<>
struct range_const_iterator<QLineString>
{ typedef std::vector<QPoint*>::const_iterator type; };
}
inline std::vector<QPoint*>::iterator
range_begin(QLineString& qls) {return qls.points.begin();}
inline std::vector<QPoint*>::iterator
range_end(QLineString& qls) {return qls.points.end();}
inline std::vector<QPoint*>::const_iterator
range_begin(const QLineString& qls) {return qls.points.begin();}
inline std::vector<QPoint*>::const_iterator
range_end(const QLineString& qls) {return qls.points.end();}
namespace boost
{
namespace geometry
{
namespace traits
{
template<>
struct tag<QRing>
{
typedef ring_tag type;
};
}
}
}
#include <boost/iterator/iterator_facade.hpp>
template <class I,
class R
>
class RingIteratorImpl : public boost::iterator_facade<
RingIteratorImpl<I,R>, R, std::random_access_iterator_tag, R>
{
public:
RingIteratorImpl() : pointIndex_(0)
{
}
explicit RingIteratorImpl(I lineStringIterCurrent)
: lineStringIterCurrent_(lineStringIterCurrent), pointIndex_(0)
{
}
template<class OtherI, class OtherR>
RingIteratorImpl(RingIteratorImpl<OtherI, OtherR> const& other) :
lineStringIterCurrent_(other.getLineStrIt()), pointIndex_(other.getPointIdx())
{
}
I getLineStrIt() const {return lineStringIterCurrent_;}
bool isEmpty() const {return isEmpty;}
size_t getPointIdx() const {return pointIndex_;}
typedef typename boost::iterator_facade<RingIteratorImpl<I,R>, R, std::random_access_iterator_tag, R>::difference_type difference_type;
private:
friend class boost::iterator_core_access;
void increment()
{
++pointIndex_;
if (pointIndex_ >= (*lineStringIterCurrent_)->points.size())
{
++lineStringIterCurrent_;
pointIndex_ = 0;
}
}
void decrement()
{
if(pointIndex_>0)
{
--pointIndex_;
}
else
{
--lineStringIterCurrent_;
pointIndex_ = (*lineStringIterCurrent_)->points.size();
}
}
void advance(difference_type n)
{
difference_type counter = n;
difference_type maxPointIndex, remainderPointIndex;
while(counter>0)
{
maxPointIndex = (*lineStringIterCurrent_)->points.size(),
remainderPointIndex = maxPointIndex - pointIndex_;
if(counter>remainderPointIndex)
{
counter -= remainderPointIndex;
++lineStringIterCurrent_;
}
else
{
counter = 0;
pointIndex_ = remainderPointIndex;
}
}
}
difference_type distance_to(const RingIteratorImpl& other) const
{
I currentLineStringIter = getLineStrIt();
I otherLineStringIter = other.getLineStrIt();
difference_type count = 0;
difference_type distance_to_other = std::distance(currentLineStringIter, otherLineStringIter);
if(distance_to_other < 0)
{
count += pointIndex_;
while(distance_to_other < 0)
{
QLineString const* ls = *otherLineStringIter;
count -= ls->points.size();
++otherLineStringIter;
++distance_to_other;
}
assert(otherLineStringIter==currentLineStringIter);
}
else if(distance_to_other > 0)
{
count -= pointIndex_;
while(distance_to_other < 0)
{
QLineString const* ls = *currentLineStringIter;
count += ls->points.size();
++currentLineStringIter;
--distance_to_other;
}
assert(otherLineStringIter==currentLineStringIter);
}
else
{
count = pointIndex_ - other.getPointIdx();
}
return count;
}
bool equal(const RingIteratorImpl& other) const
{
return (lineStringIterCurrent_ == other.getLineStrIt()) &&
(pointIndex_ == other.getPointIdx());
}
R dereference() const {return *(*lineStringIterCurrent_)->points[pointIndex_];}
I lineStringIterCurrent_;
bool empty;
size_t pointIndex_;
};
typedef RingIteratorImpl<std::vector<QLineString*>::iterator, QPoint> RingIterator;
typedef RingIteratorImpl<std::vector<QLineString*>::const_iterator, const QPoint> ConstRingIterator;
namespace boost
{
template <>
struct range_iterator<QRing>
{ typedef RingIterator type; };
template<>
struct range_const_iterator<QRing>
{ typedef ConstRingIterator type; };
}
inline RingIterator range_begin(QRing& r)
{return RingIterator(r.lines.begin());}
inline ConstRingIterator range_begin(const QRing& r)
{return ConstRingIterator(r.lines.begin());}
inline RingIterator range_end(QRing& r)
{return RingIterator(r.lines.end());}
inline ConstRingIterator range_end(const QRing& r)
{return ConstRingIterator(r.lines.end());}
namespace boost {
namespace geometry {
namespace traits {
template<> struct tag<QPolygon> { typedef polygon_tag type; };
template<> struct ring_const_type<QPolygon> { typedef const QRing& type; };
template<> struct ring_mutable_type<QPolygon> { typedef QRing& type; };
template<> struct interior_const_type<QPolygon> { typedef const CustomPolygonRingRange type; };
template<> struct interior_mutable_type<QPolygon> { typedef CustomPolygonRingRange type; };
template<> struct exterior_ring<QPolygon>
{
static QRing& get(QPolygon& p)
{
return (*p.exterior);
}
static QRing const& get(QPolygon const& p)
{
return (*p.exterior);
}
};
template<> struct interior_rings<QPolygon>
{
static CustomPolygonRingRange get(QPolygon& p)
{
return CustomPolygonRingRange(PolygonRingIterator(p.interiors.begin()), PolygonRingIterator(p.interiors.end()));
}
static const CustomPolygonRingRange get(QPolygon const& p)
{
return CustomPolygonRingRange(ConstPolygonRingIterator(p.interiors.begin()), ConstPolygonRingIterator(p.interiors.end()));
}
};
}
}
}
template <class I,
class R
>
class PolyRingIterator : public boost::iterator_facade<
PolyRingIterator<I,R>, R, std::random_access_iterator_tag, R>
{
public:
PolyRingIterator() {}
explicit PolyRingIterator(I ringIter) : _ringIter(ringIter) {}
template<class OtherI, class OtherR>
PolyRingIterator(PolyRingIterator<OtherI, OtherR> const& other) :
_ringIter(other.getRingIter()) {}
I getRingIter() const {return _ringIter;}
typedef typename boost::iterator_facade<PolyRingIterator<I,R>, R, std::random_access_iterator_tag, R>::difference_type difference_type;
private:
friend class boost::iterator_core_access;
void increment()
{
++_ringIter;
}
void decrement()
{
--_ringIter;
}
void advance(difference_type n)
{
std::advance(_ringIter,n);
}
difference_type distance_to(const PolyRingIterator& other) const
{
return std::distance(_ringIter, other.getRingIter());
}
bool equal(const PolyRingIterator& other) const
{
return _ringIter == other.getRingIter();
}
R dereference() const {return *(*_ringIter);}
I _ringIter;
};
typedef PolyRingIterator<std::vector<QRing*>::iterator, QRing> PolygonRingIterator;
typedef PolyRingIterator<std::vector<QRing*>::const_iterator, const QRing> ConstPolygonRingIterator;
class CustomPolygonRingRange
{
PolygonRingIterator _begin;
PolygonRingIterator _end;
bool isIterSet;
ConstPolygonRingIterator _cbegin;
ConstPolygonRingIterator _cend;
bool isCIterSet;
public:
CustomPolygonRingRange(PolygonRingIterator begin, PolygonRingIterator end) : _begin(begin), _end(end), isIterSet(true) {}
CustomPolygonRingRange(ConstPolygonRingIterator begin, ConstPolygonRingIterator end) : _cbegin(begin), _cend(end), isCIterSet(true) {}
PolygonRingIterator begin()
{
assert(isIterSet);
return _begin;
}
ConstPolygonRingIterator cbegin() const
{
assert(isCIterSet);
return _cbegin;
}
PolygonRingIterator end()
{
assert(isIterSet);
return _end;
}
ConstPolygonRingIterator cend() const
{
assert(isCIterSet);
return _cend;
}
};
namespace boost
{
template <>
struct range_iterator<CustomPolygonRingRange> { typedef PolygonRingIterator type; };
template<>
struct range_const_iterator<CustomPolygonRingRange> { typedef ConstPolygonRingIterator type; };
}
inline PolygonRingIterator range_begin(CustomPolygonRingRange& r)
{return r.begin();}
inline ConstPolygonRingIterator range_begin(const CustomPolygonRingRange& r)
{return r.cbegin();}
inline PolygonRingIterator range_end(CustomPolygonRingRange& r)
{return r.end();}
inline ConstPolygonRingIterator range_end(const CustomPolygonRingRange& r)
{return r.cend();}