Merge branch 'bg-prepare'

This commit is contained in:
Barend Gehrels
2017-07-05 17:14:30 +02:00
35 changed files with 817 additions and 495 deletions

View File

@@ -89,7 +89,10 @@
[include generated/clear.qbk]
[include generated/convert.qbk]
[include generated/convex_hull.qbk]
[section:correct correct]
[include generated/correct.qbk]
[endsect]
[section:covered_by covered_by]
[include generated/covered_by.qbk]

View File

@@ -18,6 +18,32 @@
[section:release_notes Release Notes]
[/=================]
[heading Boost 1.65]
[/=================]
[*Improvements]
* Add correct() overload taking area strategy
* Add missing relational operations (covered_by, crosses, equals, etc.) for MultiPoint/AnyGeometry
[*Solved issues]
* [@https://svn.boost.org/trac/boost/ticket/12410 12410] Lack of support of geographic coordinate system in correct()
* [@https://svn.boost.org/trac/boost/ticket/13035 13035] Wrong result of non-cartesian intersection strategies for segments near poles.
* [@https://svn.boost.org/trac/boost/ticket/13057 13057] Wrong result of intersects() for linestrings caused by numerical issue in disjoint() for boxes.
[*Bugfixes]
* Fix is_valid which could return false for multipolygons where an interior ring touches another interior ring
* Fix is_valid which could return false for multipolygons where a polygon was located in an interior ring, all touching each other
* Fix union which could produce invalid results (for some cases, this needs to define BOOST_GEOMETRY_INCLUDE_SELF_TURNS)
* Fix intersection (idem), but some cases are still not yet valid
* Fix difference (idem), but some cases are still not yet valid
* Fix propagation of area strategy into the internals of various algorithms from intersection strategy
* Fix uninitialized variable in relate and reference to temporary in overlay
* Fix error in disjoint for geographic Segment/Box
[/=================]
[heading Boost 1.64]
[/=================]

View File

@@ -5,6 +5,10 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -61,7 +65,8 @@ namespace detail { namespace correct
template <typename Geometry>
struct correct_nop
{
static inline void apply(Geometry& )
template <typename Strategy>
static inline void apply(Geometry& , Strategy const& )
{}
};
@@ -104,8 +109,8 @@ struct correct_box_loop<Box, DimensionCount, DimensionCount>
template <typename Box>
struct correct_box
{
static inline void apply(Box& box)
template <typename Strategy>
static inline void apply(Box& box, Strategy const& )
{
// Currently only for Cartesian coordinates
// (or spherical without crossing dateline)
@@ -119,18 +124,12 @@ struct correct_box
// Close a ring, if not closed
template <typename Ring, typename Predicate>
template <typename Ring, template <typename> class Predicate>
struct correct_ring
{
typedef typename point_type<Ring>::type point_type;
typedef typename coordinate_type<Ring>::type coordinate_type;
typedef typename strategy::area::services::default_strategy
<
typename cs_tag<point_type>::type,
point_type
>::type strategy_type;
typedef detail::area::ring_area
<
order_as_direction<geometry::point_order<Ring>::value>::value,
@@ -138,7 +137,8 @@ struct correct_ring
> ring_area_type;
static inline void apply(Ring& r)
template <typename Strategy>
static inline void apply(Ring& r, Strategy const& strategy)
{
// Check close-ness
if (boost::size(r) > 2)
@@ -158,10 +158,10 @@ struct correct_ring
}
}
// Check area
Predicate predicate;
typedef typename default_area_result<Ring>::type area_result_type;
area_result_type const zero = area_result_type();
if (predicate(ring_area_type::apply(r, strategy_type()), zero))
typedef typename Strategy::return_type area_result_type;
Predicate<area_result_type> predicate;
area_result_type const zero = 0;
if (predicate(ring_area_type::apply(r, strategy), zero))
{
std::reverse(boost::begin(r), boost::end(r));
}
@@ -174,15 +174,15 @@ template <typename Polygon>
struct correct_polygon
{
typedef typename ring_type<Polygon>::type ring_type;
typedef typename default_area_result<Polygon>::type area_result_type;
static inline void apply(Polygon& poly)
template <typename Strategy>
static inline void apply(Polygon& poly, Strategy const& strategy)
{
correct_ring
<
ring_type,
std::less<area_result_type>
>::apply(exterior_ring(poly));
std::less
>::apply(exterior_ring(poly), strategy);
typename interior_return_type<Polygon>::type
rings = interior_rings(poly);
@@ -192,8 +192,8 @@ struct correct_polygon
correct_ring
<
ring_type,
std::greater<area_result_type>
>::apply(*it);
std::greater
>::apply(*it, strategy);
}
}
};
@@ -237,7 +237,7 @@ struct correct<Ring, ring_tag>
: detail::correct::correct_ring
<
Ring,
std::less<typename default_area_result<Ring>::type>
std::less
>
{};
@@ -281,29 +281,36 @@ namespace resolve_variant {
template <typename Geometry>
struct correct
{
static inline void apply(Geometry& geometry)
template <typename Strategy>
static inline void apply(Geometry& geometry, Strategy const& strategy)
{
concepts::check<Geometry const>();
dispatch::correct<Geometry>::apply(geometry);
dispatch::correct<Geometry>::apply(geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<void>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry>
void operator()(Geometry& geometry) const
{
correct<Geometry>::apply(geometry);
correct<Geometry>::apply(geometry, m_strategy);
}
};
template <typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry, Strategy const& strategy)
{
boost::apply_visitor(visitor(), geometry);
boost::apply_visitor(visitor<Strategy>(strategy), geometry);
}
};
@@ -325,7 +332,37 @@ struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline void correct(Geometry& geometry)
{
resolve_variant::correct<Geometry>::apply(geometry);
typedef typename point_type<Geometry>::type point_type;
typedef typename strategy::area::services::default_strategy
<
typename cs_tag<point_type>::type,
point_type
>::type strategy_type;
resolve_variant::correct<Geometry>::apply(geometry, strategy_type());
}
/*!
\brief Corrects a geometry
\details Corrects a geometry: all rings which are wrongly oriented with respect
to their expected orientation are reversed. To all rings which do not have a
closing point and are typed as they should have one, the first point is
appended. Also boxes can be corrected.
\ingroup correct
\tparam Geometry \tparam_geometry
\tparam Strategy \tparam_strategy{Area}
\param geometry \param_geometry which will be corrected if necessary
\param strategy \param_strategy{area}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/correct.qbk]}
*/
template <typename Geometry, typename Strategy>
inline void correct(Geometry& geometry, Strategy const& strategy)
{
resolve_variant::correct<Geometry>::apply(geometry, strategy);
}
#if defined(_MSC_VER)

View File

@@ -142,10 +142,20 @@ struct buffered_piece_collection
robust_point_type
>::type robust_comparable_radius_type;
typedef typename strategy::side::services::default_strategy
typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
typedef typename IntersectionStrategy::template area_strategy
<
typename cs_tag<point_type>::type
>::type side_strategy;
point_type
>::type area_strategy_type;
typedef typename IntersectionStrategy::template area_strategy
<
robust_point_type
>::type robust_area_strategy_type;
typedef typename area_strategy_type::return_type area_result_type;
typedef typename robust_area_strategy_type::return_type robust_area_result_type;
typedef typename geometry::rescale_policy_type
<
@@ -306,7 +316,10 @@ struct buffered_piece_collection
cluster_type m_clusters;
IntersectionStrategy const& m_intersection_strategy;
IntersectionStrategy m_intersection_strategy;
side_strategy_type m_side_strategy;
area_strategy_type m_area_strategy;
robust_area_strategy_type m_robust_area_strategy;
RobustPolicy const& m_robust_policy;
struct redundant_turn
@@ -321,6 +334,9 @@ struct buffered_piece_collection
RobustPolicy const& robust_policy)
: m_first_piece_index(-1)
, m_intersection_strategy(intersection_strategy)
, m_side_strategy(intersection_strategy.get_side_strategy())
, m_area_strategy(intersection_strategy.template get_area_strategy<point_type>())
, m_robust_area_strategy(intersection_strategy.template get_area_strategy<robust_point_type>())
, m_robust_policy(robust_policy)
{}
@@ -699,7 +715,7 @@ struct buffered_piece_collection
++it)
{
piece& pc = *it;
if (geometry::area(pc.robust_ring) < 0)
if (geometry::area(pc.robust_ring, m_robust_area_strategy) < 0)
{
// Rings can be ccw:
// - in a concave piece
@@ -1220,14 +1236,9 @@ struct buffered_piece_collection
inline void enrich()
{
typedef typename strategy::side::services::default_strategy
<
typename cs_tag<Ring>::type
>::type side_strategy_type;
enrich_intersection_points<false, false, overlay_buffer>(m_turns,
m_clusters, offsetted_rings, offsetted_rings,
m_robust_policy, side_strategy_type());
m_robust_policy, m_side_strategy);
}
// Discards all rings which do have not-OK intersection points only.
@@ -1314,7 +1325,7 @@ struct buffered_piece_collection
buffered_ring<Ring>& ring = *it;
if (! ring.has_intersections()
&& boost::size(ring) > 0u
&& geometry::area(ring) < 0)
&& geometry::area(ring, m_area_strategy) < 0)
{
if (! point_coveredby_original(geometry::range::front(ring)))
{
@@ -1391,7 +1402,7 @@ struct buffered_piece_collection
template <typename GeometryOutput, typename OutputIterator>
inline OutputIterator assign(OutputIterator out) const
{
typedef detail::overlay::ring_properties<point_type> properties;
typedef detail::overlay::ring_properties<point_type, area_result_type> properties;
std::map<ring_identifier, properties> selected;
@@ -1407,7 +1418,7 @@ struct buffered_piece_collection
if (! it->has_intersections()
&& ! it->is_untouched_outside_original)
{
properties p = properties(*it);
properties p = properties(*it, m_area_strategy);
if (p.valid)
{
ring_identifier id(0, index, -1);
@@ -1423,7 +1434,7 @@ struct buffered_piece_collection
it != boost::end(traversed_rings);
++it, ++index)
{
properties p = properties(*it);
properties p = properties(*it, m_area_strategy);
if (p.valid)
{
ring_identifier id(2, index, -1);

View File

@@ -121,9 +121,18 @@ struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag>
// calculate positive longitude translation with b1_min as origin
calc_t const diff_min = math::longitude_distance_unsigned<units_t>(b1_min, b2_min);
calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min
calc_t b2_max_transl = b2_min_transl - constants::period() + diff2;
if (b2_min_transl > b1_max // b2_min right of b1_max
&& b2_min_transl - constants::period() + diff2 < b1_min) // b2_max left of b1_min
// if the translation is too close then use the original point
// note that math::abs(b2_max_transl - b2_max) takes values very
// close to k*2*constants::period() for k=0,1,2,...
if (math::abs(b2_max_transl - b2_max) < constants::period() / 2)
{
b2_max_transl = b2_max;
}
if (b2_min_transl > b1_max // b2_min right of b1_max
&& b2_max_transl < b1_min) // b2_max left of b1_min
{
return true;
}

View File

@@ -125,34 +125,6 @@ private:
typedef typename boost::range_value<MultiPolygon>::type polygon;
typedef is_acceptable_turn<polygon> base;
template <typename Operation>
static inline
bool check_int_ext(Operation const& op1,
detail::overlay::operation_type optype1,
Operation const& op2,
detail::overlay::operation_type optype2)
{
// u/i is acceptable for touch of interior ring with another exterior ring
// (but only if there is a colocated uu-turn of its exterior, TODO)
return op1.seg_id.ring_index == -1
&& op2.seg_id.ring_index >= 0
&& op1.operation == optype1
&& op2.operation == optype2;
}
template <typename Operation>
static inline
bool check_int_int(Operation const& op1,
Operation const& op2,
detail::overlay::operation_type optype)
{
// i/i is acceptable for touching interior/interior rings
return op1.seg_id.ring_index >= 0
&& op2.seg_id.ring_index >= 0
&& op1.operation == optype
&& op2.operation == optype;
}
public:
template <typename Turn>
static inline bool apply(Turn const& turn)
@@ -172,26 +144,11 @@ public:
return true;
}
if (turn.method != method_touch)
{
return false;
}
operation_type const reverse_op
= op == operation_union
? operation_intersection
: operation_union;
if ( check_int_int(turn.operations[0], turn.operations[1], reverse_op)
|| check_int_ext(turn.operations[0], reverse_op,
turn.operations[1], op)
|| check_int_ext(turn.operations[1], reverse_op,
turn.operations[0], op))
{
return true;
}
return false;
// Turn is acceptable only in case of a touch(interior) and both lines
// (polygons) do not cross
return (turn.method == method_touch
|| turn.method == method_touch_interior)
&& turn.touch_only;
}
};

View File

@@ -89,12 +89,15 @@ private:
{
boost::ignore_unused(visitor);
// collect all polygons that have turns
// collect all polygons that have crossing turns
std::set<signed_size_type> multi_indices;
for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit)
{
multi_indices.insert(tit->operations[0].seg_id.multi_index);
multi_indices.insert(tit->operations[1].seg_id.multi_index);
if (! tit->touch_only)
{
multi_indices.insert(tit->operations[0].seg_id.multi_index);
multi_indices.insert(tit->operations[1].seg_id.multi_index);
}
}
typedef geometry::model::box<typename point_type<MultiPolygon>::type> box_type;

View File

@@ -45,6 +45,7 @@
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/num_interior_rings.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
@@ -216,14 +217,26 @@ protected:
, m_strategy(strategy)
{}
template <typename Item>
inline bool is_within(Item const& first, Item const& second)
{
typename point_type<Polygon>::type point;
typedef detail::point_on_border::point_on_range<true> pob;
// TODO: this should check for a point on the interior, instead
// of on border. Or it should check using the overlap function.
return pob::apply(point, points_begin(first), points_end(first))
&& geometry::within(point, second, m_strategy);
}
template <typename Iterator, typename Box>
inline bool apply(partition_item<Iterator, Box> const& item1,
partition_item<Iterator, Box> const& item2)
{
if (! items_overlap
&& (geometry::within(*points_begin(*item1.get()), *item2.get(), m_strategy)
|| geometry::within(*points_begin(*item2.get()), *item1.get(), m_strategy))
)
&& (is_within(*item1.get(), *item2.get())
|| is_within(*item2.get(), *item1.get())))
{
items_overlap = true;
return false; // interrupt

View File

@@ -115,7 +115,10 @@ struct is_properly_oriented
geometry::closure<Ring>::value
> ring_area_type;
typedef typename default_area_result<Ring>::type area_result_type;
typedef typename Strategy::template area_strategy
<
point_type
>::type::return_type area_result_type;
typename ring_area_predicate
<

View File

@@ -4,6 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -40,6 +44,18 @@ struct multi_modify
Policy::apply(*it);
}
}
template <typename Strategy>
static inline void apply(MultiGeometry& multi, Strategy const& strategy)
{
typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
for (iterator_type it = boost::begin(multi);
it != boost::end(multi);
++it)
{
Policy::apply(*it, strategy);
}
}
};

View File

@@ -107,21 +107,19 @@ static inline bool within_selected_input(Item const& item2,
}
template <typename Point>
template <typename Point, typename AreaType>
struct ring_info_helper
{
typedef typename geometry::default_area_result<Point>::type area_type;
ring_identifier id;
area_type real_area;
area_type abs_area;
AreaType real_area;
AreaType abs_area;
model::box<Point> envelope;
inline ring_info_helper()
: real_area(0), abs_area(0)
{}
inline ring_info_helper(ring_identifier i, area_type a)
inline ring_info_helper(ring_identifier i, AreaType const& a)
: id(i), real_area(a), abs_area(geometry::math::abs(a))
{}
};
@@ -234,11 +232,15 @@ inline void assign_parents(Geometry1 const& geometry1,
typedef typename RingMap::mapped_type ring_info_type;
typedef typename ring_info_type::point_type point_type;
typedef model::box<point_type> box_type;
typedef typename Strategy::template area_strategy
<
point_type
>::type::return_type area_result_type;
typedef typename RingMap::iterator map_iterator_type;
{
typedef ring_info_helper<point_type> helper;
typedef ring_info_helper<point_type, area_result_type> helper;
typedef std::vector<helper> vector_type;
typedef typename boost::range_iterator<vector_type const>::type vector_iterator_type;

View File

@@ -190,6 +190,7 @@ struct touch_interior : public base_turn_handler
// Q turns left on the right side of P (test "MR3")
// Both directions for "intersection"
both(ti, operation_intersection);
ti.touch_only = true;
}
else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1)
{
@@ -197,6 +198,7 @@ struct touch_interior : public base_turn_handler
// Union: take both operation
// Intersection: skip
both(ti, operation_union);
ti.touch_only = true;
}
else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q)
{
@@ -207,6 +209,7 @@ struct touch_interior : public base_turn_handler
unsigned int index = side_qk_q == 1 ? index_q : index_p;
ti.operations[index].operation = operation_union;
ti.operations[1 - index].operation = operation_intersection;
ti.touch_only = true;
}
else if (side_qk_p == 0)
{
@@ -346,6 +349,7 @@ struct touch : public base_turn_handler
if (side_pk_q2 == -side_qk_q)
{
ui_else_iu(! q_turns_left, ti);
ti.touch_only = true;
return;
}
@@ -358,6 +362,10 @@ struct touch : public base_turn_handler
{
ti.operations[1].operation = operation_blocked;
}
else
{
ti.touch_only = true;
}
//block_second(block_q, ti);
return;
}
@@ -373,6 +381,10 @@ struct touch : public base_turn_handler
: side_qi_p1 == 1 || side_qk_p1 == 1
? operation_union
: operation_intersection;
if (! block_q)
{
ti.touch_only = true;
}
return;
}
@@ -400,6 +412,7 @@ struct touch : public base_turn_handler
if (side_pk_q1 == side_qk_p1)
{
uu_else_ii(right_to_left, ti);
ti.touch_only = true;
return;
}
}
@@ -418,6 +431,7 @@ struct touch : public base_turn_handler
if (side_pk_q2 == side_qk_p1)
{
ui_else_iu(right_to_left, ti);
ti.touch_only = true;
return;
}
}

View File

@@ -66,7 +66,7 @@ struct side_calculator
Qj const& m_qj;
Qk const& m_qk;
SideStrategy const& m_side_strategy;
SideStrategy m_side_strategy;
};
template <typename Point1, typename Point2, typename RobustPolicy>

