Merge branch 'develop' of https://github.com/boostorg/geometry into feature/shortest_points_new_strategies

This commit is contained in:
Vissarion Fisikopoulos 2021-11-05 09:24:07 +02:00
commit ea0df6db82
62 changed files with 1554 additions and 974 deletions

View File

@ -0,0 +1,34 @@
# Boost.Geometry
# Example CMakeLists.txt building the Boost.Geometry with wxWidget example
#
# Copyright (c) 2021-2021 Barend Gehrels, Amsterdam, the Netherlands.
# Use, modification and distribution is subject to the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
cmake_minimum_required(VERSION 3.10)
project(with_external_libs)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# Set BOOST_ROOT in your environment (this is cmake default)
find_package(Boost)
# Set WX_ROOT, similarly, also in your environment
set(WX_ROOT $ENV{WX_ROOT})
message(STATUS "Using wxWidgets from this folder: " $ENV{WX_ROOT})
# WX Widgets
link_directories(${WX_ROOT}/lib)
add_executable(wx x04_wxwidgets_world_mapper.cpp)
target_include_directories(wx PRIVATE ${Boost_INCLUDE_DIRS})
target_include_directories(wx PRIVATE ${WX_ROOT}/include)
target_include_directories(wx PRIVATE ${WX_ROOT}/include/wx-3.1)
# WX configuration (get the values using wx-config --cxxflags and wx-config --libs)
target_compile_definitions(wx PRIVATE WXUSINGDLL __WXGTK2__ __WXGTK__)
target_link_libraries(wx PRIVATE wx_gtk2u_html-3.1 wx_gtk2u_core-3.1 wx_baseu_net-3.1 wx_baseu-3.1)

View File

