Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Example source code: Adapting a legacy geometry object model

Boost , Chapter 1. Geometry , Examples

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Adaption of QPoint

#include <boost/geometry.hpp>
namespace boost
{
    namespace geometry
    {
        namespace traits
        {
            // Adapt QPoint to Boost.Geometry
            template<> struct tag<QPoint>
            { typedef point_tag type; };
            template<> struct coordinate_type<QPoint>
            { typedef QPoint::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::geometry::traits

Adaption of QLineString

namespace boost
{
    namespace geometry
    {
        namespace traits
        {
            template<>
            struct tag<QLineString>
            {
                typedef linestring_tag type;
            };
        }
    }
} // namespace boost::geometry::traits

Boost.Range for QLineString

#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();}

Adaption of QRing

namespace boost
{
    namespace geometry
    {
        namespace traits
        {
            template<>
            struct tag<QRing>
            {
                typedef ring_tag type;
            };
        }
    }
} // namespace boost::geometry::traits

Boost.Iterator for QRing

#include <boost/iterator/iterator_facade.hpp>
/* 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, std::random_access_iterator_tag, R> //new traversal tag boost::random_access_traversal_tag
{
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<=remainderPointIndex)
            {
                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_;
};

Boost.Range for QRing

typedef RingIteratorImpl<std::vector<QLineString*>::iterator, QPoint> RingIterator;
typedef RingIteratorImpl<std::vector<QLineString*>::const_iterator, const QPoint> ConstRingIterator;
namespace boost
{
    // Specialize metafunctions. We must include the range.hpp header.
    // We must open the 'boost' namespace.
    template <>
    struct range_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());}

Adaption of QPolygon

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()));
                }
            };
        }
    }
} // namespace boost::geometry::traits

Boost.Iterator for QRings in QPolygon

template <class I, // Line iterator type
          class R  // Point reference type
         >
class PolyRingIterator : public boost::iterator_facade<
        PolyRingIterator<I,R>, R, std::random_access_iterator_tag, R> //new traversal tag
{
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;
};

Boost.Range for PolygonRingIterator

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
{
    // Specialize metafunctions. We must include the range.hpp header.
    // We must open the 'boost' namespace.
    template <>
    struct range_iterator<CustomPolygonRingRange> { typedef PolygonRingIterator type; };
    template<>
    struct range_const_iterator<CustomPolygonRingRange> { typedef ConstPolygonRingIterator type; };
} // namespace 'boost'
// The required Range functions. These should be defined in the same namespace
// as Ring.
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();}

PrevUpHomeNext

Статья Example source code: Adapting a legacy geometry object model раздела Chapter 1. Geometry Examples может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Examples ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 21:55:29/0.010365009307861/1