update boost on linux
This commit is contained in:
@@ -91,19 +91,23 @@ template <typename Polygon, typename Point>
|
||||
struct point_to_polygon
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
typedef typename ring_return_type<Polygon>::type exterior_ring_type;
|
||||
typedef typename interior_return_type<Polygon>::type interior_ring_range_type;
|
||||
|
||||
static inline void apply(Polygon& polygon, Point const& point,
|
||||
int ring_index, int = 0)
|
||||
{
|
||||
if (ring_index == -1)
|
||||
{
|
||||
exterior_ring_type ext_ring = exterior_ring(polygon);
|
||||
append_point<ring_type, Point>::apply(
|
||||
exterior_ring(polygon), point);
|
||||
ext_ring, point);
|
||||
}
|
||||
else if (ring_index < int(num_interior_rings(polygon)))
|
||||
{
|
||||
interior_ring_range_type int_rings = interior_rings(polygon);
|
||||
append_point<ring_type, Point>::apply(
|
||||
range::at(interior_rings(polygon), ring_index), point);
|
||||
range::at(int_rings, ring_index), point);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -113,19 +117,23 @@ template <typename Polygon, typename Range>
|
||||
struct range_to_polygon
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
typedef typename ring_return_type<Polygon>::type exterior_ring_type;
|
||||
typedef typename interior_return_type<Polygon>::type interior_ring_range_type;
|
||||
|
||||
static inline void apply(Polygon& polygon, Range const& range,
|
||||
int ring_index, int = 0)
|
||||
{
|
||||
if (ring_index == -1)
|
||||
{
|
||||
exterior_ring_type ext_ring = exterior_ring(polygon);
|
||||
append_range<ring_type, Range>::apply(
|
||||
exterior_ring(polygon), range);
|
||||
ext_ring, range);
|
||||
}
|
||||
else if (ring_index < int(num_interior_rings(polygon)))
|
||||
{
|
||||
interior_ring_range_type int_rings = interior_rings(polygon);
|
||||
append_range<ring_type, Range>::apply(
|
||||
range::at(interior_rings(polygon), ring_index), range);
|
||||
range::at(int_rings, ring_index), range);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-2018 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
|
||||
@@ -19,7 +20,7 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range/functions.hpp>
|
||||
#include <boost/range/metafunctions.hpp>
|
||||
|
||||
@@ -43,7 +44,9 @@
|
||||
#include <boost/geometry/algorithms/detail/multi_sum.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/area.hpp>
|
||||
#include <boost/geometry/strategies/area_result.hpp>
|
||||
#include <boost/geometry/strategies/default_area_result.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/concepts/area_concept.hpp>
|
||||
|
||||
@@ -56,6 +59,7 @@
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace area
|
||||
{
|
||||
@@ -83,14 +87,14 @@ template
|
||||
struct ring_area
|
||||
{
|
||||
template <typename Ring, typename Strategy>
|
||||
static inline typename Strategy::return_type
|
||||
static inline typename area_result<Ring, Strategy>::type
|
||||
apply(Ring const& ring, Strategy const& strategy)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy<Strategy>) );
|
||||
BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy<Ring, Strategy>) );
|
||||
assert_dimension<Ring, 2>();
|
||||
|
||||
// Ignore warning (because using static method sometimes) on strategy
|
||||
boost::ignore_unused_variable_warning(strategy);
|
||||
boost::ignore_unused(strategy);
|
||||
|
||||
// An open ring has at least three points,
|
||||
// A closed ring has at least four points,
|
||||
@@ -98,7 +102,7 @@ struct ring_area
|
||||
if (boost::size(ring)
|
||||
< core_detail::closure::minimum_ring_size<Closure>::value)
|
||||
{
|
||||
return typename Strategy::return_type();
|
||||
return typename area_result<Ring, Strategy>::type();
|
||||
}
|
||||
|
||||
typedef typename reversible_view<Ring const, Direction>::type rview_type;
|
||||
@@ -110,7 +114,7 @@ struct ring_area
|
||||
|
||||
rview_type rview(ring);
|
||||
view_type view(rview);
|
||||
typename Strategy::state_type state;
|
||||
typename Strategy::template state<Ring> state;
|
||||
iterator_type it = boost::begin(view);
|
||||
iterator_type end = boost::end(view);
|
||||
|
||||
@@ -144,9 +148,13 @@ template
|
||||
struct area : detail::calculate_null
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy)
|
||||
static inline typename area_result<Geometry, Strategy>::type
|
||||
apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
return calculate_null::apply<typename Strategy::return_type>(geometry, strategy);
|
||||
return calculate_null::apply
|
||||
<
|
||||
typename area_result<Geometry, Strategy>::type
|
||||
>(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -170,10 +178,11 @@ template <typename Polygon>
|
||||
struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy)
|
||||
static inline typename area_result<Polygon, Strategy>::type
|
||||
apply(Polygon const& polygon, Strategy const& strategy)
|
||||
{
|
||||
return calculate_polygon_sum::apply<
|
||||
typename Strategy::return_type,
|
||||
typename area_result<Polygon, Strategy>::type,
|
||||
detail::area::ring_area
|
||||
<
|
||||
order_as_direction<geometry::point_order<Polygon>::value>::value,
|
||||
@@ -188,12 +197,12 @@ template <typename MultiGeometry>
|
||||
struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename Strategy::return_type
|
||||
static inline typename area_result<MultiGeometry, Strategy>::type
|
||||
apply(MultiGeometry const& multi, Strategy const& strategy)
|
||||
{
|
||||
return multi_sum::apply
|
||||
<
|
||||
typename Strategy::return_type,
|
||||
typename area_result<MultiGeometry, Strategy>::type,
|
||||
area<typename boost::range_value<MultiGeometry>::type>
|
||||
>(multi, strategy);
|
||||
}
|
||||
@@ -204,39 +213,78 @@ struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template <typename Strategy>
|
||||
struct area
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline typename area_result<Geometry, Strategy>::type
|
||||
apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
return dispatch::area<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct area<default_strategy>
|
||||
{
|
||||
template <typename Geometry>
|
||||
static inline typename area_result<Geometry>::type
|
||||
apply(Geometry const& geometry, default_strategy)
|
||||
{
|
||||
typedef typename strategy::area::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::area<Geometry>::apply(geometry, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct area
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline typename Strategy::return_type apply(Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
static inline typename area_result<Geometry, Strategy>::type
|
||||
apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
return dispatch::area<Geometry>::apply(geometry, strategy);
|
||||
return resolve_strategy::area<Strategy>::apply(geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
typedef boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> variant_type;
|
||||
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<typename Strategy::return_type>
|
||||
struct visitor
|
||||
: boost::static_visitor<typename area_result<variant_type, Strategy>::type>
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy): m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry>
|
||||
typename Strategy::return_type operator()(Geometry const& geometry) const
|
||||
typename area_result<variant_type, Strategy>::type
|
||||
operator()(Geometry const& geometry) const
|
||||
{
|
||||
return area<Geometry>::apply(geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline typename Strategy::return_type
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
static inline typename area_result<variant_type, Strategy>::type
|
||||
apply(variant_type const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
|
||||
@@ -268,22 +316,14 @@ and Geographic as well.
|
||||
\qbk{[area] [area_output]}
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline typename default_area_result<Geometry>::type area(Geometry const& geometry)
|
||||
inline typename area_result<Geometry>::type
|
||||
area(Geometry const& geometry)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
// TODO put this into a resolve_strategy stage
|
||||
// (and take the return type from resolve_variant)
|
||||
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;
|
||||
|
||||
// detail::throw_on_empty_input(geometry);
|
||||
|
||||
return resolve_variant::area<Geometry>::apply(geometry, strategy_type());
|
||||
return resolve_variant::area<Geometry>::apply(geometry, default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -301,19 +341,19 @@ inline typename default_area_result<Geometry>::type area(Geometry const& geometr
|
||||
\qbk{
|
||||
[include reference/algorithms/area.qbk]
|
||||
|
||||
[heading Available Strategies]
|
||||
\* [link geometry.reference.strategies.strategy_area_cartesian Cartesian]
|
||||
\* [link geometry.reference.strategies.strategy_area_spherical Spherical]
|
||||
\* [link geometry.reference.strategies.strategy_area_geographic Geographic]
|
||||
|
||||
[heading Example]
|
||||
[area_with_strategy]
|
||||
[area_with_strategy_output]
|
||||
|
||||
[heading Available Strategies]
|
||||
\* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)]
|
||||
\* [link geometry.reference.strategies.strategy_area_spherical Spherical]
|
||||
[/link geometry.reference.strategies.strategy_area_geographic Geographic]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline typename Strategy::return_type area(
|
||||
Geometry const& geometry, Strategy const& strategy)
|
||||
inline typename area_result<Geometry, Strategy>::type
|
||||
area(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
|
||||
@@ -37,52 +37,12 @@
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>
|
||||
struct box_loop
|
||||
{
|
||||
typedef typename coordinate_type<BoxOut>::type coordinate_type;
|
||||
|
||||
static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
||||
{
|
||||
coordinate_type d = distance;
|
||||
set<C, D>(box_out, get<C, D>(box_in) + d);
|
||||
box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>
|
||||
struct box_loop<BoxIn, BoxOut, T, C, N, N>
|
||||
{
|
||||
static inline void apply(BoxIn const&, T const&, BoxOut&) {}
|
||||
};
|
||||
|
||||
// Extends a box with the same amount in all directions
|
||||
template<typename BoxIn, typename BoxOut, typename T>
|
||||
inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
||||
{
|
||||
assert_dimension_equal<BoxIn, BoxOut>();
|
||||
|
||||
static const std::size_t N = dimension<BoxIn>::value;
|
||||
|
||||
box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);
|
||||
box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -29,10 +33,8 @@
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/algorithms/append.hpp>
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/for_each.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_values.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
@@ -153,7 +155,23 @@ struct range_to_range
|
||||
geometry::closure<Range1>::value
|
||||
>::type view_type;
|
||||
|
||||
struct default_policy
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
static inline void apply(Point1 const& point1, Point2 & point2)
|
||||
{
|
||||
geometry::detail::conversion::convert_point_to_point(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void apply(Range1 const& source, Range2& destination)
|
||||
{
|
||||
apply(source, destination, default_policy());
|
||||
}
|
||||
|
||||
template <typename ConvertPointPolicy>
|
||||
static inline ConvertPointPolicy apply(Range1 const& source, Range2& destination,
|
||||
ConvertPointPolicy convert_point)
|
||||
{
|
||||
geometry::clear(destination);
|
||||
|
||||
@@ -179,8 +197,12 @@ struct range_to_range
|
||||
it != boost::end(view) && i < n;
|
||||
++it, ++i)
|
||||
{
|
||||
geometry::append(destination, *it);
|
||||
typename boost::range_value<Range2>::type point;
|
||||
convert_point.apply(*it, point);
|
||||
range::push_back(destination, point);
|
||||
}
|
||||
|
||||
return convert_point;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2014-2017 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.
|
||||
@@ -28,6 +32,7 @@
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/correct_closure.hpp>
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
@@ -41,7 +46,6 @@
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/area.hpp>
|
||||
#include <boost/geometry/algorithms/disjoint.hpp>
|
||||
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
|
||||
#include <boost/geometry/util/order_as_direction.hpp>
|
||||
|
||||
@@ -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,30 +137,17 @@ 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)
|
||||
{
|
||||
// check if closed, if not, close it
|
||||
bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1));
|
||||
closure_selector const s = geometry::closure<Ring>::value;
|
||||
// Correct closure if necessary
|
||||
detail::correct_closure::close_or_open_ring<Ring>::apply(r);
|
||||
|
||||
if (disjoint && (s == closed))
|
||||
{
|
||||
geometry::append(r, *boost::begin(r));
|
||||
}
|
||||
if (! disjoint && s != closed)
|
||||
{
|
||||
// Open it by removing last point
|
||||
geometry::traits::resize<Ring>::apply(r, boost::size(r) - 1);
|
||||
}
|
||||
}
|
||||
// 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 area_result<Ring, Strategy>::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 +160,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 +178,8 @@ struct correct_polygon
|
||||
correct_ring
|
||||
<
|
||||
ring_type,
|
||||
std::greater<area_result_type>
|
||||
>::apply(*it);
|
||||
std::greater
|
||||
>::apply(*it, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -237,7 +223,7 @@ struct correct<Ring, ring_tag>
|
||||
: detail::correct::correct_ring
|
||||
<
|
||||
Ring,
|
||||
std::less<typename default_area_result<Ring>::type>
|
||||
std::less
|
||||
>
|
||||
{};
|
||||
|
||||
@@ -281,29 +267,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 +318,36 @@ 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
|
||||
>::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)
|
||||
|
||||
235
linx64/include/boost/geometry/algorithms/correct_closure.hpp
Normal file
235
linx64/include/boost/geometry/algorithms/correct_closure.hpp
Normal file
@@ -0,0 +1,235 @@
|
||||
// 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_ALGORITHMS_CORRECT_CLOSURE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/disjoint.hpp>
|
||||
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
// Silence warning C4127: conditional expression is constant
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace correct_closure
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct nop
|
||||
{
|
||||
static inline void apply(Geometry& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Close a ring, if not closed, or open it
|
||||
template <typename Ring>
|
||||
struct close_or_open_ring
|
||||
{
|
||||
static inline void apply(Ring& r)
|
||||
{
|
||||
if (boost::size(r) <= 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool const disjoint = geometry::disjoint(*boost::begin(r),
|
||||
*(boost::end(r) - 1));
|
||||
closure_selector const s = geometry::closure<Ring>::value;
|
||||
|
||||
if (disjoint && s == closed)
|
||||
{
|
||||
// Close it by adding first point
|
||||
geometry::append(r, *boost::begin(r));
|
||||
}
|
||||
else if (! disjoint && s != closed)
|
||||
{
|
||||
// Open it by removing last point
|
||||
geometry::traits::resize<Ring>::apply(r, boost::size(r) - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Close/open exterior ring and all its interior rings
|
||||
template <typename Polygon>
|
||||
struct close_or_open_polygon
|
||||
{
|
||||
typedef typename ring_type<Polygon>::type ring_type;
|
||||
|
||||
static inline void apply(Polygon& poly)
|
||||
{
|
||||
close_or_open_ring<ring_type>::apply(exterior_ring(poly));
|
||||
|
||||
typename interior_return_type<Polygon>::type
|
||||
rings = interior_rings(poly);
|
||||
|
||||
for (typename detail::interior_iterator<Polygon>::type
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
close_or_open_ring<ring_type>::apply(*it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::correct_closure
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct correct_closure: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename Point>
|
||||
struct correct_closure<Point, point_tag>
|
||||
: detail::correct_closure::nop<Point>
|
||||
{};
|
||||
|
||||
template <typename LineString>
|
||||
struct correct_closure<LineString, linestring_tag>
|
||||
: detail::correct_closure::nop<LineString>
|
||||
{};
|
||||
|
||||
template <typename Segment>
|
||||
struct correct_closure<Segment, segment_tag>
|
||||
: detail::correct_closure::nop<Segment>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct correct_closure<Box, box_tag>
|
||||
: detail::correct_closure::nop<Box>
|
||||
{};
|
||||
|
||||
template <typename Ring>
|
||||
struct correct_closure<Ring, ring_tag>
|
||||
: detail::correct_closure::close_or_open_ring<Ring>
|
||||
{};
|
||||
|
||||
template <typename Polygon>
|
||||
struct correct_closure<Polygon, polygon_tag>
|
||||
: detail::correct_closure::close_or_open_polygon<Polygon>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct correct_closure<MultiPoint, multi_point_tag>
|
||||
: detail::correct_closure::nop<MultiPoint>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiLineString>
|
||||
struct correct_closure<MultiLineString, multi_linestring_tag>
|
||||
: detail::correct_closure::nop<MultiLineString>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct_closure<Geometry, multi_polygon_tag>
|
||||
: detail::multi_modify
|
||||
<
|
||||
Geometry,
|
||||
detail::correct_closure::close_or_open_polygon
|
||||
<
|
||||
typename boost::range_value<Geometry>::type
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct correct_closure
|
||||
{
|
||||
static inline void apply(Geometry& geometry)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
dispatch::correct_closure<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct correct_closure<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry& geometry) const
|
||||
{
|
||||
correct_closure<Geometry>::apply(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
|
||||
{
|
||||
visitor vis;
|
||||
boost::apply_visitor(vis, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief Closes or opens a geometry, according to its type
|
||||
\details Corrects a geometry w.r.t. closure points to all rings which do not
|
||||
have a closing point and are typed as they should have one, the first point
|
||||
is appended.
|
||||
\ingroup correct_closure
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry which will be corrected if necessary
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline void correct_closure(Geometry& geometry)
|
||||
{
|
||||
resolve_variant::correct_closure<Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
|
||||
@@ -20,443 +20,8 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/algorithms/within.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace covered_by {
|
||||
|
||||
struct use_point_in_geometry
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
||||
{
|
||||
return detail::within::point_in_geometry(geometry1, geometry2, strategy) >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct use_relate
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
||||
{
|
||||
typedef typename detail::de9im::static_mask_covered_by_type
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type covered_by_mask;
|
||||
return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::covered_by
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag2 = typename tag<Geometry2>::type
|
||||
>
|
||||
struct covered_by
|
||||
: not_implemented<Tag1, Tag2>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point, typename Box>
|
||||
struct covered_by<Point, Box, point_tag, box_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
|
||||
{
|
||||
::boost::ignore_unused_variable_warning(strategy);
|
||||
return strategy.apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box1, typename Box2>
|
||||
struct covered_by<Box1, Box2, box_tag, box_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
|
||||
{
|
||||
assert_dimension_equal<Box1, Box2>();
|
||||
::boost::ignore_unused_variable_warning(strategy);
|
||||
return strategy.apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// P/P
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
struct covered_by<Point1, Point2, point_tag, point_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiPoint>
|
||||
struct covered_by<Point, MultiPoint, point_tag, multi_point_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
// P/L
|
||||
|
||||
template <typename Point, typename Segment>
|
||||
struct covered_by<Point, Segment, point_tag, segment_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename Linestring>
|
||||
struct covered_by<Point, Linestring, point_tag, linestring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiLinestring>
|
||||
struct covered_by<Point, MultiLinestring, point_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
// P/A
|
||||
|
||||
template <typename Point, typename Ring>
|
||||
struct covered_by<Point, Ring, point_tag, ring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename Polygon>
|
||||
struct covered_by<Point, Polygon, point_tag, polygon_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiPolygon>
|
||||
struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
// L/L
|
||||
|
||||
template <typename Linestring1, typename Linestring2>
|
||||
struct covered_by<Linestring1, Linestring2, linestring_tag, linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename MultiLinestring>
|
||||
struct covered_by<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Linestring>
|
||||
struct covered_by<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring1, typename MultiLinestring2>
|
||||
struct covered_by<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// L/A
|
||||
|
||||
template <typename Linestring, typename Ring>
|
||||
struct covered_by<Linestring, Ring, linestring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Ring>
|
||||
struct covered_by<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename Polygon>
|
||||
struct covered_by<Linestring, Polygon, linestring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Polygon>
|
||||
struct covered_by<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename MultiPolygon>
|
||||
struct covered_by<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename MultiPolygon>
|
||||
struct covered_by<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// A/A
|
||||
|
||||
template <typename Ring1, typename Ring2>
|
||||
struct covered_by<Ring1, Ring2, ring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Ring, typename Polygon>
|
||||
struct covered_by<Ring, Polygon, ring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename Ring>
|
||||
struct covered_by<Polygon, Ring, polygon_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon1, typename Polygon2>
|
||||
struct covered_by<Polygon1, Polygon2, polygon_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Ring, typename MultiPolygon>
|
||||
struct covered_by<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Ring>
|
||||
struct covered_by<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename MultiPolygon>
|
||||
struct covered_by<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Polygon>
|
||||
struct covered_by<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon1, typename MultiPolygon2>
|
||||
struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
struct covered_by
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::within::check
|
||||
<
|
||||
typename tag<Geometry1>::type,
|
||||
typename tag<Geometry2>::type,
|
||||
typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
|
||||
Strategy
|
||||
>();
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
assert_dimension_equal<Geometry1, Geometry2>();
|
||||
|
||||
return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1,
|
||||
geometry2,
|
||||
strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::covered_by::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return covered_by::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct covered_by
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::covered_by
|
||||
::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2, Strategy const& strategy)
|
||||
: m_geometry2(geometry2), m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry1>
|
||||
bool operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
return covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, m_geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1, Strategy const& strategy)
|
||||
: m_geometry1(geometry1), m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry2>
|
||||
bool operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
return covered_by<Geometry1, Geometry2>
|
||||
::apply(m_geometry1, geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool
|
||||
apply(Geometry1 const& geometry1,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
template <
|
||||
BOOST_VARIANT_ENUM_PARAMS(typename T1),
|
||||
BOOST_VARIANT_ENUM_PARAMS(typename T2)
|
||||
>
|
||||
struct covered_by<
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
|
||||
>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy): m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
bool operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
return covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check12{is inside or on border}
|
||||
\ingroup covered_by
|
||||
\details \details_check12{covered_by, is inside or on border}.
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
|
||||
\param geometry2 \param_geometry which might cover the first geometry
|
||||
\return true if geometry1 is inside of or on the border of geometry2,
|
||||
else false
|
||||
\note The default strategy is used for covered_by detection
|
||||
|
||||
\qbk{[include reference/algorithms/covered_by.qbk]}
|
||||
|
||||
*/
|
||||
template<typename Geometry1, typename Geometry2>
|
||||
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
return resolve_variant::covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_check12{is inside or on border} \brief_strategy
|
||||
\ingroup covered_by
|
||||
\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
|
||||
\param geometry2 \param_geometry which might cover the first geometry
|
||||
\param strategy strategy to be used
|
||||
\return true if geometry1 is inside of or on the border of geometry2,
|
||||
else false
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/covered_by.qbk]}
|
||||
|
||||
*/
|
||||
template<typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
|
||||
|
||||
432
linx64/include/boost/geometry/algorithms/densify.hpp
Normal file
432
linx64/include/boost/geometry/algorithms/densify.hpp
Normal file
@@ -0,0 +1,432 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2017-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/exception.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/densify.hpp>
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/range/size.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace densify
|
||||
{
|
||||
|
||||
template <typename Range>
|
||||
struct push_back_policy
|
||||
{
|
||||
typedef typename boost::range_value<Range>::type point_type;
|
||||
|
||||
inline explicit push_back_policy(Range & rng)
|
||||
: m_rng(rng)
|
||||
{}
|
||||
|
||||
inline void apply(point_type const& p)
|
||||
{
|
||||
range::push_back(m_rng, p);
|
||||
}
|
||||
|
||||
private:
|
||||
Range & m_rng;
|
||||
};
|
||||
|
||||
template <typename Range, typename Point>
|
||||
inline void convert_and_push_back(Range & range, Point const& p)
|
||||
{
|
||||
typename boost::range_value<Range>::type p2;
|
||||
geometry::detail::conversion::convert_point_to_point(p, p2);
|
||||
range::push_back(range, p2);
|
||||
}
|
||||
|
||||
template <bool AppendLastPoint = true>
|
||||
struct densify_range
|
||||
{
|
||||
template <typename FwdRng, typename MutRng, typename T, typename Strategy>
|
||||
static inline void apply(FwdRng const& rng, MutRng & rng_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_iterator<FwdRng const>::type iterator_t;
|
||||
typedef typename boost::range_value<FwdRng>::type point_t;
|
||||
|
||||
iterator_t it = boost::begin(rng);
|
||||
iterator_t end = boost::end(rng);
|
||||
|
||||
if (it == end) // empty(rng)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
push_back_policy<MutRng> policy(rng_out);
|
||||
|
||||
iterator_t prev = it;
|
||||
for ( ++it ; it != end ; prev = it++)
|
||||
{
|
||||
point_t const& p0 = *prev;
|
||||
point_t const& p1 = *it;
|
||||
|
||||
convert_and_push_back(rng_out, p0);
|
||||
|
||||
strategy.apply(p0, p1, policy, len);
|
||||
}
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(AppendLastPoint))
|
||||
{
|
||||
convert_and_push_back(rng_out, *prev); // back(rng)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <bool IsClosed1, bool IsClosed2> // false, X
|
||||
struct densify_ring
|
||||
{
|
||||
template <typename Geometry, typename GeometryOut, typename T, typename Strategy>
|
||||
static inline void apply(Geometry const& ring, GeometryOut & ring_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
geometry::detail::densify::densify_range<true>
|
||||
::apply(ring, ring_out, len, strategy);
|
||||
|
||||
if (boost::size(ring) <= 1)
|
||||
return;
|
||||
|
||||
typedef typename point_type<Geometry>::type point_t;
|
||||
point_t const& p0 = range::back(ring);
|
||||
point_t const& p1 = range::front(ring);
|
||||
|
||||
push_back_policy<GeometryOut> policy(ring_out);
|
||||
|
||||
strategy.apply(p0, p1, policy, len);
|
||||
|
||||
if (BOOST_GEOMETRY_CONDITION(IsClosed2))
|
||||
{
|
||||
convert_and_push_back(ring_out, p1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct densify_ring<true, true>
|
||||
: densify_range<true>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct densify_ring<true, false>
|
||||
: densify_range<false>
|
||||
{};
|
||||
|
||||
|
||||
}} // namespace detail::densify
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename GeometryOut,
|
||||
typename Tag1 = typename tag<Geometry>::type,
|
||||
typename Tag2 = typename tag<GeometryOut>::type
|
||||
>
|
||||
struct densify
|
||||
: not_implemented<Tag1, Tag2>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, linestring_tag, linestring_tag>
|
||||
: geometry::detail::densify::densify_range<>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, multi_linestring_tag, multi_linestring_tag>
|
||||
{
|
||||
template <typename T, typename Strategy>
|
||||
static void apply(Geometry const& mls, GeometryOut & mls_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
std::size_t count = boost::size(mls);
|
||||
range::resize(mls_out, count);
|
||||
|
||||
for (std::size_t i = 0 ; i < count ; ++i)
|
||||
{
|
||||
geometry::detail::densify::densify_range<>
|
||||
::apply(range::at(mls, i), range::at(mls_out, i),
|
||||
len, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, ring_tag, ring_tag>
|
||||
: geometry::detail::densify::densify_ring
|
||||
<
|
||||
geometry::closure<Geometry>::value != geometry::open,
|
||||
geometry::closure<GeometryOut>::value != geometry::open
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, polygon_tag, polygon_tag>
|
||||
{
|
||||
template <typename T, typename Strategy>
|
||||
static void apply(Geometry const& poly, GeometryOut & poly_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
apply_ring(exterior_ring(poly), exterior_ring(poly_out),
|
||||
len, strategy);
|
||||
|
||||
std::size_t count = boost::size(interior_rings(poly));
|
||||
range::resize(interior_rings(poly_out), count);
|
||||
|
||||
for (std::size_t i = 0 ; i < count ; ++i)
|
||||
{
|
||||
apply_ring(range::at(interior_rings(poly), i),
|
||||
range::at(interior_rings(poly_out), i),
|
||||
len, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Ring, typename RingOut, typename T, typename Strategy>
|
||||
static void apply_ring(Ring const& ring, RingOut & ring_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
densify<Ring, RingOut, ring_tag, ring_tag>
|
||||
::apply(ring, ring_out, len, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct densify<Geometry, GeometryOut, multi_polygon_tag, multi_polygon_tag>
|
||||
{
|
||||
template <typename T, typename Strategy>
|
||||
static void apply(Geometry const& mpoly, GeometryOut & mpoly_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
std::size_t count = boost::size(mpoly);
|
||||
range::resize(mpoly_out, count);
|
||||
|
||||
for (std::size_t i = 0 ; i < count ; ++i)
|
||||
{
|
||||
apply_poly(range::at(mpoly, i),
|
||||
range::at(mpoly_out, i),
|
||||
len, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Poly, typename PolyOut, typename T, typename Strategy>
|
||||
static void apply_poly(Poly const& poly, PolyOut & poly_out,
|
||||
T const& len, Strategy const& strategy)
|
||||
{
|
||||
densify<Poly, PolyOut, polygon_tag, polygon_tag>::
|
||||
apply(poly, poly_out, len, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
struct densify
|
||||
{
|
||||
template <typename Geometry, typename Distance, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
dispatch::densify<Geometry, Geometry>
|
||||
::apply(geometry, out, max_distance, strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry, typename Distance>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::densify::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type strategy_type;
|
||||
|
||||
/*BOOST_CONCEPT_ASSERT(
|
||||
(concepts::DensifyStrategy<strategy_type>)
|
||||
);*/
|
||||
|
||||
apply(geometry, out, max_distance, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct densify
|
||||
{
|
||||
template <typename Distance, typename Strategy>
|
||||
static inline void apply(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
resolve_strategy::densify::apply(geometry, out, max_distance, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct densify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Distance, typename Strategy>
|
||||
struct visitor: boost::static_visitor<void>
|
||||
{
|
||||
Distance const& m_max_distance;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Distance const& max_distance, Strategy const& strategy)
|
||||
: m_max_distance(max_distance)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
void operator()(Geometry const& geometry, Geometry& out) const
|
||||
{
|
||||
densify<Geometry>::apply(geometry, out, m_max_distance, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Distance, typename Strategy>
|
||||
static inline void
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out,
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(
|
||||
visitor<Distance, Strategy>(max_distance, strategy),
|
||||
geometry,
|
||||
out
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief Densify a geometry using a specified strategy
|
||||
\ingroup densify
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Distance A numerical distance measure
|
||||
\tparam Strategy A type fulfilling a DensifyStrategy concept
|
||||
\param geometry Input geometry, to be densified
|
||||
\param out Output geometry, densified version of the input geometry
|
||||
\param max_distance Distance threshold (in units depending on strategy)
|
||||
\param strategy Densify strategy to be used for densification
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/densify.qbk]}
|
||||
|
||||
\qbk{
|
||||
[heading Available Strategies]
|
||||
\* [link geometry.reference.strategies.strategy_densify_cartesian Cartesian]
|
||||
\* [link geometry.reference.strategies.strategy_densify_spherical Spherical]
|
||||
\* [link geometry.reference.strategies.strategy_densify_geographic Geographic]
|
||||
|
||||
[heading Example]
|
||||
[densify_strategy]
|
||||
[densify_strategy_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.line_interpolate line_interpolate]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Distance, typename Strategy>
|
||||
inline void densify(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
|
||||
if (max_distance <= Distance(0))
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(geometry::invalid_input_exception());
|
||||
}
|
||||
|
||||
geometry::clear(out);
|
||||
|
||||
resolve_variant::densify
|
||||
<
|
||||
Geometry
|
||||
>::apply(geometry, out, max_distance, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Densify a geometry
|
||||
\ingroup densify
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Distance A numerical distance measure
|
||||
\param geometry Input geometry, to be densified
|
||||
\param out Output geometry, densified version of the input geometry
|
||||
\param max_distance Distance threshold (in units depending on coordinate system)
|
||||
|
||||
\qbk{[include reference/algorithms/densify.qbk]}
|
||||
|
||||
\qbk{
|
||||
[heading Example]
|
||||
[densify]
|
||||
[densify_output]
|
||||
|
||||
[heading See also]
|
||||
\* [link geometry.reference.algorithms.line_interpolate line_interpolate]
|
||||
}
|
||||
*/
|
||||
template <typename Geometry, typename Distance>
|
||||
inline void densify(Geometry const& geometry,
|
||||
Geometry& out,
|
||||
Distance const& max_distance)
|
||||
{
|
||||
densify(geometry, out, max_distance, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
|
||||
@@ -7,6 +7,11 @@
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2018.
|
||||
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, 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)
|
||||
@@ -34,6 +39,7 @@
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/util/is_inverse_spheroidal_coordinates.hpp>
|
||||
#include <boost/geometry/util/for_each_coordinate.hpp>
|
||||
|
||||
|
||||
@@ -86,12 +92,13 @@ struct assign_inverse_box_or_segment
|
||||
typedef typename coordinate_type<point_type>::type bound_type;
|
||||
|
||||
initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
|
||||
geometry, boost::numeric::bounds<bound_type>::highest()
|
||||
geometry, geometry::bounds<bound_type>::highest()
|
||||
);
|
||||
initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
|
||||
geometry, boost::numeric::bounds<bound_type>::lowest()
|
||||
geometry, geometry::bounds<bound_type>::lowest()
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -15,18 +15,22 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/spherical.hpp>
|
||||
#include <boost/geometry/formulas/vincenty_inverse.hpp>
|
||||
|
||||
#include <boost/geometry/srs/spheroid.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
62
linx64/include/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
Executable file
62
linx64/include/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
Executable file
@@ -0,0 +1,62 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2018-2019 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_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>
|
||||
struct box_loop
|
||||
{
|
||||
typedef typename coordinate_type<BoxOut>::type coordinate_type;
|
||||
|
||||
static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
||||
{
|
||||
coordinate_type d = distance;
|
||||
set<C, D>(box_out, get<C, D>(box_in) + d);
|
||||
box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>
|
||||
struct box_loop<BoxIn, BoxOut, T, C, N, N>
|
||||
{
|
||||
static inline void apply(BoxIn const&, T const&, BoxOut&) {}
|
||||
};
|
||||
|
||||
// Extends a box with the same amount in all directions
|
||||
template<typename BoxIn, typename BoxOut, typename T>
|
||||
inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
|
||||
{
|
||||
assert_dimension_equal<BoxIn, BoxOut>();
|
||||
|
||||
static const std::size_t N = dimension<BoxIn>::value;
|
||||
|
||||
box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);
|
||||
box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out);
|
||||
}
|
||||
|
||||
}} // namespace detail::buffer
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_BOX_HPP
|
||||
@@ -41,10 +41,6 @@
|
||||
|
||||
#include <boost/geometry/views/detail/normalized_view.hpp>
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX)
|
||||
#include <boost/geometry/strategies/cartesian/distance_projected_point_ax.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -67,45 +63,21 @@ inline void simplify_input(Range const& range,
|
||||
// sensitive to small scale input features, however the result will
|
||||
// look better.
|
||||
// It also gets rid of duplicate points
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_SIMPLIFY_WITH_AX)
|
||||
geometry::simplify(range, simplified, distance.simplify_distance());
|
||||
#else
|
||||
|
||||
typedef typename boost::range_value<Range>::type point_type;
|
||||
typedef strategy::distance::detail::projected_point_ax<> ax_type;
|
||||
typedef typename strategy::distance::services::return_type
|
||||
typedef typename geometry::point_type<Range>::type point_type;
|
||||
typedef typename strategy::distance::services::default_strategy
|
||||
<
|
||||
strategy::distance::detail::projected_point_ax<>,
|
||||
point_type,
|
||||
point_type
|
||||
>::type return_type;
|
||||
|
||||
typedef strategy::distance::detail::projected_point_ax_less
|
||||
point_tag, segment_tag, point_type
|
||||
>::type ds_strategy_type;
|
||||
typedef strategy::simplify::douglas_peucker
|
||||
<
|
||||
return_type
|
||||
> comparator_type;
|
||||
point_type, ds_strategy_type
|
||||
> strategy_type;
|
||||
|
||||
typedef strategy::simplify::detail::douglas_peucker
|
||||
<
|
||||
point_type,
|
||||
strategy::distance::detail::projected_point_ax<>,
|
||||
comparator_type
|
||||
> dp_ax;
|
||||
geometry::detail::simplify::simplify_range<2>::apply(range,
|
||||
simplified, distance.simplify_distance(),
|
||||
strategy_type());
|
||||
|
||||
return_type max_distance(distance.simplify_distance() * 2.0,
|
||||
distance.simplify_distance());
|
||||
comparator_type comparator(max_distance);
|
||||
dp_ax strategy(comparator);
|
||||
|
||||
geometry::simplify(range, simplified, max_distance, strategy);
|
||||
#endif
|
||||
|
||||
if (boost::size(simplified) == 2
|
||||
&& geometry::equals(geometry::range::front(simplified),
|
||||
geometry::range::back(simplified)))
|
||||
{
|
||||
traits::resize<Range>::apply(simplified, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +94,8 @@ struct buffer_range
|
||||
typename DistanceStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline
|
||||
void add_join(Collection& collection,
|
||||
@@ -133,18 +106,19 @@ struct buffer_range
|
||||
Point const& input,
|
||||
output_point_type const& perp1,
|
||||
output_point_type const& perp2,
|
||||
strategy::buffer::buffer_side_selector side,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& )
|
||||
RobustPolicy const& ,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
output_point_type intersection_point;
|
||||
geometry::assign_zero(intersection_point);
|
||||
|
||||
strategy::buffer::join_selector join
|
||||
= get_join_type(penultimate_input, previous_input, input);
|
||||
if (join == strategy::buffer::join_convex)
|
||||
geometry::strategy::buffer::join_selector join
|
||||
= get_join_type(penultimate_input, previous_input, input, strategy);
|
||||
if (join == geometry::strategy::buffer::join_convex)
|
||||
{
|
||||
// Calculate the intersection-point formed by the two sides.
|
||||
// It might be that the two sides are not convex, but continue
|
||||
@@ -157,23 +131,23 @@ struct buffer_range
|
||||
|
||||
switch(join)
|
||||
{
|
||||
case strategy::buffer::join_continue :
|
||||
case geometry::strategy::buffer::join_continue :
|
||||
// No join, we get two consecutive sides
|
||||
break;
|
||||
case strategy::buffer::join_concave :
|
||||
case geometry::strategy::buffer::join_concave :
|
||||
{
|
||||
std::vector<output_point_type> range_out;
|
||||
range_out.push_back(prev_perp2);
|
||||
range_out.push_back(previous_input);
|
||||
collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out);
|
||||
collection.add_piece(geometry::strategy::buffer::buffered_concave, previous_input, range_out);
|
||||
|
||||
range_out.clear();
|
||||
range_out.push_back(previous_input);
|
||||
range_out.push_back(perp1);
|
||||
collection.add_piece(strategy::buffer::buffered_concave, previous_input, range_out);
|
||||
collection.add_piece(geometry::strategy::buffer::buffered_concave, previous_input, range_out);
|
||||
}
|
||||
break;
|
||||
case strategy::buffer::join_spike :
|
||||
case geometry::strategy::buffer::join_spike :
|
||||
{
|
||||
// For linestrings, only add spike at one side to avoid
|
||||
// duplicates
|
||||
@@ -183,7 +157,7 @@ struct buffer_range
|
||||
collection.set_current_ring_concave();
|
||||
}
|
||||
break;
|
||||
case strategy::buffer::join_convex :
|
||||
case geometry::strategy::buffer::join_convex :
|
||||
{
|
||||
// The corner is convex, we create a join
|
||||
// TODO (future) - avoid a separate vector, add the piece directly
|
||||
@@ -193,7 +167,7 @@ struct buffer_range
|
||||
distance.apply(previous_input, input, side),
|
||||
range_out))
|
||||
{
|
||||
collection.add_piece(strategy::buffer::buffered_join,
|
||||
collection.add_piece(geometry::strategy::buffer::buffered_join,
|
||||
previous_input, range_out);
|
||||
}
|
||||
}
|
||||
@@ -201,27 +175,24 @@ struct buffer_range
|
||||
}
|
||||
}
|
||||
|
||||
static inline strategy::buffer::join_selector get_join_type(
|
||||
template <typename Strategy>
|
||||
static inline geometry::strategy::buffer::join_selector get_join_type(
|
||||
output_point_type const& p0,
|
||||
output_point_type const& p1,
|
||||
output_point_type const& p2)
|
||||
output_point_type const& p2,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<output_point_type>::type
|
||||
>::type side_strategy;
|
||||
|
||||
int const side = side_strategy::apply(p0, p1, p2);
|
||||
return side == -1 ? strategy::buffer::join_convex
|
||||
: side == 1 ? strategy::buffer::join_concave
|
||||
int const side = strategy.apply(p0, p1, p2);
|
||||
return side == -1 ? geometry::strategy::buffer::join_convex
|
||||
: side == 1 ? geometry::strategy::buffer::join_concave
|
||||
: parallel_continue
|
||||
(
|
||||
get<0>(p2) - get<0>(p1),
|
||||
get<1>(p2) - get<1>(p1),
|
||||
get<0>(p1) - get<0>(p0),
|
||||
get<1>(p1) - get<1>(p0)
|
||||
) ? strategy::buffer::join_continue
|
||||
: strategy::buffer::join_spike;
|
||||
) ? geometry::strategy::buffer::join_continue
|
||||
: geometry::strategy::buffer::join_spike;
|
||||
}
|
||||
|
||||
template
|
||||
@@ -232,16 +203,19 @@ struct buffer_range
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code iterate(Collection& collection,
|
||||
static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
strategy::buffer::buffer_side_selector side,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy, // side strategy
|
||||
bool linear,
|
||||
output_point_type& first_p1,
|
||||
output_point_type& first_p2,
|
||||
output_point_type& last_p1,
|
||||
@@ -273,7 +247,11 @@ struct buffer_range
|
||||
* pup: penultimate_point
|
||||
*/
|
||||
|
||||
strategy::buffer::result_code result = strategy::buffer::result_no_output;
|
||||
bool const mark_flat
|
||||
= linear
|
||||
&& end_strategy.get_piece_type() == geometry::strategy::buffer::buffered_flat_end;
|
||||
|
||||
geometry::strategy::buffer::result_code result = geometry::strategy::buffer::result_no_output;
|
||||
bool first = true;
|
||||
|
||||
Iterator it = begin;
|
||||
@@ -284,25 +262,25 @@ struct buffer_range
|
||||
for (Iterator prev = it++; it != end; ++it)
|
||||
{
|
||||
generated_side.clear();
|
||||
strategy::buffer::result_code error_code
|
||||
geometry::strategy::buffer::result_code error_code
|
||||
= side_strategy.apply(*prev, *it, side,
|
||||
distance_strategy, generated_side);
|
||||
|
||||
if (error_code == strategy::buffer::result_no_output)
|
||||
if (error_code == geometry::strategy::buffer::result_no_output)
|
||||
{
|
||||
// Because input is simplified, this is improbable,
|
||||
// but it can happen for degenerate geometries
|
||||
// Further handling of this side is skipped
|
||||
continue;
|
||||
}
|
||||
else if (error_code == strategy::buffer::result_error_numerical)
|
||||
else if (error_code == geometry::strategy::buffer::result_error_numerical)
|
||||
{
|
||||
return error_code;
|
||||
}
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! generated_side.empty());
|
||||
|
||||
result = strategy::buffer::result_normal;
|
||||
result = geometry::strategy::buffer::result_normal;
|
||||
|
||||
if (! first)
|
||||
{
|
||||
@@ -312,11 +290,16 @@ struct buffer_range
|
||||
*it, generated_side.front(), generated_side.back(),
|
||||
side,
|
||||
distance_strategy, join_strategy, end_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
}
|
||||
|
||||
collection.add_side_piece(*prev, *it, generated_side, first);
|
||||
|
||||
if (first && mark_flat)
|
||||
{
|
||||
collection.mark_flat_start();
|
||||
}
|
||||
|
||||
penultimate_point = *prev;
|
||||
ultimate_point = *it;
|
||||
last_p1 = generated_side.front();
|
||||
@@ -330,6 +313,12 @@ struct buffer_range
|
||||
first_p2 = generated_side.back();
|
||||
}
|
||||
}
|
||||
|
||||
if (mark_flat)
|
||||
{
|
||||
collection.mark_flat_end();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@@ -350,7 +339,8 @@ struct buffer_multi
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(Multi const& multi,
|
||||
Collection& collection,
|
||||
@@ -359,7 +349,8 @@ struct buffer_multi
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
for (typename boost::range_iterator<Multi const>::type
|
||||
it = boost::begin(multi);
|
||||
@@ -369,7 +360,7 @@ struct buffer_multi
|
||||
Policy::apply(*it, collection,
|
||||
distance_strategy, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -393,12 +384,12 @@ inline void buffer_point(Point const& point, Collection& collection,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
PointStrategy const& point_strategy)
|
||||
{
|
||||
collection.start_new_ring();
|
||||
collection.start_new_ring(false);
|
||||
std::vector<OutputPointType> range_out;
|
||||
point_strategy.apply(point, distance_strategy, range_out);
|
||||
collection.add_piece(strategy::buffer::buffered_point, range_out, false);
|
||||
collection.add_piece(geometry::strategy::buffer::buffered_point, range_out, false);
|
||||
collection.set_piece_center(point);
|
||||
collection.finish_ring(strategy::buffer::result_normal);
|
||||
collection.finish_ring(geometry::strategy::buffer::result_normal);
|
||||
}
|
||||
|
||||
|
||||
@@ -436,7 +427,8 @@ struct buffer_inserter<point_tag, Point, RingOutput>
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(Point const& point, Collection& collection,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
@@ -444,7 +436,8 @@ struct buffer_inserter<point_tag, Point, RingOutput>
|
||||
JoinStrategy const& ,
|
||||
EndStrategy const& ,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& )
|
||||
RobustPolicy const& ,
|
||||
Strategy const& ) // side strategy
|
||||
{
|
||||
detail::buffer::buffer_point
|
||||
<
|
||||
@@ -472,29 +465,32 @@ struct buffer_inserter_ring
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code iterate(Collection& collection,
|
||||
static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
strategy::buffer::buffer_side_selector side,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
output_point_type first_p1, first_p2, last_p1, last_p2;
|
||||
|
||||
typedef detail::buffer::buffer_range<RingOutput> buffer_range;
|
||||
|
||||
strategy::buffer::result_code result
|
||||
geometry::strategy::buffer::result_code result
|
||||
= buffer_range::iterate(collection, begin, end,
|
||||
side,
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,
|
||||
first_p1, first_p2, last_p1, last_p2);
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
false, first_p1, first_p2, last_p1, last_p2);
|
||||
|
||||
// Generate closing join
|
||||
if (result == strategy::buffer::result_normal)
|
||||
if (result == geometry::strategy::buffer::result_normal)
|
||||
{
|
||||
buffer_range::add_join(collection,
|
||||
*(end - 2),
|
||||
@@ -502,7 +498,7 @@ struct buffer_inserter_ring
|
||||
*(begin + 1), first_p1, first_p2,
|
||||
side,
|
||||
distance_strategy, join_strategy, end_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
}
|
||||
|
||||
// Buffer is closed automatically by last closing corner
|
||||
@@ -517,21 +513,23 @@ struct buffer_inserter_ring
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code apply(RingInput const& ring,
|
||||
static inline geometry::strategy::buffer::result_code apply(RingInput const& ring,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
RingInput simplified;
|
||||
detail::buffer::simplify_input(ring, distance, simplified);
|
||||
|
||||
strategy::buffer::result_code code = strategy::buffer::result_no_output;
|
||||
geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
|
||||
|
||||
std::size_t n = boost::size(simplified);
|
||||
std::size_t const min_points = core_detail::closure::minimum_ring_size
|
||||
@@ -546,18 +544,20 @@ struct buffer_inserter_ring
|
||||
{
|
||||
// Walk backwards (rings will be reversed afterwards)
|
||||
code = iterate(collection, boost::rbegin(view), boost::rend(view),
|
||||
strategy::buffer::buffer_side_right,
|
||||
distance, side_strategy, join_strategy, end_strategy, robust_policy);
|
||||
geometry::strategy::buffer::buffer_side_right,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
code = iterate(collection, boost::begin(view), boost::end(view),
|
||||
strategy::buffer::buffer_side_left,
|
||||
distance, side_strategy, join_strategy, end_strategy, robust_policy);
|
||||
geometry::strategy::buffer::buffer_side_left,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
if (code == strategy::buffer::result_no_output && n >= 1)
|
||||
if (code == geometry::strategy::buffer::result_no_output && n >= 1)
|
||||
{
|
||||
// Use point_strategy to buffer degenerated ring
|
||||
detail::buffer::buffer_point<output_point_type>
|
||||
@@ -586,23 +586,25 @@ struct buffer_inserter<ring_tag, RingInput, RingOutput>
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code apply(RingInput const& ring,
|
||||
static inline geometry::strategy::buffer::result_code apply(RingInput const& ring,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
collection.start_new_ring();
|
||||
strategy::buffer::result_code const code
|
||||
collection.start_new_ring(distance.negative());
|
||||
geometry::strategy::buffer::result_code const code
|
||||
= buffer_inserter_ring<RingInput, RingOutput>::apply(ring,
|
||||
collection, distance,
|
||||
side_strategy, join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
collection.finish_ring(code);
|
||||
return code;
|
||||
}
|
||||
@@ -627,16 +629,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
typename SideStrategy,
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code iterate(Collection& collection,
|
||||
static inline geometry::strategy::buffer::result_code iterate(Collection& collection,
|
||||
Iterator begin, Iterator end,
|
||||
strategy::buffer::buffer_side_selector side,
|
||||
geometry::strategy::buffer::buffer_side_selector side,
|
||||
DistanceStrategy const& distance_strategy,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy, // side strategy
|
||||
output_point_type& first_p1)
|
||||
{
|
||||
input_point_type const& ultimate_point = *(end - 1);
|
||||
@@ -647,18 +651,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
// we have it already from the first phase (left).
|
||||
// But for the first pass, we have to generate it
|
||||
output_point_type reverse_p1;
|
||||
if (side == strategy::buffer::buffer_side_right)
|
||||
if (side == geometry::strategy::buffer::buffer_side_right)
|
||||
{
|
||||
reverse_p1 = first_p1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<output_point_type> generated_side;
|
||||
strategy::buffer::result_code code
|
||||
geometry::strategy::buffer::result_code code
|
||||
= side_strategy.apply(ultimate_point, penultimate_point,
|
||||
strategy::buffer::buffer_side_right,
|
||||
geometry::strategy::buffer::buffer_side_right,
|
||||
distance_strategy, generated_side);
|
||||
if (code != strategy::buffer::result_normal)
|
||||
if (code != geometry::strategy::buffer::result_normal)
|
||||
{
|
||||
// No output or numerical error
|
||||
return code;
|
||||
@@ -668,16 +672,18 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
|
||||
output_point_type first_p2, last_p1, last_p2;
|
||||
|
||||
strategy::buffer::result_code result
|
||||
geometry::strategy::buffer::result_code result
|
||||
= detail::buffer::buffer_range<output_ring_type>::iterate(collection,
|
||||
begin, end, side,
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy, robust_policy,
|
||||
first_p1, first_p2, last_p1, last_p2);
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
true, first_p1, first_p2, last_p1, last_p2);
|
||||
|
||||
if (result == strategy::buffer::result_normal)
|
||||
if (result == geometry::strategy::buffer::result_normal)
|
||||
{
|
||||
std::vector<output_point_type> range_out;
|
||||
end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1, side, distance_strategy, range_out);
|
||||
end_strategy.apply(penultimate_point, last_p2, ultimate_point, reverse_p1,
|
||||
side, distance_strategy, range_out);
|
||||
collection.add_endcap(end_strategy, range_out, ultimate_point);
|
||||
}
|
||||
return result;
|
||||
@@ -691,42 +697,47 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline strategy::buffer::result_code apply(Linestring const& linestring, Collection& collection,
|
||||
static inline geometry::strategy::buffer::result_code apply(Linestring const& linestring,
|
||||
Collection& collection,
|
||||
DistanceStrategy const& distance,
|
||||
SideStrategy const& side_strategy,
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
Linestring simplified;
|
||||
detail::buffer::simplify_input(linestring, distance, simplified);
|
||||
|
||||
strategy::buffer::result_code code = strategy::buffer::result_no_output;
|
||||
geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
|
||||
std::size_t n = boost::size(simplified);
|
||||
if (n > 1)
|
||||
{
|
||||
collection.start_new_ring();
|
||||
collection.start_new_ring(false);
|
||||
output_point_type first_p1;
|
||||
code = iterate(collection,
|
||||
boost::begin(simplified), boost::end(simplified),
|
||||
strategy::buffer::buffer_side_left,
|
||||
distance, side_strategy, join_strategy, end_strategy, robust_policy,
|
||||
geometry::strategy::buffer::buffer_side_left,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
first_p1);
|
||||
|
||||
if (code == strategy::buffer::result_normal)
|
||||
if (code == geometry::strategy::buffer::result_normal)
|
||||
{
|
||||
code = iterate(collection,
|
||||
boost::rbegin(simplified), boost::rend(simplified),
|
||||
strategy::buffer::buffer_side_right,
|
||||
distance, side_strategy, join_strategy, end_strategy, robust_policy,
|
||||
geometry::strategy::buffer::buffer_side_right,
|
||||
distance, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
first_p1);
|
||||
}
|
||||
collection.finish_ring(code);
|
||||
}
|
||||
if (code == strategy::buffer::result_no_output && n >= 1)
|
||||
if (code == geometry::strategy::buffer::result_no_output && n >= 1)
|
||||
{
|
||||
// Use point_strategy to buffer degenerated linestring
|
||||
detail::buffer::buffer_point<output_point_type>
|
||||
@@ -763,7 +774,8 @@ private:
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline
|
||||
void iterate(Iterator begin, Iterator end,
|
||||
@@ -774,15 +786,22 @@ private:
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy, // side strategy
|
||||
bool is_interior)
|
||||
{
|
||||
for (Iterator it = begin; it != end; ++it)
|
||||
{
|
||||
collection.start_new_ring();
|
||||
strategy::buffer::result_code const code
|
||||
// For exterior rings, it deflates if distance is negative.
|
||||
// For interior rings, it is vice versa
|
||||
bool const deflate = is_interior
|
||||
? ! distance.negative()
|
||||
: distance.negative();
|
||||
|
||||
collection.start_new_ring(deflate);
|
||||
geometry::strategy::buffer::result_code const code
|
||||
= policy::apply(*it, collection, distance, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
|
||||
collection.finish_ring(code, is_interior);
|
||||
}
|
||||
@@ -797,7 +816,8 @@ private:
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline
|
||||
void apply_interior_rings(InteriorRings const& interior_rings,
|
||||
@@ -807,12 +827,13 @@ private:
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
iterate(boost::begin(interior_rings), boost::end(interior_rings),
|
||||
collection, distance, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy, true);
|
||||
robust_policy, strategy, true);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -824,7 +845,8 @@ public:
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(PolygonInput const& polygon,
|
||||
Collection& collection,
|
||||
@@ -833,16 +855,17 @@ public:
|
||||
JoinStrategy const& join_strategy,
|
||||
EndStrategy const& end_strategy,
|
||||
PointStrategy const& point_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy) // side strategy
|
||||
{
|
||||
{
|
||||
collection.start_new_ring();
|
||||
collection.start_new_ring(distance.negative());
|
||||
|
||||
strategy::buffer::result_code const code
|
||||
geometry::strategy::buffer::result_code const code
|
||||
= policy::apply(exterior_ring(polygon), collection,
|
||||
distance, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
|
||||
collection.finish_ring(code, false,
|
||||
geometry::num_interior_rings(polygon) > 0u);
|
||||
@@ -851,7 +874,7 @@ public:
|
||||
apply_interior_rings(interior_rings(polygon),
|
||||
collection, distance, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -927,11 +950,6 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
typename tag_cast<typename tag<GeometryInput>::type, areal_tag>::type,
|
||||
areal_tag
|
||||
>::type::value;
|
||||
bool const linear = boost::is_same
|
||||
<
|
||||
typename tag_cast<typename tag<GeometryInput>::type, linear_tag>::type,
|
||||
linear_tag
|
||||
>::type::value;
|
||||
|
||||
dispatch::buffer_inserter
|
||||
<
|
||||
@@ -945,10 +963,10 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
|
||||
>::apply(geometry_input, collection,
|
||||
distance_strategy, side_strategy, join_strategy,
|
||||
end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, intersection_strategy.get_side_strategy());
|
||||
|
||||
collection.get_turns();
|
||||
collection.classify_turns(linear);
|
||||
collection.classify_turns();
|
||||
if (BOOST_GEOMETRY_CONDITION(areal))
|
||||
{
|
||||
collection.check_remaining_points(distance_strategy);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-2018, 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,
|
||||
@@ -13,10 +13,6 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
|
||||
# define BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
@@ -26,6 +22,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
@@ -127,6 +124,10 @@ public :
|
||||
void visit_traverse_reject(Turns const& , Turn const& , Operation const& ,
|
||||
detail::overlay::traverse_error_type )
|
||||
{}
|
||||
|
||||
template <typename Rings>
|
||||
void visit_generated_rings(Rings const& )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -177,9 +178,7 @@ struct buffer_turn_info
|
||||
|
||||
intersection_location_type location;
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
robust_point_type rob_pi, rob_pj, rob_qi, rob_qj;
|
||||
#endif
|
||||
|
||||
std::size_t count_within;
|
||||
|
||||
@@ -189,9 +188,7 @@ struct buffer_turn_info
|
||||
|
||||
std::size_t count_on_offsetted;
|
||||
std::size_t count_on_helper;
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
std::size_t count_within_near_offsetted;
|
||||
#endif
|
||||
|
||||
bool remove_on_multi;
|
||||
|
||||
@@ -208,9 +205,7 @@ struct buffer_turn_info
|
||||
, count_in_original(0)
|
||||
, count_on_offsetted(0)
|
||||
, count_on_helper(0)
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
, count_within_near_offsetted(0)
|
||||
#endif
|
||||
, remove_on_multi(false)
|
||||
, count_on_occupied(0)
|
||||
, count_on_multi(0)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2016-2017.
|
||||
// Modifications copyright (c) 2016-2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2016-2018.
|
||||
// Modifications copyright (c) 2016-2018 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,
|
||||
@@ -46,6 +47,7 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traverse.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
@@ -142,10 +144,34 @@ 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::envelope_strategy_type envelope_strategy_type;
|
||||
typedef typename IntersectionStrategy::expand_strategy_type expand_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::template result_type
|
||||
<
|
||||
point_type
|
||||
>::type area_result_type;
|
||||
typedef typename robust_area_strategy_type::template result_type
|
||||
<
|
||||
robust_point_type
|
||||
>::type robust_area_result_type;
|
||||
|
||||
typedef typename strategy::point_in_geometry::services::default_strategy
|
||||
<
|
||||
robust_point_type,
|
||||
robust_ring_type
|
||||
>::type point_in_geometry_strategy_type;
|
||||
|
||||
typedef typename geometry::rescale_policy_type
|
||||
<
|
||||
@@ -206,7 +232,10 @@ struct buffered_piece_collection
|
||||
// 2: half, not part of offsetted rings - part of robust ring
|
||||
std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end
|
||||
#endif
|
||||
bool is_flat_start;
|
||||
bool is_flat_end;
|
||||
|
||||
bool is_deflated;
|
||||
bool is_convex;
|
||||
bool is_monotonic_increasing[2]; // 0=x, 1=y
|
||||
bool is_monotonic_decreasing[2]; // 0=x, 1=y
|
||||
@@ -234,6 +263,9 @@ struct buffered_piece_collection
|
||||
, right_index(-1)
|
||||
, last_segment_index(-1)
|
||||
, offsetted_count(-1)
|
||||
, is_flat_start(false)
|
||||
, is_flat_end(false)
|
||||
, is_deflated(false)
|
||||
, is_convex(false)
|
||||
, robust_min_comparable_radius(0)
|
||||
, robust_max_comparable_radius(0)
|
||||
@@ -256,12 +288,14 @@ struct buffered_piece_collection
|
||||
{}
|
||||
|
||||
inline robust_original(robust_ring_type const& ring,
|
||||
bool is_interior, bool has_interiors)
|
||||
bool is_interior, bool has_interiors,
|
||||
envelope_strategy_type const& envelope_strategy,
|
||||
expand_strategy_type const& expand_strategy)
|
||||
: m_ring(ring)
|
||||
, m_is_interior(is_interior)
|
||||
, m_has_interiors(has_interiors)
|
||||
{
|
||||
geometry::envelope(m_ring, m_box);
|
||||
geometry::envelope(m_ring, m_box, envelope_strategy);
|
||||
|
||||
// create monotonic sections in x-dimension
|
||||
// The dimension is critical because the direction is later used
|
||||
@@ -269,7 +303,8 @@ struct buffered_piece_collection
|
||||
// and this strategy is scanning in x direction.
|
||||
typedef boost::mpl::vector_c<std::size_t, 0> dimensions;
|
||||
geometry::sectionalize<false, dimensions>(m_ring,
|
||||
detail::no_rescale_policy(), m_sections);
|
||||
detail::no_rescale_policy(), m_sections,
|
||||
envelope_strategy, expand_strategy);
|
||||
}
|
||||
|
||||
robust_ring_type m_ring;
|
||||
@@ -285,6 +320,8 @@ struct buffered_piece_collection
|
||||
piece_vector_type m_pieces;
|
||||
turn_vector_type m_turns;
|
||||
signed_size_type m_first_piece_index;
|
||||
bool m_deflate;
|
||||
bool m_has_deflated;
|
||||
|
||||
buffered_ring_collection<buffered_ring<Ring> > offsetted_rings; // indexed by multi_index
|
||||
std::vector<robust_original> robust_originals; // robust representation of the original(s)
|
||||
@@ -306,7 +343,13 @@ 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;
|
||||
envelope_strategy_type m_envelope_strategy;
|
||||
expand_strategy_type m_expand_strategy;
|
||||
|
||||
robust_area_strategy_type m_robust_area_strategy;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
|
||||
struct redundant_turn
|
||||
@@ -320,7 +363,14 @@ struct buffered_piece_collection
|
||||
buffered_piece_collection(IntersectionStrategy const& intersection_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
: m_first_piece_index(-1)
|
||||
, m_deflate(false)
|
||||
, m_has_deflated(false)
|
||||
, 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_envelope_strategy(intersection_strategy.get_envelope_strategy())
|
||||
, m_expand_strategy(intersection_strategy.get_expand_strategy())
|
||||
, m_robust_area_strategy(intersection_strategy.template get_area_strategy<robust_point_type>())
|
||||
, m_robust_policy(robust_policy)
|
||||
{}
|
||||
|
||||
@@ -478,11 +528,11 @@ struct buffered_piece_collection
|
||||
for (typename occupation_map_type::iterator it = occupation_map.begin();
|
||||
it != occupation_map.end(); ++it)
|
||||
{
|
||||
it->second.get_left_turns(it->first, m_turns);
|
||||
it->second.get_left_turns(it->first, m_turns, m_side_strategy);
|
||||
}
|
||||
}
|
||||
|
||||
inline void classify_turns(bool linear)
|
||||
inline void classify_turns()
|
||||
{
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it)
|
||||
@@ -491,11 +541,10 @@ struct buffered_piece_collection
|
||||
{
|
||||
it->location = inside_buffer;
|
||||
}
|
||||
if (it->count_on_original_boundary > 0 && ! linear)
|
||||
if (it->count_on_original_boundary > 0)
|
||||
{
|
||||
it->location = inside_buffer;
|
||||
}
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
if (it->count_within_near_offsetted > 0)
|
||||
{
|
||||
// Within can have in rare cases a rounding issue. We don't discard this
|
||||
@@ -504,7 +553,94 @@ struct buffered_piece_collection
|
||||
it->operations[0].enriched.startable = false;
|
||||
it->operations[1].enriched.startable = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
struct deflate_properties
|
||||
{
|
||||
bool has_inflated;
|
||||
std::size_t count;
|
||||
|
||||
inline deflate_properties()
|
||||
: has_inflated(false)
|
||||
, count(0u)
|
||||
{}
|
||||
};
|
||||
|
||||
inline void discard_turns_for_deflate()
|
||||
{
|
||||
// Deflate cases should have at least 3 points PER deflated original
|
||||
// to form a correct triangle
|
||||
|
||||
// But if there are intersections between a deflated ring and another
|
||||
// ring, it is all accepted
|
||||
|
||||
// In deflate most turns are i/u by nature, but u/u is also possible
|
||||
|
||||
std::map<signed_size_type, deflate_properties> properties;
|
||||
|
||||
for (typename boost::range_iterator<turn_vector_type const>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it)
|
||||
{
|
||||
const buffer_turn_info_type& turn = *it;
|
||||
if (turn.location == location_ok)
|
||||
{
|
||||
const buffer_turn_operation_type& op0 = turn.operations[0];
|
||||
const buffer_turn_operation_type& op1 = turn.operations[1];
|
||||
|
||||
if (! m_pieces[op0.seg_id.piece_index].is_deflated
|
||||
|| ! m_pieces[op1.seg_id.piece_index].is_deflated)
|
||||
{
|
||||
properties[op0.seg_id.multi_index].has_inflated = true;
|
||||
properties[op1.seg_id.multi_index].has_inflated = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// It is deflated, update counts
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
const buffer_turn_operation_type& op = turn.operations[i];
|
||||
if (op.operation == detail::overlay::operation_union
|
||||
|| op.operation == detail::overlay::operation_continue)
|
||||
{
|
||||
properties[op.seg_id.multi_index].count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (typename boost::range_iterator<turn_vector_type>::type it =
|
||||
boost::begin(m_turns); it != boost::end(m_turns); ++it)
|
||||
{
|
||||
buffer_turn_info_type& turn = *it;
|
||||
|
||||
if (turn.location == location_ok)
|
||||
{
|
||||
const buffer_turn_operation_type& op0 = turn.operations[0];
|
||||
const buffer_turn_operation_type& op1 = turn.operations[1];
|
||||
signed_size_type const multi0 = op0.seg_id.multi_index;
|
||||
signed_size_type const multi1 = op1.seg_id.multi_index;
|
||||
|
||||
if (multi0 == multi1)
|
||||
{
|
||||
const deflate_properties& prop = properties[multi0];
|
||||
|
||||
// NOTE: Keep brackets around prop.count
|
||||
// avoid gcc-bug "parse error in template argument list"
|
||||
// GCC versions 5.4 and 5.5 (and probably more)
|
||||
if (! prop.has_inflated && (prop.count) < 3)
|
||||
{
|
||||
// Property is not inflated
|
||||
// Not enough points, this might be caused by <float> where
|
||||
// detection turn-in-original failed because of numeric errors
|
||||
turn.location = location_discard;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Two different (possibly deflated) rings
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,6 +649,15 @@ struct buffered_piece_collection
|
||||
{
|
||||
// Check if a turn is inside any of the originals
|
||||
|
||||
typedef turn_in_original_ovelaps_box
|
||||
<
|
||||
typename IntersectionStrategy::disjoint_point_box_strategy_type
|
||||
> turn_in_original_ovelaps_box_type;
|
||||
typedef original_ovelaps_box
|
||||
<
|
||||
typename IntersectionStrategy::disjoint_box_box_strategy_type
|
||||
> original_ovelaps_box_type;
|
||||
|
||||
turn_in_original_visitor<turn_vector_type> visitor(m_turns);
|
||||
geometry::partition
|
||||
<
|
||||
@@ -520,8 +665,8 @@ struct buffered_piece_collection
|
||||
include_turn_policy,
|
||||
detail::partition::include_all_policy
|
||||
>::apply(m_turns, robust_originals, visitor,
|
||||
turn_get_box(), turn_in_original_ovelaps_box(),
|
||||
original_get_box(), original_ovelaps_box());
|
||||
turn_get_box(), turn_in_original_ovelaps_box_type(),
|
||||
original_get_box(), original_ovelaps_box_type());
|
||||
|
||||
bool const deflate = distance_strategy.negative();
|
||||
|
||||
@@ -533,7 +678,7 @@ struct buffered_piece_collection
|
||||
{
|
||||
if (deflate && turn.count_in_original <= 0)
|
||||
{
|
||||
// For deflate: it is not in original, discard
|
||||
// For deflate/negative buffers: it is not in original, discard
|
||||
turn.location = location_discard;
|
||||
}
|
||||
else if (! deflate && turn.count_in_original > 0)
|
||||
@@ -543,6 +688,12 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_has_deflated)
|
||||
{
|
||||
// Either strategy was negative, or there were interior rings
|
||||
discard_turns_for_deflate();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool assert_indices_in_robust_rings() const
|
||||
@@ -599,46 +750,47 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// Insert all rescaled turn-points into these rings, to form a
|
||||
// reliable integer-based ring. All turns can be compared (inside) to this
|
||||
// rings to see if they are inside.
|
||||
|
||||
for (typename boost::range_iterator<piece_vector_type>::type
|
||||
it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it)
|
||||
if (! use_side_of_intersection<typename geometry::cs_tag<point_type>::type>::value)
|
||||
{
|
||||
piece& pc = *it;
|
||||
signed_size_type piece_segment_index = pc.first_seg_id.segment_index;
|
||||
if (! pc.robust_turns.empty())
|
||||
// Insert all rescaled turn-points into these rings, to form a
|
||||
// reliable integer-based ring. All turns can be compared (inside) to this
|
||||
// rings to see if they are inside.
|
||||
|
||||
for (typename boost::range_iterator<piece_vector_type>::type
|
||||
it = boost::begin(m_pieces); it != boost::end(m_pieces); ++it)
|
||||
{
|
||||
if (pc.robust_turns.size() > 1u)
|
||||
piece& pc = *it;
|
||||
signed_size_type piece_segment_index = pc.first_seg_id.segment_index;
|
||||
if (! pc.robust_turns.empty())
|
||||
{
|
||||
std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less());
|
||||
}
|
||||
// Walk through them, in reverse to insert at right index
|
||||
signed_size_type index_offset = static_cast<signed_size_type>(pc.robust_turns.size()) - 1;
|
||||
for (typename boost::range_reverse_iterator<const std::vector<robust_turn> >::type
|
||||
rit = boost::const_rbegin(pc.robust_turns);
|
||||
rit != boost::const_rend(pc.robust_turns);
|
||||
++rit, --index_offset)
|
||||
{
|
||||
signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index;
|
||||
BOOST_GEOMETRY_ASSERT
|
||||
(
|
||||
index_in_vector > 0
|
||||
&& index_in_vector < pc.offsetted_count
|
||||
);
|
||||
if (pc.robust_turns.size() > 1u)
|
||||
{
|
||||
std::sort(pc.robust_turns.begin(), pc.robust_turns.end(), buffer_operation_less());
|
||||
}
|
||||
// Walk through them, in reverse to insert at right index
|
||||
signed_size_type index_offset = static_cast<signed_size_type>(pc.robust_turns.size()) - 1;
|
||||
for (typename boost::range_reverse_iterator<const std::vector<robust_turn> >::type
|
||||
rit = boost::const_rbegin(pc.robust_turns);
|
||||
rit != boost::const_rend(pc.robust_turns);
|
||||
++rit, --index_offset)
|
||||
{
|
||||
signed_size_type const index_in_vector = 1 + rit->seg_id.segment_index - piece_segment_index;
|
||||
BOOST_GEOMETRY_ASSERT
|
||||
(
|
||||
index_in_vector > 0
|
||||
&& index_in_vector < pc.offsetted_count
|
||||
);
|
||||
|
||||
pc.robust_ring.insert(boost::begin(pc.robust_ring) + index_in_vector, rit->point);
|
||||
pc.offsetted_count++;
|
||||
pc.robust_ring.insert(boost::begin(pc.robust_ring) + index_in_vector, rit->point);
|
||||
pc.offsetted_count++;
|
||||
|
||||
m_turns[rit->turn_index].operations[rit->operation_index].index_in_robust_ring = index_in_vector + index_offset;
|
||||
m_turns[rit->turn_index].operations[rit->operation_index].index_in_robust_ring = index_in_vector + index_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings());
|
||||
#endif
|
||||
BOOST_GEOMETRY_ASSERT(assert_indices_in_robust_rings());
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t Dimension>
|
||||
@@ -699,7 +851,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
|
||||
@@ -714,7 +866,8 @@ struct buffered_piece_collection
|
||||
// create monotonic sections in y-dimension
|
||||
typedef boost::mpl::vector_c<std::size_t, 1> dimensions;
|
||||
geometry::sectionalize<false, dimensions>(pc.robust_ring,
|
||||
detail::no_rescale_policy(), pc.sections);
|
||||
detail::no_rescale_policy(), pc.sections,
|
||||
m_envelope_strategy, m_expand_strategy);
|
||||
|
||||
// Determine min/max radius
|
||||
typedef geometry::model::referring_segment<robust_point_type const>
|
||||
@@ -778,12 +931,21 @@ struct buffered_piece_collection
|
||||
> visitor(m_pieces, offsetted_rings, m_turns,
|
||||
m_intersection_strategy, m_robust_policy);
|
||||
|
||||
typedef detail::section::get_section_box
|
||||
<
|
||||
typename IntersectionStrategy::expand_box_strategy_type
|
||||
> get_section_box_type;
|
||||
typedef detail::section::overlaps_section_box
|
||||
<
|
||||
typename IntersectionStrategy::disjoint_box_box_strategy_type
|
||||
> overlaps_section_box_type;
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
robust_box_type
|
||||
>::apply(monotonic_sections, visitor,
|
||||
detail::section::get_section_box(),
|
||||
detail::section::overlaps_section_box());
|
||||
get_section_box_type(),
|
||||
overlaps_section_box_type());
|
||||
}
|
||||
|
||||
insert_rescaled_piece_turns();
|
||||
@@ -798,20 +960,31 @@ struct buffered_piece_collection
|
||||
// Check if it is inside any of the pieces
|
||||
turn_in_piece_visitor
|
||||
<
|
||||
turn_vector_type, piece_vector_type
|
||||
> visitor(m_turns, m_pieces);
|
||||
typename geometry::cs_tag<point_type>::type,
|
||||
turn_vector_type, piece_vector_type,
|
||||
point_in_geometry_strategy_type
|
||||
> visitor(m_turns, m_pieces, point_in_geometry_strategy_type());
|
||||
|
||||
typedef turn_ovelaps_box
|
||||
<
|
||||
typename IntersectionStrategy::disjoint_point_box_strategy_type
|
||||
> turn_ovelaps_box_type;
|
||||
typedef piece_ovelaps_box
|
||||
<
|
||||
typename IntersectionStrategy::disjoint_box_box_strategy_type
|
||||
> piece_ovelaps_box_type;
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
robust_box_type
|
||||
>::apply(m_turns, m_pieces, visitor,
|
||||
turn_get_box(), turn_ovelaps_box(),
|
||||
piece_get_box(), piece_ovelaps_box());
|
||||
turn_get_box(), turn_ovelaps_box_type(),
|
||||
piece_get_box(), piece_ovelaps_box_type());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
inline void start_new_ring()
|
||||
inline void start_new_ring(bool deflate)
|
||||
{
|
||||
signed_size_type const n = static_cast<signed_size_type>(offsetted_rings.size());
|
||||
current_segment_id.source_index = 0;
|
||||
@@ -823,6 +996,13 @@ struct buffered_piece_collection
|
||||
current_robust_ring.clear();
|
||||
|
||||
m_first_piece_index = static_cast<signed_size_type>(boost::size(m_pieces));
|
||||
m_deflate = deflate;
|
||||
if (deflate)
|
||||
{
|
||||
// Pieces contain either deflated exterior rings, or inflated
|
||||
// interior rings which are effectively deflated too
|
||||
m_has_deflated = true;
|
||||
}
|
||||
}
|
||||
|
||||
inline void abort_ring()
|
||||
@@ -922,7 +1102,7 @@ struct buffered_piece_collection
|
||||
|
||||
robust_originals.push_back(
|
||||
robust_original(current_robust_ring,
|
||||
is_interior, has_interiors));
|
||||
is_interior, has_interiors, m_envelope_strategy, m_expand_strategy));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -957,12 +1137,12 @@ struct buffered_piece_collection
|
||||
piece pc;
|
||||
pc.type = type;
|
||||
pc.index = static_cast<signed_size_type>(boost::size(m_pieces));
|
||||
pc.is_deflated = m_deflate;
|
||||
|
||||
current_segment_id.piece_index = pc.index;
|
||||
|
||||
pc.first_seg_id = current_segment_id;
|
||||
|
||||
|
||||
// Assign left/right (for first/last piece per ring they will be re-assigned later)
|
||||
pc.left_index = pc.index - 1;
|
||||
pc.right_index = pc.index + 1;
|
||||
@@ -1039,7 +1219,7 @@ struct buffered_piece_collection
|
||||
return;
|
||||
}
|
||||
|
||||
geometry::envelope(pc.robust_ring, pc.robust_envelope);
|
||||
geometry::envelope(pc.robust_ring, pc.robust_envelope, m_envelope_strategy);
|
||||
|
||||
geometry::assign_inverse(pc.robust_offsetted_envelope);
|
||||
for (signed_size_type i = 0; i < pc.offsetted_count; i++)
|
||||
@@ -1216,18 +1396,31 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
|
||||
inline void mark_flat_start()
|
||||
{
|
||||
if (! m_pieces.empty())
|
||||
{
|
||||
piece& back = m_pieces.back();
|
||||
back.is_flat_start = true;
|
||||
}
|
||||
}
|
||||
|
||||
inline void mark_flat_end()
|
||||
{
|
||||
if (! m_pieces.empty())
|
||||
{
|
||||
piece& back = m_pieces.back();
|
||||
back.is_flat_end = true;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
@@ -1252,6 +1445,8 @@ struct buffered_piece_collection
|
||||
|
||||
inline bool point_coveredby_original(point_type const& point)
|
||||
{
|
||||
typedef typename IntersectionStrategy::disjoint_point_box_strategy_type d_pb_strategy_type;
|
||||
|
||||
robust_point_type any_point;
|
||||
geometry::recalculate(any_point, point, m_robust_policy);
|
||||
|
||||
@@ -1268,14 +1463,15 @@ struct buffered_piece_collection
|
||||
{
|
||||
robust_original const& original = *it;
|
||||
if (detail::disjoint::disjoint_point_box(any_point,
|
||||
original.m_box))
|
||||
original.m_box,
|
||||
d_pb_strategy_type()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int const geometry_code
|
||||
= detail::within::point_in_geometry(any_point,
|
||||
original.m_ring);
|
||||
original.m_ring, point_in_geometry_strategy_type());
|
||||
|
||||
if (geometry_code == -1)
|
||||
{
|
||||
@@ -1314,7 +1510,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)))
|
||||
{
|
||||
@@ -1358,12 +1554,14 @@ struct buffered_piece_collection
|
||||
overlay_buffer,
|
||||
backtrack_for_buffer
|
||||
> traverser;
|
||||
std::map<ring_identifier, overlay::ring_turn_info> turn_info_per_ring;
|
||||
|
||||
traversed_rings.clear();
|
||||
buffer_overlay_visitor visitor;
|
||||
traverser::apply(offsetted_rings, offsetted_rings,
|
||||
m_intersection_strategy, m_robust_policy,
|
||||
m_turns, traversed_rings,
|
||||
turn_info_per_ring,
|
||||
m_clusters, visitor);
|
||||
}
|
||||
|
||||
@@ -1391,7 +1589,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 +1605,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 +1621,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);
|
||||
@@ -1431,8 +1629,10 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
|
||||
detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, true);
|
||||
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out);
|
||||
detail::overlay::assign_parents<overlay_buffer>(offsetted_rings, traversed_rings,
|
||||
selected, m_intersection_strategy);
|
||||
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out,
|
||||
m_area_strategy);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-2018 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,
|
||||
@@ -13,8 +14,10 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_GET_PIECE_TURNS_HPP
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
@@ -32,34 +35,81 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace buffer
|
||||
{
|
||||
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
struct buffer_assign_turn
|
||||
// Implements a unique_sub_range for a buffered piece,
|
||||
// the range can return subsequent points
|
||||
// known as "i", "j" and "k" (and further), indexed as 0,1,2,3
|
||||
template <typename Ring>
|
||||
struct unique_sub_range_from_piece
|
||||
{
|
||||
static bool const include_no_turn = false;
|
||||
static bool const include_degenerate = false;
|
||||
static bool const include_opposite = false;
|
||||
typedef typename boost::range_iterator<Ring const>::type iterator_type;
|
||||
typedef typename geometry::point_type<Ring const>::type point_type;
|
||||
|
||||
template
|
||||
<
|
||||
typename Info,
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionInfo
|
||||
>
|
||||
static inline void apply(Info& info,
|
||||
Point1 const& /*p1*/,
|
||||
Point2 const& /*p2*/,
|
||||
IntersectionInfo const& iinfo)
|
||||
unique_sub_range_from_piece(Ring const& ring,
|
||||
iterator_type iterator_at_i, iterator_type iterator_at_j)
|
||||
: m_ring(ring)
|
||||
, m_iterator_at_i(iterator_at_i)
|
||||
, m_iterator_at_j(iterator_at_j)
|
||||
, m_point_retrieved(false)
|
||||
{}
|
||||
|
||||
static inline bool is_first_segment() { return false; }
|
||||
static inline bool is_last_segment() { return false; }
|
||||
|
||||
static inline std::size_t size() { return 3u; }
|
||||
|
||||
inline point_type const& at(std::size_t index) const
|
||||
{
|
||||
info.rob_pi = iinfo.rpi();
|
||||
info.rob_pj = iinfo.rpj();
|
||||
info.rob_qi = iinfo.rqi();
|
||||
info.rob_qj = iinfo.rqj();
|
||||
BOOST_GEOMETRY_ASSERT(index < size());
|
||||
switch (index)
|
||||
{
|
||||
case 0 : return *m_iterator_at_i;
|
||||
case 1 : return *m_iterator_at_j;
|
||||
case 2 : return get_point_k();
|
||||
default : return *m_iterator_at_i;
|
||||
}
|
||||
}
|
||||
|
||||
private :
|
||||
|
||||
inline point_type const& get_point_k() const
|
||||
{
|
||||
if (! m_point_retrieved)
|
||||
{
|
||||
m_iterator_at_k = advance_one(m_iterator_at_j);
|
||||
m_point_retrieved = true;
|
||||
}
|
||||
return *m_iterator_at_k;
|
||||
}
|
||||
|
||||
inline void circular_advance_one(iterator_type& next) const
|
||||
{
|
||||
++next;
|
||||
if (next == boost::end(m_ring))
|
||||
{
|
||||
next = boost::begin(m_ring) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline iterator_type advance_one(iterator_type it) const
|
||||
{
|
||||
iterator_type result = it;
|
||||
circular_advance_one(result);
|
||||
|
||||
// TODO: we could also use piece-boundaries
|
||||
// to check if the point equals the last one
|
||||
while (geometry::equals(*it, *result))
|
||||
{
|
||||
circular_advance_one(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Ring const& m_ring;
|
||||
iterator_type m_iterator_at_i;
|
||||
iterator_type m_iterator_at_j;
|
||||
mutable iterator_type m_iterator_at_k;
|
||||
mutable bool m_point_retrieved;
|
||||
};
|
||||
#endif
|
||||
|
||||
template
|
||||
<
|
||||
@@ -100,52 +150,34 @@ class piece_turn_visitor
|
||||
return ! m_rings[piece1.first_seg_id.multi_index].has_concave;
|
||||
}
|
||||
|
||||
template <typename Range, typename Iterator>
|
||||
inline void move_to_next_point(Range const& range, Iterator& next) const
|
||||
{
|
||||
++next;
|
||||
if (next == boost::end(range))
|
||||
{
|
||||
next = boost::begin(range) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Range, typename Iterator>
|
||||
inline Iterator next_point(Range const& range, Iterator it) const
|
||||
{
|
||||
Iterator result = it;
|
||||
move_to_next_point(range, result);
|
||||
// TODO: we could use either piece-boundaries, or comparison with
|
||||
// robust points, to check if the point equals the last one
|
||||
while(geometry::equals(*it, *result))
|
||||
{
|
||||
move_to_next_point(range, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_begin_iterator(Iterator& it_begin, Iterator it_beyond,
|
||||
signed_size_type& index, int dir, Box const& other_bounding_box)
|
||||
signed_size_type& index, int dir,
|
||||
Box const& this_bounding_box,
|
||||
Box const& other_bounding_box)
|
||||
{
|
||||
for(; it_begin != it_beyond
|
||||
&& it_begin + 1 != it_beyond
|
||||
&& detail::section::preceding<Dimension>(dir, *(it_begin + 1),
|
||||
other_bounding_box, m_robust_policy);
|
||||
this_bounding_box,
|
||||
other_bounding_box,
|
||||
m_robust_policy);
|
||||
++it_begin, index++)
|
||||
{}
|
||||
}
|
||||
|
||||
template <std::size_t Dimension, typename Iterator, typename Box>
|
||||
inline void move_end_iterator(Iterator it_begin, Iterator& it_beyond,
|
||||
int dir, Box const& other_bounding_box)
|
||||
int dir, Box const& this_bounding_box,
|
||||
Box const& other_bounding_box)
|
||||
{
|
||||
while (it_beyond != it_begin
|
||||
&& it_beyond - 1 != it_begin
|
||||
&& it_beyond - 2 != it_begin)
|
||||
{
|
||||
if (detail::section::exceeding<Dimension>(dir, *(it_beyond - 2),
|
||||
other_bounding_box, m_robust_policy))
|
||||
this_bounding_box, other_bounding_box, m_robust_policy))
|
||||
{
|
||||
--it_beyond;
|
||||
}
|
||||
@@ -191,23 +223,23 @@ class piece_turn_visitor
|
||||
// Set begin/end of monotonic ranges, in both x/y directions
|
||||
signed_size_type index1 = sec1_first_index;
|
||||
move_begin_iterator<0>(it1_first, it1_beyond, index1,
|
||||
section1.directions[0], section2.bounding_box);
|
||||
section1.directions[0], section1.bounding_box, section2.bounding_box);
|
||||
move_end_iterator<0>(it1_first, it1_beyond,
|
||||
section1.directions[0], section2.bounding_box);
|
||||
section1.directions[0], section1.bounding_box, section2.bounding_box);
|
||||
move_begin_iterator<1>(it1_first, it1_beyond, index1,
|
||||
section1.directions[1], section2.bounding_box);
|
||||
section1.directions[1], section1.bounding_box, section2.bounding_box);
|
||||
move_end_iterator<1>(it1_first, it1_beyond,
|
||||
section1.directions[1], section2.bounding_box);
|
||||
section1.directions[1], section1.bounding_box, section2.bounding_box);
|
||||
|
||||
signed_size_type index2 = sec2_first_index;
|
||||
move_begin_iterator<0>(it2_first, it2_beyond, index2,
|
||||
section2.directions[0], section1.bounding_box);
|
||||
section2.directions[0], section2.bounding_box, section1.bounding_box);
|
||||
move_end_iterator<0>(it2_first, it2_beyond,
|
||||
section2.directions[0], section1.bounding_box);
|
||||
section2.directions[0], section2.bounding_box, section1.bounding_box);
|
||||
move_begin_iterator<1>(it2_first, it2_beyond, index2,
|
||||
section2.directions[1], section1.bounding_box);
|
||||
section2.directions[1], section2.bounding_box, section1.bounding_box);
|
||||
move_end_iterator<1>(it2_first, it2_beyond,
|
||||
section2.directions[1], section1.bounding_box);
|
||||
section2.directions[1], section2.bounding_box, section1.bounding_box);
|
||||
|
||||
turn_type the_model;
|
||||
the_model.operations[0].piece_index = piece1.index;
|
||||
@@ -222,15 +254,19 @@ class piece_turn_visitor
|
||||
the_model.operations[1].piece_index = piece2.index;
|
||||
the_model.operations[1].seg_id = piece2.first_seg_id;
|
||||
the_model.operations[1].seg_id.segment_index = index2; // override
|
||||
geometry::recalculate(the_model.rob_pi, *prev1, m_robust_policy);
|
||||
geometry::recalculate(the_model.rob_pj, *it1, m_robust_policy);
|
||||
|
||||
iterator next1 = next_point(ring1, it1);
|
||||
unique_sub_range_from_piece<ring_type> unique_sub_range1(ring1, prev1, it1);
|
||||
|
||||
iterator it2 = it2_first;
|
||||
for (iterator prev2 = it2++;
|
||||
it2 != it2_beyond;
|
||||
prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
|
||||
{
|
||||
iterator next2 = next_point(ring2, it2);
|
||||
unique_sub_range_from_piece<ring_type> unique_sub_range2(ring2, prev2, it2);
|
||||
geometry::recalculate(the_model.rob_qi, *prev2, m_robust_policy);
|
||||
geometry::recalculate(the_model.rob_qj, *it2, m_robust_policy);
|
||||
|
||||
// TODO: internally get_turn_info calculates robust points.
|
||||
// But they are already calculated.
|
||||
@@ -239,20 +275,14 @@ class piece_turn_visitor
|
||||
// and iterating in sync with them...
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
buffer_assign_turn
|
||||
#else
|
||||
detail::overlay::assign_null_policy
|
||||
#endif
|
||||
> turn_policy;
|
||||
|
||||
turn_policy::apply(*prev1, *it1, *next1,
|
||||
*prev2, *it2, *next2,
|
||||
false, false, false, false,
|
||||
the_model,
|
||||
m_intersection_strategy,
|
||||
m_robust_policy,
|
||||
std::back_inserter(m_turns));
|
||||
turn_policy::apply(unique_sub_range1, unique_sub_range2,
|
||||
the_model,
|
||||
m_intersection_strategy,
|
||||
m_robust_policy,
|
||||
std::back_inserter(m_turns));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -272,10 +302,10 @@ public:
|
||||
{}
|
||||
|
||||
template <typename Section>
|
||||
inline void apply(Section const& section1, Section const& section2,
|
||||
inline bool apply(Section const& section1, Section const& section2,
|
||||
bool first = true)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(first);
|
||||
boost::ignore_unused(first);
|
||||
|
||||
typedef typename boost::range_value<Pieces const>::type piece_type;
|
||||
piece_type const& piece1 = m_pieces[section1.ring_id.source_index];
|
||||
@@ -285,12 +315,15 @@ public:
|
||||
|| is_adjacent(piece1, piece2)
|
||||
|| is_on_same_convex_ring(piece1, piece2)
|
||||
|| detail::disjoint::disjoint_box_box(section1.bounding_box,
|
||||
section2.bounding_box) )
|
||||
section2.bounding_box,
|
||||
m_intersection_strategy.get_disjoint_box_box_strategy()) )
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
calculate_turns(piece1, piece2, section1, section2);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2016.
|
||||
// Modifications copyright (c) 2016 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2016, 2018.
|
||||
// Modifications copyright (c) 2016-2018 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,
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
@@ -38,12 +39,14 @@ struct original_get_box
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointBoxBoxStrategy>
|
||||
struct original_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Original>
|
||||
static inline bool apply(Box const& box, Original const& original)
|
||||
{
|
||||
return ! detail::disjoint::disjoint_box_box(box, original.m_box);
|
||||
return ! detail::disjoint::disjoint_box_box(box, original.m_box,
|
||||
DisjointBoxBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -56,6 +59,7 @@ struct include_turn_policy
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointPointBoxStrategy>
|
||||
struct turn_in_original_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
@@ -68,7 +72,7 @@ struct turn_in_original_ovelaps_box
|
||||
}
|
||||
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(
|
||||
turn.robust_point, box);
|
||||
turn.robust_point, box, DisjointPointBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -212,27 +216,27 @@ public:
|
||||
{}
|
||||
|
||||
template <typename Turn, typename Original>
|
||||
inline void apply(Turn const& turn, Original const& original, bool first = true)
|
||||
inline bool apply(Turn const& turn, Original const& original, bool first = true)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(first);
|
||||
boost::ignore_unused(first);
|
||||
|
||||
if (turn.location != location_ok || turn.within_original)
|
||||
{
|
||||
// Skip all points already processed
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (geometry::disjoint(turn.robust_point, original.m_box))
|
||||
{
|
||||
// Skip all disjoint
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
int const code = point_in_original(turn.robust_point, original);
|
||||
|
||||
if (code == -1)
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
Turn& mutable_turn = m_mutable_turns[turn.turn_index];
|
||||
@@ -259,6 +263,8 @@ public:
|
||||
mutable_turn.within_original = true;
|
||||
mutable_turn.count_in_original = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private :
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2016.
|
||||
// Modifications copyright (c) 2016 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2016, 2018.
|
||||
// Modifications copyright (c) 2016-2018 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,
|
||||
@@ -19,6 +20,7 @@
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/config.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/dot_product.hpp>
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
@@ -33,9 +35,8 @@
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp>
|
||||
#endif
|
||||
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -55,6 +56,7 @@ struct piece_get_box
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointBoxBoxStrategy>
|
||||
struct piece_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Piece>
|
||||
@@ -70,7 +72,8 @@ struct piece_ovelaps_box
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope);
|
||||
return ! geometry::detail::disjoint::disjoint_box_box(box, piece.robust_envelope,
|
||||
DisjointBoxBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -83,12 +86,14 @@ struct turn_get_box
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointPointBoxStrategy>
|
||||
struct turn_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename Turn>
|
||||
static inline bool apply(Box const& box, Turn const& turn)
|
||||
{
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box);
|
||||
return ! geometry::detail::disjoint::disjoint_point_box(turn.robust_point, box,
|
||||
DisjointPointBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -100,10 +105,8 @@ enum analyse_result
|
||||
analyse_disjoint,
|
||||
analyse_within,
|
||||
analyse_on_original_boundary,
|
||||
analyse_on_offsetted
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
, analyse_near_offsetted
|
||||
#endif
|
||||
analyse_on_offsetted,
|
||||
analyse_near_offsetted
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
@@ -120,85 +123,115 @@ inline bool in_box(Point const& previous,
|
||||
return geometry::covered_by(point, box);
|
||||
}
|
||||
|
||||
template <typename Point, typename Turn>
|
||||
inline analyse_result check_segment(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
{
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
segment_type const r(previous, current);
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
if (side == -1 && from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
if (side == 1 && from_monotonic)
|
||||
{
|
||||
return analyse_disjoint;
|
||||
}
|
||||
return analyse_continue;
|
||||
// meta-programming-structure defining if to use side-of-intersection
|
||||
// (only for cartesian / only necessary with rescaling)
|
||||
template <typename Tag>
|
||||
struct use_side_of_intersection {};
|
||||
|
||||
#if defined(BOOST_GEOMETRY_USE_RESCALING)
|
||||
// With rescaling, let Cartesian use side-of-intersection
|
||||
template <>
|
||||
struct use_side_of_intersection<cartesian_tag> { static bool const value = true; };
|
||||
#else
|
||||
template <>
|
||||
struct use_side_of_intersection<cartesian_tag> { static bool const value = false; };
|
||||
#endif
|
||||
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
template <>
|
||||
struct use_side_of_intersection<spherical_tag> { static bool const value = false; };
|
||||
|
||||
coordinate_type const twice_area
|
||||
= side_strategy::template side_value
|
||||
<
|
||||
coordinate_type,
|
||||
coordinate_type
|
||||
>(previous, current, turn.robust_point);
|
||||
template <>
|
||||
struct use_side_of_intersection<geographic_tag> { static bool const value = false; };
|
||||
|
||||
if (twice_area == 0)
|
||||
|
||||
template <bool UseSideOfIntersection>
|
||||
struct check_segment {};
|
||||
|
||||
// Implementation using side-of-intersection
|
||||
template <>
|
||||
struct check_segment<true>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result apply(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
{
|
||||
// Collinear, only on segment if it is covered by its bbox
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
segment_type const r(previous, current);
|
||||
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||
turn.robust_point);
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
else if (twice_area < 0)
|
||||
{
|
||||
// It is in the triangle right-of the segment where the
|
||||
// segment is the hypothenusa. Check if it is close
|
||||
// (within rounding-area)
|
||||
if (twice_area * twice_area < geometry::comparable_distance(previous, current)
|
||||
&& in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_near_offsetted;
|
||||
}
|
||||
else if (from_monotonic)
|
||||
if (side == -1 && from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
if (side == 1 && from_monotonic)
|
||||
{
|
||||
return analyse_disjoint;
|
||||
}
|
||||
return analyse_continue;
|
||||
}
|
||||
else if (twice_area > 0 && from_monotonic)
|
||||
};
|
||||
|
||||
template <>
|
||||
struct check_segment<false>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result apply(Point const& previous,
|
||||
Point const& current, Turn const& turn,
|
||||
bool from_monotonic)
|
||||
{
|
||||
// Left of segment
|
||||
return analyse_disjoint;
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy;
|
||||
|
||||
int const side = side_strategy::apply(previous, current, turn.robust_point);
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
// Collinear, only on segment if it is covered by its bbox
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
else if (side == -1)
|
||||
{
|
||||
// It is in the triangle right-of the segment where the
|
||||
// segment is the hypothenusa. Check if it is close
|
||||
// (within rounding-area)
|
||||
if (in_box(previous, current, turn.robust_point))
|
||||
{
|
||||
return analyse_near_offsetted;
|
||||
}
|
||||
else if (from_monotonic)
|
||||
{
|
||||
return analyse_within;
|
||||
}
|
||||
}
|
||||
else if (from_monotonic)
|
||||
{
|
||||
// Left of segment
|
||||
return analyse_disjoint;
|
||||
}
|
||||
|
||||
// Not monotonic, on left or right side: continue analysing
|
||||
return analyse_continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Not monotonic, on left or right side: continue analysing
|
||||
return analyse_continue;
|
||||
#endif
|
||||
}
|
||||
template <bool UseSideOfIntersection>
|
||||
class analyse_turn_wrt_point_piece {};
|
||||
|
||||
|
||||
class analyse_turn_wrt_point_piece
|
||||
template <>
|
||||
class analyse_turn_wrt_point_piece<true>
|
||||
{
|
||||
public :
|
||||
template <typename Turn, typename Piece>
|
||||
@@ -208,17 +241,9 @@ public :
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
typedef geometry::model::referring_segment<point_type const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
#else
|
||||
typedef strategy::within::winding<point_type> strategy_type;
|
||||
|
||||
typename strategy_type::state_type state;
|
||||
strategy_type strategy;
|
||||
boost::ignore_unused(strategy);
|
||||
#endif
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! piece.sections.empty());
|
||||
|
||||
@@ -238,7 +263,6 @@ public :
|
||||
point_type const& previous = piece.robust_ring[i - 1];
|
||||
point_type const& current = piece.robust_ring[i];
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
|
||||
// First check if it is in range - if it is not, the
|
||||
// expensive side_of_intersection does not need to be
|
||||
@@ -269,8 +293,51 @@ public :
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
}
|
||||
#else
|
||||
analyse_result code = check_segment(previous, current, turn, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It is nowhere outside, and not on segment, so it is within
|
||||
return analyse_within;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
class analyse_turn_wrt_point_piece<false>
|
||||
{
|
||||
public :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result apply(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Piece::section_type section_type;
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
typedef strategy::within::winding<point_type> strategy_type;
|
||||
|
||||
typename strategy_type::state_type state;
|
||||
strategy_type strategy;
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(! piece.sections.empty());
|
||||
|
||||
coordinate_type const point_x = geometry::get<0>(turn.robust_point);
|
||||
|
||||
for (std::size_t s = 0; s < piece.sections.size(); s++)
|
||||
{
|
||||
section_type const& section = piece.sections[s];
|
||||
// If point within horizontal range of monotonic section:
|
||||
if (! section.duplicate
|
||||
&& section.begin_index < section.end_index
|
||||
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box) - 1
|
||||
&& point_x <= geometry::get<max_corner, 0>(section.bounding_box) + 1)
|
||||
{
|
||||
for (signed_size_type i = section.begin_index + 1; i <= section.end_index; i++)
|
||||
{
|
||||
point_type const& previous = piece.robust_ring[i - 1];
|
||||
point_type const& current = piece.robust_ring[i];
|
||||
|
||||
analyse_result code = check_segment<false>::apply(previous, current, turn, false);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
@@ -279,15 +346,10 @@ public :
|
||||
// Get the state (to determine it is within), we don't have
|
||||
// to cover the on-segment case (covered above)
|
||||
strategy.apply(turn.robust_point, previous, current, state);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// It is nowhere outside, and not on segment, so it is within
|
||||
return analyse_within;
|
||||
#else
|
||||
int const code = strategy.result(state);
|
||||
if (code == 1)
|
||||
{
|
||||
@@ -300,21 +362,24 @@ public :
|
||||
|
||||
// Should normally not occur - on-segment is covered
|
||||
return analyse_unknown;
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class analyse_turn_wrt_piece
|
||||
template <bool UseSideOfIntersection>
|
||||
struct check_helper_segment {};
|
||||
|
||||
template <>
|
||||
struct check_helper_segment<true>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result check_helper_segment(Point const& s1,
|
||||
static inline analyse_result apply(Point const& s1,
|
||||
Point const& s2, Turn const& turn,
|
||||
bool is_original,
|
||||
Point const& offsetted)
|
||||
{
|
||||
boost::ignore_unused(offsetted);
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
boost::ignore_unused(is_original);
|
||||
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||
@@ -339,11 +404,9 @@ class analyse_turn_wrt_piece
|
||||
|
||||
if (geometry::covered_by(turn.robust_point, box))
|
||||
{
|
||||
// Points on helper-segments are considered as within
|
||||
// Points on original boundary are processed differently
|
||||
return is_original
|
||||
? analyse_on_original_boundary
|
||||
: analyse_within;
|
||||
// Points on helper-segments (and not on its corners)
|
||||
// are considered as within
|
||||
return analyse_within;
|
||||
}
|
||||
|
||||
// It is collinear but not on the segment. Because these
|
||||
@@ -355,7 +418,20 @@ class analyse_turn_wrt_piece
|
||||
|
||||
// right of segment
|
||||
return analyse_continue;
|
||||
#else
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
struct check_helper_segment<false>
|
||||
{
|
||||
template <typename Point, typename Turn>
|
||||
static inline analyse_result apply(Point const& s1,
|
||||
Point const& s2, Turn const& turn,
|
||||
bool is_original,
|
||||
Point const& offsetted)
|
||||
{
|
||||
boost::ignore_unused(offsetted);
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
@@ -404,9 +480,12 @@ class analyse_turn_wrt_piece
|
||||
|
||||
// right of segment
|
||||
return analyse_continue;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <bool UseSideOfIntersection>
|
||||
class analyse_turn_wrt_piece
|
||||
{
|
||||
template <typename Turn, typename Piece>
|
||||
static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
@@ -423,6 +502,13 @@ class analyse_turn_wrt_piece
|
||||
{
|
||||
points[i] = piece.robust_ring[piece.offsetted_count + i];
|
||||
}
|
||||
|
||||
// 3--offsetted outline--0
|
||||
// | |
|
||||
// left | | right
|
||||
// | |
|
||||
// 2===>==original===>===1
|
||||
|
||||
}
|
||||
else if (helper_count == 3)
|
||||
{
|
||||
@@ -446,14 +532,20 @@ class analyse_turn_wrt_piece
|
||||
{
|
||||
return analyse_on_offsetted;
|
||||
}
|
||||
if (comparator(point, points[1]) || comparator(point, points[2]))
|
||||
if (comparator(point, points[1]))
|
||||
{
|
||||
return analyse_on_original_boundary;
|
||||
// On original, right corner
|
||||
return piece.is_flat_end ? analyse_continue : analyse_on_original_boundary;
|
||||
}
|
||||
if (comparator(point, points[2]))
|
||||
{
|
||||
// On original, left corner
|
||||
return piece.is_flat_start ? analyse_continue : analyse_on_original_boundary;
|
||||
}
|
||||
|
||||
// Right side of the piece
|
||||
analyse_result result
|
||||
= check_helper_segment(points[0], points[1], turn,
|
||||
= check_helper_segment<UseSideOfIntersection>::apply(points[0], points[1], turn,
|
||||
false, points[0]);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
@@ -461,7 +553,7 @@ class analyse_turn_wrt_piece
|
||||
}
|
||||
|
||||
// Left side of the piece
|
||||
result = check_helper_segment(points[2], points[3], turn,
|
||||
result = check_helper_segment<UseSideOfIntersection>::apply(points[2], points[3], turn,
|
||||
false, points[3]);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
@@ -471,7 +563,7 @@ class analyse_turn_wrt_piece
|
||||
if (! comparator(points[1], points[2]))
|
||||
{
|
||||
// Side of the piece at side of original geometry
|
||||
result = check_helper_segment(points[1], points[2], turn,
|
||||
result = check_helper_segment<UseSideOfIntersection>::apply(points[1], points[2], turn,
|
||||
true, point);
|
||||
if (result != analyse_continue)
|
||||
{
|
||||
@@ -518,7 +610,7 @@ class analyse_turn_wrt_piece
|
||||
// w.r.t. specified direction, and prev points to a point smaller
|
||||
// We now know if it is inside/outside
|
||||
it_type prev = it - 1;
|
||||
return check_segment(*prev, *it, turn, true);
|
||||
return check_segment<UseSideOfIntersection>::apply(*prev, *it, turn, true);
|
||||
}
|
||||
return analyse_continue;
|
||||
}
|
||||
@@ -575,7 +667,7 @@ public :
|
||||
// (on which any side or side-value would return 0)
|
||||
if (! comparator(previous, current))
|
||||
{
|
||||
code = check_segment(previous, current, turn, false);
|
||||
code = check_segment<UseSideOfIntersection>::apply(previous, current, turn, false);
|
||||
if (code != analyse_continue)
|
||||
{
|
||||
return code;
|
||||
@@ -588,45 +680,17 @@ public :
|
||||
|
||||
};
|
||||
|
||||
// Helper Structure, of which the apply method returns a side value in {-1, 0, 1}
|
||||
template <bool UseSideOfIntersection>
|
||||
struct turn_in_piece {};
|
||||
|
||||
template <typename Turns, typename Pieces>
|
||||
class turn_in_piece_visitor
|
||||
template <>
|
||||
struct turn_in_piece<true>
|
||||
{
|
||||
Turns& m_turns; // because partition is currently operating on const input only
|
||||
Pieces const& m_pieces; // to check for piece-type
|
||||
|
||||
template <typename Operation, typename Piece>
|
||||
inline bool skip(Operation const& op, Piece const& piece) const
|
||||
{
|
||||
if (op.piece_index == piece.index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Piece const& pc = m_pieces[op.piece_index];
|
||||
if (pc.left_index == piece.index || pc.right_index == piece.index)
|
||||
{
|
||||
if (pc.type == strategy::buffer::buffered_flat_end)
|
||||
{
|
||||
// If it is a flat end, don't compare against its neighbor:
|
||||
// it will always be located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
if (pc.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// If it is concave, the same applies: the IP will be
|
||||
// located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// NOTE: this function returns a side value in {-1, 0, 1}
|
||||
private :
|
||||
template <typename Turn, typename Piece>
|
||||
static inline int turn_in_convex_piece(Turn const& turn,
|
||||
Piece const& piece)
|
||||
static inline int in_convex_piece(Turn const& turn, Piece const& piece)
|
||||
{
|
||||
typedef typename Turn::robust_point_type point_type;
|
||||
typedef typename Piece::piece_robust_ring_type ring_type;
|
||||
@@ -675,43 +739,119 @@ class turn_in_piece_visitor
|
||||
}
|
||||
return 1; // inside
|
||||
}
|
||||
#endif
|
||||
|
||||
public :
|
||||
|
||||
template <typename Turn, typename Piece, typename Strategy>
|
||||
static inline int apply(Turn const& turn, Piece const& piece,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (piece.is_convex)
|
||||
{
|
||||
return in_convex_piece(turn, piece);
|
||||
}
|
||||
else
|
||||
{
|
||||
// side-of-intersection only supported for convex pieces
|
||||
// Call point_in_geometry, a performance-bottleneck
|
||||
// TODO: might be replaced by extending analysing piece
|
||||
return detail::within::point_in_geometry(turn.robust_point,
|
||||
piece.robust_ring, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct turn_in_piece<false>
|
||||
{
|
||||
public :
|
||||
|
||||
template <typename Turn, typename Piece, typename Strategy>
|
||||
static inline int apply(Turn const& turn, Piece const& piece,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return detail::within::point_in_geometry(turn.robust_point,
|
||||
piece.robust_ring, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename CsTag,
|
||||
typename Turns,
|
||||
typename Pieces,
|
||||
typename PointInGeometryStrategy
|
||||
>
|
||||
class turn_in_piece_visitor
|
||||
{
|
||||
Turns& m_turns; // because partition is currently operating on const input only
|
||||
Pieces const& m_pieces; // to check for piece-type
|
||||
PointInGeometryStrategy const& m_point_in_geometry_strategy;
|
||||
|
||||
template <typename Operation, typename Piece>
|
||||
inline bool skip(Operation const& op, Piece const& piece) const
|
||||
{
|
||||
if (op.piece_index == piece.index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Piece const& pc = m_pieces[op.piece_index];
|
||||
if (pc.left_index == piece.index || pc.right_index == piece.index)
|
||||
{
|
||||
if (pc.type == strategy::buffer::buffered_flat_end)
|
||||
{
|
||||
// If it is a flat end, don't compare against its neighbor:
|
||||
// it will always be located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
if (pc.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// If it is concave, the same applies: the IP will be
|
||||
// located on one of the helper segments
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces)
|
||||
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces,
|
||||
PointInGeometryStrategy const& strategy)
|
||||
: m_turns(turns)
|
||||
, m_pieces(pieces)
|
||||
, m_point_in_geometry_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Turn, typename Piece>
|
||||
inline void apply(Turn const& turn, Piece const& piece, bool first = true)
|
||||
inline bool apply(Turn const& turn, Piece const& piece, bool first = true)
|
||||
{
|
||||
boost::ignore_unused_variable_warning(first);
|
||||
boost::ignore_unused(first);
|
||||
|
||||
if (turn.count_within > 0)
|
||||
{
|
||||
// Already inside - no need to check again
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (piece.type == strategy::buffer::buffered_flat_end
|
||||
|| piece.type == strategy::buffer::buffered_concave)
|
||||
{
|
||||
// Turns cannot be located within flat-end or concave pieces
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! geometry::covered_by(turn.robust_point, piece.robust_envelope))
|
||||
{
|
||||
// Easy check: if the turn is not in the envelope, we can safely return
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (skip(turn.operations[0], piece) || skip(turn.operations[1], piece))
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: mutable_piece to make some on-demand preparations in analyse
|
||||
@@ -733,63 +873,51 @@ public:
|
||||
if (cd < piece.robust_min_comparable_radius)
|
||||
{
|
||||
mutable_turn.count_within++;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (cd > piece.robust_max_comparable_radius)
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static const bool use_soi = use_side_of_intersection<CsTag>::value;
|
||||
boost::ignore_unused(use_soi);
|
||||
|
||||
analyse_result analyse_code =
|
||||
piece.type == geometry::strategy::buffer::buffered_point
|
||||
? analyse_turn_wrt_point_piece::apply(turn, piece)
|
||||
: analyse_turn_wrt_piece::apply(turn, piece);
|
||||
? analyse_turn_wrt_point_piece<use_soi>::apply(turn, piece)
|
||||
: analyse_turn_wrt_piece<use_soi>::apply(turn, piece);
|
||||
|
||||
switch(analyse_code)
|
||||
{
|
||||
case analyse_disjoint :
|
||||
return;
|
||||
return true;
|
||||
case analyse_on_offsetted :
|
||||
mutable_turn.count_on_offsetted++; // value is not used anymore
|
||||
return;
|
||||
return true;
|
||||
case analyse_on_original_boundary :
|
||||
mutable_turn.count_on_original_boundary++;
|
||||
return;
|
||||
return true;
|
||||
case analyse_within :
|
||||
mutable_turn.count_within++;
|
||||
return;
|
||||
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
return true;
|
||||
case analyse_near_offsetted :
|
||||
mutable_turn.count_within_near_offsetted++;
|
||||
return;
|
||||
#endif
|
||||
return true;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||
// We don't know (yet)
|
||||
int geometry_code = 0;
|
||||
if (piece.is_convex)
|
||||
{
|
||||
geometry_code = turn_in_convex_piece(turn, piece);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// TODO: this point_in_geometry is a performance-bottleneck here and
|
||||
// will be replaced completely by extending analyse_piece functionality
|
||||
geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
|
||||
}
|
||||
#else
|
||||
int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
|
||||
#endif
|
||||
int const geometry_code = turn_in_piece<use_soi>::apply(turn, piece,
|
||||
m_point_in_geometry_strategy);
|
||||
|
||||
if (geometry_code == 1)
|
||||
{
|
||||
mutable_turn.count_within++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2017, 2019.
|
||||
// Modifications copyright (c) 2013-2019 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.
|
||||
|
||||
// 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_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/within/implementation.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace covered_by {
|
||||
|
||||
struct use_point_in_geometry
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
||||
{
|
||||
return detail::within::covered_by_point_geometry(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
struct use_relate
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
|
||||
{
|
||||
typedef typename detail::de9im::static_mask_covered_by_type
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type covered_by_mask;
|
||||
return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::covered_by
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Point, typename Box>
|
||||
struct covered_by<Point, Box, point_tag, box_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
|
||||
{
|
||||
::boost::ignore_unused(strategy);
|
||||
return strategy.apply(point, box);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Box1, typename Box2>
|
||||
struct covered_by<Box1, Box2, box_tag, box_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
|
||||
{
|
||||
assert_dimension_equal<Box1, Box2>();
|
||||
::boost::ignore_unused(strategy);
|
||||
return strategy.apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// P/P
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
struct covered_by<Point1, Point2, point_tag, point_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiPoint>
|
||||
struct covered_by<Point, MultiPoint, point_tag, multi_point_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Point>
|
||||
struct covered_by<MultiPoint, Point, multi_point_tag, point_tag>
|
||||
: public detail::within::multi_point_point
|
||||
{};
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2>
|
||||
struct covered_by<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag>
|
||||
: public detail::within::multi_point_multi_point
|
||||
{};
|
||||
|
||||
// P/L
|
||||
|
||||
template <typename Point, typename Segment>
|
||||
struct covered_by<Point, Segment, point_tag, segment_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename Linestring>
|
||||
struct covered_by<Point, Linestring, point_tag, linestring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiLinestring>
|
||||
struct covered_by<Point, MultiLinestring, point_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Segment>
|
||||
struct covered_by<MultiPoint, Segment, multi_point_tag, segment_tag>
|
||||
: public detail::within::multi_point_single_geometry<false>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Linestring>
|
||||
struct covered_by<MultiPoint, Linestring, multi_point_tag, linestring_tag>
|
||||
: public detail::within::multi_point_single_geometry<false>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename MultiLinestring>
|
||||
struct covered_by<MultiPoint, MultiLinestring, multi_point_tag, multi_linestring_tag>
|
||||
: public detail::within::multi_point_multi_geometry<false>
|
||||
{};
|
||||
|
||||
// P/A
|
||||
|
||||
template <typename Point, typename Ring>
|
||||
struct covered_by<Point, Ring, point_tag, ring_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename Polygon>
|
||||
struct covered_by<Point, Polygon, point_tag, polygon_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename Point, typename MultiPolygon>
|
||||
struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_point_in_geometry
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Ring>
|
||||
struct covered_by<MultiPoint, Ring, multi_point_tag, ring_tag>
|
||||
: public detail::within::multi_point_single_geometry<false>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Polygon>
|
||||
struct covered_by<MultiPoint, Polygon, multi_point_tag, polygon_tag>
|
||||
: public detail::within::multi_point_single_geometry<false>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename MultiPolygon>
|
||||
struct covered_by<MultiPoint, MultiPolygon, multi_point_tag, multi_polygon_tag>
|
||||
: public detail::within::multi_point_multi_geometry<false>
|
||||
{};
|
||||
|
||||
// L/L
|
||||
|
||||
template <typename Linestring1, typename Linestring2>
|
||||
struct covered_by<Linestring1, Linestring2, linestring_tag, linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename MultiLinestring>
|
||||
struct covered_by<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Linestring>
|
||||
struct covered_by<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring1, typename MultiLinestring2>
|
||||
struct covered_by<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// L/A
|
||||
|
||||
template <typename Linestring, typename Ring>
|
||||
struct covered_by<Linestring, Ring, linestring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Ring>
|
||||
struct covered_by<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename Polygon>
|
||||
struct covered_by<Linestring, Polygon, linestring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename Polygon>
|
||||
struct covered_by<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Linestring, typename MultiPolygon>
|
||||
struct covered_by<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring, typename MultiPolygon>
|
||||
struct covered_by<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
// A/A
|
||||
|
||||
template <typename Ring1, typename Ring2>
|
||||
struct covered_by<Ring1, Ring2, ring_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Ring, typename Polygon>
|
||||
struct covered_by<Ring, Polygon, ring_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename Ring>
|
||||
struct covered_by<Polygon, Ring, polygon_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon1, typename Polygon2>
|
||||
struct covered_by<Polygon1, Polygon2, polygon_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Ring, typename MultiPolygon>
|
||||
struct covered_by<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Ring>
|
||||
struct covered_by<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename Polygon, typename MultiPolygon>
|
||||
struct covered_by<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Polygon>
|
||||
struct covered_by<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon1, typename MultiPolygon2>
|
||||
struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
|
||||
: public detail::covered_by::use_relate
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP
|
||||
@@ -0,0 +1,255 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2017, 2018.
|
||||
// Modifications copyright (c) 2013-2018 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.
|
||||
|
||||
// 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_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/within/interface.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag2 = typename tag<Geometry2>::type
|
||||
>
|
||||
struct covered_by
|
||||
: not_implemented<Tag1, Tag2>
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy {
|
||||
|
||||
struct covered_by
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::within::check<Geometry1, Geometry2, Strategy>();
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
assert_dimension_equal<Geometry1, Geometry2>();
|
||||
|
||||
return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1,
|
||||
geometry2,
|
||||
strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::covered_by::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return covered_by::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct covered_by
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_strategy::covered_by
|
||||
::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2, Strategy const& strategy)
|
||||
: m_geometry2(geometry2), m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry1>
|
||||
bool operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
return covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, m_geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1, Strategy const& strategy)
|
||||
: m_geometry1(geometry1), m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry2>
|
||||
bool operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
return covered_by<Geometry1, Geometry2>
|
||||
::apply(m_geometry1, geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool
|
||||
apply(Geometry1 const& geometry1,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
template <
|
||||
BOOST_VARIANT_ENUM_PARAMS(typename T1),
|
||||
BOOST_VARIANT_ENUM_PARAMS(typename T2)
|
||||
>
|
||||
struct covered_by<
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
|
||||
>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy): m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
bool operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
return covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool
|
||||
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check12{is inside or on border}
|
||||
\ingroup covered_by
|
||||
\details \details_check12{covered_by, is inside or on border}.
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
|
||||
\param geometry2 \param_geometry which might cover the first geometry
|
||||
\return true if geometry1 is inside of or on the border of geometry2,
|
||||
else false
|
||||
\note The default strategy is used for covered_by detection
|
||||
|
||||
\qbk{[include reference/algorithms/covered_by.qbk]}
|
||||
|
||||
*/
|
||||
template<typename Geometry1, typename Geometry2>
|
||||
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
return resolve_variant::covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_check12{is inside or on border} \brief_strategy
|
||||
\ingroup covered_by
|
||||
\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
|
||||
\param geometry2 \param_geometry which might cover the first geometry
|
||||
\param strategy strategy to be used
|
||||
\return true if geometry1 is inside of or on the border of geometry2,
|
||||
else false
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/covered_by.qbk]}
|
||||
|
||||
*/
|
||||
template<typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::covered_by<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2017.
|
||||
// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -17,14 +18,22 @@
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
|
||||
// TODO: remove
|
||||
template <std::size_t Index, typename Point1, typename Point2>
|
||||
inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
@@ -37,6 +46,193 @@ inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
|
||||
}
|
||||
|
||||
|
||||
template <typename Point, typename CSTag = typename cs_tag<Point>::type>
|
||||
struct direction_code_impl
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_CS, (CSTag));
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct direction_code_impl<Point, cartesian_tag>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
|
||||
Point2 const& p)
|
||||
{
|
||||
typedef typename geometry::select_coordinate_type
|
||||
<
|
||||
Point1, Point2
|
||||
>::type calc_t;
|
||||
|
||||
if ( (math::equals(geometry::get<0>(segment_b), geometry::get<0>(segment_a))
|
||||
&& math::equals(geometry::get<1>(segment_b), geometry::get<1>(segment_a)))
|
||||
|| (math::equals(geometry::get<0>(segment_b), geometry::get<0>(p))
|
||||
&& math::equals(geometry::get<1>(segment_b), geometry::get<1>(p))) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
calc_t x1 = geometry::get<0>(segment_b) - geometry::get<0>(segment_a);
|
||||
calc_t y1 = geometry::get<1>(segment_b) - geometry::get<1>(segment_a);
|
||||
calc_t x2 = geometry::get<0>(segment_b) - geometry::get<0>(p);
|
||||
calc_t y2 = geometry::get<1>(segment_b) - geometry::get<1>(p);
|
||||
|
||||
calc_t ax = (std::min)(math::abs(x1), math::abs(x2));
|
||||
calc_t ay = (std::min)(math::abs(y1), math::abs(y2));
|
||||
|
||||
int s1 = 0, s2 = 0;
|
||||
if (ax >= ay)
|
||||
{
|
||||
s1 = x1 > 0 ? 1 : -1;
|
||||
s2 = x2 > 0 ? 1 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = y1 > 0 ? 1 : -1;
|
||||
s2 = y2 > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
return s1 == s2 ? -1 : 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct direction_code_impl<Point, spherical_equatorial_tag>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
|
||||
Point2 const& p)
|
||||
{
|
||||
typedef typename coordinate_type<Point1>::type coord1_t;
|
||||
typedef typename coordinate_type<Point2>::type coord2_t;
|
||||
typedef typename coordinate_system<Point1>::type::units units_t;
|
||||
typedef typename coordinate_system<Point2>::type::units units2_t;
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<units_t, units2_t>::value),
|
||||
NOT_IMPLEMENTED_FOR_DIFFERENT_UNITS,
|
||||
(units_t, units2_t));
|
||||
|
||||
typedef typename geometry::select_coordinate_type <Point1, Point2>::type calc_t;
|
||||
typedef math::detail::constants_on_spheroid<coord1_t, units_t> constants1;
|
||||
typedef math::detail::constants_on_spheroid<coord2_t, units_t> constants2;
|
||||
static coord1_t const pi_half1 = constants1::max_latitude();
|
||||
static coord2_t const pi_half2 = constants2::max_latitude();
|
||||
static calc_t const c0 = 0;
|
||||
|
||||
coord1_t const a0 = geometry::get<0>(segment_a);
|
||||
coord1_t const a1 = geometry::get<1>(segment_a);
|
||||
coord1_t const b0 = geometry::get<0>(segment_b);
|
||||
coord1_t const b1 = geometry::get<1>(segment_b);
|
||||
coord2_t const p0 = geometry::get<0>(p);
|
||||
coord2_t const p1 = geometry::get<1>(p);
|
||||
|
||||
if ( (math::equals(b0, a0) && math::equals(b1, a1))
|
||||
|| (math::equals(b0, p0) && math::equals(b1, p1)) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool const is_a_pole = math::equals(pi_half1, math::abs(a1));
|
||||
bool const is_b_pole = math::equals(pi_half1, math::abs(b1));
|
||||
bool const is_p_pole = math::equals(pi_half2, math::abs(p1));
|
||||
|
||||
if ( is_b_pole && ((is_a_pole && math::sign(b1) == math::sign(a1))
|
||||
|| (is_p_pole && math::sign(b1) == math::sign(p1))) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE: as opposed to the implementation for cartesian CS
|
||||
// here point b is the origin
|
||||
|
||||
calc_t const dlon1 = math::longitude_distance_signed<units_t, calc_t>(b0, a0);
|
||||
calc_t const dlon2 = math::longitude_distance_signed<units_t, calc_t>(b0, p0);
|
||||
|
||||
bool is_antilon1 = false, is_antilon2 = false;
|
||||
calc_t const dlat1 = latitude_distance_signed<units_t, calc_t>(b1, a1, dlon1, is_antilon1);
|
||||
calc_t const dlat2 = latitude_distance_signed<units_t, calc_t>(b1, p1, dlon2, is_antilon2);
|
||||
|
||||
calc_t mx = is_a_pole || is_b_pole || is_p_pole ?
|
||||
c0 :
|
||||
(std::min)(is_antilon1 ? c0 : math::abs(dlon1),
|
||||
is_antilon2 ? c0 : math::abs(dlon2));
|
||||
calc_t my = (std::min)(math::abs(dlat1),
|
||||
math::abs(dlat2));
|
||||
|
||||
int s1 = 0, s2 = 0;
|
||||
if (mx >= my)
|
||||
{
|
||||
s1 = dlon1 > 0 ? 1 : -1;
|
||||
s2 = dlon2 > 0 ? 1 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = dlat1 > 0 ? 1 : -1;
|
||||
s2 = dlat2 > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
return s1 == s2 ? -1 : 1;
|
||||
}
|
||||
|
||||
template <typename Units, typename T>
|
||||
static inline T latitude_distance_signed(T const& lat1, T const& lat2, T const& lon_ds, bool & is_antilon)
|
||||
{
|
||||
typedef math::detail::constants_on_spheroid<T, Units> constants;
|
||||
static T const pi = constants::half_period();
|
||||
static T const c0 = 0;
|
||||
|
||||
T res = lat2 - lat1;
|
||||
|
||||
is_antilon = math::equals(math::abs(lon_ds), pi);
|
||||
if (is_antilon)
|
||||
{
|
||||
res = lat2 + lat1;
|
||||
if (res >= c0)
|
||||
res = pi - res;
|
||||
else
|
||||
res = -pi - res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct direction_code_impl<Point, spherical_polar_tag>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
static inline int apply(Point1 segment_a, Point1 segment_b,
|
||||
Point2 p)
|
||||
{
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
typename coordinate_type<Point1>::type,
|
||||
typename coordinate_system<Point1>::type::units
|
||||
> constants1;
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
typename coordinate_type<Point2>::type,
|
||||
typename coordinate_system<Point2>::type::units
|
||||
> constants2;
|
||||
|
||||
geometry::set<1>(segment_a,
|
||||
constants1::max_latitude() - geometry::get<1>(segment_a));
|
||||
geometry::set<1>(segment_b,
|
||||
constants1::max_latitude() - geometry::get<1>(segment_b));
|
||||
geometry::set<1>(p,
|
||||
constants2::max_latitude() - geometry::get<1>(p));
|
||||
|
||||
return direction_code_impl
|
||||
<
|
||||
Point, spherical_equatorial_tag
|
||||
>::apply(segment_a, segment_b, p);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct direction_code_impl<Point, geographic_tag>
|
||||
: direction_code_impl<Point, spherical_equatorial_tag>
|
||||
{};
|
||||
|
||||
// Gives sense of direction for point p, collinear w.r.t. segment (a,b)
|
||||
// Returns -1 if p goes backward w.r.t (a,b), so goes from b in direction of a
|
||||
// Returns 1 if p goes forward, so extends (a,b)
|
||||
@@ -44,28 +240,9 @@ inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
|
||||
// Note that it does not do any collinearity test, that should be done before
|
||||
template <typename Point1, typename Point2>
|
||||
inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
|
||||
const Point2& p)
|
||||
Point2 const& p)
|
||||
{
|
||||
// Suppose segment = (4 3,4 4) and p =(4 2)
|
||||
// Then sign_a1 = 1 and sign_p1 = 1 -> goes backward -> return -1
|
||||
|
||||
int const sign_a0 = sign_of_difference<0>(segment_b, segment_a);
|
||||
int const sign_a1 = sign_of_difference<1>(segment_b, segment_a);
|
||||
|
||||
if (sign_a0 == 0 && sign_a1 == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int const sign_p0 = sign_of_difference<0>(segment_b, p);
|
||||
int const sign_p1 = sign_of_difference<1>(segment_b, p);
|
||||
|
||||
if (sign_p0 == 0 && sign_p1 == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sign_a0 == sign_p0 && sign_a1 == sign_p1 ? -1 : 1;
|
||||
return direction_code_impl<Point1>::apply(segment_a, segment_b, p);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +250,6 @@ inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
|
||||
#endif //DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2019.
|
||||
// Modifications copyright (c) 2013-2019, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
@@ -28,6 +28,9 @@
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -38,30 +41,15 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct check_each_ring_for_within_call_covered_by
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool point_on_border_covered_by(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
*/
|
||||
template <typename Point, typename Strategy>
|
||||
static inline bool apply(Point const& p, Geometry const& g, Strategy const& strategy)
|
||||
{
|
||||
return geometry::covered_by(p, g, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct check_each_ring_for_within_call_covered_by<Geometry, box_tag>
|
||||
{
|
||||
template <typename Point, typename Strategy>
|
||||
static inline bool apply(Point const& p, Geometry const& g, Strategy const& )
|
||||
{
|
||||
return geometry::covered_by(p, g);
|
||||
}
|
||||
};
|
||||
|
||||
typename geometry::point_type<Geometry1>::type pt;
|
||||
return geometry::point_on_border(pt, geometry1)
|
||||
&& geometry::covered_by(pt, geometry2, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
\tparam Strategy point_in_geometry strategy
|
||||
@@ -83,13 +71,8 @@ struct check_each_ring_for_within
|
||||
template <typename Range>
|
||||
inline void apply(Range const& range)
|
||||
{
|
||||
typename point_type<Range>::type pt;
|
||||
not_disjoint = not_disjoint
|
||||
|| ( geometry::point_on_border(pt, range)
|
||||
&& check_each_ring_for_within_call_covered_by
|
||||
<
|
||||
Geometry
|
||||
>::apply(pt, m_geometry, m_strategy) );
|
||||
|| point_on_border_covered_by(range, m_geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -113,7 +96,7 @@ inline bool rings_containing(FirstGeometry const& geometry1,
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct general_areal
|
||||
struct areal_areal
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy relate (segments intersection) strategy
|
||||
@@ -147,6 +130,56 @@ struct general_areal
|
||||
};
|
||||
|
||||
|
||||
template <typename Areal, typename Box>
|
||||
struct areal_box
|
||||
{
|
||||
/*!
|
||||
\tparam Strategy relate (segments intersection) strategy
|
||||
*/
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Areal const& areal,
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if ( ! for_each_segment(geometry::segments_begin(areal),
|
||||
geometry::segments_end(areal),
|
||||
box,
|
||||
strategy.get_disjoint_segment_box_strategy()) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is no intersection of any segment and box,
|
||||
// the box might be located inside areal geometry
|
||||
|
||||
if ( point_on_border_covered_by(box, areal,
|
||||
strategy.template get_point_in_geometry_strategy<Box, Areal>()) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename SegIter, typename Strategy>
|
||||
static inline bool for_each_segment(SegIter first,
|
||||
SegIter last,
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
for ( ; first != last ; ++first)
|
||||
{
|
||||
if (! disjoint_segment_box::apply(*first, box, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
@@ -160,13 +193,13 @@ namespace dispatch
|
||||
|
||||
template <typename Areal1, typename Areal2>
|
||||
struct disjoint<Areal1, Areal2, 2, areal_tag, areal_tag, false>
|
||||
: detail::disjoint::general_areal<Areal1, Areal2>
|
||||
: detail::disjoint::areal_areal<Areal1, Areal2>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Box>
|
||||
struct disjoint<Areal, Box, 2, areal_tag, box_tag, false>
|
||||
: detail::disjoint::general_areal<Areal, Box>
|
||||
: detail::disjoint::areal_box<Areal, Box>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2018.
|
||||
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
@@ -23,130 +23,30 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
|
||||
#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Box1, typename Box2,
|
||||
std::size_t Dimension = 0,
|
||||
std::size_t DimensionCount = dimension<Box1>::value,
|
||||
typename CSTag = typename tag_cast
|
||||
<
|
||||
typename cs_tag<Box1>::type,
|
||||
spherical_tag
|
||||
>::type
|
||||
>
|
||||
struct box_box
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
|
||||
{
|
||||
return apply(box1, box2);
|
||||
}
|
||||
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2)
|
||||
{
|
||||
if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return box_box
|
||||
<
|
||||
Box1, Box2,
|
||||
Dimension + 1, DimensionCount
|
||||
>::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Box1, typename Box2, std::size_t DimensionCount, typename CSTag>
|
||||
struct box_box<Box1, Box2, DimensionCount, DimensionCount, CSTag>
|
||||
{
|
||||
static inline bool apply(Box1 const& , Box2 const& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Box1, typename Box2, std::size_t DimensionCount>
|
||||
struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
|
||||
{
|
||||
return apply(box1, box2);
|
||||
}
|
||||
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2)
|
||||
{
|
||||
typedef typename geometry::select_most_precise
|
||||
<
|
||||
typename coordinate_type<Box1>::type,
|
||||
typename coordinate_type<Box2>::type
|
||||
>::type calc_t;
|
||||
typedef typename coordinate_system<Box1>::type::units units_t;
|
||||
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
|
||||
|
||||
calc_t const b1_min = get<min_corner, 0>(box1);
|
||||
calc_t const b1_max = get<max_corner, 0>(box1);
|
||||
calc_t const b2_min = get<min_corner, 0>(box2);
|
||||
calc_t const b2_max = get<max_corner, 0>(box2);
|
||||
|
||||
// min <= max <=> diff >= 0
|
||||
calc_t const diff1 = b1_max - b1_min;
|
||||
calc_t const diff2 = b2_max - b2_min;
|
||||
|
||||
// check the intersection if neither box cover the whole globe
|
||||
if (diff1 < constants::period() && diff2 < constants::period())
|
||||
{
|
||||
// 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
|
||||
|
||||
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
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return box_box
|
||||
<
|
||||
Box1, Box2,
|
||||
1, DimensionCount
|
||||
>::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Internal utility function to detect if boxes are disjoint
|
||||
\note Is used from other algorithms, declared separately
|
||||
to avoid circular references
|
||||
*/
|
||||
template <typename Box1, typename Box2>
|
||||
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2)
|
||||
template <typename Box1, typename Box2, typename Strategy>
|
||||
inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2, Strategy const&)
|
||||
{
|
||||
return box_box<Box1, Box2>::apply(box1, box2);
|
||||
return Strategy::apply(box1, box2);
|
||||
}
|
||||
|
||||
|
||||
@@ -161,8 +61,13 @@ namespace dispatch
|
||||
|
||||
template <typename Box1, typename Box2, std::size_t DimensionCount>
|
||||
struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, false>
|
||||
: detail::disjoint::box_box<Box1, Box2, 0, DimensionCount>
|
||||
{};
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const&)
|
||||
{
|
||||
return Strategy::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2014.
|
||||
// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2018.
|
||||
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
@@ -41,8 +41,9 @@
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
|
||||
|
||||
@@ -93,18 +93,6 @@ struct assign_disjoint_policy
|
||||
static bool const include_no_turn = true;
|
||||
static bool const include_degenerate = true;
|
||||
static bool const include_opposite = true;
|
||||
|
||||
// We don't assign extra info:
|
||||
template
|
||||
<
|
||||
typename Info,
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionInfo
|
||||
>
|
||||
static inline void apply(Info& , Point1 const& , Point2 const&,
|
||||
IntersectionInfo const&)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -30,13 +31,16 @@
|
||||
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/partition.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/less.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -53,10 +57,10 @@ class multipoint_multipoint
|
||||
private:
|
||||
template <typename Iterator>
|
||||
class unary_disjoint_predicate
|
||||
: detail::relate::less
|
||||
: geometry::less<>
|
||||
{
|
||||
private:
|
||||
typedef detail::relate::less base_type;
|
||||
typedef geometry::less<> base_type;
|
||||
|
||||
public:
|
||||
unary_disjoint_predicate(Iterator first, Iterator last)
|
||||
@@ -87,7 +91,7 @@ public:
|
||||
std::vector<point1_type> points1(boost::begin(multipoint1),
|
||||
boost::end(multipoint1));
|
||||
|
||||
std::sort(points1.begin(), points1.end(), detail::relate::less());
|
||||
std::sort(points1.begin(), points1.end(), geometry::less<>());
|
||||
|
||||
typedef unary_disjoint_predicate
|
||||
<
|
||||
@@ -117,49 +121,49 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: After adding non-cartesian Segment envelope to the library
|
||||
// this policy should be modified to take envelope strategy.
|
||||
template <typename EnvelopeStrategy>
|
||||
struct expand_box_segment
|
||||
{
|
||||
explicit expand_box_segment(EnvelopeStrategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Segment>
|
||||
static inline void apply(Box& total, Segment const& segment)
|
||||
inline void apply(Box& total, Segment const& segment) const
|
||||
{
|
||||
geometry::expand(total, geometry::return_envelope<Box>(segment));
|
||||
geometry::expand(total,
|
||||
geometry::return_envelope<Box>(segment, m_strategy));
|
||||
}
|
||||
|
||||
EnvelopeStrategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename DisjointPointBoxStrategy>
|
||||
struct overlaps_box_point
|
||||
{
|
||||
template <typename Box, typename Point>
|
||||
static inline bool apply(Box const& box, Point const& point)
|
||||
{
|
||||
// The default strategy is enough in this case
|
||||
typedef typename strategy::disjoint::services::default_strategy
|
||||
<
|
||||
Point, Box
|
||||
>::type strategy_type;
|
||||
return ! dispatch::disjoint<Point, Box>::apply(point, box, strategy_type());
|
||||
return ! detail::disjoint::disjoint_point_box(point, box,
|
||||
DisjointPointBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: After implementing disjoint Segment/Box for non-cartesian geometries
|
||||
// this strategy should be passed here.
|
||||
// TODO: This Segment/Box strategy should somehow be derived from Point/Segment strategy
|
||||
// which by default is winding containing CS-specific side strategy
|
||||
// TODO: disjoint Segment/Box will be called in this case which may take
|
||||
// quite long in non-cartesian CS. So we should consider passing range of bounding boxes
|
||||
// of segments after calculating them once.
|
||||
template <typename DisjointStrategy>
|
||||
struct overlaps_box_segment
|
||||
{
|
||||
explicit overlaps_box_segment(DisjointStrategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Box, typename Segment>
|
||||
static inline bool apply(Box const& box, Segment const& segment)
|
||||
inline bool apply(Box const& box, Segment const& segment) const
|
||||
{
|
||||
typedef typename strategy::disjoint::services::default_strategy
|
||||
<
|
||||
Segment, Box
|
||||
>::type strategy_type;
|
||||
return ! dispatch::disjoint<Segment, Box>::apply(segment, box, strategy_type());
|
||||
return ! dispatch::disjoint<Segment, Box>::apply(segment, box, m_strategy);
|
||||
}
|
||||
|
||||
DisjointStrategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename PtSegStrategy>
|
||||
@@ -172,13 +176,15 @@ private:
|
||||
{}
|
||||
|
||||
template <typename Item1, typename Item2>
|
||||
inline void apply(Item1 const& item1, Item2 const& item2)
|
||||
inline bool apply(Item1 const& item1, Item2 const& item2)
|
||||
{
|
||||
if (! m_intersection_found
|
||||
&& ! dispatch::disjoint<Item1, Item2>::apply(item1, item2, m_strategy))
|
||||
{
|
||||
m_intersection_found = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool intersection_found() const { return m_intersection_found; }
|
||||
@@ -219,12 +225,23 @@ public:
|
||||
{
|
||||
item_visitor_type<Strategy> visitor(strategy);
|
||||
|
||||
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
|
||||
typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
|
||||
typedef typename Strategy::disjoint_point_box_strategy_type disjoint_pb_strategy_type;
|
||||
|
||||
// TODO: disjoint Segment/Box may be called in partition multiple times
|
||||
// possibly for non-cartesian segments which could be slow. We should consider
|
||||
// passing a range of bounding boxes of segments after calculating them once.
|
||||
// Alternatively instead of a range of segments a range of Segment/Envelope pairs
|
||||
// should be passed, where envelope would be lazily calculated when needed the first time
|
||||
geometry::partition
|
||||
<
|
||||
geometry::model::box<typename point_type<MultiPoint>::type>
|
||||
>::apply(multipoint, segment_range(linear), visitor,
|
||||
expand_box_point(), overlaps_box_point(),
|
||||
expand_box_segment(), overlaps_box_segment());
|
||||
expand_box_point(),
|
||||
overlaps_box_point<disjoint_pb_strategy_type>(),
|
||||
expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
|
||||
overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
|
||||
|
||||
return ! visitor.intersection_found();
|
||||
}
|
||||
@@ -237,6 +254,195 @@ public:
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename SingleGeometry>
|
||||
class multi_point_single_geometry
|
||||
{
|
||||
public:
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPoint const& multi_point,
|
||||
SingleGeometry const& single_geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type;
|
||||
|
||||
typedef typename point_type<MultiPoint>::type point1_type;
|
||||
typedef typename point_type<SingleGeometry>::type point2_type;
|
||||
typedef model::box<point2_type> box2_type;
|
||||
|
||||
box2_type box2;
|
||||
geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy());
|
||||
geometry::detail::expand_by_epsilon(box2);
|
||||
|
||||
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
|
||||
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
|
||||
{
|
||||
// The default strategy is enough for Point/Box
|
||||
if (! detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type())
|
||||
&& ! dispatch::disjoint<point1_type, SingleGeometry>::apply(*it, single_geometry, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point, Strategy const& strategy)
|
||||
{
|
||||
return apply(multi_point, single_geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename MultiGeometry>
|
||||
class multi_point_multi_geometry
|
||||
{
|
||||
private:
|
||||
struct expand_box_point
|
||||
{
|
||||
template <typename Box, typename Point>
|
||||
static inline void apply(Box& total, Point const& point)
|
||||
{
|
||||
geometry::expand(total, point);
|
||||
}
|
||||
};
|
||||
|
||||
struct expand_box_box_pair
|
||||
{
|
||||
template <typename Box, typename BoxPair>
|
||||
inline void apply(Box& total, BoxPair const& box_pair) const
|
||||
{
|
||||
geometry::expand(total, box_pair.first);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointPointBoxStrategy>
|
||||
struct overlaps_box_point
|
||||
{
|
||||
template <typename Box, typename Point>
|
||||
static inline bool apply(Box const& box, Point const& point)
|
||||
{
|
||||
// The default strategy is enough for Point/Box
|
||||
return ! detail::disjoint::disjoint_point_box(point, box,
|
||||
DisjointPointBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointBoxBoxStrategy>
|
||||
struct overlaps_box_box_pair
|
||||
{
|
||||
template <typename Box, typename BoxPair>
|
||||
inline bool apply(Box const& box, BoxPair const& box_pair) const
|
||||
{
|
||||
// The default strategy is enough for Box/Box
|
||||
return ! detail::disjoint::disjoint_box_box(box_pair.first, box,
|
||||
DisjointBoxBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename PtSegStrategy>
|
||||
class item_visitor_type
|
||||
{
|
||||
public:
|
||||
item_visitor_type(MultiGeometry const& multi_geometry,
|
||||
PtSegStrategy const& strategy)
|
||||
: m_intersection_found(false)
|
||||
, m_multi_geometry(multi_geometry)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Point, typename BoxPair>
|
||||
inline bool apply(Point const& point, BoxPair const& box_pair)
|
||||
{
|
||||
typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pb_strategy_type;
|
||||
|
||||
typedef typename boost::range_value<MultiGeometry>::type single_type;
|
||||
|
||||
// The default strategy is enough for Point/Box
|
||||
if (! m_intersection_found
|
||||
&& ! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pb_strategy_type())
|
||||
&& ! dispatch::disjoint<Point, single_type>::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy))
|
||||
{
|
||||
m_intersection_found = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool intersection_found() const { return m_intersection_found; }
|
||||
|
||||
private:
|
||||
bool m_intersection_found;
|
||||
MultiGeometry const& m_multi_geometry;
|
||||
PtSegStrategy const& m_strategy;
|
||||
};
|
||||
// structs for partition -- end
|
||||
|
||||
public:
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiPoint const& multi_point, MultiGeometry const& multi_geometry, Strategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<MultiPoint>::type point1_type;
|
||||
typedef typename point_type<MultiGeometry>::type point2_type;
|
||||
typedef model::box<point1_type> box1_type;
|
||||
typedef model::box<point2_type> box2_type;
|
||||
typedef std::pair<box2_type, std::size_t> box_pair_type;
|
||||
|
||||
typename Strategy::envelope_strategy_type const
|
||||
envelope_strategy = strategy.get_envelope_strategy();
|
||||
|
||||
std::size_t count2 = boost::size(multi_geometry);
|
||||
std::vector<box_pair_type> boxes(count2);
|
||||
for (std::size_t i = 0 ; i < count2 ; ++i)
|
||||
{
|
||||
geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy);
|
||||
geometry::detail::expand_by_epsilon(boxes[i].first);
|
||||
boxes[i].second = i;
|
||||
}
|
||||
|
||||
item_visitor_type<Strategy> visitor(multi_geometry, strategy);
|
||||
|
||||
typedef overlaps_box_point
|
||||
<
|
||||
typename Strategy::disjoint_point_box_strategy_type
|
||||
> overlaps_box_point_type;
|
||||
typedef overlaps_box_box_pair
|
||||
<
|
||||
typename Strategy::disjoint_box_box_strategy_type
|
||||
> overlaps_box_box_pair_type;
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
box1_type
|
||||
>::apply(multi_point, boxes, visitor,
|
||||
expand_box_point(),
|
||||
overlaps_box_point_type(),
|
||||
expand_box_box_pair(),
|
||||
overlaps_box_box_pair_type());
|
||||
|
||||
return ! visitor.intersection_found();
|
||||
}
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiGeometry const& multi_geometry, MultiPoint const& multi_point, Strategy const& strategy)
|
||||
{
|
||||
return apply(multi_point, multi_geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Areal, typename Tag = typename tag<Areal>::type>
|
||||
struct multipoint_areal
|
||||
: multi_point_single_geometry<MultiPoint, Areal>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Areal>
|
||||
struct multipoint_areal<MultiPoint, Areal, multi_polygon_tag>
|
||||
: multi_point_multi_geometry<MultiPoint, Areal>
|
||||
{};
|
||||
|
||||
|
||||
}} // namespace detail::disjoint
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
@@ -321,6 +527,22 @@ struct disjoint
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename MultiPoint, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
Areal, MultiPoint, DimensionCount, areal_tag, multi_point_tag, false
|
||||
> : detail::disjoint::multipoint_areal<MultiPoint, Areal>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Areal, std::size_t DimensionCount>
|
||||
struct disjoint
|
||||
<
|
||||
MultiPoint, Areal, DimensionCount, multi_point_tag, areal_tag, false
|
||||
> : detail::disjoint::multipoint_areal<MultiPoint, Areal>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2018.
|
||||
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
@@ -41,16 +41,11 @@ namespace detail { namespace disjoint
|
||||
/*!
|
||||
\brief Internal utility function to detect if point/box are disjoint
|
||||
*/
|
||||
template <typename Point, typename Box>
|
||||
inline bool disjoint_point_box(Point const& point, Box const& box)
|
||||
template <typename Point, typename Box, typename Strategy>
|
||||
inline bool disjoint_point_box(Point const& point, Box const& box, Strategy const& )
|
||||
{
|
||||
typedef typename strategy::disjoint::services::default_strategy
|
||||
<
|
||||
Point, Box
|
||||
>::type strategy_type;
|
||||
|
||||
// ! covered_by(point, box)
|
||||
return ! strategy_type::apply(point, box);
|
||||
return ! Strategy::apply(point, box);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2015, 2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
|
||||
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
@@ -23,29 +23,15 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/strategy_transform.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/helper_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/transform.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/disjoint.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
|
||||
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -56,169 +42,15 @@ namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct point_point_generic
|
||||
{
|
||||
template <typename Point1, typename Point2, typename Strategy>
|
||||
static inline bool apply(Point1 const& p1, Point2 const& p2, Strategy const& )
|
||||
{
|
||||
return apply(p1, p2);
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
static inline bool apply(Point1 const& p1, Point2 const& p2)
|
||||
{
|
||||
if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return
|
||||
point_point_generic<Dimension + 1, DimensionCount>::apply(p1, p2);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t DimensionCount>
|
||||
struct point_point_generic<DimensionCount, DimensionCount>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
static inline bool apply(Point1 const&, Point2 const& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class point_point_on_spheroid
|
||||
{
|
||||
private:
|
||||
template <typename Point1, typename Point2, bool SameUnits>
|
||||
struct are_same_points
|
||||
{
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
typedef typename helper_geometry<Point1>::type helper_point_type1;
|
||||
typedef typename helper_geometry<Point2>::type helper_point_type2;
|
||||
|
||||
helper_point_type1 point1_normalized
|
||||
= return_normalized<helper_point_type1>(point1);
|
||||
helper_point_type2 point2_normalized
|
||||
= return_normalized<helper_point_type2>(point2);
|
||||
|
||||
return point_point_generic
|
||||
<
|
||||
0, dimension<Point1>::value
|
||||
>::apply(point1_normalized, point2_normalized);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
struct are_same_points<Point1, Point2, false> // points have different units
|
||||
{
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
typedef typename geometry::select_most_precise
|
||||
<
|
||||
typename fp_coordinate_type<Point1>::type,
|
||||
typename fp_coordinate_type<Point2>::type
|
||||
>::type calculation_type;
|
||||
|
||||
typename helper_geometry
|
||||
<
|
||||
Point1, calculation_type, radian
|
||||
>::type helper_point1, helper_point2;
|
||||
|
||||
Point1 point1_normalized = return_normalized<Point1>(point1);
|
||||
Point2 point2_normalized = return_normalized<Point2>(point2);
|
||||
|
||||
geometry::transform(point1_normalized, helper_point1);
|
||||
geometry::transform(point2_normalized, helper_point2);
|
||||
|
||||
return point_point_generic
|
||||
<
|
||||
0, dimension<Point1>::value
|
||||
>::apply(helper_point1, helper_point2);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename Point1, typename Point2, typename Strategy>
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& )
|
||||
{
|
||||
return apply(point1, point2);
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
return are_same_points
|
||||
<
|
||||
Point1,
|
||||
Point2,
|
||||
boost::is_same
|
||||
<
|
||||
typename coordinate_system<Point1>::type::units,
|
||||
typename coordinate_system<Point2>::type::units
|
||||
>::value
|
||||
>::apply(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2,
|
||||
std::size_t Dimension, std::size_t DimensionCount,
|
||||
typename CSTag1 = typename cs_tag<Point1>::type,
|
||||
typename CSTag2 = CSTag1
|
||||
>
|
||||
struct point_point
|
||||
: point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct point_point
|
||||
<
|
||||
Point1, Point2, Dimension, DimensionCount, spherical_equatorial_tag
|
||||
> : point_point_on_spheroid
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct point_point
|
||||
<
|
||||
Point1, Point2, Dimension, DimensionCount, geographic_tag
|
||||
> : point_point_on_spheroid
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>
|
||||
: point_point_generic<Dimension, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Internal utility function to detect of points are disjoint
|
||||
\note To avoid circular references
|
||||
*/
|
||||
template <typename Point1, typename Point2>
|
||||
inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2)
|
||||
template <typename Point1, typename Point2, typename Strategy>
|
||||
inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2,
|
||||
Strategy const& )
|
||||
{
|
||||
return point_point
|
||||
<
|
||||
Point1, Point2,
|
||||
0, dimension<Point1>::type::value
|
||||
>::apply(point1, point2);
|
||||
return ! Strategy::apply(point1, point2);
|
||||
}
|
||||
|
||||
|
||||
@@ -226,8 +58,6 @@ inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2)
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
@@ -235,8 +65,14 @@ namespace dispatch
|
||||
|
||||
template <typename Point1, typename Point2, std::size_t DimensionCount>
|
||||
struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, false>
|
||||
: detail::disjoint::point_point<Point1, Point2, 0, DimensionCount>
|
||||
{};
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2,
|
||||
Strategy const& )
|
||||
{
|
||||
return ! Strategy::apply(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2019.
|
||||
// Modifications copyright (c) 2013-2019, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// 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.
|
||||
@@ -24,9 +25,22 @@
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/vertex_longitude.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
|
||||
// Temporary, for envelope_segment_impl
|
||||
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -36,10 +50,202 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace disjoint
|
||||
{
|
||||
|
||||
template <typename CS_Tag>
|
||||
struct disjoint_segment_box_sphere_or_spheroid
|
||||
{
|
||||
struct disjoint_info
|
||||
{
|
||||
enum type
|
||||
{
|
||||
intersect,
|
||||
disjoint_no_vertex,
|
||||
disjoint_vertex
|
||||
};
|
||||
disjoint_info(type t) : m_(t){}
|
||||
operator type () const {return m_;}
|
||||
type m_;
|
||||
private :
|
||||
//prevent automatic conversion for any other built-in types
|
||||
template <typename T>
|
||||
operator T () const;
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment, typename Box,
|
||||
typename AzimuthStrategy,
|
||||
typename NormalizeStrategy,
|
||||
typename DisjointPointBoxStrategy,
|
||||
typename DisjointBoxBoxStrategy
|
||||
>
|
||||
static inline bool apply(Segment const& segment,
|
||||
Box const& box,
|
||||
AzimuthStrategy const& azimuth_strategy,
|
||||
NormalizeStrategy const& normalize_strategy,
|
||||
DisjointPointBoxStrategy const& disjoint_point_box_strategy,
|
||||
DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
|
||||
{
|
||||
typedef typename point_type<Segment>::type segment_point;
|
||||
segment_point vertex;
|
||||
return apply(segment, box, vertex,
|
||||
azimuth_strategy,
|
||||
normalize_strategy,
|
||||
disjoint_point_box_strategy,
|
||||
disjoint_box_box_strategy) != disjoint_info::intersect;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment, typename Box,
|
||||
typename P,
|
||||
typename AzimuthStrategy,
|
||||
typename NormalizeStrategy,
|
||||
typename DisjointPointBoxStrategy,
|
||||
typename DisjointBoxBoxStrategy
|
||||
>
|
||||
static inline disjoint_info apply(Segment const& segment,
|
||||
Box const& box,
|
||||
P& vertex,
|
||||
AzimuthStrategy const& azimuth_strategy,
|
||||
NormalizeStrategy const& ,
|
||||
DisjointPointBoxStrategy const& disjoint_point_box_strategy,
|
||||
DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
|
||||
{
|
||||
assert_dimension_equal<Segment, Box>();
|
||||
|
||||
typedef typename point_type<Segment>::type segment_point_type;
|
||||
|
||||
segment_point_type p0, p1;
|
||||
geometry::detail::assign_point_from_index<0>(segment, p0);
|
||||
geometry::detail::assign_point_from_index<1>(segment, p1);
|
||||
|
||||
//vertex not computed here
|
||||
disjoint_info disjoint_return_value = disjoint_info::disjoint_no_vertex;
|
||||
|
||||
// Simplest cases first
|
||||
|
||||
// Case 1: if box contains one of segment's endpoints then they are not disjoint
|
||||
if ( ! disjoint_point_box(p0, box, disjoint_point_box_strategy)
|
||||
|| ! disjoint_point_box(p1, box, disjoint_point_box_strategy) )
|
||||
{
|
||||
return disjoint_info::intersect;
|
||||
}
|
||||
|
||||
// Case 2: disjoint if bounding boxes are disjoint
|
||||
|
||||
typedef typename coordinate_type<segment_point_type>::type CT;
|
||||
|
||||
segment_point_type p0_normalized;
|
||||
NormalizeStrategy::apply(p0, p0_normalized);
|
||||
segment_point_type p1_normalized;
|
||||
NormalizeStrategy::apply(p1, p1_normalized);
|
||||
|
||||
CT lon1 = geometry::get_as_radian<0>(p0_normalized);
|
||||
CT lat1 = geometry::get_as_radian<1>(p0_normalized);
|
||||
CT lon2 = geometry::get_as_radian<0>(p1_normalized);
|
||||
CT lat2 = geometry::get_as_radian<1>(p1_normalized);
|
||||
|
||||
if (lon1 > lon2)
|
||||
{
|
||||
std::swap(lon1, lon2);
|
||||
std::swap(lat1, lat2);
|
||||
}
|
||||
|
||||
geometry::model::box<segment_point_type> box_seg;
|
||||
|
||||
strategy::envelope::detail::envelope_segment_impl
|
||||
<
|
||||
CS_Tag
|
||||
>::template apply<geometry::radian>(lon1, lat1,
|
||||
lon2, lat2,
|
||||
box_seg,
|
||||
azimuth_strategy);
|
||||
|
||||
if (disjoint_box_box(box, box_seg, disjoint_box_box_strategy))
|
||||
{
|
||||
return disjoint_return_value;
|
||||
}
|
||||
|
||||
// Case 3: test intersection by comparing angles
|
||||
|
||||
CT alp1, a_b0, a_b1, a_b2, a_b3;
|
||||
|
||||
CT b_lon_min = geometry::get_as_radian<geometry::min_corner, 0>(box);
|
||||
CT b_lat_min = geometry::get_as_radian<geometry::min_corner, 1>(box);
|
||||
CT b_lon_max = geometry::get_as_radian<geometry::max_corner, 0>(box);
|
||||
CT b_lat_max = geometry::get_as_radian<geometry::max_corner, 1>(box);
|
||||
|
||||
azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1);
|
||||
azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_min, a_b0);
|
||||
azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_min, a_b1);
|
||||
azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_max, a_b2);
|
||||
azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_max, a_b3);
|
||||
|
||||
bool b0 = formula::azimuth_side_value(alp1, a_b0) > 0;
|
||||
bool b1 = formula::azimuth_side_value(alp1, a_b1) > 0;
|
||||
bool b2 = formula::azimuth_side_value(alp1, a_b2) > 0;
|
||||
bool b3 = formula::azimuth_side_value(alp1, a_b3) > 0;
|
||||
|
||||
if (!(b0 && b1 && b2 && b3) && (b0 || b1 || b2 || b3))
|
||||
{
|
||||
return disjoint_info::intersect;
|
||||
}
|
||||
|
||||
// Case 4: The only intersection case not covered above is when all four
|
||||
// points of the box are above (below) the segment in northern (southern)
|
||||
// hemisphere. Then we have to compute the vertex of the segment
|
||||
|
||||
CT vertex_lat;
|
||||
CT lat_sum = lat1 + lat2;
|
||||
|
||||
if ((lat1 < b_lat_min && lat_sum > CT(0))
|
||||
|| (lat1 > b_lat_max && lat_sum < CT(0)))
|
||||
{
|
||||
CT b_lat_below; //latitude of box closest to equator
|
||||
|
||||
if (lat_sum > CT(0))
|
||||
{
|
||||
vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(box_seg);
|
||||
b_lat_below = b_lat_min;
|
||||
} else {
|
||||
vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(box_seg);
|
||||
b_lat_below = b_lat_max;
|
||||
}
|
||||
|
||||
//optimization TODO: computing the spherical longitude should suffice for
|
||||
// the majority of cases
|
||||
CT vertex_lon = geometry::formula::vertex_longitude<CT, CS_Tag>
|
||||
::apply(lon1, lat1,
|
||||
lon2, lat2,
|
||||
vertex_lat,
|
||||
alp1,
|
||||
azimuth_strategy);
|
||||
|
||||
geometry::set_from_radian<0>(vertex, vertex_lon);
|
||||
geometry::set_from_radian<1>(vertex, vertex_lat);
|
||||
disjoint_return_value = disjoint_info::disjoint_vertex; //vertex_computed
|
||||
|
||||
// Check if the vertex point is within the band defined by the
|
||||
// minimum and maximum longitude of the box; if yes, then return
|
||||
// false if the point is above the min latitude of the box; return
|
||||
// true in all other cases
|
||||
if (vertex_lon >= b_lon_min && vertex_lon <= b_lon_max
|
||||
&& std::abs(vertex_lat) > std::abs(b_lat_below))
|
||||
{
|
||||
return disjoint_info::intersect;
|
||||
}
|
||||
}
|
||||
|
||||
return disjoint_return_value;
|
||||
}
|
||||
};
|
||||
|
||||
struct disjoint_segment_box
|
||||
{
|
||||
template <typename Segment, typename Box, typename Strategy>
|
||||
static inline bool apply(Segment const& segment, Box const& box, Strategy const& strategy)
|
||||
static inline bool apply(Segment const& segment,
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return strategy.apply(segment, box);
|
||||
}
|
||||
@@ -56,7 +262,7 @@ namespace dispatch
|
||||
|
||||
template <typename Segment, typename Box, std::size_t DimensionCount>
|
||||
struct disjoint<Segment, Box, DimensionCount, segment_tag, box_tag, false>
|
||||
: detail::disjoint::disjoint_segment_box
|
||||
: detail::disjoint::disjoint_segment_box
|
||||
{};
|
||||
|
||||
|
||||
|
||||
@@ -110,6 +110,26 @@ struct default_strategy<Box1, Box2, box_tag, box_tag, false>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Linear, typename Box>
|
||||
struct default_strategy<Linear, Box, segment_tag, box_tag, false>
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
segment_tag, box_tag,
|
||||
typename point_type<Linear>::type,
|
||||
typename point_type<Box>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Linear, typename Box>
|
||||
struct default_strategy<Linear, Box, linear_tag, box_tag, false>
|
||||
: strategy::distance::services::default_strategy
|
||||
<
|
||||
segment_tag, box_tag,
|
||||
typename point_type<Linear>::type,
|
||||
typename point_type<Box>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
// Helper metafunction for default point-segment strategy retrieval
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014, 2018.
|
||||
// Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
@@ -25,6 +26,7 @@
|
||||
#include <boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_to_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/segment_to_segment.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014, 2018.
|
||||
// Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
@@ -94,9 +95,10 @@ struct distance
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
template <typename Strategy>
|
||||
struct distance
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
|
||||
apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
@@ -107,7 +109,11 @@ struct distance
|
||||
Geometry1, Geometry2, Strategy
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct distance<default_strategy>
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline
|
||||
typename distance_result<Geometry1, Geometry2, default_strategy>::type
|
||||
@@ -143,8 +149,10 @@ struct distance
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return
|
||||
resolve_strategy::distance::apply(geometry1, geometry2, strategy);
|
||||
return resolve_strategy::distance
|
||||
<
|
||||
Strategy
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -320,10 +328,10 @@ struct distance
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{distance} \brief_strategy
|
||||
\brief Calculate the distance between two geometries \brief_strategy
|
||||
\ingroup distance
|
||||
\details
|
||||
\details \details_calc{area}. \brief_strategy. \details_strategy_reasons
|
||||
\details The free function distance calculates the distance between two geometries \brief_strategy. \details_strategy_reasons
|
||||
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
@@ -376,9 +384,10 @@ distance(Geometry1 const& geometry1,
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_calc2{distance}
|
||||
\brief Calculate the distance between two geometries.
|
||||
\ingroup distance
|
||||
\details The default strategy is used, corresponding to the coordinate system of the geometries
|
||||
\details The free function distance calculates the distance between two geometries. \details_default_strategy
|
||||
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -61,7 +60,6 @@ struct linear_to_areal
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Areal1, typename Areal2, typename Strategy>
|
||||
struct areal_to_areal
|
||||
{
|
||||
@@ -110,7 +108,6 @@ struct distance
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Linear, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_BOX_HPP
|
||||
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace distance
|
||||
{
|
||||
|
||||
template <typename Linear, typename Box, typename Strategy>
|
||||
struct linear_to_box
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
Strategy,
|
||||
typename point_type<Linear>::type,
|
||||
typename point_type<Box>::type
|
||||
>::type return_type;
|
||||
|
||||
template <typename Iterator>
|
||||
static inline return_type apply(Box const& box,
|
||||
Iterator begin,
|
||||
Iterator end,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
bool first = true;
|
||||
return_type d_min(0);
|
||||
for (Iterator it = begin; it != end; ++it, first = false)
|
||||
{
|
||||
typedef typename std::iterator_traits<Iterator>::value_type
|
||||
Segment;
|
||||
|
||||
return_type d = dispatch::distance<Segment, Box, Strategy>
|
||||
::apply(*it, box, strategy);
|
||||
|
||||
if ( first || d < d_min )
|
||||
{
|
||||
d_min = d;
|
||||
}
|
||||
}
|
||||
return d_min;
|
||||
}
|
||||
|
||||
static inline return_type apply(Linear const& linear,
|
||||
Box const& box,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if ( geometry::intersects(linear, box) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return apply(box,
|
||||
geometry::segments_begin(linear),
|
||||
geometry::segments_end(linear),
|
||||
strategy);
|
||||
}
|
||||
|
||||
|
||||
static inline return_type apply(Box const& box,
|
||||
Linear const& linear,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return apply(linear, box, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::distance
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Linear, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Linear, Box, Strategy,
|
||||
linear_tag, box_tag,
|
||||
strategy_tag_distance_segment_box, false
|
||||
>
|
||||
: detail::distance::linear_to_box
|
||||
<
|
||||
Linear, Box, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Areal, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Areal, Box, Strategy,
|
||||
areal_tag, box_tag,
|
||||
strategy_tag_distance_segment_box, false
|
||||
>
|
||||
: detail::distance::linear_to_box
|
||||
<
|
||||
Areal, Box, Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_LINEAR_TO_BOX_HPP
|
||||
@@ -193,6 +193,7 @@ struct distance
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPoint, typename Linear, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014, 2019.
|
||||
// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
@@ -39,13 +40,12 @@
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/within.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
|
||||
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
|
||||
@@ -160,7 +160,8 @@ struct point_to_ring
|
||||
Ring const& ring,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (geometry::within(point, ring))
|
||||
// TODO: pass strategy
|
||||
if (within::within_point_geometry(point, ring))
|
||||
{
|
||||
return return_type(0);
|
||||
}
|
||||
@@ -204,7 +205,8 @@ private:
|
||||
{
|
||||
for (InteriorRingIterator it = first; it != last; ++it)
|
||||
{
|
||||
if (geometry::within(point, *it))
|
||||
// TODO: pass strategy
|
||||
if (within::within_point_geometry(point, *it))
|
||||
{
|
||||
// the point is inside a polygon hole, so its distance
|
||||
// to the polygon its distance to the polygon's
|
||||
@@ -233,7 +235,8 @@ public:
|
||||
Polygon const& polygon,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (!geometry::covered_by(point, exterior_ring(polygon)))
|
||||
// TODO: pass strategy
|
||||
if (! within::covered_by_point_geometry(point, exterior_ring(polygon)))
|
||||
{
|
||||
// the point is outside the exterior ring, so its distance
|
||||
// to the polygon is its distance to the polygon's exterior ring
|
||||
@@ -330,7 +333,8 @@ struct point_to_multigeometry<Point, MultiPolygon, Strategy, true>
|
||||
MultiPolygon const& multipolygon,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (geometry::covered_by(point, multipolygon))
|
||||
// TODO: pass strategy
|
||||
if (within::covered_by_point_geometry(point, multipolygon))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -391,7 +395,7 @@ struct distance
|
||||
template <typename Point, typename Polygon, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Point, Polygon, Strategy, point_tag, polygon_tag,
|
||||
Point, Polygon, Strategy, point_tag, polygon_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
> : detail::distance::point_to_polygon
|
||||
<
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2019 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -27,26 +29,26 @@
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/calculation_type.hpp>
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/intersects.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/distance.hpp>
|
||||
#include <boost/geometry/util/calculation_type.hpp>
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/has_nan_coordinate.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/disjoint.hpp>
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -58,6 +60,20 @@ namespace detail { namespace distance
|
||||
{
|
||||
|
||||
|
||||
// TODO: Take strategy
|
||||
template <typename Segment, typename Box>
|
||||
inline bool intersects_segment_box(Segment const& segment, Box const& box)
|
||||
{
|
||||
typedef typename strategy::disjoint::services::default_strategy
|
||||
<
|
||||
Segment, Box
|
||||
>::type strategy_type;
|
||||
|
||||
return ! detail::disjoint::disjoint_segment_box::apply(segment, box,
|
||||
strategy_type());
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
@@ -73,7 +89,7 @@ private:
|
||||
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
Strategy
|
||||
typename Strategy::distance_ps_strategy::type
|
||||
>::type comparable_strategy;
|
||||
|
||||
typedef detail::closest_feature::point_to_point_range
|
||||
@@ -100,7 +116,7 @@ public:
|
||||
Strategy const& strategy,
|
||||
bool check_intersection = true)
|
||||
{
|
||||
if (check_intersection && geometry::intersects(segment, box))
|
||||
if (check_intersection && intersects_segment_box(segment, box))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -108,8 +124,8 @@ public:
|
||||
comparable_strategy cstrategy =
|
||||
strategy::distance::services::get_comparable
|
||||
<
|
||||
Strategy
|
||||
>::apply(strategy);
|
||||
typename Strategy::distance_ps_strategy::type
|
||||
>::apply(strategy.get_distance_ps_strategy());
|
||||
|
||||
// get segment points
|
||||
segment_point p[2];
|
||||
@@ -159,12 +175,12 @@ public:
|
||||
|
||||
if (imin < 4)
|
||||
{
|
||||
return strategy.apply(box_points[imin], p[0], p[1]);
|
||||
return strategy.get_distance_ps_strategy().apply(box_points[imin], p[0], p[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int bimin = imin - 4;
|
||||
return strategy.apply(p[bimin],
|
||||
return strategy.get_distance_ps_strategy().apply(p[bimin],
|
||||
*bit_min[bimin].first,
|
||||
*bit_min[bimin].second);
|
||||
}
|
||||
@@ -215,7 +231,7 @@ public:
|
||||
Strategy const& strategy,
|
||||
bool check_intersection = true)
|
||||
{
|
||||
if (check_intersection && geometry::intersects(segment, box))
|
||||
if (check_intersection && intersects_segment_box(segment, box))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -280,8 +296,7 @@ template
|
||||
typename ReturnType,
|
||||
typename SegmentPoint,
|
||||
typename BoxPoint,
|
||||
typename PPStrategy,
|
||||
typename PSStrategy
|
||||
typename SBStrategy
|
||||
>
|
||||
class segment_to_box_2D
|
||||
{
|
||||
@@ -340,10 +355,9 @@ private:
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& bottom_right,
|
||||
BoxPoint const& top_right,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy)
|
||||
SBStrategy const& sb_strategy)
|
||||
{
|
||||
boost::ignore_unused(pp_strategy, ps_strategy);
|
||||
boost::ignore_unused(sb_strategy);
|
||||
|
||||
// the implementation below is written for non-negative slope
|
||||
// segments
|
||||
@@ -355,22 +369,29 @@ private:
|
||||
|
||||
LessEqual less_equal;
|
||||
|
||||
if (less_equal(geometry::get<1>(top_right), geometry::get<1>(p0)))
|
||||
typename SBStrategy::distance_ps_strategy::type ps_strategy =
|
||||
sb_strategy.get_distance_ps_strategy();
|
||||
|
||||
if (less_equal(geometry::get<1>(bottom_right), geometry::get<1>(p0)))
|
||||
{
|
||||
// closest box point is the top-right corner
|
||||
return cast::apply(pp_strategy.apply(p0, top_right));
|
||||
}
|
||||
else if (less_equal(geometry::get<1>(bottom_right),
|
||||
geometry::get<1>(p0)))
|
||||
{
|
||||
// distance is realized between p0 and right-most
|
||||
// segment of box
|
||||
ReturnType diff = cast::apply(geometry::get<0>(p0))
|
||||
- cast::apply(geometry::get<0>(bottom_right));
|
||||
return strategy::distance::services::result_from_distance
|
||||
<
|
||||
PSStrategy, BoxPoint, SegmentPoint
|
||||
>::apply(ps_strategy, math::abs(diff));
|
||||
//if p0 is in box's band
|
||||
if (less_equal(geometry::get<1>(p0), geometry::get<1>(top_right)))
|
||||
{
|
||||
// segment & crosses band (TODO:merge with box-box dist)
|
||||
if (math::equals(geometry::get<0>(p0), geometry::get<0>(p1)))
|
||||
{
|
||||
SegmentPoint high = geometry::get<1>(p1) > geometry::get<1>(p0) ? p1 : p0;
|
||||
if (less_equal(geometry::get<1>(high), geometry::get<1>(top_right)))
|
||||
{
|
||||
return cast::apply(ps_strategy.apply(high, bottom_right, top_right));
|
||||
}
|
||||
return cast::apply(ps_strategy.apply(top_right, p0, p1));
|
||||
}
|
||||
return cast::apply(ps_strategy.apply(p0, bottom_right, top_right));
|
||||
}
|
||||
// distance is realized between the top-right
|
||||
// corner of the box and the segment
|
||||
return cast::apply(ps_strategy.apply(top_right, p0, p1));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -381,45 +402,55 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// it is assumed here that p0 lies above the box (so the
|
||||
// entire segment lies above the box)
|
||||
|
||||
template <typename LessEqual>
|
||||
struct above_of_box
|
||||
{
|
||||
|
||||
static inline ReturnType apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
PSStrategy const& ps_strategy)
|
||||
SBStrategy const& sb_strategy)
|
||||
{
|
||||
boost::ignore_unused(ps_strategy);
|
||||
|
||||
// the segment lies above the box
|
||||
boost::ignore_unused(sb_strategy);
|
||||
return apply(p0, p1, p0, top_left, sb_strategy);
|
||||
}
|
||||
|
||||
static inline ReturnType apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
SegmentPoint const& p_max,
|
||||
BoxPoint const& top_left,
|
||||
SBStrategy const& sb_strategy)
|
||||
{
|
||||
boost::ignore_unused(sb_strategy);
|
||||
typedef cast_to_result<ReturnType> cast;
|
||||
|
||||
LessEqual less_equal;
|
||||
|
||||
// p0 is above the upper segment of the box
|
||||
// (and inside its band)
|
||||
if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p0)))
|
||||
// p0 is above the upper segment of the box (and inside its band)
|
||||
// then compute the vertical (i.e. meridian for spherical) distance
|
||||
if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p_max)))
|
||||
{
|
||||
ReturnType diff = cast::apply(geometry::get<1>(p0))
|
||||
- cast::apply(geometry::get<1>(top_left));
|
||||
ReturnType diff =
|
||||
sb_strategy.get_distance_ps_strategy().vertical_or_meridian(
|
||||
geometry::get_as_radian<1>(p_max),
|
||||
geometry::get_as_radian<1>(top_left));
|
||||
|
||||
return strategy::distance::services::result_from_distance
|
||||
<
|
||||
PSStrategy, SegmentPoint, BoxPoint
|
||||
>::apply(ps_strategy, math::abs(diff));
|
||||
SBStrategy, SegmentPoint, BoxPoint
|
||||
>::apply(sb_strategy, math::abs(diff));
|
||||
}
|
||||
|
||||
// p0 is to the left of the box, but p1 is above the box
|
||||
// in this case the distance is realized between the
|
||||
// top-left corner of the box and the segment
|
||||
return cast::apply(ps_strategy.apply(top_left, p0, p1));
|
||||
return cast::apply(sb_strategy.get_distance_ps_strategy().
|
||||
apply(top_left, p0, p1));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename LessEqual>
|
||||
struct check_right_left_of_box
|
||||
{
|
||||
@@ -429,8 +460,7 @@ private:
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy,
|
||||
SBStrategy const& sb_strategy,
|
||||
ReturnType& result)
|
||||
{
|
||||
// p0 lies to the right of the box
|
||||
@@ -440,7 +470,7 @@ private:
|
||||
<
|
||||
LessEqual
|
||||
>::apply(p0, p1, bottom_right, top_right,
|
||||
pp_strategy, ps_strategy);
|
||||
sb_strategy);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -451,7 +481,7 @@ private:
|
||||
<
|
||||
typename other_compare<LessEqual>::type
|
||||
>::apply(p1, p0, top_left, bottom_left,
|
||||
pp_strategy, ps_strategy);
|
||||
sb_strategy);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -459,7 +489,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename LessEqual>
|
||||
struct check_above_below_of_box
|
||||
{
|
||||
@@ -469,26 +498,35 @@ private:
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
PSStrategy const& ps_strategy,
|
||||
SBStrategy const& sb_strategy,
|
||||
ReturnType& result)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, false> GreaterEqual;
|
||||
|
||||
// the segment lies below the box
|
||||
if (geometry::get<1>(p1) < geometry::get<1>(bottom_left))
|
||||
{
|
||||
result = above_of_box
|
||||
<
|
||||
typename other_compare<LessEqual>::type
|
||||
>::apply(p1, p0, bottom_right, ps_strategy);
|
||||
result = sb_strategy.template segment_below_of_box
|
||||
<
|
||||
LessEqual,
|
||||
ReturnType
|
||||
>(p0, p1,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right);
|
||||
return true;
|
||||
}
|
||||
|
||||
// the segment lies above the box
|
||||
if (geometry::get<1>(p0) > geometry::get<1>(top_right))
|
||||
{
|
||||
result = above_of_box
|
||||
<
|
||||
LessEqual
|
||||
>::apply(p0, p1, top_left, ps_strategy);
|
||||
result = (std::min)(above_of_box
|
||||
<
|
||||
LessEqual
|
||||
>::apply(p0, p1, top_left, sb_strategy),
|
||||
above_of_box
|
||||
<
|
||||
GreaterEqual
|
||||
>::apply(p1, p0, top_right, sb_strategy));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -499,47 +537,30 @@ private:
|
||||
{
|
||||
static inline bool apply(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& bottom_left0,
|
||||
BoxPoint const& top_right0,
|
||||
BoxPoint const& bottom_left1,
|
||||
BoxPoint const& top_right1,
|
||||
BoxPoint const& corner1,
|
||||
BoxPoint const& corner2,
|
||||
PSStrategy const& ps_strategy,
|
||||
SBStrategy const& sb_strategy,
|
||||
ReturnType& result)
|
||||
{
|
||||
typedef typename geometry::strategy::side::services::default_strategy
|
||||
<
|
||||
typename geometry::cs_tag<SegmentPoint>::type
|
||||
>::type side;
|
||||
|
||||
typedef cast_to_result<ReturnType> cast;
|
||||
|
||||
ReturnType diff0 = cast::apply(geometry::get<0>(p1))
|
||||
- cast::apply(geometry::get<0>(p0));
|
||||
ReturnType t_min0 = cast::apply(geometry::get<0>(bottom_left0))
|
||||
- cast::apply(geometry::get<0>(p0));
|
||||
ReturnType t_max0 = cast::apply(geometry::get<0>(top_right0))
|
||||
- cast::apply(geometry::get<0>(p0));
|
||||
|
||||
ReturnType diff1 = cast::apply(geometry::get<1>(p1))
|
||||
- cast::apply(geometry::get<1>(p0));
|
||||
ReturnType t_min1 = cast::apply(geometry::get<1>(bottom_left1))
|
||||
- cast::apply(geometry::get<1>(p0));
|
||||
ReturnType t_max1 = cast::apply(geometry::get<1>(top_right1))
|
||||
- cast::apply(geometry::get<1>(p0));
|
||||
- cast::apply(geometry::get<1>(p0));
|
||||
|
||||
if (diff1 < 0)
|
||||
{
|
||||
diff1 = -diff1;
|
||||
t_min1 = -t_min1;
|
||||
t_max1 = -t_max1;
|
||||
}
|
||||
typename SBStrategy::distance_ps_strategy::type ps_strategy =
|
||||
sb_strategy.get_distance_ps_strategy();
|
||||
|
||||
// t_min0 > t_max1
|
||||
if (t_min0 * diff1 > t_max1 * diff0)
|
||||
int sign = diff1 < 0 ? -1 : 1;
|
||||
if (side::apply(p0, p1, corner1) * sign < 0)
|
||||
{
|
||||
result = cast::apply(ps_strategy.apply(corner1, p0, p1));
|
||||
return true;
|
||||
}
|
||||
|
||||
// t_max0 < t_min1
|
||||
if (t_max0 * diff1 < t_min1 * diff0)
|
||||
if (side::apply(p0, p1, corner2) * sign > 0)
|
||||
{
|
||||
result = cast::apply(ps_strategy.apply(corner2, p0, p1));
|
||||
return true;
|
||||
@@ -555,8 +576,7 @@ private:
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy)
|
||||
SBStrategy const& sb_strategy)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, true> less_equal;
|
||||
|
||||
@@ -576,7 +596,7 @@ private:
|
||||
less_equal
|
||||
>::apply(p0, p1,
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
pp_strategy, ps_strategy, result))
|
||||
sb_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -586,16 +606,14 @@ private:
|
||||
less_equal
|
||||
>::apply(p0, p1,
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
ps_strategy, result))
|
||||
sb_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_generic_position::apply(p0, p1,
|
||||
bottom_left, top_right,
|
||||
bottom_left, top_right,
|
||||
top_left, bottom_right,
|
||||
ps_strategy, result))
|
||||
sb_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -612,8 +630,7 @@ private:
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy)
|
||||
SBStrategy const& sb_strategy)
|
||||
{
|
||||
typedef compare_less_equal<ReturnType, false> greater_equal;
|
||||
|
||||
@@ -630,7 +647,7 @@ private:
|
||||
greater_equal
|
||||
>::apply(p0, p1,
|
||||
bottom_left, bottom_right, top_left, top_right,
|
||||
pp_strategy, ps_strategy, result))
|
||||
sb_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -640,16 +657,14 @@ private:
|
||||
greater_equal
|
||||
>::apply(p1, p0,
|
||||
top_right, top_left, bottom_right, bottom_left,
|
||||
ps_strategy, result))
|
||||
sb_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check_generic_position::apply(p0, p1,
|
||||
bottom_left, top_right,
|
||||
top_right, bottom_left,
|
||||
bottom_left, top_right,
|
||||
ps_strategy, result))
|
||||
sb_strategy, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -665,8 +680,7 @@ public:
|
||||
BoxPoint const& top_right,
|
||||
BoxPoint const& bottom_left,
|
||||
BoxPoint const& bottom_right,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy)
|
||||
SBStrategy const& sb_strategy)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( geometry::less<SegmentPoint>()(p0, p1)
|
||||
|| geometry::has_nan_coordinate(p0)
|
||||
@@ -678,27 +692,43 @@ public:
|
||||
return negative_slope_segment(p0, p1,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right,
|
||||
pp_strategy, ps_strategy);
|
||||
sb_strategy);
|
||||
}
|
||||
|
||||
return non_negative_slope_segment(p0, p1,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right,
|
||||
pp_strategy, ps_strategy);
|
||||
sb_strategy);
|
||||
}
|
||||
|
||||
template <typename LessEqual>
|
||||
static inline ReturnType call_above_of_box(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
SegmentPoint const& p_max,
|
||||
BoxPoint const& top_left,
|
||||
SBStrategy const& sb_strategy)
|
||||
{
|
||||
return above_of_box<LessEqual>::apply(p0, p1, p_max, top_left, sb_strategy);
|
||||
}
|
||||
|
||||
template <typename LessEqual>
|
||||
static inline ReturnType call_above_of_box(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const& top_left,
|
||||
SBStrategy const& sb_strategy)
|
||||
{
|
||||
return above_of_box<LessEqual>::apply(p0, p1, top_left, sb_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=========================================================================
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename std::size_t Dimension,
|
||||
typename PPStrategy,
|
||||
typename PSStrategy
|
||||
typename SBStrategy
|
||||
>
|
||||
class segment_to_box
|
||||
: not_implemented<Segment, Box>
|
||||
@@ -709,10 +739,9 @@ template
|
||||
<
|
||||
typename Segment,
|
||||
typename Box,
|
||||
typename PPStrategy,
|
||||
typename PSStrategy
|
||||
typename SBStrategy
|
||||
>
|
||||
class segment_to_box<Segment, Box, 2, PPStrategy, PSStrategy>
|
||||
class segment_to_box<Segment, Box, 2, SBStrategy>
|
||||
{
|
||||
private:
|
||||
typedef typename point_type<Segment>::type segment_point;
|
||||
@@ -720,12 +749,7 @@ private:
|
||||
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
PPStrategy
|
||||
>::type pp_comparable_strategy;
|
||||
|
||||
typedef typename strategy::distance::services::comparable_type
|
||||
<
|
||||
PSStrategy
|
||||
SBStrategy
|
||||
>::type ps_comparable_strategy;
|
||||
|
||||
typedef typename strategy::distance::services::return_type
|
||||
@@ -735,26 +759,26 @@ private:
|
||||
public:
|
||||
typedef typename strategy::distance::services::return_type
|
||||
<
|
||||
PSStrategy, segment_point, box_point
|
||||
SBStrategy, segment_point, box_point
|
||||
>::type return_type;
|
||||
|
||||
static inline return_type apply(Segment const& segment,
|
||||
Box const& box,
|
||||
PPStrategy const& pp_strategy,
|
||||
PSStrategy const& ps_strategy)
|
||||
SBStrategy const& sb_strategy)
|
||||
{
|
||||
segment_point p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
|
||||
if (geometry::equals(p[0], p[1]))
|
||||
if (detail::equals::equals_point_point(p[0], p[1],
|
||||
sb_strategy.get_equals_point_point_strategy()))
|
||||
{
|
||||
typedef typename boost::mpl::if_
|
||||
<
|
||||
boost::is_same
|
||||
<
|
||||
ps_comparable_strategy,
|
||||
PSStrategy
|
||||
SBStrategy
|
||||
>,
|
||||
typename strategy::distance::services::comparable_type
|
||||
<
|
||||
@@ -781,6 +805,10 @@ public:
|
||||
detail::assign_box_corners(box, bottom_left, bottom_right,
|
||||
top_left, top_right);
|
||||
|
||||
SBStrategy::mirror(p[0], p[1],
|
||||
bottom_left, bottom_right,
|
||||
top_left, top_right);
|
||||
|
||||
if (geometry::less<segment_point>()(p[0], p[1]))
|
||||
{
|
||||
return segment_to_box_2D
|
||||
@@ -788,12 +816,10 @@ public:
|
||||
return_type,
|
||||
segment_point,
|
||||
box_point,
|
||||
PPStrategy,
|
||||
PSStrategy
|
||||
SBStrategy
|
||||
>::apply(p[0], p[1],
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
pp_strategy,
|
||||
ps_strategy);
|
||||
sb_strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -802,12 +828,10 @@ public:
|
||||
return_type,
|
||||
segment_point,
|
||||
box_point,
|
||||
PPStrategy,
|
||||
PSStrategy
|
||||
SBStrategy
|
||||
>::apply(p[1], p[0],
|
||||
top_left, top_right, bottom_left, bottom_right,
|
||||
pp_strategy,
|
||||
ps_strategy);
|
||||
sb_strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -826,7 +850,7 @@ template <typename Segment, typename Box, typename Strategy>
|
||||
struct distance
|
||||
<
|
||||
Segment, Box, Strategy, segment_tag, box_tag,
|
||||
strategy_tag_distance_point_segment, false
|
||||
strategy_tag_distance_segment_box, false
|
||||
>
|
||||
{
|
||||
typedef typename strategy::distance::services::return_type
|
||||
@@ -843,40 +867,13 @@ struct distance
|
||||
{
|
||||
assert_dimension_equal<Segment, Box>();
|
||||
|
||||
typedef typename boost::mpl::if_
|
||||
<
|
||||
boost::is_same
|
||||
<
|
||||
typename strategy::distance::services::comparable_type
|
||||
<
|
||||
Strategy
|
||||
>::type,
|
||||
Strategy
|
||||
>,
|
||||
typename strategy::distance::services::comparable_type
|
||||
<
|
||||
typename detail::distance::default_strategy
|
||||
<
|
||||
typename point_type<Segment>::type,
|
||||
typename point_type<Box>::type
|
||||
>::type
|
||||
>::type,
|
||||
typename detail::distance::default_strategy
|
||||
<
|
||||
typename point_type<Segment>::type,
|
||||
typename point_type<Box>::type
|
||||
>::type
|
||||
>::type pp_strategy_type;
|
||||
|
||||
|
||||
return detail::distance::segment_to_box
|
||||
<
|
||||
Segment,
|
||||
Box,
|
||||
dimension<Segment>::value,
|
||||
pp_strategy_type,
|
||||
Strategy
|
||||
>::apply(segment, box, pp_strategy_type(), strategy);
|
||||
>::apply(segment, box, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2018 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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_AREAL_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_AREAL_HPP
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
struct envelope_polygon
|
||||
{
|
||||
template <typename Polygon, typename Box, typename Strategy>
|
||||
static inline void apply(Polygon const& polygon, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
typename ring_return_type<Polygon const>::type ext_ring
|
||||
= exterior_ring(polygon);
|
||||
|
||||
if (geometry::is_empty(ext_ring))
|
||||
{
|
||||
// if the exterior ring is empty, consider the interior rings
|
||||
envelope_multi_range
|
||||
<
|
||||
envelope_range
|
||||
>::apply(interior_rings(polygon), mbr, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, consider only the exterior ring
|
||||
envelope_range::apply(ext_ring, mbr, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct envelope<Ring, ring_tag>
|
||||
: detail::envelope::envelope_range
|
||||
{};
|
||||
|
||||
template <typename Polygon>
|
||||
struct envelope<Polygon, polygon_tag>
|
||||
: detail::envelope::envelope_polygon
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon>
|
||||
struct envelope<MultiPolygon, multi_polygon_tag>
|
||||
: detail::envelope::envelope_multi_range
|
||||
<
|
||||
detail::envelope::envelope_polygon
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_AREAL_HPP
|
||||
@@ -4,11 +4,12 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -17,151 +18,32 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/envelope_box.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_box.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Index,
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct envelope_indexed_box
|
||||
{
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
|
||||
{
|
||||
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
|
||||
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
|
||||
|
||||
detail::conversion::point_to_point
|
||||
<
|
||||
detail::indexed_point_view<BoxIn const, Index>,
|
||||
detail::indexed_point_view<BoxOut, Index>,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(box_in_corner, mbr_corner);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Index,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct envelope_indexed_box_on_spheroid
|
||||
{
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
|
||||
{
|
||||
// transform() does not work with boxes of dimension higher
|
||||
// than 2; to account for such boxes we transform the min/max
|
||||
// points of the boxes using the indexed_point_view
|
||||
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
|
||||
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
|
||||
|
||||
// first transform the units
|
||||
transform_units(box_in_corner, mbr_corner);
|
||||
|
||||
// now transform the remaining coordinates
|
||||
detail::conversion::point_to_point
|
||||
<
|
||||
detail::indexed_point_view<BoxIn const, Index>,
|
||||
detail::indexed_point_view<BoxOut, Index>,
|
||||
2,
|
||||
DimensionCount
|
||||
>::apply(box_in_corner, mbr_corner);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct envelope_box
|
||||
{
|
||||
template<typename BoxIn, typename BoxOut, typename Strategy>
|
||||
static inline void apply(BoxIn const& box_in,
|
||||
BoxOut& mbr,
|
||||
Strategy const&)
|
||||
{
|
||||
envelope_indexed_box
|
||||
<
|
||||
min_corner, 0, dimension<BoxIn>::value
|
||||
>::apply(box_in, mbr);
|
||||
|
||||
envelope_indexed_box
|
||||
<
|
||||
max_corner, 0, dimension<BoxIn>::value
|
||||
>::apply(box_in, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct envelope_box_on_spheroid
|
||||
{
|
||||
template <typename BoxIn, typename BoxOut, typename Strategy>
|
||||
static inline void apply(BoxIn const& box_in,
|
||||
BoxOut& mbr,
|
||||
Strategy const&)
|
||||
{
|
||||
BoxIn box_in_normalized = detail::return_normalized<BoxIn>(box_in);
|
||||
|
||||
envelope_indexed_box_on_spheroid
|
||||
<
|
||||
min_corner, dimension<BoxIn>::value
|
||||
>::apply(box_in_normalized, mbr);
|
||||
|
||||
envelope_indexed_box_on_spheroid
|
||||
<
|
||||
max_corner, dimension<BoxIn>::value
|
||||
>::apply(box_in_normalized, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Box, typename CS_Tag>
|
||||
struct envelope<Box, box_tag, CS_Tag>
|
||||
: detail::envelope::envelope_box
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct envelope<Box, box_tag, spherical_equatorial_tag>
|
||||
: detail::envelope::envelope_box_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct envelope<Box, box_tag, geographic_tag>
|
||||
: detail::envelope::envelope_box_on_spheroid
|
||||
{};
|
||||
struct envelope<Box, box_tag>
|
||||
{
|
||||
template<typename BoxIn, typename BoxOut, typename Strategy>
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& mbr, Strategy const& )
|
||||
{
|
||||
Strategy::apply(box_in, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/areal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>
|
||||
@@ -35,73 +36,4 @@
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
struct envelope_polygon
|
||||
{
|
||||
template <typename Polygon, typename Box, typename Strategy>
|
||||
static inline void apply(Polygon const& polygon, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
typename ring_return_type<Polygon const>::type ext_ring
|
||||
= exterior_ring(polygon);
|
||||
|
||||
if (geometry::is_empty(ext_ring))
|
||||
{
|
||||
// if the exterior ring is empty, consider the interior rings
|
||||
envelope_multi_range
|
||||
<
|
||||
envelope_range
|
||||
>::apply(interior_rings(polygon), mbr, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, consider only the exterior ring
|
||||
envelope_range::apply(ext_ring, mbr, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct envelope<Ring, ring_tag>
|
||||
: detail::envelope::envelope_range
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon>
|
||||
struct envelope<Polygon, polygon_tag>
|
||||
: detail::envelope::envelope_polygon
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPolygon>
|
||||
struct envelope<MultiPolygon, multi_polygon_tag>
|
||||
: detail::envelope::envelope_multi_range
|
||||
<
|
||||
detail::envelope::envelope_polygon
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_IMPLEMENTATION_HPP
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016, 2017.
|
||||
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
@@ -21,19 +21,24 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/envelope.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -57,13 +62,15 @@ struct envelope
|
||||
Box& box,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
typedef typename coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
typedef typename strategy::envelope::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type,
|
||||
coordinate_type
|
||||
typename tag<Geometry>::type,
|
||||
typename cs_tag<Geometry>::type,
|
||||
typename select_most_precise
|
||||
<
|
||||
typename coordinate_type<Geometry>::type,
|
||||
typename coordinate_type<Box>::type
|
||||
>::type
|
||||
>::type strategy_type;
|
||||
|
||||
dispatch::envelope<Geometry>::apply(geometry, box, strategy_type());
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2016, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -17,93 +18,40 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_LINEAR_HPP
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/segment_iterator.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/envelope.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope.hpp>
|
||||
#include <boost/geometry/strategies/geographic/envelope.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
struct envelope_linestring_on_spheroid
|
||||
{
|
||||
template <typename Linestring, typename Box, typename Strategy>
|
||||
static inline void apply(Linestring const& linestring,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
envelope_range::apply(geometry::segments_begin(linestring),
|
||||
geometry::segments_end(linestring),
|
||||
mbr,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Linestring, typename CS_Tag>
|
||||
struct envelope<Linestring, linestring_tag, CS_Tag>
|
||||
template <typename Linestring>
|
||||
struct envelope<Linestring, linestring_tag>
|
||||
: detail::envelope::envelope_range
|
||||
{};
|
||||
|
||||
template <typename Linestring>
|
||||
struct envelope<Linestring, linestring_tag, spherical_equatorial_tag>
|
||||
: detail::envelope::envelope_linestring_on_spheroid
|
||||
{};
|
||||
|
||||
template <typename Linestring>
|
||||
struct envelope<Linestring, linestring_tag, geographic_tag>
|
||||
: detail::envelope::envelope_linestring_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiLinestring, typename CS_Tag>
|
||||
struct envelope
|
||||
<
|
||||
MultiLinestring, multi_linestring_tag, CS_Tag
|
||||
> : detail::envelope::envelope_multi_range
|
||||
template <typename MultiLinestring>
|
||||
struct envelope<MultiLinestring, multi_linestring_tag>
|
||||
: detail::envelope::envelope_multi_range
|
||||
<
|
||||
detail::envelope::envelope_range
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct envelope
|
||||
<
|
||||
MultiLinestring, multi_linestring_tag, spherical_equatorial_tag
|
||||
> : detail::envelope::envelope_multi_range_on_spheroid
|
||||
<
|
||||
detail::envelope::envelope_linestring_on_spheroid
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct envelope
|
||||
<
|
||||
MultiLinestring, multi_linestring_tag, geographic_tag
|
||||
> : detail::envelope::envelope_multi_range_on_spheroid
|
||||
<
|
||||
detail::envelope::envelope_linestring_on_spheroid
|
||||
>
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -12,363 +13,32 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_MULTIPOINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/algorithm/minmax_element.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/helper_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand/point.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/envelope_multipoint.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_multipoint.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
class envelope_multipoint_on_spheroid
|
||||
{
|
||||
private:
|
||||
template <std::size_t Dim>
|
||||
struct coordinate_less
|
||||
{
|
||||
template <typename Point>
|
||||
inline bool operator()(Point const& point1, Point const& point2) const
|
||||
{
|
||||
return math::smaller(geometry::get<Dim>(point1),
|
||||
geometry::get<Dim>(point2));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Constants, typename MultiPoint, typename OutputIterator>
|
||||
static inline void analyze_point_coordinates(MultiPoint const& multipoint,
|
||||
bool& has_south_pole,
|
||||
bool& has_north_pole,
|
||||
OutputIterator oit)
|
||||
{
|
||||
typedef typename boost::range_value<MultiPoint>::type point_type;
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
MultiPoint const
|
||||
>::type iterator_type;
|
||||
|
||||
// analyze point coordinates:
|
||||
// (1) normalize point coordinates
|
||||
// (2) check if any point is the north or the south pole
|
||||
// (3) put all non-pole points in a container
|
||||
//
|
||||
// notice that at this point in the algorithm, we have at
|
||||
// least two points on the spheroid
|
||||
has_south_pole = false;
|
||||
has_north_pole = false;
|
||||
|
||||
for (iterator_type it = boost::begin(multipoint);
|
||||
it != boost::end(multipoint);
|
||||
++it)
|
||||
{
|
||||
point_type point = detail::return_normalized<point_type>(*it);
|
||||
|
||||
if (math::equals(geometry::get<1>(point),
|
||||
Constants::min_latitude()))
|
||||
{
|
||||
has_south_pole = true;
|
||||
}
|
||||
else if (math::equals(geometry::get<1>(point),
|
||||
Constants::max_latitude()))
|
||||
{
|
||||
has_north_pole = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
*oit++ = point;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SortedRange, typename Value>
|
||||
static inline Value maximum_gap(SortedRange const& sorted_range,
|
||||
Value& max_gap_left,
|
||||
Value& max_gap_right)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
SortedRange const
|
||||
>::type iterator_type;
|
||||
|
||||
iterator_type it1 = boost::begin(sorted_range), it2 = it1;
|
||||
++it2;
|
||||
max_gap_left = geometry::get<0>(*it1);
|
||||
max_gap_right = geometry::get<0>(*it2);
|
||||
|
||||
Value max_gap = max_gap_right - max_gap_left;
|
||||
for (++it1, ++it2; it2 != boost::end(sorted_range); ++it1, ++it2)
|
||||
{
|
||||
Value gap = geometry::get<0>(*it2) - geometry::get<0>(*it1);
|
||||
if (math::larger(gap, max_gap))
|
||||
{
|
||||
max_gap_left = geometry::get<0>(*it1);
|
||||
max_gap_right = geometry::get<0>(*it2);
|
||||
max_gap = gap;
|
||||
}
|
||||
}
|
||||
|
||||
return max_gap;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Constants,
|
||||
typename PointRange,
|
||||
typename LongitudeLess,
|
||||
typename CoordinateType
|
||||
>
|
||||
static inline void get_min_max_longitudes(PointRange& range,
|
||||
LongitudeLess const& lon_less,
|
||||
CoordinateType& lon_min,
|
||||
CoordinateType& lon_max)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
PointRange const
|
||||
>::type iterator_type;
|
||||
|
||||
// compute min and max longitude values
|
||||
std::pair<iterator_type, iterator_type> min_max_longitudes
|
||||
= boost::minmax_element(boost::begin(range),
|
||||
boost::end(range),
|
||||
lon_less);
|
||||
|
||||
lon_min = geometry::get<0>(*min_max_longitudes.first);
|
||||
lon_max = geometry::get<0>(*min_max_longitudes.second);
|
||||
|
||||
// if the longitude span is "large" compute the true maximum gap
|
||||
if (math::larger(lon_max - lon_min, Constants::half_period()))
|
||||
{
|
||||
std::sort(boost::begin(range), boost::end(range), lon_less);
|
||||
|
||||
CoordinateType max_gap_left = 0, max_gap_right = 0;
|
||||
CoordinateType max_gap
|
||||
= maximum_gap(range, max_gap_left, max_gap_right);
|
||||
|
||||
CoordinateType complement_gap
|
||||
= Constants::period() + lon_min - lon_max;
|
||||
|
||||
if (math::larger(max_gap, complement_gap))
|
||||
{
|
||||
lon_min = max_gap_right;
|
||||
lon_max = max_gap_left + Constants::period();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Constants,
|
||||
typename Iterator,
|
||||
typename LatitudeLess,
|
||||
typename CoordinateType
|
||||
>
|
||||
static inline void get_min_max_latitudes(Iterator const first,
|
||||
Iterator const last,
|
||||
LatitudeLess const& lat_less,
|
||||
bool has_south_pole,
|
||||
bool has_north_pole,
|
||||
CoordinateType& lat_min,
|
||||
CoordinateType& lat_max)
|
||||
{
|
||||
if (has_south_pole && has_north_pole)
|
||||
{
|
||||
lat_min = Constants::min_latitude();
|
||||
lat_max = Constants::max_latitude();
|
||||
}
|
||||
else if (has_south_pole)
|
||||
{
|
||||
lat_min = Constants::min_latitude();
|
||||
lat_max
|
||||
= geometry::get<1>(*std::max_element(first, last, lat_less));
|
||||
}
|
||||
else if (has_north_pole)
|
||||
{
|
||||
lat_min
|
||||
= geometry::get<1>(*std::min_element(first, last, lat_less));
|
||||
lat_max = Constants::max_latitude();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::pair<Iterator, Iterator> min_max_latitudes
|
||||
= boost::minmax_element(first, last, lat_less);
|
||||
|
||||
lat_min = geometry::get<1>(*min_max_latitudes.first);
|
||||
lat_max = geometry::get<1>(*min_max_latitudes.second);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename MultiPoint, typename Box, typename Strategy>
|
||||
static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<MultiPoint>::type point_type;
|
||||
typedef typename coordinate_type<MultiPoint>::type coordinate_type;
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
MultiPoint const
|
||||
>::type iterator_type;
|
||||
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
coordinate_type,
|
||||
typename coordinate_system<MultiPoint>::type::units
|
||||
> constants;
|
||||
|
||||
if (boost::empty(multipoint))
|
||||
{
|
||||
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
|
||||
return;
|
||||
}
|
||||
|
||||
initialize<Box, 0, 2>::apply(mbr);
|
||||
|
||||
if (boost::size(multipoint) == 1)
|
||||
{
|
||||
return dispatch::envelope
|
||||
<
|
||||
typename boost::range_value<MultiPoint>::type
|
||||
>::apply(range::front(multipoint), mbr, strategy);
|
||||
}
|
||||
|
||||
// analyze the points and put the non-pole ones in the
|
||||
// points vector
|
||||
std::vector<point_type> points;
|
||||
bool has_north_pole = false, has_south_pole = false;
|
||||
|
||||
analyze_point_coordinates<constants>(multipoint,
|
||||
has_south_pole, has_north_pole,
|
||||
std::back_inserter(points));
|
||||
|
||||
coordinate_type lon_min, lat_min, lon_max, lat_max;
|
||||
if (points.size() == 1)
|
||||
{
|
||||
// we have one non-pole point and at least one pole point
|
||||
lon_min = geometry::get<0>(range::front(points));
|
||||
lon_max = geometry::get<0>(range::front(points));
|
||||
lat_min = has_south_pole
|
||||
? constants::min_latitude()
|
||||
: constants::max_latitude();
|
||||
lat_max = has_north_pole
|
||||
? constants::max_latitude()
|
||||
: constants::min_latitude();
|
||||
}
|
||||
else if (points.empty())
|
||||
{
|
||||
// all points are pole points
|
||||
BOOST_GEOMETRY_ASSERT(has_south_pole || has_north_pole);
|
||||
lon_min = coordinate_type(0);
|
||||
lon_max = coordinate_type(0);
|
||||
lat_min = has_south_pole
|
||||
? constants::min_latitude()
|
||||
: constants::max_latitude();
|
||||
lat_max = (has_north_pole)
|
||||
? constants::max_latitude()
|
||||
: constants::min_latitude();
|
||||
}
|
||||
else
|
||||
{
|
||||
get_min_max_longitudes<constants>(points,
|
||||
coordinate_less<0>(),
|
||||
lon_min,
|
||||
lon_max);
|
||||
|
||||
get_min_max_latitudes<constants>(points.begin(),
|
||||
points.end(),
|
||||
coordinate_less<1>(),
|
||||
has_south_pole,
|
||||
has_north_pole,
|
||||
lat_min,
|
||||
lat_max);
|
||||
}
|
||||
|
||||
typedef typename helper_geometry
|
||||
<
|
||||
Box,
|
||||
coordinate_type,
|
||||
typename coordinate_system<MultiPoint>::type::units
|
||||
>::type helper_box_type;
|
||||
|
||||
helper_box_type helper_mbr;
|
||||
|
||||
geometry::set<min_corner, 0>(helper_mbr, lon_min);
|
||||
geometry::set<min_corner, 1>(helper_mbr, lat_min);
|
||||
geometry::set<max_corner, 0>(helper_mbr, lon_max);
|
||||
geometry::set<max_corner, 1>(helper_mbr, lat_max);
|
||||
|
||||
// now transform to output MBR (per index)
|
||||
envelope_indexed_box_on_spheroid<min_corner, 2>::apply(helper_mbr, mbr);
|
||||
envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr);
|
||||
|
||||
// compute envelope for higher coordinates
|
||||
iterator_type it = boost::begin(multipoint);
|
||||
envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr, strategy);
|
||||
|
||||
for (++it; it != boost::end(multipoint); ++it)
|
||||
{
|
||||
detail::expand::point_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
2, dimension<Box>::value
|
||||
>::apply(mbr, *it, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiPoint, typename CSTag>
|
||||
struct envelope<MultiPoint, multi_point_tag, CSTag>
|
||||
: detail::envelope::envelope_range
|
||||
{};
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct envelope<MultiPoint, multi_point_tag, spherical_equatorial_tag>
|
||||
: detail::envelope::envelope_multipoint_on_spheroid
|
||||
{};
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct envelope<MultiPoint, multi_point_tag, geographic_tag>
|
||||
: detail::envelope::envelope_multipoint_on_spheroid
|
||||
{};
|
||||
struct envelope<MultiPoint, multi_point_tag>
|
||||
{
|
||||
template <typename Box, typename Strategy>
|
||||
static inline void apply(MultiPoint const& multipoint, Box& mbr, Strategy const& )
|
||||
{
|
||||
Strategy::apply(multipoint, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -17,23 +18,14 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_POINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/envelope_point.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_point.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -43,53 +35,12 @@ namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct envelope_one_point
|
||||
struct envelope_point
|
||||
{
|
||||
template <std::size_t Index, typename Point, typename Box>
|
||||
static inline void apply(Point const& point, Box& mbr)
|
||||
{
|
||||
detail::indexed_point_view<Box, Index> box_corner(mbr);
|
||||
detail::conversion::point_to_point
|
||||
<
|
||||
Point,
|
||||
detail::indexed_point_view<Box, Index>,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(point, box_corner);
|
||||
}
|
||||
|
||||
template <typename Point, typename Box, typename Strategy>
|
||||
static inline void apply(Point const& point, Box& mbr, Strategy const&)
|
||||
static inline void apply(Point const& point, Box& mbr, Strategy const& )
|
||||
{
|
||||
apply<min_corner>(point, mbr);
|
||||
apply<max_corner>(point, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct envelope_point_on_spheroid
|
||||
{
|
||||
template<typename Point, typename Box, typename Strategy>
|
||||
static inline void apply(Point const& point, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
Point normalized_point = detail::return_normalized<Point>(point);
|
||||
|
||||
typename point_type<Box>::type box_point;
|
||||
|
||||
// transform units of input point to units of a box point
|
||||
transform_units(normalized_point, box_point);
|
||||
|
||||
geometry::set<min_corner, 0>(mbr, geometry::get<0>(box_point));
|
||||
geometry::set<min_corner, 1>(mbr, geometry::get<1>(box_point));
|
||||
|
||||
geometry::set<max_corner, 0>(mbr, geometry::get<0>(box_point));
|
||||
geometry::set<max_corner, 1>(mbr, geometry::get<1>(box_point));
|
||||
|
||||
envelope_one_point
|
||||
<
|
||||
2, dimension<Point>::value
|
||||
>::apply(normalized_point, mbr, strategy);
|
||||
Strategy::apply(point, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -102,21 +53,9 @@ namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Point, typename CS_Tag>
|
||||
struct envelope<Point, point_tag, CS_Tag>
|
||||
: detail::envelope::envelope_one_point<0, dimension<Point>::value>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct envelope<Point, point_tag, spherical_equatorial_tag>
|
||||
: detail::envelope::envelope_point_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct envelope<Point, point_tag, geographic_tag>
|
||||
: detail::envelope::envelope_point_on_spheroid
|
||||
struct envelope<Point, point_tag>
|
||||
: detail::envelope::envelope_point
|
||||
{};
|
||||
|
||||
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2016, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// 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.
|
||||
@@ -23,23 +24,17 @@
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/is_empty.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand/point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand/segment.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -53,7 +48,7 @@ namespace detail { namespace envelope
|
||||
struct envelope_range
|
||||
{
|
||||
template <typename Iterator, typename Box, typename Strategy>
|
||||
static inline void apply(Iterator first,
|
||||
static inline void apply(Iterator it,
|
||||
Iterator last,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
@@ -63,16 +58,21 @@ struct envelope_range
|
||||
// initialize MBR
|
||||
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
|
||||
|
||||
Iterator it = first;
|
||||
if (it != last)
|
||||
{
|
||||
// initialize box with first element in range
|
||||
dispatch::envelope<value_type>::apply(*it, mbr, strategy);
|
||||
dispatch::envelope
|
||||
<
|
||||
value_type
|
||||
>::apply(*it, mbr, strategy.get_element_envelope_strategy());
|
||||
|
||||
// consider now the remaining elements in the range (if any)
|
||||
for (++it; it != last; ++it)
|
||||
{
|
||||
dispatch::expand<Box, value_type>::apply(mbr, *it, strategy);
|
||||
dispatch::expand
|
||||
<
|
||||
Box, value_type
|
||||
>::apply(mbr, *it, strategy.get_element_expand_strategy());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ struct envelope_range
|
||||
template <typename Range, typename Box, typename Strategy>
|
||||
static inline void apply(Range const& range, Box& mbr, Strategy const& strategy)
|
||||
{
|
||||
return apply(boost::begin(range), boost::end(range), mbr, strategy);
|
||||
return apply(Strategy::begin(range), Strategy::end(range), mbr, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -94,86 +94,26 @@ struct envelope_multi_range
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
MultiRange const
|
||||
>::type iterator_type;
|
||||
|
||||
bool initialized = false;
|
||||
for (iterator_type it = boost::begin(multirange);
|
||||
it != boost::end(multirange);
|
||||
++it)
|
||||
{
|
||||
if (! geometry::is_empty(*it))
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
Box helper_mbr;
|
||||
EnvelopePolicy::apply(*it, helper_mbr, strategy);
|
||||
|
||||
dispatch::expand<Box, Box>::apply(mbr, helper_mbr, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compute the initial envelope
|
||||
EnvelopePolicy::apply(*it, mbr, strategy);
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! initialized)
|
||||
{
|
||||
// if not already initialized, initialize MBR
|
||||
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
|
||||
}
|
||||
apply(boost::begin(multirange), boost::end(multirange), mbr, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// implementation for multi-range on a spheroid (longitude is periodic)
|
||||
template <typename EnvelopePolicy>
|
||||
struct envelope_multi_range_on_spheroid
|
||||
{
|
||||
template <typename MultiRange, typename Box, typename Strategy>
|
||||
static inline void apply(MultiRange const& multirange,
|
||||
template <typename Iter, typename Box, typename Strategy>
|
||||
static inline void apply(Iter it,
|
||||
Iter last,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
MultiRange const
|
||||
>::type iterator_type;
|
||||
|
||||
// due to the periodicity of longitudes we need to compute the boxes
|
||||
// of all the single geometries and keep them in a container
|
||||
std::vector<Box> boxes;
|
||||
for (iterator_type it = boost::begin(multirange);
|
||||
it != boost::end(multirange);
|
||||
++it)
|
||||
typename Strategy::template multi_state<Box> state;
|
||||
for (; it != last; ++it)
|
||||
{
|
||||
if (! geometry::is_empty(*it))
|
||||
{
|
||||
Box helper_box;
|
||||
EnvelopePolicy::apply(*it, helper_box, strategy);
|
||||
boxes.push_back(helper_box);
|
||||
Box helper_mbr;
|
||||
EnvelopePolicy::apply(*it, helper_mbr, strategy);
|
||||
state.apply(helper_mbr);
|
||||
}
|
||||
}
|
||||
|
||||
// now we need to compute the envelope of the range of boxes
|
||||
// (cannot be done in an incremental fashion as in the
|
||||
// Cartesian coordinate system)
|
||||
// if all single geometries are empty no boxes have been found
|
||||
// and the MBR is simply initialized
|
||||
if (! boxes.empty())
|
||||
{
|
||||
envelope_range_of_boxes::apply(boxes, mbr, strategy);
|
||||
}
|
||||
else
|
||||
{
|
||||
initialize<Box, 0, dimension<Box>::value>::apply(mbr);
|
||||
}
|
||||
|
||||
state.result(mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -19,17 +20,20 @@
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/max_interval_gap.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/max_interval_gap.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -150,10 +154,8 @@ struct envelope_range_of_longitudes
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct envelope_range_of_boxes_by_expansion
|
||||
{
|
||||
template <typename RangeOfBoxes, typename Box, typename Strategy>
|
||||
static inline void apply(RangeOfBoxes const& range_of_boxes,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
template <typename RangeOfBoxes, typename Box>
|
||||
static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)
|
||||
{
|
||||
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
|
||||
|
||||
@@ -194,21 +196,17 @@ struct envelope_range_of_boxes_by_expansion
|
||||
{
|
||||
detail::expand::indexed_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
min_corner,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(mbr, *it, strategy);
|
||||
>::apply(mbr, *it);
|
||||
|
||||
detail::expand::indexed_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
max_corner,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(mbr, *it, strategy);
|
||||
>::apply(mbr, *it);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,24 +226,28 @@ struct envelope_range_of_boxes
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RangeOfBoxes, typename Box, typename Strategy>
|
||||
static inline void apply(RangeOfBoxes const& range_of_boxes,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
template <typename RangeOfBoxes, typename Box>
|
||||
static inline void apply(RangeOfBoxes const& range_of_boxes, Box& mbr)
|
||||
{
|
||||
// boxes in the range are assumed to be normalized already
|
||||
|
||||
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
|
||||
typedef typename coordinate_type<box_type>::type coordinate_type;
|
||||
typedef typename coordinate_system<box_type>::type::units units_type;
|
||||
typedef typename detail::cs_angular_units<box_type>::type units_type;
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
RangeOfBoxes const
|
||||
>::type iterator_type;
|
||||
|
||||
static const bool is_equatorial = ! boost::is_same
|
||||
<
|
||||
typename cs_tag<box_type>::type,
|
||||
spherical_polar_tag
|
||||
>::value;
|
||||
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
coordinate_type, units_type
|
||||
coordinate_type, units_type, is_equatorial
|
||||
> constants;
|
||||
|
||||
typedef longitude_interval<coordinate_type> interval_type;
|
||||
@@ -269,6 +271,11 @@ struct envelope_range_of_boxes
|
||||
it != boost::end(range_of_boxes);
|
||||
++it)
|
||||
{
|
||||
if (is_inverse_spheroidal_coordinates(*it))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
coordinate_type lat_min = geometry::get<min_corner, 1>(*it);
|
||||
coordinate_type lat_max = geometry::get<max_corner, 1>(*it);
|
||||
if (math::equals(lat_min, constants::max_latitude())
|
||||
@@ -318,7 +325,7 @@ struct envelope_range_of_boxes
|
||||
envelope_range_of_boxes_by_expansion
|
||||
<
|
||||
2, dimension<Box>::value
|
||||
>::apply(range_of_boxes, mbr, strategy);
|
||||
>::apply(range_of_boxes, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015-2017.
|
||||
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
@@ -19,34 +19,17 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_SEGMENT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/srs.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/helper_geometry.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/vertex_latitude.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand/point.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -54,275 +37,6 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
template <typename CalculationType, typename CS_Tag>
|
||||
struct envelope_segment_call_vertex_latitude
|
||||
{
|
||||
template <typename T1, typename T2, typename Strategy>
|
||||
static inline CalculationType apply(T1 const& lat1,
|
||||
T2 const& alp1,
|
||||
Strategy const& )
|
||||
{
|
||||
return geometry::formula::vertex_latitude<CalculationType, CS_Tag>
|
||||
::apply(lat1, alp1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CalculationType>
|
||||
struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag>
|
||||
{
|
||||
template <typename T1, typename T2, typename Strategy>
|
||||
static inline CalculationType apply(T1 const& lat1,
|
||||
T2 const& alp1,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return geometry::formula::vertex_latitude<CalculationType, geographic_tag>
|
||||
::apply(lat1, alp1, strategy.model());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CS_Tag>
|
||||
class envelope_segment_impl
|
||||
{
|
||||
private:
|
||||
|
||||
// degrees or radians
|
||||
template <typename CalculationType>
|
||||
static inline void swap(CalculationType& lon1,
|
||||
CalculationType& lat1,
|
||||
CalculationType& lon2,
|
||||
CalculationType& lat2)
|
||||
{
|
||||
std::swap(lon1, lon2);
|
||||
std::swap(lat1, lat2);
|
||||
}
|
||||
|
||||
// radians
|
||||
template <typename CalculationType>
|
||||
static inline bool contains_pi_half(CalculationType const& a1,
|
||||
CalculationType const& a2)
|
||||
{
|
||||
// azimuths a1 and a2 are assumed to be in radians
|
||||
BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2));
|
||||
|
||||
static CalculationType const pi_half = math::half_pi<CalculationType>();
|
||||
|
||||
return (a1 < a2)
|
||||
? (a1 < pi_half && pi_half < a2)
|
||||
: (a1 > pi_half && pi_half > a2);
|
||||
}
|
||||
|
||||
// radians or degrees
|
||||
template <typename Units, typename CoordinateType>
|
||||
static inline bool crosses_antimeridian(CoordinateType const& lon1,
|
||||
CoordinateType const& lon2)
|
||||
{
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
CoordinateType, Units
|
||||
> constants;
|
||||
|
||||
return math::abs(lon1 - lon2) > constants::half_period(); // > pi
|
||||
}
|
||||
|
||||
// degrees or radians
|
||||
template <typename Units, typename CalculationType, typename Strategy>
|
||||
static inline void compute_box_corners(CalculationType& lon1,
|
||||
CalculationType& lat1,
|
||||
CalculationType& lon2,
|
||||
CalculationType& lat2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// coordinates are assumed to be in radians
|
||||
BOOST_GEOMETRY_ASSERT(lon1 <= lon2);
|
||||
|
||||
CalculationType lon1_rad = math::as_radian<Units>(lon1);
|
||||
CalculationType lat1_rad = math::as_radian<Units>(lat1);
|
||||
CalculationType lon2_rad = math::as_radian<Units>(lon2);
|
||||
CalculationType lat2_rad = math::as_radian<Units>(lat2);
|
||||
|
||||
CalculationType a1, a2;
|
||||
strategy.apply(lon1_rad, lat1_rad, lon2_rad, lat2_rad, a1, a2);
|
||||
|
||||
if (lat1 > lat2)
|
||||
{
|
||||
std::swap(lat1, lat2);
|
||||
std::swap(lat1_rad, lat2_rad);
|
||||
std::swap(a1, a2);
|
||||
}
|
||||
|
||||
if (math::equals(a1, a2))
|
||||
{
|
||||
// the segment must lie on the equator or is very short
|
||||
return;
|
||||
}
|
||||
|
||||
if (contains_pi_half(a1, a2))
|
||||
{
|
||||
CalculationType p_max = envelope_segment_call_vertex_latitude
|
||||
<CalculationType, CS_Tag>::apply(lat1_rad, a1, strategy);
|
||||
|
||||
CalculationType const mid_lat = lat1 + lat2;
|
||||
if (mid_lat < 0)
|
||||
{
|
||||
// update using min latitude
|
||||
CalculationType const lat_min_rad = -p_max;
|
||||
CalculationType const lat_min
|
||||
= math::from_radian<Units>(lat_min_rad);
|
||||
|
||||
if (lat1 > lat_min)
|
||||
{
|
||||
lat1 = lat_min;
|
||||
}
|
||||
}
|
||||
else if (mid_lat > 0)
|
||||
{
|
||||
// update using max latitude
|
||||
CalculationType const lat_max_rad = p_max;
|
||||
CalculationType const lat_max
|
||||
= math::from_radian<Units>(lat_max_rad);
|
||||
|
||||
if (lat2 < lat_max)
|
||||
{
|
||||
lat2 = lat_max;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Units, typename CalculationType, typename Strategy>
|
||||
static inline void apply(CalculationType& lon1,
|
||||
CalculationType& lat1,
|
||||
CalculationType& lon2,
|
||||
CalculationType& lat2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
CalculationType, Units
|
||||
> constants;
|
||||
|
||||
bool is_pole1 = math::equals(math::abs(lat1), constants::max_latitude());
|
||||
bool is_pole2 = math::equals(math::abs(lat2), constants::max_latitude());
|
||||
|
||||
if (is_pole1 && is_pole2)
|
||||
{
|
||||
// both points are poles; nothing more to do:
|
||||
// longitudes are already normalized to 0
|
||||
// but just in case
|
||||
lon1 = 0;
|
||||
lon2 = 0;
|
||||
}
|
||||
else if (is_pole1 && !is_pole2)
|
||||
{
|
||||
// first point is a pole, second point is not:
|
||||
// make the longitude of the first point the same as that
|
||||
// of the second point
|
||||
lon1 = lon2;
|
||||
}
|
||||
else if (!is_pole1 && is_pole2)
|
||||
{
|
||||
// second point is a pole, first point is not:
|
||||
// make the longitude of the second point the same as that
|
||||
// of the first point
|
||||
lon2 = lon1;
|
||||
}
|
||||
|
||||
if (lon1 == lon2)
|
||||
{
|
||||
// segment lies on a meridian
|
||||
if (lat1 > lat2)
|
||||
{
|
||||
std::swap(lat1, lat2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(!is_pole1 && !is_pole2);
|
||||
|
||||
if (lon1 > lon2)
|
||||
{
|
||||
swap(lon1, lat1, lon2, lat2);
|
||||
}
|
||||
|
||||
if (crosses_antimeridian<Units>(lon1, lon2))
|
||||
{
|
||||
lon1 += constants::period();
|
||||
swap(lon1, lat1, lon2, lat2);
|
||||
}
|
||||
|
||||
compute_box_corners<Units>(lon1, lat1, lon2, lat2, strategy);
|
||||
}
|
||||
|
||||
public:
|
||||
template <
|
||||
typename Units,
|
||||
typename CalculationType,
|
||||
typename Box,
|
||||
typename Strategy
|
||||
>
|
||||
static inline void apply(CalculationType lon1,
|
||||
CalculationType lat1,
|
||||
CalculationType lon2,
|
||||
CalculationType lat2,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename coordinate_type<Box>::type box_coordinate_type;
|
||||
|
||||
typedef typename helper_geometry
|
||||
<
|
||||
Box, box_coordinate_type, Units
|
||||
>::type helper_box_type;
|
||||
|
||||
helper_box_type radian_mbr;
|
||||
|
||||
apply<Units>(lon1, lat1, lon2, lat2, strategy);
|
||||
|
||||
geometry::set
|
||||
<
|
||||
min_corner, 0
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon1));
|
||||
|
||||
geometry::set
|
||||
<
|
||||
min_corner, 1
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat1));
|
||||
|
||||
geometry::set
|
||||
<
|
||||
max_corner, 0
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon2));
|
||||
|
||||
geometry::set
|
||||
<
|
||||
max_corner, 1
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat2));
|
||||
|
||||
transform_units(radian_mbr, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct envelope_one_segment
|
||||
{
|
||||
template<typename Point, typename Box, typename Strategy>
|
||||
static inline void apply(Point const& p1,
|
||||
Point const& p2,
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
envelope_one_point<Dimension, DimensionCount>::apply(p1, mbr, strategy);
|
||||
detail::expand::point_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(mbr, p2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <std::size_t DimensionCount>
|
||||
struct envelope_segment
|
||||
{
|
||||
@@ -332,21 +46,17 @@ struct envelope_segment
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// first compute the envelope range for the first two coordinates
|
||||
strategy.apply(p1, p2, mbr);
|
||||
|
||||
// now compute the envelope range for coordinates of
|
||||
// dimension 2 and higher
|
||||
envelope_one_segment<2, DimensionCount>::apply(p1, p2, mbr, strategy);
|
||||
}
|
||||
|
||||
template <typename Segment, typename Box>
|
||||
static inline void apply(Segment const& segment, Box& mbr)
|
||||
template <typename Segment, typename Box, typename Strategy>
|
||||
static inline void apply(Segment const& segment, Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typename point_type<Segment>::type p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
apply(p[0], p[1], mbr);
|
||||
apply(p[0], p[1], mbr, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,401 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2015, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, 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.
|
||||
|
||||
// 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_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
|
||||
// For trivial checks
|
||||
#include <boost/geometry/algorithms/area.hpp>
|
||||
#include <boost/geometry/algorithms/length.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
|
||||
#include <boost/geometry/algorithms/relate.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace equals
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct point_point
|
||||
{
|
||||
template <typename Point1, typename Point2, typename Strategy>
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& )
|
||||
{
|
||||
return Strategy::apply(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct box_box
|
||||
{
|
||||
template <typename Box1, typename Box2, typename Strategy>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
|
||||
{
|
||||
if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
|
||||
|| !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t DimensionCount>
|
||||
struct box_box<DimensionCount, DimensionCount>
|
||||
{
|
||||
template <typename Box1, typename Box2, typename Strategy>
|
||||
static inline bool apply(Box1 const& , Box2 const& , Strategy const& )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct segment_segment
|
||||
{
|
||||
template <typename Segment1, typename Segment2, typename Strategy>
|
||||
static inline bool apply(Segment1 const& segment1, Segment2 const& segment2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typename Strategy::point_in_point_strategy_type const&
|
||||
pt_pt_strategy = strategy.get_point_in_point_strategy();
|
||||
|
||||
return equals::equals_point_point(
|
||||
indexed_point_view<Segment1 const, 0>(segment1),
|
||||
indexed_point_view<Segment2 const, 0>(segment2),
|
||||
pt_pt_strategy)
|
||||
? equals::equals_point_point(
|
||||
indexed_point_view<Segment1 const, 1>(segment1),
|
||||
indexed_point_view<Segment2 const, 1>(segment2),
|
||||
pt_pt_strategy)
|
||||
: ( equals::equals_point_point(
|
||||
indexed_point_view<Segment1 const, 0>(segment1),
|
||||
indexed_point_view<Segment2 const, 1>(segment2),
|
||||
pt_pt_strategy)
|
||||
&& equals::equals_point_point(
|
||||
indexed_point_view<Segment1 const, 1>(segment1),
|
||||
indexed_point_view<Segment2 const, 0>(segment2),
|
||||
pt_pt_strategy)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct area_check
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return geometry::math::equals(
|
||||
geometry::area(geometry1,
|
||||
strategy.template get_area_strategy<Geometry1>()),
|
||||
geometry::area(geometry2,
|
||||
strategy.template get_area_strategy<Geometry2>()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct length_check
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return geometry::math::equals(
|
||||
geometry::length(geometry1,
|
||||
strategy.template get_distance_strategy<Geometry1>()),
|
||||
geometry::length(geometry2,
|
||||
strategy.template get_distance_strategy<Geometry2>()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename IntersectionStrategy>
|
||||
struct collected_vector
|
||||
{
|
||||
typedef typename geometry::select_most_precise
|
||||
<
|
||||
typename select_coordinate_type
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type,
|
||||
double
|
||||
>::type calculation_type;
|
||||
|
||||
typedef geometry::collected_vector
|
||||
<
|
||||
calculation_type,
|
||||
Geometry1,
|
||||
typename IntersectionStrategy::side_strategy_type
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename TrivialCheck>
|
||||
struct equals_by_collection
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (! TrivialCheck::apply(geometry1, geometry2, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef typename collected_vector
|
||||
<
|
||||
Geometry1, Geometry2, Strategy
|
||||
>::type collected_vector_type;
|
||||
|
||||
std::vector<collected_vector_type> c1, c2;
|
||||
|
||||
geometry::collect_vectors(c1, geometry1);
|
||||
geometry::collect_vectors(c2, geometry2);
|
||||
|
||||
if (boost::size(c1) != boost::size(c2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::sort(c1.begin(), c1.end());
|
||||
std::sort(c2.begin(), c2.end());
|
||||
|
||||
// Just check if these vectors are equal.
|
||||
return std::equal(c1.begin(), c1.end(), c2.begin());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Geometry1, typename Geometry2>
|
||||
struct equals_by_relate
|
||||
: detail::relate::relate_impl
|
||||
<
|
||||
detail::de9im::static_mask_equals_type,
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>
|
||||
{};
|
||||
|
||||
// If collect_vectors which is a SideStrategy-dispatched optimization
|
||||
// is implemented in a way consistent with the Intersection/Side Strategy
|
||||
// then collect_vectors is used, otherwise relate is used.
|
||||
// NOTE: the result could be conceptually different for invalid
|
||||
// geometries in different coordinate systems because collect_vectors
|
||||
// and relate treat invalid geometries differently.
|
||||
template<typename TrivialCheck>
|
||||
struct equals_by_collection_or_relate
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::is_base_of
|
||||
<
|
||||
nyi::not_implemented_tag,
|
||||
typename collected_vector
|
||||
<
|
||||
Geometry1, Geometry2, Strategy
|
||||
>::type
|
||||
>::type enable_relate_type;
|
||||
|
||||
return apply(geometry1, geometry2, strategy, enable_relate_type());
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy,
|
||||
boost::false_type /*enable_relate*/)
|
||||
{
|
||||
return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy,
|
||||
boost::true_type /*enable_relate*/)
|
||||
{
|
||||
return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::equals
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
|
||||
struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
|
||||
: detail::equals::point_point<0, DimensionCount>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
|
||||
struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
|
||||
: detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
|
||||
{};
|
||||
|
||||
template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
|
||||
struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
|
||||
: detail::equals::equals_by_relate<Point, MultiPoint>
|
||||
{};
|
||||
|
||||
template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
|
||||
struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
|
||||
: detail::equals::box_box<0, DimensionCount>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Ring1, typename Ring2, bool Reverse>
|
||||
struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
|
||||
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon1, typename Polygon2, bool Reverse>
|
||||
struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
|
||||
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon, typename Ring, bool Reverse>
|
||||
struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
|
||||
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Ring, typename Box, bool Reverse>
|
||||
struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
|
||||
: detail::equals::equals_by_collection<detail::equals::area_check>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon, typename Box, bool Reverse>
|
||||
struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
|
||||
: detail::equals::equals_by_collection<detail::equals::area_check>
|
||||
{};
|
||||
|
||||
template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
|
||||
struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>
|
||||
: detail::equals::segment_segment
|
||||
{};
|
||||
|
||||
template <typename LineString1, typename LineString2, bool Reverse>
|
||||
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
|
||||
: detail::equals::equals_by_relate<LineString1, LineString2>
|
||||
{};
|
||||
|
||||
template <typename LineString, typename MultiLineString, bool Reverse>
|
||||
struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>
|
||||
: detail::equals::equals_by_relate<LineString, MultiLineString>
|
||||
{};
|
||||
|
||||
template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
|
||||
struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>
|
||||
: detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
|
||||
{};
|
||||
|
||||
|
||||
template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
|
||||
struct equals
|
||||
<
|
||||
MultiPolygon1, MultiPolygon2,
|
||||
multi_polygon_tag, multi_polygon_tag,
|
||||
2,
|
||||
Reverse
|
||||
>
|
||||
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Polygon, typename MultiPolygon, bool Reverse>
|
||||
struct equals
|
||||
<
|
||||
Polygon, MultiPolygon,
|
||||
polygon_tag, multi_polygon_tag,
|
||||
2,
|
||||
Reverse
|
||||
>
|
||||
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon, typename Ring, bool Reverse>
|
||||
struct equals
|
||||
<
|
||||
MultiPolygon, Ring,
|
||||
multi_polygon_tag, ring_tag,
|
||||
2,
|
||||
Reverse
|
||||
>
|
||||
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2015, 2016, 2017.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, 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.
|
||||
|
||||
// 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_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/reverse_dispatch.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/relate.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag2 = typename tag<Geometry2>::type,
|
||||
std::size_t DimensionCount = dimension<Geometry1>::type::value,
|
||||
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
|
||||
>
|
||||
struct equals: not_implemented<Tag1, Tag2>
|
||||
{};
|
||||
|
||||
|
||||
// If reversal is needed, perform it
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename Tag1, typename Tag2,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
|
||||
: equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
|
||||
{
|
||||
return equals
|
||||
<
|
||||
Geometry2, Geometry1,
|
||||
Tag2, Tag1,
|
||||
DimensionCount,
|
||||
false
|
||||
>::apply(g2, g1, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_strategy
|
||||
{
|
||||
|
||||
struct equals
|
||||
{
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return dispatch::equals
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename strategy::relate::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::equals
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_strategy
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct equals
|
||||
{
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check_concepts_and_equal_dimensions
|
||||
<
|
||||
Geometry1 const,
|
||||
Geometry2 const
|
||||
>();
|
||||
|
||||
return resolve_strategy::equals
|
||||
::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
||||
struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
Geometry2 const& m_geometry2;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry2 const& geometry2, Strategy const& strategy)
|
||||
: m_geometry2(geometry2)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1>
|
||||
inline bool operator()(Geometry1 const& geometry1) const
|
||||
{
|
||||
return equals<Geometry1, Geometry2>
|
||||
::apply(geometry1, m_geometry2, m_strategy);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy
|
||||
)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
Geometry1 const& m_geometry1;
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Geometry1 const& geometry1, Strategy const& strategy)
|
||||
: m_geometry1(geometry1)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry2>
|
||||
inline bool operator()(Geometry2 const& geometry2) const
|
||||
{
|
||||
return equals<Geometry1, Geometry2>
|
||||
::apply(m_geometry1, geometry2, m_strategy);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(
|
||||
Geometry1 const& geometry1,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
|
||||
Strategy const& strategy
|
||||
)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
template <
|
||||
BOOST_VARIANT_ENUM_PARAMS(typename T1),
|
||||
BOOST_VARIANT_ENUM_PARAMS(typename T2)
|
||||
>
|
||||
struct equals<
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
|
||||
>
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: static_visitor<bool>
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline bool operator()(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2) const
|
||||
{
|
||||
return equals<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, m_strategy);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
|
||||
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
|
||||
Strategy const& strategy
|
||||
)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check{are spatially equal}
|
||||
\details \details_check12{equals, is spatially equal}. Spatially equal means
|
||||
that the same point set is included. A box can therefore be spatially equal
|
||||
to a ring or a polygon, or a linestring can be spatially equal to a
|
||||
multi-linestring or a segment. This only works theoretically, not all
|
||||
combinations are implemented yet.
|
||||
\ingroup equals
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Equals}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param strategy \param_strategy{equals}
|
||||
\return \return_check2{are spatially equal}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/equals.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool equals(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::equals
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check{are spatially equal}
|
||||
\details \details_check12{equals, is spatially equal}. Spatially equal means
|
||||
that the same point set is included. A box can therefore be spatially equal
|
||||
to a ring or a polygon, or a linestring can be spatially equal to a
|
||||
multi-linestring or a segment. This only works theoretically, not all
|
||||
combinations are implemented yet.
|
||||
\ingroup equals
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\return \return_check2{are spatially equal}
|
||||
|
||||
\qbk{[include reference/algorithms/equals.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
return resolve_variant::equals<Geometry1, Geometry2>
|
||||
::apply(geometry1, geometry2, default_strategy());
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013-2014.
|
||||
// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2018.
|
||||
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
@@ -21,13 +21,10 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace equals
|
||||
{
|
||||
@@ -36,17 +33,16 @@ namespace detail { namespace equals
|
||||
\brief Internal utility function to detect of points are disjoint
|
||||
\note To avoid circular references
|
||||
*/
|
||||
template <typename Point1, typename Point2>
|
||||
inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
|
||||
template <typename Point1, typename Point2, typename Strategy>
|
||||
inline bool equals_point_point(Point1 const& point1, Point2 const& point2,
|
||||
Strategy const& )
|
||||
{
|
||||
return ! detail::disjoint::disjoint_point_point(point1, point2);
|
||||
return Strategy::apply(point1, point2);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::equals
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_POINT_POINT_HPP
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -18,52 +19,19 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/expand.hpp>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/expand_box.hpp>
|
||||
#include <boost/geometry/strategies/spherical/expand_box.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace expand
|
||||
{
|
||||
|
||||
|
||||
struct box_on_spheroid
|
||||
{
|
||||
template <typename BoxOut, typename BoxIn, typename Strategy>
|
||||
static inline void apply(BoxOut& box_out,
|
||||
BoxIn const& box_in,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// normalize both boxes and convert box-in to be of type of box-out
|
||||
BoxOut mbrs[2];
|
||||
detail::envelope::envelope_box_on_spheroid::apply(box_in, mbrs[0], strategy);
|
||||
detail::envelope::envelope_box_on_spheroid::apply(box_out, mbrs[1], strategy);
|
||||
|
||||
// compute the envelope of the two boxes
|
||||
detail::envelope::envelope_range_of_boxes::apply(mbrs, box_out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::expand
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
@@ -72,53 +40,23 @@ namespace dispatch
|
||||
// Box + box -> new box containing two input boxes
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename BoxIn,
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
typename CSTagOut, typename CSTag
|
||||
typename BoxOut, typename BoxIn
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, BoxIn,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, box_tag,
|
||||
CSTagOut, CSTag
|
||||
> : detail::expand::expand_indexed
|
||||
<
|
||||
0, dimension<BoxIn>::value, StrategyLess, StrategyGreater
|
||||
>
|
||||
box_tag, box_tag
|
||||
>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
|
||||
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
|
||||
(types<CSTagOut, CSTag>()));
|
||||
template <typename Strategy>
|
||||
static inline void apply(BoxOut& box_out,
|
||||
BoxIn const& box_in,
|
||||
Strategy const& )
|
||||
{
|
||||
Strategy::apply(box_out, box_in);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename BoxIn,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, BoxIn,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, box_tag,
|
||||
spherical_equatorial_tag, spherical_equatorial_tag
|
||||
> : detail::expand::box_on_spheroid
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename BoxIn,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, BoxIn,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, box_tag,
|
||||
geographic_tag, geographic_tag
|
||||
> : detail::expand::box_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// 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.
|
||||
@@ -22,15 +23,13 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INDEXED_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/compare.hpp>
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/expand.hpp>
|
||||
|
||||
|
||||
@@ -44,36 +43,25 @@ namespace detail { namespace expand
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
std::size_t Index,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct indexed_loop
|
||||
{
|
||||
template <typename Box, typename Geometry, typename Strategy>
|
||||
static inline void apply(Box& box, Geometry const& source, Strategy const& strategy)
|
||||
template <typename Box, typename Geometry>
|
||||
static inline void apply(Box& box, Geometry const& source)
|
||||
{
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
StrategyLess, 1, Box, Dimension
|
||||
>::type less_type;
|
||||
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
StrategyGreater, -1, Box, Dimension
|
||||
>::type greater_type;
|
||||
|
||||
typedef typename select_coordinate_type
|
||||
<
|
||||
Box,
|
||||
Geometry
|
||||
>::type coordinate_type;
|
||||
|
||||
less_type less;
|
||||
greater_type greater;
|
||||
|
||||
coordinate_type const coord = get<Index, Dimension>(source);
|
||||
|
||||
std::less<coordinate_type> less;
|
||||
std::greater<coordinate_type> greater;
|
||||
|
||||
if (less(coord, get<min_corner, Dimension>(box)))
|
||||
{
|
||||
set<min_corner, Dimension>(box, coord);
|
||||
@@ -86,54 +74,40 @@ struct indexed_loop
|
||||
|
||||
indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
Index, Dimension + 1, DimensionCount
|
||||
>::apply(box, source, strategy);
|
||||
>::apply(box, source);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
std::size_t Index, std::size_t DimensionCount
|
||||
>
|
||||
template <std::size_t Index, std::size_t DimensionCount>
|
||||
struct indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
Index, DimensionCount, DimensionCount
|
||||
>
|
||||
{
|
||||
template <typename Box, typename Geometry, typename Strategy>
|
||||
static inline void apply(Box&, Geometry const&, Strategy const&) {}
|
||||
template <typename Box, typename Geometry>
|
||||
static inline void apply(Box&, Geometry const&) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Changes a box such that the other box is also contained by the box
|
||||
template
|
||||
<
|
||||
std::size_t Dimension, std::size_t DimensionCount,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct expand_indexed
|
||||
{
|
||||
template <typename Box, typename Geometry, typename Strategy>
|
||||
static inline void apply(Box& box,
|
||||
Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
template <typename Box, typename Geometry>
|
||||
static inline void apply(Box& box, Geometry const& geometry)
|
||||
{
|
||||
indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
0, Dimension, DimensionCount
|
||||
>::apply(box, geometry, strategy);
|
||||
>::apply(box, geometry);
|
||||
|
||||
indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
1, Dimension, DimensionCount
|
||||
>::apply(box, geometry, strategy);
|
||||
>::apply(box, geometry);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2016, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// 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.
|
||||
@@ -25,16 +26,17 @@
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/expand.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/expand.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/envelope.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -58,14 +60,11 @@ struct expand
|
||||
Geometry const& geometry,
|
||||
default_strategy)
|
||||
{
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
typedef typename coordinate_type<point_type>::type coordinate_type;
|
||||
|
||||
typedef typename strategy::envelope::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type,
|
||||
coordinate_type
|
||||
>::type strategy_type;
|
||||
typedef typename strategy::expand::services::default_strategy
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type strategy_type;
|
||||
|
||||
dispatch::expand<Box, Geometry>::apply(box, geometry, strategy_type());
|
||||
}
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// 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.
|
||||
@@ -21,222 +22,19 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_POINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/compare.hpp>
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/expand.hpp>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/expand_point.hpp>
|
||||
#include <boost/geometry/strategies/spherical/expand_point.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace expand
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct point_loop
|
||||
{
|
||||
template <typename Box, typename Point, typename Strategy>
|
||||
static inline void apply(Box& box, Point const& source, Strategy const& strategy)
|
||||
{
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
StrategyLess, 1, Point, Dimension
|
||||
>::type less_type;
|
||||
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
StrategyGreater, -1, Point, Dimension
|
||||
>::type greater_type;
|
||||
|
||||
typedef typename select_coordinate_type
|
||||
<
|
||||
Point, Box
|
||||
>::type coordinate_type;
|
||||
|
||||
less_type less;
|
||||
greater_type greater;
|
||||
|
||||
coordinate_type const coord = get<Dimension>(source);
|
||||
|
||||
if (less(coord, get<min_corner, Dimension>(box)))
|
||||
{
|
||||
set<min_corner, Dimension>(box, coord);
|
||||
}
|
||||
|
||||
if (greater(coord, get<max_corner, Dimension>(box)))
|
||||
{
|
||||
set<max_corner, Dimension>(box, coord);
|
||||
}
|
||||
|
||||
point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, Dimension + 1, DimensionCount
|
||||
>::apply(box, source, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess,
|
||||
typename StrategyGreater,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, DimensionCount, DimensionCount
|
||||
>
|
||||
{
|
||||
template <typename Box, typename Point, typename Strategy>
|
||||
static inline void apply(Box&, Point const&, Strategy const&) {}
|
||||
};
|
||||
|
||||
|
||||
// implementation for the spherical equatorial and geographic coordinate systems
|
||||
template
|
||||
<
|
||||
typename StrategyLess,
|
||||
typename StrategyGreater,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct point_loop_on_spheroid
|
||||
{
|
||||
template <typename Box, typename Point, typename Strategy>
|
||||
static inline void apply(Box& box,
|
||||
Point const& point,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<Box>::type box_point_type;
|
||||
typedef typename coordinate_type<Box>::type box_coordinate_type;
|
||||
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
box_coordinate_type,
|
||||
typename coordinate_system<Box>::type::units
|
||||
> constants;
|
||||
|
||||
// normalize input point and input box
|
||||
Point p_normalized = detail::return_normalized<Point>(point);
|
||||
detail::normalize(box, box);
|
||||
|
||||
// transform input point to be of the same type as the box point
|
||||
box_point_type box_point;
|
||||
detail::envelope::transform_units(p_normalized, box_point);
|
||||
|
||||
box_coordinate_type p_lon = geometry::get<0>(box_point);
|
||||
box_coordinate_type p_lat = geometry::get<1>(box_point);
|
||||
|
||||
typename coordinate_type<Box>::type
|
||||
b_lon_min = geometry::get<min_corner, 0>(box),
|
||||
b_lat_min = geometry::get<min_corner, 1>(box),
|
||||
b_lon_max = geometry::get<max_corner, 0>(box),
|
||||
b_lat_max = geometry::get<max_corner, 1>(box);
|
||||
|
||||
if (math::equals(math::abs(p_lat), constants::max_latitude()))
|
||||
{
|
||||
// the point of expansion is the either the north or the
|
||||
// south pole; the only important coordinate here is the
|
||||
// pole's latitude, as the longitude can be anything;
|
||||
// we, thus, take into account the point's latitude only and return
|
||||
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
|
||||
geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
|
||||
return;
|
||||
}
|
||||
|
||||
if (math::equals(b_lat_min, b_lat_max)
|
||||
&& math::equals(math::abs(b_lat_min), constants::max_latitude()))
|
||||
{
|
||||
// the box degenerates to either the north or the south pole;
|
||||
// the only important coordinate here is the pole's latitude,
|
||||
// as the longitude can be anything;
|
||||
// we thus take into account the box's latitude only and return
|
||||
geometry::set<min_corner, 0>(box, p_lon);
|
||||
geometry::set<min_corner, 1>(box, (std::min)(p_lat, b_lat_min));
|
||||
geometry::set<max_corner, 0>(box, p_lon);
|
||||
geometry::set<max_corner, 1>(box, (std::max)(p_lat, b_lat_max));
|
||||
return;
|
||||
}
|
||||
|
||||
// update latitudes
|
||||
b_lat_min = (std::min)(b_lat_min, p_lat);
|
||||
b_lat_max = (std::max)(b_lat_max, p_lat);
|
||||
|
||||
// update longitudes
|
||||
if (math::smaller(p_lon, b_lon_min))
|
||||
{
|
||||
box_coordinate_type p_lon_shifted = p_lon + constants::period();
|
||||
|
||||
if (math::larger(p_lon_shifted, b_lon_max))
|
||||
{
|
||||
// here we could check using: ! math::larger(.., ..)
|
||||
if (math::smaller(b_lon_min - p_lon, p_lon_shifted - b_lon_max))
|
||||
{
|
||||
b_lon_min = p_lon;
|
||||
}
|
||||
else
|
||||
{
|
||||
b_lon_max = p_lon_shifted;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (math::larger(p_lon, b_lon_max))
|
||||
{
|
||||
// in this case, and since p_lon is normalized in the range
|
||||
// (-180, 180], we must have that b_lon_max <= 180
|
||||
if (b_lon_min < 0
|
||||
&& math::larger(p_lon - b_lon_max,
|
||||
constants::period() - p_lon + b_lon_min))
|
||||
{
|
||||
b_lon_min = p_lon;
|
||||
b_lon_max += constants::period();
|
||||
}
|
||||
else
|
||||
{
|
||||
b_lon_max = p_lon;
|
||||
}
|
||||
}
|
||||
|
||||
geometry::set<min_corner, 0>(box, b_lon_min);
|
||||
geometry::set<min_corner, 1>(box, b_lat_min);
|
||||
geometry::set<max_corner, 0>(box, b_lon_max);
|
||||
geometry::set<max_corner, 1>(box, b_lat_max);
|
||||
|
||||
point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, 2, DimensionCount
|
||||
>::apply(box, point, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::expand
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
@@ -245,59 +43,23 @@ namespace dispatch
|
||||
// Box + point -> new box containing also point
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename Point,
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
typename CSTagOut, typename CSTag
|
||||
typename BoxOut, typename Point
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, Point,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, point_tag,
|
||||
CSTagOut, CSTag
|
||||
> : detail::expand::point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, 0, dimension<Point>::value
|
||||
>
|
||||
box_tag, point_tag
|
||||
>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
|
||||
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
|
||||
(types<CSTagOut, CSTag>()));
|
||||
template <typename Strategy>
|
||||
static inline void apply(BoxOut& box,
|
||||
Point const& point,
|
||||
Strategy const& )
|
||||
{
|
||||
Strategy::apply(box, point);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename Point,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, Point,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, point_tag,
|
||||
spherical_equatorial_tag, spherical_equatorial_tag
|
||||
> : detail::expand::point_loop_on_spheroid
|
||||
<
|
||||
StrategyLess, StrategyGreater, dimension<Point>::value
|
||||
>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename Point,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, Point,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, point_tag,
|
||||
geographic_tag, geographic_tag
|
||||
> : detail::expand::point_loop_on_spheroid
|
||||
<
|
||||
StrategyLess, StrategyGreater, dimension<Point>::value
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016.
|
||||
// Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -18,111 +19,46 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_SEGMENT_HPP
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/expand.hpp>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/cartesian/expand_segment.hpp>
|
||||
#include <boost/geometry/strategies/geographic/expand_segment.hpp>
|
||||
#include <boost/geometry/strategies/spherical/expand_segment.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace expand
|
||||
{
|
||||
|
||||
struct segment
|
||||
{
|
||||
template <typename Box, typename Segment, typename Strategy>
|
||||
static inline void apply(Box& box,
|
||||
Segment const& segment,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
Box mbrs[2];
|
||||
|
||||
// compute the envelope of the segment
|
||||
typename point_type<Segment>::type p[2];
|
||||
detail::assign_point_from_index<0>(segment, p[0]);
|
||||
detail::assign_point_from_index<1>(segment, p[1]);
|
||||
detail::envelope::envelope_segment
|
||||
<
|
||||
dimension<Segment>::value
|
||||
>::apply(p[0], p[1], mbrs[0], strategy);
|
||||
|
||||
// normalize the box
|
||||
detail::envelope::envelope_box_on_spheroid::apply(box, mbrs[1], strategy);
|
||||
|
||||
// compute the envelope of the two boxes
|
||||
detail::envelope::envelope_range_of_boxes::apply(mbrs, box, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::expand
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Box, typename Segment,
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
typename CSTagOut, typename CSTag
|
||||
typename Box, typename Segment
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, segment_tag,
|
||||
CSTagOut, CSTag
|
||||
> : detail::expand::expand_indexed
|
||||
<
|
||||
0, dimension<Segment>::value, StrategyLess, StrategyGreater
|
||||
>
|
||||
box_tag, segment_tag
|
||||
>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
|
||||
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
|
||||
(types<CSTagOut, CSTag>()));
|
||||
template <typename Strategy>
|
||||
static inline void apply(Box& box,
|
||||
Segment const& segment,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::ignore_unused(strategy);
|
||||
strategy.apply(box, segment);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Box, typename Segment,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, segment_tag,
|
||||
spherical_equatorial_tag, spherical_equatorial_tag
|
||||
> : detail::expand::segment
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Box, typename Segment,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, segment_tag,
|
||||
geographic_tag, geographic_tag
|
||||
> : detail::expand::segment
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
@@ -3,7 +3,12 @@
|
||||
// Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2013 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-2018 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
|
||||
@@ -20,6 +25,7 @@
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
@@ -117,12 +123,6 @@ struct extreme_points_on_ring
|
||||
typedef typename boost::range_iterator<Ring const>::type range_iterator;
|
||||
typedef typename geometry::point_type<Ring>::type point_type;
|
||||
|
||||
typedef typename geometry::strategy::side::services::default_strategy
|
||||
<
|
||||
typename geometry::cs_tag<point_type>::type
|
||||
>::type side_strategy;
|
||||
|
||||
|
||||
template <typename CirclingIterator, typename Points>
|
||||
static inline bool extend(CirclingIterator& it,
|
||||
std::size_t n,
|
||||
@@ -214,10 +214,11 @@ struct extreme_points_on_ring
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Extremes, typename Intruders, typename CirclingIterator>
|
||||
template <typename Extremes, typename Intruders, typename CirclingIterator, typename SideStrategy>
|
||||
static inline void get_intruders(Ring const& ring, CirclingIterator left, CirclingIterator right,
|
||||
Extremes const& extremes,
|
||||
Intruders& intruders)
|
||||
Intruders& intruders,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
if (boost::size(extremes) < 3)
|
||||
{
|
||||
@@ -238,8 +239,8 @@ struct extreme_points_on_ring
|
||||
if (coordinate > min_value && other_coordinate > other_min && other_coordinate < other_max)
|
||||
{
|
||||
int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1;
|
||||
int const first_side = side_strategy::apply(*right, extremes.front(), *(extremes.begin() + 1)) * factor;
|
||||
int const last_side = side_strategy::apply(*right, *(extremes.rbegin() + 1), extremes.back()) * factor;
|
||||
int const first_side = strategy.apply(*right, extremes.front(), *(extremes.begin() + 1)) * factor;
|
||||
int const last_side = strategy.apply(*right, *(extremes.rbegin() + 1), extremes.back()) * factor;
|
||||
|
||||
// If not lying left from any of the extemes side
|
||||
if (first_side != 1 && last_side != 1)
|
||||
@@ -263,10 +264,11 @@ struct extreme_points_on_ring
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Extremes, typename Intruders>
|
||||
template <typename Extremes, typename Intruders, typename SideStrategy>
|
||||
static inline void get_intruders(Ring const& ring,
|
||||
Extremes const& extremes,
|
||||
Intruders& intruders)
|
||||
Intruders& intruders,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
std::size_t const n = boost::size(ring);
|
||||
if (n >= 3)
|
||||
@@ -275,12 +277,12 @@ struct extreme_points_on_ring
|
||||
geometry::ever_circling_range_iterator<Ring const> right(ring);
|
||||
++right;
|
||||
|
||||
get_intruders(ring, left, right, extremes, intruders);
|
||||
get_intruders(ring, left, right, extremes, intruders, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static inline bool right_turn(Ring const& ring, Iterator it)
|
||||
template <typename Iterator, typename SideStrategy>
|
||||
static inline bool right_turn(Ring const& ring, Iterator it, SideStrategy const& strategy)
|
||||
{
|
||||
typename std::iterator_traits<Iterator>::difference_type const index
|
||||
= std::distance(boost::begin(ring), it);
|
||||
@@ -295,8 +297,8 @@ struct extreme_points_on_ring
|
||||
}
|
||||
|
||||
int const factor = geometry::point_order<Ring>::value == geometry::clockwise ? 1 : -1;
|
||||
int const first_side = side_strategy::apply(*(right - 1), *right, *left) * factor;
|
||||
int const last_side = side_strategy::apply(*left, *(left + 1), *right) * factor;
|
||||
int const first_side = strategy.apply(*(right - 1), *right, *left) * factor;
|
||||
int const last_side = strategy.apply(*left, *(left + 1), *right) * factor;
|
||||
|
||||
//std::cout << "Candidate at " << geometry::wkt(*it) << " first=" << first_side << " last=" << last_side << std::endl;
|
||||
|
||||
@@ -306,8 +308,11 @@ struct extreme_points_on_ring
|
||||
|
||||
|
||||
// Gets the extreme segments (top point plus neighbouring points), plus intruders, if any, on the same ring
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline bool apply(Ring const& ring, Extremes& extremes, Intruders& intruders)
|
||||
template <typename Extremes, typename Intruders, typename SideStrategy>
|
||||
static inline bool apply(Ring const& ring,
|
||||
Extremes& extremes,
|
||||
Intruders& intruders,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
std::size_t const n = boost::size(ring);
|
||||
if (n < 3)
|
||||
@@ -321,7 +326,7 @@ struct extreme_points_on_ring
|
||||
compare<Dimension> smaller;
|
||||
for (range_iterator it = max_it + 1; it != boost::end(ring); ++it)
|
||||
{
|
||||
if (smaller(*max_it, *it) && right_turn(ring, it))
|
||||
if (smaller(*max_it, *it) && right_turn(ring, it, strategy))
|
||||
{
|
||||
max_it = it;
|
||||
}
|
||||
@@ -365,7 +370,7 @@ struct extreme_points_on_ring
|
||||
|
||||
std::copy(points.begin(), points.end(), std::back_inserter(extremes));
|
||||
|
||||
get_intruders(ring, left, right, extremes, intruders);
|
||||
get_intruders(ring, left, right, extremes, intruders, strategy);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -403,8 +408,9 @@ struct extreme_points<Ring, Dimension, ring_tag>
|
||||
template<typename Polygon, std::size_t Dimension>
|
||||
struct extreme_points<Polygon, Dimension, polygon_tag>
|
||||
{
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders)
|
||||
template <typename Extremes, typename Intruders, typename SideStrategy>
|
||||
static inline bool apply(Polygon const& polygon, Extremes& extremes, Intruders& intruders,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::ring_type<Polygon>::type ring_type;
|
||||
typedef detail::extreme_points::extreme_points_on_ring
|
||||
@@ -412,7 +418,8 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
|
||||
ring_type, Dimension
|
||||
> ring_implementation;
|
||||
|
||||
if (! ring_implementation::apply(geometry::exterior_ring(polygon), extremes, intruders))
|
||||
if (! ring_implementation::apply(geometry::exterior_ring(polygon),
|
||||
extremes, intruders, strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -423,7 +430,7 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
|
||||
for (typename detail::interior_iterator<Polygon const>::type
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
ring_implementation::get_intruders(*it, extremes, intruders);
|
||||
ring_implementation::get_intruders(*it, extremes, intruders, strategy);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -433,8 +440,9 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
|
||||
template<typename Box>
|
||||
struct extreme_points<Box, 1, box_tag>
|
||||
{
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline bool apply(Box const& box, Extremes& extremes, Intruders& )
|
||||
template <typename Extremes, typename Intruders, typename SideStrategy>
|
||||
static inline bool apply(Box const& box, Extremes& extremes, Intruders& ,
|
||||
SideStrategy const& )
|
||||
{
|
||||
extremes.resize(4);
|
||||
geometry::detail::assign_box_corners_oriented<false>(box, extremes);
|
||||
@@ -446,8 +454,9 @@ struct extreme_points<Box, 1, box_tag>
|
||||
template<typename Box>
|
||||
struct extreme_points<Box, 0, box_tag>
|
||||
{
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline bool apply(Box const& box, Extremes& extremes, Intruders& )
|
||||
template <typename Extremes, typename Intruders, typename SideStrategy>
|
||||
static inline bool apply(Box const& box, Extremes& extremes, Intruders& ,
|
||||
SideStrategy const& )
|
||||
{
|
||||
extremes.resize(4);
|
||||
geometry::detail::assign_box_corners_oriented<false>(box, extremes);
|
||||
@@ -460,8 +469,9 @@ struct extreme_points<Box, 0, box_tag>
|
||||
template<typename MultiPolygon, std::size_t Dimension>
|
||||
struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
|
||||
{
|
||||
template <typename Extremes, typename Intruders>
|
||||
static inline bool apply(MultiPolygon const& multi, Extremes& extremes, Intruders& intruders)
|
||||
template <typename Extremes, typename Intruders, typename SideStrategy>
|
||||
static inline bool apply(MultiPolygon const& multi, Extremes& extremes,
|
||||
Intruders& intruders, SideStrategy const& strategy)
|
||||
{
|
||||
// Get one for the very first polygon, that is (for the moment) enough.
|
||||
// It is not guaranteed the "extreme" then, but for the current purpose
|
||||
@@ -473,7 +483,7 @@ struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
|
||||
typename boost::range_value<MultiPolygon const>::type,
|
||||
Dimension,
|
||||
polygon_tag
|
||||
>::apply(*boost::begin(multi), extremes, intruders);
|
||||
>::apply(*boost::begin(multi), extremes, intruders, strategy);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -489,8 +499,18 @@ struct extreme_points<MultiPolygon, Dimension, multi_polygon_tag>
|
||||
for Edge=0 in dimension 0, the right side)
|
||||
\note We could specify a strategy (less/greater) to get bottom/left side too. However, until now we don't need that.
|
||||
*/
|
||||
template <std::size_t Edge, typename Geometry, typename Extremes, typename Intruders>
|
||||
inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intruders& intruders)
|
||||
template
|
||||
<
|
||||
std::size_t Edge,
|
||||
typename Geometry,
|
||||
typename Extremes,
|
||||
typename Intruders,
|
||||
typename SideStrategy
|
||||
>
|
||||
inline bool extreme_points(Geometry const& geometry,
|
||||
Extremes& extremes,
|
||||
Intruders& intruders,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
@@ -509,10 +529,32 @@ inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intrude
|
||||
const
|
||||
>();
|
||||
|
||||
return dispatch::extreme_points<Geometry, Edge>::apply(geometry, extremes, intruders);
|
||||
return dispatch::extreme_points
|
||||
<
|
||||
Geometry,
|
||||
Edge
|
||||
>::apply(geometry, extremes, intruders, strategy);
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Edge,
|
||||
typename Geometry,
|
||||
typename Extremes,
|
||||
typename Intruders
|
||||
>
|
||||
inline bool extreme_points(Geometry const& geometry,
|
||||
Extremes& extremes,
|
||||
Intruders& intruders)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type strategy_type;
|
||||
|
||||
return geometry::extreme_points<Edge>(geometry,extremes, intruders, strategy_type());
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-2018, 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)
|
||||
@@ -9,11 +14,14 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/iterators/closing_iterator.hpp>
|
||||
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
@@ -60,17 +68,14 @@ inline int squared_length(Vector const& vector)
|
||||
}
|
||||
|
||||
|
||||
template <typename Point>
|
||||
template <typename Point, typename SideStrategy>
|
||||
struct angle_less
|
||||
{
|
||||
typedef Point vector_type;
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy_type;
|
||||
|
||||
angle_less(Point const& origin)
|
||||
angle_less(Point const& origin, SideStrategy const& strategy)
|
||||
: m_origin(origin)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Angle>
|
||||
@@ -89,8 +94,7 @@ struct angle_less
|
||||
return quadrant_p < quadrant_q;
|
||||
}
|
||||
// Same quadrant, check if p is located left of q
|
||||
int const side = side_strategy_type::apply(m_origin, q.point,
|
||||
p.point);
|
||||
int const side = m_strategy.apply(m_origin, q.point, p.point);
|
||||
if (side != 0)
|
||||
{
|
||||
return side == 1;
|
||||
@@ -114,19 +118,17 @@ struct angle_less
|
||||
|
||||
private:
|
||||
Point m_origin;
|
||||
SideStrategy m_strategy;
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
template <typename Point, typename SideStrategy>
|
||||
struct angle_equal_to
|
||||
{
|
||||
typedef Point vector_type;
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side_strategy_type;
|
||||
|
||||
inline angle_equal_to(Point const& origin)
|
||||
|
||||
inline angle_equal_to(Point const& origin, SideStrategy const& strategy)
|
||||
: m_origin(origin)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Angle>
|
||||
@@ -143,13 +145,13 @@ struct angle_equal_to
|
||||
return false;
|
||||
}
|
||||
// Same quadrant, check if p/q are collinear
|
||||
int const side = side_strategy_type::apply(m_origin, q.point,
|
||||
p.point);
|
||||
int const side = m_strategy.apply(m_origin, q.point, p.point);
|
||||
return side == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
Point m_origin;
|
||||
SideStrategy m_strategy;
|
||||
};
|
||||
|
||||
template <typename AngleCollection, typename Turns>
|
||||
@@ -193,13 +195,14 @@ inline void get_left_turns(AngleCollection const& sorted_angles,
|
||||
|
||||
|
||||
//! Returns the number of clusters
|
||||
template <typename Point, typename AngleCollection>
|
||||
inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin)
|
||||
template <typename Point, typename AngleCollection, typename SideStrategy>
|
||||
inline std::size_t assign_cluster_indices(AngleCollection& sorted, Point const& origin,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
// Assign same cluster_index for all turns in same direction
|
||||
BOOST_GEOMETRY_ASSERT(boost::size(sorted) >= 4u);
|
||||
|
||||
angle_equal_to<Point> comparator(origin);
|
||||
angle_equal_to<Point, SideStrategy> comparator(origin, strategy);
|
||||
typename boost::range_iterator<AngleCollection>::type it = sorted.begin();
|
||||
|
||||
std::size_t cluster_index = 0;
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
// Copyright (c) 2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2018.
|
||||
// Modifications copyright (c) 2018, 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)
|
||||
@@ -12,10 +17,10 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_MAX_SIZE_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
|
||||
@@ -81,7 +81,11 @@ inline bool has_self_intersections(Geometry const& geometry,
|
||||
std::deque<turn_info> turns;
|
||||
detail::disjoint::disjoint_interrupt_policy policy;
|
||||
|
||||
geometry::self_turns<detail::overlay::assign_null_policy>(geometry, strategy, robust_policy, turns, policy);
|
||||
detail::self_get_turn_points::self_turns
|
||||
<
|
||||
false,
|
||||
detail::overlay::assign_null_policy
|
||||
>(geometry, strategy, robust_policy, turns, policy, 0, false);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
|
||||
bool first = true;
|
||||
|
||||
@@ -237,7 +237,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
multi_linestring_tag, multi_linestring_tag, point_tag,
|
||||
false, false, false
|
||||
linear_tag, linear_tag, pointlike_tag
|
||||
> : detail::intersection::intersection_multi_linestring_multi_linestring_point
|
||||
<
|
||||
GeometryOut
|
||||
@@ -259,7 +259,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
linestring_tag, multi_linestring_tag, point_tag,
|
||||
false, false, false
|
||||
linear_tag, linear_tag, pointlike_tag
|
||||
> : detail::intersection::intersection_linestring_multi_linestring_point
|
||||
<
|
||||
GeometryOut
|
||||
@@ -281,7 +281,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
multi_linestring_tag, box_tag, linestring_tag,
|
||||
false, true, false
|
||||
linear_tag, areal_tag, linear_tag
|
||||
> : detail::intersection::clip_multi_linestring
|
||||
<
|
||||
GeometryOut
|
||||
@@ -303,7 +303,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
ReverseLinestring, ReverseMultiPolygon, ReverseOut,
|
||||
linestring_tag, multi_polygon_tag, linestring_tag,
|
||||
false, true, false
|
||||
linear_tag, areal_tag, linear_tag
|
||||
> : detail::intersection::intersection_of_linestring_with_areal
|
||||
<
|
||||
ReverseMultiPolygon,
|
||||
@@ -329,7 +329,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
ReversePolygon, ReverseMultiLinestring, ReverseOut,
|
||||
polygon_tag, multi_linestring_tag, linestring_tag,
|
||||
true, false, false
|
||||
areal_tag, linear_tag, linear_tag
|
||||
> : detail::intersection::intersection_of_areal_with_multi_linestring
|
||||
<
|
||||
ReversePolygon,
|
||||
@@ -353,7 +353,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
ReverseMultiLinestring, ReverseRing, ReverseOut,
|
||||
multi_linestring_tag, ring_tag, linestring_tag,
|
||||
false, true, false
|
||||
linear_tag, areal_tag, linear_tag
|
||||
> : detail::intersection::intersection_of_multi_linestring_with_areal
|
||||
<
|
||||
ReverseRing,
|
||||
@@ -376,7 +376,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
ReverseMultiLinestring, ReverseRing, ReverseOut,
|
||||
multi_linestring_tag, polygon_tag, linestring_tag,
|
||||
false, true, false
|
||||
linear_tag, areal_tag, linear_tag
|
||||
> : detail::intersection::intersection_of_multi_linestring_with_areal
|
||||
<
|
||||
ReverseRing,
|
||||
@@ -401,7 +401,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
ReverseMultiLinestring, ReverseMultiPolygon, ReverseOut,
|
||||
multi_linestring_tag, multi_polygon_tag, linestring_tag,
|
||||
false, true, false
|
||||
linear_tag, areal_tag, linear_tag
|
||||
> : detail::intersection::intersection_of_multi_linestring_with_areal
|
||||
<
|
||||
ReverseMultiPolygon,
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ALGORITHMS_DETAIL_INTERSECTS_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_IMPLEMENTATION_HPP
|
||||
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/intersects/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/implementation.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
|
||||
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/relate.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace intersects
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct self_intersects
|
||||
{
|
||||
static bool apply(Geometry const& geometry)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
||||
typedef typename strategy::relate::services::default_strategy
|
||||
<
|
||||
Geometry, Geometry
|
||||
>::type strategy_type;
|
||||
typedef detail::no_rescale_policy rescale_policy_type;
|
||||
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
point_type,
|
||||
typename segment_ratio_type<point_type, rescale_policy_type>::type
|
||||
> turn_info;
|
||||
|
||||
std::deque<turn_info> turns;
|
||||
|
||||
typedef detail::overlay::get_turn_info
|
||||
<
|
||||
detail::overlay::assign_null_policy
|
||||
> turn_policy;
|
||||
|
||||
strategy_type strategy;
|
||||
rescale_policy_type robust_policy;
|
||||
|
||||
detail::disjoint::disjoint_interrupt_policy policy;
|
||||
// TODO: skip_adjacent should be set to false
|
||||
detail::self_get_turn_points::get_turns
|
||||
<
|
||||
false, turn_policy
|
||||
>::apply(geometry, strategy, robust_policy, turns, policy, 0, true);
|
||||
return policy.has_intersections;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::intersects
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_IMPLEMENTATION_HPP
|
||||
@@ -0,0 +1,115 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ALGORITHMS_DETAIL_INTERSECTS_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace intersects
|
||||
{
|
||||
|
||||
// Forward declaration
|
||||
template <typename Geometry>
|
||||
struct self_intersects;
|
||||
|
||||
}} // namespace detail::intersects
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check{has at least one intersection (crossing or self-tangency)}
|
||||
\note This function can be called for one geometry (self-intersection) and
|
||||
also for two geometries (intersection)
|
||||
\ingroup intersects
|
||||
\tparam Geometry \tparam_geometry
|
||||
\param geometry \param_geometry
|
||||
\return \return_check{is self-intersecting}
|
||||
|
||||
\qbk{distinguish,one geometry}
|
||||
\qbk{[def __one_parameter__]}
|
||||
\qbk{[include reference/algorithms/intersects.qbk]}
|
||||
*/
|
||||
template <typename Geometry>
|
||||
inline bool intersects(Geometry const& geometry)
|
||||
{
|
||||
return detail::intersects::self_intersects<Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check2{have at least one intersection}
|
||||
\ingroup intersects
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Intersects}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param strategy \param_strategy{intersects}
|
||||
\return \return_check2{intersect each other}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/intersects.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool intersects(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return ! geometry::disjoint(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check2{have at least one intersection}
|
||||
\ingroup intersects
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\return \return_check2{intersect each other}
|
||||
|
||||
\qbk{distinguish,two geometries}
|
||||
\qbk{[include reference/algorithms/intersects.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline bool intersects(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return ! geometry::disjoint(geometry1, geometry2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_INTERFACE_HPP
|
||||
@@ -217,14 +217,15 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg
|
||||
is_acceptable_turn<Linear>
|
||||
> interrupt_policy(predicate);
|
||||
|
||||
// TODO: skip_adjacent should be set to false
|
||||
detail::self_get_turn_points::get_turns
|
||||
<
|
||||
turn_policy
|
||||
false, turn_policy
|
||||
>::apply(linear,
|
||||
strategy,
|
||||
detail::no_rescale_policy(),
|
||||
turns,
|
||||
interrupt_policy);
|
||||
interrupt_policy, 0, true);
|
||||
|
||||
detail::is_valid::debug_print_turns(turns.begin(), turns.end());
|
||||
debug_print_boundary_points(linear);
|
||||
@@ -236,7 +237,9 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg
|
||||
template <typename Linestring, bool CheckSelfIntersections = true>
|
||||
struct is_simple_linestring
|
||||
{
|
||||
static inline bool apply(Linestring const& linestring)
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Linestring const& linestring,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
simplicity_failure_policy policy;
|
||||
return ! boost::empty(linestring)
|
||||
@@ -247,7 +250,7 @@ struct is_simple_linestring
|
||||
&& ! detail::is_valid::has_spikes
|
||||
<
|
||||
Linestring, closed
|
||||
>::apply(linestring, policy);
|
||||
>::apply(linestring, policy, strategy.get_side_strategy());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -258,7 +261,10 @@ struct is_simple_linestring<Linestring, true>
|
||||
static inline bool apply(Linestring const& linestring,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return is_simple_linestring<Linestring, false>::apply(linestring)
|
||||
return is_simple_linestring
|
||||
<
|
||||
Linestring, false
|
||||
>::apply(linestring, strategy)
|
||||
&& ! has_self_intersections(linestring, strategy);
|
||||
}
|
||||
};
|
||||
@@ -267,23 +273,44 @@ struct is_simple_linestring<Linestring, true>
|
||||
template <typename MultiLinestring>
|
||||
struct is_simple_multilinestring
|
||||
{
|
||||
private:
|
||||
template <typename Strategy>
|
||||
struct per_linestring
|
||||
{
|
||||
per_linestring(Strategy const& strategy)
|
||||
: m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Linestring>
|
||||
inline bool apply(Linestring const& linestring) const
|
||||
{
|
||||
return detail::is_simple::is_simple_linestring
|
||||
<
|
||||
Linestring,
|
||||
false // do not compute self-intersections
|
||||
>::apply(linestring, m_strategy);
|
||||
}
|
||||
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename Strategy>
|
||||
static inline bool apply(MultiLinestring const& multilinestring,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef per_linestring<Strategy> per_ls;
|
||||
|
||||
// check each of the linestrings for simplicity
|
||||
// but do not compute self-intersections yet; these will be
|
||||
// computed for the entire multilinestring
|
||||
if ( ! detail::check_iterator_range
|
||||
<
|
||||
is_simple_linestring
|
||||
<
|
||||
typename boost::range_value<MultiLinestring>::type,
|
||||
false // do not compute self-intersections
|
||||
>,
|
||||
per_ls, // do not compute self-intersections
|
||||
true // allow empty multilinestring
|
||||
>::apply(boost::begin(multilinestring),
|
||||
boost::end(multilinestring))
|
||||
boost::end(multilinestring),
|
||||
per_ls(strategy))
|
||||
)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014, 2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -19,6 +20,7 @@
|
||||
|
||||
#include <boost/core/addressof.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
@@ -221,9 +223,11 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_TEST_DEBUG
|
||||
template <typename OStream, typename TP>
|
||||
friend inline
|
||||
void debug_print_complement_graph(OStream&, complement_graph<TP> const&);
|
||||
#endif // BOOST_GEOMETRY_TEST_DEBUG
|
||||
|
||||
private:
|
||||
std::size_t m_num_rings, m_num_turns;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014, 2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -14,6 +15,8 @@
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#include <boost/geometry/algorithms/detail/is_valid/complement_graph.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014, 2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -12,11 +13,10 @@
|
||||
|
||||
#ifdef GEOMETRY_TEST_DEBUG
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
@@ -15,15 +15,17 @@
|
||||
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
#include <boost/geometry/algorithms/validity_failure_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
#include <boost/geometry/util/has_non_finite_coordinate.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/point_iterator.hpp>
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
|
||||
#include <boost/geometry/util/has_non_finite_coordinate.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -91,8 +92,9 @@ struct has_spikes
|
||||
return std::find_if(second, last, not_equal(*first));
|
||||
}
|
||||
|
||||
template <typename VisitPolicy>
|
||||
static inline bool apply(Range const& range, VisitPolicy& visitor)
|
||||
template <typename VisitPolicy, typename SideStrategy>
|
||||
static inline bool apply(Range const& range, VisitPolicy& visitor,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
boost::ignore_unused(visitor);
|
||||
|
||||
@@ -124,9 +126,11 @@ struct has_spikes
|
||||
|
||||
while (next != boost::end(view))
|
||||
{
|
||||
if ( geometry::detail::point_is_spike_or_equal(*prev,
|
||||
*next,
|
||||
*cur) )
|
||||
// Verify spike. TODO: this is a reverse order from expected
|
||||
// in is_spike_or_equal, but this order calls the side
|
||||
// strategy in the way to correctly detect the spikes,
|
||||
// also in geographic cases going over the pole
|
||||
if (detail::is_spike_or_equal(*next, *cur, *prev, strategy))
|
||||
{
|
||||
return
|
||||
! visitor.template apply<failure_spikes>(is_linear, *cur);
|
||||
@@ -146,7 +150,7 @@ struct has_spikes
|
||||
boost::rend(view));
|
||||
|
||||
iterator next = find_different_from_first(cur, boost::end(view));
|
||||
if (detail::point_is_spike_or_equal(*prev, *next, *cur))
|
||||
if (detail::is_spike_or_equal(*next, *cur, *prev, strategy))
|
||||
{
|
||||
return
|
||||
! visitor.template apply<failure_spikes>(is_linear, *cur);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
@@ -16,6 +16,12 @@
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
|
||||
#include <boost/geometry/algorithms/validity_failure_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
|
||||
@@ -23,12 +29,6 @@
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
IsAcceptableTurn
|
||||
> interrupt_policy;
|
||||
|
||||
geometry::self_turns<turn_policy>(geometry,
|
||||
detail::self_get_turn_points::self_turns<false, turn_policy>(geometry,
|
||||
strategy,
|
||||
robust_policy,
|
||||
turns,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
@@ -18,9 +18,9 @@
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/policies/is_valid/default_policy.hpp>
|
||||
#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>
|
||||
#include <boost/geometry/policies/is_valid/failure_type_policy.hpp>
|
||||
|
||||
@@ -138,10 +138,17 @@ public:
|
||||
}
|
||||
|
||||
operation_type const op = acceptable_operation<MultiPolygon>::value;
|
||||
if ( base::check_turn(turn, method_touch_interior, op)
|
||||
|| base::check_turn(turn, method_touch, op))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return base::check_turn(turn, method_touch_interior, op)
|
||||
|| base::check_turn(turn, method_touch, op)
|
||||
;
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -43,9 +43,10 @@ namespace detail { namespace is_valid
|
||||
template <typename Linestring>
|
||||
struct is_valid_linestring
|
||||
{
|
||||
template <typename VisitPolicy>
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Linestring const& linestring,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (has_invalid_coordinate<Linestring>::apply(linestring, visitor))
|
||||
{
|
||||
@@ -75,15 +76,12 @@ struct is_valid_linestring
|
||||
{
|
||||
return visitor.template apply<no_failure>();
|
||||
}
|
||||
return ! has_spikes<Linestring, closed>::apply(linestring, visitor);
|
||||
}
|
||||
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Linestring const& linestring,
|
||||
VisitPolicy& visitor,
|
||||
Strategy const&)
|
||||
{
|
||||
return apply(linestring, visitor);
|
||||
return ! has_spikes
|
||||
<
|
||||
Linestring, closed
|
||||
>::apply(linestring, visitor,
|
||||
strategy.get_side_strategy());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -132,10 +130,13 @@ class is_valid
|
||||
>
|
||||
{
|
||||
private:
|
||||
template <typename VisitPolicy>
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
struct per_linestring
|
||||
{
|
||||
per_linestring(VisitPolicy& policy) : m_policy(policy) {}
|
||||
per_linestring(VisitPolicy& policy, Strategy const& strategy)
|
||||
: m_policy(policy)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Linestring>
|
||||
inline bool apply(Linestring const& linestring) const
|
||||
@@ -143,17 +144,18 @@ private:
|
||||
return detail::is_valid::is_valid_linestring
|
||||
<
|
||||
Linestring
|
||||
>::apply(linestring, m_policy);
|
||||
>::apply(linestring, m_policy, m_strategy);
|
||||
}
|
||||
|
||||
VisitPolicy& m_policy;
|
||||
Strategy const& m_strategy;
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(MultiLinestring const& multilinestring,
|
||||
VisitPolicy& visitor,
|
||||
Strategy const&)
|
||||
Strategy const& strategy)
|
||||
{
|
||||
if (BOOST_GEOMETRY_CONDITION(
|
||||
AllowEmptyMultiGeometries && boost::empty(multilinestring)))
|
||||
@@ -161,13 +163,15 @@ public:
|
||||
return visitor.template apply<no_failure>();
|
||||
}
|
||||
|
||||
typedef per_linestring<VisitPolicy, Strategy> per_ls;
|
||||
|
||||
return detail::check_iterator_range
|
||||
<
|
||||
per_linestring<VisitPolicy>,
|
||||
per_ls,
|
||||
false // do not check for empty multilinestring (done above)
|
||||
>::apply(boost::begin(multilinestring),
|
||||
boost::end(multilinestring),
|
||||
per_linestring<VisitPolicy>(visitor));
|
||||
per_ls(visitor, strategy));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -76,45 +76,59 @@ private:
|
||||
<
|
||||
typename PolygonIterator,
|
||||
typename TurnIterator,
|
||||
typename VisitPolicy
|
||||
typename VisitPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline
|
||||
bool are_polygon_interiors_disjoint(PolygonIterator polygons_first,
|
||||
PolygonIterator polygons_beyond,
|
||||
TurnIterator turns_first,
|
||||
TurnIterator turns_beyond,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
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;
|
||||
typedef typename base::template partition_item<PolygonIterator, box_type> item_type;
|
||||
|
||||
// put polygon iterators without turns in a vector
|
||||
std::vector<PolygonIterator> polygon_iterators;
|
||||
std::vector<item_type> polygon_iterators;
|
||||
signed_size_type multi_index = 0;
|
||||
for (PolygonIterator it = polygons_first; it != polygons_beyond;
|
||||
++it, ++multi_index)
|
||||
{
|
||||
if (multi_indices.find(multi_index) == multi_indices.end())
|
||||
{
|
||||
polygon_iterators.push_back(it);
|
||||
polygon_iterators.push_back(item_type(it));
|
||||
}
|
||||
}
|
||||
|
||||
typename base::item_visitor_type item_visitor;
|
||||
// prepare strategies
|
||||
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
|
||||
envelope_strategy_type const envelope_strategy
|
||||
= strategy.get_envelope_strategy();
|
||||
|
||||
// call partition to check if polygons are disjoint from each other
|
||||
typename base::template item_visitor_type<Strategy> item_visitor(strategy);
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
geometry::model::box<typename point_type<MultiPolygon>::type>
|
||||
>::apply(polygon_iterators, item_visitor,
|
||||
typename base::expand_box(),
|
||||
typename base::overlaps_box());
|
||||
typename base::template expand_box<envelope_strategy_type>(envelope_strategy),
|
||||
typename base::template overlaps_box<envelope_strategy_type>(envelope_strategy));
|
||||
|
||||
if (item_visitor.items_overlap)
|
||||
{
|
||||
@@ -155,13 +169,15 @@ private:
|
||||
<
|
||||
typename PolygonIterator,
|
||||
typename TurnIterator,
|
||||
typename VisitPolicy
|
||||
typename VisitPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool apply(PolygonIterator polygons_first,
|
||||
PolygonIterator polygons_beyond,
|
||||
TurnIterator turns_first,
|
||||
TurnIterator turns_beyond,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
signed_size_type multi_index = 0;
|
||||
for (PolygonIterator it = polygons_first; it != polygons_beyond;
|
||||
@@ -185,7 +201,8 @@ private:
|
||||
if (! Predicate::apply(*it,
|
||||
filtered_turns_first,
|
||||
filtered_turns_beyond,
|
||||
visitor))
|
||||
visitor,
|
||||
strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -200,19 +217,21 @@ private:
|
||||
<
|
||||
typename PolygonIterator,
|
||||
typename TurnIterator,
|
||||
typename VisitPolicy
|
||||
typename VisitPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool have_holes_inside(PolygonIterator polygons_first,
|
||||
PolygonIterator polygons_beyond,
|
||||
TurnIterator turns_first,
|
||||
TurnIterator turns_beyond,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return has_property_per_polygon
|
||||
<
|
||||
typename base::has_holes_inside
|
||||
>::apply(polygons_first, polygons_beyond,
|
||||
turns_first, turns_beyond, visitor);
|
||||
turns_first, turns_beyond, visitor, strategy);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,19 +240,21 @@ private:
|
||||
<
|
||||
typename PolygonIterator,
|
||||
typename TurnIterator,
|
||||
typename VisitPolicy
|
||||
typename VisitPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool have_connected_interior(PolygonIterator polygons_first,
|
||||
PolygonIterator polygons_beyond,
|
||||
TurnIterator turns_first,
|
||||
TurnIterator turns_beyond,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return has_property_per_polygon
|
||||
<
|
||||
typename base::has_connected_interior
|
||||
>::apply(polygons_first, polygons_beyond,
|
||||
turns_first, turns_beyond, visitor);
|
||||
turns_first, turns_beyond, visitor, strategy);
|
||||
}
|
||||
|
||||
|
||||
@@ -307,7 +328,8 @@ public:
|
||||
boost::end(multipolygon),
|
||||
turns.begin(),
|
||||
turns.end(),
|
||||
visitor))
|
||||
visitor,
|
||||
strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -320,7 +342,8 @@ public:
|
||||
boost::end(multipolygon),
|
||||
turns.begin(),
|
||||
turns.end(),
|
||||
visitor))
|
||||
visitor,
|
||||
strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -332,7 +355,8 @@ public:
|
||||
boost::end(multipolygon),
|
||||
turns.begin(),
|
||||
turns.end(),
|
||||
visitor);
|
||||
visitor,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
@@ -43,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>
|
||||
@@ -142,43 +145,96 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
// Iterator value_type is a Ring or Polygon
|
||||
template <typename Iterator, typename Box>
|
||||
struct partition_item
|
||||
{
|
||||
explicit partition_item(Iterator it)
|
||||
: m_it(it)
|
||||
, m_is_initialized(false)
|
||||
{}
|
||||
|
||||
Iterator get() const
|
||||
{
|
||||
return m_it;
|
||||
}
|
||||
|
||||
template <typename EnvelopeStrategy>
|
||||
Box const& get_envelope(EnvelopeStrategy const& strategy) const
|
||||
{
|
||||
if (! m_is_initialized)
|
||||
{
|
||||
m_box = geometry::return_envelope<Box>(*m_it, strategy);
|
||||
m_is_initialized = true;
|
||||
}
|
||||
return m_box;
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator m_it;
|
||||
mutable Box m_box;
|
||||
mutable bool m_is_initialized;
|
||||
};
|
||||
|
||||
// structs for partition -- start
|
||||
template <typename EnvelopeStrategy>
|
||||
struct expand_box
|
||||
{
|
||||
explicit expand_box(EnvelopeStrategy const& strategy) : m_strategy(strategy) {}
|
||||
|
||||
template <typename Box, typename Iterator>
|
||||
static inline void apply(Box& total, Iterator const& it)
|
||||
inline void apply(Box& total, partition_item<Iterator, Box> const& item) const
|
||||
{
|
||||
geometry::expand(total, geometry::return_envelope<Box>(*it));
|
||||
geometry::expand(total, item.get_envelope(m_strategy));
|
||||
}
|
||||
|
||||
EnvelopeStrategy const& m_strategy;
|
||||
};
|
||||
|
||||
template <typename EnvelopeStrategy>
|
||||
struct overlaps_box
|
||||
{
|
||||
explicit overlaps_box(EnvelopeStrategy const& strategy) : m_strategy(strategy) {}
|
||||
|
||||
template <typename Box, typename Iterator>
|
||||
static inline bool apply(Box const& box, Iterator const& it)
|
||||
inline bool apply(Box const& box, partition_item<Iterator, Box> const& item) const
|
||||
{
|
||||
return ! geometry::disjoint(*it, box);
|
||||
return ! geometry::disjoint(item.get_envelope(m_strategy), box);
|
||||
}
|
||||
|
||||
EnvelopeStrategy const& m_strategy;
|
||||
};
|
||||
|
||||
|
||||
template <typename WithinStrategy>
|
||||
struct item_visitor_type
|
||||
{
|
||||
bool items_overlap;
|
||||
WithinStrategy const& m_strategy;
|
||||
|
||||
item_visitor_type() : items_overlap(false) {}
|
||||
explicit item_visitor_type(WithinStrategy const& strategy)
|
||||
: items_overlap(false)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Item1, typename Item2>
|
||||
inline void apply(Item1 const& item1, Item2 const& item2)
|
||||
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), *item2)
|
||||
|| geometry::within(*points_begin(*item2), *item1))
|
||||
)
|
||||
typedef boost::mpl::vector
|
||||
<
|
||||
geometry::de9im::static_mask<'T'>,
|
||||
geometry::de9im::static_mask<'*', 'T'>,
|
||||
geometry::de9im::static_mask<'*', '*', '*', 'T'>
|
||||
> relate_mask_t;
|
||||
|
||||
if ( ! items_overlap
|
||||
&& geometry::relate(*item1.get(), *item2.get(), relate_mask_t(), m_strategy) )
|
||||
{
|
||||
items_overlap = true;
|
||||
return false; // interrupt
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
// structs for partition -- end
|
||||
@@ -189,14 +245,16 @@ protected:
|
||||
typename RingIterator,
|
||||
typename ExteriorRing,
|
||||
typename TurnIterator,
|
||||
typename VisitPolicy
|
||||
typename VisitPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool are_holes_inside(RingIterator rings_first,
|
||||
RingIterator rings_beyond,
|
||||
ExteriorRing const& exterior_ring,
|
||||
TurnIterator turns_first,
|
||||
TurnIterator turns_beyond,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::ignore_unused(visitor);
|
||||
|
||||
@@ -217,6 +275,14 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
// prepare strategy
|
||||
typedef typename std::iterator_traits<RingIterator>::value_type inter_ring_type;
|
||||
typename Strategy::template point_in_geometry_strategy
|
||||
<
|
||||
inter_ring_type, ExteriorRing
|
||||
>::type const in_exterior_strategy
|
||||
= strategy.template get_point_in_geometry_strategy<inter_ring_type, ExteriorRing>();
|
||||
|
||||
signed_size_type ring_index = 0;
|
||||
for (RingIterator it = rings_first; it != rings_beyond;
|
||||
++it, ++ring_index)
|
||||
@@ -224,7 +290,7 @@ protected:
|
||||
// do not examine interior rings that have turns with the
|
||||
// exterior ring
|
||||
if (ring_indices.find(ring_index) == ring_indices.end()
|
||||
&& ! geometry::covered_by(range::front(*it), exterior_ring))
|
||||
&& ! geometry::covered_by(range::front(*it), exterior_ring, in_exterior_strategy))
|
||||
{
|
||||
return visitor.template apply<failure_interior_rings_outside>();
|
||||
}
|
||||
@@ -237,26 +303,36 @@ protected:
|
||||
ring_indices.insert(tit->operations[1].seg_id.ring_index);
|
||||
}
|
||||
|
||||
typedef geometry::model::box<typename point_type<Polygon>::type> box_type;
|
||||
typedef partition_item<RingIterator, box_type> item_type;
|
||||
|
||||
// put iterators for interior rings without turns in a vector
|
||||
std::vector<RingIterator> ring_iterators;
|
||||
std::vector<item_type> ring_iterators;
|
||||
ring_index = 0;
|
||||
for (RingIterator it = rings_first; it != rings_beyond;
|
||||
++it, ++ring_index)
|
||||
{
|
||||
if (ring_indices.find(ring_index) == ring_indices.end())
|
||||
{
|
||||
ring_iterators.push_back(it);
|
||||
ring_iterators.push_back(item_type(it));
|
||||
}
|
||||
}
|
||||
|
||||
// call partition to check is interior rings are disjoint from
|
||||
// prepare strategies
|
||||
typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
|
||||
envelope_strategy_type const envelope_strategy
|
||||
= strategy.get_envelope_strategy();
|
||||
|
||||
// call partition to check if interior rings are disjoint from
|
||||
// each other
|
||||
item_visitor_type item_visitor;
|
||||
item_visitor_type<Strategy> item_visitor(strategy);
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
geometry::model::box<typename point_type<Polygon>::type>
|
||||
>::apply(ring_iterators, item_visitor, expand_box(), overlaps_box());
|
||||
box_type
|
||||
>::apply(ring_iterators, item_visitor,
|
||||
expand_box<envelope_strategy_type>(envelope_strategy),
|
||||
overlaps_box<envelope_strategy_type>(envelope_strategy));
|
||||
|
||||
if (item_visitor.items_overlap)
|
||||
{
|
||||
@@ -273,35 +349,40 @@ protected:
|
||||
typename InteriorRings,
|
||||
typename ExteriorRing,
|
||||
typename TurnIterator,
|
||||
typename VisitPolicy
|
||||
typename VisitPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool are_holes_inside(InteriorRings const& interior_rings,
|
||||
ExteriorRing const& exterior_ring,
|
||||
TurnIterator first,
|
||||
TurnIterator beyond,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return are_holes_inside(boost::begin(interior_rings),
|
||||
boost::end(interior_rings),
|
||||
exterior_ring,
|
||||
first,
|
||||
beyond,
|
||||
visitor);
|
||||
visitor,
|
||||
strategy);
|
||||
}
|
||||
|
||||
struct has_holes_inside
|
||||
{
|
||||
template <typename TurnIterator, typename VisitPolicy>
|
||||
template <typename TurnIterator, typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Polygon const& polygon,
|
||||
TurnIterator first,
|
||||
TurnIterator beyond,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return are_holes_inside(geometry::interior_rings(polygon),
|
||||
geometry::exterior_ring(polygon),
|
||||
first,
|
||||
beyond,
|
||||
visitor);
|
||||
visitor,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -310,11 +391,12 @@ protected:
|
||||
|
||||
struct has_connected_interior
|
||||
{
|
||||
template <typename TurnIterator, typename VisitPolicy>
|
||||
template <typename TurnIterator, typename VisitPolicy, typename Strategy>
|
||||
static inline bool apply(Polygon const& polygon,
|
||||
TurnIterator first,
|
||||
TurnIterator beyond,
|
||||
VisitPolicy& visitor)
|
||||
VisitPolicy& visitor,
|
||||
Strategy const& )
|
||||
{
|
||||
boost::ignore_unused(visitor);
|
||||
|
||||
@@ -388,7 +470,8 @@ public:
|
||||
|
||||
if (! has_holes_inside::apply(polygon,
|
||||
turns.begin(), turns.end(),
|
||||
visitor))
|
||||
visitor,
|
||||
strategy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -399,7 +482,8 @@ public:
|
||||
return has_connected_interior::apply(polygon,
|
||||
turns.begin(),
|
||||
turns.end(),
|
||||
visitor);
|
||||
visitor,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
@@ -18,6 +20,7 @@
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/order_as_direction.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
@@ -34,6 +37,7 @@
|
||||
#include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>
|
||||
#include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>
|
||||
#include <boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp>
|
||||
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/area.hpp>
|
||||
|
||||
@@ -107,15 +111,16 @@ struct is_properly_oriented
|
||||
{
|
||||
boost::ignore_unused(visitor);
|
||||
|
||||
typedef typename point_type<Ring>::type point_type;
|
||||
|
||||
typedef detail::area::ring_area
|
||||
<
|
||||
order_as_direction<geometry::point_order<Ring>::value>::value,
|
||||
geometry::closure<Ring>::value
|
||||
> ring_area_type;
|
||||
|
||||
typedef typename default_area_result<Ring>::type area_result_type;
|
||||
typedef typename Strategy::template area_strategy
|
||||
<
|
||||
Ring
|
||||
>::type::template result_type<Ring>::type area_result_type;
|
||||
|
||||
typename ring_area_predicate
|
||||
<
|
||||
@@ -126,7 +131,7 @@ struct is_properly_oriented
|
||||
area_result_type const zero = 0;
|
||||
area_result_type const area
|
||||
= ring_area_type::apply(ring,
|
||||
strategy.template get_area_strategy<point_type>());
|
||||
strategy.template get_area_strategy<Ring>());
|
||||
if (predicate(area, zero))
|
||||
{
|
||||
return visitor.template apply<no_failure>();
|
||||
@@ -195,7 +200,7 @@ struct is_valid_ring
|
||||
return
|
||||
is_topologically_closed<Ring, closure>::apply(ring, visitor)
|
||||
&& ! has_duplicates<Ring, closure>::apply(ring, visitor)
|
||||
&& ! has_spikes<Ring, closure>::apply(ring, visitor)
|
||||
&& ! has_spikes<Ring, closure>::apply(ring, visitor, strategy.get_side_strategy())
|
||||
&& (! CheckSelfIntersections
|
||||
|| has_valid_self_turns<Ring>::apply(ring, visitor, strategy))
|
||||
&& is_properly_oriented<Ring, IsInteriorRing>::apply(ring, visitor, strategy);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -10,278 +11,31 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NORMALIZE_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||
#include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
// For backward compatibility
|
||||
#include <boost/geometry/strategies/normalize.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace normalization
|
||||
{
|
||||
|
||||
|
||||
struct do_nothing
|
||||
{
|
||||
template <typename GeometryIn, typename GeometryOut>
|
||||
static inline void apply(GeometryIn const&, GeometryOut&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct assign_loop
|
||||
{
|
||||
template <typename CoordinateType, typename PointIn, typename PointOut>
|
||||
static inline void apply(CoordinateType const& longitude,
|
||||
CoordinateType const& latitude,
|
||||
PointIn const& point_in,
|
||||
PointOut& point_out)
|
||||
{
|
||||
geometry::set<Dimension>(point_out, boost::numeric_cast
|
||||
<
|
||||
typename coordinate_type<PointOut>::type
|
||||
>(geometry::get<Dimension>(point_in)));
|
||||
|
||||
assign_loop
|
||||
<
|
||||
Dimension + 1, DimensionCount
|
||||
>::apply(longitude, latitude, point_in, point_out);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t DimensionCount>
|
||||
struct assign_loop<DimensionCount, DimensionCount>
|
||||
{
|
||||
template <typename CoordinateType, typename PointIn, typename PointOut>
|
||||
static inline void apply(CoordinateType const&,
|
||||
CoordinateType const&,
|
||||
PointIn const&,
|
||||
PointOut&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t DimensionCount>
|
||||
struct assign_loop<0, DimensionCount>
|
||||
{
|
||||
template <typename CoordinateType, typename PointIn, typename PointOut>
|
||||
static inline void apply(CoordinateType const& longitude,
|
||||
CoordinateType const& latitude,
|
||||
PointIn const& point_in,
|
||||
PointOut& point_out)
|
||||
{
|
||||
geometry::set<0>(point_out, boost::numeric_cast
|
||||
<
|
||||
typename coordinate_type<PointOut>::type
|
||||
>(longitude));
|
||||
|
||||
assign_loop
|
||||
<
|
||||
1, DimensionCount
|
||||
>::apply(longitude, latitude, point_in, point_out);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t DimensionCount>
|
||||
struct assign_loop<1, DimensionCount>
|
||||
{
|
||||
template <typename CoordinateType, typename PointIn, typename PointOut>
|
||||
static inline void apply(CoordinateType const& longitude,
|
||||
CoordinateType const& latitude,
|
||||
PointIn const& point_in,
|
||||
PointOut& point_out)
|
||||
{
|
||||
geometry::set<1>(point_out, boost::numeric_cast
|
||||
<
|
||||
typename coordinate_type<PointOut>::type
|
||||
>(latitude));
|
||||
|
||||
assign_loop
|
||||
<
|
||||
2, DimensionCount
|
||||
>::apply(longitude, latitude, point_in, point_out);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename PointIn, typename PointOut>
|
||||
struct normalize_point
|
||||
{
|
||||
static inline void apply(PointIn const& point_in, PointOut& point_out)
|
||||
{
|
||||
typedef typename coordinate_type<PointIn>::type in_coordinate_type;
|
||||
|
||||
in_coordinate_type longitude = geometry::get<0>(point_in);
|
||||
in_coordinate_type latitude = geometry::get<1>(point_in);
|
||||
|
||||
math::normalize_spheroidal_coordinates
|
||||
<
|
||||
typename coordinate_system<PointIn>::type::units,
|
||||
in_coordinate_type
|
||||
>(longitude, latitude);
|
||||
|
||||
assign_loop
|
||||
<
|
||||
0, dimension<PointIn>::value
|
||||
>::apply(longitude, latitude, point_in, point_out);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
class normalize_box
|
||||
{
|
||||
template <typename UnitsIn, typename UnitsOut, typename CoordinateInType>
|
||||
static inline void apply_to_coordinates(CoordinateInType& lon_min,
|
||||
CoordinateInType& lat_min,
|
||||
CoordinateInType& lon_max,
|
||||
CoordinateInType& lat_max,
|
||||
BoxIn const& box_in,
|
||||
BoxOut& box_out)
|
||||
{
|
||||
detail::indexed_point_view<BoxOut, min_corner> p_min_out(box_out);
|
||||
assign_loop
|
||||
<
|
||||
0, dimension<BoxIn>::value
|
||||
>::apply(lon_min,
|
||||
lat_min,
|
||||
detail::indexed_point_view
|
||||
<
|
||||
BoxIn const, min_corner
|
||||
>(box_in),
|
||||
p_min_out);
|
||||
|
||||
detail::indexed_point_view<BoxOut, max_corner> p_max_out(box_out);
|
||||
assign_loop
|
||||
<
|
||||
0, dimension<BoxIn>::value
|
||||
>::apply(lon_max,
|
||||
lat_max,
|
||||
detail::indexed_point_view
|
||||
<
|
||||
BoxIn const, max_corner
|
||||
>(box_in),
|
||||
p_max_out);
|
||||
}
|
||||
|
||||
public:
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& box_out)
|
||||
{
|
||||
typedef typename coordinate_type<BoxIn>::type in_coordinate_type;
|
||||
|
||||
in_coordinate_type lon_min = geometry::get<min_corner, 0>(box_in);
|
||||
in_coordinate_type lat_min = geometry::get<min_corner, 1>(box_in);
|
||||
in_coordinate_type lon_max = geometry::get<max_corner, 0>(box_in);
|
||||
in_coordinate_type lat_max = geometry::get<max_corner, 1>(box_in);
|
||||
|
||||
math::normalize_spheroidal_box_coordinates
|
||||
<
|
||||
typename coordinate_system<BoxIn>::type::units,
|
||||
in_coordinate_type
|
||||
>(lon_min, lat_min, lon_max, lat_max);
|
||||
|
||||
apply_to_coordinates
|
||||
<
|
||||
typename coordinate_system<BoxIn>::type::units,
|
||||
typename coordinate_system<BoxOut>::type::units
|
||||
>(lon_min, lat_min, lon_max, lat_max, box_in, box_out);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::normalization
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename GeometryIn,
|
||||
typename GeometryOut,
|
||||
typename TagIn = typename tag<GeometryIn>::type,
|
||||
typename TagOut = typename tag<GeometryOut>::type,
|
||||
typename CSTagIn = typename cs_tag<GeometryIn>::type,
|
||||
typename CSTagOut = typename cs_tag<GeometryOut>::type
|
||||
>
|
||||
struct normalize : detail::normalization::do_nothing
|
||||
{};
|
||||
|
||||
|
||||
template <typename PointIn, typename PointOut>
|
||||
struct normalize
|
||||
<
|
||||
PointIn, PointOut, point_tag, point_tag,
|
||||
spherical_equatorial_tag, spherical_equatorial_tag
|
||||
> : detail::normalization::normalize_point<PointIn, PointOut>
|
||||
{};
|
||||
|
||||
|
||||
template <typename PointIn, typename PointOut>
|
||||
struct normalize
|
||||
<
|
||||
PointIn, PointOut, point_tag, point_tag, geographic_tag, geographic_tag
|
||||
> : detail::normalization::normalize_point<PointIn, PointOut>
|
||||
{};
|
||||
|
||||
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
struct normalize
|
||||
<
|
||||
BoxIn, BoxOut, box_tag, box_tag,
|
||||
spherical_equatorial_tag, spherical_equatorial_tag
|
||||
> : detail::normalization::normalize_box<BoxIn, BoxOut>
|
||||
{};
|
||||
|
||||
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
struct normalize
|
||||
<
|
||||
BoxIn, BoxOut, box_tag, box_tag, geographic_tag, geographic_tag
|
||||
> : detail::normalization::normalize_box<BoxIn, BoxOut>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
|
||||
template <typename GeometryIn, typename GeometryOut>
|
||||
inline void normalize(GeometryIn const& geometry_in, GeometryOut& geometry_out)
|
||||
template <typename GeometryIn, typename GeometryOut, typename Strategy>
|
||||
inline void normalize(GeometryIn const& geometry_in, GeometryOut& geometry_out, Strategy const& )
|
||||
{
|
||||
dispatch::normalize
|
||||
<
|
||||
GeometryIn, GeometryOut
|
||||
>::apply(geometry_in, geometry_out);
|
||||
Strategy::apply(geometry_in, geometry_out);
|
||||
}
|
||||
|
||||
template <typename GeometryOut, typename GeometryIn>
|
||||
inline GeometryOut return_normalized(GeometryIn const& geometry_in)
|
||||
template <typename GeometryOut, typename GeometryIn, typename Strategy>
|
||||
inline GeometryOut return_normalized(GeometryIn const& geometry_in, Strategy const& strategy)
|
||||
{
|
||||
GeometryOut geometry_out;
|
||||
detail::normalize(geometry_in, geometry_out);
|
||||
detail::normalize(geometry_in, geometry_out, strategy);
|
||||
return geometry_out;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// Copyright (c) 2012-2014 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)
|
||||
@@ -99,12 +104,18 @@ public :
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RobustPoint, typename Turns>
|
||||
inline void get_left_turns(RobustPoint const& origin, Turns& turns)
|
||||
template <typename RobustPoint, typename Turns, typename SideStrategy>
|
||||
inline void get_left_turns(RobustPoint const& origin, Turns& turns,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
typedef detail::left_turns::angle_less
|
||||
<
|
||||
typename AngleInfo::point_type,
|
||||
SideStrategy
|
||||
> angle_less;
|
||||
|
||||
// Sort on angle
|
||||
std::sort(m_angles.begin(), m_angles.end(),
|
||||
detail::left_turns::angle_less<typename AngleInfo::point_type>(origin));
|
||||
std::sort(m_angles.begin(), m_angles.end(), angle_less(origin, strategy));
|
||||
|
||||
// Group same-angled elements
|
||||
std::size_t cluster_size = detail::left_turns::assign_cluster_indices(m_angles, origin);
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2015, 2017.
|
||||
// Modifications copyright (c) 2014-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.
|
||||
|
||||
// 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_ALGORITHMS_DETAIL_OVERLAPS_IMPLEMENTATION_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_IMPLEMENTATION_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/relate.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace overlaps
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct box_box_loop
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline void apply(Box1 const& b1, Box2 const& b2,
|
||||
bool& overlaps, bool& one_in_two, bool& two_in_one)
|
||||
{
|
||||
assert_dimension_equal<Box1, Box2>();
|
||||
|
||||
typedef typename coordinate_type<Box1>::type coordinate_type1;
|
||||
typedef typename coordinate_type<Box2>::type coordinate_type2;
|
||||
|
||||
coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
|
||||
coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
|
||||
coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
|
||||
coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
|
||||
|
||||
// We might use the (not yet accepted) Boost.Interval
|
||||
// submission in the future
|
||||
|
||||
// If:
|
||||
// B1: |-------|
|
||||
// B2: |------|
|
||||
// in any dimension -> no overlap
|
||||
if (max1 <= min2 || min1 >= max2)
|
||||
{
|
||||
overlaps = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// If:
|
||||
// B1: |--------------------|
|
||||
// B2: |-------------|
|
||||
// in all dimensions -> within, then no overlap
|
||||
// B1: |--------------------|
|
||||
// B2: |-------------|
|
||||
// this is "within-touch" -> then no overlap. So use < and >
|
||||
if (min1 < min2 || max1 > max2)
|
||||
{
|
||||
one_in_two = false;
|
||||
}
|
||||
|
||||
// Same other way round
|
||||
if (min2 < min1 || max2 > max1)
|
||||
{
|
||||
two_in_one = false;
|
||||
}
|
||||
|
||||
box_box_loop
|
||||
<
|
||||
Dimension + 1,
|
||||
DimensionCount
|
||||
>::apply(b1, b2, overlaps, one_in_two, two_in_one);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct box_box_loop<DimensionCount, DimensionCount>
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct box_box
|
||||
{
|
||||
template <typename Box1, typename Box2, typename Strategy>
|
||||
static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
|
||||
{
|
||||
bool overlaps = true;
|
||||
bool within1 = true;
|
||||
bool within2 = true;
|
||||
box_box_loop
|
||||
<
|
||||
0,
|
||||
dimension<Box1>::type::value
|
||||
>::apply(b1, b2, overlaps, within1, within2);
|
||||
|
||||
/*
|
||||
\see http://docs.codehaus.org/display/GEOTDOC/02+Geometry+Relationships#02GeometryRelationships-Overlaps
|
||||
where is stated that "inside" is not an "overlap",
|
||||
this is true and is implemented as such.
|
||||
*/
|
||||
return overlaps && ! within1 && ! within2;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::overlaps
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Box1, typename Box2>
|
||||
struct overlaps<Box1, Box2, box_tag, box_tag>
|
||||
: detail::overlaps::box_box
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_IMPLEMENTATION_HPP
|
||||
@@ -0,0 +1,124 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2015, 2017.
|
||||
// Modifications copyright (c) 2014-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.
|
||||
|
||||
// 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_ALGORITHMS_DETAIL_OVERLAPS_INTERFACE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_INTERFACE_HPP
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/relate.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Tag1 = typename tag<Geometry1>::type,
|
||||
typename Tag2 = typename tag<Geometry2>::type
|
||||
>
|
||||
struct overlaps
|
||||
: detail::relate::relate_impl
|
||||
<
|
||||
detail::de9im::static_mask_overlaps_type,
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
/*!
|
||||
\brief \brief_check2{overlap}
|
||||
\ingroup overlaps
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Overlaps}
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\param strategy \param_strategy{overlaps}
|
||||
\return \return_check2{overlap}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
\qbk{[include reference/algorithms/overlaps.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2, typename Strategy>
|
||||
inline bool overlaps(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
return dispatch::overlaps
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, strategy);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief \brief_check2{overlap}
|
||||
\ingroup overlaps
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\param geometry1 \param_geometry
|
||||
\param geometry2 \param_geometry
|
||||
\return \return_check2{overlap}
|
||||
|
||||
\qbk{[include reference/algorithms/overlaps.qbk]}
|
||||
*/
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
{
|
||||
concepts::check<Geometry1 const>();
|
||||
concepts::check<Geometry2 const>();
|
||||
|
||||
typedef typename strategy::relate::services::default_strategy
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::type strategy_type;
|
||||
|
||||
return dispatch::overlaps
|
||||
<
|
||||
Geometry1,
|
||||
Geometry2
|
||||
>::apply(geometry1, geometry2, strategy_type());
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_INTERFACE_HPP
|
||||
@@ -1,6 +1,12 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 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
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -10,8 +16,10 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/exception.hpp>
|
||||
#include <boost/geometry/algorithms/area.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/convert_ring.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
|
||||
@@ -62,6 +70,13 @@ inline void convert_and_add(GeometryOut& result,
|
||||
}
|
||||
}
|
||||
|
||||
enum add_rings_error_handling
|
||||
{
|
||||
add_rings_ignore_unordered,
|
||||
add_rings_add_unordered,
|
||||
add_rings_throw_if_reversed
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename GeometryOut,
|
||||
@@ -69,16 +84,21 @@ template
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename RingCollection,
|
||||
typename OutputIterator
|
||||
typename OutputIterator,
|
||||
typename AreaStrategy
|
||||
>
|
||||
inline OutputIterator add_rings(SelectionMap const& map,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
RingCollection const& collection,
|
||||
OutputIterator out)
|
||||
OutputIterator out,
|
||||
AreaStrategy const& area_strategy,
|
||||
add_rings_error_handling error_handling = add_rings_ignore_unordered)
|
||||
{
|
||||
typedef typename SelectionMap::const_iterator iterator;
|
||||
typedef typename SelectionMap::mapped_type property_type;
|
||||
typedef typename property_type::area_type area_type;
|
||||
typedef typename AreaStrategy::template result_type
|
||||
<
|
||||
GeometryOut
|
||||
>::type area_type;
|
||||
|
||||
area_type const zero = 0;
|
||||
std::size_t const min_num_points = core_detail::closure::minimum_ring_size
|
||||
@@ -122,10 +142,22 @@ inline OutputIterator add_rings(SelectionMap const& map,
|
||||
// Only add rings if they satisfy minimal requirements.
|
||||
// This cannot be done earlier (during traversal), not
|
||||
// everything is figured out yet (sum of positive/negative rings)
|
||||
if (geometry::num_points(result) >= min_num_points
|
||||
&& math::larger(geometry::area(result), zero))
|
||||
if (geometry::num_points(result) >= min_num_points)
|
||||
{
|
||||
*out++ = result;
|
||||
area_type const area = geometry::area(result, area_strategy);
|
||||
// Ignore if area is 0
|
||||
if (! math::equals(area, zero))
|
||||
{
|
||||
if (error_handling == add_rings_add_unordered
|
||||
|| area > zero)
|
||||
{
|
||||
*out++ = result;
|
||||
}
|
||||
else if (error_handling == add_rings_throw_if_reversed)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(invalid_output_exception());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,15 +171,17 @@ template
|
||||
typename SelectionMap,
|
||||
typename Geometry,
|
||||
typename RingCollection,
|
||||
typename OutputIterator
|
||||
typename OutputIterator,
|
||||
typename AreaStrategy
|
||||
>
|
||||
inline OutputIterator add_rings(SelectionMap const& map,
|
||||
Geometry const& geometry,
|
||||
RingCollection const& collection,
|
||||
OutputIterator out)
|
||||
OutputIterator out,
|
||||
AreaStrategy const& area_strategy)
|
||||
{
|
||||
Geometry empty;
|
||||
return add_rings<GeometryOut>(map, geometry, empty, collection, out);
|
||||
return add_rings<GeometryOut>(map, geometry, empty, collection, out, area_strategy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2016 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_ALGORITHMS_DETAIL_OVERLAY_AGGREGATE_OPERATIONS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_AGGREGATE_OPERATIONS_HPP
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace overlay { namespace sort_by_side
|
||||
{
|
||||
|
||||
struct ring_with_direction
|
||||
{
|
||||
ring_identifier ring_id;
|
||||
direction_type direction;
|
||||
bool only_turn_on_ring;
|
||||
|
||||
|
||||
inline bool operator<(ring_with_direction const& other) const
|
||||
{
|
||||
return this->ring_id != other.ring_id
|
||||
? this->ring_id < other.ring_id
|
||||
: this->direction < other.direction;
|
||||
}
|
||||
|
||||
ring_with_direction()
|
||||
: direction(dir_unknown)
|
||||
, only_turn_on_ring(false)
|
||||
{}
|
||||
};
|
||||
|
||||
struct rank_with_rings
|
||||
{
|
||||
std::size_t rank;
|
||||
std::set<ring_with_direction> rings;
|
||||
|
||||
rank_with_rings()
|
||||
: rank(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool all_to() const
|
||||
{
|
||||
for (std::set<ring_with_direction>::const_iterator it = rings.begin();
|
||||
it != rings.end(); ++it)
|
||||
{
|
||||
if (it->direction == sort_by_side::dir_from)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Sbs>
|
||||
inline void aggregate_operations(Sbs const& sbs, std::vector<rank_with_rings>& aggregation)
|
||||
{
|
||||
aggregation.clear();
|
||||
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
|
||||
{
|
||||
typename Sbs::rp const& ranked_point = sbs.m_ranked_points[i];
|
||||
|
||||
if (aggregation.empty() || aggregation.back().rank != ranked_point.rank)
|
||||
{
|
||||
rank_with_rings current;
|
||||
current.rank = ranked_point.rank;
|
||||
aggregation.push_back(current);
|
||||
}
|
||||
|
||||
ring_with_direction rwd;
|
||||
segment_identifier const& sid = ranked_point.seg_id;
|
||||
rwd.ring_id = ring_identifier(sid.source_index, sid.multi_index, sid.ring_index);
|
||||
rwd.direction = ranked_point.direction;
|
||||
rwd.only_turn_on_ring = ranked_point.only_turn_on_ring;
|
||||
|
||||
|
||||
aggregation.back().rings.insert(rwd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}} // namespace detail::overlay::sort_by_side
|
||||
#endif //DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_AGGREGATE_OPERATIONS_HPP
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2018.
|
||||
// Modifications copyright (c) 2018 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)
|
||||
@@ -10,11 +15,10 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP
|
||||
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/append.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -26,11 +30,24 @@ namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
template <typename Range, typename Point>
|
||||
inline void append_no_duplicates(Range& range, Point const& point, bool force = false)
|
||||
inline void append_with_duplicates(Range& range, Point const& point)
|
||||
{
|
||||
if (boost::size(range) == 0
|
||||
|| force
|
||||
|| ! geometry::detail::equals::equals_point_point(*(boost::end(range)-1), point))
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
|
||||
std::cout << " add: ("
|
||||
<< geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")"
|
||||
<< std::endl;
|
||||
#endif
|
||||
geometry::append(range, point);
|
||||
}
|
||||
|
||||
template <typename Range, typename Point, typename EqPPStrategy>
|
||||
inline void append_no_duplicates(Range& range, Point const& point,
|
||||
EqPPStrategy const& strategy)
|
||||
{
|
||||
if ( boost::empty(range)
|
||||
|| ! geometry::detail::equals::equals_point_point(geometry::range::back(range),
|
||||
point,
|
||||
strategy) )
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
|
||||
std::cout << " add: ("
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014, 2017, 2018.
|
||||
// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -15,11 +15,14 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPS_OR_SPIKES_HPP
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/append.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
@@ -33,12 +36,13 @@ namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
// TODO: move this / rename this
|
||||
template <typename Point1, typename Point2, typename RobustPolicy>
|
||||
template <typename Point1, typename Point2, typename EqualsStrategy, typename RobustPolicy>
|
||||
inline bool points_equal_or_close(Point1 const& point1,
|
||||
Point2 const& point2,
|
||||
EqualsStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
if (detail::equals::equals_point_point(point1, point2))
|
||||
if (detail::equals::equals_point_point(point1, point2, strategy))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -59,12 +63,20 @@ inline bool points_equal_or_close(Point1 const& point1,
|
||||
geometry::recalculate(point1_rob, point1, robust_policy);
|
||||
geometry::recalculate(point2_rob, point2, robust_policy);
|
||||
|
||||
return detail::equals::equals_point_point(point1_rob, point2_rob);
|
||||
// Only if this is the case the same strategy can be used.
|
||||
BOOST_STATIC_ASSERT((boost::is_same
|
||||
<
|
||||
typename geometry::cs_tag<Point1>::type,
|
||||
typename geometry::cs_tag<robust_point_type>::type
|
||||
>::value));
|
||||
|
||||
return detail::equals::equals_point_point(point1_rob, point2_rob, strategy);
|
||||
}
|
||||
|
||||
|
||||
template <typename Range, typename Point, typename RobustPolicy>
|
||||
template <typename Range, typename Point, typename SideStrategy, typename RobustPolicy>
|
||||
inline void append_no_dups_or_spikes(Range& range, Point const& point,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
|
||||
@@ -75,8 +87,10 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
|
||||
// The code below this condition checks all spikes/dups
|
||||
// for geometries >= 3 points.
|
||||
// So we have to check the first potential duplicate differently
|
||||
if (boost::size(range) == 1
|
||||
&& points_equal_or_close(*(boost::begin(range)), point, robust_policy))
|
||||
if ( boost::size(range) == 1
|
||||
&& points_equal_or_close(*(boost::begin(range)), point,
|
||||
strategy.get_equals_point_point_strategy(),
|
||||
robust_policy) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -92,6 +106,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
|
||||
&& point_is_spike_or_equal(point,
|
||||
*(boost::end(range) - 3),
|
||||
*(boost::end(range) - 2),
|
||||
strategy,
|
||||
robust_policy))
|
||||
{
|
||||
// Use the Concept/traits, so resize and append again
|
||||
@@ -100,8 +115,48 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Range, typename RobustPolicy>
|
||||
template <typename Range, typename Point, typename SideStrategy, typename RobustPolicy>
|
||||
inline void append_no_collinear(Range& range, Point const& point,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
// Stricter version, not allowing any point in a linear row
|
||||
// (spike, continuation or same point)
|
||||
|
||||
// The code below this condition checks all spikes/dups
|
||||
// for geometries >= 3 points.
|
||||
// So we have to check the first potential duplicate differently
|
||||
if ( boost::size(range) == 1
|
||||
&& points_equal_or_close(*(boost::begin(range)), point,
|
||||
strategy.get_equals_point_point_strategy(),
|
||||
robust_policy) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
traits::push_back<Range>::apply(range, point);
|
||||
|
||||
// If a point is equal, or forming a spike, remove the pen-ultimate point
|
||||
// because this one caused the spike.
|
||||
// If so, the now-new-pen-ultimate point can again cause a spike
|
||||
// (possibly at a corner). So keep doing this.
|
||||
// Besides spikes it will also avoid adding duplicates.
|
||||
while(boost::size(range) >= 3
|
||||
&& point_is_collinear(point,
|
||||
*(boost::end(range) - 3),
|
||||
*(boost::end(range) - 2),
|
||||
strategy,
|
||||
robust_policy))
|
||||
{
|
||||
// Use the Concept/traits, so resize and append again
|
||||
traits::resize<Range>::apply(range, boost::size(range) - 2);
|
||||
traits::push_back<Range>::apply(range, point);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Range, typename SideStrategy, typename RobustPolicy>
|
||||
inline void clean_closing_dups_and_spikes(Range& range,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
std::size_t const minsize
|
||||
@@ -134,8 +189,8 @@ inline void clean_closing_dups_and_spikes(Range& range,
|
||||
}
|
||||
|
||||
// Check if closing point is a spike (this is so if the second point is
|
||||
// considered as a spike w.r.t. the last segment)
|
||||
if (point_is_spike_or_equal(*second, *ultimate, *first, robust_policy))
|
||||
// considered as collinear w.r.t. the last segment)
|
||||
if (point_is_collinear(*second, *ultimate, *first, strategy, robust_policy))
|
||||
{
|
||||
range::erase(range, first);
|
||||
if (BOOST_GEOMETRY_CONDITION(closed))
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2017.
|
||||
// Modifications copyright (c) 2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2017, 2018.
|
||||
// Modifications copyright (c) 2017-2018 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,
|
||||
@@ -15,12 +16,12 @@
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/area.hpp>
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/detail/partition.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
|
||||
#include <boost/geometry/algorithms/within.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/box.hpp>
|
||||
|
||||
@@ -37,50 +38,88 @@ namespace detail { namespace overlay
|
||||
template
|
||||
<
|
||||
typename Item,
|
||||
typename InnerGeometry,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RingCollection
|
||||
typename RingCollection,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool within_selected_input(Item const& item2, ring_identifier const& ring_id,
|
||||
static inline bool within_selected_input(Item const& item2,
|
||||
InnerGeometry const& inner_geometry,
|
||||
ring_identifier const& outer_id,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
RingCollection const& collection)
|
||||
RingCollection const& collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::tag<Geometry1>::type tag1;
|
||||
typedef typename geometry::tag<Geometry2>::type tag2;
|
||||
|
||||
switch (ring_id.source_index)
|
||||
// NOTE: range_in_geometry first checks the item2.point and then
|
||||
// if this point is on boundary it checks points of inner_geometry
|
||||
// ring until a point inside/outside other geometry ring is found
|
||||
switch (outer_id.source_index)
|
||||
{
|
||||
// covered_by
|
||||
case 0 :
|
||||
return range_in_geometry(item2.point, inner_geometry,
|
||||
get_ring<tag1>::apply(outer_id, geometry1), strategy) >= 0;
|
||||
case 1 :
|
||||
return range_in_geometry(item2.point, inner_geometry,
|
||||
get_ring<tag2>::apply(outer_id, geometry2), strategy) >= 0;
|
||||
case 2 :
|
||||
return range_in_geometry(item2.point, inner_geometry,
|
||||
get_ring<void>::apply(outer_id, collection), strategy) >= 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Item,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RingCollection,
|
||||
typename Strategy
|
||||
>
|
||||
static inline bool within_selected_input(Item const& item2,
|
||||
ring_identifier const& inner_id, ring_identifier const& outer_id,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
RingCollection const& collection,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::tag<Geometry1>::type tag1;
|
||||
typedef typename geometry::tag<Geometry2>::type tag2;
|
||||
|
||||
switch (inner_id.source_index)
|
||||
{
|
||||
case 0 :
|
||||
return geometry::within(item2.point,
|
||||
get_ring<tag1>::apply(ring_id, geometry1));
|
||||
break;
|
||||
return within_selected_input(item2,
|
||||
get_ring<tag1>::apply(inner_id, geometry1),
|
||||
outer_id, geometry1, geometry2, collection, strategy);
|
||||
case 1 :
|
||||
return geometry::within(item2.point,
|
||||
get_ring<tag2>::apply(ring_id, geometry2));
|
||||
break;
|
||||
return within_selected_input(item2,
|
||||
get_ring<tag2>::apply(inner_id, geometry2),
|
||||
outer_id, geometry1, geometry2, collection, strategy);
|
||||
case 2 :
|
||||
return geometry::within(item2.point,
|
||||
get_ring<void>::apply(ring_id, collection));
|
||||
break;
|
||||
return within_selected_input(item2,
|
||||
get_ring<void>::apply(inner_id, collection),
|
||||
outer_id, geometry1, geometry2, collection, strategy);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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))
|
||||
{}
|
||||
};
|
||||
@@ -95,16 +134,25 @@ struct ring_info_helper_get_box
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DisjointBoxBoxStrategy>
|
||||
struct ring_info_helper_ovelaps_box
|
||||
{
|
||||
template <typename Box, typename InputItem>
|
||||
static inline bool apply(Box const& box, InputItem const& item)
|
||||
{
|
||||
return ! geometry::detail::disjoint::disjoint_box_box(box, item.envelope);
|
||||
return ! geometry::detail::disjoint::disjoint_box_box(
|
||||
box, item.envelope, DisjointBoxBoxStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2, typename Collection, typename RingMap>
|
||||
template
|
||||
<
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Collection,
|
||||
typename RingMap,
|
||||
typename Strategy
|
||||
>
|
||||
struct assign_visitor
|
||||
{
|
||||
typedef typename RingMap::mapped_type ring_info_type;
|
||||
@@ -113,26 +161,27 @@ struct assign_visitor
|
||||
Geometry2 const& m_geometry2;
|
||||
Collection const& m_collection;
|
||||
RingMap& m_ring_map;
|
||||
Strategy const& m_strategy;
|
||||
bool m_check_for_orientation;
|
||||
|
||||
|
||||
inline assign_visitor(Geometry1 const& g1, Geometry2 const& g2, Collection const& c,
|
||||
RingMap& map, bool check)
|
||||
RingMap& map, Strategy const& strategy, bool check)
|
||||
: m_geometry1(g1)
|
||||
, m_geometry2(g2)
|
||||
, m_collection(c)
|
||||
, m_ring_map(map)
|
||||
, m_strategy(strategy)
|
||||
, m_check_for_orientation(check)
|
||||
{}
|
||||
|
||||
template <typename Item>
|
||||
inline void apply(Item const& outer, Item const& inner, bool first = true)
|
||||
inline bool apply(Item const& outer, Item const& inner, bool first = true)
|
||||
{
|
||||
if (first && outer.abs_area < inner.abs_area)
|
||||
{
|
||||
// Apply with reversed arguments
|
||||
apply(inner, outer, false);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_check_for_orientation
|
||||
@@ -141,8 +190,10 @@ struct assign_visitor
|
||||
{
|
||||
ring_info_type& inner_in_map = m_ring_map[inner.id];
|
||||
|
||||
if (geometry::within(inner_in_map.point, outer.envelope)
|
||||
&& within_selected_input(inner_in_map, outer.id, m_geometry1, m_geometry2, m_collection)
|
||||
if (geometry::covered_by(inner_in_map.point, outer.envelope)
|
||||
&& within_selected_input(inner_in_map, inner.id, outer.id,
|
||||
m_geometry1, m_geometry2, m_collection,
|
||||
m_strategy)
|
||||
)
|
||||
{
|
||||
// Assign a parent if there was no earlier parent, or the newly
|
||||
@@ -155,35 +206,46 @@ struct assign_visitor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
overlay_type OverlayType,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RingCollection,
|
||||
typename RingMap
|
||||
typename RingMap,
|
||||
typename Strategy
|
||||
>
|
||||
inline void assign_parents(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RingCollection const& collection,
|
||||
RingMap& ring_map,
|
||||
bool check_for_orientation = false)
|
||||
Strategy const& strategy)
|
||||
{
|
||||
static bool const is_difference = OverlayType == overlay_difference;
|
||||
static bool const is_buffer = OverlayType == overlay_buffer;
|
||||
static bool const is_dissolve = OverlayType == overlay_dissolve;
|
||||
static bool const check_for_orientation = is_buffer || is_dissolve;
|
||||
|
||||
typedef typename geometry::tag<Geometry1>::type tag1;
|
||||
typedef typename geometry::tag<Geometry2>::type tag2;
|
||||
|
||||
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::template result_type<point_type>::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;
|
||||
|
||||
@@ -204,17 +266,21 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
{
|
||||
case 0 :
|
||||
geometry::envelope(get_ring<tag1>::apply(it->first, geometry1),
|
||||
item.envelope);
|
||||
item.envelope, strategy.get_envelope_strategy());
|
||||
break;
|
||||
case 1 :
|
||||
geometry::envelope(get_ring<tag2>::apply(it->first, geometry2),
|
||||
item.envelope);
|
||||
item.envelope, strategy.get_envelope_strategy());
|
||||
break;
|
||||
case 2 :
|
||||
geometry::envelope(get_ring<void>::apply(it->first, collection),
|
||||
item.envelope);
|
||||
item.envelope, strategy.get_envelope_strategy());
|
||||
break;
|
||||
}
|
||||
|
||||
// Expand envelope slightly
|
||||
expand_by_epsilon(item.envelope);
|
||||
|
||||
if (item.real_area > 0)
|
||||
{
|
||||
count_positive++;
|
||||
@@ -231,12 +297,14 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
return;
|
||||
}
|
||||
|
||||
if (count_positive == 1)
|
||||
if (count_positive == 1 && ! is_difference && ! is_dissolve)
|
||||
{
|
||||
// Optimization for one outer ring
|
||||
// -> assign this as parent to all others (all interior rings)
|
||||
// In unions, this is probably the most occuring case and gives
|
||||
// a dramatic improvement (factor 5 for star_comb testcase)
|
||||
// In difference or other cases where interior rings might be
|
||||
// located outside the outer ring, this cannot be done
|
||||
ring_identifier id_of_positive = vector[index_positive].id;
|
||||
ring_info_type& outer = ring_map[id_of_positive];
|
||||
index = 0;
|
||||
@@ -257,14 +325,20 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
assign_visitor
|
||||
<
|
||||
Geometry1, Geometry2,
|
||||
RingCollection, RingMap
|
||||
> visitor(geometry1, geometry2, collection, ring_map, check_for_orientation);
|
||||
RingCollection, RingMap,
|
||||
Strategy
|
||||
> visitor(geometry1, geometry2, collection, ring_map, strategy, check_for_orientation);
|
||||
|
||||
typedef ring_info_helper_ovelaps_box
|
||||
<
|
||||
typename Strategy::disjoint_box_box_strategy_type
|
||||
> overlaps_box_type;
|
||||
|
||||
geometry::partition
|
||||
<
|
||||
box_type
|
||||
>::apply(vector, visitor, ring_info_helper_get_box(),
|
||||
ring_info_helper_ovelaps_box());
|
||||
overlaps_box_type());
|
||||
}
|
||||
|
||||
if (check_for_orientation)
|
||||
@@ -272,28 +346,38 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
for (map_iterator_type it = boost::begin(ring_map);
|
||||
it != boost::end(ring_map); ++it)
|
||||
{
|
||||
if (geometry::math::equals(it->second.get_area(), 0))
|
||||
ring_info_type& info = it->second;
|
||||
if (geometry::math::equals(info.get_area(), 0))
|
||||
{
|
||||
it->second.discarded = true;
|
||||
info.discarded = true;
|
||||
}
|
||||
else if (it->second.parent.source_index >= 0
|
||||
&& math::larger(it->second.get_area(), 0))
|
||||
else if (info.parent.source_index >= 0)
|
||||
{
|
||||
const ring_info_type& parent = ring_map[it->second.parent];
|
||||
const ring_info_type& parent = ring_map[info.parent];
|
||||
bool const pos = math::larger(info.get_area(), 0);
|
||||
bool const parent_pos = math::larger(parent.area, 0);
|
||||
|
||||
if (math::larger(parent.area, 0))
|
||||
bool const double_neg = is_dissolve && ! pos && ! parent_pos;
|
||||
|
||||
if ((pos && parent_pos) || double_neg)
|
||||
{
|
||||
// Discard positive inner ring with positive parent
|
||||
it->second.discarded = true;
|
||||
// Also, for some cases (dissolve), negative inner ring
|
||||
// with negative parent should be discarded
|
||||
info.discarded = true;
|
||||
}
|
||||
|
||||
if (pos || info.discarded)
|
||||
{
|
||||
// Remove parent ID from any positive or discarded inner rings
|
||||
info.parent.source_index = -1;
|
||||
}
|
||||
// Remove parent ID from any positive inner ring
|
||||
it->second.parent.source_index = -1;
|
||||
}
|
||||
else if (it->second.parent.source_index < 0
|
||||
&& math::smaller(it->second.get_area(), 0))
|
||||
else if (info.parent.source_index < 0
|
||||
&& math::smaller(info.get_area(), 0))
|
||||
{
|
||||
// Reverse negative ring without parent
|
||||
it->second.reversed = true;
|
||||
info.reversed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -310,23 +394,25 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
}
|
||||
|
||||
|
||||
// Version for one geometry (called by buffer)
|
||||
// Version for one geometry (called by buffer/dissolve)
|
||||
template
|
||||
<
|
||||
overlay_type OverlayType,
|
||||
typename Geometry,
|
||||
typename RingCollection,
|
||||
typename RingMap
|
||||
typename RingMap,
|
||||
typename Strategy
|
||||
>
|
||||
inline void assign_parents(Geometry const& geometry,
|
||||
RingCollection const& collection,
|
||||
RingMap& ring_map,
|
||||
bool check_for_orientation)
|
||||
Strategy const& strategy)
|
||||
{
|
||||
// Call it with an empty geometry as second geometry (source_id == 1)
|
||||
// (ring_map should be empty for source_id==1)
|
||||
|
||||
Geometry empty;
|
||||
assign_parents(geometry, empty, collection, ring_map, check_for_orientation);
|
||||
assign_parents<OverlayType>(geometry, empty,
|
||||
collection, ring_map, strategy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2018.
|
||||
// Modifications copyright (c) 2018 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)
|
||||
@@ -9,11 +14,18 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
|
||||
#include <iostream>
|
||||
#endif // BOOST_GEOMETRY_DEBUG_ENRICH
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
|
||||
|
||||
|
||||
@@ -42,7 +54,7 @@ struct meta_turn
|
||||
|
||||
|
||||
template <typename MetaTurn>
|
||||
inline void display(MetaTurn const& meta_turn, std::string const& reason = "")
|
||||
inline void display(MetaTurn const& meta_turn, const char* reason = "")
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
|
||||
std::cout << meta_turn.index
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2018.
|
||||
// Modifications copyright (c) 2015-2018 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -24,6 +25,8 @@
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
#include <boost/geometry/geometries/segment.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -83,6 +86,15 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
// TODO: Temporary, this strategy should be moved, it is cartesian-only
|
||||
|
||||
typedef strategy::within::cartesian_point_point equals_point_point_strategy_type;
|
||||
|
||||
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
|
||||
{
|
||||
return equals_point_point_strategy_type();
|
||||
}
|
||||
|
||||
inline bool clip_segment(Box const& b, segment_type& s, bool& sp1_clipped, bool& sp2_clipped) const
|
||||
{
|
||||
typedef typename select_coordinate_type<Box, Point>::type coordinate_type;
|
||||
@@ -224,9 +236,10 @@ OutputIterator clip_range_with_box(Box const& b, Range const& range,
|
||||
// b. Add p1 only if it is the first point, then add p2
|
||||
if (boost::empty(line_out))
|
||||
{
|
||||
detail::overlay::append_no_duplicates(line_out, p1, true);
|
||||
detail::overlay::append_with_duplicates(line_out, p1);
|
||||
}
|
||||
detail::overlay::append_no_duplicates(line_out, p2);
|
||||
detail::overlay::append_no_duplicates(line_out, p2,
|
||||
strategy.get_equals_point_point_strategy());
|
||||
|
||||
// c. If c2 is clipped, finish the line
|
||||
if (c2)
|
||||
|
||||
@@ -26,14 +26,11 @@ struct cluster_info
|
||||
{
|
||||
std::set<signed_size_type> turn_indices;
|
||||
|
||||
bool switch_source; // For clusters with a touch, conform turn_info uu
|
||||
|
||||
//! Number of open spaces (e.g. 2 for touch)
|
||||
std::size_t open_count;
|
||||
|
||||
inline cluster_info()
|
||||
: switch_source(false)
|
||||
, open_count(0)
|
||||
: open_count(0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2018.
|
||||
// Modifications copyright (c) 2018, 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)
|
||||
@@ -9,18 +14,16 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP
|
||||
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/algorithm/reverse.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/num_points.hpp>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014, 2017, 2018.
|
||||
// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
@@ -23,22 +23,27 @@
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
||||
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
#include <boost/geometry/views/reversible_view.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
|
||||
#include <boost/geometry/views/closeable_view.hpp>
|
||||
#include <boost/geometry/views/reversible_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -56,12 +61,14 @@ struct copy_segments_ring
|
||||
<
|
||||
typename Ring,
|
||||
typename SegmentIdentifier,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
static inline void apply(Ring const& ring,
|
||||
SegmentIdentifier const& seg_id,
|
||||
signed_size_type to_index,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
@@ -108,7 +115,7 @@ struct copy_segments_ring
|
||||
|
||||
for (signed_size_type i = 0; i < count; ++i, ++it)
|
||||
{
|
||||
detail::overlay::append_no_dups_or_spikes(current_output, *it, robust_policy);
|
||||
detail::overlay::append_no_dups_or_spikes(current_output, *it, strategy, robust_policy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -118,24 +125,27 @@ class copy_segments_linestring
|
||||
{
|
||||
private:
|
||||
// remove spikes
|
||||
template <typename RangeOut, typename Point, typename RobustPolicy>
|
||||
template <typename RangeOut, typename Point, typename SideStrategy, typename RobustPolicy>
|
||||
static inline void append_to_output(RangeOut& current_output,
|
||||
Point const& point,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
boost::true_type const&)
|
||||
{
|
||||
detail::overlay::append_no_dups_or_spikes(current_output, point,
|
||||
strategy,
|
||||
robust_policy);
|
||||
}
|
||||
|
||||
// keep spikes
|
||||
template <typename RangeOut, typename Point, typename RobustPolicy>
|
||||
template <typename RangeOut, typename Point, typename SideStrategy, typename RobustPolicy>
|
||||
static inline void append_to_output(RangeOut& current_output,
|
||||
Point const& point,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const&,
|
||||
boost::false_type const&)
|
||||
{
|
||||
detail::overlay::append_no_duplicates(current_output, point);
|
||||
detail::overlay::append_no_duplicates(current_output, point, strategy.get_equals_point_point_strategy());
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -143,12 +153,14 @@ public:
|
||||
<
|
||||
typename LineString,
|
||||
typename SegmentIdentifier,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
static inline void apply(LineString const& ls,
|
||||
SegmentIdentifier const& seg_id,
|
||||
signed_size_type to_index,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
@@ -169,7 +181,7 @@ public:
|
||||
|
||||
for (signed_size_type i = 0; i < count; ++i, ++it)
|
||||
{
|
||||
append_to_output(current_output, *it, robust_policy,
|
||||
append_to_output(current_output, *it, strategy, robust_policy,
|
||||
boost::integral_constant<bool, RemoveSpikes>());
|
||||
}
|
||||
}
|
||||
@@ -182,12 +194,14 @@ struct copy_segments_polygon
|
||||
<
|
||||
typename Polygon,
|
||||
typename SegmentIdentifier,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
static inline void apply(Polygon const& polygon,
|
||||
SegmentIdentifier const& seg_id,
|
||||
signed_size_type to_index,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
@@ -198,6 +212,7 @@ struct copy_segments_polygon
|
||||
? geometry::exterior_ring(polygon)
|
||||
: range::at(geometry::interior_rings(polygon), seg_id.ring_index),
|
||||
seg_id, to_index,
|
||||
strategy,
|
||||
robust_policy,
|
||||
current_output
|
||||
);
|
||||
@@ -212,12 +227,14 @@ struct copy_segments_box
|
||||
<
|
||||
typename Box,
|
||||
typename SegmentIdentifier,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
static inline void apply(Box const& box,
|
||||
SegmentIdentifier const& seg_id,
|
||||
signed_size_type to_index,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
@@ -238,7 +255,7 @@ struct copy_segments_box
|
||||
for (signed_size_type i = 0; i < count; i++, index++)
|
||||
{
|
||||
detail::overlay::append_no_dups_or_spikes(current_output,
|
||||
bp[index % 5], robust_policy);
|
||||
bp[index % 5], strategy, robust_policy);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -252,12 +269,14 @@ struct copy_segments_multi
|
||||
<
|
||||
typename MultiGeometry,
|
||||
typename SegmentIdentifier,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
static inline void apply(MultiGeometry const& multi_geometry,
|
||||
SegmentIdentifier const& seg_id,
|
||||
signed_size_type to_index,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& current_output)
|
||||
{
|
||||
@@ -271,6 +290,7 @@ struct copy_segments_multi
|
||||
// Call the single-version
|
||||
Policy::apply(range::at(multi_geometry, seg_id.multi_index),
|
||||
seg_id, to_index,
|
||||
strategy,
|
||||
robust_policy,
|
||||
current_output);
|
||||
}
|
||||
@@ -340,12 +360,14 @@ template
|
||||
bool Reverse,
|
||||
typename Geometry,
|
||||
typename SegmentIdentifier,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy,
|
||||
typename RangeOut
|
||||
>
|
||||
inline void copy_segments(Geometry const& geometry,
|
||||
SegmentIdentifier const& seg_id,
|
||||
signed_size_type to_index,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
RangeOut& range_out)
|
||||
{
|
||||
@@ -355,7 +377,7 @@ inline void copy_segments(Geometry const& geometry,
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
Reverse
|
||||
>::apply(geometry, seg_id, to_index, robust_policy, range_out);
|
||||
>::apply(geometry, seg_id, to_index, strategy, robust_policy, range_out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 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
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -19,20 +25,21 @@
|
||||
# include <iostream>
|
||||
# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
|
||||
# include <boost/geometry/io/wkt/wkt.hpp>
|
||||
# define BOOST_GEOMETRY_DEBUG_IDENTIFIER
|
||||
# if ! defined(BOOST_GEOMETRY_DEBUG_IDENTIFIER)
|
||||
# define BOOST_GEOMETRY_DEBUG_IDENTIFIER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
|
||||
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/handle_colocations.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_type.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
|
||||
# include <boost/geometry/algorithms/detail/overlay/check_enrich.hpp>
|
||||
#endif
|
||||
@@ -45,6 +52,21 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
template <typename Turns>
|
||||
struct discarded_turn
|
||||
{
|
||||
discarded_turn(Turns const& turns)
|
||||
: m_turns(turns)
|
||||
{}
|
||||
|
||||
template <typename IndexedTurn>
|
||||
inline bool operator()(IndexedTurn const& indexed) const
|
||||
{
|
||||
return m_turns[indexed.turn_index].discarded;
|
||||
}
|
||||
|
||||
Turns const& m_turns;
|
||||
};
|
||||
|
||||
// Sorts IP-s of this ring on segment-identifier, and if on same segment,
|
||||
// on distance.
|
||||
@@ -58,15 +80,14 @@ template
|
||||
typename Turns,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename SideStrategy
|
||||
>
|
||||
inline void enrich_sort(Operations& operations,
|
||||
Turns const& turns,
|
||||
operation_type for_operation,
|
||||
Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& /*strategy*/)
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
std::sort(boost::begin(operations),
|
||||
boost::end(operations),
|
||||
@@ -76,13 +97,15 @@ inline void enrich_sort(Operations& operations,
|
||||
typename boost::range_value<Operations>::type,
|
||||
Geometry1, Geometry2,
|
||||
RobustPolicy,
|
||||
SideStrategy,
|
||||
Reverse1, Reverse2
|
||||
>(turns, for_operation, geometry1, geometry2, robust_policy));
|
||||
>(turns, geometry1, geometry2, robust_policy, strategy));
|
||||
}
|
||||
|
||||
|
||||
template <typename Operations, typename Turns>
|
||||
inline void enrich_assign(Operations& operations, Turns& turns)
|
||||
inline void enrich_assign(Operations& operations, Turns& turns,
|
||||
bool check_turns)
|
||||
{
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::turn_operation_type op_type;
|
||||
@@ -103,15 +126,18 @@ inline void enrich_assign(Operations& operations, Turns& turns)
|
||||
turn_type& turn = turns[it->turn_index];
|
||||
op_type& op = turn.operations[it->operation_index];
|
||||
|
||||
// Normal behaviour: next should point at next turn:
|
||||
if (it->turn_index == next->turn_index)
|
||||
if (check_turns && it->turn_index == next->turn_index)
|
||||
{
|
||||
// Normal behaviour: next points at next turn, increase next.
|
||||
// For dissolve this should not be done, turn_index is often
|
||||
// the same for two consecutive operations
|
||||
++next;
|
||||
}
|
||||
|
||||
// Cluster behaviour: next should point after cluster, unless
|
||||
// their seg_ids are not the same
|
||||
while (turn.cluster_id != -1
|
||||
// (For dissolve, this is still to be examined - TODO)
|
||||
while (turn.is_clustered()
|
||||
&& it->turn_index != next->turn_index
|
||||
&& turn.cluster_id == turns[next->turn_index].cluster_id
|
||||
&& op.seg_id == turns[next->turn_index].operations[next->operation_index].seg_id)
|
||||
@@ -135,6 +161,11 @@ inline void enrich_assign(Operations& operations, Turns& turns)
|
||||
// (this is one not circular therefore fraction is considered)
|
||||
op.enriched.next_ip_index = static_cast<signed_size_type>(next->turn_index);
|
||||
}
|
||||
|
||||
if (! check_turns)
|
||||
{
|
||||
++next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +176,7 @@ inline void enrich_assign(Operations& operations, Turns& turns)
|
||||
it != boost::end(operations);
|
||||
++it)
|
||||
{
|
||||
op_type& op = turns[it->turn_index]
|
||||
op_type const& op = turns[it->turn_index]
|
||||
.operations[it->operation_index];
|
||||
|
||||
std::cout << it->turn_index
|
||||
@@ -169,11 +200,85 @@ inline void enrich_assign(Operations& operations, Turns& turns)
|
||||
|
||||
}
|
||||
|
||||
template <typename Operations, typename Turns>
|
||||
inline void enrich_adapt(Operations& operations, Turns& turns)
|
||||
{
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::turn_operation_type op_type;
|
||||
typedef typename boost::range_value<Operations>::type indexed_turn_type;
|
||||
|
||||
if (operations.size() < 3)
|
||||
{
|
||||
// If it is empty, or contains one or two turns, it makes no sense
|
||||
return;
|
||||
}
|
||||
|
||||
// Operations is a vector of indexed_turn_operation<>
|
||||
|
||||
// Last index:
|
||||
std::size_t const x = operations.size() - 1;
|
||||
bool next_phase = false;
|
||||
|
||||
for (std::size_t i = 0; i < operations.size(); i++)
|
||||
{
|
||||
indexed_turn_type const& indexed = operations[i];
|
||||
|
||||
turn_type& turn = turns[indexed.turn_index];
|
||||
op_type& op = turn.operations[indexed.operation_index];
|
||||
|
||||
// Previous/next index
|
||||
std::size_t const p = i > 0 ? i - 1 : x;
|
||||
std::size_t const n = i < x ? i + 1 : 0;
|
||||
|
||||
turn_type const& next_turn = turns[operations[n].turn_index];
|
||||
op_type const& next_op = next_turn.operations[operations[n].operation_index];
|
||||
|
||||
if (op.seg_id.segment_index == next_op.seg_id.segment_index)
|
||||
{
|
||||
turn_type const& prev_turn = turns[operations[p].turn_index];
|
||||
op_type const& prev_op = prev_turn.operations[operations[p].operation_index];
|
||||
if (op.seg_id.segment_index == prev_op.seg_id.segment_index)
|
||||
{
|
||||
op.enriched.startable = false;
|
||||
next_phase = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! next_phase)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Discard turns which are both non-startable
|
||||
next_phase = false;
|
||||
for (typename boost::range_iterator<Turns>::type
|
||||
it = boost::begin(turns);
|
||||
it != boost::end(turns);
|
||||
++it)
|
||||
{
|
||||
turn_type& turn = *it;
|
||||
if (! turn.operations[0].enriched.startable
|
||||
&& ! turn.operations[1].enriched.startable)
|
||||
{
|
||||
turn.discarded = true;
|
||||
next_phase = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! next_phase)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove discarded turns from operations to avoid having them as next turn
|
||||
discarded_turn<Turns> const predicate(turns);
|
||||
operations.erase(std::remove_if(boost::begin(operations),
|
||||
boost::end(operations), predicate), boost::end(operations));
|
||||
}
|
||||
|
||||
template <typename Turns, typename MappedVector>
|
||||
inline void create_map(Turns const& turns,
|
||||
detail::overlay::operation_type for_operation,
|
||||
MappedVector& mapped_vector)
|
||||
inline void create_map(Turns const& turns, MappedVector& mapped_vector)
|
||||
{
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::container_type container_type;
|
||||
@@ -195,15 +300,6 @@ inline void create_map(Turns const& turns,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (for_operation == operation_intersection
|
||||
&& turn.cluster_id == -1
|
||||
&& turn.both(operation_union))
|
||||
{
|
||||
// Only include uu turns if part of cluster (to block potential paths),
|
||||
// otherwise they can block possibly viable paths
|
||||
continue;
|
||||
}
|
||||
|
||||
std::size_t op_index = 0;
|
||||
for (typename boost::range_iterator<container_type const>::type
|
||||
op_it = boost::begin(turn.operations);
|
||||
@@ -225,6 +321,52 @@ inline void create_map(Turns const& turns,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
inline typename geometry::coordinate_type<Point1>::type
|
||||
distance_measure(Point1 const& a, Point2 const& b)
|
||||
{
|
||||
// TODO: use comparable distance for point-point instead - but that
|
||||
// causes currently cycling include problems
|
||||
typedef typename geometry::coordinate_type<Point1>::type ctype;
|
||||
ctype const dx = get<0>(a) - get<0>(b);
|
||||
ctype const dy = get<1>(a) - get<1>(b);
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
inline void calculate_remaining_distance(Turns& turns)
|
||||
{
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::turn_operation_type op_type;
|
||||
|
||||
for (typename boost::range_iterator<Turns>::type
|
||||
it = boost::begin(turns);
|
||||
it != boost::end(turns);
|
||||
++it)
|
||||
{
|
||||
turn_type& turn = *it;
|
||||
|
||||
op_type& op0 = turn.operations[0];
|
||||
op_type& op1 = turn.operations[1];
|
||||
|
||||
if (op0.remaining_distance != 0
|
||||
|| op1.remaining_distance != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
signed_size_type const to_index0 = op0.enriched.get_next_turn_index();
|
||||
signed_size_type const to_index1 = op1.enriched.get_next_turn_index();
|
||||
if (to_index0 >= 0
|
||||
&& to_index1 >= 0
|
||||
&& to_index0 != to_index1)
|
||||
{
|
||||
op0.remaining_distance = distance_measure(turn.point, turns[to_index0].point);
|
||||
op1.remaining_distance = distance_measure(turn.point, turns[to_index1].point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}} // namespace detail::overlay
|
||||
#endif //DOXYGEN_NO_DETAIL
|
||||
@@ -239,7 +381,7 @@ inline void create_map(Turns const& turns,
|
||||
\tparam Clusters type of cluster container
|
||||
\tparam Geometry1 \tparam_geometry
|
||||
\tparam Geometry2 \tparam_geometry
|
||||
\tparam Strategy side strategy type
|
||||
\tparam SideStrategy side strategy type
|
||||
\param turns container containing intersection points
|
||||
\param clusters container containing clusters
|
||||
\param geometry1 \param_geometry
|
||||
@@ -255,16 +397,22 @@ template
|
||||
typename Clusters,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename SideStrategy
|
||||
>
|
||||
inline void enrich_intersection_points(Turns& turns,
|
||||
Clusters& clusters,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& strategy)
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
static const detail::overlay::operation_type for_operation
|
||||
static const detail::overlay::operation_type target_operation
|
||||
= detail::overlay::operation_from_overlay<OverlayType>::value;
|
||||
static const detail::overlay::operation_type opposite_operation
|
||||
= target_operation == detail::overlay::operation_union
|
||||
? detail::overlay::operation_intersection
|
||||
: detail::overlay::operation_union;
|
||||
static const bool is_dissolve = OverlayType == overlay_dissolve;
|
||||
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::turn_operation_type op_type;
|
||||
typedef detail::overlay::indexed_turn_operation
|
||||
@@ -278,27 +426,67 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
std::vector<indexed_turn_operation>
|
||||
> mapped_vector_type;
|
||||
|
||||
bool has_cc = false;
|
||||
bool const has_colocations
|
||||
= detail::overlay::handle_colocations<Reverse1, Reverse2>(turns,
|
||||
= detail::overlay::handle_colocations<Reverse1, Reverse2, OverlayType>(turns,
|
||||
clusters, geometry1, geometry2);
|
||||
|
||||
// Discard none turns, if any
|
||||
// Discard turns not part of target overlay
|
||||
for (typename boost::range_iterator<Turns>::type
|
||||
it = boost::begin(turns);
|
||||
it != boost::end(turns);
|
||||
++it)
|
||||
{
|
||||
if (it->both(detail::overlay::operation_none))
|
||||
turn_type& turn = *it;
|
||||
|
||||
if (turn.both(detail::overlay::operation_none)
|
||||
|| turn.both(opposite_operation)
|
||||
|| turn.both(detail::overlay::operation_blocked)
|
||||
|| (detail::overlay::is_self_turn<OverlayType>(turn)
|
||||
&& ! turn.is_clustered()
|
||||
&& ! turn.both(target_operation)))
|
||||
{
|
||||
it->discarded = true;
|
||||
// For all operations, discard xx and none/none
|
||||
// For intersections, remove uu to avoid the need to travel
|
||||
// a union (during intersection) in uu/cc clusters (e.g. #31,#32,#33)
|
||||
// The ux is necessary to indicate impossible paths
|
||||
// (especially if rescaling is removed)
|
||||
|
||||
// Similarly, for union, discard ii and ix
|
||||
|
||||
// For self-turns, only keep uu / ii
|
||||
|
||||
turn.discarded = true;
|
||||
turn.cluster_id = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! turn.discarded
|
||||
&& turn.both(detail::overlay::operation_continue))
|
||||
{
|
||||
has_cc = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_dissolve)
|
||||
{
|
||||
detail::overlay::discard_closed_turns
|
||||
<
|
||||
OverlayType,
|
||||
target_operation
|
||||
>::apply(turns, clusters, geometry1, geometry2);
|
||||
detail::overlay::discard_open_turns
|
||||
<
|
||||
OverlayType,
|
||||
target_operation
|
||||
>::apply(turns, clusters, geometry1, geometry2);
|
||||
}
|
||||
|
||||
// Create a map of vectors of indexed operation-types to be able
|
||||
// to sort intersection points PER RING
|
||||
mapped_vector_type mapped_vector;
|
||||
|
||||
detail::overlay::create_map(turns, for_operation, mapped_vector);
|
||||
detail::overlay::create_map(turns, mapped_vector);
|
||||
|
||||
// No const-iterator; contents of mapped copy is temporary,
|
||||
// and changed by enrich
|
||||
@@ -312,7 +500,7 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
<< mit->first << std::endl;
|
||||
#endif
|
||||
detail::overlay::enrich_sort<Reverse1, Reverse2>(
|
||||
mit->second, turns, for_operation,
|
||||
mit->second, turns,
|
||||
geometry1, geometry2,
|
||||
robust_policy, strategy);
|
||||
}
|
||||
@@ -326,13 +514,32 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
std::cout << "ENRICH-assign Ring "
|
||||
<< mit->first << std::endl;
|
||||
#endif
|
||||
detail::overlay::enrich_assign(mit->second, turns);
|
||||
if (is_dissolve)
|
||||
{
|
||||
detail::overlay::enrich_adapt(mit->second, turns);
|
||||
}
|
||||
|
||||
detail::overlay::enrich_assign(mit->second, turns, ! is_dissolve);
|
||||
}
|
||||
|
||||
if (has_colocations)
|
||||
{
|
||||
detail::overlay::gather_cluster_properties<Reverse1, Reverse2>(
|
||||
clusters, turns, for_operation, geometry1, geometry2);
|
||||
// First gather cluster properties (using even clusters with
|
||||
// discarded turns - for open turns), then clean up clusters
|
||||
detail::overlay::gather_cluster_properties
|
||||
<
|
||||
Reverse1,
|
||||
Reverse2,
|
||||
OverlayType
|
||||
>(clusters, turns, target_operation,
|
||||
geometry1, geometry2, strategy);
|
||||
|
||||
detail::overlay::cleanup_clusters(turns, clusters);
|
||||
}
|
||||
|
||||
if (has_cc)
|
||||
{
|
||||
detail::overlay::calculate_remaining_distance(turns);
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
|
||||
|
||||
@@ -35,12 +35,20 @@ struct enrichment_info
|
||||
, travels_to_ip_index(-1)
|
||||
, next_ip_index(-1)
|
||||
, startable(true)
|
||||
, prefer_start(true)
|
||||
, count_left(0)
|
||||
, count_right(0)
|
||||
, rank(-1)
|
||||
, zone(-1)
|
||||
, only_turn_on_ring(false)
|
||||
, region_id(-1)
|
||||
, isolated(false)
|
||||
{}
|
||||
|
||||
inline signed_size_type get_next_turn_index() const
|
||||
{
|
||||
return next_ip_index == -1 ? travels_to_ip_index : next_ip_index;
|
||||
}
|
||||
|
||||
// vertex to which is free travel after this IP,
|
||||
// so from "segment_index+1" to "travels_to_vertex_index", without IP-s,
|
||||
// can be -1
|
||||
@@ -53,12 +61,15 @@ struct enrichment_info
|
||||
signed_size_type next_ip_index;
|
||||
|
||||
bool startable; // Can be used to start in traverse
|
||||
bool prefer_start; // Is preferred as starting point (if true)
|
||||
|
||||
// Counts if polygons left/right of this operation
|
||||
std::size_t count_left;
|
||||
std::size_t count_right;
|
||||
signed_size_type rank; // in cluster
|
||||
signed_size_type zone; // open zone, in cluster
|
||||
bool only_turn_on_ring; // True if it is the only turn on a ring (for clusters)
|
||||
signed_size_type region_id;
|
||||
bool isolated;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014.
|
||||
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2017, 2018.
|
||||
// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -26,6 +27,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/turns.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -55,21 +57,14 @@ template
|
||||
typename Turn,
|
||||
typename Operation,
|
||||
typename LineString,
|
||||
typename Polygon
|
||||
typename Polygon,
|
||||
typename PtInPolyStrategy
|
||||
>
|
||||
static inline bool last_covered_by(Turn const& turn, Operation const& op,
|
||||
LineString const& linestring, Polygon const& polygon)
|
||||
static inline bool last_covered_by(Turn const& /*turn*/, Operation const& op,
|
||||
LineString const& linestring, Polygon const& polygon,
|
||||
PtInPolyStrategy const& strategy)
|
||||
{
|
||||
// Check any point between the this one and the first IP
|
||||
typedef typename geometry::point_type<LineString>::type point_type;
|
||||
point_type point_in_between;
|
||||
detail::point_on_border::midpoint_helper
|
||||
<
|
||||
point_type,
|
||||
0, dimension<point_type>::value
|
||||
>::apply(point_in_between, *(::boost::begin(linestring) + op.seg_id.segment_index), turn.point);
|
||||
|
||||
return geometry::covered_by(point_in_between, polygon);
|
||||
return geometry::covered_by(range::at(linestring, op.seg_id.segment_index), polygon, strategy);
|
||||
}
|
||||
|
||||
|
||||
@@ -78,17 +73,19 @@ template
|
||||
typename Turn,
|
||||
typename Operation,
|
||||
typename LineString,
|
||||
typename Polygon
|
||||
typename Polygon,
|
||||
typename PtInPolyStrategy
|
||||
>
|
||||
static inline bool is_leaving(Turn const& turn, Operation const& op,
|
||||
bool entered, bool first,
|
||||
LineString const& linestring, Polygon const& polygon)
|
||||
LineString const& linestring, Polygon const& polygon,
|
||||
PtInPolyStrategy const& strategy)
|
||||
{
|
||||
if (op.operation == operation_union)
|
||||
{
|
||||
return entered
|
||||
|| turn.method == method_crosses
|
||||
|| (first && last_covered_by(turn, op, linestring, polygon))
|
||||
|| (first && last_covered_by(turn, op, linestring, polygon, strategy))
|
||||
;
|
||||
}
|
||||
return false;
|
||||
@@ -100,11 +97,13 @@ template
|
||||
typename Turn,
|
||||
typename Operation,
|
||||
typename LineString,
|
||||
typename Polygon
|
||||
typename Polygon,
|
||||
typename PtInPolyStrategy
|
||||
>
|
||||
static inline bool is_staying_inside(Turn const& turn, Operation const& op,
|
||||
bool entered, bool first,
|
||||
LineString const& linestring, Polygon const& polygon)
|
||||
LineString const& linestring, Polygon const& polygon,
|
||||
PtInPolyStrategy const& strategy)
|
||||
{
|
||||
if (turn.method == method_crosses)
|
||||
{
|
||||
@@ -115,7 +114,7 @@ static inline bool is_staying_inside(Turn const& turn, Operation const& op,
|
||||
|
||||
if (is_entering(turn, op))
|
||||
{
|
||||
return entered || (first && last_covered_by(turn, op, linestring, polygon));
|
||||
return entered || (first && last_covered_by(turn, op, linestring, polygon, strategy));
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -126,14 +125,16 @@ template
|
||||
typename Turn,
|
||||
typename Operation,
|
||||
typename Linestring,
|
||||
typename Polygon
|
||||
typename Polygon,
|
||||
typename PtInPolyStrategy
|
||||
>
|
||||
static inline bool was_entered(Turn const& turn, Operation const& op, bool first,
|
||||
Linestring const& linestring, Polygon const& polygon)
|
||||
Linestring const& linestring, Polygon const& polygon,
|
||||
PtInPolyStrategy const& strategy)
|
||||
{
|
||||
if (first && (turn.method == method_collinear || turn.method == method_equal))
|
||||
{
|
||||
return last_covered_by(turn, op, linestring, polygon);
|
||||
return last_covered_by(turn, op, linestring, polygon, strategy);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -158,6 +159,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation,
|
||||
typename Strategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void enter(LineStringOut& current_piece,
|
||||
@@ -165,12 +167,13 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
segment_identifier& segment_id,
|
||||
signed_size_type , Point const& point,
|
||||
Operation const& operation,
|
||||
Strategy const& strategy,
|
||||
RobustPolicy const& ,
|
||||
OutputIterator& )
|
||||
{
|
||||
// On enter, append the intersection point and remember starting point
|
||||
// TODO: we don't check on spikes for linestrings (?). Consider this.
|
||||
detail::overlay::append_no_duplicates(current_piece, point);
|
||||
detail::overlay::append_no_duplicates(current_piece, point, strategy.get_equals_point_point_strategy());
|
||||
segment_id = operation.seg_id;
|
||||
}
|
||||
|
||||
@@ -181,6 +184,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation,
|
||||
typename Strategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void leave(LineStringOut& current_piece,
|
||||
@@ -188,6 +192,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
segment_identifier& segment_id,
|
||||
signed_size_type index, Point const& point,
|
||||
Operation const& ,
|
||||
Strategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator& out)
|
||||
{
|
||||
@@ -196,8 +201,8 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
detail::copy_segments::copy_segments_linestring
|
||||
<
|
||||
false, RemoveSpikes
|
||||
>::apply(linestring, segment_id, index, robust_policy, current_piece);
|
||||
detail::overlay::append_no_duplicates(current_piece, point);
|
||||
>::apply(linestring, segment_id, index, strategy, robust_policy, current_piece);
|
||||
detail::overlay::append_no_duplicates(current_piece, point, strategy.get_equals_point_point_strategy());
|
||||
if (::boost::size(current_piece) > 1)
|
||||
{
|
||||
*out++ = current_piece;
|
||||
@@ -235,17 +240,9 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
return entered;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Geometry,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool included(Point const& point,
|
||||
Geometry const& geometry,
|
||||
RobustPolicy const& )
|
||||
static inline bool included(int inside_value)
|
||||
{
|
||||
return geometry::covered_by(point, geometry);
|
||||
return inside_value >= 0; // covered_by
|
||||
}
|
||||
|
||||
};
|
||||
@@ -263,6 +260,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation,
|
||||
typename Strategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void enter(LineStringOut& current_piece,
|
||||
@@ -270,11 +268,12 @@ struct action_selector<overlay_difference, RemoveSpikes>
|
||||
segment_identifier& segment_id,
|
||||
signed_size_type index, Point const& point,
|
||||
Operation const& operation,
|
||||
Strategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator& out)
|
||||
{
|
||||
normal_action::leave(current_piece, linestring, segment_id, index,
|
||||
point, operation, robust_policy, out);
|
||||
point, operation, strategy, robust_policy, out);
|
||||
}
|
||||
|
||||
template
|
||||
@@ -284,6 +283,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation,
|
||||
typename Strategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void leave(LineStringOut& current_piece,
|
||||
@@ -291,11 +291,12 @@ struct action_selector<overlay_difference, RemoveSpikes>
|
||||
segment_identifier& segment_id,
|
||||
signed_size_type index, Point const& point,
|
||||
Operation const& operation,
|
||||
Strategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator& out)
|
||||
{
|
||||
normal_action::enter(current_piece, linestring, segment_id, index,
|
||||
point, operation, robust_policy, out);
|
||||
point, operation, strategy, robust_policy, out);
|
||||
}
|
||||
|
||||
template
|
||||
@@ -319,17 +320,9 @@ struct action_selector<overlay_difference, RemoveSpikes>
|
||||
return ! normal_action::is_entered(entered);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Geometry,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool included(Point const& point,
|
||||
Geometry const& geometry,
|
||||
RobustPolicy const& robust_policy)
|
||||
static inline bool included(int inside_value)
|
||||
{
|
||||
return ! normal_action::included(point, geometry, robust_policy);
|
||||
return ! normal_action::included(inside_value);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -352,6 +345,7 @@ template
|
||||
class follow
|
||||
{
|
||||
|
||||
#ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
template <typename Turn>
|
||||
struct sort_on_segment
|
||||
{
|
||||
@@ -398,38 +392,32 @@ class follow
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
|
||||
|
||||
public :
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename Geometry,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool included(Point const& point,
|
||||
Geometry const& geometry,
|
||||
RobustPolicy const& robust_policy)
|
||||
static inline bool included(int inside_value)
|
||||
{
|
||||
return following::action_selector
|
||||
<
|
||||
OverlayType, RemoveSpikes
|
||||
>::included(point, geometry, robust_policy);
|
||||
>::included(inside_value);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Turns,
|
||||
typename OutputIterator,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon,
|
||||
detail::overlay::operation_type , // TODO: this parameter might be redundant
|
||||
Turns& turns,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out)
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_iterator<Turns>::type turn_iterator;
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
@@ -440,9 +428,23 @@ public :
|
||||
|
||||
typedef following::action_selector<OverlayType, RemoveSpikes> action;
|
||||
|
||||
typename Strategy::template point_in_geometry_strategy
|
||||
<
|
||||
LineString, Polygon
|
||||
>::type const pt_in_poly_strategy
|
||||
= strategy.template get_point_in_geometry_strategy<LineString, Polygon>();
|
||||
|
||||
// Sort intersection points on segments-along-linestring, and distance
|
||||
// (like in enrich is done for poly/poly)
|
||||
// sort turns by Linear seg_id, then by fraction, then
|
||||
// for same ring id: x, u, i, c
|
||||
// for different ring id: c, i, u, x
|
||||
#ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
std::sort(boost::begin(turns), boost::end(turns), sort_on_segment<turn_type>());
|
||||
#else
|
||||
typedef relate::turns::less<0, relate::turns::less_op_linear_areal_single<0> > turn_less;
|
||||
std::sort(boost::begin(turns), boost::end(turns), turn_less());
|
||||
#endif
|
||||
|
||||
LineStringOut current_piece;
|
||||
geometry::segment_identifier current_segment_id(0, -1, -1, -1);
|
||||
@@ -454,13 +456,13 @@ public :
|
||||
{
|
||||
turn_operation_iterator_type iit = boost::begin(it->operations);
|
||||
|
||||
if (following::was_entered(*it, *iit, first, linestring, polygon))
|
||||
if (following::was_entered(*it, *iit, first, linestring, polygon, pt_in_poly_strategy))
|
||||
{
|
||||
debug_traverse(*it, *iit, "-> Was entered");
|
||||
entered = true;
|
||||
}
|
||||
|
||||
if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon))
|
||||
if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy))
|
||||
{
|
||||
debug_traverse(*it, *iit, "-> Staying inside");
|
||||
|
||||
@@ -473,17 +475,17 @@ public :
|
||||
entered = true;
|
||||
action::enter(current_piece, linestring, current_segment_id,
|
||||
iit->seg_id.segment_index, it->point, *iit,
|
||||
robust_policy,
|
||||
strategy, robust_policy,
|
||||
out);
|
||||
}
|
||||
else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon))
|
||||
else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy))
|
||||
{
|
||||
debug_traverse(*it, *iit, "-> Leaving");
|
||||
|
||||
entered = false;
|
||||
action::leave(current_piece, linestring, current_segment_id,
|
||||
iit->seg_id.segment_index, it->point, *iit,
|
||||
robust_policy,
|
||||
strategy, robust_policy,
|
||||
out);
|
||||
}
|
||||
first = false;
|
||||
@@ -497,7 +499,7 @@ public :
|
||||
>::apply(linestring,
|
||||
current_segment_id,
|
||||
static_cast<signed_size_type>(boost::size(linestring) - 1),
|
||||
robust_policy,
|
||||
strategy, robust_policy,
|
||||
current_piece);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_LINEAR_LINEAR_HPP
|
||||
@@ -183,7 +185,8 @@ protected:
|
||||
typename TurnIterator,
|
||||
typename TurnOperationIterator,
|
||||
typename SegmentIdentifier,
|
||||
typename OutputIterator
|
||||
typename OutputIterator,
|
||||
typename SideStrategy
|
||||
>
|
||||
static inline OutputIterator
|
||||
process_turn(TurnIterator it,
|
||||
@@ -193,7 +196,8 @@ protected:
|
||||
Linestring const& linestring,
|
||||
LinestringOut& current_piece,
|
||||
SegmentIdentifier& current_segment_id,
|
||||
OutputIterator oit)
|
||||
OutputIterator oit,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
// We don't rescale linear/linear
|
||||
detail::no_rescale_policy robust_policy;
|
||||
@@ -208,7 +212,7 @@ protected:
|
||||
action::enter(current_piece, linestring,
|
||||
current_segment_id,
|
||||
op_it->seg_id.segment_index,
|
||||
it->point, *op_it, robust_policy, oit);
|
||||
it->point, *op_it, strategy, robust_policy, oit);
|
||||
}
|
||||
++enter_count;
|
||||
}
|
||||
@@ -223,7 +227,7 @@ protected:
|
||||
action::leave(current_piece, linestring,
|
||||
current_segment_id,
|
||||
op_it->seg_id.segment_index,
|
||||
it->point, *op_it, robust_policy, oit);
|
||||
it->point, *op_it, strategy, robust_policy, oit);
|
||||
}
|
||||
}
|
||||
else if ( FollowIsolatedPoints
|
||||
@@ -249,14 +253,16 @@ protected:
|
||||
template
|
||||
<
|
||||
typename SegmentIdentifier,
|
||||
typename OutputIterator
|
||||
typename OutputIterator,
|
||||
typename SideStrategy
|
||||
>
|
||||
static inline OutputIterator
|
||||
process_end(bool entered,
|
||||
Linestring const& linestring,
|
||||
SegmentIdentifier const& current_segment_id,
|
||||
LinestringOut& current_piece,
|
||||
OutputIterator oit)
|
||||
OutputIterator oit,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
if ( action::is_entered(entered) )
|
||||
{
|
||||
@@ -269,6 +275,7 @@ protected:
|
||||
>::apply(linestring,
|
||||
current_segment_id,
|
||||
static_cast<signed_size_type>(boost::size(linestring) - 1),
|
||||
strategy,
|
||||
robust_policy,
|
||||
current_piece);
|
||||
}
|
||||
@@ -283,11 +290,12 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename TurnIterator, typename OutputIterator>
|
||||
template <typename TurnIterator, typename OutputIterator, typename SideStrategy>
|
||||
static inline OutputIterator
|
||||
apply(Linestring const& linestring, Linear const&,
|
||||
TurnIterator first, TurnIterator beyond,
|
||||
OutputIterator oit)
|
||||
OutputIterator oit,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
// Iterate through all intersection points (they are
|
||||
// ordered along the each line)
|
||||
@@ -304,7 +312,8 @@ public:
|
||||
entered, enter_count,
|
||||
linestring,
|
||||
current_piece, current_segment_id,
|
||||
oit);
|
||||
oit,
|
||||
strategy);
|
||||
}
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
|
||||
@@ -318,7 +327,8 @@ public:
|
||||
|
||||
return process_end(entered, linestring,
|
||||
current_segment_id, current_piece,
|
||||
oit);
|
||||
oit,
|
||||
strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -413,11 +423,12 @@ protected:
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename TurnIterator, typename OutputIterator>
|
||||
template <typename TurnIterator, typename OutputIterator, typename SideStrategy>
|
||||
static inline OutputIterator
|
||||
apply(MultiLinestring const& multilinestring, Linear const& linear,
|
||||
TurnIterator first, TurnIterator beyond,
|
||||
OutputIterator oit)
|
||||
OutputIterator oit,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT( first != beyond );
|
||||
|
||||
@@ -447,7 +458,7 @@ public:
|
||||
has_other_multi_id(current_multi_id));
|
||||
|
||||
oit = Base::apply(*(ls_first + current_multi_id),
|
||||
linear, per_ls_current, per_ls_next, oit);
|
||||
linear, per_ls_current, per_ls_next, oit, strategy);
|
||||
|
||||
signed_size_type next_multi_id = -1;
|
||||
linestring_iterator ls_next = ls_beyond;
|
||||
|
||||
@@ -44,12 +44,16 @@ template
|
||||
>
|
||||
struct get_turn_without_info
|
||||
{
|
||||
template <typename Strategy, typename RobustPolicy, typename OutputIterator>
|
||||
static inline OutputIterator apply(
|
||||
Point1 const& pi, Point1 const& pj, Point1 const& /*pk*/,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& /*qk*/,
|
||||
bool /*is_p_first*/, bool /*is_p_last*/,
|
||||
bool /*is_q_first*/, bool /*is_q_last*/,
|
||||
template
|
||||
<
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename Strategy,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator
|
||||
>
|
||||
static inline OutputIterator apply(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
TurnInfo const& ,
|
||||
Strategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
@@ -71,6 +75,10 @@ struct get_turn_without_info
|
||||
|
||||
typedef model::referring_segment<Point1 const> segment_type1;
|
||||
typedef model::referring_segment<Point2 const> segment_type2;
|
||||
Point1 const& pi = range_p.at(0);
|
||||
Point1 const& pj = range_p.at(1);
|
||||
Point2 const& qi = range_q.at(0);
|
||||
Point2 const& qj = range_q.at(1);
|
||||
segment_type1 p1(pi, pj);
|
||||
segment_type2 q1(qi, qj);
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// 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)
|
||||
@@ -31,20 +36,15 @@ namespace detail { namespace overlay
|
||||
but we still need to know which comes first.
|
||||
Therefore, it is useful that using sides we are able to discover this.
|
||||
*/
|
||||
template <typename Point1>
|
||||
struct get_relative_order
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point1>::type
|
||||
>::type strategy;
|
||||
|
||||
template <typename Point>
|
||||
template <typename Point, typename SideStrategy>
|
||||
static inline int value_via_product(Point const& ti, Point const& tj,
|
||||
Point const& ui, Point const& uj, int factor)
|
||||
Point const& ui, Point const& uj, int factor,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
int const side_ti_u = strategy::apply(ti, tj, ui);
|
||||
int const side_tj_u = strategy::apply(ti, tj, uj);
|
||||
int const side_ti_u = strategy.apply(ti, tj, ui);
|
||||
int const side_tj_u = strategy.apply(ti, tj, uj);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
|
||||
std::cout << (factor == 1 ? " r//s " : " s//r ")
|
||||
@@ -57,13 +57,15 @@ struct get_relative_order
|
||||
}
|
||||
|
||||
|
||||
template <typename Point1, typename SideStrategy>
|
||||
static inline int apply(
|
||||
Point1 const& pi, Point1 const& pj,
|
||||
Point1 const& ri, Point1 const& rj,
|
||||
Point1 const& si, Point1 const& sj)
|
||||
Point1 const& si, Point1 const& sj,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
int const side_ri_p = strategy::apply(pi, pj, ri);
|
||||
int const side_si_p = strategy::apply(pi, pj, si);
|
||||
int const side_ri_p = strategy.apply(pi, pj, ri);
|
||||
int const side_si_p = strategy.apply(pi, pj, si);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
|
||||
int const side_rj_p = strategy::apply(pi, pj, rj);
|
||||
@@ -72,10 +74,10 @@ struct get_relative_order
|
||||
std::cout << " s//p: " << side_si_p << " / " << side_sj_p;
|
||||
#endif
|
||||
|
||||
int value = value_via_product(si, sj, ri, rj, 1);
|
||||
int value = value_via_product(si, sj, ri, rj, 1, strategy);
|
||||
if (value == 0)
|
||||
{
|
||||
value = value_via_product(ri, rj, si, sj, -1);
|
||||
value = value_via_product(ri, rj, si, sj, -1, strategy);
|
||||
}
|
||||
|
||||
int const order = side_ri_p * side_ri_p * side_si_p * value;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2017.
|
||||
// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015, 2017, 2018, 2019.
|
||||
// Modifications copyright (c) 2015-2019 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/exception.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
@@ -84,7 +85,7 @@ struct base_turn_handler
|
||||
return side1 * side2 == 1;
|
||||
}
|
||||
|
||||
// Both continue
|
||||
// Both get the same operation
|
||||
template <typename TurnInfo>
|
||||
static inline void both(TurnInfo& ti, operation_type const op)
|
||||
{
|
||||
@@ -130,6 +131,17 @@ struct base_turn_handler
|
||||
? 1 : 0;
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
static inline typename geometry::coordinate_type<Point1>::type
|
||||
distance_measure(Point1 const& a, Point2 const& b)
|
||||
{
|
||||
// TODO: use comparable distance for point-point instead - but that
|
||||
// causes currently cycling include problems
|
||||
typedef typename geometry::coordinate_type<Point1>::type ctype;
|
||||
ctype const dx = get<0>(a) - get<0>(b);
|
||||
ctype const dy = get<1>(a) - get<1>(b);
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -143,15 +155,14 @@ struct touch_interior : public base_turn_handler
|
||||
template
|
||||
<
|
||||
unsigned int Index,
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename IntersectionInfo,
|
||||
typename DirInfo,
|
||||
typename SidePolicy
|
||||
>
|
||||
static inline void apply(
|
||||
Point1 const& , Point1 const& , Point1 const& ,
|
||||
Point2 const& , Point2 const& , Point2 const& ,
|
||||
static inline void apply(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
TurnInfo& ti,
|
||||
IntersectionInfo const& intersection_info,
|
||||
DirInfo const& dir_info,
|
||||
@@ -169,8 +180,10 @@ struct touch_interior : public base_turn_handler
|
||||
static unsigned int const index_p = Index;
|
||||
static unsigned int const index_q = 1 - Index;
|
||||
|
||||
bool const has_pk = ! range_p.is_last_segment();
|
||||
bool const has_qk = ! range_q.is_last_segment();
|
||||
int const side_qi_p = dir_info.sides.template get<index_q, 0>();
|
||||
int const side_qk_p = side.qk_wrt_p1();
|
||||
int const side_qk_p = has_qk ? side.qk_wrt_p1() : 0;
|
||||
|
||||
if (side_qi_p == -side_qk_p)
|
||||
{
|
||||
@@ -183,20 +196,36 @@ struct touch_interior : public base_turn_handler
|
||||
return;
|
||||
}
|
||||
|
||||
int const side_qk_q = side.qk_wrt_q1();
|
||||
int const side_qk_q = has_qk ? side.qk_wrt_q1() : 0;
|
||||
|
||||
// Only necessary if rescaling is turned off:
|
||||
int const side_pj_q2 = has_qk ? side.pj_wrt_q2() : 0;
|
||||
|
||||
if (side_qi_p == -1 && side_qk_p == -1 && side_qk_q == 1)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
// Q turns right on the left side of P (test "ML3")
|
||||
// Union: take both operation
|
||||
// Intersection: skip
|
||||
both(ti, operation_union);
|
||||
if (has_qk && side_pj_q2 == -1)
|
||||
{
|
||||
// Q turns right on the left side of P (test "ML3")
|
||||
// Union: take both operations
|
||||
// Intersection: skip
|
||||
both(ti, operation_union);
|
||||
}
|
||||
else
|
||||
{
|
||||
// q2 is collinear with p1, so it does not turn back. This
|
||||
// can happen in floating point precision. In this case,
|
||||
// block one of the operations to avoid taking that path.
|
||||
ti.operations[index_p].operation = operation_union;
|
||||
ti.operations[index_q].operation = operation_blocked;
|
||||
}
|
||||
ti.touch_only = true;
|
||||
}
|
||||
else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q)
|
||||
{
|
||||
@@ -205,8 +234,32 @@ struct touch_interior : public base_turn_handler
|
||||
// Union: take left turn (Q if Q turns left, P if Q turns right)
|
||||
// Intersection: other turn
|
||||
unsigned int index = side_qk_q == 1 ? index_q : index_p;
|
||||
if (has_qk && side_pj_q2 == 0)
|
||||
{
|
||||
// Even though sides xk w.r.t. 1 are distinct, pj is collinear
|
||||
// with q. Therefore swap the path
|
||||
index = 1 - index;
|
||||
}
|
||||
|
||||
if (has_pk && has_qk && opposite(side_pj_q2, side_qi_p))
|
||||
{
|
||||
// Without rescaling, floating point requires extra measures
|
||||
int const side_qj_p1 = side.qj_wrt_p1();
|
||||
int const side_qj_p2 = side.qj_wrt_p2();
|
||||
|
||||
if (same(side_qj_p1, side_qj_p2))
|
||||
{
|
||||
int const side_pj_q1 = side.pj_wrt_q1();
|
||||
if (opposite(side_pj_q1, side_pj_q2))
|
||||
{
|
||||
index = 1 - index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ti.operations[index].operation = operation_union;
|
||||
ti.operations[1 - index].operation = operation_intersection;
|
||||
ti.touch_only = true;
|
||||
}
|
||||
else if (side_qk_p == 0)
|
||||
{
|
||||
@@ -216,10 +269,16 @@ struct touch_interior : public base_turn_handler
|
||||
// Collinearly in the same direction
|
||||
// (Q comes from left of P and turns left,
|
||||
// OR Q comes from right of P and turns right)
|
||||
// Omit intersection point.
|
||||
// Omit second intersection point.
|
||||
// Union: just continue
|
||||
// Intersection: just continue
|
||||
both(ti, operation_continue);
|
||||
|
||||
// Calculate remaining distance.
|
||||
// Q arrives at p, at point qj, so use qk for q
|
||||
// and use pj for p
|
||||
ti.operations[index_p].remaining_distance = distance_measure(ti.point, range_p.at(1));
|
||||
ti.operations[index_q].remaining_distance = distance_measure(ti.point, range_q.at(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -263,15 +322,14 @@ struct touch : public base_turn_handler
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename IntersectionInfo,
|
||||
typename DirInfo,
|
||||
typename SidePolicy
|
||||
>
|
||||
static inline void apply(
|
||||
Point1 const& , Point1 const& , Point1 const& ,
|
||||
Point2 const& , Point2 const& , Point2 const& ,
|
||||
static inline void apply(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
TurnInfo& ti,
|
||||
IntersectionInfo const& intersection_info,
|
||||
DirInfo const& dir_info,
|
||||
@@ -279,17 +337,20 @@ struct touch : public base_turn_handler
|
||||
{
|
||||
assign_point(ti, method_touch, intersection_info, 0);
|
||||
|
||||
bool const has_pk = ! range_p.is_last_segment();
|
||||
bool const has_qk = ! range_q.is_last_segment();
|
||||
|
||||
int const side_qi_p1 = dir_info.sides.template get<1, 0>();
|
||||
int const side_qk_p1 = side.qk_wrt_p1();
|
||||
int const side_qk_p1 = has_qk ? side.qk_wrt_p1() : 0;
|
||||
|
||||
|
||||
// If Qi and Qk are both at same side of Pi-Pj,
|
||||
// or collinear (so: not opposite sides)
|
||||
if (! opposite(side_qi_p1, side_qk_p1))
|
||||
{
|
||||
int const side_pk_q2 = side.pk_wrt_q2();
|
||||
int const side_pk_p = side.pk_wrt_p1();
|
||||
int const side_qk_q = side.qk_wrt_q1();
|
||||
int const side_pk_q2 = has_pk && has_qk ? side.pk_wrt_q2() : 0;
|
||||
int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0;
|
||||
int const side_qk_q = has_qk ? side.qk_wrt_q1() : 0;
|
||||
|
||||
bool const q_turns_left = side_qk_q == 1;
|
||||
bool const block_q = side_qk_p1 == 0
|
||||
@@ -312,7 +373,7 @@ struct touch : public base_turn_handler
|
||||
return;
|
||||
}
|
||||
|
||||
int const side_pk_q1 = side.pk_wrt_q1();
|
||||
int const side_pk_q1 = has_pk && has_qk ? side.pk_wrt_q1() : 0;
|
||||
|
||||
|
||||
// Collinear opposite case -> block P
|
||||
@@ -346,6 +407,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 +420,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 +439,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;
|
||||
}
|
||||
@@ -380,13 +450,13 @@ struct touch : public base_turn_handler
|
||||
else
|
||||
{
|
||||
// From left to right or from right to left
|
||||
int const side_pk_p = side.pk_wrt_p1();
|
||||
int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0;
|
||||
bool const right_to_left = side_qk_p1 == 1;
|
||||
|
||||
// If p turns into direction of qi (1,2)
|
||||
if (side_pk_p == side_qi_p1)
|
||||
{
|
||||
int const side_pk_q1 = side.pk_wrt_q1();
|
||||
int const side_pk_q1 = has_pk ? side.pk_wrt_q1() : 0;
|
||||
|
||||
// Collinear opposite case -> block P
|
||||
if (side_pk_q1 == 0)
|
||||
@@ -400,6 +470,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;
|
||||
}
|
||||
}
|
||||
@@ -407,7 +478,7 @@ struct touch : public base_turn_handler
|
||||
// If p turns into direction of qk (4,5)
|
||||
if (side_pk_p == side_qk_p1)
|
||||
{
|
||||
int const side_pk_q2 = side.pk_wrt_q2();
|
||||
int const side_pk_q2 = has_pk ? side.pk_wrt_q2() : 0;
|
||||
|
||||
// Collinear case -> lines join, continue
|
||||
if (side_pk_q2 == 0)
|
||||
@@ -418,6 +489,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;
|
||||
}
|
||||
}
|
||||
@@ -425,21 +497,6 @@ struct touch : public base_turn_handler
|
||||
ui_else_iu(! right_to_left, ti);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS
|
||||
// Normally a robustness issue.
|
||||
// TODO: more research if still occuring
|
||||
std::cout << "Not yet handled" << std::endl
|
||||
<< "pi " << get<0>(pi) << " , " << get<1>(pi)
|
||||
<< " pj " << get<0>(pj) << " , " << get<1>(pj)
|
||||
<< " pk " << get<0>(pk) << " , " << get<1>(pk)
|
||||
<< std::endl
|
||||
<< "qi " << get<0>(qi) << " , " << get<1>(qi)
|
||||
<< " qj " << get<0>(qj) << " , " << get<1>(qj)
|
||||
<< " qk " << get<0>(qk) << " , " << get<1>(qk)
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -452,15 +509,14 @@ struct equal : public base_turn_handler
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename IntersectionInfo,
|
||||
typename DirInfo,
|
||||
typename SidePolicy
|
||||
>
|
||||
static inline void apply(
|
||||
Point1 const& , Point1 const& , Point1 const& ,
|
||||
Point2 const& , Point2 const& , Point2 const& ,
|
||||
static inline void apply(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
TurnInfo& ti,
|
||||
IntersectionInfo const& info,
|
||||
DirInfo const& ,
|
||||
@@ -469,10 +525,12 @@ struct equal : public base_turn_handler
|
||||
// Copy the intersection point in TO direction
|
||||
assign_point(ti, method_equal, info, non_opposite_to_index(info));
|
||||
|
||||
int const side_pk_q2 = side.pk_wrt_q2();
|
||||
int const side_pk_p = side.pk_wrt_p1();
|
||||
int const side_qk_p = side.qk_wrt_p1();
|
||||
bool const has_pk = ! range_p.is_last_segment();
|
||||
bool const has_qk = ! range_q.is_last_segment();
|
||||
|
||||
int const side_pk_q2 = has_pk && has_qk ? side.pk_wrt_q2() : 0;
|
||||
int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0;
|
||||
int const side_qk_p = has_qk ? side.qk_wrt_p1() : 0;
|
||||
|
||||
// If pk is collinear with qj-qk, they continue collinearly.
|
||||
// This can be on either side of p1 (== q1), or collinear
|
||||
@@ -511,12 +569,14 @@ struct equal_opposite : public base_turn_handler
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename OutputIterator,
|
||||
typename IntersectionInfo
|
||||
>
|
||||
static inline void apply(Point1 const& pi, Point2 const& qi,
|
||||
static inline void apply(
|
||||
UniqueSubRange1 const& /*range_p*/,
|
||||
UniqueSubRange2 const& /*range_q*/,
|
||||
/* by value: */ TurnInfo tp,
|
||||
OutputIterator& out,
|
||||
IntersectionInfo const& intersection_info)
|
||||
@@ -532,7 +592,6 @@ struct equal_opposite : public base_turn_handler
|
||||
for (unsigned int i = 0; i < intersection_info.i_info().count; i++)
|
||||
{
|
||||
assign_point(tp, method_none, intersection_info.i_info(), i);
|
||||
AssignPolicy::apply(tp, pi, qi, intersection_info);
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
@@ -579,15 +638,15 @@ struct collinear : public base_turn_handler
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename IntersectionInfo,
|
||||
typename DirInfo,
|
||||
typename SidePolicy
|
||||
>
|
||||
static inline void apply(
|
||||
Point1 const& , Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& , Point2 const& qj, Point2 const& qk,
|
||||
UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
TurnInfo& ti,
|
||||
IntersectionInfo const& info,
|
||||
DirInfo const& dir_info,
|
||||
@@ -600,8 +659,10 @@ struct collinear : public base_turn_handler
|
||||
// Should not be 0, this is checked before
|
||||
BOOST_GEOMETRY_ASSERT(arrival != 0);
|
||||
|
||||
int const side_p = side.pk_wrt_p1();
|
||||
int const side_q = side.qk_wrt_q1();
|
||||
bool const has_pk = ! range_p.is_last_segment();
|
||||
bool const has_qk = ! range_q.is_last_segment();
|
||||
int const side_p = has_pk ? side.pk_wrt_p1() : 0;
|
||||
int const side_q = has_qk ? side.qk_wrt_q1() : 0;
|
||||
|
||||
// If p arrives, use p, else use q
|
||||
int const side_p_or_q = arrival == 1
|
||||
@@ -628,25 +689,13 @@ struct collinear : public base_turn_handler
|
||||
// Calculate remaining distance. If it continues collinearly it is
|
||||
// measured until the end of the next segment
|
||||
ti.operations[0].remaining_distance
|
||||
= side_p == 0
|
||||
? distance_measure(ti.point, pk)
|
||||
: distance_measure(ti.point, pj);
|
||||
= side_p == 0 && has_pk
|
||||
? distance_measure(ti.point, range_p.at(2))
|
||||
: distance_measure(ti.point, range_p.at(1));
|
||||
ti.operations[1].remaining_distance
|
||||
= side_q == 0
|
||||
? distance_measure(ti.point, qk)
|
||||
: distance_measure(ti.point, qj);
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
static inline typename geometry::coordinate_type<Point1>::type
|
||||
distance_measure(Point1 const& a, Point2 const& b)
|
||||
{
|
||||
// TODO: use comparable distance for point-point instead - but that
|
||||
// causes currently cycling include problems
|
||||
typedef typename geometry::coordinate_type<Point1>::type ctype;
|
||||
ctype const dx = get<0>(a) - get<0>(b);
|
||||
ctype const dy = get<1>(a) - get<1>(b);
|
||||
return dx * dx + dy * dy;
|
||||
= side_q == 0 && has_qk
|
||||
? distance_measure(ti.point, range_q.at(2))
|
||||
: distance_measure(ti.point, range_q.at(1));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -685,13 +734,10 @@ private :
|
||||
template
|
||||
<
|
||||
unsigned int Index,
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionInfo
|
||||
>
|
||||
static inline bool set_tp(Point1 const& , Point1 const& , Point1 const& , int side_rk_r,
|
||||
bool const handle_robustness,
|
||||
Point2 const& , Point2 const& , int side_rk_s,
|
||||
static inline bool set_tp(int side_rk_r, bool handle_robustness,
|
||||
int side_rk_s,
|
||||
TurnInfo& tp, IntersectionInfo const& intersection_info)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(Index <= 1);
|
||||
@@ -743,15 +789,15 @@ public:
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename OutputIterator,
|
||||
typename IntersectionInfo,
|
||||
typename SidePolicy
|
||||
>
|
||||
static inline void apply(
|
||||
Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
|
||||
// Opposite collinear can deliver 2 intersection points,
|
||||
TurnInfo const& tp_model,
|
||||
@@ -760,22 +806,24 @@ public:
|
||||
IntersectionInfo const& intersection_info,
|
||||
SidePolicy const& side)
|
||||
{
|
||||
apply(pi, pj, pk, qi, qj, qk, tp_model, out, intersection_info, side, empty_transformer);
|
||||
apply(range_p, range_q,
|
||||
tp_model, out, intersection_info, side, empty_transformer);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename OutputIterator,
|
||||
typename IntersectionInfo,
|
||||
typename SidePolicy,
|
||||
typename TurnTransformer
|
||||
>
|
||||
static inline void apply(
|
||||
Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
|
||||
// Opposite collinear can deliver 2 intersection points,
|
||||
TurnInfo const& tp_model,
|
||||
@@ -783,8 +831,7 @@ public:
|
||||
|
||||
IntersectionInfo const& info,
|
||||
SidePolicy const& side,
|
||||
TurnTransformer turn_transformer,
|
||||
bool const is_pk_valid = true, bool const is_qk_valid = true)
|
||||
TurnTransformer turn_transformer)
|
||||
{
|
||||
TurnInfo tp = tp_model;
|
||||
|
||||
@@ -793,23 +840,21 @@ public:
|
||||
|
||||
// If P arrives within Q, there is a turn dependent on P
|
||||
if ( p_arrival == 1
|
||||
&& is_pk_valid
|
||||
&& set_tp<0>(pi, pj, pk, side.pk_wrt_p1(), true, qi, qj, side.pk_wrt_q1(), tp, info.i_info()) )
|
||||
&& ! range_p.is_last_segment()
|
||||
&& set_tp<0>(side.pk_wrt_p1(), true, side.pk_wrt_q1(), tp, info.i_info()) )
|
||||
{
|
||||
turn_transformer(tp);
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, info);
|
||||
*out++ = tp;
|
||||
}
|
||||
|
||||
// If Q arrives within P, there is a turn dependent on Q
|
||||
if ( q_arrival == 1
|
||||
&& is_qk_valid
|
||||
&& set_tp<1>(qi, qj, qk, side.qk_wrt_q1(), false, pi, pj, side.qk_wrt_p1(), tp, info.i_info()) )
|
||||
&& ! range_q.is_last_segment()
|
||||
&& set_tp<1>(side.qk_wrt_q1(), false, side.qk_wrt_p1(), tp, info.i_info()) )
|
||||
{
|
||||
turn_transformer(tp);
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, info);
|
||||
*out++ = tp;
|
||||
}
|
||||
|
||||
@@ -826,7 +871,6 @@ public:
|
||||
for (unsigned int i = 0; i < info.i_info().count; i++)
|
||||
{
|
||||
assign_point(tp, method_collinear, info.i_info(), i);
|
||||
AssignPolicy::apply(tp, pi, qi, info);
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
@@ -842,23 +886,14 @@ template
|
||||
>
|
||||
struct crosses : public base_turn_handler
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionInfo,
|
||||
typename DirInfo
|
||||
>
|
||||
static inline void apply(
|
||||
Point1 const& , Point1 const& , Point1 const& ,
|
||||
Point2 const& , Point2 const& , Point2 const& ,
|
||||
TurnInfo& ti,
|
||||
template <typename IntersectionInfo, typename DirInfo>
|
||||
static inline void apply(TurnInfo& ti,
|
||||
IntersectionInfo const& intersection_info,
|
||||
DirInfo const& dir_info)
|
||||
{
|
||||
assign_point(ti, method_crosses, intersection_info, 0);
|
||||
|
||||
// In all casees:
|
||||
// In all cases:
|
||||
// If Q crosses P from left to right
|
||||
// Union: take P
|
||||
// Intersection: take Q
|
||||
@@ -883,37 +918,21 @@ struct only_convert : public base_turn_handler
|
||||
|
||||
/*!
|
||||
\brief Policy doing nothing
|
||||
\details get_turn_info can have an optional policy to get/assign some
|
||||
extra information. By default it does not, and this class
|
||||
is that default.
|
||||
\details get_turn_info can have an optional policy include extra
|
||||
truns. By default it does not, and this class is that default.
|
||||
*/
|
||||
struct assign_null_policy
|
||||
{
|
||||
static bool const include_no_turn = false;
|
||||
static bool const include_degenerate = false;
|
||||
static bool const include_opposite = false;
|
||||
|
||||
template
|
||||
<
|
||||
typename Info,
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionInfo
|
||||
>
|
||||
static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&)
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Turn information: intersection point, method, and turn information
|
||||
\details Information necessary for traversal phase (a phase
|
||||
of the overlay process). The information is gathered during the
|
||||
get_turns (segment intersection) phase.
|
||||
\tparam Point1 point type of first segment
|
||||
\tparam Point2 point type of second segment
|
||||
\tparam TurnInfo type of class getting intersection and turn info
|
||||
\tparam AssignPolicy policy to assign extra info,
|
||||
e.g. to calculate distance from segment's first points
|
||||
to intersection points.
|
||||
@@ -923,23 +942,21 @@ struct assign_null_policy
|
||||
template<typename AssignPolicy>
|
||||
struct get_turn_info
|
||||
{
|
||||
// Intersect pi-pj with qi-qj
|
||||
// The points pk and qk are used do determine more information
|
||||
// about the turn (turn left/right)
|
||||
// Intersect a segment p with a segment q
|
||||
// Both p and q are modelled as sub_ranges to provide more points
|
||||
// to be able to give more information about the turn (left/right)
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename TurnInfo,
|
||||
typename IntersectionStrategy,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator
|
||||
>
|
||||
static inline OutputIterator apply(
|
||||
Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
bool /*is_p_first*/, bool /*is_p_last*/,
|
||||
bool /*is_q_first*/, bool /*is_q_last*/,
|
||||
UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
TurnInfo const& tp_model,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
@@ -947,13 +964,14 @@ struct get_turn_info
|
||||
{
|
||||
typedef intersection_info
|
||||
<
|
||||
Point1, Point2,
|
||||
UniqueSubRange1, UniqueSubRange2,
|
||||
typename TurnInfo::point_type,
|
||||
IntersectionStrategy,
|
||||
RobustPolicy
|
||||
> inters_info;
|
||||
|
||||
inters_info inters(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy);
|
||||
inters_info inters(range_p, range_q,
|
||||
intersection_strategy, robust_policy);
|
||||
|
||||
char const method = inters.d_info().how;
|
||||
|
||||
@@ -970,7 +988,6 @@ struct get_turn_info
|
||||
&& inters.i_info().count > 0)
|
||||
{
|
||||
only_convert::apply(tp, inters.i_info());
|
||||
AssignPolicy::apply(tp, pi, qi, inters);
|
||||
*out++ = tp;
|
||||
}
|
||||
break;
|
||||
@@ -988,45 +1005,28 @@ struct get_turn_info
|
||||
// If Q (1) arrives (1)
|
||||
if ( inters.d_info().arrival[1] == 1 )
|
||||
{
|
||||
policy::template apply<0>(pi, pj, pk, qi, qj, qk,
|
||||
tp, inters.i_info(), inters.d_info(),
|
||||
policy::template apply<0>(range_p, range_q, tp, inters.i_info(), inters.d_info(),
|
||||
inters.sides());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Swap p/q
|
||||
side_calculator
|
||||
<
|
||||
typename inters_info::cs_tag,
|
||||
typename inters_info::robust_point2_type,
|
||||
typename inters_info::robust_point1_type,
|
||||
typename inters_info::side_strategy_type
|
||||
> swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),
|
||||
inters.rpi(), inters.rpj(), inters.rpk(),
|
||||
inters.get_side_strategy());
|
||||
|
||||
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
|
||||
tp, inters.i_info(), inters.d_info(),
|
||||
swapped_side_calc);
|
||||
policy::template apply<1>(range_q, range_p, tp, inters.i_info(), inters.d_info(),
|
||||
inters.get_swapped_sides());
|
||||
}
|
||||
AssignPolicy::apply(tp, pi, qi, inters);
|
||||
*out++ = tp;
|
||||
}
|
||||
break;
|
||||
case 'i' :
|
||||
{
|
||||
crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, inters.i_info(), inters.d_info());
|
||||
AssignPolicy::apply(tp, pi, qi, inters);
|
||||
crosses<TurnInfo>::apply(tp, inters.i_info(), inters.d_info());
|
||||
*out++ = tp;
|
||||
}
|
||||
break;
|
||||
case 't' :
|
||||
{
|
||||
// Both touch (both arrive there)
|
||||
touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
AssignPolicy::apply(tp, pi, qi, inters);
|
||||
touch<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
*out++ = tp;
|
||||
}
|
||||
break;
|
||||
@@ -1036,9 +1036,7 @@ struct get_turn_info
|
||||
{
|
||||
// Both equal
|
||||
// or collinear-and-ending at intersection point
|
||||
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
AssignPolicy::apply(tp, pi, qi, inters);
|
||||
equal<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
*out++ = tp;
|
||||
}
|
||||
else
|
||||
@@ -1047,8 +1045,7 @@ struct get_turn_info
|
||||
<
|
||||
TurnInfo,
|
||||
AssignPolicy
|
||||
>::apply(pi, qi,
|
||||
tp, out, inters);
|
||||
>::apply(range_p, range_q, tp, out, inters);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1061,19 +1058,18 @@ struct get_turn_info
|
||||
if ( inters.d_info().arrival[0] == 0 )
|
||||
{
|
||||
// Collinear, but similar thus handled as equal
|
||||
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
equal<TurnInfo>::apply(range_p, range_q, tp,
|
||||
inters.i_info(), inters.d_info(), inters.sides());
|
||||
|
||||
// override assigned method
|
||||
tp.method = method_collinear;
|
||||
}
|
||||
else
|
||||
{
|
||||
collinear<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
|
||||
tp, inters.i_info(), inters.d_info(), inters.sides());
|
||||
collinear<TurnInfo>::apply(range_p, range_q, tp,
|
||||
inters.i_info(), inters.d_info(), inters.sides());
|
||||
}
|
||||
|
||||
AssignPolicy::apply(tp, pi, qi, inters);
|
||||
*out++ = tp;
|
||||
}
|
||||
else
|
||||
@@ -1082,7 +1078,7 @@ struct get_turn_info
|
||||
<
|
||||
TurnInfo,
|
||||
AssignPolicy
|
||||
>::apply(pi, pj, pk, qi, qj, qk,
|
||||
>::apply(range_p, range_q,
|
||||
tp, out, inters, inters.sides());
|
||||
}
|
||||
}
|
||||
@@ -1093,7 +1089,6 @@ struct get_turn_info
|
||||
if (AssignPolicy::include_degenerate)
|
||||
{
|
||||
only_convert::apply(tp, inters.i_info());
|
||||
AssignPolicy::apply(tp, pi, qi, inters);
|
||||
*out++ = tp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2017.
|
||||
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013, 2014, 2017, 2018.
|
||||
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -14,8 +14,11 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
||||
|
||||
namespace boost { namespace geometry {
|
||||
@@ -108,11 +111,12 @@ namespace detail { namespace overlay {
|
||||
class linear_intersections
|
||||
{
|
||||
public:
|
||||
template <typename Point1, typename Point2, typename IntersectionResult>
|
||||
template <typename Point1, typename Point2, typename IntersectionResult, typename EqPPStrategy>
|
||||
linear_intersections(Point1 const& pi,
|
||||
Point2 const& qi,
|
||||
IntersectionResult const& result,
|
||||
bool is_p_last, bool is_q_last)
|
||||
bool is_p_last, bool is_q_last,
|
||||
EqPPStrategy const& strategy)
|
||||
{
|
||||
int arrival_a = result.template get<1>().arrival[0];
|
||||
int arrival_b = result.template get<1>().arrival[1];
|
||||
@@ -132,10 +136,10 @@ public:
|
||||
|
||||
ips[0].is_pi
|
||||
= equals::equals_point_point(
|
||||
pi, result.template get<0>().intersections[0]);
|
||||
pi, result.template get<0>().intersections[0], strategy);
|
||||
ips[0].is_qi
|
||||
= equals::equals_point_point(
|
||||
qi, result.template get<0>().intersections[0]);
|
||||
qi, result.template get<0>().intersections[0], strategy);
|
||||
ips[1].is_pj = arrival_a != -1;
|
||||
ips[1].is_qj = arrival_b != -1;
|
||||
}
|
||||
@@ -221,39 +225,53 @@ private:
|
||||
ip_info ips[2];
|
||||
};
|
||||
|
||||
template <typename AssignPolicy, bool EnableFirst, bool EnableLast>
|
||||
template <bool EnableFirst, bool EnableLast>
|
||||
struct get_turn_info_for_endpoint
|
||||
{
|
||||
typedef std::pair<operation_type, operation_type> operations_pair;
|
||||
|
||||
BOOST_STATIC_ASSERT(EnableFirst || EnableLast);
|
||||
|
||||
template<typename Point1,
|
||||
typename Point2,
|
||||
template<typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename TurnInfo,
|
||||
typename IntersectionInfo,
|
||||
typename OutputIterator
|
||||
typename OutputIterator,
|
||||
typename EqPPStrategy
|
||||
>
|
||||
static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
bool is_p_first, bool is_p_last,
|
||||
bool is_q_first, bool is_q_last,
|
||||
static inline bool apply(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
TurnInfo const& tp_model,
|
||||
IntersectionInfo const& inters,
|
||||
method_type /*method*/,
|
||||
OutputIterator out)
|
||||
OutputIterator out,
|
||||
EqPPStrategy const& strategy)
|
||||
{
|
||||
std::size_t ip_count = inters.i_info().count;
|
||||
// no intersection points
|
||||
if ( ip_count == 0 )
|
||||
if (ip_count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !is_p_first && !is_p_last && !is_q_first && !is_q_last )
|
||||
if (! range_p.is_first_segment()
|
||||
&& ! range_q.is_first_segment()
|
||||
&& ! range_p.is_last_segment()
|
||||
&& ! range_q.is_last_segment())
|
||||
{
|
||||
// Not an end-point from segment p or q
|
||||
return false;
|
||||
}
|
||||
|
||||
linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last);
|
||||
linear_intersections intersections(range_p.at(0),
|
||||
range_q.at(0),
|
||||
inters.result(),
|
||||
range_p.is_last_segment(),
|
||||
range_q.is_last_segment(),
|
||||
strategy);
|
||||
|
||||
bool append0_last
|
||||
= analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
= analyse_segment_and_assign_ip(range_p, range_q,
|
||||
intersections.template get<0>(),
|
||||
tp_model, inters, 0, out);
|
||||
|
||||
@@ -267,8 +285,7 @@ struct get_turn_info_for_endpoint
|
||||
return result_ignore_ip0;
|
||||
|
||||
bool append1_last
|
||||
= analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,
|
||||
is_p_first, is_p_last, is_q_first, is_q_last,
|
||||
= analyse_segment_and_assign_ip(range_p, range_q,
|
||||
intersections.template get<1>(),
|
||||
tp_model, inters, 1, out);
|
||||
|
||||
@@ -278,37 +295,25 @@ struct get_turn_info_for_endpoint
|
||||
return result_ignore_ip0 || result_ignore_ip1;
|
||||
}
|
||||
|
||||
template <typename Point1,
|
||||
typename Point2,
|
||||
template <typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename TurnInfo,
|
||||
typename IntersectionInfo,
|
||||
typename OutputIterator>
|
||||
static inline
|
||||
bool analyse_segment_and_assign_ip(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
bool is_p_first, bool is_p_last,
|
||||
bool is_q_first, bool is_q_last,
|
||||
bool analyse_segment_and_assign_ip(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
linear_intersections::ip_info const& ip_info,
|
||||
TurnInfo const& tp_model,
|
||||
IntersectionInfo const& inters,
|
||||
unsigned int ip_index,
|
||||
OutputIterator out)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR
|
||||
// may this give false positives for INTs?
|
||||
typename IntersectionResult::point_type const&
|
||||
inters_pt = result.template get<0>().intersections[ip_index];
|
||||
BOOST_GEOMETRY_ASSERT(ip_info.is_pi == equals::equals_point_point(pi, inters_pt));
|
||||
BOOST_GEOMETRY_ASSERT(ip_info.is_qi == equals::equals_point_point(qi, inters_pt));
|
||||
BOOST_GEOMETRY_ASSERT(ip_info.is_pj == equals::equals_point_point(pj, inters_pt));
|
||||
BOOST_GEOMETRY_ASSERT(ip_info.is_qj == equals::equals_point_point(qj, inters_pt));
|
||||
#endif
|
||||
|
||||
// TODO - calculate first/last only if needed
|
||||
bool is_p_first_ip = is_p_first && ip_info.is_pi;
|
||||
bool is_p_last_ip = is_p_last && ip_info.is_pj;
|
||||
bool is_q_first_ip = is_q_first && ip_info.is_qi;
|
||||
bool is_q_last_ip = is_q_last && ip_info.is_qj;
|
||||
bool is_p_first_ip = range_p.is_first_segment() && ip_info.is_pi;
|
||||
bool is_p_last_ip = range_p.is_last_segment() && ip_info.is_pj;
|
||||
bool is_q_first_ip = range_q.is_first_segment() && ip_info.is_qi;
|
||||
bool is_q_last_ip = range_q.is_last_segment() && ip_info.is_qj;
|
||||
bool append_first = EnableFirst && (is_p_first_ip || is_q_first_ip);
|
||||
bool append_last = EnableLast && (is_p_last_ip || is_q_last_ip);
|
||||
|
||||
@@ -317,9 +322,7 @@ struct get_turn_info_for_endpoint
|
||||
|
||||
if ( append_first || append_last )
|
||||
{
|
||||
bool handled = handle_internal<0>(pi, pj, pk, qi, qj, qk,
|
||||
inters.rpi(), inters.rpj(), inters.rpk(),
|
||||
inters.rqi(), inters.rqj(), inters.rqk(),
|
||||
bool handled = handle_internal<0>(range_p, range_q,
|
||||
is_p_first_ip, is_p_last_ip,
|
||||
is_q_first_ip, is_q_last_ip,
|
||||
ip_info.is_qi, ip_info.is_qj,
|
||||
@@ -327,9 +330,8 @@ struct get_turn_info_for_endpoint
|
||||
p_operation, q_operation);
|
||||
if ( !handled )
|
||||
{
|
||||
handle_internal<1>(qi, qj, qk, pi, pj, pk,
|
||||
inters.rqi(), inters.rqj(), inters.rqk(),
|
||||
inters.rpi(), inters.rpj(), inters.rpk(),
|
||||
// Reverse p/q
|
||||
handle_internal<1>(range_q, range_p,
|
||||
is_q_first_ip, is_q_last_ip,
|
||||
is_p_first_ip, is_p_last_ip,
|
||||
ip_info.is_pi, ip_info.is_pj,
|
||||
@@ -347,31 +349,29 @@ struct get_turn_info_for_endpoint
|
||||
// handle spikes
|
||||
|
||||
// P is spike and should be handled
|
||||
if ( !is_p_last
|
||||
&& ip_info.is_pj // this check is redundant (also in is_spike_p) but faster
|
||||
if (ip_info.is_pj // this check is redundant (also in is_spike_p) but faster
|
||||
&& inters.i_info().count == 2
|
||||
&& inters.is_spike_p() )
|
||||
{
|
||||
assign(pi, qi, inters.result(), ip_index, method, operation_blocked, q_operation,
|
||||
assign(inters.result(), ip_index, method, operation_blocked, q_operation,
|
||||
p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out);
|
||||
assign(pi, qi, inters.result(), ip_index, method, operation_intersection, q_operation,
|
||||
assign(inters.result(), ip_index, method, operation_intersection, q_operation,
|
||||
p_pos, q_pos, is_p_first_ip, is_q_first_ip, true, false, tp_model, out);
|
||||
}
|
||||
// Q is spike and should be handled
|
||||
else if ( !is_q_last
|
||||
&& ip_info.is_qj // this check is redundant (also in is_spike_q) but faster
|
||||
else if (ip_info.is_qj // this check is redundant (also in is_spike_q) but faster
|
||||
&& inters.i_info().count == 2
|
||||
&& inters.is_spike_q() )
|
||||
{
|
||||
assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_blocked,
|
||||
assign(inters.result(), ip_index, method, p_operation, operation_blocked,
|
||||
p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out);
|
||||
assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_intersection,
|
||||
assign(inters.result(), ip_index, method, p_operation, operation_intersection,
|
||||
p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, true, tp_model, out);
|
||||
}
|
||||
// no spikes
|
||||
else
|
||||
{
|
||||
assign(pi, qi, inters.result(), ip_index, method, p_operation, q_operation,
|
||||
assign(inters.result(), ip_index, method, p_operation, q_operation,
|
||||
p_pos, q_pos, is_p_first_ip, is_q_first_ip, false, false, tp_model, out);
|
||||
}
|
||||
}
|
||||
@@ -384,28 +384,22 @@ struct get_turn_info_for_endpoint
|
||||
// however now it's lazily calculated and then it would be always calculated
|
||||
|
||||
template<std::size_t G1Index,
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename RobustPoint1,
|
||||
typename RobustPoint2,
|
||||
typename UniqueRange1,
|
||||
typename UniqueRange2,
|
||||
typename TurnInfo,
|
||||
typename IntersectionInfo
|
||||
>
|
||||
static inline bool handle_internal(Point1 const& /*i1*/, Point1 const& /*j1*/, Point1 const& /*k1*/,
|
||||
Point2 const& i2, Point2 const& j2, Point2 const& /*k2*/,
|
||||
RobustPoint1 const& ri1, RobustPoint1 const& rj1, RobustPoint1 const& /*rk1*/,
|
||||
RobustPoint2 const& ri2, RobustPoint2 const& rj2, RobustPoint2 const& rk2,
|
||||
static inline bool handle_internal(UniqueRange1 const& range1,
|
||||
UniqueRange2 const& range2,
|
||||
bool first1, bool last1, bool first2, bool last2,
|
||||
bool ip_i2, bool ip_j2, TurnInfo const& tp_model,
|
||||
IntersectionInfo const& inters, unsigned int ip_index,
|
||||
operation_type & op1, operation_type & op2)
|
||||
{
|
||||
typedef typename cs_tag<typename TurnInfo::point_type>::type cs_tag;
|
||||
boost::ignore_unused(ip_index, tp_model);
|
||||
|
||||
boost::ignore_unused_variable_warning(i2);
|
||||
boost::ignore_unused_variable_warning(j2);
|
||||
boost::ignore_unused_variable_warning(ip_index);
|
||||
boost::ignore_unused_variable_warning(tp_model);
|
||||
typename IntersectionInfo::side_strategy_type const& sides
|
||||
= inters.get_side_strategy();
|
||||
|
||||
if ( !first2 && !last2 )
|
||||
{
|
||||
@@ -427,14 +421,11 @@ struct get_turn_info_for_endpoint
|
||||
}
|
||||
else if ( ip_j2 )
|
||||
{
|
||||
side_calculator<cs_tag,
|
||||
RobustPoint1, RobustPoint2,
|
||||
typename IntersectionInfo::side_strategy_type,
|
||||
RobustPoint2>
|
||||
side_calc(ri2, ri1, rj1, ri2, rj2, rk2, inters.get_side_strategy());
|
||||
int const side_pj_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(1));
|
||||
int const side_pj_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(1));
|
||||
int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2));
|
||||
|
||||
std::pair<operation_type, operation_type>
|
||||
operations = operations_of_equal(side_calc);
|
||||
operations_pair operations = operations_of_equal(side_pj_q2, side_pj_q1, side_qk_q1);
|
||||
|
||||
// TODO: must the above be calculated?
|
||||
// wouldn't it be enough to check if segments are collinear?
|
||||
@@ -481,13 +472,11 @@ struct get_turn_info_for_endpoint
|
||||
}
|
||||
else if ( ip_j2 )
|
||||
{
|
||||
side_calculator<cs_tag, RobustPoint1, RobustPoint2,
|
||||
typename IntersectionInfo::side_strategy_type,
|
||||
RobustPoint2>
|
||||
side_calc(ri2, rj1, ri1, ri2, rj2, rk2, inters.get_side_strategy());
|
||||
|
||||
std::pair<operation_type, operation_type>
|
||||
operations = operations_of_equal(side_calc);
|
||||
int const side_pi_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(0));
|
||||
int const side_pi_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(0));
|
||||
int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2));
|
||||
|
||||
operations_pair operations = operations_of_equal(side_pi_q2, side_pi_q1, side_qk_q1);
|
||||
|
||||
// TODO: must the above be calculated?
|
||||
// wouldn't it be enough to check if segments are collinear?
|
||||
@@ -536,13 +525,10 @@ struct get_turn_info_for_endpoint
|
||||
( is_ip_last_j ? position_back : position_middle );
|
||||
}
|
||||
|
||||
template <typename Point1,
|
||||
typename Point2,
|
||||
typename IntersectionResult,
|
||||
template <typename IntersectionResult,
|
||||
typename TurnInfo,
|
||||
typename OutputIterator>
|
||||
static inline void assign(Point1 const& pi, Point2 const& qi,
|
||||
IntersectionResult const& result,
|
||||
static inline void assign(IntersectionResult const& result,
|
||||
unsigned int ip_index,
|
||||
method_type method,
|
||||
operation_type op0, operation_type op1,
|
||||
@@ -593,33 +579,27 @@ struct get_turn_info_for_endpoint
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this should get an intersection_info, which is unavailable here
|
||||
// Because the assign_null policy accepts any structure, we pass the result instead for now
|
||||
AssignPolicy::apply(tp, pi, qi, result);
|
||||
*out++ = tp;
|
||||
}
|
||||
|
||||
template <typename SidePolicy>
|
||||
static inline std::pair<operation_type, operation_type> operations_of_equal(SidePolicy const& side)
|
||||
static inline operations_pair operations_of_equal(int side_px_q2,
|
||||
int side_px_q1,
|
||||
int side_qk_q1)
|
||||
{
|
||||
int const side_pk_q2 = side.pk_wrt_q2();
|
||||
int const side_pk_p = side.pk_wrt_p1();
|
||||
int const side_qk_p = side.qk_wrt_p1();
|
||||
|
||||
// If pk is collinear with qj-qk, they continue collinearly.
|
||||
// This can be on either side of p1 (== q1), or collinear
|
||||
// If px (pi or pj) is collinear with qj-qk (q2), they continue collinearly.
|
||||
// This can be on either side of q1, or collinear
|
||||
// The second condition checks if they do not continue
|
||||
// oppositely
|
||||
if ( side_pk_q2 == 0 && side_pk_p == side_qk_p )
|
||||
if (side_px_q2 == 0 && side_px_q1 == side_qk_q1)
|
||||
{
|
||||
return std::make_pair(operation_continue, operation_continue);
|
||||
}
|
||||
|
||||
// If they turn to same side (not opposite sides)
|
||||
if ( ! base_turn_handler::opposite(side_pk_p, side_qk_p) )
|
||||
if ( ! base_turn_handler::opposite(side_px_q1, side_qk_q1) )
|
||||
{
|
||||
// If pk is left of q2 or collinear: p: union, q: intersection
|
||||
if ( side_pk_q2 != -1 )
|
||||
// If px is left of q2 or collinear: p: union, q: intersection
|
||||
if (side_px_q2 != -1 )
|
||||
{
|
||||
return std::make_pair(operation_union, operation_intersection);
|
||||
}
|
||||
@@ -632,7 +612,7 @@ struct get_turn_info_for_endpoint
|
||||
{
|
||||
// They turn opposite sides. If p turns left (or collinear),
|
||||
// p: union, q: intersection
|
||||
if ( side_pk_p != -1 )
|
||||
if (side_px_q1 != -1 )
|
||||
{
|
||||
return std::make_pair(operation_union, operation_intersection);
|
||||
}
|
||||
@@ -643,16 +623,15 @@ struct get_turn_info_for_endpoint
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool operations_both(
|
||||
std::pair<operation_type, operation_type> const& operations,
|
||||
operation_type const op)
|
||||
static inline bool operations_both(operations_pair const& operations,
|
||||
operation_type const op)
|
||||
{
|
||||
return operations.first == op && operations.second == op;
|
||||
}
|
||||
|
||||
static inline bool operations_combination(
|
||||
std::pair<operation_type, operation_type> const& operations,
|
||||
operation_type const op1, operation_type const op2)
|
||||
static inline bool operations_combination(operations_pair const& operations,
|
||||
operation_type const op1,
|
||||
operation_type const op2)
|
||||
{
|
||||
return ( operations.first == op1 && operations.second == op2 )
|
||||
|| ( operations.first == op2 && operations.second == op1 );
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2015, 2017.
|
||||
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
|
||||
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -14,7 +14,16 @@
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/detail/direction_code.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/geometries/segment.hpp> // referring_segment
|
||||
#include <boost/geometry/policies/relate/direction.hpp>
|
||||
#include <boost/geometry/policies/relate/intersection_points.hpp>
|
||||
#include <boost/geometry/policies/relate/tupled.hpp>
|
||||
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
||||
#include <boost/geometry/strategies/intersection_result.hpp>
|
||||
|
||||
namespace boost { namespace geometry {
|
||||
|
||||
@@ -36,183 +45,324 @@ struct turn_operation_linear
|
||||
bool is_collinear; // valid only for Linear geometry
|
||||
};
|
||||
|
||||
template <typename TurnPointCSTag, typename PointP, typename PointQ,
|
||||
typename SideStrategy,
|
||||
typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
|
||||
typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
|
||||
template
|
||||
<
|
||||
typename TurnPointCSTag,
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename SideStrategy
|
||||
>
|
||||
struct side_calculator
|
||||
{
|
||||
inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
|
||||
Qi const& qi, Qj const& qj, Qk const& qk,
|
||||
typedef typename UniqueSubRange1::point_type point1_type;
|
||||
typedef typename UniqueSubRange2::point_type point2_type;
|
||||
|
||||
inline side_calculator(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
SideStrategy const& side_strategy)
|
||||
: m_pi(pi), m_pj(pj), m_pk(pk)
|
||||
, m_qi(qi), m_qj(qj), m_qk(qk)
|
||||
, m_side_strategy(side_strategy)
|
||||
: m_side_strategy(side_strategy)
|
||||
, m_range_p(range_p)
|
||||
, m_range_q(range_q)
|
||||
{}
|
||||
|
||||
inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); }
|
||||
inline int pk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_pk); }
|
||||
inline int qk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_qk); }
|
||||
inline int qk_wrt_q1() const { return m_side_strategy.apply(m_qi, m_qj, m_qk); }
|
||||
inline int pk_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_pk()); }
|
||||
inline int pk_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pk()); }
|
||||
inline int qk_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_qk()); }
|
||||
inline int qk_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_qk()); }
|
||||
|
||||
inline int pk_wrt_q2() const { return m_side_strategy.apply(m_qj, m_qk, m_pk); }
|
||||
inline int qk_wrt_p2() const { return m_side_strategy.apply(m_pj, m_pk, m_qk); }
|
||||
inline int pk_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pk()); }
|
||||
inline int qk_wrt_p2() const { return m_side_strategy.apply(get_pj(), get_pk(), get_qk()); }
|
||||
|
||||
Pi const& m_pi;
|
||||
Pj const& m_pj;
|
||||
Pk const& m_pk;
|
||||
Qi const& m_qi;
|
||||
Qj const& m_qj;
|
||||
Qk const& m_qk;
|
||||
// Necessary when rescaling turns off:
|
||||
inline int qj_wrt_p1() const { return m_side_strategy.apply(get_pi(), get_pj(), get_qj()); }
|
||||
inline int qj_wrt_p2() const { return m_side_strategy.apply(get_pj(), get_pk(), get_qj()); }
|
||||
inline int pj_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pj()); }
|
||||
inline int pj_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pj()); }
|
||||
|
||||
SideStrategy const& m_side_strategy;
|
||||
inline point1_type const& get_pi() const { return m_range_p.at(0); }
|
||||
inline point1_type const& get_pj() const { return m_range_p.at(1); }
|
||||
inline point1_type const& get_pk() const { return m_range_p.at(2); }
|
||||
|
||||
inline point2_type const& get_qi() const { return m_range_q.at(0); }
|
||||
inline point2_type const& get_qj() const { return m_range_q.at(1); }
|
||||
inline point2_type const& get_qk() const { return m_range_q.at(2); }
|
||||
|
||||
// Used side-strategy, owned by the calculator,
|
||||
// created from .get_side_strategy()
|
||||
SideStrategy m_side_strategy;
|
||||
|
||||
// Used ranges - owned by get_turns or (for robust points) by intersection_info_base
|
||||
UniqueSubRange1 const& m_range_p;
|
||||
UniqueSubRange2 const& m_range_q;
|
||||
};
|
||||
|
||||
template <typename Point1, typename Point2, typename RobustPolicy>
|
||||
template<typename Point, typename UniqueSubRange, typename RobustPolicy>
|
||||
struct robust_subrange_adapter
|
||||
{
|
||||
typedef Point point_type;
|
||||
|
||||
robust_subrange_adapter(UniqueSubRange const& unique_sub_range,
|
||||
Point const& robust_point_i, Point const& robust_point_j,
|
||||
RobustPolicy const& robust_policy)
|
||||
|
||||
: m_unique_sub_range(unique_sub_range)
|
||||
, m_robust_policy(robust_policy)
|
||||
, m_robust_point_i(robust_point_i)
|
||||
, m_robust_point_j(robust_point_j)
|
||||
, m_k_retrieved(false)
|
||||
{}
|
||||
|
||||
std::size_t size() const { return m_unique_sub_range.size(); }
|
||||
|
||||
//! Get precalculated point
|
||||
Point const& at(std::size_t index) const
|
||||
{
|
||||
BOOST_GEOMETRY_ASSERT(index < size());
|
||||
switch (index)
|
||||
{
|
||||
case 0 : return m_robust_point_i;
|
||||
case 1 : return m_robust_point_j;
|
||||
case 2 : return get_point_k();
|
||||
default : return m_robust_point_i;
|
||||
}
|
||||
}
|
||||
|
||||
private :
|
||||
Point const& get_point_k() const
|
||||
{
|
||||
if (! m_k_retrieved)
|
||||
{
|
||||
geometry::recalculate(m_robust_point_k, m_unique_sub_range.at(2), m_robust_policy);
|
||||
m_k_retrieved = true;
|
||||
}
|
||||
return m_robust_point_k;
|
||||
}
|
||||
|
||||
UniqueSubRange const& m_unique_sub_range;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
|
||||
Point const& m_robust_point_i;
|
||||
Point const& m_robust_point_j;
|
||||
mutable Point m_robust_point_k;
|
||||
|
||||
mutable bool m_k_retrieved;
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename UniqueSubRange1, typename UniqueSubRange2,
|
||||
typename RobustPolicy
|
||||
>
|
||||
struct robust_points
|
||||
{
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
Point1, RobustPolicy
|
||||
typename UniqueSubRange1::point_type, RobustPolicy
|
||||
>::type robust_point1_type;
|
||||
|
||||
// TODO: define robust_point2_type using Point2?
|
||||
typedef robust_point1_type robust_point2_type;
|
||||
|
||||
inline robust_points(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
inline robust_points(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
RobustPolicy const& robust_policy)
|
||||
: m_robust_policy(robust_policy)
|
||||
, m_range_p(range_p)
|
||||
, m_range_q(range_q)
|
||||
, m_pk_retrieved(false)
|
||||
, m_qk_retrieved(false)
|
||||
{
|
||||
geometry::recalculate(m_rpi, pi, robust_policy);
|
||||
geometry::recalculate(m_rpj, pj, robust_policy);
|
||||
geometry::recalculate(m_rpk, pk, robust_policy);
|
||||
geometry::recalculate(m_rqi, qi, robust_policy);
|
||||
geometry::recalculate(m_rqj, qj, robust_policy);
|
||||
geometry::recalculate(m_rqk, qk, robust_policy);
|
||||
// Calculate pi,pj and qi,qj which are almost always necessary
|
||||
// But don't calculate pk/qk yet, which is retrieved (taking
|
||||
// more time) and not always necessary.
|
||||
geometry::recalculate(m_rpi, range_p.at(0), robust_policy);
|
||||
geometry::recalculate(m_rpj, range_p.at(1), robust_policy);
|
||||
geometry::recalculate(m_rqi, range_q.at(0), robust_policy);
|
||||
geometry::recalculate(m_rqj, range_q.at(1), robust_policy);
|
||||
}
|
||||
|
||||
robust_point1_type m_rpi, m_rpj, m_rpk;
|
||||
robust_point2_type m_rqi, m_rqj, m_rqk;
|
||||
inline robust_point1_type const& get_rpk() const
|
||||
{
|
||||
if (! m_pk_retrieved)
|
||||
{
|
||||
geometry::recalculate(m_rpk, m_range_p.at(2), m_robust_policy);
|
||||
m_pk_retrieved = true;
|
||||
}
|
||||
return m_rpk;
|
||||
}
|
||||
inline robust_point2_type const& get_rqk() const
|
||||
{
|
||||
if (! m_qk_retrieved)
|
||||
{
|
||||
geometry::recalculate(m_rqk, m_range_q.at(2), m_robust_policy);
|
||||
m_qk_retrieved = true;
|
||||
}
|
||||
return m_rqk;
|
||||
}
|
||||
|
||||
robust_point1_type m_rpi, m_rpj;
|
||||
robust_point2_type m_rqi, m_rqj;
|
||||
|
||||
private :
|
||||
RobustPolicy const& m_robust_policy;
|
||||
UniqueSubRange1 const& m_range_p;
|
||||
UniqueSubRange2 const& m_range_q;
|
||||
|
||||
// On retrieval
|
||||
mutable robust_point1_type m_rpk;
|
||||
mutable robust_point2_type m_rqk;
|
||||
mutable bool m_pk_retrieved;
|
||||
mutable bool m_qk_retrieved;
|
||||
};
|
||||
|
||||
template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy>
|
||||
template
|
||||
<
|
||||
typename UniqueSubRange1, typename UniqueSubRange2,
|
||||
typename TurnPoint, typename IntersectionStrategy, typename RobustPolicy>
|
||||
class intersection_info_base
|
||||
: private robust_points<Point1, Point2, RobustPolicy>
|
||||
: private robust_points<UniqueSubRange1, UniqueSubRange2, RobustPolicy>
|
||||
{
|
||||
typedef robust_points<Point1, Point2, RobustPolicy> base;
|
||||
typedef robust_points<UniqueSubRange1, UniqueSubRange2, RobustPolicy> base;
|
||||
|
||||
public:
|
||||
typedef Point1 point1_type;
|
||||
typedef Point2 point2_type;
|
||||
|
||||
typedef typename base::robust_point1_type robust_point1_type;
|
||||
typedef typename base::robust_point2_type robust_point2_type;
|
||||
|
||||
typedef robust_subrange_adapter<robust_point1_type, UniqueSubRange1, RobustPolicy> robust_subrange1;
|
||||
typedef robust_subrange_adapter<robust_point2_type, UniqueSubRange2, RobustPolicy> robust_subrange2;
|
||||
|
||||
typedef typename cs_tag<TurnPoint>::type cs_tag;
|
||||
|
||||
typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
|
||||
typedef side_calculator<cs_tag, robust_point1_type, robust_point2_type, side_strategy_type> side_calculator_type;
|
||||
|
||||
intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
typedef side_calculator<cs_tag, robust_subrange1, robust_subrange2,
|
||||
side_strategy_type> side_calculator_type;
|
||||
|
||||
typedef side_calculator
|
||||
<
|
||||
cs_tag, robust_subrange2, robust_subrange1,
|
||||
side_strategy_type
|
||||
> robust_swapped_side_calculator_type;
|
||||
|
||||
intersection_info_base(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
: base(pi, pj, pk, qi, qj, qk, robust_policy)
|
||||
, m_side_calc(base::m_rpi, base::m_rpj, base::m_rpk,
|
||||
base::m_rqi, base::m_rqj, base::m_rqk,
|
||||
: base(range_p, range_q, robust_policy)
|
||||
, m_range_p(range_p)
|
||||
, m_range_q(range_q)
|
||||
, m_robust_range_p(range_p, base::m_rpi, base::m_rpj, robust_policy)
|
||||
, m_robust_range_q(range_q, base::m_rqi, base::m_rqj, robust_policy)
|
||||
, m_side_calc(m_robust_range_p, m_robust_range_q,
|
||||
intersection_strategy.get_side_strategy())
|
||||
, m_pi(pi), m_pj(pj), m_pk(pk)
|
||||
, m_qi(qi), m_qj(qj), m_qk(qk)
|
||||
{}
|
||||
|
||||
inline Point1 const& pi() const { return m_pi; }
|
||||
inline Point1 const& pj() const { return m_pj; }
|
||||
inline Point1 const& pk() const { return m_pk; }
|
||||
|
||||
inline Point2 const& qi() const { return m_qi; }
|
||||
inline Point2 const& qj() const { return m_qj; }
|
||||
inline Point2 const& qk() const { return m_qk; }
|
||||
inline typename UniqueSubRange1::point_type const& pi() const { return m_range_p.at(0); }
|
||||
inline typename UniqueSubRange2::point_type const& qi() const { return m_range_q.at(0); }
|
||||
|
||||
inline robust_point1_type const& rpi() const { return base::m_rpi; }
|
||||
inline robust_point1_type const& rpj() const { return base::m_rpj; }
|
||||
inline robust_point1_type const& rpk() const { return base::m_rpk; }
|
||||
inline robust_point1_type const& rpk() const { return base::get_rpk(); }
|
||||
|
||||
inline robust_point2_type const& rqi() const { return base::m_rqi; }
|
||||
inline robust_point2_type const& rqj() const { return base::m_rqj; }
|
||||
inline robust_point2_type const& rqk() const { return base::m_rqk; }
|
||||
inline robust_point2_type const& rqk() const { return base::get_rqk(); }
|
||||
|
||||
inline side_calculator_type const& sides() const { return m_side_calc; }
|
||||
|
||||
private:
|
||||
side_calculator_type m_side_calc;
|
||||
robust_swapped_side_calculator_type get_swapped_sides() const
|
||||
{
|
||||
robust_swapped_side_calculator_type result(
|
||||
m_robust_range_q, m_robust_range_p,
|
||||
m_side_calc.m_side_strategy);
|
||||
return result;
|
||||
}
|
||||
|
||||
point1_type const& m_pi;
|
||||
point1_type const& m_pj;
|
||||
point1_type const& m_pk;
|
||||
point2_type const& m_qi;
|
||||
point2_type const& m_qj;
|
||||
point2_type const& m_qk;
|
||||
// Owned by get_turns
|
||||
UniqueSubRange1 const& m_range_p;
|
||||
UniqueSubRange2 const& m_range_q;
|
||||
private :
|
||||
// Owned by this class
|
||||
robust_subrange1 m_robust_range_p;
|
||||
robust_subrange2 m_robust_range_q;
|
||||
side_calculator_type m_side_calc;
|
||||
};
|
||||
|
||||
template <typename Point1, typename Point2, typename TurnPoint, typename IntersectionStrategy>
|
||||
class intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, detail::no_rescale_policy>
|
||||
template
|
||||
<
|
||||
typename UniqueSubRange1, typename UniqueSubRange2,
|
||||
typename TurnPoint, typename IntersectionStrategy
|
||||
>
|
||||
class intersection_info_base<UniqueSubRange1, UniqueSubRange2,
|
||||
TurnPoint, IntersectionStrategy, detail::no_rescale_policy>
|
||||
{
|
||||
public:
|
||||
typedef Point1 point1_type;
|
||||
typedef Point2 point2_type;
|
||||
typedef typename UniqueSubRange1::point_type point1_type;
|
||||
typedef typename UniqueSubRange2::point_type point2_type;
|
||||
|
||||
typedef Point1 robust_point1_type;
|
||||
typedef Point2 robust_point2_type;
|
||||
typedef typename UniqueSubRange1::point_type robust_point1_type;
|
||||
typedef typename UniqueSubRange2::point_type robust_point2_type;
|
||||
|
||||
typedef typename cs_tag<TurnPoint>::type cs_tag;
|
||||
|
||||
typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
|
||||
typedef side_calculator<cs_tag, Point1, Point2, side_strategy_type> side_calculator_type;
|
||||
typedef side_calculator<cs_tag, UniqueSubRange1, UniqueSubRange2, side_strategy_type> side_calculator_type;
|
||||
|
||||
typedef side_calculator
|
||||
<
|
||||
cs_tag, UniqueSubRange2, UniqueSubRange1,
|
||||
side_strategy_type
|
||||
> swapped_side_calculator_type;
|
||||
|
||||
intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
intersection_info_base(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
no_rescale_policy const& /*robust_policy*/)
|
||||
: m_side_calc(pi, pj, pk, qi, qj, qk,
|
||||
: m_range_p(range_p)
|
||||
, m_range_q(range_q)
|
||||
, m_side_calc(range_p, range_q,
|
||||
intersection_strategy.get_side_strategy())
|
||||
{}
|
||||
|
||||
inline Point1 const& pi() const { return m_side_calc.m_pi; }
|
||||
inline Point1 const& pj() const { return m_side_calc.m_pj; }
|
||||
inline Point1 const& pk() const { return m_side_calc.m_pk; }
|
||||
inline point1_type const& rpi() const { return m_side_calc.get_pi(); }
|
||||
inline point1_type const& rpj() const { return m_side_calc.get_pj(); }
|
||||
inline point1_type const& rpk() const { return m_side_calc.get_pk(); }
|
||||
|
||||
inline Point2 const& qi() const { return m_side_calc.m_qi; }
|
||||
inline Point2 const& qj() const { return m_side_calc.m_qj; }
|
||||
inline Point2 const& qk() const { return m_side_calc.m_qk; }
|
||||
|
||||
inline Point1 const& rpi() const { return pi(); }
|
||||
inline Point1 const& rpj() const { return pj(); }
|
||||
inline Point1 const& rpk() const { return pk(); }
|
||||
|
||||
inline Point2 const& rqi() const { return qi(); }
|
||||
inline Point2 const& rqj() const { return qj(); }
|
||||
inline Point2 const& rqk() const { return qk(); }
|
||||
inline point2_type const& rqi() const { return m_side_calc.get_qi(); }
|
||||
inline point2_type const& rqj() const { return m_side_calc.get_qj(); }
|
||||
inline point2_type const& rqk() const { return m_side_calc.get_qk(); }
|
||||
|
||||
inline side_calculator_type const& sides() const { return m_side_calc; }
|
||||
|
||||
private:
|
||||
|
||||
swapped_side_calculator_type get_swapped_sides() const
|
||||
{
|
||||
swapped_side_calculator_type result(
|
||||
m_range_q, m_range_p,
|
||||
m_side_calc.m_side_strategy);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected :
|
||||
// Owned by get_turns
|
||||
UniqueSubRange1 const& m_range_p;
|
||||
UniqueSubRange2 const& m_range_q;
|
||||
private :
|
||||
// Owned here, passed by .get_side_strategy()
|
||||
side_calculator_type m_side_calc;
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename UniqueSubRange1, typename UniqueSubRange2,
|
||||
typename TurnPoint,
|
||||
typename IntersectionStrategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
class intersection_info
|
||||
: public intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy>
|
||||
: public intersection_info_base<UniqueSubRange1, UniqueSubRange2,
|
||||
TurnPoint, IntersectionStrategy, RobustPolicy>
|
||||
{
|
||||
typedef intersection_info_base<Point1, Point2, TurnPoint, IntersectionStrategy, RobustPolicy> base;
|
||||
typedef intersection_info_base<UniqueSubRange1, UniqueSubRange2,
|
||||
TurnPoint, IntersectionStrategy, RobustPolicy> base;
|
||||
|
||||
public:
|
||||
typedef segment_intersection_points
|
||||
@@ -224,6 +374,9 @@ public:
|
||||
>::type
|
||||
> intersection_point_type;
|
||||
|
||||
typedef typename UniqueSubRange1::point_type point1_type;
|
||||
typedef typename UniqueSubRange2::point_type point2_type;
|
||||
|
||||
// NOTE: formerly defined in intersection_strategies
|
||||
typedef policies::relate::segments_tupled
|
||||
<
|
||||
@@ -237,22 +390,23 @@ public:
|
||||
typedef IntersectionStrategy intersection_strategy_type;
|
||||
typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
|
||||
|
||||
typedef model::referring_segment<Point1 const> segment_type1;
|
||||
typedef model::referring_segment<Point2 const> segment_type2;
|
||||
typedef model::referring_segment<point1_type const> segment_type1;
|
||||
typedef model::referring_segment<point2_type const> segment_type2;
|
||||
typedef typename base::side_calculator_type side_calculator_type;
|
||||
|
||||
typedef typename intersection_policy_type::return_type result_type;
|
||||
typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info
|
||||
typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info
|
||||
|
||||
intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,
|
||||
Point2 const& qi, Point2 const& qj, Point2 const& qk,
|
||||
intersection_info(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
: base(pi, pj, pk, qi, qj, qk, intersection_strategy, robust_policy)
|
||||
: base(range_p, range_q,
|
||||
intersection_strategy, robust_policy)
|
||||
, m_result(intersection_strategy.apply(
|
||||
segment_type1(pi, pj),
|
||||
segment_type2(qi, qj),
|
||||
segment_type1(range_p.at(0), range_p.at(1)),
|
||||
segment_type2(range_q.at(0), range_q.at(1)),
|
||||
intersection_policy_type(),
|
||||
robust_policy,
|
||||
base::rpi(), base::rpj(),
|
||||
@@ -265,11 +419,6 @@ public:
|
||||
inline i_info_type const& i_info() const { return m_result.template get<0>(); }
|
||||
inline d_info_type const& d_info() const { return m_result.template get<1>(); }
|
||||
|
||||
inline intersection_strategy_type const& get_intersection_strategy() const
|
||||
{
|
||||
return m_intersection_strategy;
|
||||
}
|
||||
|
||||
inline side_strategy_type get_side_strategy() const
|
||||
{
|
||||
return m_intersection_strategy.get_side_strategy();
|
||||
@@ -278,24 +427,36 @@ public:
|
||||
// TODO: it's more like is_spike_ip_p
|
||||
inline bool is_spike_p() const
|
||||
{
|
||||
if (base::m_range_p.is_last_segment())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (base::sides().pk_wrt_p1() == 0)
|
||||
{
|
||||
// p: pi--------pj--------pk
|
||||
// or: pi----pk==pj
|
||||
|
||||
if (! is_ip_j<0>())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int const qk_p1 = base::sides().qk_wrt_p1();
|
||||
int const qk_p2 = base::sides().qk_wrt_p2();
|
||||
|
||||
// TODO: why is q used to determine spike property in p?
|
||||
bool const has_qk = ! base::m_range_q.is_last_segment();
|
||||
int const qk_p1 = has_qk ? base::sides().qk_wrt_p1() : 0;
|
||||
int const qk_p2 = has_qk ? base::sides().qk_wrt_p2() : 0;
|
||||
|
||||
if (qk_p1 == -qk_p2)
|
||||
{
|
||||
if (qk_p1 == 0)
|
||||
{
|
||||
return is_spike_of_collinear(base::pi(), base::pj(),
|
||||
base::pk());
|
||||
// qk is collinear with both p1 and p2,
|
||||
// verify if pk goes backwards w.r.t. pi/pj
|
||||
return direction_code(base::rpi(), base::rpj(), base::rpk()) == -1;
|
||||
}
|
||||
|
||||
|
||||
// qk is at opposite side of p1/p2, therefore
|
||||
// p1/p2 (collinear) are opposite and form a spike
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -303,9 +464,14 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: it's more like is_spike_ip_q
|
||||
inline bool is_spike_q() const
|
||||
{
|
||||
if (base::m_range_q.is_last_segment())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// See comments at is_spike_p
|
||||
if (base::sides().qk_wrt_q1() == 0)
|
||||
{
|
||||
if (! is_ip_j<1>())
|
||||
@@ -313,15 +479,16 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
int const pk_q1 = base::sides().pk_wrt_q1();
|
||||
int const pk_q2 = base::sides().pk_wrt_q2();
|
||||
// TODO: why is p used to determine spike property in q?
|
||||
bool const has_pk = ! base::m_range_p.is_last_segment();
|
||||
int const pk_q1 = has_pk ? base::sides().pk_wrt_q1() : 0;
|
||||
int const pk_q2 = has_pk ? base::sides().pk_wrt_q2() : 0;
|
||||
|
||||
if (pk_q1 == -pk_q2)
|
||||
{
|
||||
if (pk_q1 == 0)
|
||||
{
|
||||
return is_spike_of_collinear(base::qi(), base::qj(),
|
||||
base::qk());
|
||||
return direction_code(base::rqi(), base::rqj(), base::rqk()) == -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -332,26 +499,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Point>
|
||||
inline bool is_spike_of_collinear(Point const& i, Point const& j,
|
||||
Point const& k) const
|
||||
{
|
||||
typedef model::referring_segment<Point const> seg;
|
||||
|
||||
// no need to calcualte direction info
|
||||
typedef policies::relate::segments_intersection_points
|
||||
<
|
||||
intersection_point_type
|
||||
> policy_type;
|
||||
|
||||
typename policy_type::return_type const result
|
||||
= m_intersection_strategy.apply(seg(i, j), seg(j, k),
|
||||
policy_type(),
|
||||
m_robust_policy);
|
||||
|
||||
return result.count == 2;
|
||||
}
|
||||
|
||||
template <std::size_t OpId>
|
||||
bool is_ip_j() const
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user