Merge branch 'develop' into bg-prepare

This commit is contained in:
Adam Wulkiewicz
2021-10-27 15:43:14 +02:00
297 changed files with 7601 additions and 5052 deletions

View File

@@ -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
@@ -407,15 +407,15 @@ jobs:
root: ~/project
paths:
- shared-coverage/index_rtree_exceptions
index_varray:
index_detail:
<<: *config
steps:
- *attach_workspace
- run: ./$BOOST_DIR/libs/geometry/.circleci/run_test.sh index_varray index/test//boost-geometry-index-varray
- run: ./$BOOST_DIR/libs/geometry/.circleci/run_test.sh index_detail index/test//boost-geometry-index-detail
- persist_to_workspace:
root: ~/project
paths:
- shared-coverage/index_varray
- shared-coverage/index_detail
coverage:
<<: *config
@@ -494,7 +494,7 @@ requires_4: &requires_4
- index_rtree
- index_rtree_b2d
- index_rtree_exceptions
- index_varray
- index_detail
- cs_undefined
only_master_develop: &only_master_develop
@@ -630,7 +630,7 @@ workflows:
- index_rtree_exceptions:
<<: *requires_3
<<: *only_master_develop
- index_varray:
- index_detail:
<<: *requires_3
<<: *only_master_develop
- cs_undefined:

23
LICENSE_1_0.txt Normal file
View 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.

View File

@@ -32,7 +32,7 @@ int main()
// if the invalidity is only due to lack of closing points and/or wrongly oriented rings, then bg::correct can fix it
bool could_be_fixed = (failure == boost::geometry::failure_not_closed
|| boost::geometry::failure_wrong_orientation);
|| failure == boost::geometry::failure_wrong_orientation);
std::cout << "is valid? " << (valid ? "yes" : "no") << std::endl;
if (! valid)
{

View File

@@ -0,0 +1,34 @@
# Boost.Geometry
# Example CMakeLists.txt building the Boost.Geometry with wxWidget example
#
# Copyright (c) 2021-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)
cmake_minimum_required(VERSION 3.10)
project(with_external_libs)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# Set BOOST_ROOT in your environment (this is cmake default)
find_package(Boost)
# Set WX_ROOT, similarly, also in your environment
set(WX_ROOT $ENV{WX_ROOT})
message(STATUS "Using wxWidgets from this folder: " $ENV{WX_ROOT})
# WX Widgets
link_directories(${WX_ROOT}/lib)
add_executable(wx x04_wxwidgets_world_mapper.cpp)
target_include_directories(wx PRIVATE ${Boost_INCLUDE_DIRS})
target_include_directories(wx PRIVATE ${WX_ROOT}/include)
target_include_directories(wx PRIVATE ${WX_ROOT}/include/wx-3.1)
# WX configuration (get the values using wx-config --cxxflags and wx-config --libs)
target_compile_definitions(wx PRIVATE WXUSINGDLL __WXGTK2__ __WXGTK__)
target_link_libraries(wx PRIVATE wx_gtk2u_html-3.1 wx_gtk2u_core-3.1 wx_baseu_net-3.1 wx_baseu-3.1)

View File

@@ -1,115 +1,62 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Boost.Geometry
//
// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2010-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)
//
// wxWidgets World Mapper example
//
// It will show a basic wxWidgets window, displaying world countries,
// highlighting the country under the mouse, and indicating position
// of the mouse in latitude/longitude and in pixels.
// To compile this program:
// Install wxWidgets (if not done before)
// export BOOST_ROOT=.....
// export WX_ROOT=.... (for example /home/myname/mylib/wxWidgets/Linux/x86_64)
// mkdir build
// cd build
// cmake .. -G Ninja
// ninja
// If necessary, CMakeLists.txt should be adapted, the options for wx
// are provided by "wx-config --cxxflags" and "... --libs"
// and might need a change in CMakeLists.txt
// #define EXAMPLE_WX_USE_GRAPHICS_CONTEXT 1
//#define EXAMPLE_WX_USE_GRAPHICS_CONTEXT 1
#include <fstream>
#include <sstream>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/multi_geometries.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/geometries/register/point.hpp>
#include <boost/geometry/geometries/register/ring.hpp>
#include <boost/geometry/extensions/algorithms/selected.hpp>
// wxWidgets, if these headers are NOT found, adapt include path (and lib path)
#include "wx/wx.h"
#include "wx/math.h"
#include "wx/stockitem.h"
#ifdef EXAMPLE_WX_USE_GRAPHICS_CONTEXT
#include "wx/graphics.h"
#include "wx/dcgraph.h"
#endif
typedef boost::geometry::model::d2::point_xy<double> point_2d;
typedef boost::geometry::model::multi_polygon
using point_2d = boost::geometry::model::d2::point_xy<double>;
using country_type = boost::geometry::model::multi_polygon
<
boost::geometry::model::polygon<point_2d>
> country_type;
>;
// Adapt wxWidgets points to Boost.Geometry points such that they can be used
// in e.g. transformations (see below)
BOOST_GEOMETRY_REGISTER_POINT_2D(wxPoint, int, cs::cartesian, x, y)
BOOST_GEOMETRY_REGISTER_POINT_2D(wxRealPoint, double, cs::cartesian, x, y)
// wxWidgets draws using wxPoint*, so we HAVE to use that.
// Therefore have to make a wxPoint* array
// 1) compatible with Boost.Geometry
// 2) compatible with Boost.Range (required by Boost.Geometry)
// 3) compatible with std::back_inserter (required by Boost.Geometry)
// For compatible 2):
typedef std::pair<wxPoint*,wxPoint*> wxPointPointerPair;
// For compatible 1):
BOOST_GEOMETRY_REGISTER_RING(wxPointPointerPair);
// For compatible 3):
// Specialize back_insert_iterator for the wxPointPointerPair
// (has to be done within "namespace std")
namespace std
{
template <>
class back_insert_iterator<wxPointPointerPair>
{
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
typedef wxPointPointerPair container_type;
explicit back_insert_iterator(wxPointPointerPair& x)
: current(boost::begin(x))
, end(boost::end(x))
{}
inline back_insert_iterator<wxPointPointerPair>&
operator=(wxPoint const& value)
{
// Check if not passed beyond
if (current != end)
{
*current++ = value;
}
return *this;
}
// Boiler-plate
inline back_insert_iterator<wxPointPointerPair>& operator*() { return *this; }
inline back_insert_iterator<wxPointPointerPair>& operator++() { return *this; }
inline back_insert_iterator<wxPointPointerPair>& operator++(int) { return *this; }
private:
boost::range_iterator<wxPointPointerPair>::type current, end;
};
} // namespace std
// ----------------------------------------------------------------------------
// Read an ASCII file containing WKT's
// ----------------------------------------------------------------------------
@@ -161,26 +108,29 @@ private:
void OnPaint(wxPaintEvent& );
void OnMouseMove(wxMouseEvent&);
typedef boost::geometry::strategy::transform::map_transformer
using map_transformer_type = boost::geometry::strategy::transform::map_transformer
<
double, 2, 2,
true, true
> map_transformer_type;
>;
typedef boost::geometry::strategy::transform::inverse_transformer
using inverse_transformer_type = boost::geometry::strategy::transform::inverse_transformer
<
double, 2, 2
> inverse_transformer_type;
>;
boost::shared_ptr<map_transformer_type> m_map_transformer;
boost::shared_ptr<inverse_transformer_type> m_inverse_transformer;
std::shared_ptr<map_transformer_type> m_map_transformer;
std::shared_ptr<inverse_transformer_type> m_inverse_transformer;
boost::geometry::model::box<point_2d> m_box;
std::vector<country_type> m_countries;
int m_focus;
int m_focus = -1;
wxBrush m_orange;
wxFrame* m_owner;
wxBrush m_orange = wxBrush(wxColour(255, 128, 0), wxBRUSHSTYLE_SOLID);
wxBrush m_blue = wxBrush(wxColour(0, 128, 255), wxBRUSHSTYLE_SOLID);
wxBrush m_green = wxBrush(wxColour(0, 255, 0), wxBRUSHSTYLE_SOLID);
wxFrame* m_owner = nullptr;
DECLARE_EVENT_TABLE()
};
@@ -244,19 +194,14 @@ void HelloWorldFrame::OnCloseWindow(wxCloseEvent& )
HelloWorldCanvas::HelloWorldCanvas(wxFrame *frame)
: wxWindow(frame, wxID_ANY)
, m_owner(frame)
, m_focus(-1)
{
boost::geometry::assign_inverse(m_box);
read_wkt("../data/world.wkt", m_countries, m_box);
m_orange = wxBrush(wxColour(255, 128, 0), wxSOLID);
}
void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event)
{
namespace bg = boost::geometry;
if (m_inverse_transformer)
{
// Boiler-plate wxWidgets code
@@ -264,19 +209,21 @@ void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event)
PrepareDC(dc);
m_owner->PrepareDC(dc);
// Transform the point to Lon/Lat
// Transform the point opn the screen back to Lon/Lat
point_2d point;
bg::transform(event.GetPosition(), point, *m_inverse_transformer);
boost::geometry::transform(event.GetPosition(), point,
*m_inverse_transformer);
// Determine selected object
int i = 0;
int previous_focus = m_focus;
m_focus = -1;
BOOST_FOREACH(country_type const& country, m_countries)
for (country_type const& country : m_countries)
{
if (bg::selected(country, point, 0))
if (boost::geometry::within(point, country))
{
m_focus = i;
break;
}
i++;
}
@@ -287,7 +234,7 @@ void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event)
// Undraw old focus
if (previous_focus >= 0)
{
dc.SetBrush(*wxWHITE_BRUSH);
dc.SetBrush(m_green);
DrawCountry(dc, m_countries[previous_focus]);
}
// Draw new focus
@@ -309,6 +256,11 @@ void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event)
void HelloWorldCanvas::OnPaint(wxPaintEvent& )
{
if (m_countries.empty())
{
return;
}
#if defined(EXAMPLE_WX_USE_GRAPHICS_CONTEXT)
wxPaintDC pdc(this);
wxGCDC gdc(pdc);
@@ -340,11 +292,12 @@ void HelloWorldCanvas::DrawCountries(wxDC& dc)
{
namespace bg = boost::geometry;
dc.SetBackground(*wxLIGHT_GREY_BRUSH);
dc.SetBackground(m_blue);
dc.Clear();
BOOST_FOREACH(country_type const& country, m_countries)
for (country_type const& country : m_countries)
{
dc.SetBrush(m_green);
DrawCountry(dc, country);
}
if (m_focus != -1)
@@ -357,27 +310,23 @@ void HelloWorldCanvas::DrawCountries(wxDC& dc)
void HelloWorldCanvas::DrawCountry(wxDC& dc, country_type const& country)
{
namespace bg = boost::geometry;
BOOST_FOREACH(bg::model::polygon<point_2d> const& poly, country)
for (auto const& poly : country)
{
// Use only exterior ring, holes are (for the moment) ignored. This would need
// a holey-polygon compatible wx object
// Use only exterior ring, holes are (for the moment) ignored.
// This would need a holey-polygon compatible wx object
std::size_t n = boost::size(bg::exterior_ring(poly));
boost::scoped_array<wxPoint> points(new wxPoint[n]);
wxPointPointerPair pair = std::make_pair(points.get(), points.get() + n);
bg::transform(bg::exterior_ring(poly), pair, *m_map_transformer);
dc.DrawPolygon(n, points.get());
// Define a Boost.Geometry ring of wxPoints
// Behind the scenes that is a vector, and a vector has .data(),
// can be used for the *wxPoint pointer needed for wxWidget DrawPolygon
boost::geometry::model::ring<wxPoint> ring;
boost::geometry::transform(boost::geometry::exterior_ring(poly), ring,
*m_map_transformer);
dc.DrawPolygon(ring.size(), ring.data());
}
}
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(HelloWorldFrame, wxFrame)
EVT_CLOSE(HelloWorldFrame::OnCloseWindow)
EVT_MENU(wxID_EXIT, HelloWorldFrame::OnExit)

View File

@@ -1,23 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
// Copyright Barend Gehrels 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)
wxWidgets World Mapper example
It will show a basic wxWidgets window, displaying world countries, highlighting the country under
the mouse, and indicating position of the mouse in latitude/longitude and in pixels.
To compile this program:
Install wxWidgets (if not done before)
Using Linux/gcc
- check if installation is OK, http://wiki.wxwidgets.org/Installing_and_configuring_under_Ubuntu
- compile using e.g. gcc -o x04_wxwidgets -I../../../.. x04_wxwidgets_world_mapper.cpp `wx-config --cxxflags` `wx-config --libs`

View File

@@ -23,6 +23,8 @@
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/azimuth/cartesian.hpp>
#include <boost/geometry/strategies/azimuth/geographic.hpp>

View File

@@ -28,9 +28,6 @@
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/throw_exception.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
@@ -41,15 +38,18 @@
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/centroid/translating_transformer.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/centroid/cartesian.hpp>
@@ -61,6 +61,7 @@
#include <boost/geometry/util/algorithm.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
#include <boost/geometry/views/closeable_view.hpp>
@@ -540,9 +541,9 @@ struct centroid<default_strategy, false>
} // namespace resolve_strategy
namespace resolve_variant {
namespace resolve_dynamic {
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct centroid
{
template <typename Point, typename Strategy>
@@ -553,37 +554,22 @@ struct centroid
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct centroid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct centroid<Geometry, dynamic_geometry_tag>
{
template <typename Point, typename Strategy>
struct visitor: boost::static_visitor<void>
static inline void apply(Geometry const& geometry,
Point& out,
Strategy const& strategy)
{
Point& m_out;
Strategy const& m_strategy;
visitor(Point& out, Strategy const& strategy)
: m_out(out), m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry) const
traits::visit<Geometry>::apply([&](auto const& g)
{
centroid<Geometry>::apply(geometry, m_out, m_strategy);
}
};
template <typename Point, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Point& out,
Strategy const& strategy)
{
boost::apply_visitor(visitor<Point, Strategy>(out, strategy), geometry);
centroid<util::remove_cref_t<decltype(g)>>::apply(g, out, strategy);
}, geometry);
}
};
} // namespace resolve_variant
} // namespace resolve_dynamic
/*!
@@ -604,10 +590,9 @@ struct centroid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
*/
template<typename Geometry, typename Point, typename Strategy>
inline void centroid(Geometry const& geometry, Point& c,
Strategy const& strategy)
inline void centroid(Geometry const& geometry, Point& c, Strategy const& strategy)
{
resolve_variant::centroid<Geometry>::apply(geometry, c, strategy);
resolve_dynamic::centroid<Geometry>::apply(geometry, c, strategy);
}

View File

