mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-01 08:32:10 +00:00
Merge branch 'bg-prepare'
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
[/=================]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
<
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
|
||||
50
test/algorithms/set_operations/check_validity.hpp
Normal file
50
test/algorithms/set_operations/check_validity.hpp
Normal 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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 ]
|
||||
;
|
||||
|
||||
Reference in New Issue
Block a user