Merge branch 'develop' of https://github.com/boostorg/geometry into feature/disjoint

This commit is contained in:
Menelaos Karavelas
2014-05-20 04:12:02 +03:00
57 changed files with 1095 additions and 319 deletions

View File

@@ -57,7 +57,6 @@ ALIASES = qbk{1}="\xmlonly <qbk>\1</qbk> \endxmlonly" \
tparam_radius="numeric type for radius (of sphere, earth)" \
tparam_container="container type, for example std::vector, std::deque" \
tparam_dimension_required="Dimension, this template parameter is required. Should contain \\[0 .. n-1\\] for an n-dimensional geometry" \
tparam_first_point="first point type" \
tparam_functor="Function or class with operator()" \
tparam_output_collection="output collection, either a multi-geometry, or a std::vector<Geometry> / std::deque<Geometry> etc" \
tparam_geometry="Any type fulfilling a Geometry Concept" \
@@ -67,8 +66,10 @@ ALIASES = qbk{1}="\xmlonly <qbk>\1</qbk> \endxmlonly" \
tparam_out{1}="A valid output iterator type, accepting geometries of \1 Concept" \
tparam_point="Any type fulfilling a Point Concept" \
tparam_range_point="Any type fulfilling a Range Concept where it range_value type fulfills the Point Concept" \
tparam_first_point="point type" \
tparam_first_point="first point type" \
tparam_first_box="first box type" \
tparam_second_point="second point type" \
tparam_second_box="second box type" \
tparam_segment_point="segment point type" \
tparam_strategy{1}="Any type fulfilling a \1 Strategy Concept" \
tparam_strategy_overlay="Compound strategy for segment intersection" \
@@ -176,9 +177,13 @@ WARN_LOGFILE =
INPUT = . .. ../../../../boost/geometry/core \
../../../../boost/geometry/algorithms \
../../../../boost/geometry/algorithms/detail \
../../../../boost/geometry/algorithms/detail/overlay \
../../../../boost/geometry/algorithms/detail/distance \
../../../../boost/geometry/algorithms/detail/equals \
../../../../boost/geometry/algorithms/detail/overlay \
../../../../boost/geometry/algorithms/detail/relate \
../../../../boost/geometry/algorithms/detail/sections \
../../../../boost/geometry/algorithms/detail/turns \
../../../../boost/geometry/algorithms/detail/within \
../../../../boost/geometry/arithmetic \
../../../../boost/geometry/geometries/concepts \
../../../../boost/geometry/geometries \

View File

@@ -113,6 +113,7 @@ Boost.Geometry contains contributions by:
* Federico Fern\u00E1ndez (preliminary version of R-tree spatial index)
* Karsten Ahnert (patch for cross-track distance)
* Mats Taraldsvik (documentation: adapting a legacy model)
* Samuel Debionne (variant support for distance)
[include imports.qbk]

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -105,6 +105,8 @@
[import src/examples/geometries/register/multi_polygon.cpp]
[import src/examples/io/svg.cpp]
[import src/examples/io/wkt.cpp]
[import src/examples/io/read_wkt.cpp]
[import src/examples/views/box_view.cpp]
[import src/examples/views/segment_view.cpp]

View File

@@ -51,7 +51,7 @@ The examples of structures of trees created by use of different algorithms and e
[table
[[] [Linear algorithm] [Quadratic algorithm] [R*-tree] [Packing algorithm]]
[[*Example structure*] [[$img/index/rtree/linear.png]] [[$img/index/rtree/quadratic.png]] [[$img/index/rtree/rstar.png]] [[$img/index/rtree/bulk.png]]]
[[*1M Values inserts*] [1.76s] [2.47s] [6.19s] [1.67s]]
[[*1M Values inserts*] [1.76s] [2.47s] [6.19s] [0.64s]]
[[*100k spatial queries*] [2.21s] [0.51s] [0.12s] [0.07s]]
[[*100k knn queries*] [6.37s] [2.09s] [0.64s] [0.52s]]
]

View File

@@ -30,13 +30,20 @@ __rtree__ has 5 parameters but only 2 are required:
__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.
The `__indexable__` is a type adapted to Point, Box or Segment concept.
The examples of rtrees storing `__value__`s translatable to various `__indexable__`s are presented below.
[table
[[rtree<Point, ...>] [rtree<Box, ...>] [rtree<Segment, ...>]]
[[[$img/index/rtree/rtree_pt.png]] [[$img/index/rtree/rstar.png]] [[$img/index/rtree/rtree_seg.png]]]
]
By default function objects `index::indexable<Value>` and `index::equal_to<Value>` are defined for some typically used `__value__`
types which may be stored without defining any additional classes. By default the rtree may store pure `__indexable__`s, pairs
and tuples. In the case of those two collection types, the `__indexable__` must be the first stored type.
* `__indexable__ = __point__ | __box__`
* `__value__ = Indexable | std::pair<__indexable__, T> | tuple<__indexable__, ...>`
* `__indexable__ = __point__ | __box__ | Segment`
* `__value__ = Indexable | std::pair<__indexable__, T> | boost::tuple<__indexable__, ...> [ | std::tuple<__indexable__, ...> ]`
By default `boost::tuple<...>` is supported on all compilers. If the compiler supports C++11 tuples and variadic templates
then `std::tuple<...>` may be used "out of the box" as well.
@@ -46,6 +53,7 @@ Examples of default `__value__` types:
geometry::model::point<...>
geometry::model::point_xy<...>
geometry::model::box<...>
geometry::model::segment<...>
std::pair<geometry::model::box<...>, unsigned>
boost::tuple<geometry::model::point<...>, int, float>
@@ -55,7 +63,7 @@ The predefined `index::indexable<Value>` returns const reference to the `__index
The predefined `index::equal_to<Value>`:
* for `__point__` and `__box__` - compares `__value__`s with geometry::equals().
* for `__point__`, `__box__` and `Segment` - compares `__value__`s with geometry::equals().
* for `std::pair<...>` - compares both components of the `__value__`. The first value stored in the pair is compared before the second one.
If the value stored in the pair is a Geometry, `geometry::equals()` is used. For other types it uses `operator==()`.
* for `tuple<...>` - compares all components of the `__value__`. If the component is a `Geometry`, `geometry::equals()`

View File

@@ -73,6 +73,11 @@ Examples of some basic queries may be found in the tables below. The query regio
[[[$img/index/rtree/intersects_ring.png]] [[$img/index/rtree/intersects_poly.png]] [[$img/index/rtree/intersects_mpoly.png]] [[$img/index/rtree/intersects_segment.png]] [[$img/index/rtree/intersects_linestring.png]]]
]
[table
[[intersects(Box)] [disjoint(Box)] [intersects(Box)] [disjoint(Box)]]
[[[$img/index/rtree/rtree_pt_intersects_box.png]] [[$img/index/rtree/rtree_pt_disjoint_box.png]] [[$img/index/rtree/rtree_seg_intersects_box.png]] [[$img/index/rtree/rtree_seg_disjoint_box.png]]]
]
Spatial predicates are generated by functions defined in `boost::geometry::index` namespace.
rt.query(index::contains(box), std::back_inserter(result));
@@ -91,20 +96,36 @@ All spatial predicates may be negated, e.g.:
[h4 Nearest neighbours queries]
Nearest neighbours queries returns `__value__`s which are closest to some point in space.
The example of k-NN query is presented below. 5 `__value__`s nearest to the point are orange.
Nearest neighbours queries returns `__value__`s which are closest to some Geometry.
The examples of k-NN queries are presented below. 5 `__value__`s nearest to the Geometry are orange.
[$img/index/rtree/knn.png]
[table
[[nearest(Point, k)] [nearest(Box, k)] [nearest(Segment, k)]]
[[[$img/index/rtree/knn_pt_box.png]] [[$img/index/rtree/knn_box_box.png]] [[$img/index/rtree/knn_seg_box.png]]]
]
[table
[[nearest(Point, k)] [nearest(Box, k)] [nearest(Segment, k)] [nearest(Point, k)] [nearest(Box, k)] [nearest(Segment, k)]]
[[[$img/index/rtree/rtree_pt_knn_pt.png]] [[$img/index/rtree/rtree_pt_knn_box.png]] [[$img/index/rtree/rtree_pt_knn_seg.png]]
[[$img/index/rtree/rtree_seg_knn_pt.png]] [[$img/index/rtree/rtree_seg_knn_box.png]] [[$img/index/rtree/rtree_seg_knn_seg.png]]]
]
To perform the knn query one must pass the nearest predicate generated by the
`nearest()` function defined in `boost::geometry::index` namespace.
The following query returns `k` `__value__`s closest to some point in space.
For non-point `__indexable__`s the shortest distance is calculated.
For non-point `__indexable__`s the shortest distance is calculated using `bg::comparable_distance()` function.
The following query returns `k` `__value__`s closest to some Point in space.
std::vector<__value__> returned_values;
__point__ pt(...);
__point__ pt(/*...*/);
rt.query(bgi::nearest(pt, k), std::back_inserter(returned_values));
The same way different query Geometries can be used:
__box__ box(/*...*/);
rt.query(bgi::nearest(box, k), std::back_inserter(returned_values));
Segment seg(/*...*/);
rt.query(bgi::nearest(seg, k), std::back_inserter(returned_values));
[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.

View File

@@ -741,7 +741,7 @@
<member><link linkend="geometry.reference.spatial_indexes.group__predicates.overlaps_geometry_const___">overlaps(Geometry const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__predicates.within_geometry_const___">within(Geometry const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__predicates.satisfies_unarypredicate_const___">satisfies(UnaryPredicate const &amp;)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__predicates.nearest_point_const____unsigned_">nearest(Point const &amp;, unsigned)</link></member>
<member><link linkend="geometry.reference.spatial_indexes.group__predicates.nearest_geometry_const____unsigned_">nearest(Geometry const &amp;, unsigned)</link></member>
</simplelist>
</entry>
<!--entry valign="top">

View File

@@ -223,7 +223,7 @@
[section:io IO (input/output)]
[section:wkt WKT (Well-Known Text)]
[/include generated/wkt.qbk/]
[include generated/wkt.qbk]
[endsect]
[section:svg SVG (Scalable Vector Graphics)]
[include generated/svg.qbk]

View File

@@ -0,0 +1,15 @@
[/============================================================================
Boost.Geometry (aka GGL, Generic Geometry Library)
Copyright (c) 2009-2014 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]
[read_wkt]
[heading See also]
* [link geometry.reference.io.wkt.wkt WKT streaming manipulator]

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

@@ -0,0 +1,16 @@
[/============================================================================
Boost.Geometry (aka GGL, Generic Geometry Library)
Copyright (c) 2009-2014 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]
[wkt]
[wkt_output]
[heading See also]
* [link geometry.reference.io.wkt.read_wkt Read WKT]

View File

@@ -18,4 +18,5 @@ exe quick_start : quick_start.cpp ;
build-project algorithms ;
build-project core ;
build-project geometries ;
build-project io ;
build-project views ;

View File

@@ -0,0 +1,19 @@
# Boost.Geometry (aka GGL, Generic Geometry Library)
#
# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
# Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
# Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland
# 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)
project boost-geometry-doc-example-io
: # requirements
;
exe svg : svg.cpp ;
exe wkt : wkt.cpp ;
exe read_wkt : read_wkt.cpp ;

View File

@@ -0,0 +1,37 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// QuickBook Example
// Copyright (c) 2014 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)
//[read_wkt
//` Shows the usage of read_wkt
#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::model::polygon<point_type> b;
boost::geometry::read_wkt("POINT(1 2)", a);
boost::geometry::read_wkt("POLYGON((0 0,0 7,4 2,2 0,0 0))", b);
return 0;
}
//]

View File

@@ -0,0 +1,43 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// QuickBook Example
// Copyright (c) 2014 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)
//[wkt
//` Shows the usage of wkt
#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);
std::cout << boost::geometry::wkt(a) << std::endl;
return 0;
}
//]
//[wkt_output
/*`
Output:
point(3 6)
*/
//]

View File

@@ -273,6 +273,13 @@ void test_all()
"POLYGON((5 0,2.5 9,9.5 3.5,0.5 3.5,7.5 9,5 0))",
0, 11, 25.6158412);
// CCW polygons should turn CW after dissolve
test_one<polygon, polygon>("cw",
"POLYGON((2 8,8 8,8 0,0 0,0 6,4 6,4 4,2 4,2 8))",
0, 7, 60);
test_one<polygon, polygon>("ccw",
"POLYGON((2 8,2 4,4 4,4 6,0 6,0 0,8 0,8 8,2 8))",
0, 12, 64); // TODO: should have the same, 7, 60. The polygon is dissolved (splitted) but the extra polygon is still on top of the other
// Multi-geometries
{

View File

@@ -86,13 +86,17 @@ private:
typedef typename strategy::distance::services::return_type
<
comparable_strategy, Point, typename point_type<Range>::type
comparable_strategy,
Point,
typename boost::range_value<Range>::type
>::type comparable_return_type;
public:
typedef typename strategy::distance::services::return_type
<
Strategy, Point, typename point_type<Range>::type
Strategy,
Point,
typename boost::range_value<Range>::type
>::type return_type;
static inline return_type apply(Point const& point, Range const& range,
@@ -123,7 +127,8 @@ public:
{
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Point, Range
comparable_strategy, Strategy, Point,
typename boost::range_value<Range>::type
>::apply( c_strategy.apply(point,
*boost::begin(view),
*boost::begin(view)) );
@@ -140,7 +145,10 @@ public:
{
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Point, Range
comparable_strategy,
Strategy,
Point,
typename boost::range_value<Range>::type
>::apply(zero);
}
else if (cds < cd)
@@ -151,7 +159,10 @@ public:
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Point, Range
comparable_strategy,
Strategy,
Point,
typename boost::range_value<Range>::type
>::apply(cd);
}
};

View File

@@ -127,23 +127,10 @@ private:
BoxPoints const& box_points,
ComparableStrategy const& strategy)
{
boost::ignore_unused_variable_warning(strategy);
comparable_return_type cd_min =
strategy.apply(point, box_points[0], box_points[3]);
for (unsigned int i = 0; i < 2; ++i)
{
comparable_return_type cd =
strategy.apply(point, box_points[i], box_points[i+1]);
if ( cd < cd_min )
{
cd_min = cd;
}
}
return cd_min;
return point_to_range
<
Point, BoxPoints, open, ComparableStrategy
>::apply(point, box_points, strategy);
}
};

View File