@ -1,115 +1,62 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // Boost.Geometry
// //
// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2010-2021 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// //
// wxWidgets World Mapper example // 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 <fstream>
#include <sstream> #include <sstream>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/geometry/geometry.hpp> #include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp> #include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.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/point.hpp>
#include <boost/geometry/geometries/register/ring.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/wx.h"
#include "wx/math.h" #include "wx/math.h"
#include "wx/stockitem.h" #include "wx/stockitem.h"
#ifdef EXAMPLE_WX_USE_GRAPHICS_CONTEXT #ifdef EXAMPLE_WX_USE_GRAPHICS_CONTEXT
#include "wx/graphics.h" #include "wx/graphics.h"
#include "wx/dcgraph.h" #include "wx/dcgraph.h"
#endif #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> boost::geometry::model::polygon<point_2d>
> country_type; >;
// Adapt wxWidgets points to Boost.Geometry points such that they can be used // Adapt wxWidgets points to Boost.Geometry points such that they can be used
// in e.g. transformations (see below) // in e.g. transformations (see below)
BOOST_GEOMETRY_REGISTER_POINT_2D(wxPoint, int, cs::cartesian, x, y) BOOST_GEOMETRY_REGISTER_POINT_2D(wxPoint, int, cs::cartesian, x, y)
BOOST_GEOMETRY_REGISTER_POINT_2D(wxRealPoint, double, 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 // Read an ASCII file containing WKT's
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -161,26 +108,29 @@ private:
void OnPaint(wxPaintEvent& ); void OnPaint(wxPaintEvent& );
void OnMouseMove(wxMouseEvent&); void OnMouseMove(wxMouseEvent&);
typedef boost::geometry::strategy::transform::map_transformer using map_transformer_type = boost::geometry::strategy::transform::map_transformer
< <
double, 2, 2, double, 2, 2,
true, true 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 double, 2, 2
> inverse_transformer_type; >;
boost::shared_ptr<map_transformer_type> m_map_transformer; std::shared_ptr<map_transformer_type> m_map_transformer;
boost::shared_ptr<inverse_transformer_type> m_inverse_transformer; std::shared_ptr<inverse_transformer_type> m_inverse_transformer;
boost::geometry::model::box<point_2d> m_box; boost::geometry::model::box<point_2d> m_box;
std::vector<country_type> m_countries; std::vector<country_type> m_countries;
int m_focus; int m_focus = -1;
wxBrush m_orange; wxBrush m_orange = wxBrush(wxColour(255, 128, 0), wxBRUSHSTYLE_SOLID);
wxFrame* m_owner; 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() DECLARE_EVENT_TABLE()
}; };
@ -244,19 +194,14 @@ void HelloWorldFrame::OnCloseWindow(wxCloseEvent& )
HelloWorldCanvas::HelloWorldCanvas(wxFrame *frame) HelloWorldCanvas::HelloWorldCanvas(wxFrame *frame)
: wxWindow(frame, wxID_ANY) : wxWindow(frame, wxID_ANY)
, m_owner(frame) , m_owner(frame)
, m_focus(-1)
{ {
boost::geometry::assign_inverse(m_box); boost::geometry::assign_inverse(m_box);
read_wkt("../data/world.wkt", m_countries, m_box); read_wkt("../data/world.wkt", m_countries, m_box);
m_orange = wxBrush(wxColour(255, 128, 0), wxSOLID);
} }
void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event) void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event)
{ {
namespace bg = boost::geometry;
if (m_inverse_transformer) if (m_inverse_transformer)
{ {
// Boiler-plate wxWidgets code // Boiler-plate wxWidgets code
@ -264,19 +209,21 @@ void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event)
PrepareDC(dc); PrepareDC(dc);
m_owner->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; point_2d point;
bg::transform(event.GetPosition(), point, *m_inverse_transformer); boost::geometry::transform(event.GetPosition(), point,
*m_inverse_transformer);
// Determine selected object // Determine selected object
int i = 0; int i = 0;
int previous_focus = m_focus; int previous_focus = m_focus;
m_focus = -1; 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; m_focus = i;
break;
} }
i++; i++;
} }
@ -287,7 +234,7 @@ void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event)
// Undraw old focus // Undraw old focus
if (previous_focus >= 0) if (previous_focus >= 0)
{ {
dc.SetBrush(*wxWHITE_BRUSH); dc.SetBrush(m_green);
DrawCountry(dc, m_countries[previous_focus]); DrawCountry(dc, m_countries[previous_focus]);
} }
// Draw new focus // Draw new focus
@ -309,6 +256,11 @@ void HelloWorldCanvas::OnMouseMove(wxMouseEvent &event)
void HelloWorldCanvas::OnPaint(wxPaintEvent& ) void HelloWorldCanvas::OnPaint(wxPaintEvent& )
{ {
if (m_countries.empty())
{
return;
}
#if defined(EXAMPLE_WX_USE_GRAPHICS_CONTEXT) #if defined(EXAMPLE_WX_USE_GRAPHICS_CONTEXT)
wxPaintDC pdc(this); wxPaintDC pdc(this);
wxGCDC gdc(pdc); wxGCDC gdc(pdc);
@ -340,11 +292,12 @@ void HelloWorldCanvas::DrawCountries(wxDC& dc)
{ {
namespace bg = boost::geometry; namespace bg = boost::geometry;
dc.SetBackground(*wxLIGHT_GREY_BRUSH); dc.SetBackground(m_blue);
dc.Clear(); dc.Clear();
BOOST_FOREACH(country_type const& country, m_countries) for (country_type const& country : m_countries)
{ {
dc.SetBrush(m_green);
DrawCountry(dc, country); DrawCountry(dc, country);
} }
if (m_focus != -1) if (m_focus != -1)
@ -357,27 +310,23 @@ void HelloWorldCanvas::DrawCountries(wxDC& dc)
void HelloWorldCanvas::DrawCountry(wxDC& dc, country_type const& country) void HelloWorldCanvas::DrawCountry(wxDC& dc, country_type const& country)
{ {
namespace bg = boost::geometry; for (auto const& poly : country)
BOOST_FOREACH(bg::model::polygon<point_2d> const& poly, country)
{ {
// Use only exterior ring, holes are (for the moment) ignored. This would need // Use only exterior ring, holes are (for the moment) ignored.
// a holey-polygon compatible wx object // This would need a holey-polygon compatible wx object
std::size_t n = boost::size(bg::exterior_ring(poly)); // Define a Boost.Geometry ring of wxPoints
// Behind the scenes that is a vector, and a vector has .data(),
boost::scoped_array<wxPoint> points(new wxPoint[n]); // can be used for the *wxPoint pointer needed for wxWidget DrawPolygon
boost::geometry::model::ring<wxPoint> ring;
wxPointPointerPair pair = std::make_pair(points.get(), points.get() + n); boost::geometry::transform(boost::geometry::exterior_ring(poly), ring,
bg::transform(bg::exterior_ring(poly), pair, *m_map_transformer); *m_map_transformer);
dc.DrawPolygon(ring.size(), ring.data());
dc.DrawPolygon(n, points.get());
} }
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(HelloWorldFrame, wxFrame) BEGIN_EVENT_TABLE(HelloWorldFrame, wxFrame)
EVT_CLOSE(HelloWorldFrame::OnCloseWindow) EVT_CLOSE(HelloWorldFrame::OnCloseWindow)
EVT_MENU(wxID_EXIT, HelloWorldFrame::OnExit) EVT_MENU(wxID_EXIT, HelloWorldFrame::OnExit)

View File

@ -1,23 +0,0 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
wxWidgets World Mapper example
It will show a basic wxWidgets window, displaying world countries, highlighting the country under
the mouse, and indicating position of the mouse in latitude/longitude and in pixels.
To compile this program:
Install wxWidgets (if not done before)
Using Linux/gcc
- check if installation is OK, http://wiki.wxwidgets.org/Installing_and_configuring_under_Ubuntu
- compile using e.g. gcc -o x04_wxwidgets -I../../../.. x04_wxwidgets_world_mapper.cpp `wx-config --cxxflags` `wx-config --libs`

View File

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

View File

@ -11,8 +11,14 @@
#define BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP #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/clear.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.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/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/cs.hpp>
@ -20,6 +26,8 @@
#include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.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/default_strategy.hpp>
#include <boost/geometry/strategies/densify/cartesian.hpp> #include <boost/geometry/strategies/densify/cartesian.hpp>
#include <boost/geometry/strategies/densify/geographic.hpp> #include <boost/geometry/strategies/densify/geographic.hpp>
@ -28,11 +36,6 @@
#include <boost/geometry/util/condition.hpp> #include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.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 namespace boost { namespace geometry
{ {
@ -146,6 +149,15 @@ struct densify_ring<true, false>
: densify_range<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 }} // namespace detail::densify
#endif // DOXYGEN_NO_DETAIL #endif // DOXYGEN_NO_DETAIL
@ -167,6 +179,26 @@ struct densify
: not_implemented<Tag1, Tag2> : 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> template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, linestring_tag, linestring_tag> struct densify<Geometry, GeometryOut, linestring_tag, linestring_tag>
: geometry::detail::densify::densify_range<> : geometry::detail::densify::densify_range<>
@ -328,9 +360,9 @@ struct densify<default_strategy, false>
} // namespace resolve_strategy } // namespace resolve_strategy
namespace resolve_variant { namespace resolve_dynamic {
template <typename Geometry> template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct densify struct densify
{ {
template <typename Distance, typename Strategy> template <typename Distance, typename Strategy>
@ -346,43 +378,48 @@ struct densify
} }
}; };
template <BOOST_VARIANT_ENUM_PARAMS(typename T)> template <typename Geometry>
struct densify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > 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> template <typename Distance, typename Strategy>
static inline void static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry, apply(Geometry const& geometry,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out, Geometry& out,
Distance const& max_distance, Distance const& max_distance,
Strategy const& strategy) Strategy const& strategy)
{ {
boost::apply_visitor( traits::visit<Geometry>::apply([&](auto const& g)
visitor<Distance, Strategy>(max_distance, strategy), {
geometry, using geom_t = util::remove_cref_t<decltype(g)>;
out 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); geometry::clear(out);
resolve_variant::densify resolve_dynamic::densify
< <
Geometry Geometry
>::apply(geometry, out, max_distance, strategy); >::apply(geometry, out, max_distance, strategy);

View File

@ -120,14 +120,14 @@ public:
decltype(strategies.distance(point, range)) decltype(strategies.distance(point, range))
>::apply(strategies.distance(point, range)); >::apply(strategies.distance(point, range));
auto it_pair = point_to_point_range::apply(point, auto closest_segment = point_to_point_range::apply(point,
boost::begin(range), boost::begin(range),
boost::end(range), boost::end(range),
comparable_distance, comparable_distance,
cd_min); cd_min);
auto closest_point = strategies.closest_points(point, range) auto closest_point = strategies.closest_points(point, range)
.apply(point, it_pair->first, it_pair->second); .apply(point, *closest_segment.first, *closest_segment.second);
set_segment_from_points::apply(point, closest_point, shortest_seg); set_segment_from_points::apply(point, closest_point, shortest_seg);
} }

View File

@ -98,7 +98,7 @@ struct input_geometry_collection_proxy
{ {
detail::visit_breadth_first([&](auto const& g) detail::visit_breadth_first([&](auto const& g)
{ {
call_for_non_boxes(g, fun); input_geometry_collection_proxy::call_for_non_boxes(g, fun);
return true; return true;
}, m_geometry); }, m_geometry);
@ -262,7 +262,7 @@ struct convex_hull<GeometryCollection, geometry_collection_tag>
std::vector<ring_type> box_rings; std::vector<ring_type> box_rings;
detail::visit_breadth_first([&](auto const& g) detail::visit_breadth_first([&](auto const& g)
{ {
add_ring_for_box(box_rings, g, strategy); convex_hull::add_ring_for_box(box_rings, g, strategy);
return true; return true;
}, geometry); }, geometry);

View File

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

View File

@ -7,9 +7,9 @@
// This file was modified by Oracle on 2014-2021. // This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates. // 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 Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // (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_to_linear.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.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/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/geometry_to_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_segment.hpp> #include <boost/geometry/algorithms/detail/distance/segment_to_segment.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp> #include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>

View File

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

View File

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

View File

@ -6,9 +6,9 @@
// This file was modified by Oracle on 2015-2021. // This file was modified by Oracle on 2015-2021.
// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates. // 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 Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // (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/areal.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.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/linear.hpp>
#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp> #include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>
#include <boost/geometry/algorithms/detail/envelope/point.hpp> #include <boost/geometry/algorithms/detail/envelope/point.hpp>

View File

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

View File

@ -39,8 +39,6 @@
#include <boost/geometry/views/detail/closed_clockwise_view.hpp> #include <boost/geometry/views/detail/closed_clockwise_view.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/spherical/ssf.hpp>
#include <boost/geometry/strategies/normalize.hpp> #include <boost/geometry/strategies/normalize.hpp>
@ -48,34 +46,17 @@
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
// Since these vectors (though ray would be a better name) are used in the
// implementation of equals() for Areal geometries the internal representation
// should be consistent with the side strategy.
template
<
typename T,
typename Geometry,
typename SideStrategy,
typename CSTag = typename cs_tag<Geometry>::type
>
struct collected_vector
: nyi::not_implemented_tag
{};
// compatible with side_robust cartesian strategy template <typename T>
template <typename T, typename Geometry, typename CT, typename CSTag> struct collected_vector_cartesian
struct collected_vector
<
T, Geometry, strategy::side::side_robust<CT>, CSTag
>
{ {
typedef T type; typedef T type;
inline collected_vector() inline collected_vector_cartesian()
{} {}
inline collected_vector(T const& px, T const& py, inline collected_vector_cartesian(T const& px, T const& py,
T const& pdx, T const& pdy) T const& pdx, T const& pdy)
: x(px) : x(px)
, y(py) , y(py)
, dx(pdx) , dx(pdx)
@ -85,7 +66,7 @@ struct collected_vector
{} {}
template <typename Point> template <typename Point>
inline collected_vector(Point const& p1, Point const& p2) inline collected_vector_cartesian(Point const& p1, Point const& p2)
: x(get<0>(p1)) : x(get<0>(p1))
, y(get<1>(p1)) , y(get<1>(p1))
, dx(get<0>(p2) - x) , dx(get<0>(p2) - x)
@ -96,8 +77,7 @@ struct collected_vector
bool normalize() bool normalize()
{ {
T magnitude = math::sqrt( T magnitude = math::sqrt(boost::numeric_cast<T>(dx * dx + dy * dy));
boost::numeric_cast<T>(dx * dx + dy * dy));
// NOTE: shouldn't here math::equals() be called? // NOTE: shouldn't here math::equals() be called?
if (magnitude > 0) if (magnitude > 0)
@ -111,7 +91,7 @@ struct collected_vector
} }
// For sorting // For sorting
inline bool operator<(collected_vector const& other) const inline bool operator<(collected_vector_cartesian const& other) const
{ {
if (math::equals(x, other.x)) if (math::equals(x, other.x))
{ {
@ -128,13 +108,13 @@ struct collected_vector
return x < other.x; return x < other.x;
} }
inline bool next_is_collinear(collected_vector const& other) const inline bool next_is_collinear(collected_vector_cartesian const& other) const
{ {
return same_direction(other); return same_direction(other);
} }
// For std::equals // For std::equals
inline bool operator==(collected_vector const& other) const inline bool operator==(collected_vector_cartesian const& other) const
{ {
return math::equals(x, other.x) return math::equals(x, other.x)
&& math::equals(y, other.y) && math::equals(y, other.y)
@ -142,7 +122,7 @@ struct collected_vector
} }
private: private:
inline bool same_direction(collected_vector const& other) const inline bool same_direction(collected_vector_cartesian const& other) const
{ {
// For high precision arithmetic, we have to be // For high precision arithmetic, we have to be
// more relaxed then using == // more relaxed then using ==
@ -157,49 +137,35 @@ private:
//T dx_0, dy_0; //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 // Compatible with spherical_side_formula which currently
// is the default spherical_equatorial and geographic strategy // is the default spherical_equatorial and geographic strategy
// so CSTag is spherical_equatorial_tag or geographic_tag // so CSTag is spherical_equatorial_tag or geographic_tag
template <typename T, typename Geometry, typename CT, typename CSTag> template <typename T, typename Point>
struct collected_vector struct collected_vector_spherical
<
T, Geometry, strategy::side::spherical_side_formula<CT>, CSTag
>
{ {
typedef T type; typedef T type;
typedef typename geometry::detail::cs_angular_units<Geometry>::type units_type;
typedef model::point<T, 2, cs::spherical_equatorial<units_type> > point_type;
typedef model::point<T, 3, cs::cartesian> vector_type; typedef model::point<T, 3, cs::cartesian> vector_type;
collected_vector() collected_vector_spherical()
{} {}
template <typename Point> collected_vector_spherical(Point const& p1, Point const& p2)
collected_vector(Point const& p1, Point const& p2)
: origin(get<0>(p1), get<1>(p1)) : origin(get<0>(p1), get<1>(p1))
{ {
origin = detail::return_normalized<point_type>( origin = detail::return_normalized<Point>(
origin, origin,
strategy::normalize::spherical_point()); strategy::normalize::spherical_point());
using namespace geometry::formula; using namespace geometry::formula;
prev = sph_to_cart3d<vector_type>(p1); prev = sph_to_cart3d<vector_type>(p1);
next = sph_to_cart3d<vector_type>(p2); next = sph_to_cart3d<vector_type>(p2);
direction = cross_product(prev, next); cross = direction = cross_product(prev, next);
} }
bool normalize() bool normalize()
{ {
T magnitude_sqr = dot_product(direction, direction); T const magnitude_sqr = dot_product(direction, direction);
// NOTE: shouldn't here math::equals() be called? // NOTE: shouldn't here math::equals() be called?
if (magnitude_sqr > 0) if (magnitude_sqr > 0)
@ -211,7 +177,7 @@ struct collected_vector
return false; return false;
} }
bool operator<(collected_vector const& other) const bool operator<(collected_vector_spherical const& other) const
{ {
if (math::equals(get<0>(origin), get<0>(other.origin))) if (math::equals(get<0>(origin), get<0>(other.origin)))
{ {
@ -235,13 +201,13 @@ struct collected_vector
// For consistency with side and intersection strategies used by relops // For consistency with side and intersection strategies used by relops
// IMPORTANT: this method should be called for previous vector // IMPORTANT: this method should be called for previous vector
// and next vector should be passed as parameter // and next vector should be passed as parameter
bool next_is_collinear(collected_vector const& other) const bool next_is_collinear(collected_vector_spherical const& other) const
{ {
return formula::sph_side_value(direction, other.next) == 0; return formula::sph_side_value(cross, other.next) == 0;
} }
// For std::equals // For std::equals
bool operator==(collected_vector const& other) const bool operator==(collected_vector_spherical const& other) const
{ {
return math::equals(get<0>(origin), get<0>(other.origin)) return math::equals(get<0>(origin), get<0>(other.origin))
&& math::equals(get<1>(origin), get<1>(other.origin)) && math::equals(get<1>(origin), get<1>(other.origin))
@ -250,76 +216,57 @@ struct collected_vector
private: private:
// For consistency with side and intersection strategies used by relops // For consistency with side and intersection strategies used by relops
bool is_collinear(collected_vector const& other) const // NOTE: alternative would be to equal-compare direction's coordinates
// or to check if dot product of directions is equal to 1.
bool is_collinear(collected_vector_spherical const& other) const
{ {
return formula::sph_side_value(direction, other.prev) == 0 return formula::sph_side_value(cross, other.prev) == 0
&& formula::sph_side_value(direction, other.next) == 0; && formula::sph_side_value(cross, other.next) == 0;
} }
/*bool same_direction(collected_vector const& other) const Point origin; // used for sorting and equality check
{
return math::equals_with_epsilon(get<0>(direction), get<0>(other.direction))
&& math::equals_with_epsilon(get<1>(direction), get<1>(other.direction))
&& math::equals_with_epsilon(get<2>(direction), get<2>(other.direction));
}*/
point_type origin; // used for sorting and equality check
vector_type direction; // used for sorting, only in operator< vector_type direction; // used for sorting, only in operator<
vector_type cross; // used for sorting, used for collinearity check
vector_type prev; // used for collinearity check, only in operator== vector_type prev; // used for collinearity check, only in operator==
vector_type next; // used for collinearity check vector_type next; // used for collinearity check
}; };
// Specialization for spherical polar // Version for spherical polar
template <typename T, typename Geometry, typename CT> template <typename T, typename Point>
struct collected_vector struct collected_vector_polar
< : public collected_vector_spherical<T, Point>
T, Geometry,
strategy::side::spherical_side_formula<CT>,
spherical_polar_tag
>
: public collected_vector
<
T, Geometry,
strategy::side::spherical_side_formula<CT>,
spherical_equatorial_tag
>
{ {
typedef collected_vector using type = T;
< using base_point_type
T, Geometry, = model::point<T, 2, cs::spherical_equatorial<geometry::degree>>;
strategy::side::spherical_side_formula<CT>, using base_type = collected_vector_spherical<T, base_point_type>;
spherical_equatorial_tag
> base_type;
collected_vector() {} collected_vector_polar() {}
template <typename Point> collected_vector_polar(Point const& p1, Point const& p2)
collected_vector(Point const& p1, Point const& p2)
: base_type(to_equatorial(p1), to_equatorial(p2)) : base_type(to_equatorial(p1), to_equatorial(p2))
{} {}
private: private:
template <typename Point> static base_point_type to_equatorial(Point const& p)
Point to_equatorial(Point const& p)
{ {
typedef typename coordinate_type<Point>::type coord_type; using coord_type = typename coordinate_type<Point>::type;
using constants = math::detail::constants_on_spheroid
typedef math::detail::constants_on_spheroid
< <
coord_type, coord_type,
typename coordinate_system<Point>::type::units typename coordinate_system<Point>::type::units
> constants; > ;
coord_type const pi_2 = constants::half_period() / 2; constexpr coord_type pi_2 = constants::half_period() / 2;
Point res = p; base_point_type res;
set<0>(res, get<0>(p));
set<1>(res, pi_2 - get<1>(p)); set<1>(res, pi_2 - get<1>(p));
return res; return res;
} }
}; };
// TODO: implement collected_vector type for geographic
// TODO: specialize collected_vector for geographic_tag
#ifndef DOXYGEN_NO_DETAIL #ifndef DOXYGEN_NO_DETAIL
@ -348,15 +295,11 @@ private:
return; return;
} }
typedef typename boost::range_size<Collection>::type collection_size_t; auto c_old_size = boost::size(collection);
collection_size_t c_old_size = boost::size(collection);
typedef typename boost::range_iterator<ClosedClockwiseRange const>::type iterator;
bool is_first = true; bool is_first = true;
iterator it = boost::begin(range); auto it = boost::begin(range);
for (iterator prev = it++; it != boost::end(range); prev = it++) for (auto prev = it++; it != boost::end(range); prev = it++)
{ {
typename boost::range_value<Collection>::type v(*prev, *it); typename boost::range_value<Collection>::type v(*prev, *it);
@ -375,13 +318,10 @@ private:
} }
// If first one has same direction as last one, remove first one // If first one has same direction as last one, remove first one
collection_size_t collected_count = boost::size(collection) - c_old_size; if (boost::size(collection) > c_old_size + 1)
if ( collected_count > 1 )
{ {
typedef typename boost::range_iterator<Collection>::type c_iterator; auto first = range::pos(collection, c_old_size);
c_iterator first = range::pos(collection, c_old_size); if (collection.back().next_is_collinear(*first))
if (collection.back().next_is_collinear(*first) )
{ {
//collection.erase(first); //collection.erase(first);
// O(1) instead of O(N) // O(1) instead of O(N)

View File

@ -160,26 +160,32 @@ struct length_check
*/ */
template <typename Geometry1, typename Geometry2, typename Strategy> // Small helper structure do decide to use collect_vectors, or not
struct collected_vector template <typename Strategy, typename CsTag>
struct use_collect_vectors
{ {
typedef typename geometry::select_most_precise static constexpr bool value = false;
<
typename select_coordinate_type
<
Geometry1, Geometry2
>::type,
double
>::type calculation_type;
typedef geometry::collected_vector
<
calculation_type,
Geometry1,
decltype(std::declval<Strategy>().side())
> type;
}; };
template <typename Strategy>
struct use_collect_vectors<Strategy, cartesian_tag>
{
static constexpr bool value = true;
template <typename T, typename Point>
using type = collected_vector_cartesian<T>;
};
template <typename CV>
struct use_collect_vectors<strategy::side::spherical_side_formula<CV>, spherical_tag>
{
static constexpr bool value = true;
template <typename T, typename Point>
using type = collected_vector_spherical<T, Point>;
};
template <typename TrivialCheck> template <typename TrivialCheck>
struct equals_by_collection struct equals_by_collection
{ {
@ -193,10 +199,24 @@ struct equals_by_collection
return false; return false;
} }
typedef typename collected_vector using calculation_type = typename geometry::select_most_precise
< <
Geometry1, Geometry2, Strategy typename select_coordinate_type
>::type collected_vector_type; <
Geometry1, Geometry2
>::type,
double
>::type;
using collected_vector_type = typename use_collect_vectors
<
decltype(std::declval<Strategy>().side()),
typename Strategy::cs_tag
>::template type
<
calculation_type,
typename geometry::point_type<Geometry1>::type
>;
std::vector<collected_vector_type> c1, c2; std::vector<collected_vector_type> c1, c2;
@ -211,7 +231,7 @@ struct equals_by_collection
std::sort(c1.begin(), c1.end()); std::sort(c1.begin(), c1.end());
std::sort(c2.begin(), c2.end()); std::sort(c2.begin(), c2.end());
// Just check if these vectors are equal. // Check if these vectors are equal.
return std::equal(c1.begin(), c1.end(), c2.begin()); return std::equal(c1.begin(), c1.end(), c2.begin());
} }
}; };
@ -226,47 +246,40 @@ struct equals_by_relate
> >
{}; {};
// If collect_vectors which is a SideStrategy-dispatched optimization // Use either collect_vectors or relate
// is implemented in a way consistent with the Intersection/Side Strategy
// then collect_vectors is used, otherwise relate is used.
// NOTE: the result could be conceptually different for invalid // NOTE: the result could be conceptually different for invalid
// geometries in different coordinate systems because collect_vectors // geometries in different coordinate systems because collect_vectors
// and relate treat invalid geometries differently. // and relate treat invalid geometries differently.
template<typename TrivialCheck> template<typename TrivialCheck>
struct equals_by_collection_or_relate struct equals_by_collection_or_relate
{ {
template <typename Geometry1, typename Geometry2, typename Strategy> template <typename Strategy>
using use_vectors = use_collect_vectors
<
decltype(std::declval<Strategy>().side()),
typename Strategy::cs_tag
>;
template
<
typename Geometry1, typename Geometry2, typename Strategy,
std::enable_if_t<use_vectors<Strategy>::value, int> = 0
>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy) Strategy const& strategy)
{
typedef std::is_base_of
<
nyi::not_implemented_tag,
typename collected_vector
<
Geometry1, Geometry2, Strategy
>::type
> enable_relate_type;
return apply(geometry1, geometry2, strategy, enable_relate_type());
}
private:
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
std::false_type /*enable_relate*/)
{ {
return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy); return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
} }
template <typename Geometry1, typename Geometry2, typename Strategy> template
<
typename Geometry1, typename Geometry2, typename Strategy,
std::enable_if_t<! use_vectors<Strategy>::value, int> = 0
>
static inline bool apply(Geometry1 const& geometry1, static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2, Geometry2 const& geometry2,
Strategy const& strategy, Strategy const& strategy)
std::true_type /*enable_relate*/)
{ {
return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy); return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
} }

View File

@ -22,22 +22,23 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
#define 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/algorithms/dispatch/expand.hpp>
#include <boost/geometry/core/coordinate_system.hpp> #include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.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/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp> #include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/expand/services.hpp> #include <boost/geometry/strategies/expand/services.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry
{ {
@ -97,10 +98,10 @@ struct expand<default_strategy, false>
} //namespace resolve_strategy } //namespace resolve_strategy
namespace resolve_variant namespace resolve_dynamic
{ {
template <typename Geometry> template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct expand struct expand
{ {
template <typename Box, typename Strategy> template <typename Box, typename Strategy>
@ -116,68 +117,24 @@ struct expand
} }
}; };
template <BOOST_VARIANT_ENUM_PARAMS(typename T)> template <typename Geometry>
struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > 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> template <class Box, typename Strategy>
static inline void static inline void apply(Box& box,
apply(Box& box, Geometry const& geometry,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry, Strategy const& strategy)
Strategy const& strategy)
{ {
return boost::apply_visitor(visitor<Box, Strategy>(box, strategy), traits::visit<Geometry>::apply([&](auto const& g)
geometry); {
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) \brief Expands (with strategy)
\ingroup expand \ingroup expand
@ -195,7 +152,7 @@ will be added to the box
template <typename Box, typename Geometry, typename Strategy> template <typename Box, typename Geometry, typename Strategy>
inline void expand(Box& box, Geometry const& geometry, Strategy const& 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> template <typename Box, typename Geometry>
inline void expand(Box& box, Geometry const& 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 }} // namespace boost::geometry

View File

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

View File

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

View File

@ -3,9 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. // 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. // Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // 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> template <typename Turns>
inline void calculate_remaining_distance(Turns& turns) inline void calculate_remaining_distance(Turns& turns)
{ {
typedef typename boost::range_value<Turns>::type turn_type; using turn_type = typename boost::range_value<Turns>::type;
typedef typename turn_type::turn_operation_type op_type; using op_type = typename turn_type::turn_operation_type;
for (typename boost::range_iterator<Turns>::type typename op_type::comparable_distance_type const zero_distance = 0;
it = boost::begin(turns);
it != boost::end(turns); for (auto it = boost::begin(turns); it != boost::end(turns); ++it)
++it)
{ {
turn_type& turn = *it; turn_type& turn = *it;
op_type& op0 = turn.operations[0]; op_type& op0 = turn.operations[0];
op_type& op1 = turn.operations[1]; op_type& op1 = turn.operations[1];
if (op0.remaining_distance != 0 if (op0.remaining_distance != zero_distance
|| op1.remaining_distance != 0) || op1.remaining_distance != zero_distance)
{ {
continue; continue;
} }

View File

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

View File

@ -3,9 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. // 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. // Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // 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/box.hpp>
#include <boost/geometry/geometries/concepts/check.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> #include <boost/geometry/util/condition.hpp>
@ -271,6 +273,85 @@ struct self_get_turn_points
#endif // DOXYGEN_NO_DISPATCH #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 #ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace self_get_turn_points namespace detail { namespace self_get_turn_points
{ {
@ -282,13 +363,13 @@ template
bool Reverse, bool Reverse,
typename AssignPolicy, typename AssignPolicy,
typename Geometry, typename Geometry,
typename IntersectionStrategy, typename Strategy,
typename RobustPolicy, typename RobustPolicy,
typename Turns, typename Turns,
typename InterruptPolicy typename InterruptPolicy
> >
inline void self_turns(Geometry const& geometry, inline void self_turns(Geometry const& geometry,
IntersectionStrategy const& strategy, Strategy const& strategy,
RobustPolicy const& robust_policy, RobustPolicy const& robust_policy,
Turns& turns, Turns& turns,
InterruptPolicy& interrupt_policy, InterruptPolicy& interrupt_policy,
@ -297,14 +378,9 @@ inline void self_turns(Geometry const& geometry,
{ {
concepts::check<Geometry const>(); concepts::check<Geometry const>();
typedef detail::overlay::get_turn_info<detail::overlay::assign_null_policy> turn_policy; resolve_strategy::self_get_turn_points
dispatch::self_get_turn_points
< <
Reverse, Reverse, AssignPolicy, Strategy
typename tag<Geometry>::type,
Geometry,
turn_policy
>::apply(geometry, strategy, robust_policy, turns, interrupt_policy, >::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
source_index, skip_adjacent); source_index, skip_adjacent);
} }
@ -351,12 +427,11 @@ inline void self_turns(Geometry const& geometry,
geometry::point_order<Geometry>::value geometry::point_order<Geometry>::value
>::value; >::value;
detail::self_get_turn_points::self_turns resolve_strategy::self_get_turn_points
< <
reverse, reverse, AssignPolicy, Strategy
AssignPolicy >::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
>(geometry, strategy, robust_policy, turns, interrupt_policy, source_index, skip_adjacent);
source_index, skip_adjacent);
} }

View File

@ -181,20 +181,16 @@ struct visit_breadth_first<Geometry, dynamic_geometry_tag>
} }
}; };
// NOTE: This specialization works partially like std::visit and partially like } // namespace dispatch
// std::ranges::for_each. If the argument is rvalue reference then the elements #endif // DOXYGEN_NO_DISPATCH
// 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 #ifndef DOXYGEN_NO_DETAIL
// which and references for them has to be propagated like that. If this is not namespace detail
// 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 template <bool PassIterator = false>
// but in the future there might be some issues. Consider e.g. passing a temporary struct visit_breadth_first_impl
// 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>
{ {
template <typename F, typename Geom> template <typename F, typename Geom>
static bool apply(F function, Geom && geom) static bool apply(F function, Geom && geom)
@ -217,7 +213,7 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
bool result = true; bool result = true;
traits::iter_visit<util::remove_cref_t<Geom>>::apply([&](auto && g) traits::iter_visit<util::remove_cref_t<Geom>>::apply([&](auto && g)
{ {
result = visit_breadth_first::visit_or_enqueue( result = visit_breadth_first_impl::visit_or_enqueue<PassIterator>(
function, std::forward<decltype(g)>(g), queue, it); function, std::forward<decltype(g)>(g), queue, it);
}, it); }, it);
@ -236,7 +232,7 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
// so this call can be avoided. // so this call can be avoided.
traits::iter_visit<util::remove_cref_t<Geom>>::apply([&](auto && g) traits::iter_visit<util::remove_cref_t<Geom>>::apply([&](auto && g)
{ {
visit_breadth_first::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.front());
queue.pop_front(); queue.pop_front();
} }
@ -247,7 +243,7 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
private: private:
template 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 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) static bool visit_or_enqueue(F &, Geom &&, std::deque<Iterator> & queue, Iterator iter)
@ -257,13 +253,22 @@ private:
} }
template 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 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) static bool visit_or_enqueue(F & f, Geom && g, std::deque<Iterator> & , Iterator)
{ {
return f(std::forward<Geom>(g)); 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 template
< <
@ -284,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 } // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH #endif // DOXYGEN_NO_DISPATCH

View File

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

View File

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

View File

@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // 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 Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, 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/size.hpp>
#include <boost/range/value_type.hpp> #include <boost/range/value_type.hpp>
#include <boost/variant/apply_visitor.hpp> #include <boost/geometry/algorithms/detail/counting.hpp>
#include <boost/variant/static_visitor.hpp> #include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/variant/variant_fwd.hpp> #include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.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/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/counting.hpp>
namespace boost { namespace geometry 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 struct num_segments
{ {
static inline std::size_t apply(Geometry const& geometry) static inline std::size_t apply(Geometry const& geometry)
@ -156,27 +153,38 @@ struct num_segments
}; };
template <BOOST_VARIANT_ENUM_PARAMS(typename T)> template <typename Geometry>
struct num_segments<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > 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> std::size_t result = 0;
inline std::size_t operator()(Geometry const& geometry) const traits::visit<Geometry>::apply([&](auto const& g)
{ {
return num_segments<Geometry>::apply(geometry); result = num_segments<util::remove_cref_t<decltype(g)>>::apply(g);
} }, geometry);
}; return result;
static inline std::size_t
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
{
return boost::apply_visitor(visitor(), geometry);
} }
}; };
} // 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> template <typename Geometry>
inline std::size_t num_segments(Geometry const& geometry) inline std::size_t num_segments(Geometry const& geometry)
{ {
return resolve_variant::num_segments<Geometry>::apply(geometry); return resolve_dynamic::num_segments<Geometry>::apply(geometry);
} }

View File

@ -21,20 +21,19 @@
#include <boost/range/value_type.hpp> #include <boost/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/length.hpp>
#include <boost/geometry/algorithms/detail/calculate_null.hpp> #include <boost/geometry/algorithms/detail/calculate_null.hpp>
#include <boost/geometry/algorithms/detail/calculate_sum.hpp> #include <boost/geometry/algorithms/detail/calculate_sum.hpp>
#include <boost/geometry/algorithms/detail/multi_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/throw_on_empty_input.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/core/cs.hpp> #include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/closure.hpp> #include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/tags.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/concepts/check.hpp>
#include <boost/geometry/strategies/default_length_result.hpp> #include <boost/geometry/strategies/default_length_result.hpp>
@ -162,9 +161,9 @@ struct perimeter<default_strategy, false>
} // namespace resolve_strategy } // namespace resolve_strategy
namespace resolve_variant { namespace resolve_dynamic {
template <typename Geometry> template <typename Geometry, typename Tag = typename geometry::tag<Geometry>::type>
struct perimeter struct perimeter
{ {
template <typename Strategy> template <typename Strategy>
@ -176,39 +175,40 @@ struct perimeter
} }
}; };
template <BOOST_VARIANT_ENUM_PARAMS(typename T)> template <typename Geometry>
struct perimeter<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > struct perimeter<Geometry, dynamic_geometry_tag>
{ {
typedef typename default_length_result
<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>
>::type result_type;
template <typename Strategy> 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; typename default_length_result<Geometry>::type result = 0;
traits::visit<Geometry>::apply([&](auto const& g)
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry>
typename default_length_result<Geometry>::type
operator()(Geometry const& geometry) const
{ {
return perimeter<Geometry>::apply(geometry, m_strategy); result = perimeter<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
} }, geometry);
}; return result;
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);
} }
}; };
} // 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) Geometry const& geometry)
{ {
// detail::throw_on_empty_input(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) Geometry const& geometry, Strategy const& strategy)
{ {
// detail::throw_on_empty_input(geometry); // 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 }} // namespace boost::geometry

View File

@ -31,15 +31,13 @@
#include <boost/range/end.hpp> #include <boost/range/end.hpp>
#include <boost/range/size.hpp> #include <boost/range/size.hpp>
#include <boost/range/value_type.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/area.hpp>
#include <boost/geometry/algorithms/clear.hpp> #include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/convert.hpp> #include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/dummy_geometries.hpp> #include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.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/not_implemented.hpp>
#include <boost/geometry/algorithms/is_empty.hpp> #include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/perimeter.hpp> #include <boost/geometry/algorithms/perimeter.hpp>
@ -50,7 +48,9 @@
#include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/mutable_range.hpp> #include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/tags.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/concepts/check.hpp>
#include <boost/geometry/strategies/concepts/simplify_concept.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/geographic.hpp>
#include <boost/geometry/strategies/simplify/spherical.hpp> #include <boost/geometry/strategies/simplify/spherical.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER #ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
#include <boost/geometry/io/dsv/write.hpp> #include <boost/geometry/io/dsv/write.hpp>
#endif #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 struct simplify_copy
{ {
template 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) // Linestring, keep 2 points (unless those points are the same)
template <typename Linestring> template <typename Linestring>
struct simplify<Linestring, linestring_tag> struct simplify<Linestring, linestring_tag>
@ -803,9 +833,9 @@ struct simplify_insert<default_strategy, false>
} // namespace resolve_strategy } // namespace resolve_strategy
namespace resolve_variant { namespace resolve_dynamic {
template <typename Geometry> template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct simplify struct simplify
{ {
template <typename Distance, typename Strategy> template <typename Distance, typename Strategy>
@ -818,43 +848,46 @@ struct simplify
} }
}; };
template <BOOST_VARIANT_ENUM_PARAMS(typename T)> template <typename Geometry>
struct simplify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > struct simplify<Geometry, dynamic_geometry_tag>
{ {
template <typename Distance, typename Strategy> 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; traits::visit<Geometry>::apply([&](auto const& g)
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
{ {
simplify<Geometry>::apply(geometry, out, m_max_distance, m_strategy); 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);
template <typename Distance, typename Strategy> }, geometry);
static inline void
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out,
Distance const& max_distance,
Strategy const& strategy)
{
boost::apply_visitor(
visitor<Distance, Strategy>(max_distance, strategy),
geometry,
out
);
} }
}; };
} // namespace resolve_variant 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); geometry::clear(out);
resolve_variant::simplify<Geometry>::apply(geometry, out, max_distance, strategy); resolve_dynamic::simplify<Geometry>::apply(geometry, out, max_distance, strategy);
} }

View File

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

View File

@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020. // This file was modified by Oracle on 2020-2021.
// Modifications copyright (c) 2020 Oracle and/or its affiliates. // Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@ -21,10 +21,12 @@
#include <boost/range/value_type.hpp> #include <boost/range/value_type.hpp>
#include <boost/geometry/core/geometry_types.hpp>
#include <boost/geometry/core/ring_type.hpp> #include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/static_assert.hpp> #include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp> #include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp> #include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits_std.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 } // namespace core_dispatch
#endif // DOXYGEN_NO_DISPATCH #endif // DOXYGEN_NO_DISPATCH

View File

@ -2,8 +2,8 @@
// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2016-2020. // This file was modified by Oracle on 2016-2021.
// Modifications copyright (c) 2016-2020 Oracle and/or its affiliates. // Modifications copyright (c) 2016-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // Use, modification and distribution is subject to the Boost Software License,
@ -53,8 +53,8 @@ struct less<Type, false>
template <typename Ratio> template <typename Ratio>
static inline bool apply(Ratio const& lhs, Ratio const& rhs) static inline bool apply(Ratio const& lhs, Ratio const& rhs)
{ {
BOOST_GEOMETRY_ASSERT(lhs.denominator() != 0); BOOST_GEOMETRY_ASSERT(lhs.denominator() != Type(0));
BOOST_GEOMETRY_ASSERT(rhs.denominator() != 0); BOOST_GEOMETRY_ASSERT(rhs.denominator() != Type(0));
Type const a = lhs.numerator() / lhs.denominator(); Type const a = lhs.numerator() / lhs.denominator();
Type const b = rhs.numerator() / rhs.denominator(); Type const b = rhs.numerator() / rhs.denominator();
return ! geometry::math::equals(a, b) return ! geometry::math::equals(a, b)
@ -86,8 +86,8 @@ struct equal<Type, false>
template <typename Ratio> template <typename Ratio>
static inline bool apply(Ratio const& lhs, Ratio const& rhs) static inline bool apply(Ratio const& lhs, Ratio const& rhs)
{ {
BOOST_GEOMETRY_ASSERT(lhs.denominator() != 0); BOOST_GEOMETRY_ASSERT(lhs.denominator() != Type(0));
BOOST_GEOMETRY_ASSERT(rhs.denominator() != 0); BOOST_GEOMETRY_ASSERT(rhs.denominator() != Type(0));
Type const a = lhs.numerator() / lhs.denominator(); Type const a = lhs.numerator() / lhs.denominator();
Type const b = rhs.numerator() / rhs.denominator(); Type const b = rhs.numerator() / rhs.denominator();
return geometry::math::equals(a, b); return geometry::math::equals(a, b);
@ -144,7 +144,8 @@ class segment_ratio
// Type-alias for the type itself // Type-alias for the type itself
using thistype = segment_ratio<Type>; using thistype = segment_ratio<Type>;
public : public:
using int_type = Type;
inline segment_ratio() inline segment_ratio()
: m_numerator(0) : m_numerator(0)
@ -231,7 +232,7 @@ public :
); );
} }
inline bool is_zero() const { return math::equals(m_numerator, 0); } inline bool is_zero() const { return math::equals(m_numerator, Type(0)); }
inline bool is_one() const { return math::equals(m_numerator, m_denominator); } inline bool is_one() const { return math::equals(m_numerator, m_denominator); }
inline bool on_segment() const inline bool on_segment() const
{ {

View File

@ -26,7 +26,7 @@
#include <boost/geometry/algorithms/assign.hpp> #include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/strategy/cartesian/side_robust.hpp> #include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/covered_by.hpp> #include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp> #include <boost/geometry/strategies/within.hpp>
@ -118,11 +118,14 @@ struct cartesian_point_box_by_side
template <typename Point, typename Box> template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box) static inline bool apply(Point const& point, Box const& box)
{ {
using side_strategy_type
= typename strategy::side::services::default_strategy
<cartesian_tag, CalculationType>::type;
return within::detail::point_in_box_by_side return within::detail::point_in_box_by_side
< <
within::detail::decide_within within::detail::decide_within
>(point, box, >(point, box, side_strategy_type());
strategy::side::side_robust<CalculationType>());
} }
}; };
@ -189,11 +192,13 @@ struct cartesian_point_box_by_side
template <typename Point, typename Box> template <typename Point, typename Box>
static bool apply(Point const& point, Box const& box) static bool apply(Point const& point, Box const& box)
{ {
using side_strategy_type
= typename strategy::side::services::default_strategy
<cartesian_tag, CalculationType>::type;
return within::detail::point_in_box_by_side return within::detail::point_in_box_by_side
< <
within::detail::decide_covered_by within::detail::decide_covered_by
>(point, box, >(point, box, side_strategy_type());
strategy::side::side_robust<CalculationType>());
} }
}; };

View File

@ -86,8 +86,11 @@ struct strategy_converter<strategy::area::geographic<FP, SO, S, CT> >
: strategies::area::geographic<FP, S, CT>(spheroid) : strategies::area::geographic<FP, S, CT>(spheroid)
{} {}
using strategies::area::geographic<FP, S, CT>::area;
template <typename Geometry> template <typename Geometry>
auto area(Geometry const&) const auto area(Geometry const&,
std::enable_if_t<! util::is_box<Geometry>::value> * = nullptr) const
{ {
return strategy::area::geographic<FP, SO, S, CT>(this->m_spheroid); return strategy::area::geographic<FP, SO, S, CT>(this->m_spheroid);
} }

View File

@ -38,7 +38,6 @@
#include <boost/geometry/strategy/cartesian/envelope.hpp> #include <boost/geometry/strategy/cartesian/envelope.hpp>
#include <boost/geometry/strategy/cartesian/expand_box.hpp> #include <boost/geometry/strategy/cartesian/expand_box.hpp>
#include <boost/geometry/strategy/cartesian/expand_segment.hpp> #include <boost/geometry/strategy/cartesian/expand_segment.hpp>
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp> #include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp> #include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
@ -174,7 +173,7 @@ struct cartesian_segments
// Up to now, division was postponed. Here we divide using numerator/ // Up to now, division was postponed. Here we divide using numerator/
// denominator. In case of integer this results in an integer // denominator. In case of integer this results in an integer
// division. // division.
BOOST_GEOMETRY_ASSERT(ratio.denominator() != 0); BOOST_GEOMETRY_ASSERT(ratio.denominator() != typename SegmentRatio::int_type(0));
typedef typename promote_integral<CoordinateType>::type calc_type; typedef typename promote_integral<CoordinateType>::type calc_type;
@ -439,7 +438,9 @@ struct cartesian_segments
return Policy::disjoint(); return Policy::disjoint();
} }
typedef side::side_robust<CalculationType> side_strategy_type; using side_strategy_type
= typename side::services::default_strategy
<cartesian_tag, CalculationType>::type;
side_info sides; side_info sides;
sides.set<0>(side_strategy_type::apply(q1, q2, p1), sides.set<0>(side_strategy_type::apply(q1, q2, p1),
side_strategy_type::apply(q1, q2, p2)); side_strategy_type::apply(q1, q2, p2));

View File

@ -24,7 +24,7 @@
#include <boost/geometry/util/select_calculation_type.hpp> #include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategy/cartesian/expand_point.hpp> #include <boost/geometry/strategy/cartesian/expand_point.hpp>
#include <boost/geometry/strategy/cartesian/side_robust.hpp> #include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp> #include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp> #include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
@ -116,7 +116,9 @@ public:
else // count == 2 || count == -2 else // count == 2 || count == -2
{ {
// 1 left, -1 right // 1 left, -1 right
typedef side::side_robust<CalculationType> side_strategy_type; using side_strategy_type
= typename side::services::default_strategy
<cartesian_tag, CalculationType>::type;
side = side_strategy_type::apply(s1, s2, point); side = side_strategy_type::apply(s1, s2, point);
} }

View File

@ -11,11 +11,11 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP #ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP #define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp> #include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/convex_hull/services.hpp> #include <boost/geometry/strategies/convex_hull/services.hpp>
#include <boost/geometry/strategies/detail.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
#include <boost/geometry/util/type_traits.hpp> #include <boost/geometry/util/type_traits.hpp>
@ -42,7 +42,10 @@ public:
static auto side() static auto side()
{ {
return strategy::side::side_robust<CalculationType>(); using side_strategy_type
= typename strategy::side::services::default_strategy
<cartesian_tag, CalculationType>::type;
return side_strategy_type();
} }
}; };

View File

@ -68,6 +68,13 @@ struct cartesian
{ {
return strategy::envelope::cartesian<CalculationType>(); return strategy::envelope::cartesian<CalculationType>();
} }
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_geometry_collection_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian<CalculationType>();
}
}; };

