stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,242 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 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_POLICIES_COMPARE_HPP
#define BOOST_GEOMETRY_POLICIES_COMPARE_HPP
#include <cstddef>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace compare
{
template
<
int Direction,
typename Point,
typename Strategy,
std::size_t Dimension,
std::size_t DimensionCount
>
struct compare_loop
{
typedef typename strategy::compare::detail::select_strategy
<
Strategy, Direction, Point, Dimension
>::type compare_type;
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
static inline bool apply(Point const& left, Point const& right)
{
coordinate_type const& cleft = geometry::get<Dimension>(left);
coordinate_type const& cright = geometry::get<Dimension>(right);
if (geometry::math::equals(cleft, cright))
{
return compare_loop
<
Direction, Point, Strategy,
Dimension + 1, DimensionCount
>::apply(left, right);
}
else
{
compare_type compare;
return compare(cleft, cright);
}
}
};
template
<
int Direction,
typename Point,
typename Strategy,
std::size_t DimensionCount
>
struct compare_loop<Direction, Point, Strategy, DimensionCount, DimensionCount>
{
static inline bool apply(Point const&, Point const&)
{
// On coming here, points are equal. Return true if
// direction = 0 (equal), false if -1/1 (greater/less)
return Direction == 0;
}
};
template <int Direction, typename Point, typename Strategy>
struct compare_in_all_dimensions
{
inline bool operator()(Point const& left, Point const& right) const
{
return detail::compare::compare_loop
<
Direction, Point, Strategy,
0, geometry::dimension<Point>::type::value
>::apply(left, right);
}
};
template <typename Point, typename Strategy, std::size_t Dimension>
class compare_in_one_dimension
{
Strategy compare;
public :
inline bool operator()(Point const& left, Point const& right) const
{
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
coordinate_type const& cleft = get<Dimension>(left);
coordinate_type const& cright = get<Dimension>(right);
return compare(cleft, cright);
}
};
}} // namespace detail::compare
#endif
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
int Direction,
typename Point,
typename Strategy,
int Dimension
>
struct compare_geometries
: detail::compare::compare_in_one_dimension
<
Point,
typename strategy::compare::detail::select_strategy
<
Strategy, Direction, Point, Dimension
>::type,
Dimension
>
{};
// Specialization with -1: compare in all dimensions
template <int Direction, typename Point, typename Strategy>
struct compare_geometries<Direction, Point, Strategy, -1>
: detail::compare::compare_in_all_dimensions<Direction, Point, Strategy>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
/*!
\brief Less functor, to sort points in ascending order.
\ingroup compare
\details This functor compares points and orders them on x,
then on y, then on z coordinate.
\tparam Geometry the geometry
\tparam Dimension the dimension to sort on, defaults to -1,
indicating ALL dimensions. That's to say, first on x,
on equal x-es then on y, etc.
If a dimension is specified, only that dimension is considered
\tparam Strategy underlying coordinate comparing functor,
defaults to the default comparison strategies
related to the point coordinate system. If specified, the specified
strategy is used. This can e.g. be std::less<double>.
*/
template
<
typename Point,
int Dimension = -1,
typename Strategy = strategy::compare::default_strategy
>
struct less
: dispatch::compare_geometries
<
1, // indicates ascending
Point,
Strategy,
Dimension
>
{
typedef Point first_argument_type;
typedef Point second_argument_type;
typedef bool result_type;
};
/*!
\brief Greater functor
\ingroup compare
\details Can be used to sort points in reverse order
\see Less functor
*/
template
<
typename Point,
int Dimension = -1,
typename Strategy = strategy::compare::default_strategy
>
struct greater
: dispatch::compare_geometries
<
-1, // indicates descending
Point,
Strategy,
Dimension
>
{};
/*!
\brief Equal To functor, to compare if points are equal
\ingroup compare
\tparam Geometry the geometry
\tparam Dimension the dimension to compare on, defaults to -1,
indicating ALL dimensions.
If a dimension is specified, only that dimension is considered
\tparam Strategy underlying coordinate comparing functor
*/
template
<
typename Point,
int Dimension = -1,
typename Strategy = strategy::compare::default_strategy
>
struct equal_to
: dispatch::compare_geometries
<
0,
Point,
Strategy,
Dimension
>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_COMPARE_HPP
@@ -0,0 +1,67 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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-2014.
// Modifications copyright (c) 2013-2014, 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_ALGORITHMS_POLICIES_DISJOINT_INTERRUPT_POLICY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_POLICIES_DISJOINT_INTERRUPT_POLICY_HPP
#include <boost/range.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
struct disjoint_interrupt_policy
{
static bool const enabled = true;
bool has_intersections;
inline disjoint_interrupt_policy()
: has_intersections(false)
{}
template <typename Range>
inline bool apply(Range const& range)
{
// If there is any IP in the range, it is NOT disjoint
if (boost::size(range) > 0)
{
has_intersections = true;
return true;
}
return false;
}
};
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_POLICIES_DISJOINT_INTERRUPT_POLICY_HPP
@@ -0,0 +1,59 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_POLICIES_IS_VALID_DEFAULT_POLICY_HPP
#define BOOST_GEOMETRY_POLICIES_IS_VALID_DEFAULT_POLICY_HPP
#include <boost/geometry/algorithms/validity_failure_type.hpp>
namespace boost { namespace geometry
{
template <bool AllowDuplicates = true, bool AllowSpikes = true>
class is_valid_default_policy
{
protected:
static inline bool is_valid(validity_failure_type failure)
{
return failure == no_failure
|| (AllowDuplicates && failure == failure_duplicate_points);
}
static inline bool is_valid(validity_failure_type failure, bool is_linear)
{
return is_valid(failure)
|| (is_linear && AllowSpikes && failure == failure_spikes);
}
public:
template <validity_failure_type Failure>
static inline bool apply()
{
return is_valid(Failure);
}
template <validity_failure_type Failure, typename Data>
static inline bool apply(Data const&)
{
return is_valid(Failure);
}
template <validity_failure_type Failure, typename Data1, typename Data2>
static inline bool apply(Data1 const& data1, Data2 const&)
{
return is_valid(Failure, data1);
}
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_IS_VALID_DEFAULT_POLICY_HPP
@@ -0,0 +1,224 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015, 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
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP
#define BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP
#include <sstream>
#include <boost/geometry/io/dsv/write.hpp>
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
namespace boost { namespace geometry
{
inline char const* validity_failure_type_message(validity_failure_type failure)
{
switch (failure)
{
case no_failure:
return "Geometry is valid";
case failure_few_points:
return "Geometry has too few points";
case failure_wrong_topological_dimension:
return "Geometry has wrong topological dimension";
case failure_not_closed:
return "Geometry is defined as closed but is open";
case failure_spikes:
return "Geometry has spikes";
case failure_self_intersections:
return "Geometry has invalid self-intersections";
case failure_wrong_orientation:
return "Geometry has wrong orientation";
case failure_interior_rings_outside:
return "Geometry has interior rings defined outside the outer boundary";
case failure_nested_interior_rings:
return "Geometry has nested interior rings";
case failure_disconnected_interior:
return "Geometry has disconnected interior";
case failure_intersecting_interiors:
return "Multi-polygon has intersecting interiors";
case failure_duplicate_points:
return "Geometry has duplicate (consecutive) points";
case failure_wrong_corner_order:
return "Box has corners in wrong order";
case failure_invalid_coordinate:
return "Geometry has point(s) with invalid coordinate(s)";
default: // to avoid -Wreturn-type warning
return "";
}
}
template <bool AllowDuplicates = true, bool AllowSpikes = true>
class failing_reason_policy
{
private:
static inline
validity_failure_type transform_failure_type(validity_failure_type failure)
{
if (BOOST_GEOMETRY_CONDITION(
AllowDuplicates && failure == failure_duplicate_points))
{
return no_failure;
}
return failure;
}
static inline
validity_failure_type transform_failure_type(validity_failure_type failure,
bool is_linear)
{
if (BOOST_GEOMETRY_CONDITION(
is_linear && AllowSpikes && failure == failure_spikes))
{
return no_failure;
}
return transform_failure_type(failure);
}
inline void set_failure_message(validity_failure_type failure)
{
m_oss.str("");
m_oss.clear();
m_oss << validity_failure_type_message(failure);
}
template
<
validity_failure_type Failure,
typename Data1,
typename Data2 = Data1,
typename Dummy = void
>
struct process_data
{
static inline void apply(std::ostringstream&, Data1 const&)
{
}
static inline void apply(std::ostringstream&,
Data1 const&,
Data2 const&)
{
}
};
template <typename SpikePoint>
struct process_data<failure_spikes, bool, SpikePoint>
{
static inline void apply(std::ostringstream& oss,
bool is_linear,
SpikePoint const& spike_point)
{
if (BOOST_GEOMETRY_CONDITION(is_linear && AllowSpikes))
{
return;
}
oss << ". A spike point was found with apex at "
<< geometry::dsv(spike_point);
}
};
template <typename Turns>
struct process_data<failure_self_intersections, Turns>
{
static inline
void apply_to_segment_identifier(std::ostringstream& oss,
segment_identifier seg_id)
{
oss << "{" << seg_id.source_index
<< ", " << seg_id.multi_index
<< ", " << seg_id.ring_index
<< ", " << seg_id.segment_index
<< "}";
}
static inline void apply(std::ostringstream& oss,
Turns const& turns)
{
typedef typename boost::range_value<Turns>::type turn_type;
turn_type const& turn = range::front(turns);
oss << ". A self-intersection point was found at "
<< geometry::dsv(turn.point);
oss << "; method: " << method_char(turn.method)
<< "; operations: "
<< operation_char(turn.operations[0].operation)
<< "/"
<< operation_char(turn.operations[1].operation)
<< "; segment IDs {source, multi, ring, segment}: ";
apply_to_segment_identifier(oss, turn.operations[0].seg_id);
oss << "/";
apply_to_segment_identifier(oss, turn.operations[1].seg_id);
}
};
template <typename Point>
struct process_data<failure_duplicate_points, Point>
{
static inline void apply(std::ostringstream& oss,
Point const& point)
{
if (BOOST_GEOMETRY_CONDITION(AllowDuplicates))
{
return;
}
oss << ". Duplicate points were found near point "
<< geometry::dsv(point);
}
};
public:
failing_reason_policy(std::ostringstream& oss)
: m_oss(oss)
{}
template <validity_failure_type Failure>
inline bool apply()
{
validity_failure_type const failure = transform_failure_type(Failure);
set_failure_message(failure);
return failure == no_failure;
}
template <validity_failure_type Failure, typename Data>
inline bool apply(Data const& data)
{
validity_failure_type const failure = transform_failure_type(Failure);
set_failure_message(failure);
process_data<Failure, Data>::apply(m_oss, data);
return failure == no_failure;
}
template <validity_failure_type Failure, typename Data1, typename Data2>
inline bool apply(Data1 const& data1, Data2 const& data2)
{
validity_failure_type const failure
= transform_failure_type(Failure, data1);
set_failure_message(failure);
process_data<Failure, Data1, Data2>::apply(m_oss, data1, data2);
return failure == no_failure;
}
private:
std::ostringstream& m_oss;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_IS_VALID_FAILING_REASON_POLICY_HPP
@@ -0,0 +1,83 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_POLICIES_IS_VALID_FAILURE_TYPE_POLICY_HPP
#define BOOST_GEOMETRY_POLICIES_IS_VALID_FAILURE_TYPE_POLICY_HPP
#include <boost/geometry/algorithms/validity_failure_type.hpp>
namespace boost { namespace geometry
{
// policy that simply keeps (and can return) the failure type
template <bool AllowDuplicates = true, bool AllowSpikes = true>
class failure_type_policy
{
private:
static inline
validity_failure_type transform_failure_type(validity_failure_type failure)
{
if (AllowDuplicates && failure == failure_duplicate_points)
{
return no_failure;
}
return failure;
}
static inline
validity_failure_type transform_failure_type(validity_failure_type failure,
bool is_linear)
{
if (is_linear && AllowSpikes && failure == failure_spikes)
{
return no_failure;
}
return transform_failure_type(failure);
}
public:
failure_type_policy()
: m_failure(no_failure)
{}
template <validity_failure_type Failure>
inline bool apply()
{
m_failure = transform_failure_type(Failure);
return m_failure == no_failure;
}
template <validity_failure_type Failure, typename Data>
inline bool apply(Data const&)
{
return apply<Failure>();
}
template <validity_failure_type Failure, typename Data1, typename Data2>
inline bool apply(Data1 const& data1, Data2 const&)
{
m_failure = transform_failure_type(Failure, data1);
return m_failure == no_failure;
}
validity_failure_type failure() const
{
return m_failure;
}
private:
validity_failure_type m_failure;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_IS_VALID_FAILURE_TYPE_POLICY_HPP
@@ -0,0 +1,101 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay
{
template
<
typename IsAcceptableTurnPredicate,
bool AllowEmptyTurnRange = true // by default, allow an empty turn range
>
struct stateless_predicate_based_interrupt_policy
{
static bool const enabled = true;
bool has_intersections; // set to true if there is at least one
// unacceptable turn
inline stateless_predicate_based_interrupt_policy()
: has_intersections(false)
{}
template <typename Range>
inline bool apply(Range const& range)
{
// if there is at least one unacceptable turn in the range, return false
has_intersections = !detail::check_iterator_range
<
IsAcceptableTurnPredicate,
AllowEmptyTurnRange
>::apply(boost::begin(range), boost::end(range));
return has_intersections;
}
};
template
<
typename IsAcceptableTurnPredicate,
bool AllowEmptyTurnRange = true // by default, allow an empty turn range
>
struct predicate_based_interrupt_policy
{
static bool const enabled = true;
bool has_intersections; // set to true if there is at least one
// unacceptable turn
IsAcceptableTurnPredicate const& m_predicate;
inline
predicate_based_interrupt_policy(IsAcceptableTurnPredicate const& predicate)
: has_intersections(false)
, m_predicate(predicate)
{}
template <typename Range>
inline bool apply(Range const& range)
{
// if there is at least one unacceptable turn in the range, return false
has_intersections = !detail::check_iterator_range
<
IsAcceptableTurnPredicate,
AllowEmptyTurnRange
>::apply(boost::begin(range), boost::end(range), m_predicate);
return has_intersections;
}
};
}} // namespace detail::overlay
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP
@@ -0,0 +1,391 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 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_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
#include <cstddef>
#include <string>
#include <boost/concept_check.hpp>
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace policies { namespace relate
{
struct direction_type
{
// NOTE: "char" will be replaced by enum in future version
inline direction_type(side_info const& s, char h,
int ha, int hb,
int da = 0, int db = 0,
bool op = false)
: how(h)
, opposite(op)
, how_a(ha)
, how_b(hb)
, dir_a(da)
, dir_b(db)
, sides(s)
{
arrival[0] = ha;
arrival[1] = hb;
}
inline direction_type(char h, bool op, int ha = 0, int hb = 0)
: how(h)
, opposite(op)
, how_a(ha)
, how_b(hb)
, dir_a(0)
, dir_b(0)
{
arrival[0] = ha;
arrival[1] = hb;
}
// TODO: replace this
// NOTE: "char" will be replaced by enum in future version
// "How" is the intersection formed?
char how;
// Is it opposite (for collinear/equal cases)
bool opposite;
// Information on how A arrives at intersection, how B arrives at intersection
// 1: arrives at intersection
// -1: starts from intersection
int how_a;
int how_b;
// Direction: how is A positioned from B
// 1: points left, seen from IP
// -1: points right, seen from IP
// In case of intersection: B's TO direction
// In case that B's TO direction is at A: B's from direction
// In collinear cases: it is 0
int dir_a; // Direction of A-s TO from IP
int dir_b; // Direction of B-s TO from IP
// New information
side_info sides;
// THIS IS EQUAL TO arrival_a, arrival_b - they probably can go now we have robust fractions
int arrival[2]; // 1=arrival, -1=departure, 0=neutral; == how_a//how_b
// About arrival[0] (== arrival of a2 w.r.t. b) for COLLINEAR cases
// Arrival 1: a1--------->a2 (a arrives within b)
// b1----->b2
// Arrival 1: (a in b)
//
// Arrival -1: a1--------->a2 (a does not arrive within b)
// b1----->b2
// Arrival -1: (b in a) a_1-------------a_2
// b_1---b_2
// Arrival 0: a1------->a2 (a arrives at TO-border of b)
// b1--->b2
};
struct segments_direction
{
typedef direction_type return_type;
template
<
typename Segment1,
typename Segment2,
typename SegmentIntersectionInfo
>
static inline return_type segments_crosses(side_info const& sides,
SegmentIntersectionInfo const& ,
Segment1 const& , Segment2 const& )
{
bool const ra0 = sides.get<0,0>() == 0;
bool const ra1 = sides.get<0,1>() == 0;
bool const rb0 = sides.get<1,0>() == 0;
bool const rb1 = sides.get<1,1>() == 0;
return
// opposite and same starting point (FROM)
ra0 && rb0 ? calculate_side<1>(sides, 'f', -1, -1)
// opposite and point to each other (TO)
: ra1 && rb1 ? calculate_side<0>(sides, 't', 1, 1)
// not opposite, forming an angle, first a then b,
// directed either both left, or both right
// Check side of B2 from A. This is not calculated before
: ra1 && rb0 ? angle<1>(sides, 'a', 1, -1)
// not opposite, forming a angle, first b then a,
// directed either both left, or both right
: ra0 && rb1 ? angle<0>(sides, 'a', -1, 1)
// b starts from interior of a
: rb0 ? starts_from_middle(sides, 'B', 0, -1)
// a starts from interior of b (#39)
: ra0 ? starts_from_middle(sides, 'A', -1, 0)
// b ends at interior of a, calculate direction of A from IP
: rb1 ? b_ends_at_middle(sides)
// a ends at interior of b
: ra1 ? a_ends_at_middle(sides)
// normal intersection
: calculate_side<1>(sides, 'i', -1, -1)
;
}
template <typename Ratio>
static inline int arrival_value(Ratio const& r_from, Ratio const& r_to)
{
// a1--------->a2
// b1----->b2
// a departs: -1
// a1--------->a2
// b1----->b2
// a arrives: 1
// a1--------->a2
// b1----->b2
// both arrive there -> r-to = 1/1, or 0/1 (on_segment)
// First check the TO (for arrival), then FROM (for departure)
return r_to.in_segment() ? 1
: r_to.on_segment() ? 0
: r_from.on_segment() ? -1
: -1
;
}
template <typename Ratio>
static inline void analyze(Ratio const& r,
int& in_segment_count,
int& on_end_count,
int& outside_segment_count)
{
if (r.on_end())
{
on_end_count++;
}
else if (r.in_segment())
{
in_segment_count++;
}
else
{
outside_segment_count++;
}
}
static inline int arrival_from_position_value(int /*v_from*/, int v_to)
{
return v_to == 2 ? 1
: v_to == 1 || v_to == 3 ? 0
//: v_from >= 1 && v_from <= 3 ? -1
: -1;
// NOTE: this should be an equivalent of the above for the other order
/* (v_from < 3 && v_to > 3) || (v_from > 3 && v_to < 3) ? 1
: v_from == 3 || v_to == 3 ? 0
: -1;*/
}
static inline void analyse_position_value(int pos_val,
int & in_segment_count,
int & on_end_count,
int & outside_segment_count)
{
if ( pos_val == 1 || pos_val == 3 )
{
on_end_count++;
}
else if ( pos_val == 2 )
{
in_segment_count++;
}
else
{
outside_segment_count++;
}
}
template <typename Segment1, typename Segment2, typename Ratio>
static inline return_type segments_collinear(
Segment1 const& , Segment2 const& , bool opposite,
int a1_wrt_b, int a2_wrt_b, int b1_wrt_a, int b2_wrt_a,
Ratio const& /*ra_from_wrt_b*/, Ratio const& /*ra_to_wrt_b*/,
Ratio const& /*rb_from_wrt_a*/, Ratio const& /*rb_to_wrt_a*/)
{
return_type r('c', opposite);
// IMPORTANT: the order of conditions is different as in intersection_points.hpp
// We assign A in 0 and B in 1
r.arrival[0] = arrival_from_position_value(a1_wrt_b, a2_wrt_b);
r.arrival[1] = arrival_from_position_value(b1_wrt_a, b2_wrt_a);
// Analyse them
int a_in_segment_count = 0;
int a_on_end_count = 0;
int a_outside_segment_count = 0;
int b_in_segment_count = 0;
int b_on_end_count = 0;
int b_outside_segment_count = 0;
analyse_position_value(a1_wrt_b,
a_in_segment_count, a_on_end_count, a_outside_segment_count);
analyse_position_value(a2_wrt_b,
a_in_segment_count, a_on_end_count, a_outside_segment_count);
analyse_position_value(b1_wrt_a,
b_in_segment_count, b_on_end_count, b_outside_segment_count);
analyse_position_value(b2_wrt_a,
b_in_segment_count, b_on_end_count, b_outside_segment_count);
if (a_on_end_count == 1
&& b_on_end_count == 1
&& a_outside_segment_count == 1
&& b_outside_segment_count == 1)
{
// This is a collinear touch
// --------> A (or B)
// <---------- B (or A)
// We adapt the "how"
// TODO: how was to be refactored anyway,
if (! opposite)
{
r.how = 'a';
}
else
{
r.how = r.arrival[0] == 0 ? 't' : 'f';
}
}
else if (a_on_end_count == 2
&& b_on_end_count == 2)
{
r.how = 'e';
}
return r;
}
template <typename Segment>
static inline return_type degenerate(Segment const& , bool)
{
return return_type('0', false);
}
template <typename Segment, typename Ratio>
static inline return_type one_degenerate(Segment const& ,
Ratio const& ,
bool)
{
// To be decided
return return_type('0', false);
}
static inline return_type disjoint()
{
return return_type('d', false);
}
static inline return_type error(std::string const&)
{
// Return "E" to denote error
// This will throw an error in get_turn_info
// TODO: change to enum or similar
return return_type('E', false);
}
private :
template <std::size_t I>
static inline return_type calculate_side(side_info const& sides,
char how, int how_a, int how_b)
{
int const dir = sides.get<1, I>() == 1 ? 1 : -1;
return return_type(sides, how, how_a, how_b, -dir, dir);
}
template <std::size_t I>
static inline return_type angle(side_info const& sides,
char how, int how_a, int how_b)
{
int const dir = sides.get<1, I>() == 1 ? 1 : -1;
return return_type(sides, how, how_a, how_b, dir, dir);
}
static inline return_type starts_from_middle(side_info const& sides,
char which,
int how_a, int how_b)
{
// Calculate ARROW of b segment w.r.t. s1
int dir = sides.get<1, 1>() == 1 ? 1 : -1;
// From other perspective, then reverse
bool const is_a = which == 'A';
if (is_a)
{
dir = -dir;
}
return return_type(sides, 's',
how_a,
how_b,
is_a ? dir : -dir,
! is_a ? dir : -dir);
}
// To be harmonized
static inline return_type a_ends_at_middle(side_info const& sides)
{
// Ending at the middle, one ARRIVES, the other one is NEUTRAL
// (because it both "arrives" and "departs" there)
int const dir = sides.get<1, 1>() == 1 ? 1 : -1;
return return_type(sides, 'm', 1, 0, dir, dir);
}
static inline return_type b_ends_at_middle(side_info const& sides)
{
int const dir = sides.get<0, 1>() == 1 ? 1 : -1;
return return_type(sides, 'm', 0, 1, dir, dir);
}
};
}} // namespace policies::relate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
@@ -0,0 +1,226 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2016.
// Modifications copyright (c) 2016 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_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
#include <algorithm>
#include <string>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/strategies/side_info.hpp>
namespace boost { namespace geometry
{
namespace policies { namespace relate
{
/*!
\brief Policy calculating the intersection points themselves
*/
template
<
typename ReturnType
>
struct segments_intersection_points
{
typedef ReturnType return_type;
template
<
typename Segment1,
typename Segment2,
typename SegmentIntersectionInfo
>
static inline return_type segments_crosses(side_info const&,
SegmentIntersectionInfo const& sinfo,
Segment1 const& s1, Segment2 const& s2)
{
return_type result;
result.count = 1;
bool use_a = true;
// Prefer one segment if one is on or near an endpoint
bool const a_near_end = sinfo.robust_ra.near_end();
bool const b_near_end = sinfo.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
typedef typename SegmentIntersectionInfo::promoted_type ptype;
ptype const len_a = sinfo.comparable_length_a();
ptype const len_b = sinfo.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)
{
sinfo.assign_a(result.intersections[0], s1, s2);
}
else
{
sinfo.assign_b(result.intersections[0], s1, s2);
}
result.fractions[0].assign(sinfo);
return result;
}
template <typename Segment1, typename Segment2, typename Ratio>
static inline return_type segments_collinear(
Segment1 const& a, Segment2 const& b, bool /*opposite*/,
int a1_wrt_b, int a2_wrt_b, int b1_wrt_a, int b2_wrt_a,
Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
{
return_type result;
unsigned int index = 0, count_a = 0, count_b = 0;
Ratio on_a[2];
// The conditions "index < 2" are necessary for non-robust handling,
// if index would be 2 this indicate an (currently uncatched) error
// IMPORTANT: the order of conditions is different as in direction.hpp
if (a1_wrt_b >= 1 && a1_wrt_b <= 3 // ra_from_wrt_b.on_segment()
&& index < 2)
{
// a1--------->a2
// b1----->b2
//
// ra1 (relative to b) is between 0/1:
// -> First point of A is intersection point
detail::assign_point_from_index<0>(a, result.intersections[index]);
result.fractions[index].assign(Ratio::zero(), ra_from_wrt_b);
on_a[index] = Ratio::zero();
index++;
count_a++;
}
if (b1_wrt_a == 2 //rb_from_wrt_a.in_segment()
&& index < 2)
{
// We take the first intersection point of B
// a1--------->a2
// b1----->b2
// But only if it is not located on A
// a1--------->a2
// b1----->b2 rb_from_wrt_a == 0/1 -> a already taken
detail::assign_point_from_index<0>(b, result.intersections[index]);
result.fractions[index].assign(rb_from_wrt_a, Ratio::zero());
on_a[index] = rb_from_wrt_a;
index++;
count_b++;
}
if (a2_wrt_b >= 1 && a2_wrt_b <= 3 //ra_to_wrt_b.on_segment()
&& index < 2)
{
// Similarly, second IP (here a2)
// a1--------->a2
// b1----->b2
detail::assign_point_from_index<1>(a, result.intersections[index]);
result.fractions[index].assign(Ratio::one(), ra_to_wrt_b);
on_a[index] = Ratio::one();
index++;
count_a++;
}
if (b2_wrt_a == 2 // rb_to_wrt_a.in_segment()
&& index < 2)
{
detail::assign_point_from_index<1>(b, result.intersections[index]);
result.fractions[index].assign(rb_to_wrt_a, Ratio::one());
on_a[index] = rb_to_wrt_a;
index++;
count_b++;
}
// TEMPORARY
// If both are from b, and b is reversed w.r.t. a, we swap IP's
// to align them w.r.t. a
// get_turn_info still relies on some order (in some collinear cases)
if (index == 2 && on_a[1] < on_a[0])
{
std::swap(result.fractions[0], result.fractions[1]);
std::swap(result.intersections[0], result.intersections[1]);
}
result.count = index;
return result;
}
static inline return_type disjoint()
{
return return_type();
}
static inline return_type error(std::string const&)
{
return return_type();
}
// Both degenerate
template <typename Segment>
static inline return_type degenerate(Segment const& segment, bool)
{
return_type result;
result.count = 1;
set<0>(result.intersections[0], get<0, 0>(segment));
set<1>(result.intersections[0], get<0, 1>(segment));
return result;
}
// One degenerate
template <typename Segment, typename Ratio>
static inline return_type one_degenerate(Segment const& degenerate_segment,
Ratio const& ratio, bool a_degenerate)
{
return_type result;
result.count = 1;
set<0>(result.intersections[0], get<0, 0>(degenerate_segment));
set<1>(result.intersections[0], get<0, 1>(degenerate_segment));
if (a_degenerate)
{
// IP lies on ratio w.r.t. segment b
result.fractions[0].assign(Ratio::zero(), ratio);
}
else
{
result.fractions[0].assign(ratio, Ratio::zero());
}
return result;
}
};
}} // namespace policies::relate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
@@ -0,0 +1,127 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-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_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP
#include <algorithm>
#include <string>
#include <boost/concept_check.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/side_info.hpp>
namespace boost { namespace geometry
{
namespace policies { namespace relate
{
/*!
\brief Policy returning segment ratios
\note Template argument FractionType should be a fraction_type<SegmentRatio>
*/
template
<
typename FractionType
>
struct segments_intersection_ratios
{
typedef FractionType return_type;
template
<
typename Segment1,
typename Segment2,
typename SegmentIntersectionInfo
>
static inline return_type segments_crosses(side_info const&,
SegmentIntersectionInfo const& sinfo,
Segment1 const& , Segment2 const& )
{
return_type result;
result.assign(sinfo);
return result;
}
template <typename Segment1, typename Segment2, typename Ratio>
static inline return_type segments_collinear(
Segment1 const& , Segment2 const& ,
Ratio const& ra_from_wrt_b, Ratio const& ra_to_wrt_b,
Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
{
// We have only one result, for (potentially) two IP's,
// so we take a first one
return_type result;
if (ra_from_wrt_b.on_segment())
{
result.assign(Ratio::zero(), ra_from_wrt_b);
}
else if (rb_from_wrt_a.in_segment())
{
result.assign(rb_from_wrt_a, Ratio::zero());
}
else if (ra_to_wrt_b.on_segment())
{
result.assign(Ratio::one(), ra_to_wrt_b);
}
else if (rb_to_wrt_a.in_segment())
{
result.assign(rb_to_wrt_a, Ratio::one());
}
return result;
}
static inline return_type disjoint()
{
return return_type();
}
static inline return_type error(std::string const&)
{
return return_type();
}
template <typename Segment>
static inline return_type degenerate(Segment const& segment, bool)
{
return return_type();
}
template <typename Segment, typename Ratio>
static inline return_type one_degenerate(Segment const& ,
Ratio const& ratio, bool a_degenerate)
{
return_type result;
if (a_degenerate)
{
// IP lies on ratio w.r.t. segment b
result.assign(Ratio::zero(), ratio);
}
else
{
result.assign(ratio, Ratio::zero());
}
return result;
}
};
}} // namespace policies::relate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_RATIOS_HPP
@@ -0,0 +1,116 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 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_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
#include <string>
#include <boost/tuple/tuple.hpp>
#include <boost/geometry/strategies/side_info.hpp>
namespace boost { namespace geometry
{
namespace policies { namespace relate
{
// "tupled" to return intersection results together.
// Now with two, with some meta-programming and derivations it can also be three (or more)
template <typename Policy1, typename Policy2>
struct segments_tupled
{
typedef boost::tuple
<
typename Policy1::return_type,
typename Policy2::return_type
> return_type;
template <typename Segment1, typename Segment2, typename SegmentIntersectionInfo>
static inline return_type segments_crosses(side_info const& sides,
SegmentIntersectionInfo const& sinfo,
Segment1 const& s1, Segment2 const& s2)
{
return boost::make_tuple
(
Policy1::segments_crosses(sides, sinfo, s1, s2),
Policy2::segments_crosses(sides, sinfo, s1, s2)
);
}
template <typename Segment1, typename Segment2, typename Ratio>
static inline return_type segments_collinear(
Segment1 const& segment1, Segment2 const& segment2,
bool opposite,
int pa1, int pa2, int pb1, int pb2,
Ratio const& ra1, Ratio const& ra2,
Ratio const& rb1, Ratio const& rb2)
{
return boost::make_tuple
(
Policy1::segments_collinear(segment1, segment2,
opposite,
pa1, pa2, pb1, pb2,
ra1, ra2, rb1, rb2),
Policy2::segments_collinear(segment1, segment2,
opposite,
pa1, pa2, pb1, pb2,
ra1, ra2, rb1, rb2)
);
}
template <typename Segment>
static inline return_type degenerate(Segment const& segment,
bool a_degenerate)
{
return boost::make_tuple
(
Policy1::degenerate(segment, a_degenerate),
Policy2::degenerate(segment, a_degenerate)
);
}
template <typename Segment, typename Ratio>
static inline return_type one_degenerate(Segment const& segment,
Ratio const& ratio,
bool a_degenerate)
{
return boost::make_tuple
(
Policy1::one_degenerate(segment, ratio, a_degenerate),
Policy2::one_degenerate(segment, ratio, a_degenerate)
);
}
static inline return_type disjoint()
{
return boost::make_tuple
(
Policy1::disjoint(),
Policy2::disjoint()
);
}
static inline return_type error(std::string const& msg)
{
return boost::make_tuple
(
Policy1::error(msg),
Policy2::error(msg)
);
}
};
}} // namespace policies::relate
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
@@ -0,0 +1,341 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2014-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 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 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_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
#include <cstddef>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/algorithms/detail/get_max_size.hpp>
#include <boost/geometry/policies/robustness/robust_type.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/rescale_policy.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace get_rescale_policy
{
template
<
typename Box,
typename Point,
typename RobustPoint,
typename Factor
>
inline void scale_box_to_integer_range(Box const& box,
Point& min_point,
RobustPoint& min_robust_point,
Factor& factor)
{
// Scale box to integer-range
typedef typename promote_floating_point
<
typename geometry::coordinate_type<Point>::type
>::type num_type;
num_type const diff = boost::numeric_cast<num_type>(detail::get_max_size(box));
num_type const range = 10000000.0; // Define a large range to get precise integer coordinates
num_type const half = 0.5;
if (math::equals(diff, num_type())
|| diff >= range
|| ! boost::math::isfinite(diff))
{
factor = 1;
}
else
{
factor = boost::numeric_cast<num_type>(
boost::numeric_cast<boost::long_long_type>(half + range / diff));
BOOST_GEOMETRY_ASSERT(factor >= 1);
}
// Assign input/output minimal points
detail::assign_point_from_index<0>(box, min_point);
num_type const two = 2;
boost::long_long_type const min_coordinate
= boost::numeric_cast<boost::long_long_type>(-range / two);
assign_values(min_robust_point, min_coordinate, min_coordinate);
}
template <typename Point, typename RobustPoint, typename Geometry, typename Factor>
static inline void init_rescale_policy(Geometry const& geometry,
Point& min_point,
RobustPoint& min_robust_point,
Factor& factor)
{
if (geometry::is_empty(geometry))
{
return;
}
// Get bounding boxes
model::box<Point> env = geometry::return_envelope<model::box<Point> >(geometry);
scale_box_to_integer_range(env, min_point, min_robust_point, factor);
}
template <typename Point, typename RobustPoint, typename Geometry1, typename Geometry2, typename Factor>
static inline void init_rescale_policy(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Point& min_point,
RobustPoint& min_robust_point,
Factor& factor)
{
// Get bounding boxes (when at least one of the geometries is not empty)
bool const is_empty1 = geometry::is_empty(geometry1);
bool const is_empty2 = geometry::is_empty(geometry2);
if (is_empty1 && is_empty2)
{
return;
}
model::box<Point> env;
if (is_empty1)
{
geometry::envelope(geometry2, env);
}
else if (is_empty2)
{
geometry::envelope(geometry1, env);
}
else
{
// The following approach (envelope + expand) may not give the
// optimal MBR when then two geometries are in the spherical
// equatorial or geographic coordinate systems.
// TODO: implement envelope for two (or possibly more geometries)
geometry::envelope(geometry1, env);
model::box<Point> env2 = geometry::return_envelope
<
model::box<Point>
>(geometry2);
geometry::expand(env, env2);
}
scale_box_to_integer_range(env, min_point, min_robust_point, factor);
}
template
<
typename Point,
bool IsFloatingPoint
>
struct rescale_policy_type
{
typedef no_rescale_policy type;
};
// We rescale only all FP types
template
<
typename Point
>
struct rescale_policy_type<Point, true>
{
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
typedef model::point
<
typename detail::robust_type<coordinate_type>::type,
geometry::dimension<Point>::value,
typename geometry::coordinate_system<Point>::type
> robust_point_type;
typedef typename promote_floating_point<coordinate_type>::type factor_type;
typedef detail::robust_policy<Point, robust_point_type, factor_type> type;
};
template <typename Policy>
struct get_rescale_policy
{
template <typename Geometry>
static inline Policy apply(Geometry const& geometry)
{
typedef typename point_type<Geometry>::type point_type;
typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;
typedef typename promote_floating_point<coordinate_type>::type factor_type;
typedef model::point
<
typename detail::robust_type<coordinate_type>::type,
geometry::dimension<point_type>::value,
typename geometry::coordinate_system<point_type>::type
> robust_point_type;
point_type min_point;
robust_point_type min_robust_point;
factor_type factor;
init_rescale_policy(geometry, min_point, min_robust_point, factor);
return Policy(min_point, min_robust_point, factor);
}
template <typename Geometry1, typename Geometry2>
static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
typedef typename point_type<Geometry1>::type point_type;
typedef typename geometry::coordinate_type<Geometry1>::type coordinate_type;
typedef typename promote_floating_point<coordinate_type>::type factor_type;
typedef model::point
<
typename detail::robust_type<coordinate_type>::type,
geometry::dimension<point_type>::value,
typename geometry::coordinate_system<point_type>::type
> robust_point_type;
point_type min_point;
robust_point_type min_robust_point;
factor_type factor;
init_rescale_policy(geometry1, geometry2, min_point, min_robust_point, factor);
return Policy(min_point, min_robust_point, factor);
}
};
// Specialization for no-rescaling
template <>
struct get_rescale_policy<no_rescale_policy>
{
template <typename Geometry>
static inline no_rescale_policy apply(Geometry const& )
{
return no_rescale_policy();
}
template <typename Geometry1, typename Geometry2>
static inline no_rescale_policy apply(Geometry1 const& , Geometry2 const& )
{
return no_rescale_policy();
}
};
}} // namespace detail::get_rescale_policy
#endif // DOXYGEN_NO_DETAIL
template<typename Point>
struct rescale_policy_type
: public detail::get_rescale_policy::rescale_policy_type
<
Point,
#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
false
#else
boost::is_floating_point
<
typename geometry::coordinate_type<Point>::type
>::type::value
&&
boost::is_same
<
typename geometry::coordinate_system<Point>::type,
geometry::cs::cartesian
>::value
#endif
>
{
static const bool is_point
= boost::is_same
<
typename geometry::tag<Point>::type,
geometry::point_tag
>::type::value;
BOOST_MPL_ASSERT_MSG((is_point),
INVALID_INPUT_GEOMETRY,
(typename geometry::tag<Point>::type));
};
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag_cast
<
typename tag<Geometry1>::type,
box_tag,
pointlike_tag,
linear_tag,
areal_tag
>::type,
typename Tag2 = typename tag_cast
<
typename tag<Geometry2>::type,
box_tag,
pointlike_tag,
linear_tag,
areal_tag
>::type
>
struct rescale_overlay_policy_type
// Default: no rescaling
: public detail::get_rescale_policy::rescale_policy_type
<
typename geometry::point_type<Geometry1>::type,
false
>
{};
// Areal/areal: get rescale policy based on coordinate type
template
<
typename Geometry1,
typename Geometry2
>
struct rescale_overlay_policy_type<Geometry1, Geometry2, areal_tag, areal_tag>
: public rescale_policy_type
<
typename geometry::point_type<Geometry1>::type
>
{};
template <typename Policy, typename Geometry>
inline Policy get_rescale_policy(Geometry const& geometry)
{
return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry);
}
template <typename Policy, typename Geometry1, typename Geometry2>
inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry1, geometry2);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
@@ -0,0 +1,66 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013 Bruno Lalande, Paris, France.
// Copyright (c) 2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
// 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_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP
#include <stddef.h>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// Probably this will be moved out of namespace detail
struct no_rescale_policy
{
static bool const enabled = false;
// We don't rescale but return the reference of the input
template <std::size_t Dimension, typename Value>
inline Value const& apply(Value const& value) const
{
return value;
}
};
} // namespace detail
#endif
// Implement meta-functions for this policy
template <typename Point>
struct robust_point_type<Point, detail::no_rescale_policy>
{
// The point itself
typedef Point type;
};
template <typename Point>
struct segment_ratio_type<Point, detail::no_rescale_policy>
{
// Define a segment_ratio defined on coordinate type, e.g.
// int/int or float/float
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
typedef segment_ratio<coordinate_type> type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_NO_RESCALE_POLICY_HPP
@@ -0,0 +1,88 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2014-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2015, 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_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP
#include <cstddef>
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename FpPoint, typename IntPoint, typename CalculationType>
struct robust_policy
{
static bool const enabled = true;
typedef typename geometry::coordinate_type<IntPoint>::type output_ct;
robust_policy(FpPoint const& fp_min, IntPoint const& int_min, CalculationType const& the_factor)
: m_fp_min(fp_min)
, m_int_min(int_min)
, m_multiplier(the_factor)
{
}
template <std::size_t Dimension, typename Value>
inline output_ct apply(Value const& value) const
{
// a + (v-b)*f
CalculationType const a = static_cast<CalculationType>(get<Dimension>(m_int_min));
CalculationType const b = static_cast<CalculationType>(get<Dimension>(m_fp_min));
CalculationType const result = a + (value - b) * m_multiplier;
return geometry::math::rounding_cast<output_ct>(result);
}
FpPoint m_fp_min;
IntPoint m_int_min;
CalculationType m_multiplier;
};
} // namespace detail
#endif
// Implement meta-functions for this policy
// Define the IntPoint as a robust-point type
template <typename Point, typename FpPoint, typename IntPoint, typename CalculationType>
struct robust_point_type<Point, detail::robust_policy<FpPoint, IntPoint, CalculationType> >
{
typedef IntPoint type;
};
// Meta function for rescaling, if rescaling is done segment_ratio is based on long long
template <typename Point, typename FpPoint, typename IntPoint, typename CalculationType>
struct segment_ratio_type<Point, detail::robust_policy<FpPoint, IntPoint, CalculationType> >
{
typedef segment_ratio<boost::long_long_type> type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_HPP
@@ -0,0 +1,30 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013 Bruno Lalande, Paris, France.
// Copyright (c) 2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
// 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_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP
namespace boost { namespace geometry
{
// Meta-function to typedef a robust point type for a policy
template <typename Point, typename Policy>
struct robust_point_type
{
// By default, the point itself is the robust type
typedef Point type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_POINT_TYPE_HPP
@@ -0,0 +1,67 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014 Bruno Lalande, Paris, France.
// Copyright (c) 2014 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
// 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_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP
#include <boost/config.hpp>
#include <boost/type_traits/is_floating_point.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail_dispatch
{
template <typename CoordinateType, typename IsFloatingPoint>
struct robust_type
{
};
template <typename CoordinateType>
struct robust_type<CoordinateType, boost::false_type>
{
typedef CoordinateType type;
};
template <typename CoordinateType>
struct robust_type<CoordinateType, boost::true_type>
{
typedef boost::long_long_type type;
};
} // namespace detail_dispatch
namespace detail
{
template <typename CoordinateType>
struct robust_type
{
typedef typename detail_dispatch::robust_type
<
CoordinateType,
typename boost::is_floating_point<CoordinateType>::type
>::type type;
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_ROBUST_TYPE_HPP
@@ -0,0 +1,267 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2016.
// Modifications copyright (c) 2016 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_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
#include <boost/config.hpp>
#include <boost/rational.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/promote_floating_point.hpp>
namespace boost { namespace geometry
{
namespace detail { namespace segment_ratio
{
template
<
typename Type,
bool IsIntegral = boost::is_integral<Type>::type::value
>
struct less {};
template <typename Type>
struct less<Type, true>
{
template <typename Ratio>
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
{
return boost::rational<Type>(lhs.numerator(), lhs.denominator())
< boost::rational<Type>(rhs.numerator(), rhs.denominator());
}
};
template <typename Type>
struct less<Type, false>
{
template <typename Ratio>
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
{
BOOST_GEOMETRY_ASSERT(lhs.denominator() != 0);
BOOST_GEOMETRY_ASSERT(rhs.denominator() != 0);
return lhs.numerator() * rhs.denominator()
< rhs.numerator() * lhs.denominator();
}
};
template
<
typename Type,
bool IsIntegral = boost::is_integral<Type>::type::value
>
struct equal {};
template <typename Type>
struct equal<Type, true>
{
template <typename Ratio>
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
{
return boost::rational<Type>(lhs.numerator(), lhs.denominator())
== boost::rational<Type>(rhs.numerator(), rhs.denominator());
}
};
template <typename Type>
struct equal<Type, false>
{
template <typename Ratio>
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
{
BOOST_GEOMETRY_ASSERT(lhs.denominator() != 0);
BOOST_GEOMETRY_ASSERT(rhs.denominator() != 0);
return geometry::math::equals
(
lhs.numerator() * rhs.denominator(),
rhs.numerator() * lhs.denominator()
);
}
};
}}
//! Small class to keep a ratio (e.g. 1/4)
//! Main purpose is intersections and checking on 0, 1, and smaller/larger
//! The prototype used Boost.Rational. However, we also want to store FP ratios,
//! (so numerator/denominator both in float)
//! and Boost.Rational starts with GCD which we prefer to avoid if not necessary
//! On a segment means: this ratio is between 0 and 1 (both inclusive)
//!
template <typename Type>
class segment_ratio
{
public :
typedef Type numeric_type;
// Type-alias for the type itself
typedef segment_ratio<Type> thistype;
inline segment_ratio()
: m_numerator(0)
, m_denominator(1)
, m_approximation(0)
{}
inline segment_ratio(const Type& nominator, const Type& denominator)
: m_numerator(nominator)
, m_denominator(denominator)
{
initialize();
}
inline Type const& numerator() const { return m_numerator; }
inline Type const& denominator() const { return m_denominator; }
inline void assign(const Type& nominator, const Type& denominator)
{
m_numerator = nominator;
m_denominator = denominator;
initialize();
}
inline void initialize()
{
// Minimal normalization
// 1/-4 => -1/4, -1/-4 => 1/4
if (m_denominator < 0)
{
m_numerator = -m_numerator;
m_denominator = -m_denominator;
}
m_approximation =
m_denominator == 0 ? 0
: (
boost::numeric_cast<fp_type>(m_numerator) * scale()
/ boost::numeric_cast<fp_type>(m_denominator)
);
}
inline bool is_zero() const { return math::equals(m_numerator, 0); }
inline bool is_one() const { return math::equals(m_numerator, m_denominator); }
inline bool on_segment() const
{
// e.g. 0/4 or 4/4 or 2/4
return m_numerator >= 0 && m_numerator <= m_denominator;
}
inline bool in_segment() const
{
// e.g. 1/4
return m_numerator > 0 && m_numerator < m_denominator;
}
inline bool on_end() const
{
// e.g. 0/4 or 4/4
return is_zero() || is_one();
}
inline bool left() const
{
// e.g. -1/4
return m_numerator < 0;
}
inline bool right() const
{
// e.g. 5/4
return m_numerator > m_denominator;
}
inline bool near_end() const
{
if (left() || right())
{
return false;
}
static fp_type const small_part_of_scale = scale() / 100;
return m_approximation < small_part_of_scale
|| m_approximation > scale() - small_part_of_scale;
}
inline bool close_to(thistype const& other) const
{
return geometry::math::abs(m_approximation - other.m_approximation) < 50;
}
inline bool operator< (thistype const& other) const
{
return close_to(other)
? detail::segment_ratio::less<Type>::apply(*this, other)
: m_approximation < other.m_approximation;
}
inline bool operator== (thistype const& other) const
{
return close_to(other)
&& detail::segment_ratio::equal<Type>::apply(*this, other);
}
static inline thistype zero()
{
static thistype result(0, 1);
return result;
}
static inline thistype one()
{
static thistype result(1, 1);
return result;
}
#if defined(BOOST_GEOMETRY_DEFINE_STREAM_OPERATOR_SEGMENT_RATIO)
friend std::ostream& operator<<(std::ostream &os, segment_ratio const& ratio)
{
os << ratio.m_numerator << "/" << ratio.m_denominator
<< " (" << (static_cast<double>(ratio.m_numerator)
/ static_cast<double>(ratio.m_denominator))
<< ")";
return os;
}
#endif
private :
// NOTE: if this typedef is used then fp_type is non-fundamental type
// if Type is non-fundamental type
//typedef typename promote_floating_point<Type>::type fp_type;
typedef typename boost::mpl::if_c
<
boost::is_float<Type>::value, Type, double
>::type fp_type;
Type m_numerator;
Type m_denominator;
// Contains ratio on scale 0..1000000 (for 0..1)
// This is an approximation for fast and rough comparisons
// Boost.Rational is used if the approximations are close.
// Reason: performance, Boost.Rational does a GCD by default and also the
// comparisons contain while-loops.
fp_type m_approximation;
static inline fp_type scale()
{
return 1000000.0;
}
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_HPP
@@ -0,0 +1,28 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013 Bruno Lalande, Paris, France.
// Copyright (c) 2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland.
// 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_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP
#include <boost/geometry/algorithms/not_implemented.hpp>
namespace boost { namespace geometry
{
// Meta-function to access segment-ratio for a policy
template <typename Point, typename Policy>
struct segment_ratio_type {}; // : not_implemented<> {};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP