add boost on mac

This commit is contained in:
Bassem Girgis
2019-08-10 16:38:17 -05:00
parent 861b918727
commit be945cb63b
14105 changed files with 2714968 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 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.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_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>
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
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_HPP

View File

@@ -0,0 +1,29 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2016, 2017.
// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_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>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP

View File

@@ -0,0 +1,51 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2016-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)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/azimuth.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace azimuth
{
template
<
typename CalculationType = void
>
class cartesian
{};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<cartesian_tag, CalculationType>
{
typedef strategy::azimuth::cartesian<CalculationType> type;
};
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::azimuth
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP

View File

@@ -0,0 +1,311 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// 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.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
namespace boost { namespace geometry { namespace strategy
{
namespace within
{
struct box_within_coord
{
template <typename BoxContainedValue, typename BoxContainingValue>
static inline bool apply(BoxContainedValue const& bed_min,
BoxContainedValue const& bed_max,
BoxContainingValue const& bing_min,
BoxContainingValue const& bing_max)
{
return bing_min <= bed_min && bed_max <= bing_max // contained in containing
&& bed_min < bed_max; // interiors overlap
}
};
struct box_covered_by_coord
{
template <typename BoxContainedValue, typename BoxContainingValue>
static inline bool apply(BoxContainedValue const& bed_min,
BoxContainedValue const& bed_max,
BoxContainingValue const& bing_min,
BoxContainingValue const& bing_max)
{
return bed_min >= bing_min && bed_max <= bing_max;
}
};
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>
static inline bool apply(CalcT const& diff_ed)
{
return diff_ed > CalcT(0);
}
};
struct box_covered_by_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const&)
{
return true;
}
};
template <typename Geometry,
typename CoordCheck,
typename InteriorCheck>
struct box_longitude_range
{
template <typename BoxContainedValue, typename BoxContainingValue>
static inline bool apply(BoxContainedValue const& bed_min,
BoxContainedValue const& bed_max,
BoxContainingValue const& bing_min,
BoxContainingValue const& bing_max)
{
typedef typename select_most_precise
<
BoxContainedValue,
BoxContainingValue
>::type calc_t;
typedef typename coordinate_system<Geometry>::type::units units_t;
typedef math::detail::constants_on_spheroid<calc_t, units_t> constants;
if (CoordCheck::apply(bed_min, bed_max, bing_min, bing_max))
{
return true;
}
// 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())
{
return true;
}
// if containing is smaller it cannot contain
// and check interior (within vs covered_by)
if (diff_ing < diff_ed || ! InteriorCheck::apply(diff_ed))
{
return false;
}
// calculate positive longitude translation with bing_min as origin
calc_t const diff_min = math::longitude_distance_unsigned<units_t>(bing_min, bed_min);
// max of contained translated into the containing origin must be lesser than max of containing
return bing_min + diff_min + diff_ed <= bing_max
/*|| bing_max - diff_min - diff_ed >= bing_min*/;
}
};
// 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,
std::size_t Dimension,
std::size_t DimensionCount
>
struct relate_box_box_loop
{
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(
get<min_corner, Dimension>(b_contained),
get<max_corner, Dimension>(b_contained),
get<min_corner, Dimension>(b_containing),
get<max_corner, Dimension>(b_containing)
)
)
{
return false;
}
return relate_box_box_loop
<
SubStrategy,
Box1, Box2,
Dimension + 1, DimensionCount
>::apply(b_contained, b_containing);
}
};
template
<
template <typename, std::size_t, typename> class SubStrategy,
typename Box1,
typename Box2,
std::size_t DimensionCount
>
struct relate_box_box_loop<SubStrategy, Box1, Box2, DimensionCount, DimensionCount>
{
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
{
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
return relate_box_box_loop
<
SubStrategy,
Box1, Box2, 0, dimension<Box1>::type::value
>::apply(box1, box2);
}
};
} // namespace within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace within { namespace services
{
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
BoxContained, BoxContaining,
box_tag, box_tag,
areal_tag, areal_tag,
cartesian_tag, cartesian_tag
>
{
typedef within::box_in_box<BoxContained, BoxContaining> type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
BoxContained, BoxContaining,
box_tag, box_tag,
areal_tag, areal_tag,
spherical_tag, spherical_tag
>
{
typedef within::box_in_box<BoxContained, BoxContaining> type;
};
}} // namespace within::services
namespace covered_by { namespace services
{
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
BoxContained, BoxContaining,
box_tag, box_tag,
areal_tag, areal_tag,
cartesian_tag, cartesian_tag
>
{
typedef within::box_in_box
<
BoxContained, BoxContaining,
within::box_covered_by_range
> type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename BoxContained, typename BoxContaining>
struct default_strategy
<
BoxContained, BoxContaining,
box_tag, box_tag,
areal_tag, areal_tag,
spherical_tag, spherical_tag
>
{
typedef within::box_in_box
<
BoxContained, BoxContaining,
within::box_covered_by_range
> type;
};
}} // namespace covered_by::services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}} // namespace boost::geometry::strategy
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP

View File

@@ -0,0 +1,114 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, 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_BUFFER_END_FLAT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer create flat ends
\ingroup strategies
\details This strategy can be used as EndStrategy for the buffer algorithm.
It creates a flat end for each linestring-end. It can be applied
for (multi)linestrings. Also it is applicable for spikes in (multi)polygons.
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_end_flat]
[heading Output]
[$img/strategies/buffer_end_flat.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_end_round end_round]
}
*/
class end_flat
{
public :
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a flat end
template <typename Point, typename RangeOut, typename DistanceStrategy>
inline void apply(Point const& penultimate_point,
Point const& perp_left_point,
Point const& ultimate_point,
Point const& perp_right_point,
buffer_side_selector side,
DistanceStrategy const& distance,
RangeOut& range_out) const
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename geometry::select_most_precise
<
coordinate_type,
double
>::type promoted_type;
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);
range_out.push_back(perp_left_point);
}
else
{
range_out.push_back(perp_left_point);
range_out.push_back(perp_right_point);
}
// 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
}
template <typename NumericType>
static inline NumericType max_distance(NumericType const& distance)
{
return distance;
}
//! Returns the piece_type (flat end)
static inline piece_type get_piece_type()
{
return buffered_flat_end;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_FLAT_HPP

View File

@@ -0,0 +1,178 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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.
// Contributed and/or modified by Menelaos Karavelas, 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_BUFFER_END_ROUND_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer create rounded ends
\ingroup strategies
\details This strategy can be used as EndStrategy for the buffer algorithm.
It creates a rounded end for each linestring-end. It can be applied
for (multi)linestrings. Also it is applicable for spikes in (multi)polygons.
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_end_round]
[heading Output]
[$img/strategies/buffer_end_round.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_end_flat end_flat]
}
*/
class end_round
{
private :
std::size_t m_points_per_circle;
template
<
typename Point,
typename PromotedType,
typename DistanceType,
typename RangeOut
>
inline void generate_points(Point const& point,
PromotedType alpha, // by value
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
PromotedType const two_pi = geometry::math::two_pi<PromotedType>();
std::size_t point_buffer_count = m_points_per_circle;
PromotedType const diff = two_pi / PromotedType(point_buffer_count);
// For half circle:
point_buffer_count /= 2;
point_buffer_count++;
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));
range_out.push_back(p);
}
}
template <typename T, typename P1, typename P2>
static inline T calculate_angle(P1 const& from_point, P2 const& to_point)
{
typedef P1 vector_type;
vector_type v = from_point;
geometry::subtract_point(v, to_point);
return atan2(geometry::get<1>(v), geometry::get<0>(v));
}
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)
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a flat end
template <typename Point, typename RangeOut, typename DistanceStrategy>
inline void apply(Point const& penultimate_point,
Point const& perp_left_point,
Point const& ultimate_point,
Point const& perp_right_point,
buffer_side_selector side,
DistanceStrategy const& distance,
RangeOut& range_out) const
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename geometry::select_most_precise
<
coordinate_type,
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);
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;
}
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);
}
if (m_points_per_circle % 2 == 1)
{
// For a half circle, if the number of points is not even,
// we should insert the end point too, to generate a full cap
range_out.push_back(perp_right_point);
}
}
template <typename NumericType>
static inline NumericType max_distance(NumericType const& distance)
{
return distance;
}
//! Returns the piece_type (flat end)
static inline piece_type get_piece_type()
{
return buffered_round_end;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP

View File

@@ -0,0 +1,142 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/buffer.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer create sharp corners
\ingroup strategies
\details This strategy can be used as JoinStrategy for the buffer algorithm.
It creates a sharp corners around each convex vertex. It can be applied
for (multi)linestrings and (multi)polygons.
If corners are sharp by themselves, the miters might become very long. Therefore
there is a limit (miter_limit), in terms of the used distance, which limits
their length. The miter is not changed to a bevel form (as done in some
other software), it is just adapted to the specified miter_limit but keeps
its miter form.
If the buffer distance is 5.0, and the miter limit is 2.0, generated points
will be located at a distance of at most 10.0 (2*5) units.
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_join_miter]
[heading Output]
[$img/strategies/buffer_join_miter.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_join_round join_round]
}
*/
class join_miter
{
public:
//! \brief Constructs the strategy
//! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
explicit inline join_miter(double miter_limit = 5.0)
: m_miter_limit(valid_limit(miter_limit))
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a sharp shape around a vertex
template <typename Point, typename DistanceType, typename RangeOut>
inline bool apply(Point const& ip, Point const& vertex,
Point const& perp1, Point const& perp2,
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
geometry::equal_to<Point> equals;
if (equals(ip, vertex))
{
return false;
}
if (equals(perp1, perp2))
{
return false;
}
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename geometry::select_most_precise
<
coordinate_type,
double
>::type promoted_type;
Point p = ip;
// 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 distance = geometry::math::sqrt(dx * dx + dy * dy);
promoted_type const max_distance
= m_miter_limit * geometry::math::abs(buffer_distance);
if (distance > max_distance)
{
BOOST_GEOMETRY_ASSERT(distance != 0.0);
promoted_type const proportion = max_distance / distance;
set<0>(p, get<0>(vertex) + dx * proportion);
set<1>(p, get<1>(vertex) + dy * proportion);
}
range_out.push_back(perp1);
range_out.push_back(p);
range_out.push_back(perp2);
return true;
}
template <typename NumericType>
inline NumericType max_distance(NumericType const& distance) const
{
return distance * m_miter_limit;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
private :
double valid_limit(double miter_limit) const
{
if (miter_limit < 1.0)
{
// It should always exceed the buffer distance
miter_limit = 1.0;
}
return miter_limit;
}
double m_miter_limit;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP

View File

@@ -0,0 +1,187 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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.
// Contributed and/or modified by Menelaos Karavelas, 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_BUFFER_JOIN_ROUND_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
#include <algorithm>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
#include <iostream>
#include <boost/geometry/io/wkt/wkt.hpp>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer create rounded corners
\ingroup strategies
\details This strategy can be used as JoinStrategy for the buffer algorithm.
It creates a rounded corners around each convex vertex. It can be applied
for (multi)linestrings and (multi)polygons.
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_join_round]
[heading Output]
[$img/strategies/buffer_join_round.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_join_miter join_miter]
}
*/
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)
{}
private :
template
<
typename PromotedType,
typename Point,
typename DistanceType,
typename RangeOut
>
inline void generate_points(Point const& vertex,
Point const& perp1, Point const& perp2,
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
PromotedType const dx1 = get<0>(perp1) - get<0>(vertex);
PromotedType const dy1 = get<1>(perp1) - get<1>(vertex);
PromotedType const dx2 = get<0>(perp2) - get<0>(vertex);
PromotedType const dy2 = get<1>(perp2) - get<1>(vertex);
PromotedType const two_pi = geometry::math::two_pi<PromotedType>();
PromotedType const angle1 = atan2(dy1, dx1);
PromotedType angle2 = atan2(dy2, dx2);
while (angle2 > angle1)
{
angle2 -= two_pi;
}
PromotedType const angle_diff = angle1 - angle2;
// Divide the angle into an integer amount of steps to make it
// visually correct also for a low number of points / circle
// If a full circle is divided into 3 parts (e.g. angle is 125),
// the one point in between must still be generated
// The calculation below:
// - generates 1 point in between for an angle of 125 based on 3 points
// - generates 0 points in between for an angle of 90 based on 4 points
std::size_t const n = (std::max)(static_cast<std::size_t>(
ceil(m_points_per_circle * angle_diff / two_pi)), std::size_t(1));
PromotedType const diff = angle_diff / static_cast<PromotedType>(n);
PromotedType a = angle1 - diff;
// Walk to n - 1 to avoid generating the last point
for (std::size_t i = 0; i < n - 1; i++, a -= diff)
{
Point p;
set<0>(p, get<0>(vertex) + buffer_distance * cos(a));
set<1>(p, get<1>(vertex) + buffer_distance * sin(a));
range_out.push_back(p);
}
}
public :
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a rounded shape around a vertex
template <typename Point, typename DistanceType, typename RangeOut>
inline bool apply(Point const& ip, Point const& vertex,
Point const& perp1, Point const& perp2,
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename boost::range_value<RangeOut>::type output_point_type;
typedef typename geometry::select_most_precise
<
typename geometry::select_most_precise
<
coordinate_type,
typename geometry::coordinate_type<output_point_type>::type
>::type,
double
>::type promoted_type;
geometry::equal_to<Point> equals;
if (equals(perp1, perp2))
{
#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);
range_out.push_back(perp2);
return true;
}
template <typename NumericType>
static inline NumericType max_distance(NumericType const& distance)
{
return distance;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
private :
std::size_t m_points_per_circle;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP

View File

@@ -0,0 +1,154 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
#include <boost/geometry/io/wkt/wkt.hpp>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
class join_round_by_divide
{
public :
inline join_round_by_divide(std::size_t max_level = 4)
: m_max_level(max_level)
{}
template
<
typename PromotedType,
typename Point,
typename DistanceType,
typename RangeOut
>
inline void mid_points(Point const& vertex,
Point const& p1, Point const& p2,
DistanceType const& buffer_distance,
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);
coordinate_type const vp2_x = (get<0>(p2) - get<0>(vertex));
coordinate_type 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 length2 = geometry::math::sqrt(v_x * v_x + v_y * v_y);
PromotedType prop = buffer_distance / length2;
Point mid_point;
set<0>(mid_point, get<0>(vertex) + v_x * prop);
set<1>(mid_point, get<1>(vertex) + v_y * prop);
if (level < m_max_level)
{
mid_points<PromotedType>(vertex, p1, mid_point, buffer_distance, range_out, level + 1);
}
range_out.push_back(mid_point);
if (level < m_max_level)
{
mid_points<PromotedType>(vertex, mid_point, p2, buffer_distance, range_out, level + 1);
}
}
template <typename Point, typename DistanceType, typename RangeOut>
inline bool apply(Point const& ip, Point const& vertex,
Point const& perp1, Point const& perp2,
DistanceType const& buffer_distance,
RangeOut& range_out) const
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename geometry::select_most_precise
<
coordinate_type,
double
>::type promoted_type;
geometry::equal_to<Point> equals;
if (equals(perp1, perp2))
{
#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 const vix = (get<0>(ip) - get<0>(vertex));
coordinate_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;
Point bp;
set<0>(bp, get<0>(vertex) + vix * prop);
set<1>(bp, get<1>(vertex) + viy * prop);
range_out.push_back(perp1);
if (m_max_level > 1)
{
mid_points<promoted_type>(vertex, perp1, bp, bd, range_out);
range_out.push_back(bp);
mid_points<promoted_type>(vertex, bp, perp2, bd, range_out);
}
else if (m_max_level == 1)
{
range_out.push_back(bp);
}
range_out.push_back(perp2);
return true;
}
template <typename NumericType>
static inline NumericType max_distance(NumericType const& distance)
{
return distance;
}
private :
std::size_t m_max_level;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_BY_DIVIDE_HPP

View File

@@ -0,0 +1,120 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015, 2018.
// Modifications copyright (c) 2015, 2018, 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
// 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_BUFFER_POINT_CIRCLE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_CIRCLE_HPP
#include <cstddef>
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Create a circular buffer around a point
\ingroup strategies
\details This strategy can be used as PointStrategy for the buffer algorithm.
It creates a circular buffer around a point. It can be applied
for points and multi_points, but also for a linestring (if it is degenerate,
so consisting of only one point) and for polygons (if it is degenerate).
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_point_circle]
[heading Output]
[$img/strategies/buffer_point_circle.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_point_square point_square]
\* [link geometry.reference.strategies.strategy_buffer_geographic_point_circle geographic_point_circle]
}
*/
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)
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a circle around point using distance_strategy
template
<
typename Point,
typename OutputRange,
typename DistanceStrategy
>
inline void apply(Point const& point,
DistanceStrategy const& distance_strategy,
OutputRange& output_range) const
{
typedef typename boost::range_value<OutputRange>::type output_point_type;
typedef typename geometry::select_most_precise
<
typename geometry::select_most_precise
<
typename geometry::coordinate_type<Point>::type,
typename geometry::coordinate_type<output_point_type>::type
>::type,
double
>::type promoted_type;
promoted_type const buffer_distance = distance_strategy.apply(point, point,
strategy::buffer::buffer_side_left);
promoted_type const two_pi = geometry::math::two_pi<promoted_type>();
promoted_type const diff = two_pi / promoted_type(m_count);
promoted_type a = 0;
for (std::size_t i = 0; i < m_count; i++, a -= diff)
{
output_point_type p;
set<0>(p, get<0>(point) + buffer_distance * cos(a));
set<1>(p, get<1>(point) + buffer_distance * sin(a));
output_range.push_back(p);
}
// Close it:
output_range.push_back(output_range.front());
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
private :
std::size_t m_count;
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_CIRCLE_HPP

View File

@@ -0,0 +1,116 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, 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_BUFFER_POINT_SQUARE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_SQUARE_HPP
#include <cstddef>
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Create a squared form buffer around a point
\ingroup strategies
\details This strategy can be used as PointStrategy for the buffer algorithm.
It creates a square from each point, where the point lies in the center.
It can be applied for points and multi_points, but also for a linestring (if it is degenerate,
so consisting of only one point) and for polygons (if it is degenerate).
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
[heading Example]
[buffer_point_square]
[heading Output]
[$img/strategies/buffer_point_square.png]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
\* [link geometry.reference.strategies.strategy_buffer_point_circle point_circle]
\* [link geometry.reference.strategies.strategy_buffer_geographic_point_circle geographic_point_circle]
}
*/
class point_square
{
template
<
typename Point,
typename DistanceType,
typename OutputRange
>
inline void add_point(Point const& point,
DistanceType const& distance,
DistanceType const& x,
DistanceType const& y,
OutputRange& output_range) const
{
typename boost::range_value<OutputRange>::type p;
set<0>(p, get<0>(point) + x * distance);
set<1>(p, get<1>(point) + y * distance);
output_range.push_back(p);
}
template
<
typename Point,
typename DistanceType,
typename OutputRange
>
inline void add_points(Point const& point,
DistanceType const& distance,
OutputRange& output_range) const
{
add_point(point, distance, -1.0, -1.0, output_range);
add_point(point, distance, -1.0, +1.0, output_range);
add_point(point, distance, +1.0, +1.0, output_range);
add_point(point, distance, +1.0, -1.0, output_range);
// Close it:
output_range.push_back(output_range.front());
}
public :
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a square around point using distance_strategy
template
<
typename Point,
typename DistanceStrategy,
typename OutputRange
>
inline void apply(Point const& point,
DistanceStrategy const& distance_strategy,
OutputRange& output_range) const
{
add_points(point, distance_strategy.apply(point, point,
strategy::buffer::buffer_side_left), output_range);
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_POINT_SQUARE_HPP

View File

@@ -0,0 +1,136 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SIDE_STRAIGHT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SIDE_STRAIGHT_HPP
#include <cstddef>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/strategies/side.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace buffer
{
/*!
\brief Let the buffer use straight sides along segments (the default)
\ingroup strategies
\details This strategy can be used as SideStrategy for the buffer algorithm.
It is currently the only provided strategy for this purpose
\qbk{
[heading Example]
See the examples for other buffer strategies\, for example
[link geometry.reference.strategies.strategy_buffer_join_round join_round]
[heading See also]
\* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
}
*/
class side_straight
{
public :
#ifndef DOXYGEN_SHOULD_SKIP_THIS
template
<
typename Point,
typename OutputRange,
typename DistanceStrategy
>
static inline result_code apply(
Point const& input_p1, Point const& input_p2,
buffer_side_selector side,
DistanceStrategy const& distance,
OutputRange& output_range)
{
typedef typename coordinate_type<Point>::type coordinate_type;
typedef typename geometry::select_most_precise
<
coordinate_type,
double
>::type promoted_type;
// 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);
// For normalization [0,1] (=dot product d.d, sqrt)
promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy);
if (! boost::math::isfinite(length))
{
// In case of coordinates differences of e.g. 1e300, length
// will overflow and we should not generate output
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
std::cout << "Error in length calculation for points "
<< geometry::wkt(input_p1) << " " << geometry::wkt(input_p2)
<< " length: " << length << std::endl;
#endif
return result_error_numerical;
}
if (geometry::math::equals(length, 0))
{
// Coordinates are simplified and therefore most often not equal.
// But if simplify is skipped, or for lines with two
// equal points, length is 0 and we cannot generate output.
return result_no_output;
}
promoted_type const d = distance.apply(input_p1, input_p2, side);
// Generate the normalized perpendicular p, to the left (ccw)
promoted_type const px = -dy / length;
promoted_type const py = dx / length;
if (geometry::math::equals(px, 0)
&& geometry::math::equals(py, 0))
{
// This basically should not occur - because of the checks above.
// There are no unit tests triggering this condition
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
std::cout << "Error in perpendicular calculation for points "
<< geometry::wkt(input_p1) << " " << geometry::wkt(input_p2)
<< " length: " << length
<< " distance: " << d
<< std::endl;
#endif
return result_no_output;
}
output_range.resize(2);
set<0>(output_range.front(), get<0>(input_p1) + px * d);
set<1>(output_range.front(), get<1>(input_p1) + py * d);
set<0>(output_range.back(), get<0>(input_p2) + px * d);
set<1>(output_range.back(), get<1>(input_p2) + py * d);
return result_normal;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
};
}} // namespace strategy::buffer
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_SIDE_STRAIGHT_HPP

View File

@@ -0,0 +1,128 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
#include <cstddef>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/strategies/centroid.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace centroid
{
/*!
\brief Centroid calculation taking average of points
\ingroup strategies
*/
template
<
typename PointCentroid,
typename Point = PointCentroid
>
class average
{
private :
/*! subclass to keep state */
class sum
{
friend class average;
signed_size_type count;
PointCentroid centroid;
public :
inline sum()
: count(0)
{
assign_zero(centroid);
}
};
public :
typedef sum state_type;
typedef PointCentroid centroid_point_type;
typedef Point point_type;
static inline void apply(Point const& p, sum& state)
{
add_point(state.centroid, p);
state.count++;
}
static inline bool result(sum const& state, PointCentroid& centroid)
{
centroid = state.centroid;
if ( state.count > 0 )
{
divide_value(centroid, state.count);
return true;
}
return false;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point, std::size_t DimensionCount, typename Geometry>
struct default_strategy
<
cartesian_tag,
pointlike_tag,
DimensionCount,
Point,
Geometry
>
{
typedef average
<
Point,
typename point_type<Geometry>::type
> type;
};
} // namespace services
#endif
}} // namespace strategy::centroid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP

View File

@@ -0,0 +1,259 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015, 2018.
// Modifications copyright (c) 2015, 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
#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>
namespace boost { namespace geometry
{
// Note: when calling the namespace "centroid", it sometimes,
// somehow, in gcc, gives compilation problems (confusion with function centroid).
namespace strategy { namespace centroid
{
/*!
\brief Centroid calculation using algorithm Bashein / Detmer
\ingroup strategies
\details Calculates centroid using triangulation method published by
Bashein / Detmer
\tparam Point point type of centroid to calculate
\tparam PointOfSegment point type of segments, defaults to Point
\tparam CalculationType \tparam_calculation
\author Adapted from "Centroid of a Polygon" by
Gerard Bashein and Paul R. Detmer<em>,
in "Graphics Gems IV", Academic Press, 1994</em>
\qbk{
[heading See also]
[link geometry.reference.algorithms.centroid.centroid_3_with_strategy centroid (with strategy)]
}
*/
/*
\par Research notes
The algorithm gives the same results as Oracle and PostGIS but
differs from MySQL
(tried 5.0.21 / 5.0.45 / 5.0.51a / 5.1.23).
Without holes:
- this: POINT(4.06923363095238 1.65055803571429)
- geolib: POINT(4.07254 1.66819)
- MySQL: POINT(3.6636363636364 1.6272727272727)'
- PostGIS: POINT(4.06923363095238 1.65055803571429)
- Oracle: 4.06923363095238 1.65055803571429
- SQL Server: POINT(4.06923362245959 1.65055804168294)
Statements:
- \b MySQL/PostGIS: select AsText(Centroid(GeomFromText(
'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6
,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))')))
- \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null,
sdo_elem_info_array(1, 1003, 1), sdo_ordinate_array(
2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,2,4.1,3,5.3,2.6
,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3))
, mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)
,mdsys.sdo_dim_element('y',0,10,.00000005)))
from dual
- \b SQL Server 2008: select geometry::STGeomFromText(
'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6
,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))',0)
.STCentroid()
.STAsText()
With holes:
- this: POINT(4.04663 1.6349)
- geolib: POINT(4.04675 1.65735)
- MySQL: POINT(3.6090580503834 1.607573932092)
- PostGIS: POINT(4.0466265060241 1.63489959839357)
- Oracle: 4.0466265060241 1.63489959839357
- SQL Server: POINT(4.0466264962959677 1.6348996057331333)
Statements:
- \b MySQL/PostGIS: select AsText(Centroid(GeomFromText(
'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2
,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3)
,(4 2,4.2 1.4,4.8 1.9,4.4 2.2,4 2))')));
- \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null
, sdo_elem_info_array(1, 1003, 1, 25, 2003, 1)
, sdo_ordinate_array(2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,
2,4.1,3,5.3,2.6,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3,4,2, 4.2,1.4,
4.8,1.9, 4.4,2.2, 4,2))
, mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)
,mdsys.sdo_dim_element('y',0,10,.00000005)))
from dual
*/
template
<
typename Point,
typename PointOfSegment = Point,
typename CalculationType = void
>
class bashein_detmer
{
private :
// If user specified a calculation type, use that type,
// 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
<
typename select_coordinate_type
<
Point,
PointOfSegment
>::type,
double
>::type,
CalculationType
>::type calculation_type;
/*! subclass to keep state */
class sums
{
friend class bashein_detmer;
std::size_t count;
calculation_type sum_a2;
calculation_type sum_x;
calculation_type sum_y;
public :
inline sums()
: count(0)
, sum_a2(calculation_type())
, sum_x(calculation_type())
, sum_y(calculation_type())
{}
};
public :
typedef sums state_type;
static inline void apply(PointOfSegment const& p1,
PointOfSegment const& p2, sums& state)
{
/* Algorithm:
For each segment:
begin
ai = x1 * y2 - x2 * y1;
sum_a2 += ai;
sum_x += ai * (x1 + x2);
sum_y += ai * (y1 + y2);
end
return POINT(sum_x / (3 * sum_a2), sum_y / (3 * sum_a2) )
*/
// 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);
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)
{
calculation_type const zero = calculation_type();
if (state.count > 0 && ! math::equals(state.sum_a2, zero))
{
calculation_type const v3 = 3;
calculation_type const a3 = v3 * state.sum_a2;
typedef typename geometry::coordinate_type
<
Point
>::type coordinate_type;
// Prevent NaN centroid coordinates
if (boost::math::isfinite(a3))
{
// NOTE: above calculation_type is checked, not the centroid coordinate_type
// which means that the centroid can still be filled with INF
// if e.g. calculation_type is double and centroid contains floats
set<0>(centroid,
boost::numeric_cast<coordinate_type>(state.sum_x / a3));
set<1>(centroid,
boost::numeric_cast<coordinate_type>(state.sum_y / a3));
return true;
}
}
return false;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
// Register this strategy for rings and (multi)polygons, in two dimensions
template <typename Point, typename Geometry>
struct default_strategy<cartesian_tag, areal_tag, 2, Point, Geometry>
{
typedef bashein_detmer
<
Point,
typename point_type<Geometry>::type
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::centroid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP

View File

@@ -0,0 +1,174 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
#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/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>
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
>
class weighted_length
{
private :
typedef typename select_most_precise
<
typename default_distance_result<Point>::type,
typename default_distance_result<PointOfSegment>::type
>::type distance_type;
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)
{
distance_type const d = geometry::distance(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);
}
static inline bool result(state_type const& state, Point& centroid)
{
distance_type const zero = distance_type();
if (! geometry::math::equals(state.length, zero)
&& boost::math::isfinite(state.length)) // Prevent NaN centroid coordinates
{
// 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));
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
namespace services
{
// Register this strategy for linear geometries, in all dimensions
template <std::size_t N, typename Point, typename Geometry>
struct default_strategy
<
cartesian_tag,
linear_tag,
N,
Point,
Geometry
>
{
typedef weighted_length
<
Point,
typename point_type<Geometry>::type
> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::centroid
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP

View File

@@ -0,0 +1,134 @@
// Boost.Geometry
// Copyright (c) 2017-2018, 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_DENSIFY_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DENSIFY_HPP
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/strategies/densify.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace densify
{
/*!
\brief Densification of cartesian segment.
\ingroup strategies
\tparam CalculationType \tparam_calculation
\qbk{
[heading See also]
[link geometry.reference.algorithms.densify.densify_4_with_strategy densify (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class cartesian
{
public:
template <typename Point, typename AssignPolicy, typename T>
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 select_most_precise
<
typename coordinate_type<Point>::type,
typename coordinate_type<out_point_t>::type,
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);
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);
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)
{
// pd = xy0 + d * dir01
calc_point_t pd = dir01;
// 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);
// 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);
}
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef strategy::densify::cartesian<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::densify
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DENSIFY_HPP

View File

@@ -0,0 +1,112 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2018.
// Modifications copyright (c) 2013-2018, 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_BOX_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_BOX_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/strategies/disjoint.hpp>
namespace boost { namespace geometry { namespace strategy { namespace disjoint
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
<
typename Box1, typename Box2,
std::size_t Dimension = 0,
std::size_t DimensionCount = dimension<Box1>::value
>
struct box_box
{
static inline bool apply(Box1 const& box1, Box2 const& box2)
{
if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))
{
return true;
}
if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2))
{
return true;
}
return box_box
<
Box1, Box2,
Dimension + 1, DimensionCount
>::apply(box1, box2);
}
};
template <typename Box1, typename Box2, std::size_t DimensionCount>
struct box_box<Box1, Box2, DimensionCount, DimensionCount>
{
static inline bool apply(Box1 const& , Box2 const& )
{
return false;
}
};
} // 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 detail::box_box<Box1, Box2>::apply(box1, box2);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Box1, typename Box2, int TopDim1, int TopDim2>
struct default_strategy<Box1, Box2, box_tag, box_tag, TopDim1, TopDim2, cartesian_tag, cartesian_tag>
{
typedef disjoint::cartesian_box_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}}} // namespace boost::geometry::strategy::disjoint
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_BOX_BOX_HPP

View File

@@ -0,0 +1,319 @@
// Boost.Geometry
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// 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.
// 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
// 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_DISJOINT_SEGMENT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP
#include <cstddef>
#include <utility>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/calculation_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry { namespace strategy { namespace disjoint
{
namespace detail
{
template <std::size_t I>
struct compute_tmin_tmax_per_dim
{
template <typename SegmentPoint, typename Box, typename RelativeDistance>
static inline void apply(SegmentPoint const& p0,
SegmentPoint const& p1,
Box const& box,
RelativeDistance& ti_min,
RelativeDistance& ti_max,
RelativeDistance& diff)
{
typedef typename coordinate_type<Box>::type box_coordinate_type;
typedef typename coordinate_type
<
SegmentPoint
>::type point_coordinate_type;
RelativeDistance c_p0 = boost::numeric_cast
<
point_coordinate_type
>( geometry::get<I>(p0) );
RelativeDistance c_p1 = boost::numeric_cast
<
point_coordinate_type
>( geometry::get<I>(p1) );
RelativeDistance c_b_min = boost::numeric_cast
<
box_coordinate_type
>( geometry::get<geometry::min_corner, I>(box) );
RelativeDistance c_b_max = boost::numeric_cast
<
box_coordinate_type
>( geometry::get<geometry::max_corner, I>(box) );
if ( geometry::get<I>(p1) >= geometry::get<I>(p0) )
{
diff = c_p1 - c_p0;
ti_min = c_b_min - c_p0;
ti_max = c_b_max - c_p0;
}
else
{
diff = c_p0 - c_p1;
ti_min = c_p0 - c_b_max;
ti_max = c_p0 - c_b_min;
}
}
};
template
<
typename RelativeDistance,
typename SegmentPoint,
typename Box,
std::size_t I,
std::size_t Dimension
>
struct disjoint_segment_box_impl
{
template <typename RelativeDistancePair>
static inline bool apply(SegmentPoint const& p0,
SegmentPoint const& p1,
Box const& box,
RelativeDistancePair& t_min,
RelativeDistancePair& t_max)
{
RelativeDistance ti_min, ti_max, diff;
compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff);
if ( geometry::math::equals(diff, 0) )
{
if ( (geometry::math::equals(t_min.second, 0)
&& t_min.first > ti_max)
||
(geometry::math::equals(t_max.second, 0)
&& t_max.first < ti_min)
||
(math::sign(ti_min) * math::sign(ti_max) > 0) )
{
return true;
}
}
RelativeDistance t_min_x_diff = t_min.first * diff;
RelativeDistance t_max_x_diff = t_max.first * diff;
if ( t_min_x_diff > ti_max * t_min.second
|| t_max_x_diff < ti_min * t_max.second )
{
return true;
}
if ( ti_min * t_min.second > t_min_x_diff )
{
t_min.first = ti_min;
t_min.second = diff;
}
if ( ti_max * t_max.second < t_max_x_diff )
{
t_max.first = ti_max;
t_max.second = diff;
}
if ( t_min.first > t_min.second || t_max.first < 0 )
{
return true;
}
return disjoint_segment_box_impl
<
RelativeDistance,
SegmentPoint,
Box,
I + 1,
Dimension
>::apply(p0, p1, box, t_min, t_max);
}
};
template
<
typename RelativeDistance,
typename SegmentPoint,
typename Box,
std::size_t Dimension
>
struct disjoint_segment_box_impl
<
RelativeDistance, SegmentPoint, Box, 0, Dimension
>
{
static inline bool apply(SegmentPoint const& p0,
SegmentPoint const& p1,
Box const& box)
{
std::pair<RelativeDistance, RelativeDistance> t_min, t_max;
RelativeDistance diff;
compute_tmin_tmax_per_dim<0>::apply(p0, p1, box,
t_min.first, t_max.first, diff);
if ( geometry::math::equals(diff, 0) )
{
if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
{
return true;
}
}
if ( t_min.first > diff || t_max.first < 0 )
{
return true;
}
t_min.second = t_max.second = diff;
return disjoint_segment_box_impl
<
RelativeDistance, SegmentPoint, Box, 1, Dimension
>::apply(p0, p1, box, t_min, t_max);
}
};
template
<
typename RelativeDistance,
typename SegmentPoint,
typename Box,
std::size_t Dimension
>
struct disjoint_segment_box_impl
<
RelativeDistance, SegmentPoint, Box, Dimension, Dimension
>
{
template <typename RelativeDistancePair>
static inline bool apply(SegmentPoint const&, SegmentPoint const&,
Box const&,
RelativeDistancePair&, RelativeDistancePair&)
{
return false;
}
};
} // namespace detail
// NOTE: This may be temporary place for this or corresponding strategy
// It seems to be more appropriate to implement the opposite of it
// e.g. intersection::segment_box because in disjoint() algorithm
// 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
>
{};
template <typename Segment, typename Box>
static inline typename point_in_geometry_strategy<Segment, Box>::type
get_point_in_geometry_strategy()
{
typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
return strategy_type();
}
template <typename Segment, typename Box>
static inline bool apply(Segment const& segment, Box const& box)
{
assert_dimension_equal<Segment, Box>();
typedef typename util::calculation_type::geometric::binary
<
Segment, Box, void
>::type relative_distance_type;
typedef typename point_type<Segment>::type segment_point_type;
segment_point_type p0, p1;
geometry::detail::assign_point_from_index<0>(segment, p0);
geometry::detail::assign_point_from_index<1>(segment, p1);
return detail::disjoint_segment_box_impl
<
relative_distance_type, segment_point_type, Box,
0, dimension<Box>::value
>::apply(p0, p1, box);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Linear, typename Box, typename LinearTag>
struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2, cartesian_tag, cartesian_tag>
{
typedef disjoint::segment_box type;
};
template <typename Box, typename Linear, typename LinearTag>
struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1, cartesian_tag, cartesian_tag>
{
typedef disjoint::segment_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}}}} // namespace boost::geometry::strategy::disjoint
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP

View File

@@ -0,0 +1,288 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// 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.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
#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>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#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/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
// Helper geometry (projected point on line)
#include <boost/geometry/geometries/point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
/*!
\brief Strategy for distance point to segment
\ingroup strategies
\details Calculates distance using projected-point method, and (optionally) Pythagoras
\author Adapted from: http://geometryalgorithms.com/Archive/algorithm_0102/algorithm_0102.htm
\tparam CalculationType \tparam_calculation
\tparam Strategy underlying point-point distance strategy
\par Concepts for Strategy:
- cartesian_distance operator(Point,Point)
\note If the Strategy is a "comparable::pythagoras", this strategy
automatically is a comparable projected_point strategy (so without sqrt)
\qbk{
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename CalculationType = void,
typename Strategy = pythagoras<CalculationType>
>
class projected_point
{
public :
typedef within::cartesian_point_point equals_point_point_strategy_type;
// 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 strategy::distance::services::return_type
<
Strategy,
Point,
PointOfSegment
>::type
>
{};
template <typename Point, typename PointOfSegment>
inline typename calculation_type<Point, PointOfSegment>::type
apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
{
assert_dimension_equal<Point, PointOfSegment>();
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;
// 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);
}
template <typename CT>
inline CT vertical_or_meridian(CT const& lat1, CT const& lat2) const
{
return lat1 - lat2;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType, typename Strategy>
struct tag<projected_point<CalculationType, Strategy> >
{
typedef strategy_tag_distance_point_segment type;
};
template <typename CalculationType, typename Strategy, typename P, typename PS>
struct return_type<projected_point<CalculationType, Strategy>, P, PS>
: projected_point<CalculationType, Strategy>::template calculation_type<P, PS>
{};
template <typename CalculationType, typename Strategy>
struct comparable_type<projected_point<CalculationType, Strategy> >
{
// Define a projected_point strategy with its underlying point-point-strategy
// being comparable
typedef projected_point
<
CalculationType,
typename comparable_type<Strategy>::type
> type;
};
template <typename CalculationType, typename Strategy>
struct get_comparable<projected_point<CalculationType, Strategy> >
{
typedef typename comparable_type
<
projected_point<CalculationType, Strategy>
>::type comparable_type;
public :
static inline comparable_type apply(projected_point<CalculationType, Strategy> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Strategy, typename P, typename PS>
struct result_from_distance<projected_point<CalculationType, Strategy>, P, PS>
{
private :
typedef typename return_type<projected_point<CalculationType, Strategy>, P, PS>::type return_type;
public :
template <typename T>
static inline return_type apply(projected_point<CalculationType, Strategy> const& , T const& value)
{
Strategy s;
return result_from_distance<Strategy, P, PS>::apply(s, value);
}
};
// Get default-strategy for point-segment distance calculation
// while still have the possibility to specify point-point distance strategy (PPS)
// It is used in algorithms/distance.hpp where users specify PPS for distance
// of point-to-segment or point-to-linestring.
// Convenient for geographic coordinate systems especially.
template <typename Point, typename PointOfSegment, typename Strategy>
struct default_strategy
<
point_tag, segment_tag, Point, PointOfSegment,
cartesian_tag, cartesian_tag, 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;
};
template <typename PointOfSegment, typename Point, typename Strategy>
struct default_strategy
<
segment_tag, point_tag, PointOfSegment, Point,
cartesian_tag, cartesian_tag, Strategy
>
{
typedef typename default_strategy
<
point_tag, segment_tag, Point, PointOfSegment,
cartesian_tag, cartesian_tag, Strategy
>::type type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP

View File

@@ -0,0 +1,315 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// 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.
// Modifications copyright (c) 2014, 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_AX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_AX_HPP
#include <algorithm>
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/arithmetic/dot_product.hpp>
#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/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
// Helper geometry (projected point on line)
#include <boost/geometry/geometries/point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename T>
struct projected_point_ax_result
{
typedef T value_type;
projected_point_ax_result(T const& c = T(0))
: atd(c), xtd(c)
{}
projected_point_ax_result(T const& a, T const& x)
: atd(a), xtd(x)
{}
friend inline bool operator<(projected_point_ax_result const& left,
projected_point_ax_result const& right)
{
return left.xtd < right.xtd || left.atd < right.atd;
}
T atd, xtd;
};
// This less-comparator may be used as a parameter of detail::douglas_peucker.
// In this simplify strategy distances are compared in 2 places
// 1. to choose the furthest candidate (md < dist)
// 2. to check if the candidate is further than max_distance (max_distance < md)
template <typename Distance>
class projected_point_ax_less
{
public:
projected_point_ax_less(Distance const& max_distance)
: m_max_distance(max_distance)
{}
inline bool operator()(Distance const& left, Distance const& right) const
{
//return left.xtd < right.xtd && right.atd < m_max_distance.atd;
typedef typename Distance::value_type value_type;
value_type const lx = left.xtd > m_max_distance.xtd ? left.xtd - m_max_distance.xtd : 0;
value_type const rx = right.xtd > m_max_distance.xtd ? right.xtd - m_max_distance.xtd : 0;
value_type const la = left.atd > m_max_distance.atd ? left.atd - m_max_distance.atd : 0;
value_type const ra = right.atd > m_max_distance.atd ? right.atd - m_max_distance.atd : 0;
value_type const l = (std::max)(lx, la);
value_type const r = (std::max)(rx, ra);
return l < r;
}
private:
Distance const& m_max_distance;
};
// This strategy returns 2-component Point/Segment distance.
// The ATD (along track distance) is parallel to the Segment
// and is a distance between Point projected into a line defined by a Segment and the nearest Segment's endpoint.
// If the projected Point intersects the Segment the ATD is equal to 0.
// The XTD (cross track distance) is perpendicular to the Segment
// and is a distance between input Point and its projection.
// If the Segment has length equal to 0, ATD and XTD has value equal
// to the distance between the input Point and one of the Segment's endpoints.
//
// p3 p4
// ^ 7
// | /
// p1<-----e========e----->p2
//
// p1: atd=D, xtd=0
// p2: atd=D, xtd=0
// p3: atd=0, xtd=D
// p4: atd=D/2, xtd=D
template
<
typename CalculationType = void,
typename Strategy = pythagoras<CalculationType>
>
class projected_point_ax
{
public :
template <typename Point, typename PointOfSegment>
struct calculation_type
: public projected_point<CalculationType, Strategy>
::template calculation_type<Point, PointOfSegment>
{};
template <typename Point, typename PointOfSegment>
struct result_type
{
typedef projected_point_ax_result
<
typename calculation_type<Point, PointOfSegment>::type
> type;
};
public :
template <typename Point, typename PointOfSegment>
inline typename result_type<Point, PointOfSegment>::type
apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
{
assert_dimension_equal<Point, PointOfSegment>();
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;
// 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);
typename result_type<Point, PointOfSegment>::type result;
calculation_type const zero = calculation_type();
calculation_type const c2 = dot_product(v, v);
if ( math::equals(c2, zero) )
{
result.xtd = strategy.apply(p, projected);
// assume that the 0-length segment is perpendicular to the Pt->ProjPt vector
result.atd = 0;
return result;
}
calculation_type const c1 = dot_product(w, v);
calculation_type const b = c1 / c2;
multiply_value(v, b);
add_point(projected, v);
result.xtd = strategy.apply(p, projected);
if (c1 <= zero)
{
result.atd = strategy.apply(p1, projected);
}
else if (c2 <= c1)
{
result.atd = strategy.apply(p2, projected);
}
else
{
result.atd = 0;
}
return result;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType, typename Strategy>
struct tag<detail::projected_point_ax<CalculationType, Strategy> >
{
typedef strategy_tag_distance_point_segment type;
};
template <typename CalculationType, typename Strategy, typename P, typename PS>
struct return_type<detail::projected_point_ax<CalculationType, Strategy>, P, PS>
{
typedef typename detail::projected_point_ax<CalculationType, Strategy>
::template result_type<P, PS>::type type;
};
template <typename CalculationType, typename Strategy>
struct comparable_type<detail::projected_point_ax<CalculationType, Strategy> >
{
// Define a projected_point strategy with its underlying point-point-strategy
// being comparable
typedef detail::projected_point_ax
<
CalculationType,
typename comparable_type<Strategy>::type
> type;
};
template <typename CalculationType, typename Strategy>
struct get_comparable<detail::projected_point_ax<CalculationType, Strategy> >
{
typedef typename comparable_type
<
detail::projected_point_ax<CalculationType, Strategy>
>::type comparable_type;
public :
static inline comparable_type apply(detail::projected_point_ax<CalculationType, Strategy> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Strategy, typename P, typename PS>
struct result_from_distance<detail::projected_point_ax<CalculationType, Strategy>, P, PS>
{
private :
typedef typename return_type<detail::projected_point_ax<CalculationType, Strategy>, P, PS>::type return_type;
public :
template <typename T>
static inline return_type apply(detail::projected_point_ax<CalculationType, Strategy> const& , T const& value)
{
Strategy s;
return_type ret;
ret.atd = result_from_distance<Strategy, P, PS>::apply(s, value.atd);
ret.xtd = result_from_distance<Strategy, P, PS>::apply(s, value.xtd);
return ret;
}
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_AX_HPP

View File

@@ -0,0 +1,295 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
// 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.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <size_t I, typename T>
struct compute_pythagoras
{
template <typename Point1, typename Point2>
static inline T apply(Point1 const& p1, Point2 const& p2)
{
T const c1 = boost::numeric_cast<T>(get<I-1>(p1));
T const c2 = boost::numeric_cast<T>(get<I-1>(p2));
T const d = c1 - c2;
return d * d + compute_pythagoras<I-1, T>::apply(p1, p2);
}
};
template <typename T>
struct compute_pythagoras<0, T>
{
template <typename Point1, typename Point2>
static inline T apply(Point1 const&, Point2 const&)
{
return boost::numeric_cast<T>(0);
}
};
}
#endif // DOXYGEN_NO_DETAIL
namespace comparable
{
/*!
\brief Strategy to calculate comparable distance between two points
\ingroup strategies
\tparam Point1 \tparam_first_point
\tparam Point2 \tparam_second_point
\tparam CalculationType \tparam_calculation
*/
template <typename CalculationType = void>
class pythagoras
{
public :
template <typename Point1, typename Point2>
struct calculation_type
: util::calculation_type::geometric::binary
<
Point1,
Point2,
CalculationType,
double,
double
>
{};
template <typename Point1, typename Point2>
static inline typename calculation_type<Point1, Point2>::type
apply(Point1 const& p1, Point2 const& p2)
{
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) );
// Calculate distance using Pythagoras
// (Leave comment above for Doxygen)
assert_dimension_equal<Point1, Point2>();
return detail::compute_pythagoras
<
dimension<Point1>::value,
typename calculation_type<Point1, Point2>::type
>::apply(p1, p2);
}
};
} // namespace comparable
/*!
\brief Strategy to calculate the distance between two points
\ingroup strategies
\tparam CalculationType \tparam_calculation
\qbk{
[heading Notes]
[note Can be used for points with two\, three or more dimensions]
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class pythagoras
{
public :
template <typename P1, typename P2>
struct calculation_type
: util::calculation_type::geometric::binary
<
P1,
P2,
CalculationType,
double,
double // promote integer to double
>
{};
/*!
\brief applies the distance calculation using pythagoras
\return the calculated distance (including taking the square root)
\param p1 first point
\param p2 second point
*/
template <typename P1, typename P2>
static inline typename calculation_type<P1, P2>::type
apply(P1 const& p1, P2 const& p2)
{
// The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call
return math::sqrt
(
boost::numeric_cast<typename calculation_type<P1, P2>::type>
(
comparable::pythagoras<CalculationType>::apply(p1, p2)
)
);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct tag<pythagoras<CalculationType> >
{
typedef strategy_tag_distance_point_point type;
};
template <typename CalculationType, typename P1, typename P2>
struct return_type<distance::pythagoras<CalculationType>, P1, P2>
: pythagoras<CalculationType>::template calculation_type<P1, P2>
{};
template <typename CalculationType>
struct comparable_type<pythagoras<CalculationType> >
{
typedef comparable::pythagoras<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<pythagoras<CalculationType> >
{
typedef comparable::pythagoras<CalculationType> comparable_type;
public :
static inline comparable_type apply(pythagoras<CalculationType> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Point1, typename Point2>
struct result_from_distance<pythagoras<CalculationType>, Point1, Point2>
{
private :
typedef typename return_type<pythagoras<CalculationType>, Point1, Point2>::type return_type;
public :
template <typename T>
static inline return_type apply(pythagoras<CalculationType> const& , T const& value)
{
return return_type(value);
}
};
// Specializations for comparable::pythagoras
template <typename CalculationType>
struct tag<comparable::pythagoras<CalculationType> >
{
typedef strategy_tag_distance_point_point type;
};
template <typename CalculationType, typename P1, typename P2>
struct return_type<comparable::pythagoras<CalculationType>, P1, P2>
: comparable::pythagoras<CalculationType>::template calculation_type<P1, P2>
{};
template <typename CalculationType>
struct comparable_type<comparable::pythagoras<CalculationType> >
{
typedef comparable::pythagoras<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<comparable::pythagoras<CalculationType> >
{
typedef comparable::pythagoras<CalculationType> comparable_type;
public :
static inline comparable_type apply(comparable::pythagoras<CalculationType> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Point1, typename Point2>
struct result_from_distance<comparable::pythagoras<CalculationType>, Point1, Point2>
{
private :
typedef typename return_type<comparable::pythagoras<CalculationType>, Point1, Point2>::type return_type;
public :
template <typename T>
static inline return_type apply(comparable::pythagoras<CalculationType> const& , T const& value)
{
return_type const v = value;
return v * v;
}
};
template <typename Point1, typename Point2>
struct default_strategy
<
point_tag, point_tag, Point1, Point2, cartesian_tag, cartesian_tag
>
{
typedef pythagoras<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP

View File

@@ -0,0 +1,341 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// 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.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <std::size_t I>
struct compute_pythagoras_box_box
{
template <typename Box1, typename Box2, typename T>
static inline void apply(Box1 const& box1, Box2 const& box2, T& result)
{
T const b1_min_coord =
boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box1));
T const b1_max_coord =
boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box1));
T const b2_min_coord =
boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box2));
T const b2_max_coord =
boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box2));
if ( b1_max_coord < b2_min_coord )
{
T diff = b2_min_coord - b1_max_coord;
result += diff * diff;
}
if ( b1_min_coord > b2_max_coord )
{
T diff = b1_min_coord - b2_max_coord;
result += diff * diff;
}
compute_pythagoras_box_box<I-1>::apply(box1, box2, result);
}
};
template <>
struct compute_pythagoras_box_box<0>
{
template <typename Box1, typename Box2, typename T>
static inline void apply(Box1 const&, Box2 const&, T&)
{
}
};
}
#endif // DOXYGEN_NO_DETAIL
namespace comparable
{
/*!
\brief Strategy to calculate comparable distance between two boxes
\ingroup strategies
\tparam Box1 \tparam_first_box
\tparam Box2 \tparam_second_box
\tparam CalculationType \tparam_calculation
*/
template <typename CalculationType = void>
class pythagoras_box_box
{
public :
template <typename Box1, typename Box2>
struct calculation_type
{
typedef typename util::calculation_type::geometric::binary
<
Box1,
Box2,
CalculationType
>::type type;
};
template <typename Box1, typename Box2>
static inline typename calculation_type<Box1, Box2>::type
apply(Box1 const& box1, Box2 const& box2)
{
BOOST_CONCEPT_ASSERT
( (concepts::ConstPoint<typename point_type<Box1>::type>) );
BOOST_CONCEPT_ASSERT
( (concepts::ConstPoint<typename point_type<Box2>::type>) );
// Calculate distance using Pythagoras
// (Leave comment above for Doxygen)
assert_dimension_equal<Box1, Box2>();
typename calculation_type<Box1, Box2>::type result(0);
detail::compute_pythagoras_box_box
<
dimension<Box1>::value
>::apply(box1, box2, result);
return result;
}
};
} // namespace comparable
/*!
\brief Strategy to calculate the distance between two boxes
\ingroup strategies
\tparam CalculationType \tparam_calculation
\qbk{
[heading Notes]
[note Can be used for boxes with two\, three or more dimensions]
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class pythagoras_box_box
{
public :
template <typename Box1, typename Box2>
struct calculation_type
: util::calculation_type::geometric::binary
<
Box1,
Box2,
CalculationType,
double,
double // promote integer to double
>
{};
/*!
\brief applies the distance calculation using pythagoras_box_box
\return the calculated distance (including taking the square root)
\param box1 first box
\param box2 second box
*/
template <typename Box1, typename Box2>
static inline typename calculation_type<Box1, Box2>::type
apply(Box1 const& box1, Box2 const& box2)
{
// The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call
return math::sqrt
(
boost::numeric_cast<typename calculation_type
<
Box1, Box2
>::type>
(
comparable::pythagoras_box_box
<
CalculationType
>::apply(box1, box2)
)
);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct tag<pythagoras_box_box<CalculationType> >
{
typedef strategy_tag_distance_box_box type;
};
template <typename CalculationType, typename Box1, typename Box2>
struct return_type<distance::pythagoras_box_box<CalculationType>, Box1, Box2>
: pythagoras_box_box<CalculationType>::template calculation_type<Box1, Box2>
{};
template <typename CalculationType>
struct comparable_type<pythagoras_box_box<CalculationType> >
{
typedef comparable::pythagoras_box_box<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<pythagoras_box_box<CalculationType> >
{
typedef comparable::pythagoras_box_box<CalculationType> comparable_type;
public :
static inline comparable_type
apply(pythagoras_box_box<CalculationType> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Box1, typename Box2>
struct result_from_distance<pythagoras_box_box<CalculationType>, Box1, Box2>
{
private:
typedef typename return_type
<
pythagoras_box_box<CalculationType>, Box1, Box2
>::type return_type;
public:
template <typename T>
static inline return_type
apply(pythagoras_box_box<CalculationType> const& , T const& value)
{
return return_type(value);
}
};
// Specializations for comparable::pythagoras_box_box
template <typename CalculationType>
struct tag<comparable::pythagoras_box_box<CalculationType> >
{
typedef strategy_tag_distance_box_box type;
};
template <typename CalculationType, typename Box1, typename Box2>
struct return_type<comparable::pythagoras_box_box<CalculationType>, Box1, Box2>
: comparable::pythagoras_box_box
<
CalculationType
>::template calculation_type<Box1, Box2>
{};
template <typename CalculationType>
struct comparable_type<comparable::pythagoras_box_box<CalculationType> >
{
typedef comparable::pythagoras_box_box<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<comparable::pythagoras_box_box<CalculationType> >
{
typedef comparable::pythagoras_box_box<CalculationType> comparable_type;
public :
static inline comparable_type apply(comparable_type const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Box1, typename Box2>
struct result_from_distance
<
comparable::pythagoras_box_box<CalculationType>, Box1, Box2
>
{
private :
typedef typename return_type
<
comparable::pythagoras_box_box<CalculationType>, Box1, Box2
>::type return_type;
public :
template <typename T>
static inline return_type
apply(comparable::pythagoras_box_box<CalculationType> const&,
T const& value)
{
return_type const v = value;
return v * v;
}
};
template <typename BoxPoint1, typename BoxPoint2>
struct default_strategy
<
box_tag, box_tag, BoxPoint1, BoxPoint2, cartesian_tag, cartesian_tag
>
{
typedef pythagoras_box_box<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP

View File

@@ -0,0 +1,353 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// 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.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_POINT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_POINT_BOX_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <size_t I>
struct compute_pythagoras_point_box
{
template <typename Point, typename Box, typename T>
static inline void apply(Point const& point, Box const& box, T& result)
{
T const p_coord = boost::numeric_cast<T>(geometry::get<I-1>(point));
T const b_min_coord =
boost::numeric_cast<T>(geometry::get<min_corner, I-1>(box));
T const b_max_coord =
boost::numeric_cast<T>(geometry::get<max_corner, I-1>(box));
if ( p_coord < b_min_coord )
{
T diff = b_min_coord - p_coord;
result += diff * diff;
}
if ( p_coord > b_max_coord )
{
T diff = p_coord - b_max_coord;
result += diff * diff;
}
compute_pythagoras_point_box<I-1>::apply(point, box, result);
}
};
template <>
struct compute_pythagoras_point_box<0>
{
template <typename Point, typename Box, typename T>
static inline void apply(Point const&, Box const&, T&)
{
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
namespace comparable
{
/*!
\brief Strategy to calculate comparable distance between a point
and a box
\ingroup strategies
\tparam Point \tparam_first_point
\tparam Box \tparam_second_box
\tparam CalculationType \tparam_calculation
*/
template <typename CalculationType = void>
class pythagoras_point_box
{
public :
template <typename Point, typename Box>
struct calculation_type
{
typedef typename util::calculation_type::geometric::binary
<
Point, Box, CalculationType
>::type type;
};
template <typename Point, typename Box>
static inline typename calculation_type<Point, Box>::type
apply(Point const& point, Box const& box)
{
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point>) );
BOOST_CONCEPT_ASSERT
( (concepts::ConstPoint<typename point_type<Box>::type>) );
// Calculate distance using Pythagoras
// (Leave comment above for Doxygen)
assert_dimension_equal<Point, Box>();
typename calculation_type<Point, Box>::type result(0);
detail::compute_pythagoras_point_box
<
dimension<Point>::value
>::apply(point, box, result);
return result;
}
};
} // namespace comparable
/*!
\brief Strategy to calculate the distance between a point and a box
\ingroup strategies
\tparam CalculationType \tparam_calculation
\qbk{
[heading Notes]
[note Can be used for points and boxes with two\, three or more dimensions]
[heading See also]
[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
}
*/
template
<
typename CalculationType = void
>
class pythagoras_point_box
{
public :
template <typename Point, typename Box>
struct calculation_type
: util::calculation_type::geometric::binary
<
Point,
Box,
CalculationType,
double,
double // promote integer to double
>
{};
/*!
\brief applies the distance calculation using pythagoras
\return the calculated distance (including taking the square root)
\param point point
\param box box
*/
template <typename Point, typename Box>
static inline typename calculation_type<Point, Box>::type
apply(Point const& point, Box const& box)
{
// The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call
return math::sqrt
(
boost::numeric_cast<typename calculation_type
<
Point, Box
>::type>
(
comparable::pythagoras_point_box
<
CalculationType
>::apply(point, box)
)
);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct tag<pythagoras_point_box<CalculationType> >
{
typedef strategy_tag_distance_point_box type;
};
template <typename CalculationType, typename Point, typename Box>
struct return_type<distance::pythagoras_point_box<CalculationType>, Point, Box>
: pythagoras_point_box
<
CalculationType
>::template calculation_type<Point, Box>
{};
template <typename CalculationType>
struct comparable_type<pythagoras_point_box<CalculationType> >
{
typedef comparable::pythagoras_point_box<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<pythagoras_point_box<CalculationType> >
{
typedef comparable::pythagoras_point_box<CalculationType> comparable_type;
public :
static inline comparable_type
apply(pythagoras_point_box<CalculationType> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Point, typename Box>
struct result_from_distance<pythagoras_point_box<CalculationType>, Point, Box>
{
private :
typedef typename return_type
<
pythagoras_point_box<CalculationType>, Point, Box
>::type return_type;
public :
template <typename T>
static inline return_type
apply(pythagoras_point_box<CalculationType> const& , T const& value)
{
return return_type(value);
}
};
// Specializations for comparable::pythagoras_point_box
template <typename CalculationType>
struct tag<comparable::pythagoras_point_box<CalculationType> >
{
typedef strategy_tag_distance_point_box type;
};
template <typename CalculationType, typename Point, typename Box>
struct return_type
<
comparable::pythagoras_point_box<CalculationType>, Point, Box
> : comparable::pythagoras_point_box
<
CalculationType
>::template calculation_type<Point, Box>
{};
template <typename CalculationType>
struct comparable_type<comparable::pythagoras_point_box<CalculationType> >
{
typedef comparable::pythagoras_point_box<CalculationType> type;
};
template <typename CalculationType>
struct get_comparable<comparable::pythagoras_point_box<CalculationType> >
{
typedef comparable::pythagoras_point_box<CalculationType> comparable_type;
public :
static inline comparable_type apply(comparable_type const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Point, typename Box>
struct result_from_distance
<
comparable::pythagoras_point_box<CalculationType>, Point, Box
>
{
private :
typedef typename return_type
<
comparable::pythagoras_point_box<CalculationType>, Point, Box
>::type return_type;
public :
template <typename T>
static inline return_type
apply(comparable::pythagoras_point_box<CalculationType> const& ,
T const& value)
{
return_type const v = value;
return v * v;
}
};
template <typename Point, typename BoxPoint>
struct default_strategy
<
point_tag, box_tag, Point, BoxPoint, cartesian_tag, cartesian_tag
>
{
typedef pythagoras_point_box<> type;
};
template <typename BoxPoint, typename Point>
struct default_strategy
<
box_tag, point_tag, BoxPoint, Point, cartesian_tag, cartesian_tag
>
{
typedef typename default_strategy
<
point_tag, box_tag, Point, BoxPoint, cartesian_tag, cartesian_tag
>::type type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_POINT_BOX_HPP

View File

@@ -0,0 +1,203 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2018-2019 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)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_SEGMENT_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_SEGMENT_BOX_HPP
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace distance
{
template
<
typename CalculationType = void,
typename Strategy = pythagoras<CalculationType>
>
struct cartesian_segment_box
{
template <typename PointOfSegment, typename PointOfBox>
struct calculation_type
: promote_floating_point
<
typename strategy::distance::services::return_type
<
Strategy,
PointOfSegment,
PointOfBox
>::type
>
{};
// point-point strategy getters
struct distance_pp_strategy
{
typedef Strategy type;
};
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>
inline ReturnType segment_below_of_box(SegmentPoint const& p0,
SegmentPoint const& p1,
BoxPoint const&,
BoxPoint const&,
BoxPoint const&,
BoxPoint const& bottom_right) const
{
return geometry::detail::distance::segment_to_box_2D
<
ReturnType,
SegmentPoint,
BoxPoint,
cartesian_segment_box<CalculationType, Strategy>
>::template call_above_of_box
<
typename LessEqual::other
>(p1, p0, bottom_right, *this);
}
template <typename SPoint, typename BPoint>
static void mirror(SPoint&,
SPoint&,
BPoint&,
BPoint&,
BPoint&,
BPoint&)
{}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType, typename Strategy>
struct tag<cartesian_segment_box<CalculationType, Strategy> >
{
typedef strategy_tag_distance_segment_box type;
};
template <typename CalculationType, typename Strategy, typename PS, typename PB>
struct return_type<cartesian_segment_box<CalculationType, Strategy>, PS, PB>
: cartesian_segment_box<CalculationType, Strategy>::template calculation_type<PS, PB>
{};
template <typename CalculationType, typename Strategy>
struct comparable_type<cartesian_segment_box<CalculationType, Strategy> >
{
// Define a cartesian_segment_box strategy with its underlying point-point
// strategy being comparable
typedef cartesian_segment_box
<
CalculationType,
typename comparable_type<Strategy>::type
> type;
};
template <typename CalculationType, typename Strategy>
struct get_comparable<cartesian_segment_box<CalculationType, Strategy> >
{
typedef typename comparable_type
<
cartesian_segment_box<CalculationType, Strategy>
>::type comparable_type;
public :
static inline comparable_type apply(cartesian_segment_box<CalculationType, Strategy> const& )
{
return comparable_type();
}
};
template <typename CalculationType, typename Strategy, typename PS, typename PB>
struct result_from_distance<cartesian_segment_box<CalculationType, Strategy>, PS, PB>
{
private :
typedef typename return_type<
cartesian_segment_box
<
CalculationType,
Strategy
>,
PS,
PB
>::type return_type;
public :
template <typename T>
static inline return_type apply(cartesian_segment_box<CalculationType,
Strategy> const& ,
T const& value)
{
Strategy s;
return result_from_distance<Strategy, PS, PB>::apply(s, value);
}
};
template <typename Segment, typename Box>
struct default_strategy
<
segment_tag, box_tag, Segment, Box,
cartesian_tag, cartesian_tag
>
{
typedef cartesian_segment_box<> type;
};
template <typename Box, typename Segment>
struct default_strategy
<
box_tag, segment_tag, Box, Segment,
cartesian_tag, cartesian_tag
>
{
typedef typename default_strategy
<
segment_tag, box_tag, Segment, Box,
cartesian_tag, cartesian_tag
>::type type;
};
}
#endif
}} // namespace strategy::distance
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_SEGMENT_BOX_HPP

View File

@@ -0,0 +1,153 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015, 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)
#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
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_HPP

View File

@@ -0,0 +1,119 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015-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)
#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>
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
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_BOX_HPP

View File

@@ -0,0 +1,59 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_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>
namespace boost { namespace geometry
{
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

View File

@@ -0,0 +1,111 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015, 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)
#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>
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
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_ENVELOPE_POINT_HPP

View File

@@ -0,0 +1,93 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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)
#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
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);
}
};
#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

View File

@@ -0,0 +1,69 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// 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)
#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>
namespace boost { namespace geometry
{
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

View File

@@ -0,0 +1,125 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// 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)
#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);
}
};
template <std::size_t DimensionCount>
struct point_loop<DimensionCount, DimensionCount>
{
template <typename Box, typename Point>
static inline void apply(Box&, Point const&) {}
};
} // 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

View File

@@ -0,0 +1,71 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// 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)
#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>
namespace boost { namespace geometry
{
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

View File

@@ -0,0 +1,793 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013-2017 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.
// Contributed and/or modified by Menelaos Karavelas, 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)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP
#include <algorithm>
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/geometry/geometries/concepts/segment_concept.hpp>
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/algorithms/detail/assign_values.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/util/math.hpp>
#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/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>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/strategies/within.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)
# include <boost/geometry/io/wkt/write.hpp>
#endif
namespace boost { namespace geometry
{
namespace strategy { namespace intersection
{
/*!
\see http://mathworld.wolfram.com/Line-LineIntersection.html
*/
template
<
typename CalculationType = void
>
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;
template <typename CoordinateType, typename SegmentRatio>
struct segment_intersection_info
{
private :
typedef typename select_most_precise
<
CoordinateType, double
>::type promoted_type;
promoted_type comparable_length_a() const
{
return dx_a * dx_a + dy_a * dy_a;
}
promoted_type comparable_length_b() const
{
return dx_b * dx_b + dy_b * dy_b;
}
template <typename Point, typename Segment1, typename Segment2>
void assign_a(Point& point, Segment1 const& a, Segment2 const& ) const
{
assign(point, a, dx_a, dy_a, robust_ra);
}
template <typename Point, typename Segment1, typename Segment2>
void assign_b(Point& point, Segment1 const& , Segment2 const& b) const
{
assign(point, b, dx_b, dy_b, robust_rb);
}
template <typename Point, typename Segment>
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);
typedef typename promote_integral<CoordinateType>::type promoted_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);
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));
}
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
}
if (use_a)
{
assign_a(point, a, b);
}
else
{
assign_b(point, a, b);
}
}
CoordinateType dx_a, dy_a;
CoordinateType dx_b, dy_b;
SegmentRatio robust_ra;
SegmentRatio robust_rb;
};
template <typename D, typename W, typename ResultType>
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)
{
// 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
// IntersectionPoint = (x1 + r * dx_a, y1 + r * dy_a)
}
// Relate segments a and b
template
<
typename Segment1,
typename Segment2,
typename Policy,
typename RobustPolicy
>
static inline typename Policy::return_type
apply(Segment1 const& a, Segment2 const& b,
Policy const& policy, RobustPolicy const& robust_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);
}
// The main entry-routine, calculating intersections of segments a / b
// NOTE: Robust* types may be the same as Segments' point types
template
<
typename Segment1,
typename Segment2,
typename Policy,
typename RobustPolicy,
typename RobustPoint1,
typename RobustPoint2
>
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)
{
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
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());
if(a_is_point && b_is_point)
{
return equals_point_point(robust_a1, robust_b2, point_in_point_strategy_type())
? Policy::degenerate(a, true)
: Policy::disjoint()
;
}
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));
if (sides.same<0>())
{
// Both points are at same side of other segment, we can leave
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));
if (sides.same<1>())
{
// Both points are at same side of other segment, we can leave
return Policy::disjoint();
}
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);
// 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;
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(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);
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))
{
// 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);
collinear = true;
}
else
{
sinfo.robust_ra.assign(robust_da, robust_da0);
sinfo.robust_rb.assign(robust_db, robust_db0);
}
}
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);
if (collinear_use_first.second)
{
// Degenerate cases: segments of single point, lying on other segment, are not disjoint
// This situation is collinear too
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);
}
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 Policy::segments_crosses(sides, sinfo, a, b);
}
private:
// first is true if x is more significant
// second is true if the more significant difference is not 0
template <typename RobustCoordinateType>
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,
bool const a_is_point,
bool const b_is_point)
{
//BOOST_GEOMETRY_ASSERT_MSG(!(a_is_point && b_is_point), "both segments shouldn't be degenerated");
// for degenerated segments the second is always true because this function
// shouldn't be called if both segments were degenerated
if (a_is_point)
{
return std::make_pair(abs_robust_dx_b >= abs_robust_dy_b, true);
}
else if (b_is_point)
{
return std::make_pair(abs_robust_dx_a >= abs_robust_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);
return min_dx == min_dy ?
std::make_pair(true, min_dx > RobustCoordinateType(0)) :
std::make_pair(min_dx > min_dy, true);
}
}
template
<
std::size_t Dimension,
typename Policy,
typename RatioType,
typename Segment1,
typename Segment2,
typename RobustPoint1,
typename RobustPoint2
>
static inline typename Policy::return_type
relate_collinear(Segment1 const& a,
Segment2 const& b,
RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2,
RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2,
bool a_is_point, bool b_is_point)
{
if (a_is_point)
{
return relate_one_degenerate<Policy, RatioType>(a,
get<Dimension>(robust_a1),
get<Dimension>(robust_b1), get<Dimension>(robust_b2),
true);
}
if (b_is_point)
{
return relate_one_degenerate<Policy, RatioType>(b,
get<Dimension>(robust_b1),
get<Dimension>(robust_a1), get<Dimension>(robust_a2),
false);
}
return relate_collinear<Policy, RatioType>(a, b,
get<Dimension>(robust_a1),
get<Dimension>(robust_a2),
get<Dimension>(robust_b1),
get<Dimension>(robust_b2));
}
/// Relate segments known collinear
template
<
typename Policy,
typename RatioType,
typename Segment1,
typename Segment2,
typename RobustType1,
typename RobustType2
>
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)
{
// Calculate the ratios where a starts in b, b starts in a
// a1--------->a2 (2..7)
// b1----->b2 (5..8)
// length_a: 7-2=5
// length_b: 8-5=3
// b1 is located w.r.t. a at ratio: (5-2)/5=3/5 (on a)
// b2 is located w.r.t. a at ratio: (8-2)/5=6/5 (right of a)
// a1 is located w.r.t. b at ratio: (2-5)/3=-3/3 (left of b)
// a2 is located w.r.t. b at ratio: (7-5)/3=2/3 (on b)
// A arrives (a2 on b), B departs (b1 on a)
// If both are reversed:
// a2<---------a1 (7..2)
// b2<-----b1 (8..5)
// length_a: 2-7=-5
// length_b: 5-8=-3
// b1 is located w.r.t. a at ratio: (8-7)/-5=-1/5 (before a starts)
// b2 is located w.r.t. a at ratio: (5-7)/-5=2/5 (on a)
// a1 is located w.r.t. b at ratio: (7-8)/-3=1/3 (on b)
// a2 is located w.r.t. b at ratio: (2-8)/-3=6/3 (after b ends)
// If both one is reversed:
// a1--------->a2 (2..7)
// b2<-----b1 (8..5)
// length_a: 7-2=+5
// length_b: 5-8=-3
// b1 is located w.r.t. a at ratio: (8-2)/5=6/5 (after a ends)
// 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;
RatioType ra_from(oa_1 - ob_1, length_b);
RatioType ra_to(oa_2 - ob_1, length_b);
RatioType rb_from(ob_1 - oa_1, length_a);
RatioType rb_to(ob_2 - oa_1, length_a);
// use absolute measure to detect endpoints intersection
// NOTE: it'd be possible to calculate bx_wrt_a using ax_wrt_b values
int const a1_wrt_b = position_value(oa_1, ob_1, ob_2);
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)
// but position value indicates that the IP is in the middle of the segment
// because one of the segments is very long
// In such case the ratios could be moved into the middle direction
// by some small value (e.g. EPS+1ULP)
if (a1_wrt_b == 1)
{
ra_from.assign(0, 1);
rb_from.assign(0, 1);
}
else if (a1_wrt_b == 3)
{
ra_from.assign(1, 1);
rb_to.assign(0, 1);
}
if (a2_wrt_b == 1)
{
ra_to.assign(0, 1);
rb_from.assign(1, 1);
}
else if (a2_wrt_b == 3)
{
ra_to.assign(1, 1);
rb_to.assign(1, 1);
}
if ((a1_wrt_b < 1 && a2_wrt_b < 1) || (a1_wrt_b > 3 && a2_wrt_b > 3))
//if ((ra_from.left() && ra_to.left()) || (ra_from.right() && ra_to.right()))
{
return Policy::disjoint();
}
bool const opposite = math::sign(length_a) != math::sign(length_b);
return Policy::segments_collinear(a, b, opposite,
a1_wrt_b, a2_wrt_b, b1_wrt_a, b2_wrt_a,
ra_from, ra_to, rb_from, rb_to);
}
/// Relate segments where one is degenerate
template
<
typename Policy,
typename RatioType,
typename DegenerateSegment,
typename RobustType1,
typename RobustType2
>
static inline typename Policy::return_type
relate_one_degenerate(DegenerateSegment const& degenerate_segment,
RobustType1 d, RobustType2 s1, RobustType2 s2,
bool a_degenerate)
{
// Calculate the ratios where ds starts in s
// a1--------->a2 (2..6)
// b1/b2 (4..4)
// Ratio: (4-2)/(6-2)
RatioType const ratio(d - s1, s2 - s1);
if (!ratio.on_segment())
{
return Policy::disjoint();
}
return Policy::one_degenerate(degenerate_segment, ratio, a_degenerate);
}
template <typename ProjCoord1, typename ProjCoord2>
static inline int position_value(ProjCoord1 const& ca1,
ProjCoord2 const& cb1,
ProjCoord2 const& cb2)
{
// S1x 0 1 2 3 4
// S2 |---------->
return math::equals(ca1, cb1) ? 1
: math::equals(ca1, cb2) ? 3
: cb1 < cb2 ?
( ca1 < cb1 ? 0
: ca1 > cb2 ? 4
: 2 )
: ( ca1 > cb1 ? 0
: ca1 < cb2 ? 4
: 2 );
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<cartesian_tag, CalculationType>
{
typedef cartesian_segments<CalculationType> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::intersection
namespace strategy
{
namespace within { namespace services
{
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
}} // within::services
namespace covered_by { namespace services
{
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, linear_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
template <typename Geometry1, typename Geometry2, typename AnyTag1, typename AnyTag2>
struct default_strategy<Geometry1, Geometry2, AnyTag1, AnyTag2, polygonal_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::intersection::cartesian_segments<> type;
};
}} // within::services
} // strategy
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP

View File

@@ -0,0 +1,129 @@
// Boost.Geometry
// Copyright (c) 2018, 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_LINE_INTERPOLATE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_LINE_INTERPOLATE_HPP
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#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/select_calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace line_interpolate
{
/*!
\brief Interpolate point on a cartesian segment.
\ingroup strategies
\tparam CalculationType \tparam_calculation
\tparam DistanceStrategy The underlying point-point distance strategy
\qbk{
[heading See also]
\* [link geometry.reference.algorithms.line_interpolate.line_interpolate_4_with_strategy line_interpolate (with strategy)]
}
*/
template
<
typename CalculationType = void,
typename DistanceStrategy = distance::pythagoras<CalculationType>
>
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,
Fraction const& fraction,
Point & p,
Distance const&) const
{
typedef typename select_calculation_type_alt
<
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);
//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);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef strategy::line_interpolate::cartesian<> type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
}} // namespace strategy::line_interpolate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_LINE_INTERPOLATE_HPP