View File

@ -86,6 +86,16 @@ public:
FormulaPolicy, Spheroid, CalculationType FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid); >(base_t::m_spheroid);
} }
template <typename Geometry, typename Box>
auto envelope(Geometry const&, Box const&,
typename util::enable_if_geometry_collection_t<Geometry> * = nullptr) const
{
return strategy::envelope::geographic
<
FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid);
}
}; };

View File

@ -79,6 +79,13 @@ struct spherical
{ {
return strategy::envelope::spherical<CalculationType>(); return strategy::envelope::spherical<CalculationType>();
} }
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
typename util::enable_if_geometry_collection_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical<CalculationType>();
}
}; };

View File

@ -19,8 +19,6 @@
#include <boost/geometry/policies/relate/intersection_policy.hpp> #include <boost/geometry/policies/relate/intersection_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp> #include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
#include <boost/geometry/strategies/intersection.hpp> #include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp> #include <boost/geometry/strategies/intersection_result.hpp>
#include <boost/geometry/strategies/side.hpp> #include <boost/geometry/strategies/side.hpp>

View File

@ -15,6 +15,7 @@
#include <boost/geometry/strategies/detail.hpp> #include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/is_convex/services.hpp> #include <boost/geometry/strategies/is_convex/services.hpp>
#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp> #include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
namespace boost { namespace geometry namespace boost { namespace geometry

View File

@ -158,7 +158,10 @@ public:
static auto side() static auto side()
{ {
return strategy::side::side_robust<CalculationType>(); using side_strategy_type
= typename strategy::side::services::default_strategy
<cartesian_tag, CalculationType>::type;
return side_strategy_type();
} }
// within // within

View File

@ -24,17 +24,15 @@
#include <type_traits> #include <type_traits>
#include <boost/geometry/core/config.hpp>
#include <boost/geometry/arithmetic/determinant.hpp> #include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/access.hpp> #include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp> #include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/compare.hpp> #include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/side.hpp> #include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategy/cartesian/envelope.hpp>
#include <boost/geometry/util/select_most_precise.hpp> #include <boost/geometry/util/select_most_precise.hpp>
@ -254,6 +252,23 @@ private:
} }
}; };
#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<cartesian_tag, CalculationType>
{
typedef side_by_triangle<CalculationType> type;
};
}
#endif
#endif
}} // namespace strategy::side }} // namespace strategy::side
}} // namespace boost::geometry }} // namespace boost::geometry

