Skip to content

Instantly share code, notes, and snippets.

@meastp
Created February 17, 2012 11:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save meastp/1852693 to your computer and use it in GitHub Desktop.
Save meastp/1852693 to your computer and use it in GitHub Desktop.
Adaption of legacy objects to boost::geometry concepts
#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;
}
#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
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