Merge branch 'prepare'

This commit is contained in:
Barend Gehrels
2014-10-24 16:03:05 +02:00
18 changed files with 857 additions and 432 deletions

View File

@@ -22,6 +22,8 @@
[*Improvements]
* The support of parameters convertible to value_type in rtree insert(), remove() and count() functions
* Support for counterclockwise input/output in algorithm buffer
* Support for degenerate input in algorithm buffer
[*Solved tickets]

View File

@@ -29,6 +29,8 @@
#include <boost/geometry/algorithms/simplify.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
#if defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX)
#include <boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp>
#endif
@@ -87,6 +89,13 @@ inline void simplify_input(Range const& range,
geometry::simplify(range, simplified, max_distance, strategy);
#endif
if (boost::size(simplified) == 2
&& geometry::equals(geometry::range::front(simplified),
geometry::range::back(simplified)))
{
traits::resize<Range>::apply(simplified, 1);
}
}
@@ -202,7 +211,7 @@ struct buffer_range
typename EndStrategy,
typename RobustPolicy
>
static inline void iterate(Collection& collection,
static inline bool iterate(Collection& collection,
Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
@@ -246,6 +255,7 @@ struct buffer_range
* pup: penultimate_point
*/
bool result = false;
bool first = true;
Iterator it = begin;
@@ -259,14 +269,21 @@ struct buffer_range
{
robust_point_type robust_input;
geometry::recalculate(robust_input, *it, robust_policy);
// Check on equality - however, if input is simplified, this is highly
// unlikely (though possible by rescaling)
// Check on equality - however, if input is simplified, this is
// unlikely (though possible by rescaling or for degenerated pointlike polygons)
if (! detail::equals::equals_point_point(previous_robust_input, robust_input))
{
generated_side.clear();
side_strategy.apply(*prev, *it, side,
distance_strategy, generated_side);
if (generated_side.empty())
{
break;
}
result = true;
if (! first)
{
add_join(collection,
@@ -295,6 +312,7 @@ struct buffer_range
}
previous_robust_input = robust_input;
}
return result;
}
};
@@ -345,6 +363,26 @@ struct visit_pieces_default_policy
{}
};
template
<
typename OutputPointType,
typename Point,
typename Collection,
typename DistanceStrategy,
typename PointStrategy
>
inline void buffer_point(Point const& point, Collection& collection,
DistanceStrategy const& distance_strategy,
PointStrategy const& point_strategy)
{
collection.start_new_ring();
std::vector<OutputPointType> range_out;
point_strategy.apply(point, distance_strategy, range_out);
collection.add_piece(strategy::buffer::buffered_point, range_out, false);
collection.finish_ring();
}
}} // namespace detail::buffer
#endif // DOXYGEN_NO_DETAIL
@@ -389,13 +427,10 @@ struct buffer_inserter<point_tag, Point, RingOutput>
PointStrategy const& point_strategy,
RobustPolicy const& )
{
typedef typename point_type<RingOutput>::type output_point_type;
collection.start_new_ring();
std::vector<output_point_type> range_out;
point_strategy.apply(point, distance_strategy, range_out);
collection.add_piece(strategy::buffer::buffered_point, range_out, false);
collection.finish_ring();
detail::buffer::buffer_point
<
typename point_type<RingOutput>::type
>(point, collection, distance_strategy, point_strategy);
}
};
@@ -419,7 +454,7 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
typename EndStrategy,
typename RobustPolicy
>
static inline void iterate(Collection& collection,
static inline bool iterate(Collection& collection,
Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
@@ -432,21 +467,25 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
typedef detail::buffer::buffer_range<RingOutput> buffer_range;
buffer_range::iterate(collection, begin, end,
bool result = buffer_range::iterate(collection, begin, end,
side,
distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1, first_p2, last_p1, last_p2);
// Generate closing join
buffer_range::add_join(collection,
*(end - 2),
*(end - 1), last_p1, last_p2,
*(begin + 1), first_p1, first_p2,
side,
distance_strategy, join_strategy, end_strategy,
robust_policy);
if (result)
{
buffer_range::add_join(collection,
*(end - 2),
*(end - 1), last_p1, last_p2,
*(begin + 1), first_p1, first_p2,
side,
distance_strategy, join_strategy, end_strategy,
robust_policy);
}
// Buffer is closed automatically by last closing corner
return result;
}
template
@@ -465,30 +504,43 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& ,
PointStrategy const& point_strategy,
RobustPolicy const& robust_policy)
{
if (boost::size(ring) > 3)
{
RingOutput simplified;
detail::buffer::simplify_input(ring, distance, simplified);
RingInput simplified;
detail::buffer::simplify_input(ring, distance, simplified);
bool has_output = false;
std::size_t n = boost::size(simplified);
if (n > 3)
{
detail::normalized_view<RingInput const> view(simplified);
if (distance.negative())
{
// Walk backwards (rings will be reversed afterwards)
// It might be that this will be changed later.
// TODO: decide this.
iterate(collection, boost::rbegin(simplified), boost::rend(simplified),
has_output = iterate(collection, boost::rbegin(view), boost::rend(view),
strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy);
}
else
{
iterate(collection, boost::begin(simplified), boost::end(simplified),
has_output = iterate(collection, boost::begin(view), boost::end(view),
strategy::buffer::buffer_side_left,
distance, side_strategy, join_strategy, end_strategy, robust_policy);
}
}
if (! has_output && n >= 1)
{
// Use point_strategy to buffer degenerated ring
detail::buffer::buffer_point<output_point_type>
(
geometry::range::front(simplified),
collection, distance, point_strategy
);
}
}
};
@@ -505,19 +557,6 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
typedef typename point_type<output_ring_type>::type output_point_type;
typedef typename point_type<Linestring>::type input_point_type;
template <typename DistanceStrategy, typename SideStrategy>
static inline output_point_type first_perpendicular_point(
input_point_type const& p1, input_point_type const& p2,
DistanceStrategy const& distance_strategy,
SideStrategy const& side_strategy)
{
std::vector<output_point_type> generated_side;
side_strategy.apply(p1, p2,
strategy::buffer::buffer_side_right,
distance_strategy, generated_side);
return generated_side.front();
}
template
<
typename Collection,
@@ -528,7 +567,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
typename EndStrategy,
typename RobustPolicy
>
static inline void iterate(Collection& collection,
static inline bool iterate(Collection& collection,
Iterator begin, Iterator end,
strategy::buffer::buffer_side_selector side,
DistanceStrategy const& distance_strategy,
@@ -545,10 +584,23 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
// other side of the linestring. If it is the second pass (right),
// we have it already from the first phase (left).
// But for the first pass, we have to generate it
output_point_type reverse_p1
= side == strategy::buffer::buffer_side_right
? first_p1
: first_perpendicular_point(ultimate_point, penultimate_point, distance_strategy, side_strategy);
output_point_type reverse_p1;
if (side == strategy::buffer::buffer_side_right)
{
reverse_p1 = first_p1;
}
else
{
std::vector<output_point_type> generated_side;
side_strategy.apply(ultimate_point, penultimate_point,
strategy::buffer::buffer_side_right,
distance_strategy, generated_side);
if (generated_side.empty())
{
return false;
}
reverse_p1 = generated_side.front();
}
output_point_type first_p2, last_p1, last_p2;
@@ -560,6 +612,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
std::vector<output_point_type> range_out;
end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out);
collection.add_endcap(end_strategy, range_out, ultimate_point);
return true;
}
template
@@ -577,30 +630,41 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
SideStrategy const& side_strategy,
JoinStrategy const& join_strategy,
EndStrategy const& end_strategy,
PointStrategy const& ,
PointStrategy const& point_strategy,
RobustPolicy const& robust_policy)
{
if (boost::size(linestring) > 1)
{
Linestring simplified;
detail::buffer::simplify_input(linestring, distance, simplified);
Linestring simplified;
detail::buffer::simplify_input(linestring, distance, simplified);
bool has_output = false;
std::size_t n = boost::size(simplified);
if (n > 1)
{
collection.start_new_ring();
output_point_type first_p1;
iterate(collection, boost::begin(simplified), boost::end(simplified),
has_output = iterate(collection,
boost::begin(simplified), boost::end(simplified),
strategy::buffer::buffer_side_left,
distance, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1);
iterate(collection, boost::rbegin(simplified), boost::rend(simplified),
strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1);
if (has_output)
{
iterate(collection, boost::rbegin(simplified), boost::rend(simplified),
strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1);
}
collection.finish_ring();
}
else
if (! has_output && n >= 1)
{
// Use point_strategy to buffer degenerated linestring
detail::buffer::buffer_point<output_point_type>
(
geometry::range::front(simplified),
collection, distance, point_strategy
);
}
}
};
@@ -814,7 +878,16 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
collection.enrich();
collection.traverse();
if (distance_strategy.negative() && areal)
// Reverse all offsetted rings / traversed rings if:
// - they were generated on the negative side (deflate) of polygons
// - the output is counter clockwise
// and avoid reversing twice
bool reverse = distance_strategy.negative() && areal;
if (geometry::point_order<GeometryOutput>::value == counterclockwise)
{
reverse = ! reverse;
}
if (reverse)
{
collection.reverse();
}

View File

@@ -117,6 +117,8 @@ struct buffered_piece_collection
point_type,
RobustPolicy
>::type robust_point_type;
// Robust ring/polygon type, always clockwise
typedef geometry::model::ring<robust_point_type> robust_ring_type;
typedef geometry::model::polygon<robust_point_type> robust_polygon_type;
@@ -571,7 +573,11 @@ struct buffered_piece_collection
inline void finish_ring(bool is_interior = false)
{
BOOST_ASSERT(m_first_piece_index != -1);
if (m_first_piece_index == -1)
{
return;
}
if (m_first_piece_index < static_cast<int>(boost::size(m_pieces)))
{
// If piece was added

View File

@@ -9,8 +9,6 @@
#include <cstddef>
#include <boost/assert.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/math.hpp>
@@ -69,14 +67,19 @@ public :
// Generate a block along (left or right of) the segment
// Simulate a vector d (dx,dy)
coordinate_type dx = get<0>(input_p2) - get<0>(input_p1);
coordinate_type dy = get<1>(input_p2) - get<1>(input_p1);
coordinate_type const dx = get<0>(input_p2) - get<0>(input_p1);
coordinate_type const dy = get<1>(input_p2) - get<1>(input_p1);
// For normalization [0,1] (=dot product d.d, sqrt)
promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy);
// Because coordinates are not equal, length should not be zero
BOOST_ASSERT((! geometry::math::equals(length, 0)));
if (geometry::math::equals(length, 0))
{
// Coordinates are simplified and therefore most often not equal.
// But if simplify is skipped, or for lines with two
// equal points, length is 0 and we cannot generate output.
return;
}
// Generate the normalized perpendicular p, to the left (ccw)
promoted_type const px = -dy / length;

View File

@@ -27,6 +27,12 @@ static std::string const overlapping = "LINESTRING(0 0,4 5,7 4,10 6, 10 2,2 2)";
static std::string const curve = "LINESTRING(2 7,3 5,5 4,7 5,8 7)";
static std::string const tripod = "LINESTRING(5 0,5 5,1 8,5 5,9 8)"; // with spike
static std::string const degenerate0 = "LINESTRING()";
static std::string const degenerate1 = "LINESTRING(5 5)";
static std::string const degenerate2 = "LINESTRING(5 5,5 5)";
static std::string const degenerate3 = "LINESTRING(5 5,5 5,5 5)";
static std::string const degenerate4 = "LINESTRING(5 5,5 5,4 4,5 5,5 5)";
static std::string const for_collinear = "LINESTRING(2 0,0 0,0 4,6 4,6 0,4 0)";
static std::string const for_collinear2 = "LINESTRING(2 1,2 0,0 0,0 4,6 4,6 0,4 0,4 1)";
@@ -42,11 +48,11 @@ static std::string const aimes171 = "LINESTRING(-2.393161 52.265087,-2.393002 52
static std::string const aimes181 = "LINESTRING(-2.320686 52.43505,-2.320678 52.435016,-2.320697 52.434978,-2.3207 52.434977,-2.320741 52.434964,-2.320807 52.434964,-2.320847 52.434986,-2.320903 52.435022)";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
typedef bg::model::linestring<P> linestring;
typedef bg::model::polygon<P> polygon;
typedef bg::model::polygon<P, Clockwise> polygon;
bg::strategy::buffer::join_miter join_miter;
bg::strategy::buffer::join_round join_round(100);
@@ -133,6 +139,13 @@ void test_all()
test_one<linestring, polygon>("field_sprayer1", field_sprayer1, join_round, end_round, 718.761877, 16.5, 6.5);
test_one<linestring, polygon>("field_sprayer1", field_sprayer1, join_miter, end_round, 718.939628, 16.5, 6.5);
test_one<linestring, polygon>("degenerate0", degenerate0, join_round, end_round, 0.0, 3.0);
test_one<linestring, polygon>("degenerate1", degenerate1, join_round, end_round, 28.25, 3.0);
test_one<linestring, polygon>("degenerate2", degenerate2, join_round, end_round, 28.2503, 3.0);
test_one<linestring, polygon>("degenerate3", degenerate3, join_round, end_round, 28.2503, 3.0);
test_one<linestring, polygon>("degenerate4", degenerate4, join_round, end_round, 36.7410, 3.0);
test_one<linestring, polygon>("degenerate4", degenerate4, join_round, end_flat, 8.4853, 3.0);
double tolerance = 1.0e-10;
test_one<linestring, polygon>("aimes120", aimes120, join_miter, end_flat, 1.62669948622351512e-08, 0.000018, 0.000018, false, tolerance);
@@ -165,7 +178,8 @@ void test_all()
int test_main(int, char* [])
{
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
//test_all<bg::model::point<tt, 2, bg::cs::cartesian> >();
return 0;
}

View File

@@ -15,13 +15,19 @@ static std::string const simplex = "MULTILINESTRING((0 0,4 5),(5 4,10 0))";
static std::string const two_bends = "MULTILINESTRING((0 0,4 5,7 4,10 6),(1 5,5 9,8 6))";
static std::string const turn_inside = "MULTILINESTRING((0 0,4 5,7 4,10 6),(1 5,5 9,8 6),(0 4,-2 6))";
static std::string const degenerate0 = "MULTILINESTRING()";
static std::string const degenerate1 = "MULTILINESTRING((5 5))";
static std::string const degenerate2 = "MULTILINESTRING((5 5),(9 9))";
static std::string const degenerate3 = "MULTILINESTRING((5 5),(9 9),(4 10))";
static std::string const degenerate4 = "MULTILINESTRING((5 5,5 5),(9 9,9 9,10 10,9 9,9 9,9 9),(4 10,4 10,3 11,4 12,3 11,4 10,4 10))";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
typedef bg::model::linestring<P> linestring;
typedef bg::model::multi_linestring<linestring> multi_linestring_type;
typedef bg::model::polygon<P> polygon;
typedef bg::model::polygon<P, Clockwise> polygon;
bg::strategy::buffer::join_miter join_miter;
bg::strategy::buffer::join_round join_round(100);
@@ -49,13 +55,20 @@ void test_all()
test_one<multi_linestring_type, polygon>("two_bends", two_bends, join_round_by_divide, end_flat, 64.6217, 1.5, 1.5);
test_one<multi_linestring_type, polygon>("two_bends", two_bends, join_miter, end_flat, 65.1834, 1.5, 1.5);
test_one<multi_linestring_type, polygon>("two_bends", two_bends, join_miter, end_round, 75.2917, 1.5, 1.5);
test_one<multi_linestring_type, polygon>("degenerate0", degenerate0, join_round, end_round, 0.0, 3.0, 3.0);
test_one<multi_linestring_type, polygon>("degenerate1", degenerate1, join_round, end_round, 28.2503, 3.0, 3.0);
test_one<multi_linestring_type, polygon>("degenerate2", degenerate2, join_round, end_round, 56.0457, 3.0, 3.0);
test_one<multi_linestring_type, polygon>("degenerate3", degenerate3, join_round, end_round, 80.4531, 3.0, 3.0);
test_one<multi_linestring_type, polygon>("degenerate4", degenerate4, join_round, end_round, 104.3142, 3.0, 3.0);
}
int test_main(int, char* [])
{
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
return 0;
}

View File

@@ -21,12 +21,10 @@ static std::string const multipoint_a = "MULTIPOINT((39 44),(38 37),(41 29),(15
static std::string const multipoint_b = "MULTIPOINT((5 56),(98 67),(20 7),(58 60),(10 4),(75 68),(61 68),(75 62),(92 26),(74 6),(67 54),(20 43),(63 30),(45 7))";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
//std::cout << typeid(bg::coordinate_type<P>::type).name() << std::endl;
typedef bg::model::polygon<P> polygon;
typedef bg::model::polygon<P, Clockwise> polygon;
typedef bg::model::multi_point<P> multi_point_type;
bg::strategy::buffer::join_miter join_miter;
@@ -185,9 +183,8 @@ void test_growth(int n, int distance_count)
int test_main(int, char* [])
{
//std::cout << std::setprecision(6);
//test_all<bg::model::point<float, 2, bg::cs::cartesian> >();
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
#ifdef BOOST_GEOMETRY_BUFFER_TEST_GROWTH

View File

@@ -24,6 +24,13 @@ static std::string const wrapped
static std::string const triangles
= "MULTIPOLYGON(((0 4,3 0,-2.5 -1,0 4)),((3 8,5.5 13,8 8,3 8)),((11 4,13.5 -1,8 0,11 4)))";
static std::string const degenerate0
= "MULTIPOLYGON()";
static std::string const degenerate1
= "MULTIPOLYGON(((5 5,5 5,5 5,5 5)),((6 6,6 6,6 6,6 6)))";
static std::string const degenerate2
= "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0),(5 5,5 5,5 5,5 5)),((11 5,11 5,11 5,11 5)))";
// From robustness tests (rt)
// Case with duplicate points (due to chained boxes) (round)
@@ -260,10 +267,10 @@ static std::string const rt_u12
static std::string const rt_u13
= "MULTIPOLYGON(((6 4,6 5,7 5,6 4)),((3 2,3 3,4 3,3 2)),((7 8,7 9,8 9,8 8,7 8)),((4 9,4 10,5 10,4 9)),((7 7,7 8,8 7,7 7)),((2 6,2 7,3 7,2 6)),((0 1,1 2,1 1,0 1)),((3 1,4 2,4 1,3 1)),((2 5,2 6,3 6,2 5)),((3 5,4 4,3 4,2 4,3 5)),((4 1,5 2,5 1,4 1)),((2 0,2 1,3 1,2 0)),((5 7,5 8,6 7,5 7)),((0 2,0 3,1 3,0 2)),((9 8,9 9,10 9,10 8,9 8)),((7 5,7 6,8 5,7 5)),((5 6,5 7,6 6,5 6)),((0 6,0 7,1 7,1 6,0 6)),((5 0,5 1,6 1,5 0)),((8 7,8 8,9 8,8 7)),((4.5 4.5,5 4,4 4,4 5,5 5,4.5 4.5)),((6 2,5 2,5 3,6 3,7 3,8 2,7 2,6 2)),((8 6,8 7,9 7,9 6,9 5,8 5,8 6)),((8 1,9 0,8 0,7 0,8 1)))";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
typedef bg::model::polygon<P> polygon_type;
typedef bg::model::polygon<P, Clockwise> polygon_type;
typedef bg::model::multi_polygon<polygon_type> multi_polygon_type;
bg::strategy::buffer::join_miter join_miter;
@@ -298,6 +305,10 @@ void test_all()
test_one<multi_polygon_type, polygon_type>("wrapped_15", wrapped, join_round, end_flat, 167.066, 1.5);
test_one<multi_polygon_type, polygon_type>("wrapped_15", wrapped, join_miter, end_flat, 169.000, 1.5);
test_one<multi_polygon_type, polygon_type>("degenerate0", degenerate0, join_round, end_flat, 0.0, 1.0);
test_one<multi_polygon_type, polygon_type>("degenerate1", degenerate1, join_round, end_flat, 5.708, 1.0);
test_one<multi_polygon_type, polygon_type>("degenerate2", degenerate2, join_round, end_flat, 133.0166, 0.75);
test_one<multi_polygon_type, polygon_type>("rt_a", rt_a, join_round, end_flat, 34.5381, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_a", rt_a, join_miter, end_flat, 36, 1.0);
test_one<multi_polygon_type, polygon_type>("rt_b", rt_b, join_round, end_flat, 31.4186, 1.0);
@@ -394,7 +405,8 @@ void test_all()
int test_main(int, char* [])
{
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
//test_all<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >();
return 0;

View File

@@ -7,29 +7,15 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//#define BOOST_GEOMETRY_DEBUG_WITH_MAPPER
//#define BOOST_GEOMETRY_DEBUG_ASSEMBLE
//#define BOOST_GEOMETRY_DEBUG_IDENTIFIER
#include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/buffer.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <test_buffer.hpp>
static std::string const simplex = "POINT(5 5)";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
typedef bg::model::polygon<P> polygon;
typedef bg::model::polygon<P, Clockwise> polygon;
bg::strategy::buffer::join_miter join_miter;
bg::strategy::buffer::end_flat end_flat;
@@ -44,8 +30,7 @@ void test_all()
int test_main(int, char* [])
{
//std::cout << std::setprecision(6);
//test_all<bg::model::point<float, 2, bg::cs::cartesian> >();
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<true, bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<false, bg::model::point<double, 2, bg::cs::cartesian> >();
return 0;
}

View File

@@ -63,6 +63,16 @@ static std::string const bowl
static std::string const triangle
= "POLYGON((4 5,5 4,4 4,3 4,3 5,3 6,4 5))";
static std::string const degenerate0
= "POLYGON(())";
static std::string const degenerate1
= "POLYGON((5 5))";
static std::string const degenerate2
= "POLYGON((5 5,5 5,5 5,5 5))";
static std::string const degenerate3
= "POLYGON((0 0,0 10,10 10,10 0,0 0),(5 5,5 5,5 5,5 5))";
// Real-life examples
static std::string const county1
= "POLYGON((-111.700 41.200 ,-111.681388 41.181739 ,-111.682453 41.181506 ,-111.684052 41.180804 ,-111.685295 41.180538 ,-111.686318 41.180776 ,-111.687517 41.181416 ,-111.688982 41.181520 ,-111.690670 41.181523 ,-111.692135 41.181460 ,-111.693646 41.182034 ,-111.695156 41.182204 ,-111.696489 41.182274 ,-111.697775 41.182075 ,-111.698974 41.181539 ,-111.700485 41.182348 ,-111.701374 41.182955 ,-111.700 41.200))";
@@ -98,11 +108,15 @@ static std::string const ticket_10398_4
static std::string const ticket_10412
= "POLYGON((897747.8 6270564.3,897764.3 6270569.7,897776.5 6270529.5,897768.1 6270527.1,897767.6 6270529.4,897756.3 6270525.8,897745.8 6270522.3,897752 6270502.9,897749.7 6270502,897750.7 6270499.1,897751.8 6270498.6,897752.3 6270499.3,897754.6 6270497.9,897755.8 6270500.2,897766.8 6270494.1,897765.6 6270491.5,897768.3 6270490.5,897770.9 6270491.5,897770.2 6270494.6,897780.1 6270497.5,897781 6270494.6,897786.8 6270496.6,897790.8 6270482.5,897785.3 6270480.7,897785.9 6270478.2,897768.9 6270473.2,897768.1 6270475.8,897766.1 6270475.2,897758.7 6270479.2,897753.2 6270481.8,897751.9 6270479,897746.5 6270481.9,897748 6270484.6,897745.2 6270486.1,897743.9 6270483.3,897741.4 6270484.7,897742.6 6270487.3,897739.4 6270488.9,897738.3 6270486.3,897735.6 6270487.8,897733.1 6270496.8,897731.2 6270502.7,897732.4 6270503.2,897731.5 6270506.1,897730.3 6270505.7,897725.8 6270520.2,897726.8 6270520.7,897726 6270523,897728 6270523.7,897726.3 6270529.6,897742.8 6270534.5,897741.2 6270539.9,897751.4 6270543.4,897750.7 6270546.4,897753.2 6270547.2,897747.8 6270564.3))";
static std::string const mysql_report_2014_10_24
= "POLYGON((0 0, 0 8, 8 8, 8 10, -10 10, -10 0, 0 0))";
template <typename P>
template <bool Clockwise, typename P>
void test_all()
{
typedef bg::model::polygon<P> polygon_type;
typedef bg::model::polygon<P, Clockwise, true> polygon_type;
bg::strategy::buffer::join_miter join_miter(10.0);
bg::strategy::buffer::join_round join_round(100);
@@ -210,6 +224,11 @@ void test_all()
test_one<polygon_type, polygon_type>("fork_c1", fork_c, join_miter, end_flat, 152, 1);
test_one<polygon_type, polygon_type>("triangle", triangle, join_miter, end_flat, 14.6569, 1.0);
test_one<polygon_type, polygon_type>("degenerate0", degenerate0, join_round, end_round, 0.0, 1.0);
test_one<polygon_type, polygon_type>("degenerate1", degenerate1, join_round, end_round, 3.1389, 1.0);
test_one<polygon_type, polygon_type>("degenerate2", degenerate2, join_round, end_round, 3.1389, 1.0);
test_one<polygon_type, polygon_type>("degenerate3", degenerate3, join_round, end_round, 143.1395, 1.0);
test_one<polygon_type, polygon_type>("gammagate2", gammagate, join_miter, end_flat, 130, 2);
test_one<polygon_type, polygon_type>("flower1", flower, join_miter, end_flat, 67.614, 0.1);
@@ -310,11 +329,12 @@ void test_all()
test_one<polygon_type, polygon_type>("parcel3_30", parcel3, join_round, end_flat, 45261.4196014404297, 30.0);
test_one<polygon_type, polygon_type>("parcel3_30", parcel3, join_miter, end_flat, 45567.3875694274902, 30.0);
test_one<polygon_type, polygon_type>("parcel3_bend_10", parcel3_bend, join_round, end_flat, 155.6188, 5.0);
test_one<polygon_type, polygon_type>("parcel3_bend_5", parcel3_bend, join_round, end_flat, 155.6188, 5.0);
test_one<polygon_type, polygon_type>("parcel3_bend_10", parcel3_bend, join_round, end_flat, 458.4187, 10.0);
test_one<polygon_type, polygon_type>("parcel3_bend_10", parcel3_bend, join_round, end_flat, 917.9747, 15.0);
test_one<polygon_type, polygon_type>("parcel3_bend_10", parcel3_bend, join_round, end_flat, 1534.4795, 20.0);
// These cases differ a bit based on point order (TODO: find out / describe why)
test_one<polygon_type, polygon_type>("parcel3_bend_15", parcel3_bend, join_round, end_flat, Clockwise ? 917.9747 : 917.996, 15.0);
test_one<polygon_type, polygon_type>("parcel3_bend_20", parcel3_bend, join_round, end_flat, Clockwise ? 1534.4795 : 1534.508, 20.0);
// Negative buffers making polygons smaller
test_one<polygon_type, polygon_type>("simplex", simplex, join_round, end_flat, 7.04043, -0.5);
@@ -344,8 +364,34 @@ void test_all()
test_one<polygon_type, polygon_type>("ticket_10398_4_91", ticket_10398_4, join_miter, end_flat, 819.1406, 9.1, -999, false);
test_one<polygon_type, polygon_type>("ticket_10412", ticket_10412, join_miter, end_flat, 3109.6616, 1.5, -999, false);
bg::strategy::buffer::join_round join_round32(32);
bg::strategy::buffer::end_round end_round32(32);
test_one<polygon_type, polygon_type>("mysql_report_2014_10_24", mysql_report_2014_10_24, join_round32, end_round32, 174.902, 1.0, -999, false);
}
template
<
typename InputPoint,
typename OutputPoint,
bool InputClockwise,
bool OutputClockwise,
bool InputClosed,
bool OutputClosed
>
void test_mixed()
{
typedef bg::model::polygon<InputPoint, InputClockwise, InputClosed> input_polygon_type;
typedef bg::model::polygon<OutputPoint, OutputClockwise, OutputClosed> output_polygon_type;
bg::strategy::buffer::join_round join_round(12);
bg::strategy::buffer::end_flat end_flat;
std::ostringstream name;
name << "mixed_" << std::boolalpha << InputClockwise << "_" << OutputClockwise << "_" << InputClosed << "_" << OutputClosed;
test_one<input_polygon_type, output_polygon_type>(name.str(), simplex, join_round, end_flat, 47.4831, 1.5);
}
#ifdef HAVE_TTMATH
#include <ttmath_stub.hpp>
@@ -353,8 +399,16 @@ void test_all()
int test_main(int, char* [])
{
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
typedef bg::model::point<double, 2, bg::cs::cartesian> dpoint;
test_all<true, dpoint>();
test_all<false, dpoint>();
//test_all<bg::model::point<tt, 2, bg::cs::cartesian> >();
test_mixed<dpoint, dpoint, false, false, true, true>();
test_mixed<dpoint, dpoint, false, true, true, true>();
test_mixed<dpoint, dpoint, true, false, true, true>();
test_mixed<dpoint, dpoint, true, true, true, true>();
return 0;
}

View File

@@ -412,6 +412,7 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
<< "_" << join_name
<< (end_name.empty() ? "" : "_") << end_name
<< (distance_left < 0 && distance_right < 0 ? "_deflate" : "")
<< (bg::point_order<GeometryOut>::value == bg::counterclockwise ? "_ccw" : "")
// << "_" << point_buffer_count
;

View File

@@ -8,6 +8,7 @@
# Modifications copyright (c) 2014, Oracle and/or its affiliates.
#
# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#
# Use, modification and distribution is subject to the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -16,8 +17,11 @@
test-suite boost-geometry-strategies
:
[ run cross_track.cpp ]
[ run crossings_multiply.cpp ]
[ run distance_default_result.cpp ]
[ run franklin.cpp ]
[ run haversine.cpp ]
[ run point_in_box.cpp ]
[ run projected_point.cpp ]
[ run projected_point_ax.cpp ]
[ run pythagoras.cpp ]
@@ -26,5 +30,5 @@ test-suite boost-geometry-strategies
[ run segment_intersection_collinear.cpp ]
[ run transform_cs.cpp ]
[ run transformer.cpp ]
[ run winding_franklin_crossmult.cpp ]
[ run winding.cpp ]
;

View File

@@ -0,0 +1,87 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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)
#include <strategies/test_within.hpp>
template <typename Point>
void test_all()
{
typedef bg::model::polygon<Point> polygon;
std::string const box = "POLYGON((0 0,0 2,2 2,2 0,0 0))";
std::string const triangle = "POLYGON((0 0,0 4,6 0,0 0))";
std::string const with_hole = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))";
bg::strategy::within::crossings_multiply<Point> s;
test_geometry<Point, polygon>("b1", "POINT(1 1)", box, s, true);
test_geometry<Point, polygon>("b2", "POINT(3 3)", box, s, false);
// Test ALL corners (officialy false but some strategies might answer true)
test_geometry<Point, polygon>("b3a", "POINT(0 0)", box, s, false);
test_geometry<Point, polygon>("b3b", "POINT(0 2)", box, s, false);
test_geometry<Point, polygon>("b3c", "POINT(2 2)", box, s, false);
test_geometry<Point, polygon>("b3d", "POINT(2 0)", box, s, false);
// Test ALL sides (officialy false but some strategies might answer true)
test_geometry<Point, polygon>("b4a", "POINT(0 1)", box, s, false);
test_geometry<Point, polygon>("b4b", "POINT(1 2)", box, s, true); // different
test_geometry<Point, polygon>("b4c", "POINT(2 1)", box, s, false);
test_geometry<Point, polygon>("b4d", "POINT(1 0)", box, s, false);
test_geometry<Point, polygon>("t1", "POINT(1 1)", triangle, s, true);
test_geometry<Point, polygon>("t2", "POINT(3 3)", triangle, s, false);
test_geometry<Point, polygon>("t3a", "POINT(0 0)", triangle, s, false);
test_geometry<Point, polygon>("t3b", "POINT(0 4)", triangle, s, true); // diff
test_geometry<Point, polygon>("t3c", "POINT(5 0)", triangle, s, false);
test_geometry<Point, polygon>("t4a", "POINT(0 2)", triangle, s, false);
test_geometry<Point, polygon>("t4b", "POINT(3 2)", triangle, s, false);
test_geometry<Point, polygon>("t4c", "POINT(2 0)", triangle, s, false);
test_geometry<Point, polygon>("h1", "POINT(0.5 0.5)", with_hole, s, true);
test_geometry<Point, polygon>("h2a", "POINT(1.5 1.5)", with_hole, s, false);
test_geometry<Point, polygon>("h2b", "POINT(5 5)", with_hole, s, false);
test_geometry<Point, polygon>("h3a", "POINT(1 1)", with_hole, s, true); // diff
test_geometry<Point, polygon>("h3b", "POINT(2 2)", with_hole, s, false);
test_geometry<Point, polygon>("h3c", "POINT(0 0)", with_hole, s, false);
test_geometry<Point, polygon>("h4a", "POINT(1 1.5)", with_hole, s, false);
test_geometry<Point, polygon>("h4b", "POINT(1.5 2)", with_hole, s, false);
// Lying ON (one of the sides of) interior ring
test_geometry<Point, polygon>("#77-1", "POINT(6 3.5)",
"POLYGON((5 3,5 4,4 4,4 5,3 5,3 6,5 6,5 5,7 5,7 6,8 6,8 5,9 5,9 2,8 2,8 1,7 1,7 2,5 2,5 3),(6 3,8 3,8 4,6 4,6 3))",
s, false);
}
int test_main(int, char* [])
{
test_all<bg::model::point<float, 2, bg::cs::cartesian> >();
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
#if defined(HAVE_TTMATH)
test_all<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >();
#endif
return 0;
}

View File

@@ -0,0 +1,86 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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)
#include <strategies/test_within.hpp>
template <typename Point>
void test_all()
{
typedef bg::model::polygon<Point> polygon;
std::string const box = "POLYGON((0 0,0 2,2 2,2 0,0 0))";
std::string const triangle = "POLYGON((0 0,0 4,6 0,0 0))";
std::string const with_hole = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))";
bg::strategy::within::franklin<Point> s;
test_geometry<Point, polygon>("b1", "POINT(1 1)", box, s, true);
test_geometry<Point, polygon>("b2", "POINT(3 3)", box, s, false);
// Test ALL corners (officialy false but some strategies might answer true)
test_geometry<Point, polygon>("b3a", "POINT(0 0)", box, s, true); // different
test_geometry<Point, polygon>("b3b", "POINT(0 2)", box, s, false);
test_geometry<Point, polygon>("b3c", "POINT(2 2)", box, s, false);
test_geometry<Point, polygon>("b3d", "POINT(2 0)", box, s, false);
// Test ALL sides (officialy false but some strategies might answer true)
test_geometry<Point, polygon>("b4a", "POINT(0 1)", box, s, true); // different
test_geometry<Point, polygon>("b4b", "POINT(1 2)", box, s, false);
test_geometry<Point, polygon>("b4c", "POINT(2 1)", box, s, false);
test_geometry<Point, polygon>("b4d", "POINT(1 0)", box, s, true); // different
test_geometry<Point, polygon>("t1", "POINT(1 1)", triangle, s, true);
test_geometry<Point, polygon>("t2", "POINT(3 3)", triangle, s, false);
test_geometry<Point, polygon>("t3a", "POINT(0 0)", triangle, s, true); // diff
test_geometry<Point, polygon>("t3b", "POINT(0 4)", triangle, s, false);
test_geometry<Point, polygon>("t3c", "POINT(5 0)", triangle, s, true); // diff
test_geometry<Point, polygon>("t4a", "POINT(0 2)", triangle, s, true); // diff
test_geometry<Point, polygon>("t4b", "POINT(3 2)", triangle, s, false);
test_geometry<Point, polygon>("t4c", "POINT(2 0)", triangle, s, true); // diff
test_geometry<Point, polygon>("h1", "POINT(0.5 0.5)", with_hole, s, true);
test_geometry<Point, polygon>("h2a", "POINT(1.5 1.5)", with_hole, s, false);
test_geometry<Point, polygon>("h2b", "POINT(5 5)", with_hole, s, false);
test_geometry<Point, polygon>("h3a", "POINT(1 1)", with_hole, s, false);
test_geometry<Point, polygon>("h3b", "POINT(2 2)", with_hole, s, true); // diff
test_geometry<Point, polygon>("h3c", "POINT(0 0)", with_hole, s, true); // diff
test_geometry<Point, polygon>("h4a", "POINT(1 1.5)", with_hole, s, false);
test_geometry<Point, polygon>("h4b", "POINT(1.5 2)", with_hole, s, true); // diff
// Lying ON (one of the sides of) interior ring
test_geometry<Point, polygon>("#77-1", "POINT(6 3.5)",
"POLYGON((5 3,5 4,4 4,4 5,3 5,3 6,5 6,5 5,7 5,7 6,8 6,8 5,9 5,9 2,8 2,8 1,7 1,7 2,5 2,5 3),(6 3,8 3,8 4,6 4,6 3))",
s, false);
}
int test_main(int, char* [])
{
test_all<bg::model::point<float, 2, bg::cs::cartesian> >();
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
#if defined(HAVE_TTMATH)
test_all<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >();
#endif
return 0;
}