View File

@@ -197,7 +197,16 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
typename geometry::ring_type<GeometryOut>::type
> ring_container_type;
typedef ring_properties<typename geometry::point_type<Geometry1>::type> properties;
typedef typename geometry::point_type<Geometry1>::type point_type1;
typedef ring_properties
<
point_type1,
typename Strategy::template area_strategy
<
point_type1
>::type::return_type
> properties;
// Silence warning C4127: conditional expression is constant
#if defined(_MSC_VER)
@@ -309,7 +318,7 @@ std::cout << "get turns" << std::endl;
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "enrich" << std::endl;
#endif
typename Strategy::side_strategy_type side_strategy;
typename Strategy::side_strategy_type side_strategy = strategy.get_side_strategy();
cluster_type clusters;
geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns,
@@ -341,10 +350,13 @@ std::cout << "traverse" << std::endl;
std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
get_ring_turn_info<OverlayType>(turn_info_per_ring, turns, clusters);
typedef typename Strategy::template area_strategy<point_type>::type area_strategy_type;
typedef ring_properties
<
typename geometry::point_type<GeometryOut>::type
> properties;
<
point_type,
typename area_strategy_type::return_type
> properties;
// Select all rings which are NOT touched by any intersection point
std::map<ring_identifier, properties> selected_ring_properties;
@@ -353,13 +365,15 @@ std::cout << "traverse" << std::endl;
// Add rings created during traversal
{
area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
ring_identifier id(2, 0, -1);
for (typename boost::range_iterator<ring_container_type>::type
it = boost::begin(rings);
it != boost::end(rings);
++it)
{
selected_ring_properties[id] = properties(*it);
selected_ring_properties[id] = properties(*it, area_strategy);
selected_ring_properties[id].reversed = ReverseOut;
id.multi_index++;
}

View File

@@ -27,11 +27,11 @@ namespace boost { namespace geometry
namespace detail { namespace overlay
{
template <typename Point>
template <typename Point, typename AreaType>
struct ring_properties
{
typedef Point point_type;
typedef typename default_area_result<Point>::type area_type;
typedef AreaType area_type;
bool valid;
@@ -56,13 +56,13 @@ struct ring_properties
, parent_area(-1)
{}
template <typename RingOrBox>
inline ring_properties(RingOrBox const& ring_or_box)
template <typename RingOrBox, typename AreaStrategy>
inline ring_properties(RingOrBox const& ring_or_box, AreaStrategy const& strategy)
: reversed(false)
, discarded(false)
, parent_area(-1)
{
this->area = geometry::area(ring_or_box);
this->area = geometry::area(ring_or_box, strategy);
valid = geometry::point_on_border(this->point, ring_or_box);
}

View File

@@ -59,41 +59,45 @@ namespace dispatch
template <typename Box>
struct select_rings<box_tag, Box>
{
template <typename Geometry, typename RingPropertyMap>
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Box const& box, Geometry const& ,
ring_identifier const& id, RingPropertyMap& ring_properties)
ring_identifier const& id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy)
{
ring_properties[id] = typename RingPropertyMap::mapped_type(box);
ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy);
}
template <typename RingPropertyMap>
template <typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Box const& box,
ring_identifier const& id, RingPropertyMap& ring_properties)
ring_identifier const& id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy)
{
ring_properties[id] = typename RingPropertyMap::mapped_type(box);
ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy);
}
};
template <typename Ring>
struct select_rings<ring_tag, Ring>
{
template <typename Geometry, typename RingPropertyMap>
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Ring const& ring, Geometry const& ,
ring_identifier const& id, RingPropertyMap& ring_properties)
ring_identifier const& id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy)
{
if (boost::size(ring) > 0)
{
ring_properties[id] = typename RingPropertyMap::mapped_type(ring);
ring_properties[id] = typename RingPropertyMap::mapped_type(ring, strategy);
}
}
template <typename RingPropertyMap>
template <typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Ring const& ring,
ring_identifier const& id, RingPropertyMap& ring_properties)
ring_identifier const& id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy)
{
if (boost::size(ring) > 0)
{
ring_properties[id] = typename RingPropertyMap::mapped_type(ring);
ring_properties[id] = typename RingPropertyMap::mapped_type(ring, strategy);
}
}
};
@@ -102,14 +106,15 @@ namespace dispatch
template <typename Polygon>
struct select_rings<polygon_tag, Polygon>
{
template <typename Geometry, typename RingPropertyMap>
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Polygon const& polygon, Geometry const& geometry,
ring_identifier id, RingPropertyMap& ring_properties)
ring_identifier id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef select_rings<ring_tag, ring_type> per_ring;
per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties);
per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties, strategy);
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
@@ -117,18 +122,19 @@ namespace dispatch
it = boost::begin(rings); it != boost::end(rings); ++it)
{
id.ring_index++;
per_ring::apply(*it, geometry, id, ring_properties);
per_ring::apply(*it, geometry, id, ring_properties, strategy);
}
}
template <typename RingPropertyMap>
template <typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Polygon const& polygon,
ring_identifier id, RingPropertyMap& ring_properties)
ring_identifier id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy)
{
typedef typename geometry::ring_type<Polygon>::type ring_type;
typedef select_rings<ring_tag, ring_type> per_ring;
per_ring::apply(exterior_ring(polygon), id, ring_properties);
per_ring::apply(exterior_ring(polygon), id, ring_properties, strategy);
typename interior_return_type<Polygon const>::type
rings = interior_rings(polygon);
@@ -136,7 +142,7 @@ namespace dispatch
it = boost::begin(rings); it != boost::end(rings); ++it)
{
id.ring_index++;
per_ring::apply(*it, id, ring_properties);
per_ring::apply(*it, id, ring_properties, strategy);
}
}
};
@@ -144,9 +150,10 @@ namespace dispatch
template <typename Multi>
struct select_rings<multi_polygon_tag, Multi>
{
template <typename Geometry, typename RingPropertyMap>
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
static inline void apply(Multi const& multi, Geometry const& geometry,
ring_identifier id, RingPropertyMap& ring_properties)
ring_identifier id, RingPropertyMap& ring_properties,
AreaStrategy const& strategy)
{
typedef typename boost::range_iterator
<
@@ -159,7 +166,7 @@ namespace dispatch
for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it)
{
id.ring_index = -1;
per_polygon::apply(*it, geometry, id, ring_properties);
per_polygon::apply(*it, geometry, id, ring_properties, strategy);
id.multi_index++;
}
}
@@ -311,12 +318,16 @@ inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
{
typedef typename geometry::tag<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2;
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
RingPropertyMap all_ring_properties;
dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2,
ring_identifier(0, -1, -1), all_ring_properties);
ring_identifier(0, -1, -1), all_ring_properties,
strategy.template get_area_strategy<point1_type>());
dispatch::select_rings<tag2, Geometry2>::apply(geometry2, geometry1,
ring_identifier(1, -1, -1), all_ring_properties);
ring_identifier(1, -1, -1), all_ring_properties,
strategy.template get_area_strategy<point2_type>());
update_ring_selection<OverlayType>(geometry1, geometry2, turn_info_per_ring,
all_ring_properties, selected_ring_properties,
@@ -337,10 +348,12 @@ inline void select_rings(Geometry const& geometry,
Strategy const& strategy)
{
typedef typename geometry::tag<Geometry>::type tag;
typedef typename geometry::point_type<Geometry>::type point_type;
RingPropertyMap all_ring_properties;
dispatch::select_rings<tag, Geometry>::apply(geometry,
ring_identifier(0, -1, -1), all_ring_properties);
ring_identifier(0, -1, -1), all_ring_properties,
strategy.template get_area_strategy<point_type>());
update_ring_selection<OverlayType>(geometry, geometry, turn_info_per_ring,
all_ring_properties, selected_ring_properties,

View File

@@ -89,6 +89,7 @@ struct turn_info
Point point;
method_type method;
bool touch_only; // True in case of method touch(interior) and lines do not cross
signed_size_type cluster_id; // For multiple turns on same location, >= 0. Else -1
bool discarded;
@@ -101,6 +102,7 @@ struct turn_info
inline turn_info()
: method(method_none)
, touch_only(false)
, cluster_id(-1)
, discarded(false)
, colocated_ii(false)

View File

@@ -84,43 +84,49 @@ struct midpoint_helper<Point, DimensionCount, DimensionCount>
template <bool Midpoint>
struct point_on_range
{
// Version with iterator
template<typename Point, typename Iterator>
static inline bool apply(Point& point, Iterator begin, Iterator end)
{
Iterator it = begin;
if (it == end)
{
return false;
}
if (! Midpoint)
{
geometry::detail::conversion::convert_point_to_point(*it, point);
return true;
}
Iterator prev = it++;
// Go to next non-duplicate point
while (it != end
&& detail::equals::equals_point_point(*it, *prev))
{
prev = it++;
}
if (it != end)
{
return midpoint_helper
<
Point,
0, dimension<Point>::value
>::apply(point, *prev, *it);
}
return false;
}
// Version with range
template<typename Point, typename Range>
static inline bool apply(Point& point, Range const& range)
{
typedef typename geometry::cs_tag<Point>::type cs_tag;
BOOST_STATIC_ASSERT((! Midpoint || boost::is_same<cs_tag, cartesian_tag>::value));
const std::size_t n = boost::size(range);
if (Midpoint && n > 1)
{
typedef typename boost::range_iterator
<
Range const
>::type iterator;
iterator it = boost::begin(range);
iterator prev = it++;
while (it != boost::end(range)
&& detail::equals::equals_point_point(*it, *prev))
{
prev = it++;
}
if (it != boost::end(range))
{
return midpoint_helper
<
Point,
0, dimension<Point>::value
>::apply(point, *prev, *it);
}
}
if (n > 0)
{
geometry::detail::conversion::convert_point_to_point(*boost::begin(range), point);
return true;
}
return false;
return apply(point, boost::begin(range), boost::end(range));
}
};

View File

@@ -165,6 +165,8 @@ private:
m_endpoints.reserve(boost::size(m_mls) * 2);
m_has_interior = false;
typedef typename boost::range_iterator<MultiLinestring const>::type ls_iterator;
for ( ls_iterator it = boost::begin(m_mls) ; it != boost::end(m_mls) ; ++it )
{

View File

@@ -1,8 +1,9 @@
// Boost.Geometry
// Copyright (c) 2016 Oracle and/or its affiliates.
// Copyright (c) 2016-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, 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
@@ -306,7 +307,7 @@ public :
//Segment lay on meridian
if (math::equals(lon1, lon2))
{
return std::max(lat1, lat2);
return (std::max)(lat1, lat2);
}
BOOST_ASSERT(lon1 < lon2);

View File

@@ -289,6 +289,8 @@ private:
typedef typename select_calculation_type
<Segment1, Segment2, CalculationType>::type calc_t;
static const calc_t c0 = 0;
// normalized spheroid
srs::spheroid<calc_t> spheroid = normalized_spheroid<calc_t>(m_spheroid);
@@ -325,31 +327,80 @@ private:
// TODO: no need to call inverse formula if we know that the points are equal
// distance can be set to 0 in this case and azimuth may be not calculated
bool const is_equal_a1_b1 = equals_point_point(a1, b1);
bool const is_equal_a2_b1 = equals_point_point(a2, b1);
bool is_equal_a1_b1 = equals_point_point(a1, b1);
bool is_equal_a2_b1 = equals_point_point(a2, b1);
bool degen_neq_coords = false;
inverse_result res_b1_b2 = inverse_dist_azi::apply(b1_lon, b1_lat, b2_lon, b2_lat, spheroid);
inverse_result res_b1_a1 = inverse_dist_azi::apply(b1_lon, b1_lat, a1_lon, a1_lat, spheroid);
inverse_result res_b1_a2 = inverse_dist_azi::apply(b1_lon, b1_lat, a2_lon, a2_lat, spheroid);
sides.set<0>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_b1_a1.azimuth, res_b1_b2.azimuth),
is_equal_a2_b1 ? 0 : formula::azimuth_side_value(res_b1_a2.azimuth, res_b1_b2.azimuth));
if (sides.same<0>())
inverse_result res_b1_b2, res_b1_a1, res_b1_a2;
if (! b_is_point)
{
// Both points are at the same side of other segment, we can leave
return Policy::disjoint();
res_b1_b2 = inverse_dist_azi::apply(b1_lon, b1_lat, b2_lon, b2_lat, spheroid);
if (math::equals(res_b1_b2.distance, c0))
{
b_is_point = true;
degen_neq_coords = true;
}
else
{
res_b1_a1 = inverse_dist_azi::apply(b1_lon, b1_lat, a1_lon, a1_lat, spheroid);
if (math::equals(res_b1_a1.distance, c0))
{
is_equal_a1_b1 = true;
}
res_b1_a2 = inverse_dist_azi::apply(b1_lon, b1_lat, a2_lon, a2_lat, spheroid);
if (math::equals(res_b1_a2.distance, c0))
{
is_equal_a2_b1 = true;
}
sides.set<0>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_b1_a1.azimuth, res_b1_b2.azimuth),
is_equal_a2_b1 ? 0 : formula::azimuth_side_value(res_b1_a2.azimuth, res_b1_b2.azimuth));
if (sides.same<0>())
{
// Both points are at the same side of other segment, we can leave
return Policy::disjoint();
}
}
}
bool const is_equal_a1_b2 = equals_point_point(a1, b2);
bool is_equal_a1_b2 = equals_point_point(a1, b2);
inverse_result res_a1_a2 = inverse_dist_azi::apply(a1_lon, a1_lat, a2_lon, a2_lat, spheroid);
inverse_result res_a1_b1 = inverse_dist_azi::apply(a1_lon, a1_lat, b1_lon, b1_lat, spheroid);
inverse_result res_a1_b2 = inverse_dist_azi::apply(a1_lon, a1_lat, b2_lon, b2_lat, spheroid);
sides.set<1>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_a1_b1.azimuth, res_a1_a2.azimuth),
is_equal_a1_b2 ? 0 : formula::azimuth_side_value(res_a1_b2.azimuth, res_a1_a2.azimuth));
if (sides.same<1>())
inverse_result res_a1_a2, res_a1_b1, res_a1_b2;
if (! a_is_point)
{
// Both points are at the same side of other segment, we can leave
return Policy::disjoint();
res_a1_a2 = inverse_dist_azi::apply(a1_lon, a1_lat, a2_lon, a2_lat, spheroid);
if (math::equals(res_a1_a2.distance, c0))
{
a_is_point = true;
degen_neq_coords = true;
}
else
{
res_a1_b1 = inverse_dist_azi::apply(a1_lon, a1_lat, b1_lon, b1_lat, spheroid);
if (math::equals(res_a1_b1.distance, c0))
{
is_equal_a1_b1 = true;
}
res_a1_b2 = inverse_dist_azi::apply(a1_lon, a1_lat, b2_lon, b2_lat, spheroid);
if (math::equals(res_a1_b2.distance, c0))
{
is_equal_a1_b2 = true;
}
sides.set<1>(is_equal_a1_b1 ? 0 : formula::azimuth_side_value(res_a1_b1.azimuth, res_a1_a2.azimuth),
is_equal_a1_b2 ? 0 : formula::azimuth_side_value(res_a1_b2.azimuth, res_a1_a2.azimuth));
if (sides.same<1>())
{
// Both points are at the same side of other segment, we can leave
return Policy::disjoint();
}
}
}
if(a_is_point && b_is_point)
{
return is_equal_a1_b2
? Policy::degenerate(a, true)
: Policy::disjoint()
;
}
// NOTE: at this point the segments may still be disjoint
@@ -379,11 +430,11 @@ private:
{
if (a_is_point)
{
return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, res_b1_b2, res_b1_a1, is_b_reversed);
return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, res_b1_b2, res_b1_a1, res_b1_a2, is_b_reversed, degen_neq_coords);
}
else if (b_is_point)
{
return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, res_a1_a2, res_a1_b1, is_a_reversed);
return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, is_a_reversed, degen_neq_coords);
}
else
{
@@ -392,16 +443,16 @@ private:
// use shorter segment
if (res_a1_a2.distance <= res_b1_b2.distance)
{
calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, dist_a1_a2, dist_a1_b1);
calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, dist_a1_a2, dist_a1_b2);
calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, dist_a1_a2, dist_a1_b1);
calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, res_a1_b1, dist_a1_a2, dist_a1_b2);
dist_b1_b2 = dist_a1_b2 - dist_a1_b1;
dist_b1_a1 = -dist_a1_b1;
dist_b1_a2 = dist_a1_a2 - dist_a1_b1;
}
else
{
calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, dist_b1_b2, dist_b1_a1);
calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, dist_b1_b2, dist_b1_a2);
calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, res_b1_a2, dist_b1_b2, dist_b1_a1);
calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, res_b1_a1, dist_b1_b2, dist_b1_a2);
dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
dist_a1_b1 = -dist_b1_a1;
dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
@@ -549,11 +600,13 @@ private:
Point1 const& a1, Point1 const& a2,
Point2 const& b1, Point2 const& b2,
ResultInverse const& res_a1_a2,
ResultInverse const& res_a1_bi,
bool is_other_reversed)
ResultInverse const& res_a1_b1,
ResultInverse const& res_a1_b2,
bool is_other_reversed,
bool degen_neq_coords)
{
CalcT dist_1_2, dist_1_o;
if (! calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_bi, dist_1_2, dist_1_o))
if (! calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, dist_1_2, dist_1_o, degen_neq_coords))
{
return Policy::disjoint();
}
@@ -574,13 +627,16 @@ private:
static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in
Point2 const& b1, Point2 const& b2, // in
ResultInverse const& res_a1_a2, // in
ResultInverse const& res_a1_bi, // in
CalcT& dist_a1_a2, CalcT& dist_a1_bi) // out
ResultInverse const& res_a1_b1, // in
ResultInverse const& res_a1_b2, // in
CalcT& dist_a1_a2, // out
CalcT& dist_a1_bi, // out
bool degen_neq_coords = false) // in
{
dist_a1_a2 = res_a1_a2.distance;
dist_a1_bi = res_a1_bi.distance;
if (! same_direction(res_a1_bi.azimuth, res_a1_a2.azimuth))
dist_a1_bi = res_a1_b1.distance;
if (! same_direction(res_a1_b1.azimuth, res_a1_a2.azimuth))
{
dist_a1_bi = -dist_a1_bi;
}
@@ -598,6 +654,22 @@ private:
return true;
}
// check the other endpoint of a very short segment near the pole
if (degen_neq_coords)
{
static CalcT const c0 = 0;
if (math::equals(res_a1_b2.distance, c0))
{
dist_a1_bi = 0;
return true;
}
else if (math::equals(dist_a1_a2 - res_a1_b2.distance, c0))
{
dist_a1_bi = dist_a1_a2;
return true;
}
}
// or i1 is on b
return segment_ratio<CalcT>(dist_a1_bi, dist_a1_a2).on_segment();
}
@@ -825,8 +897,9 @@ private:
static inline bool is_endpoint_equal(CalcT const& dist,
P1 const& ai, P2 const& b1, P2 const& b2)
{
static CalcT const c0 = 0;
using geometry::detail::equals::equals_point_point;
return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2));
return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2) || math::equals(dist, c0));
}
template <typename CalcT>