View File

@ -18,6 +18,7 @@
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP #ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP #define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
#include <boost/geometry/core/config.hpp>
#include <boost/geometry/strategy/cartesian/side_non_robust.hpp> #include <boost/geometry/strategy/cartesian/side_non_robust.hpp>
#include <boost/geometry/strategies/side.hpp> #include <boost/geometry/strategies/side.hpp>
@ -177,6 +178,7 @@ public:
}; };
#ifdef BOOST_GEOMETRY_USE_RESCALING
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services namespace services
@ -190,6 +192,7 @@ struct default_strategy<cartesian_tag, CalculationType>
} }
#endif
#endif #endif
}} // namespace strategy::side }} // namespace strategy::side

View File

@ -26,7 +26,16 @@ test-suite boost-geometry-algorithms-buffer
[ run buffer_multi_linestring.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_multi_linestring ] [ run buffer_multi_linestring.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_multi_linestring ]
[ run buffer_multi_polygon.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_multi_polygon ] [ run buffer_multi_polygon.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_multi_polygon ]
[ run buffer_linestring_aimes.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_linestring_aimes ] [ run buffer_linestring_aimes.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_linestring_aimes ]
# Uncomment next line if you want to test this manually; requires access to data/ folder # TODO
# [ run buffer_linestring.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_buffer_linestring_norescale ]
# [ run buffer_multi_linestring.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_buffer_multi_linestring_norescale ]
[ run buffer_ring.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_buffer_ring_norescale ]
[ run buffer_polygon.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_buffer_polygon_norescale ]
[ run buffer_multi_point.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_buffer_multi_point_norescale ]
[ run buffer_multi_polygon.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_buffer_multi_polygon_norescale ]
[ run buffer_linestring_aimes.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_buffer_linestring_aimes_norescale ]
# Uncomment next lines if you want to test this manually; requires access to data/ folder
# [ run buffer_countries.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_countries ] # [ run buffer_countries.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_buffer_countries ]
# [ run buffer_countries.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_buffer_countries_norescale ]
; ;