@@ -5,8 +5,8 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-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
@@ -28,12 +28,11 @@
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/correct_closure.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
@@ -42,12 +41,18 @@
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
#include <boost/geometry/util/order_as_direction.hpp>
#include <boost/geometry/strategies/area/cartesian.hpp>
#include <boost/geometry/strategies/area/geographic.hpp>
#include <boost/geometry/strategies/area/spherical.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/util/algorithm.hpp>
namespace boost { namespace geometry
{
@@ -62,92 +67,56 @@ namespace boost { namespace geometry
namespace detail { namespace correct
{
template <typename Geometry>
struct correct_nop
{
template <typename Strategy>
template <typename Geometry, typename Strategy>
static inline void apply(Geometry& , Strategy const& )
{}
};
template <typename Box, std::size_t Dimension, std::size_t DimensionCount>
struct correct_box_loop
{
typedef typename coordinate_type<Box>::type coordinate_type;
static inline void apply(Box& box)
{
if (get<min_corner, Dimension>(box) > get<max_corner, Dimension>(box))
{
// Swap the coordinates
coordinate_type max_value = get<min_corner, Dimension>(box);
coordinate_type min_value = get<max_corner, Dimension>(box);
set<min_corner, Dimension>(box, min_value);
set<max_corner, Dimension>(box, max_value);
}
correct_box_loop
<
Box, Dimension + 1, DimensionCount
>::apply(box);
}
};
template <typename Box, std::size_t DimensionCount>
struct correct_box_loop<Box, DimensionCount, DimensionCount>
{
static inline void apply(Box& )
{}
};
// Correct a box: make min/max correct
template <typename Box>
struct correct_box
{
template <typename Strategy>
template <typename Box, typename Strategy>
static inline void apply(Box& box, Strategy const& )
{
using coordinate_type = typename geometry::coordinate_type<Box>::type;
// Currently only for Cartesian coordinates
// (or spherical without crossing dateline)
// Future version: adapt using strategies
correct_box_loop
<
Box, 0, dimension<Box>::type::value
>::apply(box);
detail::for_each_dimension<Box>([&](auto dimension)
{
if (get<min_corner, dimension>(box) > get<max_corner, dimension>(box))
{
// Swap the coordinates
coordinate_type max_value = get<min_corner, dimension>(box);
coordinate_type min_value = get<max_corner, dimension>(box);
set<min_corner, dimension>(box, min_value);
set<max_corner, dimension>(box, max_value);
}
});
}
};
// Close a ring, if not closed
template <typename Ring, template <typename> class Predicate>
template <typename Predicate = std::less<>>
struct correct_ring
{
typedef typename point_type<Ring>::type point_type;
typedef typename coordinate_type<Ring>::type coordinate_type;
template <typename Strategy>
template <typename Ring, typename Strategy>
static inline void apply(Ring& r, Strategy const& strategy)
{
// Correct closure if necessary
detail::correct_closure::close_or_open_ring<Ring>::apply(r);
detail::correct_closure::close_or_open_ring::apply(r);
// NOTE: calculate_point_order should probably be used here instead.
// Check area
typedef typename area_result<Ring, Strategy>::type area_result_type;
Predicate<area_result_type> predicate;
area_result_type const zero = 0;
if (predicate(detail::area::ring_area::apply(
r,
// TEMP - in the future (umbrella) strategy will be passed
geometry::strategies::area::services::strategy_converter
<
Strategy
>::get(strategy)),
zero))
using area_t = typename area_result<Ring, Strategy>::type;
area_t const zero = 0;
if (Predicate()(detail::area::ring_area::apply(r, strategy), zero))
{
std::reverse(boost::begin(r), boost::end(r));
}
@@ -156,30 +125,18 @@ struct correct_ring
// Correct a polygon: normalizes all rings, sets outer ring clockwise, sets all
// inner rings counter clockwise (or vice versa depending on orientation)
template <typename Polygon>
struct correct_polygon
{
typedef typename ring_type<Polygon>::type ring_type;
template <typename Strategy>
template <typename Polygon, typename Strategy>
static inline void apply(Polygon& poly, Strategy const& strategy)
{
correct_ring
<
ring_type,
std::less
>::apply(exterior_ring(poly), strategy);
correct_ring<std::less<>>::apply(exterior_ring(poly), strategy);
typename interior_return_type<Polygon>::type
rings = interior_rings(poly);
for (typename detail::interior_iterator<Polygon>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
auto&& rings = interior_rings(poly);
auto const end = boost::end(rings);
for (auto it = boost::begin(rings); it != end; ++it)
{
correct_ring
<
ring_type,
std::greater
>::apply(*it, strategy);
correct_ring<std::greater<>>::apply(*it, strategy);
}
}
};
@@ -199,62 +156,51 @@ struct correct: not_implemented<Tag>
template <typename Point>
struct correct<Point, point_tag>
: detail::correct::correct_nop<Point>
: detail::correct::correct_nop
{};
template <typename LineString>
struct correct<LineString, linestring_tag>
: detail::correct::correct_nop<LineString>
: detail::correct::correct_nop
{};
template <typename Segment>
struct correct<Segment, segment_tag>
: detail::correct::correct_nop<Segment>
: detail::correct::correct_nop
{};
template <typename Box>
struct correct<Box, box_tag>
: detail::correct::correct_box<Box>
: detail::correct::correct_box
{};
template <typename Ring>
struct correct<Ring, ring_tag>
: detail::correct::correct_ring
<
Ring,
std::less
>
: detail::correct::correct_ring<>
{};
template <typename Polygon>
struct correct<Polygon, polygon_tag>
: detail::correct::correct_polygon<Polygon>
: detail::correct::correct_polygon
{};
template <typename MultiPoint>
struct correct<MultiPoint, multi_point_tag>
: detail::correct::correct_nop<MultiPoint>
: detail::correct::correct_nop
{};
template <typename MultiLineString>
struct correct<MultiLineString, multi_linestring_tag>
: detail::correct::correct_nop<MultiLineString>
: detail::correct::correct_nop
{};
template <typename Geometry>
struct correct<Geometry, multi_polygon_tag>
: detail::multi_modify
<
Geometry,
detail::correct::correct_polygon
<
typename boost::range_value<Geometry>::type
>
>
: detail::multi_modify<detail::correct::correct_polygon>
{};
@@ -262,45 +208,96 @@ struct correct<Geometry, multi_polygon_tag>
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_variant {
namespace resolve_strategy
{
template <typename Geometry>
template
<
typename Strategy,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
>
struct correct
{
template <typename Geometry>
static inline void apply(Geometry& geometry, Strategy const& strategy)
{
dispatch::correct<Geometry>::apply(geometry, strategy);
}
};
template <typename Strategy>
struct correct<Strategy, false>
{
template <typename Geometry>
static inline void apply(Geometry& geometry, Strategy const& strategy)
{
// NOTE: calculate_point_order strategy should probably be used here instead.
using geometry::strategies::area::services::strategy_converter;
dispatch::correct<Geometry>::apply(geometry, strategy_converter<Strategy>::get(strategy));
}
};
template <>
struct correct<default_strategy, false>
{
template <typename Geometry>
static inline void apply(Geometry& geometry, default_strategy const& )
{
// NOTE: calculate_point_order strategy should probably be used here instead.
using strategy_type = typename strategies::area::services::default_strategy
<
Geometry
>::type;
dispatch::correct<Geometry>::apply(geometry, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_dynamic
{
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct correct
{
template <typename Strategy>
static inline void apply(Geometry& geometry, Strategy const& strategy)
{
concepts::check<Geometry const>();
dispatch::correct<Geometry>::apply(geometry, strategy);
concepts::check<Geometry>();
resolve_strategy::correct<Strategy>::apply(geometry, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct correct<Geometry, dynamic_geometry_tag>
{
template <typename Strategy>
struct visitor: boost::static_visitor<void>
static inline void apply(Geometry& geometry, Strategy const& strategy)
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry>
void operator()(Geometry& geometry) const
traits::visit<Geometry>::apply([&](auto & g)
{
correct<Geometry>::apply(geometry, m_strategy);
}
};
template <typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry, Strategy const& strategy)
{
boost::apply_visitor(visitor<Strategy>(strategy), geometry);
correct<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
}, geometry);
}
};
} // namespace resolve_variant
template <typename Geometry>
struct correct<Geometry, geometry_collection_tag>
{
template <typename Strategy>
static inline void apply(Geometry& geometry, Strategy const& strategy)
{
detail::visit_breadth_first([&](auto & g)
{
correct<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
return true;
}, geometry);
}
};
} // namespace resolve_dynamic
/*!
@@ -318,14 +315,7 @@ struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline void correct(Geometry& geometry)
{
typedef typename point_type<Geometry>::type point_type;
typedef typename strategy::area::services::default_strategy
<
typename cs_tag<point_type>::type
>::type strategy_type;
resolve_variant::correct<Geometry>::apply(geometry, strategy_type());
resolve_dynamic::correct<Geometry>::apply(geometry, default_strategy());
}
/*!
@@ -347,7 +337,7 @@ inline void correct(Geometry& geometry)
template <typename Geometry, typename Strategy>
inline void correct(Geometry& geometry, Strategy const& strategy)
{
resolve_variant::correct<Geometry>::apply(geometry, strategy);
resolve_dynamic::correct<Geometry>::apply(geometry, strategy);
}
#if defined(_MSC_VER)

View File

@@ -2,8 +2,8 @@
// Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands.
// 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,
@@ -15,16 +15,9 @@
#include <cstddef>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
@@ -32,10 +25,11 @@
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
@@ -50,59 +44,55 @@ namespace boost { namespace geometry
namespace detail { namespace correct_closure
{
template <typename Geometry>
struct nop
{
template <typename Geometry>
static inline void apply(Geometry& )
{}
};
// Close a ring, if not closed, or open it
template <typename Ring>
struct close_or_open_ring
{
template <typename Ring>
static inline void apply(Ring& r)
{
if (boost::size(r) <= 2)
auto size = boost::size(r);
if (size <= 2)
{
return;
}
bool const disjoint = geometry::disjoint(*boost::begin(r),
*(boost::end(r) - 1));
closure_selector const s = geometry::closure<Ring>::value;
// TODO: This requires relate(pt, pt) strategy
bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1));
closure_selector const closure = geometry::closure<Ring>::value;
if (disjoint && s == closed)
if (disjoint && closure == closed)
{
// Close it by adding first point
geometry::append(r, *boost::begin(r));
}
else if (! disjoint && s != closed)
else if (! disjoint && closure == open)
{
// Open it by removing last point
geometry::traits::resize<Ring>::apply(r, boost::size(r) - 1);
range::resize(r, size - 1);
}
}
};
// Close/open exterior ring and all its interior rings
template <typename Polygon>
struct close_or_open_polygon
{
typedef typename ring_type<Polygon>::type ring_type;
template <typename Polygon>
static inline void apply(Polygon& poly)
{
close_or_open_ring<ring_type>::apply(exterior_ring(poly));
close_or_open_ring::apply(exterior_ring(poly));
typename interior_return_type<Polygon>::type
rings = interior_rings(poly);
for (typename detail::interior_iterator<Polygon>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
auto&& rings = interior_rings(poly);
auto const end = boost::end(rings);
for (auto it = boost::begin(rings); it != end; ++it)
{
close_or_open_ring<ring_type>::apply(*it);
close_or_open_ring::apply(*it);
}
}
};
@@ -121,45 +111,45 @@ struct correct_closure: not_implemented<Tag>
template <typename Point>
struct correct_closure<Point, point_tag>
: detail::correct_closure::nop<Point>
: detail::correct_closure::nop
{};
template <typename LineString>
struct correct_closure<LineString, linestring_tag>
: detail::correct_closure::nop<LineString>
: detail::correct_closure::nop
{};
template <typename Segment>
struct correct_closure<Segment, segment_tag>
: detail::correct_closure::nop<Segment>
: detail::correct_closure::nop
{};
template <typename Box>
struct correct_closure<Box, box_tag>
: detail::correct_closure::nop<Box>
: detail::correct_closure::nop
{};
template <typename Ring>
struct correct_closure<Ring, ring_tag>
: detail::correct_closure::close_or_open_ring<Ring>
: detail::correct_closure::close_or_open_ring
{};
template <typename Polygon>
struct correct_closure<Polygon, polygon_tag>
: detail::correct_closure::close_or_open_polygon<Polygon>
: detail::correct_closure::close_or_open_polygon
{};
template <typename MultiPoint>
struct correct_closure<MultiPoint, multi_point_tag>
: detail::correct_closure::nop<MultiPoint>
: detail::correct_closure::nop
{};
template <typename MultiLineString>
struct correct_closure<MultiLineString, multi_linestring_tag>
: detail::correct_closure::nop<MultiLineString>
: detail::correct_closure::nop
{};
@@ -167,11 +157,7 @@ template <typename Geometry>
struct correct_closure<Geometry, multi_polygon_tag>
: detail::multi_modify
<
Geometry,
detail::correct_closure::close_or_open_polygon
<
typename boost::range_value<Geometry>::type
>
>
{};
@@ -183,7 +169,7 @@ struct correct_closure<Geometry, multi_polygon_tag>
namespace resolve_variant
{
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct correct_closure
{
static inline void apply(Geometry& geometry)
@@ -193,29 +179,37 @@ struct correct_closure
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct correct_closure<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct correct_closure<Geometry, dynamic_geometry_tag>
{
struct visitor: boost::static_visitor<void>
static void apply(Geometry& geometry)
{
template <typename Geometry>
void operator()(Geometry& geometry) const
traits::visit<Geometry>::apply([](auto & g)
{
correct_closure<Geometry>::apply(geometry);
}
};
correct_closure<util::remove_cref_t<decltype(g)>>::apply(g);
}, geometry);
}
};
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
template <typename Geometry>
struct correct_closure<Geometry, geometry_collection_tag>
{
static void apply(Geometry& geometry)
{
visitor vis;
boost::apply_visitor(vis, geometry);
detail::visit_breadth_first([](auto & g)
{
correct_closure<util::remove_cref_t<decltype(g)>>::apply(g);
return true;
}, geometry);
}
};
} // namespace resolve_variant
// TODO: This algorithm should use relate(pt, pt) strategy
/*!
\brief Closes or opens a geometry, according to its type
\details Corrects a geometry w.r.t. closure points to all rings which do not

View File

@@ -11,8 +11,14 @@
#define BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/throw_exception.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
@@ -20,6 +26,8 @@
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/densify/cartesian.hpp>
#include <boost/geometry/strategies/densify/geographic.hpp>
@@ -28,11 +36,6 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/throw_exception.hpp>
namespace boost { namespace geometry
{
@@ -146,6 +149,15 @@ struct densify_ring<true, false>
: densify_range<false>
{};
struct densify_convert
{
template <typename GeometryIn, typename GeometryOut, typename T, typename Strategy>
static void apply(GeometryIn const& in, GeometryOut &out,
T const& , Strategy const& )
{
geometry::convert(in, out);
}
};
}} // namespace detail::densify
#endif // DOXYGEN_NO_DETAIL
@@ -167,6 +179,26 @@ struct densify
: not_implemented<Tag1, Tag2>
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, point_tag, point_tag>
: geometry::detail::densify::densify_convert
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, segment_tag, segment_tag>
: geometry::detail::densify::densify_convert
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, box_tag, box_tag>
: geometry::detail::densify::densify_convert
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, multi_point_tag, multi_point_tag>
: geometry::detail::densify::densify_convert
{};
template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, linestring_tag, linestring_tag>
: geometry::detail::densify::densify_range<>
@@ -328,9 +360,9 @@ struct densify<default_strategy, false>
} // namespace resolve_strategy
namespace resolve_variant {
namespace resolve_dynamic {
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct densify
{
template <typename Distance, typename Strategy>
@@ -346,43 +378,48 @@ struct densify
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct densify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct densify<Geometry, dynamic_geometry_tag>
{
template <typename Distance, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Distance const& m_max_distance;
Strategy const& m_strategy;
visitor(Distance const& max_distance, Strategy const& strategy)
: m_max_distance(max_distance)
, m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry, Geometry& out) const
{
densify<Geometry>::apply(geometry, out, m_max_distance, m_strategy);
}
};
template <typename Distance, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out,
apply(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
boost::apply_visitor(
visitor<Distance, Strategy>(max_distance, strategy),
geometry,
out
);
traits::visit<Geometry>::apply([&](auto const& g)
{
using geom_t = util::remove_cref_t<decltype(g)>;
geom_t o;
densify<geom_t>::apply(g, o, max_distance, strategy);
out = std::move(o);
}, geometry);
}
};
} // namespace resolve_variant
template <typename Geometry>
struct densify<Geometry, geometry_collection_tag>
{
template <typename Distance, typename Strategy>
static inline void
apply(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
detail::visit_breadth_first([&](auto const& g)
{
using geom_t = util::remove_cref_t<decltype(g)>;
geom_t o;
densify<geom_t>::apply(g, o, max_distance, strategy);
traits::emplace_back<Geometry>::apply(out, std::move(o));
return true;
}, geometry);
}
};
} // namespace resolve_dynamic
/*!
@@ -428,7 +465,7 @@ inline void densify(Geometry const& geometry,
geometry::clear(out);
resolve_variant::densify
resolve_dynamic::densify
<
Geometry
>::apply(geometry, out, max_distance, strategy);

View File

@@ -1,91 +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.
// 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct as_range : not_implemented<Geometry, Tag>
{};
template <typename Geometry>
struct as_range<Geometry, linestring_tag>
{
static inline typename ring_return_type<Geometry>::type get(Geometry& geometry)
{
return geometry;
}
};
template <typename Geometry>
struct as_range<Geometry, ring_tag>
: as_range<Geometry, linestring_tag>
{};
template <typename Geometry>
struct as_range<Geometry, polygon_tag>
{
static inline typename ring_return_type<Geometry>::type get(Geometry& geometry)
{
return exterior_ring(geometry);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
// Will probably be replaced by the more generic "view_as", therefore in detail
namespace detail
{
/*!
\brief Function getting either the range (ring, linestring) itself
or the outer ring (polygon)
\details Utility to handle polygon's outer ring as a range
\ingroup utility
*/
template <typename Geometry>
inline typename ring_return_type<Geometry>::type as_range(Geometry& geometry)
{
return dispatch::as_range<Geometry>::get(geometry);
}
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP

View File

@@ -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>

View File

@@ -175,7 +175,7 @@ public:
// unit tests of hard cases start to fail (5 in multi_polygon)
// But it is acknowlegded that such a threshold depends on the
// scale of the input.
if (state.m_min_distance > 1.0e-5 || ! state.m_close_to_offset)
if (state.m_min_distance > 1.0e-4 || ! state.m_close_to_offset)
{
Turn& mutable_turn = m_turns[turn.turn_index];
mutable_turn.is_turn_traversable = false;

View File

@@ -23,20 +23,19 @@
#include <algorithm>
#include <vector>
#include <boost/range/begin.hpp>
#include <boost/range/empty.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
#include <boost/geometry/strategies/convex_hull/geographic.hpp>
#include <boost/geometry/strategies/convex_hull/spherical.hpp>
#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
{
@@ -45,13 +44,15 @@ namespace boost { namespace geometry
namespace detail { namespace convex_hull
{
template <typename Geometry, typename Point, typename Less>
inline void get_extremes(Geometry const& geometry,
// TODO: All of the copies could be avoided if this function stored pointers to points.
// But would it be possible considering that a range can return proxy reference?
template <typename InputProxy, typename Point, typename Less>
inline void get_extremes(InputProxy const& in_proxy,
Point& left, Point& right,
Less const& less)
{
bool first = true;
geometry::detail::for_each_range(geometry, [&](auto const& range)
in_proxy.for_each_range([&](auto const& range)
{
if (boost::empty(range))
{
@@ -107,19 +108,13 @@ inline void get_extremes(Geometry const& geometry,
}
template
<
typename Geometry,
typename Point,
typename Container,
typename SideStrategy
>
inline void assign_ranges(Geometry const& geometry,
template <typename InputProxy, typename Point, typename Container, typename SideStrategy>
inline void assign_ranges(InputProxy const& in_proxy,
Point const& most_left, Point const& most_right,
Container& lower_points, Container& upper_points,
SideStrategy const& side)
{
geometry::detail::for_each_range(geometry, [&](auto const& range)
in_proxy.for_each_range([&](auto const& range)
{
// Put points in one of the two output sequences
for (auto it = boost::begin(range); it != boost::end(range); ++it)
@@ -145,34 +140,17 @@ inline void assign_ranges(Geometry const& geometry,
}
template <typename Range, typename Less>
inline void sort(Range& range, Less const& less)
{
std::sort(boost::begin(range), boost::end(range), less);
}
} // namespace convex_hull
/*!
\brief Graham scan algorithm to calculate convex hull
*/
template <typename InputGeometry, typename OutputPoint>
template <typename InputPoint>
class graham_andrew
{
public :
typedef OutputPoint point_type;
typedef InputGeometry geometry_type;
private:
typedef typename cs_tag<point_type>::type cs_tag;
typedef InputPoint point_type;
typedef typename std::vector<point_type> container_type;
typedef typename std::vector<point_type>::const_iterator iterator;
typedef typename std::vector<point_type>::const_reverse_iterator rev_iterator;
class partitions
{
friend class graham_andrew;
@@ -182,14 +160,23 @@ private:
container_type m_copied_input;
};
public:
typedef partitions state_type;
template <typename InputProxy, typename OutputRing, typename Strategy>
static void apply(InputProxy const& in_proxy, OutputRing & out_ring, Strategy& strategy)
{
partitions state;
template <typename Strategy>
inline void apply(InputGeometry const& geometry,
partitions& state,
Strategy& strategy) const
apply(in_proxy, state, strategy);
result(state,
range::back_inserter(out_ring),
geometry::point_order<OutputRing>::value == clockwise,
geometry::closure<OutputRing>::value != open);
}
private:
template <typename InputProxy, typename Strategy>
static void apply(InputProxy const& in_proxy, partitions& state, Strategy& strategy)
{
// First pass.
// Get min/max (in most cases left / right) points
@@ -203,14 +190,12 @@ public:
// For symmetry and to get often more balanced lower/upper halves
// we keep it.
typedef typename geometry::point_type<InputGeometry>::type point_type;
point_type most_left, most_right;
// TODO: User-defined CS-specific less-compare
geometry::less<point_type> less;
detail::convex_hull::get_extremes(geometry, most_left, most_right, less);
detail::convex_hull::get_extremes(in_proxy, most_left, most_right, less);
container_type lower_points, upper_points;
@@ -219,13 +204,13 @@ public:
// Bounding left/right points
// Second pass, now that extremes are found, assign all points
// in either lower, either upper
detail::convex_hull::assign_ranges(geometry, most_left, most_right,
detail::convex_hull::assign_ranges(in_proxy, most_left, most_right,
lower_points, upper_points,
side_strategy);
// Sort both collections, first on x(, then on y)
detail::convex_hull::sort(lower_points, less);
detail::convex_hull::sort(upper_points, less);
std::sort(boost::begin(lower_points), boost::end(lower_points), less);
std::sort(boost::begin(upper_points), boost::end(upper_points), less);
// And decide which point should be in the final hull
build_half_hull<-1>(lower_points, state.m_lower_hull,
@@ -236,26 +221,6 @@ public:
side_strategy);
}
template <typename OutputIterator>
inline void result(partitions const& state,
OutputIterator out,
bool clockwise,
bool closed) const
{
if (clockwise)
{
output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);
}
else
{
output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);
}
}
private:
template <int Factor, typename SideStrategy>
static inline void build_half_hull(container_type const& input,
container_type& output,
@@ -300,6 +265,19 @@ private:
}
template <typename OutputIterator>
static void result(partitions const& state, OutputIterator out, bool clockwise, bool closed)
{
if (clockwise)
{
output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);
}
else
{
output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);
}
}
template <typename OutputIterator>
static inline void output_ranges(container_type const& first,
container_type const& second,
@@ -327,7 +305,7 @@ private:
};
} // namespace detail
}} // namespace detail::convex_hull
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry

View File

@@ -21,86 +21,171 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP
#include <boost/array.hpp>
#include <array>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/as_range.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/algorithms/detail/select_geometry_type.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/geometry_types.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/geometries/ring.hpp>
#include <boost/geometry/strategies/convex_hull/services.hpp>
#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
#include <boost/geometry/strategies/convex_hull/geographic.hpp>
#include <boost/geometry/strategies/convex_hull/spherical.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
// TODO: This file is named interface.hpp but the code below is not the interface.
// It's the implementation of the algorithm.
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace convex_hull
{
template <order_selector Order, closure_selector Closure>
struct hull_insert
// Abstraction representing ranges/rings of a geometry
template <typename Geometry>
struct input_geometry_proxy
{
// Member template function (to avoid inconvenient declaration
// of output-iterator-type, from hull_to_geometry)
template <typename Geometry, typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry const& geometry,
OutputIterator out,
Strategy const& strategy)
input_geometry_proxy(Geometry const& geometry)
: m_geometry(geometry)
{}
template <typename UnaryFunction>
inline void for_each_range(UnaryFunction fun) const
{
typedef graham_andrew
<
Geometry,
typename point_type<Geometry>::type
> ConvexHullAlgorithm;
ConvexHullAlgorithm algorithm;
typename ConvexHullAlgorithm::state_type state;
algorithm.apply(geometry, state, strategy);
algorithm.result(state, out, Order == clockwise, Closure != open);
return out;
geometry::detail::for_each_range(m_geometry, fun);
}
Geometry const& m_geometry;
};
struct hull_to_geometry
// Abstraction representing ranges/rings of subgeometries of geometry collection
// with boxes converted to rings
template <typename Geometry, typename BoxRings>
struct input_geometry_collection_proxy
{
template <typename Geometry, typename OutputGeometry, typename Strategy>
static inline void apply(Geometry const& geometry, OutputGeometry& out,
Strategy const& strategy)
input_geometry_collection_proxy(Geometry const& geometry, BoxRings const& box_rings)
: m_geometry(geometry)
, m_box_rings(box_rings)
{}
template <typename UnaryFunction>
inline void for_each_range(UnaryFunction fun) const
{
// TODO: Why not handle multi-polygon here?
// TODO: detail::as_range() is only used in this place in the whole library
// it should probably be located here.
// NOTE: A variable is created here because this can be a proxy range
// and back_insert_iterator<> can store a pointer to it.
// Handle linestring, ring and polygon the same:
auto&& range = detail::as_range(out);
hull_insert
<
geometry::point_order<OutputGeometry>::value,
geometry::closure<OutputGeometry>::value
>::apply(geometry, range::back_inserter(range), strategy);
detail::visit_breadth_first([&](auto const& g)
{
input_geometry_collection_proxy::call_for_non_boxes(g, fun);
return true;
}, m_geometry);
for (auto const& r : m_box_rings)
{
geometry::detail::for_each_range(r, fun);
}
}
private:
template <typename G, typename F, std::enable_if_t<! util::is_box<G>::value, int> = 0>
static inline void call_for_non_boxes(G const& g, F & f)
{
geometry::detail::for_each_range(g, f);
}
template <typename G, typename F, std::enable_if_t<util::is_box<G>::value, int> = 0>
static inline void call_for_non_boxes(G const&, F &)
{}
Geometry const& m_geometry;
BoxRings const& m_box_rings;
};
// TODO: Or just implement point_type<> for GeometryCollection
// and enforce the same point_type used in the whole sequence in check().
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct default_strategy
{
using type = typename strategies::convex_hull::services::default_strategy
<
Geometry
>::type;
};
template <typename Geometry>
struct default_strategy<Geometry, geometry_collection_tag>
: default_strategy<typename detail::first_geometry_type<Geometry>::type>
{};
// Utilities for output GC and DG
template <typename G1, typename G2>
struct output_polygonal_less
{
template <typename G>
using priority = std::integral_constant
<
int,
(util::is_ring<G>::value ? 0 :
util::is_polygon<G>::value ? 1 :
util::is_multi_polygon<G>::value ? 2 : 3)
>;
static const bool value = priority<G1>::value < priority<G2>::value;
};
template <typename G1, typename G2>
struct output_linear_less
{
template <typename G>
using priority = std::integral_constant
<
int,
(util::is_segment<G>::value ? 0 :
util::is_linestring<G>::value ? 1 :
util::is_multi_linestring<G>::value ? 2 : 3)
>;
static const bool value = priority<G1>::value < priority<G2>::value;
};
template <typename G1, typename G2>
struct output_pointlike_less
{
template <typename G>
using priority = std::integral_constant
<
int,
(util::is_point<G>::value ? 0 :
util::is_multi_point<G>::value ? 1 : 2)
>;
static const bool value = priority<G1>::value < priority<G2>::value;
};
}} // namespace detail::convex_hull
#endif // DOXYGEN_NO_DETAIL
@@ -116,39 +201,289 @@ template
typename Tag = typename tag<Geometry>::type
>
struct convex_hull
: detail::convex_hull::hull_to_geometry
{};
{
template <typename OutputGeometry, typename Strategy>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
Strategy const& strategy)
{
detail::convex_hull::input_geometry_proxy<Geometry> in_proxy(geometry);
detail::convex_hull::graham_andrew
<
typename point_type<Geometry>::type
>::apply(in_proxy, out, strategy);
}
};
// TODO: This is not correct in spherical and geographic CS
// A hull for boxes is trivial. Any strategy is (currently) skipped.
// TODO: This is not correct in spherical and geographic CS.
template <typename Box>
struct convex_hull<Box, box_tag>
{
template <typename OutputGeometry, typename Strategy>
static inline void apply(Box const& box,
OutputGeometry& out,
Strategy const& )
Strategy const& strategy)
{
static bool const Close
= geometry::closure<OutputGeometry>::value == closed;
static bool const Reverse
= geometry::point_order<OutputGeometry>::value == counterclockwise;
// A hull for boxes is trivial. Any strategy is (currently) skipped.
boost::array<typename point_type<Box>::type, 4> range;
geometry::detail::assign_box_corners_oriented<Reverse>(box, range);
geometry::append(out, range);
std::array<typename point_type<OutputGeometry>::type, 4> arr;
// TODO: This assigns only 2d cooridnates!
// And it is also used in box_view<>!
geometry::detail::assign_box_corners_oriented<Reverse>(box, arr);
std::move(arr.begin(), arr.end(), range::back_inserter(out));
if (BOOST_GEOMETRY_CONDITION(Close))
{
geometry::append(out, *boost::begin(range));
range::push_back(out, range::front(out));
}
}
};
template <typename GeometryCollection>
struct convex_hull<GeometryCollection, geometry_collection_tag>
{
template <typename OutputGeometry, typename Strategy>
static inline void apply(GeometryCollection const& geometry,
OutputGeometry& out,
Strategy const& strategy)
{
// Assuming that single point_type is used by the GeometryCollection
using subgeometry_type = typename detail::first_geometry_type<GeometryCollection>::type;
using point_type = typename geometry::point_type<subgeometry_type>::type;
using ring_type = model::ring<point_type, true, false>;
template <order_selector Order, closure_selector Closure>
struct convex_hull_insert
: detail::convex_hull::hull_insert<Order, Closure>
// Calculate box rings once
std::vector<ring_type> box_rings;
detail::visit_breadth_first([&](auto const& g)
{
convex_hull::add_ring_for_box(box_rings, g, strategy);
return true;
}, geometry);
detail::convex_hull::input_geometry_collection_proxy
<
GeometryCollection, std::vector<ring_type>
> in_proxy(geometry, box_rings);
detail::convex_hull::graham_andrew
<
point_type
>::apply(in_proxy, out, strategy);
}
private:
template
<
typename Ring, typename SubGeometry, typename Strategy,
std::enable_if_t<util::is_box<SubGeometry>::value, int> = 0
>
static inline void add_ring_for_box(std::vector<Ring> & rings, SubGeometry const& box,
Strategy const& strategy)
{
Ring ring;
convex_hull<SubGeometry>::apply(box, ring, strategy);
rings.push_back(std::move(ring));
}
template
<
typename Ring, typename SubGeometry, typename Strategy,
std::enable_if_t<! util::is_box<SubGeometry>::value, int> = 0
>
static inline void add_ring_for_box(std::vector<Ring> & , SubGeometry const& ,
Strategy const& )
{}
};
template <typename OutputGeometry, typename Tag = typename tag<OutputGeometry>::type>
struct convex_hull_out
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE("This OutputGeometry is not supported.", OutputGeometry, Tag);
};
template <typename OutputGeometry>
struct convex_hull_out<OutputGeometry, ring_tag>
{
template <typename Geometry, typename Strategies>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
Strategies const& strategies)
{
dispatch::convex_hull<Geometry>::apply(geometry, out, strategies);
}
};
template <typename OutputGeometry>
struct convex_hull_out<OutputGeometry, polygon_tag>
{
template <typename Geometry, typename Strategies>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
Strategies const& strategies)
{
auto&& ring = exterior_ring(out);
dispatch::convex_hull<Geometry>::apply(geometry, ring, strategies);
}
};
template <typename OutputGeometry>
struct convex_hull_out<OutputGeometry, multi_polygon_tag>
{
template <typename Geometry, typename Strategies>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
Strategies const& strategies)
{
typename boost::range_value<OutputGeometry>::type polygon;
auto&& ring = exterior_ring(polygon);
dispatch::convex_hull<Geometry>::apply(geometry, ring, strategies);
// Empty input is checked so the output shouldn't be empty
range::push_back(out, std::move(polygon));
}
};
template <typename OutputGeometry>
struct convex_hull_out<OutputGeometry, geometry_collection_tag>
{
using polygonal_t = typename util::sequence_min_element
<
typename traits::geometry_types<OutputGeometry>::type,
detail::convex_hull::output_polygonal_less
>::type;
using linear_t = typename util::sequence_min_element
<
typename traits::geometry_types<OutputGeometry>::type,
detail::convex_hull::output_linear_less
>::type;
using pointlike_t = typename util::sequence_min_element
<
typename traits::geometry_types<OutputGeometry>::type,
detail::convex_hull::output_pointlike_less
>::type;
// select_element may define different kind of geometry than the one that is desired
BOOST_GEOMETRY_STATIC_ASSERT(util::is_polygonal<polygonal_t>::value,
"It must be possible to store polygonal geometry in OutputGeometry.", polygonal_t);
BOOST_GEOMETRY_STATIC_ASSERT(util::is_linear<linear_t>::value,
"It must be possible to store linear geometry in OutputGeometry.", linear_t);
BOOST_GEOMETRY_STATIC_ASSERT(util::is_pointlike<pointlike_t>::value,
"It must be possible to store pointlike geometry in OutputGeometry.", pointlike_t);
template <typename Geometry, typename Strategies>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
Strategies const& strategies)
{
polygonal_t polygonal;
convex_hull_out<polygonal_t>::apply(geometry, polygonal, strategies);
// Empty input is checked so the output shouldn't be empty
auto&& out_ring = ring(polygonal);
if (boost::size(out_ring) == detail::minimum_ring_size<polygonal_t>::value)
{
using detail::equals::equals_point_point;
if (equals_point_point(range::front(out_ring), range::at(out_ring, 1), strategies))
{
pointlike_t pointlike;
move_to_pointlike(out_ring, pointlike);
move_to_out(pointlike, out);
return;
}
if (equals_point_point(range::front(out_ring), range::at(out_ring, 2), strategies))
{
linear_t linear;
move_to_linear(out_ring, linear);
move_to_out(linear, out);
return;
}
}
move_to_out(polygonal, out);
}
private:
template <typename Polygonal, util::enable_if_ring_t<Polygonal, int> = 0>
static decltype(auto) ring(Polygonal const& polygonal)
{
return polygonal;
}
template <typename Polygonal, util::enable_if_polygon_t<Polygonal, int> = 0>
static decltype(auto) ring(Polygonal const& polygonal)
{
return exterior_ring(polygonal);
}
template <typename Polygonal, util::enable_if_multi_polygon_t<Polygonal, int> = 0>
static decltype(auto) ring(Polygonal const& polygonal)
{
return exterior_ring(range::front(polygonal));
}
template <typename Range, typename Linear, util::enable_if_segment_t<Linear, int> = 0>
static void move_to_linear(Range & out_range, Linear & seg)
{
detail::assign_point_to_index<0>(range::front(out_range), seg);
detail::assign_point_to_index<1>(range::at(out_range, 1), seg);
}
template <typename Range, typename Linear, util::enable_if_linestring_t<Linear, int> = 0>
static void move_to_linear(Range & out_range, Linear & ls)
{
std::move(boost::begin(out_range), boost::begin(out_range) + 2, range::back_inserter(ls));
}
template <typename Range, typename Linear, util::enable_if_multi_linestring_t<Linear, int> = 0>
static void move_to_linear(Range & out_range, Linear & mls)
{
typename boost::range_value<Linear>::type ls;
std::move(boost::begin(out_range), boost::begin(out_range) + 2, range::back_inserter(ls));
range::push_back(mls, std::move(ls));
}
template <typename Range, typename PointLike, util::enable_if_point_t<PointLike, int> = 0>
static void move_to_pointlike(Range & out_range, PointLike & pt)
{
pt = range::front(out_range);
}
template <typename Range, typename PointLike, util::enable_if_multi_point_t<PointLike, int> = 0>
static void move_to_pointlike(Range & out_range, PointLike & mpt)
{
range::push_back(mpt, std::move(range::front(out_range)));
}
template
<
typename Geometry, typename OutputGeometry_,
util::enable_if_geometry_collection_t<OutputGeometry_, int> = 0
>
static void move_to_out(Geometry & g, OutputGeometry_ & out)
{
range::emplace_back(out, std::move(g));
}
template
<
typename Geometry, typename OutputGeometry_,
util::enable_if_dynamic_geometry_t<OutputGeometry_, int> = 0
>
static void move_to_out(Geometry & g, OutputGeometry_ & out)
{
out = std::move(g);
}
};
template <typename OutputGeometry>
struct convex_hull_out<OutputGeometry, dynamic_geometry_tag>
: convex_hull_out<OutputGeometry, geometry_collection_tag>
{};
// For backward compatibility
template <typename OutputGeometry>
struct convex_hull_out<OutputGeometry, linestring_tag>
: convex_hull_out<OutputGeometry, ring_tag>
{};
@@ -158,66 +493,42 @@ struct convex_hull_insert
namespace resolve_strategy {
template <typename Strategies>
struct convex_hull
{
template <typename Geometry, typename OutputGeometry, typename Strategy>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
Strategy const& strategy)
{
//BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
dispatch::convex_hull<Geometry>::apply(geometry, out, strategy);
}
template <typename Geometry, typename OutputGeometry>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
default_strategy)
Strategies const& strategies)
{
typedef typename strategies::convex_hull::services::default_strategy
<
Geometry
>::type strategy_type;
apply(geometry, out, strategy_type());
dispatch::convex_hull_out<OutputGeometry>::apply(geometry, out, strategies);
}
};
struct convex_hull_insert
template <>
struct convex_hull<default_strategy>
{
template <typename Geometry, typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry const& geometry,
OutputIterator& out,
Strategy const& strategy)
template <typename Geometry, typename OutputGeometry>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
default_strategy const&)
{
//BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
return dispatch::convex_hull_insert<
geometry::point_order<Geometry>::value,
geometry::closure<Geometry>::value
>::apply(geometry, out, strategy);
}
template <typename Geometry, typename OutputIterator>
static inline OutputIterator apply(Geometry const& geometry,
OutputIterator& out,
default_strategy)
{
typedef typename strategies::convex_hull::services::default_strategy
using strategy_type = typename detail::convex_hull::default_strategy
<
Geometry
>::type strategy_type;
>::type;
return apply(geometry, out, strategy_type());
dispatch::convex_hull_out<OutputGeometry>::apply(geometry, out, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
namespace resolve_dynamic {
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct convex_hull
{
template <typename OutputGeometry, typename Strategy>
@@ -230,88 +541,27 @@ struct convex_hull
OutputGeometry
>();
resolve_strategy::convex_hull::apply(geometry, out, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct convex_hull<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename OutputGeometry, typename Strategy>
struct visitor: boost::static_visitor<void>
{
OutputGeometry& m_out;
Strategy const& m_strategy;
visitor(OutputGeometry& out, Strategy const& strategy)
: m_out(out), m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry) const
{
convex_hull<Geometry>::apply(geometry, m_out, m_strategy);
}
};
template <typename OutputGeometry, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
OutputGeometry& out,
Strategy const& strategy)
{
boost::apply_visitor(visitor<OutputGeometry, Strategy>(out, strategy),
geometry);
resolve_strategy::convex_hull<Strategy>::apply(geometry, out, strategy);
}
};
template <typename Geometry>
struct convex_hull_insert
struct convex_hull<Geometry, dynamic_geometry_tag>
{
template <typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry const& geometry,
OutputIterator& out,
Strategy const& strategy)
template <typename OutputGeometry, typename Strategy>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
Strategy const& strategy)
{
// Concept: output point type = point type of input geometry
concepts::check<Geometry const>();
concepts::check<typename point_type<Geometry>::type>();
return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct convex_hull_insert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename OutputIterator, typename Strategy>
struct visitor: boost::static_visitor<OutputIterator>
{
OutputIterator& m_out;
Strategy const& m_strategy;
visitor(OutputIterator& out, Strategy const& strategy)
: m_out(out), m_strategy(strategy)
{}
template <typename Geometry>
OutputIterator operator()(Geometry const& geometry) const
traits::visit<Geometry>::apply([&](auto const& g)
{
return convex_hull_insert<Geometry>::apply(geometry, m_out, m_strategy);
}
};
template <typename OutputIterator, typename Strategy>
static inline OutputIterator
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
OutputIterator& out,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<OutputIterator, Strategy>(out, strategy), geometry);
convex_hull<util::remove_cref_t<decltype(g)>>::apply(g, out, strategy);
}, geometry);
}
};
} // namespace resolve_variant
} // namespace resolve_dynamic
/*!
@@ -330,8 +580,7 @@ struct convex_hull_insert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
\qbk{[include reference/algorithms/convex_hull.qbk]}
*/
template<typename Geometry, typename OutputGeometry, typename Strategy>
inline void convex_hull(Geometry const& geometry,
OutputGeometry& out, Strategy const& strategy)
inline void convex_hull(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy)
{
if (geometry::is_empty(geometry))
{
@@ -339,7 +588,7 @@ inline void convex_hull(Geometry const& geometry,
return;
}
resolve_variant::convex_hull<Geometry>::apply(geometry, out, strategy);
resolve_dynamic::convex_hull<Geometry>::apply(geometry, out, strategy);
}
@@ -355,52 +604,11 @@ inline void convex_hull(Geometry const& geometry,
\qbk{[include reference/algorithms/convex_hull.qbk]}
*/
template<typename Geometry, typename OutputGeometry>
inline void convex_hull(Geometry const& geometry,
OutputGeometry& hull)
inline void convex_hull(Geometry const& geometry, OutputGeometry& hull)
{
geometry::convex_hull(geometry, hull, default_strategy());
}
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace convex_hull
{
template<typename Geometry, typename OutputIterator, typename Strategy>
inline OutputIterator convex_hull_insert(Geometry const& geometry,
OutputIterator out, Strategy const& strategy)
{
return resolve_variant::convex_hull_insert
<
Geometry
>::apply(geometry, out, strategy);
}
/*!
\brief Calculate the convex hull of a geometry, output-iterator version
\ingroup convex_hull
\tparam Geometry the input geometry type
\tparam OutputIterator: an output-iterator
\param geometry the geometry to calculate convex hull from
\param out an output iterator outputing points of the convex hull
\note This overloaded version outputs to an output iterator.
In this case, nothing is known about its point-type or
about its clockwise order. Therefore, the input point-type
and order are copied
*/
template<typename Geometry, typename OutputIterator>
inline OutputIterator convex_hull_insert(Geometry const& geometry,
OutputIterator out)
{
return convex_hull_insert(geometry, out, default_strategy());
}
}} // namespace detail::convex_hull
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry

View File

@@ -79,7 +79,8 @@ struct direction_code_impl<cartesian_tag>
}
calc_t const sv = arithmetic::side_value(line, point);
return sv == 0 ? 0 : sv > 0 ? 1 : -1;
static calc_t const zero = 0;
return sv == zero ? 0 : sv > zero ? 1 : -1;
}
};

View File

@@ -0,0 +1,237 @@
// 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_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_COLLECTION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_COLLECTION_HPP
#include <vector>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/distance_result.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace distance
{
template <typename Geometry, typename GeometryCollection, typename Strategies>
inline auto geometry_to_collection(Geometry const& geometry,
GeometryCollection const& collection,
Strategies const& strategies)
{
using result_t = typename geometry::distance_result<Geometry, GeometryCollection, Strategies>::type;
result_t result = 0;
bool is_first = true;
detail::visit_breadth_first([&](auto const& g)
{
result_t r = dispatch::distance
<
Geometry, util::remove_cref_t<decltype(g)>, Strategies
>::apply(geometry, g, strategies);
if (is_first)
{
result = r;
is_first = false;
}
else if (r < result)
{
result = r;
}
return result > result_t(0);
}, collection);
return result;
}
template <typename GeometryCollection1, typename GeometryCollection2, typename Strategies>
inline auto collection_to_collection(GeometryCollection1 const& collection1,
GeometryCollection2 const& collection2,
Strategies const& strategies)
{
using result_t = typename geometry::distance_result<GeometryCollection1, GeometryCollection2, Strategies>::type;
using point1_t = typename geometry::point_type<GeometryCollection1>::type;
using box1_t = model::box<point1_t>;
using point2_t = typename geometry::point_type<GeometryCollection2>::type;
using box2_t = model::box<point2_t>;
using rtree_value_t = std::pair<box1_t, typename boost::range_iterator<GeometryCollection1 const>::type>;
using rtree_params_t = index::parameters<index::rstar<4>, Strategies>;
using rtree_t = index::rtree<rtree_value_t, rtree_params_t>;
rtree_params_t rtree_params(index::rstar<4>(), strategies);
rtree_t rtree(rtree_params);
// Build rtree of boxes and iterators of elements of GC1
// TODO: replace this with visit_breadth_first_iterator to avoid creating an unnecessary container?
{
std::vector<rtree_value_t> values;
visit_breadth_first_impl<true>::apply([&](auto & g1, auto it)
{
box1_t b1 = geometry::return_envelope<box1_t>(g1, strategies);
geometry::detail::expand_by_epsilon(b1);
values.emplace_back(b1, it);
return true;
}, collection1);
rtree_t rt(values.begin(), values.end(), rtree_params);
rtree = std::move(rt);
}
result_t const zero = 0;
auto const rtree_qend = rtree.qend();
result_t result = 0;
bool is_first = true;
visit_breadth_first([&](auto const& g2)
{
box2_t b2 = geometry::return_envelope<box2_t>(g2, strategies);
geometry::detail::expand_by_epsilon(b2);
for (auto it = rtree.qbegin(index::nearest(b2, rtree.size())) ; it != rtree_qend ; ++it)
{
// If the distance between boxes is greater than or equal to previously found
// distance between geometries then stop processing the current b2 because no
// closer b1 will be found
if (! is_first)
{
result_t const bd = dispatch::distance
<
box1_t, box2_t, Strategies
>::apply(it->first, b2, strategies);
if (bd >= result)
{
break;
}
}
// Boxes are closer than the previously found distance (or it's the first time),
// calculate the new distance between geometries and check if it's closer (or assign it).
traits::iter_visit<GeometryCollection1>::apply([&](auto const& g1)
{
result_t const d = dispatch::distance
<
util::remove_cref_t<decltype(g1)>, util::remove_cref_t<decltype(g2)>,
Strategies
>::apply(g1, g2, strategies);
if (is_first)
{
result = d;
is_first = false;
}
else if (d < result)
{
result = d;
}
}, it->second);
// The smallest possible distance found, end searching.
if (! is_first && result <= zero)
{
return false;
}
}
// Just in case
return is_first || result > zero;
}, collection2);
return result;
}
}} // namespace detail::distance
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry, typename GeometryCollection, typename Strategies, typename Tag1
>
struct distance
<
Geometry, GeometryCollection, Strategies,
Tag1, geometry_collection_tag, void, false
>
{
static inline auto apply(Geometry const& geometry,
GeometryCollection const& collection,
Strategies const& strategies)
{
assert_dimension_equal<Geometry, GeometryCollection>();
return detail::distance::geometry_to_collection(geometry, collection, strategies);
}
};
template
<
typename GeometryCollection, typename Geometry, typename Strategies, typename Tag2
>
struct distance
<
GeometryCollection, Geometry, Strategies,
geometry_collection_tag, Tag2, void, false
>
{
static inline auto apply(GeometryCollection const& collection,
Geometry const& geometry,
Strategies const& strategies)
{
assert_dimension_equal<Geometry, GeometryCollection>();
return detail::distance::geometry_to_collection(geometry, collection, strategies);
}
};
template
<
typename GeometryCollection1, typename GeometryCollection2, typename Strategies
>
struct distance
<
GeometryCollection1, GeometryCollection2, Strategies,
geometry_collection_tag, geometry_collection_tag, void, false
>
{
static inline auto apply(GeometryCollection1 const& collection1,
GeometryCollection2 const& collection2,
Strategies const& strategies)
{
assert_dimension_equal<GeometryCollection1, GeometryCollection2>();
// Build the rtree for the smaller GC (ignoring recursive GCs)
return boost::size(collection1) <= boost::size(collection2)
? detail::distance::collection_to_collection(collection1, collection2, strategies)
: detail::distance::collection_to_collection(collection2, collection1, strategies);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP

View File

@@ -7,9 +7,9 @@
// 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 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.
@@ -27,6 +27,7 @@
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_to_box.hpp>
#include <boost/geometry/algorithms/detail/distance/geometry_collection.hpp>
#include <boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_segment.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>

View File

@@ -8,7 +8,6 @@
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -28,6 +27,7 @@
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -92,10 +92,9 @@ template
struct distance
{
template <typename Geometry1, typename Geometry2>
static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
static inline auto apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return dispatch::distance
<
@@ -123,11 +122,9 @@ struct distance<Strategy, false>
typename Geometry1, typename Geometry2, typename S,
std::enable_if_t<is_strategy_converter_specialized<S>::value, int> = 0
>
static inline
typename distance_result<Geometry1, Geometry2, S>::type
apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
S const& strategy)
static inline auto apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
S const& strategy)
{
typedef strategies::distance::services::strategy_converter<Strategy> converter;
typedef decltype(converter::get(strategy)) strategy_type;
@@ -143,11 +140,9 @@ struct distance<Strategy, false>
typename Geometry1, typename Geometry2, typename S,
std::enable_if_t<! is_strategy_converter_specialized<S>::value, int> = 0
>
static inline
typename distance_result<Geometry1, Geometry2, S>::type
apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
S const& strategy)
static inline auto apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
S const& strategy)
{
typedef strategies::distance::services::custom_strategy_converter
<
@@ -166,11 +161,9 @@ template <>
struct distance<default_strategy, false>
{
template <typename Geometry1, typename Geometry2>
static inline
typename distance_result<Geometry1, Geometry2, default_strategy>::type
apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
static inline auto apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategies::distance::services::default_strategy
<
@@ -187,18 +180,22 @@ struct distance<default_strategy, false>
} // namespace resolve_strategy
namespace resolve_variant
namespace resolve_dynamic
{
template <typename Geometry1, typename Geometry2>
template
<
typename Geometry1, typename Geometry2,
typename Tag1 = typename geometry::tag<Geometry1>::type,
typename Tag2 = typename geometry::tag<Geometry2>::type
>
struct distance
{
template <typename Strategy>
static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
static inline auto apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_strategy::distance
<
@@ -208,174 +205,72 @@ struct distance
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
struct distance<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
struct visitor: static_visitor
<
typename distance_result
<
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
Geometry2,
Strategy
>::type
>
static inline auto apply(DynamicGeometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2,
Strategy const& strategy)
: m_geometry2(geometry2),
m_strategy(strategy)
{}
template <typename Geometry1>
typename distance_result<Geometry1, Geometry2, Strategy>::type
operator()(Geometry1 const& geometry1) const
using result_t = typename geometry::distance_result<DynamicGeometry1, Geometry2, Strategy>::type;
result_t result = 0;
traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
return distance
<
Geometry1,
Geometry2
>::template apply
<
Strategy
>(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline typename distance_result
<
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
Geometry2,
Strategy
>::type
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
result = resolve_strategy::distance
<
Strategy
>::apply(g1, geometry2, strategy);
}, geometry1);
return result;
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
struct distance<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
struct visitor: static_visitor
<
typename distance_result
<
Geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
Strategy
>::type
>
static inline auto apply(Geometry1 const& geometry1,
DynamicGeometry2 const& geometry2,
Strategy const& strategy)
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1,
Strategy const& strategy)
: m_geometry1(geometry1),
m_strategy(strategy)
{}
template <typename Geometry2>
typename distance_result<Geometry1, Geometry2, Strategy>::type
operator()(Geometry2 const& geometry2) const
using result_t = typename geometry::distance_result<Geometry1, DynamicGeometry2, Strategy>::type;
result_t result = 0;
traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
return distance
<
Geometry1,
Geometry2
>::template apply
<
Strategy
>(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline typename distance_result
<
Geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
Strategy
>::type
apply(
Geometry1 const& geometry1,
const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
result = resolve_strategy::distance
<
Strategy
>::apply(geometry1, g2, strategy);
}, geometry2);
return result;
}
};
template
<
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct distance
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
template <typename DynamicGeometry1, typename DynamicGeometry2>
struct distance<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
struct visitor: static_visitor
<
typename distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
Strategy
>::type
>
static inline auto apply(DynamicGeometry1 const& geometry1,
DynamicGeometry2 const& geometry2,
Strategy const& strategy)
{
Strategy const& m_strategy;
visitor(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
typename distance_result<Geometry1, Geometry2, Strategy>::type
operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const
using result_t = typename geometry::distance_result<DynamicGeometry1, DynamicGeometry2, Strategy>::type;
result_t result = 0;
traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
return distance
<
Geometry1,
Geometry2
>::template apply
<
Strategy
>(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline typename distance_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
Strategy
>::type
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
result = resolve_strategy::distance
<
Strategy
>::apply(g1, g2, strategy);
}, geometry1, geometry2);
return result;
}
};
} // namespace resolve_variant
} // namespace resolve_dynamic
/*!
@@ -415,10 +310,9 @@ for distance, it is probably so that there is no specialization
for return_type<...> for your strategy.
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline typename distance_result<Geometry1, Geometry2, Strategy>::type
distance(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
inline auto distance(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -426,7 +320,7 @@ distance(Geometry1 const& geometry1,
detail::throw_on_empty_input(geometry1);
detail::throw_on_empty_input(geometry2);
return resolve_variant::distance
return resolve_dynamic::distance
<
Geometry1,
Geometry2
@@ -448,13 +342,9 @@ distance(Geometry1 const& geometry1,
\qbk{[include reference/algorithms/distance.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline typename default_distance_result<Geometry1, Geometry2>::type
distance(Geometry1 const& geometry1,
Geometry2 const& geometry2)
inline auto distance(Geometry1 const& geometry1,
Geometry2 const& geometry2)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return geometry::distance(geometry1, geometry2, default_strategy());
}

View File

@@ -0,0 +1,63 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_GEOMETRY_COLLECTION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_GEOMETRY_COLLECTION_HPP
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/core/tags.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Collection>
struct envelope<Collection, geometry_collection_tag>
{
template <typename Geometry, typename Box, typename Strategy>
static inline void apply(Geometry const& geometry,
Box& mbr,
Strategy const& strategy)
{
using strategy_t = decltype(strategy.envelope(geometry, mbr));
using state_t = typename strategy_t::template multi_state<Box>;
state_t state;
detail::visit_breadth_first([&](auto const& g)
{
if (! geometry::is_empty(g))
{
Box b;
envelope<util::remove_cref_t<decltype(g)>>::apply(g, b, strategy);
state.apply(b);
}
return true;
}, geometry);
state.result(mbr);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_GEOMETRY_COLLECTION_HPP

View File

@@ -6,9 +6,9 @@
// 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.
@@ -28,6 +28,7 @@
#include <boost/geometry/algorithms/detail/envelope/areal.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
#include <boost/geometry/algorithms/detail/envelope/geometry_collection.hpp>
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>
#include <boost/geometry/algorithms/detail/envelope/point.hpp>

View File

@@ -22,16 +22,14 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
@@ -39,6 +37,7 @@
#include <boost/geometry/strategies/envelope/services.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
@@ -98,10 +97,10 @@ struct envelope<default_strategy, false>
} // namespace resolve_strategy
namespace resolve_variant
namespace resolve_dynamic
{
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct envelope
{
template <typename Box, typename Strategy>
@@ -117,38 +116,22 @@ struct envelope
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct envelope<Geometry, dynamic_geometry_tag>
{
template <typename Box, typename Strategy>
struct visitor: boost::static_visitor<void>
static inline void apply(Geometry const& geometry,
Box& box,
Strategy const& strategy)
{
Box& m_box;
Strategy const& m_strategy;
visitor(Box& box, Strategy const& strategy)
: m_box(box)
, m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry) const
traits::visit<Geometry>::apply([&](auto const& g)
{
envelope<Geometry>::apply(geometry, m_box, m_strategy);
}
};
template <typename Box, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Box& box,
Strategy const& strategy)
{
boost::apply_visitor(visitor<Box, Strategy>(box, strategy), geometry);
envelope<util::remove_cref_t<decltype(g)>>::apply(g, box, strategy);
}, geometry);
}
};
} // namespace resolve_variant
} // namespace resolve_dynamic
/*!
@@ -172,7 +155,7 @@ struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template<typename Geometry, typename Box, typename Strategy>
inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strategy)
{
resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, strategy);
}
/*!
@@ -193,7 +176,7 @@ inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strateg
template<typename Geometry, typename Box>
inline void envelope(Geometry const& geometry, Box& mbr)
{
resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, default_strategy());
}
@@ -219,7 +202,7 @@ template<typename Box, typename Geometry, typename Strategy>
inline Box return_envelope(Geometry const& geometry, Strategy const& strategy)
{
Box mbr;
resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, strategy);
return mbr;
}
@@ -242,7 +225,7 @@ template<typename Box, typename Geometry>
inline Box return_envelope(Geometry const& geometry)
{
Box mbr;
resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, default_strategy());
return mbr;
}

View File

@@ -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

View File

@@ -22,22 +22,23 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/expand/services.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
{
@@ -97,10 +98,10 @@ struct expand<default_strategy, false>
} //namespace resolve_strategy
namespace resolve_variant
namespace resolve_dynamic
{
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct expand
{
template <typename Box, typename Strategy>
@@ -116,68 +117,24 @@ struct expand
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct expand<Geometry, dynamic_geometry_tag>
{
template <typename Box, typename Strategy>
struct visitor: boost::static_visitor<void>
{
Box& m_box;
Strategy const& m_strategy;
visitor(Box& box, Strategy const& strategy)
: m_box(box)
, m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry) const
{
return expand<Geometry>::apply(m_box, geometry, m_strategy);
}
};
template <class Box, typename Strategy>
static inline void
apply(Box& box,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Strategy const& strategy)
static inline void apply(Box& box,
Geometry const& geometry,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Box, Strategy>(box, strategy),
geometry);
traits::visit<Geometry>::apply([&](auto const& g)
{
expand<util::remove_cref_t<decltype(g)>>::apply(box, g, strategy);
}, geometry);
}
};
} // namespace resolve_variant
} // namespace resolve_dynamic
/***
*!
\brief Expands a box using the extend (envelope) of another geometry (box, point)
\ingroup expand
\tparam Box type of the box
\tparam Geometry of second geometry, to be expanded with the box
\param box box to expand another geometry with, might be changed
\param geometry other geometry
\param strategy_less
\param strategy_greater
\note Strategy is currently ignored
*
template
<
typename Box, typename Geometry,
typename StrategyLess, typename StrategyGreater
>
inline void expand(Box& box, Geometry const& geometry,
StrategyLess const& strategy_less,
StrategyGreater const& strategy_greater)
{
concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();
dispatch::expand<Box, Geometry>::apply(box, geometry);
}
***/
/*!
\brief Expands (with strategy)
\ingroup expand
@@ -195,7 +152,7 @@ will be added to the box
template <typename Box, typename Geometry, typename Strategy>
inline void expand(Box& box, Geometry const& geometry, Strategy const& strategy)
{
resolve_variant::expand<Geometry>::apply(box, geometry, strategy);
resolve_dynamic::expand<Geometry>::apply(box, geometry, strategy);
}
/*!
@@ -213,7 +170,7 @@ added to the box
template <typename Box, typename Geometry>
inline void expand(Box& box, Geometry const& geometry)
{
resolve_variant::expand<Geometry>::apply(box, geometry, default_strategy());
resolve_dynamic::expand<Geometry>::apply(box, geometry, default_strategy());
}
}} // namespace boost::geometry

View File

@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2020, Oracle and/or its affiliates.
// Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -54,11 +54,6 @@ private:
CSTag
>::type rescale_policy_type;
typedef detail::overlay::get_turn_info
<
detail::overlay::assign_null_policy
> turn_policy;
public:
typedef detail::overlay::turn_info
<
@@ -88,12 +83,11 @@ public:
> interrupt_policy;
// Calculate self-turns, skipping adjacent segments
detail::self_get_turn_points::self_turns<false, turn_policy>(geometry,
strategy,
robust_policy,
turns,
interrupt_policy,
0, true);
detail::self_get_turn_points::self_turns
<
false, detail::overlay::assign_null_policy
>(geometry, strategy, robust_policy, turns, interrupt_policy,
0, true);
if (interrupt_policy.has_intersections)
{

View File

@@ -1,6 +1,6 @@
// Boost.Geometry
// Copyright (c) 2014-2020, Oracle and/or its affiliates.
// Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -14,12 +14,11 @@
#include <sstream>
#include <string>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/policies/is_valid/default_policy.hpp>
#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>
@@ -90,10 +89,10 @@ struct is_valid<default_strategy, false>
} // namespace resolve_strategy
namespace resolve_variant
namespace resolve_dynamic
{
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct is_valid
{
template <typename VisitPolicy, typename Strategy>
@@ -110,39 +109,42 @@ struct is_valid
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct is_valid<Geometry, dynamic_geometry_tag>
{
template <typename VisitPolicy, typename Strategy>
struct visitor : boost::static_visitor<bool>
static inline bool apply(Geometry const& geometry,
VisitPolicy& policy_visitor,
Strategy const& strategy)
{
visitor(VisitPolicy& policy, Strategy const& strategy)
: m_policy(policy)
, m_strategy(strategy)
{}
template <typename Geometry>
bool operator()(Geometry const& geometry) const
bool result = true;
traits::visit<Geometry>::apply([&](auto const& g)
{
return is_valid<Geometry>::apply(geometry, m_policy, m_strategy);
}
VisitPolicy& m_policy;
Strategy const& m_strategy;
};
template <typename VisitPolicy, typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
VisitPolicy& policy_visitor,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<VisitPolicy, Strategy>(policy_visitor, strategy),
geometry);
result = is_valid<util::remove_cref_t<decltype(g)>>::apply(g, policy_visitor, strategy);
}, geometry);
return result;
}
};
} // namespace resolve_variant
template <typename Geometry>
struct is_valid<Geometry, geometry_collection_tag>
{
template <typename VisitPolicy, typename Strategy>
static inline bool apply(Geometry const& geometry,
VisitPolicy& policy_visitor,
Strategy const& strategy)
{
bool result = true;
detail::visit_breadth_first([&](auto const& g)
{
result = is_valid<util::remove_cref_t<decltype(g)>>::apply(g, policy_visitor, strategy);
return result;
}, geometry);
return result;
}
};
} // namespace resolve_dynamic
// Undocumented for now
@@ -151,7 +153,7 @@ inline bool is_valid(Geometry const& geometry,
VisitPolicy& visitor,
Strategy const& strategy)
{
return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
return resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
}
@@ -175,7 +177,7 @@ template <typename Geometry, typename Strategy>
inline bool is_valid(Geometry const& geometry, Strategy const& strategy)
{
is_valid_default_policy<> visitor;
return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
return resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
}
/*!
@@ -220,7 +222,7 @@ template <typename Geometry, typename Strategy>
inline bool is_valid(Geometry const& geometry, validity_failure_type& failure, Strategy const& strategy)
{
failure_type_policy<> visitor;
bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
bool result = resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
failure = visitor.failure();
return result;
}
@@ -271,7 +273,7 @@ inline bool is_valid(Geometry const& geometry, std::string& message, Strategy co
{
std::ostringstream stream;
failing_reason_policy<> visitor(stream);
bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
bool result = resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
message = stream.str();
return result;
}

View File

@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-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
@@ -32,27 +32,24 @@ namespace detail
{
template <typename MultiGeometry, typename Policy>
template <typename Policy>
struct multi_modify
{
template <typename MultiGeometry>
static inline void apply(MultiGeometry& multi)
{
typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
for (iterator_type it = boost::begin(multi);
it != boost::end(multi);
++it)
auto const end = boost::end(multi);
for (auto it = boost::begin(multi); it != end; ++it)
{
Policy::apply(*it);
}
}
template <typename Strategy>
template <typename MultiGeometry, typename Strategy>
static inline void apply(MultiGeometry& multi, Strategy const& strategy)
{
typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
for (iterator_type it = boost::begin(multi);
it != boost::end(multi);
++it)
auto const end = boost::end(multi);
for (auto it = boost::begin(multi); it != end; ++it)
{
Policy::apply(*it, strategy);
}

View File

@@ -23,7 +23,7 @@ namespace detail { namespace overlay
template <typename Point1, typename Point2, typename E>
inline bool approximately_equals(Point1 const& a, Point2 const& b,
E const& multiplier)
E const& epsilon_multiplier)
{
using coor_t = typename select_coordinate_type<Point1, Point2>::type;
using calc_t = typename geometry::select_most_precise<coor_t, E>::type;
@@ -34,7 +34,7 @@ inline bool approximately_equals(Point1 const& a, Point2 const& b,
calc_t const& b1 = geometry::get<1>(b);
math::detail::equals_factor_policy<calc_t> policy(a0, b0, a1, b1);
policy.factor *= multiplier;
policy.multiply_epsilon(epsilon_multiplier);
return math::detail::equals_by_policy(a0, b0, policy)
&& math::detail::equals_by_policy(a1, b1, policy);

View File

@@ -3,9 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017-2020.
// This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-2020 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,
@@ -353,21 +352,20 @@ inline typename geometry::coordinate_type<Point1>::type
template <typename Turns>
inline void calculate_remaining_distance(Turns& turns)
{
typedef typename boost::range_value<Turns>::type turn_type;
typedef typename turn_type::turn_operation_type op_type;
using turn_type = typename boost::range_value<Turns>::type;
using op_type = typename turn_type::turn_operation_type;
for (typename boost::range_iterator<Turns>::type
it = boost::begin(turns);
it != boost::end(turns);
++it)
typename op_type::comparable_distance_type const zero_distance = 0;
for (auto it = boost::begin(turns); it != boost::end(turns); ++it)
{
turn_type& turn = *it;
op_type& op0 = turn.operations[0];
op_type& op1 = turn.operations[1];
if (op0.remaining_distance != 0
|| op1.remaining_distance != 0)
if (op0.remaining_distance != zero_distance
|| op1.remaining_distance != zero_distance)
{
continue;
}

View File

@@ -39,7 +39,8 @@ struct sweep_equal_policy
static inline bool equals(P const& p1, P const& p2)
{
// Points within a kilo epsilon are considered as equal
return approximately_equals(p1, p2, 1000.0);
using coor_t = typename coordinate_type<P>::type;
return approximately_equals(p1, p2, coor_t(1000));
}
template <typename T>
@@ -47,7 +48,8 @@ struct sweep_equal_policy
{
// This threshold is an arbitrary value
// as long as it is than the used kilo-epsilon
return value > 1.0e-3;
T const limit = T(1) / T(1000);
return value > limit;
}
};

View File

@@ -128,7 +128,8 @@ struct base_turn_handler
}
auto const dm = get_distance_measure(range_p.at(range_index), range_p.at(range_index + 1), range_q.at(point_index));
return dm.measure == 0 ? 0 : dm.measure > 0 ? 1 : -1;
static decltype(dm.measure) const zero = 0;
return dm.measure == zero ? 0 : dm.measure > zero ? 1 : -1;
}
template
@@ -241,33 +242,45 @@ struct base_turn_handler
BOOST_GEOMETRY_ASSERT(index_q > 0 && index_q <= 2);
#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
ti.operations[IndexP].remaining_distance = distance_measure(ti.point, range_p.at(index_p));
ti.operations[IndexQ].remaining_distance = distance_measure(ti.point, range_q.at(index_q));
bool const p_in_range = index_p < range_p.size();
bool const q_in_range = index_q < range_q.size();
ti.operations[IndexP].remaining_distance
= p_in_range
? distance_measure(ti.point, range_p.at(index_p))
: 0;
ti.operations[IndexQ].remaining_distance
= q_in_range
? distance_measure(ti.point, range_q.at(index_q))
: 0;
// pk/q2 is considered as collinear, but there might be
// a tiny measurable difference. If so, use that.
// Calculate pk // qj-qk
bool const p_closer =
ti.operations[IndexP].remaining_distance
< ti.operations[IndexQ].remaining_distance;
auto const dm
if (p_in_range && q_in_range)
{
// pk/q2 is considered as collinear, but there might be
// a tiny measurable difference. If so, use that.
// Calculate pk // qj-qk
bool const p_closer
= ti.operations[IndexP].remaining_distance
< ti.operations[IndexQ].remaining_distance;
auto const dm
= p_closer
? get_distance_measure(range_q.at(index_q - 1),
range_q.at(index_q), range_p.at(index_p))
: get_distance_measure(range_p.at(index_p - 1),
range_p.at(index_p), range_q.at(index_q));
if (! dm.is_zero())
{
// Not truely collinear, distinguish for union/intersection
// If p goes left (positive), take that for a union
bool const p_left = p_closer ? dm.is_positive() : dm.is_negative();
if (! dm.is_zero())
{
// Not truely collinear, distinguish for union/intersection
// If p goes left (positive), take that for a union
bool const p_left
= p_closer ? dm.is_positive() : dm.is_negative();
ti.operations[IndexP].operation = p_left
? operation_union : operation_intersection;
ti.operations[IndexQ].operation = p_left
? operation_intersection : operation_union;
return;
ti.operations[IndexP].operation = p_left
? operation_union : operation_intersection;
ti.operations[IndexQ].operation = p_left
? operation_intersection : operation_union;
return;
}
}
#endif

View File

@@ -26,8 +26,7 @@ struct is_self_turn_check
template <typename Turn>
static inline bool apply(Turn const& turn)
{
return turn.operations[0].seg_id.source_index
== turn.operations[1].seg_id.source_index;
return turn.is_self();
}
};

View File

@@ -3,9 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-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,
@@ -33,6 +32,9 @@
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/util/condition.hpp>
@@ -271,6 +273,85 @@ struct self_get_turn_points
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
template
<
bool Reverse,
typename AssignPolicy,
typename Strategies,
bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
>
struct self_get_turn_points
{
template
<
typename Geometry,
typename RobustPolicy,
typename Turns,
typename InterruptPolicy
>
static inline void apply(Geometry const& geometry,
Strategies const& strategies,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy,
int source_index,
bool skip_adjacent)
{
using turn_policy = detail::overlay::get_turn_info<AssignPolicy>;
dispatch::self_get_turn_points
<
Reverse,
typename tag<Geometry>::type,
Geometry,
turn_policy
>::apply(geometry, strategies, robust_policy, turns, interrupt_policy,
source_index, skip_adjacent);
}
};
template <bool Reverse, typename AssignPolicy, typename Strategy>
struct self_get_turn_points<Reverse, AssignPolicy, Strategy, false>
{
template
<
typename Geometry,
typename RobustPolicy,
typename Turns,
typename InterruptPolicy
>
static inline void apply(Geometry const& geometry,
Strategy const& strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy,
int source_index,
bool skip_adjacent)
{
using strategies::relate::services::strategy_converter;
self_get_turn_points
<
Reverse,
AssignPolicy,
decltype(strategy_converter<Strategy>::get(strategy))
>::apply(geometry,
strategy_converter<Strategy>::get(strategy),
robust_policy,
turns,
interrupt_policy,
source_index,
skip_adjacent);
}
};
} // namespace resolve_strategy
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace self_get_turn_points
{
@@ -282,13 +363,13 @@ template
bool Reverse,
typename AssignPolicy,
typename Geometry,
typename IntersectionStrategy,
typename Strategy,
typename RobustPolicy,
typename Turns,
typename InterruptPolicy
>
inline void self_turns(Geometry const& geometry,
IntersectionStrategy const& strategy,
Strategy const& strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy,
@@ -297,14 +378,9 @@ inline void self_turns(Geometry const& geometry,
{
concepts::check<Geometry const>();
typedef detail::overlay::get_turn_info<detail::overlay::assign_null_policy> turn_policy;
dispatch::self_get_turn_points
resolve_strategy::self_get_turn_points
<
Reverse,
typename tag<Geometry>::type,
Geometry,
turn_policy
Reverse, AssignPolicy, Strategy
>::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
source_index, skip_adjacent);
}
@@ -351,12 +427,11 @@ inline void self_turns(Geometry const& geometry,
geometry::point_order<Geometry>::value
>::value;
detail::self_get_turn_points::self_turns
resolve_strategy::self_get_turn_points
<
reverse,
AssignPolicy
>(geometry, strategy, robust_policy, turns, interrupt_policy,
source_index, skip_adjacent);
reverse, AssignPolicy, Strategy
>::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
source_index, skip_adjacent);
}

View File

@@ -316,7 +316,15 @@ public :
// then take a point (or more) further back.
// The limit of offset avoids theoretical infinite loops.
// In practice it currently walks max 1 point back in all cases.
double const tolerance = 1.0e9;
// Use the coordinate type, but if it is too small (e.g. std::int16), use a double
using ct_type = typename geometry::select_most_precise
<
typename geometry::coordinate_type<Point>::type,
double
>::type;
ct_type const tolerance = 1000000000;
int offset = 0;
while (approximately_equals(point_from, turn.point, tolerance)
&& offset > -10)

View File

@@ -621,31 +621,32 @@ public :
return m_turns[rp.turn_index].operations[rp.operation_index];
}
inline sort_by_side::rank_type select_rank(sbs_type const& sbs,
bool skip_isolated) const
inline sort_by_side::rank_type select_rank(sbs_type const& sbs) const
{
static bool const is_intersection
= target_operation == operation_intersection;
// Take the first outgoing rank corresponding to incoming region,
// or take another region if it is not isolated
turn_operation_type const& incoming_op
= operation_from_rank(sbs.m_ranked_points.front());
auto const& in_op = operation_from_rank(sbs.m_ranked_points.front());
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
{
typename sbs_type::rp const& rp = sbs.m_ranked_points[i];
auto const& rp = sbs.m_ranked_points[i];
if (rp.rank == 0 || rp.direction == sort_by_side::dir_from)
{
continue;
}
turn_operation_type const& op = operation_from_rank(rp);
auto const& out_op = operation_from_rank(rp);
if (op.operation != target_operation
&& op.operation != operation_continue)
if (out_op.operation != target_operation
&& out_op.operation != operation_continue)
{
continue;
}
if (op.enriched.region_id == incoming_op.enriched.region_id
|| (skip_isolated && ! op.enriched.isolated))
if (in_op.enriched.region_id == out_op.enriched.region_id
|| (is_intersection && ! out_op.enriched.isolated))
{
// Region corresponds to incoming region, or (for intersection)
// there is a non-isolated other region which should be taken
@@ -660,7 +661,7 @@ public :
int& op_index, sbs_type const& sbs,
signed_size_type start_turn_index, int start_op_index) const
{
sort_by_side::rank_type const selected_rank = select_rank(sbs, false);
sort_by_side::rank_type const selected_rank = select_rank(sbs);
int current_priority = 0;
for (std::size_t i = 1; i < sbs.m_ranked_points.size(); i++)
@@ -688,49 +689,59 @@ public :
inline bool analyze_cluster_intersection(signed_size_type& turn_index,
int& op_index, sbs_type const& sbs) const
{
sort_by_side::rank_type const selected_rank = select_rank(sbs, true);
// Select the rank based on regions and isolation
sort_by_side::rank_type const selected_rank = select_rank(sbs);
if (selected_rank > 0)
if (selected_rank <= 0)
{
typename turn_operation_type::comparable_distance_type
min_remaining_distance = 0;
return false;
}
std::size_t selected_index = sbs.m_ranked_points.size();
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
// From these ranks, select the index: the first, or the one with
// the smallest remaining distance
typename turn_operation_type::comparable_distance_type
min_remaining_distance = 0;
std::size_t selected_index = sbs.m_ranked_points.size();
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
{
auto const& ranked_point = sbs.m_ranked_points[i];
if (ranked_point.rank > selected_rank)
{
typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i];
if (ranked_point.rank == selected_rank)
{
turn_operation_type const& op = operation_from_rank(ranked_point);
if (op.visited.finalized())
{
// This direction is already traveled before, the same
// cannot be traveled again
continue;
}
// Take turn with the smallest remaining distance
if (selected_index == sbs.m_ranked_points.size()
|| op.remaining_distance < min_remaining_distance)
{
selected_index = i;
min_remaining_distance = op.remaining_distance;
}
}
break;
}
if (selected_index < sbs.m_ranked_points.size())
else if (ranked_point.rank == selected_rank)
{
typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[selected_index];
turn_index = ranked_point.turn_index;
op_index = ranked_point.operation_index;
return true;
auto const& op = operation_from_rank(ranked_point);
if (op.visited.finalized())
{
// This direction is already traveled,
// it cannot be traveled again
continue;
}
if (selected_index == sbs.m_ranked_points.size()
|| op.remaining_distance < min_remaining_distance)
{
// It was unassigned or it is better
selected_index = i;
min_remaining_distance = op.remaining_distance;
}
}
}
return false;
if (selected_index == sbs.m_ranked_points.size())
{
// Should not happen, there must be points with the selected rank
return false;
}
auto const& ranked_point = sbs.m_ranked_points[selected_index];
turn_index = ranked_point.turn_index;
op_index = ranked_point.operation_index;
return true;
}
inline bool fill_sbs(sbs_type& sbs,
@@ -819,6 +830,7 @@ public :
return result;
}
// Analyzes a non-clustered "ii" intersection, as if it is clustered.
inline bool analyze_ii_intersection(signed_size_type& turn_index, int& op_index,
turn_type const& current_turn,
segment_identifier const& previous_seg_id)

View File

@@ -89,7 +89,6 @@ struct traversal_switch_detector
enum isolation_type
{
isolation_unknown = -1,
isolation_no = 0,
isolation_yes = 1,
isolation_multiple = 2
@@ -121,7 +120,7 @@ struct traversal_switch_detector
struct region_properties
{
signed_size_type region_id = -1;
isolation_type isolated = isolation_unknown;
isolation_type isolated = isolation_no;
set_type unique_turn_ids;
connection_map connected_region_counts;
};
@@ -374,7 +373,7 @@ struct traversal_switch_detector
{
region_properties& properties = key_val.second;
if (properties.isolated == isolation_unknown
if (properties.isolated == isolation_no
&& has_only_isolated_children(properties))
{
properties.isolated = isolation_yes;
@@ -388,13 +387,36 @@ struct traversal_switch_detector
{
for (turn_type& turn : m_turns)
{
// For difference, for the input walked through in reverse,
// the meaning is reversed: what is isolated is actually not,
// and vice versa.
bool const reverseMeaningInTurn
= (Reverse1 || Reverse2)
&& ! turn.is_self()
&& ! turn.is_clustered()
&& uu_or_ii(turn)
&& turn.operations[0].enriched.region_id
!= turn.operations[1].enriched.region_id;
for (auto& op : turn.operations)
{
auto mit = m_connected_regions.find(op.enriched.region_id);
if (mit != m_connected_regions.end())
{
bool const reverseMeaningInOp
= reverseMeaningInTurn
&& ((op.seg_id.source_index == 0 && Reverse1)
|| (op.seg_id.source_index == 1 && Reverse2));
// It is assigned to isolated if it's property is "Yes",
// (one connected interior, or chained).
// "Multiple" doesn't count for isolation,
// neither for intersection, neither for difference.
region_properties const& prop = mit->second;
op.enriched.isolated = prop.isolated == isolation_yes;
op.enriched.isolated
= reverseMeaningInOp
? false
: prop.isolated == isolation_yes;
}
}
}
@@ -478,8 +500,12 @@ struct traversal_switch_detector
// Discarded turns don't connect rings to the same region
// Also xx are not relevant
// (otherwise discarded colocated uu turn could make a connection)
return ! turn.discarded
&& ! turn.both(operation_blocked);
return ! turn.discarded && ! turn.both(operation_blocked);
}
inline bool uu_or_ii(turn_type const& turn) const
{
return turn.both(operation_union) || turn.both(operation_intersection);
}
inline bool connects_same_region(turn_type const& turn) const
@@ -492,7 +518,7 @@ struct traversal_switch_detector
if (! turn.is_clustered())
{
// If it is a uu/ii-turn (non clustered), it is never same region
return ! (turn.both(operation_union) || turn.both(operation_intersection));
return ! uu_or_ii(turn);
}
if (BOOST_GEOMETRY_CONDITION(target_operation == operation_union))
@@ -565,10 +591,83 @@ struct traversal_switch_detector
}
}
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
void debug_show_results()
{
auto isolation_to_string = [](isolation_type const& iso) -> std::string
{
switch(iso)
{
case isolation_no : return "no";
case isolation_yes : return "yes";
case isolation_multiple : return "multiple";
}
return "error";
};
auto set_to_string = [](auto const& s) -> std::string
{
std::ostringstream result;
for (auto item : s) { result << " " << item; }
return result.str();
};
for (auto const& kv : m_connected_regions)
{
auto const& prop = kv.second;
std::ostringstream sub;
sub << "[turns" << set_to_string(prop.unique_turn_ids)
<< "] regions";
for (auto const& kvs : prop.connected_region_counts)
{
sub << " { " << kvs.first
<< " : via [" << set_to_string(kvs.second.unique_turn_ids)
<< " ] }";
}
std::cout << "REGION " << prop.region_id
<< " " << isolation_to_string(prop.isolated)
<< " " << sub.str()
<< std::endl;
}
for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
{
turn_type const& turn = m_turns[turn_index];
if (uu_or_ii(turn) && ! turn.is_clustered())
{
std::cout << (turn.both(operation_union) ? "UU" : "II")
<< " " << turn_index
<< " (" << geometry::get<0>(turn.point)
<< ", " << geometry::get<1>(turn.point) << ")"
<< " -> " << std::boolalpha
<< " [" << turn.operations[0].seg_id.source_index
<< "/" << turn.operations[1].seg_id.source_index << "] "
<< "(" << turn.operations[0].enriched.region_id
<< " " << turn.operations[0].enriched.isolated
<< ") / (" << turn.operations[1].enriched.region_id
<< " " << turn.operations[1].enriched.isolated << ")"
<< std::endl;
}
}
for (auto const& key_val : m_clusters)
{
cluster_info const& cinfo = key_val.second;
std::cout << "CL RESULT " << key_val.first
<< " -> " << cinfo.open_count << std::endl;
}
}
#endif
void iterate()
{
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
std::cout << "BEGIN SWITCH DETECTOR (region_ids and isolation)" << std::endl;
std::cout << "BEGIN SWITCH DETECTOR (region_ids and isolation)"
<< (Reverse1 ? " REVERSE_1" : "")
<< (Reverse2 ? " REVERSE_2" : "")
<< std::endl;
#endif
// Collect turns per ring
@@ -608,33 +707,7 @@ struct traversal_switch_detector
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
std::cout << "END SWITCH DETECTOR" << std::endl;
for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
{
turn_type const& turn = m_turns[turn_index];
if ((turn.both(operation_union) || turn.both(operation_intersection))
&& ! turn.is_clustered())
{
std::cout << (turn.both(operation_union) ? "UU" : "II")
<< " " << turn_index
<< " (" << geometry::get<0>(turn.point)
<< ", " << geometry::get<1>(turn.point) << ")"
<< " -> " << std::boolalpha
<< "(" << turn.operations[0].enriched.region_id
<< " " << turn.operations[0].enriched.isolated
<< ") / (" << turn.operations[1].enriched.region_id
<< " " << turn.operations[1].enriched.isolated << ")"
<< std::endl;
}
}
for (auto const& key_val : m_clusters)
{
cluster_info const& cinfo = key_val.second;
std::cout << "CL RESULT " << key_val.first
<< " -> " << cinfo.open_count << std::endl;
}
debug_show_results();
#endif
}

View File

@@ -138,6 +138,11 @@ struct turn_info
{
return cluster_id > 0;
}
inline bool is_self() const
{
return operations[0].seg_id.source_index
== operations[1].seg_id.source_index;
}
private :
inline bool has12(operation_type type1, operation_type type2) const

View File

@@ -783,22 +783,24 @@ inline void enlarge_sections(Sections& sections, Strategy const&)
// It makes section a tiny bit too large, which might cause (a small number)
// of more comparisons
for (typename boost::range_iterator<Sections>::type it = boost::begin(sections);
it != boost::end(sections);
++it)
for (auto& section : sections)
{
#if defined(BOOST_GEOMETRY_USE_RESCALING)
detail::sectionalize::expand_by_epsilon
<
typename Strategy::cs_tag
>::apply(it->bounding_box);
>::apply(section.bounding_box);
#else
// Expand the box to avoid missing any intersection. The amount is
// should be larger than epsilon. About the value itself: the smaller
// it is, the higher the risk to miss intersections. The larger it is,
// the more comparisons are made. So it should be on the high side.
detail::buffer::buffer_box(it->bounding_box, 0.001, it->bounding_box);
using gt = decltype(section.bounding_box);
using ct = typename geometry::coordinate_type<gt>::type;
ct const tolerance = ct(1) / ct(1000);
detail::buffer::buffer_box(section.bounding_box, tolerance,
section.bounding_box);
#endif
}
}

View File

@@ -11,6 +11,9 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SELECT_GEOMETRY_TYPE_HPP
#include <boost/geometry/core/geometry_types.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits.hpp>
@@ -21,29 +24,33 @@ namespace boost { namespace geometry
namespace detail
{
template
<
typename Geometry,
template <typename, typename> class LessPred,
bool IsDynamicOrCollection = util::is_dynamic_geometry<Geometry>::value
|| util::is_geometry_collection<Geometry>::value
>
struct select_geometry_type
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct first_geometry_type
{
using type = Geometry;
};
template
<
typename Geometry,
template <typename, typename> class LessPred
>
struct select_geometry_type<Geometry, LessPred, true>
: util::select_element
template <typename Geometry>
struct first_geometry_type<Geometry, geometry_collection_tag>
{
template <typename T>
using pred = util::bool_constant
<
typename traits::geometry_types<std::remove_const_t<Geometry>>::type,
LessPred
>
! util::is_dynamic_geometry<T>::value
&& ! util::is_geometry_collection<T>::value
>;
using type = typename util::sequence_find_if
<
typename traits::geometry_types<Geometry>::type,
pred
>::type;
};
template <typename Geometry>
struct first_geometry_type<Geometry, dynamic_geometry_tag>
: first_geometry_type<Geometry, geometry_collection_tag>
{};
@@ -65,6 +72,32 @@ struct geometry_types<Geometry, true>
};
template
<
typename Geometry,
template <typename, typename> class LessPred,
bool IsDynamicOrCollection = util::is_dynamic_geometry<Geometry>::value
|| util::is_geometry_collection<Geometry>::value
>
struct select_geometry_type
{
using type = Geometry;
};
template
<
typename Geometry,
template <typename, typename> class LessPred
>
struct select_geometry_type<Geometry, LessPred, true>
: util::sequence_min_element
<
typename traits::geometry_types<std::remove_const_t<Geometry>>::type,
LessPred
>
{};
template
<
typename Geometry1, typename Geometry2,
@@ -89,10 +122,13 @@ template
template <typename, typename> class LessPred
>
struct select_geometry_types<Geometry1, Geometry2, LessPred, true>
: util::select_combination_element
: util::sequence_min_element
<
typename geometry_types<Geometry1>::type,
typename geometry_types<Geometry2>::type,
typename util::sequence_combine
<
typename geometry_types<Geometry1>::type,
typename geometry_types<Geometry2>::type
>::type,
LessPred
>
{};

View File

@@ -181,20 +181,16 @@ struct visit_breadth_first<Geometry, dynamic_geometry_tag>
}
};
// NOTE: This specialization works partially like std::visit and partially like
// std::ranges::for_each. If the argument is rvalue reference then the elements
// are passed into the function as rvalue references as well. This is consistent
// with std::visit but different than std::ranges::for_each. It's done this way
// because visit_breadth_first is also specialized for static and dynamic geometries
// which and references for them has to be propagated like that. If this is not
// desireable then the support for other kinds of geometries should be dropped and
// this algorithm should work only for geometry collection.
// This is not a problem right now because only non-rvalue references are passed
// but in the future there might be some issues. Consider e.g. passing a temporary
// mutable proxy range as geometry collection. In such case the elements would be
// passed as rvalue references which would be incorrect.
template <typename Geometry>
struct visit_breadth_first<Geometry, geometry_collection_tag>
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <bool PassIterator = false>
struct visit_breadth_first_impl
{
template <typename F, typename Geom>
static bool apply(F function, Geom && geom)
@@ -217,7 +213,8 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
bool result = true;
traits::iter_visit<util::remove_cref_t<Geom>>::apply([&](auto && g)
{
result = visit_or_enqueue(function, std::forward<decltype(g)>(g), queue, it);
result = visit_breadth_first_impl::visit_or_enqueue<PassIterator>(
function, std::forward<decltype(g)>(g), queue, it);
}, it);
if (! result)
@@ -235,7 +232,7 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
// so this call can be avoided.
traits::iter_visit<util::remove_cref_t<Geom>>::apply([&](auto && g)
{
set_iterators(std::forward<decltype(g)>(g), it, end);
visit_breadth_first_impl::set_iterators(std::forward<decltype(g)>(g), it, end);
}, queue.front());
queue.pop_front();
}
@@ -246,7 +243,7 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
private:
template
<
typename F, typename Geom, typename Iterator,
bool PassIter, typename F, typename Geom, typename Iterator,
std::enable_if_t<util::is_geometry_collection<Geom>::value, int> = 0
>
static bool visit_or_enqueue(F &, Geom &&, std::deque<Iterator> & queue, Iterator iter)
@@ -256,13 +253,22 @@ private:
}
template
<
typename F, typename Geom, typename Iterator,
std::enable_if_t<! util::is_geometry_collection<Geom>::value, int> = 0
bool PassIter, typename F, typename Geom, typename Iterator,
std::enable_if_t<! util::is_geometry_collection<Geom>::value && ! PassIter, int> = 0
>
static bool visit_or_enqueue(F & f, Geom && g, std::deque<Iterator> & , Iterator)
{
return f(std::forward<Geom>(g));
}
template
<
bool PassIter, typename F, typename Geom, typename Iterator,
std::enable_if_t<! util::is_geometry_collection<Geom>::value && PassIter, int> = 0
>
static bool visit_or_enqueue(F & f, Geom && g, std::deque<Iterator> & , Iterator iter)
{
return f(std::forward<Geom>(g), iter);
}
template
<
@@ -283,6 +289,32 @@ private:
{}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
// NOTE: This specialization works partially like std::visit and partially like
// std::ranges::for_each. If the argument is rvalue reference then the elements
// are passed into the function as rvalue references as well. This is consistent
// with std::visit but different than std::ranges::for_each. It's done this way
// because visit_breadth_first is also specialized for static and dynamic geometries
// and references for them has to be propagated like that. If this is not
// desireable then the support for other kinds of geometries should be dropped and
// this algorithm should work only for geometry collection. Or forwarding of rvalue
// references should simply be dropped entirely.
// This is not a problem right now because only non-rvalue references are passed
// but in the future there might be some issues. Consider e.g. passing a temporary
// mutable proxy range as geometry collection. In such case the elements would be
// passed as rvalue references which would be incorrect.
template <typename Geometry>
struct visit_breadth_first<Geometry, geometry_collection_tag>
: detail::visit_breadth_first_impl<>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@@ -68,6 +68,29 @@ struct distance_strategy_type<Geometry1, Geometry2, Strategies, true, true>
{};
template
<
typename Geometry1, typename Geometry2, typename Strategies,
bool IsDynamicOrGC = util::is_dynamic_geometry<Geometry1>::value
|| util::is_dynamic_geometry<Geometry2>::value
|| util::is_geometry_collection<Geometry1>::value
|| util::is_geometry_collection<Geometry2>::value
>
struct distance_strategy_tag
{
using type = void;
};
template <typename Geometry1, typename Geometry2, typename Strategies>
struct distance_strategy_tag<Geometry1, Geometry2, Strategies, false>
{
using type = typename strategy::distance::services::tag
<
typename distance_strategy_type<Geometry1, Geometry2, Strategies>::type
>::type;
};
template
<
typename Geometry1, typename Geometry2,
@@ -91,11 +114,11 @@ template
linear_tag,
areal_tag
>::type,
typename StrategyTag = typename strategy::distance::services::tag
typename StrategyTag = typename distance_strategy_tag
<
typename distance_strategy_type<Geometry1, Geometry2, Strategy>::type
Geometry1, Geometry2, Strategy
>::type,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::value
>
struct distance : not_implemented<Tag1, Tag2>
{};

View File

@@ -17,12 +17,9 @@
#include <boost/range/empty.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
@@ -30,6 +27,8 @@
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
@@ -53,10 +52,7 @@ struct ring_is_convex
static inline bool apply(Ring const& ring, Strategies const& strategies)
{
std::size_t n = boost::size(ring);
if (boost::size(ring) < core_detail::closure::minimum_ring_size
<
geometry::closure<Ring>::value
>::value)
if (n < detail::minimum_ring_size<Ring>::value)
{
// (Too) small rings are considered as non-concave, is convex
return true;
@@ -137,6 +133,17 @@ struct polygon_is_convex
}
};
struct multi_polygon_is_convex
{
template <typename MultiPolygon, typename Strategies>
static inline bool apply(MultiPolygon const& multi_polygon, Strategies const& strategies)
{
auto const size = boost::size(multi_polygon);
return size == 0 // For consistency with ring_is_convex
|| (size == 1 && polygon_is_convex::apply(range::front(multi_polygon), strategies));
}
};
}} // namespace detail::is_convex
#endif // DOXYGEN_NO_DETAIL
@@ -151,14 +158,29 @@ template
typename Geometry,
typename Tag = typename tag<Geometry>::type
>
struct is_convex : not_implemented<Tag>
{};
struct is_convex
{
template <typename Strategies>
static inline bool apply(Geometry const&, Strategies const&)
{
// Convexity is not defined for PointLike and Linear geometries.
// We could implement this because the following definitions would work:
// - no line segment between two points on the interior or boundary ever goes outside.
// - convex_hull of geometry is equal to the original geometry, this implies equal
// topological dimension.
// For MultiPoint we'd have to check whether or not an arbitrary number of equal points
// is stored.
// MultiPolygon we'd have to check for continuous chain of Linestrings which would require
// the use of relate(pt, seg) or distance(pt, pt) strategy.
return false;
}
};
template <typename Box>
struct is_convex<Box, box_tag>
{
template <typename Strategy>
static inline bool apply(Box const& , Strategy const& )
template <typename Strategies>
static inline bool apply(Box const& , Strategies const& )
{
// Any box is convex (TODO: consider spherical boxes)
// TODO: in spherical and geographic the answer would be "false" most of the time.
@@ -187,6 +209,10 @@ template <typename Polygon>
struct is_convex<Polygon, polygon_tag> : detail::is_convex::polygon_is_convex
{};
template <typename MultiPolygon>
struct is_convex<MultiPolygon, multi_polygon_tag> : detail::is_convex::multi_polygon_is_convex
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
@@ -238,9 +264,9 @@ struct is_convex<default_strategy, false>
} // namespace resolve_strategy
namespace resolve_variant {
namespace resolve_dynamic {
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct is_convex
{
template <typename Strategy>
@@ -251,38 +277,50 @@ struct is_convex
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_convex<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct is_convex<Geometry, dynamic_geometry_tag>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
static inline bool apply(Geometry const& geometry, Strategy const& strategy)
{
Strategy const& m_strategy;
visitor(Strategy const& strategy) : m_strategy(strategy) {}
template <typename Geometry>
bool operator()(Geometry const& geometry) const
bool result = false;
traits::visit<Geometry>::apply([&](auto const& g)
{
return is_convex<Geometry>::apply(geometry, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
result = is_convex<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
}, geometry);
return result;
}
};
} // namespace resolve_variant
// NOTE: This is a simple implementation checking if a GC contains single convex geometry.
// Technically a GC could store e.g. polygons touching with edges and together creating a convex
// region. To check this we'd require relate() strategy and the algorithm would be quite complex.
template <typename Geometry>
struct is_convex<Geometry, geometry_collection_tag>
{
template <typename Strategy>
static inline bool apply(Geometry const& geometry, Strategy const& strategy)
{
bool result = false;
bool is_first = true;
detail::visit_breadth_first([&](auto const& g)
{
result = is_first
&& is_convex<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
is_first = false;
return result;
}, geometry);
return result;
}
};
} // namespace resolve_dynamic
// TODO: documentation / qbk
template<typename Geometry>
inline bool is_convex(Geometry const& geometry)
{
return resolve_variant::is_convex
return resolve_dynamic::is_convex
<
Geometry
>::apply(geometry, geometry::default_strategy());
@@ -292,7 +330,7 @@ inline bool is_convex(Geometry const& geometry)
template<typename Geometry, typename Strategy>
inline bool is_convex(Geometry const& geometry, Strategy const& strategy)
{
return resolve_variant::is_convex<Geometry>::apply(geometry, strategy);
return resolve_dynamic::is_convex<Geometry>::apply(geometry, strategy);
}

View File

@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2020, Oracle and/or its affiliates.
// Copyright (c) 2015-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,21 +15,21 @@
#include <boost/range/empty.hpp>
#include <boost/range/end.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/geometry_types.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
{
@@ -152,10 +152,10 @@ struct is_empty<Geometry, multi_polygon_tag>
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_variant
namespace resolve_dynamic
{
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct is_empty
{
static inline bool apply(Geometry const& geometry)
@@ -166,26 +166,36 @@ struct is_empty
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_empty<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct is_empty<Geometry, dynamic_geometry_tag>
{
struct visitor : boost::static_visitor<bool>
static inline bool apply(Geometry const& geometry)
{
template <typename Geometry>
inline bool operator()(Geometry const& geometry) const
bool result = true;
traits::visit<Geometry>::apply([&](auto const& g)
{
return is_empty<Geometry>::apply(geometry);
}
};
static bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
{
return boost::apply_visitor(visitor(), geometry);
result = is_empty<util::remove_cref_t<decltype(g)>>::apply(g);
}, geometry);
return result;
}
};
} // namespace resolve_variant
template <typename Geometry>
struct is_empty<Geometry, geometry_collection_tag>
{
static inline bool apply(Geometry const& geometry)
{
bool result = true;
detail::visit_breadth_first([&](auto const& g)
{
result = is_empty<util::remove_cref_t<decltype(g)>>::apply(g);
return result;
}, geometry);
return result;
}
};
} // namespace resolve_dynamic
/*!
@@ -200,7 +210,7 @@ struct is_empty<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline bool is_empty(Geometry const& geometry)
{
return resolve_variant::is_empty<Geometry>::apply(geometry);
return resolve_dynamic::is_empty<Geometry>::apply(geometry);
}

View File

@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -26,21 +26,20 @@
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/counting.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/counting.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
{
@@ -140,48 +139,54 @@ struct num_points<Geometry, AddForOpen, multi_tag>
#endif
namespace resolve_variant
namespace resolve_dynamic
{
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct num_points
{
static inline std::size_t apply(Geometry const& geometry,
bool add_for_open)
static inline std::size_t apply(Geometry const& geometry, bool add_for_open)
{
concepts::check<Geometry const>();
return add_for_open
? dispatch::num_points<Geometry, true>::apply(geometry)
: dispatch::num_points<Geometry, false>::apply(geometry);
? dispatch::num_points<Geometry, true>::apply(geometry)
: dispatch::num_points<Geometry, false>::apply(geometry);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct num_points<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct num_points<Geometry, dynamic_geometry_tag>
{
struct visitor: boost::static_visitor<std::size_t>
static inline std::size_t apply(Geometry const& geometry, bool add_for_open)
{
bool m_add_for_open;
visitor(bool add_for_open): m_add_for_open(add_for_open) {}
template <typename Geometry>
inline std::size_t operator()(Geometry const& geometry) const
std::size_t result = 0;
traits::visit<Geometry>::apply([&](auto const& g)
{
return num_points<Geometry>::apply(geometry, m_add_for_open);
}
};
static inline std::size_t
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
bool add_for_open)
{
return boost::apply_visitor(visitor(add_for_open), geometry);
result = num_points<util::remove_cref_t<decltype(g)>>::apply(g, add_for_open);
}, geometry);
return result;
}
};
} // namespace resolve_variant
template <typename Geometry>
struct num_points<Geometry, geometry_collection_tag>
{
static inline std::size_t apply(Geometry const& geometry, bool add_for_open)
{
std::size_t result = 0;
detail::visit_breadth_first([&](auto const& g)
{
result += num_points<util::remove_cref_t<decltype(g)>>::apply(g, add_for_open);
return true;
}, geometry);
return result;
}
};
} // namespace resolve_dynamic
/*!
@@ -198,7 +203,7 @@ struct num_points<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline std::size_t num_points(Geometry const& geometry, bool add_for_open = false)
{
return resolve_variant::num_points<Geometry>::apply(geometry, add_for_open);
return resolve_dynamic::num_points<Geometry>::apply(geometry, add_for_open);
}
#if defined(_MSC_VER)

View File

@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2020, Oracle and/or its affiliates.
// Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -16,22 +16,19 @@
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/counting.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/counting.hpp>
#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
{
@@ -140,11 +137,11 @@ struct num_segments<Geometry, multi_polygon_tag>
namespace resolve_variant
namespace resolve_dynamic
{
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct num_segments
{
static inline std::size_t apply(Geometry const& geometry)
@@ -156,27 +153,38 @@ struct num_segments
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct num_segments<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct num_segments<Geometry, dynamic_geometry_tag>
{
struct visitor: boost::static_visitor<std::size_t>
static inline std::size_t apply(Geometry const& geometry)
{
template <typename Geometry>
inline std::size_t operator()(Geometry const& geometry) const
std::size_t result = 0;
traits::visit<Geometry>::apply([&](auto const& g)
{
return num_segments<Geometry>::apply(geometry);
}
};
static inline std::size_t
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
{
return boost::apply_visitor(visitor(), geometry);
result = num_segments<util::remove_cref_t<decltype(g)>>::apply(g);
}, geometry);
return result;
}
};
} // namespace resolve_variant
template <typename Geometry>
struct num_segments<Geometry, geometry_collection_tag>
{
static inline std::size_t apply(Geometry const& geometry)
{
std::size_t result = 0;
detail::visit_breadth_first([&](auto const& g)
{
result += num_segments<util::remove_cref_t<decltype(g)>>::apply(g);
return true;
}, geometry);
return result;
}
};
} // namespace resolve_dynamic
@@ -193,7 +201,7 @@ struct num_segments<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline std::size_t num_segments(Geometry const& geometry)
{
return resolve_variant::num_segments<Geometry>::apply(geometry);
return resolve_dynamic::num_segments<Geometry>::apply(geometry);
}

View File

@@ -21,20 +21,19 @@
#include <boost/range/value_type.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/length.hpp>
#include <boost/geometry/algorithms/detail/calculate_null.hpp>
#include <boost/geometry/algorithms/detail/calculate_sum.hpp>
#include <boost/geometry/algorithms/detail/multi_sum.hpp>
// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_length_result.hpp>
@@ -162,9 +161,9 @@ struct perimeter<default_strategy, false>
} // namespace resolve_strategy
namespace resolve_variant {
namespace resolve_dynamic {
template <typename Geometry>
template <typename Geometry, typename Tag = typename geometry::tag<Geometry>::type>
struct perimeter
{
template <typename Strategy>
@@ -176,39 +175,40 @@ struct perimeter
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct perimeter<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct perimeter<Geometry, dynamic_geometry_tag>
{
typedef typename default_length_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>
>::type result_type;
template <typename Strategy>
struct visitor: boost::static_visitor<result_type>
static inline typename default_length_result<Geometry>::type
apply(Geometry const& geometry, Strategy const& strategy)
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry>
typename default_length_result<Geometry>::type
operator()(Geometry const& geometry) const
typename default_length_result<Geometry>::type result = 0;
traits::visit<Geometry>::apply([&](auto const& g)
{
return perimeter<Geometry>::apply(geometry, m_strategy);
}
};
template <typename Strategy>
static inline result_type
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
result = perimeter<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
}, geometry);
return result;
}
};
} // namespace resolve_variant
template <typename Geometry>
struct perimeter<Geometry, geometry_collection_tag>
{
template <typename Strategy>
static inline typename default_length_result<Geometry>::type
apply(Geometry const& geometry, Strategy const& strategy)
{
typename default_length_result<Geometry>::type result = 0;
detail::visit_breadth_first([&](auto const& g)
{
result += perimeter<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
return true;
}, geometry);
return result;
}
};
} // namespace resolve_dynamic
/*!
@@ -232,7 +232,7 @@ inline typename default_length_result<Geometry>::type perimeter(
Geometry const& geometry)
{
// detail::throw_on_empty_input(geometry);
return resolve_variant::perimeter<Geometry>::apply(geometry, default_strategy());
return resolve_dynamic::perimeter<Geometry>::apply(geometry, default_strategy());
}
/*!
@@ -254,7 +254,7 @@ inline typename default_length_result<Geometry>::type perimeter(
Geometry const& geometry, Strategy const& strategy)
{
// detail::throw_on_empty_input(geometry);
return resolve_variant::perimeter<Geometry>::apply(geometry, strategy);
return resolve_dynamic::perimeter<Geometry>::apply(geometry, strategy);
}
}} // namespace boost::geometry

View File

@@ -5,8 +5,8 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -24,15 +24,15 @@
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
@@ -61,11 +61,9 @@ struct polygon_reverse: private range_reverse
{
range_reverse::apply(exterior_ring(polygon));
typename interior_return_type<Polygon>::type
rings = interior_rings(polygon);
for (typename detail::interior_iterator<Polygon>::type
it = boost::begin(rings); it != boost::end(rings); ++it)
auto&& rings = interior_rings(polygon);
auto const end = boost::end(rings);
for (auto it = boost::begin(rings); it != end; ++it)
{
range_reverse::apply(*it);
}
@@ -110,21 +108,13 @@ struct reverse<Polygon, polygon_tag>
template <typename Geometry>
struct reverse<Geometry, multi_linestring_tag>
: detail::multi_modify
<
Geometry,
detail::reverse::range_reverse
>
: detail::multi_modify<detail::reverse::range_reverse>
{};
template <typename Geometry>
struct reverse<Geometry, multi_polygon_tag>
: detail::multi_modify
<
Geometry,
detail::reverse::polygon_reverse
>
: detail::multi_modify<detail::reverse::polygon_reverse>
{};
@@ -133,10 +123,10 @@ struct reverse<Geometry, multi_polygon_tag>
#endif
namespace resolve_variant
namespace resolve_dynamic
{
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct reverse
{
static void apply(Geometry& geometry)
@@ -146,25 +136,32 @@ struct reverse
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct reverse<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct reverse<Geometry, dynamic_geometry_tag>
{
struct visitor: boost::static_visitor<void>
static void apply(Geometry& geometry)
{
template <typename Geometry>
void operator()(Geometry& geometry) const
traits::visit<Geometry>::apply([](auto & g)
{
reverse<Geometry>::apply(geometry);
}
};
static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
{
boost::apply_visitor(visitor(), geometry);
reverse<util::remove_cref_t<decltype(g)>>::apply(g);
}, geometry);
}
};
} // namespace resolve_variant
template <typename Geometry>
struct reverse<Geometry, geometry_collection_tag>
{
static void apply(Geometry& geometry)
{
detail::visit_breadth_first([](auto & g)
{
reverse<util::remove_cref_t<decltype(g)>>::apply(g);
return true;
}, geometry);
}
};
} // namespace resolve_dynamic
/*!
@@ -181,7 +178,7 @@ struct reverse<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline void reverse(Geometry& geometry)
{
resolve_variant::reverse<Geometry>::apply(geometry);
resolve_dynamic::reverse<Geometry>::apply(geometry);
}
}} // namespace boost::geometry

View File

@@ -31,15 +31,13 @@
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/perimeter.hpp>
@@ -50,7 +48,9 @@
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/concepts/simplify_concept.hpp>
@@ -60,6 +60,8 @@
#include <boost/geometry/strategies/simplify/geographic.hpp>
#include <boost/geometry/strategies/simplify/spherical.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
#include <boost/geometry/io/dsv/write.hpp>
#endif
@@ -301,6 +303,23 @@ struct simplify_range_insert
};
struct simplify_copy_assign
{
template
<
typename In, typename Out, typename Distance,
typename Impl, typename Strategies
>
static inline void apply(In const& in, Out& out,
Distance const& ,
Impl const& ,
Strategies const& )
{
out = in;
}
};
struct simplify_copy
{
template
@@ -615,6 +634,17 @@ struct simplify<Point, point_tag>
}
};
template <typename Segment>
struct simplify<Segment, segment_tag>
: detail::simplify::simplify_copy_assign
{};
template <typename Box>
struct simplify<Box, box_tag>
: detail::simplify::simplify_copy_assign
{};
// Linestring, keep 2 points (unless those points are the same)
template <typename Linestring>
struct simplify<Linestring, linestring_tag>
@@ -803,9 +833,9 @@ struct simplify_insert<default_strategy, false>
} // namespace resolve_strategy
namespace resolve_variant {
namespace resolve_dynamic {
template <typename Geometry>
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct simplify
{
template <typename Distance, typename Strategy>
@@ -818,43 +848,46 @@ struct simplify
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct simplify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
struct simplify<Geometry, dynamic_geometry_tag>
{
template <typename Distance, typename Strategy>
struct visitor: boost::static_visitor<void>
static inline void apply(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
Distance const& m_max_distance;
Strategy const& m_strategy;
visitor(Distance const& max_distance, Strategy const& strategy)
: m_max_distance(max_distance)
, m_strategy(strategy)
{}
template <typename Geometry>
void operator()(Geometry const& geometry, Geometry& out) const
traits::visit<Geometry>::apply([&](auto const& g)
{
simplify<Geometry>::apply(geometry, out, m_max_distance, m_strategy);
}
};
template <typename Distance, typename Strategy>
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out,
Distance const& max_distance,
Strategy const& strategy)
{
boost::apply_visitor(
visitor<Distance, Strategy>(max_distance, strategy),
geometry,
out
);
using geom_t = util::remove_cref_t<decltype(g)>;
geom_t o;
simplify<geom_t>::apply(g, o, max_distance, strategy);
out = std::move(o);
}, geometry);
}
};
} // namespace resolve_variant
template <typename Geometry>
struct simplify<Geometry, geometry_collection_tag>
{
template <typename Distance, typename Strategy>
static inline void apply(Geometry const& geometry,
Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
detail::visit_breadth_first([&](auto const& g)
{
using geom_t = util::remove_cref_t<decltype(g)>;
geom_t o;
simplify<geom_t>::apply(g, o, max_distance, strategy);
traits::emplace_back<Geometry>::apply(out, std::move(o));
return true;
}, geometry);
}
};
} // namespace resolve_dynamic
/*!
@@ -882,7 +915,7 @@ inline void simplify(Geometry const& geometry, Geometry& out,
geometry::clear(out);
resolve_variant::simplify<Geometry>::apply(geometry, out, max_distance, strategy);
resolve_dynamic::simplify<Geometry>::apply(geometry, out, max_distance, strategy);
}

View File

@@ -1,6 +1,6 @@
// Boost.Geometry
// Copyright (c) 2019 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2019-2021 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2018-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,10 +23,6 @@
#define BOOST_GEOMETRY_CXX11_TUPLE
#endif
// Defining this selects Kramer rule for segment-intersection
// That is default behaviour.
#define BOOST_GEOMETRY_USE_KRAMER_RULE
// Rescaling is turned on, unless NO_ROBUSTNESS is defined
// In future versions of Boost.Geometry, it will be turned off by default
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)

View 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

View File

@@ -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

View File

@@ -45,39 +45,43 @@ struct geometry_id
template <>
struct geometry_id<point_tag> : std::integral_constant<int, 1> {};
struct geometry_id<point_tag> : std::integral_constant<int, 1> {};
template <>
struct geometry_id<linestring_tag> : std::integral_constant<int, 2> {};
struct geometry_id<linestring_tag> : std::integral_constant<int, 2> {};
template <>
struct geometry_id<polygon_tag> : std::integral_constant<int, 3> {};
struct geometry_id<polygon_tag> : std::integral_constant<int, 3> {};
template <>
struct geometry_id<multi_point_tag> : std::integral_constant<int, 4> {};
struct geometry_id<multi_point_tag> : std::integral_constant<int, 4> {};
template <>
struct geometry_id<multi_linestring_tag> : std::integral_constant<int, 5> {};
struct geometry_id<multi_linestring_tag> : std::integral_constant<int, 5> {};
template <>
struct geometry_id<multi_polygon_tag> : std::integral_constant<int, 6> {};
struct geometry_id<multi_polygon_tag> : std::integral_constant<int, 6> {};
template <>
struct geometry_id<segment_tag> : std::integral_constant<int, 92> {};
struct geometry_id<geometry_collection_tag> : std::integral_constant<int, 7> {};
template <>
struct geometry_id<ring_tag> : std::integral_constant<int, 93> {};
struct geometry_id<segment_tag> : std::integral_constant<int, 92> {};
template <>
struct geometry_id<box_tag> : std::integral_constant<int, 94> {};
struct geometry_id<ring_tag> : std::integral_constant<int, 93> {};
template <>
struct geometry_id<box_tag> : std::integral_constant<int, 94> {};
} // namespace core_dispatch

View File

@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -21,10 +21,12 @@
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/geometry_types.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
@@ -137,6 +139,36 @@ struct point_type<multi_polygon_tag, MultiPolygon>
};
template <typename DynamicGeometry>
struct point_type<dynamic_geometry_tag, DynamicGeometry>
{
using geometry_t = typename util::sequence_front
<
typename traits::geometry_types<DynamicGeometry>::type
>::type;
using type = typename point_type
<
typename tag<geometry_t>::type,
typename util::remove_cptrref<geometry_t>::type
>::type;
};
template <typename GeometryCollection>
struct point_type<geometry_collection_tag, GeometryCollection>
{
using geometry_t = typename util::sequence_front
<
typename traits::geometry_types<GeometryCollection>::type
>::type;
using type = typename point_type
<
typename tag<geometry_t>::type,
typename util::remove_cptrref<geometry_t>::type
>::type;
};
} // namespace core_dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@@ -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>

View File

@@ -38,16 +38,6 @@ namespace boost { namespace geometry
namespace detail
{
template <typename ...>
struct parameter_pack_first_type {};
template <typename T, typename ... Ts>
struct parameter_pack_first_type<T, Ts...>
{
typedef T type;
};
template <typename Seq, typename ResultSeq = util::type_sequence<>>
struct boost_variant_types;
@@ -78,7 +68,7 @@ template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct point_type<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
: point_type
<
typename detail::parameter_pack_first_type
typename util::pack_front
<
BOOST_VARIANT_ENUM_PARAMS(T)
>::type

View File

@@ -22,6 +22,8 @@
#include <boost/concept_check.hpp>
#include <boost/concept/requires.hpp>
#include <boost/geometry/algorithms/detail/select_geometry_type.hpp>
#include <boost/geometry/geometries/concepts/concept_type.hpp>
#include <boost/geometry/geometries/concepts/box_concept.hpp>
#include <boost/geometry/geometries/concepts/dynamic_geometry_concept.hpp>
@@ -39,7 +41,6 @@
namespace boost { namespace geometry { namespace concepts
{
/*!
\brief Checks, in compile-time, the concept of any geometry
\ingroup concepts
@@ -69,7 +70,11 @@ inline void check_concepts_and_equal_dimensions()
{
check<Geometry1>();
check<Geometry2>();
assert_dimension_equal<Geometry1, Geometry2>();
assert_dimension_equal
<
typename geometry::detail::first_geometry_type<Geometry1>::type,
typename geometry::detail::first_geometry_type<Geometry2>::type
>();
}

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -15,6 +15,11 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
#include <boost/geometry/algorithms/detail/envelope/interface.hpp>
#include <boost/geometry/algorithms/detail/expand/interface.hpp>
#include <boost/geometry/index/detail/bounded_view.hpp>
namespace boost { namespace geometry { namespace index { namespace detail

View File

@@ -4,6 +4,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)
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP
#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>

View File

@@ -4,6 +4,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)
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP
#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>
#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>

View File

@@ -4,6 +4,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)
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP
#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2014 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,
@@ -15,7 +15,12 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -20,6 +20,9 @@
#include <boost/geometry/index/detail/algorithms/content.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
// Util to distinguish between default and non-default index strategy

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2014 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,
@@ -18,6 +18,7 @@
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2014 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,
@@ -15,7 +15,12 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
// WARNING! comparable_margin() will work only if the same Geometries are compared
// so it shouldn't be used in the case of Variants!

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2017 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,
@@ -20,6 +20,7 @@
#include <boost/geometry/index/detail/algorithms/segment_intersection.hpp>
#include <boost/geometry/strategies/default_distance_result.hpp>
#include <boost/geometry/strategies/default_length_result.hpp>

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2014 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,
@@ -15,9 +15,14 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
#include <limits>
#include <type_traits>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {

View File

@@ -5,8 +5,8 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -22,7 +22,7 @@
#include <boost/geometry/index/detail/algorithms/comparable_distance_far.hpp>
#include <boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp>
#include <boost/geometry/index/detail/algorithms/path_intersection.hpp>
#include <boost/geometry/index/detail/predicates.hpp>
#include <boost/geometry/index/detail/tags.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {

View 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

View 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

View File

@@ -20,9 +20,13 @@
//#include <utility>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/index/detail/tags.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
namespace predicates {
@@ -31,10 +35,10 @@ namespace predicates {
// predicates
// ------------------------------------------------------------------ //
template <typename Fun, bool IsFunction>
template <typename Fun, bool IsFunction = std::is_function<Fun>::value>
struct satisfies_impl
{
satisfies_impl() : fun(NULL) {}
satisfies_impl() : fun(nullptr) {}
satisfies_impl(Fun f) : fun(f) {}
Fun * fun;
};
@@ -42,20 +46,19 @@ struct satisfies_impl
template <typename Fun>
struct satisfies_impl<Fun, false>
{
satisfies_impl() {}
satisfies_impl() = default;
satisfies_impl(Fun const& f) : fun(f) {}
Fun fun;
};
template <typename Fun, bool Negated>
struct satisfies
: satisfies_impl<Fun, ::boost::is_function<Fun>::value>
struct satisfies : satisfies_impl<Fun>
{
typedef satisfies_impl<Fun, ::boost::is_function<Fun>::value> base;
using base_t = satisfies_impl<Fun>;
satisfies() {}
satisfies(Fun const& f) : base(f) {}
satisfies(base const& b) : base(b) {}
satisfies() = default;
satisfies(Fun const& f) : base_t(f) {}
satisfies(base_t const& b) : base_t(b) {}
};
// ------------------------------------------------------------------ //
@@ -619,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);
}
// ------------------------------------------------------------------ //

View 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

View File

@@ -4,6 +4,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)
@@ -11,13 +15,13 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP
#include <deque>
#include <boost/static_assert.hpp>
#include <vector>
#include <boost/geometry/index/adaptors/query.hpp>
namespace boost { namespace geometry { namespace index {
// Forward declaration
template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>
class rtree;

View File

@@ -4,6 +4,10 @@
//
// 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
//
// 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)
@@ -11,6 +15,10 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP
#include <iterator>
#include <boost/geometry/index/detail/rtree/visitors/iterator.hpp>
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
template <typename Value, typename Allocators>

View File

@@ -4,6 +4,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)
@@ -11,6 +15,6 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP
#include <boost/geometry/index/rtree/kmeans/split.hpp>
#include <boost/geometry/index/detail/rtree/kmeans/split.hpp>
#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP

View File

@@ -4,6 +4,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)
@@ -11,13 +15,17 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_SPLIT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_SPLIT_HPP
#include <boost/geometry/index/rtree/node/node.hpp>
#include <boost/geometry/index/rtree/visitors/insert.hpp>
#include <boost/geometry/index/detail/rtree/node/concept.hpp>
#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
// TODO: This should be defined in options.hpp
// For now it's defined here to satisfy Boost header policy
struct split_kmeans_tag {};
namespace kmeans {
// some details
@@ -56,25 +64,34 @@ namespace kmeans {
// 4. Pamietac o parametryzacji kontenera z nadmiarowymi elementami
// PS. Z R* reinsertami moze byc masakra
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
class split<Value, Options, Translator, Box, Allocators, split_kmeans_tag>
template <typename MembersHolder>
class split<MembersHolder, split_kmeans_tag>
{
protected:
typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::box_type box_type;
typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::allocators_type allocators_type;
typedef typename MembersHolder::size_type size_type;
typedef typename Options::parameters_type parameters_type;
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
public:
typedef index::detail::varray
<
typename rtree::elements_type<internal_node>::type::value_type,
1
> nodes_container_type;
template <typename Node>
static inline void apply(node* & root_node,
size_t & leafs_level,
static inline void apply(nodes_container_type & additional_nodes,
Node & n,
internal_node *parent_node,
size_t current_child_index,
Translator const& tr,
Allocators & allocators)
box_type & n_box,
parameters_type const& parameters,
translator_type const& translator,
allocators_type & allocators)
{
}

View File

@@ -4,6 +4,10 @@
//
// 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
//
// 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)
@@ -15,6 +19,7 @@
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/index/detail/varray.hpp>
#include <boost/geometry/index/detail/rtree/node/pairs.hpp>
#include <boost/geometry/index/detail/translator.hpp>
namespace boost { namespace geometry { namespace index {

View File

@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2018 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)
@@ -11,6 +15,8 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP
#include <boost/container/allocator_traits.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {

View File

@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2018 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)
@@ -11,7 +15,15 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP
#include <boost/container/allocator_traits.hpp>
#include <boost/container/vector.hpp>
#include <boost/core/pointer_traits.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant.hpp>
#include <boost/geometry/index/detail/rtree/options.hpp>
#include <boost/geometry/index/detail/rtree/node/concept.hpp>
#include <boost/geometry/index/detail/rtree/node/pairs.hpp>
namespace boost { namespace geometry { namespace index {

View File

@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2018 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)
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_STATIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_STATIC_HPP
#include <boost/geometry/index/detail/rtree/node/variant_dynamic.hpp>
#include <boost/geometry/index/detail/varray.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {

View File

@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2018 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)
@@ -11,10 +15,24 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP
#include <boost/container/allocator_traits.hpp>
#include <boost/container/vector.hpp>
#include <boost/core/pointer_traits.hpp>
#include <boost/geometry/index/detail/rtree/options.hpp>
#include <boost/geometry/index/detail/rtree/node/concept.hpp>
#include <boost/geometry/index/detail/rtree/node/pairs.hpp>
#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
// TODO: This should be defined in options.hpp
// For now it's defined here to satisfy Boost header policy
struct node_weak_dynamic_tag {};
struct node_weak_static_tag {};
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct weak_internal_node
: public weak_node<Value, Parameters, Box, Allocators, Tag>
@@ -87,7 +105,7 @@ struct visitor<Value, Parameters, Box, Allocators, node_weak_dynamic_tag, IsVisi
template <typename Allocator, typename Value, typename Parameters, typename Box, typename Tag>
struct internal_node_alloc
{
typedef typename internal_nod
typedef typename internal_node
<
Value, Parameters, Box,
allocators<Allocator, Value, Parameters, Box, Tag>,
@@ -116,6 +134,22 @@ struct leaf_alloc
>::template rebind_alloc<node_type> type;
};
template <typename Allocator, typename Value, typename Parameters, typename Box, typename Tag>
struct node_alloc
{
typedef typename weak_node
<
Value, Parameters, Box,
allocators<Allocator, Value, Parameters, Box, Tag>,
Tag
>::type node_type;
typedef typename ::boost::container::allocator_traits
<
Allocator
>::template rebind_alloc<node_type> type;
};
template <typename Allocator, typename Value, typename Parameters, typename Box>
class allocators<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>
: public internal_node_alloc<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>::type

View File

@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2018 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)
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_STATIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_STATIC_HPP
#include <boost/geometry/index/detail/rtree/node/weak_dynamic.hpp>
#include <boost/geometry/index/detail/varray.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {

View File

@@ -4,6 +4,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)
@@ -11,6 +15,8 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_VISITOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_VISITOR_HPP
#include <boost/geometry/index/detail/assert.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {

View File

@@ -5,8 +5,8 @@
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2020 Caian Benedicto, Campinas, Brazil.
//
// This file was modified by Oracle on 2019.
// Modifications copyright (c) 2019 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -18,12 +18,15 @@
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/index/detail/algorithms/content.hpp>
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/index/parameters.hpp>
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019.
// Modifications copyright (c) 2019 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -17,7 +17,9 @@
#include <boost/scoped_ptr.hpp>
//#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/visitors/distance_query.hpp>
#include <boost/geometry/index/detail/rtree/visitors/spatial_query.hpp>
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
@@ -65,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;
@@ -79,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;
}
@@ -117,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;
@@ -151,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;
}
@@ -189,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;
};
@@ -280,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)
@@ -296,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) )
@@ -305,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) )
@@ -320,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
{

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2019 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019.
// Modifications copyright (c) 2019 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -27,6 +27,8 @@
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
#include <boost/geometry/index/detail/rtree/node/node.hpp>
#include <boost/geometry/index/detail/rtree/options.hpp>
#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
namespace boost { namespace geometry { namespace index {

View File

@@ -19,7 +19,12 @@
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
#include <boost/geometry/index/detail/algorithms/content.hpp>
#include <boost/geometry/index/detail/rtree/node/concept.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
namespace boost { namespace geometry { namespace index {

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -15,7 +15,16 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
#include <limits>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -17,7 +17,11 @@
#include <iostream>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {

View File

@@ -15,6 +15,15 @@
#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>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
@@ -40,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;
@@ -131,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;
@@ -140,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
@@ -288,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;
@@ -318,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;
@@ -331,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);
}
}
}
@@ -422,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;
}
@@ -537,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

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -21,12 +21,14 @@
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
#include <boost/geometry/index/detail/algorithms/content.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
#include <boost/geometry/index/detail/rtree/options.hpp>
#include <boost/geometry/util/condition.hpp>
namespace boost { namespace geometry { namespace index {

View File

@@ -4,6 +4,10 @@
//
// 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
//
// 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)
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
#include <boost/geometry/index/detail/rtree/node/concept.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019.
// Modifications copyright (c) 2019 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -15,11 +15,13 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
#include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {

View File

@@ -15,13 +15,16 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/predicates.hpp>
#include <boost/geometry/index/parameters.hpp>
namespace boost { namespace geometry { namespace index {
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;
@@ -33,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;
@@ -106,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;
@@ -119,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
{
@@ -157,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();
}
@@ -169,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
@@ -180,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;
}
@@ -200,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

View File

@@ -2,6 +2,10 @@
//
// 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
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -9,11 +13,21 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/aligned_storage.hpp>
//#include <boost/serialization/serialization.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/version.hpp>
//#include <boost/serialization/nvp.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/index/parameters.hpp>
#include <boost/geometry/index/detail/rtree/node/concept.hpp>
#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
// TODO
// how about using the unsigned type capable of storing Max in compile-time versions?
@@ -26,7 +40,13 @@
// each geometry save without this info
// TODO - move to index/detail/serialization.hpp
namespace boost { namespace geometry { namespace index { namespace detail {
namespace boost { namespace geometry { namespace index {
// Forward declaration
template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>
class rtree;
namespace detail {
// TODO - use boost::move?
template<typename T>

View File

@@ -2,8 +2,8 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -15,6 +15,8 @@
#include <type_traits>
#include <boost/geometry/strategies/default_strategy.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail {

View File

@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-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,
@@ -15,13 +15,13 @@
#ifndef BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
#define BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
#include <limits>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/index/detail/exception.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
namespace boost { namespace geometry { namespace index {

View File

@@ -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);
}
/*!

View File

@@ -478,9 +478,10 @@ struct wkt<Geometry, geometry_collection_tag>
static inline void apply(OutputStream& os, Geometry const& geometry,
bool force_closure)
{
output_or_recursive_call(os, geometry, force_closure);
wkt::output_or_recursive_call(os, geometry, force_closure);
}
private:
template
<
typename OutputStream, typename Geom,
@@ -501,7 +502,7 @@ struct wkt<Geometry, geometry_collection_tag>
traits::iter_visit<Geom>::apply([&](auto const& g)
{
output_or_recursive_call(os, g, force_closure);
wkt::output_or_recursive_call(os, g, force_closure);
}, it);
}

View File

@@ -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

Some files were not shown because too many files have changed in this diff Show More