View File

@@ -302,36 +302,64 @@ struct ecef_segments
vec3d_t const b1v = calc_policy.template to_cart3d<vec3d_t>(b1);
vec3d_t const b2v = calc_policy.template to_cart3d<vec3d_t>(b2);
bool degen_neq_coords = false;
side_info sides;
typename CalcPolicy::template plane<vec3d_t>
plane2 = calc_policy.get_plane(b1v, b2v);
// not normalized normals, the same as in side strategy
sides.set<0>(plane2.side_value(a1v), plane2.side_value(a2v));
if (sides.same<0>())
calc_t dist_b1_b2 = 0;
if (! b_is_point)
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
calculate_dist(b1v, b2v, plane2, dist_b1_b2);
if (math::equals(dist_b1_b2, c0))
{
degen_neq_coords = true;
b_is_point = true;
dist_b1_b2 = 0;
}
else
{
// not normalized normals, the same as in side strategy
sides.set<0>(plane2.side_value(a1v), plane2.side_value(a2v));
if (sides.same<0>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
}
}
typename CalcPolicy::template plane<vec3d_t>
plane1 = calc_policy.get_plane(a1v, a2v);
// not normalized normals, the same as in side strategy
sides.set<1>(plane1.side_value(b1v), plane1.side_value(b2v));
if (sides.same<1>())
calc_t dist_a1_a2 = 0;
if (! a_is_point)
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
calculate_dist(a1v, a2v, plane1, dist_a1_a2);
if (math::equals(dist_a1_a2, c0))
{
degen_neq_coords = true;
a_is_point = true;
dist_a1_a2 = 0;
}
else
{
// not normalized normals, the same as in side strategy
sides.set<1>(plane1.side_value(b1v), plane1.side_value(b2v));
if (sides.same<1>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
}
}
// NOTE: at this point the segments may still be disjoint
calc_t len1, len2;
calc_t len1 = 0;
// point or opposite sides of a sphere/spheroid, assume point
if (! detail::vec_normalize(plane1.normal, len1))
if (! a_is_point && ! detail::vec_normalize(plane1.normal, len1))
{
a_is_point = true;
if (sides.get<0, 0>() == 0 || sides.get<0, 1>() == 0)
@@ -340,7 +368,8 @@ struct ecef_segments
}
}
if (! detail::vec_normalize(plane2.normal, len2))
calc_t len2 = 0;
if (! b_is_point && ! detail::vec_normalize(plane2.normal, len2))
{
b_is_point = true;
if (sides.get<1, 0>() == 0 || sides.get<1, 1>() == 0)
@@ -404,30 +433,32 @@ struct ecef_segments
{
if (a_is_point)
{
return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, b1v, b2v, plane2, a1v);
return collinear_one_degenerated<Policy, calc_t>(a, true, b1, b2, a1, a2, b1v, b2v,
plane2, a1v, a2v, dist_b1_b2, degen_neq_coords);
}
else if (b_is_point)
{
// b2 used to be consistent with (degenerated) checks above (is it needed?)
return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, a1v, a2v, plane1, b1v);
return collinear_one_degenerated<Policy, calc_t>(b, false, a1, a2, b1, b2, a1v, a2v,
plane1, b1v, b2v, dist_a1_a2, degen_neq_coords);
}
else
{
calc_t dist_a1_a2, dist_a1_b1, dist_a1_b2;
calc_t dist_b1_b2, dist_b1_a1, dist_b1_a2;
calc_t dist_a1_b1, dist_a1_b2;
calc_t dist_b1_a1, dist_b1_a2;
// use shorter segment
if (len1 <= len2)
{
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b1v, dist_a1_a2, dist_a1_b1);
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b2v, dist_a1_a2, dist_a1_b2);
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b1v, b2v, dist_a1_a2, dist_a1_b1);
calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane1, b2v, b1v, dist_a1_a2, dist_a1_b2);
dist_b1_b2 = dist_a1_b2 - dist_a1_b1;
dist_b1_a1 = -dist_a1_b1;
dist_b1_a2 = dist_a1_a2 - dist_a1_b1;
}
else
{
calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a1v, dist_b1_b2, dist_b1_a1);
calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a2v, dist_b1_b2, dist_b1_a2);
calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a1v, a2v, dist_b1_b2, dist_b1_a1);
calculate_collinear_data(b1, b2, a1, a2, b1v, b2v, plane2, a2v, a1v, dist_b1_b2, dist_b1_a2);
dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
dist_a1_b1 = -dist_b1_a1;
dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
@@ -487,10 +518,11 @@ struct ecef_segments
vec3d_t i1;
intersection_point_flag ip_flag;
calc_t dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1;
calc_t dist_a1_i1, dist_b1_i1;
if (calculate_ip_data(a1, a2, b1, b2, a1v, a2v, b1v, b2v,
plane1, plane2, calc_policy, sides,
i1, dist_a1_a2, dist_a1_i1, dist_b1_b2, dist_b1_i1, ip_flag))
plane1, plane2, calc_policy,
sides, dist_a1_a2, dist_b1_b2,
i1, dist_a1_i1, dist_b1_i1, ip_flag))
{
// intersects
segment_intersection_info
@@ -520,12 +552,14 @@ private:
collinear_one_degenerated(Segment const& segment, bool degenerated_a,
Point1 const& a1, Point1 const& a2,
Point2 const& b1, Point2 const& b2,
Vec3d const& v1, Vec3d const& v2,
Vec3d const& a1v, Vec3d const& a2v,
Plane const& plane,
Vec3d const& vother)
Vec3d const& b1v, Vec3d const& b2v,
CalcT const& dist_1_2,
bool degen_neq_coords)
{
CalcT dist_1_2, dist_1_o;
return ! calculate_collinear_data(a1, a2, b1, b2, v1, v2, plane, vother, dist_1_2, dist_1_o)
CalcT dist_1_o;
return ! calculate_collinear_data(a1, a2, b1, b2, a1v, a2v, plane, b1v, b2v, dist_1_2, dist_1_o, degen_neq_coords)
? Policy::disjoint()
: Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);
}
@@ -536,11 +570,14 @@ private:
Vec3d const& a1v, // in
Vec3d const& a2v, // in
Plane const& plane1, // in
Vec3d const& b1v_or_b2v, // in
CalcT& dist_a1_a2, CalcT& dist_a1_i1) // out
Vec3d const& b1v, // in
Vec3d const& b2v, // in
CalcT const& dist_a1_a2, // in
CalcT& dist_a1_i1, // out
bool degen_neq_coords = false) // in
{
// calculate dist_a1_a2 and dist_a1_i1
calculate_dists(a1v, a2v, plane1, b1v_or_b2v, dist_a1_a2, dist_a1_i1);
calculate_dist(a1v, a2v, plane1, b1v, dist_a1_i1);
// if i1 is close to a1 and b1 or b2 is equal to a1
if (is_endpoint_equal(dist_a1_i1, a1, b1, b2))
@@ -555,6 +592,26 @@ private:
return true;
}
// check the other endpoint of a very short segment near the pole
if (degen_neq_coords)
{
static CalcT const c0 = 0;
CalcT dist_a1_i2 = 0;
calculate_dist(a1v, a2v, plane1, b2v, dist_a1_i2);
if (math::equals(dist_a1_i2, c0))
{
dist_a1_i1 = 0;
return true;
}
else if (math::equals(dist_a1_a2 - dist_a1_i2, c0))
{
dist_a1_i1 = dist_a1_a2;
return true;
}
}
// or i1 is on b
return segment_ratio<CalcT>(dist_a1_i1, dist_a1_a2).on_segment();
}
@@ -568,15 +625,17 @@ private:
Plane const& plane2, // in
CalcPolicy const& calc_policy, // in
side_info const& sides, // in
Vec3d & ip, // out
CalcT& dist_a1_a2, CalcT& dist_a1_ip, // out
CalcT& dist_b1_b2, CalcT& dist_b1_ip, // out
intersection_point_flag& ip_flag) // out
CalcT const& dist_a1_a2, // in
CalcT const& dist_b1_b2, // in
Vec3d & ip, // out
CalcT& dist_a1_ip, // out
CalcT& dist_b1_ip, // out
intersection_point_flag& ip_flag) // out
{
Vec3d ip1, ip2;
calc_policy.intersection_points(plane1, plane2, ip1, ip2);
calculate_dists(a1v, a2v, plane1, ip1, dist_a1_a2, dist_a1_ip);
calculate_dist(a1v, a2v, plane1, ip1, dist_a1_ip);
ip = ip1;
// choose the opposite side of the globe if the distance is shorter
@@ -602,7 +661,7 @@ private:
return false;
}
calculate_dists(b1v, b2v, plane2, ip, dist_b1_b2, dist_b1_ip);
calculate_dist(b1v, b2v, plane2, ip, dist_b1_ip);
bool is_on_b = false, is_near_b1 = false, is_near_b2 = false;
if (! is_potentially_crossing(dist_b1_b2, dist_b1_ip, is_on_b, is_near_b1, is_near_b2))
@@ -701,20 +760,26 @@ private:
}
template <typename Vec3d, typename Plane, typename CalcT>
static inline void calculate_dists(Vec3d const& a1v, // in
Vec3d const& a2v, // in
Plane const& plane1, // in
Vec3d const& i1, // in
CalcT& dist_a1_a2, // out
CalcT& dist_a1_i1) // out
static inline void calculate_dist(Vec3d const& a1v, // in
Vec3d const& a2v, // in
Plane const& plane1, // in
CalcT& dist_a1_a2) // out
{
//CalcT const c0 = 0;
CalcT const c1 = 1;
CalcT const c2 = 2;
CalcT const c4 = 4;
CalcT cos_a1_a2 = plane1.cos_angle_between(a1v, a2v);
static CalcT const c1 = 1;
CalcT const cos_a1_a2 = plane1.cos_angle_between(a1v, a2v);
dist_a1_a2 = -cos_a1_a2 + c1; // [1, -1] -> [0, 2] representing [0, pi]
}
template <typename Vec3d, typename Plane, typename CalcT>
static inline void calculate_dist(Vec3d const& a1v, // in
Vec3d const& /*a2v*/, // in
Plane const& plane1, // in
Vec3d const& i1, // in
CalcT& dist_a1_i1) // out
{
static CalcT const c1 = 1;
static CalcT const c2 = 2;
static CalcT const c4 = 4;
bool is_forward = true;
CalcT cos_a1_i1 = plane1.cos_angle_between(a1v, i1, is_forward);
@@ -728,7 +793,19 @@ private:
dist_a1_i1 += c4; // += 2pi
}
}
/*
template <typename Vec3d, typename Plane, typename CalcT>
static inline void calculate_dists(Vec3d const& a1v, // in
Vec3d const& a2v, // in
Plane const& plane1, // in
Vec3d const& i1, // in
CalcT& dist_a1_a2, // out
CalcT& dist_a1_i1) // out
{
calculate_dist(a1v, a2v, plane1, dist_a1_a2);
calculate_dist(a1v, a2v, plane1, i1, dist_a1_i1);
}
*/
// the dist of the ip on the other side of the sphere
template <typename CalcT>
static inline CalcT dist_of_i2(CalcT const& dist_a1_i1)
@@ -769,8 +846,9 @@ private:
static inline bool is_endpoint_equal(CalcT const& dist,
P1 const& ai, P2 const& b1, P2 const& b2)
{
static CalcT const c0 = 0;
using geometry::detail::equals::equals_point_point;
return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2));
return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2) || math::equals(dist, c0));
}
template <typename CalcT>