View File

@ -1,7 +1,7 @@
// Boost.Geometry // Boost.Geometry
// Unit Test // Unit Test
// Copyright (c) 2017-2018, Oracle and/or its affiliates. // Copyright (c) 2017-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -9,6 +9,8 @@
// http://www.boost.org/users/license.html // http://www.boost.org/users/license.html
#include <boost/variant/variant.hpp>
#include <geometry_test_common.hpp> #include <geometry_test_common.hpp>
#include <boost/geometry/geometries/geometries.hpp> #include <boost/geometry/geometries/geometries.hpp>
@ -159,6 +161,17 @@ inline void test_geometry(std::string const& wkt, Check const& check)
bg::densify(g, o, max_distance); bg::densify(g, o, max_distance);
check_result(g, o, max_distance, def_s, check); check_result(g, o, max_distance, def_s, check);
using variant_t = boost::variant<G, typename bg::point_type<G>::type>;
variant_t v = g, vo;
bg::densify(v, vo, max_distance);
check(v, vo, def_s);
bg::model::geometry_collection<variant_t> gc{v}, gco;
bg::densify(gc, gco, max_distance);
check(gc, gco, def_s);
} }
{ {

View File

@ -491,6 +491,24 @@ void test_variant()
//BOOST_CHECK_CLOSE(bg::distance(point, v2, s), bg::distance(point, point, s), 0.0001); //BOOST_CHECK_CLOSE(bg::distance(point, v2, s), bg::distance(point, point, s), 0.0001);
} }
template <typename T>
void test_geometry_collection()
{
using point_type = bg::model::point<T, 2, bg::cs::cartesian>;
using segment_type = bg::model::segment<point_type>;
using box_type = bg::model::box<point_type>;
using variant_type = boost::variant<point_type, segment_type, box_type>;
using gc_type = bg::model::geometry_collection<variant_type>;
point_type p1 {1, 3}, p2 {2, 3};
segment_type s1 {{2, 2}, {4, 4}}, s2 {{3, 2}, {5, 4}};
gc_type gc1 {p1, s1}, gc2 {p2, s2};
BOOST_CHECK_CLOSE(bg::distance(p1, gc2), bg::distance(p1, p2), 0.0001);
BOOST_CHECK_CLOSE(bg::distance(gc1, s2), bg::distance(s1, s2), 0.0001);
BOOST_CHECK_CLOSE(bg::distance(gc1, gc2), bg::distance(s1, s2), 0.0001);
}
int test_main(int, char* []) int test_main(int, char* [])
{ {
#ifdef TEST_ARRAY #ifdef TEST_ARRAY
@ -525,5 +543,7 @@ int test_main(int, char* [])
test_variant<double>(); test_variant<double>();
test_variant<int>(); test_variant<int>();
test_geometry_collection<double>();
return 0; return 0;
} }

