mirror of
https://github.com/boostorg/geometry.git
synced 2026-01-28 07:12:13 +00:00
Merge branch 'develop' into bg-prepare
This commit is contained in:
@@ -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
23
LICENSE_1_0.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
34
example/with_external_libs/CMakeLists.txt
Normal file
34
example/with_external_libs/CMakeLists.txt
Normal 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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
>
|
||||
{};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
{};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
111
include/boost/geometry/core/coordinate_promotion.hpp
Normal file
111
include/boost/geometry/core/coordinate_promotion.hpp
Normal file
@@ -0,0 +1,111 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_CORE_COORDINATE_PROMOTION_HPP
|
||||
#define BOOST_GEOMETRY_CORE_COORDINATE_PROMOTION_HPP
|
||||
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
|
||||
// TODO: move this to a future headerfile implementing traits for these types
|
||||
#include <boost/rational.hpp>
|
||||
#include <boost/multiprecision/cpp_bin_float.hpp>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace traits
|
||||
{
|
||||
|
||||
// todo
|
||||
|
||||
} // namespace traits
|
||||
|
||||
/*!
|
||||
\brief Meta-function converting, if necessary, to "a floating point" type
|
||||
\details
|
||||
- if input type is integer, type is double
|
||||
- else type is input type
|
||||
\ingroup utility
|
||||
*/
|
||||
// TODO: replace with, or call, promoted_to_floating_point
|
||||
template <typename T, typename PromoteIntegerTo = double>
|
||||
struct promote_floating_point
|
||||
{
|
||||
typedef std::conditional_t
|
||||
<
|
||||
std::is_integral<T>::value,
|
||||
PromoteIntegerTo,
|
||||
T
|
||||
> type;
|
||||
};
|
||||
|
||||
// TODO: replace with promoted_to_floating_point
|
||||
template <typename Geometry>
|
||||
struct fp_coordinate_type
|
||||
{
|
||||
typedef typename promote_floating_point
|
||||
<
|
||||
typename coordinate_type<Geometry>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Promote any integral type to double. Floating point
|
||||
// and other user defined types stay as they are, unless specialized.
|
||||
// TODO: we shold add a coordinate_promotion traits for promotion to
|
||||
// floating point or (larger) integer types.
|
||||
template <typename Type>
|
||||
struct promoted_to_floating_point
|
||||
{
|
||||
using type = std::conditional_t
|
||||
<
|
||||
std::is_integral<Type>::value, double, Type
|
||||
>;
|
||||
};
|
||||
|
||||
// Boost.Rational goes to double
|
||||
template <typename T>
|
||||
struct promoted_to_floating_point<boost::rational<T>>
|
||||
{
|
||||
using type = double;
|
||||
};
|
||||
|
||||
// Any Boost.Multiprecision goes to double (for example int128_t),
|
||||
// unless specialized
|
||||
template <typename Backend>
|
||||
struct promoted_to_floating_point<boost::multiprecision::number<Backend>>
|
||||
{
|
||||
using type = double;
|
||||
};
|
||||
|
||||
// Boost.Multiprecision binary floating point numbers are used as FP.
|
||||
template <unsigned Digits>
|
||||
struct promoted_to_floating_point
|
||||
<
|
||||
boost::multiprecision::number
|
||||
<
|
||||
boost::multiprecision::cpp_bin_float<Digits>
|
||||
>
|
||||
>
|
||||
{
|
||||
using type = boost::multiprecision::number
|
||||
<
|
||||
boost::multiprecision::cpp_bin_float<Digits>
|
||||
>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_CORE_COORDINATE_PROMOTION_HPP
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/core/static_assert.hpp>
|
||||
#include <boost/geometry/core/tag.hpp>
|
||||
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||
#include <boost/geometry/util/type_traits_std.hpp>
|
||||
|
||||
|
||||
@@ -94,15 +93,6 @@ struct coordinate_type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
struct fp_coordinate_type
|
||||
{
|
||||
typedef typename promote_floating_point
|
||||
<
|
||||
typename coordinate_type<Geometry>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief assert_coordinate_type_equal, a compile-time check for equality of two coordinate types
|
||||
\ingroup utility
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
107
include/boost/geometry/index/detail/maxmin_heap.hpp
Normal file
107
include/boost/geometry/index/detail/maxmin_heap.hpp
Normal file
@@ -0,0 +1,107 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_MAXMIN_HEAP_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_MAXMIN_HEAP_HPP
|
||||
|
||||
#include <boost/geometry/index/detail/minmax_heap.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail
|
||||
{
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void push_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
minmax_heap_detail::push_heap<max_call, min_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void push_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
minmax_heap_detail::push_heap<max_call, min_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void pop_top_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
pop_heap<max_call, min_call>(first, first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void pop_top_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
pop_heap<max_call, min_call>(first, first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void pop_bottom_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
It bottom = minmax_heap_detail::bottom_heap<max_call>(first, last, comp);
|
||||
pop_heap<max_call, min_call>(first, bottom, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void pop_bottom_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
auto&& comp = std::less<>();
|
||||
It bottom = minmax_heap_detail::bottom_heap<max_call>(first, last, comp);
|
||||
pop_heap<max_call, min_call>(first, bottom, last, comp);
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void make_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::make_heap<max_call, min_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void make_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::make_heap<max_call, min_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline bool is_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::is_heap<max_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline bool is_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::is_heap<max_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline decltype(auto) bottom_maxmin_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return *minmax_heap_detail::bottom_heap<max_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline decltype(auto) bottom_maxmin_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return *minmax_heap_detail::bottom_heap<max_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_MAXMIN_HEAP_HPP
|
||||
519
include/boost/geometry/index/detail/minmax_heap.hpp
Normal file
519
include/boost/geometry/index/detail/minmax_heap.hpp
Normal file
@@ -0,0 +1,519 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_MINMAX_HEAP_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_MINMAX_HEAP_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#ifdef _MSC_VER // msvc and clang-win
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail
|
||||
{
|
||||
|
||||
// Resources:
|
||||
// https://en.wikipedia.org/wiki/Min-max_heap
|
||||
// http://akira.ruc.dk/~keld/teaching/algoritmedesign_f03/Artikler/02/Atkinson86.pdf
|
||||
// https://probablydance.com/2020/08/31/on-modern-hardware-the-min-max-heap-beats-a-binary-heap/
|
||||
// https://stackoverflow.com/questions/6531543/efficient-implementation-of-binary-heaps
|
||||
// https://stackoverflow.com/questions/994593/how-to-do-an-integer-log2-in-c
|
||||
|
||||
namespace minmax_heap_detail
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
using bitsize = std::integral_constant<std::size_t, sizeof(T) * CHAR_BIT>;
|
||||
|
||||
template <typename It>
|
||||
using diff_t = typename std::iterator_traits<It>::difference_type;
|
||||
template <typename It>
|
||||
using val_t = typename std::iterator_traits<It>::value_type;
|
||||
|
||||
// TODO: In C++20 use std::bit_width()
|
||||
|
||||
template <typename T, std::enable_if_t<!std::is_integral<T>::value || (bitsize<T>::value != 32 && bitsize<T>::value != 64), int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
++i;
|
||||
int r = 0;
|
||||
while (i >>= 1) { ++r; }
|
||||
return r;
|
||||
}
|
||||
|
||||
//template <typename T>
|
||||
//inline int level(T i)
|
||||
//{
|
||||
// using std::log2;
|
||||
// return int(log2(i + 1));
|
||||
//}
|
||||
|
||||
#ifdef _MSC_VER // msvc and clang-win
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 32, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse(&r, (unsigned long)(i + 1));
|
||||
return int(r);
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 64, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
unsigned long r = 0;
|
||||
#ifdef _WIN64
|
||||
_BitScanReverse64(&r, (unsigned long long)(i + 1));
|
||||
#else
|
||||
if (_BitScanReverse(&r, (unsigned long)((i + 1) >> 32))) { r += 32; }
|
||||
else { _BitScanReverse(&r, (unsigned long)(i + 1)); }
|
||||
#endif
|
||||
return int(r);
|
||||
}
|
||||
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
// Only available in gcc-10 and clang-10
|
||||
//#elif defined(__has_builtin) && __has_builtin(__builtin_clzl) && __has_builtin(__builtin_clzll)
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 32, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
return 31 - __builtin_clzl((unsigned long)(i + 1));
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 64, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
return 63 - __builtin_clzll((unsigned long long)(i + 1));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 32, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
++i;
|
||||
int r = 0;
|
||||
if (i >= 65536) { r += 16; i >>= 16; }
|
||||
if (i >= 256) { r += 8; i >>= 8; }
|
||||
if (i >= 16) { r += 4; i >>= 4; }
|
||||
if (i >= 4) { r += 2; i >>= 2; }
|
||||
if (i >= 2) { r += 1; i >>= 1; }
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 64, int> = 0>
|
||||
inline int level(T i)
|
||||
{
|
||||
++i;
|
||||
int r = 0;
|
||||
if (i >= 4294967296ll) { r += 32; i >>= 32; }
|
||||
if (i >= 65536ll) { r += 16; i >>= 16; }
|
||||
if (i >= 256ll) { r += 8; i >>= 8; }
|
||||
if (i >= 16ll) { r += 4; i >>= 4; }
|
||||
if (i >= 4ll) { r += 2; i >>= 2; }
|
||||
if (i >= 2ll) { r += 1; i >>= 1; }
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// min/max functions only differ in the order of arguments in comp
|
||||
struct min_call
|
||||
{
|
||||
template <typename Compare, typename T1, typename T2>
|
||||
bool operator()(Compare&& comp, T1 const& v1, T2 const& v2) const
|
||||
{
|
||||
return comp(v1, v2);
|
||||
}
|
||||
};
|
||||
|
||||
struct max_call
|
||||
{
|
||||
template <typename Compare, typename T1, typename T2>
|
||||
bool operator()(Compare&& comp, T1 const& v1, T2 const& v2) const
|
||||
{
|
||||
return comp(v2, v1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Call, typename It, typename Compare>
|
||||
inline void push_heap2(It first, diff_t<It> c, val_t<It> val, Compare comp)
|
||||
{
|
||||
while (c > 2)
|
||||
{
|
||||
diff_t<It> const g = (c - 3) >> 2; // grandparent index
|
||||
if (! Call()(comp, val, *(first + g)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
*(first + c) = std::move(*(first + g));
|
||||
c = g;
|
||||
}
|
||||
|
||||
*(first + c) = std::move(val);
|
||||
}
|
||||
|
||||
template <typename MinCall, typename MaxCall, typename It, typename Compare>
|
||||
inline void push_heap1(It first, diff_t<It> c, val_t<It> val, Compare comp)
|
||||
{
|
||||
diff_t<It> const p = (c - 1) >> 1; // parent index
|
||||
if (MinCall()(comp, *(first + p), val))
|
||||
{
|
||||
*(first + c) = std::move(*(first + p));
|
||||
return push_heap2<MaxCall>(first, p, std::move(val), comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return push_heap2<MinCall>(first, c, std::move(val), comp);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MinCall, typename MaxCall, typename It, typename Compare>
|
||||
inline void push_heap(It first, It last, Compare comp)
|
||||
{
|
||||
diff_t<It> const size = last - first;
|
||||
if (size < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
diff_t<It> c = size - 1; // back index
|
||||
val_t<It> val = std::move(*(first + c));
|
||||
if (level(c) % 2 == 0) // is min level
|
||||
{
|
||||
push_heap1<MinCall, MaxCall>(first, c, std::move(val), comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
push_heap1<MaxCall, MinCall>(first, c, std::move(val), comp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Call, typename It, typename Compare>
|
||||
inline diff_t<It> pick_grandchild4(It first, diff_t<It> f, Compare comp)
|
||||
{
|
||||
It it = first + f;
|
||||
diff_t<It> m1 = Call()(comp, *(it), *(it + 1)) ? f : f + 1;
|
||||
diff_t<It> m2 = Call()(comp, *(it + 2), *(it + 3)) ? f + 2 : f + 3;
|
||||
return Call()(comp, *(first + m1), *(first + m2)) ? m1 : m2;
|
||||
}
|
||||
|
||||
//template <typename Call, typename It, typename Compare>
|
||||
//inline diff_t<It> pick_descendant(It first, diff_t<It> f, diff_t<It> l, Compare comp)
|
||||
//{
|
||||
// diff_t<It> m = f;
|
||||
// for (++f; f != l; ++f)
|
||||
// {
|
||||
// if (Call()(comp, *(first + f), *(first + m)))
|
||||
// {
|
||||
// m = f;
|
||||
// }
|
||||
// }
|
||||
// return m;
|
||||
//}
|
||||
|
||||
template <typename Call, typename It, typename Compare>
|
||||
inline void pop_heap1(It first, diff_t<It> p, diff_t<It> size, val_t<It> val, Compare comp)
|
||||
{
|
||||
if (size >= 7) // grandparent of 4 grandchildren is possible
|
||||
{
|
||||
diff_t<It> const last_g = (size - 3) >> 2; // grandparent of the element behind back
|
||||
while (p < last_g) // p is grandparent of 4 grandchildren
|
||||
{
|
||||
diff_t<It> const ll = 4 * p + 3;
|
||||
diff_t<It> const m = pick_grandchild4<Call>(first, ll, comp);
|
||||
|
||||
if (! Call()(comp, *(first + m), val))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
*(first + p) = std::move(*(first + m));
|
||||
|
||||
diff_t<It> par = (m - 1) >> 1;
|
||||
if (Call()(comp, *(first + par), val))
|
||||
{
|
||||
using std::swap;
|
||||
swap(*(first + par), val);
|
||||
}
|
||||
|
||||
p = m;
|
||||
}
|
||||
}
|
||||
|
||||
if (size >= 2 && p <= ((size - 2) >> 1)) // at least one child
|
||||
{
|
||||
diff_t<It> const l = 2 * p + 1;
|
||||
diff_t<It> m = l; // left child
|
||||
if (size >= 3 && p <= ((size - 3) >> 1)) // at least two children
|
||||
{
|
||||
// m = left child
|
||||
diff_t<It> m2 = l + 1; // right child
|
||||
if (size >= 4 && p <= ((size - 4) >> 2)) // at least two children and one grandchild
|
||||
{
|
||||
diff_t<It> const ll = 2 * l + 1;
|
||||
m = ll; // left most grandchild
|
||||
// m2 = right child
|
||||
if (size >= 5 && p <= ((size - 5) >> 2)) // at least two children and two grandchildren
|
||||
{
|
||||
m = Call()(comp, *(first + ll), *(first + ll + 1)) ? ll : (ll + 1); // greater of the left grandchildren
|
||||
// m2 = right child
|
||||
if (size >= 6 && p <= ((size - 6) >> 2)) // at least two children and three grandchildren
|
||||
{
|
||||
// m = greater of the left grandchildren
|
||||
m2 = ll + 2; // third grandchild
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Call()(comp, *(first + m), *(first + m2)) ? m : m2;
|
||||
}
|
||||
|
||||
if (Call()(comp, *(first + m), val))
|
||||
{
|
||||
*(first + p) = std::move(*(first + m));
|
||||
|
||||
if (m >= 3 && p <= ((m - 3) >> 2)) // is p grandparent of m
|
||||
{
|
||||
diff_t<It> par = (m - 1) >> 1;
|
||||
if (Call()(comp, *(first + par), val))
|
||||
{
|
||||
using std::swap;
|
||||
swap(*(first + par), val);
|
||||
}
|
||||
}
|
||||
|
||||
p = m;
|
||||
}
|
||||
}
|
||||
|
||||
*(first + p) = std::move(val);
|
||||
}
|
||||
|
||||
template <typename MinCall, typename MaxCall, typename It, typename Compare>
|
||||
inline void pop_heap(It first, It el, It last, Compare comp)
|
||||
{
|
||||
diff_t<It> size = last - first;
|
||||
if (size < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
--last;
|
||||
val_t<It> val = std::move(*last);
|
||||
*last = std::move(*el);
|
||||
|
||||
// Ignore the last element
|
||||
--size;
|
||||
|
||||
diff_t<It> p = el - first;
|
||||
if (level(p) % 2 == 0) // is min level
|
||||
{
|
||||
pop_heap1<MinCall>(first, p, size, std::move(val), comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
pop_heap1<MaxCall>(first, p, size, std::move(val), comp);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MinCall, typename MaxCall, typename It, typename Compare>
|
||||
inline void make_heap(It first, It last, Compare comp)
|
||||
{
|
||||
diff_t<It> size = last - first;
|
||||
diff_t<It> p = size / 2;
|
||||
if (p <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int level_p = level(p - 1);
|
||||
diff_t<It> level_f = (diff_t<It>(1) << level_p) - 1;
|
||||
while (p > 0)
|
||||
{
|
||||
--p;
|
||||
val_t<It> val = std::move(*(first + p));
|
||||
if (level_p % 2 == 0) // is min level
|
||||
{
|
||||
pop_heap1<MinCall>(first, p, size, std::move(val), comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
pop_heap1<MaxCall>(first, p, size, std::move(val), comp);
|
||||
}
|
||||
|
||||
if (p == level_f)
|
||||
{
|
||||
--level_p;
|
||||
level_f >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Call, typename It, typename Compare>
|
||||
inline bool is_heap(It first, It last, Compare comp)
|
||||
{
|
||||
diff_t<It> const size = last - first;
|
||||
diff_t<It> pow2 = 4;
|
||||
bool is_min_level = false;
|
||||
for (diff_t<It> i = 1; i < size; ++i)
|
||||
{
|
||||
if (i == pow2 - 1)
|
||||
{
|
||||
pow2 *= 2;
|
||||
is_min_level = ! is_min_level;
|
||||
}
|
||||
|
||||
diff_t<It> const p = (i - 1) >> 1;
|
||||
if (is_min_level)
|
||||
{
|
||||
if (Call()(comp, *(first + p), *(first + i)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Call()(comp, *(first + i), *(first + p)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= 3)
|
||||
{
|
||||
diff_t<It> const g = (p - 1) >> 1;
|
||||
if (is_min_level)
|
||||
{
|
||||
if (Call()(comp, *(first + i), *(first + g)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Call()(comp, *(first + g), *(first + i)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Call, typename It, typename Compare>
|
||||
inline It bottom_heap(It first, It last, Compare comp)
|
||||
{
|
||||
diff_t<It> const size = last - first;
|
||||
return size <= 1 ? first :
|
||||
size == 2 ? (first + 1) :
|
||||
Call()(comp, *(first + 1), *(first + 2)) ? (first + 2) : (first + 1);
|
||||
}
|
||||
|
||||
} // namespace minmax_heap_detail
|
||||
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void push_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
minmax_heap_detail::push_heap<min_call, max_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void push_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
minmax_heap_detail::push_heap<min_call, max_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void pop_top_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
pop_heap<min_call, max_call>(first, first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void pop_top_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
pop_heap<min_call, max_call>(first, first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void pop_bottom_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
It bottom = minmax_heap_detail::bottom_heap<min_call>(first, last, comp);
|
||||
pop_heap<min_call, max_call>(first, bottom, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void pop_bottom_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
auto&& comp = std::less<>();
|
||||
It bottom = minmax_heap_detail::bottom_heap<min_call>(first, last, comp);
|
||||
pop_heap<min_call, max_call>(first, bottom, last, comp);
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline void make_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::make_heap<min_call, max_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline void make_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::make_heap<min_call, max_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline bool is_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::is_heap<min_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline bool is_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return minmax_heap_detail::is_heap<min_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
template <typename It, typename Compare>
|
||||
inline decltype(auto) bottom_minmax_heap(It first, It last, Compare comp)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return *minmax_heap_detail::bottom_heap<min_call>(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
inline decltype(auto) bottom_minmax_heap(It first, It last)
|
||||
{
|
||||
using namespace minmax_heap_detail;
|
||||
return *minmax_heap_detail::bottom_heap<min_call>(first, last, std::less<>());
|
||||
}
|
||||
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_MINMAX_HEAP_HPP
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
|
||||
150
include/boost/geometry/index/detail/priority_dequeue.hpp
Normal file
150
include/boost/geometry/index/detail/priority_dequeue.hpp
Normal file
@@ -0,0 +1,150 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_PRIORITY_DEQUEUE_HPP
|
||||
#define BOOST_GEOMETRY_INDEX_DETAIL_PRIORITY_DEQUEUE_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/geometry/index/detail/maxmin_heap.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace index { namespace detail
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename T,
|
||||
typename Container = std::vector<T>,
|
||||
typename Compare = std::less<typename Container::value_type>
|
||||
>
|
||||
class priority_dequeue
|
||||
{
|
||||
public:
|
||||
using container_type = Container;
|
||||
using value_compare = Compare;
|
||||
using value_type = typename Container::value_type;
|
||||
using size_type = typename Container::size_type;
|
||||
using reference = typename Container::reference;
|
||||
using const_reference = typename Container::const_reference;
|
||||
|
||||
priority_dequeue()
|
||||
: c(), comp()
|
||||
{}
|
||||
|
||||
explicit priority_dequeue(Compare const& compare)
|
||||
: c(), comp(compare)
|
||||
{}
|
||||
|
||||
priority_dequeue(Compare const& compare, Container const& cont)
|
||||
: c(cont), comp(compare)
|
||||
{
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
priority_dequeue(Compare const& compare, Container&& cont)
|
||||
: c(std::move(cont)), comp(compare)
|
||||
{
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
priority_dequeue(It first, It last)
|
||||
: c(first, last), comp()
|
||||
{
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
priority_dequeue(It first, It last, Compare const& compare)
|
||||
: c(first, last), comp(compare)
|
||||
{
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
priority_dequeue(It first, It last, Compare const& compare, Container const& cont)
|
||||
: c(cont), comp(compare)
|
||||
{
|
||||
c.insert(first, last);
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
priority_dequeue(It first, It last, Compare const& compare, Container&& cont)
|
||||
: c(std::move(cont)), comp(compare)
|
||||
{
|
||||
c.insert(first, last);
|
||||
make_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
const_reference top() const
|
||||
{
|
||||
return *c.begin();
|
||||
}
|
||||
|
||||
const_reference bottom() const
|
||||
{
|
||||
return bottom_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
void push(const value_type& value)
|
||||
{
|
||||
c.push_back(value);
|
||||
push_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
void push(value_type&& value)
|
||||
{
|
||||
c.push_back(std::move(value));
|
||||
push_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
void emplace(Args&& ...args)
|
||||
{
|
||||
c.emplace_back(std::forward<Args>(args)...);
|
||||
push_maxmin_heap(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
void pop_top()
|
||||
{
|
||||
pop_top_maxmin_heap(c.begin(), c.end(), comp);
|
||||
c.pop_back();
|
||||
}
|
||||
|
||||
void pop_bottom()
|
||||
{
|
||||
pop_bottom_maxmin_heap(c.begin(), c.end(), comp);
|
||||
c.pop_back();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return c.empty();
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return c.size();
|
||||
}
|
||||
|
||||
void swap(priority_dequeue& other)
|
||||
{
|
||||
using std::swap;
|
||||
std::swap(c, other.c);
|
||||
std::swap(comp, other.comp);
|
||||
}
|
||||
|
||||
protected:
|
||||
Container c;
|
||||
Compare comp;
|
||||
};
|
||||
|
||||
}}}} // namespace boost::geometry::index::detail
|
||||
|
||||
#endif // BOOST_GEOMETRY_INDEX_DETAIL_PRIORITY_DEQUEUE_HPP
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user