View File

@@ -963,6 +963,12 @@ inline void test_open_multipolygons()
"MULTIPOLYGON(((10 5,5 10,0 5,5 0),(10 5,5 4,4 6)),((10 5,10 0,20 0,20 10,10 10),(10 5,18 8,15 3)))",
true);
// Two polygons, one inside interior of other one, touching all at same point (0,0)
test::apply
("mpg23",
"MULTIPOLYGON(((0 0,10 0,10 10,0 10),(0 0,1 9,9 9,9 1)),((0 0,8 2,8 8,2 8)))",
true);
// MySQL report 12.06.2015
{
std::string wkt = "MULTIPOLYGON("
@@ -1186,11 +1192,8 @@ inline void test_open_multipolygons()
BOOST_AUTO_TEST_CASE( test_is_valid_multipolygon )
{
bool const allow_duplicates = true;
bool const do_not_allow_duplicates = !allow_duplicates;
test_open_multipolygons<point_type, allow_duplicates>();
test_open_multipolygons<point_type, do_not_allow_duplicates>();
test_open_multipolygons<point_type, true>();
test_open_multipolygons<point_type, false>();
}

View File

@@ -36,6 +36,7 @@ void test_with_point(std::string const& caseid,
T pi_x, T pi_y, T pj_x, T pj_y, T pk_x, T pk_y,
T qi_x, T qi_y, T qj_x, T qj_y, T qk_x, T qk_y,
bg::detail::overlay::method_type expected_method,
bool expected_touch_only,
T ip_x, T ip_y,
std::string const& expected,
T ip_x2, T ip_y2)
@@ -100,6 +101,10 @@ void test_with_point(std::string const& caseid,
if (! info.empty())
{
BOOST_CHECK_EQUAL(info[0].method, expected_method);
BOOST_CHECK_MESSAGE(info[0].touch_only == expected_touch_only,
caseid
<< " detected: " << info[0].touch_only
<< " expected: " << expected_touch_only);
BOOST_CHECK_CLOSE(bg::get<0>(info[0].point), ip_x, 0.001);
BOOST_CHECK_CLOSE(bg::get<1>(info[0].point), ip_y, 0.001);
@@ -164,6 +169,8 @@ void test_with_point(std::string const& caseid,
op.clear();
op += bg::method_char(it->method);
op += ' ';
op += (it->touch_only ? 'o' : '*');
if (info.size() != 1)
{
op += ch;
@@ -183,6 +190,7 @@ void test_both(std::string const& caseid,
T qi_x, T qi_y, T qj_x, T qj_y, T qk_x, T qk_y,
bg::detail::overlay::method_type method
= bg::detail::overlay::method_none,
bool expected_touch_only = false,
T ip_x = -1, T ip_y = -1,
std::string const& expected = "",
T ip_x2 = -1, T ip_y2 = -1)
@@ -190,9 +198,7 @@ void test_both(std::string const& caseid,
test_with_point<P, double>(caseid,
pi_x, pi_y, pj_x, pj_y, pk_x, pk_y,
qi_x, qi_y, qj_x, qj_y, qk_x, qk_y,
method, ip_x, ip_y, expected, ip_x2, ip_y2);
//return;
method, expected_touch_only, ip_x, ip_y, expected, ip_x2, ip_y2);
std::string reversed(expected.rbegin(), expected.rend());
@@ -205,7 +211,7 @@ void test_both(std::string const& caseid,
test_with_point<P, double>(caseid + "_r",
qi_x, qi_y, qj_x, qj_y, qk_x, qk_y, // q
pi_x, pi_y, pj_x, pj_y, pk_x, pk_y, // p
method, ip_x, ip_y, reversed, ip_x2, ip_y2);
method, expected_touch_only, ip_x, ip_y, reversed, ip_x2, ip_y2);
}
@@ -223,27 +229,27 @@ void test_all()
test_both<P, double>("il1",
5, 1, 5, 6, 7, 8, // p
3, 3, 7, 5, 8, 3, // q
method_crosses, 5, 4, "ui");
method_crosses, false, 5, 4, "ui");
test_both<P, double>("il2",
5, 1, 5, 6, 7, 8, // p
3, 5, 7, 5, 3, 3, // q
method_crosses, 5, 5, "ui");
method_crosses, false, 5, 5, "ui");
test_both<P, double>("il3",
5, 1, 5, 6, 7, 8, // p
3, 3, 7, 5, 3, 5, // q
method_crosses, 5, 4, "ui");
method_crosses, false, 5, 4, "ui");
test_both<P, double>("il4",
5, 1, 5, 6, 7, 8, // p
3, 3, 7, 5, 4, 8, // q
method_crosses, 5, 4, "ui");
method_crosses, false, 5, 4, "ui");
test_both<P, double>("ir1",
5, 1, 5, 6, 7, 8, // p
7, 5, 3, 3, 2, 5, // q
method_crosses, 5, 4, "iu");
method_crosses, false, 5, 4, "iu");
// ------------------------------------------------------------------------
@@ -252,52 +258,52 @@ void test_all()
test_both<P, double>("ml1",
5, 1, 5, 6, 7, 8, // p
3, 3, 5, 4, 7, 3, // q
method_touch_interior, 5, 4, "ui");
method_touch_interior, false, 5, 4, "ui");
test_both<P, double>("ml2",
5, 1, 5, 6, 7, 8, // p
3, 3, 5, 4, 3, 6, // q
method_touch_interior, 5, 4, "iu");
method_touch_interior, true, 5, 4, "iu");
test_both<P, double>("ml3",
5, 1, 5, 6, 7, 8, // p
3, 6, 5, 4, 3, 3, // q
method_touch_interior, 5, 4, "uu");
method_touch_interior, true, 5, 4, "uu");
test_both<P, double>("mr1",
5, 1, 5, 6, 7, 8, // p
7, 3, 5, 4, 3, 3, // q
method_touch_interior, 5, 4, "iu");
method_touch_interior, false, 5, 4, "iu");
test_both<P, double>("mr2",
5, 1, 5, 6, 7, 8, // p
7, 3, 5, 4, 7, 6, // q
method_touch_interior, 5, 4, "ui");
method_touch_interior, true, 5, 4, "ui");
test_both<P, double>("mr3",
5, 1, 5, 6, 7, 8, // p
7, 6, 5, 4, 7, 3, // q
method_touch_interior, 5, 4, "ii");
method_touch_interior, true, 5, 4, "ii");
test_both<P, double>("mcl",
5, 1, 5, 6, 7, 8, // p
3, 2, 5, 3, 5, 5, // q
method_touch_interior, 5, 3, "cc");
method_touch_interior, false, 5, 3, "cc");
test_both<P, double>("mcr",
5, 1, 5, 6, 7, 8, // p
7, 2, 5, 3, 5, 5, // q
method_touch_interior, 5, 3, "cc");
method_touch_interior, false, 5, 3, "cc");
test_both<P, double>("mclo",
5, 1, 5, 6, 7, 8, // p
3, 4, 5, 5, 5, 3, // q
method_touch_interior, 5, 5, "ux");
method_touch_interior, false, 5, 5, "ux");
test_both<P, double>("mcro",
5, 1, 5, 6, 7, 8, // p
7, 4, 5, 5, 5, 3, // q
method_touch_interior, 5, 5, "ix");
method_touch_interior, false, 5, 5, "ix");
// ------------------------------------------------------------------------
// COLLINEAR
@@ -305,53 +311,53 @@ void test_all()
test_both<P, double>("cll1",
5, 1, 5, 6, 3, 8, // p
5, 5, 5, 7, 3, 8, // q
method_collinear, 5, 6, "ui");
method_collinear, false, 5, 6, "ui");
test_both<P, double>("cll2",
5, 1, 5, 6, 3, 8, // p
5, 3, 5, 5, 3, 6, // q
method_collinear, 5, 5, "iu");
method_collinear, false, 5, 5, "iu");
test_both<P, double>("clr1",
5, 1, 5, 6, 3, 8, // p
5, 5, 5, 7, 6, 8, // q
method_collinear, 5, 6, "ui");
method_collinear, false, 5, 6, "ui");
test_both<P, double>("clr2",
5, 1, 5, 6, 3, 8, // p
5, 3, 5, 5, 6, 6, // q
method_collinear, 5, 5, "ui");
method_collinear, false, 5, 5, "ui");
test_both<P, double>("crl1",
5, 1, 5, 6, 7, 8, // p
5, 5, 5, 7, 3, 8, // q
method_collinear, 5, 6, "iu");
method_collinear, false, 5, 6, "iu");
test_both<P, double>("crl2",
5, 1, 5, 6, 7, 8, // p
5, 3, 5, 5, 3, 6, // q
method_collinear, 5, 5, "iu");
method_collinear, false, 5, 5, "iu");
test_both<P, double>("crr1",
5, 1, 5, 6, 7, 8, // p
5, 5, 5, 7, 6, 8, // q
method_collinear, 5, 6, "iu");
method_collinear, false, 5, 6, "iu");
test_both<P, double>("crr2",
5, 1, 5, 6, 7, 8, // p
5, 3, 5, 5, 6, 6, // q
method_collinear, 5, 5, "ui");
method_collinear, false, 5, 5, "ui");
// The next two cases are changed (BSG 2013-09-24), they contain turn info (#buffer_rt_g)
// In new approach they are changed back (BSG 2013-10-20)
test_both<P, double>("ccx1",
5, 1, 5, 6, 5, 8, // p
5, 5, 5, 7, 3, 8, // q
method_collinear, 5, 6, "cc"); // "iu");
method_collinear, false, 5, 6, "cc"); // "iu");
test_both<P, double>("cxc1",
5, 1, 5, 6, 7, 8, // p
5, 3, 5, 5, 5, 7, // q
method_collinear, 5, 5, "cc"); // "iu");
method_collinear, false, 5, 5, "cc"); // "iu");
// Bug in case #54 of "overlay_cases.hpp"
test_both<P, double>("c_bug1",
5, 0, 2, 0, 2, 2, // p
4, 0, 1, 0, 1, 2, // q
method_collinear, 2, 0, "iu");
method_collinear, false, 2, 0, "iu");
// ------------------------------------------------------------------------
@@ -361,66 +367,66 @@ void test_all()
test_both<P, double>("clo1",
5, 2, 5, 6, 3, 8, // p
5, 7, 5, 5, 3, 3, // q
method_collinear, 5, 6, "ixxu", 5, 5);
method_collinear, false, 5, 6, "ixxu", 5, 5);
test_both<P, double>("clo2",
5, 2, 5, 6, 3, 8, // p
5, 7, 5, 5, 5, 2, // q
method_collinear, 5, 6, "ix");
method_collinear, false, 5, 6, "ix");
// actually "xxix", xx is skipped everywhere
test_both<P, double>("clo3",
5, 2, 5, 6, 3, 8, // p
5, 7, 5, 5, 7, 3, // q
method_collinear, 5, 6, "ixxi", 5, 5);
method_collinear, false, 5, 6, "ixxi", 5, 5);
test_both<P, double>("cco1",
5, 2, 5, 6, 5, 8, // p
5, 7, 5, 5, 3, 3, // q
method_collinear, 5, 5, "xu"); // "xuxx"
method_collinear, false, 5, 5, "xu"); // "xuxx"
test_both<P, double>("cco2",
5, 2, 5, 6, 5, 8, // p
5, 7, 5, 5, 5, 2); // q "xxxx"
test_both<P, double>("cco3",
5, 2, 5, 6, 5, 8, // p
5, 7, 5, 5, 7, 3, // q
method_collinear, 5, 5, "xi"); // "xixx"
method_collinear, false, 5, 5, "xi"); // "xixx"
test_both<P, double>("cro1",
5, 2, 5, 6, 7, 8, // p
5, 7, 5, 5, 3, 3, // q
method_collinear, 5, 6, "uxxu", 5, 5);
method_collinear, false, 5, 6, "uxxu", 5, 5);
test_both<P, double>("cro2",
5, 2, 5, 6, 7, 8, // p
5, 7, 5, 5, 5, 2, // q
method_collinear, 5, 6, "ux"); // "xxux"
method_collinear, false, 5, 6, "ux"); // "xxux"
test_both<P, double>("cro3",
5, 2, 5, 6, 7, 8, // p
5, 7, 5, 5, 7, 3, // q
method_collinear, 5, 6, "uxxi", 5, 5);
method_collinear, false, 5, 6, "uxxi", 5, 5);
test_both<P, double>("cxo1",
5, 2, 5, 6, 3, 8, // p
5, 5, 5, 3, 3, 1, // q
method_collinear, 5, 3, "xu");
method_collinear, false, 5, 3, "xu");
test_both<P, double>("cxo2",
5, 2, 5, 6, 3, 8, // p
5, 5, 5, 3, 5, 0); // q "xx"
test_both<P, double>("cxo3",
5, 2, 5, 6, 3, 8, // p
5, 5, 5, 3, 7, 1, // q
method_collinear, 5, 3, "xi");
method_collinear, false, 5, 3, "xi");
test_both<P, double>("cxo4",
5, 2, 5, 6, 3, 8, // p
5, 7, 5, 1, 3, 0, // q
method_collinear, 5, 6, "ix");
method_collinear, false, 5, 6, "ix");
test_both<P, double>("cxo5",
5, 2, 5, 6, 5, 8, // p
5, 7, 5, 1, 3, 0); // q "xx"
test_both<P, double>("cxo6",
5, 2, 5, 6, 7, 8, // p
5, 7, 5, 1, 3, 0, // q
method_collinear, 5, 6, "ux");
method_collinear, false, 5, 6, "ux");
// Verify
@@ -441,61 +447,61 @@ void test_all()
test_both<P, double>("blr1",
5, 1, 5, 6, 4, 4, // p
3, 7, 5, 6, 3, 5, // q
method_touch, 5, 6, "ui");
method_touch, true, 5, 6, "ui");
test_both<P, double>("blr2",
5, 1, 5, 6, 1, 4, // p
3, 7, 5, 6, 3, 5, // q
method_touch, 5, 6, "cc");
method_touch, false, 5, 6, "cc");
test_both<P, double>("blr3",
5, 1, 5, 6, 3, 6, // p
3, 7, 5, 6, 3, 5, // q
method_touch, 5, 6, "iu");
method_touch, false, 5, 6, "iu");
test_both<P, double>("blr4",
5, 1, 5, 6, 1, 8, // p
3, 7, 5, 6, 3, 5, // q
method_touch, 5, 6, "xu");
method_touch, false, 5, 6, "xu");
test_both<P, double>("blr5",
5, 1, 5, 6, 4, 8, // p
3, 7, 5, 6, 3, 5, // q
method_touch, 5, 6, "uu");
method_touch, true, 5, 6, "uu");
test_both<P, double>("blr6",
5, 1, 5, 6, 6, 4, // p
3, 7, 5, 6, 3, 5, // q
method_touch, 5, 6, "uu");
method_touch, true, 5, 6, "uu");
test_both<P, double>("blr7",
5, 1, 5, 6, 3, 6, // p
3, 7, 5, 6, 5, 3, // q
method_touch, 5, 6, "ix");
method_touch, false, 5, 6, "ix");
test_both<P, double>("blr8",
5, 1, 5, 6, 3, 6, // p
3, 6, 5, 6, 5, 3, // q
method_touch, 5, 6, "xx");
method_touch, false, 5, 6, "xx");
test_both<P, double>("blr9",
5, 1, 5, 6, 3, 6, // p
3, 5, 5, 6, 5, 3, // q
method_touch, 5, 6, "ux");
method_touch, false, 5, 6, "ux");
// Variants
test_both<P, double>("blr7-a",
5, 1, 5, 6, 3, 6, // p
5, 8, 5, 6, 5, 3, // q
method_touch, 5, 6, "ix");
method_touch, false, 5, 6, "ix");
test_both<P, double>("blr7-b", // in fact NOT "both-left"
5, 1, 5, 6, 3, 6, // p
6, 8, 5, 6, 5, 3, // q
method_touch, 5, 6, "ix");
method_touch, false, 5, 6, "ix");
// To check if "collinear-check" on other side
// does not apply to this side
test_both<P, double>("blr6-c1",
5, 1, 5, 6, 7, 5, // p
3, 7, 5, 6, 3, 5, // q
method_touch, 5, 6, "uu");
method_touch, true, 5, 6, "uu");
test_both<P, double>("blr6-c2",
5, 1, 5, 6, 7, 7, // p
3, 7, 5, 6, 3, 5, // q
method_touch, 5, 6, "uu");
method_touch, true, 5, 6, "uu");
@@ -503,75 +509,75 @@ void test_all()
test_both<P, double>("brr1",
5, 1, 5, 6, 6, 4, // p
7, 5, 5, 6, 7, 7, // q
method_touch, 5, 6, "uu");
method_touch, true, 5, 6, "uu");
test_both<P, double>("brr2",
5, 1, 5, 6, 9, 4, // p
7, 5, 5, 6, 7, 7, // q
method_touch, 5, 6, "xu");
method_touch, false, 5, 6, "xu");
test_both<P, double>("brr3",
5, 1, 5, 6, 7, 6, // p
7, 5, 5, 6, 7, 7, // q
method_touch, 5, 6, "iu");
method_touch, false, 5, 6, "iu");
test_both<P, double>("brr4",
5, 1, 5, 6, 9, 8, // p
7, 5, 5, 6, 7, 7, // q
method_touch, 5, 6, "cc");
method_touch, false, 5, 6, "cc");
test_both<P, double>("brr5",
5, 1, 5, 6, 6, 8, // p
7, 5, 5, 6, 7, 7, // q
method_touch, 5, 6, "ui");
method_touch, true, 5, 6, "ui");
test_both<P, double>("brr6",
5, 1, 5, 6, 4, 4, // p
7, 5, 5, 6, 7, 7, // q
method_touch, 5, 6, "ui");
method_touch, true, 5, 6, "ui");
// Both right, Q turns left
test_both<P, double>("brl1",
5, 1, 5, 6, 6, 4, // p
7, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "iu");
method_touch, true, 5, 6, "iu");
test_both<P, double>("brl2",
5, 1, 5, 6, 9, 4, // p
7, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "cc");
method_touch, false, 5, 6, "cc");
test_both<P, double>("brl3",
5, 1, 5, 6, 7, 6, // p
7, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "ui");
method_touch, false, 5, 6, "ui");
test_both<P, double>("brl4",
5, 1, 5, 6, 9, 8, // p
7, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "xi");
method_touch, false, 5, 6, "xi");
test_both<P, double>("brl5",
5, 1, 5, 6, 6, 8, // p
7, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "ii");
method_touch, true, 5, 6, "ii");
test_both<P, double>("brl6",
5, 1, 5, 6, 4, 4, // p
7, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "ii");
method_touch, true, 5, 6, "ii");
test_both<P, double>("brl7",
5, 1, 5, 6, 7, 6, // p
7, 7, 5, 6, 5, 3, // q
method_touch, 5, 6, "ux");
method_touch, false, 5, 6, "ux");
test_both<P, double>("brl8",
5, 1, 5, 6, 7, 6, // p
7, 6, 5, 6, 5, 3, // q
method_touch, 5, 6, "xx");
method_touch, false, 5, 6, "xx");
test_both<P, double>("brl9",
5, 1, 5, 6, 7, 6, // p
7, 5, 5, 6, 5, 3, // q
method_touch, 5, 6, "ix");
method_touch, false, 5, 6, "ix");
// Variants
test_both<P, double>("brl7-a",
5, 1, 5, 6, 7, 6, // p
5, 8, 5, 6, 5, 3, // q
method_touch, 5, 6, "ux");
method_touch, false, 5, 6, "ux");
test_both<P, double>("brl7-b", // in fact NOT "both right"
5, 1, 5, 6, 7, 6, // p
4, 8, 5, 6, 5, 3, // q
method_touch, 5, 6, "ux");
method_touch, false, 5, 6, "ux");
@@ -579,251 +585,251 @@ void test_all()
test_both<P, double>("bll1",
5, 1, 5, 6, 4, 4, // p
3, 5, 5, 6, 3, 7, // q
method_touch, 5, 6, "ii");
method_touch, true, 5, 6, "ii");
test_both<P, double>("bll2",
5, 1, 5, 6, 1, 4, // p
3, 5, 5, 6, 3, 7, // q
method_touch, 5, 6, "xi");
method_touch, false, 5, 6, "xi");
test_both<P, double>("bll3",
5, 1, 5, 6, 3, 6, // p
3, 5, 5, 6, 3, 7, // q
method_touch, 5, 6, "ui");
method_touch, false, 5, 6, "ui");
test_both<P, double>("bll4",
5, 1, 5, 6, 1, 8, // p
3, 5, 5, 6, 3, 7, // q
method_touch, 5, 6, "cc");
method_touch, false, 5, 6, "cc");
test_both<P, double>("bll5",
5, 1, 5, 6, 4, 8, // p
3, 5, 5, 6, 3, 7, // q
method_touch, 5, 6, "iu");
method_touch, true, 5, 6, "iu");
test_both<P, double>("bll6",
5, 1, 5, 6, 6, 4, // p
3, 5, 5, 6, 3, 7, // q
method_touch, 5, 6, "iu");
method_touch, true, 5, 6, "iu");
// TOUCH - COLLINEAR + one side
// Collinear/left, Q turns right
test_both<P, double>("t-clr1",
5, 1, 5, 6, 4, 4, // p
5, 8, 5, 6, 3, 5, // q
method_touch, 5, 6, "ui");
method_touch, true, 5, 6, "ui");
test_both<P, double>("t-clr2",
5, 1, 5, 6, 1, 4, // p
5, 8, 5, 6, 3, 5, // q
method_touch, 5, 6, "cc");
method_touch, false, 5, 6, "cc");
test_both<P, double>("t-clr3",
5, 1, 5, 6, 3, 6, // p
5, 8, 5, 6, 3, 5, // q
method_touch, 5, 6, "iu");
method_touch, false, 5, 6, "iu");
test_both<P, double>("t-clr4",
5, 1, 5, 6, 5, 8, // p
5, 8, 5, 6, 3, 5, // q
method_touch, 5, 6, "xu");
method_touch, false, 5, 6, "xu");
// 5 n.a.
test_both<P, double>("t-clr6",
5, 1, 5, 6, 6, 4, // p
5, 8, 5, 6, 3, 5, // q
method_touch, 5, 6, "uu");
method_touch, true, 5, 6, "uu");
// Collinear/right, Q turns right
test_both<P, double>("t-crr1",
5, 1, 5, 6, 6, 4, // p
7, 5, 5, 6, 5, 8, // q
method_touch, 5, 6, "uu");
method_touch, true, 5, 6, "uu");
test_both<P, double>("t-crr2",
5, 1, 5, 6, 9, 4, // p
7, 5, 5, 6, 5, 8, // q
method_touch, 5, 6, "xu");
method_touch, false, 5, 6, "xu");
test_both<P, double>("t-crr3",
5, 1, 5, 6, 7, 6, // p
7, 5, 5, 6, 5, 8, // q
method_touch, 5, 6, "iu");
method_touch, false, 5, 6, "iu");
test_both<P, double>("t-crr4",
5, 1, 5, 6, 5, 9, // p
7, 5, 5, 6, 5, 8, // q
method_touch, 5, 6, "cc");
method_touch, false, 5, 6, "cc");
// 5 n.a.
test_both<P, double>("t-crr6",
5, 1, 5, 6, 4, 4, // p
7, 5, 5, 6, 5, 8, // q
method_touch, 5, 6, "ui");
method_touch, true, 5, 6, "ui");
// Collinear/right, Q turns left
test_both<P, double>("t-crl1",
5, 1, 5, 6, 6, 4, // p
5, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "iu");
method_touch, true, 5, 6, "iu");
test_both<P, double>("t-crl2",
5, 1, 5, 6, 9, 4, // p
5, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "cc");
method_touch, false, 5, 6, "cc");
test_both<P, double>("t-crl3",
5, 1, 5, 6, 7, 6, // p
5, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "ui");
method_touch, false, 5, 6, "ui");
test_both<P, double>("t-crl4",
5, 1, 5, 6, 5, 8, // p
5, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "xi");
method_touch, false, 5, 6, "xi");
// 5 n.a.
test_both<P, double>("t-crl6",
5, 1, 5, 6, 4, 4, // p
5, 7, 5, 6, 7, 5, // q
method_touch, 5, 6, "ii");
method_touch, true, 5, 6, "ii");
// Collinear/left, Q turns left
test_both<P, double>("t-cll1",
5, 1, 5, 6, 4, 4, // p
3, 5, 5, 6, 5, 8, // q
method_touch, 5, 6, "ii");
method_touch, true, 5, 6, "ii");
test_both<P, double>("t-cll2",
5, 1, 5, 6, 1, 4, // p
3, 5, 5, 6, 5, 8, // q
method_touch, 5, 6, "xi");
method_touch, false, 5, 6, "xi");
test_both<P, double>("t-cll3",
5, 1, 5, 6, 3, 6, // p
3, 5, 5, 6, 5, 8, // q
method_touch, 5, 6, "ui");
method_touch, false, 5, 6, "ui");
test_both<P, double>("t-cll4",
5, 1, 5, 6, 5, 9, // p
3, 5, 5, 6, 5, 8, // q
method_touch, 5, 6, "cc");
method_touch, false, 5, 6, "cc");
// 5 n.a.
test_both<P, double>("t-cll6",
5, 1, 5, 6, 6, 4, // p
3, 5, 5, 6, 5, 8, // q
method_touch, 5, 6, "iu");
method_touch, true, 5, 6, "iu");
// Left to right
test_both<P, double>("lr1",
5, 1, 5, 6, 3, 3, // p
1, 5, 5, 6, 9, 5, // q
method_touch, 5, 6, "ii");
method_touch, true, 5, 6, "ii");
test_both<P, double>("lr2",
5, 1, 5, 6, 1, 5, // p
1, 5, 5, 6, 9, 5, // q
method_touch, 5, 6, "xi");
method_touch, false, 5, 6, "xi");
test_both<P, double>("lr3",
5, 1, 5, 6, 4, 8, // p
1, 5, 5, 6, 9, 5, // q
method_touch, 5, 6, "ui");
method_touch, false, 5, 6, "ui");
test_both<P, double>("lr4",
5, 1, 5, 6, 9, 5, // p
1, 5, 5, 6, 9, 5, // q
method_touch, 5, 6, "cc");
method_touch, false, 5, 6, "cc");
test_both<P, double>("lr5",
5, 1, 5, 6, 7, 3, // p
1, 5, 5, 6, 9, 5, // q
method_touch, 5, 6, "iu");
method_touch, true, 5, 6, "iu");
// otherwise case more thoroughly
test_both<P, double>("lr3a",
5, 1, 5, 6, 1, 6, // p
1, 5, 5, 6, 9, 5, // q
method_touch, 5, 6, "ui");
method_touch, false, 5, 6, "ui");
test_both<P, double>("lr3b",
5, 1, 5, 6, 5, 10, // p
1, 5, 5, 6, 9, 5, // q
method_touch, 5, 6, "ui");
method_touch, false, 5, 6, "ui");
test_both<P, double>("lr3c",
5, 1, 5, 6, 8, 9, // p
1, 5, 5, 6, 9, 5, // q
method_touch, 5, 6, "ui");
method_touch, false, 5, 6, "ui");
test_both<P, double>("lr3d",
5, 1, 5, 6, 9, 7, // p
1, 5, 5, 6, 9, 5, // q
method_touch, 5, 6, "ui");
method_touch, false, 5, 6, "ui");
test_both<P, double>("lr3e",
5, 1, 5, 6, 9, 6, // p
1, 5, 5, 6, 9, 5, // q
method_touch, 5, 6, "ui");
method_touch, false, 5, 6, "ui");
// Right to left
test_both<P, double>("rl1",
5, 1, 5, 6, 3, 3, // p
9, 5, 5, 6, 1, 5, // q
method_touch, 5, 6, "ui");
method_touch, true, 5, 6, "ui");
test_both<P, double>("rl2",
5, 1, 5, 6, 1, 5, // p
9, 5, 5, 6, 1, 5, // q
method_touch, 5, 6, "cc");
method_touch, false, 5, 6, "cc");
test_both<P, double>("rl3",
5, 1, 5, 6, 4, 8, // p
9, 5, 5, 6, 1, 5, // q
method_touch, 5, 6, "iu");
method_touch, false, 5, 6, "iu");
test_both<P, double>("rl4",
5, 1, 5, 6, 9, 5, // p
9, 5, 5, 6, 1, 5, // q
method_touch, 5, 6, "xu");
method_touch, false, 5, 6, "xu");
test_both<P, double>("rl5",
5, 1, 5, 6, 7, 3, // p
9, 5, 5, 6, 1, 5, // q
method_touch, 5, 6, "uu");
method_touch, true, 5, 6, "uu");
// Equal (p1/q1 are equal)
test_both<P, double>("ebl1",
5, 1, 5, 6, 3, 4, // p
5, 1, 5, 6, 3, 8, // q
method_equal, 5, 6, "ui");
method_equal, false, 5, 6, "ui");
test_both<P, double>("ebl2",
5, 1, 5, 6, 3, 8, // p
5, 1, 5, 6, 3, 4, // q
method_equal, 5, 6, "iu");
method_equal, false, 5, 6, "iu");
test_both<P, double>("ebl3",
5, 1, 5, 6, 3, 8, // p
5, 1, 5, 6, 3, 8, // q
method_equal, 5, 6, "cc");
method_equal, false, 5, 6, "cc");
test_both<P, double>("ebl3-c1",
5, 1, 5, 6, 10, 1, // p
5, 1, 5, 6, 3, 8, // q
method_equal, 5, 6, "iu");
method_equal, false, 5, 6, "iu");
test_both<P, double>("ebr1",
5, 1, 5, 6, 7, 4, // p
5, 1, 5, 6, 7, 8, // q
method_equal, 5, 6, "iu");
method_equal, false, 5, 6, "iu");
test_both<P, double>("ebr2",
5, 1, 5, 6, 7, 8, // p
5, 1, 5, 6, 7, 4, // q
method_equal, 5, 6, "ui");
method_equal, false, 5, 6, "ui");
test_both<P, double>("ebr3",
5, 1, 5, 6, 7, 8, // p
5, 1, 5, 6, 7, 8, // q
method_equal, 5, 6, "cc");
method_equal, false, 5, 6, "cc");
test_both<P, double>("ebr3-c1",
5, 1, 5, 6, 0, 1, // p
5, 1, 5, 6, 7, 8, // q
method_equal, 5, 6, "ui");
method_equal, false, 5, 6, "ui");
test_both<P, double>("elr1",
5, 1, 5, 6, 7, 8, // p
5, 1, 5, 6, 3, 8, // q
method_equal, 5, 6, "iu");
method_equal, false, 5, 6, "iu");
test_both<P, double>("elr2",
5, 1, 5, 6, 3, 8, // p
5, 1, 5, 6, 7, 8, // q
method_equal, 5, 6, "ui");
method_equal, false, 5, 6, "ui");
test_both<P, double>("ec1",
5, 1, 5, 6, 5, 8, // p
5, 1, 5, 6, 5, 8, // q
method_equal, 5, 6, "cc");
method_equal, false, 5, 6, "cc");
test_both<P, double>("ec2",
5, 1, 5, 6, 5, 8, // p
5, 1, 5, 6, 5, 7, // q
method_equal, 5, 6, "cc");
method_equal, false, 5, 6, "cc");
test_both<P, double>("snl-1",
0, 3, 2, 3, 4, 3, // p
4, 3, 2, 3, 0, 3, // q
method_touch, 2, 3, "xx");
method_touch, false, 2, 3, "xx");
// BSG 2012-05-26 to be decided what's the problem here and what it tests...
// Anyway, test results are not filled out.
//test_both<P, double>("issue_buffer_mill",
// 5.1983614873206241 , 6.7259025813913107 , 5.0499999999999998 , 6.4291796067500622 , 5.1983614873206241 , 6.7259025813913107, // p
// 5.0499999999999998 , 6.4291796067500622 , 5.0499999999999998 , 6.4291796067500622 , 5.1983614873206241 , 6.7259025813913107, // q
// method_collinear, 2, 0, "tt");
// method_collinear, false, 2, 0, "tt");
}