View File

@@ -0,0 +1,332 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015-2018.
// Modifications copyright (c) 2015-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
namespace boost { namespace geometry { namespace strategy
{
namespace within
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct within_coord
{
template <typename Value1, typename Value2>
static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
{
return value > min_value && value < max_value;
}
};
struct covered_by_coord
{
template <typename Value1, typename Value2>
static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
{
return value >= min_value && value <= max_value;
}
};
template <typename Geometry, std::size_t Dimension, typename CSTag>
struct within_range
: within_coord
{};
template <typename Geometry, std::size_t Dimension, typename CSTag>
struct covered_by_range
: covered_by_coord
{};
// NOTE: the result would be the same if instead of structs defined below
// the above xxx_range were used with the following arguments:
// (min_value + diff_min, min_value, max_value)
struct within_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)
{
CalcT const c0 = 0;
return diff_min > c0
&& (min_value + diff_min < max_value
/*|| max_value - diff_min > min_value*/);
}
};
struct covered_by_longitude_diff
{
template <typename CalcT>
static inline bool apply(CalcT const& diff_min, CalcT const& min_value, CalcT const& max_value)
{
return min_value + diff_min <= max_value
/*|| max_value - diff_min >= min_value*/;
}
};
template <typename Geometry,
typename CoordCheck,
typename DiffCheck>
struct longitude_range
{
template <typename Value1, typename Value2>
static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
{
typedef typename select_most_precise
<
Value1, Value2
>::type calc_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(value, min_value, max_value))
{
return true;
}
// min <= max <=> diff >= 0
calc_t const diff_ing = max_value - min_value;
// if containing covers the whole globe it contains all
if (diff_ing >= constants::period())
{
return true;
}
// calculate positive longitude translation with min_value as origin
calc_t const diff_min = math::longitude_distance_unsigned<units_t, calc_t>(min_value, value);
return DiffCheck::template apply<calc_t>(diff_min, min_value, max_value);
}
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename Geometry>
struct within_range<Geometry, 0, spherical_tag>
: longitude_range<Geometry, within_coord, within_longitude_diff>
{};
template <typename Geometry>
struct covered_by_range<Geometry, 0, spherical_tag>
: longitude_range<Geometry, covered_by_coord, covered_by_longitude_diff>
{};
template
<
template <typename, std::size_t, typename> class SubStrategy,
typename CSTag, // cartesian_tag or spherical_tag
std::size_t Dimension,
std::size_t DimensionCount
>
struct relate_point_box_loop
{
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
if (! SubStrategy<Point, Dimension, CSTag>::apply(get<Dimension>(point),
get<min_corner, Dimension>(box),
get<max_corner, Dimension>(box))
)
{
return false;
}
return relate_point_box_loop
<
SubStrategy,
CSTag,
Dimension + 1, DimensionCount
>::apply(point, box);
}
};
template
<
template <typename, std::size_t, typename> class SubStrategy,
typename CSTag,
std::size_t DimensionCount
>
struct relate_point_box_loop<SubStrategy, CSTag, DimensionCount, DimensionCount>
{
template <typename Point, typename Box>
static inline bool apply(Point const& , Box const& )
{
return true;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
struct cartesian_point_box
{
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
return detail::relate_point_box_loop
<
detail::within_range,
cartesian_tag,
0, dimension<Point>::value
>::apply(point, box);
}
};
struct spherical_point_box
{
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
return detail::relate_point_box_loop
<
detail::within_range,
spherical_tag,
0, dimension<Point>::value
>::apply(point, box);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point, typename Box>
struct default_strategy
<
Point, Box,
point_tag, box_tag,
pointlike_tag, areal_tag,
cartesian_tag, cartesian_tag
>
{
typedef within::cartesian_point_box type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename Point, typename Box>
struct default_strategy
<
Point, Box,
point_tag, box_tag,
pointlike_tag, areal_tag,
spherical_tag, spherical_tag
>
{
typedef within::spherical_point_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
} // namespace within
namespace covered_by
{
struct cartesian_point_box
{
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
return within::detail::relate_point_box_loop
<
within::detail::covered_by_range,
cartesian_tag,
0, dimension<Point>::value
>::apply(point, box);
}
};
struct spherical_point_box
{
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
return within::detail::relate_point_box_loop
<
within::detail::covered_by_range,
spherical_tag,
0, dimension<Point>::value
>::apply(point, box);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename Point, typename Box>
struct default_strategy
<
Point, Box,
point_tag, box_tag,
pointlike_tag, areal_tag,
cartesian_tag, cartesian_tag
>
{
typedef covered_by::cartesian_point_box type;
};
// spherical_equatorial_tag, spherical_polar_tag and geographic_cat are casted to spherical_tag
template <typename Point, typename Box>
struct default_strategy
<
Point, Box,
point_tag, box_tag,
pointlike_tag, areal_tag,
spherical_tag, spherical_tag
>
{
typedef covered_by::spherical_point_box type;
};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
} // namespace covered_by
}}} // namespace boost::geometry::strategy
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP

View File

@@ -0,0 +1,124 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// 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.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POINT_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POINT_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/util/math.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within
{
template <std::size_t Dimension, std::size_t DimensionCount>
struct point_point_generic
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& p1, Point2 const& p2)
{
if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
{
return false;
}
return
point_point_generic<Dimension + 1, DimensionCount>::apply(p1, p2);
}
};
template <std::size_t DimensionCount>
struct point_point_generic<DimensionCount, DimensionCount>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const&, Point2 const& )
{
return true;
}
};
}} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL
namespace strategy { namespace within
{
struct cartesian_point_point
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& point1, Point2 const& point2)
{
return geometry::detail::within::point_point_generic
<
0, dimension<Point1>::type::value
>::apply(point1, point2);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2>
struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::cartesian_point_point type;
};
} // namespace services
#endif
}} // namespace strategy::within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace strategy { namespace covered_by { namespace services
{
template <typename PointLike1, typename PointLike2, typename Tag1, typename Tag2>
struct default_strategy<PointLike1, PointLike2, Tag1, Tag2, pointlike_tag, pointlike_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::cartesian_point_point type;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POINT_HPP

View File

@@ -0,0 +1,130 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using cross counting,
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\see http://tog.acm.org/resources/GraphicsGems/gemsiv/ptpoly_haines/ptinpoly.c
\note Does NOT work correctly for point ON border
\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 crossings_multiply
{
typedef typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
class flags
{
bool inside_flag;
bool first;
bool yflag0;
public :
friend class crossings_multiply;
inline flags()
: inside_flag(false)
, first(true)
, yflag0(false)
{}
};
public :
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef flags state_type;
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);
if (state.first)
{
state.first = false;
state.yflag0 = y0 >= ty;
}
bool yflag1 = y1 >= ty;
if (state.yflag0 != yflag1)
{
if ( ((y1-ty) * (x0-x1) >= (x1-tx) * (y0-y1)) == yflag1 )
{
state.inside_flag = ! state.inside_flag;
}
}
state.yflag0 = yflag1;
return true;
}
static inline int result(flags const& state)
{
return state.inside_flag ? 1 : -1;
}
};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP

View File

@@ -0,0 +1,124 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\brief Within detection using cross counting
\ingroup strategies
\tparam Point \tparam_point
\tparam PointOfSegment \tparam_segment_point
\tparam CalculationType \tparam_calculation
\author adapted from Randolph Franklin algorithm
\author Barend and Maarten, 1995
\author Revised for templatized library, Barend Gehrels, 2007
\return true if point is in ring, works for closed rings in both directions
\note Does NOT work correctly for point ON border
\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 franklin
{
typedef typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
/*! subclass to keep state */
class crossings
{
bool crosses;
public :
friend class franklin;
inline crossings()
: crosses(false)
{}
};
public :
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef crossings state_type;
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);
if (
( (y2 <= py && py < y1) || (y1 <= py && py < y2) )
&& (px < (x1 - x2) * (py - y2) / (y1 - y2) + x2)
)
{
state.crosses = ! state.crosses;
}
return true;
}
static inline int result(crossings const& state)
{
return state.crosses ? 1 : -1;
}
};
}} // namespace strategy::within
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP

View File

@@ -0,0 +1,310 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POLY_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POLY_WINDING_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.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>
namespace boost { namespace geometry
{
namespace strategy { namespace within
{
/*!
\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
\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
{
typedef side::side_by_triangle<CalculationType> side_strategy_type;
typedef typename select_calculation_type
<
Point,
PointOfSegment,
CalculationType
>::type calculation_type;
/*! subclass to keep state */
class counter
{
int m_count;
bool m_touches;
inline int code() const
{
return m_touches ? 0 : m_count == 0 ? -1 : 1;
}
public :
friend class cartesian_winding;
inline counter()
: m_count(0)
, m_touches(false)
{}
};
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;
// Typedefs and static methods to fulfill the concept
typedef Point point_type;
typedef PointOfSegment segment_point_type;
typedef counter state_type;
static inline bool apply(Point const& point,
PointOfSegment const& s1, PointOfSegment const& s2,
counter& state)
{
bool eq1 = false;
bool eq2 = false;
int count = check_segment(point, s1, s2, state, eq1, eq2);
if (count != 0)
{
int side = 0;
if (count == 1 || count == -1)
{
side = side_equal(point, eq1 ? s1 : s2, count);
}
else // count == 2 || count == -2
{
// 1 left, -1 right
side = side_strategy_type::apply(s1, s2, point);
}
if (side == 0)
{
// Point is lying on segment
state.m_touches = true;
state.m_count = 0;
return false;
}
// Side is NEG for right, POS for left.
// The count is -2 for left, 2 for right (or -1/1)
// Side positive thus means RIGHT and LEFTSIDE or LEFT and RIGHTSIDE
// See accompagnying figure (TODO)
if (side * count > 0)
{
state.m_count += count;
}
}
return ! state.m_touches;
}
static inline int result(counter const& state)
{
return state.code();
}
private:
static inline int check_segment(Point const& point,
PointOfSegment const& seg1,
PointOfSegment const& seg2,
counter& state,
bool& eq1, bool& eq2)
{
if (check_touch(point, seg1, seg2, state, eq1, eq2))
{
return 0;
}
return calculate_count(point, seg1, seg2, eq1, eq2);
}
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);
eq1 = math::equals(s1x, px);
eq2 = math::equals(s2x, px);
// Both equal p -> segment vertical
// 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);
if ((s1y <= py && s2y >= py) || (s2y <= py && s1y >= py))
{
state.m_touches = true;
}
return true;
}
return false;
}
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);
return eq1 ? (s2 > p ? 1 : -1) // Point on level s1, E/W depending on s2
: eq2 ? (s1 > p ? -1 : 1) // idem
: s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> E
: s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> W
: 0;
}
static inline int side_equal(Point const& point,
PointOfSegment const& se,
int count)
{
// NOTE: for D=0 the signs would be reversed
return math::equals(get<1>(point), get<1>(se)) ?
0 :
get<1>(point) < get<1>(se) ?
// assuming count is equal to 1 or -1
-count : // ( count > 0 ? -1 : 1) :
count; // ( count > 0 ? 1 : -1) ;
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
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;
};
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;
};
} // namespace services
#endif
}} // namespace strategy::within
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
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;
};
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;
};
}}} // namespace strategy::covered_by::services
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_POINT_IN_POLY_WINDING_HPP

View File

@@ -0,0 +1,296 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015, 2017, 2018.
// Modifications copyright (c) 2015-2018, 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
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_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>
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
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP

View File

@@ -0,0 +1,351 @@
// 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