View File

@ -21,6 +21,7 @@
#include <boost/geometry/algorithms/envelope.hpp> #include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/geometries/box.hpp> #include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/geometry_collection.hpp>
#include <boost/geometry/strategies/strategies.hpp> #include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/io/wkt/read.hpp> #include <boost/geometry/io/wkt/read.hpp>
@ -97,6 +98,10 @@ void test_envelope(std::string const& wkt,
check_result<box_type, bg::dimension<Geometry>::type::value> check_result<box_type, bg::dimension<Geometry>::type::value>
::apply(b, x1, y1, z1, x2, y2, z2); ::apply(b, x1, y1, z1, x2, y2, z2);
bg::model::geometry_collection<boost::variant<Geometry>> gc{v};
bg::envelope(gc, b);
check_result<box_type, bg::dimension<Geometry>::type::value>
::apply(b, x1, y1, z1, x2, y2, z2);
} }

View File

@ -19,4 +19,5 @@ test-suite boost-geometry-algorithms-equals
[ run equals.cpp : : : : algorithms_equals ] [ run equals.cpp : : : : algorithms_equals ]
[ run equals_multi.cpp : : : : algorithms_equals_multi ] [ run equals_multi.cpp : : : : algorithms_equals_multi ]
[ run equals_on_spheroid.cpp : : : : algorithms_equals_on_spheroid ] [ run equals_on_spheroid.cpp : : : : algorithms_equals_on_spheroid ]
[ run equals_sph.cpp : : : : algorithms_equals_sph ]
; ;

View File

@ -233,3 +233,32 @@ BOOST_AUTO_TEST_CASE( equals_segment_segment_geo )
test_segment_segment<bgm::point<double, 2, cs_type> >("geo"); test_segment_segment<bgm::point<double, 2, cs_type> >("geo");
test_segment_segment<bgm::point<long double, 2, cs_type> >("geo"); test_segment_segment<bgm::point<long double, 2, cs_type> >("geo");
} }
// This version uses collect_vectors (because its side
// strategy is spherical_side_formula) and fails
BOOST_AUTO_TEST_CASE( equals_ring_ring_se)
{
using cs_type = bg::cs::spherical_equatorial<bg::degree> ;
using ring_type = bgm::ring<bgm::point<double, 2, cs_type> >;
test_geometry<ring_type, ring_type>("ring_simplex",
"POLYGON((10 50,10 51,11 50,10 50))",
"POLYGON((10 50,10 51,11 50,10 50))",
true);
}
BOOST_AUTO_TEST_CASE( equals_ring_ring_geo )
{
using cs_type = bg::cs::geographic<bg::degree> ;
using ring_type = bgm::ring<bgm::point<double, 2, cs_type> >;
test_geometry<ring_type, ring_type>("ring_simplex",
"POLYGON((10 50,10 51,11 50,10 50))",
"POLYGON((10 50,10 51,11 50,10 50))",
true);
test_geometry<ring_type, ring_type>("ring_simplex_false",
"POLYGON((10 50,10 51,11 50,10 50))",
"POLYGON((10 50,10 51.01,11 50,10 50))",
false);
}

View File

@ -147,5 +147,13 @@ int test_main( int , char* [] )
{ {
test_all<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > >(); test_all<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > >();
// TODO: the polar version needs several traits more, for example in cs_tag,
// to compile properly.
//test_all<bg::model::point<double, 2, bg::cs::polar<bg::degree> > >();
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
test_all<bg::model::point<double, 2, bg::cs::geographic<bg::degree> > >();
#endif
return 0; return 0;
} }

View File

@ -26,7 +26,10 @@
#include <boost/variant/variant.hpp> #include <boost/variant/variant.hpp>
struct no_strategy {}; struct no_strategy
{
using cs_tag = void;
};
template <typename Geometry1, typename Geometry2, typename Strategy> template <typename Geometry1, typename Geometry2, typename Strategy>
bool call_equals(Geometry1 const& geometry1, bool call_equals(Geometry1 const& geometry1,
@ -60,7 +63,9 @@ void check_geometry(Geometry1 const& geometry1,
<< " equals: " << wkt1 << " equals: " << wkt1
<< " to " << wkt2 << " to " << wkt2
<< " -> Expected: " << expected << " -> Expected: " << expected
<< " detected: " << detected); << " detected: " << detected
<< " strategy: " << typeid(Strategy).name()
<< " cs: " << typeid(typename Strategy::cs_tag).name());
detected = call_equals(geometry2, geometry1, strategy); detected = call_equals(geometry2, geometry1, strategy);
@ -69,7 +74,8 @@ void check_geometry(Geometry1 const& geometry1,
<< " equals: " << wkt2 << " equals: " << wkt2
<< " to " << wkt1 << " to " << wkt1
<< " -> Expected: " << expected << " -> Expected: " << expected
<< " detected: " << detected); << " strategy: " << typeid(Strategy).name()
<< " cs: " << typeid(typename Strategy::cs_tag).name());
} }