View File

@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
//
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017 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)
@@ -36,7 +41,11 @@ template
void test_geometry(std::string const& wkt1, std::string const& wkt2,
RingIdVector const& expected_ids)
{
typedef bg::detail::overlay::ring_properties<typename bg::point_type<Geometry1>::type> properties;
typedef bg::detail::overlay::ring_properties
<
typename bg::point_type<Geometry1>::type,
double
> properties;
Geometry1 geometry1;
Geometry2 geometry2;

View File

@@ -232,32 +232,24 @@ void test_all()
// Selection of test cases having only one cluster
TEST_INT(case_62_multi, list_of(1));
TEST_INT(case_63_multi, list_of(1));
TEST_INT(case_64_multi, list_of(1));
TEST_INT(case_72_multi, list_of(3));
TEST_INT(case_107_multi, list_of(2));
TEST_INT(case_123_multi, list_of(3));
TEST_INT(case_124_multi, list_of(3));
TEST_INT(case_recursive_boxes_1, list_of(2));
TEST_INT(case_recursive_boxes_10, list_of(2));
TEST_INT(case_recursive_boxes_18, list_of(0));
TEST_INT(case_recursive_boxes_19, list_of(0));
TEST_INT(case_recursive_boxes_20, list_of(2));
TEST_INT(case_recursive_boxes_21, list_of(1));
TEST_INT(case_recursive_boxes_22, list_of(0));
TEST_INT(case_recursive_boxes_23, list_of(1));
TEST_UNION(case_recursive_boxes_46, list_of(2)(1)(2)(1)(1)(2)(1));
TEST_UNION(case_62_multi, list_of(2));
TEST_UNION(case_63_multi, list_of(2));
TEST_UNION(case_64_multi, list_of(1));
TEST_UNION(case_72_multi, list_of(0));
TEST_UNION(case_107_multi, list_of(1));
TEST_UNION(case_123_multi, list_of(1));
TEST_UNION(case_124_multi, list_of(1));
TEST_UNION(case_recursive_boxes_1, list_of(1));
TEST_UNION(case_recursive_boxes_10, list_of(1));
TEST_UNION(case_recursive_boxes_18, list_of(3));
TEST_UNION(case_recursive_boxes_19, list_of(3));

View File

@@ -188,6 +188,21 @@ void test_linestring_linestring()
test_geometry<ls, ls>("LINESTRING(1 0,2 2,2 3)", "LINESTRING(0 0, 2 2, 3 2)", false);
}
//https://svn.boost.org/trac10/ticket/13057
template <typename P>
void test_linestring_linestring_radians()
{
typedef bg::model::linestring<P> ls;
test_geometry<ls, ls>("LINESTRING(0 -0.31415926535897897853,\
0.26179938779914918578 0,\
-0.034906585039886556254 0.13962634015954622502,\
-0.12217304763960294689 0.12217304763960294689)",\
"LINESTRING(-0.034906585039886556254 0.13962634015954622502,\
-0.26179938779914918578 0)", false);
}
template <typename P>
void test_linestring_multi_linestring()
{
@@ -255,6 +270,9 @@ void test_all()
test_linestring_multi_linestring<P>();
test_multi_linestring_multi_linestring<P>();
test_linestring_linestring_radians<bg::model::point<double, 2,
bg::cs::spherical_equatorial<bg::radian> > >();
test_point_polygon<P>();
}