View File

@@ -0,0 +1,81 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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)
#include <strategies/test_within.hpp>
template <typename Point>
void test_box_of(std::string const& wkt_point, std::string const& wkt_box,
bool expected_within, bool expected_covered_by)
{
typedef bg::model::box<Point> box_type;
Point point;
box_type box;
bg::read_wkt(wkt_point, point);
bg::read_wkt(wkt_box, box);
bool detected_within = bg::within(point, box);
bool detected_covered_by = bg::covered_by(point, box);
BOOST_CHECK_EQUAL(detected_within, expected_within);
BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by);
// Also test with the non-default agnostic side version
namespace wi = bg::strategy::within;
wi::point_in_box_by_side<Point, box_type> within_strategy;
wi::point_in_box_by_side<Point, box_type, wi::decide_covered_by> covered_by_strategy;
detected_within = bg::within(point, box, within_strategy);
detected_covered_by = bg::covered_by(point, box, covered_by_strategy);
BOOST_CHECK_EQUAL(detected_within, expected_within);
BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by);
// We might exchange strategies between within/covered by.
// So the lines below might seem confusing, but are as intended
detected_within = bg::covered_by(point, box, within_strategy);
detected_covered_by = bg::within(point, box, covered_by_strategy);
BOOST_CHECK_EQUAL(detected_within, expected_within);
BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by);
// Finally we call the strategies directly
detected_within = within_strategy.apply(point, box);
detected_covered_by = covered_by_strategy.apply(point, box);
BOOST_CHECK_EQUAL(detected_within, expected_within);
BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by);
}
template <typename Point>
void test_box()
{
test_box_of<Point>("POINT(1 1)", "BOX(0 0,2 2)", true, true);
test_box_of<Point>("POINT(0 0)", "BOX(0 0,2 2)", false, true);
test_box_of<Point>("POINT(2 2)", "BOX(0 0,2 2)", false, true);
test_box_of<Point>("POINT(0 1)", "BOX(0 0,2 2)", false, true);
test_box_of<Point>("POINT(1 0)", "BOX(0 0,2 2)", false, true);
test_box_of<Point>("POINT(3 3)", "BOX(0 0,2 2)", false, false);
}
int test_main(int, char* [])
{
test_box<bg::model::point<float, 2, bg::cs::cartesian> >();
test_box<bg::model::point<double, 2, bg::cs::cartesian> >();
#if defined(HAVE_TTMATH)
test_box<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >();
#endif
return 0;
}