View File

@ -1,7 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test // Unit Test
// Copyright (c) 2014-2018, 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 Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@ -27,6 +27,8 @@
#include <boost/geometry/algorithms/intersection.hpp> #include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/reverse.hpp> #include <boost/geometry/algorithms/reverse.hpp>
#include <boost/geometry/geometries/geometry_collection.hpp>
BOOST_AUTO_TEST_CASE( test_is_valid_point ) BOOST_AUTO_TEST_CASE( test_is_valid_point )
{ {
#ifdef BOOST_GEOMETRY_TEST_DEBUG #ifdef BOOST_GEOMETRY_TEST_DEBUG
@ -1414,3 +1416,40 @@ BOOST_AUTO_TEST_CASE( test_is_valid_variant )
vg = invalid_polygon; vg = invalid_polygon;
test::apply("v04", vg, false); test::apply("v04", vg, false);
} }
BOOST_AUTO_TEST_CASE( test_is_valid_geometry_collection )
{
#ifdef BOOST_GEOMETRY_TEST_DEBUG
std::cout << std::endl << std::endl;
std::cout << "************************************" << std::endl;
std::cout << " is_valid: geometry collection" << std::endl;
std::cout << "************************************" << std::endl;
#endif
using polygon_type = bg::model::polygon<point_type>; // cw, closed
using variant_type = boost::variant
<
linestring_type, multi_linestring_type, polygon_type
>;
using gc_type = bg::model::geometry_collection<variant_type>;
typedef test_valid_variant<gc_type> test;
gc_type gc;
linestring_type valid_linestring =
from_wkt<linestring_type>("LINESTRING(0 0,1 0)");
multi_linestring_type invalid_multi_linestring =
from_wkt<multi_linestring_type>("MULTILINESTRING((0 0,1 0),(0 0))");
polygon_type valid_polygon =
from_wkt<polygon_type>("POLYGON((0 0,1 1,1 0,0 0))");
polygon_type invalid_polygon =
from_wkt<polygon_type>("POLYGON((0 0,2 2,2 0,1 0))");
gc = {valid_linestring, valid_polygon};
test::apply("gc01", gc, true);
gc = {invalid_multi_linestring, valid_polygon};
test::apply("gc02", gc, false);
gc = {valid_linestring, invalid_polygon};
test::apply("gc03", gc, false);
}

View File

@ -6,6 +6,10 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2013-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, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -67,6 +71,12 @@ int test_main(int, char* [])
typedef bg::model::polygon<point, true, false> open_polygon; typedef bg::model::polygon<point, true, false> open_polygon;
typedef bg::model::multi_polygon<open_polygon> open_multi_polygon; typedef bg::model::multi_polygon<open_polygon> open_multi_polygon;
using variant = boost::variant<linestring, polygon>;
using open_variant = boost::variant<linestring, open_polygon>;
using geometry_collection = bg::model::geometry_collection<variant>;
using open_geometry_collection = bg::model::geometry_collection<open_variant>;
test_num_points<point>("POINT(0 0)", 1u); test_num_points<point>("POINT(0 0)", 1u);
test_num_points<linestring>("LINESTRING(0 0,1 1)", 2u); test_num_points<linestring>("LINESTRING(0 0,1 1)", 2u);
test_num_points<segment>("LINESTRING(0 0,1 1)", 2u); test_num_points<segment>("LINESTRING(0 0,1 1)", 2u);
@ -89,6 +99,12 @@ int test_main(int, char* [])
test_num_points<open_multi_polygon>("MULTIPOLYGON(((0 0,0 10,10 10,10 0)),((0 10,1 10,1 9)))", 7u, 9u); test_num_points<open_multi_polygon>("MULTIPOLYGON(((0 0,0 10,10 10,10 0)),((0 10,1 10,1 9)))", 7u, 9u);
test_num_points<open_multi_polygon>("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((0 10,1 10,1 9,0 10)))", 7u, 9u); test_num_points<open_multi_polygon>("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((0 10,1 10,1 9,0 10)))", 7u, 9u);
test_num_points<variant>("POLYGON((0 0,1 1,0 1,0 0))", 4u);
test_num_points<open_variant>("POLYGON((0 0,1 1,0 1))", 3u, 4u);
test_num_points<geometry_collection>("GEOMETRYCOLLECTION(POLYGON((0 0,1 1,0 1,0 0)),LINESTRING(0 0,1 1))", 6u);
test_num_points<open_geometry_collection>("GEOMETRYCOLLECTION(POLYGON((0 0,1 1,0 1)),LINESTRING(0 0,1 1))", 5u, 6u);
return 0; return 0;
} }

View File

@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library) // Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test // Unit Test
// Copyright (c) 2014, 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 Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0. // Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html // http://www.boost.org/users/license.html
@ -289,3 +290,16 @@ BOOST_AUTO_TEST_CASE( test_variant )
variant_geometry = p_closed; variant_geometry = p_closed;
tester::apply(variant_geometry, 4); tester::apply(variant_geometry, 4);
} }
BOOST_AUTO_TEST_CASE( test_geometry_collection )
{
using variant = boost::variant<linestring, polygon_cw_closed>;
using geometry_collection = bg::model::geometry_collection<variant>;
using tester = test_num_segments<geometry_collection>;
geometry_collection gc;
bg::read_wkt("GEOMETRYCOLLECTION(LINESTRING(0 0,1 1,2 2),POLYGON((0 0,0 1,1 1,1 0,0 0)))", gc);
tester::apply(gc, 6);
}

View File

@ -16,16 +16,15 @@
test-suite boost-geometry-algorithms-difference test-suite boost-geometry-algorithms-difference
: :
[ run difference.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE [ run difference.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_difference ]
: algorithms_difference ] [ run difference_multi.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_difference_multi ]
[ run difference.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_difference_norescale ]
[ run difference_multi.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_difference_multi_norescale ]
[ run difference_multi_spike.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_difference_multi_spike ]
[ run difference_areal_linear.cpp : : : : algorithms_difference_areal_linear ] [ run difference_areal_linear.cpp : : : : algorithms_difference_areal_linear ]
[ run difference_l_a_sph.cpp : : : : algorithms_difference_l_a_sph ] [ run difference_l_a_sph.cpp : : : : algorithms_difference_l_a_sph ]
[ run difference_linear_linear.cpp : : : : algorithms_difference_linear_linear ] [ run difference_linear_linear.cpp : : : : algorithms_difference_linear_linear ]
[ run difference_multi.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
: algorithms_difference_multi ]
[ run difference_multi_areal_linear.cpp : : : : algorithms_difference_multi_areal_linear ] [ run difference_multi_areal_linear.cpp : : : : algorithms_difference_multi_areal_linear ]
[ run difference_multi_spike.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
: algorithms_difference_multi_spike ]
[ run difference_pl_a.cpp : : : : algorithms_difference_pl_a ] [ run difference_pl_a.cpp : : : : algorithms_difference_pl_a ]
[ run difference_pl_l.cpp : : : : algorithms_difference_pl_l ] [ run difference_pl_l.cpp : : : : algorithms_difference_pl_l ]
[ run difference_pl_pl.cpp : : : : algorithms_difference_pl_pl ] [ run difference_pl_pl.cpp : : : : algorithms_difference_pl_pl ]

View File

@ -51,7 +51,7 @@ void test_spikes_in_ticket_8364()
"MULTIPOLYGON(((1032 2556,1778 2556,1032 2130,1032 2556)),((3234 2580,3234 2556,1778 2556,2136 2760,3234 2580)))", "MULTIPOLYGON(((1032 2556,1778 2556,1032 2130,1032 2556)),((3234 2580,3234 2556,1778 2556,2136 2760,3234 2580)))",
count_set(1, 2), -1, expectation_limits(2615783, 2616030), // SQL Server: 2616029.55616044 count_set(1, 2), -1, expectation_limits(2615783, 2616030), // SQL Server: 2616029.55616044
1, -1, expectation_limits(161054, 161134), // SQL Server: 161054.560110092 1, -1, expectation_limits(161054, 161134), // SQL Server: 161054.560110092
count_set(1, 3)); count_set(1, 3), ignore_validity);
} }
template <typename P, bool ClockWise, bool Closed> template <typename P, bool ClockWise, bool Closed>

View File

@ -16,12 +16,12 @@
test-suite boost-geometry-algorithms-intersection test-suite boost-geometry-algorithms-intersection
: :
[ run intersection.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE [ run intersection.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_intersection ]
: algorithms_intersection ] [ run intersection_multi.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_intersection_multi ]
[ run intersection.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_intersection_norescale ]
[ run intersection_multi.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_intersection_multi_norescale ]
[ run intersection_areal_areal_linear.cpp : : : : algorithms_intersection_areal_areal_linear ] [ run intersection_areal_areal_linear.cpp : : : : algorithms_intersection_areal_areal_linear ]
[ run intersection_linear_linear.cpp : : : : algorithms_intersection_linear_linear ] [ run intersection_linear_linear.cpp : : : : algorithms_intersection_linear_linear ]
[ run intersection_multi.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
: algorithms_intersection_multi ]
[ run intersection_pl_a.cpp : : : : algorithms_intersection_pl_a ] [ run intersection_pl_a.cpp : : : : algorithms_intersection_pl_a ]
[ run intersection_pl_l.cpp : : : : algorithms_intersection_pl_l ] [ run intersection_pl_l.cpp : : : : algorithms_intersection_pl_l ]
[ run intersection_pl_pl.cpp : : : : algorithms_intersection_pl_pl ] [ run intersection_pl_pl.cpp : : : : algorithms_intersection_pl_pl ]

View File

@ -16,14 +16,14 @@
test-suite boost-geometry-algorithms-union test-suite boost-geometry-algorithms-union
: :
[ run union.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE [ run union.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_union ]
: algorithms_union ] [ run union_multi.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_union_multi ]
[ run union.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_union_norescale ]
[ run union_multi.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE <define>BOOST_GEOMETRY_NO_ROBUSTNESS : algorithms_union_multi_norescale ]
[ run union_aa_geo.cpp : : : : algorithms_union_aa_geo ] [ run union_aa_geo.cpp : : : : algorithms_union_aa_geo ]
[ run union_aa_sph.cpp : : : : algorithms_union_aa_sph ] [ run union_aa_sph.cpp : : : : algorithms_union_aa_sph ]
[ run union_linear_linear.cpp : : : : algorithms_union_linear_linear ] [ run union_linear_linear.cpp : : : : algorithms_union_linear_linear ]
[ run union_multi.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE
: algorithms_union_multi ]
[ run union_pl_pl.cpp : : : : algorithms_union_pl_pl ] [ run union_pl_pl.cpp : : : : algorithms_union_pl_pl ]
[ run union_tupled.cpp : : : : algorithms_union_tupled ] [ run union_tupled.cpp : : : : algorithms_union_tupled ]
[ run union_other_types.cpp : : : : algorithms_union_other_types ] [ run union_other_types.cpp : : : <define>BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE : algorithms_union_other_types ]
; ;