View File

@@ -0,0 +1,50 @@
// Boost.Geometry
// Copyright (c) 2017 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)
#ifndef BOOST_GEOMETRY_TEST_SETOP_CHECK_VALIDITY_HPP
#define BOOST_GEOMETRY_TEST_SETOP_CHECK_VALIDITY_HPP
#include <boost/foreach.hpp>
#include <boost/geometry/algorithms/is_valid.hpp>
template
<
typename Geometry,
typename Tag = typename bg::tag<Geometry>::type
>
struct check_validity
{
static inline
bool apply(Geometry const& geometry, std::string& message)
{
return bg::is_valid(geometry, message);
}
};
// Specialization for vector of <geometry> (e.g. rings)
template <typename Geometry>
struct check_validity<Geometry, void>
{
static inline
bool apply(Geometry const& geometry, std::string& message)
{
typedef typename boost::range_value<Geometry>::type single_type;
BOOST_FOREACH(single_type const& element, geometry)
{
if (! bg::is_valid(element, message))
{
return false;
}
}
return true;
}
};
#endif // BOOST_GEOMETRY_TEST_SETOP_CHECK_VALIDITY_HPP

View File

@@ -41,10 +41,13 @@
( #caseid, caseid[0], caseid[1], clips1, -1, area1, clips2, -1, area2, \
clips3, -1, area1 + area2)
#if !defined(BOOST_GEOMETRY_INCLUDE_SELF_TURNS)
#define TEST_DIFFERENCE_IGNORE(caseid, clips1, area1, clips2, area2, clips3) \
{ ut_settings ignore_validity; ignore_validity.test_validity = false; \
(test_one<polygon, polygon, polygon>) \
( #caseid, caseid[0], caseid[1], clips1, -1, area1, clips2, -1, area2, \
clips3, -1, area1 + area2, ignore_validity)
clips3, -1, area1 + area2, ignore_validity); }
#endif
template <typename P>
void test_all()
@@ -55,9 +58,6 @@ void test_all()
typedef typename bg::coordinate_type<P>::type ct;
ut_settings ignore_validity;
ignore_validity.test_validity = false;
ut_settings sym_settings;
#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
sym_settings.sym_difference = false;
@@ -211,8 +211,7 @@ void test_all()
test_one<polygon, polygon, polygon>("case_80",
case_80[0], case_80[1],
1, 9, 44.5,
1, 10, 84.5,
ignore_validity);
1, 10, 84.5);
#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
// Fails, holes are not subtracted
@@ -371,10 +370,18 @@ void test_all()
}
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<polygon, polygon, polygon>("ggl_list_20110820_christophe",
ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1],
1, -1, 2.8570121719168924,
1, -1, 64.498061986388564);
{
// symmetric difference is not valid due to robustness issue, it has
// two turns (touch_only) and a midpoint is located in other polygon
ut_settings ignore_validity;
ignore_validity.test_validity = false;
test_one<polygon, polygon, polygon>("ggl_list_20110820_christophe",
ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1],
1, -1, 2.8570121719168924,
1, -1, 64.498061986388564,
ignore_validity);
}
#endif
test_one<polygon, polygon, polygon>("ggl_list_20120717_volker",
@@ -540,20 +547,16 @@ void test_all()
TEST_DIFFERENCE(mysql_21965285, 1, 92.0, 1, 14.0, 1);
TEST_DIFFERENCE_IGNORE(mysql_23023665_1, 1, 92.0, 1, 142.5, 2);
TEST_DIFFERENCE_IGNORE(mysql_23023665_2, 1, 96.0, 1, 16.0, 2);
TEST_DIFFERENCE_IGNORE(mysql_23023665_3, 1, 225.0, 1, 66.0, 2);
TEST_DIFFERENCE(mysql_23023665_1, 1, 92.0, 1, 142.5, 2);
TEST_DIFFERENCE(mysql_23023665_2, 1, 96.0, 1, 16.0, 2);
TEST_DIFFERENCE(mysql_23023665_3, 1, 225.0, 1, 66.0, 2);
#ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS
TEST_DIFFERENCE(mysql_23023665_5, 2, 165.23735, 2, 105.73735, 4);
#else
TEST_DIFFERENCE_IGNORE(mysql_23023665_5, 1, 165.23735, 2, 105.73735, 3);
#endif
#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
TEST_DIFFERENCE(mysql_23023665_6, 2, 105.68756, 3, 10.18756, 5);
#else
TEST_DIFFERENCE_IGNORE(mysql_23023665_6, 2, 105.68756, 3, 10.18756, 5);
#endif
#ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS
TEST_DIFFERENCE(mysql_23023665_13, 3, 99.74526, 3, 37.74526, 6);
@@ -585,15 +588,10 @@ void test_specific()
2, 8, 489763.5,
1, 4, 6731652.0);
// Generates spikes, both a-b and b-a
#ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS
TEST_DIFFERENCE(ticket_11676, 2, 2537992.5, 2, 294963.5, 3);
#else
ut_settings ignore_validity;
ignore_validity.test_validity = false;
TEST_DIFFERENCE_IGNORE(ticket_11676, 1, 2537992.5, 2, 294963.5, 2);
#endif
}

