mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-11 05:24:02 +00:00
Merge branch 'develop' into feature/gc3
This commit is contained in:
commit
8c9b11bb85
@ -60,7 +60,7 @@ jobs:
|
||||
git submodule update --init tools/build
|
||||
git submodule update --init libs/config
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py geometry
|
||||
python tools/boostdep/depinst/depinst.py geometry -I index/test
|
||||
./bootstrap.sh
|
||||
./b2 headers
|
||||
- run: mkdir $COVERAGE_DIR
|
||||
|
23
LICENSE_1_0.txt
Normal file
23
LICENSE_1_0.txt
Normal file
@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
@ -3,6 +3,10 @@
|
||||
|
||||
// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021 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)
|
||||
@ -57,7 +61,7 @@ void test_connect(std::string const& caseid, Geometry const& geometry,
|
||||
std::size_t count = boost::size(connected_vector);
|
||||
std::size_t point_count = 0;
|
||||
|
||||
BOOST_FOREACH(GeometryOut& connected, connected_vector)
|
||||
for (GeometryOut& connected : connected_vector)
|
||||
{
|
||||
bg::unique(connected);
|
||||
length += bg::length(connected);
|
||||
@ -99,7 +103,7 @@ void test_connect(std::string const& caseid, Geometry const& geometry,
|
||||
|
||||
|
||||
mapper.map(geometry, "opacity:0.6;fill:rgb(0,0,255);stroke:rgb(0,0,0);stroke-width:1");
|
||||
BOOST_FOREACH(GeometryOut& connected, connected_vector)
|
||||
for (GeometryOut& connected : connected_vector)
|
||||
{
|
||||
mapper.map(connected, "opacity:0.6;fill:none;stroke:rgb(255,0,0);stroke-width:5");
|
||||
}
|
||||
|
@ -6,6 +6,10 @@
|
||||
// Contributed and/or modified by Tinko Bartels,
|
||||
// as part of Google Summer of Code 2019 program.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, 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)
|
||||
@ -13,7 +17,7 @@
|
||||
#include <geometry_test_common.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/point_xy.hpp>
|
||||
#include <boost/geometry/extensions/triangulation/strategies/cartesian/in_circle_robust.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/in_circle_robust.hpp>
|
||||
|
||||
template <typename P>
|
||||
void test_all()
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <boost/geometry/algorithms/comparable_distance.hpp>
|
||||
#include <boost/geometry/algorithms/equals.hpp>
|
||||
#include <boost/geometry/algorithms/expand.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
|
||||
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/turn_in_ring_winding.hpp>
|
||||
|
@ -39,7 +39,8 @@
|
||||
|
||||
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
#include <boost/geometry/strategies/spherical/ssf.hpp>
|
||||
#include <boost/geometry/strategies/normalize.hpp>
|
||||
|
||||
@ -61,11 +62,11 @@ struct collected_vector
|
||||
: nyi::not_implemented_tag
|
||||
{};
|
||||
|
||||
// compatible with side_by_triangle cartesian strategy
|
||||
// compatible with side_robust cartesian strategy
|
||||
template <typename T, typename Geometry, typename CT, typename CSTag>
|
||||
struct collected_vector
|
||||
<
|
||||
T, Geometry, strategy::side::side_by_triangle<CT>, CSTag
|
||||
T, Geometry, strategy::side::side_robust<CT>, CSTag
|
||||
>
|
||||
{
|
||||
typedef T type;
|
||||
@ -156,6 +157,14 @@ private:
|
||||
//T dx_0, dy_0;
|
||||
};
|
||||
|
||||
template <typename T, typename Geometry, typename CT, typename CSTag>
|
||||
struct collected_vector
|
||||
<
|
||||
T, Geometry, strategy::side::side_by_triangle<CT>, CSTag
|
||||
>
|
||||
: collected_vector<T, Geometry, strategy::side::side_robust<CT>, CSTag>
|
||||
{};
|
||||
|
||||
// Compatible with spherical_side_formula which currently
|
||||
// is the default spherical_equatorial and geographic strategy
|
||||
// so CSTag is spherical_equatorial_tag or geographic_tag
|
||||
|
111
include/boost/geometry/core/coordinate_promotion.hpp
Normal file
111
include/boost/geometry/core/coordinate_promotion.hpp
Normal file
@ -0,0 +1,111 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021 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_CORE_COORDINATE_PROMOTION_HPP
|
||||
#define BOOST_GEOMETRY_CORE_COORDINATE_PROMOTION_HPP
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
// TODO: move this to a future headerfile implementing traits for these types
|
||||
#include <boost/rational.hpp>
|
||||
#include <boost/multiprecision/cpp_bin_float.hpp>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace traits
|
||||
{
|
||||
|
||||
// todo
|
||||
|
||||
} // namespace traits
|
||||
|
||||
/*!
|
||||
\brief Meta-function converting, if necessary, to "a floating point" type
|
||||
\details
|
||||
- if input type is integer, type is double
|
||||
- else type is input type
|
||||
\ingroup utility
|
||||
*/
|
||||
// TODO: replace with, or call, promoted_to_floating_point
|
||||
template <typename T, typename PromoteIntegerTo = double>
|
||||
struct promote_floating_point
|
||||
{
|
||||
typedef std::conditional_t
|
||||
<
|
||||
std::is_integral<T>::value,
|
||||
PromoteIntegerTo,
|
||||
T
|
||||
> type;
|
||||
};
|
||||
|
||||
// TODO: replace with promoted_to_floating_point
|
||||
template <typename Geometry>
|
||||
struct fp_coordinate_type
|
||||
{
|
||||
typedef typename promote_floating_point
|
||||
<
|
||||
typename coordinate_type<Geometry>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Promote any integral type to double. Floating point
|
||||
// and other user defined types stay as they are, unless specialized.
|
||||
// TODO: we shold add a coordinate_promotion traits for promotion to
|
||||
// floating point or (larger) integer types.
|
||||
template <typename Type>
|
||||
struct promoted_to_floating_point
|
||||
{
|
||||
using type = std::conditional_t
|
||||
<
|
||||
std::is_integral<Type>::value, double, Type
|
||||
>;
|
||||
};
|
||||
|
||||
// Boost.Rational goes to double
|
||||
template <typename T>
|
||||
struct promoted_to_floating_point<boost::rational<T>>
|
||||
{
|
||||
using type = double;
|
||||
};
|
||||
|
||||
// Any Boost.Multiprecision goes to double (for example int128_t),
|
||||
// unless specialized
|
||||
template <typename Backend>
|
||||
struct promoted_to_floating_point<boost::multiprecision::number<Backend>>
|
||||
{
|
||||
using type = double;
|
||||
};
|
||||
|
||||
// Boost.Multiprecision binary floating point numbers are used as FP.
|
||||
template <unsigned Digits>
|
||||
struct promoted_to_floating_point
|
||||
<
|
||||
boost::multiprecision::number
|
||||
<
|
||||
boost::multiprecision::cpp_bin_float<Digits>
|
||||
>
|
||||
>
|
||||
{
|
||||
using type = boost::multiprecision::number
|
||||
<
|
||||
boost::multiprecision::cpp_bin_float<Digits>
|
||||
>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_CORE_COORDINATE_PROMOTION_HPP
|
@ -22,7 +22,6 @@
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/static_assert.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/type_traits_std.hpp>
|
||||
|
||||
|
||||
@ -94,15 +93,6 @@ struct coordinate_type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct fp_coordinate_type
|
||||
{
|
||||
typedef typename promote_floating_point
|
||||
<
|
||||
typename coordinate_type<Geometry>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief assert_coordinate_type_equal, a compile-time check for equality of two coordinate types
|
||||
\ingroup utility
|
||||
|
@ -27,8 +27,7 @@
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
|
@ -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 2020.
|
||||
// Modifications copyright (c) 2020, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2020-2021.
|
||||
// Modifications copyright (c) 2020-2021, 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,
|
||||
@ -30,10 +30,9 @@
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/default_distance_result.hpp>
|
||||
#include <boost/geometry/strategies/distance/cartesian.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/extensions/strategies/cartesian/distance_info.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2020.
|
||||
// Modifications copyright (c) 2020, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2020-2021.
|
||||
// Modifications copyright (c) 2020-2021, 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,
|
||||
@ -31,7 +31,7 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/detail/endian.hpp>
|
||||
#include <boost/predef/other/endian.h>
|
||||
|
||||
#if CHAR_BIT != 8
|
||||
#error Platforms with CHAR_BIT != 8 are not supported
|
||||
@ -50,10 +50,16 @@ namespace detail { namespace endian
|
||||
struct big_endian_tag {};
|
||||
struct little_endian_tag {};
|
||||
|
||||
#ifdef BOOST_BIG_ENDIAN
|
||||
#if defined(BOOST_ENDIAN_BIG_BYTE_AVAILABLE)
|
||||
typedef big_endian_tag native_endian_tag;
|
||||
#else
|
||||
#elif defined(BOOST_ENDIAN_LITTLE_BYTE_AVAILABLE)
|
||||
typedef little_endian_tag native_endian_tag;
|
||||
#elif defined(BOOST_ENDIAN_BIG_WORD_BYTE_AVAILABLE)
|
||||
#error Word-swapped big-endian not supported
|
||||
#elif defined(BOOST_ENDIAN_LITTLE_WORD_BYTE_AVAILABLE)
|
||||
#error Word-swapped little-endian not supported
|
||||
#else
|
||||
#error Unknown endian memory ordering
|
||||
#endif
|
||||
|
||||
// Unrolled loops for loading and storing streams of bytes.
|
||||
|
@ -1,50 +0,0 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
#ifndef BOOST_GEOMETRY_EXTENSIONS_NSPHERE_GEOMETRIES_CONCEPTS_CHECK_HPP
|
||||
#define BOOST_GEOMETRY_EXTENSIONS_NSPHERE_GEOMETRIES_CONCEPTS_CHECK_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DISPATCH
|
||||
namespace dispatch
|
||||
{
|
||||
|
||||
template <typename Geometry>
|
||||
struct check<Geometry, nsphere_tag, true>
|
||||
: detail::concept_check::check<concepts::ConstNsphere<Geometry> >
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
struct check<Geometry, nsphere_tag, false>
|
||||
: detail::concept_check::check<concepts::Nsphere<Geometry> >
|
||||
{};
|
||||
|
||||
} // namespace dispatch
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_EXTENSIONS_NSPHERE_GEOMETRIES_CONCEPTS_CHECK_HPP
|
@ -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 2021.
|
||||
// Modifications copyright (c) 2021, 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.
|
||||
|
||||
@ -117,6 +121,18 @@ public :
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct concept_type<Geometry, nsphere_tag>
|
||||
{
|
||||
using type = Nsphere<Geometry>;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct concept_type<Geometry const, nsphere_tag>
|
||||
{
|
||||
using type = ConstNsphere<Geometry>;
|
||||
};
|
||||
|
||||
|
||||
}}} // namespace boost::geometry::concepts
|
||||
|
||||
|
@ -5,6 +5,10 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, 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.
|
||||
|
||||
@ -22,7 +26,6 @@
|
||||
#include <boost/geometry/extensions/nsphere/core/tags.hpp>
|
||||
#include <boost/geometry/extensions/nsphere/core/topological_dimension.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/nsphere/geometries/concepts/check.hpp>
|
||||
#include <boost/geometry/extensions/nsphere/geometries/concepts/nsphere_concept.hpp>
|
||||
|
||||
#include <boost/geometry/extensions/nsphere/geometries/nsphere.hpp>
|
||||
|
107
include/boost/geometry/index/detail/maxmin_heap.hpp
Normal file
107
include/boost/geometry/index/detail/maxmin_heap.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_MAXMIN_HEAP_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_MAXMIN_HEAP_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/minmax_heap.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail
|
||||
{
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void push_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
minmax_heap_detail::push_heap<max_call, min_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void push_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
minmax_heap_detail::push_heap<max_call, min_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void pop_top_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
pop_heap<max_call, min_call>(first, first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void pop_top_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
pop_heap<max_call, min_call>(first, first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void pop_bottom_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
It bottom = minmax_heap_detail::bottom_heap<max_call>(first, last, comp);
|
||||
pop_heap<max_call, min_call>(first, bottom, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void pop_bottom_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
auto&& comp = std::less<>();
|
||||
It bottom = minmax_heap_detail::bottom_heap<max_call>(first, last, comp);
|
||||
pop_heap<max_call, min_call>(first, bottom, last, comp);
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void make_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::make_heap<max_call, min_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void make_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::make_heap<max_call, min_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline bool is_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::is_heap<max_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline bool is_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::is_heap<max_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline decltype(auto) bottom_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return *minmax_heap_detail::bottom_heap<max_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline decltype(auto) bottom_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return *minmax_heap_detail::bottom_heap<max_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_MAXMIN_HEAP_HPP
|
519
include/boost/geometry/index/detail/minmax_heap.hpp
Normal file
519
include/boost/geometry/index/detail/minmax_heap.hpp
Normal file
@ -0,0 +1,519 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_MINMAX_HEAP_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_MINMAX_HEAP_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#ifdef _MSC_VER // msvc and clang-win
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail
|
||||
{
|
||||
|
||||
// Resources:
|
||||
// https://en.wikipedia.org/wiki/Min-max_heap
|
||||
// http://akira.ruc.dk/~keld/teaching/algoritmedesign_f03/Artikler/02/Atkinson86.pdf
|
||||
// https://probablydance.com/2020/08/31/on-modern-hardware-the-min-max-heap-beats-a-binary-heap/
|
||||
// https://stackoverflow.com/questions/6531543/efficient-implementation-of-binary-heaps
|
||||
// https://stackoverflow.com/questions/994593/how-to-do-an-integer-log2-in-c
|
||||
|
||||
namespace minmax_heap_detail
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
using bitsize = std::integral_constant<std::size_t, sizeof(T) * CHAR_BIT>;
|
||||
|
||||
template <typename It>
|
||||
using diff_t = typename std::iterator_traits<It>::difference_type;
|
||||
template <typename It>
|
||||
using val_t = typename std::iterator_traits<It>::value_type;
|
||||
|
||||
// TODO: In C++20 use std::bit_width()
|
||||
|
||||
template <typename T, std::enable_if_t<!std::is_integral<T>::value || (bitsize<T>::value != 32 && bitsize<T>::value != 64), int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
++i;
|
||||
int r = 0;
|
||||
while (i >>= 1) { ++r; }
|
||||
return r;
|
||||
}
|
||||
|
||||
//template <typename T>
|
||||
//inline int level(T i)
|
||||
//{
|
||||
// using std::log2;
|
||||
// return int(log2(i + 1));
|
||||
//}
|
||||
|
||||
#ifdef _MSC_VER // msvc and clang-win
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 32, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse(&r, (unsigned long)(i + 1));
|
||||
return int(r);
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 64, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
unsigned long r = 0;
|
||||
#ifdef _WIN64
|
||||
_BitScanReverse64(&r, (unsigned long long)(i + 1));
|
||||
#else
|
||||
if (_BitScanReverse(&r, (unsigned long)((i + 1) >> 32))) { r += 32; }
|
||||
else { _BitScanReverse(&r, (unsigned long)(i + 1)); }
|
||||
#endif
|
||||
return int(r);
|
||||
}
|
||||
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
// Only available in gcc-10 and clang-10
|
||||
//#elif defined(__has_builtin) && __has_builtin(__builtin_clzl) && __has_builtin(__builtin_clzll)
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 32, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
return 31 - __builtin_clzl((unsigned long)(i + 1));
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 64, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
return 63 - __builtin_clzll((unsigned long long)(i + 1));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 32, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
++i;
|
||||
int r = 0;
|
||||
if (i >= 65536) { r += 16; i >>= 16; }
|
||||
if (i >= 256) { r += 8; i >>= 8; }
|
||||
if (i >= 16) { r += 4; i >>= 4; }
|
||||
if (i >= 4) { r += 2; i >>= 2; }
|
||||
if (i >= 2) { r += 1; i >>= 1; }
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 64, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
++i;
|
||||
int r = 0;
|
||||
if (i >= 4294967296ll) { r += 32; i >>= 32; }
|
||||
if (i >= 65536ll) { r += 16; i >>= 16; }
|
||||
if (i >= 256ll) { r += 8; i >>= 8; }
|
||||
if (i >= 16ll) { r += 4; i >>= 4; }
|
||||
if (i >= 4ll) { r += 2; i >>= 2; }
|
||||
if (i >= 2ll) { r += 1; i >>= 1; }
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// min/max functions only differ in the order of arguments in comp
|
||||
struct min_call
|
||||
{
|
||||
template <typename Compare, typename T1, typename T2>
|
||||
bool operator()(Compare&& comp, T1 const& v1, T2 const& v2) const
|
||||
{
|
||||
return comp(v1, v2);
|
||||
}
|
||||
};
|
||||
|
||||
struct max_call
|
||||
{
|
||||
template <typename Compare, typename T1, typename T2>
|
||||
bool operator()(Compare&& comp, T1 const& v1, T2 const& v2) const
|
||||
{
|
||||
return comp(v2, v1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Call, typename It, typename Compare>
|
||||
inline void push_heap2(It first, diff_t<It> c, val_t<It> val, Compare comp)
|
||||
{
|
||||
while (c > 2)
|
||||
{
|
||||
diff_t<It> const g = (c - 3) >> 2; // grandparent index
|
||||
if (! Call()(comp, val, *(first + g)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
*(first + c) = std::move(*(first + g));
|
||||
c = g;
|
||||
}
|
||||
|
||||
*(first + c) = std::move(val);
|
||||
}
|
||||
|
||||
template <typename MinCall, typename MaxCall, typename It, typename Compare>
|
||||
inline void push_heap1(It first, diff_t<It> c, val_t<It> val, Compare comp)
|
||||
{
|
||||
diff_t<It> const p = (c - 1) >> 1; // parent index
|
||||
if (MinCall()(comp, *(first + p), val))
|
||||
{
|
||||
*(first + c) = std::move(*(first + p));
|
||||
return push_heap2<MaxCall>(first, p, std::move(val), comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return push_heap2<MinCall>(first, c, std::move(val), comp);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MinCall, typename MaxCall, typename It, typename Compare>
|
||||
inline void push_heap(It first, It last, Compare comp)
|
||||
{
|
||||
diff_t<It> const size = last - first;
|
||||
if (size < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
diff_t<It> c = size - 1; // back index
|
||||
val_t<It> val = std::move(*(first + c));
|
||||
if (level(c) % 2 == 0) // is min level
|
||||
{
|
||||
push_heap1<MinCall, MaxCall>(first, c, std::move(val), comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
push_heap1<MaxCall, MinCall>(first, c, std::move(val), comp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Call, typename It, typename Compare>
|
||||
inline diff_t<It> pick_grandchild4(It first, diff_t<It> f, Compare comp)
|
||||
{
|
||||
It it = first + f;
|
||||
diff_t<It> m1 = Call()(comp, *(it), *(it + 1)) ? f : f + 1;
|
||||
diff_t<It> m2 = Call()(comp, *(it + 2), *(it + 3)) ? f + 2 : f + 3;
|
||||
return Call()(comp, *(first + m1), *(first + m2)) ? m1 : m2;
|
||||
}
|
||||
|
||||
//template <typename Call, typename It, typename Compare>
|
||||
//inline diff_t<It> pick_descendant(It first, diff_t<It> f, diff_t<It> l, Compare comp)
|
||||
//{
|
||||
// diff_t<It> m = f;
|
||||
// for (++f; f != l; ++f)
|
||||
// {
|
||||
// if (Call()(comp, *(first + f), *(first + m)))
|
||||
// {
|
||||
// m = f;
|
||||
// }
|
||||
// }
|
||||
// return m;
|
||||
//}
|
||||
|
||||
template <typename Call, typename It, typename Compare>
|
||||
inline void pop_heap1(It first, diff_t<It> p, diff_t<It> size, val_t<It> val, Compare comp)
|
||||
{
|
||||
if (size >= 7) // grandparent of 4 grandchildren is possible
|
||||
{
|
||||
diff_t<It> const last_g = (size - 3) >> 2; // grandparent of the element behind back
|
||||
while (p < last_g) // p is grandparent of 4 grandchildren
|
||||
{
|
||||
diff_t<It> const ll = 4 * p + 3;
|
||||
diff_t<It> const m = pick_grandchild4<Call>(first, ll, comp);
|
||||
|
||||
if (! Call()(comp, *(first + m), val))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
*(first + p) = std::move(*(first + m));
|
||||
|
||||
diff_t<It> par = (m - 1) >> 1;
|
||||
if (Call()(comp, *(first + par), val))
|
||||
{
|
||||
using std::swap;
|
||||
swap(*(first + par), val);
|
||||
}
|
||||
|
||||
p = m;
|
||||
}
|
||||
}
|
||||
|
||||
if (size >= 2 && p <= ((size - 2) >> 1)) // at least one child
|
||||
{
|
||||
diff_t<It> const l = 2 * p + 1;
|
||||
diff_t<It> m = l; // left child
|
||||
if (size >= 3 && p <= ((size - 3) >> 1)) // at least two children
|
||||
{
|
||||
// m = left child
|
||||
diff_t<It> m2 = l + 1; // right child
|
||||
if (size >= 4 && p <= ((size - 4) >> 2)) // at least two children and one grandchild
|
||||
{
|
||||
diff_t<It> const ll = 2 * l + 1;
|
||||
m = ll; // left most grandchild
|
||||
// m2 = right child
|
||||
if (size >= 5 && p <= ((size - 5) >> 2)) // at least two children and two grandchildren
|
||||
{
|
||||
m = Call()(comp, *(first + ll), *(first + ll + 1)) ? ll : (ll + 1); // greater of the left grandchildren
|
||||
// m2 = right child
|
||||
if (size >= 6 && p <= ((size - 6) >> 2)) // at least two children and three grandchildren
|
||||
{
|
||||
// m = greater of the left grandchildren
|
||||
m2 = ll + 2; // third grandchild
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Call()(comp, *(first + m), *(first + m2)) ? m : m2;
|
||||
}
|
||||
|
||||
if (Call()(comp, *(first + m), val))
|
||||
{
|
||||
*(first + p) = std::move(*(first + m));
|
||||
|
||||
if (m >= 3 && p <= ((m - 3) >> 2)) // is p grandparent of m
|
||||
{
|
||||
diff_t<It> par = (m - 1) >> 1;
|
||||
if (Call()(comp, *(first + par), val))
|
||||
{
|
||||
using std::swap;
|
||||
swap(*(first + par), val);
|
||||
}
|
||||
}
|
||||
|
||||
p = m;
|
||||
}
|
||||
}
|
||||
|
||||
*(first + p) = std::move(val);
|
||||
}
|
||||
|
||||
template <typename MinCall, typename MaxCall, typename It, typename Compare>
|
||||
inline void pop_heap(It first, It el, It last, Compare comp)
|
||||
{
|
||||
diff_t<It> size = last - first;
|
||||
if (size < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
--last;
|
||||
val_t<It> val = std::move(*last);
|
||||
*last = std::move(*el);
|
||||
|
||||
// Ignore the last element
|
||||
--size;
|
||||
|
||||
diff_t<It> p = el - first;
|
||||
if (level(p) % 2 == 0) // is min level
|
||||
{
|
||||
pop_heap1<MinCall>(first, p, size, std::move(val), comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
pop_heap1<MaxCall>(first, p, size, std::move(val), comp);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MinCall, typename MaxCall, typename It, typename Compare>
|
||||
inline void make_heap(It first, It last, Compare comp)
|
||||
{
|
||||
diff_t<It> size = last - first;
|
||||
diff_t<It> p = size / 2;
|
||||
if (p <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int level_p = level(p - 1);
|
||||
diff_t<It> level_f = (diff_t<It>(1) << level_p) - 1;
|
||||
while (p > 0)
|
||||
{
|
||||
--p;
|
||||
val_t<It> val = std::move(*(first + p));
|
||||
if (level_p % 2 == 0) // is min level
|
||||
{
|
||||
pop_heap1<MinCall>(first, p, size, std::move(val), comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
pop_heap1<MaxCall>(first, p, size, std::move(val), comp);
|
||||
}
|
||||
|
||||
if (p == level_f)
|
||||
{
|
||||
--level_p;
|
||||
level_f >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Call, typename It, typename Compare>
|
||||
inline bool is_heap(It first, It last, Compare comp)
|
||||
{
|
||||
diff_t<It> const size = last - first;
|
||||
diff_t<It> pow2 = 4;
|
||||
bool is_min_level = false;
|
||||
for (diff_t<It> i = 1; i < size; ++i)
|
||||
{
|
||||
if (i == pow2 - 1)
|
||||
{
|
||||
pow2 *= 2;
|
||||
is_min_level = ! is_min_level;
|
||||
}
|
||||
|
||||
diff_t<It> const p = (i - 1) >> 1;
|
||||
if (is_min_level)
|
||||
{
|
||||
if (Call()(comp, *(first + p), *(first + i)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Call()(comp, *(first + i), *(first + p)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= 3)
|
||||
{
|
||||
diff_t<It> const g = (p - 1) >> 1;
|
||||
if (is_min_level)
|
||||
{
|
||||
if (Call()(comp, *(first + i), *(first + g)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Call()(comp, *(first + g), *(first + i)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Call, typename It, typename Compare>
|
||||
inline It bottom_heap(It first, It last, Compare comp)
|
||||
{
|
||||
diff_t<It> const size = last - first;
|
||||
return size <= 1 ? first :
|
||||
size == 2 ? (first + 1) :
|
||||
Call()(comp, *(first + 1), *(first + 2)) ? (first + 2) : (first + 1);
|
||||
}
|
||||
|
||||
} // namespace minmax_heap_detail
|
||||
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void push_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
minmax_heap_detail::push_heap<min_call, max_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void push_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
minmax_heap_detail::push_heap<min_call, max_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void pop_top_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
pop_heap<min_call, max_call>(first, first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void pop_top_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
pop_heap<min_call, max_call>(first, first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void pop_bottom_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
It bottom = minmax_heap_detail::bottom_heap<min_call>(first, last, comp);
|
||||
pop_heap<min_call, max_call>(first, bottom, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void pop_bottom_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
auto&& comp = std::less<>();
|
||||
It bottom = minmax_heap_detail::bottom_heap<min_call>(first, last, comp);
|
||||
pop_heap<min_call, max_call>(first, bottom, last, comp);
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void make_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::make_heap<min_call, max_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void make_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::make_heap<min_call, max_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline bool is_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::is_heap<min_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline bool is_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::is_heap<min_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline decltype(auto) bottom_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return *minmax_heap_detail::bottom_heap<min_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline decltype(auto) bottom_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return *minmax_heap_detail::bottom_heap<min_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_MINMAX_HEAP_HPP
|
@ -622,11 +622,13 @@ struct predicates_check_impl<std::tuple<Ts...>, Tag, First, Last>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Tag, std::size_t First, std::size_t Last, typename Predicates, typename Value, typename Indexable, typename Strategy>
|
||||
template <typename Tag, typename Predicates, typename Value, typename Indexable, typename Strategy>
|
||||
inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i, Strategy const& s)
|
||||
{
|
||||
return detail::predicates_check_impl<Predicates, Tag, First, Last>
|
||||
::apply(p, v, i, s);
|
||||
return detail::predicates_check_impl
|
||||
<
|
||||
Predicates, Tag, 0, predicates_length<Predicates>::value
|
||||
>::apply(p, v, i, s);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
150
include/boost/geometry/index/detail/priority_dequeue.hpp
Normal file
150
include/boost/geometry/index/detail/priority_dequeue.hpp
Normal file
@ -0,0 +1,150 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_PRIORITY_DEQUEUE_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_PRIORITY_DEQUEUE_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/geometry/index/detail/maxmin_heap.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename T,
|
||||
typename Container = std::vector<T>,
|
||||
typename Compare = std::less<typename Container::value_type>
|
||||
>
|
||||
class priority_dequeue
|
||||
{
|
||||
public:
|
||||
using container_type = Container;
|
||||
using value_compare = Compare;
|
||||
using value_type = typename Container::value_type;
|
||||
using size_type = typename Container::size_type;
|
||||
using reference = typename Container::reference;
|
||||
using const_reference = typename Container::const_reference;
|
||||
|
||||
priority_dequeue()
|
||||
: c(), comp()
|
||||
{}
|
||||
|
||||
explicit priority_dequeue(Compare const& compare)
|
||||
: c(), comp(compare)
|
||||
{}
|
||||
|
||||
priority_dequeue(Compare const& compare, Container const& cont)
|
||||
: c(cont), comp(compare)
|
||||
{
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
priority_dequeue(Compare const& compare, Container&& cont)
|
||||
: c(std::move(cont)), comp(compare)
|
||||
{
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
priority_dequeue(It first, It last)
|
||||
: c(first, last), comp()
|
||||
{
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
priority_dequeue(It first, It last, Compare const& compare)
|
||||
: c(first, last), comp(compare)
|
||||
{
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
priority_dequeue(It first, It last, Compare const& compare, Container const& cont)
|
||||
: c(cont), comp(compare)
|
||||
{
|
||||
c.insert(first, last);
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
priority_dequeue(It first, It last, Compare const& compare, Container&& cont)
|
||||
: c(std::move(cont)), comp(compare)
|
||||
{
|
||||
c.insert(first, last);
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
const_reference top() const
|
||||
{
|
||||
return *c.begin();
|
||||
}
|
||||
|
||||
const_reference bottom() const
|
||||
{
|
||||
return bottom_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
void push(const value_type& value)
|
||||
{
|
||||
c.push_back(value);
|
||||
push_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
void push(value_type&& value)
|
||||
{
|
||||
c.push_back(std::move(value));
|
||||
push_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
void emplace(Args&& ...args)
|
||||
{
|
||||
c.emplace_back(std::forward<Args>(args)...);
|
||||
push_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
void pop_top()
|
||||
{
|
||||
pop_top_maxmin_heap(c.begin(), c.end(), comp);
|
||||
c.pop_back();
|
||||
}
|
||||
|
||||
void pop_bottom()
|
||||
{
|
||||
pop_bottom_maxmin_heap(c.begin(), c.end(), comp);
|
||||
c.pop_back();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return c.empty();
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return c.size();
|
||||
}
|
||||
|
||||
void swap(priority_dequeue& other)
|
||||
{
|
||||
using std::swap;
|
||||
std::swap(c, other.c);
|
||||
std::swap(comp, other.comp);
|
||||
}
|
||||
|
||||
protected:
|
||||
Container c;
|
||||
Compare comp;
|
||||
};
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_PRIORITY_DEQUEUE_HPP
|
@ -21,8 +21,6 @@
|
||||
#include <boost/geometry/index/detail/rtree/visitors/distance_query.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/visitors/spatial_query.hpp>
|
||||
|
||||
//#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
|
||||
|
||||
template <typename Value, typename Allocators>
|
||||
@ -69,13 +67,8 @@ struct end_query_iterator
|
||||
template <typename MembersHolder, typename Predicates>
|
||||
class spatial_query_iterator
|
||||
{
|
||||
typedef typename MembersHolder::parameters_type parameters_type;
|
||||
typedef typename MembersHolder::translator_type translator_type;
|
||||
typedef typename MembersHolder::allocators_type allocators_type;
|
||||
|
||||
typedef visitors::spatial_query_incremental<MembersHolder, Predicates> visitor_type;
|
||||
typedef typename visitor_type::node_pointer node_pointer;
|
||||
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef typename MembersHolder::value_type value_type;
|
||||
@ -83,32 +76,31 @@ public:
|
||||
typedef typename allocators_type::difference_type difference_type;
|
||||
typedef typename allocators_type::const_pointer pointer;
|
||||
|
||||
inline spatial_query_iterator()
|
||||
spatial_query_iterator() = default;
|
||||
|
||||
explicit spatial_query_iterator(Predicates const& pred)
|
||||
: m_impl(pred)
|
||||
{}
|
||||
|
||||
inline spatial_query_iterator(parameters_type const& par, translator_type const& t, Predicates const& p)
|
||||
: m_visitor(par, t, p)
|
||||
{}
|
||||
|
||||
inline spatial_query_iterator(node_pointer root, parameters_type const& par, translator_type const& t, Predicates const& p)
|
||||
: m_visitor(par, t, p)
|
||||
spatial_query_iterator(MembersHolder const& members, Predicates const& pred)
|
||||
: m_impl(members, pred)
|
||||
{
|
||||
m_visitor.initialize(root);
|
||||
m_impl.initialize(members);
|
||||
}
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
return m_visitor.dereference();
|
||||
return m_impl.dereference();
|
||||
}
|
||||
|
||||
const value_type * operator->() const
|
||||
{
|
||||
return boost::addressof(m_visitor.dereference());
|
||||
return boost::addressof(m_impl.dereference());
|
||||
}
|
||||
|
||||
spatial_query_iterator & operator++()
|
||||
{
|
||||
m_visitor.increment();
|
||||
m_impl.increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -121,33 +113,28 @@ public:
|
||||
|
||||
friend bool operator==(spatial_query_iterator const& l, spatial_query_iterator const& r)
|
||||
{
|
||||
return l.m_visitor == r.m_visitor;
|
||||
return l.m_impl == r.m_impl;
|
||||
}
|
||||
|
||||
friend bool operator==(spatial_query_iterator const& l, end_query_iterator<value_type, allocators_type> const& /*r*/)
|
||||
{
|
||||
return l.m_visitor.is_end();
|
||||
return l.m_impl.is_end();
|
||||
}
|
||||
|
||||
friend bool operator==(end_query_iterator<value_type, allocators_type> const& /*l*/, spatial_query_iterator const& r)
|
||||
{
|
||||
return r.m_visitor.is_end();
|
||||
return r.m_impl.is_end();
|
||||
}
|
||||
|
||||
private:
|
||||
visitor_type m_visitor;
|
||||
visitors::spatial_query_incremental<MembersHolder, Predicates> m_impl;
|
||||
};
|
||||
|
||||
template <typename MembersHolder, typename Predicates, unsigned NearestPredicateIndex>
|
||||
template <typename MembersHolder, typename Predicates>
|
||||
class distance_query_iterator
|
||||
{
|
||||
typedef typename MembersHolder::parameters_type parameters_type;
|
||||
typedef typename MembersHolder::translator_type translator_type;
|
||||
typedef typename MembersHolder::allocators_type allocators_type;
|
||||
|
||||
typedef visitors::distance_query_incremental<MembersHolder, Predicates, NearestPredicateIndex> visitor_type;
|
||||
typedef typename visitor_type::node_pointer node_pointer;
|
||||
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef typename MembersHolder::value_type value_type;
|
||||
@ -155,32 +142,31 @@ public:
|
||||
typedef typename allocators_type::difference_type difference_type;
|
||||
typedef typename allocators_type::const_pointer pointer;
|
||||
|
||||
inline distance_query_iterator()
|
||||
distance_query_iterator() = default;
|
||||
|
||||
explicit distance_query_iterator(Predicates const& pred)
|
||||
: m_impl(pred)
|
||||
{}
|
||||
|
||||
inline distance_query_iterator(parameters_type const& par, translator_type const& t, Predicates const& p)
|
||||
: m_visitor(par, t, p)
|
||||
{}
|
||||
|
||||
inline distance_query_iterator(node_pointer root, parameters_type const& par, translator_type const& t, Predicates const& p)
|
||||
: m_visitor(par, t, p)
|
||||
distance_query_iterator(MembersHolder const& members, Predicates const& pred)
|
||||
: m_impl(members, pred)
|
||||
{
|
||||
m_visitor.initialize(root);
|
||||
m_impl.initialize(members);
|
||||
}
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
return m_visitor.dereference();
|
||||
return m_impl.dereference();
|
||||
}
|
||||
|
||||
const value_type * operator->() const
|
||||
{
|
||||
return boost::addressof(m_visitor.dereference());
|
||||
return boost::addressof(m_impl.dereference());
|
||||
}
|
||||
|
||||
distance_query_iterator & operator++()
|
||||
{
|
||||
m_visitor.increment();
|
||||
m_impl.increment();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -193,21 +179,21 @@ public:
|
||||
|
||||
friend bool operator==(distance_query_iterator const& l, distance_query_iterator const& r)
|
||||
{
|
||||
return l.m_visitor == r.m_visitor;
|
||||
return l.m_impl == r.m_impl;
|
||||
}
|
||||
|
||||
friend bool operator==(distance_query_iterator const& l, end_query_iterator<value_type, allocators_type> const& /*r*/)
|
||||
{
|
||||
return l.m_visitor.is_end();
|
||||
return l.m_impl.is_end();
|
||||
}
|
||||
|
||||
friend bool operator==(end_query_iterator<value_type, allocators_type> const& /*l*/, distance_query_iterator const& r)
|
||||
{
|
||||
return r.m_visitor.is_end();
|
||||
return r.m_impl.is_end();
|
||||
}
|
||||
|
||||
private:
|
||||
visitor_type m_visitor;
|
||||
visitors::distance_query_incremental<MembersHolder, Predicates> m_impl;
|
||||
};
|
||||
|
||||
|
||||
@ -284,8 +270,7 @@ public:
|
||||
typedef typename Allocators::difference_type difference_type;
|
||||
typedef typename Allocators::const_pointer pointer;
|
||||
|
||||
query_iterator()
|
||||
{}
|
||||
query_iterator() = default;
|
||||
|
||||
template <typename It>
|
||||
query_iterator(It const& it)
|
||||
@ -300,7 +285,6 @@ public:
|
||||
: m_ptr(o.m_ptr.get() ? o.m_ptr->clone() : 0)
|
||||
{}
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
|
||||
query_iterator & operator=(query_iterator const& o)
|
||||
{
|
||||
if ( this != boost::addressof(o) )
|
||||
@ -309,12 +293,13 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
query_iterator(query_iterator && o)
|
||||
: m_ptr(0)
|
||||
{
|
||||
m_ptr.swap(o.m_ptr);
|
||||
}
|
||||
|
||||
query_iterator & operator=(query_iterator && o)
|
||||
{
|
||||
if ( this != boost::addressof(o) )
|
||||
@ -324,34 +309,6 @@ public:
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#else // !BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(query_iterator)
|
||||
public:
|
||||
query_iterator & operator=(BOOST_COPY_ASSIGN_REF(query_iterator) o)
|
||||
{
|
||||
if ( this != boost::addressof(o) )
|
||||
{
|
||||
m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
query_iterator(BOOST_RV_REF(query_iterator) o)
|
||||
: m_ptr(0)
|
||||
{
|
||||
m_ptr.swap(o.m_ptr);
|
||||
}
|
||||
query_iterator & operator=(BOOST_RV_REF(query_iterator) o)
|
||||
{
|
||||
if ( this != boost::addressof(o) )
|
||||
{
|
||||
m_ptr.swap(o.m_ptr);
|
||||
o.m_ptr.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
|
@ -15,8 +15,11 @@
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include <boost/geometry/index/detail/distance_predicates.hpp>
|
||||
#include <boost/geometry/index/detail/predicates.hpp>
|
||||
#include <boost/geometry/index/detail/priority_dequeue.hpp>
|
||||
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
|
||||
#include <boost/geometry/index/detail/translator.hpp>
|
||||
#include <boost/geometry/index/parameters.hpp>
|
||||
@ -46,90 +49,114 @@ struct pair_first_greater
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Comp>
|
||||
struct priority_dequeue : index::detail::priority_dequeue<T, std::vector<T>, Comp>
|
||||
{
|
||||
priority_dequeue() = default;
|
||||
//void reserve(typename std::vector<T>::size_type n)
|
||||
//{
|
||||
// this->c.reserve(n);
|
||||
//}
|
||||
//void clear()
|
||||
//{
|
||||
// this->c.clear();
|
||||
//}
|
||||
};
|
||||
|
||||
template <typename Value, typename Translator, typename DistanceType, typename OutIt>
|
||||
template <typename T, typename Comp>
|
||||
struct priority_queue : std::priority_queue<T, std::vector<T>, Comp>
|
||||
{
|
||||
priority_queue() = default;
|
||||
//void reserve(typename std::vector<T>::size_type n)
|
||||
//{
|
||||
// this->c.reserve(n);
|
||||
//}
|
||||
void clear()
|
||||
{
|
||||
this->c.clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct branch_data_comp
|
||||
{
|
||||
template <typename BranchData>
|
||||
bool operator()(BranchData const& b1, BranchData const& b2) const
|
||||
{
|
||||
return b1.distance > b2.distance || (b1.distance == b2.distance && b1.reverse_level > b2.reverse_level);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DistanceType, typename Value>
|
||||
class distance_query_result
|
||||
{
|
||||
using neighbor_data = std::pair<DistanceType, const Value *>;
|
||||
using neighbors_type = std::vector<neighbor_data>;
|
||||
using size_type = typename neighbors_type::size_type;
|
||||
|
||||
public:
|
||||
typedef DistanceType distance_type;
|
||||
|
||||
inline explicit distance_query_result(size_t k, OutIt out_it)
|
||||
: m_count(k), m_out_it(out_it)
|
||||
inline distance_query_result(size_type k)
|
||||
: m_count(k)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < m_count, "Number of neighbors should be greater than 0");
|
||||
|
||||
m_neighbors.reserve(m_count);
|
||||
}
|
||||
|
||||
inline void store(Value const& val, distance_type const& curr_comp_dist)
|
||||
// NOTE: Do not call if max_count() == 0
|
||||
inline void store(DistanceType const& distance, const Value * value_ptr)
|
||||
{
|
||||
if ( m_neighbors.size() < m_count )
|
||||
if (m_neighbors.size() < m_count)
|
||||
{
|
||||
m_neighbors.push_back(std::make_pair(curr_comp_dist, val));
|
||||
m_neighbors.push_back(std::make_pair(distance, value_ptr));
|
||||
|
||||
if ( m_neighbors.size() == m_count )
|
||||
std::make_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( curr_comp_dist < m_neighbors.front().first )
|
||||
if (m_neighbors.size() == m_count)
|
||||
{
|
||||
std::pop_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
|
||||
m_neighbors.back().first = curr_comp_dist;
|
||||
m_neighbors.back().second = val;
|
||||
std::push_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
|
||||
std::make_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
|
||||
}
|
||||
}
|
||||
else if (distance < m_neighbors.front().first)
|
||||
{
|
||||
std::pop_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
|
||||
m_neighbors.back().first = distance;
|
||||
m_neighbors.back().second = value_ptr;
|
||||
std::push_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
|
||||
}
|
||||
}
|
||||
|
||||
inline bool has_enough_neighbors() const
|
||||
// NOTE: Do not call if max_count() == 0
|
||||
inline bool ignore_branch(DistanceType const& distance) const
|
||||
{
|
||||
return m_count <= m_neighbors.size();
|
||||
return m_neighbors.size() == m_count
|
||||
&& m_neighbors.front().first <= distance;
|
||||
}
|
||||
|
||||
inline distance_type greatest_comparable_distance() const
|
||||
template <typename OutIt>
|
||||
inline size_type finish(OutIt out_it) const
|
||||
{
|
||||
// greatest distance is in the first neighbor only
|
||||
// if there is at least m_count values found
|
||||
// this is just for safety reasons since is_comparable_distance_valid() is checked earlier
|
||||
// TODO - may be replaced by ASSERT
|
||||
return m_neighbors.size() < m_count
|
||||
? (std::numeric_limits<distance_type>::max)()
|
||||
: m_neighbors.front().first;
|
||||
}
|
||||
|
||||
inline size_t finish()
|
||||
{
|
||||
typedef typename std::vector< std::pair<distance_type, Value> >::const_iterator neighbors_iterator;
|
||||
for ( neighbors_iterator it = m_neighbors.begin() ; it != m_neighbors.end() ; ++it, ++m_out_it )
|
||||
*m_out_it = it->second;
|
||||
for (auto const& p : m_neighbors)
|
||||
{
|
||||
*out_it = *(p.second);
|
||||
++out_it;
|
||||
}
|
||||
|
||||
return m_neighbors.size();
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_count;
|
||||
OutIt m_out_it;
|
||||
size_type max_count() const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
std::vector< std::pair<distance_type, Value> > m_neighbors;
|
||||
private:
|
||||
size_type m_count;
|
||||
neighbors_type m_neighbors;
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename MembersHolder,
|
||||
typename Predicates,
|
||||
std::size_t DistancePredicateIndex,
|
||||
typename OutIter
|
||||
>
|
||||
template <typename MembersHolder, typename Predicates>
|
||||
class distance_query
|
||||
: public MembersHolder::visitor_const
|
||||
{
|
||||
public:
|
||||
typedef typename MembersHolder::value_type value_type;
|
||||
typedef typename MembersHolder::box_type box_type;
|
||||
typedef typename MembersHolder::parameters_type parameters_type;
|
||||
typedef typename MembersHolder::translator_type translator_type;
|
||||
typedef typename MembersHolder::allocators_type allocators_type;
|
||||
|
||||
typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
|
||||
|
||||
@ -137,7 +164,10 @@ public:
|
||||
typedef typename MembersHolder::internal_node internal_node;
|
||||
typedef typename MembersHolder::leaf leaf;
|
||||
|
||||
typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
|
||||
typedef index::detail::predicates_element
|
||||
<
|
||||
index::detail::predicates_find_distance<Predicates>::value, Predicates
|
||||
> nearest_predicate_access;
|
||||
typedef typename nearest_predicate_access::type nearest_predicate_type;
|
||||
typedef typename indexable_type<translator_type>::type indexable_type;
|
||||
|
||||
@ -146,147 +176,141 @@ public:
|
||||
typedef typename calculate_value_distance::result_type value_distance_type;
|
||||
typedef typename calculate_node_distance::result_type node_distance_type;
|
||||
|
||||
static const std::size_t predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
typedef typename MembersHolder::size_type size_type;
|
||||
typedef typename MembersHolder::node_pointer node_pointer;
|
||||
|
||||
inline distance_query(parameters_type const& parameters, translator_type const& translator, Predicates const& pred, OutIter out_it)
|
||||
: m_parameters(parameters), m_translator(translator)
|
||||
using neighbor_data = std::pair<value_distance_type, const value_type *>;
|
||||
using neighbors_type = std::vector<neighbor_data>;
|
||||
|
||||
struct branch_data
|
||||
{
|
||||
branch_data(node_distance_type d, size_type rl, node_pointer p)
|
||||
: distance(d), reverse_level(rl), ptr(p)
|
||||
{}
|
||||
|
||||
node_distance_type distance;
|
||||
size_type reverse_level;
|
||||
node_pointer ptr;
|
||||
};
|
||||
using branches_type = priority_queue<branch_data, branch_data_comp>;
|
||||
|
||||
public:
|
||||
distance_query(MembersHolder const& members, Predicates const& pred)
|
||||
: m_tr(members.translator())
|
||||
, m_strategy(index::detail::get_strategy(members.parameters()))
|
||||
, m_pred(pred)
|
||||
, m_result(nearest_predicate_access::get(m_pred).count, out_it)
|
||||
, m_strategy(index::detail::get_strategy(parameters))
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
|
||||
// array of active nodes
|
||||
typedef typename index::detail::rtree::container_from_elements_type<
|
||||
elements_type,
|
||||
std::pair<node_distance_type, typename allocators_type::node_pointer>
|
||||
>::type active_branch_list_type;
|
||||
|
||||
active_branch_list_type active_branch_list;
|
||||
active_branch_list.reserve(m_parameters.get_max_elements());
|
||||
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// fill array of nodes meeting predicates
|
||||
for (typename elements_type::const_iterator it = elements.begin();
|
||||
it != elements.end(); ++it)
|
||||
{
|
||||
// if current node meets predicates
|
||||
// 0 - dummy value
|
||||
if ( index::detail::predicates_check
|
||||
<
|
||||
index::detail::bounds_tag, 0, predicates_len
|
||||
>(m_pred, 0, it->first, m_strategy) )
|
||||
{
|
||||
// calculate node's distance(s) for distance predicate
|
||||
node_distance_type node_distance;
|
||||
// if distance isn't ok - move to the next node
|
||||
if ( !calculate_node_distance::apply(predicate(), it->first,
|
||||
m_strategy, node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if current node is further than found neighbors - don't analyze it
|
||||
if ( m_result.has_enough_neighbors() &&
|
||||
is_node_prunable(m_result.greatest_comparable_distance(), node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// add current node's data into the list
|
||||
active_branch_list.push_back( std::make_pair(node_distance, it->second) );
|
||||
}
|
||||
}
|
||||
|
||||
// if there aren't any nodes in ABL - return
|
||||
if ( active_branch_list.empty() )
|
||||
return;
|
||||
|
||||
// sort array
|
||||
std::sort(active_branch_list.begin(), active_branch_list.end(), pair_first_less());
|
||||
|
||||
// recursively visit nodes
|
||||
for ( typename active_branch_list_type::const_iterator it = active_branch_list.begin();
|
||||
it != active_branch_list.end() ; ++it )
|
||||
{
|
||||
// if current node is further than furthest neighbor, the rest of nodes also will be further
|
||||
if ( m_result.has_enough_neighbors() &&
|
||||
is_node_prunable(m_result.greatest_comparable_distance(), it->first) )
|
||||
break;
|
||||
|
||||
rtree::apply_visitor(*this, *(it->second));
|
||||
}
|
||||
|
||||
// ALTERNATIVE VERSION - use heap instead of sorted container
|
||||
// It seems to be faster for greater MaxElements and slower otherwise
|
||||
// CONSIDER: using one global container/heap for active branches
|
||||
// instead of a sorted container per level
|
||||
// This would also change the way how branches are traversed!
|
||||
// The same may be applied to the iterative version which btw suffers
|
||||
// from the copying of the whole containers on resize of the ABLs container
|
||||
|
||||
//// make a heap
|
||||
//std::make_heap(active_branch_list.begin(), active_branch_list.end(), pair_first_greater());
|
||||
|
||||
//// recursively visit nodes
|
||||
//while ( !active_branch_list.empty() )
|
||||
//{
|
||||
// //if current node is further than furthest neighbor, the rest of nodes also will be further
|
||||
// if ( m_result.has_enough_neighbors()
|
||||
// && is_node_prunable(m_result.greatest_comparable_distance(), active_branch_list.front().first) )
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
|
||||
// rtree::apply_visitor(*this, *(active_branch_list.front().second));
|
||||
|
||||
// std::pop_heap(active_branch_list.begin(), active_branch_list.end(), pair_first_greater());
|
||||
// active_branch_list.pop_back();
|
||||
//}
|
||||
m_neighbors.reserve((std::min)(members.values_count, size_type(max_count())));
|
||||
//m_branches.reserve(members.parameters().get_min_elements() * members.leafs_level); ?
|
||||
// min, max or average?
|
||||
}
|
||||
|
||||
inline void operator()(leaf const& n)
|
||||
template <typename OutIter>
|
||||
size_type apply(MembersHolder const& members, OutIter out_it)
|
||||
{
|
||||
typedef typename rtree::elements_type<leaf>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// search leaf for closest value meeting predicates
|
||||
for (typename elements_type::const_iterator it = elements.begin();
|
||||
it != elements.end(); ++it)
|
||||
{
|
||||
// if value meets predicates
|
||||
if ( index::detail::predicates_check
|
||||
<
|
||||
index::detail::value_tag, 0, predicates_len
|
||||
>(m_pred, *it, m_translator(*it), m_strategy) )
|
||||
{
|
||||
// calculate values distance for distance predicate
|
||||
value_distance_type value_distance;
|
||||
// if distance is ok
|
||||
if ( calculate_value_distance::apply(predicate(), m_translator(*it),
|
||||
m_strategy, value_distance) )
|
||||
{
|
||||
// store value
|
||||
m_result.store(*it, value_distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t finish()
|
||||
{
|
||||
return m_result.finish();
|
||||
return apply(members.root, members.leafs_level, out_it);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Distance>
|
||||
static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d)
|
||||
template <typename OutIter>
|
||||
size_type apply(node_pointer ptr, size_type reverse_level, OutIter out_it)
|
||||
{
|
||||
return greatest_dist <= d;
|
||||
namespace id = index::detail;
|
||||
|
||||
if (max_count() <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (reverse_level > 0)
|
||||
{
|
||||
internal_node& n = rtree::get<internal_node>(*ptr);
|
||||
// fill array of nodes meeting predicates
|
||||
for (auto const& p : rtree::elements(n))
|
||||
{
|
||||
node_distance_type node_distance; // for distance predicate
|
||||
|
||||
// if current node meets predicates (0 is dummy value)
|
||||
if (id::predicates_check<id::bounds_tag>(m_pred, 0, p.first, m_strategy)
|
||||
// and if distance is ok
|
||||
&& calculate_node_distance::apply(predicate(), p.first, m_strategy, node_distance)
|
||||
// and if current node is closer than the furthest neighbor
|
||||
&& ! ignore_branch(node_distance))
|
||||
{
|
||||
// add current node's data into the list
|
||||
m_branches.push(branch_data(node_distance, reverse_level - 1, p.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
leaf& n = rtree::get<leaf>(*ptr);
|
||||
// search leaf for closest value meeting predicates
|
||||
for (auto const& v : rtree::elements(n))
|
||||
{
|
||||
value_distance_type value_distance; // for distance predicate
|
||||
|
||||
// if value meets predicates
|
||||
if (id::predicates_check<id::value_tag>(m_pred, v, m_tr(v), m_strategy)
|
||||
// and if distance is ok
|
||||
&& calculate_value_distance::apply(predicate(), m_tr(v), m_strategy, value_distance))
|
||||
{
|
||||
// store value
|
||||
store_value(value_distance, boost::addressof(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_branches.empty()
|
||||
|| ignore_branch(m_branches.top().distance))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = m_branches.top().ptr;
|
||||
reverse_level = m_branches.top().reverse_level;
|
||||
m_branches.pop();
|
||||
}
|
||||
|
||||
for (auto const& p : m_neighbors)
|
||||
{
|
||||
*out_it = *(p.second);
|
||||
++out_it;
|
||||
}
|
||||
|
||||
return m_neighbors.size();
|
||||
}
|
||||
|
||||
bool ignore_branch(node_distance_type const& node_distance) const
|
||||
{
|
||||
return m_neighbors.size() == max_count()
|
||||
&& m_neighbors.front().first <= node_distance;
|
||||
}
|
||||
|
||||
void store_value(value_distance_type value_distance, const value_type * value_ptr)
|
||||
{
|
||||
if (m_neighbors.size() < max_count())
|
||||
{
|
||||
m_neighbors.push_back(std::make_pair(value_distance, value_ptr));
|
||||
|
||||
if (m_neighbors.size() == max_count())
|
||||
{
|
||||
std::make_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
|
||||
}
|
||||
}
|
||||
else if (value_distance < m_neighbors.front().first)
|
||||
{
|
||||
std::pop_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
|
||||
m_neighbors.back() = std::make_pair(value_distance, value_ptr);
|
||||
std::push_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t max_count() const
|
||||
{
|
||||
return nearest_predicate_access::get(m_pred).count;
|
||||
}
|
||||
|
||||
nearest_predicate_type const& predicate() const
|
||||
@ -294,24 +318,18 @@ private:
|
||||
return nearest_predicate_access::get(m_pred);
|
||||
}
|
||||
|
||||
parameters_type const& m_parameters;
|
||||
translator_type const& m_translator;
|
||||
|
||||
Predicates m_pred;
|
||||
distance_query_result<value_type, translator_type, value_distance_type, OutIter> m_result;
|
||||
|
||||
translator_type const& m_tr;
|
||||
strategy_type m_strategy;
|
||||
|
||||
Predicates const& m_pred;
|
||||
|
||||
branches_type m_branches;
|
||||
neighbors_type m_neighbors;
|
||||
};
|
||||
|
||||
template <
|
||||
typename MembersHolder,
|
||||
typename Predicates,
|
||||
std::size_t DistancePredicateIndex
|
||||
>
|
||||
template <typename MembersHolder, typename Predicates>
|
||||
class distance_query_incremental
|
||||
: public MembersHolder::visitor_const
|
||||
{
|
||||
public:
|
||||
typedef typename MembersHolder::value_type value_type;
|
||||
typedef typename MembersHolder::box_type box_type;
|
||||
typedef typename MembersHolder::parameters_type parameters_type;
|
||||
@ -324,7 +342,10 @@ public:
|
||||
typedef typename MembersHolder::internal_node internal_node;
|
||||
typedef typename MembersHolder::leaf leaf;
|
||||
|
||||
typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
|
||||
typedef index::detail::predicates_element
|
||||
<
|
||||
index::detail::predicates_find_distance<Predicates>::value, Predicates
|
||||
> nearest_predicate_access;
|
||||
typedef typename nearest_predicate_access::type nearest_predicate_type;
|
||||
typedef typename indexable_type<translator_type>::type indexable_type;
|
||||
|
||||
@ -337,90 +358,114 @@ public:
|
||||
typedef typename allocators_type::const_reference const_reference;
|
||||
typedef typename allocators_type::node_pointer node_pointer;
|
||||
|
||||
static const std::size_t predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
|
||||
typedef typename rtree::elements_type<internal_node>::type internal_elements;
|
||||
typedef typename internal_elements::const_iterator internal_iterator;
|
||||
typedef typename rtree::elements_type<leaf>::type leaf_elements;
|
||||
|
||||
typedef std::pair<node_distance_type, node_pointer> branch_data;
|
||||
typedef std::vector<branch_data> internal_heap_type;
|
||||
using neighbor_data = std::pair<value_distance_type, const value_type *>;
|
||||
using neighbors_type = priority_dequeue<neighbor_data, pair_first_greater>;
|
||||
|
||||
struct branch_data
|
||||
{
|
||||
branch_data(node_distance_type d, size_type rl, node_pointer p)
|
||||
: distance(d), reverse_level(rl), ptr(p)
|
||||
{}
|
||||
|
||||
node_distance_type distance;
|
||||
size_type reverse_level;
|
||||
node_pointer ptr;
|
||||
};
|
||||
using branches_type = priority_queue<branch_data, branch_data_comp>;
|
||||
|
||||
public:
|
||||
inline distance_query_incremental()
|
||||
: m_translator(NULL)
|
||||
: m_tr(nullptr)
|
||||
// , m_strategy()
|
||||
// , m_pred()
|
||||
, current_neighbor((std::numeric_limits<size_type>::max)())
|
||||
// , m_strategy_type()
|
||||
, m_neighbors_count(0)
|
||||
, m_neighbor_ptr(nullptr)
|
||||
{}
|
||||
|
||||
inline distance_query_incremental(parameters_type const& params, translator_type const& translator, Predicates const& pred)
|
||||
: m_translator(::boost::addressof(translator))
|
||||
inline distance_query_incremental(Predicates const& pred)
|
||||
: m_tr(nullptr)
|
||||
// , m_strategy()
|
||||
, m_pred(pred)
|
||||
, current_neighbor((std::numeric_limits<size_type>::max)())
|
||||
, m_strategy(index::detail::get_strategy(params))
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(0 < max_count(), "k must be greather than 0");
|
||||
}
|
||||
, m_neighbors_count(0)
|
||||
, m_neighbor_ptr(nullptr)
|
||||
{}
|
||||
|
||||
inline distance_query_incremental(MembersHolder const& members, Predicates const& pred)
|
||||
: m_tr(::boost::addressof(members.translator()))
|
||||
, m_strategy(index::detail::get_strategy(members.parameters()))
|
||||
, m_pred(pred)
|
||||
, m_neighbors_count(0)
|
||||
, m_neighbor_ptr(nullptr)
|
||||
{}
|
||||
|
||||
const_reference dereference() const
|
||||
{
|
||||
return *(neighbors[current_neighbor].second);
|
||||
return *m_neighbor_ptr;
|
||||
}
|
||||
|
||||
void initialize(node_pointer root)
|
||||
void initialize(MembersHolder const& members)
|
||||
{
|
||||
rtree::apply_visitor(*this, *root);
|
||||
increment();
|
||||
if (0 < max_count())
|
||||
{
|
||||
apply(members.root, members.leafs_level);
|
||||
increment();
|
||||
}
|
||||
}
|
||||
|
||||
void increment()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
size_type new_neighbor = current_neighbor == (std::numeric_limits<size_type>::max)() ? 0 : current_neighbor + 1;
|
||||
|
||||
if ( internal_heap.empty() )
|
||||
if (m_branches.empty())
|
||||
{
|
||||
if ( new_neighbor < neighbors.size() )
|
||||
current_neighbor = new_neighbor;
|
||||
// there exists a next closest neighbor so we can increment
|
||||
if (! m_neighbors.empty())
|
||||
{
|
||||
m_neighbor_ptr = m_neighbors.top().second;
|
||||
++m_neighbors_count;
|
||||
m_neighbors.pop_top();
|
||||
}
|
||||
else
|
||||
{
|
||||
current_neighbor = (std::numeric_limits<size_type>::max)();
|
||||
// clear() is used to disable the condition above
|
||||
neighbors.clear();
|
||||
// there aren't any neighbors left, end
|
||||
m_neighbor_ptr = nullptr;
|
||||
m_neighbors_count = max_count();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
branch_data const& closest_branch = internal_heap.front();
|
||||
node_distance_type const& closest_distance = closest_branch.first;
|
||||
branch_data const& closest_branch = m_branches.top();
|
||||
|
||||
// if there are no nodes which can have closer values, set new value
|
||||
if ( new_neighbor < neighbors.size() &&
|
||||
// NOTE: In order to use <= current neighbor can't be sorted again
|
||||
neighbors[new_neighbor].first <= closest_distance )
|
||||
// if next neighbor is closer or as close as the closest branch, set next neighbor
|
||||
if (! m_neighbors.empty() && m_neighbors.top().first <= closest_branch.distance )
|
||||
{
|
||||
current_neighbor = new_neighbor;
|
||||
m_neighbor_ptr = m_neighbors.top().second;
|
||||
++m_neighbors_count;
|
||||
m_neighbors.pop_top();
|
||||
return;
|
||||
}
|
||||
|
||||
// if node is further than the furthest neighbor, following nodes will also be further
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(neighbors.size() <= max_count(), "unexpected neighbors count");
|
||||
if ( max_count() <= neighbors.size() &&
|
||||
neighbors.back().first <= closest_distance )
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(m_neighbors_count + m_neighbors.size() <= max_count(), "unexpected neighbors count");
|
||||
|
||||
// if there is enough neighbors and there is no closer branch
|
||||
if (ignore_branch_or_value(closest_branch.distance))
|
||||
{
|
||||
internal_heap.clear();
|
||||
m_branches.clear();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
node_pointer ptr = closest_branch.second;
|
||||
std::pop_heap(internal_heap.begin(), internal_heap.end(), pair_first_greater());
|
||||
internal_heap.pop_back();
|
||||
node_pointer ptr = closest_branch.ptr;
|
||||
size_type reverse_level = closest_branch.reverse_level;
|
||||
m_branches.pop();
|
||||
|
||||
rtree::apply_visitor(*this, *ptr);
|
||||
apply(ptr, reverse_level);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -428,112 +473,80 @@ public:
|
||||
|
||||
bool is_end() const
|
||||
{
|
||||
return (std::numeric_limits<size_type>::max)() == current_neighbor;
|
||||
return m_neighbor_ptr == nullptr;
|
||||
}
|
||||
|
||||
friend bool operator==(distance_query_incremental const& l, distance_query_incremental const& r)
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(l.current_neighbor != r.current_neighbor ||
|
||||
(std::numeric_limits<size_type>::max)() == l.current_neighbor ||
|
||||
(std::numeric_limits<size_type>::max)() == r.current_neighbor ||
|
||||
l.neighbors[l.current_neighbor].second == r.neighbors[r.current_neighbor].second,
|
||||
"not corresponding iterators");
|
||||
return l.current_neighbor == r.current_neighbor;
|
||||
return l.m_neighbors_count == r.m_neighbors_count;
|
||||
}
|
||||
|
||||
// Put node's elements into the list of active branches if those elements meets predicates
|
||||
// and distance predicates(currently not used)
|
||||
// and aren't further than found neighbours (if there is enough neighbours)
|
||||
inline void operator()(internal_node const& n)
|
||||
private:
|
||||
void apply(node_pointer ptr, size_type reverse_level)
|
||||
{
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// fill active branch list array of nodes meeting predicates
|
||||
for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it )
|
||||
namespace id = index::detail;
|
||||
// Put node's elements into the list of active branches if those elements meets predicates
|
||||
// and distance predicates(currently not used)
|
||||
// and aren't further than found neighbours (if there is enough neighbours)
|
||||
if (reverse_level > 0)
|
||||
{
|
||||
// if current node meets predicates
|
||||
// 0 - dummy value
|
||||
if ( index::detail::predicates_check
|
||||
<
|
||||
index::detail::bounds_tag, 0, predicates_len
|
||||
>(m_pred, 0, it->first, m_strategy) )
|
||||
internal_node& n = rtree::get<internal_node>(*ptr);
|
||||
// fill active branch list array of nodes meeting predicates
|
||||
for (auto const& p : rtree::elements(n))
|
||||
{
|
||||
// calculate node's distance(s) for distance predicate
|
||||
node_distance_type node_distance;
|
||||
// if distance isn't ok - move to the next node
|
||||
if ( !calculate_node_distance::apply(predicate(), it->first,
|
||||
m_strategy, node_distance) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
node_distance_type node_distance; // for distance predicate
|
||||
|
||||
// if current node is further than found neighbors - don't analyze it
|
||||
if ( max_count() <= neighbors.size() &&
|
||||
neighbors.back().first <= node_distance )
|
||||
// if current node meets predicates (0 is dummy value)
|
||||
if (id::predicates_check<id::bounds_tag>(m_pred, 0, p.first, m_strategy)
|
||||
// and if distance is ok
|
||||
&& calculate_node_distance::apply(predicate(), p.first, m_strategy, node_distance)
|
||||
// and if current node is closer than the furthest neighbor
|
||||
&& ! ignore_branch_or_value(node_distance))
|
||||
{
|
||||
continue;
|
||||
// add current node into the queue
|
||||
m_branches.push(branch_data(node_distance, reverse_level - 1, p.second));
|
||||
}
|
||||
|
||||
// add current node's data into the queue
|
||||
internal_heap.push_back(std::make_pair(node_distance, it->second));
|
||||
std::push_heap(internal_heap.begin(), internal_heap.end(), pair_first_greater());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Put values into the list of neighbours if those values meets predicates
|
||||
// and distance predicates(currently not used)
|
||||
// and aren't further than already found neighbours (if there is enough neighbours)
|
||||
inline void operator()(leaf const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<leaf>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// store distance to the furthest neighbour
|
||||
bool not_enough_neighbors = neighbors.size() < max_count();
|
||||
value_distance_type greatest_distance = !not_enough_neighbors ? neighbors.back().first : (std::numeric_limits<value_distance_type>::max)();
|
||||
|
||||
// search leaf for closest value meeting predicates
|
||||
for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
|
||||
// Put values into the list of neighbours if those values meets predicates
|
||||
// and distance predicates(currently not used)
|
||||
// and aren't further than already found neighbours (if there is enough neighbours)
|
||||
else
|
||||
{
|
||||
// if value meets predicates
|
||||
if ( index::detail::predicates_check
|
||||
<
|
||||
index::detail::value_tag, 0, predicates_len
|
||||
>(m_pred, *it, (*m_translator)(*it), m_strategy) )
|
||||
leaf& n = rtree::get<leaf>(*ptr);
|
||||
// search leaf for closest value meeting predicates
|
||||
for (auto const& v : rtree::elements(n))
|
||||
{
|
||||
// calculate values distance for distance predicate
|
||||
value_distance_type value_distance;
|
||||
// if distance is ok
|
||||
if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it),
|
||||
m_strategy, value_distance) )
|
||||
value_distance_type value_distance; // for distance predicate
|
||||
|
||||
// if value meets predicates
|
||||
if (id::predicates_check<id::value_tag>(m_pred, v, (*m_tr)(v), m_strategy)
|
||||
// and if distance is ok
|
||||
&& calculate_value_distance::apply(predicate(), (*m_tr)(v), m_strategy, value_distance)
|
||||
// and if current value is closer than the furthest neighbor
|
||||
&& ! ignore_branch_or_value(value_distance))
|
||||
{
|
||||
// if there is not enough values or current value is closer than furthest neighbour
|
||||
if ( not_enough_neighbors || value_distance < greatest_distance )
|
||||
// add current value into the queue
|
||||
m_neighbors.push(std::make_pair(value_distance, boost::addressof(v)));
|
||||
|
||||
// remove unneeded value
|
||||
if (m_neighbors_count + m_neighbors.size() > max_count())
|
||||
{
|
||||
neighbors.push_back(std::make_pair(value_distance, boost::addressof(*it)));
|
||||
m_neighbors.pop_bottom();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: sort is probably suboptimal.
|
||||
// An alternative would be std::set, but it'd probably add constant cost.
|
||||
// Ideally replace this with double-ended priority queue, e.g. min-max heap.
|
||||
// NOTE: A condition in increment() relies on the fact that current neighbor doesn't
|
||||
// participate in sorting anymore.
|
||||
|
||||
// sort array
|
||||
size_type sort_first = current_neighbor == (std::numeric_limits<size_type>::max)() ? 0 : current_neighbor + 1;
|
||||
std::sort(neighbors.begin() + sort_first, neighbors.end(), pair_first_less());
|
||||
// remove furthest values
|
||||
if ( max_count() < neighbors.size() )
|
||||
neighbors.resize(max_count());
|
||||
}
|
||||
|
||||
private:
|
||||
inline std::size_t max_count() const
|
||||
template <typename Distance>
|
||||
bool ignore_branch_or_value(Distance const& distance)
|
||||
{
|
||||
return m_neighbors_count + m_neighbors.size() == max_count()
|
||||
&& (m_neighbors.empty() || m_neighbors.bottom().first <= distance);
|
||||
}
|
||||
|
||||
std::size_t max_count() const
|
||||
{
|
||||
return nearest_predicate_access::get(m_pred).count;
|
||||
}
|
||||
@ -543,15 +556,15 @@ private:
|
||||
return nearest_predicate_access::get(m_pred);
|
||||
}
|
||||
|
||||
const translator_type * m_translator;
|
||||
const translator_type * m_tr;
|
||||
strategy_type m_strategy;
|
||||
|
||||
Predicates m_pred;
|
||||
|
||||
internal_heap_type internal_heap;
|
||||
std::vector< std::pair<value_distance_type, const value_type *> > neighbors;
|
||||
size_type current_neighbor;
|
||||
|
||||
strategy_type m_strategy;
|
||||
branches_type m_branches;
|
||||
neighbors_type m_neighbors;
|
||||
size_type m_neighbors_count;
|
||||
const value_type * m_neighbor_ptr;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
@ -25,7 +25,6 @@ namespace detail { namespace rtree { namespace visitors {
|
||||
|
||||
template <typename MembersHolder, typename Predicates, typename OutIter>
|
||||
struct spatial_query
|
||||
: public MembersHolder::visitor_const
|
||||
{
|
||||
typedef typename MembersHolder::parameters_type parameters_type;
|
||||
typedef typename MembersHolder::translator_type translator_type;
|
||||
@ -37,71 +36,69 @@ struct spatial_query
|
||||
typedef typename MembersHolder::internal_node internal_node;
|
||||
typedef typename MembersHolder::leaf leaf;
|
||||
|
||||
typedef typename allocators_type::node_pointer node_pointer;
|
||||
typedef typename allocators_type::size_type size_type;
|
||||
|
||||
static const std::size_t predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
|
||||
inline spatial_query(parameters_type const& par, translator_type const& t, Predicates const& p, OutIter out_it)
|
||||
: tr(t), pred(p), out_iter(out_it), found_count(0), strategy(index::detail::get_strategy(par))
|
||||
spatial_query(MembersHolder const& members, Predicates const& p, OutIter out_it)
|
||||
: m_tr(members.translator())
|
||||
, m_strategy(index::detail::get_strategy(members.parameters()))
|
||||
, m_pred(p)
|
||||
, m_out_iter(out_it)
|
||||
, m_found_count(0)
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node const& n)
|
||||
size_type apply(node_pointer ptr, size_type reverse_level)
|
||||
{
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// traverse nodes meeting predicates
|
||||
for (typename elements_type::const_iterator it = elements.begin();
|
||||
it != elements.end(); ++it)
|
||||
namespace id = index::detail;
|
||||
if (reverse_level > 0)
|
||||
{
|
||||
// if node meets predicates
|
||||
// 0 - dummy value
|
||||
if ( index::detail::predicates_check
|
||||
<
|
||||
index::detail::bounds_tag, 0, predicates_len
|
||||
>(pred, 0, it->first, strategy) )
|
||||
internal_node& n = rtree::get<internal_node>(*ptr);
|
||||
// traverse nodes meeting predicates
|
||||
for (auto const& p : rtree::elements(n))
|
||||
{
|
||||
rtree::apply_visitor(*this, *it->second);
|
||||
// if node meets predicates (0 is dummy value)
|
||||
if (id::predicates_check<id::bounds_tag>(m_pred, 0, p.first, m_strategy))
|
||||
{
|
||||
apply(p.second, reverse_level - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void operator()(leaf const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<leaf>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
|
||||
// get all values meeting predicates
|
||||
for (typename elements_type::const_iterator it = elements.begin();
|
||||
it != elements.end(); ++it)
|
||||
else
|
||||
{
|
||||
// if value meets predicates
|
||||
if ( index::detail::predicates_check
|
||||
<
|
||||
index::detail::value_tag, 0, predicates_len
|
||||
>(pred, *it, tr(*it), strategy) )
|
||||
leaf& n = rtree::get<leaf>(*ptr);
|
||||
// get all values meeting predicates
|
||||
for (auto const& v : rtree::elements(n))
|
||||
{
|
||||
*out_iter = *it;
|
||||
++out_iter;
|
||||
|
||||
++found_count;
|
||||
// if value meets predicates
|
||||
if (id::predicates_check<id::value_tag>(m_pred, v, m_tr(v), m_strategy))
|
||||
{
|
||||
*m_out_iter = v;
|
||||
++m_out_iter;
|
||||
++m_found_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_found_count;
|
||||
}
|
||||
|
||||
translator_type const& tr;
|
||||
size_type apply(MembersHolder const& members)
|
||||
{
|
||||
return apply(members.root, members.leafs_level);
|
||||
}
|
||||
|
||||
Predicates pred;
|
||||
private:
|
||||
translator_type const& m_tr;
|
||||
strategy_type m_strategy;
|
||||
|
||||
OutIter out_iter;
|
||||
size_type found_count;
|
||||
Predicates const& m_pred;
|
||||
OutIter m_out_iter;
|
||||
|
||||
strategy_type strategy;
|
||||
size_type m_found_count;
|
||||
};
|
||||
|
||||
template <typename MembersHolder, typename Predicates>
|
||||
class spatial_query_incremental
|
||||
: public MembersHolder::visitor_const
|
||||
{
|
||||
typedef typename MembersHolder::value_type value_type;
|
||||
typedef typename MembersHolder::parameters_type parameters_type;
|
||||
@ -110,7 +107,6 @@ class spatial_query_incremental
|
||||
|
||||
typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
|
||||
|
||||
public:
|
||||
typedef typename MembersHolder::node node;
|
||||
typedef typename MembersHolder::internal_node internal_node;
|
||||
typedef typename MembersHolder::leaf leaf;
|
||||
@ -123,37 +119,40 @@ public:
|
||||
typedef typename rtree::elements_type<leaf>::type leaf_elements;
|
||||
typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;
|
||||
|
||||
static const std::size_t predicates_len = index::detail::predicates_length<Predicates>::value;
|
||||
struct internal_data
|
||||
{
|
||||
internal_data(internal_iterator f, internal_iterator l, size_type rl)
|
||||
: first(f), last(l), reverse_level(rl)
|
||||
{}
|
||||
internal_iterator first;
|
||||
internal_iterator last;
|
||||
size_type reverse_level;
|
||||
};
|
||||
|
||||
inline spatial_query_incremental()
|
||||
: m_translator(NULL)
|
||||
// , m_pred()
|
||||
, m_values(NULL)
|
||||
, m_current()
|
||||
public:
|
||||
spatial_query_incremental()
|
||||
: m_translator(nullptr)
|
||||
// , m_strategy()
|
||||
{}
|
||||
|
||||
inline spatial_query_incremental(parameters_type const& params, translator_type const& t, Predicates const& p)
|
||||
: m_translator(::boost::addressof(t))
|
||||
, m_pred(p)
|
||||
, m_values(NULL)
|
||||
// , m_pred()
|
||||
, m_values(nullptr)
|
||||
, m_current()
|
||||
, m_strategy(index::detail::get_strategy(params))
|
||||
{}
|
||||
|
||||
inline void operator()(internal_node const& n)
|
||||
{
|
||||
typedef typename rtree::elements_type<internal_node>::type elements_type;
|
||||
elements_type const& elements = rtree::elements(n);
|
||||
spatial_query_incremental(Predicates const& p)
|
||||
: m_translator(nullptr)
|
||||
// , m_strategy()
|
||||
, m_pred(p)
|
||||
, m_values(nullptr)
|
||||
, m_current()
|
||||
{}
|
||||
|
||||
m_internal_stack.push_back(std::make_pair(elements.begin(), elements.end()));
|
||||
}
|
||||
|
||||
inline void operator()(leaf const& n)
|
||||
{
|
||||
m_values = ::boost::addressof(rtree::elements(n));
|
||||
m_current = rtree::elements(n).begin();
|
||||
}
|
||||
spatial_query_incremental(MembersHolder const& members, Predicates const& p)
|
||||
: m_translator(::boost::addressof(members.translator()))
|
||||
, m_strategy(index::detail::get_strategy(members.parameters()))
|
||||
, m_pred(p)
|
||||
, m_values(nullptr)
|
||||
, m_current()
|
||||
{}
|
||||
|
||||
const_reference dereference() const
|
||||
{
|
||||
@ -161,9 +160,9 @@ public:
|
||||
return *m_current;
|
||||
}
|
||||
|
||||
void initialize(node_pointer root)
|
||||
void initialize(MembersHolder const& members)
|
||||
{
|
||||
rtree::apply_visitor(*this, *root);
|
||||
apply(members.root, members.leafs_level);
|
||||
search_value();
|
||||
}
|
||||
|
||||
@ -173,8 +172,38 @@ public:
|
||||
search_value();
|
||||
}
|
||||
|
||||
bool is_end() const
|
||||
{
|
||||
return 0 == m_values;
|
||||
}
|
||||
|
||||
friend bool operator==(spatial_query_incremental const& l, spatial_query_incremental const& r)
|
||||
{
|
||||
return (l.m_values == r.m_values) && (0 == l.m_values || l.m_current == r.m_current);
|
||||
}
|
||||
|
||||
private:
|
||||
void apply(node_pointer ptr, size_type reverse_level)
|
||||
{
|
||||
namespace id = index::detail;
|
||||
|
||||
if (reverse_level > 0)
|
||||
{
|
||||
internal_node& n = rtree::get<internal_node>(*ptr);
|
||||
auto const& elements = rtree::elements(n);
|
||||
m_internal_stack.push_back(internal_data(elements.begin(), elements.end(), reverse_level - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
leaf& n = rtree::get<leaf>(*ptr);
|
||||
m_values = ::boost::addressof(rtree::elements(n));
|
||||
m_current = rtree::elements(n).begin();
|
||||
}
|
||||
}
|
||||
|
||||
void search_value()
|
||||
{
|
||||
namespace id = index::detail;
|
||||
for (;;)
|
||||
{
|
||||
// if leaf is choosen, move to the next value in leaf
|
||||
@ -184,10 +213,7 @@ public:
|
||||
{
|
||||
// return if next value is found
|
||||
value_type const& v = *m_current;
|
||||
if (index::detail::predicates_check
|
||||
<
|
||||
index::detail::value_tag, 0, predicates_len
|
||||
>(m_pred, v, (*m_translator)(v), m_strategy))
|
||||
if (id::predicates_check<id::value_tag>(m_pred, v, (*m_translator)(v), m_strategy))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -204,52 +230,40 @@ public:
|
||||
else
|
||||
{
|
||||
// return if there is no more nodes to traverse
|
||||
if ( m_internal_stack.empty() )
|
||||
if (m_internal_stack.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// no more children in current node, remove it from stack
|
||||
if ( m_internal_stack.back().first == m_internal_stack.back().second )
|
||||
internal_data& current_data = m_internal_stack.back();
|
||||
|
||||
// no more children in current node, remove it from stack
|
||||
if (current_data.first == current_data.last)
|
||||
{
|
||||
m_internal_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
internal_iterator it = m_internal_stack.back().first;
|
||||
++m_internal_stack.back().first;
|
||||
internal_iterator it = current_data.first;
|
||||
++current_data.first;
|
||||
|
||||
// next node is found, push it to the stack
|
||||
if (index::detail::predicates_check
|
||||
<
|
||||
index::detail::bounds_tag, 0, predicates_len
|
||||
>(m_pred, 0, it->first, m_strategy))
|
||||
if (id::predicates_check<id::bounds_tag>(m_pred, 0, it->first, m_strategy))
|
||||
{
|
||||
rtree::apply_visitor(*this, *(it->second));
|
||||
apply(it->second, current_data.reverse_level);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_end() const
|
||||
{
|
||||
return 0 == m_values;
|
||||
}
|
||||
|
||||
friend bool operator==(spatial_query_incremental const& l, spatial_query_incremental const& r)
|
||||
{
|
||||
return (l.m_values == r.m_values) && (0 == l.m_values || l.m_current == r.m_current );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
const translator_type * m_translator;
|
||||
strategy_type m_strategy;
|
||||
|
||||
Predicates m_pred;
|
||||
|
||||
std::vector< std::pair<internal_iterator, internal_iterator> > m_internal_stack;
|
||||
std::vector<internal_data> m_internal_stack;
|
||||
const leaf_elements * m_values;
|
||||
leaf_iterator m_current;
|
||||
|
||||
strategy_type m_strategy;
|
||||
};
|
||||
|
||||
}}} // namespace detail::rtree::visitors
|
||||
|
@ -1079,17 +1079,9 @@ public:
|
||||
template <typename Predicates, typename OutIter>
|
||||
size_type query(Predicates const& predicates, OutIter out_it) const
|
||||
{
|
||||
if ( !m_members.root )
|
||||
return 0;
|
||||
|
||||
static const std::size_t distance_predicates_count = detail::predicates_count_distance<Predicates>::value;
|
||||
static const bool is_distance_predicate = 0 < distance_predicates_count;
|
||||
BOOST_GEOMETRY_STATIC_ASSERT((distance_predicates_count <= 1),
|
||||
"Only one distance predicate can be passed.",
|
||||
Predicates);
|
||||
|
||||
return query_dispatch(predicates, out_it,
|
||||
std::integral_constant<bool, is_distance_predicate>());
|
||||
return m_members.root
|
||||
? query_dispatch(predicates, out_it)
|
||||
: 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1183,6 +1175,15 @@ public:
|
||||
return const_query_iterator();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Predicates>
|
||||
using query_iterator_t = std::conditional_t
|
||||
<
|
||||
detail::predicates_count_distance<Predicates>::value == 0,
|
||||
detail::rtree::iterators::spatial_query_iterator<members_holder, Predicates>,
|
||||
detail::rtree::iterators::distance_query_iterator<members_holder, Predicates>
|
||||
>;
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
|
||||
private:
|
||||
#endif
|
||||
@ -1240,38 +1241,15 @@ private:
|
||||
\return The iterator pointing at the begin of the query range.
|
||||
*/
|
||||
template <typename Predicates>
|
||||
std::conditional_t
|
||||
<
|
||||
detail::predicates_count_distance<Predicates>::value == 0,
|
||||
detail::rtree::iterators::spatial_query_iterator<members_holder, Predicates>,
|
||||
detail::rtree::iterators::distance_query_iterator
|
||||
<
|
||||
members_holder, Predicates,
|
||||
detail::predicates_find_distance<Predicates>::value
|
||||
>
|
||||
>
|
||||
qbegin_(Predicates const& predicates) const
|
||||
query_iterator_t<Predicates> qbegin_(Predicates const& predicates) const
|
||||
{
|
||||
static const std::size_t distance_predicates_count = detail::predicates_count_distance<Predicates>::value;
|
||||
BOOST_GEOMETRY_STATIC_ASSERT((distance_predicates_count <= 1),
|
||||
BOOST_GEOMETRY_STATIC_ASSERT((detail::predicates_count_distance<Predicates>::value <= 1),
|
||||
"Only one distance predicate can be passed.",
|
||||
Predicates);
|
||||
|
||||
typedef std::conditional_t
|
||||
<
|
||||
detail::predicates_count_distance<Predicates>::value == 0,
|
||||
detail::rtree::iterators::spatial_query_iterator<members_holder, Predicates>,
|
||||
detail::rtree::iterators::distance_query_iterator
|
||||
<
|
||||
members_holder, Predicates,
|
||||
detail::predicates_find_distance<Predicates>::value
|
||||
>
|
||||
> iterator_type;
|
||||
|
||||
if ( !m_members.root )
|
||||
return iterator_type(m_members.parameters(), m_members.translator(), predicates);
|
||||
|
||||
return iterator_type(m_members.root, m_members.parameters(), m_members.translator(), predicates);
|
||||
return m_members.root
|
||||
? query_iterator_t<Predicates>(m_members, predicates)
|
||||
: query_iterator_t<Predicates>(predicates);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1307,35 +1285,13 @@ private:
|
||||
\return The iterator pointing at the end of the query range.
|
||||
*/
|
||||
template <typename Predicates>
|
||||
std::conditional_t
|
||||
<
|
||||
detail::predicates_count_distance<Predicates>::value == 0,
|
||||
detail::rtree::iterators::spatial_query_iterator<members_holder, Predicates>,
|
||||
detail::rtree::iterators::distance_query_iterator
|
||||
<
|
||||
members_holder, Predicates,
|
||||
detail::predicates_find_distance<Predicates>::value
|
||||
>
|
||||
>
|
||||
qend_(Predicates const& predicates) const
|
||||
query_iterator_t<Predicates> qend_(Predicates const& predicates) const
|
||||
{
|
||||
static const std::size_t distance_predicates_count = detail::predicates_count_distance<Predicates>::value;
|
||||
BOOST_GEOMETRY_STATIC_ASSERT((distance_predicates_count <= 1),
|
||||
BOOST_GEOMETRY_STATIC_ASSERT((detail::predicates_count_distance<Predicates>::value <= 1),
|
||||
"Only one distance predicate can be passed.",
|
||||
Predicates);
|
||||
|
||||
typedef std::conditional_t
|
||||
<
|
||||
detail::predicates_count_distance<Predicates>::value == 0,
|
||||
detail::rtree::iterators::spatial_query_iterator<members_holder, Predicates>,
|
||||
detail::rtree::iterators::distance_query_iterator
|
||||
<
|
||||
members_holder, Predicates,
|
||||
detail::predicates_find_distance<Predicates>::value
|
||||
>
|
||||
> iterator_type;
|
||||
|
||||
return iterator_type(m_members.parameters(), m_members.translator(), predicates);
|
||||
return query_iterator_t<Predicates>(m_members.parameters(), m_members.translator(), predicates);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1436,10 +1392,9 @@ public:
|
||||
*/
|
||||
const_iterator begin() const
|
||||
{
|
||||
if ( !m_members.root )
|
||||
return const_iterator();
|
||||
|
||||
return const_iterator(m_members.root);
|
||||
return m_members.root
|
||||
? const_iterator(m_members.root)
|
||||
: const_iterator();
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1894,15 +1849,16 @@ private:
|
||||
\par Exception-safety
|
||||
strong
|
||||
*/
|
||||
template <typename Predicates, typename OutIter>
|
||||
size_type query_dispatch(Predicates const& predicates, OutIter out_it, std::false_type /*is_distance_predicate*/) const
|
||||
template
|
||||
<
|
||||
typename Predicates, typename OutIter,
|
||||
std::enable_if_t<(detail::predicates_count_distance<Predicates>::value == 0), int> = 0
|
||||
>
|
||||
size_type query_dispatch(Predicates const& predicates, OutIter out_it) const
|
||||
{
|
||||
detail::rtree::visitors::spatial_query<members_holder, Predicates, OutIter>
|
||||
find_v(m_members.parameters(), m_members.translator(), predicates, out_it);
|
||||
|
||||
detail::rtree::apply_visitor(find_v, *m_members.root);
|
||||
|
||||
return find_v.found_count;
|
||||
query(m_members, predicates, out_it);
|
||||
return query.apply(m_members);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1911,22 +1867,21 @@ private:
|
||||
\par Exception-safety
|
||||
strong
|
||||
*/
|
||||
template <typename Predicates, typename OutIter>
|
||||
size_type query_dispatch(Predicates const& predicates, OutIter out_it, std::true_type /*is_distance_predicate*/) const
|
||||
template
|
||||
<
|
||||
typename Predicates, typename OutIter,
|
||||
std::enable_if_t<(detail::predicates_count_distance<Predicates>::value > 0), int> = 0
|
||||
>
|
||||
size_type query_dispatch(Predicates const& predicates, OutIter out_it) const
|
||||
{
|
||||
BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist");
|
||||
BOOST_GEOMETRY_STATIC_ASSERT((detail::predicates_count_distance<Predicates>::value == 1),
|
||||
"Only one distance predicate can be passed.",
|
||||
Predicates);
|
||||
|
||||
static const std::size_t distance_predicate_index = detail::predicates_find_distance<Predicates>::value;
|
||||
detail::rtree::visitors::distance_query<
|
||||
members_holder,
|
||||
Predicates,
|
||||
distance_predicate_index,
|
||||
OutIter
|
||||
> distance_v(m_members.parameters(), m_members.translator(), predicates, out_it);
|
||||
detail::rtree::visitors::distance_query<members_holder, Predicates>
|
||||
distance_v(m_members, predicates);
|
||||
|
||||
detail::rtree::apply_visitor(distance_v, *m_members.root);
|
||||
|
||||
return distance_v.finish();
|
||||
return distance_v.apply(m_members, out_it);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/config.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/tag_cast.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/envelope.hpp>
|
||||
@ -37,7 +38,6 @@
|
||||
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/rescale_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_type.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/type_traits.hpp>
|
||||
|
||||
// TEMP
|
||||
|
@ -19,8 +19,8 @@
|
||||
#include <boost/rational.hpp>
|
||||
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@ -135,11 +135,15 @@ struct possibly_collinear<Type, false>
|
||||
template <typename Type>
|
||||
class segment_ratio
|
||||
{
|
||||
public :
|
||||
typedef Type numeric_type;
|
||||
// Type used for the approximation (a helper value)
|
||||
// and for the edge value (0..1) (a helper function).
|
||||
using floating_point_type =
|
||||
typename detail::promoted_to_floating_point<Type>::type;
|
||||
|
||||
// Type-alias for the type itself
|
||||
typedef segment_ratio<Type> thistype;
|
||||
using thistype = segment_ratio<Type>;
|
||||
|
||||
public :
|
||||
|
||||
inline segment_ratio()
|
||||
: m_numerator(0)
|
||||
@ -221,8 +225,8 @@ public :
|
||||
m_approximation =
|
||||
m_denominator == 0 ? 0
|
||||
: (
|
||||
boost::numeric_cast<fp_type>(m_numerator) * scale()
|
||||
/ boost::numeric_cast<fp_type>(m_denominator)
|
||||
boost::numeric_cast<floating_point_type>(m_numerator) * scale()
|
||||
/ boost::numeric_cast<floating_point_type>(m_denominator)
|
||||
);
|
||||
}
|
||||
|
||||
@ -254,21 +258,16 @@ public :
|
||||
return m_numerator > m_denominator;
|
||||
}
|
||||
|
||||
inline bool near_end() const
|
||||
//! Returns a value between 0.0 and 1.0
|
||||
//! 0.0 means: exactly in the middle
|
||||
//! 1.0 means: exactly on one of the edges (or even over it)
|
||||
inline floating_point_type edge_value() const
|
||||
{
|
||||
if (left() || right())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static fp_type const small_part_of_scale = scale() / 100;
|
||||
return m_approximation < small_part_of_scale
|
||||
|| m_approximation > scale() - small_part_of_scale;
|
||||
}
|
||||
|
||||
inline bool close_to(thistype const& other) const
|
||||
{
|
||||
return geometry::math::abs(m_approximation - other.m_approximation) < 50;
|
||||
using fp = floating_point_type;
|
||||
fp const one{1.0};
|
||||
floating_point_type const result
|
||||
= fp(2) * geometry::math::abs(fp(0.5) - m_approximation / scale());
|
||||
return result > one ? one : result;
|
||||
}
|
||||
|
||||
template <typename Threshold>
|
||||
@ -313,19 +312,7 @@ public :
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
private :
|
||||
// NOTE: if this typedef is used then fp_type is non-fundamental type
|
||||
// if Type is non-fundamental type
|
||||
//typedef typename promote_floating_point<Type>::type fp_type;
|
||||
|
||||
// TODO: What with user-defined numeric types?
|
||||
// Shouldn't here is_integral be checked?
|
||||
typedef std::conditional_t
|
||||
<
|
||||
std::is_floating_point<Type>::value, Type, double
|
||||
> fp_type;
|
||||
|
||||
Type m_numerator;
|
||||
Type m_denominator;
|
||||
@ -335,12 +322,19 @@ private :
|
||||
// Boost.Rational is used if the approximations are close.
|
||||
// Reason: performance, Boost.Rational does a GCD by default and also the
|
||||
// comparisons contain while-loops.
|
||||
fp_type m_approximation;
|
||||
floating_point_type m_approximation;
|
||||
|
||||
|
||||
static inline fp_type scale()
|
||||
inline bool close_to(thistype const& other) const
|
||||
{
|
||||
return 1000000.0;
|
||||
static floating_point_type const threshold{50.0};
|
||||
return geometry::math::abs(m_approximation - other.m_approximation)
|
||||
< threshold;
|
||||
}
|
||||
|
||||
static inline floating_point_type scale()
|
||||
{
|
||||
static floating_point_type const fp_scale{1000000.0};
|
||||
return fp_scale;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -20,12 +20,16 @@
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/covered_by.hpp>
|
||||
#include <boost/geometry/strategies/within.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategies/geographic/side.hpp>
|
||||
#include <boost/geometry/strategies/spherical/ssf.hpp>
|
||||
|
||||
@ -118,7 +122,7 @@ struct cartesian_point_box_by_side
|
||||
<
|
||||
within::detail::decide_within
|
||||
>(point, box,
|
||||
strategy::side::side_by_triangle<CalculationType>());
|
||||
strategy::side::side_robust<CalculationType>());
|
||||
}
|
||||
};
|
||||
|
||||
@ -189,7 +193,7 @@ struct cartesian_point_box_by_side
|
||||
<
|
||||
within::detail::decide_covered_by
|
||||
>(point, box,
|
||||
strategy::side::side_by_triangle<CalculationType>());
|
||||
strategy::side::side_robust<CalculationType>());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -14,10 +14,10 @@
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/azimuth.hpp>
|
||||
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
@ -38,13 +38,13 @@
|
||||
#include <boost/geometry/strategy/cartesian/envelope.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/expand_segment.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.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>
|
||||
#include <boost/geometry/strategies/intersection_result.hpp>
|
||||
@ -68,6 +68,61 @@ namespace boost { namespace geometry
|
||||
namespace strategy { namespace intersection
|
||||
{
|
||||
|
||||
namespace detail_usage
|
||||
{
|
||||
|
||||
// When calculating the intersection, the information of "a" or "b" can be used.
|
||||
// Theoretically this gives equal results, but due to floating point precision
|
||||
// there might be tiny differences. These are edge cases.
|
||||
// This structure is to determine if "a" or "b" should be used.
|
||||
// Prefer the segment closer to the endpoint.
|
||||
// If both are about equally close, then prefer the longer segment
|
||||
// To avoid hard thresholds, behavior is made fluent.
|
||||
// Calculate comparable length indications,
|
||||
// the longer the segment (relatively), the lower the value
|
||||
// such that the shorter lengths are evaluated higher and will
|
||||
// be preferred.
|
||||
template <bool IsArithmetic>
|
||||
struct use_a
|
||||
{
|
||||
template <typename Ct, typename Ev>
|
||||
static bool apply(Ct const& cla, Ct const& clb, Ev const& eva, Ev const& evb)
|
||||
{
|
||||
auto const clm = (std::max)(cla, clb);
|
||||
if (clm <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Relative comparible length
|
||||
auto const rcla = Ct(1.0) - cla / clm;
|
||||
auto const rclb = Ct(1.0) - clb / clm;
|
||||
|
||||
// Multipliers for edgevalue (ev) and relative comparible length (rcl)
|
||||
// They determine the balance between edge value (should be larger)
|
||||
// and segment length. In 99.9xx% of the cases there is no difference
|
||||
// at all (if either a or b is used). Therefore the values of the
|
||||
// constants are not sensitive for the majority of the situations.
|
||||
// One known case is #mysql_23023665_6 (difference) which needs mev >= 2
|
||||
Ev const mev = 5;
|
||||
Ev const mrcl = 1;
|
||||
|
||||
return mev * eva + mrcl * rcla > mev * evb + mrcl * rclb;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization for non arithmetic types. They will always use "a"
|
||||
template <>
|
||||
struct use_a<false>
|
||||
{
|
||||
template <typename Ct, typename Ev>
|
||||
static bool apply(Ct const& , Ct const& , Ev const& , Ev const& )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
\see http://mathworld.wolfram.com/Line-LineIntersection.html
|
||||
@ -180,30 +235,12 @@ struct cartesian_segments
|
||||
template <typename Point, typename Segment1, typename Segment2>
|
||||
void calculate(Point& point, Segment1 const& a, Segment2 const& b) const
|
||||
{
|
||||
bool use_a = true;
|
||||
|
||||
// Prefer one segment if one is on or near an endpoint
|
||||
bool const a_near_end = robust_ra.near_end();
|
||||
bool const b_near_end = robust_rb.near_end();
|
||||
if (a_near_end && ! b_near_end)
|
||||
{
|
||||
use_a = true;
|
||||
}
|
||||
else if (b_near_end && ! a_near_end)
|
||||
{
|
||||
use_a = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prefer shorter segment
|
||||
promoted_type const len_a = comparable_length_a();
|
||||
promoted_type const len_b = comparable_length_b();
|
||||
if (len_b < len_a)
|
||||
{
|
||||
use_a = false;
|
||||
}
|
||||
// else use_a is true but was already assigned like that
|
||||
}
|
||||
bool const use_a
|
||||
= detail_usage::use_a
|
||||
<
|
||||
std::is_arithmetic<CoordinateType>::value
|
||||
>::apply(comparable_length_a(), comparable_length_b(),
|
||||
robust_ra.edge_value(), robust_rb.edge_value());
|
||||
|
||||
if (use_a)
|
||||
{
|
||||
@ -402,7 +439,7 @@ struct cartesian_segments
|
||||
return Policy::disjoint();
|
||||
}
|
||||
|
||||
typedef side::side_by_triangle<CalculationType> side_strategy_type;
|
||||
typedef side::side_robust<CalculationType> side_strategy_type;
|
||||
side_info sides;
|
||||
sides.set<0>(side_strategy_type::apply(q1, q2, p1),
|
||||
side_strategy_type::apply(q1, q2, p2));
|
||||
|
@ -24,10 +24,10 @@
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategies/covered_by.hpp>
|
||||
#include <boost/geometry/strategies/within.hpp>
|
||||
|
||||
@ -116,7 +116,7 @@ public:
|
||||
else // count == 2 || count == -2
|
||||
{
|
||||
// 1 left, -1 right
|
||||
typedef side::side_by_triangle<CalculationType> side_strategy_type;
|
||||
typedef side::side_robust<CalculationType> side_strategy_type;
|
||||
side = side_strategy_type::apply(s1, s2, point);
|
||||
}
|
||||
|
||||
|
@ -1,275 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// 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) 2021, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015-2021.
|
||||
// Modifications copyright (c) 2015-2021, 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.
|
||||
|
||||
// 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)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
|
||||
#include <boost/geometry/strategies/compare.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace side
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Check at which side of a segment a point lies:
|
||||
left of segment (> 0), right of segment (< 0), on segment (0)
|
||||
\ingroup strategies
|
||||
\tparam CalculationType \tparam_calculation
|
||||
*/
|
||||
template <typename CalculationType = void>
|
||||
class side_by_triangle
|
||||
{
|
||||
template <typename Policy>
|
||||
struct eps_policy
|
||||
{
|
||||
eps_policy() {}
|
||||
template <typename Type>
|
||||
eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)
|
||||
: policy(a, b, c, d)
|
||||
{}
|
||||
Policy policy;
|
||||
};
|
||||
|
||||
struct eps_empty
|
||||
{
|
||||
eps_empty() {}
|
||||
template <typename Type>
|
||||
eps_empty(Type const&, Type const&, Type const&, Type const&) {}
|
||||
};
|
||||
|
||||
public :
|
||||
typedef cartesian_tag cs_tag;
|
||||
|
||||
// Template member function, because it is not always trivial
|
||||
// or convenient to explicitly mention the typenames in the
|
||||
// strategy-struct itself.
|
||||
|
||||
// Types can be all three different. Therefore it is
|
||||
// not implemented (anymore) as "segment"
|
||||
|
||||
template
|
||||
<
|
||||
typename CoordinateType,
|
||||
typename PromotedType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
typename P,
|
||||
typename EpsPolicy
|
||||
>
|
||||
static inline
|
||||
PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)
|
||||
{
|
||||
CoordinateType const x = get<0>(p);
|
||||
CoordinateType const y = get<1>(p);
|
||||
|
||||
CoordinateType const sx1 = get<0>(p1);
|
||||
CoordinateType const sy1 = get<1>(p1);
|
||||
CoordinateType const sx2 = get<0>(p2);
|
||||
CoordinateType const sy2 = get<1>(p2);
|
||||
|
||||
PromotedType const dx = sx2 - sx1;
|
||||
PromotedType const dy = sy2 - sy1;
|
||||
PromotedType const dpx = x - sx1;
|
||||
PromotedType const dpy = y - sy1;
|
||||
|
||||
eps_policy = EpsPolicy(dx, dy, dpx, dpy);
|
||||
|
||||
return geometry::detail::determinant<PromotedType>
|
||||
(
|
||||
dx, dy,
|
||||
dpx, dpy
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename CoordinateType,
|
||||
typename PromotedType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
typename P
|
||||
>
|
||||
static inline
|
||||
PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)
|
||||
{
|
||||
eps_empty dummy;
|
||||
return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename CoordinateType,
|
||||
typename PromotedType,
|
||||
bool AreAllIntegralCoordinates
|
||||
>
|
||||
struct compute_side_value
|
||||
{
|
||||
template <typename P1, typename P2, typename P, typename EpsPolicy>
|
||||
static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
|
||||
{
|
||||
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CoordinateType, typename PromotedType>
|
||||
struct compute_side_value<CoordinateType, PromotedType, false>
|
||||
{
|
||||
template <typename P1, typename P2, typename P, typename EpsPolicy>
|
||||
static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
|
||||
{
|
||||
// For robustness purposes, first check if any two points are
|
||||
// the same; in this case simply return that the points are
|
||||
// collinear
|
||||
if (equals_point_point(p1, p2)
|
||||
|| equals_point_point(p1, p)
|
||||
|| equals_point_point(p2, p))
|
||||
{
|
||||
return PromotedType(0);
|
||||
}
|
||||
|
||||
// The side_by_triangle strategy computes the signed area of
|
||||
// the point triplet (p1, p2, p); as such it is (in theory)
|
||||
// invariant under cyclic permutations of its three arguments.
|
||||
//
|
||||
// In the context of numerical errors that arise in
|
||||
// floating-point computations, and in order to make the strategy
|
||||
// consistent with respect to cyclic permutations of its three
|
||||
// arguments, we cyclically permute them so that the first
|
||||
// argument is always the lexicographically smallest point.
|
||||
|
||||
typedef compare::cartesian<compare::less> less;
|
||||
|
||||
if (less::apply(p, p1))
|
||||
{
|
||||
if (less::apply(p, p2))
|
||||
{
|
||||
// p is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// p2 is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
|
||||
}
|
||||
}
|
||||
|
||||
if (less::apply(p1, p2))
|
||||
{
|
||||
// p1 is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// p2 is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename P1, typename P2, typename P>
|
||||
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
|
||||
{
|
||||
typedef typename coordinate_type<P1>::type coordinate_type1;
|
||||
typedef typename coordinate_type<P2>::type coordinate_type2;
|
||||
typedef typename coordinate_type<P>::type coordinate_type3;
|
||||
|
||||
typedef std::conditional_t
|
||||
<
|
||||
std::is_void<CalculationType>::value,
|
||||
typename select_most_precise
|
||||
<
|
||||
coordinate_type1,
|
||||
coordinate_type2,
|
||||
coordinate_type3
|
||||
>::type,
|
||||
CalculationType
|
||||
> coordinate_type;
|
||||
|
||||
// Promote float->double, small int->int
|
||||
typedef typename select_most_precise
|
||||
<
|
||||
coordinate_type,
|
||||
double
|
||||
>::type promoted_type;
|
||||
|
||||
bool const are_all_integral_coordinates =
|
||||
std::is_integral<coordinate_type1>::value
|
||||
&& std::is_integral<coordinate_type2>::value
|
||||
&& std::is_integral<coordinate_type3>::value;
|
||||
|
||||
eps_policy< math::detail::equals_factor_policy<promoted_type> > epsp;
|
||||
promoted_type s = compute_side_value
|
||||
<
|
||||
coordinate_type, promoted_type, are_all_integral_coordinates
|
||||
>::apply(p1, p2, p, epsp);
|
||||
|
||||
promoted_type const zero = promoted_type();
|
||||
return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0
|
||||
: s > zero ? 1
|
||||
: -1;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename P1, typename P2>
|
||||
static inline bool equals_point_point(P1 const& p1, P2 const& p2)
|
||||
{
|
||||
return strategy::within::cartesian_point_point::apply(p1, p2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef side_by_triangle<CalculationType> type;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}} // namespace strategy::side
|
||||
|
||||
}} // namespace boost::geometry
|
||||
#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
@ -32,7 +33,6 @@
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/point_xy.hpp>
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
@ -37,7 +38,6 @@
|
||||
#include <boost/geometry/formulas/vincenty_direct.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
#include <boost/geometry/srs/spheroid.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
@ -26,7 +28,6 @@
|
||||
#include <boost/geometry/strategies/spherical/distance_segment_box.hpp>
|
||||
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
|
||||
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
|
@ -17,10 +17,10 @@
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/radius.hpp>
|
||||
|
||||
@ -32,7 +33,6 @@
|
||||
#include <boost/geometry/strategy/geographic/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
|
@ -19,12 +19,12 @@
|
||||
#include <boost/geometry/policies/relate/intersection_policy.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/intersection.hpp>
|
||||
#include <boost/geometry/strategies/intersection_result.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/intersection.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategies/spherical/intersection.hpp>
|
||||
#include <boost/geometry/strategies/spherical/ssf.hpp>
|
||||
|
||||
|
@ -11,10 +11,10 @@
|
||||
#define BOOST_GEOMETRY_STRATEGIES_IS_CONVEX_CARTESIAN_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
#include <boost/geometry/strategies/is_convex/services.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include <boost/geometry/strategies/detail.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/area.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/area_box.hpp>
|
||||
|
||||
#include <boost/geometry/util/type_traits.hpp>
|
||||
@ -156,7 +158,7 @@ public:
|
||||
|
||||
static auto side()
|
||||
{
|
||||
return strategy::side::side_by_triangle<CalculationType>();
|
||||
return strategy::side::side_robust<CalculationType>();
|
||||
}
|
||||
|
||||
// within
|
||||
@ -381,6 +383,15 @@ struct strategy_converter<strategy::side::side_by_triangle<CalculationType>>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CalculationType>
|
||||
struct strategy_converter<strategy::side::side_robust<CalculationType>>
|
||||
{
|
||||
static auto get(strategy::side::side_robust<CalculationType> const&)
|
||||
{
|
||||
return strategies::relate::cartesian<CalculationType>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace services
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
@ -36,7 +37,6 @@
|
||||
#include <boost/geometry/strategies/spherical/intersection.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
|
||||
@ -26,7 +27,6 @@
|
||||
#include <boost/geometry/strategies/spherical/get_radius.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
|
||||
@ -26,7 +27,6 @@
|
||||
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/spherical/envelope.hpp>
|
||||
|
@ -67,7 +67,6 @@
|
||||
#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/line_interpolate.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/spherical/azimuth.hpp>
|
||||
#include <boost/geometry/strategies/spherical/densify.hpp>
|
||||
@ -135,6 +134,8 @@
|
||||
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/expand_segment.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/geographic/area.hpp>
|
||||
#include <boost/geometry/strategy/geographic/envelope.hpp>
|
||||
|
@ -30,10 +30,10 @@
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/radian_access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/strategies/transform.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
|
@ -33,9 +33,9 @@
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
|
262
include/boost/geometry/strategy/cartesian/side_by_triangle.hpp
Normal file
262
include/boost/geometry/strategy/cartesian/side_by_triangle.hpp
Normal file
@ -0,0 +1,262 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015-2021.
|
||||
// Modifications copyright (c) 2015-2021, 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.
|
||||
|
||||
// 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_STRATEGY_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
|
||||
#include <boost/geometry/strategies/compare.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace side
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Check at which side of a segment a point lies:
|
||||
left of segment (> 0), right of segment (< 0), on segment (0)
|
||||
\ingroup strategies
|
||||
\tparam CalculationType \tparam_calculation
|
||||
*/
|
||||
template <typename CalculationType = void>
|
||||
class side_by_triangle
|
||||
{
|
||||
template <typename Policy>
|
||||
struct eps_policy
|
||||
{
|
||||
eps_policy() {}
|
||||
template <typename Type>
|
||||
eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)
|
||||
: policy(a, b, c, d)
|
||||
{}
|
||||
Policy policy;
|
||||
};
|
||||
|
||||
struct eps_empty
|
||||
{
|
||||
eps_empty() {}
|
||||
template <typename Type>
|
||||
eps_empty(Type const&, Type const&, Type const&, Type const&) {}
|
||||
};
|
||||
|
||||
public :
|
||||
typedef cartesian_tag cs_tag;
|
||||
|
||||
// Template member function, because it is not always trivial
|
||||
// or convenient to explicitly mention the typenames in the
|
||||
// strategy-struct itself.
|
||||
|
||||
// Types can be all three different. Therefore it is
|
||||
// not implemented (anymore) as "segment"
|
||||
|
||||
template
|
||||
<
|
||||
typename CoordinateType,
|
||||
typename PromotedType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
typename P,
|
||||
typename EpsPolicy
|
||||
>
|
||||
static inline
|
||||
PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)
|
||||
{
|
||||
CoordinateType const x = get<0>(p);
|
||||
CoordinateType const y = get<1>(p);
|
||||
|
||||
CoordinateType const sx1 = get<0>(p1);
|
||||
CoordinateType const sy1 = get<1>(p1);
|
||||
CoordinateType const sx2 = get<0>(p2);
|
||||
CoordinateType const sy2 = get<1>(p2);
|
||||
|
||||
PromotedType const dx = sx2 - sx1;
|
||||
PromotedType const dy = sy2 - sy1;
|
||||
PromotedType const dpx = x - sx1;
|
||||
PromotedType const dpy = y - sy1;
|
||||
|
||||
eps_policy = EpsPolicy(dx, dy, dpx, dpy);
|
||||
|
||||
return geometry::detail::determinant<PromotedType>
|
||||
(
|
||||
dx, dy,
|
||||
dpx, dpy
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename CoordinateType,
|
||||
typename PromotedType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
typename P
|
||||
>
|
||||
static inline
|
||||
PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)
|
||||
{
|
||||
eps_empty dummy;
|
||||
return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename CoordinateType,
|
||||
typename PromotedType,
|
||||
bool AreAllIntegralCoordinates
|
||||
>
|
||||
struct compute_side_value
|
||||
{
|
||||
template <typename P1, typename P2, typename P, typename EpsPolicy>
|
||||
static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
|
||||
{
|
||||
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CoordinateType, typename PromotedType>
|
||||
struct compute_side_value<CoordinateType, PromotedType, false>
|
||||
{
|
||||
template <typename P1, typename P2, typename P, typename EpsPolicy>
|
||||
static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
|
||||
{
|
||||
// For robustness purposes, first check if any two points are
|
||||
// the same; in this case simply return that the points are
|
||||
// collinear
|
||||
if (equals_point_point(p1, p2)
|
||||
|| equals_point_point(p1, p)
|
||||
|| equals_point_point(p2, p))
|
||||
{
|
||||
return PromotedType(0);
|
||||
}
|
||||
|
||||
// The side_by_triangle strategy computes the signed area of
|
||||
// the point triplet (p1, p2, p); as such it is (in theory)
|
||||
// invariant under cyclic permutations of its three arguments.
|
||||
//
|
||||
// In the context of numerical errors that arise in
|
||||
// floating-point computations, and in order to make the strategy
|
||||
// consistent with respect to cyclic permutations of its three
|
||||
// arguments, we cyclically permute them so that the first
|
||||
// argument is always the lexicographically smallest point.
|
||||
|
||||
typedef compare::cartesian<compare::less> less;
|
||||
|
||||
if (less::apply(p, p1))
|
||||
{
|
||||
if (less::apply(p, p2))
|
||||
{
|
||||
// p is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// p2 is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
|
||||
}
|
||||
}
|
||||
|
||||
if (less::apply(p1, p2))
|
||||
{
|
||||
// p1 is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// p2 is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename P1, typename P2, typename P>
|
||||
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
|
||||
{
|
||||
typedef typename coordinate_type<P1>::type coordinate_type1;
|
||||
typedef typename coordinate_type<P2>::type coordinate_type2;
|
||||
typedef typename coordinate_type<P>::type coordinate_type3;
|
||||
|
||||
typedef std::conditional_t
|
||||
<
|
||||
std::is_void<CalculationType>::value,
|
||||
typename select_most_precise
|
||||
<
|
||||
coordinate_type1,
|
||||
coordinate_type2,
|
||||
coordinate_type3
|
||||
>::type,
|
||||
CalculationType
|
||||
> coordinate_type;
|
||||
|
||||
// Promote float->double, small int->int
|
||||
typedef typename select_most_precise
|
||||
<
|
||||
coordinate_type,
|
||||
double
|
||||
>::type promoted_type;
|
||||
|
||||
bool const are_all_integral_coordinates =
|
||||
std::is_integral<coordinate_type1>::value
|
||||
&& std::is_integral<coordinate_type2>::value
|
||||
&& std::is_integral<coordinate_type3>::value;
|
||||
|
||||
eps_policy< math::detail::equals_factor_policy<promoted_type> > epsp;
|
||||
promoted_type s = compute_side_value
|
||||
<
|
||||
coordinate_type, promoted_type, are_all_integral_coordinates
|
||||
>::apply(p1, p2, p, epsp);
|
||||
|
||||
promoted_type const zero = promoted_type();
|
||||
return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0
|
||||
: s > zero ? 1
|
||||
: -1;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename P1, typename P2>
|
||||
static inline bool equals_point_point(P1 const& p1, P2 const& p2)
|
||||
{
|
||||
return strategy::within::cartesian_point_point::apply(p1, p2);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace strategy::side
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
@ -1,6 +1,6 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2020-2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
#include <boost/geometry/util/precise_math.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@ -21,7 +23,7 @@ namespace strategy { namespace side
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Adaptive precision predicate to check at which side of a segment a point lies:
|
||||
\brief Predicate to check at which side of a segment a point lies:
|
||||
left of segment (>0), right of segment (< 0), on segment (0).
|
||||
\ingroup strategies
|
||||
\tparam CalculationType \tparam_calculation
|
||||
@ -35,8 +37,6 @@ struct side_non_robust
|
||||
{
|
||||
public:
|
||||
//! \brief Computes double the signed area of the CCW triangle p1, p2, p
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
template
|
||||
<
|
||||
typename P1,
|
||||
@ -51,21 +51,44 @@ public:
|
||||
P1,
|
||||
P2,
|
||||
P
|
||||
>::type coordinate_type;
|
||||
>::type CoordinateType;
|
||||
typedef typename select_most_precise
|
||||
<
|
||||
coordinate_type,
|
||||
CoordinateType,
|
||||
double
|
||||
>::type promoted_type;
|
||||
>::type PromotedType;
|
||||
|
||||
auto detleft = (promoted_type(get<0>(p1)) - promoted_type(get<0>(p)))
|
||||
* (promoted_type(get<1>(p2)) - promoted_type(get<1>(p)));
|
||||
auto detright = (promoted_type(get<1>(p1)) - promoted_type(get<1>(p)))
|
||||
* (promoted_type(get<0>(p2)) - promoted_type(get<0>(p)));
|
||||
return detleft > detright ? 1 : (detleft < detright ? -1 : 0 );
|
||||
CoordinateType const x = get<0>(p);
|
||||
CoordinateType const y = get<1>(p);
|
||||
|
||||
CoordinateType const sx1 = get<0>(p1);
|
||||
CoordinateType const sy1 = get<1>(p1);
|
||||
CoordinateType const sx2 = get<0>(p2);
|
||||
CoordinateType const sy2 = get<1>(p2);
|
||||
|
||||
//non-robust 1
|
||||
//the following is 2x slower in some generic cases when compiled with g++
|
||||
//(tested versions 9 and 10)
|
||||
//
|
||||
//auto detleft = (sx1 - x) * (sy2 - y);
|
||||
//auto detright = (sy1 - y) * (sx2 - x);
|
||||
//return detleft > detright ? 1 : (detleft < detright ? -1 : 0 );
|
||||
|
||||
//non-robust 2
|
||||
PromotedType const dx = sx2 - sx1;
|
||||
PromotedType const dy = sy2 - sy1;
|
||||
PromotedType const dpx = x - sx1;
|
||||
PromotedType const dpy = y - sy1;
|
||||
|
||||
PromotedType sv = geometry::detail::determinant<PromotedType>
|
||||
(
|
||||
dx, dy,
|
||||
dpx, dpy
|
||||
);
|
||||
PromotedType const zero = PromotedType();
|
||||
|
||||
return sv == 0 ? 0 : sv > zero ? 1 : -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@ -17,9 +18,14 @@
|
||||
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/side_non_robust.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
#include <boost/geometry/util/precise_math.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@ -27,6 +33,27 @@ namespace boost { namespace geometry
|
||||
namespace strategy { namespace side
|
||||
{
|
||||
|
||||
struct epsilon_equals_policy
|
||||
{
|
||||
public:
|
||||
template <typename Policy, typename T1, typename T2>
|
||||
static bool apply(T1 const& a, T2 const& b, Policy const& policy)
|
||||
{
|
||||
return boost::geometry::math::detail::equals_by_policy(a, b, policy);
|
||||
}
|
||||
};
|
||||
|
||||
struct fp_equals_policy
|
||||
{
|
||||
public:
|
||||
template <typename Policy, typename T1, typename T2>
|
||||
static bool apply(T1 const& a, T2 const& b, Policy const&)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
\brief Adaptive precision predicate to check at which side of a segment a point lies:
|
||||
left of segment (>0), right of segment (< 0), on segment (0).
|
||||
@ -38,21 +65,52 @@ namespace strategy { namespace side
|
||||
template
|
||||
<
|
||||
typename CalculationType = void,
|
||||
typename EqualsPolicy = epsilon_equals_policy,
|
||||
std::size_t Robustness = 3
|
||||
>
|
||||
struct side_robust
|
||||
{
|
||||
|
||||
template <typename CT>
|
||||
struct epsilon_policy
|
||||
{
|
||||
using Policy = boost::geometry::math::detail::equals_factor_policy<CT>;
|
||||
|
||||
epsilon_policy() {}
|
||||
|
||||
template <typename Type>
|
||||
epsilon_policy(Type const& a, Type const& b, Type const& c, Type const& d)
|
||||
: m_policy(a, b, c, d)
|
||||
{}
|
||||
Policy m_policy;
|
||||
|
||||
public:
|
||||
|
||||
template <typename T1, typename T2>
|
||||
bool apply(T1 a, T2 b) const
|
||||
{
|
||||
return EqualsPolicy::apply(a, b, m_policy);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
//! \brief Computes double the signed area of the CCW triangle p1, p2, p
|
||||
|
||||
typedef cartesian_tag cs_tag;
|
||||
|
||||
//! \brief Computes the sign of the CCW triangle p1, p2, p
|
||||
template
|
||||
<
|
||||
typename PromotedType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
typename P
|
||||
typename P,
|
||||
typename EpsPolicyInternal,
|
||||
std::enable_if_t<std::is_fundamental<PromotedType>::value, int> = 0
|
||||
>
|
||||
static inline PromotedType side_value(P1 const& p1, P2 const& p2,
|
||||
P const& p)
|
||||
static inline PromotedType side_value(P1 const& p1,
|
||||
P2 const& p2,
|
||||
P const& p,
|
||||
EpsPolicyInternal& eps_policy)
|
||||
{
|
||||
using vec2d = ::boost::geometry::detail::precise_math::vec2d<PromotedType>;
|
||||
vec2d pa;
|
||||
@ -65,7 +123,22 @@ public:
|
||||
pc.x = get<0>(p);
|
||||
pc.y = get<1>(p);
|
||||
return ::boost::geometry::detail::precise_math::orient2d
|
||||
<PromotedType, Robustness>(pa, pb, pc);
|
||||
<PromotedType, Robustness>(pa, pb, pc, eps_policy);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename PromotedType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
typename P,
|
||||
typename EpsPolicyInternal,
|
||||
std::enable_if_t<!std::is_fundamental<PromotedType>::value, int> = 0
|
||||
>
|
||||
static inline auto side_value(P1 const& p1, P2 const& p2, P const& p,
|
||||
EpsPolicyInternal&)
|
||||
{
|
||||
return side_non_robust<>::apply(p1, p2, p);
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
@ -77,28 +150,48 @@ public:
|
||||
>
|
||||
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
|
||||
{
|
||||
typedef typename select_calculation_type_alt
|
||||
using coordinate_type = typename select_calculation_type_alt
|
||||
<
|
||||
CalculationType,
|
||||
P1,
|
||||
P2,
|
||||
P
|
||||
>::type coordinate_type;
|
||||
typedef typename select_most_precise
|
||||
>::type;
|
||||
|
||||
using promoted_type = typename select_most_precise
|
||||
<
|
||||
coordinate_type,
|
||||
double
|
||||
>::type promoted_type;
|
||||
>::type;
|
||||
|
||||
promoted_type sv = side_value<promoted_type>(p1, p2, p);
|
||||
return sv > 0 ? 1
|
||||
: sv < 0 ? -1
|
||||
: 0;
|
||||
epsilon_policy<promoted_type> epsp;
|
||||
promoted_type sv = side_value<promoted_type>(p1, p2, p, epsp);
|
||||
promoted_type const zero = promoted_type();
|
||||
|
||||
return epsp.apply(sv, zero) ? 0
|
||||
: sv > zero ? 1
|
||||
: -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef side_robust<CalculationType> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}} // namespace strategy::side
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
@ -5,6 +5,10 @@
|
||||
// Contributed and/or modified by Tinko Bartels,
|
||||
// as part of Google Summer of Code 2019 program.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fisikopoulos, 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)
|
||||
@ -157,7 +161,9 @@ inline int fast_expansion_sum_zeroelim(
|
||||
int n = InSize2)
|
||||
{
|
||||
std::array<RealNumber, 2> Qh;
|
||||
int i_e = 0, i_f = 0, i_h = 0;
|
||||
int i_e = 0;
|
||||
int i_f = 0;
|
||||
int i_h = 0;
|
||||
if (std::abs(f[0]) > std::abs(e[0]))
|
||||
{
|
||||
Qh[0] = e[i_e++];
|
||||
@ -282,14 +288,16 @@ inline RealNumber orient2dtail(vec2d<RealNumber> const& p1,
|
||||
std::array<RealNumber, 2>& t4,
|
||||
std::array<RealNumber, 2>& t5_01,
|
||||
std::array<RealNumber, 2>& t6_01,
|
||||
RealNumber const& magnitude
|
||||
)
|
||||
RealNumber const& magnitude)
|
||||
{
|
||||
t5_01[1] = two_product_tail(t1[0], t2[0], t5_01[0]);
|
||||
t6_01[1] = two_product_tail(t3[0], t4[0], t6_01[0]);
|
||||
std::array<RealNumber, 4> tA_03 = two_two_expansion_diff(t5_01, t6_01);
|
||||
RealNumber det = std::accumulate(tA_03.begin(), tA_03.end(), static_cast<RealNumber>(0));
|
||||
if(Robustness == 1) return det;
|
||||
if (Robustness == 1)
|
||||
{
|
||||
return det;
|
||||
}
|
||||
// see p.39, mind the different definition of epsilon for error bound
|
||||
RealNumber B_relative_bound =
|
||||
(1 + 3 * std::numeric_limits<RealNumber>::epsilon())
|
||||
@ -347,29 +355,37 @@ inline RealNumber orient2dtail(vec2d<RealNumber> const& p1,
|
||||
return(D[D_nz - 1]);
|
||||
}
|
||||
|
||||
// see page 38, Figure 21 for the calculations, notation follows the notation in the figure.
|
||||
// see page 38, Figure 21 for the calculations, notation follows the notation
|
||||
// in the figure.
|
||||
template
|
||||
<
|
||||
typename RealNumber,
|
||||
std::size_t Robustness = 3
|
||||
std::size_t Robustness = 3,
|
||||
typename EpsPolicy
|
||||
>
|
||||
inline RealNumber orient2d(vec2d<RealNumber> const& p1,
|
||||
vec2d<RealNumber> const& p2,
|
||||
vec2d<RealNumber> const& p3)
|
||||
vec2d<RealNumber> const& p3,
|
||||
EpsPolicy& eps_policy)
|
||||
{
|
||||
if(Robustness == 0)
|
||||
{
|
||||
return (p1.x - p3.x) * (p2.y - p3.y) - (p1.y - p3.y) * (p2.x - p3.x);
|
||||
}
|
||||
std::array<RealNumber, 2> t1, t2, t3, t4;
|
||||
t1[0] = p1.x - p3.x;
|
||||
t2[0] = p2.y - p3.y;
|
||||
t3[0] = p1.y - p3.y;
|
||||
t4[0] = p2.x - p3.x;
|
||||
|
||||
eps_policy = EpsPolicy(t1[0], t2[0], t3[0], t4[0]);
|
||||
|
||||
std::array<RealNumber, 2> t5_01, t6_01;
|
||||
t5_01[0] = t1[0] * t2[0];
|
||||
t6_01[0] = t3[0] * t4[0];
|
||||
RealNumber det = t5_01[0] - t6_01[0];
|
||||
|
||||
if (Robustness == 0)
|
||||
{
|
||||
return det;
|
||||
}
|
||||
|
||||
RealNumber const magnitude = std::abs(t5_01[0]) + std::abs(t6_01[0]);
|
||||
|
||||
// see p.39, mind the different definition of epsilon for error bound
|
||||
@ -388,7 +404,8 @@ inline RealNumber orient2d(vec2d<RealNumber> const& p1,
|
||||
//obvious
|
||||
return det;
|
||||
}
|
||||
return orient2dtail<RealNumber, Robustness>(p1, p2, p3, t1, t2, t3, t4, t5_01, t6_01, magnitude);
|
||||
return orient2dtail<RealNumber, Robustness>(p1, p2, p3, t1, t2, t3, t4,
|
||||
t5_01, t6_01, magnitude);
|
||||
}
|
||||
|
||||
// This method adaptively computes increasingly precise approximations of the following
|
||||
|
@ -18,35 +18,9 @@
|
||||
#ifndef BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
|
||||
#define BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
|
||||
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
BOOST_HEADER_DEPRECATED("boost/geometry/core/coordinate_promotion.hpp")
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
/*!
|
||||
\brief Meta-function converting, if necessary, to "a floating point" type
|
||||
\details
|
||||
- if input type is integer, type is double
|
||||
- else type is input type
|
||||
\ingroup utility
|
||||
*/
|
||||
|
||||
template <typename T, typename PromoteIntegerTo = double>
|
||||
struct promote_floating_point
|
||||
{
|
||||
typedef std::conditional_t
|
||||
<
|
||||
std::is_integral<T>::value,
|
||||
PromoteIntegerTo,
|
||||
T
|
||||
> type;
|
||||
};
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
|
||||
#endif // BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
|
||||
|
@ -2,6 +2,10 @@
|
||||
#
|
||||
# Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
#
|
||||
# This file was modified by Oracle on 2021.
|
||||
# Modifications copyright (c) 2021 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)
|
||||
@ -16,12 +20,12 @@ project boost-geometry-index-test
|
||||
<toolset>msvc:<asynch-exceptions>on
|
||||
<toolset>msvc:<cxxflags>/bigobj
|
||||
<host-os>windows,<toolset>intel:<cxxflags>/bigobj
|
||||
<define>BOOST_NO_AUTO_PTR # disable the deprecated std::auto_ptr support in SmartPtr and Core
|
||||
<library>/boost/timer//boost_timer
|
||||
;
|
||||
|
||||
test-suite boost-geometry-index-varray
|
||||
test-suite boost-geometry-index-detail
|
||||
:
|
||||
[ run minmax_heap.cpp ]
|
||||
[ run varray_old.cpp ]
|
||||
[ run varray.cpp ]
|
||||
;
|
||||
|
282
index/test/minmax_heap.cpp
Normal file
282
index/test/minmax_heap.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
#include <boost/test/impl/execution_monitor.ipp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <boost/geometry/index/detail/minmax_heap.hpp>
|
||||
#include <boost/geometry/index/detail/maxmin_heap.hpp>
|
||||
|
||||
using namespace boost::geometry::index::detail;
|
||||
|
||||
struct noncopyable
|
||||
{
|
||||
noncopyable(int i_) : i(i_) {}
|
||||
noncopyable(noncopyable const&) = delete;
|
||||
noncopyable& operator=(noncopyable const&) = delete;
|
||||
noncopyable(noncopyable&&) = default;
|
||||
noncopyable& operator=(noncopyable&&) = default;
|
||||
bool operator<(noncopyable const& other) const { return i < other.i; }
|
||||
operator int() const { return i; }
|
||||
int i;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct minmax_default
|
||||
{
|
||||
minmax_default() = default;
|
||||
minmax_default(std::vector<int> const& vec)
|
||||
: heap(vec.begin(), vec.end())
|
||||
{
|
||||
make_minmax_heap(heap.begin(), heap.end());
|
||||
}
|
||||
T const& top() const
|
||||
{
|
||||
return heap[0];
|
||||
}
|
||||
T const& bottom() const
|
||||
{
|
||||
return bottom_minmax_heap(heap.begin(), heap.end());
|
||||
}
|
||||
void push(int i)
|
||||
{
|
||||
heap.push_back(T(i));
|
||||
push_minmax_heap(heap.begin(), heap.end());
|
||||
}
|
||||
void pop_top()
|
||||
{
|
||||
pop_top_minmax_heap(heap.begin(), heap.end());
|
||||
heap.pop_back();
|
||||
}
|
||||
void pop_bottom()
|
||||
{
|
||||
pop_bottom_minmax_heap(heap.begin(), heap.end());
|
||||
heap.pop_back();
|
||||
}
|
||||
bool is_heap() const
|
||||
{
|
||||
return is_minmax_heap(heap.begin(), heap.end());
|
||||
}
|
||||
bool empty() const
|
||||
{
|
||||
return heap.empty();
|
||||
}
|
||||
std::vector<T> heap;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct minmax_less
|
||||
{
|
||||
minmax_less() = default;
|
||||
minmax_less(std::vector<int> const& vec)
|
||||
: heap(vec.begin(), vec.end())
|
||||
{
|
||||
make_minmax_heap(heap.begin(), heap.end(), std::less<>());
|
||||
}
|
||||
T const& top() const
|
||||
{
|
||||
return heap[0];
|
||||
}
|
||||
T const& bottom() const
|
||||
{
|
||||
return bottom_minmax_heap(heap.begin(), heap.end(), std::less<>());
|
||||
}
|
||||
void push(int i)
|
||||
{
|
||||
heap.push_back(T(i));
|
||||
push_minmax_heap(heap.begin(), heap.end(), std::less<>());
|
||||
}
|
||||
void pop_top()
|
||||
{
|
||||
pop_top_minmax_heap(heap.begin(), heap.end(), std::less<>());
|
||||
heap.pop_back();
|
||||
}
|
||||
void pop_bottom()
|
||||
{
|
||||
pop_bottom_minmax_heap(heap.begin(), heap.end(), std::less<>());
|
||||
heap.pop_back();
|
||||
}
|
||||
bool is_heap() const
|
||||
{
|
||||
return is_minmax_heap(heap.begin(), heap.end(), std::less<>());
|
||||
}
|
||||
bool empty() const
|
||||
{
|
||||
return heap.empty();
|
||||
}
|
||||
std::vector<T> heap;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct maxmin_greater
|
||||
{
|
||||
maxmin_greater() = default;
|
||||
maxmin_greater(std::vector<int> const& vec)
|
||||
: heap(vec.begin(), vec.end())
|
||||
{
|
||||
make_maxmin_heap(heap.begin(), heap.end(), std::greater<>());
|
||||
}
|
||||
T const& top() const
|
||||
{
|
||||
return heap[0];
|
||||
}
|
||||
T const& bottom() const
|
||||
{
|
||||
return bottom_maxmin_heap(heap.begin(), heap.end(), std::greater<>());
|
||||
}
|
||||
void push(int i)
|
||||
{
|
||||
heap.push_back(T(i));
|
||||
push_maxmin_heap(heap.begin(), heap.end(), std::greater<>());
|
||||
}
|
||||
void pop_top()
|
||||
{
|
||||
pop_top_maxmin_heap(heap.begin(), heap.end(), std::greater<>());
|
||||
heap.pop_back();
|
||||
}
|
||||
void pop_bottom()
|
||||
{
|
||||
pop_bottom_maxmin_heap(heap.begin(), heap.end(), std::greater<>());
|
||||
heap.pop_back();
|
||||
}
|
||||
bool is_heap() const
|
||||
{
|
||||
return is_maxmin_heap(heap.begin(), heap.end(), std::greater<>());
|
||||
}
|
||||
bool empty() const
|
||||
{
|
||||
return heap.empty();
|
||||
}
|
||||
std::vector<T> heap;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct maxmin_default_switch
|
||||
{
|
||||
maxmin_default_switch() = default;
|
||||
maxmin_default_switch(std::vector<int> const& vec)
|
||||
: heap(vec.begin(), vec.end())
|
||||
{
|
||||
make_maxmin_heap(heap.begin(), heap.end());
|
||||
}
|
||||
T const& bottom() const
|
||||
{
|
||||
return heap[0];
|
||||
}
|
||||
T const& top() const
|
||||
{
|
||||
return bottom_maxmin_heap(heap.begin(), heap.end());
|
||||
}
|
||||
void push(int i)
|
||||
{
|
||||
heap.push_back(T(i));
|
||||
push_maxmin_heap(heap.begin(), heap.end());
|
||||
}
|
||||
void pop_top()
|
||||
{
|
||||
pop_bottom_maxmin_heap(heap.begin(), heap.end());
|
||||
heap.pop_back();
|
||||
}
|
||||
void pop_bottom()
|
||||
{
|
||||
pop_top_maxmin_heap(heap.begin(), heap.end());
|
||||
heap.pop_back();
|
||||
}
|
||||
bool is_heap() const
|
||||
{
|
||||
return is_maxmin_heap(heap.begin(), heap.end());
|
||||
}
|
||||
bool empty() const
|
||||
{
|
||||
return heap.empty();
|
||||
}
|
||||
std::vector<T> heap;
|
||||
};
|
||||
|
||||
template <typename Heap>
|
||||
void test()
|
||||
{
|
||||
std::vector<int> vec;
|
||||
int const n = 20;
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
vec.push_back(rand() % n);
|
||||
}
|
||||
|
||||
{
|
||||
std::map<int, int> map;
|
||||
Heap heap;
|
||||
for (int i : vec)
|
||||
{
|
||||
heap.push(i);
|
||||
BOOST_CHECK(heap.is_heap());
|
||||
|
||||
map[i]++;
|
||||
BOOST_CHECK_EQUAL(heap.top(), map.begin()->first);
|
||||
BOOST_CHECK_EQUAL(heap.bottom(), (--map.end())->first);
|
||||
}
|
||||
|
||||
while (! heap.empty())
|
||||
{
|
||||
int i = heap.top();
|
||||
BOOST_CHECK_EQUAL(i, map.begin()->first);
|
||||
BOOST_CHECK_EQUAL(heap.bottom(), (--map.end())->first);
|
||||
BOOST_CHECK(map[i] > 0);
|
||||
map[i]--;
|
||||
if (map[i] <= 0)
|
||||
map.erase(i);
|
||||
|
||||
heap.pop_top();
|
||||
BOOST_CHECK(heap.is_heap());
|
||||
}
|
||||
|
||||
BOOST_CHECK(map.empty());
|
||||
}
|
||||
|
||||
{
|
||||
Heap heap(vec);
|
||||
BOOST_CHECK(heap.is_heap());
|
||||
|
||||
std::map<int, int> map;
|
||||
for (int i : vec)
|
||||
map[i]++;
|
||||
BOOST_CHECK_EQUAL(heap.top(), map.begin()->first);
|
||||
BOOST_CHECK_EQUAL(heap.bottom(), (--map.end())->first);
|
||||
|
||||
while (! heap.empty())
|
||||
{
|
||||
int i = heap.bottom();
|
||||
BOOST_CHECK_EQUAL(heap.top(), map.begin()->first);
|
||||
BOOST_CHECK_EQUAL(i, (--map.end())->first);
|
||||
BOOST_CHECK(map[i] > 0);
|
||||
map[i]--;
|
||||
if (map[i] <= 0)
|
||||
map.erase(i);
|
||||
|
||||
heap.pop_bottom();
|
||||
BOOST_CHECK(heap.is_heap());
|
||||
}
|
||||
|
||||
BOOST_CHECK(map.empty());
|
||||
}
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
{
|
||||
test<minmax_default<int>>();
|
||||
test<minmax_default<noncopyable>>();
|
||||
test<minmax_less<int>>();
|
||||
test<maxmin_greater<int>>();
|
||||
test<maxmin_default_switch<int>>();
|
||||
|
||||
return 0;
|
||||
}
|
@ -3,6 +3,10 @@
|
||||
|
||||
// Copyright (c) 2016 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, 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)
|
||||
@ -101,7 +105,7 @@ void test_ticket_12413()
|
||||
|
||||
size_t num_removed = rtree.remove(std::make_pair(point_t(-0.127592, 51.503407), 796));
|
||||
|
||||
BOOST_CHECK_EQUAL(num_removed, 1);
|
||||
BOOST_CHECK_EQUAL(num_removed, 1u);
|
||||
}
|
||||
|
||||
template <typename Point>
|
||||
|
@ -3,6 +3,10 @@
|
||||
|
||||
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, 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,7 +14,6 @@
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
@ -46,13 +49,13 @@ int main()
|
||||
testsets.push_back(std::make_pair("testset::queries", "que"));
|
||||
testsets.push_back(std::make_pair("testset::additional", "add"));
|
||||
|
||||
BOOST_FOREACH(P const& p, parameters)
|
||||
for (P const& p : parameters)
|
||||
{
|
||||
BOOST_FOREACH(TS const& ts, testsets)
|
||||
for (TS const& ts : testsets)
|
||||
{
|
||||
BOOST_FOREACH(std::string const& i, indexables)
|
||||
for (std::string const& i : indexables)
|
||||
{
|
||||
BOOST_FOREACH(std::string const& d, dimensions)
|
||||
for (std::string const& d : dimensions)
|
||||
{
|
||||
// If the I is Segment, generate only for 2d
|
||||
if ( i == "s" && d != "2" )
|
||||
@ -60,7 +63,7 @@ int main()
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(CT const& c, coordinate_types)
|
||||
for (CT const& c : coordinate_types)
|
||||
{
|
||||
std::string filename = std::string() +
|
||||
"rtree_" + boost::get<1>(p) + '_' + ts.second + '_' + i + d + boost::get<1>(c) + ".cpp";
|
||||
|
@ -14,7 +14,6 @@
|
||||
#ifndef BOOST_GEOMETRY_INDEX_TEST_RTREE_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_TEST_RTREE_HPP
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
@ -415,6 +414,8 @@ struct counting_value
|
||||
counting_value(counting_value const& c) : indexable(c.indexable) { counter()++; }
|
||||
~counting_value() { counter()--; }
|
||||
|
||||
counting_value& operator=(counting_value const& c) = default;
|
||||
|
||||
static size_t & counter() { static size_t c = 0; return c; }
|
||||
Indexable indexable;
|
||||
};
|
||||
@ -681,15 +682,16 @@ void rtree(Rtree & tree, Elements & input, Box & qbox)
|
||||
|
||||
} // namespace generate
|
||||
|
||||
namespace basictest {
|
||||
namespace basictest
|
||||
{
|
||||
|
||||
// low level test functions
|
||||
|
||||
template <typename Rtree, typename Iter, typename Value>
|
||||
Iter find(Rtree const& rtree, Iter first, Iter last, Value const& value)
|
||||
{
|
||||
for ( ; first != last ; ++first )
|
||||
if ( rtree.value_eq()(value, *first) )
|
||||
for (; first != last; ++first)
|
||||
if (rtree.value_eq()(value, *first))
|
||||
return first;
|
||||
return first;
|
||||
}
|
||||
@ -698,12 +700,12 @@ template <typename Rtree, typename Value>
|
||||
void compare_outputs(Rtree const& rtree, std::vector<Value> const& output, std::vector<Value> const& expected_output)
|
||||
{
|
||||
bool are_sizes_ok = (expected_output.size() == output.size());
|
||||
BOOST_CHECK( are_sizes_ok );
|
||||
if ( are_sizes_ok )
|
||||
BOOST_CHECK(are_sizes_ok);
|
||||
if (are_sizes_ok)
|
||||
{
|
||||
BOOST_FOREACH(Value const& v, expected_output)
|
||||
for (Value const& v : expected_output)
|
||||
{
|
||||
BOOST_CHECK(find(rtree, output.begin(), output.end(), v) != output.end() );
|
||||
BOOST_CHECK(find(rtree, output.begin(), output.end(), v) != output.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -715,13 +717,13 @@ void exactly_the_same_outputs(Rtree const& rtree, Range1 const& output, Range2 c
|
||||
size_t s2 = std::distance(expected_output.begin(), expected_output.end());
|
||||
BOOST_CHECK(s1 == s2);
|
||||
|
||||
if ( s1 == s2 )
|
||||
if (s1 == s2)
|
||||
{
|
||||
typename Range1::const_iterator it1 = output.begin();
|
||||
typename Range2::const_iterator it2 = expected_output.begin();
|
||||
for ( ; it1 != output.end() && it2 != expected_output.end() ; ++it1, ++it2 )
|
||||
for (; it1 != output.end() && it2 != expected_output.end(); ++it1, ++it2)
|
||||
{
|
||||
if ( !rtree.value_eq()(*it1, *it2) )
|
||||
if (!rtree.value_eq()(*it1, *it2))
|
||||
{
|
||||
BOOST_CHECK(false && "rtree.translator().equals(*it1, *it2)");
|
||||
break;
|
||||
@ -734,7 +736,7 @@ void exactly_the_same_outputs(Rtree const& rtree, Range1 const& output, Range2 c
|
||||
template <typename First, typename Last, typename Out>
|
||||
void copy_alt(First first, Last last, Out out)
|
||||
{
|
||||
for ( ; first != last ; ++first, ++out )
|
||||
for (; first != last; ++first, ++out)
|
||||
*out = *first;
|
||||
}
|
||||
|
||||
@ -759,7 +761,7 @@ void check_fwd_iterators(QItF first, QItL last)
|
||||
#endif
|
||||
|
||||
QItF it = first;
|
||||
for ( ; it != last && first != last ; ++it, ++first)
|
||||
for (; it != last && first != last; ++it, ++first)
|
||||
{
|
||||
BOOST_CHECK(it == first);
|
||||
|
||||
@ -775,20 +777,20 @@ void check_fwd_iterators(QItF first, QItL last)
|
||||
template <typename Rtree, typename Value, typename Predicates>
|
||||
void spatial_query(Rtree & rtree, Predicates const& pred, std::vector<Value> const& expected_output)
|
||||
{
|
||||
BOOST_CHECK( bgi::detail::rtree::utilities::are_levels_ok(rtree) );
|
||||
if ( !rtree.empty() )
|
||||
BOOST_CHECK( bgi::detail::rtree::utilities::are_boxes_ok(rtree) );
|
||||
BOOST_CHECK(bgi::detail::rtree::utilities::are_levels_ok(rtree));
|
||||
if (!rtree.empty())
|
||||
BOOST_CHECK(bgi::detail::rtree::utilities::are_boxes_ok(rtree));
|
||||
|
||||
std::vector<Value> output;
|
||||
size_t n = rtree.query(pred, std::back_inserter(output));
|
||||
|
||||
BOOST_CHECK( expected_output.size() == n );
|
||||
BOOST_CHECK(expected_output.size() == n);
|
||||
compare_outputs(rtree, output, expected_output);
|
||||
|
||||
std::vector<Value> output2;
|
||||
size_t n2 = query(rtree, pred, std::back_inserter(output2));
|
||||
|
||||
BOOST_CHECK( n == n2 );
|
||||
|
||||
BOOST_CHECK(n == n2);
|
||||
exactly_the_same_outputs(rtree, output, output2);
|
||||
|
||||
exactly_the_same_outputs(rtree, output, rtree | bgi::adaptors::queried(pred));
|
||||
@ -827,9 +829,13 @@ void intersects(Rtree const& tree, std::vector<Value> const& input, Box const& q
|
||||
{
|
||||
std::vector<Value> expected_output;
|
||||
|
||||
BOOST_FOREACH(Value const& v, input)
|
||||
if ( bg::intersects(tree.indexable_get()(v), qbox) )
|
||||
for (Value const& v : input)
|
||||
{
|
||||
if (bg::intersects(tree.indexable_get()(v), qbox))
|
||||
{
|
||||
expected_output.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
//spatial_query(tree, qbox, expected_output);
|
||||
spatial_query(tree, bgi::intersects(qbox), expected_output);
|
||||
@ -851,9 +857,13 @@ void disjoint(Rtree const& tree, std::vector<Value> const& input, Box const& qbo
|
||||
{
|
||||
std::vector<Value> expected_output;
|
||||
|
||||
BOOST_FOREACH(Value const& v, input)
|
||||
if ( bg::disjoint(tree.indexable_get()(v), qbox) )
|
||||
for (Value const& v : input)
|
||||
{
|
||||
if (bg::disjoint(tree.indexable_get()(v), qbox))
|
||||
{
|
||||
expected_output.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
spatial_query(tree, bgi::disjoint(qbox), expected_output);
|
||||
spatial_query(tree, !bgi::intersects(qbox), expected_output);
|
||||
@ -875,9 +885,13 @@ struct contains_impl
|
||||
{
|
||||
std::vector<Value> expected_output;
|
||||
|
||||
BOOST_FOREACH(Value const& v, input)
|
||||
if ( bg::within(qbox, tree.indexable_get()(v)) )
|
||||
for (Value const& v : input)
|
||||
{
|
||||
if (bg::within(qbox, tree.indexable_get()(v)))
|
||||
{
|
||||
expected_output.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
spatial_query(tree, bgi::contains(qbox), expected_output);
|
||||
|
||||
@ -912,7 +926,7 @@ void contains(Rtree const& tree, std::vector<Value> const& input, Box const& qbo
|
||||
{
|
||||
contains_impl<
|
||||
typename bg::tag<
|
||||
typename Rtree::indexable_type
|
||||
typename Rtree::indexable_type
|
||||
>::type
|
||||
>::apply(tree, input, qbox);
|
||||
}
|
||||
@ -925,12 +939,12 @@ struct covered_by_impl
|
||||
{
|
||||
std::vector<Value> expected_output;
|
||||
|
||||
BOOST_FOREACH(Value const& v, input)
|
||||
for (Value const& v : input)
|
||||
{
|
||||
if ( bgi::detail::covered_by_bounds(
|
||||
tree.indexable_get()(v),
|
||||
qbox,
|
||||
bgi::detail::get_strategy(tree.parameters())) )
|
||||
if (bgi::detail::covered_by_bounds(
|
||||
tree.indexable_get()(v),
|
||||
qbox,
|
||||
bgi::detail::get_strategy(tree.parameters())))
|
||||
{
|
||||
expected_output.push_back(v);
|
||||
}
|
||||
@ -961,7 +975,7 @@ void covered_by(Rtree const& tree, std::vector<Value> const& input, Box const& q
|
||||
{
|
||||
covered_by_impl<
|
||||
typename bg::tag<
|
||||
typename Rtree::indexable_type
|
||||
typename Rtree::indexable_type
|
||||
>::type
|
||||
>::apply(tree, input, qbox);
|
||||
}
|
||||
@ -974,9 +988,13 @@ struct covers_impl
|
||||
{
|
||||
std::vector<Value> expected_output;
|
||||
|
||||
BOOST_FOREACH(Value const& v, input)
|
||||
if ( bg::covered_by(qbox, tree.indexable_get()(v)) )
|
||||
for (Value const& v : input)
|
||||
{
|
||||
if (bg::covered_by(qbox, tree.indexable_get()(v)))
|
||||
{
|
||||
expected_output.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
spatial_query(tree, bgi::covers(qbox), expected_output);
|
||||
|
||||
@ -1011,7 +1029,7 @@ void covers(Rtree const& tree, std::vector<Value> const& input, Box const& qbox)
|
||||
{
|
||||
covers_impl<
|
||||
typename bg::tag<
|
||||
typename Rtree::indexable_type
|
||||
typename Rtree::indexable_type
|
||||
>::type
|
||||
>::apply(tree, input, qbox);
|
||||
}
|
||||
@ -1024,9 +1042,13 @@ struct overlaps_impl
|
||||
{
|
||||
std::vector<Value> expected_output;
|
||||
|
||||
BOOST_FOREACH(Value const& v, input)
|
||||
if ( bg::overlaps(tree.indexable_get()(v), qbox) )
|
||||
for (Value const& v : input)
|
||||
{
|
||||
if (bg::overlaps(tree.indexable_get()(v), qbox))
|
||||
{
|
||||
expected_output.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
spatial_query(tree, bgi::overlaps(qbox), expected_output);
|
||||
|
||||
@ -1061,7 +1083,7 @@ void overlaps(Rtree const& tree, std::vector<Value> const& input, Box const& qbo
|
||||
{
|
||||
overlaps_impl<
|
||||
typename bg::tag<
|
||||
typename Rtree::indexable_type
|
||||
typename Rtree::indexable_type
|
||||
>::type
|
||||
>::apply(tree, input, qbox);
|
||||
}
|
||||
@ -1082,9 +1104,13 @@ void overlaps(Rtree const& tree, std::vector<Value> const& input, Box const& qbo
|
||||
// {
|
||||
// std::vector<Value> expected_output;
|
||||
//
|
||||
// BOOST_FOREACH(Value const& v, input)
|
||||
// if ( bg::touches(tree.translator()(v), qbox) )
|
||||
// for (Value const& v : input)
|
||||
// {
|
||||
// if (bg::touches(tree.translator()(v), qbox))
|
||||
// {
|
||||
// expected_output.push_back(v);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// spatial_query(tree, bgi::touches(qbox), expected_output);
|
||||
// }
|
||||
@ -1107,9 +1133,13 @@ struct within_impl
|
||||
{
|
||||
std::vector<Value> expected_output;
|
||||
|
||||
BOOST_FOREACH(Value const& v, input)
|
||||
if ( bg::within(tree.indexable_get()(v), qbox) )
|
||||
for (Value const& v : input)
|
||||
{
|
||||
if (bg::within(tree.indexable_get()(v), qbox))
|
||||
{
|
||||
expected_output.push_back(v);
|
||||
}
|
||||
}
|
||||
|
||||
spatial_query(tree, bgi::within(qbox), expected_output);
|
||||
|
||||
@ -1172,15 +1202,15 @@ inline void compare_nearest_outputs(Rtree const& rtree, std::vector<Value> const
|
||||
{
|
||||
// check output
|
||||
bool are_sizes_ok = (expected_output.size() == output.size());
|
||||
BOOST_CHECK( are_sizes_ok );
|
||||
if ( are_sizes_ok )
|
||||
BOOST_CHECK(are_sizes_ok);
|
||||
if (are_sizes_ok)
|
||||
{
|
||||
BOOST_FOREACH(Value const& v, output)
|
||||
for (Value const& v : output)
|
||||
{
|
||||
// TODO - perform explicit check here?
|
||||
// should all objects which are closest be checked and should exactly the same be found?
|
||||
|
||||
if ( find(rtree, expected_output.begin(), expected_output.end(), v) == expected_output.end() )
|
||||
if (find(rtree, expected_output.begin(), expected_output.end(), v) == expected_output.end())
|
||||
{
|
||||
Distance d = bg::comparable_distance(pt, rtree.indexable_get()(v));
|
||||
BOOST_CHECK(d == greatest_distance);
|
||||
@ -1195,7 +1225,7 @@ inline void check_sorted_by_distance(Rtree const& rtree, std::vector<Value> cons
|
||||
typedef typename bg::default_distance_result<Point, typename Rtree::indexable_type>::type D;
|
||||
|
||||
D prev_dist = 0;
|
||||
BOOST_FOREACH(Value const& v, output)
|
||||
for (Value const& v : output)
|
||||
{
|
||||
D d = bg::comparable_distance(pt, rtree.indexable_get()(v));
|
||||
BOOST_CHECK(prev_dist <= d);
|
||||
@ -1214,25 +1244,31 @@ inline void nearest_query_k(Rtree const& rtree, std::vector<Value> const& input,
|
||||
std::vector< std::pair<D, Value> > test_output;
|
||||
|
||||
// calculate test output - k closest values pairs
|
||||
BOOST_FOREACH(Value const& v, input)
|
||||
for (Value const& v : input)
|
||||
{
|
||||
D d = bg::comparable_distance(pt, rtree.indexable_get()(v));
|
||||
|
||||
if ( test_output.size() < k )
|
||||
if (test_output.size() < k)
|
||||
{
|
||||
test_output.push_back(std::make_pair(d, v));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::sort(test_output.begin(), test_output.end(), NearestKLess<Rtree, Point>());
|
||||
if ( d < test_output.back().first )
|
||||
if (d < test_output.back().first)
|
||||
{
|
||||
test_output.back() = std::make_pair(d, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// caluclate biggest distance
|
||||
std::sort(test_output.begin(), test_output.end(), NearestKLess<Rtree, Point>());
|
||||
D greatest_distance = 0;
|
||||
if ( !test_output.empty() )
|
||||
if (! test_output.empty())
|
||||
{
|
||||
greatest_distance = test_output.back().first;
|
||||
}
|
||||
|
||||
// transform test output to vector of values
|
||||
std::vector<Value> expected_output(test_output.size(), generate::value_default<Value>::apply());
|
||||
@ -1441,8 +1477,10 @@ void create_insert(Rtree const& tree, std::vector<Value> const& input, Box const
|
||||
|
||||
{
|
||||
Rtree t(tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator());
|
||||
BOOST_FOREACH(Value const& v, input)
|
||||
for (Value const& v : input)
|
||||
{
|
||||
t.insert(v);
|
||||
}
|
||||
BOOST_CHECK(tree.size() == t.size());
|
||||
std::vector<Value> output;
|
||||
t.query(bgi::intersects(qbox), std::back_inserter(output));
|
||||
@ -1490,8 +1528,10 @@ void create_insert(Rtree const& tree, std::vector<Value> const& input, Box const
|
||||
|
||||
{
|
||||
Rtree t(tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator());
|
||||
BOOST_FOREACH(Value const& v, input)
|
||||
for (Value const& v : input)
|
||||
{
|
||||
bgi::insert(t, v);
|
||||
}
|
||||
BOOST_CHECK(tree.size() == t.size());
|
||||
std::vector<Value> output;
|
||||
bgi::query(t, bgi::intersects(qbox), std::back_inserter(output));
|
||||
@ -1538,8 +1578,10 @@ void remove(Rtree const& tree, Box const& qbox)
|
||||
{
|
||||
Rtree t(tree);
|
||||
size_t r = 0;
|
||||
BOOST_FOREACH(Value const& v, values_to_remove)
|
||||
for (Value const& v : values_to_remove)
|
||||
{
|
||||
r += t.remove(v);
|
||||
}
|
||||
BOOST_CHECK( r == expected_removed_count );
|
||||
std::vector<Value> output;
|
||||
t.query(bgi::disjoint(qbox), std::back_inserter(output));
|
||||
@ -1571,8 +1613,10 @@ void remove(Rtree const& tree, Box const& qbox)
|
||||
{
|
||||
Rtree t(tree);
|
||||
size_t r = 0;
|
||||
BOOST_FOREACH(Value const& v, values_to_remove)
|
||||
for (Value const& v : values_to_remove)
|
||||
{
|
||||
r += bgi::remove(t, v);
|
||||
}
|
||||
BOOST_CHECK( r == expected_removed_count );
|
||||
std::vector<Value> output;
|
||||
bgi::query(t, bgi::disjoint(qbox), std::back_inserter(output));
|
||||
@ -1643,7 +1687,7 @@ void range(Rtree & tree, std::vector<Value> const& input)
|
||||
BOOST_CHECK(count == tree.size());
|
||||
|
||||
count = 0;
|
||||
BOOST_FOREACH(Value const& v, tree)
|
||||
for (Value const& v : tree)
|
||||
{
|
||||
boost::ignore_unused(v);
|
||||
++count;
|
||||
@ -1777,7 +1821,7 @@ void test_count_rtree_values(Parameters const& parameters, Allocator const& allo
|
||||
|
||||
size_t values_count = Value::counter();
|
||||
|
||||
BOOST_FOREACH(Value const& v, values_to_remove)
|
||||
for (Value const& v : values_to_remove)
|
||||
{
|
||||
size_t r = t.remove(v);
|
||||
--values_count;
|
||||
|
@ -4,6 +4,10 @@
|
||||
// Copyright (c) 2012-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2012-2013 Andrew Hundt.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, 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)
|
||||
@ -55,11 +59,11 @@ void test_ctor_nc(size_t n)
|
||||
if ( 1 < n )
|
||||
{
|
||||
T val10(10);
|
||||
s[0] = val10;
|
||||
s[0] = std::move(val10);
|
||||
BOOST_CHECK(T(10) == s[0]);
|
||||
BOOST_CHECK(T(10) == s.at(0));
|
||||
T val20(20);
|
||||
s.at(1) = val20;
|
||||
s.at(1) = std::move(val20);
|
||||
BOOST_CHECK(T(20) == s[1]);
|
||||
BOOST_CHECK(T(20) == s.at(1));
|
||||
}
|
||||
@ -103,11 +107,11 @@ void test_resize_nc(size_t n)
|
||||
if ( 1 < n )
|
||||
{
|
||||
T val10(10);
|
||||
s[0] = val10;
|
||||
s[0] = std::move(val10);
|
||||
BOOST_CHECK(T(10) == s[0]);
|
||||
BOOST_CHECK(T(10) == s.at(0));
|
||||
T val20(20);
|
||||
s.at(1) = val20;
|
||||
s.at(1) = std::move(val20);
|
||||
BOOST_CHECK(T(20) == s[1]);
|
||||
BOOST_CHECK(T(20) == s.at(1));
|
||||
}
|
||||
|
@ -4,6 +4,10 @@
|
||||
// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2012-2013 Andrew Hundt.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, 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)
|
||||
@ -23,9 +27,11 @@ public:
|
||||
~value_ndc() {}
|
||||
bool operator==(value_ndc const& v) const { return aa == v.aa; }
|
||||
bool operator<(value_ndc const& v) const { return aa < v.aa; }
|
||||
value_ndc(value_ndc const&) = delete;
|
||||
value_ndc & operator=(value_ndc const&) = delete;
|
||||
value_ndc(value_ndc&&) = default;
|
||||
value_ndc & operator=(value_ndc&&) = default;
|
||||
private:
|
||||
value_ndc(value_ndc const&) {}
|
||||
value_ndc & operator=(value_ndc const&) { return *this; }
|
||||
size_t aa;
|
||||
};
|
||||
|
||||
@ -47,9 +53,11 @@ public:
|
||||
~value_nc() {}
|
||||
bool operator==(value_nc const& v) const { return aa == v.aa; }
|
||||
bool operator<(value_nc const& v) const { return aa < v.aa; }
|
||||
value_nc(value_nc const&) = delete;
|
||||
value_nc & operator=(value_nc const&) = delete;
|
||||
value_nc(value_nc&&) = default;
|
||||
value_nc & operator=(value_nc&&) = default;
|
||||
private:
|
||||
value_nc(value_nc const&) {}
|
||||
value_nc & operator=(value_ndc const&) { return *this; }
|
||||
size_t aa;
|
||||
};
|
||||
|
||||
|
@ -430,7 +430,7 @@ int test_main(int, char* [])
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
|
||||
BoostGeometryWriteExpectedFailures(2, 4, 9, 4);
|
||||
BoostGeometryWriteExpectedFailures(2, 4, 11, 3);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -686,7 +686,7 @@ int test_main(int, char* [])
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
|
||||
BoostGeometryWriteExpectedFailures(5, 1, 3, 4);
|
||||
BoostGeometryWriteExpectedFailures(3, 1, 3, 3);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -6,6 +6,7 @@
|
||||
// This file was modified by Oracle on 2014-2021.
|
||||
// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
@ -31,8 +32,10 @@
|
||||
#include <boost/geometry/strategies/strategies.hpp>
|
||||
#include <boost/geometry/strategies/spherical/side_by_cross_track.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/precise_area.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_non_robust.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/precise_area.hpp>
|
||||
|
||||
#include <boost/geometry/io/wkt/wkt.hpp>
|
||||
@ -44,7 +47,11 @@ struct robust_cartesian : boost::geometry::strategies::convex_hull::cartesian<>
|
||||
{
|
||||
static auto side()
|
||||
{
|
||||
return boost::geometry::strategy::side::side_robust<>();
|
||||
return boost::geometry::strategy::side::side_robust
|
||||
<
|
||||
double,
|
||||
boost::geometry::strategy::side::fp_equals_policy
|
||||
>();
|
||||
}
|
||||
};
|
||||
|
||||
@ -75,6 +82,7 @@ struct sphrerical_side_by_cross_track : boost::geometry::strategies::convex_hull
|
||||
|
||||
struct precise_cartesian : boost::geometry::strategies::area::cartesian<>
|
||||
{
|
||||
// Technically this should be enabled only for non-boxes
|
||||
template <typename Geometry>
|
||||
static auto area(Geometry const&)
|
||||
{
|
||||
@ -147,6 +155,7 @@ struct test_convex_hull
|
||||
check_convex_hull(geometry, hull, size_original, size_hull,
|
||||
expected_area, expected_perimeter, false, AreaStrategy());
|
||||
|
||||
bg::clear(hull);
|
||||
bg::convex_hull(geometry, hull, Strategy());
|
||||
|
||||
using point_t = typename bg::point_type<Hull>::type;
|
||||
@ -207,7 +216,34 @@ struct test_convex_hull<Hull, robust_cartesian, AreaStrategy>
|
||||
bg::convex_hull(geometry, hull.outer(), robust_cartesian());
|
||||
check_convex_hull(geometry, hull, size_original, size_hull, expected_area,
|
||||
expected_perimeter, false, AreaStrategy());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Hull
|
||||
>
|
||||
struct test_convex_hull<Hull, robust_cartesian, precise_cartesian>
|
||||
{
|
||||
template <typename Geometry>
|
||||
static void apply(Geometry const& geometry,
|
||||
std::size_t size_original,
|
||||
std::size_t size_hull_closed,
|
||||
double expected_area,
|
||||
double expected_perimeter,
|
||||
bool )
|
||||
{
|
||||
static bool const is_hull_closed = bg::closure<Hull>::value != bg::open;
|
||||
std::size_t const size_hull = is_hull_closed ? size_hull_closed :
|
||||
size_hull_closed - 1;
|
||||
|
||||
// Test version with strategy
|
||||
Hull hull;
|
||||
bg::convex_hull(geometry, hull.outer(), robust_cartesian());
|
||||
|
||||
check_convex_hull(geometry, hull, size_original, size_hull, expected_area,
|
||||
expected_perimeter, false, precise_cartesian());
|
||||
}
|
||||
};
|
||||
|
||||
@ -236,7 +272,6 @@ void test_geometry_order(std::string const& wkt,
|
||||
Geometry geometry;
|
||||
bg::read_wkt(wkt, geometry);
|
||||
|
||||
|
||||
test_convex_hull<hull_type, Strategy, AreaStrategy>::apply(geometry, size_original,
|
||||
size_hull_closed, expected_area, expected_perimeter, !Clockwise);
|
||||
|
||||
@ -307,5 +342,4 @@ void test_empty_input()
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -284,21 +284,12 @@ void test_all()
|
||||
"LINESTRING(2 8,4 0.4,8 1,0 5)",
|
||||
expected("iuu++")("mui=+")("tiu+="));
|
||||
|
||||
#if ! ( defined(BOOST_CLANG) && defined(BOOST_GEOMETRY_COMPILER_MODE_RELEASE) )
|
||||
|
||||
// In clang/release mode this testcase gives other results
|
||||
|
||||
// assertion failure in 1.57
|
||||
// FAILING - no assertion failure but the result is not very good
|
||||
test_geometry<ls, ls>("LINESTRING(-2305843009213693956 4611686018427387906, -33 -92, 78 83)",
|
||||
"LINESTRING(31 -97, -46 57, -20 -4)",
|
||||
expected("")(""));
|
||||
expected("iuu++"));
|
||||
test_geometry<ls, ls>("LINESTRING(31 -97, -46 57, -20 -4)",
|
||||
"LINESTRING(-2305843009213693956 4611686018427387906, -33 -92, 78 83)",
|
||||
expected("")(""));
|
||||
|
||||
#endif
|
||||
|
||||
expected("iuu++"));
|
||||
}
|
||||
|
||||
// In 1.57 the results of those combinations was different for MinGW
|
||||
|
@ -27,9 +27,11 @@
|
||||
# include <boost/geometry/io/svg/svg_mapper.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
template <typename P, typename T>
|
||||
void test_with_point(std::string const& /*caseid*/,
|
||||
|
@ -46,8 +46,6 @@ void test_all()
|
||||
{
|
||||
typedef bg::model::polygon<P> polygon;
|
||||
|
||||
typedef typename bg::coordinate_type<P>::type ct;
|
||||
|
||||
test_one<polygon, polygon, polygon>("simplex_normal",
|
||||
simplex_normal[0], simplex_normal[1],
|
||||
3, 12, 2.52636706856656,
|
||||
@ -68,10 +66,15 @@ void test_all()
|
||||
1, 5, 8.0,
|
||||
1, 5, 8.0);
|
||||
|
||||
test_one<polygon, polygon, polygon>("star_comb_15",
|
||||
star_comb_15[0], star_comb_15[1],
|
||||
30, -1, 227.658275102812,
|
||||
30, -1, 480.485775259312);
|
||||
{
|
||||
ut_settings settings;
|
||||
settings.validity_false_negative_sym = true;
|
||||
test_one<polygon, polygon, polygon>("star_comb_15",
|
||||
star_comb_15[0], star_comb_15[1],
|
||||
30, -1, 227.658275102812,
|
||||
30, -1, 480.485775259312,
|
||||
settings);
|
||||
}
|
||||
|
||||
test_one<polygon, polygon, polygon>("new_hole",
|
||||
new_hole[0], new_hole[1],
|
||||
@ -106,7 +109,7 @@ void test_all()
|
||||
|
||||
{
|
||||
ut_settings settings;
|
||||
settings.sym_difference_validity = BG_IF_RESCALED(true, false);
|
||||
settings.validity_false_negative_sym = true;
|
||||
|
||||
test_one<polygon, polygon, polygon>("only_hole_intersections1",
|
||||
only_hole_intersections[0], only_hole_intersections[1],
|
||||
@ -114,7 +117,7 @@ void test_all()
|
||||
4, 16, 10.9090909,
|
||||
settings);
|
||||
|
||||
test_one<polygon, polygon, polygon>("only_hole_intersection2",
|
||||
test_one<polygon, polygon, polygon>("only_hole_intersections2",
|
||||
only_hole_intersections[0], only_hole_intersections[2],
|
||||
3, 20, 30.9090909,
|
||||
4, 16, 10.9090909,
|
||||
@ -144,7 +147,7 @@ void test_all()
|
||||
|
||||
{
|
||||
ut_settings settings;
|
||||
settings.sym_difference_validity = BG_IF_RESCALED(false, true);
|
||||
settings.validity_of_sym = BG_IF_RESCALED(false, true);
|
||||
test_one<polygon, polygon, polygon>("intersect_holes_intersect_and_disjoint",
|
||||
intersect_holes_intersect_and_disjoint[0], intersect_holes_intersect_and_disjoint[1],
|
||||
2, 16, 15.75,
|
||||
@ -180,7 +183,6 @@ void test_all()
|
||||
|
||||
{
|
||||
ut_settings settings;
|
||||
settings.sym_difference_validity = BG_IF_RESCALED(false, true);
|
||||
test_one<polygon, polygon, polygon>("intersect_holes_intersect",
|
||||
intersect_holes_intersect[0], intersect_holes_intersect[1],
|
||||
2, 16, 15.75,
|
||||
@ -295,10 +297,9 @@ void test_all()
|
||||
1, 61, 10.2717,
|
||||
1, 61, 10.2717);
|
||||
|
||||
if ( BOOST_GEOMETRY_CONDITION((std::is_same<ct, double>::value)) )
|
||||
{
|
||||
ut_settings settings;
|
||||
settings.sym_difference_validity = BG_IF_RESCALED(true, false);
|
||||
settings.validity_false_negative_sym = true;
|
||||
TEST_DIFFERENCE_WITH(buffer_mp2, 1, 12.09857, 1, 24.19714,
|
||||
count_set(1, 2), settings);
|
||||
}
|
||||
@ -319,7 +320,7 @@ void test_all()
|
||||
ut_settings settings;
|
||||
settings.percentage = BG_IF_RESCALED(0.001, 0.1);
|
||||
settings.set_test_validity(BG_IF_RESCALED(true, false));
|
||||
settings.sym_difference = BG_IF_RESCALED(true, false);
|
||||
settings.sym_difference = false;
|
||||
|
||||
// Isovist - the # output polygons differ per compiler/pointtype, (very) small
|
||||
// rings might be discarded. We check area only
|
||||
@ -330,18 +331,24 @@ void test_all()
|
||||
|
||||
test_one<polygon, polygon, polygon>("isovist",
|
||||
isovist1[0], isovist1[1],
|
||||
ignore_count(), -1, 0.279132,
|
||||
ignore_count(), -1, expectation_limits(0.279128, 0.279132),
|
||||
ignore_count(), -1, 224.8892,
|
||||
settings);
|
||||
}
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
|
||||
// SQL Server gives: 0.28937764436705 and 0.000786406897532288 with 44/35 rings
|
||||
// PostGIS gives: 0.30859375 and 0.033203125 with 35/35 rings
|
||||
TEST_DIFFERENCE_WITH(geos_1,
|
||||
ignore_count(), expectation_limits(0.20705, 0.29172),
|
||||
ignore_count(), expectation_limits(0.00060440758, 0.00076856),
|
||||
ignore_count(), ut_settings(0.1, false));
|
||||
{
|
||||
ut_settings settings(0.1);
|
||||
settings.set_test_validity(BG_IF_RESCALED(false, true));
|
||||
settings.validity_false_negative_sym = BG_IF_RESCALED(true, false);
|
||||
|
||||
// SQL Server gives: 0.28937764436705 and 0.000786406897532288 with 44/35 rings
|
||||
// PostGIS gives: 0.30859375 and 0.033203125 with 35/35 rings
|
||||
TEST_DIFFERENCE_WITH(geos_1,
|
||||
ignore_count(), expectation_limits(0.20705, 0.29172),
|
||||
ignore_count(), expectation_limits(0.00060440758, 0.00076856),
|
||||
ignore_count(), settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
@ -425,7 +432,7 @@ void test_all()
|
||||
// With rescaling, difference of output a-b and a sym b is invalid
|
||||
ut_settings settings;
|
||||
settings.set_test_validity(BG_IF_RESCALED(false, true));
|
||||
settings.sym_difference_validity = BG_IF_RESCALED(false, true);
|
||||
settings.validity_of_sym = BG_IF_RESCALED(false, true);
|
||||
TEST_DIFFERENCE_WITH(ggl_list_20190307_matthieu_1,
|
||||
count_set(1, 2), 0.18461532,
|
||||
count_set(1, 2), 0.617978,
|
||||
@ -563,6 +570,7 @@ void test_all()
|
||||
{
|
||||
ut_settings settings;
|
||||
settings.set_test_validity(BG_IF_RESCALED(true, false));
|
||||
settings.validity_false_negative_a = true;
|
||||
TEST_DIFFERENCE_WITH(issue_838,
|
||||
count_set(1, 2), expectation_limits(0.000026, 0.0002823),
|
||||
count_set(1, 2), expectation_limits(0.67257, 0.67499),
|
||||
@ -583,12 +591,16 @@ void test_all()
|
||||
TEST_DIFFERENCE(mysql_23023665_3, 1, 225.0, 1, 66.0, 2);
|
||||
TEST_DIFFERENCE(mysql_23023665_5, 2, 165.23735, 2, 105.73735, 4);
|
||||
{
|
||||
// Without recaling it is invalid
|
||||
// Without rescaling it is invalid
|
||||
ut_settings settings;
|
||||
settings.set_test_validity(BG_IF_RESCALED(true, false));
|
||||
settings.set_test_validity(true);
|
||||
TEST_DIFFERENCE_WITH(mysql_23023665_6, 2, 105.68756, 3, 10.18756, 5, settings);
|
||||
}
|
||||
TEST_DIFFERENCE(mysql_23023665_13, 3, 99.74526, 3, 37.74526, 6);
|
||||
{
|
||||
ut_settings settings;
|
||||
settings.validity_false_negative_sym = true;
|
||||
TEST_DIFFERENCE_WITH(mysql_23023665_13, 3, 99.74526, 3, 37.74526, 6, settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -633,7 +645,7 @@ int test_main(int, char* [])
|
||||
// Not yet fully tested for float and long double.
|
||||
// The difference algorithm can generate (additional) slivers
|
||||
// Many of the failures are self-intersection points.
|
||||
BoostGeometryWriteExpectedFailures(19, 10, 17, 12);
|
||||
BoostGeometryWriteExpectedFailures(15, 5, 17, 10);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -240,8 +240,8 @@ int test_main(int, char* [])
|
||||
test_all<bg::model::d2::point_xy<double> >();
|
||||
|
||||
test_ticket_10835<int>
|
||||
("MULTILINESTRING((5239 2113,5233 2114),(4794 2205,1020 2986))",
|
||||
"MULTILINESTRING((5239 2113,5233 2114),(4794 2205,1460 2895))");
|
||||
("MULTILINESTRING((5239 2113,5232 2115),(4794 2205,1020 2986))",
|
||||
"MULTILINESTRING((5239 2113,5232 2115),(4794 2205,1460 2895))");
|
||||
|
||||
test_ticket_10835<double>
|
||||
("MULTILINESTRING((5239 2113,5232.52 2114.34),(4794.39 2205,1020 2986))",
|
||||
|
@ -155,10 +155,12 @@ void test_areal()
|
||||
#if ! defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
|
||||
{
|
||||
// 1: Very small sliver for B (discarded when rescaling)
|
||||
// 2: sym difference is not considered as valid
|
||||
// 2: sym difference is not considered as valid (without rescaling
|
||||
// this is a false negative)
|
||||
// 3: with rescaling A is considered as invalid (robustness problem)
|
||||
ut_settings settings;
|
||||
settings.sym_difference_validity = false;
|
||||
settings.validity_of_sym = BG_IF_RESCALED(false, true);
|
||||
settings.validity_false_negative_sym = true;
|
||||
TEST_DIFFERENCE_WITH(0, 1, bug_21155501,
|
||||
(count_set(1, 4)), expectation_limits(3.75893, 3.75894),
|
||||
(count_set(1, 4)), (expectation_limits(1.776357e-15, 7.661281e-15)),
|
||||
@ -172,7 +174,7 @@ void test_areal()
|
||||
// Without rescaling, one ring is missing (for a and s)
|
||||
ut_settings settings;
|
||||
settings.set_test_validity(BG_IF_RESCALED(false, true));
|
||||
settings.sym_difference_validity = BG_IF_RESCALED(false, true);
|
||||
settings.validity_of_sym = BG_IF_RESCALED(false, true);
|
||||
TEST_DIFFERENCE_WITH(0, 1, ticket_9081,
|
||||
2, 0.0907392476356186,
|
||||
4, 0.126018011439877,
|
||||
@ -211,9 +213,12 @@ void test_areal()
|
||||
TEST_DIFFERENCE(issue_888_34, 22, 0.2506824, 6, 0.0253798, 28); // a went wrong
|
||||
TEST_DIFFERENCE(issue_888_37, 15, 0.0451408, 65, 0.3014843, 80); // b went wrong
|
||||
|
||||
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
|
||||
TEST_DIFFERENCE(issue_888_53, 117, 0.2973268, 17, 0.0525798, 134); // a goes wrong
|
||||
#endif
|
||||
{
|
||||
ut_settings settings;
|
||||
settings.validity_false_negative_a = true;
|
||||
settings.validity_false_negative_sym = true;
|
||||
TEST_DIFFERENCE_WITH(0, 1, issue_888_53, 117, 0.2973268, 17, 0.0525798, 134);
|
||||
}
|
||||
|
||||
// Areas and #clips correspond with POSTGIS (except sym case)
|
||||
test_one<Polygon, MultiPolygon, MultiPolygon>("case_101_multi",
|
||||
@ -472,24 +477,29 @@ void test_specific_areal()
|
||||
|
||||
{
|
||||
const std::string a_min_b =
|
||||
TEST_DIFFERENCE(ticket_10661, 2, 1441632.5, 2, 13167454, 4);
|
||||
test_one<Polygon, MultiPolygon, MultiPolygon>("ticket_10661",
|
||||
ticket_10661[0], ticket_10661[1],
|
||||
2, -1, expectation_limits(1441632, 1441855),
|
||||
2, -1, expectation_limits(13167454, 13182415),
|
||||
count_set(3, 4));
|
||||
|
||||
test_one<Polygon, MultiPolygon, MultiPolygon>("ticket_10661_2",
|
||||
a_min_b, ticket_10661[2],
|
||||
1, 8, 825192.0,
|
||||
1, 10, expectation_limits(27226370, 27842812),
|
||||
1, -1, 825192.0 + 27226370.5);
|
||||
1, 10, expectation_limits(27226148, 27842812),
|
||||
count_set(1, 2));
|
||||
}
|
||||
|
||||
{
|
||||
ut_settings settings;
|
||||
settings.sym_difference = false;
|
||||
|
||||
TEST_DIFFERENCE_WITH(0, 1, ticket_9942, 4, expectation_limits(7427727.5), 4,
|
||||
expectation_limits(130083, 131507), 4);
|
||||
TEST_DIFFERENCE_WITH(0, 1, ticket_9942, 4,
|
||||
expectation_limits(7427727, 7428108), 4,
|
||||
expectation_limits(130083, 131823), 4);
|
||||
TEST_DIFFERENCE_WITH(0, 1, ticket_9942a, 2,
|
||||
expectation_limits(412676, 413184), 2,
|
||||
expectation_limits(76779, 76925), 4);
|
||||
expectation_limits(412676, 413469), 2,
|
||||
expectation_limits(76779, 77038), 4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,7 +526,7 @@ int test_main(int, char* [])
|
||||
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
|
||||
// Not yet fully tested for float.
|
||||
// The difference algorithm can generate (additional) slivers
|
||||
BoostGeometryWriteExpectedFailures(28, 15, 19, 10);
|
||||
BoostGeometryWriteExpectedFailures(24, 11, 21, 7);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -20,6 +20,7 @@ void test_spikes_in_ticket_8364()
|
||||
{
|
||||
ut_settings ignore_validity;
|
||||
ignore_validity.set_test_validity(false);
|
||||
ignore_validity.validity_of_sym = false;
|
||||
|
||||
// See: https://svn.boost.org/trac/boost/ticket/8364
|
||||
//_TPolygon<T> polygon( "MULTIPOLYGON(((1031 1056,3232 1056,3232 2856,1031 2856)))" );
|
||||
@ -30,44 +31,27 @@ void test_spikes_in_ticket_8364()
|
||||
//polygon -= _TPolygon<T>( "MULTIPOLYGON(((1032 2556,1032 2130,1778 2556)),((3234 2580,2136 2760,1778 2556,3234 2556)))" ); USED IN STEP 4
|
||||
// NOTE: polygons below are closed and clockwise
|
||||
|
||||
typedef typename bg::coordinate_type<P>::type ct;
|
||||
typedef bg::model::polygon<P, ClockWise, Closed> polygon;
|
||||
typedef bg::model::multi_polygon<polygon> multi_polygon;
|
||||
|
||||
// The difference of polygons below result in a spike. The spike should be there, it was also generated in ttmath,
|
||||
// and (e.g.) in SQL Server. However, using int-coordinates, the spike makes the polygon invalid. Therefore it is now (since August 2013) checked and removed.
|
||||
|
||||
#ifdef BOOST_GEOMETRY_TEST_FAILURES
|
||||
// TODO: commented working at ii/validity, this changes the area slightly, to be checked
|
||||
// So using int's, the spike is removed automatically. Therefore there is one polygon less, and less points. Also area differs
|
||||
test_one<polygon, multi_polygon, multi_polygon>("ticket_8364_step3",
|
||||
"MULTIPOLYGON(((3232 2532,2136 2790,1032 1764,1032 1458,1032 1212,2136 2328,3232 2220,3232 1056,1031 1056,1031 2856,3232 2856,3232 2532)))",
|
||||
"MULTIPOLYGON(((1032 2130,2052 2712,1032 1764,1032 2130)),((3234 2580,3234 2532,2558 2690,3234 2580)),((2558 2690,2136 2760,2052 2712,2136 2790,2558 2690)))",
|
||||
2,
|
||||
if_typed<ct, int>(19, 22),
|
||||
if_typed<ct, int>(2775595.5, 2775256.487954), // SQL Server: 2775256.47588724
|
||||
3,
|
||||
-1, // don't check point-count
|
||||
if_typed<ct, int>(7893.0, 7810.487954), // SQL Server: 7810.48711165739
|
||||
if_typed<ct, int>(1, 5),
|
||||
-1,
|
||||
if_typed<ct, int>(2783349.5, 2775256.487954 + 7810.487954),
|
||||
ignore_validity);
|
||||
#endif
|
||||
count_set(2, 3), -1, expectation_limits(2775256, 2775610), // SQL Server: 2775256.47588724
|
||||
3, -1, expectation_limits(7810, 7893), // SQL Server: 7810.48711165739
|
||||
count_set(2, 6), ignore_validity);
|
||||
|
||||
// TODO: behaviour is not good yet. It is changed at introduction of self-turns.
|
||||
test_one<polygon, multi_polygon, multi_polygon>("ticket_8364_step4",
|
||||
"MULTIPOLYGON(((2567 2688,2136 2790,2052 2712,1032 2130,1032 1764,1032 1458,1032 1212,2136 2328,3232 2220,3232 1056,1031 1056,1031 2856,3232 2856,3232 2580,2567 2688)))",
|
||||
"MULTIPOLYGON(((1032 2556,1778 2556,1032 2130,1032 2556)),((3234 2580,3234 2556,1778 2556,2136 2760,3234 2580)))",
|
||||
if_typed<ct, int>(1, 2),
|
||||
if_typed<ct, int>(17, 20),
|
||||
if_typed<ct, int>(2615783.5, 2616029.559567), // SQL Server: 2616029.55616044
|
||||
1,
|
||||
if_typed<ct, int>(9, 11),
|
||||
if_typed<ct, int>(161133.5, 161054.559567), // SQL Server: 161054.560110092
|
||||
if_typed<ct, int>(1, 3),
|
||||
if_typed<ct, int>(25, 31),
|
||||
if_typed<ct, int>(2776875.5, 2616029.559567 + 161054.559567));
|
||||
count_set(1, 2), -1, expectation_limits(2615783, 2616030), // SQL Server: 2616029.55616044
|
||||
1, -1, expectation_limits(161054, 161134), // SQL Server: 161054.560110092
|
||||
count_set(1, 3));
|
||||
}
|
||||
|
||||
template <typename P, bool ClockWise, bool Closed>
|
||||
@ -76,7 +60,6 @@ void test_spikes_in_ticket_8365()
|
||||
// See: https://svn.boost.org/trac/boost/ticket/8365
|
||||
// NOTE: polygons below are closed and clockwise
|
||||
|
||||
typedef typename bg::coordinate_type<P>::type ct;
|
||||
typedef bg::model::polygon<P, ClockWise, Closed> polygon;
|
||||
typedef bg::model::multi_polygon<polygon> multi_polygon;
|
||||
|
||||
@ -85,13 +68,11 @@ void test_spikes_in_ticket_8365()
|
||||
"MULTIPOLYGON(((5388 1560,4650 1722,3912 1884,4650 1398)),((2442 3186,1704 3348,966 2700,1704 3024)))",
|
||||
2,
|
||||
18,
|
||||
if_typed<ct, int>(7975092.5, 7975207.6047877), // SQL Server:
|
||||
expectation_limits(7975092.5, 7975207.6047877),
|
||||
2,
|
||||
-1,
|
||||
if_typed<ct, int>(196.5, 197.1047877), // SQL Server:
|
||||
if_typed<ct, int>(3, 4),
|
||||
-1,
|
||||
if_typed<ct, int>(7975092.5 + 196.5, 7975207.6047877 + 197.1047877));
|
||||
expectation_limits(196.5, 198.5),
|
||||
count_set(2, 4));
|
||||
}
|
||||
|
||||
|
||||
@ -109,6 +90,7 @@ int test_main(int, char* [])
|
||||
test_spikes_in_ticket_8364<bg::model::d2::point_xy<int>, false, false>();
|
||||
test_spikes_in_ticket_8365<bg::model::d2::point_xy<int>, true, true >();
|
||||
test_spikes_in_ticket_8365<bg::model::d2::point_xy<int>, false, false >();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -59,20 +59,45 @@
|
||||
# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
|
||||
#endif
|
||||
|
||||
enum difference_type
|
||||
{
|
||||
difference_a, difference_b, difference_sym
|
||||
};
|
||||
|
||||
struct ut_settings : ut_base_settings
|
||||
{
|
||||
double percentage;
|
||||
bool sym_difference;
|
||||
bool sym_difference_validity = true;
|
||||
bool validity_of_sym = true;
|
||||
bool remove_spikes = false;
|
||||
|
||||
// The validity check gives sometimes false negatives.
|
||||
// boost::geometry::is_valid can return FALSE while it is valid.
|
||||
// (especially at touch in combination with a u/u turn)
|
||||
// For now, the cases where this is the case are skipped for validity check.
|
||||
bool validity_false_negative_a = false;
|
||||
bool validity_false_negative_b = false;
|
||||
bool validity_false_negative_sym = false;
|
||||
|
||||
explicit ut_settings(double p = 0.0001, bool validity = true, bool sd = true)
|
||||
: ut_base_settings(validity)
|
||||
, percentage(p)
|
||||
, sym_difference(sd)
|
||||
{}
|
||||
|
||||
bool test_validity_of_diff(difference_type dtype) const
|
||||
{
|
||||
bool const sym = dtype == difference_sym;
|
||||
bool const a = dtype == difference_a;
|
||||
bool const b = dtype == difference_b;
|
||||
|
||||
return sym && validity_false_negative_sym ? false
|
||||
: a && validity_false_negative_a ? false
|
||||
: b && validity_false_negative_b ? false
|
||||
: sym ? (validity_of_sym || BG_IF_TEST_FAILURES)
|
||||
: test_validity();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline ut_settings tolerance(double percentage)
|
||||
@ -137,7 +162,7 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g
|
||||
const count_set& expected_count,
|
||||
int expected_rings_count, int expected_point_count,
|
||||
expectation_limits const& expected_area,
|
||||
bool sym,
|
||||
difference_type dtype,
|
||||
ut_settings const& settings)
|
||||
{
|
||||
typedef typename bg::coordinate_type<G1>::type coordinate_type;
|
||||
@ -145,8 +170,7 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g
|
||||
|
||||
bg::model::multi_polygon<OutputType> result;
|
||||
|
||||
|
||||
if (sym)
|
||||
if (dtype == difference_sym)
|
||||
{
|
||||
bg::sym_difference(g1, g2, result);
|
||||
}
|
||||
@ -167,7 +191,7 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g
|
||||
<
|
||||
G1, G2
|
||||
>::type strategy_type;
|
||||
if (sym)
|
||||
if (dtype == difference_sym)
|
||||
{
|
||||
bg::sym_difference(g1, g2, result_s, strategy_type());
|
||||
}
|
||||
@ -191,12 +215,7 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g
|
||||
typename bg::default_area_result<G1>::type const area = bg::area(result);
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST)
|
||||
bool const test_validity
|
||||
= sym
|
||||
? (settings.sym_difference_validity || BG_IF_TEST_FAILURES)
|
||||
: settings.test_validity();
|
||||
|
||||
if (test_validity)
|
||||
if (settings.test_validity_of_diff(dtype))
|
||||
{
|
||||
// std::cout << bg::dsv(result) << std::endl;
|
||||
typedef bg::model::multi_polygon<OutputType> result_type;
|
||||
@ -218,7 +237,7 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g
|
||||
typename setop_output_type<OutputType>::type
|
||||
inserted, array_with_one_empty_geometry;
|
||||
array_with_one_empty_geometry.push_back(OutputType());
|
||||
if (sym)
|
||||
if (dtype == difference_sym)
|
||||
{
|
||||
boost::copy(array_with_one_empty_geometry,
|
||||
bg::detail::sym_difference::sym_difference_insert<OutputType>
|
||||
@ -287,12 +306,12 @@ template <typename OutputType, typename G1, typename G2>
|
||||
std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g2,
|
||||
const count_set& expected_count, int expected_point_count,
|
||||
expectation_limits const& expected_area,
|
||||
bool sym,
|
||||
difference_type dtype,
|
||||
ut_settings const& settings)
|
||||
{
|
||||
return test_difference<OutputType>(caseid, g1, g2,
|
||||
expected_count, -1, expected_point_count, expected_area,
|
||||
sym, settings);
|
||||
dtype, settings);
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_CHECK_WITH_POSTGIS
|
||||
@ -331,7 +350,7 @@ std::string test_one(std::string const& caseid,
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_DIFFERENCE_ONLY_B)
|
||||
result = test_difference<OutputType>(caseid + "_a", g1, g2,
|
||||
expected_count1, expected_rings_count1, expected_point_count1,
|
||||
expected_area1, false, settings);
|
||||
expected_area1, difference_a, settings);
|
||||
#endif
|
||||
#if defined(BOOST_GEOMETRY_TEST_DIFFERENCE_ONLY_A)
|
||||
return result;
|
||||
@ -339,7 +358,7 @@ std::string test_one(std::string const& caseid,
|
||||
|
||||
test_difference<OutputType>(caseid + "_b", g2, g1,
|
||||
expected_count2, expected_rings_count2, expected_point_count2,
|
||||
expected_area2, false, settings);
|
||||
expected_area2, difference_b, settings);
|
||||
|
||||
#if defined(BOOST_GEOMETRY_TEST_DIFFERENCE_ONLY_B)
|
||||
return result;
|
||||
@ -354,7 +373,7 @@ std::string test_one(std::string const& caseid,
|
||||
expected_rings_count_s,
|
||||
expected_point_count_s,
|
||||
expected_area_s,
|
||||
true, settings);
|
||||
difference_sym, settings);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -383,6 +402,7 @@ std::string test_one(std::string const& caseid,
|
||||
settings);
|
||||
}
|
||||
|
||||
// Version with expectations of symmetric: all specified
|
||||
template <typename OutputType, typename G1, typename G2>
|
||||
std::string test_one(std::string const& caseid,
|
||||
std::string const& wkt1, std::string const& wkt2,
|
||||
@ -404,6 +424,30 @@ std::string test_one(std::string const& caseid,
|
||||
settings);
|
||||
}
|
||||
|
||||
// Version with expectations of symmetric: specify only count
|
||||
template <typename OutputType, typename G1, typename G2>
|
||||
std::string test_one(std::string const& caseid,
|
||||
std::string const& wkt1, std::string const& wkt2,
|
||||
const count_set& expected_count1,
|
||||
int expected_point_count1,
|
||||
expectation_limits const& expected_area1,
|
||||
const count_set& expected_count2,
|
||||
int expected_point_count2,
|
||||
expectation_limits const& expected_area2,
|
||||
const count_set& expected_count_s,
|
||||
ut_settings const& settings = ut_settings())
|
||||
{
|
||||
return test_one<OutputType, G1, G2>(caseid, wkt1, wkt2,
|
||||
expected_count1, -1, expected_point_count1, expected_area1,
|
||||
expected_count2, -1, expected_point_count2, expected_area2,
|
||||
expected_count_s, -1,
|
||||
expected_point_count1 >= 0 && expected_point_count2 >= 0
|
||||
? (expected_point_count1 + expected_point_count2) : -1,
|
||||
expected_area1 + expected_area2,
|
||||
settings);
|
||||
}
|
||||
|
||||
// Version with expectations of symmetric: all automatically
|
||||
template <typename OutputType, typename G1, typename G2>
|
||||
std::string test_one(std::string const& caseid,
|
||||
std::string const& wkt1, std::string const& wkt2,
|
||||
|
@ -75,7 +75,7 @@ struct test_sym_difference_of_areal_geometries
|
||||
PolygonOut
|
||||
>(case_id, areal1, areal2,
|
||||
expected_polygon_count, expected_point_count, expected_area,
|
||||
true, settings);
|
||||
difference_sym, settings);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -348,7 +348,7 @@ inline void test_aa()
|
||||
"MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0),(0 0, 4 1, 4 4, 1 4, 0 0)),"
|
||||
"((2 6, 2 8, 8 8, 8 5, 7 5, 7 6, 2 6)))",
|
||||
"MULTIPOLYGON(((0 0, 1 4, 5 4, 5 1, 4 1, 0 0),(0 0, 2 1, 2 2, 1 2, 0 0)),"
|
||||
"((5 0, 5 1, 6 1, 6 4, 5 4, 3 6, 2 5, 2 7, 7 7, 7 0 5 0)))",
|
||||
"((5 0, 5 1, 6 1, 6 4, 5 4, 3 6, 2 5, 2 7, 7 7, 7 0, 5 0)))",
|
||||
"MULTIPOINT()",
|
||||
"MULTILINESTRING()",
|
||||
"MULTIPOLYGON(((0 0,0 5,4 5,3 6,7 6,7 7,2 7,2 8,8 8,8 5,7 5,7 0,0 0),"
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Boost.Geometry
|
||||
// Robustness Test
|
||||
|
||||
// Copyright (c) 2019 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2019-2021 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
|
||||
@ -11,6 +11,8 @@
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_GEOMETRY_NO_ROBUSTNESS
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
@ -42,11 +44,22 @@ static std::string case_c[2] =
|
||||
"MULTIPOLYGON(((1 1,0 1,0 3,1 3,1 1)))"
|
||||
};
|
||||
|
||||
struct test_settings
|
||||
{
|
||||
bool verbose{false};
|
||||
bool do_output{false};
|
||||
|
||||
// Settings currently not modifiable, and still giving quite some errors
|
||||
double start_bound{1.0e-2};
|
||||
double step_factor{50.0}; // on each side -> 100 steps per factor
|
||||
int max_factor{10000};
|
||||
};
|
||||
|
||||
template <bg::overlay_type OverlayType, typename Geometry>
|
||||
bool test_overlay(std::string const& caseid,
|
||||
Geometry const& g1, Geometry const& g2,
|
||||
double expected_area,
|
||||
bool do_output)
|
||||
test_settings const& settings)
|
||||
{
|
||||
|
||||
typedef typename boost::range_value<Geometry>::type geometry_out;
|
||||
@ -62,9 +75,9 @@ bool test_overlay(std::string const& caseid,
|
||||
OverlayType
|
||||
> overlay;
|
||||
|
||||
typedef typename bg::strategy::intersection::services::default_strategy
|
||||
typedef typename bg::strategies::relate::services::default_strategy
|
||||
<
|
||||
typename bg::cs_tag<Geometry>::type
|
||||
Geometry, Geometry
|
||||
>::type strategy_type;
|
||||
|
||||
strategy_type strategy;
|
||||
@ -86,7 +99,7 @@ bool test_overlay(std::string const& caseid,
|
||||
const double detected_area = bg::area(result);
|
||||
if (std::fabs(detected_area - expected_area) > 0.01)
|
||||
{
|
||||
if (do_output)
|
||||
if (settings.do_output)
|
||||
{
|
||||
std::cout << "ERROR: " << caseid << std::setprecision(18)
|
||||
<< " detected=" << detected_area
|
||||
@ -118,9 +131,9 @@ template <bg::overlay_type OverlayType, typename MultiPolygon>
|
||||
std::size_t test_case(std::size_t& error_count,
|
||||
std::size_t case_index, std::size_t i, std::size_t j,
|
||||
std::size_t min_vertex_index, std::size_t max_vertex_index,
|
||||
double x, double y, double expectation,
|
||||
double offset_x, double offset_y, double expectation,
|
||||
MultiPolygon const& poly1, MultiPolygon const& poly2,
|
||||
bool do_output)
|
||||
test_settings const settings)
|
||||
{
|
||||
std::size_t n = 0;
|
||||
for (std::size_t k = min_vertex_index; k <= max_vertex_index; k++, ++n)
|
||||
@ -130,21 +143,23 @@ std::size_t test_case(std::size_t& error_count,
|
||||
switch (case_index)
|
||||
{
|
||||
case 2 :
|
||||
update(bg::interior_rings(poly2_adapted.front()).front(), x, y, k);
|
||||
update(bg::interior_rings(poly2_adapted.front()).front(), offset_x, offset_y, k);
|
||||
break;
|
||||
default :
|
||||
update(bg::exterior_ring(poly2_adapted.front()), x, y, k);
|
||||
update(bg::exterior_ring(poly2_adapted.front()), offset_x, offset_y, k);
|
||||
break;
|
||||
}
|
||||
|
||||
std::ostringstream out;
|
||||
out << "case_" << i << "_" << j << "_" << k;
|
||||
if (! test_overlay<OverlayType>(out.str(), poly1, poly2_adapted, expectation, do_output))
|
||||
if (! test_overlay<OverlayType>(out.str(), poly1, poly2_adapted, expectation, settings))
|
||||
{
|
||||
if (error_count == 0)
|
||||
if (error_count == 0 && ! settings.do_output)
|
||||
{
|
||||
// First failure is always reported
|
||||
test_overlay<OverlayType>(out.str(), poly1, poly2_adapted, expectation, true);
|
||||
test_settings adapted = settings;
|
||||
adapted.do_output = true;
|
||||
test_overlay<OverlayType>(out.str(), poly1, poly2_adapted, expectation, adapted);
|
||||
}
|
||||
error_count++;
|
||||
}
|
||||
@ -155,7 +170,7 @@ std::size_t test_case(std::size_t& error_count,
|
||||
template <typename T, bool Clockwise, bg::overlay_type OverlayType>
|
||||
std::size_t test_all(std::size_t case_index, std::size_t min_vertex_index,
|
||||
std::size_t max_vertex_index,
|
||||
double expectation, bool do_output)
|
||||
double expectation, test_settings const& settings)
|
||||
{
|
||||
typedef bg::model::point<T, 2, bg::cs::cartesian> point_type;
|
||||
typedef bg::model::polygon<point_type, Clockwise> polygon;
|
||||
@ -177,21 +192,25 @@ std::size_t test_all(std::size_t case_index, std::size_t min_vertex_index,
|
||||
|
||||
std::size_t error_count = 0;
|
||||
std::size_t n = 0;
|
||||
for (double factor = 1.0; factor > 1.0e-10; factor /= 10.0)
|
||||
for (int factor = 1; factor < settings.max_factor; factor *= 2)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
double const bound = 1.0e-5 * factor;
|
||||
double const step = 1.0e-6 * factor;
|
||||
for (double x = -bound; x <= bound; x += step, ++i)
|
||||
double const bound = settings.start_bound / factor;
|
||||
double const step = bound / settings.step_factor;
|
||||
if (settings.verbose)
|
||||
{
|
||||
std::cout << "--> use " << bound << " " << step << std::endl;
|
||||
}
|
||||
for (double offset_x = -bound; offset_x <= bound; offset_x += step, ++i)
|
||||
{
|
||||
std::size_t j = 0;
|
||||
for (double y = -bound; y <= bound; y += step, ++j, ++n)
|
||||
for (double offset_y = -bound; offset_y <= bound; offset_y += step, ++j, ++n)
|
||||
{
|
||||
n += test_case<OverlayType>(error_count,
|
||||
case_index, i, j,
|
||||
min_vertex_index, max_vertex_index,
|
||||
x, y, expectation,
|
||||
poly1, poly2, do_output);
|
||||
min_vertex_index, max_vertex_index,
|
||||
offset_x, offset_y, expectation,
|
||||
poly1, poly2, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -205,22 +224,17 @@ std::size_t test_all(std::size_t case_index, std::size_t min_vertex_index,
|
||||
|
||||
int test_main(int argc, char** argv)
|
||||
{
|
||||
typedef double coordinate_type;
|
||||
BoostGeometryWriteTestConfiguration();
|
||||
using coor_t = default_test_type;
|
||||
|
||||
const double factor = argc > 1 ? atof(argv[1]) : 2.0;
|
||||
const bool do_output = argc > 2 && atol(argv[2]) == 1;
|
||||
test_settings settings;
|
||||
settings.do_output = argc > 2 && atol(argv[2]) == 1;
|
||||
|
||||
std::cout << std::endl << " -> TESTING "
|
||||
<< string_from_type<coordinate_type>::name()
|
||||
<< " " << factor
|
||||
<< std::endl;
|
||||
|
||||
test_all<coordinate_type, true, bg::overlay_union>(1, 0, 3, 22.0, do_output);
|
||||
test_all<coordinate_type, true, bg::overlay_union>(2, 0, 3, 73.0, do_output);
|
||||
test_all<coordinate_type, true, bg::overlay_intersection>(3, 1, 2, 2.0, do_output);
|
||||
test_all<coordinate_type, true, bg::overlay_union>(3, 1, 2, 14.0, do_output);
|
||||
// Test three polygons, for the last test two types of intersections
|
||||
test_all<coor_t, true, bg::overlay_union>(1, 0, 3, 22.0, settings);
|
||||
test_all<coor_t, true, bg::overlay_union>(2, 0, 3, 73.0, settings);
|
||||
test_all<coor_t, true, bg::overlay_intersection>(3, 1, 2, 2.0, settings);
|
||||
test_all<coor_t, true, bg::overlay_union>(3, 1, 2, 14.0, settings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Robustness Test
|
||||
|
||||
// Copyright (c) 2009-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2009-2021 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)
|
||||
|
||||
#define BOOST_GEOMETRY_NO_BOOST_TEST
|
||||
#define BOOST_GEOMETRY_NO_ROBUSTNESS
|
||||
#define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
|
||||
|
||||
// NOTE: there is no randomness here. Count is to measure performance
|
||||
|
||||
#include <test_overlay_p_q.hpp>
|
||||
|
||||
@ -113,8 +117,10 @@ int main(int argc, char** argv)
|
||||
("count_y", po::value<int>(&count_y)->default_value(10), "Triangle count in y-direction")
|
||||
("offset", po::value<int>(&offset)->default_value(0), "Offset of second triangle in x-direction")
|
||||
("diff", po::value<bool>(&settings.also_difference)->default_value(false), "Include testing on difference")
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons")
|
||||
("open", po::value<bool>(&open)->default_value(false), "Open polygons")
|
||||
#endif
|
||||
("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
|
||||
("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
|
||||
;
|
||||
@ -129,6 +135,7 @@ int main(int argc, char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
if (ccw && open)
|
||||
{
|
||||
test_all<default_test_type, false, false>(count, count_x, count_y, offset, settings);
|
||||
@ -142,6 +149,7 @@ int main(int argc, char** argv)
|
||||
test_all<default_test_type, true, false>(count, count_x, count_y, offset, settings);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
test_all<default_test_type, true, true>(count, count_x, count_y, offset, settings);
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Robustness Test
|
||||
|
||||
// Copyright (c) 2009-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2009-2021 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)
|
||||
|
||||
#define BOOST_GEOMETRY_NO_BOOST_TEST
|
||||
#define BOOST_GEOMETRY_NO_ROBUSTNESS
|
||||
#define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
|
||||
|
||||
#include <test_overlay_p_q.hpp>
|
||||
|
||||
@ -256,8 +258,10 @@ int main(int argc, char** argv)
|
||||
("help", "Help message")
|
||||
("multi", po::value<bool>(&multi)->default_value(false), "Multiple tangencies at one point")
|
||||
("diff", po::value<bool>(&settings.also_difference)->default_value(false), "Include testing on difference")
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons")
|
||||
("open", po::value<bool>(&open)->default_value(false), "Open polygons")
|
||||
#endif
|
||||
("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
|
||||
("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
|
||||
;
|
||||
@ -273,6 +277,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
// template par's are: CoordinateType, Clockwise, Closed
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
if (ccw && open)
|
||||
{
|
||||
test_all<default_test_type, false, false>(multi, single_selftangent, settings);
|
||||
@ -286,6 +291,7 @@ int main(int argc, char** argv)
|
||||
test_all<default_test_type, true, false>(multi, single_selftangent, settings);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
test_all<default_test_type, true, true>(multi, single_selftangent, settings);
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Robustness Test
|
||||
|
||||
// Copyright (c) 2009-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2009-2021 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)
|
||||
|
||||
#define BOOST_GEOMETRY_NO_BOOST_TEST
|
||||
#define BOOST_GEOMETRY_NO_ROBUSTNESS
|
||||
#define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
|
||||
|
||||
// NOTE: there is no randomness here. Count is to measure performance
|
||||
|
||||
#include <test_overlay_p_q.hpp>
|
||||
|
||||
@ -109,12 +113,14 @@ void test_type(int count, int min_points, int max_points, T rotation, p_q_settin
|
||||
template <typename T>
|
||||
void test_all(std::string const& type, int count, int min_points, int max_points, T rotation, p_q_settings settings)
|
||||
{
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
if (type == "float")
|
||||
{
|
||||
settings.tolerance = 1.0e-3;
|
||||
test_type<float, float>(count, min_points, max_points, rotation, settings);
|
||||
}
|
||||
else if (type == "double")
|
||||
#endif
|
||||
{
|
||||
test_type<double, double>(count, min_points, max_points, rotation, settings);
|
||||
}
|
||||
@ -130,7 +136,7 @@ int main(int argc, char** argv)
|
||||
|
||||
int count = 1;
|
||||
//int seed = static_cast<unsigned int>(std::time(0));
|
||||
std::string type = "float";
|
||||
std::string type = "double";
|
||||
int min_points = 9;
|
||||
int max_points = 9;
|
||||
bool ccw = false;
|
||||
@ -140,15 +146,17 @@ int main(int argc, char** argv)
|
||||
|
||||
description.add_options()
|
||||
("help", "Help message")
|
||||
//("seed", po::value<int>(&seed), "Initialization seed for random generator")
|
||||
// ("seed", po::value<int>(&seed), "Initialization seed for random generator")
|
||||
("count", po::value<int>(&count)->default_value(1), "Number of tests")
|
||||
("diff", po::value<bool>(&settings.also_difference)->default_value(false), "Include testing on difference")
|
||||
("min_points", po::value<int>(&min_points)->default_value(9), "Minimum number of points")
|
||||
("max_points", po::value<int>(&max_points)->default_value(9), "Maximum number of points")
|
||||
("rotation", po::value<double>(&rotation)->default_value(1.0e-13), "Rotation angle")
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons")
|
||||
("open", po::value<bool>(&open)->default_value(false), "Open polygons")
|
||||
("type", po::value<std::string>(&type)->default_value("float"), "Type (float,double)")
|
||||
("type", po::value<std::string>(&type)->default_value("double"), "Type (float,double)")
|
||||
#endif
|
||||
("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
|
||||
("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
|
||||
;
|
||||
|
@ -1,13 +1,17 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Robustness Test
|
||||
|
||||
// Copyright (c) 2011-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2011-2021 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)
|
||||
|
||||
#define BOOST_GEOMETRY_NO_BOOST_TEST
|
||||
#define BOOST_GEOMETRY_NO_ROBUSTNESS
|
||||
#define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
|
||||
|
||||
// NOTE: there is no randomness here. Count is to measure performance
|
||||
|
||||
#include <test_overlay_p_q.hpp>
|
||||
|
||||
@ -43,9 +47,8 @@ inline void make_polygon(MultiPolygon& mp, int count_x, int count_y, int index,
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename MultiPolygon>
|
||||
void test_intersects(int count_x, int count_y, int width_x, p_q_settings const& settings)
|
||||
void test_intersects(int index, int count_x, int count_y, int width_x, p_q_settings const& settings)
|
||||
{
|
||||
MultiPolygon mp;
|
||||
|
||||
@ -64,6 +67,10 @@ void test_intersects(int count_x, int count_y, int width_x, p_q_settings const&
|
||||
std::ostringstream filename;
|
||||
filename << "intersects_"
|
||||
<< string_from_type<coordinate_type>::name()
|
||||
<< "_" << index
|
||||
<< "_" << count_x
|
||||
<< "_" << count_y
|
||||
<< "_" << width_x
|
||||
<< ".svg";
|
||||
|
||||
std::ofstream svg(filename.str().c_str());
|
||||
@ -92,7 +99,7 @@ void test_all(int count, int count_x, int count_y, int width_x, p_q_settings con
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
test_intersects<multi_polygon>(count_x, count_y, width_x, settings);
|
||||
test_intersects<multi_polygon>(i, count_x, count_y, width_x, settings);
|
||||
}
|
||||
auto const t = std::chrono::high_resolution_clock::now();
|
||||
auto const elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t - t0).count();
|
||||
@ -123,8 +130,10 @@ int main(int argc, char** argv)
|
||||
("count_x", po::value<int>(&count_x)->default_value(10), "Triangle count in x-direction")
|
||||
("count_y", po::value<int>(&count_y)->default_value(10), "Triangle count in y-direction")
|
||||
("width_x", po::value<int>(&width_x)->default_value(7), "Width of triangle in x-direction")
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons")
|
||||
("open", po::value<bool>(&open)->default_value(false), "Open polygons")
|
||||
#endif
|
||||
("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
|
||||
("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
|
||||
;
|
||||
@ -139,6 +148,7 @@ int main(int argc, char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
if (ccw && open)
|
||||
{
|
||||
test_all<default_test_type, false, false>(count, count_x, count_y, width_x, settings);
|
||||
@ -152,6 +162,7 @@ int main(int argc, char** argv)
|
||||
test_all<default_test_type, true, false>(count, count_x, count_y, width_x, settings);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
test_all<default_test_type, true, true>(count, count_x, count_y, width_x, settings);
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Robustness Test
|
||||
|
||||
// Copyright (c) 2009-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2009-2021 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)
|
||||
|
||||
#define BOOST_GEOMETRY_NO_BOOST_TEST
|
||||
#define BOOST_GEOMETRY_NO_ROBUSTNESS
|
||||
#define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
|
||||
|
||||
#include <test_overlay_p_q.hpp>
|
||||
|
||||
@ -166,11 +168,13 @@ void test_type(int seed, int count, p_q_settings const& settings)
|
||||
template <bool Clockwise, bool Closed>
|
||||
void test_all(std::string const& type, int seed, int count, p_q_settings settings)
|
||||
{
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
if (type == "float")
|
||||
{
|
||||
test_type<float, Clockwise, Closed>(seed, count, settings);
|
||||
}
|
||||
else if (type == "double")
|
||||
#endif
|
||||
{
|
||||
test_type<double, Clockwise, Closed>(seed, count, settings);
|
||||
}
|
||||
@ -187,7 +191,7 @@ int main(int argc, char** argv)
|
||||
|
||||
int count = 1;
|
||||
int seed = static_cast<unsigned int>(std::time(0));
|
||||
std::string type = "float";
|
||||
std::string type = "double";
|
||||
bool ccw = false;
|
||||
bool open = false;
|
||||
p_q_settings settings;
|
||||
@ -197,9 +201,11 @@ int main(int argc, char** argv)
|
||||
("seed", po::value<int>(&seed), "Initialization seed for random generator")
|
||||
("count", po::value<int>(&count)->default_value(1), "Number of tests")
|
||||
("diff", po::value<bool>(&settings.also_difference)->default_value(false), "Include testing on difference")
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons")
|
||||
("open", po::value<bool>(&open)->default_value(false), "Open polygons")
|
||||
("type", po::value<std::string>(&type)->default_value("float"), "Type (float,double)")
|
||||
("type", po::value<std::string>(&type)->default_value("double"), "Type (float,double)")
|
||||
#endif
|
||||
("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
|
||||
("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
|
||||
;
|
||||
@ -214,6 +220,7 @@ int main(int argc, char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
if (ccw && open)
|
||||
{
|
||||
test_all<false, false>(type, seed, count, settings);
|
||||
@ -227,6 +234,7 @@ int main(int argc, char** argv)
|
||||
test_all<true, false>(type, seed, count, settings);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
test_all<true, true>(type, seed, count, settings);
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Robustness Test
|
||||
|
||||
// Copyright (c) 2009-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2009-2021 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)
|
||||
|
||||
#define BOOST_GEOMETRY_NO_BOOST_TEST
|
||||
#define BOOST_GEOMETRY_NO_ROBUSTNESS
|
||||
#define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
|
||||
|
||||
#include <test_overlay_p_q.hpp>
|
||||
|
||||
@ -174,8 +176,10 @@ int main(int argc, char** argv)
|
||||
("level", po::value<int>(&level)->default_value(3), "Level to reach (higher->slower)")
|
||||
("size", po::value<int>(&field_size)->default_value(10), "Size of the field")
|
||||
("form", po::value<std::string>(&form)->default_value("box"), "Form of the polygons (box, triangle)")
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons")
|
||||
("open", po::value<bool>(&open)->default_value(false), "Open polygons")
|
||||
#endif
|
||||
("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
|
||||
("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
|
||||
;
|
||||
@ -193,7 +197,7 @@ int main(int argc, char** argv)
|
||||
|
||||
bool triangular = form != "box";
|
||||
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
if (ccw && open)
|
||||
{
|
||||
test_all<default_test_type, false, false>(seed, count, field_size, level, triangular, settings);
|
||||
@ -207,6 +211,7 @@ int main(int argc, char** argv)
|
||||
test_all<default_test_type, true, false>(seed, count, field_size, level, triangular, settings);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
test_all<default_test_type, true, true>(seed, count, field_size, level, triangular, settings);
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Robustness Test
|
||||
|
||||
// Copyright (c) 2009-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2009-2021 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)
|
||||
|
||||
#define BOOST_GEOMETRY_NO_BOOST_TEST
|
||||
#define BOOST_GEOMETRY_NO_ROBUSTNESS
|
||||
#define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
|
||||
|
||||
#include <test_overlay_p_q.hpp>
|
||||
|
||||
@ -98,8 +100,10 @@ int main(int argc, char** argv)
|
||||
("count", po::value<int>(&count)->default_value(1), "Number of tests")
|
||||
("point_count", po::value<int>(&point_count)->default_value(1), "Number of points in the star")
|
||||
("diff", po::value<bool>(&settings.also_difference)->default_value(false), "Include testing on difference")
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons")
|
||||
("open", po::value<bool>(&open)->default_value(false), "Open polygons")
|
||||
#endif
|
||||
("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
|
||||
("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
|
||||
;
|
||||
@ -117,7 +121,7 @@ int main(int argc, char** argv)
|
||||
int star_point_count = point_count * 2 + 1;
|
||||
int comb_comb_count = point_count;
|
||||
|
||||
|
||||
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
|
||||
if (ccw && open)
|
||||
{
|
||||
test_all<default_test_type, false, false>(count, star_point_count, comb_comb_count, factor1, factor2, do_union, settings);
|
||||
@ -131,6 +135,7 @@ int main(int argc, char** argv)
|
||||
test_all<default_test_type, true, false>(count, star_point_count, comb_comb_count, factor1, factor2, do_union, settings);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
test_all<default_test_type, true, true>(count, star_point_count, comb_comb_count, factor1, factor2, do_union, settings);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Robustness Test
|
||||
|
||||
// Copyright (c) 2009-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2009-2021 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2021.
|
||||
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
|
||||
@ -40,21 +40,16 @@
|
||||
|
||||
struct p_q_settings
|
||||
{
|
||||
bool svg;
|
||||
bool also_difference;
|
||||
bool validity;
|
||||
bool wkt;
|
||||
bool verify_area;
|
||||
double tolerance;
|
||||
bool svg{false};
|
||||
bool also_difference{false};
|
||||
bool validity{false};
|
||||
bool wkt{false};
|
||||
bool verify_area{false};
|
||||
double tolerance{1.0e-3};
|
||||
bool verbose{false};
|
||||
|
||||
p_q_settings()
|
||||
: svg(false)
|
||||
, also_difference(false)
|
||||
, validity(false)
|
||||
, wkt(false)
|
||||
, verify_area(false)
|
||||
, tolerance(1.0e-3) // since rescaling to integer the tolerance should be less. Was originally 1.0e-6
|
||||
{}
|
||||
// NOTE: since rescaling to integer the tolerance is less.
|
||||
// Was originally 1.0e-6 TODO: restore
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
@ -209,6 +204,7 @@ static bool test_overlay_p_q(std::string const& caseid,
|
||||
}
|
||||
|
||||
bool svg = settings.svg;
|
||||
bool wkt = settings.wkt;
|
||||
|
||||
if (wrong || settings.wkt)
|
||||
{
|
||||
@ -216,53 +212,66 @@ static bool test_overlay_p_q(std::string const& caseid,
|
||||
{
|
||||
result = false;
|
||||
svg = true;
|
||||
wkt = true;
|
||||
}
|
||||
bg::unique(out_i);
|
||||
bg::unique(out_u);
|
||||
|
||||
std::cout
|
||||
<< "type: " << string_from_type<CalculationType>::name()
|
||||
<< " id: " << caseid
|
||||
<< " area i: " << area_i
|
||||
<< " area u: " << area_u
|
||||
<< " area p: " << area_p
|
||||
<< " area q: " << area_q
|
||||
<< " sum: " << sum;
|
||||
|
||||
if (settings.also_difference)
|
||||
if (settings.verbose)
|
||||
{
|
||||
std::cout
|
||||
<< " area d1: " << area_d1
|
||||
<< " area d2: " << area_d2;
|
||||
}
|
||||
std::cout
|
||||
<< std::endl
|
||||
<< std::setprecision(9)
|
||||
<< " p: " << bg::wkt(p) << std::endl
|
||||
<< " q: " << bg::wkt(q) << std::endl
|
||||
<< " i: " << bg::wkt(out_i) << std::endl
|
||||
<< " u: " << bg::wkt(out_u) << std::endl
|
||||
;
|
||||
<< "type: " << string_from_type<CalculationType>::name()
|
||||
<< " id: " << caseid
|
||||
<< " area i: " << area_i
|
||||
<< " area u: " << area_u
|
||||
<< " area p: " << area_p
|
||||
<< " area q: " << area_q
|
||||
<< " sum: " << sum;
|
||||
|
||||
if (settings.also_difference)
|
||||
{
|
||||
std::cout
|
||||
<< " area d1: " << area_d1
|
||||
<< " area d2: " << area_d2;
|
||||
}
|
||||
std::cout
|
||||
<< std::endl
|
||||
<< std::setprecision(9)
|
||||
<< " p: " << bg::wkt(p) << std::endl
|
||||
<< " q: " << bg::wkt(q) << std::endl
|
||||
<< " i: " << bg::wkt(out_i) << std::endl
|
||||
<< " u: " << bg::wkt(out_u) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if(svg)
|
||||
std::string filename;
|
||||
{
|
||||
std::ostringstream filename;
|
||||
filename << "overlay_" << caseid << "_"
|
||||
std::ostringstream out;
|
||||
out << "overlay_" << caseid << "_"
|
||||
<< string_from_type<coordinate_type>::name();
|
||||
if (!std::is_same<coordinate_type, CalculationType>::value)
|
||||
{
|
||||
filename << string_from_type<CalculationType>::name();
|
||||
out << string_from_type<CalculationType>::name();
|
||||
}
|
||||
|
||||
filename
|
||||
out
|
||||
#if defined(BOOST_GEOMETRY_USE_RESCALING)
|
||||
<< "_rescaled"
|
||||
<< "_rescaled"
|
||||
#endif
|
||||
<< ".svg";
|
||||
<< ".";
|
||||
filename = out.str();
|
||||
}
|
||||
|
||||
std::ofstream svg(filename.str().c_str());
|
||||
if (wkt)
|
||||
{
|
||||
std::ofstream stream(filename + "wkt");
|
||||
// Stream input WKT's
|
||||
stream << bg::wkt(p) << std::endl;
|
||||
stream << bg::wkt(q) << std::endl;
|
||||
// If you need the output WKT, then stream out_i and out_u
|
||||
}
|
||||
|
||||
|
||||
if (svg)
|
||||
{
|
||||
std::ofstream svg(filename + "svg");
|
||||
|
||||
bg::svg_mapper<point_type> mapper(svg, 500, 500);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Robustness Test
|
||||
|
||||
// Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2012-2021 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2015-2021.
|
||||
// Modifications copyright (c) 2015-2021 Oracle and/or its affiliates.
|
||||
@ -13,6 +13,8 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_GEOMETRY_NO_BOOST_TEST
|
||||
#define BOOST_GEOMETRY_NO_ROBUSTNESS
|
||||
#define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning( disable : 4244 )
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <boost/geometry/strategies/spherical/side_by_cross_track.hpp>
|
||||
//#include <boost/geometry/strategies/spherical/side_via_plane.hpp>
|
||||
#include <boost/geometry/strategies/spherical/ssf.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/geographic/mapping_ssf.hpp>
|
||||
#include <boost/geometry/strategies/geographic/side_andoyer.hpp>
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||
#include <boost/geometry/algorithms/within.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
|
||||
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
|
||||
@ -28,7 +30,6 @@
|
||||
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
|
||||
#include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategies/spherical/ssf.hpp>
|
||||
|
||||
// TEMP
|
||||
|
Loading…
x
Reference in New Issue
Block a user