View File

@ -113,6 +113,7 @@ int test_main(int, char* [])
using bg::model::d2::point_xy; using bg::model::d2::point_xy;
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
// Standard floating point types // Standard floating point types
test_areal<point_xy<float>>({exclude::hard}); test_areal<point_xy<float>>({exclude::hard});
test_areal<point_xy<double>>({}); test_areal<point_xy<double>>({});
@ -121,23 +122,30 @@ int test_main(int, char* [])
// Standard integer types // Standard integer types
test_areal<point_xy<std::int16_t>>({exclude::fp}); test_areal<point_xy<std::int16_t>>({exclude::fp});
test_areal<point_xy<std::int32_t>>({exclude::fp}); test_areal<point_xy<std::int32_t>>({exclude::fp});
#endif
test_areal<point_xy<std::int64_t>>({exclude::fp}); test_areal<point_xy<std::int64_t>>({exclude::fp});
// Boost multi precision (integer) // Boost multi precision (integer)
test_areal<point_xy<bm::int128_t>>({exclude::fp}); test_areal<point_xy<bm::int128_t>>({exclude::fp});
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
test_areal<point_xy<bm::checked_int128_t>>({exclude::fp}); test_areal<point_xy<bm::checked_int128_t>>({exclude::fp});
#endif
// Boost multi precision (floating point) // Boost multi precision (floating point)
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
test_areal<point_xy<bm::number<bm::cpp_bin_float<5>>>>(); test_areal<point_xy<bm::number<bm::cpp_bin_float<5>>>>();
test_areal<point_xy<bm::number<bm::cpp_bin_float<10>>>>(); test_areal<point_xy<bm::number<bm::cpp_bin_float<10>>>>();
test_areal<point_xy<bm::number<bm::cpp_bin_float<50>>>>(); test_areal<point_xy<bm::number<bm::cpp_bin_float<50>>>>();
#endif
test_areal<point_xy<bm::number<bm::cpp_bin_float<100>>>>(); test_areal<point_xy<bm::number<bm::cpp_bin_float<100>>>>();
test_areal<point_xy<bm::number<bm::cpp_dec_float<50>>>>({}); test_areal<point_xy<bm::number<bm::cpp_dec_float<50>>>>({});
// Boost multi precision (rational) // Boost multi precision (rational)
test_areal<point_xy<bm::cpp_rational>>({exclude::fp}); test_areal<point_xy<bm::cpp_rational>>({exclude::fp});
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
test_areal<point_xy<bm::checked_cpp_rational>>({exclude::fp}); test_areal<point_xy<bm::checked_cpp_rational>>({exclude::fp});
#endif
// Boost multi precision float128 wrapper, is currently NOT supported // Boost multi precision float128 wrapper, is currently NOT supported
// and it is limited to certain compilers anyway // and it is limited to certain compilers anyway
@ -146,8 +154,10 @@ int test_main(int, char* [])
// Boost rational (tests compilation) // Boost rational (tests compilation)
// (the rectangular case is correct; other input might give wrong results) // (the rectangular case is correct; other input might give wrong results)
// The int16 version throws a <zero denominator> exception // The int16 version throws a <zero denominator> exception
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
test_areal<point_xy<boost::rational<std::int16_t>>>({exclude::all}); test_areal<point_xy<boost::rational<std::int16_t>>>({exclude::all});
test_areal<point_xy<boost::rational<std::int32_t>>>({exclude::fp}); test_areal<point_xy<boost::rational<std::int32_t>>>({exclude::fp});
#endif
test_areal<point_xy<boost::rational<std::int64_t>>>({exclude::fp}); test_areal<point_xy<boost::rational<std::int64_t>>>({exclude::fp});
return 0; return 0;

View File

@ -5,6 +5,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2021.
// Modifications copyright (c) 2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@ -222,6 +226,18 @@ void test_all()
"POINT(0 0)", "POINT(0 0)",
"POINT(0 0)", 1.0); "POINT(0 0)", 1.0);
test_geometry<bg::model::segment<P> >(
"SEGMENT(0 0, 1 1)",
"SEGMENT(0 0, 1 1)", 1.0);
test_geometry<bg::model::box<P> >(
"BOX(0 0, 1 1)",
"BOX(0 0, 1 1)", 1.0);
test_geometry<bg::model::multi_point<P> >(
"MULTIPOINT(0 0, 1 1, 2 2)",
"MULTIPOINT(0 0, 1 1, 2 2)", 1.0);
// RING: check compilation and behaviour // RING: check compilation and behaviour
test_geometry<bg::model::ring<P> >( test_geometry<bg::model::ring<P> >(

View File

@ -2,6 +2,11 @@
// Unit Test // Unit Test
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2021.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -15,6 +20,7 @@
#include <geometry_test_common.hpp> #include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/perimeter.hpp> #include <boost/geometry/algorithms/perimeter.hpp>
#include <boost/geometry/geometries/geometry_collection.hpp>
#include <boost/geometry/strategies/strategies.hpp> #include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/io/wkt/read.hpp> #include <boost/geometry/io/wkt/read.hpp>
@ -37,6 +43,16 @@ void test_perimeter(Geometry const& geometry, long double expected_perimeter)
#endif #endif
BOOST_CHECK_CLOSE(perimeter, expected_perimeter, 0.0001); BOOST_CHECK_CLOSE(perimeter, expected_perimeter, 0.0001);
boost::variant<Geometry> v(geometry);
perimeter = bg::perimeter(v);
BOOST_CHECK_CLOSE(perimeter, expected_perimeter, 0.0001);
bg::model::geometry_collection<boost::variant<Geometry>> gc{v};
perimeter = bg::perimeter(gc);
BOOST_CHECK_CLOSE(perimeter, expected_perimeter, 0.0001);
} }
@ -58,6 +74,16 @@ void test_perimeter(Geometry const& geometry, long double expected_perimeter, St
#endif #endif
BOOST_CHECK_CLOSE(perimeter, expected_perimeter, 0.0001); BOOST_CHECK_CLOSE(perimeter, expected_perimeter, 0.0001);
boost::variant<Geometry> v(geometry);
perimeter = bg::perimeter(v, strategy);
BOOST_CHECK_CLOSE(perimeter, expected_perimeter, 0.0001);
bg::model::geometry_collection<boost::variant<Geometry>> gc{v};
perimeter = bg::perimeter(gc, strategy);
BOOST_CHECK_CLOSE(perimeter, expected_perimeter, 0.0001);
} }
template <typename Geometry> template <typename Geometry>
@ -65,12 +91,7 @@ void test_geometry(std::string const& wkt, double expected_perimeter)
{ {
Geometry geometry; Geometry geometry;
bg::read_wkt(wkt, geometry); bg::read_wkt(wkt, geometry);
boost::variant<Geometry> v(geometry);
test_perimeter(geometry, expected_perimeter); test_perimeter(geometry, expected_perimeter);
#if !defined(BOOST_GEOMETRY_TEST_DEBUG)
test_perimeter(v, expected_perimeter);
#endif
} }
template <typename Geometry, typename Strategy> template <typename Geometry, typename Strategy>

View File

@ -2,6 +2,11 @@
// Unit Test // Unit Test
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2021.
// Modifications copyright (c) 2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License, // Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -18,11 +23,24 @@
#include <boost/geometry/algorithms/equals.hpp> #include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/simplify.hpp> #include <boost/geometry/algorithms/simplify.hpp>
#include <boost/geometry/algorithms/distance.hpp> #include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/geometries/geometry_collection.hpp>
#include <boost/geometry/strategies/strategies.hpp> #include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/io/wkt/wkt.hpp> #include <boost/geometry/io/wkt/wkt.hpp>
#include <boost/variant/variant.hpp> #include <boost/variant/variant.hpp>
template <typename Geometry, typename Tag = typename bg::tag<Geometry>::type>
struct boost_variant_type
{
using type = boost::variant<Geometry, typename bg::point_type<Geometry>::type>;
};
template <typename Geometry>
struct boost_variant_type<Geometry, bg::point_tag>
{
using type = boost::variant<Geometry>;
};
template template
< <
typename GeometryForTag, typename GeometryForTag,
@ -158,7 +176,8 @@ void test_geometry(std::string const& wkt,
bg::read_wkt(wkt, geometry); bg::read_wkt(wkt, geometry);
bg::read_wkt(expected_wkt, expected); bg::read_wkt(expected_wkt, expected);
boost::variant<Geometry> v(geometry); using variant_t = typename boost_variant_type<Geometry>::type;
variant_t v(geometry);
// Define default strategy for testing // Define default strategy for testing
typedef bg::strategy::simplify::douglas_peucker typedef bg::strategy::simplify::douglas_peucker
@ -167,15 +186,27 @@ void test_geometry(std::string const& wkt,
bg::strategy::distance::projected_point<double> bg::strategy::distance::projected_point<double>
> dp; > dp;
BOOST_CONCEPT_ASSERT((bg::concepts::SimplifyStrategy<dp, point_type>));
check_geometry(geometry, expected, distance); check_geometry(geometry, expected, distance);
check_geometry(v, expected, distance); check_geometry(v, expected, distance);
BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy<dp, point_type>) );
check_geometry(geometry, expected, distance, dp()); check_geometry(geometry, expected, distance, dp());
check_geometry(v, expected, distance, dp()); check_geometry(v, expected, distance, dp());
// For now check GC here because it's not supported by equals()
{
using gc_t = bg::model::geometry_collection<variant_t>;
gc_t gc{v};
gc_t gc_simplified;
bg::simplify(gc, gc_simplified, distance);
bg::detail::visit_breadth_first([&](auto const& g)
{
test_equality<Geometry>::apply(g, expected);
return false;
}, gc_simplified);
}
// Check inserter (if applicable) // Check inserter (if applicable)
test_inserter test_inserter
< <
@ -217,7 +248,7 @@ void test_geometry(std::string const& wkt,
bg::correct_closure(geometry); bg::correct_closure(geometry);
bg::correct_closure(expected); bg::correct_closure(expected);
boost::variant<Geometry> v(geometry); typename boost_variant_type<Geometry>::type v(geometry);
BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy<Strategy, BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy<Strategy,
typename bg::point_type<Geometry>::type>) ); typename bg::point_type<Geometry>::type>) );