View File

@@ -30,9 +30,10 @@
clips3, -1, area1 + area2)
#define TEST_DIFFERENCE_IGNORE(caseid, clips1, area1, clips2, area2, clips3) \
{ ut_settings ignore_validity; ignore_validity.test_validity = false; \
(test_one<Polygon, MultiPolygon, MultiPolygon>) \
( #caseid, caseid[0], caseid[1], clips1, -1, area1, clips2, -1, area2, \
clips3, -1, area1 + area2, ignore_validity)
clips3, -1, area1 + area2, ignore_validity); }
#define TEST_DIFFERENCE_WITH(index1, index2, caseid, clips1, area1, \
clips2, area2, clips3) \
@@ -46,9 +47,6 @@
template <typename Ring, typename Polygon, typename MultiPolygon>
void test_areal()
{
ut_settings ignore_validity;
ignore_validity.test_validity = false;
ut_settings sym_settings;
#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
sym_settings.sym_difference = false;
@@ -94,7 +92,7 @@ void test_areal()
test_one<Polygon, MultiPolygon, MultiPolygon>("case_72_multi",
case_72_multi[0], case_72_multi[1],
3, 13, 1.65, 3, 17, 6.15, ignore_validity);
3, 13, 1.65, 3, 17, 6.15);
test_one<Polygon, MultiPolygon, MultiPolygon>("case_77_multi",
case_77_multi[0], case_77_multi[1],
@@ -108,7 +106,7 @@ void test_areal()
TEST_DIFFERENCE(case_123_multi, 1, 0.25, 2, 0.625, 3);
TEST_DIFFERENCE(case_124_multi, 1, 0.25, 2, 0.4375, 3);
TEST_DIFFERENCE_IGNORE(case_125_multi, 1, 0.25, 2, 0.400, 3);
TEST_DIFFERENCE(case_125_multi, 1, 0.25, 2, 0.400, 3);
// A should have 3 clips, B should have 5 clips
#ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS
@@ -178,11 +176,7 @@ void test_areal()
tolerance(0.001));
// POSTGIS areas: 3.75893745345145, 2.5810000723917e-15
test_one<Polygon, MultiPolygon, MultiPolygon>("bug_21155501",
bug_21155501[0], bug_21155501[1],
1, 9, 3.758937,
0, 0, 0.0,
ignore_validity);
TEST_DIFFERENCE_IGNORE(bug_21155501, 1, 3.758937, 0, 0.0, 1);
#endif
// Areas and #clips correspond with POSTGIS (except sym case)