View File

@@ -0,0 +1,106 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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)
#ifndef BOOST_GEOMETRY_TEST_STRATEGIES_TEST_WITHIN_HPP
#define BOOST_GEOMETRY_TEST_STRATEGIES_TEST_WITHIN_HPP
#include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
template <typename Strategy>
inline const char * strategy_name(Strategy const&)
{
return typeid(Strategy).name();
}
template <typename P, typename PoS, typename CT>
inline const char * strategy_name(bg::strategy::within::crossings_multiply<P, PoS, CT> const&)
{
return "crossings_multiply";
}
template <typename P, typename PoS, typename CT>
inline const char * strategy_name(bg::strategy::within::franklin<P, PoS, CT> const&)
{
return "franklin";
}
template <typename P, typename PoS, typename CT>
inline const char * strategy_name(bg::strategy::within::winding<P, PoS, CT> const&)
{
return "winding";
}
template <typename Point, typename Polygon, typename Strategy>
void test_point_in_polygon(std::string const& case_id,
Point const& point,
Polygon const& polygon,
Strategy const& strategy,
bool expected,
bool use_within = true)
{
BOOST_CONCEPT_ASSERT( (bg::concept::WithinStrategyPolygonal<Strategy>) );
bool detected = use_within ?
bg::within(point, polygon, strategy) :
bg::covered_by(point, polygon, strategy);
BOOST_CHECK_MESSAGE(detected == expected,
(use_within ? "within: " : "covered_by: ") << case_id
<< " strategy: " << strategy_name(strategy)
<< " output expected: " << int(expected)
<< " detected: " << int(detected)
);
}
template <typename Point, typename Polygon, typename Strategy>
void test_geometry(std::string const& case_id,
std::string const& wkt_point,
std::string const& wkt_polygon,
Strategy const& strategy,
bool expected,
bool use_within = true)
{
Point point;
Polygon polygon;
bg::read_wkt(wkt_point, point);
bg::read_wkt(wkt_polygon, polygon);
test_point_in_polygon(case_id, point, polygon, strategy, expected, use_within);
}
#endif // BOOST_GEOMETRY_TEST_STRATEGIES_TEST_WITHIN_HPP

