update boost
This commit is contained in:
@@ -1,147 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2016-2018, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_HPP
|
||||
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
//#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/strategies/area.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace area
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Cartesian area calculation
|
||||
\ingroup strategies
|
||||
\details Calculates cartesian area using the trapezoidal rule
|
||||
\tparam CalculationType \tparam_calculation
|
||||
|
||||
\qbk{
|
||||
[heading See also]
|
||||
[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
|
||||
}
|
||||
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename CalculationType = void
|
||||
>
|
||||
class cartesian
|
||||
{
|
||||
public :
|
||||
template <typename Geometry>
|
||||
struct result_type
|
||||
: strategy::area::detail::result_type
|
||||
<
|
||||
Geometry,
|
||||
CalculationType
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Geometry>
|
||||
class state
|
||||
{
|
||||
friend class cartesian;
|
||||
|
||||
typedef typename result_type<Geometry>::type return_type;
|
||||
|
||||
public:
|
||||
inline state()
|
||||
: sum(0)
|
||||
{
|
||||
// Strategy supports only 2D areas
|
||||
assert_dimension<Geometry, 2>();
|
||||
}
|
||||
|
||||
private:
|
||||
inline return_type area() const
|
||||
{
|
||||
return_type const two = 2;
|
||||
return sum / two;
|
||||
}
|
||||
|
||||
return_type sum;
|
||||
};
|
||||
|
||||
template <typename PointOfSegment, typename Geometry>
|
||||
static inline void apply(PointOfSegment const& p1,
|
||||
PointOfSegment const& p2,
|
||||
state<Geometry>& st)
|
||||
{
|
||||
typedef typename state<Geometry>::return_type return_type;
|
||||
|
||||
// Below formulas are equivalent, however the two lower ones
|
||||
// suffer less from accuracy loss for great values of coordinates.
|
||||
// See: https://svn.boost.org/trac/boost/ticket/11928
|
||||
|
||||
// SUM += x2 * y1 - x1 * y2;
|
||||
// state.sum += detail::determinant<return_type>(p2, p1);
|
||||
|
||||
// SUM += (x2 - x1) * (y2 + y1)
|
||||
//state.sum += (return_type(get<0>(p2)) - return_type(get<0>(p1)))
|
||||
// * (return_type(get<1>(p2)) + return_type(get<1>(p1)));
|
||||
|
||||
// SUM += (x1 + x2) * (y1 - y2)
|
||||
st.sum += (return_type(get<0>(p1)) + return_type(get<0>(p2)))
|
||||
* (return_type(get<1>(p1)) - return_type(get<1>(p2)));
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
static inline typename result_type<Geometry>::type
|
||||
result(state<Geometry>& st)
|
||||
{
|
||||
return st.area();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
template <>
|
||||
struct default_strategy<cartesian_tag>
|
||||
{
|
||||
typedef strategy::area::cartesian<> type;
|
||||
};
|
||||
|
||||
} // namespace services
|
||||
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
|
||||
}} // namespace strategy::area
|
||||
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
#include <boost/geometry/strategy/cartesian/area.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_HPP
|
||||
|
||||
@@ -1,29 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2016, 2017.
|
||||
// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP
|
||||
|
||||
|
||||
// keep this file for now, for backward compatibility
|
||||
// functionality-wise, make it equivalent to boost/geometry/strategies/cartesian/area.hpp
|
||||
#include <boost/geometry/strategies/cartesian/area.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/area.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2016-2018 Oracle and/or its affiliates.
|
||||
// Copyright (c) 2016-2021 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -11,32 +11,81 @@
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/azimuth.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace azimuth
|
||||
{
|
||||
|
||||
template
|
||||
<
|
||||
typename CalculationType = void
|
||||
>
|
||||
template <typename CalculationType = void>
|
||||
class cartesian
|
||||
{};
|
||||
{
|
||||
public:
|
||||
template <typename T1, typename T2>
|
||||
struct result_type
|
||||
: geometry::select_most_precise
|
||||
<
|
||||
// NOTE: this promotes any integer type to double
|
||||
typename geometry::promote_floating_point<T1, double>::type,
|
||||
typename geometry::promote_floating_point<T2, double>::type,
|
||||
CalculationType
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename T1, typename T2, typename Result>
|
||||
static inline void apply(T1 const& x1, T1 const& y1,
|
||||
T2 const& x2, T2 const& y2,
|
||||
Result& a1, Result& a2)
|
||||
{
|
||||
compute(x1, y1, x2, y2, a1, a2);
|
||||
}
|
||||
template <typename T1, typename T2, typename Result>
|
||||
static inline void apply(T1 const& x1, T1 const& y1,
|
||||
T2 const& x2, T2 const& y2,
|
||||
Result& a1)
|
||||
{
|
||||
compute(x1, y1, x2, y2, a1, a1);
|
||||
}
|
||||
template <typename T1, typename T2, typename Result>
|
||||
static inline void apply_reverse(T1 const& x1, T1 const& y1,
|
||||
T2 const& x2, T2 const& y2,
|
||||
Result& a2)
|
||||
{
|
||||
compute(x1, y1, x2, y2, a2, a2);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T1, typename T2, typename Result>
|
||||
static inline void compute(T1 const& x1, T1 const& y1,
|
||||
T2 const& x2, T2 const& y2,
|
||||
Result& a1, Result& a2)
|
||||
{
|
||||
typedef typename result_type<T1, T2>::type calc_t;
|
||||
|
||||
// NOTE: azimuth 0 is at Y axis, increasing right
|
||||
// as in spherical/geographic where 0 is at North axis
|
||||
a1 = a2 = atan2(calc_t(x2) - calc_t(x1), calc_t(y2) - calc_t(y1));
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<cartesian_tag, CalculationType>
|
||||
template <>
|
||||
struct default_strategy<cartesian_tag>
|
||||
{
|
||||
typedef strategy::azimuth::cartesian<CalculationType> type;
|
||||
typedef strategy::azimuth::cartesian<> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016, 2017.
|
||||
// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2020.
|
||||
// Modifications copyright (c) 2016-2020, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -36,6 +36,11 @@ namespace within
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
|
||||
struct box_within_coord
|
||||
{
|
||||
template <typename BoxContainedValue, typename BoxContainingValue>
|
||||
@@ -63,18 +68,6 @@ struct box_covered_by_coord
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry, std::size_t Dimension, typename CSTag>
|
||||
struct box_within_range
|
||||
: box_within_coord
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry, std::size_t Dimension, typename CSTag>
|
||||
struct box_covered_by_range
|
||||
: box_covered_by_coord
|
||||
{};
|
||||
|
||||
|
||||
struct box_within_longitude_diff
|
||||
{
|
||||
template <typename CalcT>
|
||||
@@ -109,7 +102,7 @@ struct box_longitude_range
|
||||
BoxContainedValue,
|
||||
BoxContainingValue
|
||||
>::type calc_t;
|
||||
typedef typename coordinate_system<Geometry>::type::units units_t;
|
||||
typedef typename geometry::detail::cs_angular_units<Geometry>::type units_t;
|
||||
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
|
||||
|
||||
if (CoordCheck::apply(bed_min, bed_max, bing_min, bing_max))
|
||||
@@ -120,7 +113,7 @@ struct box_longitude_range
|
||||
// min <= max <=> diff >= 0
|
||||
calc_t const diff_ed = bed_max - bed_min;
|
||||
calc_t const diff_ing = bing_max - bing_min;
|
||||
|
||||
|
||||
// if containing covers the whole globe it contains all
|
||||
if (diff_ing >= constants::period())
|
||||
{
|
||||
@@ -144,35 +137,21 @@ struct box_longitude_range
|
||||
};
|
||||
|
||||
|
||||
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
|
||||
template <typename Geometry>
|
||||
struct box_within_range<Geometry, 0, spherical_tag>
|
||||
: box_longitude_range<Geometry, box_within_coord, box_within_longitude_diff>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct box_covered_by_range<Geometry, 0, spherical_tag>
|
||||
: box_longitude_range<Geometry, box_covered_by_coord, box_covered_by_longitude_diff>
|
||||
{};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
template <typename, std::size_t, typename> class SubStrategy,
|
||||
typename Box1,
|
||||
typename Box2,
|
||||
typename CSTag,
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct relate_box_box_loop
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)
|
||||
{
|
||||
assert_dimension_equal<Box1, Box2>();
|
||||
typedef typename tag_cast<typename cs_tag<Box1>::type, spherical_tag>::type cs_tag_t;
|
||||
|
||||
if (! SubStrategy<Box1, Dimension, cs_tag_t>::apply(
|
||||
if (! SubStrategy<Box1, Dimension, CSTag>::apply(
|
||||
get<min_corner, Dimension>(b_contained),
|
||||
get<max_corner, Dimension>(b_contained),
|
||||
get<min_corner, Dimension>(b_containing),
|
||||
@@ -183,10 +162,9 @@ struct relate_box_box_loop
|
||||
return false;
|
||||
}
|
||||
|
||||
return relate_box_box_loop
|
||||
return within::detail::relate_box_box_loop
|
||||
<
|
||||
SubStrategy,
|
||||
Box1, Box2,
|
||||
SubStrategy, CSTag,
|
||||
Dimension + 1, DimensionCount
|
||||
>::apply(b_contained, b_containing);
|
||||
}
|
||||
@@ -195,32 +173,82 @@ struct relate_box_box_loop
|
||||
template
|
||||
<
|
||||
template <typename, std::size_t, typename> class SubStrategy,
|
||||
typename Box1,
|
||||
typename Box2,
|
||||
typename CSTag,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct relate_box_box_loop<SubStrategy, Box1, Box2, DimensionCount, DimensionCount>
|
||||
struct relate_box_box_loop<SubStrategy, CSTag, DimensionCount, DimensionCount>
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline bool apply(Box1 const& , Box2 const& )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template
|
||||
<
|
||||
typename Box1,
|
||||
typename Box2,
|
||||
template <typename, std::size_t, typename> class SubStrategy = box_within_range
|
||||
>
|
||||
struct box_in_box
|
||||
|
||||
template <typename Geometry, std::size_t Dimension, typename CSTag>
|
||||
struct box_within_range
|
||||
: within::detail::box_within_coord
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry, std::size_t Dimension, typename CSTag>
|
||||
struct box_covered_by_range
|
||||
: within::detail::box_covered_by_coord
|
||||
{};
|
||||
|
||||
|
||||
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
|
||||
template <typename Geometry>
|
||||
struct box_within_range<Geometry, 0, spherical_tag>
|
||||
: within::detail::box_longitude_range
|
||||
<
|
||||
Geometry,
|
||||
within::detail::box_within_coord,
|
||||
within::detail::box_within_longitude_diff
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct box_covered_by_range<Geometry, 0, spherical_tag>
|
||||
: within::detail::box_longitude_range
|
||||
<
|
||||
Geometry,
|
||||
within::detail::box_covered_by_coord,
|
||||
within::detail::box_covered_by_longitude_diff
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
struct cartesian_box_box
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2)
|
||||
{
|
||||
return relate_box_box_loop
|
||||
return within::detail::relate_box_box_loop
|
||||
<
|
||||
SubStrategy,
|
||||
Box1, Box2, 0, dimension<Box1>::type::value
|
||||
within::detail::box_within_range,
|
||||
cartesian_tag,
|
||||
0, dimension<Box1>::type::value
|
||||
>::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
struct spherical_box_box
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2)
|
||||
{
|
||||
return within::detail::relate_box_box_loop
|
||||
<
|
||||
within::detail::box_within_range,
|
||||
spherical_tag,
|
||||
0, dimension<Box1>::type::value
|
||||
>::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
@@ -229,6 +257,42 @@ struct box_in_box
|
||||
} // namespace within
|
||||
|
||||
|
||||
namespace covered_by
|
||||
{
|
||||
|
||||
|
||||
struct cartesian_box_box
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2)
|
||||
{
|
||||
return within::detail::relate_box_box_loop
|
||||
<
|
||||
within::detail::box_covered_by_range,
|
||||
cartesian_tag,
|
||||
0, dimension<Box1>::type::value
|
||||
>::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
struct spherical_box_box
|
||||
{
|
||||
template <typename Box1, typename Box2>
|
||||
static inline bool apply(Box1 const& box1, Box2 const& box2)
|
||||
{
|
||||
return within::detail::relate_box_box_loop
|
||||
<
|
||||
within::detail::box_covered_by_range,
|
||||
spherical_tag,
|
||||
0, dimension<Box1>::type::value
|
||||
>::apply(box1, box2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
|
||||
@@ -244,7 +308,7 @@ struct default_strategy
|
||||
cartesian_tag, cartesian_tag
|
||||
>
|
||||
{
|
||||
typedef within::box_in_box<BoxContained, BoxContaining> type;
|
||||
typedef cartesian_box_box type;
|
||||
};
|
||||
|
||||
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
|
||||
@@ -257,7 +321,7 @@ struct default_strategy
|
||||
spherical_tag, spherical_tag
|
||||
>
|
||||
{
|
||||
typedef within::box_in_box<BoxContained, BoxContaining> type;
|
||||
typedef spherical_box_box type;
|
||||
};
|
||||
|
||||
|
||||
@@ -275,11 +339,7 @@ struct default_strategy
|
||||
cartesian_tag, cartesian_tag
|
||||
>
|
||||
{
|
||||
typedef within::box_in_box
|
||||
<
|
||||
BoxContained, BoxContaining,
|
||||
within::box_covered_by_range
|
||||
> type;
|
||||
typedef cartesian_box_box type;
|
||||
};
|
||||
|
||||
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
|
||||
@@ -292,11 +352,7 @@ struct default_strategy
|
||||
spherical_tag, spherical_tag
|
||||
>
|
||||
{
|
||||
typedef within::box_in_box
|
||||
<
|
||||
BoxContained, BoxContaining,
|
||||
within::box_covered_by_range
|
||||
> type;
|
||||
typedef spherical_box_box type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public :
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
//! Fills output_range with a flat end
|
||||
template <typename Point, typename RangeOut, typename DistanceStrategy>
|
||||
template <typename Point, typename DistanceStrategy, typename RangeOut>
|
||||
inline void apply(Point const& penultimate_point,
|
||||
Point const& perp_left_point,
|
||||
Point const& ultimate_point,
|
||||
@@ -63,20 +63,13 @@ public :
|
||||
DistanceStrategy const& distance,
|
||||
RangeOut& range_out) const
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
auto const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);
|
||||
auto const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);
|
||||
|
||||
typedef typename geometry::select_most_precise
|
||||
<
|
||||
coordinate_type,
|
||||
double
|
||||
>::type promoted_type;
|
||||
bool const reversed =
|
||||
(side == buffer_side_left && dist_right < 0 && -dist_right > dist_left)
|
||||
|| (side == buffer_side_right && dist_left < 0 && -dist_left > dist_right);
|
||||
|
||||
promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);
|
||||
promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);
|
||||
|
||||
bool reversed = (side == buffer_side_left && dist_right < 0 && -dist_right > dist_left)
|
||||
|| (side == buffer_side_right && dist_left < 0 && -dist_left > dist_right)
|
||||
;
|
||||
if (reversed)
|
||||
{
|
||||
range_out.push_back(perp_right_point);
|
||||
@@ -89,7 +82,7 @@ public :
|
||||
}
|
||||
// Don't add the ultimate_point (endpoint of the linestring).
|
||||
// The buffer might be generated completely at one side.
|
||||
// In other cases it does no harm but is further useless
|
||||
// In other cases it does no harm but it is useless
|
||||
}
|
||||
|
||||
template <typename NumericType>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015-2023.
|
||||
// Modifications copyright (c) 2015-2023, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
@@ -14,7 +14,11 @@
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
@@ -22,8 +26,6 @@
|
||||
#include <boost/geometry/strategies/buffer.hpp>
|
||||
|
||||
|
||||
#include <boost/geometry/io/wkt/wkt.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
@@ -80,8 +82,8 @@ private :
|
||||
for (std::size_t i = 0; i < point_buffer_count; i++, alpha -= diff)
|
||||
{
|
||||
typename boost::range_value<RangeOut>::type p;
|
||||
set<0>(p, get<0>(point) + buffer_distance * cos(alpha));
|
||||
set<1>(p, get<1>(point) + buffer_distance * sin(alpha));
|
||||
geometry::set<0>(p, geometry::get<0>(point) + buffer_distance * cos(alpha));
|
||||
geometry::set<1>(p, geometry::get<1>(point) + buffer_distance * sin(alpha));
|
||||
range_out.push_back(p);
|
||||
}
|
||||
}
|
||||
@@ -98,16 +100,15 @@ private :
|
||||
public :
|
||||
|
||||
//! \brief Constructs the strategy
|
||||
//! \param points_per_circle points which would be used for a full circle
|
||||
//! (if points_per_circle is smaller than 4, it is internally set to 4)
|
||||
explicit inline end_round(std::size_t points_per_circle = 90)
|
||||
: m_points_per_circle((points_per_circle < 4u) ? 4u : points_per_circle)
|
||||
//! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
|
||||
explicit inline end_round(std::size_t points_per_circle = default_points_per_circle)
|
||||
: m_points_per_circle(get_point_count_for_end(points_per_circle))
|
||||
{}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
//! Fills output_range with a flat end
|
||||
template <typename Point, typename RangeOut, typename DistanceStrategy>
|
||||
//! Fills output_range with a round end
|
||||
template <typename Point, typename DistanceStrategy, typename RangeOut>
|
||||
inline void apply(Point const& penultimate_point,
|
||||
Point const& perp_left_point,
|
||||
Point const& ultimate_point,
|
||||
@@ -116,6 +117,7 @@ public :
|
||||
DistanceStrategy const& distance,
|
||||
RangeOut& range_out) const
|
||||
{
|
||||
boost::ignore_unused(perp_left_point);
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
typedef typename geometry::select_most_precise
|
||||
@@ -124,28 +126,29 @@ public :
|
||||
double
|
||||
>::type promoted_type;
|
||||
|
||||
promoted_type const alpha = calculate_angle<promoted_type>(perp_left_point, ultimate_point);
|
||||
|
||||
promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);
|
||||
promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);
|
||||
promoted_type const alpha
|
||||
= calculate_angle<promoted_type>(penultimate_point, ultimate_point)
|
||||
- geometry::math::half_pi<promoted_type>();
|
||||
|
||||
if (geometry::math::equals(dist_left, dist_right))
|
||||
{
|
||||
generate_points(ultimate_point, alpha, dist_left, range_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
promoted_type const two = 2.0;
|
||||
promoted_type dist_half_diff = (dist_left - dist_right) / two;
|
||||
|
||||
if (side == buffer_side_right)
|
||||
{
|
||||
dist_half_diff = -dist_half_diff;
|
||||
}
|
||||
static promoted_type const two = 2.0;
|
||||
promoted_type const dist_average = (dist_left + dist_right) / two;
|
||||
promoted_type const dist_half
|
||||
= (side == buffer_side_right
|
||||
? (dist_right - dist_left)
|
||||
: (dist_left - dist_right)) / two;
|
||||
|
||||
Point shifted_point;
|
||||
set<0>(shifted_point, get<0>(ultimate_point) + dist_half_diff * cos(alpha));
|
||||
set<1>(shifted_point, get<1>(ultimate_point) + dist_half_diff * sin(alpha));
|
||||
generate_points(shifted_point, alpha, (dist_left + dist_right) / two, range_out);
|
||||
geometry::set<0>(shifted_point, geometry::get<0>(ultimate_point) + dist_half * cos(alpha));
|
||||
geometry::set<1>(shifted_point, geometry::get<1>(ultimate_point) + dist_half * sin(alpha));
|
||||
generate_points(shifted_point, alpha, dist_average, range_out);
|
||||
}
|
||||
|
||||
if (m_points_per_circle % 2 == 1)
|
||||
|
||||
@@ -89,8 +89,8 @@ public:
|
||||
// Check the distance ip-vertex (= miter distance)
|
||||
// (We calculate it manually (not using Pythagoras strategy) to reuse
|
||||
// dx and dy)
|
||||
coordinate_type const dx = get<0>(p) - get<0>(vertex);
|
||||
coordinate_type const dy = get<1>(p) - get<1>(vertex);
|
||||
promoted_type const dx = get<0>(p) - get<0>(vertex);
|
||||
promoted_type const dy = get<1>(p) - get<1>(vertex);
|
||||
|
||||
promoted_type const distance = geometry::math::sqrt(dx * dx + dy * dy);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
|
||||
@@ -58,9 +59,9 @@ class join_round
|
||||
public :
|
||||
|
||||
//! \brief Constructs the strategy
|
||||
//! \param points_per_circle points which would be used for a full circle
|
||||
explicit inline join_round(std::size_t points_per_circle = 90)
|
||||
: m_points_per_circle(points_per_circle)
|
||||
//! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
|
||||
explicit inline join_round(std::size_t points_per_circle = default_points_per_circle)
|
||||
: m_points_per_circle(get_point_count_for_join(points_per_circle))
|
||||
{}
|
||||
|
||||
private :
|
||||
@@ -143,26 +144,15 @@ public :
|
||||
geometry::equal_to<Point> equals;
|
||||
if (equals(perp1, perp2))
|
||||
{
|
||||
boost::ignore_unused(ip);
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
|
||||
std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate 'vectors'
|
||||
coordinate_type vix = (get<0>(ip) - get<0>(vertex));
|
||||
coordinate_type viy = (get<1>(ip) - get<1>(vertex));
|
||||
|
||||
promoted_type length_i = geometry::math::sqrt(vix * vix + viy * viy);
|
||||
DistanceType const bd = geometry::math::abs(buffer_distance);
|
||||
promoted_type prop = bd / length_i;
|
||||
|
||||
Point bp;
|
||||
set<0>(bp, get<0>(vertex) + vix * prop);
|
||||
set<1>(bp, get<1>(vertex) + viy * prop);
|
||||
|
||||
range_out.push_back(perp1);
|
||||
generate_points<promoted_type>(vertex, perp1, perp2, bd, range_out);
|
||||
generate_points<promoted_type>(vertex, perp1, perp2, geometry::math::abs(buffer_distance), range_out);
|
||||
range_out.push_back(perp2);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,23 +48,21 @@ public :
|
||||
RangeOut& range_out,
|
||||
std::size_t level = 1) const
|
||||
{
|
||||
typedef typename coordinate_type<Point>::type coordinate_type;
|
||||
|
||||
// Generate 'vectors'
|
||||
coordinate_type const vp1_x = get<0>(p1) - get<0>(vertex);
|
||||
coordinate_type const vp1_y = get<1>(p1) - get<1>(vertex);
|
||||
PromotedType const vp1_x = get<0>(p1) - get<0>(vertex);
|
||||
PromotedType const vp1_y = get<1>(p1) - get<1>(vertex);
|
||||
|
||||
coordinate_type const vp2_x = (get<0>(p2) - get<0>(vertex));
|
||||
coordinate_type const vp2_y = (get<1>(p2) - get<1>(vertex));
|
||||
PromotedType const vp2_x = (get<0>(p2) - get<0>(vertex));
|
||||
PromotedType const vp2_y = (get<1>(p2) - get<1>(vertex));
|
||||
|
||||
// Average them to generate vector in between
|
||||
coordinate_type const two = 2;
|
||||
coordinate_type const v_x = (vp1_x + vp2_x) / two;
|
||||
coordinate_type const v_y = (vp1_y + vp2_y) / two;
|
||||
PromotedType const two = 2;
|
||||
PromotedType const v_x = (vp1_x + vp2_x) / two;
|
||||
PromotedType const v_y = (vp1_y + vp2_y) / two;
|
||||
|
||||
PromotedType const length2 = geometry::math::sqrt(v_x * v_x + v_y * v_y);
|
||||
|
||||
PromotedType prop = buffer_distance / length2;
|
||||
PromotedType const prop = buffer_distance / length2;
|
||||
|
||||
Point mid_point;
|
||||
set<0>(mid_point, get<0>(vertex) + v_x * prop);
|
||||
@@ -106,13 +104,13 @@ public :
|
||||
}
|
||||
|
||||
// Generate 'vectors'
|
||||
coordinate_type const vix = (get<0>(ip) - get<0>(vertex));
|
||||
coordinate_type const viy = (get<1>(ip) - get<1>(vertex));
|
||||
promoted_type const vix = (get<0>(ip) - get<0>(vertex));
|
||||
promoted_type const viy = (get<1>(ip) - get<1>(vertex));
|
||||
|
||||
promoted_type const length_i = geometry::math::sqrt(vix * vix + viy * viy);
|
||||
|
||||
promoted_type const bd = geometry::math::abs(buffer_distance);
|
||||
promoted_type prop = bd / length_i;
|
||||
promoted_type const prop = bd / length_i;
|
||||
|
||||
Point bp;
|
||||
set<0>(bp, get<0>(vertex) + vix * prop);
|
||||
|
||||
@@ -57,10 +57,9 @@ class point_circle
|
||||
{
|
||||
public :
|
||||
//! \brief Constructs the strategy
|
||||
//! \param count number of points for the created circle (if count
|
||||
//! is smaller than 3, count is internally set to 3)
|
||||
explicit point_circle(std::size_t count = 90)
|
||||
: m_count((count < 3u) ? 3u : count)
|
||||
//! \param count Number of points (minimum 3) for the created circle
|
||||
explicit point_circle(std::size_t count = default_points_per_circle)
|
||||
: m_count(get_point_count_for_circle(count))
|
||||
{}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
@@ -54,12 +54,13 @@ class point_square
|
||||
<
|
||||
typename Point,
|
||||
typename DistanceType,
|
||||
typename MultiplierType,
|
||||
typename OutputRange
|
||||
>
|
||||
inline void add_point(Point const& point,
|
||||
DistanceType const& distance,
|
||||
DistanceType const& x,
|
||||
DistanceType const& y,
|
||||
MultiplierType const& x,
|
||||
MultiplierType const& y,
|
||||
OutputRange& output_range) const
|
||||
{
|
||||
typename boost::range_value<OutputRange>::type p;
|
||||
|
||||
@@ -47,6 +47,13 @@ class side_straight
|
||||
{
|
||||
public :
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
// Returns true if the buffer distance is always the same
|
||||
static inline bool equidistant()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
@@ -69,8 +76,8 @@ public :
|
||||
// Generate a block along (left or right of) the segment
|
||||
|
||||
// Simulate a vector d (dx,dy)
|
||||
coordinate_type const dx = get<0>(input_p2) - get<0>(input_p1);
|
||||
coordinate_type const dy = get<1>(input_p2) - get<1>(input_p1);
|
||||
promoted_type const dx = get<0>(input_p2) - get<0>(input_p1);
|
||||
promoted_type const dy = get<1>(input_p2) - get<1>(input_p1);
|
||||
|
||||
// For normalization [0,1] (=dot product d.d, sqrt)
|
||||
promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy);
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2015-2021.
|
||||
// Modifications copyright (c) 2015-2021 Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -44,19 +44,20 @@ namespace strategy { namespace centroid
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename PointCentroid,
|
||||
typename Point = PointCentroid
|
||||
typename Ignored1 = void,
|
||||
typename Ignored2 = void
|
||||
>
|
||||
class average
|
||||
{
|
||||
private :
|
||||
|
||||
/*! subclass to keep state */
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
class sum
|
||||
{
|
||||
friend class average;
|
||||
signed_size_type count;
|
||||
PointCentroid centroid;
|
||||
ResultPoint centroid;
|
||||
|
||||
public :
|
||||
inline sum()
|
||||
@@ -67,17 +68,23 @@ private :
|
||||
};
|
||||
|
||||
public :
|
||||
typedef sum state_type;
|
||||
typedef PointCentroid centroid_point_type;
|
||||
typedef Point point_type;
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
struct state_type
|
||||
{
|
||||
typedef sum<GeometryPoint, ResultPoint> type;
|
||||
};
|
||||
|
||||
static inline void apply(Point const& p, sum& state)
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
static inline void apply(GeometryPoint const& p,
|
||||
sum<GeometryPoint, ResultPoint>& state)
|
||||
{
|
||||
add_point(state.centroid, p);
|
||||
state.count++;
|
||||
}
|
||||
|
||||
static inline bool result(sum const& state, PointCentroid& centroid)
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
static inline bool result(sum<GeometryPoint, ResultPoint> const& state,
|
||||
ResultPoint& centroid)
|
||||
{
|
||||
centroid = state.centroid;
|
||||
if ( state.count > 0 )
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2018.
|
||||
// Modifications copyright (c) 2015, 2018, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015-2021.
|
||||
// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
@@ -23,16 +22,14 @@
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/type_traits/is_void.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
#include <boost/geometry/strategies/centroid.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -121,8 +118,8 @@ Statements:
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename PointOfSegment = Point,
|
||||
typename Ignored1 = void,
|
||||
typename Ignored2 = void,
|
||||
typename CalculationType = void
|
||||
>
|
||||
class bashein_detmer
|
||||
@@ -132,45 +129,52 @@ private :
|
||||
// whatever it is and whatever the point-type(s) are.
|
||||
// Else, use the most appropriate coordinate type
|
||||
// of the two points, but at least double
|
||||
typedef typename
|
||||
boost::mpl::if_c
|
||||
<
|
||||
boost::is_void<CalculationType>::type::value,
|
||||
typename select_most_precise
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
struct calculation_type
|
||||
: std::conditional
|
||||
<
|
||||
typename select_coordinate_type
|
||||
std::is_void<CalculationType>::value,
|
||||
typename select_most_precise
|
||||
<
|
||||
Point,
|
||||
PointOfSegment
|
||||
typename coordinate_type<GeometryPoint>::type,
|
||||
typename coordinate_type<ResultPoint>::type,
|
||||
double
|
||||
>::type,
|
||||
double
|
||||
>::type,
|
||||
CalculationType
|
||||
>::type calculation_type;
|
||||
CalculationType
|
||||
>
|
||||
{};
|
||||
|
||||
/*! subclass to keep state */
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
class sums
|
||||
{
|
||||
typedef typename calculation_type<GeometryPoint, ResultPoint>::type calc_type;
|
||||
|
||||
friend class bashein_detmer;
|
||||
std::size_t count;
|
||||
calculation_type sum_a2;
|
||||
calculation_type sum_x;
|
||||
calculation_type sum_y;
|
||||
calc_type sum_a2;
|
||||
calc_type sum_x;
|
||||
calc_type sum_y;
|
||||
|
||||
public :
|
||||
inline sums()
|
||||
: count(0)
|
||||
, sum_a2(calculation_type())
|
||||
, sum_x(calculation_type())
|
||||
, sum_y(calculation_type())
|
||||
, sum_a2(calc_type())
|
||||
, sum_x(calc_type())
|
||||
, sum_y(calc_type())
|
||||
{}
|
||||
};
|
||||
|
||||
public :
|
||||
typedef sums state_type;
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
struct state_type
|
||||
{
|
||||
typedef sums<GeometryPoint, ResultPoint> type;
|
||||
};
|
||||
|
||||
static inline void apply(PointOfSegment const& p1,
|
||||
PointOfSegment const& p2, sums& state)
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
static inline void apply(GeometryPoint const& p1, GeometryPoint const& p2,
|
||||
sums<GeometryPoint, ResultPoint>& state)
|
||||
{
|
||||
/* Algorithm:
|
||||
For each segment:
|
||||
@@ -183,29 +187,35 @@ public :
|
||||
return POINT(sum_x / (3 * sum_a2), sum_y / (3 * sum_a2) )
|
||||
*/
|
||||
|
||||
typedef typename calculation_type<GeometryPoint, ResultPoint>::type calc_type;
|
||||
|
||||
// Get coordinates and promote them to calculation_type
|
||||
calculation_type const x1 = boost::numeric_cast<calculation_type>(get<0>(p1));
|
||||
calculation_type const y1 = boost::numeric_cast<calculation_type>(get<1>(p1));
|
||||
calculation_type const x2 = boost::numeric_cast<calculation_type>(get<0>(p2));
|
||||
calculation_type const y2 = boost::numeric_cast<calculation_type>(get<1>(p2));
|
||||
calculation_type const ai = geometry::detail::determinant<calculation_type>(p1, p2);
|
||||
calc_type const x1 = boost::numeric_cast<calc_type>(get<0>(p1));
|
||||
calc_type const y1 = boost::numeric_cast<calc_type>(get<1>(p1));
|
||||
calc_type const x2 = boost::numeric_cast<calc_type>(get<0>(p2));
|
||||
calc_type const y2 = boost::numeric_cast<calc_type>(get<1>(p2));
|
||||
calc_type const ai = geometry::detail::determinant<calc_type>(p1, p2);
|
||||
state.count++;
|
||||
state.sum_a2 += ai;
|
||||
state.sum_x += ai * (x1 + x2);
|
||||
state.sum_y += ai * (y1 + y2);
|
||||
}
|
||||
|
||||
static inline bool result(sums const& state, Point& centroid)
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
static inline bool result(sums<GeometryPoint, ResultPoint> const& state,
|
||||
ResultPoint& centroid)
|
||||
{
|
||||
calculation_type const zero = calculation_type();
|
||||
typedef typename calculation_type<GeometryPoint, ResultPoint>::type calc_type;
|
||||
|
||||
calc_type const zero = calc_type();
|
||||
if (state.count > 0 && ! math::equals(state.sum_a2, zero))
|
||||
{
|
||||
calculation_type const v3 = 3;
|
||||
calculation_type const a3 = v3 * state.sum_a2;
|
||||
calc_type const v3 = 3;
|
||||
calc_type const a3 = v3 * state.sum_a2;
|
||||
|
||||
typedef typename geometry::coordinate_type
|
||||
<
|
||||
Point
|
||||
ResultPoint
|
||||
>::type coordinate_type;
|
||||
|
||||
// Prevent NaN centroid coordinates
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2015.
|
||||
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015-2023.
|
||||
// Modifications copyright (c) 2015-2023, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
@@ -21,17 +21,19 @@
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/distance/interface.hpp>
|
||||
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
|
||||
#include <boost/geometry/algorithms/assign.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/arithmetic.hpp>
|
||||
#include <boost/geometry/util/for_each_coordinate.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
#include <boost/geometry/strategies/centroid.hpp>
|
||||
#include <boost/geometry/strategies/default_distance_result.hpp>
|
||||
|
||||
// Helper geometry
|
||||
#include <boost/geometry/geometries/point.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/strategies/centroid.hpp>
|
||||
|
||||
#include <boost/geometry/util/algorithm.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -39,66 +41,85 @@ namespace boost { namespace geometry
|
||||
namespace strategy { namespace centroid
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename Type, std::size_t DimensionCount>
|
||||
struct weighted_length_sums
|
||||
{
|
||||
typedef typename geometry::model::point
|
||||
<
|
||||
Type, DimensionCount,
|
||||
cs::cartesian
|
||||
> work_point;
|
||||
|
||||
Type length;
|
||||
work_point average_sum;
|
||||
|
||||
inline weighted_length_sums()
|
||||
: length(Type())
|
||||
{
|
||||
geometry::assign_zero(average_sum);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename PointOfSegment = Point
|
||||
typename Ignored1 = void,
|
||||
typename Ignored2 = void,
|
||||
typename CalculationType = void
|
||||
>
|
||||
class weighted_length
|
||||
{
|
||||
private :
|
||||
typedef typename select_most_precise
|
||||
<
|
||||
typename default_distance_result<Point>::type,
|
||||
typename default_distance_result<PointOfSegment>::type
|
||||
>::type distance_type;
|
||||
typedef geometry::strategy::distance::pythagoras<CalculationType> pythagoras_strategy;
|
||||
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
struct calculation_type
|
||||
{
|
||||
// Below the distance between two GeometryPoints is calculated.
|
||||
// ResultPoint is taken into account by passing them together here.
|
||||
typedef typename pythagoras_strategy::template calculation_type
|
||||
<
|
||||
GeometryPoint, ResultPoint
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
class sums
|
||||
{
|
||||
friend class weighted_length;
|
||||
template <typename, typename> friend struct set_sum_div_length;
|
||||
|
||||
typedef typename calculation_type<GeometryPoint, ResultPoint>::type calc_type;
|
||||
typedef typename geometry::model::point
|
||||
<
|
||||
calc_type,
|
||||
geometry::dimension<ResultPoint>::value,
|
||||
cs::cartesian
|
||||
> work_point;
|
||||
|
||||
calc_type length;
|
||||
work_point average_sum;
|
||||
|
||||
public:
|
||||
inline sums()
|
||||
: length(calc_type())
|
||||
{
|
||||
geometry::assign_zero(average_sum);
|
||||
}
|
||||
};
|
||||
|
||||
public :
|
||||
typedef detail::weighted_length_sums
|
||||
<
|
||||
distance_type,
|
||||
geometry::dimension<Point>::type::value
|
||||
> state_type;
|
||||
|
||||
static inline void apply(PointOfSegment const& p1,
|
||||
PointOfSegment const& p2, state_type& state)
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
struct state_type
|
||||
{
|
||||
distance_type const d = geometry::distance(p1, p2);
|
||||
typedef sums<GeometryPoint, ResultPoint> type;
|
||||
};
|
||||
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
static inline void apply(GeometryPoint const& p1, GeometryPoint const& p2,
|
||||
sums<GeometryPoint, ResultPoint>& state)
|
||||
{
|
||||
typedef typename calculation_type<GeometryPoint, ResultPoint>::type distance_type;
|
||||
|
||||
distance_type const d = pythagoras_strategy::apply(p1, p2);
|
||||
state.length += d;
|
||||
|
||||
typename state_type::work_point weighted_median;
|
||||
geometry::assign_zero(weighted_median);
|
||||
geometry::add_point(weighted_median, p1);
|
||||
geometry::add_point(weighted_median, p2);
|
||||
geometry::multiply_value(weighted_median, d/2);
|
||||
geometry::add_point(state.average_sum, weighted_median);
|
||||
distance_type const d_half = d / distance_type(2);
|
||||
geometry::detail::for_each_dimension<ResultPoint>([&](auto dimension)
|
||||
{
|
||||
distance_type const coord1 = get<dimension>(p1);
|
||||
distance_type const coord2 = get<dimension>(p2);
|
||||
distance_type const wm = (coord1 + coord2) * d_half; // weighted median
|
||||
set<dimension>(state.average_sum, get<dimension>(state.average_sum) + wm);
|
||||
});
|
||||
}
|
||||
|
||||
static inline bool result(state_type const& state, Point& centroid)
|
||||
template <typename GeometryPoint, typename ResultPoint>
|
||||
static inline bool result(sums<GeometryPoint, ResultPoint> const& state,
|
||||
ResultPoint& centroid)
|
||||
{
|
||||
typedef typename calculation_type<GeometryPoint, ResultPoint>::type distance_type;
|
||||
|
||||
distance_type const zero = distance_type();
|
||||
if (! geometry::math::equals(state.length, zero)
|
||||
&& boost::math::isfinite(state.length)) // Prevent NaN centroid coordinates
|
||||
@@ -106,31 +127,21 @@ public :
|
||||
// NOTE: above distance_type is checked, not the centroid coordinate_type
|
||||
// which means that the centroid can still be filled with INF
|
||||
// if e.g. distance_type is double and centroid contains floats
|
||||
geometry::for_each_coordinate(centroid, set_sum_div_length(state));
|
||||
geometry::detail::for_each_dimension<ResultPoint>([&](auto dimension)
|
||||
{
|
||||
typedef typename geometry::coordinate_type<ResultPoint>::type coordinate_type;
|
||||
geometry::set<dimension>(
|
||||
centroid,
|
||||
boost::numeric_cast<coordinate_type>(
|
||||
geometry::get<dimension>(state.average_sum) / state.length
|
||||
)
|
||||
);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct set_sum_div_length
|
||||
{
|
||||
state_type const& m_state;
|
||||
set_sum_div_length(state_type const& state)
|
||||
: m_state(state)
|
||||
{}
|
||||
template <typename Pt, std::size_t Dimension>
|
||||
void apply(Pt & centroid) const
|
||||
{
|
||||
typedef typename geometry::coordinate_type<Pt>::type coordinate_type;
|
||||
geometry::set<Dimension>(
|
||||
centroid,
|
||||
boost::numeric_cast<coordinate_type>(
|
||||
geometry::get<Dimension>(m_state.average_sum) / m_state.length
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2021-2023, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CLOSEST_POINTS_PT_SEG_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CLOSEST_POINTS_PT_SEG_HPP
|
||||
|
||||
#include <boost/geometry/algorithms/convert.hpp>
|
||||
|
||||
#include <boost/geometry/core/coordinate_promotion.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/point.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/strategies/closest_points/services.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace closest_points
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct compute_closest_point_to_segment
|
||||
{
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline auto
|
||||
apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2)
|
||||
{
|
||||
// A projected point of points in Integer coordinates must be able to be
|
||||
// represented in FP.
|
||||
using fp_point_type = model::point
|
||||
<
|
||||
CalculationType,
|
||||
dimension<PointOfSegment>::value,
|
||||
typename coordinate_system<PointOfSegment>::type
|
||||
>;
|
||||
|
||||
// For convenience
|
||||
using fp_vector_type = fp_point_type;
|
||||
|
||||
/*
|
||||
Algorithm [p: (px,py), p1: (x1,y1), p2: (x2,y2)]
|
||||
VECTOR v(x2 - x1, y2 - y1)
|
||||
VECTOR w(px - x1, py - y1)
|
||||
c1 = w . v
|
||||
c2 = v . v
|
||||
b = c1 / c2
|
||||
RETURN POINT(x1 + b * vx, y1 + b * vy)
|
||||
*/
|
||||
|
||||
// v is multiplied below with a (possibly) FP-value, so should be in FP
|
||||
// For consistency we define w also in FP
|
||||
fp_vector_type v, w, projected;
|
||||
|
||||
geometry::convert(p2, v);
|
||||
geometry::convert(p, w);
|
||||
geometry::convert(p1, projected);
|
||||
subtract_point(v, projected);
|
||||
subtract_point(w, projected);
|
||||
|
||||
CalculationType const zero = CalculationType();
|
||||
CalculationType const c1 = dot_product(w, v);
|
||||
if (c1 <= zero)
|
||||
{
|
||||
fp_vector_type fp_p1;
|
||||
geometry::convert(p1, fp_p1);
|
||||
return fp_p1;
|
||||
}
|
||||
CalculationType const c2 = dot_product(v, v);
|
||||
if (c2 <= c1)
|
||||
{
|
||||
fp_vector_type fp_p2;
|
||||
geometry::convert(p2, fp_p2);
|
||||
return fp_p2;
|
||||
}
|
||||
|
||||
// See above, c1 > 0 AND c2 > c1 so: c2 != 0
|
||||
CalculationType const b = c1 / c2;
|
||||
|
||||
multiply_value(v, b);
|
||||
add_point(projected, v);
|
||||
|
||||
return projected;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
template
|
||||
<
|
||||
typename CalculationType = void
|
||||
>
|
||||
class projected_point
|
||||
{
|
||||
public:
|
||||
// The three typedefs below are necessary to calculate distances
|
||||
// from segments defined in integer coordinates.
|
||||
|
||||
// Integer coordinates can still result in FP distances.
|
||||
// There is a division, which must be represented in FP.
|
||||
// So promote.
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
struct calculation_type
|
||||
: promote_floating_point
|
||||
<
|
||||
typename select_most_precise
|
||||
<
|
||||
typename coordinate_type<Point>::type,
|
||||
typename coordinate_type<PointOfSegment>::type,
|
||||
CalculationType
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
inline auto
|
||||
apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
|
||||
{
|
||||
assert_dimension_equal<Point, PointOfSegment>();
|
||||
|
||||
using calculation_type = typename calculation_type<Point, PointOfSegment>::type;
|
||||
|
||||
return detail::compute_closest_point_to_segment<calculation_type>::apply(p, p1, p2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}} // namespace strategy::closest_points
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CLOSEST_POINTS_PT_SEG_HPP
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// 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
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/geometries/point.hpp>
|
||||
#include <boost/geometry/strategies/densify.hpp>
|
||||
#include <boost/geometry/util/algorithm.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_most_precise.hpp>
|
||||
|
||||
@@ -52,60 +53,53 @@ public:
|
||||
static inline void apply(Point const& p0, Point const& p1, AssignPolicy & policy, T const& length_threshold)
|
||||
{
|
||||
typedef typename AssignPolicy::point_type out_point_t;
|
||||
typedef typename coordinate_type<out_point_t>::type out_coord_t;
|
||||
typedef typename select_most_precise
|
||||
<
|
||||
typename coordinate_type<Point>::type,
|
||||
typename coordinate_type<out_point_t>::type,
|
||||
typename coordinate_type<Point>::type, out_coord_t,
|
||||
CalculationType
|
||||
>::type calc_t;
|
||||
|
||||
typedef model::point<calc_t, geometry::dimension<Point>::value, cs::cartesian> calc_point_t;
|
||||
|
||||
calc_point_t cp0, cp1;
|
||||
geometry::detail::conversion::convert_point_to_point(p0, cp0);
|
||||
geometry::detail::conversion::convert_point_to_point(p1, cp1);
|
||||
|
||||
// dir01 = xy1 - xy0
|
||||
calc_point_t dir01 = cp1;
|
||||
geometry::subtract_point(dir01, cp0);
|
||||
assert_dimension_equal<calc_point_t, out_point_t>();
|
||||
|
||||
calc_point_t cp0, dir01;
|
||||
// dir01 = p1 - p0
|
||||
geometry::detail::for_each_dimension<calc_point_t>([&](auto index)
|
||||
{
|
||||
calc_t const coord0 = boost::numeric_cast<calc_t>(get<index>(p0));
|
||||
calc_t const coord1 = boost::numeric_cast<calc_t>(get<index>(p1));
|
||||
set<index>(cp0, coord0);
|
||||
set<index>(dir01, coord1 - coord0);
|
||||
});
|
||||
|
||||
calc_t const dot01 = geometry::dot_product(dir01, dir01);
|
||||
calc_t const len = math::sqrt(dot01);
|
||||
|
||||
BOOST_GEOMETRY_ASSERT(length_threshold > T(0));
|
||||
|
||||
signed_size_type n = signed_size_type(len / length_threshold);
|
||||
signed_size_type const n = signed_size_type(len / length_threshold);
|
||||
if (n <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: Normalization will not work for integral coordinates
|
||||
// normalize
|
||||
//geometry::divide_value(dir01, len);
|
||||
|
||||
calc_t step = len / (n + 1);
|
||||
|
||||
calc_t d = step;
|
||||
for (signed_size_type i = 0 ; i < n ; ++i, d += step)
|
||||
calc_t const den = calc_t(n + 1);
|
||||
for (signed_size_type i = 0 ; i < n ; ++i)
|
||||
{
|
||||
// pd = xy0 + d * dir01
|
||||
calc_point_t pd = dir01;
|
||||
out_point_t out;
|
||||
|
||||
// without normalization
|
||||
geometry::multiply_value(pd, calc_t(i + 1));
|
||||
geometry::divide_value(pd, calc_t(n + 1));
|
||||
// with normalization
|
||||
//geometry::multiply_value(pd, d);
|
||||
|
||||
geometry::add_point(pd, cp0);
|
||||
calc_t const num = calc_t(i + 1);
|
||||
geometry::detail::for_each_dimension<out_point_t>([&](auto index)
|
||||
{
|
||||
// out = p0 + d * dir01
|
||||
calc_t const coord = get<index>(cp0) + get<index>(dir01) * num / den;
|
||||
|
||||
// NOTE: Only needed if types calc_point_t and out_point_t are different
|
||||
// otherwise pd could simply be passed into policy
|
||||
out_point_t p;
|
||||
assert_dimension_equal<calc_point_t, out_point_t>();
|
||||
geometry::detail::conversion::convert_point_to_point(pd, p);
|
||||
|
||||
policy.apply(p);
|
||||
set<index>(out, boost::numeric_cast<out_coord_t>(coord));
|
||||
});
|
||||
|
||||
policy.apply(out);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013-2017.
|
||||
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2019.
|
||||
// Modifications copyright (c) 2013-2019, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
|
||||
#include <boost/geometry/strategies/disjoint.hpp>
|
||||
|
||||
|
||||
@@ -161,7 +162,7 @@ struct disjoint_segment_box_impl
|
||||
<
|
||||
RelativeDistance,
|
||||
SegmentPoint,
|
||||
Box,
|
||||
Box,
|
||||
I + 1,
|
||||
Dimension
|
||||
>::apply(p0, p1, box, t_min, t_max);
|
||||
@@ -246,22 +247,11 @@ struct disjoint_segment_box_impl
|
||||
// other strategies that are used are intersection and covered_by strategies.
|
||||
struct segment_box
|
||||
{
|
||||
template <typename Segment, typename Box>
|
||||
struct point_in_geometry_strategy
|
||||
: services::default_strategy
|
||||
<
|
||||
typename point_type<Segment>::type,
|
||||
Box
|
||||
>
|
||||
{};
|
||||
typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type;
|
||||
|
||||
template <typename Segment, typename Box>
|
||||
static inline typename point_in_geometry_strategy<Segment, Box>::type
|
||||
get_point_in_geometry_strategy()
|
||||
static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy()
|
||||
{
|
||||
typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
|
||||
|
||||
return strategy_type();
|
||||
return disjoint_point_box_strategy_type();
|
||||
}
|
||||
|
||||
template <typename Segment, typename Box>
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2018.
|
||||
// Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2014-2021.
|
||||
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_void.hpp>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/point_type.hpp>
|
||||
@@ -36,10 +36,10 @@
|
||||
#include <boost/geometry/strategies/tags.hpp>
|
||||
#include <boost/geometry/strategies/distance.hpp>
|
||||
#include <boost/geometry/strategies/default_distance_result.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/closest_points_pt_seg.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/intersection.hpp>
|
||||
|
||||
// Helper geometry (projected point on line)
|
||||
#include <boost/geometry/geometries/point.hpp>
|
||||
@@ -77,9 +77,7 @@ template
|
||||
>
|
||||
class projected_point
|
||||
{
|
||||
public :
|
||||
typedef within::cartesian_point_point equals_point_point_strategy_type;
|
||||
|
||||
public:
|
||||
// The three typedefs below are necessary to calculate distances
|
||||
// from segments defined in integer coordinates.
|
||||
|
||||
@@ -107,60 +105,10 @@ public :
|
||||
|
||||
typedef typename calculation_type<Point, PointOfSegment>::type calculation_type;
|
||||
|
||||
// A projected point of points in Integer coordinates must be able to be
|
||||
// represented in FP.
|
||||
typedef model::point
|
||||
<
|
||||
calculation_type,
|
||||
dimension<PointOfSegment>::value,
|
||||
typename coordinate_system<PointOfSegment>::type
|
||||
> fp_point_type;
|
||||
auto closest_point = closest_points::detail::compute_closest_point_to_segment
|
||||
<calculation_type>::apply(p, p1, p2);
|
||||
|
||||
// For convenience
|
||||
typedef fp_point_type fp_vector_type;
|
||||
|
||||
/*
|
||||
Algorithm [p: (px,py), p1: (x1,y1), p2: (x2,y2)]
|
||||
VECTOR v(x2 - x1, y2 - y1)
|
||||
VECTOR w(px - x1, py - y1)
|
||||
c1 = w . v
|
||||
c2 = v . v
|
||||
b = c1 / c2
|
||||
RETURN POINT(x1 + b * vx, y1 + b * vy)
|
||||
*/
|
||||
|
||||
// v is multiplied below with a (possibly) FP-value, so should be in FP
|
||||
// For consistency we define w also in FP
|
||||
fp_vector_type v, w, projected;
|
||||
|
||||
geometry::convert(p2, v);
|
||||
geometry::convert(p, w);
|
||||
geometry::convert(p1, projected);
|
||||
subtract_point(v, projected);
|
||||
subtract_point(w, projected);
|
||||
|
||||
Strategy strategy;
|
||||
boost::ignore_unused(strategy);
|
||||
|
||||
calculation_type const zero = calculation_type();
|
||||
calculation_type const c1 = dot_product(w, v);
|
||||
if (c1 <= zero)
|
||||
{
|
||||
return strategy.apply(p, p1);
|
||||
}
|
||||
calculation_type const c2 = dot_product(v, v);
|
||||
if (c2 <= c1)
|
||||
{
|
||||
return strategy.apply(p, p2);
|
||||
}
|
||||
|
||||
// See above, c1 > 0 AND c2 > c1 so: c2 != 0
|
||||
calculation_type const b = c1 / c2;
|
||||
|
||||
multiply_value(v, b);
|
||||
add_point(projected, v);
|
||||
|
||||
return strategy.apply(p, projected);
|
||||
return Strategy().apply(p, closest_point);
|
||||
}
|
||||
|
||||
template <typename CT>
|
||||
@@ -245,19 +193,19 @@ struct default_strategy
|
||||
>
|
||||
{
|
||||
typedef strategy::distance::projected_point
|
||||
<
|
||||
void,
|
||||
typename boost::mpl::if_
|
||||
<
|
||||
boost::is_void<Strategy>,
|
||||
typename default_strategy
|
||||
<
|
||||
point_tag, point_tag, Point, PointOfSegment,
|
||||
cartesian_tag, cartesian_tag
|
||||
>::type,
|
||||
Strategy
|
||||
>::type
|
||||
> type;
|
||||
<
|
||||
void,
|
||||
std::conditional_t
|
||||
<
|
||||
std::is_void<Strategy>::value,
|
||||
typename default_strategy
|
||||
<
|
||||
point_tag, point_tag, Point, PointOfSegment,
|
||||
cartesian_tag, cartesian_tag
|
||||
>::type,
|
||||
Strategy
|
||||
>
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename PointOfSegment, typename Point, typename Strategy>
|
||||
|
||||
@@ -128,7 +128,7 @@ public :
|
||||
assert_dimension_equal<Box1, Box2>();
|
||||
|
||||
typename calculation_type<Box1, Box2>::type result(0);
|
||||
|
||||
|
||||
detail::compute_pythagoras_box_box
|
||||
<
|
||||
dimension<Box1>::value
|
||||
|
||||
@@ -123,7 +123,7 @@ public :
|
||||
assert_dimension_equal<Point, Box>();
|
||||
|
||||
typename calculation_type<Point, Box>::type result(0);
|
||||
|
||||
|
||||
detail::compute_pythagoras_point_box
|
||||
<
|
||||
dimension<Point>::value
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2018-2019 Oracle and/or its affiliates.
|
||||
// Copyright (c) 2018-2021 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
@@ -43,55 +45,33 @@ struct cartesian_segment_box
|
||||
>
|
||||
{};
|
||||
|
||||
// point-point strategy getters
|
||||
struct distance_pp_strategy
|
||||
{
|
||||
typedef Strategy type;
|
||||
};
|
||||
typedef cartesian_tag cs_tag;
|
||||
|
||||
inline typename distance_pp_strategy::type get_distance_pp_strategy() const
|
||||
{
|
||||
return typename distance_pp_strategy::type();
|
||||
}
|
||||
// point-segment strategy getters
|
||||
struct distance_ps_strategy
|
||||
{
|
||||
typedef projected_point<CalculationType, Strategy> type;
|
||||
};
|
||||
|
||||
inline typename distance_ps_strategy::type get_distance_ps_strategy() const
|
||||
{
|
||||
return typename distance_ps_strategy::type();
|
||||
}
|
||||
|
||||
typedef within::cartesian_point_point equals_point_point_strategy_type;
|
||||
|
||||
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
|
||||
{
|
||||
return equals_point_point_strategy_type();
|
||||
}
|
||||
|
||||
template <typename LessEqual, typename ReturnType,
|
||||
typename SegmentPoint, typename BoxPoint>
|
||||
template
|
||||
<
|
||||
typename LessEqual, typename ReturnType,
|
||||
typename SegmentPoint, typename BoxPoint,
|
||||
typename Strategies
|
||||
>
|
||||
inline ReturnType segment_below_of_box(SegmentPoint const& p0,
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const&,
|
||||
BoxPoint const&,
|
||||
BoxPoint const&,
|
||||
BoxPoint const& bottom_right) const
|
||||
SegmentPoint const& p1,
|
||||
BoxPoint const&,
|
||||
BoxPoint const&,
|
||||
BoxPoint const&,
|
||||
BoxPoint const& bottom_right,
|
||||
Strategies const& strategies) const
|
||||
{
|
||||
|
||||
|
||||
// TODO: The strategy should not call the algorithm like that
|
||||
return geometry::detail::distance::segment_to_box_2D
|
||||
<
|
||||
ReturnType,
|
||||
SegmentPoint,
|
||||
BoxPoint,
|
||||
cartesian_segment_box<CalculationType, Strategy>
|
||||
Strategies
|
||||
>::template call_above_of_box
|
||||
<
|
||||
typename LessEqual::other
|
||||
>(p1, p0, bottom_right, *this);
|
||||
>(p1, p0, bottom_right, strategies);
|
||||
}
|
||||
|
||||
template <typename SPoint, typename BPoint>
|
||||
|
||||
@@ -1,153 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// 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)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/envelope_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/envelope_segment.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/expand_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/expand_segment.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace envelope
|
||||
{
|
||||
|
||||
template <typename CalculationType = void>
|
||||
class cartesian
|
||||
{
|
||||
public:
|
||||
typedef cartesian_point element_envelope_strategy_type;
|
||||
static inline element_envelope_strategy_type get_element_envelope_strategy()
|
||||
{
|
||||
return element_envelope_strategy_type();
|
||||
}
|
||||
|
||||
typedef expand::cartesian_point element_expand_strategy_type;
|
||||
static inline element_expand_strategy_type get_element_expand_strategy()
|
||||
{
|
||||
return element_expand_strategy_type();
|
||||
}
|
||||
|
||||
typedef expand::cartesian_box box_expand_strategy_type;
|
||||
static inline box_expand_strategy_type get_box_expand_strategy()
|
||||
{
|
||||
return box_expand_strategy_type();
|
||||
}
|
||||
|
||||
// Linestring, Ring, Polygon
|
||||
|
||||
template <typename Range>
|
||||
static inline typename boost::range_iterator<Range const>::type begin(Range const& range)
|
||||
{
|
||||
return boost::begin(range);
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
static inline typename boost::range_iterator<Range const>::type end(Range const& range)
|
||||
{
|
||||
return boost::end(range);
|
||||
}
|
||||
|
||||
// MultiLinestring, MultiPolygon
|
||||
|
||||
template <typename Box>
|
||||
struct multi_state
|
||||
{
|
||||
multi_state()
|
||||
: m_initialized(false)
|
||||
{}
|
||||
|
||||
void apply(Box const& single_box)
|
||||
{
|
||||
if (! m_initialized)
|
||||
{
|
||||
m_box = single_box;
|
||||
m_initialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
box_expand_strategy_type::apply(m_box, single_box);
|
||||
}
|
||||
}
|
||||
|
||||
void result(Box & box)
|
||||
{
|
||||
if (m_initialized)
|
||||
{
|
||||
box = m_box;
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(box);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_initialized;
|
||||
Box m_box;
|
||||
};
|
||||
|
||||
// Segment
|
||||
|
||||
template <typename Point1, typename Point2, typename Box>
|
||||
static inline void apply(Point1 const& point1, Point2 const& point2,
|
||||
Box& box)
|
||||
{
|
||||
cartesian_segment<CalculationType>::apply(point1, point2, box);
|
||||
}
|
||||
|
||||
// Box
|
||||
|
||||
template <typename BoxIn, typename Box>
|
||||
static inline void apply(BoxIn const& box_in, Box& box)
|
||||
{
|
||||
cartesian_box::apply(box_in, box);
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename Tag, typename CalculationType>
|
||||
struct default_strategy<Tag, cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef strategy::envelope::cartesian<CalculationType> type;
|
||||
};
|
||||
|
||||
} // namespace services
|
||||
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
}} // namespace strategy::envelope
|
||||
#include <boost/geometry/strategy/cartesian/envelope.hpp>
|
||||
|
||||
}} //namepsace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP
|
||||
|
||||
@@ -1,119 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015-2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_BOX_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_BOX_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
#include <boost/geometry/algorithms/detail/normalize.hpp>
|
||||
#include <boost/geometry/algorithms/detail/envelope/transform_units.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/envelope.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
std::size_t Index,
|
||||
std::size_t Dimension,
|
||||
std::size_t DimensionCount
|
||||
>
|
||||
struct envelope_indexed_box
|
||||
{
|
||||
template <typename BoxIn, typename BoxOut>
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
|
||||
{
|
||||
detail::indexed_point_view<BoxIn const, Index> box_in_corner(box_in);
|
||||
detail::indexed_point_view<BoxOut, Index> mbr_corner(mbr);
|
||||
|
||||
detail::conversion::point_to_point
|
||||
<
|
||||
detail::indexed_point_view<BoxIn const, Index>,
|
||||
detail::indexed_point_view<BoxOut, Index>,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(box_in_corner, mbr_corner);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
namespace strategy { namespace envelope
|
||||
{
|
||||
|
||||
|
||||
struct cartesian_box
|
||||
{
|
||||
template<typename BoxIn, typename BoxOut>
|
||||
static inline void apply(BoxIn const& box_in, BoxOut& mbr)
|
||||
{
|
||||
geometry::detail::envelope::envelope_indexed_box
|
||||
<
|
||||
min_corner, 0, dimension<BoxIn>::value
|
||||
>::apply(box_in, mbr);
|
||||
|
||||
geometry::detail::envelope::envelope_indexed_box
|
||||
<
|
||||
max_corner, 0, dimension<BoxIn>::value
|
||||
>::apply(box_in, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<box_tag, cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef strategy::envelope::cartesian_box type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
|
||||
}} // namespace strategy::envelope
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
#include <boost/geometry/strategy/cartesian/envelope_box.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_BOX_HPP
|
||||
|
||||
@@ -1,59 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2018, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2020, 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)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_MULTIPOINT_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_MULTIPOINT_HPP
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/envelope/range.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/envelope.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
#include <boost/geometry/strategy/cartesian/envelope_multipoint.hpp>
|
||||
|
||||
namespace strategy { namespace envelope
|
||||
{
|
||||
|
||||
class cartesian_multipoint
|
||||
{
|
||||
public:
|
||||
template <typename MultiPoint, typename Box>
|
||||
static inline void apply(MultiPoint const& multipoint, Box& mbr)
|
||||
{
|
||||
geometry::detail::envelope::envelope_range::apply(multipoint, mbr, cartesian<>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<multi_point_tag, cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef strategy::envelope::cartesian_multipoint type;
|
||||
};
|
||||
|
||||
|
||||
} // namespace services
|
||||
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
|
||||
}} // namespace strategy::envelope
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_MULTIPOINT_HPP
|
||||
|
||||
@@ -1,111 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_POINT_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_POINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/cs.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/views/detail/indexed_point_view.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/envelope.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace envelope
|
||||
{
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct envelope_one_point
|
||||
{
|
||||
template <std::size_t Index, typename Point, typename Box>
|
||||
static inline void apply(Point const& point, Box& mbr)
|
||||
{
|
||||
detail::indexed_point_view<Box, Index> box_corner(mbr);
|
||||
detail::conversion::point_to_point
|
||||
<
|
||||
Point,
|
||||
detail::indexed_point_view<Box, Index>,
|
||||
Dimension,
|
||||
DimensionCount
|
||||
>::apply(point, box_corner);
|
||||
}
|
||||
|
||||
template <typename Point, typename Box>
|
||||
static inline void apply(Point const& point, Box& mbr)
|
||||
{
|
||||
apply<min_corner>(point, mbr);
|
||||
apply<max_corner>(point, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespace detail::envelope
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
namespace strategy { namespace envelope
|
||||
{
|
||||
|
||||
struct cartesian_point
|
||||
{
|
||||
template <typename Point, typename Box>
|
||||
static inline void apply(Point const& point, Box& mbr)
|
||||
{
|
||||
geometry::detail::envelope::envelope_one_point
|
||||
<
|
||||
0, dimension<Point>::value
|
||||
>::apply(point, mbr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<point_tag, cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef strategy::envelope::cartesian_point type;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
|
||||
}} // namespace strategy::envelope
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_POINT_HPP
|
||||
|
||||
@@ -1,93 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
|
||||
// Copyright (c) 2017-2018 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/envelope_point.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/expand_point.hpp>
|
||||
#include <boost/geometry/strategies/envelope.hpp>
|
||||
|
||||
namespace boost { namespace geometry { namespace strategy { namespace envelope
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct envelope_one_segment
|
||||
{
|
||||
template<typename Point, typename Box>
|
||||
static inline void apply(Point const& p1,
|
||||
Point const& p2,
|
||||
Box& mbr)
|
||||
{
|
||||
geometry::detail::envelope::envelope_one_point
|
||||
<
|
||||
Dimension, DimensionCount
|
||||
>::apply(p1, mbr);
|
||||
|
||||
strategy::expand::detail::point_loop
|
||||
<
|
||||
Dimension, DimensionCount
|
||||
>::apply(mbr, p2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename CalculationType = void
|
||||
>
|
||||
class cartesian_segment
|
||||
{
|
||||
public:
|
||||
template <typename Point, typename Box>
|
||||
static inline void apply(Point const& point1, Point const& point2, Box& box)
|
||||
{
|
||||
strategy::envelope::detail::envelope_one_segment
|
||||
<
|
||||
0,
|
||||
dimension<Point>::value
|
||||
>::apply(point1, point2, box);
|
||||
}
|
||||
#include <boost/geometry/strategy/cartesian/envelope_segment.hpp>
|
||||
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<segment_tag, cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef strategy::envelope::cartesian_segment<CalculationType> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
|
||||
}} // namespace strategy::envelope
|
||||
|
||||
}} //namepsace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_SEGMENT_HPP
|
||||
|
||||
@@ -1,69 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016, 2017.
|
||||
// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_BOX_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_BOX_HPP
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/expand.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
|
||||
|
||||
namespace strategy { namespace expand
|
||||
{
|
||||
|
||||
struct cartesian_box
|
||||
{
|
||||
template <typename BoxOut, typename BoxIn>
|
||||
static void apply(BoxOut & box_out, BoxIn const& box_in)
|
||||
{
|
||||
geometry::detail::expand::expand_indexed
|
||||
<
|
||||
0, dimension<BoxIn>::value
|
||||
>::apply(box_out, box_in);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<box_tag, cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef cartesian_box type;
|
||||
};
|
||||
|
||||
|
||||
} // namespace services
|
||||
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
|
||||
}} // namespace strategy::expand
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_BOX_HPP
|
||||
|
||||
@@ -1,125 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015-2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// 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)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_POINT_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_POINT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||
#include <boost/geometry/core/coordinate_system.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/expand.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace expand
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <std::size_t Dimension, std::size_t DimensionCount>
|
||||
struct point_loop
|
||||
{
|
||||
template <typename Box, typename Point>
|
||||
static inline void apply(Box& box, Point const& source)
|
||||
{
|
||||
typedef typename select_coordinate_type
|
||||
<
|
||||
Point, Box
|
||||
>::type coordinate_type;
|
||||
|
||||
std::less<coordinate_type> less;
|
||||
std::greater<coordinate_type> greater;
|
||||
|
||||
coordinate_type const coord = get<Dimension>(source);
|
||||
|
||||
if (less(coord, get<min_corner, Dimension>(box)))
|
||||
{
|
||||
set<min_corner, Dimension>(box, coord);
|
||||
}
|
||||
|
||||
if (greater(coord, get<max_corner, Dimension>(box)))
|
||||
{
|
||||
set<max_corner, Dimension>(box, coord);
|
||||
}
|
||||
|
||||
point_loop<Dimension + 1, DimensionCount>::apply(box, source);
|
||||
}
|
||||
};
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
template <std::size_t DimensionCount>
|
||||
struct point_loop<DimensionCount, DimensionCount>
|
||||
{
|
||||
template <typename Box, typename Point>
|
||||
static inline void apply(Box&, Point const&) {}
|
||||
};
|
||||
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
|
||||
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
|
||||
struct cartesian_point
|
||||
{
|
||||
template <typename Box, typename Point>
|
||||
static void apply(Box & box, Point const& point)
|
||||
{
|
||||
expand::detail::point_loop
|
||||
<
|
||||
0, dimension<Point>::value
|
||||
>::apply(box, point);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<point_tag, cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef cartesian_point type;
|
||||
};
|
||||
|
||||
|
||||
} // namespace services
|
||||
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
|
||||
}} // namespace strategy::expand
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_POINT_HPP
|
||||
|
||||
@@ -1,71 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_SEGMENT_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_SEGMENT_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/expand/indexed.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/expand.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
#include <boost/geometry/strategy/cartesian/expand_segment.hpp>
|
||||
|
||||
namespace strategy { namespace expand
|
||||
{
|
||||
|
||||
class cartesian_segment
|
||||
{
|
||||
public:
|
||||
template <typename Box, typename Segment>
|
||||
static void apply(Box & box, Segment const& segment)
|
||||
{
|
||||
geometry::detail::expand::expand_indexed
|
||||
<
|
||||
0, dimension<Segment>::value
|
||||
>::apply(box, segment);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<segment_tag, cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef cartesian_segment type;
|
||||
};
|
||||
|
||||
|
||||
} // namespace services
|
||||
|
||||
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
|
||||
}} // namespace strategy::expand
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_EXPAND_SEGMENT_HPP
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
|
||||
// Copyright (c) 2013-2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2014, 2016, 2017, 2018, 2019.
|
||||
// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2014-2021.
|
||||
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <boost/geometry/geometries/concepts/point_concept.hpp>
|
||||
#include <boost/geometry/geometries/concepts/segment_concept.hpp>
|
||||
#include <boost/geometry/geometries/segment.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_values.hpp>
|
||||
@@ -33,16 +34,16 @@
|
||||
#include <boost/geometry/util/promote_integral.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/area.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/area.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/envelope.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
|
||||
#include <boost/geometry/strategy/cartesian/expand_segment.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/envelope.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/expand_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/expand_segment.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategies/covered_by.hpp>
|
||||
#include <boost/geometry/strategies/intersection.hpp>
|
||||
#include <boost/geometry/strategies/intersection_result.hpp>
|
||||
@@ -50,8 +51,8 @@
|
||||
#include <boost/geometry/strategies/side_info.hpp>
|
||||
#include <boost/geometry/strategies/within.hpp>
|
||||
|
||||
#include <boost/geometry/policies/robustness/rescale_policy_tags.hpp>
|
||||
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
|
||||
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
|
||||
|
||||
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
|
||||
@@ -66,6 +67,61 @@ namespace boost { namespace geometry
|
||||
namespace strategy { namespace intersection
|
||||
{
|
||||
|
||||
namespace detail_usage
|
||||
{
|
||||
|
||||
// When calculating the intersection, the information of "a" or "b" can be used.
|
||||
// Theoretically this gives equal results, but due to floating point precision
|
||||
// there might be tiny differences. These are edge cases.
|
||||
// This structure is to determine if "a" or "b" should be used.
|
||||
// Prefer the segment closer to the endpoint.
|
||||
// If both are about equally close, then prefer the longer segment
|
||||
// To avoid hard thresholds, behavior is made fluent.
|
||||
// Calculate comparable length indications,
|
||||
// the longer the segment (relatively), the lower the value
|
||||
// such that the shorter lengths are evaluated higher and will
|
||||
// be preferred.
|
||||
template <bool IsArithmetic>
|
||||
struct use_a
|
||||
{
|
||||
template <typename Ct, typename Ev>
|
||||
static bool apply(Ct const& cla, Ct const& clb, Ev const& eva, Ev const& evb)
|
||||
{
|
||||
auto const clm = (std::max)(cla, clb);
|
||||
if (clm <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Relative comparible length
|
||||
auto const rcla = Ct(1.0) - cla / clm;
|
||||
auto const rclb = Ct(1.0) - clb / clm;
|
||||
|
||||
// Multipliers for edgevalue (ev) and relative comparible length (rcl)
|
||||
// They determine the balance between edge value (should be larger)
|
||||
// and segment length. In 99.9xx% of the cases there is no difference
|
||||
// at all (if either a or b is used). Therefore the values of the
|
||||
// constants are not sensitive for the majority of the situations.
|
||||
// One known case is #mysql_23023665_6 (difference) which needs mev >= 2
|
||||
Ev const mev = 5;
|
||||
Ev const mrcl = 1;
|
||||
|
||||
return mev * eva + mrcl * rcla > mev * evb + mrcl * rclb;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization for non arithmetic types. They will always use "a"
|
||||
template <>
|
||||
struct use_a<false>
|
||||
{
|
||||
template <typename Ct, typename Ev>
|
||||
static bool apply(Ct const& , Ct const& , Ev const& , Ev const& )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
\see http://mathworld.wolfram.com/Line-LineIntersection.html
|
||||
@@ -76,111 +132,7 @@ template
|
||||
>
|
||||
struct cartesian_segments
|
||||
{
|
||||
typedef side::side_by_triangle<CalculationType> side_strategy_type;
|
||||
|
||||
static inline side_strategy_type get_side_strategy()
|
||||
{
|
||||
return side_strategy_type();
|
||||
}
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
struct point_in_geometry_strategy
|
||||
{
|
||||
typedef strategy::within::cartesian_winding
|
||||
<
|
||||
typename point_type<Geometry1>::type,
|
||||
typename point_type<Geometry2>::type,
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Geometry1, typename Geometry2>
|
||||
static inline typename point_in_geometry_strategy<Geometry1, Geometry2>::type
|
||||
get_point_in_geometry_strategy()
|
||||
{
|
||||
typedef typename point_in_geometry_strategy
|
||||
<
|
||||
Geometry1, Geometry2
|
||||
>::type strategy_type;
|
||||
return strategy_type();
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
struct area_strategy
|
||||
{
|
||||
typedef area::cartesian
|
||||
<
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
static inline typename area_strategy<Geometry>::type get_area_strategy()
|
||||
{
|
||||
typedef typename area_strategy<Geometry>::type strategy_type;
|
||||
return strategy_type();
|
||||
}
|
||||
|
||||
template <typename Geometry>
|
||||
struct distance_strategy
|
||||
{
|
||||
typedef distance::pythagoras
|
||||
<
|
||||
CalculationType
|
||||
> type;
|
||||
};
|
||||
|
||||
template <typename Geometry>
|
||||
static inline typename distance_strategy<Geometry>::type get_distance_strategy()
|
||||
{
|
||||
typedef typename distance_strategy<Geometry>::type strategy_type;
|
||||
return strategy_type();
|
||||
}
|
||||
|
||||
typedef envelope::cartesian<CalculationType> envelope_strategy_type;
|
||||
|
||||
static inline envelope_strategy_type get_envelope_strategy()
|
||||
{
|
||||
return envelope_strategy_type();
|
||||
}
|
||||
|
||||
typedef expand::cartesian_segment expand_strategy_type;
|
||||
|
||||
static inline expand_strategy_type get_expand_strategy()
|
||||
{
|
||||
return expand_strategy_type();
|
||||
}
|
||||
|
||||
typedef within::cartesian_point_point point_in_point_strategy_type;
|
||||
|
||||
static inline point_in_point_strategy_type get_point_in_point_strategy()
|
||||
{
|
||||
return point_in_point_strategy_type();
|
||||
}
|
||||
|
||||
typedef within::cartesian_point_point equals_point_point_strategy_type;
|
||||
|
||||
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
|
||||
{
|
||||
return equals_point_point_strategy_type();
|
||||
}
|
||||
|
||||
typedef disjoint::cartesian_box_box disjoint_box_box_strategy_type;
|
||||
|
||||
static inline disjoint_box_box_strategy_type get_disjoint_box_box_strategy()
|
||||
{
|
||||
return disjoint_box_box_strategy_type();
|
||||
}
|
||||
|
||||
typedef disjoint::segment_box disjoint_segment_box_strategy_type;
|
||||
|
||||
static inline disjoint_segment_box_strategy_type get_disjoint_segment_box_strategy()
|
||||
{
|
||||
return disjoint_segment_box_strategy_type();
|
||||
}
|
||||
|
||||
typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type;
|
||||
typedef expand::cartesian_box expand_box_strategy_type;
|
||||
typedef cartesian_tag cs_tag;
|
||||
|
||||
template <typename CoordinateType, typename SegmentRatio>
|
||||
struct segment_intersection_info
|
||||
@@ -213,61 +165,80 @@ struct cartesian_segments
|
||||
}
|
||||
|
||||
template <typename Point, typename Segment>
|
||||
void assign(Point& point, Segment const& segment, CoordinateType const& dx, CoordinateType const& dy, SegmentRatio const& ratio) const
|
||||
void assign(Point& point, Segment const& segment,
|
||||
CoordinateType const& dx, CoordinateType const& dy,
|
||||
SegmentRatio const& ratio) const
|
||||
{
|
||||
// Calculate the intersection point based on segment_ratio
|
||||
// Up to now, division was postponed. Here we divide using numerator/
|
||||
// denominator. In case of integer this results in an integer
|
||||
// division.
|
||||
BOOST_GEOMETRY_ASSERT(ratio.denominator() != 0);
|
||||
// The division, postponed until here, is done now. In case of integer this
|
||||
// results in an integer which rounds to the nearest integer.
|
||||
BOOST_GEOMETRY_ASSERT(ratio.denominator() != typename SegmentRatio::int_type(0));
|
||||
|
||||
typedef typename promote_integral<CoordinateType>::type promoted_type;
|
||||
typedef typename promote_integral<CoordinateType>::type calc_type;
|
||||
|
||||
promoted_type const numerator
|
||||
= boost::numeric_cast<promoted_type>(ratio.numerator());
|
||||
promoted_type const denominator
|
||||
= boost::numeric_cast<promoted_type>(ratio.denominator());
|
||||
promoted_type const dx_promoted = boost::numeric_cast<promoted_type>(dx);
|
||||
promoted_type const dy_promoted = boost::numeric_cast<promoted_type>(dy);
|
||||
calc_type const numerator
|
||||
= boost::numeric_cast<calc_type>(ratio.numerator());
|
||||
calc_type const denominator
|
||||
= boost::numeric_cast<calc_type>(ratio.denominator());
|
||||
calc_type const dx_calc = boost::numeric_cast<calc_type>(dx);
|
||||
calc_type const dy_calc = boost::numeric_cast<calc_type>(dy);
|
||||
|
||||
set<0>(point, get<0, 0>(segment) + boost::numeric_cast
|
||||
<
|
||||
CoordinateType
|
||||
>(numerator * dx_promoted / denominator));
|
||||
set<1>(point, get<0, 1>(segment) + boost::numeric_cast
|
||||
<
|
||||
CoordinateType
|
||||
>(numerator * dy_promoted / denominator));
|
||||
set<0>(point, get<0, 0>(segment)
|
||||
+ boost::numeric_cast<CoordinateType>(
|
||||
math::divide<calc_type>(numerator * dx_calc, denominator)));
|
||||
set<1>(point, get<0, 1>(segment)
|
||||
+ boost::numeric_cast<CoordinateType>(
|
||||
math::divide<calc_type>(numerator * dy_calc, denominator)));
|
||||
}
|
||||
|
||||
template <int Index, int Dim, typename Point, typename Segment>
|
||||
static bool exceeds_side_in_dimension(Point& p, Segment const& s)
|
||||
{
|
||||
// Situation a (positive)
|
||||
// 0>-------------->1 segment
|
||||
// * point left of segment<I> in D x or y
|
||||
// Situation b (negative)
|
||||
// 1<--------------<0 segment
|
||||
// * point right of segment<I>
|
||||
// Situation c (degenerate), return false (check other dimension)
|
||||
auto const& c = get<Dim>(p);
|
||||
auto const& c0 = get<Index, Dim>(s);
|
||||
auto const& c1 = get<1 - Index, Dim>(s);
|
||||
return c0 < c1 ? math::smaller(c, c0)
|
||||
: c0 > c1 ? math::larger(c, c0)
|
||||
: false;
|
||||
}
|
||||
|
||||
template <int Index, typename Point, typename Segment>
|
||||
static bool exceeds_side_of_segment(Point& p, Segment const& s)
|
||||
{
|
||||
return exceeds_side_in_dimension<Index, 0>(p, s)
|
||||
|| exceeds_side_in_dimension<Index, 1>(p, s);
|
||||
}
|
||||
|
||||
template <typename Point, typename Segment>
|
||||
static void assign_if_exceeds(Point& point, Segment const& s)
|
||||
{
|
||||
if (exceeds_side_of_segment<0>(point, s))
|
||||
{
|
||||
detail::assign_point_from_index<0>(s, point);
|
||||
}
|
||||
else if (exceeds_side_of_segment<1>(point, s))
|
||||
{
|
||||
detail::assign_point_from_index<1>(s, point);
|
||||
}
|
||||
}
|
||||
|
||||
public :
|
||||
template <typename Point, typename Segment1, typename Segment2>
|
||||
void calculate(Point& point, Segment1 const& a, Segment2 const& b) const
|
||||
{
|
||||
bool use_a = true;
|
||||
|
||||
// Prefer one segment if one is on or near an endpoint
|
||||
bool const a_near_end = robust_ra.near_end();
|
||||
bool const b_near_end = robust_rb.near_end();
|
||||
if (a_near_end && ! b_near_end)
|
||||
{
|
||||
use_a = true;
|
||||
}
|
||||
else if (b_near_end && ! a_near_end)
|
||||
{
|
||||
use_a = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prefer shorter segment
|
||||
promoted_type const len_a = comparable_length_a();
|
||||
promoted_type const len_b = comparable_length_b();
|
||||
if (len_b < len_a)
|
||||
{
|
||||
use_a = false;
|
||||
}
|
||||
// else use_a is true but was already assigned like that
|
||||
}
|
||||
bool const use_a
|
||||
= detail_usage::use_a
|
||||
<
|
||||
std::is_arithmetic<CoordinateType>::value
|
||||
>::apply(comparable_length_a(), comparable_length_b(),
|
||||
robust_ra.edge_value(), robust_rb.edge_value());
|
||||
|
||||
if (use_a)
|
||||
{
|
||||
@@ -277,6 +248,23 @@ struct cartesian_segments
|
||||
{
|
||||
assign_b(point, a, b);
|
||||
}
|
||||
|
||||
#ifndef BOOST_GEOMETRY_USE_RESCALING
|
||||
// Verify nearly collinear cases (the threshold is arbitrary
|
||||
// but influences performance). If the intersection is located
|
||||
// outside the segments, then it should be moved.
|
||||
if (robust_ra.possibly_collinear(1.0e-3)
|
||||
&& robust_rb.possibly_collinear(1.0e-3))
|
||||
{
|
||||
// The segments are nearly collinear and because of the calculation
|
||||
// method with very small denominator, the IP appears outside the
|
||||
// segment(s). Correct it to the end point.
|
||||
// Because they are nearly collinear, it doesn't really matter to
|
||||
// to which endpoint (or it is corrected twice).
|
||||
assign_if_exceeds(point, a);
|
||||
assign_if_exceeds(point, b);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CoordinateType dx_a, dy_a;
|
||||
@@ -289,87 +277,170 @@ struct cartesian_segments
|
||||
static inline void cramers_rule(D const& dx_a, D const& dy_a,
|
||||
D const& dx_b, D const& dy_b, W const& wx, W const& wy,
|
||||
// out:
|
||||
ResultType& d, ResultType& da)
|
||||
ResultType& nominator, ResultType& denominator)
|
||||
{
|
||||
// Cramers rule
|
||||
d = geometry::detail::determinant<ResultType>(dx_a, dy_a, dx_b, dy_b);
|
||||
da = geometry::detail::determinant<ResultType>(dx_b, dy_b, wx, wy);
|
||||
// Ratio is da/d , collinear if d == 0, intersecting if 0 <= r <= 1
|
||||
nominator = geometry::detail::determinant<ResultType>(dx_b, dy_b, wx, wy);
|
||||
denominator = geometry::detail::determinant<ResultType>(dx_a, dy_a, dx_b, dy_b);
|
||||
// Ratio r = nominator/denominator
|
||||
// Collinear if denominator == 0, intersecting if 0 <= r <= 1
|
||||
// IntersectionPoint = (x1 + r * dx_a, y1 + r * dy_a)
|
||||
}
|
||||
|
||||
|
||||
// Relate segments a and b
|
||||
// Version for non-rescaled policies
|
||||
template
|
||||
<
|
||||
typename Segment1,
|
||||
typename Segment2,
|
||||
typename Policy,
|
||||
typename RobustPolicy
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename Policy
|
||||
>
|
||||
static inline typename Policy::return_type
|
||||
apply(Segment1 const& a, Segment2 const& b,
|
||||
Policy const& policy, RobustPolicy const& robust_policy)
|
||||
apply(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
Policy const& policy)
|
||||
{
|
||||
// type them all as in Segment1 - TODO reconsider this, most precise?
|
||||
typedef typename geometry::point_type<Segment1>::type point_type;
|
||||
|
||||
typedef typename geometry::robust_point_type
|
||||
<
|
||||
point_type, RobustPolicy
|
||||
>::type robust_point_type;
|
||||
|
||||
point_type a0, a1, b0, b1;
|
||||
robust_point_type a0_rob, a1_rob, b0_rob, b1_rob;
|
||||
|
||||
detail::assign_point_from_index<0>(a, a0);
|
||||
detail::assign_point_from_index<1>(a, a1);
|
||||
detail::assign_point_from_index<0>(b, b0);
|
||||
detail::assign_point_from_index<1>(b, b1);
|
||||
|
||||
geometry::recalculate(a0_rob, a0, robust_policy);
|
||||
geometry::recalculate(a1_rob, a1, robust_policy);
|
||||
geometry::recalculate(b0_rob, b0, robust_policy);
|
||||
geometry::recalculate(b1_rob, b1, robust_policy);
|
||||
|
||||
return apply(a, b, policy, robust_policy, a0_rob, a1_rob, b0_rob, b1_rob);
|
||||
// Pass the same ranges both as normal ranges and as modelled ranges
|
||||
return apply(range_p, range_q, policy, range_p, range_q);
|
||||
}
|
||||
|
||||
// The main entry-routine, calculating intersections of segments a / b
|
||||
// NOTE: Robust* types may be the same as Segments' point types
|
||||
// Version for non rescaled versions.
|
||||
// The "modelled" parameter might be rescaled (will be removed later)
|
||||
template
|
||||
<
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2,
|
||||
typename Policy,
|
||||
typename ModelledUniqueSubRange1,
|
||||
typename ModelledUniqueSubRange2
|
||||
>
|
||||
static inline typename Policy::return_type
|
||||
apply(UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q,
|
||||
Policy const& policy,
|
||||
ModelledUniqueSubRange1 const& modelled_range_p,
|
||||
ModelledUniqueSubRange2 const& modelled_range_q)
|
||||
{
|
||||
typedef typename UniqueSubRange1::point_type point1_type;
|
||||
typedef typename UniqueSubRange2::point_type point2_type;
|
||||
|
||||
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point1_type>) );
|
||||
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point2_type>) );
|
||||
|
||||
point1_type const& p1 = range_p.at(0);
|
||||
point1_type const& p2 = range_p.at(1);
|
||||
point2_type const& q1 = range_q.at(0);
|
||||
point2_type const& q2 = range_q.at(1);
|
||||
|
||||
// Declare segments, currently necessary for the policies
|
||||
// (segment_crosses, segment_colinear, degenerate, one_degenerate, etc)
|
||||
model::referring_segment<point1_type const> const p(p1, p2);
|
||||
model::referring_segment<point2_type const> const q(q1, q2);
|
||||
|
||||
typedef typename select_most_precise
|
||||
<
|
||||
typename geometry::coordinate_type<typename ModelledUniqueSubRange1::point_type>::type,
|
||||
typename geometry::coordinate_type<typename ModelledUniqueSubRange1::point_type>::type
|
||||
>::type modelled_coordinate_type;
|
||||
|
||||
typedef segment_ratio<modelled_coordinate_type> ratio_type;
|
||||
segment_intersection_info
|
||||
<
|
||||
typename select_calculation_type<point1_type, point2_type, CalculationType>::type,
|
||||
ratio_type
|
||||
> sinfo;
|
||||
|
||||
sinfo.dx_a = get<0>(p2) - get<0>(p1); // distance in x-dir
|
||||
sinfo.dx_b = get<0>(q2) - get<0>(q1);
|
||||
sinfo.dy_a = get<1>(p2) - get<1>(p1); // distance in y-dir
|
||||
sinfo.dy_b = get<1>(q2) - get<1>(q1);
|
||||
|
||||
return unified<ratio_type>(sinfo, p, q, policy, modelled_range_p, modelled_range_q);
|
||||
}
|
||||
|
||||
//! Returns true if two segments do not overlap.
|
||||
//! If not, then no further calculations need to be done.
|
||||
template
|
||||
<
|
||||
std::size_t Dimension,
|
||||
typename PointP,
|
||||
typename PointQ
|
||||
>
|
||||
static inline bool disjoint_by_range(PointP const& p1, PointP const& p2,
|
||||
PointQ const& q1, PointQ const& q2)
|
||||
{
|
||||
auto minp = get<Dimension>(p1);
|
||||
auto maxp = get<Dimension>(p2);
|
||||
auto minq = get<Dimension>(q1);
|
||||
auto maxq = get<Dimension>(q2);
|
||||
if (minp > maxp)
|
||||
{
|
||||
std::swap(minp, maxp);
|
||||
}
|
||||
if (minq > maxq)
|
||||
{
|
||||
std::swap(minq, maxq);
|
||||
}
|
||||
|
||||
// In this case, max(p) < min(q)
|
||||
// P Q
|
||||
// <-------> <------->
|
||||
// (and the space in between is not extremely small)
|
||||
return math::smaller(maxp, minq) || math::smaller(maxq, minp);
|
||||
}
|
||||
|
||||
// Implementation for either rescaled or non rescaled versions.
|
||||
template
|
||||
<
|
||||
typename RatioType,
|
||||
typename SegmentInfo,
|
||||
typename Segment1,
|
||||
typename Segment2,
|
||||
typename Policy,
|
||||
typename RobustPolicy,
|
||||
typename RobustPoint1,
|
||||
typename RobustPoint2
|
||||
typename UniqueSubRange1,
|
||||
typename UniqueSubRange2
|
||||
>
|
||||
static inline typename Policy::return_type
|
||||
apply(Segment1 const& a, Segment2 const& b,
|
||||
Policy const&, RobustPolicy const& /*robust_policy*/,
|
||||
RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
|
||||
RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2)
|
||||
unified(SegmentInfo& sinfo,
|
||||
Segment1 const& p, Segment2 const& q, Policy const&,
|
||||
UniqueSubRange1 const& range_p,
|
||||
UniqueSubRange2 const& range_q)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
|
||||
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
|
||||
typedef typename UniqueSubRange1::point_type point1_type;
|
||||
typedef typename UniqueSubRange2::point_type point2_type;
|
||||
typedef typename select_most_precise
|
||||
<
|
||||
typename geometry::coordinate_type<point1_type>::type,
|
||||
typename geometry::coordinate_type<point2_type>::type
|
||||
>::type coordinate_type;
|
||||
|
||||
using geometry::detail::equals::equals_point_point;
|
||||
bool const a_is_point = equals_point_point(robust_a1, robust_a2, point_in_point_strategy_type());
|
||||
bool const b_is_point = equals_point_point(robust_b1, robust_b2, point_in_point_strategy_type());
|
||||
point1_type const& p1 = range_p.at(0);
|
||||
point1_type const& p2 = range_p.at(1);
|
||||
point2_type const& q1 = range_q.at(0);
|
||||
point2_type const& q2 = range_q.at(1);
|
||||
|
||||
if(a_is_point && b_is_point)
|
||||
bool const p_is_point = equals_point_point(p1, p2);
|
||||
bool const q_is_point = equals_point_point(q1, q2);
|
||||
|
||||
if (p_is_point && q_is_point)
|
||||
{
|
||||
return equals_point_point(robust_a1, robust_b2, point_in_point_strategy_type())
|
||||
? Policy::degenerate(a, true)
|
||||
return equals_point_point(p1, q2)
|
||||
? Policy::degenerate(p, true)
|
||||
: Policy::disjoint()
|
||||
;
|
||||
}
|
||||
|
||||
if (disjoint_by_range<0>(p1, p2, q1, q2)
|
||||
|| disjoint_by_range<1>(p1, p2, q1, q2))
|
||||
{
|
||||
return Policy::disjoint();
|
||||
}
|
||||
|
||||
using side_strategy_type
|
||||
= typename side::services::default_strategy
|
||||
<cartesian_tag, CalculationType>::type;
|
||||
side_info sides;
|
||||
sides.set<0>(side_strategy_type::apply(robust_b1, robust_b2, robust_a1),
|
||||
side_strategy_type::apply(robust_b1, robust_b2, robust_a2));
|
||||
sides.set<0>(side_strategy_type::apply(q1, q2, p1),
|
||||
side_strategy_type::apply(q1, q2, p2));
|
||||
|
||||
if (sides.same<0>())
|
||||
{
|
||||
@@ -377,9 +448,9 @@ struct cartesian_segments
|
||||
return Policy::disjoint();
|
||||
}
|
||||
|
||||
sides.set<1>(side_strategy_type::apply(robust_a1, robust_a2, robust_b1),
|
||||
side_strategy_type::apply(robust_a1, robust_a2, robust_b2));
|
||||
|
||||
sides.set<1>(side_strategy_type::apply(p1, p2, q1),
|
||||
side_strategy_type::apply(p1, p2, q2));
|
||||
|
||||
if (sides.same<1>())
|
||||
{
|
||||
// Both points are at same side of other segment, we can leave
|
||||
@@ -388,78 +459,58 @@ struct cartesian_segments
|
||||
|
||||
bool collinear = sides.collinear();
|
||||
|
||||
typedef typename select_most_precise
|
||||
<
|
||||
typename geometry::coordinate_type<RobustPoint1>::type,
|
||||
typename geometry::coordinate_type<RobustPoint2>::type
|
||||
>::type robust_coordinate_type;
|
||||
|
||||
typedef typename segment_ratio_type
|
||||
<
|
||||
typename geometry::point_type<Segment1>::type, // TODO: most precise point?
|
||||
RobustPolicy
|
||||
>::type ratio_type;
|
||||
|
||||
segment_intersection_info
|
||||
<
|
||||
typename select_calculation_type<Segment1, Segment2, CalculationType>::type,
|
||||
ratio_type
|
||||
> sinfo;
|
||||
|
||||
sinfo.dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir
|
||||
sinfo.dx_b = get<1, 0>(b) - get<0, 0>(b);
|
||||
sinfo.dy_a = get<1, 1>(a) - get<0, 1>(a); // distance in y-dir
|
||||
sinfo.dy_b = get<1, 1>(b) - get<0, 1>(b);
|
||||
|
||||
robust_coordinate_type const robust_dx_a = get<0>(robust_a2) - get<0>(robust_a1);
|
||||
robust_coordinate_type const robust_dx_b = get<0>(robust_b2) - get<0>(robust_b1);
|
||||
robust_coordinate_type const robust_dy_a = get<1>(robust_a2) - get<1>(robust_a1);
|
||||
robust_coordinate_type const robust_dy_b = get<1>(robust_b2) - get<1>(robust_b1);
|
||||
// Calculate the differences again
|
||||
// (for rescaled version, this is different from dx_p etc)
|
||||
coordinate_type const dx_p = get<0>(p2) - get<0>(p1);
|
||||
coordinate_type const dx_q = get<0>(q2) - get<0>(q1);
|
||||
coordinate_type const dy_p = get<1>(p2) - get<1>(p1);
|
||||
coordinate_type const dy_q = get<1>(q2) - get<1>(q1);
|
||||
|
||||
// r: ratio 0-1 where intersection divides A/B
|
||||
// (only calculated for non-collinear segments)
|
||||
if (! collinear)
|
||||
{
|
||||
robust_coordinate_type robust_da0, robust_da;
|
||||
robust_coordinate_type robust_db0, robust_db;
|
||||
coordinate_type denominator_a, nominator_a;
|
||||
coordinate_type denominator_b, nominator_b;
|
||||
|
||||
cramers_rule(robust_dx_a, robust_dy_a, robust_dx_b, robust_dy_b,
|
||||
get<0>(robust_a1) - get<0>(robust_b1),
|
||||
get<1>(robust_a1) - get<1>(robust_b1),
|
||||
robust_da0, robust_da);
|
||||
cramers_rule(dx_p, dy_p, dx_q, dy_q,
|
||||
get<0>(p1) - get<0>(q1),
|
||||
get<1>(p1) - get<1>(q1),
|
||||
nominator_a, denominator_a);
|
||||
|
||||
cramers_rule(robust_dx_b, robust_dy_b, robust_dx_a, robust_dy_a,
|
||||
get<0>(robust_b1) - get<0>(robust_a1),
|
||||
get<1>(robust_b1) - get<1>(robust_a1),
|
||||
robust_db0, robust_db);
|
||||
cramers_rule(dx_q, dy_q, dx_p, dy_p,
|
||||
get<0>(q1) - get<0>(p1),
|
||||
get<1>(q1) - get<1>(p1),
|
||||
nominator_b, denominator_b);
|
||||
|
||||
math::detail::equals_factor_policy<robust_coordinate_type>
|
||||
policy(robust_dx_a, robust_dy_a, robust_dx_b, robust_dy_b);
|
||||
robust_coordinate_type const zero = 0;
|
||||
if (math::detail::equals_by_policy(robust_da0, zero, policy)
|
||||
|| math::detail::equals_by_policy(robust_db0, zero, policy))
|
||||
math::detail::equals_factor_policy<coordinate_type>
|
||||
policy(dx_p, dy_p, dx_q, dy_q);
|
||||
|
||||
coordinate_type const zero = 0;
|
||||
if (math::detail::equals_by_policy(denominator_a, zero, policy)
|
||||
|| math::detail::equals_by_policy(denominator_b, zero, policy))
|
||||
{
|
||||
// If this is the case, no rescaling is done for FP precision.
|
||||
// We set it to collinear, but it indicates a robustness issue.
|
||||
sides.set<0>(0,0);
|
||||
sides.set<1>(0,0);
|
||||
sides.set<0>(0, 0);
|
||||
sides.set<1>(0, 0);
|
||||
collinear = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sinfo.robust_ra.assign(robust_da, robust_da0);
|
||||
sinfo.robust_rb.assign(robust_db, robust_db0);
|
||||
sinfo.robust_ra.assign(nominator_a, denominator_a);
|
||||
sinfo.robust_rb.assign(nominator_b, denominator_b);
|
||||
}
|
||||
}
|
||||
|
||||
if (collinear)
|
||||
{
|
||||
std::pair<bool, bool> const collinear_use_first
|
||||
= is_x_more_significant(geometry::math::abs(robust_dx_a),
|
||||
geometry::math::abs(robust_dy_a),
|
||||
geometry::math::abs(robust_dx_b),
|
||||
geometry::math::abs(robust_dy_b),
|
||||
a_is_point, b_is_point);
|
||||
= is_x_more_significant(geometry::math::abs(dx_p),
|
||||
geometry::math::abs(dy_p),
|
||||
geometry::math::abs(dx_q),
|
||||
geometry::math::abs(dy_q),
|
||||
p_is_point, q_is_point);
|
||||
|
||||
if (collinear_use_first.second)
|
||||
{
|
||||
@@ -468,32 +519,32 @@ struct cartesian_segments
|
||||
|
||||
if (collinear_use_first.first)
|
||||
{
|
||||
return relate_collinear<0, Policy, ratio_type>(a, b,
|
||||
robust_a1, robust_a2, robust_b1, robust_b2,
|
||||
a_is_point, b_is_point);
|
||||
return relate_collinear<0, Policy, RatioType>(p, q,
|
||||
p1, p2, q1, q2,
|
||||
p_is_point, q_is_point);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Y direction contains larger segments (maybe dx is zero)
|
||||
return relate_collinear<1, Policy, ratio_type>(a, b,
|
||||
robust_a1, robust_a2, robust_b1, robust_b2,
|
||||
a_is_point, b_is_point);
|
||||
return relate_collinear<1, Policy, RatioType>(p, q,
|
||||
p1, p2, q1, q2,
|
||||
p_is_point, q_is_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Policy::segments_crosses(sides, sinfo, a, b);
|
||||
return Policy::segments_crosses(sides, sinfo, p, q);
|
||||
}
|
||||
|
||||
private:
|
||||
// first is true if x is more significant
|
||||
// second is true if the more significant difference is not 0
|
||||
template <typename RobustCoordinateType>
|
||||
template <typename CoordinateType>
|
||||
static inline std::pair<bool, bool>
|
||||
is_x_more_significant(RobustCoordinateType const& abs_robust_dx_a,
|
||||
RobustCoordinateType const& abs_robust_dy_a,
|
||||
RobustCoordinateType const& abs_robust_dx_b,
|
||||
RobustCoordinateType const& abs_robust_dy_b,
|
||||
is_x_more_significant(CoordinateType const& abs_dx_a,
|
||||
CoordinateType const& abs_dy_a,
|
||||
CoordinateType const& abs_dx_b,
|
||||
CoordinateType const& abs_dy_b,
|
||||
bool const a_is_point,
|
||||
bool const b_is_point)
|
||||
{
|
||||
@@ -504,18 +555,18 @@ private:
|
||||
|
||||
if (a_is_point)
|
||||
{
|
||||
return std::make_pair(abs_robust_dx_b >= abs_robust_dy_b, true);
|
||||
return std::make_pair(abs_dx_b >= abs_dy_b, true);
|
||||
}
|
||||
else if (b_is_point)
|
||||
{
|
||||
return std::make_pair(abs_robust_dx_a >= abs_robust_dy_a, true);
|
||||
return std::make_pair(abs_dx_a >= abs_dy_a, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
RobustCoordinateType const min_dx = (std::min)(abs_robust_dx_a, abs_robust_dx_b);
|
||||
RobustCoordinateType const min_dy = (std::min)(abs_robust_dy_a, abs_robust_dy_b);
|
||||
CoordinateType const min_dx = (std::min)(abs_dx_a, abs_dx_b);
|
||||
CoordinateType const min_dy = (std::min)(abs_dy_a, abs_dy_b);
|
||||
return min_dx == min_dy ?
|
||||
std::make_pair(true, min_dx > RobustCoordinateType(0)) :
|
||||
std::make_pair(true, min_dx > CoordinateType(0)) :
|
||||
std::make_pair(min_dx > min_dy, true);
|
||||
}
|
||||
}
|
||||
@@ -565,13 +616,13 @@ private:
|
||||
typename RatioType,
|
||||
typename Segment1,
|
||||
typename Segment2,
|
||||
typename RobustType1,
|
||||
typename RobustType2
|
||||
typename Type1,
|
||||
typename Type2
|
||||
>
|
||||
static inline typename Policy::return_type
|
||||
relate_collinear(Segment1 const& a, Segment2 const& b,
|
||||
RobustType1 oa_1, RobustType1 oa_2,
|
||||
RobustType2 ob_1, RobustType2 ob_2)
|
||||
Type1 oa_1, Type1 oa_2,
|
||||
Type2 ob_1, Type2 ob_2)
|
||||
{
|
||||
// Calculate the ratios where a starts in b, b starts in a
|
||||
// a1--------->a2 (2..7)
|
||||
@@ -603,8 +654,8 @@ private:
|
||||
// b2 is located w.r.t. a at ratio: (5-2)/5=3/5 (on a)
|
||||
// a1 is located w.r.t. b at ratio: (2-8)/-3=6/3 (after b ends)
|
||||
// a2 is located w.r.t. b at ratio: (7-8)/-3=1/3 (on b)
|
||||
RobustType1 const length_a = oa_2 - oa_1; // no abs, see above
|
||||
RobustType2 const length_b = ob_2 - ob_1;
|
||||
Type1 const length_a = oa_2 - oa_1; // no abs, see above
|
||||
Type2 const length_b = ob_2 - ob_1;
|
||||
|
||||
RatioType ra_from(oa_1 - ob_1, length_b);
|
||||
RatioType ra_to(oa_2 - ob_1, length_b);
|
||||
@@ -617,7 +668,7 @@ private:
|
||||
int const a2_wrt_b = position_value(oa_2, ob_1, ob_2);
|
||||
int const b1_wrt_a = position_value(ob_1, oa_1, oa_2);
|
||||
int const b2_wrt_a = position_value(ob_2, oa_1, oa_2);
|
||||
|
||||
|
||||
// fix the ratios if necessary
|
||||
// CONSIDER: fixing ratios also in other cases, if they're inconsistent
|
||||
// e.g. if ratio == 1 or 0 (so IP at the endpoint)
|
||||
@@ -634,7 +685,7 @@ private:
|
||||
{
|
||||
ra_from.assign(1, 1);
|
||||
rb_to.assign(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (a2_wrt_b == 1)
|
||||
{
|
||||
@@ -666,12 +717,12 @@ private:
|
||||
typename Policy,
|
||||
typename RatioType,
|
||||
typename DegenerateSegment,
|
||||
typename RobustType1,
|
||||
typename RobustType2
|
||||
typename Type1,
|
||||
typename Type2
|
||||
>
|
||||
static inline typename Policy::return_type
|
||||
relate_one_degenerate(DegenerateSegment const& degenerate_segment,
|
||||
RobustType1 d, RobustType2 s1, RobustType2 s2,
|
||||
Type1 d, Type2 s1, Type2 s2,
|
||||
bool a_degenerate)
|
||||
{
|
||||
// Calculate the ratios where ds starts in s
|
||||
@@ -705,6 +756,12 @@ private:
|
||||
: ca1 < cb2 ? 4
|
||||
: 2 );
|
||||
}
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
static inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
return strategy::within::cartesian_point_point::apply(point1, point2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2018, Oracle and/or its affiliates.
|
||||
// Copyright (c) 2018-2021, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
@@ -15,6 +16,7 @@
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/strategies/line_interpolate.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
|
||||
#include <boost/geometry/util/algorithm.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
|
||||
@@ -45,19 +47,6 @@ template
|
||||
class cartesian
|
||||
{
|
||||
public:
|
||||
|
||||
// point-point strategy getters
|
||||
struct distance_pp_strategy
|
||||
{
|
||||
typedef DistanceStrategy type;
|
||||
};
|
||||
|
||||
inline typename distance_pp_strategy::type get_distance_pp_strategy() const
|
||||
{
|
||||
typedef typename distance_pp_strategy::type distance_type;
|
||||
return distance_type();
|
||||
}
|
||||
|
||||
template <typename Point, typename Fraction, typename Distance>
|
||||
inline void apply(Point const& p0,
|
||||
Point const& p1,
|
||||
@@ -67,41 +56,22 @@ public:
|
||||
{
|
||||
typedef typename select_calculation_type_alt
|
||||
<
|
||||
CalculationType,
|
||||
Point
|
||||
CalculationType, Point
|
||||
>::type calc_t;
|
||||
|
||||
typedef model::point
|
||||
<
|
||||
calc_t,
|
||||
geometry::dimension<Point>::value,
|
||||
cs::cartesian
|
||||
> calc_point_t;
|
||||
|
||||
calc_point_t cp0, cp1;
|
||||
geometry::detail::conversion::convert_point_to_point(p0, cp0);
|
||||
geometry::detail::conversion::convert_point_to_point(p1, cp1);
|
||||
typedef typename coordinate_type<Point>::type coord_t;
|
||||
|
||||
//segment convex combination: p0*fraction + p1*(1-fraction)
|
||||
Fraction const one_minus_fraction = 1-fraction;
|
||||
for_each_coordinate(cp1, detail::value_operation
|
||||
<
|
||||
Fraction,
|
||||
std::multiplies
|
||||
>(fraction));
|
||||
for_each_coordinate(cp0, detail::value_operation
|
||||
<
|
||||
Fraction,
|
||||
std::multiplies
|
||||
>(one_minus_fraction));
|
||||
for_each_coordinate(cp1, detail::point_operation
|
||||
<
|
||||
calc_point_t,
|
||||
std::plus
|
||||
>(cp0));
|
||||
|
||||
assert_dimension_equal<calc_point_t, Point>();
|
||||
geometry::detail::conversion::convert_point_to_point(cp1, p);
|
||||
geometry::detail::for_each_dimension<Point>([&](auto dimension)
|
||||
{
|
||||
// NOTE: numeric_cast is a leftover from convert, it could probably be ommited.
|
||||
// NOTE: the order of points is different than in the formula above
|
||||
// this is also a leftover from the previous implementation
|
||||
calc_t coord0 = boost::numeric_cast<calc_t>(get<dimension>(p0));
|
||||
calc_t coord1 = boost::numeric_cast<calc_t>(get<dimension>(p1));
|
||||
calc_t result = calc_t(coord1 * fraction) + calc_t(coord0 * one_minus_fraction);
|
||||
set<dimension>(p, boost::numeric_cast<coord_t>(result));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018.
|
||||
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
|
||||
// Modifications copyright (c) 2013-2019, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
@@ -76,6 +76,8 @@ namespace strategy { namespace within
|
||||
|
||||
struct cartesian_point_point
|
||||
{
|
||||
typedef cartesian_tag cs_tag;
|
||||
|
||||
template <typename Point1, typename Point2>
|
||||
static inline bool apply(Point1 const& point1, Point2 const& point2)
|
||||
{
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2018.
|
||||
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2018, 2019.
|
||||
// Modifications copyright (c) 2018, 2019, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -47,18 +47,21 @@ namespace strategy { namespace within
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename PointOfSegment = Point,
|
||||
typename Point_, // for backward compatibility
|
||||
typename PointOfSegment_ = Point_, // for backward compatibility
|
||||
typename CalculationType = void
|
||||
>
|
||||
class crossings_multiply
|
||||
{
|
||||
typedef typename select_calculation_type
|
||||
<
|
||||
Point,
|
||||
PointOfSegment,
|
||||
CalculationType
|
||||
>::type calculation_type;
|
||||
template <typename Point, typename PointOfSegment>
|
||||
struct calculation_type
|
||||
: select_calculation_type
|
||||
<
|
||||
Point,
|
||||
PointOfSegment,
|
||||
CalculationType
|
||||
>
|
||||
{};
|
||||
|
||||
class flags
|
||||
{
|
||||
@@ -79,20 +82,21 @@ class crossings_multiply
|
||||
|
||||
public :
|
||||
|
||||
typedef Point point_type;
|
||||
typedef PointOfSegment segment_point_type;
|
||||
typedef flags state_type;
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline bool apply(Point const& point,
|
||||
PointOfSegment const& seg1, PointOfSegment const& seg2,
|
||||
flags& state)
|
||||
{
|
||||
calculation_type const tx = get<0>(point);
|
||||
calculation_type const ty = get<1>(point);
|
||||
calculation_type const x0 = get<0>(seg1);
|
||||
calculation_type const y0 = get<1>(seg1);
|
||||
calculation_type const x1 = get<0>(seg2);
|
||||
calculation_type const y1 = get<1>(seg2);
|
||||
typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
|
||||
|
||||
calc_t const tx = get<0>(point);
|
||||
calc_t const ty = get<1>(point);
|
||||
calc_t const x0 = get<0>(seg1);
|
||||
calc_t const y0 = get<1>(seg1);
|
||||
calc_t const x1 = get<0>(seg2);
|
||||
calc_t const y1 = get<1>(seg2);
|
||||
|
||||
if (state.first)
|
||||
{
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
||||
|
||||
// This file was modified by Oracle on 2018.
|
||||
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2018, 2019.
|
||||
// Modifications copyright (c) 2018, 2019, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
@@ -51,48 +51,52 @@ namespace strategy { namespace within
|
||||
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename PointOfSegment = Point,
|
||||
typename Point_, // for backward compatibility
|
||||
typename PointOfSegment_ = Point_, // for backward compatibility
|
||||
typename CalculationType = void
|
||||
>
|
||||
class franklin
|
||||
{
|
||||
typedef typename select_calculation_type
|
||||
<
|
||||
Point,
|
||||
PointOfSegment,
|
||||
CalculationType
|
||||
>::type calculation_type;
|
||||
template <typename Point, typename PointOfSegment>
|
||||
struct calculation_type
|
||||
: select_calculation_type
|
||||
<
|
||||
Point,
|
||||
PointOfSegment,
|
||||
CalculationType
|
||||
>
|
||||
{};
|
||||
|
||||
/*! subclass to keep state */
|
||||
class crossings
|
||||
{
|
||||
bool crosses;
|
||||
/*! subclass to keep state */
|
||||
class crossings
|
||||
{
|
||||
bool crosses;
|
||||
|
||||
public :
|
||||
public :
|
||||
|
||||
friend class franklin;
|
||||
inline crossings()
|
||||
: crosses(false)
|
||||
{}
|
||||
};
|
||||
friend class franklin;
|
||||
inline crossings()
|
||||
: crosses(false)
|
||||
{}
|
||||
};
|
||||
|
||||
public :
|
||||
|
||||
typedef Point point_type;
|
||||
typedef PointOfSegment segment_point_type;
|
||||
typedef crossings state_type;
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline bool apply(Point const& point,
|
||||
PointOfSegment const& seg1, PointOfSegment const& seg2,
|
||||
crossings& state)
|
||||
{
|
||||
calculation_type const& px = get<0>(point);
|
||||
calculation_type const& py = get<1>(point);
|
||||
calculation_type const& x1 = get<0>(seg1);
|
||||
calculation_type const& y1 = get<1>(seg1);
|
||||
calculation_type const& x2 = get<0>(seg2);
|
||||
calculation_type const& y2 = get<1>(seg2);
|
||||
typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
|
||||
|
||||
calc_t const& px = get<0>(point);
|
||||
calc_t const& py = get<1>(point);
|
||||
calc_t const& x1 = get<0>(seg1);
|
||||
calc_t const& y1 = get<1>(seg1);
|
||||
calc_t const& x2 = get<0>(seg2);
|
||||
calc_t const& y2 = get<1>(seg2);
|
||||
|
||||
if (
|
||||
( (y2 <= py && py < y1) || (y1 <= py && py < y2) )
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2013, 2014, 2016, 2017, 2018.
|
||||
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
|
||||
// This file was modified by Oracle on 2013-2021.
|
||||
// Modifications copyright (c) 2013-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
|
||||
@@ -23,9 +23,11 @@
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/strategies/covered_by.hpp>
|
||||
#include <boost/geometry/strategies/within.hpp>
|
||||
|
||||
@@ -36,37 +38,29 @@ namespace boost { namespace geometry
|
||||
namespace strategy { namespace within
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Within detection using winding rule in cartesian coordinate system.
|
||||
\ingroup strategies
|
||||
\tparam Point \tparam_point
|
||||
\tparam PointOfSegment \tparam_segment_point
|
||||
\tparam SideStrategy A strategy defining creation along sides
|
||||
\tparam CalculationType \tparam_calculation
|
||||
\author Barend Gehrels
|
||||
|
||||
\qbk{
|
||||
[heading See also]
|
||||
[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
|
||||
}
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Point,
|
||||
typename PointOfSegment = Point,
|
||||
typename CalculationType = void
|
||||
>
|
||||
class cartesian_winding
|
||||
template <typename SideStrategy, typename CalculationType>
|
||||
class cartesian_winding_base
|
||||
{
|
||||
typedef side::side_by_triangle<CalculationType> side_strategy_type;
|
||||
template <typename Point, typename PointOfSegment>
|
||||
struct calculation_type
|
||||
: select_calculation_type
|
||||
<
|
||||
Point,
|
||||
PointOfSegment,
|
||||
CalculationType
|
||||
>
|
||||
{};
|
||||
|
||||
typedef typename select_calculation_type
|
||||
<
|
||||
Point,
|
||||
PointOfSegment,
|
||||
CalculationType
|
||||
>::type calculation_type;
|
||||
|
||||
/*! subclass to keep state */
|
||||
class counter
|
||||
{
|
||||
@@ -79,7 +73,7 @@ class cartesian_winding
|
||||
}
|
||||
|
||||
public :
|
||||
friend class cartesian_winding;
|
||||
friend class cartesian_winding_base;
|
||||
|
||||
inline counter()
|
||||
: m_count(0)
|
||||
@@ -89,39 +83,12 @@ class cartesian_winding
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename side_strategy_type::envelope_strategy_type envelope_strategy_type;
|
||||
|
||||
static inline envelope_strategy_type get_envelope_strategy()
|
||||
{
|
||||
return side_strategy_type::get_envelope_strategy();
|
||||
}
|
||||
|
||||
typedef typename side_strategy_type::disjoint_strategy_type disjoint_strategy_type;
|
||||
|
||||
static inline disjoint_strategy_type get_disjoint_strategy()
|
||||
{
|
||||
return side_strategy_type::get_disjoint_strategy();
|
||||
}
|
||||
|
||||
typedef typename side_strategy_type::equals_point_point_strategy_type equals_point_point_strategy_type;
|
||||
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
|
||||
{
|
||||
return side_strategy_type::get_equals_point_point_strategy();
|
||||
}
|
||||
|
||||
typedef disjoint::cartesian_box_box disjoint_box_box_strategy_type;
|
||||
static inline disjoint_box_box_strategy_type get_disjoint_box_box_strategy()
|
||||
{
|
||||
return disjoint_box_box_strategy_type();
|
||||
}
|
||||
|
||||
typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type;
|
||||
typedef cartesian_tag cs_tag;
|
||||
|
||||
// Typedefs and static methods to fulfill the concept
|
||||
typedef Point point_type;
|
||||
typedef PointOfSegment segment_point_type;
|
||||
typedef counter state_type;
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline bool apply(Point const& point,
|
||||
PointOfSegment const& s1, PointOfSegment const& s2,
|
||||
counter& state)
|
||||
@@ -140,9 +107,9 @@ public:
|
||||
else // count == 2 || count == -2
|
||||
{
|
||||
// 1 left, -1 right
|
||||
side = side_strategy_type::apply(s1, s2, point);
|
||||
side = SideStrategy::apply(s1, s2, point);
|
||||
}
|
||||
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
// Point is lying on segment
|
||||
@@ -169,6 +136,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline int check_segment(Point const& point,
|
||||
PointOfSegment const& seg1,
|
||||
PointOfSegment const& seg2,
|
||||
@@ -183,15 +151,18 @@ private:
|
||||
return calculate_count(point, seg1, seg2, eq1, eq2);
|
||||
}
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline bool check_touch(Point const& point,
|
||||
PointOfSegment const& seg1,
|
||||
PointOfSegment const& seg2,
|
||||
counter& state,
|
||||
bool& eq1, bool& eq2)
|
||||
{
|
||||
calculation_type const px = get<0>(point);
|
||||
calculation_type const s1x = get<0>(seg1);
|
||||
calculation_type const s2x = get<0>(seg2);
|
||||
typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
|
||||
|
||||
calc_t const px = get<0>(point);
|
||||
calc_t const s1x = get<0>(seg1);
|
||||
calc_t const s2x = get<0>(seg2);
|
||||
|
||||
eq1 = math::equals(s1x, px);
|
||||
eq2 = math::equals(s2x, px);
|
||||
@@ -200,9 +171,9 @@ private:
|
||||
// The only thing which has to be done is check if point is ON segment
|
||||
if (eq1 && eq2)
|
||||
{
|
||||
calculation_type const py = get<1>(point);
|
||||
calculation_type const s1y = get<1>(seg1);
|
||||
calculation_type const s2y = get<1>(seg2);
|
||||
calc_t const py = get<1>(point);
|
||||
calc_t const s1y = get<1>(seg1);
|
||||
calc_t const s2y = get<1>(seg2);
|
||||
if ((s1y <= py && s2y >= py) || (s2y <= py && s1y >= py))
|
||||
{
|
||||
state.m_touches = true;
|
||||
@@ -212,14 +183,17 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline int calculate_count(Point const& point,
|
||||
PointOfSegment const& seg1,
|
||||
PointOfSegment const& seg2,
|
||||
bool eq1, bool eq2)
|
||||
{
|
||||
calculation_type const p = get<0>(point);
|
||||
calculation_type const s1 = get<0>(seg1);
|
||||
calculation_type const s2 = get<0>(seg2);
|
||||
typedef typename calculation_type<Point, PointOfSegment>::type calc_t;
|
||||
|
||||
calc_t const p = get<0>(point);
|
||||
calc_t const s1 = get<0>(seg1);
|
||||
calc_t const s2 = get<0>(seg2);
|
||||
|
||||
return eq1 ? (s2 > p ? 1 : -1) // Point on level s1, E/W depending on s2
|
||||
: eq2 ? (s1 > p ? -1 : 1) // idem
|
||||
@@ -228,6 +202,7 @@ private:
|
||||
: 0;
|
||||
}
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline int side_equal(Point const& point,
|
||||
PointOfSegment const& se,
|
||||
int count)
|
||||
@@ -242,6 +217,34 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
/*!
|
||||
\brief Within detection using winding rule in cartesian coordinate system.
|
||||
\ingroup strategies
|
||||
\tparam Point_ \tparam_point
|
||||
\tparam PointOfSegment_ \tparam_segment_point
|
||||
\tparam CalculationType \tparam_calculation
|
||||
|
||||
\qbk{
|
||||
[heading See also]
|
||||
[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
|
||||
}
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Point_ = void, // for backward compatibility
|
||||
typename PointOfSegment_ = Point_, // for backward compatibility
|
||||
typename CalculationType = void
|
||||
>
|
||||
class cartesian_winding
|
||||
: public detail::cartesian_winding_base
|
||||
<
|
||||
typename side::services::default_strategy<cartesian_tag, CalculationType>::type,
|
||||
CalculationType
|
||||
>
|
||||
{};
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
|
||||
@@ -251,21 +254,13 @@ namespace services
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
|
||||
{
|
||||
typedef cartesian_winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
using type = cartesian_winding<>;
|
||||
};
|
||||
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
|
||||
{
|
||||
typedef cartesian_winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
using type = cartesian_winding<>;
|
||||
};
|
||||
|
||||
} // namespace services
|
||||
@@ -283,21 +278,13 @@ namespace strategy { namespace covered_by { namespace services
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
|
||||
{
|
||||
typedef within::cartesian_winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
using type = within::cartesian_winding<>;
|
||||
};
|
||||
|
||||
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
|
||||
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
|
||||
{
|
||||
typedef within::cartesian_winding
|
||||
<
|
||||
typename geometry::point_type<PointLike>::type,
|
||||
typename geometry::point_type<Geometry>::type
|
||||
> type;
|
||||
using type = within::cartesian_winding<>;
|
||||
};
|
||||
|
||||
}}} // namespace strategy::covered_by::services
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2019-2020, 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_STRATEGIES_CARTESIAN_POINT_ORDER_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_ORDER_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/core/tags.hpp>
|
||||
|
||||
#include <boost/geometry/strategy/cartesian/area.hpp>
|
||||
#include <boost/geometry/strategies/point_order.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace point_order
|
||||
{
|
||||
|
||||
template <typename CalculationType = void>
|
||||
struct cartesian
|
||||
: strategy::area::cartesian<CalculationType>
|
||||
{
|
||||
typedef area_tag version_tag;
|
||||
|
||||
// TEMP
|
||||
static strategy::area::cartesian<CalculationType> get_area_strategy()
|
||||
{
|
||||
return strategy::area::cartesian<CalculationType>();
|
||||
}
|
||||
};
|
||||
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <>
|
||||
struct default_strategy<cartesian_tag>
|
||||
{
|
||||
typedef cartesian<> type;
|
||||
};
|
||||
|
||||
} // namespace services
|
||||
|
||||
}} // namespace strategy::point_order
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_ORDER_HPP
|
||||
@@ -1,296 +1,21 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
// Boost.Geometry
|
||||
|
||||
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||
// Copyright (c) 2021, Oracle and/or its affiliates.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2017, 2018.
|
||||
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
|
||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Licensed under the Boost Software License version 1.0.
|
||||
// http://www.boost.org/users/license.html
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/is_void.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/envelope.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
|
||||
#include <boost/geometry/strategies/compare.hpp>
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace side
|
||||
{
|
||||
|
||||
/*!
|
||||
\brief Check at which side of a segment a point lies:
|
||||
left of segment (> 0), right of segment (< 0), on segment (0)
|
||||
\ingroup strategies
|
||||
\tparam CalculationType \tparam_calculation
|
||||
*/
|
||||
template <typename CalculationType = void>
|
||||
class side_by_triangle
|
||||
{
|
||||
template <typename Policy>
|
||||
struct eps_policy
|
||||
{
|
||||
eps_policy() {}
|
||||
template <typename Type>
|
||||
eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)
|
||||
: policy(a, b, c, d)
|
||||
{}
|
||||
Policy policy;
|
||||
};
|
||||
|
||||
struct eps_empty
|
||||
{
|
||||
eps_empty() {}
|
||||
template <typename Type>
|
||||
eps_empty(Type const&, Type const&, Type const&, Type const&) {}
|
||||
};
|
||||
|
||||
public :
|
||||
typedef strategy::envelope::cartesian<CalculationType> envelope_strategy_type;
|
||||
|
||||
static inline envelope_strategy_type get_envelope_strategy()
|
||||
{
|
||||
return envelope_strategy_type();
|
||||
}
|
||||
|
||||
typedef strategy::disjoint::segment_box disjoint_strategy_type;
|
||||
|
||||
static inline disjoint_strategy_type get_disjoint_strategy()
|
||||
{
|
||||
return disjoint_strategy_type();
|
||||
}
|
||||
|
||||
typedef strategy::within::cartesian_point_point equals_point_point_strategy_type;
|
||||
static inline equals_point_point_strategy_type get_equals_point_point_strategy()
|
||||
{
|
||||
return equals_point_point_strategy_type();
|
||||
}
|
||||
|
||||
// Template member function, because it is not always trivial
|
||||
// or convenient to explicitly mention the typenames in the
|
||||
// strategy-struct itself.
|
||||
|
||||
// Types can be all three different. Therefore it is
|
||||
// not implemented (anymore) as "segment"
|
||||
|
||||
template
|
||||
<
|
||||
typename CoordinateType,
|
||||
typename PromotedType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
typename P,
|
||||
typename EpsPolicy
|
||||
>
|
||||
static inline
|
||||
PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)
|
||||
{
|
||||
CoordinateType const x = get<0>(p);
|
||||
CoordinateType const y = get<1>(p);
|
||||
|
||||
CoordinateType const sx1 = get<0>(p1);
|
||||
CoordinateType const sy1 = get<1>(p1);
|
||||
CoordinateType const sx2 = get<0>(p2);
|
||||
CoordinateType const sy2 = get<1>(p2);
|
||||
|
||||
PromotedType const dx = sx2 - sx1;
|
||||
PromotedType const dy = sy2 - sy1;
|
||||
PromotedType const dpx = x - sx1;
|
||||
PromotedType const dpy = y - sy1;
|
||||
|
||||
eps_policy = EpsPolicy(dx, dy, dpx, dpy);
|
||||
|
||||
return geometry::detail::determinant<PromotedType>
|
||||
(
|
||||
dx, dy,
|
||||
dpx, dpy
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename CoordinateType,
|
||||
typename PromotedType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
typename P
|
||||
>
|
||||
static inline
|
||||
PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)
|
||||
{
|
||||
eps_empty dummy;
|
||||
return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename CoordinateType,
|
||||
typename PromotedType,
|
||||
bool AreAllIntegralCoordinates
|
||||
>
|
||||
struct compute_side_value
|
||||
{
|
||||
template <typename P1, typename P2, typename P, typename EpsPolicy>
|
||||
static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
|
||||
{
|
||||
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CoordinateType, typename PromotedType>
|
||||
struct compute_side_value<CoordinateType, PromotedType, false>
|
||||
{
|
||||
template <typename P1, typename P2, typename P, typename EpsPolicy>
|
||||
static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
|
||||
{
|
||||
// For robustness purposes, first check if any two points are
|
||||
// the same; in this case simply return that the points are
|
||||
// collinear
|
||||
if (equals_point_point(p1, p2)
|
||||
|| equals_point_point(p1, p)
|
||||
|| equals_point_point(p2, p))
|
||||
{
|
||||
return PromotedType(0);
|
||||
}
|
||||
|
||||
// The side_by_triangle strategy computes the signed area of
|
||||
// the point triplet (p1, p2, p); as such it is (in theory)
|
||||
// invariant under cyclic permutations of its three arguments.
|
||||
//
|
||||
// In the context of numerical errors that arise in
|
||||
// floating-point computations, and in order to make the strategy
|
||||
// consistent with respect to cyclic permutations of its three
|
||||
// arguments, we cyclically permute them so that the first
|
||||
// argument is always the lexicographically smallest point.
|
||||
|
||||
typedef compare::cartesian<compare::less> less;
|
||||
|
||||
if (less::apply(p, p1))
|
||||
{
|
||||
if (less::apply(p, p2))
|
||||
{
|
||||
// p is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// p2 is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
|
||||
}
|
||||
}
|
||||
|
||||
if (less::apply(p1, p2))
|
||||
{
|
||||
// p1 is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// p2 is the lexicographically smallest
|
||||
return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename P1, typename P2, typename P>
|
||||
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
|
||||
{
|
||||
typedef typename coordinate_type<P1>::type coordinate_type1;
|
||||
typedef typename coordinate_type<P2>::type coordinate_type2;
|
||||
typedef typename coordinate_type<P>::type coordinate_type3;
|
||||
|
||||
typedef typename boost::mpl::if_c
|
||||
<
|
||||
boost::is_void<CalculationType>::type::value,
|
||||
typename select_most_precise
|
||||
<
|
||||
typename select_most_precise
|
||||
<
|
||||
coordinate_type1, coordinate_type2
|
||||
>::type,
|
||||
coordinate_type3
|
||||
>::type,
|
||||
CalculationType
|
||||
>::type coordinate_type;
|
||||
|
||||
// Promote float->double, small int->int
|
||||
typedef typename select_most_precise
|
||||
<
|
||||
coordinate_type,
|
||||
double
|
||||
>::type promoted_type;
|
||||
|
||||
bool const are_all_integral_coordinates =
|
||||
boost::is_integral<coordinate_type1>::value
|
||||
&& boost::is_integral<coordinate_type2>::value
|
||||
&& boost::is_integral<coordinate_type3>::value;
|
||||
|
||||
eps_policy< math::detail::equals_factor_policy<promoted_type> > epsp;
|
||||
promoted_type s = compute_side_value
|
||||
<
|
||||
coordinate_type, promoted_type, are_all_integral_coordinates
|
||||
>::apply(p1, p2, p, epsp);
|
||||
|
||||
promoted_type const zero = promoted_type();
|
||||
return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0
|
||||
: s > zero ? 1
|
||||
: -1;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename P1, typename P2>
|
||||
static inline bool equals_point_point(P1 const& p1, P2 const& p2)
|
||||
{
|
||||
typedef equals_point_point_strategy_type strategy_t;
|
||||
return geometry::detail::equals::equals_point_point(p1, p2, strategy_t());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
||||
namespace services
|
||||
{
|
||||
|
||||
template <typename CalculationType>
|
||||
struct default_strategy<cartesian_tag, CalculationType>
|
||||
{
|
||||
typedef side_by_triangle<CalculationType> type;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}} // namespace strategy::side
|
||||
|
||||
}} // namespace boost::geometry
|
||||
#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
|
||||
|
||||
@@ -1,351 +0,0 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
|
||||
// This file was modified by Oracle on 2015, 2019.
|
||||
// Modifications copyright (c) 2015-2019, Oracle and/or its affiliates.
|
||||
|
||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_OF_INTERSECTION_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_OF_INTERSECTION_HPP
|
||||
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
|
||||
#include <boost/geometry/arithmetic/determinant.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/assert.hpp>
|
||||
#include <boost/geometry/core/coordinate_type.hpp>
|
||||
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
|
||||
#include <boost/math/common_factor_ct.hpp>
|
||||
#include <boost/math/common_factor_rt.hpp>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace side
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// A tool for multiplication of integers avoiding overflow
|
||||
// It's a temporary workaround until we can use Multiprecision
|
||||
// The algorithm is based on Karatsuba algorithm
|
||||
// see: http://en.wikipedia.org/wiki/Karatsuba_algorithm
|
||||
template <typename T>
|
||||
struct multiplicable_integral
|
||||
{
|
||||
// Currently this tool can't be used with non-integral coordinate types.
|
||||
// Also side_of_intersection strategy sign_of_product() and sign_of_compare()
|
||||
// functions would have to be modified to properly support floating-point
|
||||
// types (comparisons and multiplication).
|
||||
BOOST_STATIC_ASSERT(boost::is_integral<T>::value);
|
||||
|
||||
static const std::size_t bits = CHAR_BIT * sizeof(T);
|
||||
static const std::size_t half_bits = bits / 2;
|
||||
typedef typename boost::make_unsigned<T>::type unsigned_type;
|
||||
static const unsigned_type base = unsigned_type(1) << half_bits; // 2^half_bits
|
||||
|
||||
int m_sign;
|
||||
unsigned_type m_ms;
|
||||
unsigned_type m_ls;
|
||||
|
||||
multiplicable_integral(int sign, unsigned_type ms, unsigned_type ls)
|
||||
: m_sign(sign), m_ms(ms), m_ls(ls)
|
||||
{}
|
||||
|
||||
explicit multiplicable_integral(T const& val)
|
||||
{
|
||||
unsigned_type val_u = val > 0 ?
|
||||
unsigned_type(val)
|
||||
: val == (std::numeric_limits<T>::min)() ?
|
||||
unsigned_type((std::numeric_limits<T>::max)()) + 1
|
||||
: unsigned_type(-val);
|
||||
// MMLL -> S 00MM 00LL
|
||||
m_sign = math::sign(val);
|
||||
m_ms = val_u >> half_bits; // val_u / base
|
||||
m_ls = val_u - m_ms * base;
|
||||
}
|
||||
|
||||
friend multiplicable_integral operator*(multiplicable_integral const& a,
|
||||
multiplicable_integral const& b)
|
||||
{
|
||||
// (S 00MM 00LL) * (S 00MM 00LL) -> (S Z2MM 00LL)
|
||||
unsigned_type z2 = a.m_ms * b.m_ms;
|
||||
unsigned_type z0 = a.m_ls * b.m_ls;
|
||||
unsigned_type z1 = (a.m_ms + a.m_ls) * (b.m_ms + b.m_ls) - z2 - z0;
|
||||
// z0 may be >= base so it must be normalized to allow comparison
|
||||
unsigned_type z0_ms = z0 >> half_bits; // z0 / base
|
||||
return multiplicable_integral(a.m_sign * b.m_sign,
|
||||
z2 * base + z1 + z0_ms,
|
||||
z0 - base * z0_ms);
|
||||
}
|
||||
|
||||
friend bool operator<(multiplicable_integral const& a,
|
||||
multiplicable_integral const& b)
|
||||
{
|
||||
if ( a.m_sign == b.m_sign )
|
||||
{
|
||||
bool u_less = a.m_ms < b.m_ms
|
||||
|| (a.m_ms == b.m_ms && a.m_ls < b.m_ls);
|
||||
return a.m_sign > 0 ? u_less : (! u_less);
|
||||
}
|
||||
else
|
||||
{
|
||||
return a.m_sign < b.m_sign;
|
||||
}
|
||||
}
|
||||
|
||||
friend bool operator>(multiplicable_integral const& a,
|
||||
multiplicable_integral const& b)
|
||||
{
|
||||
return b < a;
|
||||
}
|
||||
|
||||
#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
|
||||
template <typename CmpVal>
|
||||
void check_value(CmpVal const& cmp_val) const
|
||||
{
|
||||
unsigned_type b = base; // a workaround for MinGW - undefined reference base
|
||||
CmpVal val = CmpVal(m_sign) * (CmpVal(m_ms) * CmpVal(b) + CmpVal(m_ls));
|
||||
BOOST_GEOMETRY_ASSERT(cmp_val == val);
|
||||
}
|
||||
#endif // BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Calculates the side of the intersection-point (if any) of
|
||||
// of segment a//b w.r.t. segment c
|
||||
// This is calculated without (re)calculating the IP itself again and fully
|
||||
// based on integer mathematics; there are no divisions
|
||||
// It can be used for either integer (rescaled) points, and also for FP
|
||||
class side_of_intersection
|
||||
{
|
||||
private :
|
||||
template <typename T, typename U>
|
||||
static inline
|
||||
int sign_of_product(T const& a, U const& b)
|
||||
{
|
||||
return a == 0 || b == 0 ? 0
|
||||
: a > 0 && b > 0 ? 1
|
||||
: a < 0 && b < 0 ? 1
|
||||
: -1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline
|
||||
int sign_of_compare(T const& a, T const& b, T const& c, T const& d)
|
||||
{
|
||||
// Both a*b and c*d are positive
|
||||
// We have to judge if a*b > c*d
|
||||
|
||||
using side::detail::multiplicable_integral;
|
||||
multiplicable_integral<T> ab = multiplicable_integral<T>(a)
|
||||
* multiplicable_integral<T>(b);
|
||||
multiplicable_integral<T> cd = multiplicable_integral<T>(c)
|
||||
* multiplicable_integral<T>(d);
|
||||
|
||||
int result = ab > cd ? 1
|
||||
: ab < cd ? -1
|
||||
: 0
|
||||
;
|
||||
|
||||
#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
|
||||
using namespace boost::multiprecision;
|
||||
cpp_int const lab = cpp_int(a) * cpp_int(b);
|
||||
cpp_int const lcd = cpp_int(c) * cpp_int(d);
|
||||
|
||||
ab.check_value(lab);
|
||||
cd.check_value(lcd);
|
||||
|
||||
int result2 = lab > lcd ? 1
|
||||
: lab < lcd ? -1
|
||||
: 0
|
||||
;
|
||||
BOOST_GEOMETRY_ASSERT(result == result2);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline
|
||||
int sign_of_addition_of_two_products(T const& a, T const& b, T const& c, T const& d)
|
||||
{
|
||||
// sign of a*b+c*d, 1 if positive, -1 if negative, else 0
|
||||
int const ab = sign_of_product(a, b);
|
||||
int const cd = sign_of_product(c, d);
|
||||
if (ab == 0)
|
||||
{
|
||||
return cd;
|
||||
}
|
||||
if (cd == 0)
|
||||
{
|
||||
return ab;
|
||||
}
|
||||
|
||||
if (ab == cd)
|
||||
{
|
||||
// Both positive or both negative
|
||||
return ab;
|
||||
}
|
||||
|
||||
// One is positive, one is negative, both are non zero
|
||||
// If ab is positive, we have to judge if a*b > -c*d (then 1 because sum is positive)
|
||||
// If ab is negative, we have to judge if c*d > -a*b (idem)
|
||||
return ab == 1
|
||||
? sign_of_compare(a, b, -c, d)
|
||||
: sign_of_compare(c, d, -a, b);
|
||||
}
|
||||
|
||||
|
||||
public :
|
||||
|
||||
// Calculates the side of the intersection-point (if any) of
|
||||
// of segment a//b w.r.t. segment c
|
||||
// This is calculated without (re)calculating the IP itself again and fully
|
||||
// based on integer mathematics
|
||||
template <typename T, typename Segment, typename Point>
|
||||
static inline T side_value(Segment const& a, Segment const& b,
|
||||
Segment const& c, Point const& fallback_point)
|
||||
{
|
||||
// The first point of the three segments is reused several times
|
||||
T const ax = get<0, 0>(a);
|
||||
T const ay = get<0, 1>(a);
|
||||
T const bx = get<0, 0>(b);
|
||||
T const by = get<0, 1>(b);
|
||||
T const cx = get<0, 0>(c);
|
||||
T const cy = get<0, 1>(c);
|
||||
|
||||
T const dx_a = get<1, 0>(a) - ax;
|
||||
T const dy_a = get<1, 1>(a) - ay;
|
||||
|
||||
T const dx_b = get<1, 0>(b) - bx;
|
||||
T const dy_b = get<1, 1>(b) - by;
|
||||
|
||||
T const dx_c = get<1, 0>(c) - cx;
|
||||
T const dy_c = get<1, 1>(c) - cy;
|
||||
|
||||
// Cramer's rule: d (see cart_intersect.hpp)
|
||||
T const d = geometry::detail::determinant<T>
|
||||
(
|
||||
dx_a, dy_a,
|
||||
dx_b, dy_b
|
||||
);
|
||||
|
||||
T const zero = T();
|
||||
if (d == zero)
|
||||
{
|
||||
// There is no IP of a//b, they are collinear or parallel
|
||||
// Assuming they intersect (this method should be called for
|
||||
// segments known to intersect), they are collinear and overlap.
|
||||
// They have one or two intersection points - we don't know and
|
||||
// have to rely on the fallback intersection point
|
||||
|
||||
Point c1, c2;
|
||||
geometry::detail::assign_point_from_index<0>(c, c1);
|
||||
geometry::detail::assign_point_from_index<1>(c, c2);
|
||||
return side_by_triangle<>::apply(c1, c2, fallback_point);
|
||||
}
|
||||
|
||||
// Cramer's rule: da (see cart_intersect.hpp)
|
||||
T const da = geometry::detail::determinant<T>
|
||||
(
|
||||
dx_b, dy_b,
|
||||
ax - bx, ay - by
|
||||
);
|
||||
|
||||
// IP is at (ax + (da/d) * dx_a, ay + (da/d) * dy_a)
|
||||
// Side of IP is w.r.t. c is: determinant(dx_c, dy_c, ipx-cx, ipy-cy)
|
||||
// We replace ipx by expression above and multiply each term by d
|
||||
|
||||
#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
|
||||
T const result1 = geometry::detail::determinant<T>
|
||||
(
|
||||
dx_c * d, dy_c * d,
|
||||
d * (ax - cx) + dx_a * da, d * (ay - cy) + dy_a * da
|
||||
);
|
||||
|
||||
// Note: result / (d * d)
|
||||
// is identical to the side_value of side_by_triangle
|
||||
// Therefore, the sign is always the same as that result, and the
|
||||
// resulting side (left,right,collinear) is the same
|
||||
|
||||
// The first row we divide again by d because of determinant multiply rule
|
||||
T const result2 = d * geometry::detail::determinant<T>
|
||||
(
|
||||
dx_c, dy_c,
|
||||
d * (ax - cx) + dx_a * da, d * (ay - cy) + dy_a * da
|
||||
);
|
||||
// Write out:
|
||||
T const result3 = d * (dx_c * (d * (ay - cy) + dy_a * da)
|
||||
- dy_c * (d * (ax - cx) + dx_a * da));
|
||||
// Write out in braces:
|
||||
T const result4 = d * (dx_c * d * (ay - cy) + dx_c * dy_a * da
|
||||
- dy_c * d * (ax - cx) - dy_c * dx_a * da);
|
||||
// Write in terms of d * XX + da * YY
|
||||
T const result5 = d * (d * (dx_c * (ay - cy) - dy_c * (ax - cx))
|
||||
+ da * (dx_c * dy_a - dy_c * dx_a));
|
||||
|
||||
boost::ignore_unused(result1, result2, result3, result4, result5);
|
||||
//return result;
|
||||
#endif
|
||||
|
||||
// We consider the results separately
|
||||
// (in the end we only have to return the side-value 1,0 or -1)
|
||||
|
||||
// To avoid multiplications we judge the product (easy, avoids *d)
|
||||
// and the sign of p*q+r*s (more elaborate)
|
||||
T const result = sign_of_product
|
||||
(
|
||||
d,
|
||||
sign_of_addition_of_two_products
|
||||
(
|
||||
d, dx_c * (ay - cy) - dy_c * (ax - cx),
|
||||
da, dx_c * dy_a - dy_c * dx_a
|
||||
)
|
||||
);
|
||||
return result;
|
||||
|
||||
|
||||
}
|
||||
|
||||
template <typename Segment, typename Point>
|
||||
static inline int apply(Segment const& a, Segment const& b,
|
||||
Segment const& c,
|
||||
Point const& fallback_point)
|
||||
{
|
||||
typedef typename geometry::coordinate_type<Segment>::type coordinate_type;
|
||||
coordinate_type const s = side_value<coordinate_type>(a, b, c, fallback_point);
|
||||
coordinate_type const zero = coordinate_type();
|
||||
return math::equals(s, zero) ? 0
|
||||
: s > zero ? 1
|
||||
: -1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}} // namespace strategy::side
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_OF_INTERSECTION_HPP
|
||||
@@ -0,0 +1,65 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2021 Tinko Bartels, Berlin, Germany.
|
||||
|
||||
// This file was modified by Oracle on 2023.
|
||||
// Modifications copyright (c) 2023 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROUNDED_INPUT_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROUNDED_INPUT_HPP
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/config.hpp>
|
||||
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/side.hpp>
|
||||
|
||||
#include <boost/geometry/util/select_calculation_type.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace side
|
||||
{
|
||||
|
||||
template <typename CalculationType = void, int Coeff1 = 5, int Coeff2 = 32>
|
||||
struct side_rounded_input
|
||||
{
|
||||
using cs_tag = cartesian_tag;
|
||||
|
||||
template <typename P1, typename P2, typename P>
|
||||
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
|
||||
{
|
||||
using coor_t = typename select_calculation_type_alt<CalculationType, P1, P2, P>::type;
|
||||
|
||||
coor_t const p1_x = geometry::get<0>(p1);
|
||||
coor_t const p1_y = geometry::get<1>(p1);
|
||||
coor_t const p2_x = geometry::get<0>(p2);
|
||||
coor_t const p2_y = geometry::get<1>(p2);
|
||||
coor_t const p_x = geometry::get<0>(p);
|
||||
coor_t const p_y = geometry::get<1>(p);
|
||||
|
||||
constexpr coor_t eps = std::numeric_limits<coor_t>::epsilon() / 2;
|
||||
coor_t const det = (p1_x - p_x) * (p2_y - p_y) - (p1_y - p_y) * (p2_x - p_x);
|
||||
coor_t const err_bound = (Coeff1 * eps + Coeff2 * eps * eps) *
|
||||
( (geometry::math::abs(p1_x) + geometry::math::abs(p_x))
|
||||
* (geometry::math::abs(p2_y) + geometry::math::abs(p_y))
|
||||
+ (geometry::math::abs(p2_x) + geometry::math::abs(p_x))
|
||||
* (geometry::math::abs(p1_y) + geometry::math::abs(p_y)));
|
||||
return (det > err_bound) - (det < -err_bound);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace strategy::side
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROUNDED_INPUT_HPP
|
||||
@@ -0,0 +1,230 @@
|
||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||
|
||||
// Copyright (c) 2020 Barend Gehrels, Amsterdam, the Netherlands.
|
||||
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
|
||||
|
||||
// This file was modified by Oracle on 2023.
|
||||
// Modifications copyright (c) 2023 Oracle and/or its affiliates.
|
||||
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software License,
|
||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_TURN_IN_RING_WINDING_HPP
|
||||
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_TURN_IN_RING_WINDING_HPP
|
||||
|
||||
#include <boost/geometry/arithmetic/infinite_line_functions.hpp>
|
||||
#include <boost/geometry/core/access.hpp>
|
||||
#include <boost/geometry/core/config.hpp>
|
||||
#include <boost/geometry/algorithms/detail/make/make.hpp>
|
||||
#include <boost/geometry/util/math.hpp>
|
||||
|
||||
#include <boost/geometry/strategies/cartesian/side_rounded_input.hpp>
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
namespace strategy { namespace buffer
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
|
||||
enum place_on_ring_type
|
||||
{
|
||||
// +----offsetted----> (offsetted is considered as outside)
|
||||
// | |
|
||||
// | |
|
||||
// left right (first point outside, rest inside)
|
||||
// | |
|
||||
// | |
|
||||
// <-----original----+ (original is considered as inside)
|
||||
place_on_ring_offsetted,
|
||||
place_on_ring_original,
|
||||
place_on_ring_to_offsetted,
|
||||
place_on_ring_from_offsetted,
|
||||
};
|
||||
|
||||
template <typename CalculationType>
|
||||
class turn_in_ring_winding
|
||||
{
|
||||
|
||||
// Implements the winding rule.
|
||||
// Basic calculations (on a clockwise ring of 5 segments)
|
||||
// (as everywhere in BG, -1 = right, 0 = on segment, +1 = left)
|
||||
// +--------2--------+ // P : For 1/3, nothing happens, it returns
|
||||
// | | // For 2, side is right (-1), multiplier=2, -2
|
||||
// | P | // For 4, side is right (-1), multiplier=1, -1
|
||||
// 1 3 // For 5, side is right (-1), multiplier=1, -1, total -4
|
||||
// | Q | // Q : For 2: -2, for 4: -2, total -4
|
||||
// | | // R : For 2: -2, for 5: +2, total 0
|
||||
// +----5---*----4---+ // S : For 2: -1, 3: nothing, 4: +1, total 0
|
||||
//
|
||||
// R S
|
||||
//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
struct counter
|
||||
{
|
||||
//! Counter, is increased if point is left of a segment (outside),
|
||||
//! and decreased if point is right of a segment (inside)
|
||||
int count{0};
|
||||
|
||||
int count_on_offsetted{0};
|
||||
int count_on_origin{0};
|
||||
int count_on_edge{0};
|
||||
|
||||
CalculationType edge_min_fraction{(std::numeric_limits<CalculationType>::max)()};
|
||||
#if defined(BOOST_GEOMETRY_USE_RESCALING)
|
||||
CalculationType inside_min_measure{(std::numeric_limits<CalculationType>::max)()};
|
||||
#endif
|
||||
|
||||
inline bool is_inside() const
|
||||
{
|
||||
return count < 0 || count_on_origin > 0;
|
||||
}
|
||||
|
||||
inline bool is_on_boundary() const
|
||||
{
|
||||
return count_on_origin == 0
|
||||
&& (count_on_offsetted > 0
|
||||
|| (count_on_edge > 0 && edge_min_fraction < 1.0e-3)
|
||||
#if defined(BOOST_GEOMETRY_USE_RESCALING)
|
||||
|| (count < 0 && inside_min_measure < 1.0e-5)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
using state_type = counter;
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline bool is_in_vertical_range(Point const& point,
|
||||
PointOfSegment const& s1,
|
||||
PointOfSegment const& s2)
|
||||
{
|
||||
CalculationType const py = get<1>(point);
|
||||
CalculationType const s1y = get<1>(s1);
|
||||
CalculationType const s2y = get<1>(s2);
|
||||
|
||||
return s1y < s2y ? (py >= s1y && py <= s2y) : (py >= s2y && py <= s1y);
|
||||
}
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline void apply_on_boundary(Point const& point,
|
||||
PointOfSegment const& s1,
|
||||
PointOfSegment const& s2,
|
||||
place_on_ring_type place_on_ring,
|
||||
counter& the_state)
|
||||
{
|
||||
if (place_on_ring == place_on_ring_offsetted)
|
||||
{
|
||||
the_state.count_on_offsetted++;
|
||||
}
|
||||
else if (place_on_ring == place_on_ring_to_offsetted
|
||||
|| place_on_ring == place_on_ring_from_offsetted)
|
||||
{
|
||||
the_state.count_on_edge++;
|
||||
|
||||
auto const line1 = detail::make::make_perpendicular_line<CalculationType>(s1, s2, s1);
|
||||
auto const line2 = detail::make::make_perpendicular_line<CalculationType>(s2, s1, s2);
|
||||
|
||||
auto const value1 = arithmetic::side_value(line1, point);
|
||||
auto const value2 = arithmetic::side_value(line2, point);
|
||||
if (value1 >= 0 && value2 >= 0)
|
||||
{
|
||||
auto const length_value = value1 + value2;
|
||||
if (length_value > 0)
|
||||
{
|
||||
// If it is to the utmost point s1 or s2, it is "outside"
|
||||
auto const fraction = (place_on_ring == place_on_ring_to_offsetted ? value2 : value1) / length_value;
|
||||
if (fraction < the_state.edge_min_fraction)
|
||||
{
|
||||
the_state.edge_min_fraction = fraction;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
the_state.count_on_origin++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Point, typename PointOfSegment>
|
||||
static inline bool apply(Point const& point,
|
||||
PointOfSegment const& s1,
|
||||
PointOfSegment const& s2,
|
||||
place_on_ring_type place_on_ring,
|
||||
bool is_convex,
|
||||
counter& the_state)
|
||||
{
|
||||
int const side = strategy::side::side_rounded_input<CalculationType>::apply(s1, s2, point);
|
||||
|
||||
if (is_convex && side > 0)
|
||||
{
|
||||
// If the point is left of this segment of a convex piece, it can never be inside.
|
||||
// Stop further processing
|
||||
the_state.count = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
CalculationType const px = get<0>(point);
|
||||
CalculationType const s1x = get<0>(s1);
|
||||
CalculationType const s2x = get<0>(s2);
|
||||
|
||||
bool const in_horizontal_range = s1x < s2x ? (px >= s1x && px <= s2x) : (px >= s2x && px <= s1x);
|
||||
|
||||
bool const vertical = s1x == s2x;
|
||||
|
||||
if (in_horizontal_range || (vertical && is_in_vertical_range(point, s1, s2)))
|
||||
{
|
||||
if (side == 0)
|
||||
{
|
||||
apply_on_boundary(point, s1, s2, place_on_ring, the_state);
|
||||
}
|
||||
#if defined(BOOST_GEOMETRY_USE_RESCALING)
|
||||
else if (side == -1)
|
||||
{
|
||||
auto const line = detail::make::make_infinite_line<CalculationType>(s1, s2);
|
||||
auto const value = -arithmetic::side_value(line, point);
|
||||
if (value > 0 && value < the_state.inside_min_measure) { the_state.inside_min_measure = value; }
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (in_horizontal_range)
|
||||
{
|
||||
auto const on_boundary = the_state.count_on_offsetted + the_state.count_on_edge + the_state.count_on_origin;
|
||||
if (on_boundary == 0)
|
||||
{
|
||||
// Use only absolute comparisons, because the ring is continuous -
|
||||
// what was missed is there earlier or later, and turns should
|
||||
// not be counted twice (which can happen if an epsilon is used).
|
||||
bool const eq1 = s1x == px;
|
||||
bool const eq2 = s2x == px;
|
||||
|
||||
// Account for 1 or 2 for left side (outside)
|
||||
// and for -1 or -2 for right side (inside)
|
||||
int const multiplier = eq1 || eq2 ? 1 : 2;
|
||||
|
||||
the_state.count += side * multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // DOXYGEN_NO_DETAIL
|
||||
|
||||
}} // namespace strategy::buffer
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_TURN_IN_RING_WINDING_HPP
|
||||
|
||||
Reference in New Issue
Block a user