[geometry] merged up to 84394 into Release branch

[SVN r84395]
This commit is contained in:
Barend Gehrels
2013-05-20 20:31:45 +00:00
27 changed files with 1029 additions and 177 deletions

View File

@@ -10,7 +10,7 @@
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section:aboutdoc About this documentation]
[section:aboutdoc About this Documentation]
Within the Boost community there are several styles of documenting. Most libraries nowadays are using QuickBook, the WikiWiki style documentation.

View File

@@ -184,6 +184,8 @@ INPUT = . .. ../../../../boost/geometry/core \
../../../../boost/geometry/geometries/adapted \
../../../../boost/geometry/geometries/register \
../../../../boost/geometry/iterators \
../../../../boost/geometry/io/wkt \
../../../../boost/geometry/io/svg \
../../../../boost/geometry/multi/algorithms \
../../../../boost/geometry/multi/algorithms/detail \
../../../../boost/geometry/multi/core \

View File

@@ -0,0 +1,587 @@
[section Example: Adapting a legacy geometry object model]
One of the primary benefits of __boost_geometry__, and the reason for its fairly complex template-based implementation, is that it allows for integration with legacy classes/objects.
By defining the relationship between the __boost_geometry__ concepts and an existing, legacy object model, the legacy objects can be used in place of __boost_geometry__'s own geometry classes.
__boost_geometry__ will then happliy read and write directly from and to the legacy object, treating it as a native __boost_geometry__ object.
This means that one can adapt algorithms and methods from __boost_geometry__ to any existing legacy geometry object model at a very small runtime cost, which is simply not possible with most geometry libraries, where one has to make an intermediate object specific to the geometry library one is using.
The following example will demonstrate the adaption process of a legacy geometry object model for use with __boost_geometry__.
[h2 Adapting a shared geometry legacy object model]
[h3 Example code: object hierarcy]
class QPoint
{
public:
double x;
double y;
QPoint(double x, double 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;
};
The legacy object hierarcy is based on topology (e.g. two QRings might share one QLineString) instead of points directly (i.e. each object does not point directly to it's QPoints), and it also uses pointers for access.
This is the other common way to approach geometries, to enable e.g. shared boundaries between surfaces. __boost_geometry__'s approach use simple features, and does not have shared geometries.
The mismatch in representation is fixed by creating a custom iterator, that exposes a __boost_range__ of Points for every object. This way, __boost_geometry__'s functions will operate on the QRing as if it was a collection of Points, which is a requirement.
[h2 Adapting QPoint]
The [link adaption_of_qpoint_source_code adaption of the QPoint] is fairly straightforward, one just needs to implement the requirements.
Even though the geometries in our legacy object model use pointers of QPoints, __boost_geometry__ automatically handles the conversion from pointers-to-Points to references-to-Points internally, so we do not have to convert them manually.
Alternatively, we can use the [link geometry.reference.adapted.register.boost_geometry_register_point_2d BOOST_GEOMETRY_REGISTER_POINT_2D(QPoint, double, cs::cartesian, x, y)] helper macro, which does exactly the same as our manual adaption.
The sample code adapts QPoint to the [link geometry.reference.concepts.concept_point Point Concept] using specialization of the traits class.
[h2 Adapting QLineString]
The [link adaption_of_qlinestring_source_code adaption of the QLineString] is very simple on the surface, as it is just "a specialization of traits::tag defining linestring_tag as type". Alternatively, we can use the [link geometry.reference.adapted.register.boost_geometry_register_linestring BOOST_GEOMETRY_REGISTER_LINESTRING(QLineString)] helper macro, which does exactly the same as our manual adaption.
However, the [link geometry.reference.concepts.concept_linestring LineString concept] also requires that the collection of Points "must behave like a __boost_range__ Random Access Range" and "the type defined by the metafunction range_value<...>::type must fulfill the Point Concept".
This means that we have to do two things:
* Make QLineString behave like a __boost_range__, with Random Access requirements
* Make sure that the __boost_range__ iterates over QPoints, which we already have adapted
This might look like a lot of work, but we are in luck: a std::vector is nearly a __boost_range__, and already iterate over pointers-to-QPoints, that are handled by __boost_geometry__. The [link adaption_of_qlinestring_range_source_code code for making QLineString a __boost_range__] is therefore fairly straightforward.
[h2 Adapting QRing]
The [link adaption_of_qring_source_code adaption of the QRing] is mostly equal to the QLineString in that there is a tag and a collection to iterate through. Alternatively, we can use the [link geometry.reference.adapted.register.boost_geometry_register_ring BOOST_GEOMETRY_REGISTER_RING(QRing)] helper macro, which does exactly the same as our manual adaption.
However, the QRing expose pointers-to-QLineStrings, and not QPoints directly, which is [link geometry.reference.concepts.concept_ring required in the Ring concept], so it is not enough to trivially make the std::vector into a __boost_range__. We need to create a Boost.Iterator that expose QPoints, and because we are dealing with a legacy object model, we are not allowed to change the class definition.
The [link adaption_of_qring_iterator_source_code custom iterator that does this] uses Boost.Iterator Facade, and is not very different from the [@http://www.boost.org/doc/libs/1_53_0/libs/iterator/doc/iterator_facade.html example provided in Boost.Iterator's own documentation](link), except that our __boost_range__ need to be random access.
Now, with the custom iterator made, we can [link adaption_of_qring_range_source_code define the __boost_range__] that traverses through QPoints.
[h2 Adapting QPolygon]
[link adaption_of_qpolygon_source_code Adapting the QPolygon] to the [link geometry.reference.concepts.concept_polygon Polygon Concept] is a little more involved than the other geometry types.
The only requirement that is not straightforward to adapt is the interior_rings' get method.
A __boost_geometry__ Polygon operates on Ring objects, and unfortunately, __boost_geometry__ does not automatically handle the conversion from pointers to references for Rings internally (only Points, as mentioned).
Therefore, we need to expose QRings instead of pointers-to-QRings for the interior Rings, which means a little more work than the pointers-to-QPoints for QLineString and QRing.
First, we [link adaption_of_qpolygon_iterator_source_code create a Boost.Iterator Facade] that returns QRing instead of pointer-to-QRing:
Now we have an iterator that can "convert" our pointer-to-QRing into QRing. However, the get method of the interior Rings must return a __boost_range__ compatible object, which a plain PolygonRingIterator is not.
We need to [link adaption_of_qpolygon_range_source_code define another __boost_range__], that can be constructed with PolygonRingIterators as arguments, and returned from the get method.
[h2 Conclusion]
That's it! The methods of __boost_geometry__ can now be used directly on instances of our legacy object model.
[endsect]
[section Example source code: Adapting a legacy geometry object model]
[h2 Adaption of QPoint]
[#adaption_of_qpoint_source_code]
#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
[h2 Adaption of QLineString]
[#adaption_of_qlinestring_source_code]
namespace boost
{
namespace geometry
{
namespace traits
{
template<>
struct tag<QLineString>
{
typedef linestring_tag type;
};
}
}
} // namespace boost::geometry::traits
[h3 Boost.Range for QLineString]
[#adaption_of_qlinestring_range_source_code]
#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();}
[h2 Adaption of QRing]
[#adaption_of_qring_source_code]
namespace boost
{
namespace geometry
{
namespace traits
{
template<>
struct tag<QRing>
{
typedef ring_tag type;
};
}
}
} // namespace boost::geometry::traits
[h3 Boost.Iterator for QRing]
[#adaption_of_qring_iterator_source_code]
#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_;
};
[h3 Boost.Range for QRing]
[#adaption_of_qring_range_source_code]
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());}
[h2 Adaption of QPolygon]
[#adaption_of_qpolygon_source_code]
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
[h3 Boost.Iterator for QRings in QPolygon]
[#adaption_of_qpolygon_iterator_source_code]
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;
};
[h3 Boost.Range for PolygonRingIterator]
[#adaption_of_qpolygon_range_source_code]
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();}
[endsect]

View File

@@ -115,15 +115,17 @@ Boost.Geometry contains contributions by:
[include imports.qbk]
[include introduction.qbk]
[include quickstart.qbk]
[include design_rationale.qbk]
[include compiling.qbk]
[section Spatial indexes]
[include design_rationale.qbk]
[include quickstart.qbk]
[section Spatial Indexes]
[include index/index.qbk]
[endsect]
[include reference.qbk]
[section Indexes]
[include matrix.qbk]
[section Alphabetical Index]
@@ -131,7 +133,9 @@ Boost.Geometry contains contributions by:
[endsect]
[endsect]
[include reference.qbk]
[section Examples]
[include example_adapting_a_legacy_geometry_object_model.qbk]
[endsect]
[include release_notes.qbk]

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -3,7 +3,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Chapter&#160;1.&#160;Geometry</title>
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="home" href="index.html" title="Chapter&#160;1.&#160;Geometry">
<link rel="next" href="geometry/introduction.html" title="Introduction">
</head>
@@ -46,15 +46,17 @@
<p><b>Table of Contents</b></p>
<dl>
<dt><span class="section"><a href="geometry/introduction.html">Introduction</a></span></dt>
<dt><span class="section"><a href="geometry/quickstart.html">Quick Start</a></span></dt>
<dt><span class="section"><a href="geometry/design.html">Design Rationale</a></span></dt>
<dt><span class="section"><a href="geometry/compilation.html">Compilation</a></span></dt>
<dt><span class="section"><a href="geometry/spatial_indexes.html">Spatial indexes</a></span></dt>
<dd><dl><dt><span class="section"><a href="geometry/spatial_indexes/r_tree.html">R-tree</a></span></dt></dl></dd>
<dt><span class="section"><a href="geometry/indexes.html">Indexes</a></span></dt>
<dt><span class="section"><a href="geometry/design.html">Design Rationale</a></span></dt>
<dt><span class="section"><a href="geometry/quickstart.html">Quick Start</a></span></dt>
<dt><span class="section"><a href="geometry/spatial_indexes.html">Spatial Indexes</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="geometry/indexes/matrix.html">Reference matrix</a></span></dt>
<dt><span class="section"><a href="geometry/indexes/alphabetical_index.html">Alphabetical Index</a></span></dt>
<dt><span class="section"><a href="geometry/spatial_indexes/introduction.html">Introduction</a></span></dt>
<dt><span class="section"><a href="geometry/spatial_indexes/rtree_quickstart.html">Quick Start</a></span></dt>
<dt><span class="section"><a href="geometry/spatial_indexes/creation_and_modification.html">Creation
and Modification</a></span></dt>
<dt><span class="section"><a href="geometry/spatial_indexes/queries.html">Queries</a></span></dt>
<dt><span class="section"><a href="geometry/spatial_indexes/rtree_examples.html">Examples</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="geometry/reference.html">Reference</a></span></dt>
<dd><dl>
@@ -70,23 +72,28 @@
<dt><span class="section"><a href="geometry/reference/exceptions.html">Exceptions</a></span></dt>
<dt><span class="section"><a href="geometry/reference/iterators.html">Iterators</a></span></dt>
<dt><span class="section"><a href="geometry/reference/models.html">Models</a></span></dt>
<dt><span class="section"><a href="geometry/reference/spatial_indexes.html">Spatial indexes</a></span></dt>
<dt><span class="section"><a href="geometry/reference/spatial_indexes.html">Spatial Indexes</a></span></dt>
<dt><span class="section"><a href="geometry/reference/strategies.html">Strategies</a></span></dt>
<dt><span class="section"><a href="geometry/reference/views.html">Views</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="geometry/indexes.html">Indexes</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="geometry/indexes/matrix.html">Reference Matrix</a></span></dt>
<dt><span class="section"><a href="geometry/indexes/alphabetical_index.html">Alphabetical Index</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="geometry/release_notes.html">Release Notes</a></span></dt>
<dt><span class="section"><a href="geometry/aboutdoc.html">About this documentation</a></span></dt>
<dt><span class="section"><a href="geometry/aboutdoc.html">About this Documentation</a></span></dt>
<dt><span class="section"><a href="geometry/acknowledgments.html">Acknowledgments</a></span></dt>
</dl>
</div>
<h3>
<a name="geometry.h0"></a>
<span><a name="geometry.contributions"></a></span><a class="link" href="index.html#geometry.contributions">Contributions</a>
<span class="phrase"><a name="geometry.contributions"></a></span><a class="link" href="index.html#geometry.contributions">Contributions</a>
</h3>
<p>
Boost.Geometry contains contributions by:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Akira Takahashi (adaption of Boost.Fusion)
</li>
@@ -102,7 +109,7 @@
</ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: May 12, 2013 at 10:55:03 GMT</small></p></td>
<td align="left"><p><small>Last revised: May 16, 2013 at 10:14:50 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>

View File

@@ -104,5 +104,7 @@
[import src/examples/geometries/register/multi_linestring.cpp]
[import src/examples/geometries/register/multi_polygon.cpp]
[import src/examples/io/svg.cpp]
[import src/examples/views/box_view.cpp]
[import src/examples/views/segment_view.cpp]

View File

@@ -33,6 +33,11 @@
[include imports.qbk]
[/include introduction.qbk/]
[include introduction.qbk]
[include rtree.qbk]
[/include rtree.qbk]
[include rtree/quickstart.qbk]
[include rtree/creation.qbk]
[include rtree/query.qbk]
[include rtree/examples.qbk]
[/include rtree/experimental.qbk]

View File

@@ -1,7 +1,7 @@
[/============================================================================
Boost.Geometry Index
Copyright (c) 2011-2012 Adam Wulkiewicz.
Copyright (c) 2011-2013 Adam Wulkiewicz.
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -10,10 +10,68 @@
[section Introduction]
The __boost_geometry_index__ is intetended to gather containers (spatial indexes) which may be used to accelerate spatial searching.
It is a part of the __boost_geometry__ library. In general, spatial indexes stores geometric objects' representations and
allows searching for objects occupying some space or close to some point in space.
The __boost_geometry_index__ is intended to gather data structures called spatial
indexes which may be used to accelerate searching for objects in space. In general,
spatial indexes stores geometric objects' representations and allows searching for
objects occupying some space or close to some point in space.
Currently, only one spatial index is implemented - __rtree__.
[heading __rtree__]
__rtree__ is a tree data structure used for spatial searching. It was proposed by
Antonin Guttman in 1984 [footnote Guttman, A. (1984). /R-Trees: A Dynamic Index Structure for Spatial Searching/]
as an expansion of B-tree for multi-dimensional data. It may be used to store points or volumetric data in order to
perform a spatial query. This query may for example return objects that are inside some area or are close to some point in space
[footnote Cheung, K.; Fu, A. (1998). /Enhanced Nearest Neighbour Search on the R-tree/]. It's possible to insert new objects or
to remove the ones already stored.
The __rtree__ structure is presented on the image below. Each __rtree__'s node store a box descring the space occupied by
its children nodes. At the bottom of the structure, there are leaf-nodes which contains values
(geometric objects representations).
[$img/index/rtree/rstar.png]
The __rtree__ is a self-balanced data structure. The key part of balancing algorithm is node splitting algorithm
[footnote Greene, D. (1989). /An implementation and performance analysis of spatial data access methods/]
[footnote Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990). /The R*-tree: an efficient and robust access method for points and rectangles/].
Each algorithm produces different splits so the internal structure of a tree may be different for each one of them.
In general more complex algorithms analyses elements better and produces less overlapping nodes. In the searching process less nodes must be traversed
in order to find desired obejcts. On the other hand more complex analysis takes more time. In general faster inserting will result in slower searching
and vice versa. The performance of the R-tree depends on balancing algorithm, parameters and data inserted into the container.
Example structures of trees created by use of three different algorithms and operations time are presented below. Data used in benchmark was random,
non-overlapping boxes.
[table
[[] [linear algorithm] [quadratic algorithm] [R*-tree]]
[[*Example structure*] [[$img/index/rtree/linear.png]] [[$img/index/rtree/quadratic.png]] [[$img/index/rtree/rstar.png]]]
[[*1M Values inserts*] [1.65s] [2.51s] [4.96s]]
[[*100k spatial queries*] [0.87s] [0.25s] [0.09s]]
[[*100k knn queries*] [3.25s] [1.41s] [0.51s]]
]
[heading Implementation details]
Key features of this implementation of the __rtree__ are:
* capable to store arbitrary __value__ type,
* three different creation algorithms - linear, quadratic or rstar,
* parameters (including maximal and minimal number of elements) may be passed as compile- or run-time parameters,
* advanced queries - e.g. search for 5 nearest values to some point and intersecting some region but not within the other one,
* C++11 conformant: move semantics, stateful allocators,
* capable to store __value__ type with no default constructor.
[heading Dependencies]
R-tree depends on *Boost.Move*, *Boost.Container*, *Boost.Tuple*, *Boost.Utility*, *Boost.MPL*.
[heading Contributors]
The spatial index was originally started by Federico J. Fernandez during the Google Summer of Code 2008 program, mentored by Hartmut Kaiser.
[heading Spatial thanks]
I'd like to thank Barend Gehrels, Bruno Lalande, Mateusz Łoskot, Lucanus J. Simonson for their support and ideas.
[endsect]

View File

@@ -8,11 +8,11 @@
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section Creation and modification]
[section Creation and Modification]
[section Template parameters]
[h4 Template parameters]
__rtree__ has 5 parameters:
__rtree__ has 5 parameters but only 2 are required:
rtree<Value,
Parameters,
@@ -26,9 +26,7 @@ __rtree__ has 5 parameters:
* `EqualTo` - function object comparing `__value__`s,
* `Allocator` - `Value`s allocator, all allocators needed by the container are created from it.
[endsect]
[section Values and Indexables]
[h4 Values and Indexables]
__rtree__ may store `__value__`s of any type as long as passed function objects know how to interpret those `__value__`s, that is
extract an `__indexable__` that the __rtree__ can handle and compare `__value__`s.
@@ -63,11 +61,7 @@ The predefined `index::equal_to<Value>`:
* for `tuple<...>` - compares all components of the `__value__`. If the component is a `Geometry`, `geometry::equals()`
function is used. For other types it uses `operator==()`.
[endsect]
[section Balancing algorithms]
[heading Compile-time]
[h4 Balancing algorithms compile-time parameters]
`__value__`s may be inserted to the __rtree__ in many various ways. Final internal structure
of the __rtree__ depends on algorithms used in the insertion process and parameters. The most important is
@@ -85,7 +79,7 @@ R*-tree - balancing algorithm minimizing nodes' overlap with forced reinsertions
index::rtree< __value__, index::rstar<16> > rt;
[heading Run-time]
[h4 Balancing algorithms run-time parameters]
Balancing algorithm parameters may be passed to the __rtree__ in run-time.
To use run-time versions of the __rtree__ one may pass parameters which
@@ -102,13 +96,11 @@ names start with `dynamic_`.
The obvious drawback is a slightly slower __rtree__.
[heading Non-default parameters]
[h4 Non-default parameters]
Non-default R-tree parameters are described in the reference.
[endsect]
[section Copying, moving and swapping]
[h4 Copying, moving and swapping]
The __rtree__ is copyable and movable container. Move semantics is implemented using Boost.Move library
so it's possible to move the container on a compilers without rvalue references support.
@@ -131,9 +123,7 @@ so it's possible to move the container on a compilers without rvalue references
// swap
rt3.swap(rt2);
[endsect]
[section Inserting and removing Values]
[h4 Inserting and removing Values]
The following code creates an __rtree__ using quadratic balancing algorithm.
@@ -163,7 +153,7 @@ Typically you will perform those operations in a loop in order to e.g. insert
some number of `__value__`s corresponding to geometrical objects (e.g. `Polygons`)
stored in another container.
[heading Additional interface]
[h4 Additional interface]
The __rtree__ allows creation, inserting and removing of Values from a range. The range may be passed as
[first, last) Iterators pair or as a Range.
@@ -204,7 +194,7 @@ The __rtree__ allows creation, inserting and removing of Values from a range. Th
// remove values with remove(Range)
rt3.remove(values);
[heading Insert iterator]
[h4 Insert iterator]
There are functions like `std::copy()`, or __rtree__'s queries that copy values to an output iterator.
In order to insert values to a container in this kind of function insert iterators may be used.
@@ -226,6 +216,4 @@ Geometry.Index provide its own `bgi::insert_iterator<Container>` which is genera
RTree rt2;
rt1.spatial_query(Box(/*...*/), bgi::inserter(rt2));
[endsect]
[endsect] [/ Creation and modification /]
[endsect] [/ Creation and Modification /]

View File

@@ -8,7 +8,7 @@
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section Experimental features]
[section Experimental Features]
This section describes experimental features which are implemented but unavailable by default.
Be aware that they may not be released in the future or functionalities may be released but
@@ -33,14 +33,15 @@ a relation object instead of a Point to the nearest predicate, as follows:
[heading Path query]
Path query returns `k` first `__value__`s intersecting a path defined by a `Linestring`. The result of a query returning first 5
Path query returns `k` first `__value__`s intersecting a path defined by a `Segment` or a`Linestring`. The result of a query returning first 5
values intersecting a path is presented below. Path's flow is denoted by blue arrows, returned values are orange.
[$img/index/rtree/path.png]
To perform this query one may pass a `path()` predicate taking a `Linestring` and maximum number of `__value__`s which
To perform this query one may pass a `path()` predicate taking a `Segment` or a `Linestring` and maximum number of `__value__`s which
should be returned:
rtree.query(index::path(segment, k), std::back_inserter(returned_values));
rtree.query(index::path(linestring, k), std::back_inserter(returned_values));
[warning Only one distance predicate may be used in a query. This means that there can be only one `nearest()` or `path()` predicate passed. Passing more of them will result in compile-time error.]

View File

@@ -22,7 +22,7 @@ For example queries may be used to retrieve Values:
* are nearest to some point,
* overlapping a box and has user-defined property.
[section Performing a query]
[h4 Performing a query]
There are three ways to perform a query presented below. All of them returns `__value__`s intersecting some
region defined as a `__box__`.
@@ -45,9 +45,7 @@ Use of pipe operator generating a range
BOOST_FOREACH(__value__ & v, rt | index::adaptors::queried(bgi::intersects(box_region)))
; // do something with v
[endsect]
[section Spatial predicates]
[h4 Spatial predicates]
Queries using spatial predicates returns `__value__`s which are related somehow to some Geometry - box, polygon, etc.
Names of spatial predicates correspond to names of __boost_geometry__ algorithms. Examples of some
@@ -77,11 +75,9 @@ All spatial predicates may be negated, e.g.:
// the same as
rt.query(index::disjoint(box), std::back_inserter(result));
[endsect]
[h4 Distance predicates]
[section Distance predicates]
[heading Nearest neighbours queries]
[h5 Nearest neighbours queries]
Nearest neighbours queries returns `__value__`s which are closest to some point in space.
Additionally it is possible to define how the distance to the `Value` should be calculated.
@@ -89,7 +85,7 @@ The example of knn query is presented below. 5 `__value__`s nearest to some poin
[$img/index/rtree/knn.png]
[heading k nearest neighbours]
[h5 k nearest neighbours]
There are three ways of performing knn queries. Following queries returns
`k` `__value__`s closest to some point in space. For `__box__`es
@@ -113,9 +109,7 @@ Use of `operator |`
BOOST_FOREACH(__value__ & v, rt | index::adaptors::queried(index::nearest(pt, k)))
; // do something with v
[endsect]
[section User-defined unary predicate]
[h4 User-defined unary predicate]
The user may pass a `UnaryPredicate` - function, function object or lambda expression taking const reference to Value and returning bool.
This object may be passed to the query in order to check if `__value__` should be returned by the query. To do it one
@@ -161,9 +155,7 @@ may use `index::satisfies()` function like on the example below:
rt.query(index::intersects(box) && !index::satisfies(is_not_red),
std::back_inserter(result));
[endsect]
[section Passing a set of predicates]
[h4 Passing a set of predicates]
It's possible to use some number of predicates in one query by connecting them with `operator&&` e.g. `Pred1 && Pred2 && Pred3 && ...`.
@@ -185,9 +177,7 @@ Of course it's possible to connect different types of predicates together.
BOOST_FOREACH(Value & v, rt | index::adaptors::queried(index::nearest(pt, k) && index::covered_by(b)))
; // do something with v
[endsect]
[section Inserting query results into the other R-tree]
[h4 Inserting query results into the other R-tree]
There are several ways of inserting Values returned by a query to the other R-tree container.
The most basic way is creating a temporary container for Values and insert them later.
@@ -214,6 +204,4 @@ constructor.
RTree rt4(rt1 | bgi::adaptors::queried(bgi::intersects(Box(/*...*/)))));
[endsect]
[endsect] [/ Queries /]

View File

@@ -145,8 +145,11 @@ for i in views:
model_to_quickbook2("d2_1_1point__xy", "point_xy")
group_to_quickbook("arithmetic")
group_to_quickbook("register")
group_to_quickbook("enum")
group_to_quickbook("register")
group_to_quickbook("svg")
class_to_quickbook("svg_mapper")
group_to_quickbook("wkt")
os.chdir("index")
execfile("make_qbk.py")

View File

@@ -10,6 +10,6 @@
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[section:matrix Reference matrix]
[section:matrix Reference Matrix]
[xinclude quickref.xml]
[endsect]

View File

@@ -643,69 +643,69 @@
<entry valign="top">
<bridgehead renderas="sect3">R-tree</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree">boost::geometry::index::rtree</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree">boost::geometry::index::rtree</link></member>
</simplelist>
<bridgehead renderas="sect3">R-tree parameters</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.spatial_indexes.rtree.parameters.boost__geometry__index__linear">boost::geometry::index::linear</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.parameters.boost__geometry__index__quadratic">boost::geometry::index::quadratic</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.parameters.boost__geometry__index__rstar">boost::geometry::index::rstar</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.parameters.boost__geometry__index__dynamic_linear">boost::geometry::index::dynamic_linear</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.parameters.boost__geometry__index__dynamic_quadratic">boost::geometry::index::dynamic_quadratic</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.parameters.boost__geometry__index__dynamic_rstar">boost::geometry::index::dynamic_rstar</link></member>
<member><link linkend="geometry.reference.spatial_indexes.parameters.boost__geometry__index__linear">boost::geometry::index::linear</link></member>
<member><link linkend="geometry.reference.spatial_indexes.parameters.boost__geometry__index__quadratic">boost::geometry::index::quadratic</link></member>
<member><link linkend="geometry.reference.spatial_indexes.parameters.boost__geometry__index__rstar">boost::geometry::index::rstar</link></member>
<member><link linkend="geometry.reference.spatial_indexes.parameters.boost__geometry__index__dynamic_linear">boost::geometry::index::dynamic_linear</link></member>
<member><link linkend="geometry.reference.spatial_indexes.parameters.boost__geometry__index__dynamic_quadratic">boost::geometry::index::dynamic_quadratic</link></member>
<member><link linkend="geometry.reference.spatial_indexes.parameters.boost__geometry__index__dynamic_rstar">boost::geometry::index::dynamic_rstar</link></member>
</simplelist>
<bridgehead renderas="sect3">R-tree constructors and destructor</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.rtree__">rtree()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.rtree_parameters_type_const____indexable_getter_const____value_equal_const____allocator_type_const___">rtree(parameters_type const &amp;, indexable_getter const &amp;, value_equal const &amp;, allocator_type const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.rtree_iterator__iterator_">rtree(Iterator, Iterator)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.rtree_range_const___">rtree(Range const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.rtree_rtree_const___">rtree(rtree const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.rtree_rtree_const____allocator_type_const___">rtree(rtree const &amp;, allocator_type const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.rtree_rtree____">rtree(rtree &amp;&amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.rtree_rtree_____allocator_type_const___">rtree(rtree &amp;&amp;, allocator_type const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree._rtree__">~rtree()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.rtree__">rtree()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.rtree_parameters_type_const____indexable_getter_const____value_equal_const____allocator_type_const___">rtree(parameters_type const &amp;, indexable_getter const &amp;, value_equal const &amp;, allocator_type const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.rtree_iterator__iterator_">rtree(Iterator, Iterator)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.rtree_range_const___">rtree(Range const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.rtree_rtree_const___">rtree(rtree const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.rtree_rtree_const____allocator_type_const___">rtree(rtree const &amp;, allocator_type const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.rtree_rtree____">rtree(rtree &amp;&amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.rtree_rtree_____allocator_type_const___">rtree(rtree &amp;&amp;, allocator_type const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree._rtree__">~rtree()</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">R-tree member functions</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.operator__rtree_const___">operator=(const rtree &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.operator__rtree____">operator=(rtree &amp;&amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.swap_rtree___">swap(rtree &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.insert_value_type_const___">insert(value_type const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.insert_iterator__iterator_">insert(Iterator, Iterator)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.insert_range_const___">insert(Range const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.remove_value_type_const___">remove(value_type const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.remove_iterator__iterator_">remove(Iterator, Iterator)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.remove_range_const___">remove(Range const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.query_predicates_const____outiter_">query(Predicates const &amp;, OutIter)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.size__">size()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.empty__">empty()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.clear__">clear()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.bounds__">bounds()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.count_valueorindexable_const___">count(ValueOrIndexable const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.parameters__">parameters()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.indexable_get__">indexable_get()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.value_eq__">value_eq()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.boost__geometry__index__rtree.get_allocator__">get_allocator()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.operator__rtree_const___">operator=(const rtree &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.operator__rtree____">operator=(rtree &amp;&amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.swap_rtree___">swap(rtree &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.insert_value_type_const___">insert(value_type const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.insert_iterator__iterator_">insert(Iterator, Iterator)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.insert_range_const___">insert(Range const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.remove_value_type_const___">remove(value_type const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.remove_iterator__iterator_">remove(Iterator, Iterator)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.remove_range_const___">remove(Range const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.query_predicates_const____outiter_">query(Predicates const &amp;, OutIter)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.size__">size()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.empty__">empty()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.clear__">clear()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.bounds__">bounds()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.count_valueorindexable_const___">count(ValueOrIndexable const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.parameters__">parameters()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.indexable_get__">indexable_get()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.value_eq__">value_eq()</link></member>
<member><link linkend="geometry.reference.spatial_indexes.boost__geometry__index__rtree.get_allocator__">get_allocator()</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">R-tree free functions (boost::geometry::index::)</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.insert_rtree_________value_const___">insert(rtree&lt;...&gt; &amp;, Value const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.insert_rtree_________iterator__iterator_">insert(rtree&lt;...&gt; &amp;, Iterator, Iterator)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.insert_rtree_________range_const___">insert(rtree&lt;...&gt; &amp;, Range const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.remove_rtree_________value_const___">remove(rtree&lt;...&gt; &amp;, Value const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.remove_rtree_________iterator__iterator_">remove(rtree&lt;...&gt; &amp;, Iterator, Iterator)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.remove_rtree_________range_const___">remove(rtree&lt;...&gt; &amp;, Range const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.query_rtree______const____predicates_const____outiter_">query(rtree&lt;...&gt; const &amp;, Predicates const &amp;, OutIter)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.clear_rtree________">clear(rtree&lt;...&gt; &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.size_rtree______const___">size(rtree&lt;...&gt; const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.empty_rtree______const___">empty(rtree&lt;...&gt; const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.bounds_rtree______const___">bounds(rtree&lt;...&gt; const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.rtree.group__rtree__functions.swap_rtree_________rtree________">swap(rtree&lt;...&gt; &amp;, rtree&lt;...&gt; &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.insert_rtree_________value_const___">insert(rtree&lt;...&gt; &amp;, Value const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.insert_rtree_________iterator__iterator_">insert(rtree&lt;...&gt; &amp;, Iterator, Iterator)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.insert_rtree_________range_const___">insert(rtree&lt;...&gt; &amp;, Range const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.remove_rtree_________value_const___">remove(rtree&lt;...&gt; &amp;, Value const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.remove_rtree_________iterator__iterator_">remove(rtree&lt;...&gt; &amp;, Iterator, Iterator)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.remove_rtree_________range_const___">remove(rtree&lt;...&gt; &amp;, Range const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.query_rtree______const____predicates_const____outiter_">query(rtree&lt;...&gt; const &amp;, Predicates const &amp;, OutIter)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.clear_rtree________">clear(rtree&lt;...&gt; &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.size_rtree______const___">size(rtree&lt;...&gt; const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.empty_rtree______const___">empty(rtree&lt;...&gt; const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.bounds_rtree______const___">bounds(rtree&lt;...&gt; const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__rtree__functions.swap_rtree_________rtree________">swap(rtree&lt;...&gt; &amp;, rtree&lt;...&gt; &amp;)</link></member>
</simplelist>
</entry>
</row>

View File

@@ -219,6 +219,17 @@
[endsect]
[section:io IO (input/output)]
[section:wkt WKT (Well-Known Text)]
[/include generated/wkt.qbk/]
[endsect]
[section:svg SVG (Scalable Vector Graphics)]
[include generated/svg.qbk]
[include generated/svg_mapper.qbk]
[endsect]
[endsect]
[section:iterators Iterators]
[include generated/closing_iterator.qbk]
[include generated/circular_iterator.qbk]
@@ -242,9 +253,9 @@
[endsect]
[section:spatial_indexes Spatial indexes]
[section:spatial_indexes Spatial Indexes]
[section:rtree R-tree]
[/section:rtree R-tree]
[include index/generated/rtree.qbk]
[include index/generated/rtree_functions.qbk]
[section:parameters R-tree parameters (boost::geometry::index::)]
@@ -255,7 +266,7 @@
[include index/generated/rtree_dynamic_quadratic.qbk]
[include index/generated/rtree_dynamic_rstar.qbk]
[endsect]
[endsect]
[/endsect]
[section:observers Observers (boost::geometry::index::)]
[include index/generated/indexable.qbk]

16
doc/reference/io/svg.qbk Normal file
View File

@@ -0,0 +1,16 @@
[/============================================================================
Boost.Geometry (aka GGL, Generic Geometry Library)
Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
Use, modification and distribution is subject to the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]
[heading Example]
[svg_mapper]
[svg_mapper_output]
[heading See also]
* [link geometry.reference.io.svg.svg The SVG manipulator]

View File

@@ -20,9 +20,18 @@
[*Additional functionality]
* added Spatial Index, developed for Boost.Geometry by Adam Wulkiewicz. The spatial index was originally started by Federico J. Fernandez during the Google Summer of Code 2008 program, mentored by Hartmut Kaiser.
* added SVG-output, this was already in extensions for several years
[*Documentation]
* small fixes of missing words
[*Bugfixes]
* collinear opposite segments did sometimes (in circles) have a robustness issue, fixed
* fixed insertion of false intersection point (found by buffer)
* applied patch of Vladimir Petrovic for debugging traversals
[*Solved tickets]
@@ -34,6 +43,10 @@
* [@https://svn.boost.org/trac/boost/ticket/8403 8403] silenced compiler warning C4127: conditional expression is constant
* [@https://svn.boost.org/trac/boost/ticket/8405 8405] silenced compiler warning C4189: '...' : local variable is initialized but not referenced
[*Internal changes]
* Made several algorithms variant-aware (append, area, clear, convert, equals, length, num_points)
[/=================]
[heading Boost 1.53]

View File

@@ -0,0 +1,65 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// QuickBook Example
// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//[svg_mapper
//` Shows the usage of svg_mapper
#include <iostream>
#include <fstream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
int main()
{
// Specify the basic type
typedef boost::geometry::model::d2::point_xy<double> point_type;
// Declare some geometries and set their values
point_type a;
boost::geometry::assign_values(a, 3, 6);
boost::geometry::model::polygon<point_type> b;
boost::geometry::read_wkt("POLYGON((0 0,0 7,4 2,2 0,0 0))", b);
boost::geometry::model::linestring<point_type> c;
c.push_back(point_type(3, 4));
c.push_back(point_type(4, 5));
// Declare a stream and an SVG mapper
std::ofstream svg("my_map.svg");
boost::geometry::svg_mapper<point_type> mapper(svg, 400, 400);
// Add geometries such that all these geometries fit on the map
mapper.add(a);
mapper.add(b);
mapper.add(c);
// Draw the geometries on the SVG map, using a specific SVG style
mapper.map(a, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2", 5);
mapper.map(b, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:2");
mapper.map(c, "opacity:0.4;fill:none;stroke:rgb(212,0,0);stroke-width:5");
// Destructor of map will be called - adding </svg>
// Destructor of stream will be called, closing the file
return 0;
}
//]
//[svg_mapper_output
/*`
Output:
[$img/io/svg_mapper.png]
*/
//]

View File

@@ -17,24 +17,33 @@ namespace boost { namespace geometry { namespace index { namespace detail {
namespace dispatch {
template <typename Indexable, typename LineString, typename Tag>
template <typename Indexable, typename Geometry, typename IndexableTag, typename GeometryTag>
struct path_intersection
{
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_GEOMETRY, (path_intersection));
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_OR_INDEXABLE, (path_intersection));
};
template <typename Indexable, typename Segment>
struct path_intersection<Indexable, Segment, box_tag, segment_tag>
{
typedef typename default_distance_result<typename ::boost::geometry::traits::point_type<Segment>::type>::type comparable_distance_type;
static inline bool apply(Indexable const& b, Segment const& segment, comparable_distance_type & comparable_distance)
{
typedef typename ::boost::geometry::traits::point_type<Segment>::type point_type;
point_type p1, p2;
geometry::detail::assign_point_from_index<0>(segment, p1);
geometry::detail::assign_point_from_index<1>(segment, p2);
return index::detail::segment_intersection(b, p1, p2, comparable_distance);
}
};
template <typename Indexable, typename Linestring>
struct path_intersection<Indexable, Linestring, point_tag>
struct path_intersection<Indexable, Linestring, box_tag, linestring_tag>
{
BOOST_MPL_ASSERT_MSG((false), SEGMENT_POINT_INTERSECTION_UNAVAILABLE, (path_intersection));
};
typedef typename default_length_result<Linestring>::type comparable_distance_type;
template <typename Indexable, typename Linestring>
struct path_intersection<Indexable, Linestring, box_tag>
{
typedef typename default_length_result<Linestring>::type length_type;
static inline bool apply(Indexable const& b, Linestring const& path, length_type & comparable_distance)
static inline bool apply(Indexable const& b, Linestring const& path, comparable_distance_type & comparable_distance)
{
typedef typename ::boost::range_value<Linestring>::type point_type;
typedef typename ::boost::range_const_iterator<Linestring>::type const_iterator;
@@ -59,7 +68,7 @@ struct path_intersection<Indexable, Linestring, box_tag>
typename default_distance_result<point_type, point_type>::type
dist = geometry::distance(*it0, *it1);
length_type rel_dist;
comparable_distance_type rel_dist;
if ( index::detail::segment_intersection(b, *it0, *it1, rel_dist) )
{
comparable_distance += dist * rel_dist;
@@ -76,19 +85,28 @@ struct path_intersection<Indexable, Linestring, box_tag>
} // namespace dispatch
// TODO - change the name e.g. to path_intersection_distance
// and segment_intersection e.g. to segment_intersection_relative_distance
template <typename Indexable, typename SegmentOrLinestring>
struct default_path_intersection_distance_type
{
typedef typename dispatch::path_intersection<
Indexable, SegmentOrLinestring,
typename detail::traits::tag<Indexable>::type,
typename detail::traits::tag<SegmentOrLinestring>::type
>::comparable_distance_type type;
};
template <typename Indexable, typename Linestring> inline
template <typename Indexable, typename SegmentOrLinestring> inline
bool path_intersection(Indexable const& b,
Linestring const& path,
typename default_length_result<Linestring>::type & distance)
SegmentOrLinestring const& path,
typename default_path_intersection_distance_type<Indexable, SegmentOrLinestring>::type & comparable_distance)
{
// TODO check Indexable and Linestring concepts
return dispatch::path_intersection<
Indexable, Linestring, typename detail::traits::tag<Indexable>::type
>::apply(b, path, distance);
Indexable, SegmentOrLinestring,
typename detail::traits::tag<Indexable>::type,
typename detail::traits::tag<SegmentOrLinestring>::type
>::apply(b, path, comparable_distance);
}
}}}} // namespace boost::geometry::index::detail

View File

@@ -143,14 +143,16 @@ struct calculate_distance< nearest< to_furthest<Point> >, Indexable, value_tag>
}
};
template <typename Linestring, typename Indexable, typename Tag>
struct calculate_distance< path<Linestring>, Indexable, Tag>
template <typename SegmentOrLinestring, typename Indexable, typename Tag>
struct calculate_distance< path<SegmentOrLinestring>, Indexable, Tag>
{
typedef typename geometry::default_length_result<Linestring>::type result_type;
typedef typename index::detail::default_path_intersection_distance_type<
Indexable, SegmentOrLinestring
>::type result_type;
static inline bool apply(path<Linestring> const& p, Indexable const& i, result_type & result)
static inline bool apply(path<SegmentOrLinestring> const& p, Indexable const& i, result_type & result)
{
return index::detail::path_intersection(i, p.linestring, result);
return index::detail::path_intersection(i, p.geometry, result);
}
};

View File

@@ -151,14 +151,14 @@ struct nearest
unsigned count;
};
template <typename Linestring>
template <typename SegmentOrLinestring>
struct path
{
path(Linestring const& ls, unsigned k)
: linestring(ls)
path(SegmentOrLinestring const& g, unsigned k)
: geometry(g)
, count(k)
{}
Linestring linestring;
SegmentOrLinestring geometry;
unsigned count;
};

View File

@@ -240,14 +240,14 @@ nearest(Point const& point, unsigned k)
/*!
\brief Generate path() predicate.
When path predicate is passed to the query, the returned values are k values on the path closest to
its begin. \c path() predicate takes a \c Linestring defining the path and the maximum
When path predicate is passed to the query, the returned values are k values along the path closest to
its begin. \c path() predicate takes a \c Segment or a \c Linestring defining the path and the maximum
number of \c Values that should be returned.
\par Example
\verbatim
bgi::query(spatial_index, bgi::path(pt, 5), std::back_inserter(result));
bgi::query(spatial_index, bgi::path(pt, 5) && bgi::intersects(box), std::back_inserter(result));
bgi::query(spatial_index, bgi::path(segment, 5), std::back_inserter(result));
bgi::query(spatial_index, bgi::path(linestring, 5) && bgi::intersects(box), std::back_inserter(result));
\endverbatim
\warning
@@ -255,14 +255,14 @@ Only one distance predicate (\c nearest() or \c path()) may be used in a query.
\ingroup predicates
\param point The point from which distance is calculated.
\param linestring The path along which distance is calculated.
\param k The maximum number of values to return.
*/
template <typename Linestring> inline
detail::path<Linestring>
path(Linestring const& linestring, unsigned k)
template <typename SegmentOrLinestring> inline
detail::path<SegmentOrLinestring>
path(SegmentOrLinestring const& linestring, unsigned k)
{
return detail::path<Linestring>(linestring, k);
return detail::path<SegmentOrLinestring>(linestring, k);
}
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL

View File

@@ -214,6 +214,15 @@ inline void svg_map(std::ostream& stream,
}
/*!
\brief Helper class to create SVG maps
\tparam Point Point type, for input geometries.
\tparam SameScale Boolean flag indicating if horizontal and vertical scale should
be the same. The default value is true
\ingroup svg
\qbk{[include reference/io/svg.qbk]}
*/
template <typename Point, bool SameScale = true>
class svg_mapper : boost::noncopyable
{
@@ -252,21 +261,39 @@ class svg_mapper : boost::noncopyable
}
public :
svg_mapper(std::ostream& s, int w, int h
/*!
\brief Constructor, initializing the SVG map. Opens and initializes the SVG.
Should be called explicitly.
\param stream Output stream, should be a stream already open
\param width Width of the SVG map (in SVG pixels)
\param height Height of the SVG map (in SVG pixels)
\param width_height Optional information to increase width and/or height
*/
explicit svg_mapper(std::ostream& stream, int width, int height
, std::string const& width_height = "width=\"100%\" height=\"100%\"")
: m_stream(s)
, m_width(w)
, m_height(h)
: m_stream(stream)
, m_width(width)
, m_height(height)
, m_width_height(width_height)
{
assign_inverse(m_bounding_box);
}
/*!
\brief Destructor, called automatically. Closes the SVG by streaming <\/svg>
*/
virtual ~svg_mapper()
{
m_stream << "</svg>" << std::endl;
}
/*!
\brief Adds a geometry to the transformation matrix. After doing this,
the specified geometry can be mapped fully into the SVG map
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
*/
template <typename Geometry>
void add(Geometry const& geometry)
{
@@ -280,6 +307,14 @@ public :
}
}
/*!
\brief Maps a geometry into the SVG map using the specified style
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\param style String containing verbatim SVG style information
\param size Optional size (used for SVG points) in SVG pixels. For linestrings,
specify linewidth in the SVG style information
*/
template <typename Geometry>
void map(Geometry const& geometry, std::string const& style,
int size = -1)
@@ -300,6 +335,16 @@ public :
svg_map(m_stream, style, size, geometry, *m_matrix);
}
/*!
\brief Adds a text to the SVG map
\tparam TextPoint \tparam_point
\param point Location of the text (in map units)
\param s The text itself
\param style String containing verbatim SVG style information, of the text
\param offset_x Offset in SVG pixels, defaults to 0
\param offset_y Offset in SVG pixels, defaults to 0
\param lineheight Line height in SVG pixels, in case the text contains \n
*/
template <typename TextPoint>
void text(TextPoint const& point, std::string const& s,
std::string const& style,

View File

@@ -224,7 +224,7 @@ struct svg<polygon_tag, Polygon>
/*!
\brief Generic geometry template manipulator class, takes corresponding output class from traits class
\ingroup svg
\details Stream manipulator, streams geometry classes as Virtual Earth shape
\details Stream manipulator, streams geometry classes as SVG (Scalable Vector Graphics)
*/
template <typename G>
class svg_manipulator
@@ -256,15 +256,20 @@ private:
};
/*!
\brief Main svg function to stream geometries as SVG
\brief Manipulator to stream geometries as SVG
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\param style String containing verbatim SVG style information
\param size Optional size (used for SVG points) in SVG pixels. For linestrings,
specify linewidth in the SVG style information
\ingroup svg
*/
template <typename Geometry>
inline svg_manipulator<Geometry> svg(Geometry const& t, std::string const& style, int size = -1)
inline svg_manipulator<Geometry> svg(Geometry const& geometry, std::string const& style, int size = -1)
{
concept::check<Geometry const>();
return svg_manipulator<Geometry>(t, style, size);
return svg_manipulator<Geometry>(geometry, style, size);
}
}} // namespace boost::geometry

View File

@@ -18,6 +18,7 @@
#include <boost/geometry/index/rtree.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/segment.hpp>
namespace bg = boost::geometry;
namespace bgi = bg::index;
@@ -25,6 +26,7 @@ namespace bgi = bg::index;
typedef bg::model::point<double, 2, bg::cs::cartesian> P;
typedef bg::model::box<P> B;
typedef bg::model::linestring<P> LS;
typedef bg::model::segment<P> S;
template <typename I1, typename I2, typename O>
void mycopy(I1 first, I2 last, O o)
@@ -283,7 +285,7 @@ int main()
temp += result.size();
}
dur_t time = clock_t::now() - start;
std::cout << time << " - query(path(LS, " << path_values_count << ")) " << path_queries_count << " found " << temp << '\n';
std::cout << time << " - query(path(LS6, " << path_values_count << ")) " << path_queries_count << " found " << temp << '\n';
}
{
@@ -303,7 +305,23 @@ int main()
temp += result.size();
}
dur_t time = clock_t::now() - start;
std::cout << time << " - query(path(LS, " << path_values_count << ")) " << path_queries_count2 << " found " << temp << '\n';
std::cout << time << " - query(path(LS2, " << path_values_count << ")) " << path_queries_count2 << " found " << temp << '\n';
}
{
clock_t::time_point start = clock_t::now();
size_t temp = 0;
for (size_t i = 0 ; i < path_queries_count2 ; ++i )
{
float x = coords[i].first;
float y = coords[i].second;
S seg(P(x, y), P(x+max_val/100, y+max_val/100));
result.clear();
t.query(bgi::path(seg, path_values_count), std::back_inserter(result));
temp += result.size();
}
dur_t time = clock_t::now() - start;
std::cout << time << " - query(path(S, " << path_values_count << ")) " << path_queries_count2 << " found " << temp << '\n';
}
#endif
{

View File

@@ -11,6 +11,12 @@
#include <boost/geometry/index/detail/algorithms/path_intersection.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/segment.hpp>
//#include <boost/geometry/io/wkt/read.hpp>
template <typename Box, typename Linestring>
@@ -18,11 +24,24 @@ void test_path_intersection(Box const& box, Linestring const& path,
bool expected_result,
typename bg::default_length_result<Linestring>::type expected_dist)
{
typename bg::default_length_result<Linestring>::type dist;
typename bgi::detail::default_path_intersection_distance_type<Box, Linestring>::type dist;
bool value = bgi::detail::path_intersection(box, path, dist);
BOOST_CHECK(value == expected_result);
if ( value && expected_result )
BOOST_CHECK_CLOSE(dist, expected_dist, 0.0001);
if ( ::boost::size(path) == 2 )
{
typedef typename ::boost::range_value<Linestring>::type P;
typedef bg::model::segment<P> Seg;
typename bgi::detail::default_path_intersection_distance_type<Box, Seg>::type dist;
Seg seg(*::boost::begin(path), *(::boost::begin(path)+1));
bool value = bgi::detail::path_intersection(box, seg, dist);
BOOST_CHECK(value == expected_result);
if ( value && expected_result )
BOOST_CHECK_CLOSE(dist, expected_dist, 0.0001);
}
}
template <typename Box, typename Linestring>
@@ -37,11 +56,6 @@ void test_geometry(std::string const& wkt_g, std::string const& wkt_path,
test_path_intersection(box, path, expected_result, expected_dist);
}
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/linestring.hpp>
void test_large_integers()
{
typedef bg::model::point<int, 2, bg::cs::cartesian> int_point_type;