View File

@@ -48,8 +48,7 @@ BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::vector)
#if ! defined(BOOST_GEOMETRY_INCLUDE_SELF_TURNS)
#define TEST_INTERSECTION_IGNORE(caseid, clips, points, area) \
{ ut_settings ignore_validity; \
ignore_validity.test_validity = false; \
{ ut_settings ignore_validity; ignore_validity.test_validity = false; \
(test_one<Polygon, Polygon, Polygon>) \
( #caseid, caseid[0], caseid[1], clips, points, area, ignore_validity); }
#endif

View File

@@ -33,15 +33,13 @@
( #caseid, caseid[0], caseid[1], clips, points, area)
#define TEST_INTERSECTION_IGNORE(caseid, clips, points, area) \
{ ut_settings ignore_validity; ignore_validity.test_validity = false; \
(test_one<Polygon, MultiPolygon, MultiPolygon>) \
( #caseid, caseid[0], caseid[1], clips, points, area, ignore_validity)
( #caseid, caseid[0], caseid[1], clips, points, area, ignore_validity); }
template <typename Ring, typename Polygon, typename MultiPolygon>
void test_areal()
{
ut_settings ignore_validity;
ignore_validity.test_validity = false;
test_one<Polygon, MultiPolygon, MultiPolygon>("simplex_multi",
case_multi_simplex[0], case_multi_simplex[1],
2, 12, 6.42);

View File

@@ -41,6 +41,7 @@
#include <geometry_test_common.hpp>
#include "../setop_output_type.hpp"
#include "../check_validity.hpp"
struct ut_settings
{
@@ -56,7 +57,13 @@ struct ut_settings
};
template <typename G1, typename G2, typename IntersectionOutput>
template
<
typename G1,
typename G2,
typename ResultType,
typename IntersectionOutput
>
typename bg::default_area_result<G1>::type
check_result(
IntersectionOutput const& intersection_output,
@@ -96,15 +103,15 @@ check_result(
{
std::cout << std::setprecision(20) << bg::wkt(*it) << std::endl;
}
}
if (settings.test_validity)
{
std::string message;
bool const valid = bg::is_valid(*it, message);
BOOST_CHECK_MESSAGE(valid,
"intersection: " << caseid << " not valid: " << message
<< " type: " << (type_for_assert_message<G1, G2>()));
}
if (settings.test_validity)
{
std::string message;
bool const valid = check_validity<ResultType>::apply(intersection_output, message);
BOOST_CHECK_MESSAGE(valid,
"intersection: " << caseid << " not valid: " << message
<< " type: " << (type_for_assert_message<G1, G2>()));
}
#if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST)
@@ -194,7 +201,7 @@ typename bg::default_area_result<G1>::type test_intersection(std::string const&
result_type intersection_output;
bg::intersection(g1, g2, intersection_output);
check_result<G1, G2>(intersection_output, caseid, expected_count,
check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
expected_holes_count, expected_point_count, expected_length_or_area,
settings);
@@ -203,21 +210,21 @@ typename bg::default_area_result<G1>::type test_intersection(std::string const&
intersection_output.clear();
bg::intersection(boost::variant<G1>(g1), g2, intersection_output);
check_result<G1, G2>(intersection_output, caseid, expected_count,
check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
expected_holes_count, expected_point_count, expected_length_or_area,
settings);
intersection_output.clear();
bg::intersection(g1, boost::variant<G2>(g2), intersection_output);
check_result<G1, G2>(intersection_output, caseid, expected_count,
check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
expected_holes_count, expected_point_count, expected_length_or_area,
settings);
intersection_output.clear();
bg::intersection(boost::variant<G1>(g1), boost::variant<G2>(g2), intersection_output);
check_result<G1, G2>(intersection_output, caseid, expected_count,
check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
expected_holes_count, expected_point_count, expected_length_or_area,
settings);
#endif

View File

@@ -19,6 +19,7 @@
#include <geometry_test_common.hpp>
#include "../setop_output_type.hpp"
#include "../check_validity.hpp"
#include <boost/core/ignore_unused.hpp>
#include <boost/foreach.hpp>
@@ -71,42 +72,6 @@ inline void check_input_validity(std::string const& caseid, int case_index,
}
#endif
template
<
typename Geometry,
typename Tag = typename bg::tag<Geometry>::type
>
struct check_validity
{
static inline
bool apply(Geometry const& geometry, std::string& message)
{
if (! bg::is_valid(geometry, message))
{
std::cout << bg::wkt(geometry) << std::endl;
}
return bg::is_valid(geometry, message);
}
};
// Specialization for vector of <geometry> (e.g. rings)
template <typename Geometry>
struct check_validity<Geometry, void>
{
static inline
bool apply(Geometry const& geometry, std::string& message)
{
typedef typename boost::range_value<Geometry>::type single_type;
BOOST_FOREACH(single_type const& element, geometry)
{
if (! bg::is_valid(element, message))
{
return false;
}
}
return true;
}
};
template <typename Range>

View File

@@ -1,6 +1,6 @@
# Boost.Geometry
#
# Copyright (c) 2016, Oracle and/or its affiliates.
# Copyright (c) 2016-2017, Oracle and/or its affiliates.
#
# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#
@@ -13,5 +13,5 @@ test-suite boost-geometry-formulas
[ run inverse.cpp : : : : formulas_inverse ]
[ run direct.cpp : : : : formulas_direct ]
[ run intersection.cpp : : : : formulas_intersection ]
[ run vertex_longitude.cpp : : : : vertex_longitude ]
[ run vertex_longitude.cpp : : : : formulas_vertex_longitude ]
;