227
test/strategies/winding.cpp Normal file
View File

@@ -0,0 +1,227 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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)
#include <strategies/test_within.hpp>
template <typename Point>
void test_cartesian()
{
typedef bg::model::polygon<Point> polygon;
std::string const box = "POLYGON((0 0,0 2,2 2,2 0,0 0))";
std::string const triangle = "POLYGON((0 0,0 4,6 0,0 0))";
std::string const with_hole = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))";
bg::strategy::within::winding<Point> s;
test_geometry<Point, polygon>("b1", "POINT(1 1)", box, s, true);
test_geometry<Point, polygon>("b2", "POINT(3 3)", box, s, false);
// Test ALL corners (officialy false but some strategies might answer true)
test_geometry<Point, polygon>("b3a", "POINT(0 0)", box, s, false);
test_geometry<Point, polygon>("b3b", "POINT(0 2)", box, s, false);
test_geometry<Point, polygon>("b3c", "POINT(2 2)", box, s, false);
test_geometry<Point, polygon>("b3d", "POINT(2 0)", box, s, false);
// Test ALL sides (officialy false but some strategies might answer true)
test_geometry<Point, polygon>("b4a", "POINT(0 1)", box, s, false);
test_geometry<Point, polygon>("b4b", "POINT(1 2)", box, s, false);
test_geometry<Point, polygon>("b4c", "POINT(2 1)", box, s, false);
test_geometry<Point, polygon>("b4d", "POINT(1 0)", box, s, false);
test_geometry<Point, polygon>("t1", "POINT(1 1)", triangle, s, true);
test_geometry<Point, polygon>("t2", "POINT(3 3)", triangle, s, false);
test_geometry<Point, polygon>("t3a", "POINT(0 0)", triangle, s, false);
test_geometry<Point, polygon>("t3b", "POINT(0 4)", triangle, s, false);
test_geometry<Point, polygon>("t3c", "POINT(5 0)", triangle, s, false);
test_geometry<Point, polygon>("t4a", "POINT(0 2)", triangle, s, false);
test_geometry<Point, polygon>("t4b", "POINT(3 2)", triangle, s, false);
test_geometry<Point, polygon>("t4c", "POINT(2 0)", triangle, s, false);
test_geometry<Point, polygon>("h1", "POINT(0.5 0.5)", with_hole, s, true);
test_geometry<Point, polygon>("h2a", "POINT(1.5 1.5)", with_hole, s, false);
test_geometry<Point, polygon>("h2b", "POINT(5 5)", with_hole, s, false);
test_geometry<Point, polygon>("h3a", "POINT(1 1)", with_hole, s, false);
test_geometry<Point, polygon>("h3b", "POINT(2 2)", with_hole, s, false);
test_geometry<Point, polygon>("h3c", "POINT(0 0)", with_hole, s, false);
test_geometry<Point, polygon>("h4a", "POINT(1 1.5)", with_hole, s, false);
test_geometry<Point, polygon>("h4b", "POINT(1.5 2)", with_hole, s, false);
// Lying ON (one of the sides of) interior ring
test_geometry<Point, polygon>("#77-1", "POINT(6 3.5)",
"POLYGON((5 3,5 4,4 4,4 5,3 5,3 6,5 6,5 5,7 5,7 6,8 6,8 5,9 5,9 2,8 2,8 1,7 1,7 2,5 2,5 3),(6 3,8 3,8 4,6 4,6 3))",
s, false);
}
template <typename T>
void test_spherical()
{
typedef bg::model::point<T, 2, bg::cs::spherical_equatorial<bg::degree> > point;
typedef bg::model::polygon<point> polygon;
bg::strategy::within::winding<point> s;
// Ticket #9354
test_geometry<point, polygon>(
"#9354",
"POINT(-78.1239 25.9556)",
"POLYGON((-97.08466667 25.95683333, -97.13683333 25.954, -97.1 26, -97.08466667 25.95683333))",
s,
false);
#ifdef BOOST_GEOMETRY_TEST_STRATEGIES_WINDING_ENABLE_FAILING_TESTS
test_geometry<point, polygon>(
"sph1N",
"POINT(0 10.001)",
"POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))",
s,
bg::strategy::side::spherical_side_formula<>::apply(
point(-10, 10),
point(10, 10),
point(0, (T)10.001)) == -1 // right side
/*true*/);
test_geometry<point, polygon>(
"sph1S",
"POINT(0 -10.001)",
"POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))",
s,
bg::strategy::side::spherical_side_formula<>::apply(
point(10, -10),
point(-10, -10),
point(0, (T)-10.001)) == -1 // right side
/*true*/);
test_geometry<point, polygon>(
"sph2S",
"POINT(0 10.001)",
"POLYGON((-10 20, 10 20, 10 10, -10 10, -10 20))",
s,
bg::strategy::side::spherical_side_formula<>::apply(
point(10, 10),
point(-10, 10),
point(0, (T)10.001)) == -1 // right side
/*false*/);
test_geometry<point, polygon>(
"sph3N",
"POINT(0 10)",
"POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))",
s,
bg::strategy::side::spherical_side_formula<>::apply(
point(-10, 10),
point(10, 10),
point(0, (T)10.001)) == -1 // right side
/*true*/);
test_geometry<point, polygon>(
"sph3S",
"POINT(0 -10)",
"POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))",
s,
bg::strategy::side::spherical_side_formula<>::apply(
point(10, -10),
point(-10, -10),
point(0, (T)-10.001)) == -1 // right side
/*true*/);
#endif // BOOST_GEOMETRY_TEST_STRATEGIES_WINDING_ENABLE_FAILING_TESTS
test_geometry<point, polygon>(
"sphEq1",
"POINT(179 10)",
"POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))",
s,
true,
false);
test_geometry<point, polygon>(
"sphEq2",
"POINT(179 10)",
"POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))",
s,
true,
false);
test_geometry<point, polygon>(
"sphEq3",
"POINT(-179 10)",
"POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))",
s,
true,
false);
test_geometry<point, polygon>(
"sphEq4",
"POINT(-179 10)",
"POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))",
s,
true,
false);
#ifdef BOOST_GEOMETRY_TEST_STRATEGIES_WINDING_ENABLE_FAILING_TESTS
test_geometry<point, polygon>(
"sphEq5",
"POINT(169 10)",
"POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))",
s,
false,
false);
test_geometry<point, polygon>(
"sphEq6",
"POINT(-169 10)",
"POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))",
s,
false,
false);
test_geometry<point, polygon>(
"sphEq7",
"POINT(169 10)",
"POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))",
s,
false,
false);
test_geometry<point, polygon>(
"sphEq8",
"POINT(-169 10)",
"POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))",
s,
false,
false);
#endif // BOOST_GEOMETRY_TEST_STRATEGIES_WINDING_ENABLE_FAILING_TESTS
}
int test_main(int, char* [])
{
test_cartesian<bg::model::point<float, 2, bg::cs::cartesian> >();
test_cartesian<bg::model::point<double, 2, bg::cs::cartesian> >();
test_spherical<float>();
test_spherical<double>();
#if defined(HAVE_TTMATH)
test_cartesian<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >();
test_spherical<ttmath_big>();
#endif
return 0;
}

