mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-01 20:42:10 +00:00
Merge branch 'develop' into feature/meridian_andoyer
This commit is contained in:
@@ -16,6 +16,8 @@ machine:
|
||||
environment:
|
||||
# define tests list, if parallelism is enabled they are run in parallel
|
||||
TESTS: test index/test
|
||||
TESTS0: test/core test/concepts test/geometries test/arithmetic test/algorithms test/formulas test/iterators
|
||||
TESTS1: test/strategies test/policies test/io test/util test/views index/test
|
||||
|
||||
# this is not fully bulletproof, ideally one should check
|
||||
# if the current branch originates in master or develop
|
||||
@@ -109,7 +111,11 @@ test:
|
||||
#- cd $BOOST_ROOT/libs/geometry && index=0 ; run_tests() { for i in "$1"/* ; do if [ -f "$i"/Jamfile* ] ; then ((index++)) ; echo "$index - $i" ; ../../b2 cxxflags="--coverage" linkflags="--coverage" "$i" ; run_tests "$i" ; fi ; done } ; run_tests test
|
||||
|
||||
# so for now just run the tests from the list
|
||||
- cd $BOOST_ROOT/libs/geometry && status=0; index=0 ; for t in ${TESTS[@]} ; do if [ $(((index++)%CIRCLE_NODE_TOTAL)) == $CIRCLE_NODE_INDEX ] ; then ../../b2 -j2 cxxflags="--coverage" linkflags="--coverage" $t ; fi || status=$? ; done ; exit $status :
|
||||
#- cd $BOOST_ROOT/libs/geometry && status=0; index=0 ; for t in ${TESTS[@]} ; do if [ $(((index++)%CIRCLE_NODE_TOTAL)) == $CIRCLE_NODE_INDEX ] ; then ../../b2 -j2 cxxflags="--coverage" linkflags="--coverage" $t ; fi || status=$? ; done ; exit $status :
|
||||
# parallel: true
|
||||
|
||||
# so for now just run the tests from 2 lists
|
||||
- cd $BOOST_ROOT/libs/geometry && status=0; case $CIRCLE_NODE_INDEX in 0) for t in ${TESTS0[@]} ; do ../../b2 -j2 cxxflags="--coverage" linkflags="--coverage" $t || status=$? ; done ;; 1) for t in ${TESTS1[@]} ; do ../../b2 -j2 cxxflags="--coverage" linkflags="--coverage" $t || status=$? ; done ;; esac ; exit $status :
|
||||
parallel: true
|
||||
|
||||
post:
|
||||
|
||||
@@ -546,7 +546,7 @@ where a strategy is specified explicitly and constructed with a radius.
|
||||
[heading Point Concept]
|
||||
The five traits classes mentioned in the previous sections form together the
|
||||
Point Concept. Any point type for which specializations are implemented in
|
||||
the traits namespace should be accepted a as valid type. So the Point Concept
|
||||
the traits namespace should be accepted as a valid type. So the Point Concept
|
||||
consists of:
|
||||
|
||||
* a specialization for `traits::tag`
|
||||
@@ -637,6 +637,20 @@ and modify our distance function:
|
||||
Of course also the apply functions in the dispatch specializations will return a result like this.
|
||||
They have a strategy as a template parameter everywhere, making the less verbose version possible.
|
||||
|
||||
[heading Axis Order]
|
||||
|
||||
This is an important note for users who develop GIS applications, require compliance with OGC
|
||||
standards or use variety of coordinate reference systems (CRS).
|
||||
|
||||
Boost.Geometry convention is that coordinate values of 2D tuple is always given according to
|
||||
mathematical axis order: X,Y. Considering GIS applications, that always means easting,northing or,
|
||||
in terms of geographic coordinate system: longitude,latitude.
|
||||
Boost.Geometry does not allow or respect coordinate values listed in the axis order as
|
||||
specified by coordinate reference system (CRS).
|
||||
|
||||
In practice, users may easily adapt point types with alternate axis ordering and
|
||||
specify coordinate access in order as expected by Boost.Geometry.
|
||||
|
||||
[heading Summary]
|
||||
|
||||
In this design rationale, __boost_geometry__ is step by step designed using tag dispatching,
|
||||
|
||||
@@ -69,14 +69,19 @@ Examples of some basic queries may be found in the tables below. The query regio
|
||||
]
|
||||
|
||||
[table
|
||||
[[intersects(Ring)] [intersects(Polygon)] [intersects(MultiPolygon)] [intersects(Segment)] [intersects(Linestring)]]
|
||||
[[[$img/index/rtree/intersects_ring.png]] [[$img/index/rtree/intersects_poly.png]] [[$img/index/rtree/intersects_mpoly.png]] [[$img/index/rtree/intersects_segment.png]] [[$img/index/rtree/intersects_linestring.png]]]
|
||||
[[intersects(Segment)] [intersects(Box)] [disjoint(Box)] [intersects(Box)] [disjoint(Box)]]
|
||||
[[[$img/index/rtree/intersects_segment.png]] [[$img/index/rtree/rtree_pt_intersects_box.png]] [[$img/index/rtree/rtree_pt_disjoint_box.png]] [[$img/index/rtree/rtree_seg_intersects_box.png]] [[$img/index/rtree/rtree_seg_disjoint_box.png]]]
|
||||
]
|
||||
|
||||
[table
|
||||
[/table
|
||||
[[intersects(Ring)] [intersects(Polygon)] [intersects(MultiPolygon)] [intersects(Segment)] [intersects(Linestring)]]
|
||||
[[[$img/index/rtree/intersects_ring.png]] [[$img/index/rtree/intersects_poly.png]] [[$img/index/rtree/intersects_mpoly.png]] [[$img/index/rtree/intersects_segment.png]] [[$img/index/rtree/intersects_linestring.png]]]
|
||||
/]
|
||||
|
||||
[/table
|
||||
[[intersects(Box)] [disjoint(Box)] [intersects(Box)] [disjoint(Box)]]
|
||||
[[[$img/index/rtree/rtree_pt_intersects_box.png]] [[$img/index/rtree/rtree_pt_disjoint_box.png]] [[$img/index/rtree/rtree_seg_intersects_box.png]] [[$img/index/rtree/rtree_seg_disjoint_box.png]]]
|
||||
]
|
||||
/]
|
||||
|
||||
Spatial predicates are generated by functions defined in `boost::geometry::index` namespace.
|
||||
|
||||
|
||||
@@ -89,7 +89,10 @@
|
||||
[include generated/clear.qbk]
|
||||
[include generated/convert.qbk]
|
||||
[include generated/convex_hull.qbk]
|
||||
|
||||
[section:correct correct]
|
||||
[include generated/correct.qbk]
|
||||
[endsect]
|
||||
|
||||
[section:covered_by covered_by]
|
||||
[include generated/covered_by.qbk]
|
||||
|
||||
@@ -18,20 +18,48 @@
|
||||
|
||||
[section:release_notes Release Notes]
|
||||
|
||||
[/=================]
|
||||
[heading Boost 1.66]
|
||||
[/=================]
|
||||
|
||||
[*Improvements]
|
||||
|
||||
[*Solved issues]
|
||||
|
||||
* [@https://svn.boost.org/trac10/ticket/12503 12503] Validity of complex polygon
|
||||
|
||||
[*Bugfixes]
|
||||
|
||||
* Fixes in validity of union/intersection/differece which were sometimes invalid. In most cases, results are valid now.
|
||||
* Fixes in results of union/intersection/differece which could be incorrect in very complex cases
|
||||
|
||||
[/=================]
|
||||
[heading Boost 1.65]
|
||||
[/=================]
|
||||
|
||||
[*Improvements]
|
||||
|
||||
* Add correct() overload taking area strategy
|
||||
* Add is_convex() overload taking side strategy
|
||||
* Add missing relational operations (covered_by, crosses, equals, etc.) for MultiPoint/AnyGeometry
|
||||
|
||||
[*Solved issues]
|
||||
|
||||
* [@https://svn.boost.org/trac/boost/ticket/12410 12410] Lack of support of geographic coordinate system in correct()
|
||||
* [@https://svn.boost.org/trac/boost/ticket/13035 13035] Wrong result of non-cartesian intersection strategies for segments near poles.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/13057 13057] Wrong result of intersects() for linestrings caused by numerical issue in disjoint() for boxes.
|
||||
|
||||
[*Bugfixes]
|
||||
|
||||
* Fix is_valid which could return false for multipolygons where an interior ring touches another interior ring
|
||||
* Fix union which could produce invalid results (for some cases, this needs to define BOOST_GEOMETRY_INCLUDE_SELF_TURNS
|
||||
* Fix is_valid which could return false for multipolygons where a polygon was located in an interior ring, all touching each other
|
||||
* Fix union which could produce invalid results (for some cases, this needs to define BOOST_GEOMETRY_INCLUDE_SELF_TURNS)
|
||||
* Fix intersection (idem), but some cases are still not yet valid
|
||||
* Fix difference (idem), but some cases are still not yet valid
|
||||
* Fix propagation of area strategy into the internals of various algorithms from intersection strategy
|
||||
* Fix uninitialized variable in relate and reference to temporary in overlay
|
||||
* Fix error in disjoint for geographic Segment/Box
|
||||
* Fix handling of non-cartesian geometries in various algorithms
|
||||
|
||||
[/=================]
|
||||
[heading Boost 1.64]
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -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.
|
||||
|
||||
@@ -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 Strategy::return_type area_result_type;
|
||||
Predicate<area_result_type> predicate;
|
||||
area_result_type const zero = 0;
|
||||
if (predicate(ring_area_type::apply(r, strategy), zero))
|
||||
{
|
||||
std::reverse(boost::begin(r), boost::end(r));
|
||||
}
|
||||
@@ -174,15 +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,37 @@ struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry>
|
||||
inline void correct(Geometry& geometry)
|
||||
{
|
||||
resolve_variant::correct<Geometry>::apply(geometry);
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
|
||||
typedef typename strategy::area::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type,
|
||||
point_type
|
||||
>::type strategy_type;
|
||||
|
||||
resolve_variant::correct<Geometry>::apply(geometry, strategy_type());
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Corrects a geometry
|
||||
\details Corrects a geometry: all rings which are wrongly oriented with respect
|
||||
to their expected orientation are reversed. To all rings which do not have a
|
||||
closing point and are typed as they should have one, the first point is
|
||||
appended. Also boxes can be corrected.
|
||||
\ingroup correct
|
||||
\tparam Geometry \tparam_geometry
|
||||
\tparam Strategy \tparam_strategy{Area}
|
||||
\param geometry \param_geometry which will be corrected if necessary
|
||||
\param strategy \param_strategy{area}
|
||||
|
||||
\qbk{distinguish,with strategy}
|
||||
|
||||
\qbk{[include reference/algorithms/correct.qbk]}
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline void correct(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
resolve_variant::correct<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
235
include/boost/geometry/algorithms/correct_closure.hpp
Normal file
235
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
|
||||
@@ -122,7 +122,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 +134,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 +159,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 +185,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 +195,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 +203,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 +231,18 @@ 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
|
||||
output_point_type& first_p1,
|
||||
output_point_type& first_p2,
|
||||
output_point_type& last_p1,
|
||||
@@ -273,7 +274,7 @@ struct buffer_range
|
||||
* pup: penultimate_point
|
||||
*/
|
||||
|
||||
strategy::buffer::result_code result = strategy::buffer::result_no_output;
|
||||
geometry::strategy::buffer::result_code result = geometry::strategy::buffer::result_no_output;
|
||||
bool first = true;
|
||||
|
||||
Iterator it = begin;
|
||||
@@ -284,25 +285,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,7 +313,7 @@ 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);
|
||||
@@ -350,7 +351,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 +361,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 +372,7 @@ struct buffer_multi
|
||||
Policy::apply(*it, collection,
|
||||
distance_strategy, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -396,9 +399,9 @@ inline void buffer_point(Point const& point, Collection& collection,
|
||||
collection.start_new_ring();
|
||||
std::vector<OutputPointType> range_out;
|
||||
point_strategy.apply(point, distance_strategy, range_out);
|
||||
collection.add_piece(strategy::buffer::buffered_point, range_out, false);
|
||||
collection.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 +439,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 +448,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 +477,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,
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
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 +510,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 +525,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 +556,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 +598,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
|
||||
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 +641,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 +663,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 +684,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,
|
||||
distance_strategy, side_strategy, join_strategy, end_strategy,
|
||||
robust_policy, strategy,
|
||||
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,20 +709,23 @@ 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)
|
||||
{
|
||||
@@ -712,21 +733,23 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
|
||||
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 +786,8 @@ private:
|
||||
typename JoinStrategy,
|
||||
typename EndStrategy,
|
||||
typename PointStrategy,
|
||||
typename RobustPolicy
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
>
|
||||
static inline
|
||||
void iterate(Iterator begin, Iterator end,
|
||||
@@ -774,15 +798,16 @@ 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
|
||||
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 +822,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 +833,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 +851,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 +861,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();
|
||||
|
||||
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 +880,7 @@ public:
|
||||
apply_interior_rings(interior_rings(polygon),
|
||||
collection, distance, side_strategy,
|
||||
join_strategy, end_strategy, point_strategy,
|
||||
robust_policy);
|
||||
robust_policy, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -945,7 +974,7 @@ 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);
|
||||
|
||||
@@ -46,6 +46,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 +143,20 @@ struct buffered_piece_collection
|
||||
robust_point_type
|
||||
>::type robust_comparable_radius_type;
|
||||
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
typedef typename IntersectionStrategy::side_strategy_type side_strategy_type;
|
||||
|
||||
typedef typename IntersectionStrategy::template area_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type
|
||||
>::type side_strategy;
|
||||
point_type
|
||||
>::type area_strategy_type;
|
||||
|
||||
typedef typename IntersectionStrategy::template area_strategy
|
||||
<
|
||||
robust_point_type
|
||||
>::type robust_area_strategy_type;
|
||||
|
||||
typedef typename area_strategy_type::return_type area_result_type;
|
||||
typedef typename robust_area_strategy_type::return_type robust_area_result_type;
|
||||
|
||||
typedef typename geometry::rescale_policy_type
|
||||
<
|
||||
@@ -306,7 +317,10 @@ struct buffered_piece_collection
|
||||
|
||||
cluster_type m_clusters;
|
||||
|
||||
IntersectionStrategy const& m_intersection_strategy;
|
||||
IntersectionStrategy m_intersection_strategy;
|
||||
side_strategy_type m_side_strategy;
|
||||
area_strategy_type m_area_strategy;
|
||||
robust_area_strategy_type m_robust_area_strategy;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
|
||||
struct redundant_turn
|
||||
@@ -321,6 +335,9 @@ struct buffered_piece_collection
|
||||
RobustPolicy const& robust_policy)
|
||||
: m_first_piece_index(-1)
|
||||
, m_intersection_strategy(intersection_strategy)
|
||||
, m_side_strategy(intersection_strategy.get_side_strategy())
|
||||
, m_area_strategy(intersection_strategy.template get_area_strategy<point_type>())
|
||||
, m_robust_area_strategy(intersection_strategy.template get_area_strategy<robust_point_type>())
|
||||
, m_robust_policy(robust_policy)
|
||||
{}
|
||||
|
||||
@@ -478,7 +495,7 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,7 +716,7 @@ struct buffered_piece_collection
|
||||
++it)
|
||||
{
|
||||
piece& pc = *it;
|
||||
if (geometry::area(pc.robust_ring) < 0)
|
||||
if (geometry::area(pc.robust_ring, m_robust_area_strategy) < 0)
|
||||
{
|
||||
// Rings can be ccw:
|
||||
// - in a concave piece
|
||||
@@ -1220,14 +1237,9 @@ struct buffered_piece_collection
|
||||
|
||||
inline void enrich()
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Ring>::type
|
||||
>::type side_strategy_type;
|
||||
|
||||
enrich_intersection_points<false, false, overlay_buffer>(m_turns,
|
||||
m_clusters, offsetted_rings, offsetted_rings,
|
||||
m_robust_policy, side_strategy_type());
|
||||
m_robust_policy, m_side_strategy);
|
||||
}
|
||||
|
||||
// Discards all rings which do have not-OK intersection points only.
|
||||
@@ -1314,7 +1326,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 +1370,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 +1405,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 +1421,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 +1437,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,7 +1445,10 @@ struct buffered_piece_collection
|
||||
}
|
||||
}
|
||||
|
||||
detail::overlay::assign_parents(offsetted_rings, traversed_rings, selected, m_intersection_strategy, true);
|
||||
// Assign parents, checking orientation but NOT discarding double
|
||||
// negative rings (negative child with negative parent)
|
||||
detail::overlay::assign_parents(offsetted_rings, traversed_rings,
|
||||
selected, m_intersection_strategy, true, false);
|
||||
return detail::overlay::add_rings<GeometryOutput>(selected, offsetted_rings, traversed_rings, out);
|
||||
}
|
||||
|
||||
|
||||
@@ -127,26 +127,31 @@ class piece_turn_visitor
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -192,23 +197,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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -121,9 +121,18 @@ struct box_box<Box1, Box2, 0, DimensionCount, spherical_tag>
|
||||
// calculate positive longitude translation with b1_min as origin
|
||||
calc_t const diff_min = math::longitude_distance_unsigned<units_t>(b1_min, b2_min);
|
||||
calc_t const b2_min_transl = b1_min + diff_min; // always right of b1_min
|
||||
calc_t b2_max_transl = b2_min_transl - constants::period() + diff2;
|
||||
|
||||
if (b2_min_transl > b1_max // b2_min right of b1_max
|
||||
&& b2_min_transl - constants::period() + diff2 < b1_min) // b2_max left of b1_min
|
||||
// if the translation is too close then use the original point
|
||||
// note that math::abs(b2_max_transl - b2_max) takes values very
|
||||
// close to k*2*constants::period() for k=0,1,2,...
|
||||
if (math::abs(b2_max_transl - b2_max) < constants::period() / 2)
|
||||
{
|
||||
b2_max_transl = b2_max;
|
||||
}
|
||||
|
||||
if (b2_min_transl > b1_max // b2_min right of b1_max
|
||||
&& b2_max_transl < b1_min) // b2_max left of b1_min
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,10 +36,11 @@
|
||||
#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
|
||||
{
|
||||
@@ -56,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)
|
||||
@@ -90,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
|
||||
<
|
||||
|
||||
@@ -391,7 +391,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
|
||||
<
|
||||
|
||||
@@ -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.
|
||||
// Modifications copyright (c) 2015-2017, 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
|
||||
@@ -146,12 +147,18 @@ namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Box, typename CS_Tag>
|
||||
struct envelope<Box, box_tag, CS_Tag>
|
||||
template <typename Box>
|
||||
struct envelope<Box, box_tag, cartesian_tag>
|
||||
: detail::envelope::envelope_box
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct envelope<Box, box_tag, spherical_polar_tag>
|
||||
: detail::envelope::envelope_box_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct envelope<Box, box_tag, spherical_equatorial_tag>
|
||||
: detail::envelope::envelope_box_on_spheroid
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2015-2017, 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
|
||||
@@ -336,8 +337,6 @@ public:
|
||||
{
|
||||
detail::expand::point_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
2, dimension<Box>::value
|
||||
>::apply(mbr, *it, strategy);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
// This file was modified by Oracle on 2015, 2016, 2017.
|
||||
// Modifications copyright (c) 2015-2016, 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
|
||||
@@ -102,12 +103,18 @@ namespace dispatch
|
||||
{
|
||||
|
||||
|
||||
template <typename Point, typename CS_Tag>
|
||||
struct envelope<Point, point_tag, CS_Tag>
|
||||
template <typename Point>
|
||||
struct envelope<Point, point_tag, cartesian_tag>
|
||||
: detail::envelope::envelope_one_point<0, dimension<Point>::value>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct envelope<Point, point_tag, spherical_polar_tag>
|
||||
: detail::envelope::envelope_point_on_spheroid
|
||||
{};
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct envelope<Point, point_tag, spherical_equatorial_tag>
|
||||
: detail::envelope::envelope_point_on_spheroid
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015-2016, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2015-2017, 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
|
||||
@@ -194,8 +195,6 @@ struct envelope_range_of_boxes_by_expansion
|
||||
{
|
||||
detail::expand::indexed_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
min_corner,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
@@ -203,8 +202,6 @@ struct envelope_range_of_boxes_by_expansion
|
||||
|
||||
detail::expand::indexed_loop
|
||||
<
|
||||
strategy::compare::default_strategy,
|
||||
strategy::compare::default_strategy,
|
||||
max_corner,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
@@ -243,9 +240,15 @@ struct envelope_range_of_boxes
|
||||
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;
|
||||
|
||||
@@ -80,6 +80,35 @@ struct envelope_segment_call_vertex_latitude<CalculationType, geographic_tag>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Units, typename CS_Tag>
|
||||
struct envelope_segment_convert_polar
|
||||
{
|
||||
template <typename T>
|
||||
static inline void pre(T & , T & ) {}
|
||||
|
||||
template <typename T>
|
||||
static inline void post(T & , T & ) {}
|
||||
};
|
||||
|
||||
template <typename Units>
|
||||
struct envelope_segment_convert_polar<Units, spherical_polar_tag>
|
||||
{
|
||||
template <typename T>
|
||||
static inline void pre(T & lat1, T & lat2)
|
||||
{
|
||||
lat1 = math::latitude_convert_ep<Units>(lat1);
|
||||
lat2 = math::latitude_convert_ep<Units>(lat2);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline void post(T & lat1, T & lat2)
|
||||
{
|
||||
lat1 = math::latitude_convert_ep<Units>(lat1);
|
||||
lat2 = math::latitude_convert_ep<Units>(lat2);
|
||||
std::swap(lat1, lat2);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CS_Tag>
|
||||
class envelope_segment_impl
|
||||
{
|
||||
@@ -266,29 +295,29 @@ private:
|
||||
Box, box_coordinate_type, Units
|
||||
>::type helper_box_type;
|
||||
|
||||
helper_box_type radian_mbr;
|
||||
helper_box_type helper_mbr;
|
||||
|
||||
geometry::set
|
||||
<
|
||||
min_corner, 0
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon1));
|
||||
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lon1));
|
||||
|
||||
geometry::set
|
||||
<
|
||||
min_corner, 1
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat1));
|
||||
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lat1));
|
||||
|
||||
geometry::set
|
||||
<
|
||||
max_corner, 0
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lon2));
|
||||
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lon2));
|
||||
|
||||
geometry::set
|
||||
<
|
||||
max_corner, 1
|
||||
>(radian_mbr, boost::numeric_cast<box_coordinate_type>(lat2));
|
||||
>(helper_mbr, boost::numeric_cast<box_coordinate_type>(lat2));
|
||||
|
||||
transform_units(radian_mbr, mbr);
|
||||
transform_units(helper_mbr, mbr);
|
||||
}
|
||||
|
||||
|
||||
@@ -347,7 +376,14 @@ public:
|
||||
Box& mbr,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef envelope_segment_convert_polar<Units, typename cs_tag<Box>::type> convert_polar;
|
||||
|
||||
convert_polar::pre(lat1, lat2);
|
||||
|
||||
apply<Units>(lon1, lat1, lon2, lat2, strategy);
|
||||
|
||||
convert_polar::post(lat1, lat2);
|
||||
|
||||
create_box<Units>(lon1, lat1, lon2, lat2, mbr);
|
||||
}
|
||||
|
||||
@@ -366,7 +402,14 @@ public:
|
||||
Strategy const& strategy,
|
||||
CalculationType alp1)
|
||||
{
|
||||
typedef envelope_segment_convert_polar<Units, typename cs_tag<Box>::type> convert_polar;
|
||||
|
||||
convert_polar::pre(lat1, lat2);
|
||||
|
||||
apply<Units>(lon1, lat1, lon2, lat2, strategy, alp1);
|
||||
|
||||
convert_polar::post(lat1, lat2);
|
||||
|
||||
create_box<Units>(lon1, lat1, lon2, lat2, mbr);
|
||||
}
|
||||
};
|
||||
@@ -383,8 +426,6 @@ struct envelope_one_segment
|
||||
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);
|
||||
@@ -409,13 +450,14 @@ struct envelope_segment
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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.
|
||||
// Modifications copyright (c) 2015-2017, 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
|
||||
@@ -73,48 +74,54 @@ namespace dispatch
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename BoxIn,
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
typename CSTagOut, typename CSTag
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, BoxIn,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, box_tag,
|
||||
CSTagOut, CSTag
|
||||
> : detail::expand::expand_indexed
|
||||
<
|
||||
0, dimension<BoxIn>::value, StrategyLess, StrategyGreater
|
||||
>
|
||||
>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
|
||||
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
|
||||
BOOST_MPL_ASSERT_MSG((false),
|
||||
NOT_IMPLEMENTED_FOR_THESE_COORDINATE_SYSTEMS,
|
||||
(types<CSTagOut, CSTag>()));
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename BoxIn,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
template <typename BoxOut, typename BoxIn>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, BoxIn,
|
||||
box_tag, box_tag,
|
||||
cartesian_tag, cartesian_tag
|
||||
> : detail::expand::expand_indexed
|
||||
<
|
||||
0, dimension<BoxIn>::value
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename BoxOut, typename BoxIn>
|
||||
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
|
||||
>
|
||||
template <typename BoxOut, typename BoxIn>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, BoxIn,
|
||||
box_tag, box_tag,
|
||||
spherical_polar_tag, spherical_polar_tag
|
||||
> : detail::expand::box_on_spheroid
|
||||
{};
|
||||
|
||||
template <typename BoxOut, typename BoxIn>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, BoxIn,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, box_tag,
|
||||
geographic_tag, geographic_tag
|
||||
> : detail::expand::box_on_spheroid
|
||||
|
||||
@@ -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.
|
||||
// Modifications copyright (c) 2015-2017, 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,7 +43,6 @@ namespace detail { namespace expand
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
std::size_t Index,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
@@ -53,27 +51,17 @@ struct indexed_loop
|
||||
template <typename Box, typename Geometry, typename Strategy>
|
||||
static inline void apply(Box& box, Geometry const& source, Strategy const& strategy)
|
||||
{
|
||||
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,21 +74,15 @@ struct indexed_loop
|
||||
|
||||
indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
Index, Dimension + 1, DimensionCount
|
||||
>::apply(box, source, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
>
|
||||
{
|
||||
@@ -111,11 +93,7 @@ struct indexed_loop
|
||||
|
||||
|
||||
// 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>
|
||||
@@ -125,13 +103,11 @@ struct expand_indexed
|
||||
{
|
||||
indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
0, Dimension, DimensionCount
|
||||
>::apply(box, geometry, strategy);
|
||||
|
||||
indexed_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
1, Dimension, DimensionCount
|
||||
>::apply(box, geometry, strategy);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
// Modifications copyright (c) 2015-2017, 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,6 +24,7 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
@@ -36,9 +38,6 @@
|
||||
#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>
|
||||
|
||||
@@ -53,33 +52,19 @@ namespace detail { namespace expand
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
template <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;
|
||||
std::less<coordinate_type> less;
|
||||
std::greater<coordinate_type> greater;
|
||||
|
||||
coordinate_type const coord = get<Dimension>(source);
|
||||
|
||||
@@ -93,37 +78,21 @@ struct point_loop
|
||||
set<max_corner, Dimension>(box, coord);
|
||||
}
|
||||
|
||||
point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, Dimension + 1, DimensionCount
|
||||
>::apply(box, source, strategy);
|
||||
point_loop<Dimension + 1, DimensionCount>::apply(box, source, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess,
|
||||
typename StrategyGreater,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, DimensionCount, DimensionCount
|
||||
>
|
||||
template <std::size_t DimensionCount>
|
||||
struct point_loop<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
|
||||
>
|
||||
// implementation for the spherical and geographic coordinate systems
|
||||
template <std::size_t DimensionCount, bool IsEquatorial = true>
|
||||
struct point_loop_on_spheroid
|
||||
{
|
||||
template <typename Box, typename Point, typename Strategy>
|
||||
@@ -133,11 +102,12 @@ struct point_loop_on_spheroid
|
||||
{
|
||||
typedef typename point_type<Box>::type box_point_type;
|
||||
typedef typename coordinate_type<Box>::type box_coordinate_type;
|
||||
typedef typename coordinate_system<Box>::type::units units_type;
|
||||
|
||||
typedef math::detail::constants_on_spheroid
|
||||
<
|
||||
box_coordinate_type,
|
||||
typename coordinate_system<Box>::type::units
|
||||
units_type
|
||||
> constants;
|
||||
|
||||
// normalize input point and input box
|
||||
@@ -157,7 +127,7 @@ struct point_loop_on_spheroid
|
||||
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()))
|
||||
if (math::is_latitude_pole<units_type, IsEquatorial>(p_lat))
|
||||
{
|
||||
// the point of expansion is the either the north or the
|
||||
// south pole; the only important coordinate here is the
|
||||
@@ -169,7 +139,7 @@ struct point_loop_on_spheroid
|
||||
}
|
||||
|
||||
if (math::equals(b_lat_min, b_lat_max)
|
||||
&& math::equals(math::abs(b_lat_min), constants::max_latitude()))
|
||||
&& math::is_latitude_pole<units_type, IsEquatorial>(b_lat_min))
|
||||
{
|
||||
// the box degenerates to either the north or the south pole;
|
||||
// the only important coordinate here is the pole's latitude,
|
||||
@@ -228,7 +198,7 @@ struct point_loop_on_spheroid
|
||||
|
||||
point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, 2, DimensionCount
|
||||
2, DimensionCount
|
||||
>::apply(box, point, strategy);
|
||||
}
|
||||
};
|
||||
@@ -246,56 +216,70 @@ namespace dispatch
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename Point,
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
typename CSTagOut, typename CSTag
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, Point,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, point_tag,
|
||||
CSTagOut, CSTag
|
||||
> : detail::expand::point_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater, 0, dimension<Point>::value
|
||||
>
|
||||
>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
|
||||
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
|
||||
BOOST_MPL_ASSERT_MSG((false),
|
||||
NOT_IMPLEMENTED_FOR_THESE_COORDINATE_SYSTEMS,
|
||||
(types<CSTagOut, CSTag>()));
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename Point,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
|
||||
template <typename BoxOut, typename Point>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, Point,
|
||||
box_tag, point_tag,
|
||||
cartesian_tag, cartesian_tag
|
||||
> : detail::expand::point_loop
|
||||
<
|
||||
0, dimension<Point>::value
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename BoxOut, typename Point>
|
||||
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
|
||||
dimension<Point>::value
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename BoxOut, typename Point>
|
||||
struct expand
|
||||
<
|
||||
BoxOut, Point,
|
||||
box_tag, point_tag,
|
||||
spherical_polar_tag, spherical_polar_tag
|
||||
> : detail::expand::point_loop_on_spheroid
|
||||
<
|
||||
dimension<Point>::value,
|
||||
false
|
||||
>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename Point,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
typename BoxOut, typename Point
|
||||
>
|
||||
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
|
||||
dimension<Point>::value
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
@@ -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.
|
||||
// Modifications copyright (c) 2015-2017, 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
|
||||
@@ -77,48 +78,57 @@ namespace dispatch
|
||||
template
|
||||
<
|
||||
typename Box, typename Segment,
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
typename CSTagOut, typename CSTag
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, segment_tag,
|
||||
CSTagOut, CSTag
|
||||
> : detail::expand::expand_indexed
|
||||
<
|
||||
0, dimension<Segment>::value, StrategyLess, StrategyGreater
|
||||
>
|
||||
>
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((boost::is_same<CSTagOut, CSTag>::value),
|
||||
COORDINATE_SYSTEMS_MUST_BE_THE_SAME,
|
||||
BOOST_MPL_ASSERT_MSG((false),
|
||||
NOT_IMPLEMENTED_FOR_THESE_COORDINATE_SYSTEMS,
|
||||
(types<CSTagOut, CSTag>()));
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Box, typename Segment,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
typename Box, typename Segment
|
||||
>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, segment_tag,
|
||||
cartesian_tag, cartesian_tag
|
||||
> : detail::expand::expand_indexed
|
||||
<
|
||||
0, dimension<Segment>::value
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Box, typename Segment>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
box_tag, segment_tag,
|
||||
spherical_polar_tag, spherical_polar_tag
|
||||
> : detail::expand::segment
|
||||
{};
|
||||
|
||||
template <typename Box, typename Segment>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
box_tag, segment_tag,
|
||||
spherical_equatorial_tag, spherical_equatorial_tag
|
||||
> : detail::expand::segment
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Box, typename Segment,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
>
|
||||
template <typename Box, typename Segment>
|
||||
struct expand
|
||||
<
|
||||
Box, Segment,
|
||||
StrategyLess, StrategyGreater,
|
||||
box_tag, segment_tag,
|
||||
geographic_tag, geographic_tag
|
||||
> : detail::expand::segment
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-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
|
||||
|
||||
// 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)
|
||||
@@ -117,12 +122,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 +213,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 +238,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 +263,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 +276,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 +296,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 +307,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 +325,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 +369,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 +407,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 +417,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 +429,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 +439,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 +453,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 +468,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 +482,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 +498,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,7 +528,11 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -60,17 +65,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 +91,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 +115,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 +142,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 +192,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;
|
||||
|
||||
@@ -81,7 +81,11 @@ inline bool has_self_intersections(Geometry const& geometry,
|
||||
std::deque<turn_info> turns;
|
||||
detail::disjoint::disjoint_interrupt_policy policy;
|
||||
|
||||
detail::self_get_turn_points::self_turns<false, 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,
|
||||
|
||||
@@ -72,10 +72,11 @@ struct self_intersects
|
||||
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);
|
||||
>::apply(geometry, strategy, robust_policy, turns, policy, 0, true);
|
||||
return policy.has_intersections;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -217,6 +217,7 @@ 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
|
||||
<
|
||||
false, turn_policy
|
||||
@@ -224,7 +225,7 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg
|
||||
strategy,
|
||||
detail::no_rescale_policy(),
|
||||
turns,
|
||||
interrupt_policy, 0);
|
||||
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-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,8 @@ struct has_spikes
|
||||
|
||||
while (next != boost::end(view))
|
||||
{
|
||||
if ( geometry::detail::point_is_spike_or_equal(*prev,
|
||||
*next,
|
||||
*cur) )
|
||||
if ( geometry::detail::point_is_spike_or_equal(*prev, *next, *cur,
|
||||
strategy) )
|
||||
{
|
||||
return
|
||||
! visitor.template apply<failure_spikes>(is_linear, *cur);
|
||||
@@ -146,7 +147,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::point_is_spike_or_equal(*prev, *next, *cur, strategy))
|
||||
{
|
||||
return
|
||||
! visitor.template apply<failure_spikes>(is_linear, *cur);
|
||||
|
||||
@@ -125,34 +125,6 @@ private:
|
||||
typedef typename boost::range_value<MultiPolygon>::type polygon;
|
||||
typedef is_acceptable_turn<polygon> base;
|
||||
|
||||
template <typename Operation>
|
||||
static inline
|
||||
bool check_int_ext(Operation const& op1,
|
||||
detail::overlay::operation_type optype1,
|
||||
Operation const& op2,
|
||||
detail::overlay::operation_type optype2)
|
||||
{
|
||||
// u/i is acceptable for touch of interior ring with another exterior ring
|
||||
// (but only if there is a colocated uu-turn of its exterior, TODO)
|
||||
return op1.seg_id.ring_index == -1
|
||||
&& op2.seg_id.ring_index >= 0
|
||||
&& op1.operation == optype1
|
||||
&& op2.operation == optype2;
|
||||
}
|
||||
|
||||
template <typename Operation>
|
||||
static inline
|
||||
bool check_int_int(Operation const& op1,
|
||||
Operation const& op2,
|
||||
detail::overlay::operation_type optype)
|
||||
{
|
||||
// i/i is acceptable for touching interior/interior rings
|
||||
return op1.seg_id.ring_index >= 0
|
||||
&& op2.seg_id.ring_index >= 0
|
||||
&& op1.operation == optype
|
||||
&& op2.operation == optype;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename Turn>
|
||||
static inline bool apply(Turn const& turn)
|
||||
@@ -172,26 +144,11 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (turn.method != method_touch)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
operation_type const reverse_op
|
||||
= op == operation_union
|
||||
? operation_intersection
|
||||
: operation_union;
|
||||
|
||||
if ( check_int_int(turn.operations[0], turn.operations[1], reverse_op)
|
||||
|| check_int_ext(turn.operations[0], reverse_op,
|
||||
turn.operations[1], op)
|
||||
|| check_int_ext(turn.operations[1], reverse_op,
|
||||
turn.operations[0], op))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
// Turn is acceptable only in case of a touch(interior) and both lines
|
||||
// (polygons) do not cross
|
||||
return (turn.method == method_touch
|
||||
|| turn.method == method_touch_interior)
|
||||
&& turn.touch_only;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -89,12 +89,15 @@ private:
|
||||
{
|
||||
boost::ignore_unused(visitor);
|
||||
|
||||
// collect all polygons that have turns
|
||||
// collect all polygons that have crossing turns
|
||||
std::set<signed_size_type> multi_indices;
|
||||
for (TurnIterator tit = turns_first; tit != turns_beyond; ++tit)
|
||||
{
|
||||
multi_indices.insert(tit->operations[0].seg_id.multi_index);
|
||||
multi_indices.insert(tit->operations[1].seg_id.multi_index);
|
||||
if (! tit->touch_only)
|
||||
{
|
||||
multi_indices.insert(tit->operations[0].seg_id.multi_index);
|
||||
multi_indices.insert(tit->operations[1].seg_id.multi_index);
|
||||
}
|
||||
}
|
||||
|
||||
typedef geometry::model::box<typename point_type<MultiPolygon>::type> box_type;
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/num_interior_rings.hpp>
|
||||
#include <boost/geometry/algorithms/validity_failure_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
||||
#include <boost/geometry/algorithms/within.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
|
||||
@@ -216,14 +217,26 @@ protected:
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Item>
|
||||
inline bool is_within(Item const& first, Item const& second)
|
||||
{
|
||||
typename point_type<Polygon>::type point;
|
||||
typedef detail::point_on_border::point_on_range<true> pob;
|
||||
|
||||
// TODO: this should check for a point on the interior, instead
|
||||
// of on border. Or it should check using the overlap function.
|
||||
|
||||
return pob::apply(point, points_begin(first), points_end(first))
|
||||
&& geometry::within(point, second, m_strategy);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Box>
|
||||
inline bool apply(partition_item<Iterator, Box> const& item1,
|
||||
partition_item<Iterator, Box> const& item2)
|
||||
{
|
||||
if (! items_overlap
|
||||
&& (geometry::within(*points_begin(*item1.get()), *item2.get(), m_strategy)
|
||||
|| geometry::within(*points_begin(*item2.get()), *item1.get(), m_strategy))
|
||||
)
|
||||
&& (is_within(*item1.get(), *item2.get())
|
||||
|| is_within(*item2.get(), *item1.get())))
|
||||
{
|
||||
items_overlap = true;
|
||||
return false; // interrupt
|
||||
|
||||
@@ -115,7 +115,10 @@ struct is_properly_oriented
|
||||
geometry::closure<Ring>::value
|
||||
> ring_area_type;
|
||||
|
||||
typedef typename default_area_result<Ring>::type area_result_type;
|
||||
typedef typename Strategy::template area_strategy
|
||||
<
|
||||
point_type
|
||||
>::type::return_type area_result_type;
|
||||
|
||||
typename ring_area_predicate
|
||||
<
|
||||
@@ -195,7 +198,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-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
|
||||
@@ -120,7 +121,7 @@ struct assign_loop<1, DimensionCount>
|
||||
};
|
||||
|
||||
|
||||
template <typename PointIn, typename PointOut>
|
||||
template <typename PointIn, typename PointOut, bool IsEquatorial = true>
|
||||
struct normalize_point
|
||||
{
|
||||
static inline void apply(PointIn const& point_in, PointOut& point_out)
|
||||
@@ -133,6 +134,7 @@ struct normalize_point
|
||||
math::normalize_spheroidal_coordinates
|
||||
<
|
||||
typename coordinate_system<PointIn>::type::units,
|
||||
IsEquatorial,
|
||||
in_coordinate_type
|
||||
>(longitude, latitude);
|
||||
|
||||
@@ -144,7 +146,7 @@ struct normalize_point
|
||||
};
|
||||
|
||||
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
template <typename BoxIn, typename BoxOut, bool IsEquatorial = true>
|
||||
class normalize_box
|
||||
{
|
||||
template <typename UnitsIn, typename UnitsOut, typename CoordinateInType>
|
||||
@@ -193,6 +195,7 @@ public:
|
||||
math::normalize_spheroidal_box_coordinates
|
||||
<
|
||||
typename coordinate_system<BoxIn>::type::units,
|
||||
IsEquatorial,
|
||||
in_coordinate_type
|
||||
>(lon_min, lat_min, lon_max, lat_max);
|
||||
|
||||
@@ -234,6 +237,15 @@ struct normalize
|
||||
{};
|
||||
|
||||
|
||||
template <typename PointIn, typename PointOut>
|
||||
struct normalize
|
||||
<
|
||||
PointIn, PointOut, point_tag, point_tag,
|
||||
spherical_polar_tag, spherical_polar_tag
|
||||
> : detail::normalization::normalize_point<PointIn, PointOut, false>
|
||||
{};
|
||||
|
||||
|
||||
template <typename PointIn, typename PointOut>
|
||||
struct normalize
|
||||
<
|
||||
@@ -251,6 +263,15 @@ struct normalize
|
||||
{};
|
||||
|
||||
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
struct normalize
|
||||
<
|
||||
BoxIn, BoxOut, box_tag, box_tag,
|
||||
spherical_polar_tag, spherical_polar_tag
|
||||
> : detail::normalization::normalize_box<BoxIn, BoxOut, false>
|
||||
{};
|
||||
|
||||
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
struct normalize
|
||||
<
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -25,7 +25,7 @@ struct ring_with_direction
|
||||
ring_identifier ring_id;
|
||||
direction_type direction;
|
||||
|
||||
std::size_t turn_index;
|
||||
signed_size_type turn_index;
|
||||
int operation_index;
|
||||
operation_type operation;
|
||||
signed_size_type region_id;
|
||||
@@ -50,8 +50,12 @@ struct ring_with_direction
|
||||
|
||||
struct rank_with_rings
|
||||
{
|
||||
// Define a set having a ring, with its direction (from/to). Each ring
|
||||
// arrive at / leaves a cluster only once. TODO: this is not true for
|
||||
// invalid ring. The rank needs to be considered too.
|
||||
typedef std::set<ring_with_direction> container_type;
|
||||
std::size_t rank;
|
||||
std::set<ring_with_direction> rings;
|
||||
container_type rings;
|
||||
|
||||
rank_with_rings()
|
||||
: rank(0)
|
||||
@@ -60,7 +64,7 @@ struct rank_with_rings
|
||||
|
||||
inline bool all_equal(direction_type dir_type) const
|
||||
{
|
||||
for (std::set<ring_with_direction>::const_iterator it = rings.begin();
|
||||
for (container_type::const_iterator it = rings.begin();
|
||||
it != rings.end(); ++it)
|
||||
{
|
||||
if (it->direction != dir_type)
|
||||
@@ -83,7 +87,7 @@ struct rank_with_rings
|
||||
|
||||
inline bool has_only(operation_type op) const
|
||||
{
|
||||
for (std::set<ring_with_direction>::const_iterator it = rings.begin();
|
||||
for (container_type::const_iterator it = rings.begin();
|
||||
it != rings.end(); ++it)
|
||||
{
|
||||
const ring_with_direction& rwd = *it;
|
||||
@@ -100,7 +104,7 @@ struct rank_with_rings
|
||||
{
|
||||
bool has1 = false;
|
||||
bool has2 = false;
|
||||
for (std::set<ring_with_direction>::const_iterator it = rings.begin();
|
||||
for (container_type::const_iterator it = rings.begin();
|
||||
it != rings.end(); ++it)
|
||||
{
|
||||
const ring_with_direction& rwd = *it;
|
||||
@@ -114,7 +118,7 @@ struct rank_with_rings
|
||||
|
||||
inline bool is_isolated() const
|
||||
{
|
||||
for (std::set<ring_with_direction>::const_iterator it = rings.begin();
|
||||
for (container_type::const_iterator it = rings.begin();
|
||||
it != rings.end(); ++it)
|
||||
{
|
||||
const ring_with_direction& rwd = *it;
|
||||
@@ -128,8 +132,8 @@ struct rank_with_rings
|
||||
|
||||
inline bool has_unique_region_id() const
|
||||
{
|
||||
int region_id = -1;
|
||||
for (std::set<ring_with_direction>::const_iterator it = rings.begin();
|
||||
signed_size_type region_id = -1;
|
||||
for (container_type::const_iterator it = rings.begin();
|
||||
it != rings.end(); ++it)
|
||||
{
|
||||
const ring_with_direction& rwd = *it;
|
||||
@@ -145,10 +149,10 @@ struct rank_with_rings
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int region_id() const
|
||||
inline signed_size_type region_id() const
|
||||
{
|
||||
int region_id = -1;
|
||||
for (std::set<ring_with_direction>::const_iterator it = rings.begin();
|
||||
signed_size_type region_id = -1;
|
||||
for (container_type::const_iterator it = rings.begin();
|
||||
it != rings.end(); ++it)
|
||||
{
|
||||
const ring_with_direction& rwd = *it;
|
||||
@@ -170,7 +174,7 @@ struct rank_with_rings
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::turn_operation_type turn_operation_type;
|
||||
|
||||
for (std::set<ring_with_direction>::const_iterator it = rings.begin();
|
||||
for (container_type::const_iterator it = rings.begin();
|
||||
it != rings.end(); ++it)
|
||||
{
|
||||
const ring_with_direction& rwd = *it;
|
||||
|
||||
@@ -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.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -63,8 +63,9 @@ inline bool points_equal_or_close(Point1 const& point1,
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
@@ -92,6 +93,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 +102,9 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Range, typename RobustPolicy>
|
||||
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
|
||||
@@ -135,7 +138,7 @@ 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))
|
||||
if (point_is_spike_or_equal(*second, *ultimate, *first, strategy, robust_policy))
|
||||
{
|
||||
range::erase(range, first);
|
||||
if (BOOST_GEOMETRY_CONDITION(closed))
|
||||
|
||||
@@ -107,21 +107,19 @@ static inline bool within_selected_input(Item const& item2,
|
||||
}
|
||||
|
||||
|
||||
template <typename Point>
|
||||
template <typename Point, typename AreaType>
|
||||
struct ring_info_helper
|
||||
{
|
||||
typedef typename geometry::default_area_result<Point>::type area_type;
|
||||
|
||||
ring_identifier id;
|
||||
area_type real_area;
|
||||
area_type abs_area;
|
||||
AreaType real_area;
|
||||
AreaType abs_area;
|
||||
model::box<Point> envelope;
|
||||
|
||||
inline ring_info_helper()
|
||||
: real_area(0), abs_area(0)
|
||||
{}
|
||||
|
||||
inline ring_info_helper(ring_identifier i, area_type a)
|
||||
inline ring_info_helper(ring_identifier i, AreaType const& a)
|
||||
: id(i), real_area(a), abs_area(geometry::math::abs(a))
|
||||
{}
|
||||
};
|
||||
@@ -226,7 +224,8 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
RingCollection const& collection,
|
||||
RingMap& ring_map,
|
||||
Strategy const& strategy,
|
||||
bool check_for_orientation = false)
|
||||
bool check_for_orientation = false,
|
||||
bool discard_double_negative = false)
|
||||
{
|
||||
typedef typename geometry::tag<Geometry1>::type tag1;
|
||||
typedef typename geometry::tag<Geometry2>::type tag2;
|
||||
@@ -234,11 +233,15 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
typedef typename RingMap::mapped_type ring_info_type;
|
||||
typedef typename ring_info_type::point_type point_type;
|
||||
typedef model::box<point_type> box_type;
|
||||
typedef typename Strategy::template area_strategy
|
||||
<
|
||||
point_type
|
||||
>::type::return_type area_result_type;
|
||||
|
||||
typedef typename RingMap::iterator map_iterator_type;
|
||||
|
||||
{
|
||||
typedef ring_info_helper<point_type> helper;
|
||||
typedef ring_info_helper<point_type, area_result_type> helper;
|
||||
typedef std::vector<helper> vector_type;
|
||||
typedef typename boost::range_iterator<vector_type const>::type vector_iterator_type;
|
||||
|
||||
@@ -332,28 +335,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 = discard_double_negative && ! 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 shouild 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -370,7 +383,7 @@ inline void assign_parents(Geometry1 const& geometry1,
|
||||
}
|
||||
|
||||
|
||||
// Version for one geometry (called by buffer)
|
||||
// Version for one geometry (called by buffer/dissolve)
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
@@ -382,13 +395,15 @@ inline void assign_parents(Geometry const& geometry,
|
||||
RingCollection const& collection,
|
||||
RingMap& ring_map,
|
||||
Strategy const& strategy,
|
||||
bool check_for_orientation)
|
||||
bool check_for_orientation,
|
||||
bool discard_double_negative)
|
||||
{
|
||||
// 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, strategy, check_for_orientation);
|
||||
assign_parents(geometry, empty, collection, ring_map, strategy,
|
||||
check_for_orientation, discard_double_negative);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
// Modifications 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
|
||||
@@ -57,12 +57,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)
|
||||
{
|
||||
@@ -109,7 +111,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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -119,20 +121,23 @@ 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&,
|
||||
RobustPolicy const&,
|
||||
boost::false_type const&)
|
||||
{
|
||||
@@ -144,12 +149,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)
|
||||
{
|
||||
@@ -170,7 +177,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>());
|
||||
}
|
||||
}
|
||||
@@ -183,12 +190,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)
|
||||
{
|
||||
@@ -199,6 +208,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
|
||||
);
|
||||
@@ -213,12 +223,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)
|
||||
{
|
||||
@@ -239,7 +251,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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -253,12 +265,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)
|
||||
{
|
||||
@@ -272,6 +286,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);
|
||||
}
|
||||
@@ -341,12 +356,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)
|
||||
{
|
||||
@@ -356,7 +373,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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -59,7 +64,7 @@ template
|
||||
typename Turns,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename Strategy
|
||||
typename SideStrategy
|
||||
>
|
||||
inline void enrich_sort(Operations& operations,
|
||||
Turns const& turns,
|
||||
@@ -67,7 +72,7 @@ inline void enrich_sort(Operations& operations,
|
||||
Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
Strategy const& /*strategy*/)
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
std::sort(boost::begin(operations),
|
||||
boost::end(operations),
|
||||
@@ -77,8 +82,9 @@ 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, for_operation, geometry1, geometry2, robust_policy, strategy));
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +118,7 @@ inline void enrich_assign(Operations& operations, Turns& turns)
|
||||
|
||||
// Cluster behaviour: next should point after cluster, unless
|
||||
// their seg_ids are not the same
|
||||
while (turn.cluster_id != -1
|
||||
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)
|
||||
@@ -239,10 +245,6 @@ inline void calculate_remaining_distance(Turns& turns)
|
||||
++it)
|
||||
{
|
||||
turn_type& turn = *it;
|
||||
if (! turn.both(detail::overlay::operation_continue))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
op_type& op0 = turn.operations[0];
|
||||
op_type& op1 = turn.operations[1];
|
||||
@@ -255,7 +257,7 @@ inline void calculate_remaining_distance(Turns& turns)
|
||||
|
||||
int const to_index0 = op0.enriched.get_next_turn_index();
|
||||
int const to_index1 = op1.enriched.get_next_turn_index();
|
||||
if (to_index1 >= 0
|
||||
if (to_index0 >= 0
|
||||
&& to_index1 >= 0
|
||||
&& to_index0 != to_index1)
|
||||
{
|
||||
@@ -279,7 +281,7 @@ inline void calculate_remaining_distance(Turns& 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
|
||||
@@ -295,13 +297,13 @@ 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 target_operation
|
||||
= detail::overlay::operation_from_overlay<OverlayType>::value;
|
||||
@@ -353,12 +355,11 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
}
|
||||
|
||||
if (detail::overlay::is_self_turn<OverlayType>(turn)
|
||||
&& turn.cluster_id < 0
|
||||
&& ! turn.is_clustered()
|
||||
&& ! turn.both(target_operation))
|
||||
{
|
||||
// Only keep self-uu-turns or self-ii-turns
|
||||
turn.discarded = true;
|
||||
turn.cluster_id = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -373,12 +374,12 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
<
|
||||
OverlayType,
|
||||
target_operation
|
||||
>::apply(turns, geometry1, geometry2);
|
||||
>::apply(turns, clusters, geometry1, geometry2);
|
||||
detail::overlay::discard_open_turns
|
||||
<
|
||||
OverlayType,
|
||||
target_operation
|
||||
>::apply(turns, geometry1, geometry2);
|
||||
>::apply(turns, clusters, geometry1, geometry2);
|
||||
|
||||
// Create a map of vectors of indexed operation-types to be able
|
||||
// to sort intersection points PER RING
|
||||
@@ -415,6 +416,9 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
detail::overlay::enrich_assign(mit->second, turns);
|
||||
}
|
||||
|
||||
// Check some specific type of self-turns (after getting enriched info)
|
||||
detail::overlay::discard_self_turns_which_loop<OverlayType>(turns);
|
||||
|
||||
if (has_colocations)
|
||||
{
|
||||
// First gather cluster properties (using even clusters with
|
||||
@@ -424,7 +428,8 @@ inline void enrich_intersection_points(Turns& turns,
|
||||
Reverse1,
|
||||
Reverse2,
|
||||
OverlayType
|
||||
>(clusters, turns, target_operation, geometry1, geometry2);
|
||||
>(clusters, turns, target_operation,
|
||||
geometry1, geometry2, strategy);
|
||||
|
||||
detail::overlay::cleanup_clusters(turns, clusters);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,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
|
||||
@@ -157,6 +158,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void enter(LineStringOut& current_piece,
|
||||
@@ -164,6 +166,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
segment_identifier& segment_id,
|
||||
signed_size_type , Point const& point,
|
||||
Operation const& operation,
|
||||
SideStrategy const& ,
|
||||
RobustPolicy const& ,
|
||||
OutputIterator& )
|
||||
{
|
||||
@@ -180,6 +183,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void leave(LineStringOut& current_piece,
|
||||
@@ -187,6 +191,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
segment_identifier& segment_id,
|
||||
signed_size_type index, Point const& point,
|
||||
Operation const& ,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator& out)
|
||||
{
|
||||
@@ -195,7 +200,7 @@ struct action_selector<overlay_intersection, RemoveSpikes>
|
||||
detail::copy_segments::copy_segments_linestring
|
||||
<
|
||||
false, RemoveSpikes
|
||||
>::apply(linestring, segment_id, index, robust_policy, current_piece);
|
||||
>::apply(linestring, segment_id, index, strategy, robust_policy, current_piece);
|
||||
detail::overlay::append_no_duplicates(current_piece, point);
|
||||
if (::boost::size(current_piece) > 1)
|
||||
{
|
||||
@@ -254,6 +259,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void enter(LineStringOut& current_piece,
|
||||
@@ -261,11 +267,12 @@ struct action_selector<overlay_difference, RemoveSpikes>
|
||||
segment_identifier& segment_id,
|
||||
signed_size_type index, Point const& point,
|
||||
Operation const& operation,
|
||||
SideStrategy 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
|
||||
@@ -275,6 +282,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
|
||||
typename LineString,
|
||||
typename Point,
|
||||
typename Operation,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline void leave(LineStringOut& current_piece,
|
||||
@@ -282,11 +290,12 @@ struct action_selector<overlay_difference, RemoveSpikes>
|
||||
segment_identifier& segment_id,
|
||||
signed_size_type index, Point const& point,
|
||||
Operation const& operation,
|
||||
SideStrategy 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
|
||||
@@ -335,6 +344,7 @@ template
|
||||
class follow
|
||||
{
|
||||
|
||||
#ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
template <typename Turn>
|
||||
struct sort_on_segment
|
||||
{
|
||||
@@ -381,7 +391,7 @@ class follow
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
|
||||
|
||||
public :
|
||||
@@ -425,7 +435,15 @@ public :
|
||||
|
||||
// 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);
|
||||
@@ -456,7 +474,7 @@ 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, pt_in_poly_strategy))
|
||||
@@ -466,7 +484,7 @@ public :
|
||||
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;
|
||||
@@ -480,7 +498,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -190,6 +190,7 @@ struct touch_interior : public base_turn_handler
|
||||
// Q turns left on the right side of P (test "MR3")
|
||||
// Both directions for "intersection"
|
||||
both(ti, operation_intersection);
|
||||
ti.touch_only = true;
|
||||
}
|
||||
else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1)
|
||||
{
|
||||
@@ -197,6 +198,7 @@ struct touch_interior : public base_turn_handler
|
||||
// Union: take both operation
|
||||
// Intersection: skip
|
||||
both(ti, operation_union);
|
||||
ti.touch_only = true;
|
||||
}
|
||||
else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q)
|
||||
{
|
||||
@@ -207,6 +209,7 @@ struct touch_interior : public base_turn_handler
|
||||
unsigned int index = side_qk_q == 1 ? index_q : index_p;
|
||||
ti.operations[index].operation = operation_union;
|
||||
ti.operations[1 - index].operation = operation_intersection;
|
||||
ti.touch_only = true;
|
||||
}
|
||||
else if (side_qk_p == 0)
|
||||
{
|
||||
@@ -346,6 +349,7 @@ struct touch : public base_turn_handler
|
||||
if (side_pk_q2 == -side_qk_q)
|
||||
{
|
||||
ui_else_iu(! q_turns_left, ti);
|
||||
ti.touch_only = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -358,6 +362,10 @@ struct touch : public base_turn_handler
|
||||
{
|
||||
ti.operations[1].operation = operation_blocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
ti.touch_only = true;
|
||||
}
|
||||
//block_second(block_q, ti);
|
||||
return;
|
||||
}
|
||||
@@ -373,6 +381,10 @@ struct touch : public base_turn_handler
|
||||
: side_qi_p1 == 1 || side_qk_p1 == 1
|
||||
? operation_union
|
||||
: operation_intersection;
|
||||
if (! block_q)
|
||||
{
|
||||
ti.touch_only = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -400,6 +412,7 @@ struct touch : public base_turn_handler
|
||||
if (side_pk_q1 == side_qk_p1)
|
||||
{
|
||||
uu_else_ii(right_to_left, ti);
|
||||
ti.touch_only = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -418,6 +431,7 @@ struct touch : public base_turn_handler
|
||||
if (side_pk_q2 == side_qk_p1)
|
||||
{
|
||||
ui_else_iu(right_to_left, ti);
|
||||
ti.touch_only = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ struct side_calculator
|
||||
Qj const& m_qj;
|
||||
Qk const& m_qk;
|
||||
|
||||
SideStrategy const& m_side_strategy;
|
||||
SideStrategy m_side_strategy;
|
||||
};
|
||||
|
||||
template <typename Point1, typename Point2, typename RobustPolicy>
|
||||
|
||||
@@ -144,7 +144,7 @@ class get_turns_in_sections
|
||||
|
||||
|
||||
template <typename Geometry, typename Section>
|
||||
static inline bool neighbouring(Section const& section,
|
||||
static inline bool adjacent(Section const& section,
|
||||
signed_size_type index1, signed_size_type index2)
|
||||
{
|
||||
// About n-2:
|
||||
@@ -152,7 +152,7 @@ class get_turns_in_sections
|
||||
// -> 0-3 are adjacent, don't check on intersections)
|
||||
// Also tested for open polygons, and/or duplicates
|
||||
// About first condition: will be optimized by compiler (static)
|
||||
// It checks if it is areal (box,ring,(multi)polygon
|
||||
// It checks if it is areal (box, ring, (multi)polygon)
|
||||
signed_size_type const n = static_cast<signed_size_type>(section.range_count);
|
||||
|
||||
boost::ignore_unused_variable_warning(n);
|
||||
@@ -180,7 +180,7 @@ public :
|
||||
static inline bool apply(
|
||||
int source_id1, Geometry1 const& geometry1, Section1 const& sec1,
|
||||
int source_id2, Geometry2 const& geometry2, Section2 const& sec2,
|
||||
bool skip_larger,
|
||||
bool skip_larger, bool skip_adjacent,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns,
|
||||
@@ -214,11 +214,6 @@ public :
|
||||
signed_size_type index1 = sec1.begin_index;
|
||||
signed_size_type ndi1 = sec1.non_duplicate_index;
|
||||
|
||||
bool const same_source =
|
||||
source_id1 == source_id2
|
||||
&& sec1.ring_id.multi_index == sec2.ring_id.multi_index
|
||||
&& sec1.ring_id.ring_index == sec2.ring_id.ring_index;
|
||||
|
||||
range1_iterator prev1, it1, end1;
|
||||
|
||||
get_start_point_iterator(sec1, view1, prev1, it1, end1,
|
||||
@@ -233,7 +228,7 @@ public :
|
||||
// section 2: [--------------]
|
||||
// section 1: |----|---|---|---|---|
|
||||
for (prev1 = it1++, next1++;
|
||||
it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec2.bounding_box, robust_policy);
|
||||
it1 != end1 && ! detail::section::exceeding<0>(dir1, *prev1, sec1.bounding_box, sec2.bounding_box, robust_policy);
|
||||
++prev1, ++it1, ++index1, ++next1, ++ndi1)
|
||||
{
|
||||
ever_circling_iterator<range1_iterator> nd_next1(
|
||||
@@ -251,25 +246,35 @@ public :
|
||||
next2++;
|
||||
|
||||
for (prev2 = it2++, next2++;
|
||||
it2 != end2 && ! detail::section::exceeding<0>(dir2, *prev2, sec1.bounding_box, robust_policy);
|
||||
it2 != end2 && ! detail::section::exceeding<0>(dir2, *prev2, sec2.bounding_box, sec1.bounding_box, robust_policy);
|
||||
++prev2, ++it2, ++index2, ++next2, ++ndi2)
|
||||
{
|
||||
bool skip = same_source;
|
||||
if (skip)
|
||||
bool skip = false;
|
||||
|
||||
if (source_id1 == source_id2
|
||||
&& sec1.ring_id.multi_index == sec2.ring_id.multi_index
|
||||
&& sec1.ring_id.ring_index == sec2.ring_id.ring_index)
|
||||
{
|
||||
// If sources are the same (possibly self-intersecting):
|
||||
// skip if it is a neighbouring segment.
|
||||
// (including first-last segment
|
||||
// and two segments with one or more degenerate/duplicate
|
||||
// (zero-length) segments in between)
|
||||
// Sources and rings are the same
|
||||
|
||||
// Also skip if index1 < index2 to avoid getting all
|
||||
// intersections twice (only do this on same source!)
|
||||
if (skip_larger && index1 >= index2)
|
||||
{
|
||||
// Skip to avoid getting all intersections twice
|
||||
skip = true;
|
||||
}
|
||||
else if (skip_adjacent)
|
||||
{
|
||||
// In some cases (dissolve, has_self_intersections)
|
||||
// neighbouring segments should be checked
|
||||
// (for example to detect spikes properly)
|
||||
|
||||
skip = (skip_larger && index1 >= index2)
|
||||
|| ndi2 == ndi1 + 1
|
||||
|| neighbouring<Geometry1>(sec1, index1, index2)
|
||||
;
|
||||
// skip if it is a neighbouring segment.
|
||||
// (including, for areas, first-last segment
|
||||
// and two segments with one or more degenerate/duplicate
|
||||
// (zero-length) segments in between)
|
||||
skip = ndi2 == ndi1 + 1
|
||||
|| adjacent<Geometry1>(sec1, index1, index2);
|
||||
}
|
||||
}
|
||||
|
||||
if (! skip)
|
||||
@@ -359,7 +364,7 @@ private :
|
||||
// skips to the begin-point, we loose the index or have to recalculate it)
|
||||
// So we mimic it here
|
||||
template <typename Range, typename Section, typename Box, typename RobustPolicy>
|
||||
static inline void get_start_point_iterator(Section & section,
|
||||
static inline void get_start_point_iterator(Section const& section,
|
||||
Range const& range,
|
||||
typename boost::range_iterator<Range const>::type& it,
|
||||
typename boost::range_iterator<Range const>::type& prev,
|
||||
@@ -373,7 +378,7 @@ private :
|
||||
// Mimic section-iterator:
|
||||
// Skip to point such that section interects other box
|
||||
prev = it++;
|
||||
for(; it != end && detail::section::preceding<0>(dir, *it, other_bounding_box, robust_policy);
|
||||
for(; it != end && detail::section::preceding<0>(dir, *it, section.bounding_box, other_bounding_box, robust_policy);
|
||||
prev = it++, index++, ndi++)
|
||||
{}
|
||||
// Go back one step because we want to start completely preceding
|
||||
@@ -431,7 +436,7 @@ struct section_visitor
|
||||
TurnPolicy
|
||||
>::apply(m_source_id1, m_geometry1, sec1,
|
||||
m_source_id2, m_geometry2, sec2,
|
||||
false,
|
||||
false, false,
|
||||
m_intersection_strategy,
|
||||
m_rescale_policy,
|
||||
m_turns, m_interrupt_policy);
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// Copyright (c) 2015 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)
|
||||
@@ -19,6 +24,7 @@
|
||||
#include <boost/geometry/core/point_order.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
@@ -176,6 +182,7 @@ inline signed_size_type add_turn_to_cluster(Turn const& turn,
|
||||
|
||||
if (cid0 == -1 && cid1 == -1)
|
||||
{
|
||||
// Because of this, first cluster ID will be 1
|
||||
++cluster_id;
|
||||
add_cluster_id(turn.operations[0], cluster_per_segment, cluster_id);
|
||||
add_cluster_id(turn.operations[1], cluster_per_segment, cluster_id);
|
||||
@@ -309,7 +316,7 @@ inline void assign_cluster_to_turns(Turns& turns,
|
||||
if (it != cluster_per_segment.end())
|
||||
{
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS)
|
||||
if (turn.cluster_id != -1
|
||||
if (turn.is_clustered()
|
||||
&& turn.cluster_id != it->second)
|
||||
{
|
||||
std::cout << " CONFLICT " << std::endl;
|
||||
@@ -498,6 +505,7 @@ inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)
|
||||
|
||||
template
|
||||
<
|
||||
overlay_type OverlayType,
|
||||
typename Turns,
|
||||
typename Clusters
|
||||
>
|
||||
@@ -512,38 +520,65 @@ inline void set_colocation(Turns& turns, Clusters const& clusters)
|
||||
cluster_info const& cinfo = cit->second;
|
||||
std::set<signed_size_type> const& ids = cinfo.turn_indices;
|
||||
|
||||
bool has_ii = false;
|
||||
bool has_uu = false;
|
||||
bool both_target = false;
|
||||
for (set_iterator it = ids.begin(); it != ids.end(); ++it)
|
||||
{
|
||||
turn_type const& turn = turns[*it];
|
||||
if (turn.both(operation_intersection))
|
||||
if (turn.both(operation_from_overlay<OverlayType>::value))
|
||||
{
|
||||
has_ii = true;
|
||||
}
|
||||
if (turn.both(operation_union) || turn.combination(operation_union, operation_blocked))
|
||||
{
|
||||
has_uu = true;
|
||||
both_target = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_ii || has_uu)
|
||||
|
||||
if (both_target)
|
||||
{
|
||||
for (set_iterator it = ids.begin(); it != ids.end(); ++it)
|
||||
{
|
||||
turn_type& turn = turns[*it];
|
||||
if (has_ii)
|
||||
|
||||
if (both_target)
|
||||
{
|
||||
turn.colocated_ii = true;
|
||||
}
|
||||
if (has_uu)
|
||||
{
|
||||
turn.colocated_uu = true;
|
||||
turn.has_colocated_both = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Turns,
|
||||
typename Clusters
|
||||
>
|
||||
inline void check_colocation(bool& has_blocked,
|
||||
int cluster_id, Turns const& turns, Clusters const& clusters)
|
||||
{
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
|
||||
has_blocked = false;
|
||||
|
||||
typename Clusters::const_iterator mit = clusters.find(cluster_id);
|
||||
if (mit == clusters.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cluster_info const& cinfo = mit->second;
|
||||
|
||||
for (std::set<signed_size_type>::const_iterator it
|
||||
= cinfo.turn_indices.begin();
|
||||
it != cinfo.turn_indices.end(); ++it)
|
||||
{
|
||||
turn_type const& turn = turns[*it];
|
||||
if (turn.any_blocked())
|
||||
{
|
||||
has_blocked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Checks colocated turns and flags combinations of uu/other, possibly a
|
||||
// combination of a ring touching another geometry's interior ring which is
|
||||
// tangential to the exterior ring
|
||||
@@ -622,6 +657,10 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters,
|
||||
> cluster_per_segment_type;
|
||||
|
||||
cluster_per_segment_type cluster_per_segment;
|
||||
|
||||
// Assign to zero, because of pre-increment later the cluster_id
|
||||
// effectively starts with 1
|
||||
// (and can later be negated to use uniquely with turn_index)
|
||||
signed_size_type cluster_id = 0;
|
||||
|
||||
for (typename map_type::const_iterator it = map.begin();
|
||||
@@ -635,7 +674,9 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters,
|
||||
}
|
||||
|
||||
assign_cluster_to_turns(turns, clusters, cluster_per_segment);
|
||||
set_colocation(turns, clusters);
|
||||
// Get colocated information here and not later, to keep information
|
||||
// on turns which are discarded afterwards
|
||||
set_colocation<OverlayType>(turns, clusters);
|
||||
discard_interior_exterior_turns
|
||||
<
|
||||
do_reverse<geometry::point_order<Geometry1>::value>::value != Reverse1,
|
||||
@@ -697,11 +738,13 @@ template
|
||||
typename Turns,
|
||||
typename Clusters,
|
||||
typename Geometry1,
|
||||
typename Geometry2
|
||||
typename Geometry2,
|
||||
typename SideStrategy
|
||||
>
|
||||
inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
|
||||
operation_type for_operation,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2)
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::point_type point_type;
|
||||
@@ -711,7 +754,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
|
||||
// right side
|
||||
typedef sort_by_side::side_sorter
|
||||
<
|
||||
Reverse1, Reverse2, OverlayType, point_type, std::less<int>
|
||||
Reverse1, Reverse2, OverlayType, point_type, SideStrategy, std::less<int>
|
||||
> sbs_type;
|
||||
|
||||
for (typename Clusters::iterator mit = clusters.begin();
|
||||
@@ -724,7 +767,7 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
|
||||
continue;
|
||||
}
|
||||
|
||||
sbs_type sbs;
|
||||
sbs_type sbs(strategy);
|
||||
point_type turn_point; // should be all the same for all turns in cluster
|
||||
|
||||
bool first = true;
|
||||
@@ -751,7 +794,9 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
|
||||
|
||||
cinfo.open_count = sbs.open_count(for_operation);
|
||||
|
||||
// Unset the startable flag for all 'closed' zones
|
||||
// Unset the startable flag for all 'closed' zones. This does not
|
||||
// apply for self-turns, because those counts are not from both
|
||||
// polygons
|
||||
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
|
||||
{
|
||||
const typename sbs_type::rp& ranked = sbs.m_ranked_points[i];
|
||||
@@ -773,6 +818,13 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
|
||||
op.enriched.rank = ranked.rank;
|
||||
op.enriched.zone = ranked.zone;
|
||||
|
||||
if (OverlayType != overlay_difference
|
||||
&& is_self_turn<OverlayType>(turn))
|
||||
{
|
||||
// Difference needs the self-turns, TODO: investigate
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((for_operation == operation_union
|
||||
&& ranked.count_left != 0)
|
||||
|| (for_operation == operation_intersection
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
|
||||
#include <boost/geometry/algorithms/within.hpp>
|
||||
@@ -24,9 +25,9 @@ namespace detail { namespace overlay
|
||||
|
||||
struct discard_turns
|
||||
{
|
||||
template <typename Turns, typename Geometry0, typename Geometry1>
|
||||
template <typename Turns, typename Clusters, typename Geometry0, typename Geometry1>
|
||||
static inline
|
||||
void apply(Turns& , Geometry0 const& , Geometry1 const& )
|
||||
void apply(Turns& , Clusters const& , Geometry0 const& , Geometry1 const& )
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -38,9 +39,9 @@ template <>
|
||||
struct discard_closed_turns<overlay_union, operation_union>
|
||||
{
|
||||
|
||||
template <typename Turns, typename Geometry0, typename Geometry1>
|
||||
template <typename Turns, typename Clusters, typename Geometry0, typename Geometry1>
|
||||
static inline
|
||||
void apply(Turns& turns,
|
||||
void apply(Turns& turns, Clusters const& clusters,
|
||||
Geometry0 const& geometry0, Geometry1 const& geometry1)
|
||||
{
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
@@ -52,9 +53,7 @@ struct discard_closed_turns<overlay_union, operation_union>
|
||||
{
|
||||
turn_type& turn = *it;
|
||||
|
||||
if (turn.cluster_id >= 0
|
||||
|| turn.discarded
|
||||
|| ! is_self_turn<overlay_union>(turn))
|
||||
if (turn.discarded || ! is_self_turn<overlay_union>(turn))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -75,11 +74,106 @@ struct discard_closed_turns<overlay_union, operation_union>
|
||||
|
||||
struct discard_self_intersection_turns
|
||||
{
|
||||
template <typename Turns, typename Geometry0, typename Geometry1>
|
||||
private :
|
||||
|
||||
template <typename Turns, typename Clusters>
|
||||
static inline
|
||||
void apply(Turns& turns,
|
||||
bool any_blocked(signed_size_type cluster_id,
|
||||
const Turns& turns, Clusters const& clusters)
|
||||
{
|
||||
typename Clusters::const_iterator cit = clusters.find(cluster_id);
|
||||
if (cit == clusters.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
cluster_info const& cinfo = cit->second;
|
||||
for (std::set<signed_size_type>::const_iterator it
|
||||
= cinfo.turn_indices.begin();
|
||||
it != cinfo.turn_indices.end(); ++it)
|
||||
{
|
||||
typename boost::range_value<Turns>::type const& turn = turns[*it];
|
||||
if (turn.any_blocked())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Turns, typename Clusters>
|
||||
static inline
|
||||
bool is_self_cluster(signed_size_type cluster_id,
|
||||
const Turns& turns, Clusters const& clusters)
|
||||
{
|
||||
typename Clusters::const_iterator cit = clusters.find(cluster_id);
|
||||
if (cit == clusters.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cluster_info const& cinfo = cit->second;
|
||||
for (std::set<signed_size_type>::const_iterator it
|
||||
= cinfo.turn_indices.begin();
|
||||
it != cinfo.turn_indices.end(); ++it)
|
||||
{
|
||||
if (! is_self_turn<overlay_intersection>(turns[*it]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Turn, typename Geometry0, typename Geometry1>
|
||||
static inline
|
||||
bool within(Turn const& turn, Geometry0 const& geometry0,
|
||||
Geometry1 const& geometry1)
|
||||
{
|
||||
return turn.operations[0].seg_id.source_index == 0
|
||||
? geometry::within(turn.point, geometry1)
|
||||
: geometry::within(turn.point, geometry0);
|
||||
}
|
||||
|
||||
template <typename Turns, typename Clusters,
|
||||
typename Geometry0, typename Geometry1>
|
||||
static inline
|
||||
void discard_clusters(Turns& turns, Clusters const& clusters,
|
||||
Geometry0 const& geometry0, Geometry1 const& geometry1)
|
||||
{
|
||||
for (typename Clusters::const_iterator cit = clusters.begin();
|
||||
cit != clusters.end(); ++cit)
|
||||
{
|
||||
signed_size_type cluster_id = cit->first;
|
||||
|
||||
// If there are only self-turns in the cluster, the cluster should
|
||||
// be located within the other geometry, for intersection
|
||||
if (is_self_cluster(cluster_id, turns, clusters))
|
||||
{
|
||||
cluster_info const& cinfo = cit->second;
|
||||
if (! within(turns[*cinfo.turn_indices.begin()], geometry0, geometry1))
|
||||
{
|
||||
// Discard all turns in cluster
|
||||
for (std::set<signed_size_type>::const_iterator sit = cinfo.turn_indices.begin();
|
||||
sit != cinfo.turn_indices.end(); ++sit)
|
||||
{
|
||||
turns[*sit].discarded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public :
|
||||
|
||||
template <typename Turns, typename Clusters,
|
||||
typename Geometry0, typename Geometry1>
|
||||
static inline
|
||||
void apply(Turns& turns, Clusters const& clusters,
|
||||
Geometry0 const& geometry0, Geometry1 const& geometry1)
|
||||
{
|
||||
discard_clusters(turns, clusters, geometry0, geometry1);
|
||||
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
|
||||
for (typename boost::range_iterator<Turns>::type
|
||||
@@ -89,9 +183,7 @@ struct discard_self_intersection_turns
|
||||
{
|
||||
turn_type& turn = *it;
|
||||
|
||||
if (turn.cluster_id >= 0
|
||||
|| turn.discarded
|
||||
|| ! is_self_turn<overlay_intersection>(turn))
|
||||
if (turn.discarded || ! is_self_turn<overlay_intersection>(turn))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -106,16 +198,22 @@ struct discard_self_intersection_turns
|
||||
continue;
|
||||
}
|
||||
|
||||
// It is a non co-located ii self-turn
|
||||
if (turn.is_clustered() && turn.has_colocated_both)
|
||||
{
|
||||
// Don't delete a self-ii-turn colocated with another ii-turn
|
||||
// (for example #case_recursive_boxes_70)
|
||||
// But for some cases (#case_58_iet) they should be deleted,
|
||||
// there are many self-turns there and also blocked turns there
|
||||
if (! any_blocked(turn.cluster_id, turns, clusters))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// It is a ii self-turn
|
||||
// Check if it is within the other geometry
|
||||
// If not, it can be ignored
|
||||
|
||||
bool const within =
|
||||
turn.operations[0].seg_id.source_index == 0
|
||||
? geometry::within(turn.point, geometry1)
|
||||
: geometry::within(turn.point, geometry0);
|
||||
|
||||
if (! within)
|
||||
if (! within(turn, geometry0, geometry1))
|
||||
{
|
||||
// It is not within another geometry, discard the turn
|
||||
turn.discarded = true;
|
||||
@@ -134,6 +232,61 @@ struct discard_open_turns<overlay_intersection, operation_intersection>
|
||||
|
||||
// For difference, it should be done in a different way (TODO)
|
||||
|
||||
|
||||
template <overlay_type OverlayType, typename Turns>
|
||||
inline void discard_self_turns_which_loop(Turns& turns)
|
||||
{
|
||||
if (operation_from_overlay<OverlayType>::value == operation_union)
|
||||
{
|
||||
// For union, self-turn i/u traveling to itself are allowed to form
|
||||
// holes. #case_recursive_boxes_37
|
||||
// TODO: this can be finetuned by inspecting the cluster too,
|
||||
// and if there are non-self-turns the polygons on their sides can
|
||||
// be checked
|
||||
return;
|
||||
}
|
||||
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::turn_operation_type op_type;
|
||||
|
||||
signed_size_type turn_index = 0;
|
||||
for (typename boost::range_iterator<Turns>::type
|
||||
it = boost::begin(turns);
|
||||
it != boost::end(turns);
|
||||
++it, ++turn_index)
|
||||
{
|
||||
turn_type& turn = *it;
|
||||
|
||||
if (! is_self_turn<OverlayType>(turn))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (! turn.combination(operation_intersection, operation_union))
|
||||
{
|
||||
// ii may travel to itself
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
op_type& op = turn.operations[i];
|
||||
|
||||
if (op.enriched.startable
|
||||
&& op.operation == operation_intersection
|
||||
&& op.enriched.get_next_turn_index() == turn_index)
|
||||
{
|
||||
// Self-turn i/u, i part traveling to itself. Discard it.
|
||||
// (alternatively it might be made unstartable - but the
|
||||
// intersection-operation may not be traveled anyway, and the
|
||||
// union-operation is not traveled at all in intersections
|
||||
// #case_recursive_boxes_77
|
||||
turn.discarded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}} // namespace detail::overlay
|
||||
#endif //DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
@@ -208,6 +208,8 @@ struct intersection_of_linestring_with_areal
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
|
||||
class is_crossing_turn
|
||||
{
|
||||
// return true is the operation is intersection or blocked
|
||||
@@ -310,6 +312,91 @@ struct intersection_of_linestring_with_areal
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
|
||||
template <typename Linestring, typename Areal, typename Strategy, typename Turns>
|
||||
static inline bool simple_turns_analysis(Linestring const& linestring,
|
||||
Areal const& areal,
|
||||
Strategy const& strategy,
|
||||
Turns const& turns,
|
||||
int & inside_value)
|
||||
{
|
||||
using namespace overlay;
|
||||
|
||||
bool found_continue = false;
|
||||
bool found_intersection = false;
|
||||
bool found_union = false;
|
||||
bool found_front = false;
|
||||
|
||||
for (typename Turns::const_iterator it = turns.begin();
|
||||
it != turns.end(); ++it)
|
||||
{
|
||||
method_type const method = it->method;
|
||||
operation_type const op = it->operations[0].operation;
|
||||
|
||||
if (method == method_crosses)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (op == operation_intersection)
|
||||
{
|
||||
found_intersection = true;
|
||||
}
|
||||
else if (op == operation_union)
|
||||
{
|
||||
found_union = true;
|
||||
}
|
||||
else if (op == operation_continue)
|
||||
{
|
||||
found_continue = true;
|
||||
}
|
||||
|
||||
if ((found_intersection || found_continue) && found_union)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (it->operations[0].position == position_front)
|
||||
{
|
||||
found_front = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_front)
|
||||
{
|
||||
if (found_intersection)
|
||||
{
|
||||
inside_value = 1; // inside
|
||||
}
|
||||
else if (found_union)
|
||||
{
|
||||
inside_value = -1; // outside
|
||||
}
|
||||
else // continue and blocked
|
||||
{
|
||||
inside_value = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// if needed analyse points of a linestring
|
||||
// NOTE: range_in_geometry checks points of a linestring
|
||||
// until a point inside/outside areal is found
|
||||
// TODO: Could be replaced with point_in_geometry() because found_front is false
|
||||
inside_value = range_in_geometry(linestring, areal, strategy);
|
||||
|
||||
if ( (found_intersection && inside_value == -1) // going in from outside
|
||||
|| (found_continue && inside_value == -1) // going on boundary from outside
|
||||
|| (found_union && inside_value == 1) ) // going out from inside
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
|
||||
template
|
||||
<
|
||||
typename LineString, typename Areal,
|
||||
@@ -336,14 +423,30 @@ struct intersection_of_linestring_with_areal
|
||||
> follower;
|
||||
|
||||
typedef typename point_type<LineStringOut>::type point_type;
|
||||
#ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
typedef detail::overlay::traversal_turn_info
|
||||
<
|
||||
point_type,
|
||||
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
|
||||
> turn_info;
|
||||
<
|
||||
point_type,
|
||||
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
|
||||
> turn_info;
|
||||
#else
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
point_type,
|
||||
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type,
|
||||
detail::overlay::turn_operation_linear
|
||||
<
|
||||
point_type,
|
||||
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
|
||||
>
|
||||
> turn_info;
|
||||
#endif
|
||||
std::deque<turn_info> turns;
|
||||
|
||||
detail::get_turns::no_interrupt_policy policy;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
|
||||
geometry::get_turns
|
||||
<
|
||||
false,
|
||||
@@ -366,7 +469,7 @@ struct intersection_of_linestring_with_areal
|
||||
// until a point inside/outside areal is found
|
||||
inside_value = overlay::range_in_geometry(linestring, areal, strategy);
|
||||
}
|
||||
// add point to the output if conditions are met
|
||||
// add linestring to the output if conditions are met
|
||||
if (inside_value != 0 && follower::included(inside_value))
|
||||
{
|
||||
LineStringOut copy;
|
||||
@@ -376,6 +479,47 @@ struct intersection_of_linestring_with_areal
|
||||
return out;
|
||||
}
|
||||
|
||||
#else // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
|
||||
typedef detail::overlay::get_turn_info_linear_areal
|
||||
<
|
||||
detail::overlay::assign_null_policy
|
||||
> turn_policy;
|
||||
|
||||
dispatch::get_turns
|
||||
<
|
||||
typename geometry::tag<LineString>::type,
|
||||
typename geometry::tag<Areal>::type,
|
||||
LineString,
|
||||
Areal,
|
||||
false,
|
||||
(OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal),
|
||||
turn_policy
|
||||
>::apply(0, linestring, 1, areal,
|
||||
strategy, robust_policy,
|
||||
turns, policy);
|
||||
|
||||
int inside_value = 0;
|
||||
if (simple_turns_analysis(linestring, areal, strategy, turns, inside_value))
|
||||
{
|
||||
// No crossing the boundary, it is either
|
||||
// inside (interior + borders)
|
||||
// or outside (exterior + borders)
|
||||
// or on boundary
|
||||
|
||||
// add linestring to the output if conditions are met
|
||||
if (follower::included(inside_value))
|
||||
{
|
||||
LineStringOut copy;
|
||||
geometry::convert(linestring, copy);
|
||||
*out++ = copy;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
|
||||
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
|
||||
int index = 0;
|
||||
for(typename std::deque<turn_info>::const_iterator
|
||||
@@ -395,6 +539,135 @@ struct intersection_of_linestring_with_areal
|
||||
};
|
||||
|
||||
|
||||
template <typename Turns, typename OutputIterator>
|
||||
inline OutputIterator intersection_output_turn_points(Turns const& turns,
|
||||
OutputIterator out)
|
||||
{
|
||||
for (typename Turns::const_iterator
|
||||
it = turns.begin(); it != turns.end(); ++it)
|
||||
{
|
||||
*out++ = it->point;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename PointOut>
|
||||
struct intersection_areal_areal_point
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator,
|
||||
typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
PointOut,
|
||||
typename segment_ratio_type<PointOut, RobustPolicy>::type
|
||||
> turn_info;
|
||||
std::vector<turn_info> turns;
|
||||
|
||||
detail::get_turns::no_interrupt_policy policy;
|
||||
|
||||
geometry::get_turns
|
||||
<
|
||||
false, false, detail::overlay::assign_null_policy
|
||||
>(geometry1, geometry2, strategy, robust_policy, turns, policy);
|
||||
|
||||
return intersection_output_turn_points(turns, out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename PointOut>
|
||||
struct intersection_linear_areal_point
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator,
|
||||
typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::segment_ratio_type
|
||||
<
|
||||
PointOut, RobustPolicy
|
||||
>::type segment_ratio_type;
|
||||
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
PointOut,
|
||||
segment_ratio_type,
|
||||
detail::overlay::turn_operation_linear
|
||||
<
|
||||
PointOut,
|
||||
segment_ratio_type
|
||||
>
|
||||
> turn_info;
|
||||
|
||||
typedef detail::overlay::get_turn_info_linear_areal
|
||||
<
|
||||
detail::overlay::assign_null_policy
|
||||
> turn_policy;
|
||||
|
||||
std::vector<turn_info> turns;
|
||||
|
||||
detail::get_turns::no_interrupt_policy interrupt_policy;
|
||||
|
||||
dispatch::get_turns
|
||||
<
|
||||
typename geometry::tag<Geometry1>::type,
|
||||
typename geometry::tag<Geometry2>::type,
|
||||
Geometry1,
|
||||
Geometry2,
|
||||
false,
|
||||
false,
|
||||
turn_policy
|
||||
>::apply(0, geometry1, 1, geometry2,
|
||||
strategy, robust_policy,
|
||||
turns, interrupt_policy);
|
||||
|
||||
return intersection_output_turn_points(turns, out);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename PointOut>
|
||||
struct intersection_areal_linear_point
|
||||
{
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename OutputIterator,
|
||||
typename Strategy
|
||||
>
|
||||
static inline OutputIterator apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return intersection_linear_areal_point
|
||||
<
|
||||
PointOut
|
||||
>::apply(geometry2, geometry1, robust_policy, out, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::intersection
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
@@ -420,9 +693,9 @@ template
|
||||
typename TagIn2 = typename geometry::tag<Geometry2>::type,
|
||||
typename TagOut = typename geometry::tag<GeometryOut>::type,
|
||||
// metafunction finetuning helpers:
|
||||
bool Areal1 = geometry::is_areal<Geometry1>::value,
|
||||
bool Areal2 = geometry::is_areal<Geometry2>::value,
|
||||
bool ArealOut = geometry::is_areal<GeometryOut>::value
|
||||
typename CastedTagIn1 = typename geometry::tag_cast<TagIn1, areal_tag, linear_tag, pointlike_tag>::type,
|
||||
typename CastedTagIn2 = typename geometry::tag_cast<TagIn2, areal_tag, linear_tag, pointlike_tag>::type,
|
||||
typename CastedTagOut = typename geometry::tag_cast<TagOut, areal_tag, linear_tag, pointlike_tag>::type
|
||||
>
|
||||
struct intersection_insert
|
||||
{
|
||||
@@ -449,7 +722,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
TagIn1, TagIn2, TagOut,
|
||||
true, true, true
|
||||
areal_tag, areal_tag, areal_tag
|
||||
> : detail::overlay::overlay
|
||||
<Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType>
|
||||
{};
|
||||
@@ -471,7 +744,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
TagIn, box_tag, TagOut,
|
||||
true, true, true
|
||||
areal_tag, areal_tag, areal_tag
|
||||
> : detail::overlay::overlay
|
||||
<Geometry, Box, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType>
|
||||
{};
|
||||
@@ -491,7 +764,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
segment_tag, segment_tag, point_tag,
|
||||
false, false, false
|
||||
linear_tag, linear_tag, pointlike_tag
|
||||
> : detail::intersection::intersection_segment_segment_point<GeometryOut>
|
||||
{};
|
||||
|
||||
@@ -510,7 +783,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
linestring_tag, linestring_tag, point_tag,
|
||||
false, false, false
|
||||
linear_tag, linear_tag, pointlike_tag
|
||||
> : detail::intersection::intersection_linestring_linestring_point<GeometryOut>
|
||||
{};
|
||||
|
||||
@@ -528,7 +801,7 @@ struct intersection_insert
|
||||
overlay_intersection,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
linestring_tag, box_tag, linestring_tag,
|
||||
false, true, false
|
||||
linear_tag, areal_tag, linear_tag
|
||||
>
|
||||
{
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
@@ -559,7 +832,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
ReverseLinestring, ReversePolygon, ReverseOut,
|
||||
linestring_tag, polygon_tag, linestring_tag,
|
||||
false, true, false
|
||||
linear_tag, areal_tag, linear_tag
|
||||
> : detail::intersection::intersection_of_linestring_with_areal
|
||||
<
|
||||
ReversePolygon,
|
||||
@@ -583,7 +856,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
ReverseLinestring, ReverseRing, ReverseOut,
|
||||
linestring_tag, ring_tag, linestring_tag,
|
||||
false, true, false
|
||||
linear_tag, areal_tag, linear_tag
|
||||
> : detail::intersection::intersection_of_linestring_with_areal
|
||||
<
|
||||
ReverseRing,
|
||||
@@ -606,7 +879,7 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
segment_tag, box_tag, linestring_tag,
|
||||
false, true, false
|
||||
linear_tag, areal_tag, linear_tag
|
||||
>
|
||||
{
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
@@ -630,8 +903,7 @@ template
|
||||
typename PointOut,
|
||||
overlay_type OverlayType,
|
||||
bool Reverse1, bool Reverse2, bool ReverseOut,
|
||||
typename Tag1, typename Tag2,
|
||||
bool Areal1, bool Areal2
|
||||
typename Tag1, typename Tag2
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
@@ -640,38 +912,59 @@ struct intersection_insert
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
Tag1, Tag2, point_tag,
|
||||
Areal1, Areal2, false
|
||||
areal_tag, areal_tag, pointlike_tag
|
||||
>
|
||||
{
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
RobustPolicy const& robust_policy,
|
||||
OutputIterator out, Strategy const& strategy)
|
||||
{
|
||||
: public detail::intersection::intersection_areal_areal_point
|
||||
<
|
||||
PointOut
|
||||
>
|
||||
{};
|
||||
|
||||
typedef detail::overlay::turn_info
|
||||
<
|
||||
PointOut,
|
||||
typename segment_ratio_type<PointOut, RobustPolicy>::type
|
||||
> turn_info;
|
||||
std::vector<turn_info> turns;
|
||||
|
||||
detail::get_turns::no_interrupt_policy policy;
|
||||
geometry::get_turns
|
||||
<
|
||||
false, false, detail::overlay::assign_null_policy
|
||||
>(geometry1, geometry2, strategy, robust_policy, turns, policy);
|
||||
for (typename std::vector<turn_info>::const_iterator it
|
||||
= turns.begin(); it != turns.end(); ++it)
|
||||
{
|
||||
*out++ = it->point;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
};
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename PointOut,
|
||||
overlay_type OverlayType,
|
||||
bool Reverse1, bool Reverse2, bool ReverseOut,
|
||||
typename Tag1, typename Tag2
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
Geometry1, Geometry2,
|
||||
PointOut,
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
Tag1, Tag2, point_tag,
|
||||
linear_tag, areal_tag, pointlike_tag
|
||||
>
|
||||
: public detail::intersection::intersection_linear_areal_point
|
||||
<
|
||||
PointOut
|
||||
>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename PointOut,
|
||||
overlay_type OverlayType,
|
||||
bool Reverse1, bool Reverse2, bool ReverseOut,
|
||||
typename Tag1, typename Tag2
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
Geometry1, Geometry2,
|
||||
PointOut,
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
Tag1, Tag2, point_tag,
|
||||
areal_tag, linear_tag, pointlike_tag
|
||||
>
|
||||
: public detail::intersection::intersection_areal_linear_point
|
||||
<
|
||||
PointOut
|
||||
>
|
||||
{};
|
||||
|
||||
template
|
||||
<
|
||||
@@ -713,7 +1006,7 @@ struct intersection_insert
|
||||
overlay_intersection,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
Tag1, Tag2, linestring_tag,
|
||||
true, true, false
|
||||
areal_tag, areal_tag, linear_tag
|
||||
>
|
||||
{
|
||||
template
|
||||
@@ -739,47 +1032,20 @@ struct intersection_insert
|
||||
}
|
||||
};
|
||||
|
||||
// dispatch for non-areal geometries
|
||||
// dispatch for difference/intersection of linear geometries
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2, typename GeometryOut,
|
||||
typename Linear1, typename Linear2, typename LineStringOut,
|
||||
overlay_type OverlayType,
|
||||
bool Reverse1, bool Reverse2, bool ReverseOut,
|
||||
typename TagIn1, typename TagIn2
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
Geometry1, Geometry2, GeometryOut,
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
TagIn1, TagIn2, linestring_tag,
|
||||
false, false, false
|
||||
> : intersection_insert
|
||||
<
|
||||
Geometry1, Geometry2, GeometryOut,
|
||||
OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
typename tag_cast<TagIn1, pointlike_tag, linear_tag>::type,
|
||||
typename tag_cast<TagIn2, pointlike_tag, linear_tag>::type,
|
||||
linestring_tag,
|
||||
false, false, false
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
// dispatch for difference/intersection of linear geometries
|
||||
template
|
||||
<
|
||||
typename Linear1, typename Linear2, typename LineStringOut,
|
||||
overlay_type OverlayType,
|
||||
bool Reverse1, bool Reverse2, bool ReverseOut
|
||||
>
|
||||
struct intersection_insert
|
||||
<
|
||||
Linear1, Linear2, LineStringOut, OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
linear_tag, linear_tag, linestring_tag,
|
||||
false, false, false
|
||||
TagIn1, TagIn2, linestring_tag,
|
||||
linear_tag, linear_tag, linear_tag
|
||||
> : detail::overlay::linear_linear_linestring
|
||||
<
|
||||
Linear1, Linear2, LineStringOut, OverlayType
|
||||
@@ -800,7 +1066,7 @@ struct intersection_insert
|
||||
Point1, Point2, PointOut, OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
point_tag, point_tag, point_tag,
|
||||
false, false, false
|
||||
pointlike_tag, pointlike_tag, pointlike_tag
|
||||
> : detail::overlay::point_point_point
|
||||
<
|
||||
Point1, Point2, PointOut, OverlayType
|
||||
@@ -819,7 +1085,7 @@ struct intersection_insert
|
||||
MultiPoint, Point, PointOut, OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
multi_point_tag, point_tag, point_tag,
|
||||
false, false, false
|
||||
pointlike_tag, pointlike_tag, pointlike_tag
|
||||
> : detail::overlay::multipoint_point_point
|
||||
<
|
||||
MultiPoint, Point, PointOut, OverlayType
|
||||
@@ -838,7 +1104,7 @@ struct intersection_insert
|
||||
Point, MultiPoint, PointOut, OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
point_tag, multi_point_tag, point_tag,
|
||||
false, false, false
|
||||
pointlike_tag, pointlike_tag, pointlike_tag
|
||||
> : detail::overlay::point_multipoint_point
|
||||
<
|
||||
Point, MultiPoint, PointOut, OverlayType
|
||||
@@ -857,7 +1123,7 @@ struct intersection_insert
|
||||
MultiPoint1, MultiPoint2, PointOut, OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
multi_point_tag, multi_point_tag, point_tag,
|
||||
false, false, false
|
||||
pointlike_tag, pointlike_tag, pointlike_tag
|
||||
> : detail::overlay::multipoint_multipoint_point
|
||||
<
|
||||
MultiPoint1, MultiPoint2, PointOut, OverlayType
|
||||
@@ -878,7 +1144,7 @@ struct intersection_insert
|
||||
Point, Linear, PointOut, OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
point_tag, Tag, point_tag,
|
||||
false, false, false
|
||||
pointlike_tag, linear_tag, pointlike_tag
|
||||
> : detail_dispatch::overlay::pointlike_linear_point
|
||||
<
|
||||
Point, Linear, PointOut, OverlayType,
|
||||
@@ -899,7 +1165,7 @@ struct intersection_insert
|
||||
MultiPoint, Linear, PointOut, OverlayType,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
multi_point_tag, Tag, point_tag,
|
||||
false, false, false
|
||||
pointlike_tag, linear_tag, pointlike_tag
|
||||
> : detail_dispatch::overlay::pointlike_linear_point
|
||||
<
|
||||
MultiPoint, Linear, PointOut, OverlayType,
|
||||
@@ -919,7 +1185,7 @@ struct intersection_insert
|
||||
Linestring, MultiPoint, PointOut, overlay_intersection,
|
||||
Reverse1, Reverse2, ReverseOut,
|
||||
linestring_tag, multi_point_tag, point_tag,
|
||||
false, false, false
|
||||
linear_tag, pointlike_tag, pointlike_tag
|
||||
>
|
||||
{
|
||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||
|
||||
@@ -41,7 +41,7 @@ struct is_self_turn_check<overlay_buffer>
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_self_turn_check<overlay_dissolve>
|
||||
struct is_self_turn_check<overlay_dissolve_union>
|
||||
{
|
||||
template <typename Turn>
|
||||
static inline bool apply(Turn const& turn)
|
||||
@@ -50,6 +50,15 @@ struct is_self_turn_check<overlay_dissolve>
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_self_turn_check<overlay_dissolve_intersection>
|
||||
{
|
||||
template <typename Turn>
|
||||
static inline bool apply(Turn const& turn)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <overlay_type OverlayType, typename Turn>
|
||||
bool is_self_turn(Turn const& turn)
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// Copyright (c) 2007-2015 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)
|
||||
@@ -60,6 +65,7 @@ template
|
||||
typename Indexed,
|
||||
typename Geometry1, typename Geometry2,
|
||||
typename RobustPolicy,
|
||||
typename SideStrategy,
|
||||
bool Reverse1, bool Reverse2
|
||||
>
|
||||
struct less_by_segment_ratio
|
||||
@@ -68,12 +74,14 @@ struct less_by_segment_ratio
|
||||
, operation_type for_operation
|
||||
, Geometry1 const& geometry1
|
||||
, Geometry2 const& geometry2
|
||||
, RobustPolicy const& robust_policy)
|
||||
, RobustPolicy const& robust_policy
|
||||
, SideStrategy const& strategy)
|
||||
: m_turns(turns)
|
||||
, m_for_operation(for_operation)
|
||||
, m_geometry1(geometry1)
|
||||
, m_geometry2(geometry2)
|
||||
, m_robust_policy(robust_policy)
|
||||
, m_strategy(strategy)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -84,6 +92,7 @@ private :
|
||||
Geometry1 const& m_geometry1;
|
||||
Geometry2 const& m_geometry2;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
SideStrategy const& m_strategy;
|
||||
|
||||
typedef typename geometry::point_type<Geometry1>::type point_type;
|
||||
|
||||
@@ -108,13 +117,8 @@ private :
|
||||
*right.other_seg_id,
|
||||
si, sj);
|
||||
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type
|
||||
>::type strategy;
|
||||
|
||||
int const side_rj_p = strategy::apply(pi, pj, rj);
|
||||
int const side_sj_p = strategy::apply(pi, pj, sj);
|
||||
int const side_rj_p = m_strategy.apply(pi, pj, rj);
|
||||
int const side_sj_p = m_strategy.apply(pi, pj, sj);
|
||||
|
||||
// Put the one turning left (1; right == -1) as last
|
||||
if (side_rj_p != side_sj_p)
|
||||
@@ -122,8 +126,8 @@ private :
|
||||
return side_rj_p < side_sj_p;
|
||||
}
|
||||
|
||||
int const side_sj_r = strategy::apply(ri, rj, sj);
|
||||
int const side_rj_s = strategy::apply(si, sj, rj);
|
||||
int const side_sj_r = m_strategy.apply(ri, rj, sj);
|
||||
int const side_rj_s = m_strategy.apply(si, sj, rj);
|
||||
|
||||
// If they both turn left: the most left as last
|
||||
// If they both turn right: this is not relevant, but take also here most left
|
||||
|
||||
@@ -194,13 +194,15 @@ protected:
|
||||
typename Turns,
|
||||
typename LinearGeometry1,
|
||||
typename LinearGeometry2,
|
||||
typename OutputIterator
|
||||
typename OutputIterator,
|
||||
typename IntersectionStrategy
|
||||
>
|
||||
static inline OutputIterator
|
||||
sort_and_follow_turns(Turns& turns,
|
||||
LinearGeometry1 const& linear1,
|
||||
LinearGeometry2 const& linear2,
|
||||
OutputIterator oit)
|
||||
OutputIterator oit,
|
||||
IntersectionStrategy const& strategy)
|
||||
{
|
||||
// remove turns that have no added value
|
||||
turns::filter_continue_turns
|
||||
@@ -228,7 +230,7 @@ protected:
|
||||
FollowIsolatedPoints,
|
||||
!EnableFilterContinueTurns || OverlayType == overlay_intersection
|
||||
>::apply(linear1, linear2, boost::begin(turns), boost::end(turns),
|
||||
oit);
|
||||
oit, strategy.get_side_strategy());
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -277,7 +279,7 @@ public:
|
||||
OverlayType,
|
||||
EnableFollowIsolatedPoints
|
||||
&& OverlayType == overlay_intersection
|
||||
>(turns, linear1, linear2, oit);
|
||||
>(turns, linear1, linear2, oit, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2017-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_DETAIL_OVERLAY_NEEDS_SELF_TURNS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_NEEDS_SELF_TURNS_HPP
|
||||
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/algorithms/num_interior_rings.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry,
|
||||
typename Tag = typename tag<Geometry>::type
|
||||
>
|
||||
struct needs_self_turns
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct needs_self_turns<Geometry, box_tag>
|
||||
{
|
||||
static inline bool apply(Geometry const&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct needs_self_turns<Geometry, ring_tag>
|
||||
{
|
||||
static inline bool apply(Geometry const&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct needs_self_turns<Geometry, polygon_tag>
|
||||
{
|
||||
static inline bool apply(Geometry const& polygon)
|
||||
{
|
||||
return geometry::num_interior_rings(polygon) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct needs_self_turns<Geometry, multi_polygon_tag>
|
||||
{
|
||||
static inline bool apply(Geometry const& multi)
|
||||
{
|
||||
typedef typename boost::range_value<Geometry>::type polygon_type;
|
||||
std::size_t const n = boost::size(multi);
|
||||
return n > 1 || (n == 1
|
||||
&& needs_self_turns<polygon_type>
|
||||
::apply(*boost::begin(multi)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::overlay
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_NEEDS_SELF_TURNS_HPP
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/needs_self_turns.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traverse.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
|
||||
@@ -99,89 +100,88 @@ template
|
||||
inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, Clusters const& clusters)
|
||||
{
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::turn_operation_type turn_operation_type;
|
||||
typedef typename turn_type::container_type container_type;
|
||||
|
||||
static const operation_type target_operation
|
||||
= operation_from_overlay<OverlayType>::value;
|
||||
static const operation_type opposite_operation
|
||||
= target_operation == operation_union ? operation_intersection : operation_union;
|
||||
= target_operation == operation_union
|
||||
? operation_intersection
|
||||
: operation_union;
|
||||
|
||||
signed_size_type turn_index = 0;
|
||||
for (typename boost::range_iterator<Turns const>::type
|
||||
it = boost::begin(turns);
|
||||
it != boost::end(turns);
|
||||
++it, turn_index++)
|
||||
++it)
|
||||
{
|
||||
typename boost::range_value<Turns>::type const& turn = *it;
|
||||
turn_type const& turn = *it;
|
||||
|
||||
bool const colocated_target = target_operation == operation_union
|
||||
? turn.colocated_uu : turn.colocated_ii;
|
||||
bool const colocated_opp = target_operation == operation_union
|
||||
? turn.colocated_ii : turn.colocated_uu;
|
||||
bool const both_opposite = turn.both(opposite_operation);
|
||||
|
||||
bool const traversed
|
||||
= turn.operations[0].visited.finalized()
|
||||
|| turn.operations[0].visited.rejected()
|
||||
|| turn.operations[1].visited.finalized()
|
||||
|| turn.operations[1].visited.rejected()
|
||||
|| turn.both(operation_blocked)
|
||||
|| turn.combination(opposite_operation, operation_blocked);
|
||||
|
||||
bool is_closed = false;
|
||||
if (turn.cluster_id >= 0 && target_operation == operation_union)
|
||||
{
|
||||
typename Clusters::const_iterator mit = clusters.find(turn.cluster_id);
|
||||
BOOST_ASSERT(mit != clusters.end());
|
||||
|
||||
cluster_info const& cinfo = mit->second;
|
||||
is_closed = cinfo.open_count == 0;
|
||||
}
|
||||
bool cluster_checked = false;
|
||||
bool has_blocked = false;
|
||||
|
||||
for (typename boost::range_iterator<container_type const>::type
|
||||
op_it = boost::begin(turn.operations);
|
||||
op_it != boost::end(turn.operations);
|
||||
++op_it)
|
||||
{
|
||||
turn_operation_type const& op = *op_it;
|
||||
ring_identifier const ring_id
|
||||
(
|
||||
op_it->seg_id.source_index,
|
||||
op_it->seg_id.multi_index,
|
||||
op_it->seg_id.ring_index
|
||||
op.seg_id.source_index,
|
||||
op.seg_id.multi_index,
|
||||
op.seg_id.ring_index
|
||||
);
|
||||
|
||||
if (traversed || is_closed || ! op_it->enriched.startable)
|
||||
if (! is_self_turn<OverlayType>(turn)
|
||||
&& (
|
||||
(target_operation == operation_union
|
||||
&& op.enriched.count_left > 0)
|
||||
|| (target_operation == operation_intersection
|
||||
&& op.enriched.count_right <= 2)))
|
||||
{
|
||||
turn_info_map[ring_id].has_traversed_turn = true;
|
||||
// Avoid including untraversed rings which have polygons on
|
||||
// their left side (union) or not two on their right side (int)
|
||||
// This can only be done for non-self-turns because of count
|
||||
// information
|
||||
turn_info_map[ring_id].has_blocked_turn = true;
|
||||
continue;
|
||||
}
|
||||
else if (both_opposite && colocated_target)
|
||||
{
|
||||
// For union: ii, colocated with a uu
|
||||
// For example, two interior rings touch where two exterior rings also touch.
|
||||
// The interior rings are not yet traversed, and should be taken from the input
|
||||
|
||||
// For intersection: uu, colocated with an ii
|
||||
// unless it is two interior inner rings colocated with a uu
|
||||
if (turn.any_blocked())
|
||||
{
|
||||
turn_info_map[ring_id].has_blocked_turn = true;
|
||||
}
|
||||
if (turn_info_map[ring_id].has_traversed_turn
|
||||
|| turn_info_map[ring_id].has_blocked_turn)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// So don't set has_traversed_turn here
|
||||
}
|
||||
else if (both_opposite && ! is_self_turn<OverlayType>(turn))
|
||||
// Check information in colocated turns
|
||||
if (! cluster_checked && turn.is_clustered())
|
||||
{
|
||||
// For union, mark any ring with a ii turn as traversed
|
||||
// For intersection, any uu - but not if it is a self-turn
|
||||
turn_info_map[ring_id].has_traversed_turn = true;
|
||||
check_colocation(has_blocked, turn.cluster_id, turns, clusters);
|
||||
cluster_checked = true;
|
||||
}
|
||||
else if (colocated_opp && ! colocated_target)
|
||||
|
||||
// Block rings where any other turn is blocked,
|
||||
// and (with exceptions): i for union and u for intersection
|
||||
// Exceptions: don't block self-uu for intersection
|
||||
// don't block self-ii for union
|
||||
// don't block (for union) i/u if there is an self-ii too
|
||||
if (has_blocked
|
||||
|| (op.operation == opposite_operation
|
||||
&& ! turn.has_colocated_both
|
||||
&& ! (turn.both(opposite_operation)
|
||||
&& is_self_turn<OverlayType>(turn))))
|
||||
{
|
||||
// For union, a turn colocated with ii and NOT with uu/ux
|
||||
// For intersection v.v.
|
||||
turn_info_map[ring_id].has_traversed_turn = true;
|
||||
turn_info_map[ring_id].has_blocked_turn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename GeometryOut, overlay_type OverlayType, bool ReverseOut,
|
||||
@@ -197,7 +197,16 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
|
||||
typename geometry::ring_type<GeometryOut>::type
|
||||
> ring_container_type;
|
||||
|
||||
typedef ring_properties<typename geometry::point_type<Geometry1>::type> properties;
|
||||
typedef typename geometry::point_type<Geometry1>::type point_type1;
|
||||
|
||||
typedef ring_properties
|
||||
<
|
||||
point_type1,
|
||||
typename Strategy::template area_strategy
|
||||
<
|
||||
point_type1
|
||||
>::type::return_type
|
||||
> properties;
|
||||
|
||||
// Silence warning C4127: conditional expression is constant
|
||||
#if defined(_MSC_VER)
|
||||
@@ -297,9 +306,13 @@ std::cout << "get turns" << std::endl;
|
||||
visitor.visit_turns(1, turns);
|
||||
|
||||
#ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS
|
||||
if (needs_self_turns<Geometry1>::apply(geometry1))
|
||||
{
|
||||
self_get_turn_points::self_turns<Reverse1, assign_null_policy>(geometry1,
|
||||
strategy, robust_policy, turns, policy, 0);
|
||||
}
|
||||
if (needs_self_turns<Geometry2>::apply(geometry2))
|
||||
{
|
||||
self_get_turn_points::self_turns<Reverse2, assign_null_policy>(geometry2,
|
||||
strategy, robust_policy, turns, policy, 1);
|
||||
}
|
||||
@@ -309,8 +322,9 @@ std::cout << "get turns" << std::endl;
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
|
||||
std::cout << "enrich" << std::endl;
|
||||
#endif
|
||||
typename Strategy::side_strategy_type side_strategy;
|
||||
typename Strategy::side_strategy_type side_strategy = strategy.get_side_strategy();
|
||||
cluster_type clusters;
|
||||
std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
|
||||
|
||||
geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns,
|
||||
clusters, geometry1, geometry2,
|
||||
@@ -334,17 +348,21 @@ std::cout << "traverse" << std::endl;
|
||||
strategy,
|
||||
robust_policy,
|
||||
turns, rings,
|
||||
turn_info_per_ring,
|
||||
clusters,
|
||||
visitor
|
||||
);
|
||||
visitor.visit_turns(3, turns);
|
||||
|
||||
std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
|
||||
get_ring_turn_info<OverlayType>(turn_info_per_ring, turns, clusters);
|
||||
|
||||
typedef typename Strategy::template area_strategy<point_type>::type area_strategy_type;
|
||||
|
||||
typedef ring_properties
|
||||
<
|
||||
typename geometry::point_type<GeometryOut>::type
|
||||
> properties;
|
||||
<
|
||||
point_type,
|
||||
typename area_strategy_type::return_type
|
||||
> properties;
|
||||
|
||||
// Select all rings which are NOT touched by any intersection point
|
||||
std::map<ring_identifier, properties> selected_ring_properties;
|
||||
@@ -353,13 +371,15 @@ std::cout << "traverse" << std::endl;
|
||||
|
||||
// Add rings created during traversal
|
||||
{
|
||||
area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
|
||||
|
||||
ring_identifier id(2, 0, -1);
|
||||
for (typename boost::range_iterator<ring_container_type>::type
|
||||
it = boost::begin(rings);
|
||||
it != boost::end(rings);
|
||||
++it)
|
||||
{
|
||||
selected_ring_properties[id] = properties(*it);
|
||||
selected_ring_properties[id] = properties(*it, area_strategy);
|
||||
selected_ring_properties[id].reversed = ReverseOut;
|
||||
id.multi_index++;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ enum overlay_type
|
||||
overlay_intersection,
|
||||
overlay_difference,
|
||||
overlay_buffer,
|
||||
overlay_dissolve
|
||||
overlay_dissolve_union,
|
||||
overlay_dissolve_intersection
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
@@ -41,6 +42,17 @@ enum operation_type
|
||||
|
||||
template <overlay_type OverlayType>
|
||||
struct operation_from_overlay
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct operation_from_overlay<overlay_union>
|
||||
{
|
||||
static const operation_type value = operation_union;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct operation_from_overlay<overlay_buffer>
|
||||
{
|
||||
static const operation_type value = operation_union;
|
||||
};
|
||||
@@ -57,6 +69,19 @@ struct operation_from_overlay<overlay_difference>
|
||||
static const operation_type value = operation_intersection;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct operation_from_overlay<overlay_dissolve_union>
|
||||
{
|
||||
static const operation_type value = operation_union;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct operation_from_overlay<overlay_dissolve_intersection>
|
||||
{
|
||||
static const operation_type value = operation_intersection;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::overlay
|
||||
#endif //DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <boost/geometry/algorithms/detail/not.hpp>
|
||||
#include <boost/geometry/algorithms/detail/partition.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/less.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// 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
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP
|
||||
@@ -24,10 +25,11 @@
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/relate/less.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
|
||||
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -264,17 +266,20 @@ struct multipoint_multipoint_point
|
||||
>::apply(multipoint2, multipoint1, robust_policy, oit, strategy);
|
||||
}
|
||||
|
||||
std::vector<typename boost::range_value<MultiPoint2>::type>
|
||||
points2(boost::begin(multipoint2), boost::end(multipoint2));
|
||||
typedef typename boost::range_value<MultiPoint2>::type point2_type;
|
||||
|
||||
std::sort(points2.begin(), points2.end(), detail::relate::less());
|
||||
std::vector<point2_type> points2(boost::begin(multipoint2),
|
||||
boost::end(multipoint2));
|
||||
|
||||
geometry::less<> const less = geometry::less<>();
|
||||
std::sort(points2.begin(), points2.end(), less);
|
||||
|
||||
for (typename boost::range_iterator<MultiPoint1 const>::type
|
||||
it1 = boost::begin(multipoint1);
|
||||
it1 != boost::end(multipoint1); ++it1)
|
||||
{
|
||||
bool found = std::binary_search(points2.begin(), points2.end(),
|
||||
*it1, detail::relate::less());
|
||||
*it1, less);
|
||||
|
||||
action_selector_pl_pl
|
||||
<
|
||||
|
||||
@@ -27,11 +27,11 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
template <typename Point>
|
||||
template <typename Point, typename AreaType>
|
||||
struct ring_properties
|
||||
{
|
||||
typedef Point point_type;
|
||||
typedef typename default_area_result<Point>::type area_type;
|
||||
typedef AreaType area_type;
|
||||
|
||||
bool valid;
|
||||
|
||||
@@ -56,13 +56,13 @@ struct ring_properties
|
||||
, parent_area(-1)
|
||||
{}
|
||||
|
||||
template <typename RingOrBox>
|
||||
inline ring_properties(RingOrBox const& ring_or_box)
|
||||
template <typename RingOrBox, typename AreaStrategy>
|
||||
inline ring_properties(RingOrBox const& ring_or_box, AreaStrategy const& strategy)
|
||||
: reversed(false)
|
||||
, discarded(false)
|
||||
, parent_area(-1)
|
||||
{
|
||||
this->area = geometry::area(ring_or_box);
|
||||
this->area = geometry::area(ring_or_box, strategy);
|
||||
valid = geometry::point_on_border(this->point, ring_or_box);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,10 +41,12 @@ namespace detail { namespace overlay
|
||||
struct ring_turn_info
|
||||
{
|
||||
bool has_traversed_turn;
|
||||
bool has_blocked_turn;
|
||||
bool within_other;
|
||||
|
||||
ring_turn_info()
|
||||
: has_traversed_turn(false)
|
||||
, has_blocked_turn(false)
|
||||
, within_other(false)
|
||||
{}
|
||||
};
|
||||
@@ -59,41 +61,45 @@ namespace dispatch
|
||||
template <typename Box>
|
||||
struct select_rings<box_tag, Box>
|
||||
{
|
||||
template <typename Geometry, typename RingPropertyMap>
|
||||
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
|
||||
static inline void apply(Box const& box, Geometry const& ,
|
||||
ring_identifier const& id, RingPropertyMap& ring_properties)
|
||||
ring_identifier const& id, RingPropertyMap& ring_properties,
|
||||
AreaStrategy const& strategy)
|
||||
{
|
||||
ring_properties[id] = typename RingPropertyMap::mapped_type(box);
|
||||
ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy);
|
||||
}
|
||||
|
||||
template <typename RingPropertyMap>
|
||||
template <typename RingPropertyMap, typename AreaStrategy>
|
||||
static inline void apply(Box const& box,
|
||||
ring_identifier const& id, RingPropertyMap& ring_properties)
|
||||
ring_identifier const& id, RingPropertyMap& ring_properties,
|
||||
AreaStrategy const& strategy)
|
||||
{
|
||||
ring_properties[id] = typename RingPropertyMap::mapped_type(box);
|
||||
ring_properties[id] = typename RingPropertyMap::mapped_type(box, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Ring>
|
||||
struct select_rings<ring_tag, Ring>
|
||||
{
|
||||
template <typename Geometry, typename RingPropertyMap>
|
||||
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
|
||||
static inline void apply(Ring const& ring, Geometry const& ,
|
||||
ring_identifier const& id, RingPropertyMap& ring_properties)
|
||||
ring_identifier const& id, RingPropertyMap& ring_properties,
|
||||
AreaStrategy const& strategy)
|
||||
{
|
||||
if (boost::size(ring) > 0)
|
||||
{
|
||||
ring_properties[id] = typename RingPropertyMap::mapped_type(ring);
|
||||
ring_properties[id] = typename RingPropertyMap::mapped_type(ring, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RingPropertyMap>
|
||||
template <typename RingPropertyMap, typename AreaStrategy>
|
||||
static inline void apply(Ring const& ring,
|
||||
ring_identifier const& id, RingPropertyMap& ring_properties)
|
||||
ring_identifier const& id, RingPropertyMap& ring_properties,
|
||||
AreaStrategy const& strategy)
|
||||
{
|
||||
if (boost::size(ring) > 0)
|
||||
{
|
||||
ring_properties[id] = typename RingPropertyMap::mapped_type(ring);
|
||||
ring_properties[id] = typename RingPropertyMap::mapped_type(ring, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -102,14 +108,15 @@ namespace dispatch
|
||||
template <typename Polygon>
|
||||
struct select_rings<polygon_tag, Polygon>
|
||||
{
|
||||
template <typename Geometry, typename RingPropertyMap>
|
||||
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
|
||||
static inline void apply(Polygon const& polygon, Geometry const& geometry,
|
||||
ring_identifier id, RingPropertyMap& ring_properties)
|
||||
ring_identifier id, RingPropertyMap& ring_properties,
|
||||
AreaStrategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::ring_type<Polygon>::type ring_type;
|
||||
typedef select_rings<ring_tag, ring_type> per_ring;
|
||||
|
||||
per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties);
|
||||
per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties, strategy);
|
||||
|
||||
typename interior_return_type<Polygon const>::type
|
||||
rings = interior_rings(polygon);
|
||||
@@ -117,18 +124,19 @@ namespace dispatch
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
id.ring_index++;
|
||||
per_ring::apply(*it, geometry, id, ring_properties);
|
||||
per_ring::apply(*it, geometry, id, ring_properties, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RingPropertyMap>
|
||||
template <typename RingPropertyMap, typename AreaStrategy>
|
||||
static inline void apply(Polygon const& polygon,
|
||||
ring_identifier id, RingPropertyMap& ring_properties)
|
||||
ring_identifier id, RingPropertyMap& ring_properties,
|
||||
AreaStrategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::ring_type<Polygon>::type ring_type;
|
||||
typedef select_rings<ring_tag, ring_type> per_ring;
|
||||
|
||||
per_ring::apply(exterior_ring(polygon), id, ring_properties);
|
||||
per_ring::apply(exterior_ring(polygon), id, ring_properties, strategy);
|
||||
|
||||
typename interior_return_type<Polygon const>::type
|
||||
rings = interior_rings(polygon);
|
||||
@@ -136,7 +144,7 @@ namespace dispatch
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
id.ring_index++;
|
||||
per_ring::apply(*it, id, ring_properties);
|
||||
per_ring::apply(*it, id, ring_properties, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -144,9 +152,10 @@ namespace dispatch
|
||||
template <typename Multi>
|
||||
struct select_rings<multi_polygon_tag, Multi>
|
||||
{
|
||||
template <typename Geometry, typename RingPropertyMap>
|
||||
template <typename Geometry, typename RingPropertyMap, typename AreaStrategy>
|
||||
static inline void apply(Multi const& multi, Geometry const& geometry,
|
||||
ring_identifier id, RingPropertyMap& ring_properties)
|
||||
ring_identifier id, RingPropertyMap& ring_properties,
|
||||
AreaStrategy const& strategy)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
@@ -159,7 +168,7 @@ namespace dispatch
|
||||
for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it)
|
||||
{
|
||||
id.ring_index = -1;
|
||||
per_polygon::apply(*it, geometry, id, ring_properties);
|
||||
per_polygon::apply(*it, geometry, id, ring_properties, strategy);
|
||||
id.multi_index++;
|
||||
}
|
||||
}
|
||||
@@ -258,9 +267,9 @@ inline void update_ring_selection(Geometry1 const& geometry1,
|
||||
info = tcit->second; // Copy by value
|
||||
}
|
||||
|
||||
if (info.has_traversed_turn)
|
||||
if (info.has_traversed_turn || info.has_blocked_turn)
|
||||
{
|
||||
// This turn is traversed (or blocked),
|
||||
// This turn is traversed or blocked,
|
||||
// don't include the original ring
|
||||
continue;
|
||||
}
|
||||
@@ -311,12 +320,16 @@ inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
{
|
||||
typedef typename geometry::tag<Geometry1>::type tag1;
|
||||
typedef typename geometry::tag<Geometry2>::type tag2;
|
||||
typedef typename geometry::point_type<Geometry1>::type point1_type;
|
||||
typedef typename geometry::point_type<Geometry2>::type point2_type;
|
||||
|
||||
RingPropertyMap all_ring_properties;
|
||||
dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2,
|
||||
ring_identifier(0, -1, -1), all_ring_properties);
|
||||
ring_identifier(0, -1, -1), all_ring_properties,
|
||||
strategy.template get_area_strategy<point1_type>());
|
||||
dispatch::select_rings<tag2, Geometry2>::apply(geometry2, geometry1,
|
||||
ring_identifier(1, -1, -1), all_ring_properties);
|
||||
ring_identifier(1, -1, -1), all_ring_properties,
|
||||
strategy.template get_area_strategy<point2_type>());
|
||||
|
||||
update_ring_selection<OverlayType>(geometry1, geometry2, turn_info_per_ring,
|
||||
all_ring_properties, selected_ring_properties,
|
||||
@@ -337,10 +350,12 @@ inline void select_rings(Geometry const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::tag<Geometry>::type tag;
|
||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
||||
|
||||
RingPropertyMap all_ring_properties;
|
||||
dispatch::select_rings<tag, Geometry>::apply(geometry,
|
||||
ring_identifier(0, -1, -1), all_ring_properties);
|
||||
ring_identifier(0, -1, -1), all_ring_properties,
|
||||
strategy.template get_area_strategy<point_type>());
|
||||
|
||||
update_ring_selection<OverlayType>(geometry, geometry, turn_info_per_ring,
|
||||
all_ring_properties, selected_ring_properties,
|
||||
|
||||
@@ -78,19 +78,22 @@ struct self_section_visitor
|
||||
Turns& m_turns;
|
||||
InterruptPolicy& m_interrupt_policy;
|
||||
std::size_t m_source_index;
|
||||
bool m_skip_adjacent;
|
||||
|
||||
inline self_section_visitor(Geometry const& g,
|
||||
IntersectionStrategy const& is,
|
||||
RobustPolicy const& rp,
|
||||
Turns& turns,
|
||||
InterruptPolicy& ip,
|
||||
std::size_t source_index)
|
||||
std::size_t source_index,
|
||||
bool skip_adjacent)
|
||||
: m_geometry(g)
|
||||
, m_intersection_strategy(is)
|
||||
, m_rescale_policy(rp)
|
||||
, m_turns(turns)
|
||||
, m_interrupt_policy(ip)
|
||||
, m_source_index(source_index)
|
||||
, m_skip_adjacent(skip_adjacent)
|
||||
{}
|
||||
|
||||
template <typename Section>
|
||||
@@ -109,7 +112,7 @@ struct self_section_visitor
|
||||
TurnPolicy
|
||||
>::apply(m_source_index, m_geometry, sec1,
|
||||
m_source_index, m_geometry, sec2,
|
||||
false,
|
||||
false, m_skip_adjacent,
|
||||
m_intersection_strategy,
|
||||
m_rescale_policy,
|
||||
m_turns, m_interrupt_policy);
|
||||
@@ -132,7 +135,7 @@ struct get_turns
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns,
|
||||
InterruptPolicy& interrupt_policy,
|
||||
std::size_t source_index)
|
||||
std::size_t source_index, bool skip_adjacent)
|
||||
{
|
||||
typedef model::box
|
||||
<
|
||||
@@ -143,9 +146,11 @@ struct get_turns
|
||||
>::type
|
||||
> box_type;
|
||||
|
||||
typedef geometry::sections<box_type, 1> sections_type;
|
||||
// sectionalize in two dimensions to detect
|
||||
// all potential spikes correctly
|
||||
typedef geometry::sections<box_type, 2> sections_type;
|
||||
|
||||
typedef boost::mpl::vector_c<std::size_t, 0> dimensions;
|
||||
typedef boost::mpl::vector_c<std::size_t, 0, 1> dimensions;
|
||||
|
||||
sections_type sec;
|
||||
geometry::sectionalize<Reverse, dimensions>(geometry, robust_policy, sec,
|
||||
@@ -155,7 +160,7 @@ struct get_turns
|
||||
<
|
||||
Reverse, Geometry,
|
||||
Turns, TurnPolicy, IntersectionStrategy, RobustPolicy, InterruptPolicy
|
||||
> visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy, source_index);
|
||||
> visitor(geometry, intersection_strategy, robust_policy, turns, interrupt_policy, source_index, skip_adjacent);
|
||||
|
||||
// false if interrupted
|
||||
geometry::partition
|
||||
@@ -224,7 +229,8 @@ struct self_get_turn_points
|
||||
RobustPolicy const& ,
|
||||
Turns& ,
|
||||
InterruptPolicy& ,
|
||||
std::size_t)
|
||||
std::size_t /*source_index*/,
|
||||
bool /*skip_adjacent*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -286,7 +292,8 @@ inline void self_turns(Geometry const& geometry,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns,
|
||||
InterruptPolicy& interrupt_policy,
|
||||
std::size_t source_index = 0)
|
||||
std::size_t source_index = 0,
|
||||
bool skip_adjacent = false)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
@@ -298,7 +305,8 @@ inline void self_turns(Geometry const& geometry,
|
||||
typename tag<Geometry>::type,
|
||||
Geometry,
|
||||
turn_policy
|
||||
>::apply(geometry, strategy, robust_policy, turns, interrupt_policy, source_index);
|
||||
>::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
|
||||
source_index, skip_adjacent);
|
||||
}
|
||||
|
||||
}} // namespace detail::self_get_turn_points
|
||||
@@ -331,7 +339,8 @@ inline void self_turns(Geometry const& geometry,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns,
|
||||
InterruptPolicy& interrupt_policy,
|
||||
std::size_t source_index = 0)
|
||||
std::size_t source_index = 0,
|
||||
bool skip_adjacent = false)
|
||||
{
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
@@ -344,7 +353,8 @@ inline void self_turns(Geometry const& geometry,
|
||||
<
|
||||
reverse,
|
||||
AssignPolicy
|
||||
>(geometry, strategy, robust_policy, turns, interrupt_policy, source_index);
|
||||
>(geometry, strategy, robust_policy, turns, interrupt_policy,
|
||||
source_index, skip_adjacent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// Copyright (c) 2015 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)
|
||||
@@ -18,7 +23,6 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
|
||||
#include <boost/geometry/algorithms/detail/direction_code.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -87,13 +91,20 @@ struct less_by_index
|
||||
template <typename T>
|
||||
inline bool operator()(const T& first, const T& second) const
|
||||
{
|
||||
// Length might be considered too
|
||||
// First order by from/to
|
||||
if (first.direction != second.direction)
|
||||
{
|
||||
return first.direction < second.direction;
|
||||
}
|
||||
// All the same, order by turn index (we might consider length too)
|
||||
return first.turn_index < second.turn_index;
|
||||
// Then by turn index
|
||||
if (first.turn_index != second.turn_index)
|
||||
{
|
||||
return first.turn_index < second.turn_index;
|
||||
}
|
||||
// This can also be the same (for example in buffer), but seg_id is
|
||||
// never the same
|
||||
return first.seg_id < second.seg_id;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -106,17 +117,13 @@ struct less_false
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point, typename LessOnSame, typename Compare>
|
||||
template <typename Point, typename SideStrategy, typename LessOnSame, typename Compare>
|
||||
struct less_by_side
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type side;
|
||||
|
||||
less_by_side(const Point& p1, const Point& p2)
|
||||
less_by_side(const Point& p1, const Point& p2, SideStrategy const& strategy)
|
||||
: m_p1(p1)
|
||||
, m_p2(p2)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
@@ -125,8 +132,8 @@ struct less_by_side
|
||||
LessOnSame on_same;
|
||||
Compare compare;
|
||||
|
||||
int const side_first = side::apply(m_p1, m_p2, first.point);
|
||||
int const side_second = side::apply(m_p1, m_p2, second.point);
|
||||
int const side_first = m_strategy.apply(m_p1, m_p2, first.point);
|
||||
int const side_second = m_strategy.apply(m_p1, m_p2, second.point);
|
||||
|
||||
if (side_first == 0 && side_second == 0)
|
||||
{
|
||||
@@ -166,7 +173,7 @@ struct less_by_side
|
||||
|
||||
// They are both left, both right, and/or both collinear (with each other and/or with p1,p2)
|
||||
// Check mutual side
|
||||
int const side_second_wrt_first = side::apply(m_p2, first.point, second.point);
|
||||
int const side_second_wrt_first = m_strategy.apply(m_p2, first.point, second.point);
|
||||
|
||||
if (side_second_wrt_first == 0)
|
||||
{
|
||||
@@ -184,6 +191,7 @@ struct less_by_side
|
||||
|
||||
private :
|
||||
Point m_p1, m_p2;
|
||||
SideStrategy const& m_strategy;
|
||||
};
|
||||
|
||||
// Sorts vectors in counter clockwise order (by default)
|
||||
@@ -193,6 +201,7 @@ template
|
||||
bool Reverse2,
|
||||
overlay_type OverlayType,
|
||||
typename Point,
|
||||
typename SideStrategy,
|
||||
typename Compare
|
||||
>
|
||||
struct side_sorter
|
||||
@@ -223,9 +232,10 @@ private :
|
||||
};
|
||||
|
||||
public :
|
||||
side_sorter()
|
||||
side_sorter(SideStrategy const& strategy)
|
||||
: m_origin_count(0)
|
||||
, m_origin_segment_distance(0)
|
||||
, m_strategy(strategy)
|
||||
{}
|
||||
|
||||
template <typename Operation, typename Geometry1, typename Geometry2>
|
||||
@@ -309,8 +319,8 @@ public :
|
||||
// to give colinear points
|
||||
|
||||
// Sort by side and assign rank
|
||||
less_by_side<Point, less_by_index, Compare> less_unique(m_origin, turn_point);
|
||||
less_by_side<Point, less_false, Compare> less_non_unique(m_origin, turn_point);
|
||||
less_by_side<Point, SideStrategy, less_by_index, Compare> less_unique(m_origin, turn_point, m_strategy);
|
||||
less_by_side<Point, SideStrategy, less_false, Compare> less_non_unique(m_origin, turn_point, m_strategy);
|
||||
|
||||
std::sort(m_ranked_points.begin(), m_ranked_points.end(), less_unique);
|
||||
|
||||
@@ -425,6 +435,7 @@ public :
|
||||
Point m_origin;
|
||||
std::size_t m_origin_count;
|
||||
int m_origin_segment_distance;
|
||||
SideStrategy m_strategy;
|
||||
|
||||
private :
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -94,6 +99,7 @@ template
|
||||
typename Turns,
|
||||
typename Clusters,
|
||||
typename RobustPolicy,
|
||||
typename SideStrategy,
|
||||
typename Visitor
|
||||
>
|
||||
struct traversal
|
||||
@@ -108,22 +114,25 @@ struct traversal
|
||||
typedef sort_by_side::side_sorter
|
||||
<
|
||||
Reverse1, Reverse2, OverlayType,
|
||||
point_type, side_compare_type
|
||||
point_type, SideStrategy, side_compare_type
|
||||
> sbs_type;
|
||||
|
||||
inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Turns& turns, Clusters const& clusters,
|
||||
RobustPolicy const& robust_policy, Visitor& visitor)
|
||||
RobustPolicy const& robust_policy, SideStrategy const& strategy,
|
||||
Visitor& visitor)
|
||||
: m_geometry1(geometry1)
|
||||
, m_geometry2(geometry2)
|
||||
, m_turns(turns)
|
||||
, m_clusters(clusters)
|
||||
, m_robust_policy(robust_policy)
|
||||
, m_strategy(strategy)
|
||||
, m_visitor(visitor)
|
||||
{
|
||||
}
|
||||
|
||||
inline void finalize_visit_info()
|
||||
template <typename TurnInfoMap>
|
||||
inline void finalize_visit_info(TurnInfoMap& turn_info_map)
|
||||
{
|
||||
for (typename boost::range_iterator<Turns>::type
|
||||
it = boost::begin(m_turns);
|
||||
@@ -134,6 +143,32 @@ struct traversal
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
turn_operation_type& op = turn.operations[i];
|
||||
if (op.visited.visited()
|
||||
|| op.visited.started()
|
||||
|| op.visited.finished() )
|
||||
{
|
||||
ring_identifier const ring_id
|
||||
(
|
||||
op.seg_id.source_index,
|
||||
op.seg_id.multi_index,
|
||||
op.seg_id.ring_index
|
||||
);
|
||||
turn_info_map[ring_id].has_traversed_turn = true;
|
||||
|
||||
if (op.operation == operation_continue)
|
||||
{
|
||||
// Continue operations should mark the other operation
|
||||
// as traversed too
|
||||
turn_operation_type& other_op = turn.operations[1 - i];
|
||||
ring_identifier const other_ring_id
|
||||
(
|
||||
other_op.seg_id.source_index,
|
||||
other_op.seg_id.multi_index,
|
||||
other_op.seg_id.ring_index
|
||||
);
|
||||
turn_info_map[other_ring_id].has_traversed_turn = true;
|
||||
}
|
||||
}
|
||||
op.visited.finalize();
|
||||
}
|
||||
}
|
||||
@@ -184,7 +219,7 @@ struct traversal
|
||||
{
|
||||
op.visited.set_visited();
|
||||
}
|
||||
if (turn.cluster_id >= 0)
|
||||
if (turn.is_clustered())
|
||||
{
|
||||
set_visited_in_cluster(turn.cluster_id, op.enriched.rank);
|
||||
}
|
||||
@@ -245,7 +280,7 @@ struct traversal
|
||||
|
||||
// It is not a dead end if there is an operation to continue, or of
|
||||
// there is a cluster (assuming for now we can get out of the cluster)
|
||||
return turn.cluster_id >= 0
|
||||
return turn.is_clustered()
|
||||
|| turn.has(target_operation)
|
||||
|| turn.has(operation_continue);
|
||||
}
|
||||
@@ -372,13 +407,50 @@ struct traversal
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int select_turn_in_cluster_union(std::size_t selected_rank,
|
||||
typename sbs_type::rp const& ranked_point,
|
||||
signed_size_type start_turn_index, int start_op_index) const
|
||||
{
|
||||
// Returns 0 if it not OK
|
||||
// Returns 1 if it OK
|
||||
// Returns 2 if it OK and start turn matches
|
||||
// Returns 3 if it OK and start turn and start op both match
|
||||
if (ranked_point.rank != selected_rank
|
||||
|| ranked_point.direction != sort_by_side::dir_to)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
turn_type const& turn = m_turns[ranked_point.turn_index];
|
||||
turn_operation_type const& op = turn.operations[ranked_point.operation_index];
|
||||
|
||||
// Check counts: in some cases interior rings might be generated with
|
||||
// polygons on both sides
|
||||
|
||||
// Check finalized: TODO: this should be finetuned, it is not necessary
|
||||
bool const ok = op.enriched.count_left == 0
|
||||
&& op.enriched.count_right > 0
|
||||
&& ! op.visited.finalized();
|
||||
|
||||
if (! ok)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ranked_point.turn_index == start_turn_index
|
||||
&& ranked_point.operation_index == start_op_index ? 3
|
||||
: ranked_point.turn_index == start_turn_index ? 2
|
||||
: 1
|
||||
;
|
||||
}
|
||||
|
||||
inline bool select_from_cluster_union(signed_size_type& turn_index,
|
||||
int& op_index, sbs_type& sbs) const
|
||||
int& op_index, sbs_type& sbs,
|
||||
signed_size_type start_turn_index, int start_op_index) const
|
||||
{
|
||||
std::vector<sort_by_side::rank_with_rings> aggregation;
|
||||
sort_by_side::aggregate_operations(sbs, aggregation, m_turns, operation_union);
|
||||
|
||||
|
||||
sort_by_side::rank_with_rings const& incoming = aggregation.front();
|
||||
|
||||
// Take the first one outgoing for the incoming region
|
||||
@@ -394,62 +466,32 @@ struct traversal
|
||||
}
|
||||
}
|
||||
|
||||
int best_code = 0;
|
||||
bool result = false;
|
||||
for (std::size_t i = 1; i < sbs.m_ranked_points.size(); i++)
|
||||
{
|
||||
typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i];
|
||||
if (ranked_point.rank == selected_rank
|
||||
&& ranked_point.direction == sort_by_side::dir_to)
|
||||
|
||||
if (ranked_point.rank > selected_rank)
|
||||
{
|
||||
// Sorted on rank, so it makes no sense to continue
|
||||
break;
|
||||
}
|
||||
|
||||
int const code
|
||||
= select_turn_in_cluster_union(selected_rank, ranked_point,
|
||||
start_turn_index, start_op_index);
|
||||
|
||||
if (code > best_code)
|
||||
{
|
||||
// It is 1 or higher and matching better than previous
|
||||
best_code = code;
|
||||
turn_index = ranked_point.turn_index;
|
||||
op_index = ranked_point.operation_index;
|
||||
|
||||
turn_type const& turn = m_turns[turn_index];
|
||||
turn_operation_type const& op = turn.operations[op_index];
|
||||
|
||||
if (op.enriched.count_left == 0
|
||||
&& op.enriched.count_right > 0
|
||||
&& ! op.visited.finalized())
|
||||
{
|
||||
// In some cases interior rings might be generated with polygons
|
||||
// on both sides
|
||||
|
||||
// TODO: this should be finetuned such that checking
|
||||
// finalized is not necessary
|
||||
return true;
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
inline bool all_operations_of_type(sort_by_side::rank_with_rings const& rwr,
|
||||
operation_type op_type,
|
||||
sort_by_side::direction_type dir) const
|
||||
{
|
||||
typedef std::set<sort_by_side::ring_with_direction>::const_iterator sit_type;
|
||||
for (sit_type it = rwr.rings.begin(); it != rwr.rings.end(); ++it)
|
||||
{
|
||||
sort_by_side::ring_with_direction const& rwd = *it;
|
||||
if (rwd.direction != dir)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
turn_type const& turn = m_turns[rwd.turn_index];
|
||||
if (! turn.both(op_type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if this is not yet taken
|
||||
turn_operation_type const& op = turn.operations[rwd.operation_index];
|
||||
if (op.visited.finalized())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool analyze_cluster_intersection(signed_size_type& turn_index,
|
||||
@@ -467,12 +509,14 @@ struct traversal
|
||||
|| intersection_pattern_common_interior2(selected_rank, aggregation)
|
||||
|| intersection_pattern_common_interior3(selected_rank, aggregation)
|
||||
|| intersection_pattern_common_interior4(selected_rank, aggregation)
|
||||
|| intersection_pattern_common_interior5(selected_rank, aggregation)
|
||||
|| intersection_pattern_common_interior6(selected_rank, aggregation)
|
||||
;
|
||||
|
||||
if (! detected)
|
||||
{
|
||||
int incoming_region_id = 0;
|
||||
std::set<int> outgoing_region_ids;
|
||||
signed_size_type incoming_region_id = 0;
|
||||
std::set<signed_size_type> outgoing_region_ids;
|
||||
|
||||
for (std::size_t i = 0; i < aggregation.size(); i++)
|
||||
{
|
||||
@@ -522,7 +566,7 @@ struct traversal
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
int const region_id = turn.operations[i].enriched.region_id;
|
||||
signed_size_type const region_id = turn.operations[i].enriched.region_id;
|
||||
if (outgoing_region_ids.count(region_id) == 1)
|
||||
{
|
||||
selected_rank = 0;
|
||||
@@ -537,6 +581,9 @@ struct traversal
|
||||
|
||||
if (selected_rank > 0)
|
||||
{
|
||||
typename turn_operation_type::comparable_distance_type
|
||||
min_remaining_distance = 0;
|
||||
|
||||
std::size_t selected_index = sbs.m_ranked_points.size();
|
||||
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
|
||||
{
|
||||
@@ -554,8 +601,13 @@ struct traversal
|
||||
continue;
|
||||
}
|
||||
|
||||
// Take the last turn from this rank
|
||||
selected_index = i;
|
||||
// Take turn with the smallest remaining distance
|
||||
if (selected_index == sbs.m_ranked_points.size()
|
||||
|| ranked_op.remaining_distance < min_remaining_distance)
|
||||
{
|
||||
selected_index = i;
|
||||
min_remaining_distance = ranked_op.remaining_distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,13 +625,13 @@ struct traversal
|
||||
|
||||
inline bool select_turn_from_cluster(signed_size_type& turn_index,
|
||||
int& op_index,
|
||||
signed_size_type start_turn_index,
|
||||
signed_size_type start_turn_index, int start_op_index,
|
||||
segment_identifier const& previous_seg_id) const
|
||||
{
|
||||
bool const is_union = target_operation == operation_union;
|
||||
|
||||
turn_type const& turn = m_turns[turn_index];
|
||||
BOOST_ASSERT(turn.cluster_id >= 0);
|
||||
BOOST_ASSERT(turn.is_clustered());
|
||||
|
||||
typename Clusters::const_iterator mit = m_clusters.find(turn.cluster_id);
|
||||
BOOST_ASSERT(mit != m_clusters.end());
|
||||
@@ -587,7 +639,7 @@ struct traversal
|
||||
cluster_info const& cinfo = mit->second;
|
||||
std::set<signed_size_type> const& ids = cinfo.turn_indices;
|
||||
|
||||
sbs_type sbs;
|
||||
sbs_type sbs(m_strategy);
|
||||
|
||||
for (typename std::set<signed_size_type>::const_iterator sit = ids.begin();
|
||||
sit != ids.end(); ++sit)
|
||||
@@ -620,7 +672,8 @@ struct traversal
|
||||
|
||||
if (is_union)
|
||||
{
|
||||
result = select_from_cluster_union(turn_index, op_index, sbs);
|
||||
result = select_from_cluster_union(turn_index, op_index, sbs,
|
||||
start_turn_index, start_op_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -633,7 +686,7 @@ struct traversal
|
||||
turn_type const& current_turn,
|
||||
segment_identifier const& previous_seg_id)
|
||||
{
|
||||
sbs_type sbs;
|
||||
sbs_type sbs(m_strategy);
|
||||
|
||||
// Add this turn to the sort-by-side sorter
|
||||
for (int i = 0; i < 2; i++)
|
||||
@@ -661,7 +714,9 @@ struct traversal
|
||||
turn_operation_type const& start_op,
|
||||
int start_op_index) const
|
||||
{
|
||||
if (OverlayType != overlay_buffer)
|
||||
if (OverlayType != overlay_buffer
|
||||
&& OverlayType != overlay_dissolve_union
|
||||
&& OverlayType != overlay_dissolve_intersection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -689,6 +744,9 @@ struct traversal
|
||||
|
||||
bool const correct
|
||||
= ! start_turn.both(operation_union)
|
||||
&& start_op.seg_id.source_index == other_op.seg_id.source_index
|
||||
&& start_op.seg_id.multi_index == other_op.seg_id.multi_index
|
||||
&& start_op.seg_id.ring_index == other_op.seg_id.ring_index
|
||||
&& start_op.seg_id.segment_index == to_vertex_index;
|
||||
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE)
|
||||
@@ -762,7 +820,7 @@ struct traversal
|
||||
if (target_operation == operation_intersection)
|
||||
{
|
||||
bool const back_at_start_cluster
|
||||
= current_turn.cluster_id >= 0
|
||||
= current_turn.is_clustered()
|
||||
&& m_turns[start_turn_index].cluster_id == current_turn.cluster_id;
|
||||
|
||||
if (turn_index == start_turn_index || back_at_start_cluster)
|
||||
@@ -773,7 +831,7 @@ struct traversal
|
||||
return true;
|
||||
}
|
||||
|
||||
if (current_turn.cluster_id < 0
|
||||
if (! current_turn.is_clustered()
|
||||
&& current_turn.both(operation_intersection))
|
||||
{
|
||||
if (analyze_ii_intersection(turn_index, op_index,
|
||||
@@ -784,10 +842,10 @@ struct traversal
|
||||
}
|
||||
}
|
||||
|
||||
if (current_turn.cluster_id >= 0)
|
||||
if (current_turn.is_clustered())
|
||||
{
|
||||
if (! select_turn_from_cluster(turn_index, op_index,
|
||||
start_turn_index, previous_seg_id))
|
||||
start_turn_index, start_op_index, previous_seg_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -825,6 +883,7 @@ private :
|
||||
Turns& m_turns;
|
||||
Clusters const& m_clusters;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
SideStrategy m_strategy;
|
||||
Visitor& m_visitor;
|
||||
};
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ inline bool check_pairs(std::vector<sort_by_side::rank_with_rings> const& aggreg
|
||||
{
|
||||
sort_by_side::rank_with_rings const& curr = aggregation[i];
|
||||
sort_by_side::rank_with_rings const& next = aggregation[i + 1];
|
||||
int const curr_id = curr.region_id();
|
||||
int const next_id = next.region_id();
|
||||
signed_size_type const curr_id = curr.region_id();
|
||||
signed_size_type const next_id = next.region_id();
|
||||
|
||||
bool const possible =
|
||||
curr.rings.size() == 2
|
||||
@@ -249,7 +249,7 @@ inline bool intersection_pattern_common_interior4(std::size_t& selected_rank,
|
||||
//Rank 1 {13[0] (s:0, r:0, m:0) i T rgn: 2 ISO ->15} {11[1] (s:1, r:1, m:0) i T rgn: 2 ISO ->15}
|
||||
//Rank 2 {13[0] (s:0, r:0, m:0) i F rgn: 2 ISO} {11[1] (s:1, r:1, m:0) i F rgn: 2 ISO}
|
||||
|
||||
// LEAVING (in two different directions, take last one)
|
||||
// LEAVING (in two different directions, take penultimate one)
|
||||
//Rank 3 {10[1] (s:1, m:0) i T rgn: 1 ISO ->0}
|
||||
//Rank 4 {11[0] (s:0, m:0) i T rgn: 1 ISO ->12}
|
||||
|
||||
@@ -292,12 +292,157 @@ inline bool intersection_pattern_common_interior4(std::size_t& selected_rank,
|
||||
// Check if pairs 1,2 (and possibly 3,4 and 5,6 etc) satisfy
|
||||
if (check_pairs(aggregation, incoming.region_id(), 1, n - 3))
|
||||
{
|
||||
selected_rank = n - 1;
|
||||
selected_rank = n - 2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool intersection_pattern_common_interior5(std::size_t& selected_rank,
|
||||
std::vector<sort_by_side::rank_with_rings> const& aggregation)
|
||||
{
|
||||
// Pattern: isolated regions
|
||||
|
||||
// See #case_recursive_boxes_65
|
||||
|
||||
// INCOMING:
|
||||
// Rank 0 {19[0] (s:0, r:2, m:0) i F rgn: 4 ISO}
|
||||
|
||||
// Rank 1 {19[1] (s:1, m:0) i T rgn: 1 ISO FIN ->18 (2.5)}
|
||||
// Rank 2 {21[1] (s:1, m:2) i F rgn: 1 ISO}
|
||||
// Rank 3 {21[1] (s:1, m:2) i T rgn: 1 ISO ->17 (2)}
|
||||
// Rank 4 {19[1] (s:1, m:0) i F rgn: 1 ISO FIN}
|
||||
|
||||
// LEAVING (take this one):
|
||||
// Rank 5 {19[0] (s:0, r:2, m:0) i T rgn: 4 ISO ->22 (1)}
|
||||
|
||||
std::size_t const n = aggregation.size();
|
||||
if (n < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sort_by_side::rank_with_rings const& incoming = aggregation.front();
|
||||
sort_by_side::rank_with_rings const& outgoing = aggregation.back();
|
||||
|
||||
bool const incoming_ok =
|
||||
incoming.all_from()
|
||||
&& incoming.has_unique_region_id()
|
||||
&& incoming.is_isolated();
|
||||
|
||||
if (! incoming_ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
signed_size_type const incoming_region_id = incoming.region_id();
|
||||
|
||||
bool const outgoing_ok =
|
||||
outgoing.all_to()
|
||||
&& outgoing.has_unique_region_id()
|
||||
&& outgoing.is_isolated()
|
||||
&& outgoing.region_id() == incoming_region_id;
|
||||
|
||||
if (! outgoing_ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
selected_rank = n - 1;
|
||||
bool other_region = true;
|
||||
|
||||
// Assumed is that other regions go (T) and come back (F)
|
||||
for (std::size_t i = 1; i < n - 1; i++)
|
||||
{
|
||||
sort_by_side::rank_with_rings const& rwr = aggregation[i];
|
||||
if (! rwr.has_unique_region_id() || ! rwr.is_isolated())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
signed_size_type const region_id = rwr.region_id();
|
||||
if (other_region && region_id != incoming_region_id)
|
||||
{
|
||||
// OK
|
||||
}
|
||||
else if (other_region && region_id == incoming_region_id)
|
||||
{
|
||||
// OK, next phase (same region as incoming region)
|
||||
selected_rank = i;
|
||||
other_region = false;
|
||||
}
|
||||
else if (! other_region && region_id != incoming_region_id)
|
||||
{
|
||||
// After that the region is the same is incoming, it should
|
||||
// stay like that
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool intersection_pattern_common_interior6(std::size_t& selected_rank,
|
||||
std::vector<sort_by_side::rank_with_rings> const& aggregation)
|
||||
{
|
||||
// Pattern: isolated regions in between
|
||||
|
||||
// See #case_recursive_boxes_75
|
||||
|
||||
// Incoming: one region
|
||||
// In between: several rings having isolated region, all the same
|
||||
// Outging == incoming
|
||||
|
||||
std::size_t const n = aggregation.size();
|
||||
if (n < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sort_by_side::rank_with_rings const& incoming = aggregation.front();
|
||||
sort_by_side::rank_with_rings const& outgoing = aggregation.back();
|
||||
sort_by_side::rank_with_rings const& first_isolated = aggregation[2];
|
||||
|
||||
bool const incoming_ok =
|
||||
incoming.all_from()
|
||||
&& incoming.has_unique_region_id()
|
||||
&& ! incoming.is_isolated();
|
||||
|
||||
if (! incoming_ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
signed_size_type const incoming_region_id = incoming.region_id();
|
||||
|
||||
bool const outgoing_ok =
|
||||
outgoing.all_to()
|
||||
&& outgoing.has_unique_region_id()
|
||||
&& ! outgoing.is_isolated()
|
||||
&& outgoing.region_id() == incoming_region_id;
|
||||
|
||||
if (! outgoing_ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const signed_size_type isolated_region_id = first_isolated.region_id();
|
||||
|
||||
for (std::size_t i = 1; i < n - 1; i++)
|
||||
{
|
||||
sort_by_side::rank_with_rings const& rwr = aggregation[i];
|
||||
if (! rwr.has_unique_region_id()
|
||||
|| ! rwr.is_isolated()
|
||||
|| rwr.region_id() != isolated_region_id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
selected_rank = n - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}} // namespace detail::overlay
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ template
|
||||
typename Geometry1,
|
||||
typename Geometry2,
|
||||
typename Turns,
|
||||
typename TurnInfoMap,
|
||||
typename Clusters,
|
||||
typename IntersectionStrategy,
|
||||
typename RobustPolicy,
|
||||
@@ -49,9 +50,13 @@ template
|
||||
>
|
||||
struct traversal_ring_creator
|
||||
{
|
||||
typedef traversal<Reverse1, Reverse2, OverlayType,
|
||||
Geometry1, Geometry2, Turns, Clusters, RobustPolicy, Visitor>
|
||||
traversal_type;
|
||||
typedef traversal
|
||||
<
|
||||
Reverse1, Reverse2, OverlayType,
|
||||
Geometry1, Geometry2, Turns, Clusters,
|
||||
RobustPolicy, typename IntersectionStrategy::side_strategy_type,
|
||||
Visitor
|
||||
> traversal_type;
|
||||
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::turn_operation_type turn_operation_type;
|
||||
@@ -60,13 +65,17 @@ struct traversal_ring_creator
|
||||
= operation_from_overlay<OverlayType>::value;
|
||||
|
||||
inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Turns& turns, Clusters const& clusters,
|
||||
Turns& turns, TurnInfoMap& turn_info_map,
|
||||
Clusters const& clusters,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
RobustPolicy const& robust_policy, Visitor& visitor)
|
||||
: m_trav(geometry1, geometry2, turns, clusters, robust_policy,visitor)
|
||||
: m_trav(geometry1, geometry2, turns, clusters,
|
||||
robust_policy, intersection_strategy.get_side_strategy(),
|
||||
visitor)
|
||||
, m_geometry1(geometry1)
|
||||
, m_geometry2(geometry2)
|
||||
, m_turns(turns)
|
||||
, m_turn_info_map(turn_info_map)
|
||||
, m_clusters(clusters)
|
||||
, m_intersection_strategy(intersection_strategy)
|
||||
, m_robust_policy(robust_policy)
|
||||
@@ -103,12 +112,14 @@ struct traversal_ring_creator
|
||||
{
|
||||
geometry::copy_segments<Reverse1>(m_geometry1,
|
||||
previous_op.seg_id, to_vertex_index,
|
||||
m_intersection_strategy.get_side_strategy(),
|
||||
m_robust_policy, current_ring);
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry::copy_segments<Reverse2>(m_geometry2,
|
||||
previous_op.seg_id, to_vertex_index,
|
||||
m_intersection_strategy.get_side_strategy(),
|
||||
m_robust_policy, current_ring);
|
||||
}
|
||||
}
|
||||
@@ -152,6 +163,7 @@ struct traversal_ring_creator
|
||||
turn_type& current_turn = m_turns[turn_index];
|
||||
turn_operation_type& op = current_turn.operations[op_index];
|
||||
detail::overlay::append_no_dups_or_spikes(current_ring, current_turn.point,
|
||||
m_intersection_strategy.get_side_strategy(),
|
||||
m_robust_policy);
|
||||
|
||||
// Register the visit
|
||||
@@ -169,6 +181,7 @@ struct traversal_ring_creator
|
||||
turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index];
|
||||
|
||||
detail::overlay::append_no_dups_or_spikes(ring, start_turn.point,
|
||||
m_intersection_strategy.get_side_strategy(),
|
||||
m_robust_policy);
|
||||
|
||||
signed_size_type current_turn_index = start_turn_index;
|
||||
@@ -193,7 +206,7 @@ struct traversal_ring_creator
|
||||
return traverse_error_none;
|
||||
}
|
||||
|
||||
if (start_turn.cluster_id >= 0)
|
||||
if (start_turn.is_clustered())
|
||||
{
|
||||
turn_type const& turn = m_turns[current_turn_index];
|
||||
if (turn.cluster_id == start_turn.cluster_id)
|
||||
@@ -271,10 +284,12 @@ struct traversal_ring_creator
|
||||
|
||||
if (geometry::num_points(ring) >= min_num_points)
|
||||
{
|
||||
clean_closing_dups_and_spikes(ring, m_robust_policy);
|
||||
clean_closing_dups_and_spikes(ring,
|
||||
m_intersection_strategy.get_side_strategy(),
|
||||
m_robust_policy);
|
||||
rings.push_back(ring);
|
||||
|
||||
m_trav.finalize_visit_info();
|
||||
m_trav.finalize_visit_info(m_turn_info_map);
|
||||
finalized_ring_size++;
|
||||
}
|
||||
}
|
||||
@@ -335,6 +350,7 @@ private:
|
||||
Geometry1 const& m_geometry1;
|
||||
Geometry2 const& m_geometry2;
|
||||
Turns& m_turns;
|
||||
TurnInfoMap& m_turn_info_map; // contains turn-info information per ring
|
||||
Clusters const& m_clusters;
|
||||
IntersectionStrategy const& m_intersection_strategy;
|
||||
RobustPolicy const& m_robust_policy;
|
||||
|
||||
@@ -48,17 +48,24 @@ template
|
||||
>
|
||||
struct traversal_switch_detector
|
||||
{
|
||||
enum isolation_type { isolation_unknown = -1, isolation_no = 0, isolation_yes = 1 };
|
||||
enum isolation_type
|
||||
{
|
||||
isolation_unknown = -1,
|
||||
isolation_no = 0,
|
||||
isolation_yes = 1,
|
||||
isolation_multiple = 2
|
||||
};
|
||||
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
typedef typename turn_type::turn_operation_type turn_operation_type;
|
||||
typedef std::set<signed_size_type> set_type;
|
||||
|
||||
// Per ring, first turns are collected (in turn_indices), and later
|
||||
// a region_id is assigned
|
||||
struct merged_ring_properties
|
||||
{
|
||||
signed_size_type region_id;
|
||||
std::set<signed_size_type> turn_indices;
|
||||
set_type turn_indices;
|
||||
|
||||
merged_ring_properties()
|
||||
: region_id(-1)
|
||||
@@ -68,7 +75,8 @@ struct traversal_switch_detector
|
||||
struct connection_properties
|
||||
{
|
||||
std::size_t count;
|
||||
std::set<signed_size_type> cluster_indices;
|
||||
// Contains turn-index OR, if clustered, minus-cluster_id
|
||||
set_type unique_turn_ids;
|
||||
connection_properties()
|
||||
: count(0)
|
||||
{}
|
||||
@@ -82,6 +90,7 @@ struct traversal_switch_detector
|
||||
{
|
||||
signed_size_type region_id;
|
||||
isolation_type isolated;
|
||||
set_type unique_turn_ids;
|
||||
|
||||
// Maps from connected region_id to their properties
|
||||
connection_map connected_region_counts;
|
||||
@@ -96,7 +105,7 @@ struct traversal_switch_detector
|
||||
typedef std::map<ring_identifier, merged_ring_properties > merge_map;
|
||||
typedef std::map<signed_size_type, region_properties> region_connection_map;
|
||||
|
||||
typedef std::set<signed_size_type>::const_iterator set_iterator;
|
||||
typedef set_type::const_iterator set_iterator;
|
||||
|
||||
inline traversal_switch_detector(Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
Turns& turns, Clusters& clusters,
|
||||
@@ -110,111 +119,232 @@ struct traversal_switch_detector
|
||||
{
|
||||
}
|
||||
|
||||
isolation_type get_isolation(region_properties const& properties,
|
||||
signed_size_type parent_region_id,
|
||||
const std::set<signed_size_type>& visited)
|
||||
bool inspect_difference(set_type& turn_id_difference,
|
||||
set_type const& turn_ids,
|
||||
set_type const& other_turn_ids) const
|
||||
{
|
||||
if (properties.isolated != isolation_unknown)
|
||||
// TODO: consider if std::set_difference can be used in the final version
|
||||
int const turn_count = turn_ids.size();
|
||||
int const other_turn_count = other_turn_ids.size();
|
||||
|
||||
// First quick check on size (TODO: implement multiple-multiple connections)
|
||||
if (turn_count - other_turn_count > 1)
|
||||
{
|
||||
return properties.isolated;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool all_colocated = true;
|
||||
int unique_cluster_id = -1;
|
||||
for (typename connection_map::const_iterator it = properties.connected_region_counts.begin();
|
||||
all_colocated && it != properties.connected_region_counts.end(); ++it)
|
||||
// Check if all turns are also present in the connection.
|
||||
// The difference is returned
|
||||
for (set_iterator it = turn_ids.begin(); it != turn_ids.end(); ++it)
|
||||
{
|
||||
signed_size_type const& id = *it;
|
||||
if (other_turn_ids.count(id) == 0)
|
||||
{
|
||||
turn_id_difference.insert(id);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool one_connection_to_another_region(region_properties const& region) const
|
||||
{
|
||||
// For example:
|
||||
// +----------------------+
|
||||
// | __ |
|
||||
// | / \|
|
||||
// | | x
|
||||
// | \__/|
|
||||
// | |
|
||||
// +----------------------+
|
||||
|
||||
if (region.connected_region_counts.size() == 1)
|
||||
{
|
||||
connection_properties const& cprop = region.connected_region_counts.begin()->second;
|
||||
return cprop.count <= 1;
|
||||
}
|
||||
return region.connected_region_counts.empty();
|
||||
}
|
||||
|
||||
// TODO: might be combined with previous
|
||||
bool multiple_connections_to_one_region(region_properties const& region) const
|
||||
{
|
||||
// For example:
|
||||
// +----------------------+
|
||||
// | __ |
|
||||
// | / \|
|
||||
// | | x
|
||||
// | \ /|
|
||||
// | / \|
|
||||
// | | x
|
||||
// | \__/|
|
||||
// | |
|
||||
// +----------------------+
|
||||
|
||||
if (region.connected_region_counts.size() == 1)
|
||||
{
|
||||
connection_properties const& cprop = region.connected_region_counts.begin()->second;
|
||||
return cprop.count > 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool one_connection_to_multiple_regions(region_properties const& region) const
|
||||
{
|
||||
// For example:
|
||||
// +----------------------+
|
||||
// | __ | __
|
||||
// | / \|/ |
|
||||
// | | x |
|
||||
// | \__/|\__|
|
||||
// | |
|
||||
// +----------------------+
|
||||
|
||||
bool first = true;
|
||||
signed_size_type first_turn_id = 0;
|
||||
for (typename connection_map::const_iterator it = region.connected_region_counts.begin();
|
||||
it != region.connected_region_counts.end(); ++it)
|
||||
{
|
||||
connection_properties const& cprop = it->second;
|
||||
if (cprop.cluster_indices.size() != 1)
|
||||
|
||||
if (cprop.count != 1)
|
||||
{
|
||||
// Either no cluster (non colocated point), or more clusters
|
||||
all_colocated = false;
|
||||
return false;
|
||||
}
|
||||
int const cluster_id = *cprop.cluster_indices.begin();
|
||||
if (cluster_id == -1)
|
||||
signed_size_type const unique_turn_id = *cprop.unique_turn_ids.begin();
|
||||
if (first)
|
||||
{
|
||||
all_colocated = false;
|
||||
first_turn_id = unique_turn_id;
|
||||
first = false;
|
||||
}
|
||||
else if (unique_cluster_id == -1)
|
||||
else if (first_turn_id != unique_turn_id)
|
||||
{
|
||||
unique_cluster_id = cluster_id;
|
||||
}
|
||||
else if (unique_cluster_id != cluster_id)
|
||||
{
|
||||
all_colocated = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (all_colocated)
|
||||
{
|
||||
return isolation_yes;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool has_only_isolated_children(region_properties const& region) const
|
||||
{
|
||||
bool first_with_turn = true;
|
||||
bool first_with_multiple = true;
|
||||
signed_size_type first_turn_id = 0;
|
||||
signed_size_type first_multiple_region_id = 0;
|
||||
|
||||
// It is isolated if there is only one connection, or if there are more connections but all
|
||||
// of them are isolated themselves, or if there are more connections
|
||||
// but they are all colocated
|
||||
std::size_t non_isolation_count = 0;
|
||||
bool child_not_isolated = false;
|
||||
for (typename connection_map::const_iterator it = properties.connected_region_counts.begin();
|
||||
it != properties.connected_region_counts.end(); ++it)
|
||||
for (typename connection_map::const_iterator it = region.connected_region_counts.begin();
|
||||
it != region.connected_region_counts.end(); ++it)
|
||||
{
|
||||
signed_size_type const region_id = it->first;
|
||||
connection_properties const& cprop = it->second;
|
||||
|
||||
if (region_id == parent_region_id)
|
||||
{
|
||||
// Normal situation, skip its direct parent
|
||||
continue;
|
||||
}
|
||||
if (visited.count(region_id) > 0)
|
||||
{
|
||||
// Find one of its ancestors again, this is a ring. Not isolated.
|
||||
return isolation_no;
|
||||
}
|
||||
if (cprop.count > 1)
|
||||
{
|
||||
return isolation_no;
|
||||
}
|
||||
|
||||
typename region_connection_map::iterator mit = m_connected_regions.find(region_id);
|
||||
typename region_connection_map::const_iterator mit = m_connected_regions.find(region_id);
|
||||
if (mit == m_connected_regions.end())
|
||||
{
|
||||
// Should not occur
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<signed_size_type> vis = visited;
|
||||
vis.insert(parent_region_id);
|
||||
region_properties const& connected_region = mit->second;
|
||||
|
||||
region_properties& prop = mit->second;
|
||||
if (prop.isolated == isolation_unknown)
|
||||
bool const multiple = connected_region.isolated == isolation_multiple;
|
||||
|
||||
if (cprop.count != 1)
|
||||
{
|
||||
isolation_type const iso = get_isolation(prop, properties.region_id, vis);
|
||||
prop.isolated = iso;
|
||||
if (iso == isolation_no)
|
||||
if (! multiple)
|
||||
{
|
||||
child_not_isolated = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// It connects multiple times to an isolated region.
|
||||
// This is allowed as long as it happens only once
|
||||
if (first_with_multiple)
|
||||
{
|
||||
first_multiple_region_id = connected_region.region_id;
|
||||
first_with_multiple = false;
|
||||
}
|
||||
else if (first_multiple_region_id != connected_region.region_id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Turns in region should be either present in the connection,
|
||||
// of form part of the connection with the other region
|
||||
set_type diff;
|
||||
if (! inspect_difference(diff, region.unique_turn_ids,
|
||||
connected_region.unique_turn_ids))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (diff.size() > 1)
|
||||
{
|
||||
// For now:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (prop.isolated == isolation_no)
|
||||
|
||||
if (connected_region.isolated != isolation_yes && ! multiple)
|
||||
{
|
||||
non_isolation_count++;
|
||||
signed_size_type const unique_turn_id = *cprop.unique_turn_ids.begin();
|
||||
if (first_with_turn)
|
||||
{
|
||||
first_turn_id = unique_turn_id;
|
||||
first_with_turn = false;
|
||||
}
|
||||
else if (first_turn_id != unique_turn_id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return child_not_isolated || non_isolation_count > 1 ? isolation_no : isolation_yes;
|
||||
// If there is only one connection (with a 'parent'), and all other
|
||||
// connections are itself isolated, it is isolated
|
||||
return true;
|
||||
}
|
||||
|
||||
void get_isolated_regions()
|
||||
{
|
||||
for (typename region_connection_map::iterator it = m_connected_regions.begin();
|
||||
typedef typename region_connection_map::iterator it_type;
|
||||
|
||||
// First time: check regions isolated (one connection only),
|
||||
// semi-isolated (multiple connections between same region),
|
||||
// and complex isolated (connection with multiple rings but all
|
||||
// at same point)
|
||||
for (it_type it = m_connected_regions.begin();
|
||||
it != m_connected_regions.end(); ++it)
|
||||
{
|
||||
region_properties& properties = it->second;
|
||||
if (properties.isolated == isolation_unknown)
|
||||
if (one_connection_to_another_region(properties))
|
||||
{
|
||||
std::set<signed_size_type> visited;
|
||||
properties.isolated = get_isolation(properties, properties.region_id, visited);
|
||||
properties.isolated = isolation_yes;
|
||||
}
|
||||
else if (multiple_connections_to_one_region(properties))
|
||||
{
|
||||
properties.isolated = isolation_multiple;
|
||||
}
|
||||
else if (one_connection_to_multiple_regions(properties))
|
||||
{
|
||||
properties.isolated = isolation_yes;
|
||||
}
|
||||
}
|
||||
|
||||
// Propagate isolation to next level
|
||||
// TODO: should be optimized
|
||||
std::size_t defensive_check = 0;
|
||||
bool changed = true;
|
||||
while (changed && defensive_check++ < m_connected_regions.size())
|
||||
{
|
||||
changed = false;
|
||||
for (it_type it = m_connected_regions.begin();
|
||||
it != m_connected_regions.end(); ++it)
|
||||
{
|
||||
region_properties& properties = it->second;
|
||||
|
||||
if (properties.isolated == isolation_unknown
|
||||
&& has_only_isolated_children(properties))
|
||||
{
|
||||
properties.isolated = isolation_yes;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -238,7 +368,7 @@ struct traversal_switch_detector
|
||||
}
|
||||
}
|
||||
|
||||
void assign_regions()
|
||||
void assign_region_ids()
|
||||
{
|
||||
for (typename merge_map::const_iterator it
|
||||
= m_turns_per_ring.begin(); it != m_turns_per_ring.end(); ++it)
|
||||
@@ -259,39 +389,53 @@ struct traversal_switch_detector
|
||||
op.enriched.region_id = properties.region_id;
|
||||
}
|
||||
}
|
||||
signed_size_type const& id0 = turn.operations[0].enriched.region_id;
|
||||
signed_size_type const& id1 = turn.operations[1].enriched.region_id;
|
||||
if (id0 != id1 && id0 != -1 && id1 != -1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assign_connected_regions()
|
||||
{
|
||||
for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
|
||||
{
|
||||
turn_type const& turn = m_turns[turn_index];
|
||||
|
||||
signed_size_type const unique_turn_id
|
||||
= turn.is_clustered() ? -turn.cluster_id : turn_index;
|
||||
|
||||
turn_operation_type op0 = turn.operations[0];
|
||||
turn_operation_type op1 = turn.operations[1];
|
||||
|
||||
signed_size_type const& id0 = op0.enriched.region_id;
|
||||
signed_size_type const& id1 = op1.enriched.region_id;
|
||||
|
||||
// Add region (by assigning) and add involved turns
|
||||
if (id0 != -1)
|
||||
{
|
||||
m_connected_regions[id0].region_id = id0;
|
||||
m_connected_regions[id0].unique_turn_ids.insert(unique_turn_id);
|
||||
}
|
||||
if (id1 != -1 && id0 != id1)
|
||||
{
|
||||
m_connected_regions[id1].region_id = id1;
|
||||
m_connected_regions[id1].unique_turn_ids.insert(unique_turn_id);
|
||||
}
|
||||
|
||||
if (id0 != id1 && id0 != -1 && id1 != -1)
|
||||
{
|
||||
// Assign connections
|
||||
connection_properties& prop0 = m_connected_regions[id0].connected_region_counts[id1];
|
||||
connection_properties& prop1 = m_connected_regions[id1].connected_region_counts[id0];
|
||||
|
||||
// Reference this turn or cluster to later check uniqueness on ring
|
||||
if (prop0.unique_turn_ids.count(unique_turn_id) == 0)
|
||||
{
|
||||
// Force insertion
|
||||
m_connected_regions[id0].region_id = id0;
|
||||
m_connected_regions[id1].region_id = id1;
|
||||
|
||||
connection_properties& prop0 = m_connected_regions[id0].connected_region_counts[id1];
|
||||
connection_properties& prop1 = m_connected_regions[id1].connected_region_counts[id0];
|
||||
|
||||
if (turn.cluster_id < 0)
|
||||
{
|
||||
// Turn is not colocated, add reference to connection
|
||||
prop0.count++;
|
||||
prop1.count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Turn is colocated, only add region reference if it was not yet registered
|
||||
if (prop0.cluster_indices.count(turn.cluster_id) == 0)
|
||||
{
|
||||
prop0.count++;
|
||||
}
|
||||
if (prop1.cluster_indices.count(turn.cluster_id) == 0)
|
||||
{
|
||||
prop1.count++;
|
||||
}
|
||||
}
|
||||
// Insert cluster-id (also -1 is inserted - reinsertion of
|
||||
// same cluster id is OK)
|
||||
prop0.cluster_indices.insert(turn.cluster_id);
|
||||
prop1.cluster_indices.insert(turn.cluster_id);
|
||||
prop0.count++;
|
||||
prop0.unique_turn_ids.insert(unique_turn_id);
|
||||
}
|
||||
if (prop1.unique_turn_ids.count(unique_turn_id) == 0)
|
||||
{
|
||||
prop1.count++;
|
||||
prop1.unique_turn_ids.insert(unique_turn_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,7 +450,7 @@ struct traversal_switch_detector
|
||||
return false;
|
||||
}
|
||||
|
||||
if (turn.cluster_id == -1)
|
||||
if (! turn.is_clustered())
|
||||
{
|
||||
// If it is a uu/ii-turn (non clustered), it is never same region
|
||||
return ! (turn.both(operation_union) || turn.both(operation_intersection));
|
||||
@@ -320,39 +464,22 @@ struct traversal_switch_detector
|
||||
== turn.operations[1].enriched.zone;
|
||||
}
|
||||
|
||||
// If a cluster contains an ii/cc it is not same region (for intersection)
|
||||
typename Clusters::const_iterator it = m_clusters.find(turn.cluster_id);
|
||||
if (it == m_clusters.end())
|
||||
{
|
||||
// Should not occur
|
||||
return true;
|
||||
}
|
||||
|
||||
cluster_info const& cinfo = it->second;
|
||||
for (set_iterator sit = cinfo.turn_indices.begin();
|
||||
sit != cinfo.turn_indices.end(); ++sit)
|
||||
{
|
||||
turn_type const& cluster_turn = m_turns[*sit];
|
||||
if (cluster_turn.both(operation_union)
|
||||
|| cluster_turn.both(operation_intersection))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// It is the same region
|
||||
return false;
|
||||
// For an intersection, two regions connect if they are not ii
|
||||
// (ii-regions are isolated) or, in some cases, not iu (for example
|
||||
// when a multi-polygon is inside an interior ring and connecting it)
|
||||
return ! (turn.both(operation_intersection)
|
||||
|| turn.combination(operation_intersection, operation_union));
|
||||
}
|
||||
|
||||
|
||||
inline int get_region_id(turn_operation_type const& op) const
|
||||
inline signed_size_type get_region_id(turn_operation_type const& op) const
|
||||
{
|
||||
return op.enriched.region_id;
|
||||
}
|
||||
|
||||
|
||||
void create_region(signed_size_type& new_region_id, ring_identifier const& ring_id,
|
||||
merged_ring_properties& properties, int region_id = -1)
|
||||
merged_ring_properties& properties, signed_size_type region_id = -1)
|
||||
{
|
||||
if (properties.region_id > 0)
|
||||
{
|
||||
@@ -400,7 +527,7 @@ struct traversal_switch_detector
|
||||
}
|
||||
|
||||
void propagate_region(signed_size_type& new_region_id,
|
||||
ring_identifier const& ring_id, int region_id)
|
||||
ring_identifier const& ring_id, signed_size_type region_id)
|
||||
{
|
||||
typename merge_map::iterator it = m_turns_per_ring.find(ring_id);
|
||||
if (it != m_turns_per_ring.end())
|
||||
@@ -438,7 +565,7 @@ struct traversal_switch_detector
|
||||
}
|
||||
}
|
||||
|
||||
// All rings having turns are in the map. Now iterate them
|
||||
// All rings having turns are in turns/ring map. Process them.
|
||||
{
|
||||
signed_size_type new_region_id = 1;
|
||||
for (typename merge_map::iterator it
|
||||
@@ -447,7 +574,8 @@ struct traversal_switch_detector
|
||||
create_region(new_region_id, it->first, it->second);
|
||||
}
|
||||
|
||||
assign_regions();
|
||||
assign_region_ids();
|
||||
assign_connected_regions();
|
||||
get_isolated_regions();
|
||||
assign_isolation();
|
||||
}
|
||||
@@ -464,9 +592,8 @@ struct traversal_switch_detector
|
||||
}
|
||||
|
||||
// A touching cluster, gather regions
|
||||
std::set<int> regions;
|
||||
|
||||
std::set<signed_size_type> const& ids = cinfo.turn_indices;
|
||||
set_type regions;
|
||||
set_type const& ids = cinfo.turn_indices;
|
||||
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
|
||||
std::cout << "SWITCH EXAMINE CLUSTER " << it->first << std::endl;
|
||||
@@ -476,14 +603,10 @@ struct traversal_switch_detector
|
||||
{
|
||||
signed_size_type turn_index = *sit;
|
||||
turn_type const& turn = m_turns[turn_index];
|
||||
if (turn.colocated_ii && ! turn.colocated_uu)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (int oi = 0; oi < 2; oi++)
|
||||
{
|
||||
int const region = get_region_id(turn.operations[oi]);
|
||||
regions.insert(region);
|
||||
signed_size_type const region_id = get_region_id(turn.operations[oi]);
|
||||
regions.insert(region_id);
|
||||
}
|
||||
}
|
||||
// Switch source if this cluster connects the same region
|
||||
@@ -497,7 +620,7 @@ struct traversal_switch_detector
|
||||
|
||||
if (turn.discarded
|
||||
|| turn.blocked()
|
||||
|| turn.cluster_id >= 0
|
||||
|| turn.is_clustered()
|
||||
|| ! (turn.both(operation_union) || turn.both(operation_intersection)))
|
||||
{
|
||||
// Skip discarded, blocked, non-uu/ii and clustered turns
|
||||
@@ -513,8 +636,8 @@ struct traversal_switch_detector
|
||||
continue;
|
||||
}
|
||||
|
||||
int const region0 = get_region_id(turn.operations[0]);
|
||||
int const region1 = get_region_id(turn.operations[1]);
|
||||
signed_size_type const region0 = get_region_id(turn.operations[0]);
|
||||
signed_size_type const region1 = get_region_id(turn.operations[1]);
|
||||
|
||||
// Switch sources for same region
|
||||
turn.switch_source = region0 == region1;
|
||||
@@ -529,7 +652,7 @@ struct traversal_switch_detector
|
||||
turn_type const& turn = m_turns[turn_index];
|
||||
|
||||
if ((turn.both(operation_union) || turn.both(operation_intersection))
|
||||
&& turn.cluster_id < 0)
|
||||
&& ! turn.is_clustered())
|
||||
{
|
||||
std::cout << "UU/II SWITCH RESULT "
|
||||
<< turn_index << " -> "
|
||||
|
||||
@@ -62,14 +62,16 @@ public :
|
||||
typename RobustPolicy,
|
||||
typename Turns,
|
||||
typename Rings,
|
||||
typename Visitor,
|
||||
typename Clusters
|
||||
typename TurnInfoMap,
|
||||
typename Clusters,
|
||||
typename Visitor
|
||||
>
|
||||
static inline void apply(Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
IntersectionStrategy const& intersection_strategy,
|
||||
RobustPolicy const& robust_policy,
|
||||
Turns& turns, Rings& rings,
|
||||
TurnInfoMap& turn_info_map,
|
||||
Clusters& clusters,
|
||||
Visitor& visitor)
|
||||
{
|
||||
@@ -89,11 +91,11 @@ public :
|
||||
<
|
||||
Reverse1, Reverse2, OverlayType,
|
||||
Geometry1, Geometry2,
|
||||
Turns, Clusters,
|
||||
Turns, TurnInfoMap, Clusters,
|
||||
IntersectionStrategy,
|
||||
RobustPolicy, Visitor,
|
||||
Backtrack
|
||||
> trav(geometry1, geometry2, turns, clusters,
|
||||
> trav(geometry1, geometry2, turns, turn_info_map, clusters,
|
||||
intersection_strategy, robust_policy, visitor);
|
||||
|
||||
std::size_t finalized_ring_size = boost::size(rings);
|
||||
|
||||
@@ -89,22 +89,21 @@ struct turn_info
|
||||
|
||||
Point point;
|
||||
method_type method;
|
||||
signed_size_type cluster_id; // For multiple turns on same location, >= 0. Else -1
|
||||
bool touch_only; // True in case of method touch(interior) and lines do not cross
|
||||
signed_size_type cluster_id; // For multiple turns on same location, > 0. Else -1. 0 is unused.
|
||||
bool discarded;
|
||||
|
||||
// TODO: move this to enriched
|
||||
bool colocated_ii; // Colocated with a ii turn (TODO: or a ix turn)
|
||||
bool colocated_uu; // Colocated with a uu turn or a ux turn
|
||||
bool has_colocated_both; // Colocated with a uu turn (for union) or ii (other)
|
||||
bool switch_source; // For u/u turns which can either switch or not
|
||||
|
||||
Container operations;
|
||||
|
||||
inline turn_info()
|
||||
: method(method_none)
|
||||
, touch_only(false)
|
||||
, cluster_id(-1)
|
||||
, discarded(false)
|
||||
, colocated_ii(false)
|
||||
, colocated_uu(false)
|
||||
, has_colocated_both(false)
|
||||
, switch_source(false)
|
||||
{}
|
||||
|
||||
@@ -136,6 +135,10 @@ struct turn_info
|
||||
{
|
||||
return has(operation_blocked);
|
||||
}
|
||||
inline bool is_clustered() const
|
||||
{
|
||||
return cluster_id > 0;
|
||||
}
|
||||
|
||||
private :
|
||||
inline bool has12(operation_type type1, operation_type type2) const
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// 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
|
||||
@@ -19,11 +20,13 @@
|
||||
|
||||
#include <boost/geometry/algorithms/detail/direction_code.hpp>
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -32,6 +35,26 @@ namespace boost { namespace geometry
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Point1, typename Point2, typename Point3>
|
||||
inline bool collinear_point_is_spike_or_equal(Point1 const& last_point,
|
||||
Point2 const& segment_a,
|
||||
Point3 const& segment_b)
|
||||
{
|
||||
// Check if segment is equal
|
||||
int const sgn_x1 = sign_of_difference<0>(last_point, segment_b);
|
||||
int const sgn_y1 = sign_of_difference<1>(last_point, segment_b);
|
||||
if (sgn_x1 == 0 && sgn_y1 == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if segment moves forward
|
||||
int const sgn_x2 = sign_of_difference<0>(segment_b, segment_a);
|
||||
int const sgn_y2 = sign_of_difference<1>(segment_b, segment_a);
|
||||
|
||||
return sgn_x1 != sgn_x2 || sgn_y1 != sgn_y2;
|
||||
}
|
||||
|
||||
// Checks if a point ("last_point") causes a spike w.r.t.
|
||||
// the specified two other points (segment_a, segment_b)
|
||||
//
|
||||
@@ -42,33 +65,29 @@ namespace detail
|
||||
// So specify last point first, then (a,b)
|
||||
// The segment's orientation does matter: if lp is to the right of b
|
||||
// no spike is reported
|
||||
template <typename Point1, typename Point2, typename Point3>
|
||||
static inline bool point_is_spike_or_equal(Point1 const& last_point,
|
||||
Point2 const& segment_a,
|
||||
Point3 const& segment_b)
|
||||
template
|
||||
<
|
||||
typename Point1, typename Point2, typename Point3,
|
||||
typename SideStrategy
|
||||
>
|
||||
static inline bool point_is_spike_or_equal(Point1 const& last_point, // prev | back
|
||||
Point2 const& segment_a, // next | back - 2
|
||||
Point3 const& segment_b, // curr | back - 1 | spike's vertex
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point1>::type
|
||||
>::type side_strategy;
|
||||
|
||||
int const side = side_strategy::apply(last_point, segment_a, segment_b);
|
||||
int const side = strategy.apply(segment_a, segment_b, last_point);
|
||||
if (side == 0)
|
||||
{
|
||||
// Last point is collinear w.r.t previous segment.
|
||||
// Check if it is equal
|
||||
int const sgn_x1 = sign_of_difference<0>(last_point, segment_b);
|
||||
int const sgn_y1 = sign_of_difference<1>(last_point, segment_b);
|
||||
if (sgn_x1 == 0 && sgn_y1 == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if it moves forward
|
||||
int const sgn_x2 = sign_of_difference<0>(segment_b, segment_a);
|
||||
int const sgn_y2 = sign_of_difference<1>(segment_b, segment_a);
|
||||
|
||||
return sgn_x1 != sgn_x2 || sgn_y1 != sgn_y2;
|
||||
#ifdef BOOST_GEOMETRY_ENABLE_POINT_IS_SPIKE_OR_EQUAL_TEST
|
||||
bool r1 = collinear_point_is_spike_or_equal(last_point, segment_a, segment_b);
|
||||
bool r2 = direction_code(segment_a, segment_b, last_point) < 1;
|
||||
if (r1 != r2)
|
||||
std::cout << "spike detection failure with: " << r1 << " " << r2 << std::endl;
|
||||
return r2;
|
||||
#else
|
||||
return direction_code(segment_a, segment_b, last_point) < 1;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -78,14 +97,16 @@ template
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename Point3,
|
||||
typename SideStrategy,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool point_is_spike_or_equal(Point1 const& last_point,
|
||||
Point2 const& segment_a,
|
||||
Point3 const& segment_b,
|
||||
SideStrategy const& strategy,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
if (point_is_spike_or_equal(last_point, segment_a, segment_b))
|
||||
if (point_is_spike_or_equal(last_point, segment_a, segment_b, strategy))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -111,7 +132,8 @@ static inline bool point_is_spike_or_equal(Point1 const& last_point,
|
||||
(
|
||||
last_point_rob,
|
||||
segment_a_rob,
|
||||
segment_b_rob
|
||||
segment_b_rob,
|
||||
strategy
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,43 +84,49 @@ struct midpoint_helper<Point, DimensionCount, DimensionCount>
|
||||
template <bool Midpoint>
|
||||
struct point_on_range
|
||||
{
|
||||
// Version with iterator
|
||||
template<typename Point, typename Iterator>
|
||||
static inline bool apply(Point& point, Iterator begin, Iterator end)
|
||||
{
|
||||
Iterator it = begin;
|
||||
if (it == end)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! Midpoint)
|
||||
{
|
||||
geometry::detail::conversion::convert_point_to_point(*it, point);
|
||||
return true;
|
||||
}
|
||||
|
||||
Iterator prev = it++;
|
||||
|
||||
// Go to next non-duplicate point
|
||||
while (it != end
|
||||
&& detail::equals::equals_point_point(*it, *prev))
|
||||
{
|
||||
prev = it++;
|
||||
}
|
||||
if (it != end)
|
||||
{
|
||||
return midpoint_helper
|
||||
<
|
||||
Point,
|
||||
0, dimension<Point>::value
|
||||
>::apply(point, *prev, *it);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Version with range
|
||||
template<typename Point, typename Range>
|
||||
static inline bool apply(Point& point, Range const& range)
|
||||
{
|
||||
typedef typename geometry::cs_tag<Point>::type cs_tag;
|
||||
BOOST_STATIC_ASSERT((! Midpoint || boost::is_same<cs_tag, cartesian_tag>::value));
|
||||
|
||||
const std::size_t n = boost::size(range);
|
||||
if (Midpoint && n > 1)
|
||||
{
|
||||
typedef typename boost::range_iterator
|
||||
<
|
||||
Range const
|
||||
>::type iterator;
|
||||
|
||||
iterator it = boost::begin(range);
|
||||
iterator prev = it++;
|
||||
while (it != boost::end(range)
|
||||
&& detail::equals::equals_point_point(*it, *prev))
|
||||
{
|
||||
prev = it++;
|
||||
}
|
||||
if (it != boost::end(range))
|
||||
{
|
||||
return midpoint_helper
|
||||
<
|
||||
Point,
|
||||
0, dimension<Point>::value
|
||||
>::apply(point, *prev, *it);
|
||||
}
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
geometry::detail::conversion::convert_point_to_point(*boost::begin(range), point);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return apply(point, boost::begin(range), boost::end(range));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// 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.
|
||||
|
||||
// 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)
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace detail_dispatch { namespace relate {
|
||||
|
||||
// TODO: Integrate it with geometry::less?
|
||||
|
||||
template <typename Point1,
|
||||
typename Point2,
|
||||
std::size_t I = 0,
|
||||
std::size_t D = geometry::dimension<Point1>::value>
|
||||
struct less
|
||||
{
|
||||
static inline bool apply(Point1 const& left, Point2 const& right)
|
||||
{
|
||||
typename geometry::coordinate_type<Point1>::type
|
||||
cleft = geometry::get<I>(left);
|
||||
typename geometry::coordinate_type<Point2>::type
|
||||
cright = geometry::get<I>(right);
|
||||
|
||||
if ( geometry::math::equals(cleft, cright) )
|
||||
{
|
||||
return less<Point1, Point2, I + 1, D>::apply(left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
return cleft < cright;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Point1, typename Point2, std::size_t D>
|
||||
struct less<Point1, Point2, D, D>
|
||||
{
|
||||
static inline bool apply(Point1 const&, Point2 const&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail_dispatch::relate
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace relate {
|
||||
|
||||
struct less
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
inline bool operator()(Point1 const& point1, Point2 const& point2) const
|
||||
{
|
||||
return detail_dispatch::relate::less<Point1, Point2>::apply(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::relate
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
|
||||
@@ -260,17 +260,19 @@ struct linear_areal
|
||||
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
|
||||
return;
|
||||
|
||||
typedef typename IntersectionStrategy::template point_in_geometry_strategy<Geometry1, Geometry2>::type within_strategy_type;
|
||||
within_strategy_type const within_strategy = intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>();
|
||||
boundary_checker<Geometry1> boundary_checker1(geometry1);
|
||||
no_turns_la_linestring_pred
|
||||
<
|
||||
Geometry2,
|
||||
Result,
|
||||
typename IntersectionStrategy::template point_in_geometry_strategy<Geometry1, Geometry2>::type,
|
||||
within_strategy_type,
|
||||
boundary_checker<Geometry1>,
|
||||
TransposeResult
|
||||
> pred1(geometry2,
|
||||
result,
|
||||
intersection_strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>(),
|
||||
within_strategy,
|
||||
boundary_checker1);
|
||||
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
|
||||
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
|
||||
|
||||
@@ -121,7 +121,7 @@ struct multi_point_geometry_eb<Geometry, multi_linestring_tag>
|
||||
template <typename Point>
|
||||
bool apply(Point const& boundary_point)
|
||||
{
|
||||
if (! std::binary_search(m_points.begin(), m_points.end(), boundary_point, relate::less()))
|
||||
if (! std::binary_search(m_points.begin(), m_points.end(), boundary_point, geometry::less<>()))
|
||||
{
|
||||
m_boundary_found = true;
|
||||
return false;
|
||||
@@ -143,7 +143,7 @@ struct multi_point_geometry_eb<Geometry, multi_linestring_tag>
|
||||
typedef typename boost::range_value<MultiPoint>::type point_type;
|
||||
typedef std::vector<point_type> points_type;
|
||||
points_type points(boost::begin(multi_point), boost::end(multi_point));
|
||||
std::sort(points.begin(), points.end(), relate::less());
|
||||
std::sort(points.begin(), points.end(), geometry::less<>());
|
||||
|
||||
boundary_visitor<points_type> visitor(points);
|
||||
tc.for_each_boundary_point(visitor);
|
||||
|
||||
@@ -21,9 +21,10 @@
|
||||
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/less.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/result.hpp>
|
||||
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -213,7 +214,9 @@ struct multipoint_multipoint
|
||||
// sort points from the 1 MPt
|
||||
typedef typename geometry::point_type<SortedMultiPoint>::type point_type;
|
||||
std::vector<point_type> points(boost::begin(sorted_mpt), boost::end(sorted_mpt));
|
||||
std::sort(points.begin(), points.end(), less());
|
||||
|
||||
geometry::less<> const less = geometry::less<>();
|
||||
std::sort(points.begin(), points.end(), less);
|
||||
|
||||
bool found_inside = false;
|
||||
bool found_outside = false;
|
||||
@@ -224,7 +227,7 @@ struct multipoint_multipoint
|
||||
it != boost::end(iterated_mpt) ; ++it )
|
||||
{
|
||||
bool ii =
|
||||
std::binary_search(points.begin(), points.end(), *it, less());
|
||||
std::binary_search(points.begin(), points.end(), *it, less);
|
||||
if ( ii )
|
||||
found_inside = true;
|
||||
else
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
|
||||
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/less.hpp>
|
||||
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
#include <boost/geometry/util/has_nan_coordinate.hpp>
|
||||
#include <boost/geometry/util/range.hpp>
|
||||
@@ -165,6 +166,8 @@ private:
|
||||
|
||||
m_endpoints.reserve(boost::size(m_mls) * 2);
|
||||
|
||||
m_has_interior = false;
|
||||
|
||||
typedef typename boost::range_iterator<MultiLinestring const>::type ls_iterator;
|
||||
for ( ls_iterator it = boost::begin(m_mls) ; it != boost::end(m_mls) ; ++it )
|
||||
{
|
||||
@@ -212,7 +215,7 @@ private:
|
||||
|
||||
if (! m_endpoints.empty() )
|
||||
{
|
||||
std::sort(m_endpoints.begin(), m_endpoints.end(), relate::less());
|
||||
std::sort(m_endpoints.begin(), m_endpoints.end(), geometry::less<>());
|
||||
m_has_boundary = find_odd_count(m_endpoints.begin(), m_endpoints.end());
|
||||
}
|
||||
|
||||
@@ -222,7 +225,7 @@ private:
|
||||
template <typename It, typename Point>
|
||||
static inline std::size_t count_equal(It first, It last, Point const& point)
|
||||
{
|
||||
std::pair<It, It> rng = std::equal_range(first, last, point, relate::less());
|
||||
std::pair<It, It> rng = std::equal_range(first, last, point, geometry::less<>());
|
||||
return (std::size_t)std::distance(rng.first, rng.second);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// 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 Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
#include <boost/geometry/algorithms/detail/recalculate.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
|
||||
// For spherical/geographic longitudes covered_by point/box
|
||||
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -27,6 +30,90 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace section
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Dimension,
|
||||
typename Geometry,
|
||||
typename CastedCSTag = typename tag_cast
|
||||
<
|
||||
typename cs_tag<Geometry>::type,
|
||||
spherical_tag
|
||||
>::type
|
||||
>
|
||||
struct preceding_check
|
||||
{
|
||||
template <typename Point, typename Box>
|
||||
static inline bool apply(int dir, Point const& point, Box const& /*point_box*/, Box const& other_box)
|
||||
{
|
||||
return (dir == 1 && get<Dimension>(point) < get<min_corner, Dimension>(other_box))
|
||||
|| (dir == -1 && get<Dimension>(point) > get<max_corner, Dimension>(other_box));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct preceding_check<0, Geometry, spherical_tag>
|
||||
{
|
||||
template <typename Point, typename Box>
|
||||
static inline bool apply(int dir, Point const& point, Box const& point_box, Box const& other_box)
|
||||
{
|
||||
typedef typename select_coordinate_type
|
||||
<
|
||||
Point, Box
|
||||
>::type calc_t;
|
||||
typedef typename coordinate_system<Point>::type::units units_t;
|
||||
|
||||
calc_t const c0 = 0;
|
||||
|
||||
calc_t const value = get<0>(point);
|
||||
calc_t const other_min = get<min_corner, 0>(other_box);
|
||||
calc_t const other_max = get<max_corner, 0>(other_box);
|
||||
|
||||
bool const pt_covered = strategy::within::covered_by_range
|
||||
<
|
||||
Point, 0, spherical_tag
|
||||
>::apply(value,
|
||||
other_min,
|
||||
other_max);
|
||||
|
||||
if (pt_covered)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dir == 1)
|
||||
{
|
||||
calc_t const diff_min = math::longitude_distance_signed
|
||||
<
|
||||
units_t, calc_t
|
||||
>(other_min, value);
|
||||
|
||||
calc_t const diff_min_min = math::longitude_distance_signed
|
||||
<
|
||||
units_t, calc_t
|
||||
>(other_min, get<min_corner, 0>(point_box));
|
||||
|
||||
return diff_min < c0 && diff_min_min <= c0 && diff_min_min <= diff_min;
|
||||
}
|
||||
else if (dir == -1)
|
||||
{
|
||||
calc_t const diff_max = math::longitude_distance_signed
|
||||
<
|
||||
units_t, calc_t
|
||||
>(other_max, value);
|
||||
|
||||
calc_t const diff_max_max = math::longitude_distance_signed
|
||||
<
|
||||
units_t, calc_t
|
||||
>(other_max, get<max_corner, 0>(point_box));
|
||||
|
||||
return diff_max > c0 && diff_max_max >= c0 && diff_max <= diff_max_max;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Dimension,
|
||||
@@ -34,14 +121,15 @@ template
|
||||
typename RobustBox,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool preceding(int dir, Point const& point,
|
||||
RobustBox const& robust_box,
|
||||
RobustPolicy const& robust_policy)
|
||||
static inline bool preceding(int dir,
|
||||
Point const& point,
|
||||
RobustBox const& point_robust_box,
|
||||
RobustBox const& other_robust_box,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
|
||||
geometry::recalculate(robust_point, point, robust_policy);
|
||||
return (dir == 1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box))
|
||||
|| (dir == -1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box));
|
||||
return preceding_check<Dimension, Point>::apply(dir, robust_point, point_robust_box, other_robust_box);
|
||||
}
|
||||
|
||||
template
|
||||
@@ -51,14 +139,13 @@ template
|
||||
typename RobustBox,
|
||||
typename RobustPolicy
|
||||
>
|
||||
static inline bool exceeding(int dir, Point const& point,
|
||||
RobustBox const& robust_box,
|
||||
RobustPolicy const& robust_policy)
|
||||
static inline bool exceeding(int dir,
|
||||
Point const& point,
|
||||
RobustBox const& point_robust_box,
|
||||
RobustBox const& other_robust_box,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
|
||||
geometry::recalculate(robust_point, point, robust_policy);
|
||||
return (dir == 1 && get<Dimension>(robust_point) > get<max_corner, Dimension>(robust_box))
|
||||
|| (dir == -1 && get<Dimension>(robust_point) < get<min_corner, Dimension>(robust_box));
|
||||
return preceding<Dimension>(-dir, point, point_robust_box, other_robust_box, robust_policy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2015.
|
||||
// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013, 2014, 2015, 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
|
||||
@@ -136,11 +136,21 @@ struct sections : std::vector<section<Box, DimensionCount> >
|
||||
namespace detail { namespace sectionalize
|
||||
{
|
||||
|
||||
// NOTE: This utility will NOT work for latitudes, dimension 1 in spherical
|
||||
// and geographic coordinate system because in these coordinate systems
|
||||
// e.g. a segment on northern hemisphere may go towards greater latitude
|
||||
// and then towards lesser latitude.
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename DimensionVector,
|
||||
std::size_t Index,
|
||||
std::size_t Count
|
||||
std::size_t Count,
|
||||
typename CastedCSTag = typename tag_cast
|
||||
<
|
||||
typename cs_tag<Point>::type,
|
||||
spherical_tag
|
||||
>::type
|
||||
>
|
||||
struct get_direction_loop
|
||||
{
|
||||
@@ -161,21 +171,67 @@ struct get_direction_loop
|
||||
|
||||
get_direction_loop
|
||||
<
|
||||
Point,
|
||||
DimensionVector,
|
||||
Index + 1,
|
||||
Count
|
||||
Count,
|
||||
CastedCSTag
|
||||
>::apply(seg, directions);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DimensionVector, std::size_t Count>
|
||||
struct get_direction_loop<DimensionVector, Count, Count>
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename DimensionVector,
|
||||
std::size_t Count
|
||||
>
|
||||
struct get_direction_loop<Point, DimensionVector, 0, Count, spherical_tag>
|
||||
{
|
||||
typedef typename boost::mpl::at_c<DimensionVector, 0>::type dimension;
|
||||
|
||||
template <typename Segment>
|
||||
static inline void apply(Segment const& seg,
|
||||
int directions[Count])
|
||||
{
|
||||
typedef typename coordinate_type<Segment>::type coordinate_type;
|
||||
typedef typename coordinate_system<Point>::type::units units_t;
|
||||
|
||||
coordinate_type const diff = math::longitude_distance_signed
|
||||
<
|
||||
units_t, coordinate_type
|
||||
>(geometry::get<0, 0>(seg),
|
||||
geometry::get<1, 0>(seg));
|
||||
|
||||
coordinate_type zero = coordinate_type();
|
||||
directions[0] = diff > zero ? 1 : diff < zero ? -1 : 0;
|
||||
|
||||
get_direction_loop
|
||||
<
|
||||
Point,
|
||||
DimensionVector,
|
||||
1,
|
||||
Count,
|
||||
spherical_tag
|
||||
>::apply(seg, directions);
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename DimensionVector,
|
||||
std::size_t Count,
|
||||
typename CastedCSTag
|
||||
>
|
||||
struct get_direction_loop<Point, DimensionVector, Count, Count, CastedCSTag>
|
||||
{
|
||||
template <typename Segment>
|
||||
static inline void apply(Segment const&, int [Count])
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
//! Copy one static array to another
|
||||
template <typename T, std::size_t Index, std::size_t Count>
|
||||
struct copy_loop
|
||||
@@ -410,7 +466,7 @@ struct sectionalize_part
|
||||
int direction_classes[dimension_count] = {0};
|
||||
get_direction_loop
|
||||
<
|
||||
DimensionVector, 0, dimension_count
|
||||
Point, DimensionVector, 0, dimension_count
|
||||
>::apply(robust_segment, direction_classes);
|
||||
|
||||
// if "dir" == 0 for all point-dimensions, it is duplicate.
|
||||
@@ -929,9 +985,12 @@ inline void sectionalize(Geometry const& geometry,
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type envelope_strategy_type;
|
||||
|
||||
sectionalize<Reverse, DimensionVector>(geometry, robust_policy, sections,
|
||||
envelope_strategy_type(),
|
||||
source_index, max_count);
|
||||
boost::geometry::sectionalize
|
||||
<
|
||||
Reverse, DimensionVector
|
||||
>(geometry, robust_policy, sections,
|
||||
envelope_strategy_type(),
|
||||
source_index, max_count);
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
@@ -413,7 +413,8 @@ struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false>
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
namespace resolve_variant {
|
||||
namespace resolve_variant
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct self_touches
|
||||
@@ -443,10 +444,11 @@ struct self_touches
|
||||
detail::touches::areal_interrupt_policy policy;
|
||||
strategy_type strategy;
|
||||
rescale_policy_type robust_policy;
|
||||
// TODO: skip_adjacent should be set to false
|
||||
detail::self_get_turn_points::get_turns
|
||||
<
|
||||
false, policy_type
|
||||
>::apply(geometry, strategy, robust_policy, turns, policy, 0);
|
||||
>::apply(geometry, strategy, robust_policy, turns, policy, 0, true);
|
||||
|
||||
return policy.result();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
|
||||
#include <boost/geometry/algorithms/detail/relate/less.hpp>
|
||||
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
#include <boost/geometry/algorithms/detail/partition.hpp>
|
||||
@@ -33,6 +32,8 @@
|
||||
|
||||
#include <boost/geometry/index/rtree.hpp>
|
||||
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/covered_by.hpp>
|
||||
#include <boost/geometry/strategies/disjoint.hpp>
|
||||
|
||||
@@ -63,7 +64,7 @@ struct multi_point_point
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: currently the strategy is ignored, math::equals() is used inside relate::less
|
||||
// NOTE: currently the strategy is ignored, math::equals() is used inside geometry::less<>
|
||||
struct multi_point_multi_point
|
||||
{
|
||||
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
|
||||
@@ -73,7 +74,7 @@ struct multi_point_multi_point
|
||||
{
|
||||
typedef typename boost::range_value<MultiPoint2>::type point2_type;
|
||||
|
||||
relate::less const less = relate::less();
|
||||
geometry::less<> const less = geometry::less<>();
|
||||
|
||||
std::vector<point2_type> points2(boost::begin(multi_point2), boost::end(multi_point2));
|
||||
std::sort(points2.begin(), points2.end(), less);
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
|
||||
// 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
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
@@ -39,8 +40,6 @@ namespace dispatch
|
||||
template
|
||||
<
|
||||
typename GeometryOut, typename Geometry,
|
||||
typename StrategyLess = strategy::compare::default_strategy,
|
||||
typename StrategyGreater = strategy::compare::default_strategy,
|
||||
typename TagOut = typename tag<GeometryOut>::type,
|
||||
typename Tag = typename tag<Geometry>::type,
|
||||
typename CSTagOut = typename cs_tag<GeometryOut>::type,
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
// Copyright (c) 2015 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)
|
||||
@@ -10,17 +15,23 @@
|
||||
#define BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP
|
||||
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/closure.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/views/detail/normalized_view.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -31,15 +42,9 @@ namespace detail { namespace is_convex
|
||||
|
||||
struct ring_is_convex
|
||||
{
|
||||
template <typename Ring>
|
||||
static inline bool apply(Ring const& ring)
|
||||
template <typename Ring, typename SideStrategy>
|
||||
static inline bool apply(Ring const& ring, SideStrategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::point_type<Ring>::type point_type;
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<point_type>::type
|
||||
>::type side_strategy_type;
|
||||
|
||||
std::size_t n = boost::size(ring);
|
||||
if (boost::size(ring) < core_detail::closure::minimum_ring_size
|
||||
<
|
||||
@@ -86,7 +91,7 @@ struct ring_is_convex
|
||||
// iterator
|
||||
for (std::size_t i = 0; i < n; i++)
|
||||
{
|
||||
int const side = side_strategy_type::apply(*previous, *current, *next);
|
||||
int const side = strategy.apply(*previous, *current, *next);
|
||||
if (side == 1)
|
||||
{
|
||||
// Next is on the left side of clockwise ring:
|
||||
@@ -129,7 +134,8 @@ struct is_convex : not_implemented<Tag>
|
||||
template <typename Box>
|
||||
struct is_convex<Box, box_tag>
|
||||
{
|
||||
static inline bool apply(Box const& )
|
||||
template <typename Strategy>
|
||||
static inline bool apply(Box const& , Strategy const& )
|
||||
{
|
||||
// Any box is convex (TODO: consider spherical boxes)
|
||||
return true;
|
||||
@@ -144,13 +150,71 @@ struct is_convex<Box, ring_tag> : detail::is_convex::ring_is_convex
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
// TODO: variants
|
||||
namespace resolve_variant {
|
||||
|
||||
template <typename Geometry>
|
||||
struct is_convex
|
||||
{
|
||||
template <typename Strategy>
|
||||
static bool apply(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
return dispatch::is_convex<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
static bool apply(Geometry const& geometry, geometry::default_strategy const&)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type side_strategy;
|
||||
|
||||
return apply(geometry, side_strategy());
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct is_convex<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename Strategy>
|
||||
struct visitor: boost::static_visitor<bool>
|
||||
{
|
||||
Strategy const& m_strategy;
|
||||
|
||||
visitor(Strategy const& strategy) : m_strategy(strategy) {}
|
||||
|
||||
template <typename Geometry>
|
||||
bool operator()(Geometry const& geometry) const
|
||||
{
|
||||
return is_convex<Geometry>::apply(geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Strategy>
|
||||
static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace resolve_variant
|
||||
|
||||
// TODO: documentation / qbk
|
||||
template<typename Geometry>
|
||||
inline bool is_convex(Geometry const& geometry)
|
||||
{
|
||||
return dispatch::is_convex<Geometry>::apply(geometry);
|
||||
return resolve_variant::is_convex
|
||||
<
|
||||
Geometry
|
||||
>::apply(geometry, geometry::default_strategy());
|
||||
}
|
||||
|
||||
// TODO: documentation / qbk
|
||||
template<typename Geometry, typename Strategy>
|
||||
inline bool is_convex(Geometry const& geometry, Strategy const& strategy)
|
||||
{
|
||||
return resolve_variant::is_convex<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013 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.
|
||||
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <boost/geometry/algorithms/detail/extreme_points.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -241,8 +242,9 @@ inline void replace_extremes_for_self_tangencies(Extremes& extremes, Intruders&
|
||||
extremes = triangle;
|
||||
}
|
||||
|
||||
template <int Dimension, typename Geometry, typename Point>
|
||||
inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)
|
||||
template <int Dimension, typename Geometry, typename Point, typename SideStrategy>
|
||||
inline bool calculate_point_on_surface(Geometry const& geometry, Point& point,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
||||
typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;
|
||||
@@ -250,7 +252,7 @@ inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)
|
||||
|
||||
typedef std::vector<std::vector<point_type> > intruders_type;
|
||||
intruders_type intruders;
|
||||
geometry::extreme_points<Dimension>(geometry, extremes, intruders);
|
||||
geometry::extreme_points<Dimension>(geometry, extremes, intruders, strategy);
|
||||
|
||||
if (extremes.size() < 3)
|
||||
{
|
||||
@@ -291,21 +293,57 @@ inline bool calculate_point_on_surface(Geometry const& geometry, Point& point)
|
||||
\tparam Geometry geometry type. This also defines the type of the output point
|
||||
\param geometry Geometry to take point from
|
||||
\param point Point to assign
|
||||
\param strategy side strategy
|
||||
*/
|
||||
template <typename Geometry, typename Point>
|
||||
inline void point_on_surface(Geometry const& geometry, Point & point)
|
||||
template <typename Geometry, typename Point, typename SideStrategy>
|
||||
inline void point_on_surface(Geometry const& geometry, Point & point,
|
||||
SideStrategy const& strategy)
|
||||
{
|
||||
concepts::check<Point>();
|
||||
concepts::check<Geometry const>();
|
||||
|
||||
// First try in Y-direction (which should always succeed for valid polygons)
|
||||
if (! detail::point_on_surface::calculate_point_on_surface<1>(geometry, point))
|
||||
if (! detail::point_on_surface::calculate_point_on_surface<1>(geometry, point, strategy))
|
||||
{
|
||||
// For invalid polygons, we might try X-direction
|
||||
detail::point_on_surface::calculate_point_on_surface<0>(geometry, point);
|
||||
detail::point_on_surface::calculate_point_on_surface<0>(geometry, point, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Assigns a Point guaranteed to lie on the surface of the Geometry
|
||||
\tparam Geometry geometry type. This also defines the type of the output point
|
||||
\param geometry Geometry to take point from
|
||||
\param point Point to assign
|
||||
*/
|
||||
template <typename Geometry, typename Point>
|
||||
inline void point_on_surface(Geometry const& geometry, Point & point)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type strategy_type;
|
||||
|
||||
point_on_surface(geometry, point, strategy_type());
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Returns point guaranteed to lie on the surface of the Geometry
|
||||
\tparam Geometry geometry type. This also defines the type of the output point
|
||||
\param geometry Geometry to take point from
|
||||
\param strategy side strategy
|
||||
\return The Point guaranteed to lie on the surface of the Geometry
|
||||
*/
|
||||
template<typename Geometry, typename SideStrategy>
|
||||
inline typename geometry::point_type<Geometry>::type
|
||||
return_point_on_surface(Geometry const& geometry, SideStrategy const& strategy)
|
||||
{
|
||||
typename geometry::point_type<Geometry>::type result;
|
||||
geometry::point_on_surface(geometry, result, strategy);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Returns point guaranteed to lie on the surface of the Geometry
|
||||
\tparam Geometry geometry type. This also defines the type of the output point
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-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
|
||||
|
||||
// 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,8 @@
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
#include <boost/geometry/algorithms/clear.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/default_strategy.hpp>
|
||||
|
||||
#include <boost/geometry/util/condition.hpp>
|
||||
|
||||
|
||||
@@ -59,20 +66,13 @@ namespace detail { namespace remove_spikes
|
||||
{
|
||||
|
||||
|
||||
template <typename Range>
|
||||
struct range_remove_spikes
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Range>::type
|
||||
>::type side_strategy;
|
||||
|
||||
typedef typename coordinate_type<Range>::type coordinate_type;
|
||||
typedef typename point_type<Range>::type point_type;
|
||||
|
||||
|
||||
static inline void apply(Range& range)
|
||||
template <typename Range, typename SideStrategy>
|
||||
static inline void apply(Range& range, SideStrategy const& strategy)
|
||||
{
|
||||
typedef typename point_type<Range>::type point_type;
|
||||
|
||||
std::size_t n = boost::size(range);
|
||||
std::size_t const min_num_points = core_detail::closure::minimum_ring_size
|
||||
<
|
||||
@@ -91,7 +91,10 @@ struct range_remove_spikes
|
||||
cleaned.push_back(*it);
|
||||
|
||||
while(cleaned.size() >= 3
|
||||
&& detail::point_is_spike_or_equal(cleaned.back(), *(cleaned.end() - 3), *(cleaned.end() - 2)))
|
||||
&& detail::point_is_spike_or_equal(cleaned.back(),
|
||||
*(cleaned.end() - 3),
|
||||
*(cleaned.end() - 2),
|
||||
strategy))
|
||||
{
|
||||
// Remove pen-ultimate point causing the spike (or which was equal)
|
||||
cleaned.erase(cleaned.end() - 2);
|
||||
@@ -110,13 +113,21 @@ struct range_remove_spikes
|
||||
found = false;
|
||||
// Check for spike in first point
|
||||
int const penultimate = 2;
|
||||
while(cleaned.size() >= 3 && detail::point_is_spike_or_equal(cleaned.front(), *(cleaned.end() - penultimate), cleaned.back()))
|
||||
while(cleaned.size() >= 3
|
||||
&& detail::point_is_spike_or_equal(cleaned.front(),
|
||||
*(cleaned.end() - penultimate),
|
||||
cleaned.back(),
|
||||
strategy))
|
||||
{
|
||||
cleaned.pop_back();
|
||||
found = true;
|
||||
}
|
||||
// Check for spike in second point
|
||||
while(cleaned.size() >= 3 && detail::point_is_spike_or_equal(*(cleaned.begin() + 1), cleaned.back(), cleaned.front()))
|
||||
while(cleaned.size() >= 3
|
||||
&& detail::point_is_spike_or_equal(*(cleaned.begin() + 1),
|
||||
cleaned.back(),
|
||||
cleaned.front(),
|
||||
strategy))
|
||||
{
|
||||
cleaned.pop_front();
|
||||
found = true;
|
||||
@@ -144,15 +155,13 @@ struct range_remove_spikes
|
||||
};
|
||||
|
||||
|
||||
template <typename Polygon>
|
||||
struct polygon_remove_spikes
|
||||
{
|
||||
static inline void apply(Polygon& polygon)
|
||||
template <typename Polygon, typename SideStrategy>
|
||||
static inline void apply(Polygon& polygon, SideStrategy const& strategy)
|
||||
{
|
||||
typedef typename geometry::ring_type<Polygon>::type ring_type;
|
||||
|
||||
typedef range_remove_spikes<ring_type> per_range;
|
||||
per_range::apply(exterior_ring(polygon));
|
||||
typedef range_remove_spikes per_range;
|
||||
per_range::apply(exterior_ring(polygon), strategy);
|
||||
|
||||
typename interior_return_type<Polygon>::type
|
||||
rings = interior_rings(polygon);
|
||||
@@ -160,23 +169,24 @@ struct polygon_remove_spikes
|
||||
for (typename detail::interior_iterator<Polygon>::type
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
per_range::apply(*it);
|
||||
per_range::apply(*it, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename MultiGeometry, typename SingleVersion>
|
||||
template <typename SingleVersion>
|
||||
struct multi_remove_spikes
|
||||
{
|
||||
static inline void apply(MultiGeometry& multi)
|
||||
template <typename MultiGeometry, typename SideStrategy>
|
||||
static inline void apply(MultiGeometry& multi, SideStrategy const& strategy)
|
||||
{
|
||||
for (typename boost::range_iterator<MultiGeometry>::type
|
||||
it = boost::begin(multi);
|
||||
it != boost::end(multi);
|
||||
++it)
|
||||
{
|
||||
SingleVersion::apply(*it);
|
||||
SingleVersion::apply(*it, strategy);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -199,21 +209,22 @@ template
|
||||
>
|
||||
struct remove_spikes
|
||||
{
|
||||
static inline void apply(Geometry&)
|
||||
template <typename SideStrategy>
|
||||
static inline void apply(Geometry&, SideStrategy const&)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template <typename Ring>
|
||||
struct remove_spikes<Ring, ring_tag>
|
||||
: detail::remove_spikes::range_remove_spikes<Ring>
|
||||
: detail::remove_spikes::range_remove_spikes
|
||||
{};
|
||||
|
||||
|
||||
|
||||
template <typename Polygon>
|
||||
struct remove_spikes<Polygon, polygon_tag>
|
||||
: detail::remove_spikes::polygon_remove_spikes<Polygon>
|
||||
: detail::remove_spikes::polygon_remove_spikes
|
||||
{};
|
||||
|
||||
|
||||
@@ -221,11 +232,7 @@ template <typename MultiPolygon>
|
||||
struct remove_spikes<MultiPolygon, multi_polygon_tag>
|
||||
: detail::remove_spikes::multi_remove_spikes
|
||||
<
|
||||
MultiPolygon,
|
||||
detail::remove_spikes::polygon_remove_spikes
|
||||
<
|
||||
typename boost::range_value<MultiPolygon>::type
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
@@ -239,28 +246,46 @@ namespace resolve_variant {
|
||||
template <typename Geometry>
|
||||
struct remove_spikes
|
||||
{
|
||||
static void apply(Geometry& geometry)
|
||||
template <typename Strategy>
|
||||
static void apply(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
concepts::check<Geometry>();
|
||||
dispatch::remove_spikes<Geometry>::apply(geometry);
|
||||
dispatch::remove_spikes<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
static void apply(Geometry& geometry, geometry::default_strategy const&)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Geometry>::type
|
||||
>::type side_strategy;
|
||||
|
||||
apply(geometry, side_strategy());
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct remove_spikes<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
|
||||
{
|
||||
remove_spikes<Geometry>::apply(geometry);
|
||||
remove_spikes<Geometry>::apply(geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
|
||||
template <typename Strategy>
|
||||
static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry,
|
||||
Strategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor(), geometry);
|
||||
boost::apply_visitor(visitor<Strategy>(strategy), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -275,7 +300,20 @@ struct remove_spikes<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
template <typename Geometry>
|
||||
inline void remove_spikes(Geometry& geometry)
|
||||
{
|
||||
resolve_variant::remove_spikes<Geometry>::apply(geometry);
|
||||
resolve_variant::remove_spikes<Geometry>::apply(geometry, geometry::default_strategy());
|
||||
}
|
||||
|
||||
/*!
|
||||
\ingroup remove_spikes
|
||||
\tparam Geometry geometry type
|
||||
\tparam Strategy side strategy type
|
||||
\param geometry the geometry to make remove_spikes
|
||||
\param strategy the side strategy used by the algorithm
|
||||
*/
|
||||
template <typename Geometry, typename Strategy>
|
||||
inline void remove_spikes(Geometry& geometry, Strategy const& strategy)
|
||||
{
|
||||
resolve_variant::remove_spikes<Geometry>::apply(geometry, strategy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -110,50 +110,41 @@ public :
|
||||
}
|
||||
};
|
||||
|
||||
struct dissolve_overlay_visitor
|
||||
{
|
||||
public :
|
||||
void print(char const* /*header*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/, int /*op_index*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns>
|
||||
void visit_turns(int , Turns const& ) {}
|
||||
|
||||
template <typename Clusters, typename Turns>
|
||||
void visit_clusters(Clusters const& , Turns const& ) {}
|
||||
|
||||
template <typename Turns, typename Turn, typename Operation>
|
||||
void visit_traverse(Turns const& /*turns*/, Turn const& /*turn*/, Operation const& /*op*/, const char* /*header*/)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Turns, typename Turn, typename Operation>
|
||||
void visit_traverse_reject(Turns const& , Turn const& , Operation const& ,
|
||||
detail::overlay::traverse_error_type )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename Geometry, typename GeometryOut>
|
||||
struct dissolve_ring_or_polygon
|
||||
{
|
||||
template <typename RescalePolicy, typename OutputIterator, typename Strategy>
|
||||
template <typename Turns>
|
||||
static inline void clear(Turns& turns)
|
||||
{
|
||||
typedef typename boost::range_value<Turns>::type turn_type;
|
||||
|
||||
for (typename boost::range_iterator<Turns>::type
|
||||
it = boost::begin(turns);
|
||||
it != boost::end(turns);
|
||||
++it)
|
||||
{
|
||||
turn_type& turn = *it;
|
||||
turn.discarded = false;
|
||||
turn.cluster_id = -1;
|
||||
turn.has_colocated_both = false;
|
||||
turn.switch_source = false;
|
||||
turn.touch_only = false;
|
||||
}
|
||||
|
||||
clear_visit_info(turns);
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename RescalePolicy, typename OutputIterator,
|
||||
typename Strategy, typename Visitor
|
||||
>
|
||||
static inline OutputIterator apply(Geometry const& geometry,
|
||||
RescalePolicy const& rescale_policy,
|
||||
OutputIterator out,
|
||||
Strategy const& strategy)
|
||||
Strategy const& strategy,
|
||||
Visitor& visitor)
|
||||
{
|
||||
typedef typename point_type<Geometry>::type point_type;
|
||||
|
||||
@@ -169,93 +160,111 @@ struct dissolve_ring_or_polygon
|
||||
geometry::self_turns
|
||||
<
|
||||
detail::overlay::assign_null_policy
|
||||
>(geometry, strategy, rescale_policy, turns, policy);
|
||||
>(geometry, strategy, rescale_policy, turns, policy, 0, false);
|
||||
|
||||
// The dissolve process is not necessary if there are no turns at all
|
||||
visitor.visit_turns(1, turns);
|
||||
|
||||
if (boost::size(turns) > 0)
|
||||
{
|
||||
typedef typename ring_type<Geometry>::type ring_type;
|
||||
typedef std::vector<ring_type> out_vector;
|
||||
out_vector rings;
|
||||
|
||||
typedef std::map
|
||||
<
|
||||
signed_size_type,
|
||||
detail::overlay::cluster_info
|
||||
> cluster_type;
|
||||
|
||||
cluster_type clusters;
|
||||
dissolve_overlay_visitor visitor;
|
||||
|
||||
// Enrich/traverse the polygons twice: once for union...
|
||||
typename Strategy::side_strategy_type const
|
||||
side_strategy = strategy.get_side_strategy();
|
||||
|
||||
enrich_intersection_points<false, false, overlay_dissolve>(turns,
|
||||
clusters, geometry, geometry, rescale_policy,
|
||||
side_strategy);
|
||||
|
||||
detail::overlay::traverse
|
||||
<
|
||||
false, false,
|
||||
Geometry, Geometry,
|
||||
overlay_dissolve,
|
||||
backtrack_for_dissolve<Geometry>
|
||||
>::apply(geometry, geometry,
|
||||
strategy, rescale_policy,
|
||||
turns, rings, clusters, visitor);
|
||||
|
||||
clear_visit_info(turns);
|
||||
|
||||
// ... and for intersection
|
||||
enrich_intersection_points<false, false, overlay_intersection>(turns,
|
||||
clusters, geometry, geometry, rescale_policy,
|
||||
side_strategy);
|
||||
|
||||
detail::overlay::traverse
|
||||
<
|
||||
false, false,
|
||||
Geometry, Geometry,
|
||||
overlay_intersection,
|
||||
backtrack_for_dissolve<Geometry>
|
||||
>::apply(geometry, geometry,
|
||||
strategy, rescale_policy,
|
||||
turns, rings, clusters, visitor);
|
||||
|
||||
std::map<ring_identifier, detail::overlay::ring_turn_info> map;
|
||||
detail::overlay::get_ring_turn_info<overlay_dissolve>(map, turns, clusters);
|
||||
|
||||
typedef detail::overlay::ring_properties<typename geometry::point_type<Geometry>::type> properties;
|
||||
|
||||
std::map<ring_identifier, properties> selected;
|
||||
|
||||
detail::overlay::select_rings<overlay_dissolve>(geometry, map, selected, strategy);
|
||||
|
||||
// Add intersected rings
|
||||
{
|
||||
ring_identifier id(2, 0, -1);
|
||||
for (typename boost::range_iterator<std::vector<ring_type> const>::type
|
||||
it = boost::begin(rings);
|
||||
it != boost::end(rings);
|
||||
++it)
|
||||
{
|
||||
selected[id] = properties(*it);
|
||||
id.multi_index++;
|
||||
}
|
||||
}
|
||||
|
||||
detail::overlay::assign_parents(geometry, rings, selected, strategy, true);
|
||||
return detail::overlay::add_rings<GeometryOut>(selected, geometry, rings, out);
|
||||
|
||||
}
|
||||
else
|
||||
if (boost::size(turns) == 0)
|
||||
{
|
||||
// No self-turns, then add original geometry
|
||||
GeometryOut g;
|
||||
geometry::convert(geometry, g);
|
||||
*out++ = g;
|
||||
return out;
|
||||
}
|
||||
|
||||
typedef typename ring_type<Geometry>::type ring_type;
|
||||
typedef std::vector<ring_type> out_vector;
|
||||
out_vector rings;
|
||||
|
||||
typedef std::map
|
||||
<
|
||||
signed_size_type,
|
||||
detail::overlay::cluster_info
|
||||
> cluster_type;
|
||||
|
||||
cluster_type clusters;
|
||||
|
||||
// Enrich/traverse the polygons twice: first for union...
|
||||
typename Strategy::side_strategy_type const
|
||||
side_strategy = strategy.get_side_strategy();
|
||||
|
||||
enrich_intersection_points<false, false, overlay_dissolve_union>(turns,
|
||||
clusters, geometry, geometry, rescale_policy,
|
||||
side_strategy);
|
||||
|
||||
visitor.visit_turns(2, turns);
|
||||
|
||||
visitor.visit_clusters(clusters, turns);
|
||||
|
||||
std::map<ring_identifier, overlay::ring_turn_info> turn_info_per_ring;
|
||||
|
||||
detail::overlay::traverse
|
||||
<
|
||||
false, false,
|
||||
Geometry, Geometry,
|
||||
overlay_dissolve_union,
|
||||
backtrack_for_dissolve<Geometry>
|
||||
>::apply(geometry, geometry,
|
||||
strategy, rescale_policy,
|
||||
turns, rings, turn_info_per_ring, clusters, visitor);
|
||||
|
||||
visitor.visit_turns(3, turns);
|
||||
|
||||
// ... and then for intersection
|
||||
clear(turns);
|
||||
enrich_intersection_points<false, false, overlay_dissolve_intersection>(turns,
|
||||
clusters, geometry, geometry, rescale_policy,
|
||||
side_strategy);
|
||||
|
||||
visitor.visit_turns(4, turns);
|
||||
|
||||
detail::overlay::traverse
|
||||
<
|
||||
false, false,
|
||||
Geometry, Geometry,
|
||||
overlay_dissolve_intersection,
|
||||
backtrack_for_dissolve<Geometry>
|
||||
>::apply(geometry, geometry,
|
||||
strategy, rescale_policy,
|
||||
turns, rings, turn_info_per_ring, clusters, visitor);
|
||||
|
||||
visitor.visit_turns(5, turns);
|
||||
|
||||
detail::overlay::get_ring_turn_info<overlay_dissolve_union>(turn_info_per_ring, turns, clusters);
|
||||
|
||||
typedef typename geometry::point_type<Geometry>::type point_type;
|
||||
typedef typename Strategy::template area_strategy
|
||||
<
|
||||
point_type
|
||||
>::type area_strategy_type;
|
||||
typedef typename area_strategy_type::return_type area_result_type;
|
||||
typedef detail::overlay::ring_properties<point_type, area_result_type> properties;
|
||||
|
||||
std::map<ring_identifier, properties> selected;
|
||||
|
||||
detail::overlay::select_rings<overlay_dissolve_union>(geometry, turn_info_per_ring, selected, strategy);
|
||||
|
||||
// Add intersected rings
|
||||
{
|
||||
area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
|
||||
|
||||
ring_identifier id(2, 0, -1);
|
||||
for (typename boost::range_iterator<std::vector<ring_type> const>::type
|
||||
it = boost::begin(rings);
|
||||
it != boost::end(rings);
|
||||
++it)
|
||||
{
|
||||
selected[id] = properties(*it, area_strategy);
|
||||
id.multi_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// Assign parents, checking orientation and discarding negative
|
||||
// children with negative parents
|
||||
detail::overlay::assign_parents(geometry, rings, selected,
|
||||
strategy, true, true);
|
||||
return detail::overlay::add_rings<GeometryOut>(selected, geometry, rings, out);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -335,13 +344,15 @@ inline OutputIterator dissolve_inserter(Geometry const& geometry,
|
||||
rescale_policy_type robust_policy
|
||||
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
|
||||
|
||||
detail::overlay::overlay_null_visitor visitor;
|
||||
|
||||
return dispatch::dissolve
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
typename tag<GeometryOut>::type,
|
||||
Geometry,
|
||||
GeometryOut
|
||||
>::apply(geometry, robust_policy, out, strategy);
|
||||
>::apply(geometry, robust_policy, out, strategy, visitor);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -388,6 +399,8 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection, St
|
||||
|
||||
concepts::check<geometry_out>();
|
||||
|
||||
detail::overlay::overlay_null_visitor visitor;
|
||||
|
||||
dispatch::dissolve
|
||||
<
|
||||
typename tag<Geometry>::type,
|
||||
@@ -396,7 +409,7 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection, St
|
||||
geometry_out
|
||||
>::apply(geometry, detail::no_rescale_policy(),
|
||||
std::back_inserter(output_collection),
|
||||
strategy);
|
||||
strategy, visitor);
|
||||
}
|
||||
|
||||
template
|
||||
|
||||
@@ -38,9 +38,14 @@ namespace detail { namespace dissolve
|
||||
template <typename Multi, typename GeometryOut>
|
||||
struct dissolve_multi
|
||||
{
|
||||
template <typename RescalePolicy, typename OutputIterator, typename Strategy>
|
||||
static inline OutputIterator apply(Multi const& multi, RescalePolicy const& rescale_policy,
|
||||
OutputIterator out, Strategy const& strategy)
|
||||
template
|
||||
<
|
||||
typename RescalePolicy, typename OutputIterator,
|
||||
typename Strategy, typename Visitor
|
||||
>
|
||||
static inline OutputIterator apply(Multi const& multi,
|
||||
RescalePolicy const& rescale_policy, OutputIterator out,
|
||||
Strategy const& strategy, Visitor& visitor)
|
||||
{
|
||||
typedef typename boost::range_value<Multi>::type polygon_type;
|
||||
typedef typename boost::range_iterator<Multi const>::type iterator_type;
|
||||
@@ -55,7 +60,8 @@ struct dissolve_multi
|
||||
<
|
||||
polygon_type,
|
||||
GeometryOut
|
||||
>::apply(*it, rescale_policy, std::back_inserter(step1), strategy);
|
||||
>::apply(*it, rescale_policy, std::back_inserter(step1),
|
||||
strategy, visitor);
|
||||
}
|
||||
|
||||
// Step 2: remove mutual overlap
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013 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.
|
||||
|
||||
@@ -17,6 +22,7 @@
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
@@ -26,9 +32,6 @@
|
||||
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/compare.hpp>
|
||||
#include <boost/geometry/policies/compare.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -40,7 +43,6 @@ namespace detail { namespace expand
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
std::size_t Dimension, std::size_t DimensionCount
|
||||
>
|
||||
struct nsphere_loop
|
||||
@@ -48,20 +50,10 @@ struct nsphere_loop
|
||||
template <typename Box, typename NSphere>
|
||||
static inline void apply(Box& box, NSphere const& source)
|
||||
{
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
StrategyLess, 1, NSphere, Dimension
|
||||
>::type less_type;
|
||||
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
StrategyGreater, -1, NSphere, Dimension
|
||||
>::type greater_type;
|
||||
|
||||
typedef typename select_coordinate_type<NSphere, Box>::type coordinate_type;
|
||||
|
||||
less_type less;
|
||||
greater_type greater;
|
||||
std::less<coordinate_type> const less;
|
||||
std::greater<coordinate_type> const greater;
|
||||
|
||||
coordinate_type const min_coord = get<Dimension>(source) - get_radius<0>(source);
|
||||
coordinate_type const max_coord = get<Dimension>(source) + get_radius<0>(source);
|
||||
@@ -78,7 +70,6 @@ struct nsphere_loop
|
||||
|
||||
nsphere_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
Dimension + 1, DimensionCount
|
||||
>::apply(box, source);
|
||||
}
|
||||
@@ -87,12 +78,10 @@ struct nsphere_loop
|
||||
|
||||
template
|
||||
<
|
||||
typename StrategyLess, typename StrategyGreater,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct nsphere_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
DimensionCount, DimensionCount
|
||||
>
|
||||
{
|
||||
@@ -112,13 +101,11 @@ namespace dispatch
|
||||
// Box + Nsphere -> new box containing also nsphere
|
||||
template
|
||||
<
|
||||
typename BoxOut, typename NSphere,
|
||||
typename StrategyLess, typename StrategyGreater
|
||||
typename BoxOut, typename NSphere
|
||||
>
|
||||
struct expand<BoxOut, NSphere, StrategyLess, StrategyGreater, box_tag, nsphere_tag>
|
||||
struct expand<BoxOut, NSphere, box_tag, nsphere_tag>
|
||||
: detail::expand::nsphere_loop
|
||||
<
|
||||
StrategyLess, StrategyGreater,
|
||||
0, dimension<NSphere>::type::value
|
||||
>
|
||||
{};
|
||||
|
||||
96
include/boost/geometry/formulas/authalic_radius_sqr.hpp
Normal file
96
include/boost/geometry/formulas/authalic_radius_sqr.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_FORMULAS_AUTHALIC_RADIUS_SQR_HPP
|
||||
#define BOOST_GEOMETRY_FORMULAS_AUTHALIC_RADIUS_SQR_HPP
|
||||
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/formulas/eccentricity_sqr.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
#include <boost/math/special_functions/atanh.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace formula_dispatch
|
||||
{
|
||||
|
||||
template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct authalic_radius_sqr
|
||||
: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename ResultType, typename Geometry>
|
||||
struct authalic_radius_sqr<ResultType, Geometry, srs_sphere_tag>
|
||||
{
|
||||
static inline ResultType apply(Geometry const& geometry)
|
||||
{
|
||||
return math::sqr<ResultType>(get_radius<0>(geometry));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ResultType, typename Geometry>
|
||||
struct authalic_radius_sqr<ResultType, Geometry, srs_spheroid_tag>
|
||||
{
|
||||
static inline ResultType apply(Geometry const& geometry)
|
||||
{
|
||||
ResultType const a2 = math::sqr<ResultType>(get_radius<0>(geometry));
|
||||
ResultType const e2 = formula::eccentricity_sqr<ResultType>(geometry);
|
||||
|
||||
return apply(a2, e2);
|
||||
}
|
||||
|
||||
static inline ResultType apply(ResultType const& a2, ResultType const& e2)
|
||||
{
|
||||
ResultType const c0 = 0;
|
||||
|
||||
if (math::equals(e2, c0))
|
||||
{
|
||||
return a2;
|
||||
}
|
||||
|
||||
ResultType const e = math::sqrt(e2);
|
||||
ResultType const c2 = 2;
|
||||
|
||||
//ResultType const b2 = math::sqr(get_radius<2>(geometry));
|
||||
//return a2 / c2 + b2 * boost::math::atanh(e) / (c2 * e);
|
||||
|
||||
ResultType const c1 = 1;
|
||||
return (a2 / c2) * ( c1 + (c1 - e2) * boost::math::atanh(e) / e );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace formula_dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace formula
|
||||
{
|
||||
|
||||
template <typename ResultType, typename Geometry>
|
||||
inline ResultType authalic_radius_sqr(Geometry const& geometry)
|
||||
{
|
||||
return formula_dispatch::authalic_radius_sqr<ResultType, Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
} // namespace formula
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_FORMULAS_AUTHALIC_RADIUS_SQR_HPP
|
||||
375
include/boost/geometry/formulas/distance_point_segment.hpp
Normal file
375
include/boost/geometry/formulas/distance_point_segment.hpp
Normal file
@@ -0,0 +1,375 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2016-2017 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_FORMULAS_CROSS_TRACK_GEO_HPP
|
||||
#define BOOST_GEOMETRY_FORMULAS_CROSS_TRACK_GEO_HPP
|
||||
|
||||
#include <boost/geometry/formulas/result_direct.hpp>
|
||||
#include <boost/geometry/formulas/mean_radius.hpp>
|
||||
|
||||
#ifndef BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS
|
||||
#define BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS 100
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief Algorithm to compute the distance between a segment and a point using
|
||||
direct and inverse geodesic problems as subroutines. The algorithm
|
||||
approximates the distance by an iterative Newton method.
|
||||
\see C.F.F.Karney - Geodesics on an ellipsoid of revolution,
|
||||
https://arxiv.org/abs/1102.1215
|
||||
*/
|
||||
|
||||
namespace boost { namespace geometry { namespace formula
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename CT,
|
||||
typename Units,
|
||||
template <typename, bool, bool, bool, bool ,bool> class Inverse,
|
||||
template <typename, bool, bool, bool, bool> class Direct,
|
||||
bool EnableClosestPoint = false
|
||||
>
|
||||
class distance_point_segment{
|
||||
|
||||
public:
|
||||
|
||||
typedef Inverse<CT, true, false, false, true, true> inverse_distance_quantities_type;
|
||||
typedef Inverse<CT, true, false, false, false, false> inverse_distance_type;
|
||||
typedef Inverse<CT, false, true, false, false, false> inverse_azimuth_type;
|
||||
typedef Inverse<CT, false, true, true, false, false> inverse_azimuth_reverse_type;
|
||||
typedef Direct<CT, true, false, false, false> direct_distance_type;
|
||||
|
||||
struct result_distance_point_segment
|
||||
{
|
||||
result_distance_point_segment()
|
||||
: distance(0)
|
||||
, closest_point_lon(0)
|
||||
, closest_point_lat(0)
|
||||
{}
|
||||
|
||||
CT distance;
|
||||
CT closest_point_lon;
|
||||
CT closest_point_lat;
|
||||
};
|
||||
|
||||
result_distance_point_segment
|
||||
static inline non_iterative_case(CT lon, CT lat, CT distance)
|
||||
{
|
||||
result_distance_point_segment result;
|
||||
result.distance = distance;
|
||||
|
||||
if (EnableClosestPoint)
|
||||
{
|
||||
result.closest_point_lon = lon;
|
||||
result.closest_point_lat = lat;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Spheroid>
|
||||
result_distance_point_segment
|
||||
static inline non_iterative_case(CT lon1, CT lat1, //p1
|
||||
CT lon2, CT lat2, //p2
|
||||
Spheroid const& spheroid)
|
||||
{
|
||||
CT distance = inverse_distance_quantities_type::apply(lon1, lat1,
|
||||
lon2, lat2,
|
||||
spheroid).distance;
|
||||
return non_iterative_case(lon1, lat1, distance);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T static inline normalize(T g4)
|
||||
{
|
||||
CT const pi = math::pi<CT>();
|
||||
if (g4 < 0 && g4 < -pi)//close to -270
|
||||
{
|
||||
return g4 + 1.5 * pi;
|
||||
}
|
||||
else if (g4 > 0 && g4 > pi)//close to 270
|
||||
{
|
||||
return - g4 + 1.5 * pi;
|
||||
}
|
||||
else if (g4 < 0 && g4 > -pi)//close to -90
|
||||
{
|
||||
return -g4 - pi/2;
|
||||
}
|
||||
return g4 - pi/2;
|
||||
}
|
||||
|
||||
template <typename Spheroid>
|
||||
result_distance_point_segment
|
||||
static inline apply(CT lon1, CT lat1, //p1
|
||||
CT lon2, CT lat2, //p2
|
||||
CT lon3, CT lat3, //query point p3
|
||||
Spheroid const& spheroid)
|
||||
{
|
||||
CT const earth_radius = geometry::formula::mean_radius<CT>(spheroid);
|
||||
|
||||
result_distance_point_segment result;
|
||||
|
||||
// Constants
|
||||
CT const f = flattening<CT>(spheroid);
|
||||
CT const pi = math::pi<CT>();
|
||||
CT const half_pi = pi / CT(2);
|
||||
CT const c0 = CT(0);
|
||||
|
||||
// Convert to radians
|
||||
lon1 = math::as_radian<Units>(lon1);
|
||||
lat1 = math::as_radian<Units>(lat1);
|
||||
lon2 = math::as_radian<Units>(lon2);
|
||||
lat2 = math::as_radian<Units>(lat2);
|
||||
lon3 = math::as_radian<Units>(lon3);
|
||||
lat3 = math::as_radian<Units>(lat3);
|
||||
|
||||
if (lon1 > lon2)
|
||||
{
|
||||
std::swap(lon1, lon2);
|
||||
std::swap(lat1, lat2);
|
||||
}
|
||||
|
||||
//segment on equator
|
||||
//TODO: use the meridian distance when it'll be available
|
||||
if (math::equals(lat1, c0) && math::equals(lat2, c0))
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DISTANCE_POINT_SEGMENT_DEBUG
|
||||
std::cout << "Equatorial segment" << std::endl;
|
||||
#endif
|
||||
if (lon3 <= lon1)
|
||||
{
|
||||
return non_iterative_case(lon1, lat1, lon3, lat3, spheroid);
|
||||
}
|
||||
if (lon3 >= lon2)
|
||||
{
|
||||
return non_iterative_case(lon2, lat2, lon3, lat3, spheroid);
|
||||
}
|
||||
return non_iterative_case(lon3, lat1, lon3, lat3, spheroid);
|
||||
}
|
||||
|
||||
CT d1 = inverse_distance_type::apply(lon1, lat1,
|
||||
lon3, lat3, spheroid).distance;
|
||||
CT d3 = inverse_distance_type::apply(lon1, lat1,
|
||||
lon2, lat2, spheroid).distance;
|
||||
|
||||
if (geometry::math::equals(d3, c0))
|
||||
{
|
||||
return non_iterative_case(lon1, lat2, d1);
|
||||
}
|
||||
|
||||
CT d2 = inverse_distance_type::apply(lon2, lat2,
|
||||
lon3, lat3, spheroid).distance;
|
||||
|
||||
// Compute a12 (GEO)
|
||||
geometry::formula::result_inverse<CT> res12 =
|
||||
inverse_azimuth_reverse_type::apply(lon1, lat1, lon2, lat2, spheroid);
|
||||
CT a12 = res12.azimuth;
|
||||
CT a13 = inverse_azimuth_type::apply(lon1, lat1, lon3, lat3, spheroid).azimuth;
|
||||
|
||||
CT a312 = a13 - a12;
|
||||
|
||||
if (geometry::math::equals(a312, c0))
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DISTANCE_POINT_SEGMENT_DEBUG
|
||||
std::cout << "point on segment" << std::endl;
|
||||
#endif
|
||||
return non_iterative_case(lon3, lat3, c0);
|
||||
}
|
||||
|
||||
CT projection1 = cos( a312 ) * d1 / d3;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DISTANCE_POINT_SEGMENT_DEBUG
|
||||
std::cout << "segment=(" << lon1 * math::r2d<CT>();
|
||||
std::cout << "," << lat1 * math::r2d<CT>();
|
||||
std::cout << "),(" << lon2 * math::r2d<CT>();
|
||||
std::cout << "," << lat2 * math::r2d<CT>();
|
||||
std::cout << ")\np=(" << lon3 * math::r2d<CT>();
|
||||
std::cout << "," << lat3 * math::r2d<CT>();
|
||||
std::cout << ")\na1=" << a12 * math::r2d<CT>() << std::endl;
|
||||
std::cout << "a13=" << a13 * math::r2d<CT>() << std::endl;
|
||||
std::cout << "a312=" << a312 * math::r2d<CT>() << std::endl;
|
||||
std::cout << "cos(a312)=" << cos(a312) << std::endl;
|
||||
#endif
|
||||
if (projection1 < 0.0)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DISTANCE_POINT_SEGMENT_DEBUG
|
||||
std::cout << "projection closer to p1" << std::endl;
|
||||
#endif
|
||||
// projection of p3 on geodesic spanned by segment (p1,p2) fall
|
||||
// outside of segment on the side of p1
|
||||
return non_iterative_case(lon1, lat1, lon3, lat3, spheroid);
|
||||
}
|
||||
|
||||
CT a21 = res12.reverse_azimuth - pi;
|
||||
CT a23 = inverse_azimuth_type::apply(lon2, lat2, lon3, lat3, spheroid).azimuth;
|
||||
|
||||
CT a321 = a23 - a21;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DISTANCE_POINT_SEGMENT_DEBUG
|
||||
std::cout << "a21=" << a21 * math::r2d<CT>() << std::endl;
|
||||
std::cout << "a23=" << a13 * math::r2d<CT>() << std::endl;
|
||||
std::cout << "a321=" << a321 * math::r2d<CT>() << std::endl;
|
||||
std::cout << "cos(a321)=" << cos(a321) << std::endl;
|
||||
#endif
|
||||
CT projection2 = cos( a321 ) * d2 / d3;
|
||||
|
||||
if (projection2 < 0.0)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DISTANCE_POINT_SEGMENT_DEBUG
|
||||
std::cout << "projection closer to p2" << std::endl;
|
||||
#endif
|
||||
// projection of p3 on geodesic spanned by segment (p1,p2) fall
|
||||
// outside of segment on the side of p2
|
||||
return non_iterative_case(lon2, lat2, lon3, lat3, spheroid);
|
||||
}
|
||||
|
||||
// Guess s14 (SPHERICAL)
|
||||
typedef geometry::model::point
|
||||
<
|
||||
CT, 2,
|
||||
geometry::cs::spherical_equatorial<geometry::radian>
|
||||
> point;
|
||||
|
||||
CT bet1 = atan((1 - f) * tan(lon1));
|
||||
CT bet2 = atan((1 - f) * tan(lon2));
|
||||
CT bet3 = atan((1 - f) * tan(lon3));
|
||||
point p1 = point(bet1, lat1);
|
||||
point p2 = point(bet2, lat2);
|
||||
point p3 = point(bet3, lat3);
|
||||
|
||||
geometry::strategy::distance::cross_track<CT> cross_track(earth_radius);
|
||||
CT s34 = cross_track.apply(p3, p1, p2);
|
||||
|
||||
geometry::strategy::distance::haversine<CT> str(earth_radius);
|
||||
CT s13 = str.apply(p1, p3);
|
||||
CT s14 = acos( cos(s13/earth_radius) / cos(s34/earth_radius) ) * earth_radius;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DISTANCE_POINT_SEGMENT_DEBUG
|
||||
std::cout << "s34=" << s34 << std::endl;
|
||||
std::cout << "s13=" << s13 << std::endl;
|
||||
std::cout << "s14=" << s14 << std::endl;
|
||||
std::cout << "===============" << std::endl;
|
||||
#endif
|
||||
|
||||
// Update s14 (using Newton method)
|
||||
CT prev_distance = 0;
|
||||
geometry::formula::result_direct<CT> res14;
|
||||
geometry::formula::result_inverse<CT> res34;
|
||||
|
||||
int counter = 0; // robustness
|
||||
CT g4;
|
||||
CT delta_g4;
|
||||
|
||||
do{
|
||||
prev_distance = res34.distance;
|
||||
|
||||
// Solve the direct problem to find p4 (GEO)
|
||||
res14 = direct_distance_type::apply(lon1, lat1, s14, a12, spheroid);
|
||||
|
||||
// Solve an inverse problem to find g4
|
||||
// g4 is the angle between segment (p1,p2) and segment (p3,p4) that meet on p4 (GEO)
|
||||
|
||||
CT a4 = inverse_azimuth_type::apply(res14.lon2, res14.lat2,
|
||||
lon2, lat2, spheroid).azimuth;
|
||||
res34 = inverse_distance_quantities_type::apply(res14.lon2, res14.lat2,
|
||||
lon3, lat3, spheroid);
|
||||
g4 = res34.azimuth - a4;
|
||||
|
||||
delta_g4 = normalize(g4);
|
||||
|
||||
CT M43 = res34.geodesic_scale; // cos(s14/earth_radius) is the spherical limit
|
||||
CT m34 = res34.reduced_length;
|
||||
CT der = (M43 / m34) * sin(g4);
|
||||
s14 = s14 - delta_g4 / der;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DISTANCE_POINT_SEGMENT_DEBUG
|
||||
std::cout << "p4=" << res14.lon2 * math::r2d<CT>() <<
|
||||
"," << res14.lat2 * math::r2d<CT>() << std::endl;
|
||||
std::cout << "delta_g4=" << delta_g4 << std::endl;
|
||||
std::cout << "g4=" << g4 * math::r2d<CT>() << std::endl;
|
||||
std::cout << "der=" << der << std::endl;
|
||||
std::cout << "M43=" << M43 << std::endl;
|
||||
std::cout << "spherical limit=" << cos(s14/earth_radius) << std::endl;
|
||||
std::cout << "m34=" << m34 << std::endl;
|
||||
std::cout << "new_s14=" << s14 << std::endl;
|
||||
std::cout << std::setprecision(16) << "dist =" << res34.distance << std::endl;
|
||||
std::cout << "---------end of step " << counter << std::endl<< std::endl;
|
||||
#endif
|
||||
result.distance = prev_distance;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DISTANCE_POINT_SEGMENT_DEBUG
|
||||
if (g4 == half_pi)
|
||||
{
|
||||
std::cout << "Stop msg: g4 == half_pi" << std::endl;
|
||||
}
|
||||
if (res34.distance >= prev_distance && prev_distance != 0)
|
||||
{
|
||||
std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl;
|
||||
}
|
||||
if (delta_g4 == 0)
|
||||
{
|
||||
std::cout << "Stop msg: delta_g4 == 0" << std::endl;
|
||||
}
|
||||
if (counter == 19)
|
||||
{
|
||||
std::cout << "Stop msg: counter" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
} while (g4 != half_pi
|
||||
&& (prev_distance > res34.distance || prev_distance == 0)
|
||||
&& delta_g4 != 0
|
||||
&& ++counter < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS ) ;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DISTANCE_POINT_SEGMENT_DEBUG
|
||||
std::cout << "distance=" << res34.distance << std::endl;
|
||||
|
||||
point p4(res14.lon2, res14.lat2);
|
||||
CT s34_sph = str.apply(p4, p3);
|
||||
|
||||
std::cout << "s34(sph) =" << s34_sph << std::endl;
|
||||
std::cout << "s34(geo) ="
|
||||
<< inverse_distance_quantities_type::apply(get<0>(p4), get<1>(p4), lon3, lat3, spheroid).distance
|
||||
<< ", p4=(" << get<0>(p4) * math::r2d<double>() << ","
|
||||
<< get<1>(p4) * math::r2d<double>() << ")"
|
||||
<< std::endl;
|
||||
|
||||
CT s31 = inverse_distance_quantities_type::apply(lon3, lat3, lon1, lat1, spheroid).distance;
|
||||
CT s32 = inverse_distance_quantities_type::apply(lon3, lat3, lon2, lat2, spheroid).distance;
|
||||
|
||||
CT a4 = inverse_azimuth_type::apply(get<0>(p4), get<1>(p4), lon2, lat2, spheroid).azimuth;
|
||||
geometry::formula::result_direct<CT> res4 = direct_distance_type::apply(get<0>(p4), get<1>(p4), .04, a4, spheroid);
|
||||
CT p4_plus = inverse_distance_quantities_type::apply(res4.lon2, res4.lat2, lon3, lat3, spheroid).distance;
|
||||
|
||||
geometry::formula::result_direct<CT> res1 = direct_distance_type::apply(lon1, lat1, s14-.04, a12, spheroid);
|
||||
CT p4_minus = inverse_distance_quantities_type::apply(res1.lon2, res1.lat2, lon3, lat3, spheroid).distance;
|
||||
|
||||
std::cout << "s31=" << s31 << "\ns32=" << s32
|
||||
<< "\np4_plus=" << p4_plus << ", p4=(" << res4.lon2 * math::r2d<double>() << "," << res4.lat2 * math::r2d<double>() << ")"
|
||||
<< "\np4_minus=" << p4_minus << ", p4=(" << res1.lon2 * math::r2d<double>() << "," << res1.lat2 * math::r2d<double>() << ")"
|
||||
<< std::endl;
|
||||
|
||||
if (res34.distance <= p4_plus && res34.distance <= p4_minus)
|
||||
{
|
||||
std::cout << "Closest point computed" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "There is a closer point nearby" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}} // namespace boost::geometry::formula
|
||||
#endif // BOOST_GEOMETRY_FORMULAS_CROSS_TRACK_GEO_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2016, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2016-2017, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <boost/geometry/formulas/eccentricity_sqr.hpp>
|
||||
#include <boost/geometry/formulas/flattening.hpp>
|
||||
#include <boost/geometry/formulas/unit_spheroid.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||
@@ -186,7 +187,7 @@ inline Point3d projected_to_surface(Point3d const& direction, Spheroid const& sp
|
||||
//coord_t const b_sqr = math::sqr(get_radius<2>(spheroid));
|
||||
// "unit" spheroid, a = 1
|
||||
coord_t const a_sqr = 1;
|
||||
coord_t const b_sqr = math::sqr(get_radius<2>(spheroid) / get_radius<0>(spheroid));
|
||||
coord_t const b_sqr = math::sqr(formula::unit_spheroid_b<coord_t>(spheroid));
|
||||
|
||||
coord_t const param_a = (dx*dx + dy*dy) / a_sqr + dz*dz / b_sqr;
|
||||
coord_t const delta = c4 * param_a;
|
||||
@@ -226,7 +227,7 @@ inline bool projected_to_surface(Point3d const& origin, Point3d const& direction
|
||||
//coord_t const b_sqr = math::sqr(get_radius<2>(spheroid));
|
||||
// "unit" spheroid, a = 1
|
||||
coord_t const a_sqr = 1;
|
||||
coord_t const b_sqr = math::sqr(get_radius<2>(spheroid) / get_radius<0>(spheroid));
|
||||
coord_t const b_sqr = math::sqr(formula::unit_spheroid_b<coord_t>(spheroid));
|
||||
|
||||
coord_t const param_a = (dx*dx + dy*dy) / a_sqr + dz*dz / b_sqr;
|
||||
coord_t const param_b = c2 * ((ox*dx + oy*dy) / a_sqr + oz*dz / b_sqr);
|
||||
|
||||
71
include/boost/geometry/formulas/mean_radius.hpp
Normal file
71
include/boost/geometry/formulas/mean_radius.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_FORMULAS_MEAN_RADIUS_HPP
|
||||
#define BOOST_GEOMETRY_FORMULAS_MEAN_RADIUS_HPP
|
||||
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/not_implemented.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace formula_dispatch
|
||||
{
|
||||
|
||||
template <typename ResultType, typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct mean_radius
|
||||
: not_implemented<Tag>
|
||||
{};
|
||||
|
||||
template <typename ResultType, typename Geometry>
|
||||
struct mean_radius<ResultType, Geometry, srs_sphere_tag>
|
||||
{
|
||||
static inline ResultType apply(Geometry const& geometry)
|
||||
{
|
||||
return ResultType(get_radius<0>(geometry));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ResultType, typename Geometry>
|
||||
struct mean_radius<ResultType, Geometry, srs_spheroid_tag>
|
||||
{
|
||||
static inline ResultType apply(Geometry const& geometry)
|
||||
{
|
||||
// (2*a + b) / 3
|
||||
return (ResultType(2) * ResultType(get_radius<0>(geometry))
|
||||
+ ResultType(get_radius<2>(geometry)))
|
||||
/ ResultType(3);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace formula_dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace formula
|
||||
{
|
||||
|
||||
template <typename ResultType, typename Geometry>
|
||||
inline ResultType mean_radius(Geometry const& geometry)
|
||||
{
|
||||
return formula_dispatch::mean_radius<ResultType, Geometry>::apply(geometry);
|
||||
}
|
||||
|
||||
} // namespace formula
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_FORMULAS_MEAN_RADIUS_HPP
|
||||
43
include/boost/geometry/formulas/unit_spheroid.hpp
Normal file
43
include/boost/geometry/formulas/unit_spheroid.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_FORMULAS_UNIT_SPHEROID_HPP
|
||||
#define BOOST_GEOMETRY_FORMULAS_UNIT_SPHEROID_HPP
|
||||
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace formula
|
||||
{
|
||||
|
||||
template <typename ResultType, typename Spheroid>
|
||||
inline ResultType unit_spheroid_b(Spheroid const& spheroid)
|
||||
{
|
||||
return ResultType(get_radius<2>(spheroid))
|
||||
/ ResultType(get_radius<0>(spheroid));
|
||||
}
|
||||
|
||||
template <typename ResultSpheroid, typename Spheroid>
|
||||
inline ResultSpheroid unit_spheroid(Spheroid const& spheroid)
|
||||
{
|
||||
typedef typename radius_type<ResultSpheroid>::type radius_t;
|
||||
return ResultSpheroid(radius_t(1),
|
||||
unit_spheroid_b<radius_t>(spheroid));
|
||||
}
|
||||
|
||||
} // namespace formula
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_FORMULAS_UNIT_SPHEROID_HPP
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015, Oracle and/or its affiliates.
|
||||
// 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
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -10,6 +11,8 @@
|
||||
#ifndef BOOST_GEOMETRY_GEOMETRIES_HELPER_GEOMETRY_HPP
|
||||
#define BOOST_GEOMETRY_GEOMETRIES_HELPER_GEOMETRY_HPP
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
@@ -52,6 +55,14 @@ struct default_units<Geometry, cartesian_tag>
|
||||
|
||||
template <typename Units, typename CS_Tag>
|
||||
struct cs_tag_to_coordinate_system
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG((false),
|
||||
NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM,
|
||||
(types<CS_Tag>));
|
||||
};
|
||||
|
||||
template <typename Units>
|
||||
struct cs_tag_to_coordinate_system<Units, cartesian_tag>
|
||||
{
|
||||
typedef cs::cartesian type;
|
||||
};
|
||||
@@ -63,7 +74,7 @@ struct cs_tag_to_coordinate_system<Units, spherical_equatorial_tag>
|
||||
};
|
||||
|
||||
template <typename Units>
|
||||
struct cs_tag_to_coordinate_system<Units, spherical_tag>
|
||||
struct cs_tag_to_coordinate_system<Units, spherical_polar_tag>
|
||||
{
|
||||
typedef cs::spherical<Units> type;
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// 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.
|
||||
// Copyright (c) 2007-2017 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2017 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2017 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
|
||||
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
@@ -111,7 +111,7 @@ template <typename Point, typename Policy>
|
||||
struct wkt_point
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os, Point const& p)
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os, Point const& p, bool)
|
||||
{
|
||||
os << Policy::apply() << "(";
|
||||
stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p);
|
||||
@@ -123,12 +123,18 @@ struct wkt_point
|
||||
\brief Stream ranges as WKT
|
||||
\note policy is used to stream prefix/postfix, enabling derived classes to override this
|
||||
*/
|
||||
template <typename Range, typename PrefixPolicy, typename SuffixPolicy>
|
||||
template
|
||||
<
|
||||
typename Range,
|
||||
bool ForceClosurePossible,
|
||||
typename PrefixPolicy,
|
||||
typename SuffixPolicy
|
||||
>
|
||||
struct wkt_range
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Range const& range, bool force_closed)
|
||||
Range const& range, bool force_closure = ForceClosurePossible)
|
||||
{
|
||||
typedef typename boost::range_iterator<Range const>::type iterator_type;
|
||||
|
||||
@@ -153,7 +159,8 @@ struct wkt_range
|
||||
}
|
||||
|
||||
// optionally, close range to ring by repeating the first point
|
||||
if (force_closed
|
||||
if (ForceClosurePossible
|
||||
&& force_closure
|
||||
&& boost::size(range) > 1
|
||||
&& detail::disjoint::disjoint_point_point(*begin, *(end - 1)))
|
||||
{
|
||||
@@ -164,12 +171,6 @@ struct wkt_range
|
||||
os << SuffixPolicy::apply();
|
||||
}
|
||||
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Range const& range)
|
||||
{
|
||||
apply(os, range, false);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename boost::range_value<Range>::type point_type;
|
||||
@@ -179,11 +180,12 @@ private:
|
||||
\brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4)
|
||||
\note Used in polygon, all multi-geometries
|
||||
*/
|
||||
template <typename Range>
|
||||
template <typename Range, bool ForceClosurePossible = true>
|
||||
struct wkt_sequence
|
||||
: wkt_range
|
||||
<
|
||||
Range,
|
||||
ForceClosurePossible,
|
||||
opening_parenthesis,
|
||||
closing_parenthesis
|
||||
>
|
||||
@@ -194,15 +196,14 @@ struct wkt_poly
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Polygon const& poly)
|
||||
Polygon const& poly, bool force_closure)
|
||||
{
|
||||
typedef typename ring_type<Polygon const>::type ring;
|
||||
bool const force_closed = true;
|
||||
|
||||
os << PrefixPolicy::apply();
|
||||
// TODO: check EMPTY here
|
||||
os << "(";
|
||||
wkt_sequence<ring>::apply(os, exterior_ring(poly), force_closed);
|
||||
wkt_sequence<ring>::apply(os, exterior_ring(poly), force_closure);
|
||||
|
||||
typename interior_return_type<Polygon const>::type
|
||||
rings = interior_rings(poly);
|
||||
@@ -210,10 +211,11 @@ struct wkt_poly
|
||||
it = boost::begin(rings); it != boost::end(rings); ++it)
|
||||
{
|
||||
os << ",";
|
||||
wkt_sequence<ring>::apply(os, *it, force_closed);
|
||||
wkt_sequence<ring>::apply(os, *it, force_closure);
|
||||
}
|
||||
os << ")";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename Multi, typename StreamPolicy, typename PrefixPolicy>
|
||||
@@ -221,7 +223,7 @@ struct wkt_multi
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Multi const& geometry)
|
||||
Multi const& geometry, bool force_closure)
|
||||
{
|
||||
os << PrefixPolicy::apply();
|
||||
// TODO: check EMPTY here
|
||||
@@ -236,7 +238,7 @@ struct wkt_multi
|
||||
{
|
||||
os << ",";
|
||||
}
|
||||
StreamPolicy::apply(os, *it);
|
||||
StreamPolicy::apply(os, *it, force_closure);
|
||||
}
|
||||
|
||||
os << ")";
|
||||
@@ -250,15 +252,19 @@ struct wkt_box
|
||||
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Box const& box)
|
||||
Box const& box, bool force_closure)
|
||||
{
|
||||
// Convert to ring, then stream
|
||||
typedef model::ring<point_type> ring_type;
|
||||
ring_type ring;
|
||||
geometry::convert(box, ring);
|
||||
os << "POLYGON(";
|
||||
wkt_sequence<ring_type>::apply(os, ring);
|
||||
os << ")";
|
||||
// Convert to a clockwire ring, then stream.
|
||||
// Never close it based on last point (box might be empty and
|
||||
// that should result in POLYGON((0 0,0 0,0 0,0 0, ...)) )
|
||||
if (force_closure)
|
||||
{
|
||||
do_apply<model::ring<point_type, true, true> >(os, box);
|
||||
}
|
||||
else
|
||||
{
|
||||
do_apply<model::ring<point_type, true, false> >(os, box);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -268,6 +274,18 @@ struct wkt_box
|
||||
// Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron!
|
||||
//assert_dimension<B, 2>();
|
||||
}
|
||||
|
||||
template <typename RingType, typename Char, typename Traits>
|
||||
static inline void do_apply(std::basic_ostream<Char, Traits>& os,
|
||||
Box const& box)
|
||||
{
|
||||
RingType ring;
|
||||
geometry::convert(box, ring);
|
||||
os << "POLYGON(";
|
||||
wkt_sequence<RingType, false>::apply(os, ring);
|
||||
os << ")";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -278,7 +296,7 @@ struct wkt_segment
|
||||
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Segment const& segment)
|
||||
Segment const& segment, bool)
|
||||
{
|
||||
// Convert to two points, then stream
|
||||
typedef boost::array<point_type, 2> sequence;
|
||||
@@ -290,7 +308,7 @@ struct wkt_segment
|
||||
// In Boost.Geometry a segment is represented
|
||||
// in WKT-format like (for 2D): LINESTRING(x y,x y)
|
||||
os << "LINESTRING";
|
||||
wkt_sequence<sequence>::apply(os, points);
|
||||
wkt_sequence<sequence, false>::apply(os, points);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -324,6 +342,7 @@ struct wkt<Linestring, linestring_tag>
|
||||
: detail::wkt::wkt_range
|
||||
<
|
||||
Linestring,
|
||||
false,
|
||||
detail::wkt::prefix_linestring_par,
|
||||
detail::wkt::closing_parenthesis
|
||||
>
|
||||
@@ -355,6 +374,7 @@ struct wkt<Ring, ring_tag>
|
||||
: detail::wkt::wkt_range
|
||||
<
|
||||
Ring,
|
||||
true,
|
||||
detail::wkt::prefix_ring_par_par,
|
||||
detail::wkt::double_closing_parenthesis
|
||||
>
|
||||
@@ -393,7 +413,8 @@ struct wkt<Multi, multi_linestring_tag>
|
||||
Multi,
|
||||
detail::wkt::wkt_sequence
|
||||
<
|
||||
typename boost::range_value<Multi>::type
|
||||
typename boost::range_value<Multi>::type,
|
||||
false
|
||||
>,
|
||||
detail::wkt::prefix_multilinestring
|
||||
>
|
||||
@@ -418,9 +439,10 @@ template <typename Geometry>
|
||||
struct devarianted_wkt
|
||||
{
|
||||
template <typename OutputStream>
|
||||
static inline void apply(OutputStream& os, Geometry const& geometry)
|
||||
static inline void apply(OutputStream& os, Geometry const& geometry,
|
||||
bool force_closure)
|
||||
{
|
||||
wkt<Geometry>::apply(os, geometry);
|
||||
wkt<Geometry>::apply(os, geometry, force_closure);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -431,25 +453,27 @@ struct devarianted_wkt<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
OutputStream& m_os;
|
||||
bool m_force_closure;
|
||||
|
||||
visitor(OutputStream& os)
|
||||
visitor(OutputStream& os, bool force_closure)
|
||||
: m_os(os)
|
||||
, m_force_closure(force_closure)
|
||||
{}
|
||||
|
||||
template <typename Geometry>
|
||||
inline void operator()(Geometry const& geometry) const
|
||||
{
|
||||
devarianted_wkt<Geometry>::apply(m_os, geometry);
|
||||
devarianted_wkt<Geometry>::apply(m_os, geometry, m_force_closure);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OutputStream>
|
||||
static inline void apply(
|
||||
OutputStream& os,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry
|
||||
)
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
bool force_closure)
|
||||
{
|
||||
boost::apply_visitor(visitor<OutputStream>(os), geometry);
|
||||
boost::apply_visitor(visitor<OutputStream>(os, force_closure), geometry);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -473,8 +497,12 @@ class wkt_manipulator
|
||||
{
|
||||
public:
|
||||
|
||||
inline wkt_manipulator(Geometry const& g)
|
||||
// Boost.Geometry, by default, closes polygons explictly, but not rings
|
||||
// NOTE: this might change in the future!
|
||||
inline wkt_manipulator(Geometry const& g,
|
||||
bool force_closure = ! boost::is_same<typename tag<Geometry>::type, ring_tag>::value)
|
||||
: m_geometry(g)
|
||||
, m_force_closure(force_closure)
|
||||
{}
|
||||
|
||||
template <typename Char, typename Traits>
|
||||
@@ -482,13 +510,14 @@ public:
|
||||
std::basic_ostream<Char, Traits>& os,
|
||||
wkt_manipulator const& m)
|
||||
{
|
||||
dispatch::devarianted_wkt<Geometry>::apply(os, m.m_geometry);
|
||||
dispatch::devarianted_wkt<Geometry>::apply(os, m.m_geometry, m.m_force_closure);
|
||||
os.flush();
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
Geometry const& m_geometry;
|
||||
bool m_force_closure;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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)
|
||||
@@ -20,170 +25,56 @@ namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace compare
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
int Direction,
|
||||
typename Point,
|
||||
typename Strategy,
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct compare_loop
|
||||
{
|
||||
typedef typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
Strategy, Direction, Point, Dimension
|
||||
>::type compare_type;
|
||||
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
static inline bool apply(Point const& left, Point const& right)
|
||||
{
|
||||
coordinate_type const& cleft = geometry::get<Dimension>(left);
|
||||
coordinate_type const& cright = geometry::get<Dimension>(right);
|
||||
|
||||
if (geometry::math::equals(cleft, cright))
|
||||
{
|
||||
return compare_loop
|
||||
<
|
||||
Direction, Point, Strategy,
|
||||
Dimension + 1, DimensionCount
|
||||
>::apply(left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
compare_type compare;
|
||||
return compare(cleft, cright);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
int Direction,
|
||||
typename Point,
|
||||
typename Strategy,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct compare_loop<Direction, Point, Strategy, DimensionCount, DimensionCount>
|
||||
{
|
||||
static inline bool apply(Point const&, Point const&)
|
||||
{
|
||||
// On coming here, points are equal. Return true if
|
||||
// direction = 0 (equal), false if -1/1 (greater/less)
|
||||
return Direction == 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <int Direction, typename Point, typename Strategy>
|
||||
struct compare_in_all_dimensions
|
||||
{
|
||||
inline bool operator()(Point const& left, Point const& right) const
|
||||
{
|
||||
return detail::compare::compare_loop
|
||||
<
|
||||
Direction, Point, Strategy,
|
||||
0, geometry::dimension<Point>::type::value
|
||||
>::apply(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Point, typename Strategy, std::size_t Dimension>
|
||||
class compare_in_one_dimension
|
||||
{
|
||||
Strategy compare;
|
||||
|
||||
public :
|
||||
inline bool operator()(Point const& left, Point const& right) const
|
||||
{
|
||||
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
coordinate_type const& cleft = get<Dimension>(left);
|
||||
coordinate_type const& cright = get<Dimension>(right);
|
||||
return compare(cleft, cright);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace detail::compare
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
int Direction,
|
||||
typename Point,
|
||||
typename Strategy,
|
||||
int Dimension
|
||||
>
|
||||
struct compare_geometries
|
||||
: detail::compare::compare_in_one_dimension
|
||||
<
|
||||
Point,
|
||||
typename strategy::compare::detail::select_strategy
|
||||
<
|
||||
Strategy, Direction, Point, Dimension
|
||||
>::type,
|
||||
Dimension
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
// Specialization with -1: compare in all dimensions
|
||||
template <int Direction, typename Point, typename Strategy>
|
||||
struct compare_geometries<Direction, Point, Strategy, -1>
|
||||
: detail::compare::compare_in_all_dimensions<Direction, Point, Strategy>
|
||||
{};
|
||||
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
/*!
|
||||
\brief Less functor, to sort points in ascending order.
|
||||
\ingroup compare
|
||||
\details This functor compares points and orders them on x,
|
||||
then on y, then on z coordinate.
|
||||
\tparam Geometry the geometry
|
||||
\tparam Point the geometry
|
||||
\tparam Dimension the dimension to sort on, defaults to -1,
|
||||
indicating ALL dimensions. That's to say, first on x,
|
||||
on equal x-es then on y, etc.
|
||||
If a dimension is specified, only that dimension is considered
|
||||
\tparam Strategy underlying coordinate comparing functor,
|
||||
defaults to the default comparison strategies
|
||||
related to the point coordinate system. If specified, the specified
|
||||
strategy is used. This can e.g. be std::less<double>.
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
int Dimension = -1,
|
||||
typename Strategy = strategy::compare::default_strategy
|
||||
typename Point = void,
|
||||
int Dimension = -1
|
||||
>
|
||||
struct less
|
||||
: dispatch::compare_geometries
|
||||
<
|
||||
1, // indicates ascending
|
||||
Point,
|
||||
Strategy,
|
||||
Dimension
|
||||
>
|
||||
{
|
||||
typedef Point first_argument_type;
|
||||
typedef Point second_argument_type;
|
||||
typedef bool result_type;
|
||||
|
||||
inline bool operator()(Point const& left, Point const& right) const
|
||||
{
|
||||
typedef typename strategy::compare::services::default_strategy
|
||||
<
|
||||
strategy::compare::less,
|
||||
Point, Point,
|
||||
Dimension
|
||||
>::type strategy_type;
|
||||
|
||||
return strategy_type::apply(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
template <int Dimension>
|
||||
struct less<void, Dimension>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
inline bool operator()(Point1 const& left, Point2 const& right) const
|
||||
{
|
||||
typedef typename strategy::compare::services::default_strategy
|
||||
<
|
||||
strategy::compare::less,
|
||||
Point1, Point2,
|
||||
Dimension
|
||||
>::type strategy_type;
|
||||
|
||||
return strategy_type::apply(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -195,19 +86,44 @@ struct less
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
int Dimension = -1,
|
||||
typename Strategy = strategy::compare::default_strategy
|
||||
typename Point = void,
|
||||
int Dimension = -1
|
||||
>
|
||||
struct greater
|
||||
: dispatch::compare_geometries
|
||||
<
|
||||
-1, // indicates descending
|
||||
Point,
|
||||
Strategy,
|
||||
Dimension
|
||||
>
|
||||
{};
|
||||
{
|
||||
typedef Point first_argument_type;
|
||||
typedef Point second_argument_type;
|
||||
typedef bool result_type;
|
||||
|
||||
bool operator()(Point const& left, Point const& right) const
|
||||
{
|
||||
typedef typename strategy::compare::services::default_strategy
|
||||
<
|
||||
strategy::compare::greater,
|
||||
Point, Point,
|
||||
Dimension
|
||||
>::type strategy_type;
|
||||
|
||||
return strategy_type::apply(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
template <int Dimension>
|
||||
struct greater<void, Dimension>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
bool operator()(Point1 const& left, Point2 const& right) const
|
||||
{
|
||||
typedef typename strategy::compare::services::default_strategy
|
||||
<
|
||||
strategy::compare::greater,
|
||||
Point1, Point2,
|
||||
Dimension
|
||||
>::type strategy_type;
|
||||
|
||||
return strategy_type::apply(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
@@ -217,23 +133,47 @@ struct greater
|
||||
\tparam Dimension the dimension to compare on, defaults to -1,
|
||||
indicating ALL dimensions.
|
||||
If a dimension is specified, only that dimension is considered
|
||||
\tparam Strategy underlying coordinate comparing functor
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
int Dimension = -1,
|
||||
typename Strategy = strategy::compare::default_strategy
|
||||
int Dimension = -1
|
||||
>
|
||||
struct equal_to
|
||||
: dispatch::compare_geometries
|
||||
<
|
||||
0,
|
||||
Point,
|
||||
Strategy,
|
||||
Dimension
|
||||
>
|
||||
{};
|
||||
{
|
||||
typedef Point first_argument_type;
|
||||
typedef Point second_argument_type;
|
||||
typedef bool result_type;
|
||||
|
||||
bool operator()(Point const& left, Point const& right) const
|
||||
{
|
||||
typedef typename strategy::compare::services::default_strategy
|
||||
<
|
||||
strategy::compare::equal_to,
|
||||
Point, Point,
|
||||
Dimension
|
||||
>::type strategy_type;
|
||||
|
||||
return strategy_type::apply(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
template <int Dimension>
|
||||
struct equal_to<void, Dimension>
|
||||
{
|
||||
template <typename Point1, typename Point2>
|
||||
bool operator()(Point1 const& left, Point2 const& right) const
|
||||
{
|
||||
typedef typename strategy::compare::services::default_strategy
|
||||
<
|
||||
strategy::compare::equal_to,
|
||||
Point1, Point2,
|
||||
Dimension
|
||||
>::type strategy_type;
|
||||
|
||||
return strategy_type::apply(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
@@ -32,7 +32,7 @@ struct point_in_point
|
||||
{
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
return detail::equals::equals_point_point(point1, point2);
|
||||
return geometry::detail::equals::equals_point_point(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -18,14 +18,15 @@
|
||||
#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
|
||||
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
#include <boost/geometry/strategies/covered_by.hpp>
|
||||
#include <boost/geometry/strategies/within.hpp>
|
||||
#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -34,292 +35,63 @@ namespace boost { namespace geometry
|
||||
namespace strategy { namespace within
|
||||
{
|
||||
|
||||
// 1 deg or pi/180 rad
|
||||
template <typename Point,
|
||||
typename CalculationType = typename coordinate_type<Point>::type>
|
||||
struct winding_small_angle
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
typedef typename coordinate_system<Point>::type cs_t;
|
||||
typedef math::detail::constants_on_spheroid
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename PointOfSegment,
|
||||
typename CalculationType,
|
||||
typename CSTag = typename tag_cast
|
||||
<
|
||||
typename cs_tag<Point>::type,
|
||||
spherical_tag
|
||||
>::type
|
||||
>
|
||||
struct winding_base_type
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(false,
|
||||
NOT_IMPLEMENTED_FOR_THIS_COORDINATE_SYSTEM,
|
||||
(CSTag));
|
||||
};
|
||||
|
||||
template <typename Point, typename PointOfSegment, typename CalculationType>
|
||||
struct winding_base_type<Point, PointOfSegment, CalculationType, cartesian_tag>
|
||||
{
|
||||
typedef within::cartesian_winding<Point, PointOfSegment, CalculationType> type;
|
||||
};
|
||||
|
||||
template <typename Point, typename PointOfSegment, typename CalculationType>
|
||||
struct winding_base_type<Point, PointOfSegment, CalculationType, spherical_tag>
|
||||
{
|
||||
typedef within::detail::spherical_winding_base
|
||||
<
|
||||
CalculationType,
|
||||
typename cs_t::units
|
||||
> constants;
|
||||
|
||||
static inline CalculationType apply()
|
||||
{
|
||||
return constants::half_period() / CalculationType(180);
|
||||
}
|
||||
Point,
|
||||
PointOfSegment,
|
||||
typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type,
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
|
||||
// Fix for https://svn.boost.org/trac/boost/ticket/9628
|
||||
// For floating point coordinates, the <D> coordinate of a point is compared
|
||||
// with the segment's points using some EPS. If the coordinates are "equal"
|
||||
// the sides are calculated. Therefore we can treat a segment as a long areal
|
||||
// geometry having some width. There is a small ~triangular area somewhere
|
||||
// between the segment's effective area and a segment's line used in sides
|
||||
// calculation where the segment is on the one side of the line but on the
|
||||
// other side of a segment (due to the width).
|
||||
// Below picture assuming D = 1, if D = 0 horiz<->vert, E<->N, RIGHT<->UP.
|
||||
// For the s1 of a segment going NE the real side is RIGHT but the point may
|
||||
// be detected as LEFT, like this:
|
||||
// RIGHT
|
||||
// ___----->
|
||||
// ^ O Pt __ __
|
||||
// EPS __ __
|
||||
// v__ __ BUT DETECTED AS LEFT OF THIS LINE
|
||||
// _____7
|
||||
// _____/
|
||||
// _____/
|
||||
// In the code below actually D = 0, so segments are nearly-vertical
|
||||
// Called when the point is on the same level as one of the segment's points
|
||||
// but the point is not aligned with a vertical segment
|
||||
template <typename CSTag>
|
||||
struct winding_side_equal
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
CSTag
|
||||
>::type strategy_side_type;
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline int apply(Point const& point,
|
||||
PointOfSegment const& se,
|
||||
int count)
|
||||
{
|
||||
typedef typename coordinate_type<PointOfSegment>::type scoord_t;
|
||||
typedef typename coordinate_system<PointOfSegment>::type::units units_t;
|
||||
|
||||
if (math::equals(get<1>(point), get<1>(se)))
|
||||
return 0;
|
||||
|
||||
// Create a horizontal segment intersecting the original segment's endpoint
|
||||
// equal to the point, with the derived direction (E/W).
|
||||
PointOfSegment ss1, ss2;
|
||||
set<1>(ss1, get<1>(se));
|
||||
set<0>(ss1, get<0>(se));
|
||||
set<1>(ss2, get<1>(se));
|
||||
scoord_t ss20 = get<0>(se);
|
||||
if (count > 0)
|
||||
{
|
||||
ss20 += winding_small_angle<PointOfSegment>::apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
ss20 -= winding_small_angle<PointOfSegment>::apply();
|
||||
}
|
||||
math::normalize_longitude<units_t>(ss20);
|
||||
set<0>(ss2, ss20);
|
||||
|
||||
// Check the side using this vertical segment
|
||||
return strategy_side_type::apply(ss1, ss2, point);
|
||||
}
|
||||
};
|
||||
// The optimization for cartesian
|
||||
template <>
|
||||
struct winding_side_equal<cartesian_tag>
|
||||
{
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline int apply(Point const& point,
|
||||
PointOfSegment const& se,
|
||||
int count)
|
||||
{
|
||||
// NOTE: for D=0 the signs would be reversed
|
||||
return math::equals(get<1>(point), get<1>(se)) ?
|
||||
0 :
|
||||
get<1>(point) < get<1>(se) ?
|
||||
// assuming count is equal to 1 or -1
|
||||
-count : // ( count > 0 ? -1 : 1) :
|
||||
count; // ( count > 0 ? 1 : -1) ;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Point,
|
||||
typename CalculationType,
|
||||
typename CSTag = typename cs_tag<Point>::type>
|
||||
struct winding_check_touch
|
||||
{
|
||||
typedef CalculationType calc_t;
|
||||
typedef typename coordinate_system<Point>::type::units units_t;
|
||||
typedef math::detail::constants_on_spheroid<CalculationType, units_t> constants;
|
||||
|
||||
template <typename PointOfSegment, typename State>
|
||||
static inline int apply(Point const& point,
|
||||
PointOfSegment const& seg1,
|
||||
PointOfSegment const& seg2,
|
||||
State& state,
|
||||
bool& eq1,
|
||||
bool& eq2)
|
||||
{
|
||||
calc_t const pi = constants::half_period();
|
||||
calc_t const pi2 = pi / calc_t(2);
|
||||
|
||||
calc_t const px = get<0>(point);
|
||||
calc_t const s1x = get<0>(seg1);
|
||||
calc_t const s2x = get<0>(seg2);
|
||||
calc_t const py = get<1>(point);
|
||||
calc_t const s1y = get<1>(seg1);
|
||||
calc_t const s2y = get<1>(seg2);
|
||||
|
||||
// NOTE: lat in {-90, 90} and arbitrary lon
|
||||
// it doesn't matter what lon it is if it's a pole
|
||||
// so e.g. if one of the segment endpoints is a pole
|
||||
// then only the other lon matters
|
||||
|
||||
bool eq1_strict = math::equals(s1x, px);
|
||||
bool eq2_strict = math::equals(s2x, px);
|
||||
|
||||
eq1 = eq1_strict // lon strictly equal to s1
|
||||
|| math::equals(s1y, pi2) || math::equals(s1y, -pi2); // s1 is pole
|
||||
eq2 = eq2_strict // lon strictly equal to s2
|
||||
|| math::equals(s2y, pi2) || math::equals(s2y, -pi2); // s2 is pole
|
||||
|
||||
// segment overlapping pole
|
||||
calc_t s1x_anti = s1x + constants::half_period();
|
||||
math::normalize_longitude<units_t, calc_t>(s1x_anti);
|
||||
bool antipodal = math::equals(s2x, s1x_anti);
|
||||
if (antipodal)
|
||||
{
|
||||
eq1 = eq2 = eq1 || eq2;
|
||||
|
||||
// segment overlapping pole and point is pole
|
||||
if (math::equals(py, pi2) || math::equals(py, -pi2))
|
||||
{
|
||||
eq1 = eq2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Both equal p -> segment vertical
|
||||
// The only thing which has to be done is check if point is ON segment
|
||||
if (eq1 && eq2)
|
||||
{
|
||||
// segment endpoints on the same sides of the globe
|
||||
if (! antipodal
|
||||
// p's lat between segment endpoints' lats
|
||||
? (s1y <= py && s2y >= py) || (s2y <= py && s1y >= py)
|
||||
// going through north or south pole?
|
||||
: (pi - s1y - s2y <= pi
|
||||
? (eq1_strict && s1y <= py) || (eq2_strict && s2y <= py) // north
|
||||
|| math::equals(py, pi2) // point on north pole
|
||||
: (eq1_strict && s1y >= py) || (eq2_strict && s2y >= py)) // south
|
||||
|| math::equals(py, -pi2) // point on south pole
|
||||
)
|
||||
{
|
||||
state.m_touches = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// The optimization for cartesian
|
||||
template <typename Point, typename CalculationType>
|
||||
struct winding_check_touch<Point, CalculationType, cartesian_tag>
|
||||
{
|
||||
typedef CalculationType calc_t;
|
||||
|
||||
template <typename PointOfSegment, typename State>
|
||||
static inline bool apply(Point const& point,
|
||||
PointOfSegment const& seg1,
|
||||
PointOfSegment const& seg2,
|
||||
State& state,
|
||||
bool& eq1,
|
||||
bool& eq2)
|
||||
{
|
||||
calc_t const px = get<0>(point);
|
||||
calc_t const s1x = get<0>(seg1);
|
||||
calc_t const s2x = get<0>(seg2);
|
||||
|
||||
eq1 = math::equals(s1x, px);
|
||||
eq2 = math::equals(s2x, px);
|
||||
|
||||
// Both equal p -> segment vertical
|
||||
// The only thing which has to be done is check if point is ON segment
|
||||
if (eq1 && eq2)
|
||||
{
|
||||
calc_t const py = get<1>(point);
|
||||
calc_t const s1y = get<1>(seg1);
|
||||
calc_t const s2y = get<1>(seg2);
|
||||
if ((s1y <= py && s2y >= py) || (s2y <= py && s1y >= py))
|
||||
{
|
||||
state.m_touches = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Called if point is not aligned with a vertical segment
|
||||
template <typename Point,
|
||||
typename CalculationType,
|
||||
typename CSTag = typename cs_tag<Point>::type>
|
||||
struct winding_calculate_count
|
||||
{
|
||||
typedef CalculationType calc_t;
|
||||
typedef typename coordinate_system<Point>::type::units units_t;
|
||||
|
||||
static inline bool greater(calc_t const& l, calc_t const& r)
|
||||
{
|
||||
calc_t diff = l - r;
|
||||
math::normalize_longitude<units_t, calc_t>(diff);
|
||||
return diff > calc_t(0);
|
||||
}
|
||||
|
||||
static inline int apply(calc_t const& p,
|
||||
calc_t const& s1, calc_t const& s2,
|
||||
bool eq1, bool eq2)
|
||||
{
|
||||
// Probably could be optimized by avoiding normalization for some comparisons
|
||||
// e.g. s1 > p could be calculated from p > s1
|
||||
|
||||
// If both segment endpoints were poles below checks wouldn't be enough
|
||||
// but this means that either both are the same or that they are N/S poles
|
||||
// and therefore the segment is not valid.
|
||||
// If needed (eq1 && eq2 ? 0) could be returned
|
||||
|
||||
return
|
||||
eq1 ? (greater(s2, p) ? 1 : -1) // Point on level s1, E/W depending on s2
|
||||
: eq2 ? (greater(s1, p) ? -1 : 1) // idem
|
||||
: greater(p, s1) && greater(s2, p) ? 2 // Point between s1 -> s2 --> E
|
||||
: greater(p, s2) && greater(s1, p) ? -2 // Point between s2 -> s1 --> W
|
||||
: 0;
|
||||
}
|
||||
};
|
||||
// The optimization for cartesian
|
||||
template <typename Point, typename CalculationType>
|
||||
struct winding_calculate_count<Point, CalculationType, cartesian_tag>
|
||||
{
|
||||
typedef CalculationType calc_t;
|
||||
|
||||
static inline int apply(calc_t const& p,
|
||||
calc_t const& s1, calc_t const& s2,
|
||||
bool eq1, bool eq2)
|
||||
{
|
||||
return
|
||||
eq1 ? (s2 > p ? 1 : -1) // Point on level s1, E/W depending on s2
|
||||
: eq2 ? (s1 > p ? -1 : 1) // idem
|
||||
: s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> E
|
||||
: s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> W
|
||||
: 0;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
/*!
|
||||
\brief Within detection using winding rule
|
||||
\brief Within detection using winding rule. Side strategy used internally is
|
||||
choosen based on Point's coordinate system.
|
||||
\ingroup strategies
|
||||
\tparam Point \tparam_point
|
||||
\tparam PointOfSegment \tparam_segment_point
|
||||
\tparam SideStrategy Side strategy
|
||||
\tparam CalculationType \tparam_calculation
|
||||
\author Barend Gehrels
|
||||
\note The implementation is inspired by terralib http://www.terralib.org (LGPL)
|
||||
\note but totally revised afterwards, especially for cases on segments
|
||||
\note Only dependant on "side", -> agnostic, suitable for spherical/latlong
|
||||
|
||||
\qbk{
|
||||
[heading See also]
|
||||
@@ -330,245 +102,32 @@ template
|
||||
<
|
||||
typename Point,
|
||||
typename PointOfSegment = Point,
|
||||
typename SideStrategy = typename strategy::side::services::default_strategy
|
||||
<
|
||||
typename cs_tag<Point>::type
|
||||
>::type,
|
||||
typename CalculationType = void
|
||||
>
|
||||
class winding
|
||||
{
|
||||
typedef typename select_calculation_type
|
||||
: public within::detail::winding_base_type
|
||||
<
|
||||
Point,
|
||||
PointOfSegment,
|
||||
CalculationType
|
||||
>::type calculation_type;
|
||||
|
||||
/*! subclass to keep state */
|
||||
class counter
|
||||
{
|
||||
int m_count;
|
||||
bool m_touches;
|
||||
|
||||
inline int code() const
|
||||
{
|
||||
return m_touches ? 0 : m_count == 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
public :
|
||||
friend class winding;
|
||||
|
||||
template <typename P, typename CT, typename CST>
|
||||
friend struct winding_check_touch;
|
||||
|
||||
inline counter()
|
||||
: m_count(0)
|
||||
, m_touches(false)
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
static inline int check_segment(Point const& point,
|
||||
PointOfSegment const& seg1, PointOfSegment const& seg2,
|
||||
counter& state, bool& eq1, bool& eq2)
|
||||
{
|
||||
if (winding_check_touch<Point, calculation_type>
|
||||
::apply(point, seg1, seg2, state, eq1, eq2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
calculation_type const p = get<0>(point);
|
||||
calculation_type const s1 = get<0>(seg1);
|
||||
calculation_type const s2 = get<0>(seg2);
|
||||
return winding_calculate_count<Point, calculation_type>
|
||||
::apply(p, s1, s2, eq1, eq2);
|
||||
}
|
||||
|
||||
Point, PointOfSegment, CalculationType
|
||||
>::type
|
||||
{
|
||||
typedef typename within::detail::winding_base_type
|
||||
<
|
||||
Point, PointOfSegment, CalculationType
|
||||
>::type base_t;
|
||||
|
||||
public:
|
||||
typedef typename SideStrategy::envelope_strategy_type envelope_strategy_type;
|
||||
winding() {}
|
||||
|
||||
inline envelope_strategy_type get_envelope_strategy() const
|
||||
{
|
||||
return m_side_strategy.get_envelope_strategy();
|
||||
}
|
||||
|
||||
typedef typename SideStrategy::disjoint_strategy_type disjoint_strategy_type;
|
||||
|
||||
inline disjoint_strategy_type get_disjoint_strategy() const
|
||||
{
|
||||
return m_side_strategy.get_disjoint_strategy();
|
||||
}
|
||||
|
||||
winding()
|
||||
template <typename Model>
|
||||
explicit winding(Model const& model)
|
||||
: base_t(model)
|
||||
{}
|
||||
|
||||
explicit winding(SideStrategy const& side_strategy)
|
||||
: m_side_strategy(side_strategy)
|
||||
{}
|
||||
|
||||
// Typedefs and static methods to fulfill the concept
|
||||
typedef Point point_type;
|
||||
typedef PointOfSegment segment_point_type;
|
||||
typedef counter state_type;
|
||||
|
||||
inline bool apply(Point const& point,
|
||||
PointOfSegment const& s1, PointOfSegment const& s2,
|
||||
counter& state) const
|
||||
{
|
||||
typedef typename cs_tag<Point>::type cs_t;
|
||||
|
||||
bool eq1 = false;
|
||||
bool eq2 = false;
|
||||
boost::ignore_unused(eq2);
|
||||
|
||||
int count = check_segment(point, s1, s2, state, eq1, eq2);
|
||||
if (count != 0)
|
||||
{
|
||||
int side = 0;
|
||||
if (count == 1 || count == -1)
|
||||
{
|
||||
side = winding_side_equal<cs_t>::apply(point, eq1 ? s1 : s2, count);
|
||||
}
|
||||
else // count == 2 || count == -2
|
||||
{
|
||||
// 1 left, -1 right
|
||||
side = m_side_strategy.apply(s1, s2, point);
|
||||
}
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
// Point is lying on segment
|
||||
state.m_touches = true;
|
||||
state.m_count = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Side is NEG for right, POS for left.
|
||||
// The count is -2 for down, 2 for up (or -1/1)
|
||||
// Side positive thus means UP and LEFTSIDE or DOWN and RIGHTSIDE
|
||||
// See accompagnying figure (TODO)
|
||||
if (side * count > 0)
|
||||
{
|
||||
state.m_count += count;
|
||||
}
|
||||
}
|
||||
return ! state.m_touches;
|
||||
}
|
||||
|
||||
static inline int result(counter const& state)
|
||||
{
|
||||
return state.code();
|
||||
}
|
||||
|
||||
private:
|
||||
SideStrategy m_side_strategy;
|
||||
};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
|
||||
{
|
||||
typedef winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
|
||||
{
|
||||
typedef winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
|
||||
{
|
||||
typedef winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
|
||||
{
|
||||
typedef winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
} // namespace services
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}} // namespace strategy::within
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
namespace strategy { namespace covered_by { namespace services
|
||||
{
|
||||
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
|
||||
{
|
||||
typedef within::winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
|
||||
{
|
||||
typedef within::winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
|
||||
{
|
||||
typedef within::winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
|
||||
{
|
||||
typedef within::winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
}}} // namespace strategy::covered_by::services
|
||||
#endif
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
#include <boost/geometry/util/promote_integral.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategies/covered_by.hpp>
|
||||
#include <boost/geometry/strategies/intersection.hpp>
|
||||
@@ -81,11 +81,10 @@ struct cartesian_segments
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct point_in_geometry_strategy
|
||||
{
|
||||
typedef strategy::within::winding
|
||||
typedef strategy::within::cartesian_winding
|
||||
<
|
||||
typename point_type<Geometry1>::type,
|
||||
typename point_type<Geometry2>::type,
|
||||
side_strategy_type,
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user