@@ -10,6 +10,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
#include <vector>
#include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/type_traits/is_same.hpp>
@@ -29,11 +31,14 @@
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
@@ -48,6 +53,165 @@ namespace detail { namespace distance
{
template
<
typename Segment,
typename Box,
typename Strategy,
bool UsePointBoxStrategy = false
>
class segment_to_box_2D_generic
{
private:
typedef typename point_type<Segment>::type segment_point;
typedef typename point_type<Box>::type box_point;
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
<
comparable_strategy, segment_point, box_point
>::type comparable_return_type;
typedef point_to_range
<
segment_point, std::vector<box_point>, open, comparable_strategy
> point_to_box_boundary;
public:
typedef typename strategy::distance::services::return_type
<
Strategy, segment_point, box_point
>::type return_type;
static inline return_type apply(Segment const& segment,
Box const& box,
Strategy const& strategy,
bool check_intersection = true)
{
if ( check_intersection && geometry::intersects(segment, box) )
{
return 0;
}
comparable_strategy cstrategy =
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
boost::ignore_unused_variable_warning(cstrategy);
// get segment points
segment_point p[2];
detail::assign_point_from_index<0>(segment, p[0]);
detail::assign_point_from_index<1>(segment, p[1]);
// get box points
std::vector<box_point> box_points(4);
detail::assign_box_corners_oriented<true>(box, box_points);
comparable_return_type cd[6];
for (unsigned int i = 0; i < 4; ++i)
{
cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
}
cd[4] = point_to_box_boundary::apply(p[0], box_points, cstrategy);
cd[5] = point_to_box_boundary::apply(p[1], box_points, cstrategy);
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Segment, Box
>::apply( *std::min_element(cd, cd + 6) );
}
};
template
<
typename Segment,
typename Box,
typename Strategy
>
class segment_to_box_2D_generic<Segment, Box, Strategy, true>
{
private:
typedef typename point_type<Segment>::type segment_point;
typedef typename point_type<Box>::type box_point;
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
<
comparable_strategy, segment_point, box_point
>::type comparable_return_type;
typedef typename strategy::distance::services::comparable_type
<
typename detail::distance::default_strategy
<
segment_point, Box
>::type
>::type point_box_comparable_strategy;
public:
typedef typename strategy::distance::services::return_type
<
Strategy, segment_point, box_point
>::type return_type;
static inline return_type apply(Segment const& segment,
Box const& box,
Strategy const& strategy,
bool check_intersection = true)
{
if ( check_intersection && geometry::intersects(segment, box) )
{
return 0;
}
comparable_strategy cstrategy =
strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
boost::ignore_unused_variable_warning(cstrategy);
// get segment points
segment_point p[2];
detail::assign_point_from_index<0>(segment, p[0]);
detail::assign_point_from_index<1>(segment, p[1]);
// get box points
std::vector<box_point> box_points(4);
detail::assign_box_corners_oriented<true>(box, box_points);
comparable_return_type cd[6];
for (unsigned int i = 0; i < 4; ++i)
{
cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
}
point_box_comparable_strategy pb_cstrategy;
boost::ignore_unused_variable_warning(pb_cstrategy);
cd[4] = pb_cstrategy.apply(p[0], box);
cd[5] = pb_cstrategy.apply(p[1], box);
return strategy::distance::services::comparable_to_regular
<
comparable_strategy, Strategy, Segment, Box
>::apply( *std::min_element(cd, cd + 6) );
}
};
template
<
typename ReturnType,
@@ -118,7 +282,7 @@ private:
}
// p1 lies to the left of the box
if ( geometry::get<0>(p1) <= geometry::get<1>(bottom_left) )
if ( geometry::get<0>(p1) <= geometry::get<0>(bottom_left) )
{
if ( geometry::get<1>(p1) <= geometry::get<1>(bottom_left) )
{
@@ -253,7 +417,7 @@ private:
}
// p1 lies to the left of the box
if ( geometry::get<0>(p1) <= geometry::get<1>(bottom_left) )
if ( geometry::get<0>(p1) <= geometry::get<0>(bottom_left) )
{
if ( geometry::get<1>(p1) >= geometry::get<1>(top_left) )
{
@@ -322,9 +486,9 @@ private:
ReturnType diff1 = cast::apply(geometry::get<1>(p0))
- cast::apply(geometry::get<1>(p1));
ReturnType t_min1 = cast::apply(geometry::get<1>(p0))
- cast::apply(geometry::get<1>(top_right));
ReturnType t_max1 = cast::apply(geometry::get<1>(p0))
- cast::apply(geometry::get<1>(bottom_left));
ReturnType t_max1 = cast::apply(geometry::get<1>(p0))
- cast::apply(geometry::get<1>(top_right));
// t_max0 < t_max1
if ( t_max0 * diff1 < t_max1 * diff0 )

View File

@@ -38,8 +38,8 @@ struct get_turn_without_info
{
template <typename RobustPolicy, typename OutputIterator>
static inline OutputIterator apply(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
Point1 const& pi, Point1 const& pj, Point1 const& /*pk*/,
Point2 const& qi, Point2 const& qj, Point2 const& /*qk*/,
bool /*is_p_first*/, bool /*is_p_last*/,
bool /*is_q_first*/, bool /*is_q_last*/,
TurnInfo const& ,

View File

@@ -394,8 +394,8 @@ struct get_turn_info_for_endpoint
typename TurnInfo,
typename IntersectionInfo
>
static inline bool handle_internal(Point1 const& i1, Point1 const& j1, Point1 const& /*k1*/,
Point2 const& i2, Point2 const& j2, Point2 const& k2,
static inline bool handle_internal(Point1 const& /*i1*/, Point1 const& /*j1*/, Point1 const& /*k1*/,
Point2 const& i2, Point2 const& j2, Point2 const& /*k2*/,
RobustPoint1 const& ri1, RobustPoint1 const& rj1, RobustPoint1 const& /*rk1*/,
RobustPoint2 const& ri2, RobustPoint2 const& rj2, RobustPoint2 const& rk2,
bool first1, bool last1, bool first2, bool last2,
@@ -403,6 +403,8 @@ struct get_turn_info_for_endpoint
IntersectionInfo const& inters, int ip_index,
operation_type & op1, operation_type & op2)
{
boost::ignore_unused_variable_warning(i2);
boost::ignore_unused_variable_warning(j2);
boost::ignore_unused_variable_warning(ip_index);
boost::ignore_unused_variable_warning(tp_model);

View File

@@ -160,7 +160,7 @@ public:
intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
no_rescale_policy const& robust_policy)
no_rescale_policy const& /*robust_policy*/)
: m_side_calc(pi, pj, pk, qi, qj, qk)
{}

View File

@@ -446,7 +446,7 @@ struct get_turn_info_linear_areal
typename OutIt>
static inline bool append_collinear_spikes(TurnInfo & tp,
IntersectionInfo const& inters,
bool is_p_last, bool is_q_last,
bool is_p_last, bool /*is_q_last*/,
method_type method, append_version_c version,
OutIt out)
{
@@ -489,7 +489,7 @@ struct get_turn_info_linear_areal
typename OutIt>
static inline bool append_opposite_spikes(TurnInfo & tp,
IntersectionInfo const& inters,
bool is_p_last, bool is_q_last,
bool is_p_last, bool /*is_q_last*/,
OutIt out)
{
bool is_p_spike = ( Version == append_touches ?
@@ -635,10 +635,10 @@ struct get_turn_info_linear_areal
typename IntersectionInfo,
typename OutputIterator>
static inline bool get_turn_info_for_endpoint(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
Point1 const& pi, Point1 const& /*pj*/, Point1 const& /*pk*/,
Point2 const& qi, Point2 const& /*qj*/, Point2 const& /*qk*/,
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
bool /*is_q_first*/, bool is_q_last,
TurnInfo const& tp_model,
IntersectionInfo const& inters,
method_type /*method*/,
@@ -659,6 +659,8 @@ struct get_turn_info_linear_areal
if ( !is_p_first && !is_p_last )
return false;
// TODO: is_q_last could probably be replaced by false and removed from parameters
linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last);
linear_intersections::ip_info const& ip0 = intersections.template get<0>();
linear_intersections::ip_info const& ip1 = intersections.template get<1>();

View File

@@ -464,14 +464,11 @@ struct linear_areal
typename Geometry,
typename OtherGeometry,
typename BoundaryChecker>
void apply(Result & res,
TurnIt first, TurnIt it, TurnIt last,
void apply(Result & res, TurnIt it,
Geometry const& geometry,
OtherGeometry const& other_geometry,
BoundaryChecker const& boundary_checker)
{
//BOOST_ASSERT( it != last );
overlay::operation_type op = it->operations[op_id].operation;
if ( op != overlay::operation_union
@@ -769,7 +766,7 @@ struct linear_areal
void apply(Result & res,
TurnIt first, TurnIt last,
Geometry const& geometry,
OtherGeometry const& other_geometry,
OtherGeometry const& /*other_geometry*/,
BoundaryChecker const& boundary_checker)
{
//BOOST_ASSERT( first != last );
@@ -966,7 +963,7 @@ struct linear_areal
for ( TurnIt it = first ; it != last ; ++it )
{
analyser.apply(res, first, it, last,
analyser.apply(res, it,
geometry, other_geometry,
boundary_checker);

View File

@@ -257,15 +257,12 @@ struct linear_linear
typename OtherGeometry,
typename BoundaryChecker,
typename OtherBoundaryChecker>
void apply(Result & res,
TurnIt first, TurnIt it, TurnIt last,
void apply(Result & res, TurnIt it,
Geometry const& geometry,
OtherGeometry const& other_geometry,
BoundaryChecker const& boundary_checker,
OtherBoundaryChecker const& other_boundary_checker)
{
//BOOST_ASSERT( it != last );
overlay::operation_type op = it->operations[op_id].operation;
segment_identifier const& seg_id = it->operations[op_id].seg_id;
@@ -563,7 +560,7 @@ struct linear_linear
Geometry const& geometry,
OtherGeometry const& /*other_geometry*/,
BoundaryChecker const& boundary_checker,
OtherBoundaryChecker const& other_boundary_checker)
OtherBoundaryChecker const& /*other_boundary_checker*/)
{
//BOOST_ASSERT( first != last );
@@ -621,7 +618,7 @@ struct linear_linear
Geometry const& geometry,
OtherGeometry const& other_geometry,
BoundaryChecker const& boundary_checker,
OtherBoundaryChecker const& other_boundary_checker,
OtherBoundaryChecker const& /*other_boundary_checker*/,
bool first_in_range)
{
typename detail::single_geometry_return_type<Geometry const>::type
@@ -747,7 +744,7 @@ struct linear_linear
for ( TurnIt it = first ; it != last ; ++it )
{
analyser.apply(res, first, it, last,
analyser.apply(res, it,
geometry, other_geometry,
boundary_checker, other_boundary_checker);

View File

@@ -823,7 +823,7 @@ template <typename Last, char D, field F1, field F2>
struct static_may_update_sequence<Last, Last, D, F1, F2>
{
template <typename Matrix>
static inline bool apply(Matrix const& matrix)
static inline bool apply(Matrix const& /*matrix*/)
{
return false;
}
@@ -911,7 +911,7 @@ struct static_check_dispatch
return el == mask_el;
}
// else
static inline bool apply_dispatch(char el, integral_constant<int, 3>)
static inline bool apply_dispatch(char /*el*/, integral_constant<int, 3>)
{
return true;
}
@@ -943,7 +943,7 @@ template <typename Last>
struct static_check_sequence<Last, Last>
{
template <typename Matrix>
static inline bool apply(Matrix const& matrix)
static inline bool apply(Matrix const& /*matrix*/)
{
return false;
}

View File

@@ -37,15 +37,17 @@ namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within {
// TODO: is this needed?
inline int check_result_type(int result)
{
return result;
}
template <typename T>
inline void check_result_type(T result)
inline T check_result_type(T result)
{
BOOST_ASSERT(false);
return result;
}
template <typename Point, typename Range, typename Strategy> inline

View File

@@ -54,7 +54,7 @@ struct fe_point_per_point
struct fe_point_per_segment
{
template <typename Point, typename Functor>
static inline void apply(Point& , Functor& f)
static inline void apply(Point& , Functor& /*f*/)
{
// TODO: if non-const, we should extract the points from the segment
// and call the functor on those two points

View File

@@ -125,7 +125,12 @@ class plusmin_policy
//negative = true;
typedef typename geometry::point_type<Geometry2>::type point_type;
typedef overlay::turn_info<point_type> turn_info;
typedef overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, RescalePolicy>::type
> turn_info;
std::deque<turn_info> turns;
// Get (and stop on) any intersection

View File

@@ -294,7 +294,7 @@ private:
inline static
subtree_elements_counts calculate_subtree_elements_counts(std::size_t elements_count, parameters_type const& parameters, size_type & leafs_level)
{
(void)parameters;
boost::ignore_unused_variable_warning(parameters);
subtree_elements_counts res(1, 1);
leafs_level = 0;

View File

@@ -11,6 +11,8 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
namespace utilities {
@@ -26,8 +28,16 @@ struct gl_draw_point<Point, 2>
{
static inline void apply(Point const& p, typename coordinate_type<Point>::type z)
{
glBegin(GL_POINT);
glVertex3f(geometry::get<0>(p), geometry::get<1>(p), z);
typename coordinate_type<Point>::type const& x = geometry::get<0>(p);
typename coordinate_type<Point>::type const& y = geometry::get<1>(p);
/*glBegin(GL_POINT);
glVertex3f(x, y, z);
glEnd();*/
glBegin(GL_QUADS);
glVertex3f(x+1, y, z);
glVertex3f(x, y+1, z);
glVertex3f(x-1, y, z);
glVertex3f(x, y-1, z);
glEnd();
}
};
@@ -50,32 +60,42 @@ struct gl_draw_box<Box, 2>
}
};
template <typename Segment, size_t Dimension>
struct gl_draw_segment
{};
template <typename Segment>
struct gl_draw_segment<Segment, 2>
{
static inline void apply(Segment const& s, typename coordinate_type<Segment>::type z)
{
glBegin(GL_LINES);
glVertex3f(geometry::get<0, 0>(s), geometry::get<0, 1>(s), z);
glVertex3f(geometry::get<1, 0>(s), geometry::get<1, 1>(s), z);
glEnd();
}
};
template <typename Indexable, typename Tag>
struct gl_draw_indexable
{
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
};
template <typename Indexable>
struct gl_draw_indexable<Indexable, box_tag>
{
static const size_t dimension = geometry::dimension<Indexable>::value;
template <typename Box>
struct gl_draw_indexable<Box, box_tag>
: gl_draw_box<Box, geometry::dimension<Box>::value>
{};
static inline void apply(Indexable const& i, typename coordinate_type<Indexable>::type z)
{
gl_draw_box<Indexable, dimension>::apply(i, z);
}
};
template <typename Point>
struct gl_draw_indexable<Point, point_tag>
: gl_draw_point<Point, geometry::dimension<Point>::value>
{};
template <typename Indexable>
struct gl_draw_indexable<Indexable, point_tag>
{
static const size_t dimension = geometry::dimension<Indexable>::value;
static inline void apply(Indexable const& i, typename coordinate_type<Indexable>::type z)
{
gl_draw_point<Indexable, dimension>::apply(i, z);
}
};
template <typename Segment>
struct gl_draw_indexable<Segment, segment_tag>
: gl_draw_segment<Segment, geometry::dimension<Segment>::value>
{};
} // namespace dispatch

View File

@@ -66,6 +66,7 @@ struct print_corner<Box, Corner, 1>
template <typename Indexable, typename Tag>
struct print_indexable
{
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
};
template <typename Indexable>
@@ -96,6 +97,21 @@ struct print_indexable<Indexable, point_tag>
}
};
template <typename Indexable>
struct print_indexable<Indexable, segment_tag>
{
static const size_t dimension = geometry::dimension<Indexable>::value;
static inline void apply(std::ostream &os, Indexable const& i)
{
os << '(';
print_corner<Indexable, 0, dimension>::apply(os, i);
os << ")-(";
print_corner<Indexable, 1, dimension>::apply(os, i);
os << ')';
}
};
} // namespace dispatch
template <typename Indexable> inline

View File

@@ -662,28 +662,11 @@ struct read_wkt<segment_tag, Segment>
/*!
\brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry)
\ingroup wkt
\tparam Geometry \tparam_geometry
\param wkt string containing \ref WKT
\param geometry output geometry
\par Example:
\note It is case insensitive and can have the WKT forms "point", "point m", "point z", "point zm", "point mz"
\note Empty sequences can have forms as "LINESTRING ()" or "POLYGON(())"
Small example showing how to use read_wkt to build a point
\dontinclude doxygen_1.cpp
\skip example_from_wkt_point
\line {
\until }
\par Example:
Small example showing how to use read_wkt to build a linestring
\dontinclude doxygen_1.cpp
\skip example_from_wkt_linestring
\line {
\until }
\par Example:
Small example showing how to use read_wkt to build a polygon
\dontinclude doxygen_1.cpp
\skip example_from_wkt_polygon
\line {
\until }
\param geometry \param_geometry output geometry
\ingroup wkt
\qbk{[include reference/io/read_wkt.qbk]}
*/
template <typename Geometry>
inline void read_wkt(std::string const& wkt, Geometry& geometry)

View File

@@ -22,10 +22,8 @@
// Don't use namespace boost::geometry, to enable the library to stream custom
// geometries which are living outside the namespace boost::geometry
/*!
\brief Streams a geometry as Well-Known Text
\ingroup wkt
*/
// This is currently not documented on purpose: the Doxygen 2 QBK generator
// should be updated w.r.t. << which in the end ruins the DocBook XML
template<typename Char, typename Traits, typename Geometry>
inline std::basic_ostream<Char, Traits>& operator<<
(

View File

@@ -416,13 +416,10 @@ private:
/*!
\brief Main WKT-streaming function
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\ingroup wkt
\par Example:
Small example showing how to use the wkt helper function
\dontinclude doxygen_1.cpp
\skip example_as_wkt_vector
\line {
\until }
\qbk{[include reference/io/wkt.qbk]}
*/
template <typename Geometry>
inline wkt_manipulator<Geometry> wkt(Geometry const& geometry)

View File

@@ -1,7 +1,7 @@
// Boost.Geometry Index
// Additional tests
// OpenGL visualization
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -26,29 +26,172 @@
#include <boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp>
#include <boost/geometry/index/detail/rtree/utilities/statistics.hpp>
#include <boost/variant.hpp>
#define ENABLE_POINTS_AND_SEGMENTS
namespace bg = boost::geometry;
namespace bgi = bg::index;
// used types
typedef bg::model::point<float, 2, boost::geometry::cs::cartesian> P;
typedef bg::model::box<P> B;
//bgi::rtree<B> t(2, 1);
typedef bg::model::linestring<P> LS;
typedef bg::model::segment<P> S;
typedef bg::model::ring<P> R;
typedef bg::model::polygon<P> Poly;
typedef bg::model::multi_polygon<Poly> MPoly;
typedef bgi::rtree<
B,
bgi::rstar<4, 2>
> RTree;
RTree t;
std::vector<B> vect;
// containers variant
template <typename V>
struct containers
{
containers & operator=(containers const& c)
{
tree = c.tree;
values = c.values;
result = c.result;
return *this;
}
bgi::rtree< V, bgi::rstar<4, 2> > tree;
std::vector<V> values;
std::vector<V> result;
};
boost::variant<
containers<B>
#ifdef ENABLE_POINTS_AND_SEGMENTS
, containers<P>
, containers<S>
#endif
> cont;
// visitors
template <typename Pred>
struct query_v : boost::static_visitor<size_t>
{
Pred m_pred;
query_v(Pred const& pred) : m_pred(pred) {}
template <typename C>
size_t operator()(C & c) const
{
c.result.clear();
return c.tree.query(m_pred, std::back_inserter(c.result));
}
};
template <typename Cont, typename Pred>
inline size_t query(Cont & cont, Pred const& pred)
{
return boost::apply_visitor(query_v<Pred>(pred), cont);
}
struct print_result_v : boost::static_visitor<>
{
template <typename C>
void operator()(C & c) const
{
for ( size_t i = 0 ; i < c.result.size() ; ++i )
{
bgi::detail::utilities::print_indexable(std::cout, c.result[i]);
std::cout << '\n';
}
}
};
template <typename Cont>
inline void print_result(Cont const& cont)
{
boost::apply_visitor(print_result_v(), cont);
}
struct bounds_v : boost::static_visitor<B>
{
template <typename C>
B operator()(C & c) const
{
return c.tree.bounds();
}
};
template <typename Cont>
inline B bounds(Cont const& cont)
{
return boost::apply_visitor(bounds_v(), cont);
}
struct depth_v : boost::static_visitor<size_t>
{
template <typename C>
size_t operator()(C & c) const
{
return get(c.tree);
}
template <typename RTree>
static size_t get(RTree const& t)
{
return bgi::detail::rtree::utilities::view<RTree>(t).depth();
}
};
template <typename Cont>
inline size_t depth(Cont const& cont)
{
return boost::apply_visitor(depth_v(), cont);
}
struct draw_tree_v : boost::static_visitor<>
{
template <typename C>
void operator()(C & c) const
{
bgi::detail::rtree::utilities::gl_draw(c.tree);
}
};
template <typename Cont>
inline void draw_tree(Cont const& cont)
{
return boost::apply_visitor(draw_tree_v(), cont);
}
struct draw_result_v : boost::static_visitor<>
{
template <typename C>
void operator()(C & c) const
{
for ( size_t i = 0 ; i < c.result.size() ; ++i )
{
bgi::detail::utilities::gl_draw_indexable(c.result[i], depth_v::get(c.tree));
}
}
};
template <typename Cont>
inline void draw_result(Cont const& cont)
{
return boost::apply_visitor(draw_result_v(), cont);
}
struct print_tree_v : boost::static_visitor<>
{
template <typename C>
void operator()(C & c) const
{
bgi::detail::rtree::utilities::print(std::cout, c.tree);
}
};
template <typename Cont>
inline void print_tree(Cont const& cont)
{
return boost::apply_visitor(print_tree_v(), cont);
}
// globals used in querying
size_t found_count = 0;
P search_point;
size_t count = 5;
std::vector<B> nearest_boxes;
P search_point;
B search_box;
R search_ring;
Poly search_poly;
@@ -58,38 +201,73 @@ LS search_linestring;
LS search_path;
enum query_mode_type {
qm_knn, qm_c, qm_d, qm_i, qm_o, qm_w, qm_nc, qm_nd, qm_ni, qm_no, qm_nw, qm_all, qm_ri, qm_pi, qm_mpi, qm_si, qm_lsi, qm_path
qm_knn, qm_knnb, qm_knns, qm_c, qm_d, qm_i, qm_o, qm_w, qm_nc, qm_nd, qm_ni, qm_no, qm_nw, qm_all, qm_ri, qm_pi, qm_mpi, qm_si, qm_lsi, qm_path
} query_mode = qm_knn;
bool search_valid = false;
// various queries
void query_knn()
{
float x = ( rand() % 1000 ) / 10.0f;
float y = ( rand() % 1000 ) / 10.0f;
search_point = P(x, y);
nearest_boxes.clear();
found_count = t.query(
bgi::nearest(search_point, count),
std::back_inserter(nearest_boxes)
);
if ( query_mode == qm_knn )
{
search_point = P(x, y);
found_count = query(cont, bgi::nearest(search_point, count));
}
else if ( query_mode == qm_knnb )
{
float w = 2 + ( rand() % 1000 ) / 500.0f;
float h = 2 + ( rand() % 1000 ) / 500.0f;
search_box = B(P(x - w, y - h), P(x + w, y + h));
found_count = query(cont, bgi::nearest(search_box, count));
}
else if ( query_mode == qm_knns )
{
int signx = rand() % 2 ? 1 : -1;
int signy = rand() % 2 ? 1 : -1;
float w = (10 + ( rand() % 1000 ) / 100.0f) * signx;
float h = (10 + ( rand() % 1000 ) / 100.0f) * signy;
search_segment = S(P(x - w, y - h), P(x + w, y + h));
found_count = query(cont, bgi::nearest(search_segment, count));
}
else
{
BOOST_ASSERT(false);
}
if ( found_count > 0 )
{
std::cout << "search point: ";
bgi::detail::utilities::print_indexable(std::cout, search_point);
std::cout << "\nfound: ";
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
if ( query_mode == qm_knn )
{
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
std::cout << '\n';
std::cout << "search point: ";
bgi::detail::utilities::print_indexable(std::cout, search_point);
}
else if ( query_mode == qm_knnb )
{
std::cout << "search box: ";
bgi::detail::utilities::print_indexable(std::cout, search_box);
}
else if ( query_mode == qm_knns )
{
std::cout << "search segment: ";
bgi::detail::utilities::print_indexable(std::cout, search_segment);
}
else
{
BOOST_ASSERT(false);
}
std::cout << "\nfound: ";
print_result(cont);
}
else
std::cout << "nearest not found\n";
}
#ifndef ENABLE_POINTS_AND_SEGMENTS
void query_path()
{
float x = ( rand() % 1000 ) / 10.0f;
@@ -105,11 +283,7 @@ void query_path()
search_path[2 * i + 1] = P(x+w, yy);
}
nearest_boxes.clear();
found_count = t.query(
bgi::detail::path<LS>(search_path, count),
std::back_inserter(nearest_boxes)
);
found_count = query(cont, bgi::detail::path<LS>(search_path, count));
if ( found_count > 0 )
{
@@ -117,15 +291,12 @@ void query_path()
BOOST_FOREACH(P const& p, search_path)
bgi::detail::utilities::print_indexable(std::cout, p);
std::cout << "\nfound: ";
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
{
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
std::cout << '\n';
}
print_result(cont);
}
else
std::cout << "values on path not found\n";
}
#endif
template <typename Predicate>
void query()
@@ -138,26 +309,20 @@ void query()
float h = 10 + ( rand() % 1000 ) / 100.0f;
search_box = B(P(x - w, y - h), P(x + w, y + h));
nearest_boxes.clear();
found_count = t.query(Predicate(search_box), std::back_inserter(nearest_boxes) );
}
else
{
search_box = t.bounds();
nearest_boxes.clear();
found_count = t.query(Predicate(search_box), std::back_inserter(nearest_boxes) );
search_box = bounds(cont);
}
found_count = query(cont, Predicate(search_box));
if ( found_count > 0 )
{
std::cout << "search box: ";
bgi::detail::utilities::print_indexable(std::cout, search_box);
std::cout << "\nfound: ";
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
{
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
std::cout << '\n';
}
print_result(cont);
}
else
std::cout << "boxes not found\n";
@@ -190,8 +355,7 @@ void query_ring()
search_ring.push_back(P(x - w, y - h/2));
search_ring.push_back(P(x - w, y - h));
nearest_boxes.clear();
found_count = t.query(Predicate(search_ring), std::back_inserter(nearest_boxes) );
found_count = query(cont, Predicate(search_ring));
if ( found_count > 0 )
{
@@ -202,11 +366,7 @@ void query_ring()
std::cout << ' ';
}
std::cout << "\nfound: ";
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
{
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
std::cout << '\n';
}
print_result(cont);
}
else
std::cout << "boxes not found\n";
@@ -246,8 +406,7 @@ void query_poly()
search_poly.inners()[0].push_back(P(x - w/2, y + h/2));
search_poly.inners()[0].push_back(P(x - w/2, y - h/2));
nearest_boxes.clear();
found_count = t.query(Predicate(search_poly), std::back_inserter(nearest_boxes) );
found_count = query(cont, Predicate(search_poly));
if ( found_count > 0 )
{
@@ -258,11 +417,7 @@ void query_poly()
std::cout << ' ';
}
std::cout << "\nfound: ";
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
{
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
std::cout << '\n';
}
print_result(cont);
}
else
std::cout << "boxes not found\n";
@@ -318,9 +473,8 @@ void query_multi_poly()
search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 2*h));
search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 6*h/5));
nearest_boxes.clear();
found_count = t.query(Predicate(search_multi_poly), std::back_inserter(nearest_boxes) );
found_count = query(cont, Predicate(search_multi_poly));
if ( found_count > 0 )
{
std::cout << "search multi_poly[0] outer: ";
@@ -330,11 +484,7 @@ void query_multi_poly()
std::cout << ' ';
}
std::cout << "\nfound: ";
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
{
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
std::cout << '\n';
}
print_result(cont);
}
else
std::cout << "boxes not found\n";
@@ -355,9 +505,8 @@ void query_segment()
boost::geometry::set<1, 0>(search_segment, x + w);
boost::geometry::set<1, 1>(search_segment, y + h);
nearest_boxes.clear();
found_count = t.query(Predicate(search_segment), std::back_inserter(nearest_boxes) );
found_count = query(cont, Predicate(search_segment));
if ( found_count > 0 )
{
std::cout << "search segment: ";
@@ -365,11 +514,7 @@ void query_segment()
bgi::detail::utilities::print_indexable(std::cout, P(x+w, y+h));
std::cout << "\nfound: ";
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
{
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
std::cout << '\n';
}
print_result(cont);
}
else
std::cout << "boxes not found\n";
@@ -393,9 +538,8 @@ void query_linestring()
search_linestring.push_back(P(xx, yy));
}
nearest_boxes.clear();
found_count = t.query(Predicate(search_linestring), std::back_inserter(nearest_boxes) );
found_count = query(cont, Predicate(search_linestring));
if ( found_count > 0 )
{
std::cout << "search linestring: ";
@@ -405,44 +549,46 @@ void query_linestring()
std::cout << ' ';
}
std::cout << "\nfound: ";
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
{
bgi::detail::utilities::print_indexable(std::cout, nearest_boxes[i]);
std::cout << '\n';
}
print_result(cont);
}
else
std::cout << "boxes not found\n";
}
// the function running the correct query based on the query_mode
void search()
{
namespace d = bgi::detail;
if ( query_mode == qm_knn )
if ( query_mode == qm_knn || query_mode == qm_knnb || query_mode == qm_knns )
query_knn();
else if ( query_mode == qm_c )
query< d::spatial_predicate<B, d::covered_by_tag, false> >();
else if ( query_mode == qm_d )
query< d::spatial_predicate<B, d::disjoint_tag, false> >();
else if ( query_mode == qm_i )
query< d::spatial_predicate<B, d::intersects_tag, false> >();
else if ( query_mode == qm_nd )
query< d::spatial_predicate<B, d::disjoint_tag, true> >();
else if ( query_mode == qm_ni )
query< d::spatial_predicate<B, d::intersects_tag, true> >();
else if ( query_mode == qm_all )
query< d::spatial_predicate<B, d::intersects_tag, false> >();
#ifdef ENABLE_POINTS_AND_SEGMENTS
else
std::cout << "query disabled\n";
#else
else if ( query_mode == qm_c )
query< d::spatial_predicate<B, d::covered_by_tag, false> >();
else if ( query_mode == qm_o )
query< d::spatial_predicate<B, d::overlaps_tag, false> >();
else if ( query_mode == qm_w )
query< d::spatial_predicate<B, d::within_tag, false> >();
else if ( query_mode == qm_nc )
query< d::spatial_predicate<B, d::covered_by_tag, true> >();
else if ( query_mode == qm_nd )
query< d::spatial_predicate<B, d::disjoint_tag, true> >();
else if ( query_mode == qm_ni )
query< d::spatial_predicate<B, d::intersects_tag, true> >();
else if ( query_mode == qm_no )
query< d::spatial_predicate<B, d::overlaps_tag, true> >();
else if ( query_mode == qm_nw )
query< d::spatial_predicate<B, d::within_tag, true> >();
else if ( query_mode == qm_all )
query< d::spatial_predicate<B, d::intersects_tag, false> >();
else if ( query_mode == qm_ri )
query_ring< d::spatial_predicate<R, d::intersects_tag, false> >();
else if ( query_mode == qm_pi )
@@ -455,22 +601,34 @@ void search()
query_linestring< d::spatial_predicate<LS, d::intersects_tag, false> >();
else if ( query_mode == qm_path )
query_path();
#endif
search_valid = true;
}
// various drawing functions
void draw_point(P const& p)
{
float x = boost::geometry::get<0>(p);
float y = boost::geometry::get<1>(p);
float z = depth(cont);
glBegin(GL_QUADS);
glVertex3f(x+1, y, z);
glVertex3f(x, y+1, z);
glVertex3f(x-1, y, z);
glVertex3f(x, y-1, z);
glEnd();
}
void draw_knn_area(float min_distance, float max_distance)
{
float x = boost::geometry::get<0>(search_point);
float y = boost::geometry::get<1>(search_point);
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
float z = depth(cont);
// search point
glBegin(GL_TRIANGLES);
glVertex3f(x, y, z);
glVertex3f(x + 1, y, z);
glVertex3f(x + 1, y + 1, z);
glEnd();
draw_point(search_point);
// search min circle
@@ -495,7 +653,7 @@ void draw_linestring(LS const& ls)
{
float x = boost::geometry::get<0>(p);
float y = boost::geometry::get<1>(p);
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
float z = depth(cont);
glVertex3f(x, y, z);
}
@@ -508,7 +666,7 @@ void draw_segment(S const& s)
float y1 = boost::geometry::get<0, 1>(s);
float x2 = boost::geometry::get<1, 0>(s);
float y2 = boost::geometry::get<1, 1>(s);
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
float z = depth(cont);
glBegin(GL_LINES);
glVertex3f(x1, y1, z);
@@ -523,7 +681,7 @@ void draw_box(Box const& box)
float y1 = boost::geometry::get<bg::min_corner, 1>(box);
float x2 = boost::geometry::get<bg::max_corner, 0>(box);
float y2 = boost::geometry::get<bg::max_corner, 1>(box);
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
float z = depth(cont);
// search box
glBegin(GL_LINE_LOOP);
@@ -537,7 +695,7 @@ void draw_box(Box const& box)
template <typename Range>
void draw_ring(Range const& range)
{
float z = bgi::detail::rtree::utilities::view<RTree>(t).depth();
float z = depth(cont);
// search box
glBegin(GL_LINE_LOOP);
@@ -567,18 +725,24 @@ void draw_multi_polygon(MultiPolygon const& multi_polygon)
draw_polygon(p);
}
// render the scene -> tree, if searching data available also the query geometry and result
void render_scene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
bgi::detail::rtree::utilities::gl_draw(t);
draw_tree(cont);
if ( search_valid )
{
glColor3f(1.0f, 0.5f, 0.0f);
glColor3f(1.0f, 0.25f, 0.0f);
if ( query_mode == qm_knn )
draw_knn_area(0, 0);
else if ( query_mode == qm_knnb )
draw_box(search_box);
else if ( query_mode == qm_knns )
draw_segment(search_segment);
else if ( query_mode == qm_ri )
draw_ring(search_ring);
else if ( query_mode == qm_pi )
@@ -594,10 +758,9 @@ void render_scene(void)
else
draw_box(search_box);
for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i )
bgi::detail::utilities::gl_draw_indexable(
nearest_boxes[i],
bgi::detail::rtree::utilities::view<RTree>(t).depth());
glColor3f(1.0f, 0.5f, 0.0f);
draw_result(cont);
}
glFlush();
@@ -634,49 +797,100 @@ void resize(int w, int h)
srand(1);
}
// randomize various indexables
inline void rand_val(B & b)
{
float x = ( rand() % 100 );
float y = ( rand() % 100 );
float w = ( rand() % 2 ) + 1;
float h = ( rand() % 2 ) + 1;
b = B(P(x - w, y - h),P(x + w, y + h));
}
inline void rand_val(P & p)
{
float x = ( rand() % 100 );
float y = ( rand() % 100 );
p = P(x, y);
}
inline void rand_val(S & s)
{
float x = ( rand() % 100 );
float y = ( rand() % 100 );
float w = ( rand() % 2 + 1) * (rand() % 2 ? 1.0f : -1.0f);
float h = ( rand() % 2 + 1) * (rand() % 2 ? 1.0f : -1.0f);
s = S(P(x - w, y - h),P(x + w, y + h));
}
// more higher-level visitors
struct insert_random_value_v : boost::static_visitor<>
{
template <typename V>
void operator()(containers<V> & c) const
{
V v;
rand_val(v);
boost::geometry::index::insert(c.tree, v);
c.values.push_back(v);
std::cout << "inserted: ";
bgi::detail::utilities::print_indexable(std::cout, v);
std::cout << '\n';
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
std::cout << "\n";
}
};
template <typename Cont>
inline void insert_random_value(Cont & cont)
{
return boost::apply_visitor(insert_random_value_v(), cont);
}
struct remove_random_value_v : boost::static_visitor<>
{
template <typename V>
void operator()(containers<V> & c) const
{
if ( c.values.empty() )
return;
size_t i = rand() % c.values.size();
V v = c.values[i];
c.tree.remove(v);
c.values.erase(c.values.begin() + i);
std::cout << "removed: ";
bgi::detail::utilities::print_indexable(std::cout, v);
std::cout << '\n';
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
std::cout << "\n";
}
};
template <typename Cont>
inline void remove_random_value(Cont & cont)
{
return boost::apply_visitor(remove_random_value_v(), cont);
}
// handle mouse input
void mouse(int button, int state, int /*x*/, int /*y*/)
{
if ( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
{
float x = ( rand() % 100 );
float y = ( rand() % 100 );
float w = ( rand() % 2 ) + 1;
float h = ( rand() % 2 ) + 1;
B b(P(x - w, y - h),P(x + w, y + h));
boost::geometry::index::insert(t, b);
vect.push_back(b);
std::cout << "inserted: ";
bgi::detail::utilities::print_indexable(std::cout, b);
std::cout << '\n';
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" );
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" );
std::cout << "\n";
insert_random_value(cont);
search_valid = false;
}
else if ( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
{
if ( vect.empty() )
return;
size_t i = rand() % vect.size();
B b = vect[i];
bgi::remove(t, b);
vect.erase(vect.begin() + i);
std::cout << "removed: ";
bgi::detail::utilities::print_indexable(std::cout, b);
std::cout << '\n';
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" );
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" );
std::cout << "\n";
remove_random_value(cont);
search_valid = false;
}
else if ( button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN )
@@ -687,71 +901,117 @@ void mouse(int button, int state, int /*x*/, int /*y*/)
glutPostRedisplay();
}
// more higher-level visitors
struct insert_random_values_v : boost::static_visitor<>
{
template <typename V>
void operator()(containers<V> & c) const
{
for ( size_t i = 0 ; i < 35 ; ++i )
{
V v;
rand_val(v);
c.tree.insert(v);
c.values.push_back(v);
std::cout << "inserted: ";
bgi::detail::utilities::print_indexable(std::cout, v);
std::cout << '\n';
}
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
std::cout << "\n";
}
};
template <typename Cont>
inline void insert_random_values(Cont & cont)
{
return boost::apply_visitor(insert_random_values_v(), cont);
}
struct bulk_insert_random_values_v : boost::static_visitor<>
{
template <typename V>
void operator()(containers<V> & c) const
{
c.values.clear();
for ( size_t i = 0 ; i < 35 ; ++i )
{
V v;
rand_val(v);
c.values.push_back(v);
std::cout << "inserted: ";
bgi::detail::utilities::print_indexable(std::cout, v);
std::cout << '\n';
}
create(c.tree, c.values);
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
std::cout << "\n";
}
template <typename Tree, typename Values>
void create(Tree & tree, Values const& values) const
{
Tree t(values);
tree = boost::move(t);
}
};
template <typename Cont>
inline void bulk_insert_random_values(Cont & cont)
{
return boost::apply_visitor(bulk_insert_random_values_v(), cont);
}
// handle keyboard input
std::string current_line;
void keyboard(unsigned char key, int /*x*/, int /*y*/)
{
if ( key == '\r' || key == '\n' )
{
if ( current_line == "t" )
if ( current_line == "storeb" )
{
cont = containers<B>();
glutPostRedisplay();
}
#ifdef ENABLE_POINTS_AND_SEGMENTS
else if ( current_line == "storep" )
{
cont = containers<P>();
glutPostRedisplay();
}
else if ( current_line == "stores" )
{
cont = containers<S>();
glutPostRedisplay();
}
#endif
else if ( current_line == "t" )
{
std::cout << "\n";
bgi::detail::rtree::utilities::print(std::cout, t);
print_tree(cont);
std::cout << "\n";
}
else if ( current_line == "rand" )
{
for ( size_t i = 0 ; i < 35 ; ++i )
{
float x = ( rand() % 100 );
float y = ( rand() % 100 );
float w = ( rand() % 2 ) + 1;
float h = ( rand() % 2 ) + 1;
B b(P(x - w, y - h),P(x + w, y + h));
boost::geometry::index::insert(t, b);
vect.push_back(b);
std::cout << "inserted: ";
bgi::detail::utilities::print_indexable(std::cout, b);
std::cout << '\n';
}
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" );
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" );
std::cout << "\n";
insert_random_values(cont);
search_valid = false;
glutPostRedisplay();
}
else if ( current_line == "bulk" )
{
vect.clear();
for ( size_t i = 0 ; i < 35 ; ++i )
{
float x = ( rand() % 100 );
float y = ( rand() % 100 );
float w = ( rand() % 2 ) + 1;
float h = ( rand() % 2 ) + 1;
B b(P(x - w, y - h),P(x + w, y + h));
vect.push_back(b);
std::cout << "inserted: ";
bgi::detail::utilities::print_indexable(std::cout, b);
std::cout << '\n';
}
RTree t2(vect);
t = boost::move(t2);
std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(t) ? "boxes OK\n" : "WRONG BOXES!\n" );
std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(t) ? "levels OK\n" : "WRONG LEVELS!\n" );
std::cout << "\n";
bulk_insert_random_values(cont);
search_valid = false;
glutPostRedisplay();
@@ -760,6 +1020,10 @@ void keyboard(unsigned char key, int /*x*/, int /*y*/)
{
if ( current_line == "knn" )
query_mode = qm_knn;
else if ( current_line == "knnb" )
query_mode = qm_knnb;
else if ( current_line == "knns" )
query_mode = qm_knns;
else if ( current_line == "c" )
query_mode = qm_c;
else if ( current_line == "d" )
@@ -809,6 +1073,8 @@ void keyboard(unsigned char key, int /*x*/, int /*y*/)
}
}
// main function
int main(int argc, char **argv)
{
glutInit(&argc, argv);

View File

@@ -38,7 +38,7 @@ void check_geometry(Geometry const& geometry, std::string const& expected)
}
template <typename Geometry, typename Points>
void check_assign_points(Points const& points, std::string const& expected)
void check_assign_points(Points const& points, std::string const& /*expected*/)
{
Geometry geometry;
bg::assign_points(geometry, points);

View File

@@ -226,6 +226,16 @@ void test_distance_segment_box(Strategy const& strategy)
typedef test_distance_of_geometries<B, S> tester;
typedef test_distance_of_geometries<B, IS> itester;
// 1st example by Adam Wulkiewicz
tester::apply("BOX(5 51,42 96)",
"SEGMENT(6.6799994 95.260002,35.119999 56.340004)",
0, 0, strategy);
// 2nd example by Adam Wulkiewicz
tester::apply("BOX(51 55,94 100)",
"SEGMENT(92.439995 50.130001,59.959999 80.870003)",
0, 0, strategy);
// segments that intersect the box
tester::apply("box(0 0,1 1)",
"segment(-1 0.5,0.5 0.75)",

View File

@@ -27,7 +27,7 @@
template <typename Geometry, typename Hull>
void check_convex_hull(Geometry const& geometry, Hull const& hull,
std::size_t size_original, std::size_t size_hull,
std::size_t /*size_original*/, std::size_t size_hull,
double expected_area, bool reverse)
{
std::size_t n = bg::num_points(hull);

View File

@@ -426,6 +426,146 @@ struct test_distance_of_geometries
}
};
//========================================================================
template <typename Box, typename Segment>
struct test_distance_of_geometries
<
Box, Segment,
94 /* box */, 92 /* segment */
>
{
template
<
typename DistanceType,
typename ComparableDistanceType,
typename Strategy
>
static inline
void apply(std::string const& wkt_box,
std::string const& wkt_segment,
DistanceType const& expected_distance,
ComparableDistanceType const& expected_comparable_distance,
Strategy const& strategy)
{
test_distance_of_geometries
<
Segment, Box, 92, 94
>::apply(wkt_segment,
wkt_box,
expected_distance,
expected_comparable_distance,
strategy);
}
};
template <typename Segment, typename Box>
struct test_distance_of_geometries
<
Segment, Box,
92 /* segment */, 94 /* box */
>
: public test_distance_of_geometries<Segment, Box, 0, 0>
{
typedef test_distance_of_geometries<Segment, Box, 0, 0> base;
template
<
typename DistanceType,
typename ComparableDistanceType,
typename Strategy
>
static inline
void apply(std::string const& wkt_segment,
std::string const& wkt_box,
DistanceType const& expected_distance,
ComparableDistanceType const& expected_comparable_distance,
Strategy const& strategy)
{
Segment segment = from_wkt<Segment>(wkt_segment);
Box box = from_wkt<Box>(wkt_box);
apply(segment,
box,
expected_distance,
expected_comparable_distance,
strategy);
}
template
<
typename DistanceType,
typename ComparableDistanceType,
typename Strategy
>
static inline
void apply(Segment const& segment,
Box const& box,
DistanceType const& expected_distance,
ComparableDistanceType const& expected_comparable_distance,
Strategy const& strategy)
{
typedef typename bg::strategy::distance::services::return_type
<
Strategy, Segment, Box
>::type distance_result_type;
typedef typename bg::strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename bg::strategy::distance::services::return_type
<
comparable_strategy, Segment, Box
>::type comparable_distance_result_type;
base::apply(segment, box, expected_distance,
expected_comparable_distance, strategy);
comparable_strategy cstrategy =
bg::strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
distance_result_type distance_generic =
bg::detail::distance::segment_to_box_2D_generic
<
Segment, Box, Strategy
>::apply(segment, box, strategy);
comparable_distance_result_type comparable_distance_generic =
bg::detail::distance::segment_to_box_2D_generic
<
Segment, Box, comparable_strategy
>::apply(segment, box, cstrategy);
check_equal
<
distance_result_type
>::apply(distance_generic, expected_distance);
check_equal
<
comparable_distance_result_type
>::apply(comparable_distance_generic, expected_comparable_distance);
#ifdef GEOMETRY_TEST_DEBUG
std::cout << "... testing with naive seg-box distance algorithm..."
<< std::endl;
std::cout << "distance (generic algorithm) = "
<< distance_generic << " ; "
<< "comp. distance (generic algorithm) = "
<< comparable_distance_generic
<< std::endl;
std::cout << std::endl << std::endl;
#endif
}
};
//========================================================================

View File

@@ -36,8 +36,8 @@ struct check_result<Box, 2>
ctype
>::type type;
static void apply(Box const& b, const type& x1, const type& y1, const type& z1,
const type& x2, const type& y2, const type& z2)
static void apply(Box const& b, const type& x1, const type& y1, const type& /*z1*/,
const type& x2, const type& y2, const type& /*z2*/)
{
BOOST_CHECK_CLOSE((bg::get<bg::min_corner, 0>(b)), x1, 0.001);
BOOST_CHECK_CLOSE((bg::get<bg::min_corner, 1>(b)), y1, 0.001);

View File

@@ -44,7 +44,9 @@ void test_geometry(std::string const& wkt, double expected_length)
Geometry geometry;
bg::read_wkt(wkt, geometry);
test_length(geometry, expected_length);
#if !defined(GEOMETRY_TEST_DEBUG)
test_length(boost::variant<Geometry>(geometry), expected_length);
#endif
}
template <typename Geometry>

View File

@@ -29,7 +29,7 @@ void test_perimeter(Geometry const& geometry, long double expected_perimeter)
std::ostringstream out;
out << typeid(typename bg::coordinate_type<Geometry>::type).name()
<< std::endl
<< typeid(typename bg::perimeter_result<Geometry>::type).name()
<< typeid(typename bg::default_length_result<Geometry>::type).name()
<< std::endl
<< "perimeter : " << bg::perimeter(geometry)
<< std::endl;
@@ -48,7 +48,9 @@ void test_geometry(std::string const& wkt, double expected_perimeter)
boost::variant<Geometry> v(geometry);
test_perimeter(geometry, expected_perimeter);
#if !defined(GEOMETRY_TEST_DEBUG)
test_perimeter(v, expected_perimeter);
#endif
}
template <typename Geometry>