View File

@@ -1,326 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2010-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)
// Tests with-strategies, especially point-in-polygon
#include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp>
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
template <typename Point, typename Polygon, typename Strategy>
void test_point_in_polygon(std::string const& case_id,
Point const& point, Polygon const& polygon,
Strategy const& strategy, std::string const& strategy_id,
bool expected, bool use_within = true)
{
BOOST_CONCEPT_ASSERT( (bg::concept::WithinStrategyPolygonal<Strategy>) );
bool detected = use_within ?
bg::within(point, polygon, strategy) :
bg::covered_by(point, polygon, strategy);
BOOST_CHECK_MESSAGE(detected == expected,
(use_within ? "within: " : "covered_by: ") << case_id
<< " strategy: " << strategy_id // typeid(strategy).name() is too long
<< " output expected: " << int(expected)
<< " detected: " << int(detected)
);
}
template <typename Point, typename Polygon>
void test_geometry(std::string const& case_id, std::string const& wkt_point
, std::string const& wkt_polygon
, bool expected
, std::string const& deviations = ""
, bool use_within = true)
{
Point point;
Polygon polygon;
bg::read_wkt(wkt_point, point);
bg::read_wkt(wkt_polygon, polygon);
namespace sw = bg::strategy::within;
test_point_in_polygon(case_id, point, polygon, sw::winding<Point>(),
"winding", expected, use_within);
test_point_in_polygon(case_id, point, polygon, sw::franklin<Point>(),
"franklin", boost::contains(deviations, "f") ? !expected : expected, use_within);
test_point_in_polygon(case_id, point, polygon, sw::crossings_multiply<Point>(),
"cross.mult", boost::contains(deviations, "c") ? !expected : expected, use_within);
}
template <typename Point, typename Polygon>
void test_geometry_default(std::string const& case_id, std::string const& wkt_point
, std::string const& wkt_polygon
, bool expected
, bool use_within = true)
{
Point point;
Polygon polygon;
bg::read_wkt(wkt_point, point);
bg::read_wkt(wkt_polygon, polygon);
namespace sw = bg::strategy::within;
test_point_in_polygon(case_id, point, polygon, sw::winding<Point>(),
"winding", expected, use_within);
}
template <typename Point>
void test_box_of(std::string const& wkt_point, std::string const& wkt_box,
bool expected_within, bool expected_covered_by)
{
typedef bg::model::box<Point> box_type;
Point point;
box_type box;
bg::read_wkt(wkt_point, point);
bg::read_wkt(wkt_box, box);
bool detected_within = bg::within(point, box);
bool detected_covered_by = bg::covered_by(point, box);
BOOST_CHECK_EQUAL(detected_within, expected_within);
BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by);
// Also test with the non-default agnostic side version
namespace wi = bg::strategy::within;
wi::point_in_box_by_side<Point, box_type> within_strategy;
wi::point_in_box_by_side<Point, box_type, wi::decide_covered_by> covered_by_strategy;
detected_within = bg::within(point, box, within_strategy);
detected_covered_by = bg::covered_by(point, box, covered_by_strategy);
BOOST_CHECK_EQUAL(detected_within, expected_within);
BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by);
// We might exchange strategies between within/covered by.
// So the lines below might seem confusing, but are as intended
detected_within = bg::covered_by(point, box, within_strategy);
detected_covered_by = bg::within(point, box, covered_by_strategy);
BOOST_CHECK_EQUAL(detected_within, expected_within);
BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by);
// Finally we call the strategies directly
detected_within = within_strategy.apply(point, box);
detected_covered_by = covered_by_strategy.apply(point, box);
BOOST_CHECK_EQUAL(detected_within, expected_within);
BOOST_CHECK_EQUAL(detected_covered_by, expected_covered_by);
}
template <typename Point>
void test_box()
{
test_box_of<Point>("POINT(1 1)", "BOX(0 0,2 2)", true, true);
test_box_of<Point>("POINT(0 0)", "BOX(0 0,2 2)", false, true);
test_box_of<Point>("POINT(2 2)", "BOX(0 0,2 2)", false, true);
test_box_of<Point>("POINT(0 1)", "BOX(0 0,2 2)", false, true);
test_box_of<Point>("POINT(1 0)", "BOX(0 0,2 2)", false, true);
test_box_of<Point>("POINT(3 3)", "BOX(0 0,2 2)", false, false);
}
template <typename Point>
void test_all()
{
test_box<Point>();
typedef bg::model::polygon<Point> polygon;
std::string const box = "POLYGON((0 0,0 2,2 2,2 0,0 0))";
std::string const triangle = "POLYGON((0 0,0 4,6 0,0 0))";
std::string const with_hole = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))";
test_geometry<Point, polygon>("b1", "POINT(1 1)", box, true);
test_geometry<Point, polygon>("b2", "POINT(3 3)", box, false);
// Test ALL corners (officialy false but some strategies might answer true)
test_geometry<Point, polygon>("b3a", "POINT(0 0)", box, false, "f");
test_geometry<Point, polygon>("b3b", "POINT(0 2)", box, false);
test_geometry<Point, polygon>("b3c", "POINT(2 2)", box, false);
test_geometry<Point, polygon>("b3d", "POINT(2 0)", box, false);
// Test ALL sides (officialy false but some strategies might answer true)
test_geometry<Point, polygon>("b4a", "POINT(0 1)", box, false, "f");
test_geometry<Point, polygon>("b4b", "POINT(1 2)", box, false, "c");
test_geometry<Point, polygon>("b4c", "POINT(2 1)", box, false);
test_geometry<Point, polygon>("b4d", "POINT(1 0)", box, false, "f");
test_geometry<Point, polygon>("t1", "POINT(1 1)", triangle, true);
test_geometry<Point, polygon>("t2", "POINT(3 3)", triangle, false);
test_geometry<Point, polygon>("t3a", "POINT(0 0)", triangle, false, "f");
test_geometry<Point, polygon>("t3b", "POINT(0 4)", triangle, false, "c");
test_geometry<Point, polygon>("t3c", "POINT(5 0)", triangle, false, "f");
test_geometry<Point, polygon>("t4a", "POINT(0 2)", triangle, false, "f");
test_geometry<Point, polygon>("t4b", "POINT(3 2)", triangle, false);
test_geometry<Point, polygon>("t4c", "POINT(2 0)", triangle, false, "f");
test_geometry<Point, polygon>("h1", "POINT(0.5 0.5)", with_hole, true);
test_geometry<Point, polygon>("h2a", "POINT(1.5 1.5)", with_hole, false);
test_geometry<Point, polygon>("h2b", "POINT(5 5)", with_hole, false);
test_geometry<Point, polygon>("h3a", "POINT(1 1)", with_hole, false, "c");
test_geometry<Point, polygon>("h3b", "POINT(2 2)", with_hole, false, "f");
test_geometry<Point, polygon>("h3c", "POINT(0 0)", with_hole, false, "f");
test_geometry<Point, polygon>("h4a", "POINT(1 1.5)", with_hole, false);
test_geometry<Point, polygon>("h4b", "POINT(1.5 2)", with_hole, false, "f");
// Lying ON (one of the sides of) interior ring
test_geometry<Point, polygon>("#77-1", "POINT(6 3.5)", "POLYGON((5 3,5 4,4 4,4 5,3 5,3 6,5 6,5 5,7 5,7 6,8 6,8 5,9 5,9 2,8 2,8 1,7 1,7 2,5 2,5 3),(6 3,8 3,8 4,6 4,6 3))", false);
}
void test_spherical()
{
typedef bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > point;
typedef bg::model::polygon<point> polygon;
// Ticket #9354
test_geometry_default<point, polygon>(
"#9354",
"POINT(-78.1239 25.9556)",
"POLYGON((-97.08466667 25.95683333, -97.13683333 25.954, -97.1 26, -97.08466667 25.95683333))",
false);
test_geometry_default<point, polygon>(
"sph1N",
"POINT(0 10.001)",
"POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))",
bg::strategy::side::spherical_side_formula<>::apply(
point(-10, 10),
point(10, 10),
point(0, 10.001)) == -1 // right side
/*true*/);
test_geometry_default<point, polygon>(
"sph1S",
"POINT(0 -10.001)",
"POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))",
bg::strategy::side::spherical_side_formula<>::apply(
point(10, -10),
point(-10, -10),
point(0, -10.001)) == -1 // right side
/*true*/);
test_geometry_default<point, polygon>(
"sph2S",
"POINT(0 10.001)",
"POLYGON((-10 20, 10 20, 10 10, -10 10, -10 20))",
bg::strategy::side::spherical_side_formula<>::apply(
point(10, 10),
point(-10, 10),
point(0, 10.001)) == -1 // right side
/*false*/);
test_geometry_default<point, polygon>(
"sph3N",
"POINT(0 10)",
"POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))",
bg::strategy::side::spherical_side_formula<>::apply(
point(-10, 10),
point(10, 10),
point(0, 10.001)) == -1 // right side
/*true*/);
test_geometry_default<point, polygon>(
"sph3S",
"POINT(0 -10)",
"POLYGON((-10 10, 10 10, 10 -10, -10 -10, -10 10))",
bg::strategy::side::spherical_side_formula<>::apply(
point(10, -10),
point(-10, -10),
point(0, -10.001)) == -1 // right side
/*true*/);
test_geometry_default<point, polygon>(
"sphEq1",
"POINT(179 10)",
"POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))",
true,
false);
test_geometry_default<point, polygon>(
"sphEq2",
"POINT(179 10)",
"POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))",
true,
false);
test_geometry_default<point, polygon>(
"sphEq3",
"POINT(-179 10)",
"POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))",
true,
false);
test_geometry_default<point, polygon>(
"sphEq4",
"POINT(-179 10)",
"POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))",
true,
false);
test_geometry_default<point, polygon>(
"sphEq5",
"POINT(169 10)",
"POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))",
false,
false);
test_geometry_default<point, polygon>(
"sphEq6",
"POINT(-169 10)",
"POLYGON((170 20, -170 20, -170 10, 170 10, 170 20))",
false,
false);
test_geometry_default<point, polygon>(
"sphEq7",
"POINT(169 10)",
"POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))",
false,
false);
test_geometry_default<point, polygon>(
"sphEq8",
"POINT(-169 10)",
"POLYGON((170 10, -170 10, -170 0, 170 0, 170 10))",
false,
false);
}
int test_main(int, char* [])
{
test_all<bg::model::point<float, 2, bg::cs::cartesian> >();
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_spherical();
#if defined(HAVE_TTMATH)
test_all<bg::model::point<ttmath_big, 2, bg::cs::cartesian> >();
#endif
return 0;
}