Created
February 17, 2012 11:04
-
-
Save meastp/1852693 to your computer and use it in GitHub Desktop.
Adaption of legacy objects to boost::geometry concepts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <boost/geometry.hpp> | |
#include <boost/range.hpp> | |
#include <boost/iterator/iterator_facade.hpp> | |
#include "objdefs.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 double get(QPoint* const p) | |
{ | |
return p->x; | |
} | |
static void set(QPoint* p, double const& value) | |
{ | |
p->x = value; | |
} | |
}; | |
template<> | |
struct access<QPoint*, 1> | |
{ | |
static double get(QPoint* const p) | |
{ | |
return p->y; | |
} | |
static void set(QPoint* p, double const& value) | |
{ | |
p->y = value; | |
} | |
}; | |
// const version: | |
template<> struct tag<QPoint const*> | |
{ typedef point_tag type; }; | |
template<> struct coordinate_type<QPoint const*> | |
{ typedef double type; }; | |
template<> struct coordinate_system<QPoint const*> | |
{ typedef cs::cartesian type; }; | |
template<> struct dimension<QPoint const*> : boost::mpl::int_<2> {}; | |
template<> | |
struct access<QPoint const*, 0> | |
{ | |
static double get(QPoint const* const p) | |
{ | |
return p->x; | |
} | |
}; | |
template<> | |
struct access<QPoint const*, 1> | |
{ | |
static double get(QPoint const* const p) | |
{ | |
return p->y; | |
} | |
}; | |
} | |
} | |
} // namespace boost::geometry::traits | |
namespace boost | |
{ | |
// | |
// Specialize metafunctions. We must include the range.hpp header. | |
// We must open the 'boost' namespace. | |
// | |
template<> | |
struct range_iterator< QLineString* > | |
{ | |
typedef std::vector<QPoint*>::iterator type; | |
}; | |
template<> | |
struct range_const_iterator< QLineString* > | |
{ | |
// | |
// Remark: this is defined similar to 'range_iterator' | |
// because the 'Pair' type does not distinguish | |
// between an iterator and a const_iterator. | |
// | |
typedef std::vector<QPoint*>::const_iterator type; | |
}; | |
template<> | |
struct range_size< QLineString* > | |
{ | |
typedef std::size_t type; | |
}; | |
} // namespace boost | |
// | |
// The required functions. These should be defined in | |
// the same namespace as 'Pair', in this case | |
// in namespace 'Foo'. | |
// | |
inline std::vector<QPoint*>::iterator range_begin( QLineString* x ) | |
{ | |
return x->points.begin(); | |
} | |
inline std::vector<QPoint*>::const_iterator range_begin( const QLineString* x ) | |
{ | |
return x->points.begin(); | |
} | |
inline std::vector<QPoint*>::iterator range_end( QLineString* x ) | |
{ | |
return x->points.end(); | |
} | |
inline std::vector<QPoint*>::const_iterator range_end( const QLineString* x ) | |
{ | |
return x->points.end(); | |
} | |
inline std::vector<QPoint*>::size_type | |
range_size( const QLineString* x ) | |
{ | |
return x->points.size(); | |
} | |
//BOOST_GEOMETRY_REGISTER_LINESTRING(QLineString); | |
namespace boost { | |
namespace geometry { | |
namespace traits { | |
template | |
<> | |
struct tag<QLineString*> | |
{ | |
typedef linestring_tag type; | |
}; | |
} | |
} | |
} | |
// Ring adaption | |
/* Custom iterator type that flattens a 2D array into a 1D array */ | |
template <class I, // Line iterator type | |
class R // Point reference type | |
> | |
class RingIteratorImpl : public boost::iterator_facade< | |
RingIteratorImpl<I,R>, R, boost::forward_traversal_tag, R> | |
{ | |
public: | |
RingIteratorImpl() : lineStringIter_(0), pointIndex_(0) {} | |
explicit RingIteratorImpl(I lineStringIter) | |
: lineStringIter_(lineStringIter), pointIndex_(0) {} | |
private: | |
friend class boost::iterator_core_access; | |
void increment() | |
{ | |
++pointIndex_; | |
if (pointIndex_ >= (*lineStringIter_)->points.size()) | |
{ | |
++lineStringIter_; | |
pointIndex_ = 0; | |
} | |
} | |
bool equal(const RingIteratorImpl& other) const | |
{ | |
return (lineStringIter_ == other.lineStringIter_) && | |
(pointIndex_ == other.pointIndex_); | |
} | |
R dereference() const {return (*lineStringIter_)->points[pointIndex_];} | |
I lineStringIter_; | |
size_t pointIndex_; | |
}; | |
typedef RingIteratorImpl<std::vector<QLineString*>::iterator, QPoint*> RingIterator; | |
typedef RingIteratorImpl<std::vector<QLineString*>::const_iterator, QPoint* const> ConstRingIterator; | |
namespace boost | |
{ | |
// Specialize metafunctions. We must include the range.hpp header. | |
// We must open the 'boost' namespace. | |
template <> | |
struct range_mutable_iterator<QRing> { typedef RingIterator type; }; | |
template<> | |
struct range_const_iterator<QRing> { typedef ConstRingIterator type; }; | |
} // namespace 'boost' | |
// The required Range functions. These should be defined in the same namespace | |
// as Ring. | |
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<QRing> | |
{ | |
typedef ring_tag type; | |
}; | |
/* | |
template | |
< | |
typename Point, | |
bool Closed, | |
template<typename, typename> class Container, | |
template<typename> class Allocator | |
> | |
struct point_order<QRing> | |
{ | |
static const order_selector value = counterclockwise; | |
}; | |
template | |
< | |
typename Point, | |
bool Closed, | |
template<typename, typename> class Container, | |
template<typename> class Allocator | |
> | |
struct point_order<QRing> | |
{ | |
static const order_selector value = clockwise; | |
}; | |
template | |
< | |
typename Point, | |
bool PointOrder, | |
template<typename, typename> class Container, | |
template<typename> class Allocator | |
> | |
struct closure<QRing> | |
{ | |
static const closure_selector value = closed; | |
}; | |
template | |
< | |
typename Point, | |
bool PointOrder, | |
template<typename, typename> class Container, | |
template<typename> class Allocator | |
> | |
struct closure<QRing> | |
{ | |
static const closure_selector value = open; | |
}; | |
*/ | |
} // namespace traits | |
} // namespace geometry | |
} // namespace boost | |
int main() | |
{ | |
QPoint* pP1 = new QPoint(1,2); | |
QPoint* pP2 = new QPoint(2,3); | |
QPoint* pP3 = new QPoint(3,4); | |
QPoint* pP4 = new QPoint(5,6); | |
QPoint* pP5 = new QPoint(7,8); | |
QPoint* pP6 = new QPoint(9,10); | |
QLineString* pls = new QLineString(); | |
pls->cw = true; | |
pls->points.push_back(pP1); | |
pls->points.push_back(pP2); | |
pls->points.push_back(pP3); | |
std::cout << boost::geometry::wkt(pls) << std::endl; | |
QLineString* pls2 = new QLineString(); | |
pls2->cw = true; | |
pls2->points.push_back(pP4); | |
pls2->points.push_back(pP5); | |
pls2->points.push_back(pP6); | |
std::cout << boost::geometry::wkt(pls2) << std::endl; | |
QRing r1 = QRing(); | |
r1.lines.push_back(pls); | |
r1.lines.push_back(pls2); | |
RingIterator ri = range_begin(r1); | |
ri++; | |
ri++; | |
QPoint* p = *ri; | |
p->x = 50; | |
std::cout << boost::geometry::wkt(p); | |
std::cout << boost::geometry::wkt(r1) << std::endl; | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef OBJDEFS_DEF_H_INCLUDED | |
#define OBJDEFS_DEF_H_INCLUDED | |
#include <vector> | |
class QPoint { | |
public: | |
long x; | |
long y; | |
QPoint(long x, long y) : x(x), y(y) {} | |
}; | |
class QLineString { | |
public: | |
bool cw; | |
std::vector<QPoint*> points; | |
}; | |
class QRing { | |
public: | |
std::vector<QLineString*> lines; | |
}; | |
class QPolygon { | |
public: | |
QRing* exterior; | |
std::vector<QRing*> interiors; | |
}; | |
#endif // OBJDEFS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
LINESTRING(1 2,2 3, 3 4) | |
LINESTRING(5 6,7 8,9 10) | |
POINT(50 4)POLYGON((1 2,2 3,50 4,5 6,7 8,9 10)) | |
Process returnd 0 (0x0) execution time : 0.005 s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment