Merge branch 'develop' into bg-prepare

This commit is contained in:
Adam Wulkiewicz
2019-10-24 17:34:16 +02:00
104 changed files with 3263 additions and 1300 deletions

View File

@@ -614,6 +614,8 @@
<member><link linkend="geometry.reference.strategies.strategy_simplify_douglas_peucker">strategy::simplify::douglas_peucker</link></member>
</simplelist>
</entry>
</row>
<row>
<entry valign="top">
<bridgehead renderas="sect3">Transform</bridgehead>
<simplelist type="vert" columns="1">
@@ -625,9 +627,7 @@
<member><link linkend="geometry.reference.strategies.strategy_transform_rotate_transformer">strategy::transform::rotate_transformer</link></member>
</simplelist>
</entry>
</row>
<row>
<entry valign="top" namest="a" nameend="c">
<entry valign="top" namest="b" nameend="c">
<bridgehead renderas="sect3">Within</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="geometry.reference.strategies.strategy_within_winding">strategy::winding</link></member>

View File

@@ -19,6 +19,25 @@
[section:release_notes Release Notes]
[/=================]
[heading Boost 1.71]
[/=================]
[*Improvements]
* [@https://github.com/boostorg/geometry/pull/568 568] Add a constructor that takes matrix_type to matrix_transformer.
* [@https://github.com/boostorg/geometry/pull/605 605] Improvement of handling of coordinate systems in various algorithms.
* Various improvements related to robustness of set and relational operation.
[*Solved issues]
* [@https://github.com/boostorg/geometry/issues/596 596] boost::geometry::buffer generates (multi)polygon with spike.
[*Bugfixes]
* [@https://github.com/boostorg/geometry/pull/595 595] Fix inaccuracy in geographic point-segment distance computation.
* Fix various compiler warnings.
[/=================]
[heading Boost 1.70]
[/=================]

View File

@@ -31,14 +31,16 @@
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/algorithms/detail/make/make.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp>
#include <boost/geometry/algorithms/detail/buffer/line_line_intersection.hpp>
#include <boost/geometry/algorithms/detail/buffer/parallel_continue.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/num_interior_rings.hpp>
#include <boost/geometry/algorithms/simplify.hpp>
#include <boost/geometry/arithmetic/infinite_line_functions.hpp>
#include <boost/geometry/views/detail/normalized_view.hpp>
@@ -175,6 +177,16 @@ struct buffer_range
}
}
static inline bool similar_direction(output_point_type const& p0,
output_point_type const& p1,
output_point_type const& p2)
{
typedef model::infinite_line<coordinate_type> line_type;
line_type const p = detail::make::make_infinite_line<coordinate_type>(p0, p1);
line_type const q = detail::make::make_infinite_line<coordinate_type>(p1, p2);
return arithmetic::similar_direction(p, q);
}
template <typename Strategy>
static inline geometry::strategy::buffer::join_selector get_join_type(
output_point_type const& p0,
@@ -185,13 +197,8 @@ struct buffer_range
int const side = strategy.apply(p0, p1, p2);
return side == -1 ? geometry::strategy::buffer::join_convex
: side == 1 ? geometry::strategy::buffer::join_concave
: parallel_continue
(
get<0>(p2) - get<0>(p1),
get<1>(p2) - get<1>(p1),
get<0>(p1) - get<0>(p0),
get<1>(p1) - get<1>(p0)
) ? geometry::strategy::buffer::join_continue
: similar_direction(p0, p1, p2)
? geometry::strategy::buffer::join_continue
: geometry::strategy::buffer::join_spike;
}

View File

@@ -179,23 +179,22 @@ struct buffered_piece_collection
typename IntersectionStrategy::cs_tag
>::type rescale_policy_type;
typedef typename geometry::segment_ratio_type
typedef geometry::segment_ratio
<
point_type,
RobustPolicy
>::type segment_ratio_type;
typename geometry::coordinate_type<robust_point_type>::type
> ratio_type;
typedef buffer_turn_info
<
point_type,
robust_point_type,
segment_ratio_type
ratio_type
> buffer_turn_info_type;
typedef buffer_turn_operation
<
point_type,
segment_ratio_type
ratio_type
> buffer_turn_operation_type;
typedef std::vector<buffer_turn_info_type> turn_vector_type;
@@ -206,7 +205,7 @@ struct buffered_piece_collection
int operation_index;
robust_point_type point;
segment_identifier seg_id;
segment_ratio_type fraction;
ratio_type fraction;
};
struct piece
@@ -484,25 +483,25 @@ struct buffered_piece_collection
// intersection-point -> outgoing)
// for all (co-located) points still present in the map
for (iterator_type it = boost::begin(m_turns);
it != boost::end(m_turns);
++it)
for (iterator_type tit = boost::begin(m_turns);
tit != boost::end(m_turns);
++tit)
{
typename occupation_map_type::iterator mit =
occupation_map.find(it->get_robust_point());
occupation_map.find(tit->get_robust_point());
if (mit != occupation_map.end())
{
buffer_occupation_info& info = mit->second;
for (int i = 0; i < 2; i++)
{
add_incoming_and_outgoing_angles(it->get_robust_point(), *it,
add_incoming_and_outgoing_angles(tit->get_robust_point(), *tit,
m_pieces,
i, it->operations[i].seg_id,
i, tit->operations[i].seg_id,
info);
}
it->count_on_multi++;
tit->count_on_multi++;
}
}
@@ -526,10 +525,10 @@ struct buffered_piece_collection
#endif
// Get left turns from all clusters
for (typename occupation_map_type::iterator it = occupation_map.begin();
it != occupation_map.end(); ++it)
for (typename occupation_map_type::iterator mit = occupation_map.begin();
mit != occupation_map.end(); ++mit)
{
it->second.get_left_turns(it->first, m_turns, m_side_strategy);
mit->second.get_left_turns(mit->first, m_turns, m_side_strategy);
}
}

View File

@@ -10,9 +10,9 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/arithmetic/infinite_line_functions.hpp>
#include <boost/geometry/algorithms/detail/make/make.hpp>
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/algorithms/detail/buffer/parallel_continue.hpp>
namespace boost { namespace geometry
{
@@ -22,55 +22,33 @@ namespace boost { namespace geometry
namespace detail { namespace buffer
{
// TODO: once change this to proper strategy
// It is different from current segment intersection because these are not segments but lines
// If we have the Line concept, we can create a strategy
// Assumes a convex corner
// TODO: it might once be changed this to proper strategy
struct line_line_intersection
{
template <typename Point>
static inline strategy::buffer::join_selector apply(Point const& pi, Point const& pj,
Point const& qi, Point const& qj, Point& ip)
static inline strategy::buffer::join_selector
apply(Point const& pi, Point const& pj,
Point const& qi, Point const& qj,
Point& ip)
{
typedef typename coordinate_type<Point>::type ct;
typedef model::infinite_line<ct> line_type;
// Construct lines in general form (ax + by + c = 0),
// (will be replaced by a general_form structure in a next PR)
ct const pa = get<1>(pi) - get<1>(pj);
ct const pb = get<0>(pj) - get<0>(pi);
ct const pc = -pa * get<0>(pi) - pb * get<1>(pi);
line_type const p = detail::make::make_infinite_line<ct>(pi, pj);
line_type const q = detail::make::make_infinite_line<ct>(qi, qj);
ct const qa = get<1>(qi) - get<1>(qj);
ct const qb = get<0>(qj) - get<0>(qi);
ct const qc = -qa * get<0>(qi) - qb * get<1>(qi);
ct const denominator = pb * qa - pa * qb;
// Even if the corner was checked before (so it is convex now), that
// was done on the original geometry. This function runs on the buffered
// geometries, where sides are generated and might be slightly off. In
// Floating Point, that slightly might just exceed the limit and we have
// to check it again.
// For round joins, it will not be used at all.
// For miter joins, there is a miter limit
// If segments are parallel/collinear we must be distinguish two cases:
// they continue each other, or they form a spike
ct const zero = ct();
if (math::equals(denominator, zero))
if (arithmetic::intersection_point(p, q, ip))
{
return parallel_continue(qb, -qa, pb, -pa)
? strategy::buffer::join_continue
: strategy::buffer::join_spike
;
return strategy::buffer::join_convex;
}
set<0>(ip, (pc * qb - pb * qc) / denominator);
set<1>(ip, (pa * qc - pc * qa) / denominator);
return strategy::buffer::join_convex;
// The lines do not intersect.
// Distinguish between continuing lines (having a similar direction)
// and spikes (having the opposite direction).
return arithmetic::similar_direction(p, q)
? strategy::buffer::join_continue
: strategy::buffer::join_spike
;
}
};

View File

@@ -1,33 +0,0 @@
// 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_ALGORITHMS_DETAIL_BUFFER_PARALLEL_CONTINUE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PARALLEL_CONTINUE_HPP
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace buffer
{
template <typename T>
inline bool parallel_continue(T dx1, T dy1, T dx2, T dy2)
{
T const dot = dx1 * dx2 + dy1 * dy2;
return dot > 0;
}
}} // namespace detail::buffer
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PARALLEL_CONTINUE_HPP

View File

@@ -0,0 +1,370 @@
// Boost.Geometry
// Copyright (c) 2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_POINT_ORDER_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_POINT_ORDER_HPP
#include <vector>
#include <boost/mpl/assert.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/strategies/geographic/point_order.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
{
namespace detail
{
template <typename Iter, typename CalcT>
struct clean_point
{
explicit clean_point(Iter const& iter)
: m_iter(iter), m_azi(0), m_razi(0), m_azi_diff(0)
, m_is_azi_valid(false), m_is_azi_diff_valid(false)
{}
typename boost::iterators::iterator_reference<Iter>::type ref() const
{
return *m_iter;
}
CalcT const& azimuth() const
{
return m_azi;
}
CalcT const& reverse_azimuth() const
{
return m_razi;
}
CalcT const& azimuth_difference() const
{
return m_azi_diff;
}
void set_azimuths(CalcT const& azi, CalcT const& razi)
{
m_azi = azi;
m_razi = razi;
m_is_azi_valid = true;
}
void set_azimuth_invalid()
{
m_is_azi_valid = false;
}
bool is_azimuth_valid() const
{
return m_is_azi_valid;
}
void set_azimuth_difference(CalcT const& diff)
{
m_azi_diff = diff;
m_is_azi_diff_valid = true;
}
void set_azimuth_difference_invalid()
{
m_is_azi_diff_valid = false;
}
bool is_azimuth_difference_valid() const
{
return m_is_azi_diff_valid;
}
private:
Iter m_iter;
CalcT m_azi;
CalcT m_razi;
CalcT m_azi_diff;
// NOTE: these flags could be removed and replaced with some magic number
// assigned to the above variables, e.g. CalcT(1000).
bool m_is_azi_valid;
bool m_is_azi_diff_valid;
};
struct calculate_point_order_by_azimuth
{
template <typename Ring, typename Strategy>
static geometry::order_selector apply(Ring const& ring, Strategy const& strategy)
{
typedef typename boost::range_iterator<Ring const>::type iter_t;
typedef typename Strategy::template result_type<Ring>::type calc_t;
typedef clean_point<iter_t, calc_t> clean_point_t;
typedef std::vector<clean_point_t> cleaned_container_t;
typedef typename cleaned_container_t::iterator cleaned_iter_t;
calc_t const zero = 0;
calc_t const pi = math::pi<calc_t>();
std::size_t const count = boost::size(ring);
if (count < 3)
{
return geometry::order_undetermined;
}
// non-duplicated, non-spike points
cleaned_container_t cleaned;
cleaned.reserve(count);
for (iter_t it = boost::begin(ring); it != boost::end(ring); ++it)
{
// Add point
cleaned.push_back(clean_point_t(it));
while (cleaned.size() >= 3)
{
cleaned_iter_t it0 = cleaned.end() - 3;
cleaned_iter_t it1 = cleaned.end() - 2;
cleaned_iter_t it2 = cleaned.end() - 1;
calc_t diff;
if (get_or_calculate_azimuths_difference(*it0, *it1, *it2, diff, strategy)
&& ! math::equals(math::abs(diff), pi))
{
// neither duplicate nor a spike - difference already stored
break;
}
else
{
// spike detected
// TODO: angles have to be invalidated only if spike is detected
// for duplicates it'd be ok to leave them
it0->set_azimuth_invalid();
it0->set_azimuth_difference_invalid();
it2->set_azimuth_difference_invalid();
cleaned.erase(it1);
}
}
}
// filter-out duplicates and spikes at the front and back of cleaned
cleaned_iter_t cleaned_b = cleaned.begin();
cleaned_iter_t cleaned_e = cleaned.end();
std::size_t cleaned_count = cleaned.size();
bool found = false;
do
{
found = false;
while(cleaned_count >= 3)
{
cleaned_iter_t it0 = cleaned_e - 2;
cleaned_iter_t it1 = cleaned_e - 1;
cleaned_iter_t it2 = cleaned_b;
cleaned_iter_t it3 = cleaned_b + 1;
calc_t diff = 0;
if (! get_or_calculate_azimuths_difference(*it0, *it1, *it2, diff, strategy)
|| math::equals(math::abs(diff), pi))
{
// spike at the back
// TODO: angles have to be invalidated only if spike is detected
// for duplicates it'd be ok to leave them
it0->set_azimuth_invalid();
it0->set_azimuth_difference_invalid();
it2->set_azimuth_difference_invalid();
--cleaned_e;
--cleaned_count;
found = true;
}
else if (! get_or_calculate_azimuths_difference(*it1, *it2, *it3, diff, strategy)
|| math::equals(math::abs(diff), pi))
{
// spike at the front
// TODO: angles have to be invalidated only if spike is detected
// for duplicates it'd be ok to leave them
it1->set_azimuth_invalid();
it1->set_azimuth_difference_invalid();
it3->set_azimuth_difference_invalid();
++cleaned_b;
--cleaned_count;
found = true;
}
else
{
break;
}
}
}
while (found);
if (cleaned_count < 3)
{
return geometry::order_undetermined;
}
// calculate the sum of external angles
calc_t angles_sum = zero;
for (cleaned_iter_t it = cleaned_b; it != cleaned_e; ++it)
{
cleaned_iter_t it0 = (it == cleaned_b ? cleaned_e - 1 : it - 1);
cleaned_iter_t it2 = (it == cleaned_e - 1 ? cleaned_b : it + 1);
calc_t diff = 0;
get_or_calculate_azimuths_difference(*it0, *it, *it2, diff, strategy);
angles_sum += diff;
}
#ifdef BOOST_GEOMETRY_DEBUG_POINT_ORDER
std::cout << angles_sum << " for " << geometry::wkt(ring) << std::endl;
#endif
return angles_sum == zero ? geometry::order_undetermined
: angles_sum > zero ? geometry::clockwise
: geometry::counterclockwise;
}
private:
template <typename Iter, typename T, typename Strategy>
static bool get_or_calculate_azimuths_difference(clean_point<Iter, T> & p0,
clean_point<Iter, T> & p1,
clean_point<Iter, T> const& p2,
T & diff,
Strategy const& strategy)
{
if (p1.is_azimuth_difference_valid())
{
diff = p1.azimuth_difference();
return true;
}
T azi1, razi1, azi2, razi2;
if (get_or_calculate_azimuths(p0, p1, azi1, razi1, strategy)
&& get_or_calculate_azimuths(p1, p2, azi2, razi2, strategy))
{
diff = strategy.apply(p0.ref(), p1.ref(), p2.ref(), razi1, azi2);
p1.set_azimuth_difference(diff);
return true;
}
return false;
}
template <typename Iter, typename T, typename Strategy>
static bool get_or_calculate_azimuths(clean_point<Iter, T> & p0,
clean_point<Iter, T> const& p1,
T & azi, T & razi,
Strategy const& strategy)
{
if (p0.is_azimuth_valid())
{
azi = p0.azimuth();
razi = p0.reverse_azimuth();
return true;
}
if (strategy.apply(p0.ref(), p1.ref(), azi, razi))
{
p0.set_azimuths(azi, razi);
return true;
}
return false;
}
};
struct calculate_point_order_by_area
{
template <typename Ring, typename Strategy>
static geometry::order_selector apply(Ring const& ring, Strategy const& strategy)
{
typedef detail::area::ring_area
<
geometry::order_as_direction<geometry::point_order<Ring>::value>::value,
geometry::closure<Ring>::value
> ring_area_type;
typedef typename area_result
<
Ring, Strategy
>::type result_type;
result_type const result = ring_area_type::apply(ring, strategy);
result_type const zero = 0;
return result == zero ? geometry::order_undetermined
: result > zero ? geometry::clockwise
: geometry::counterclockwise;
}
};
} // namespace detail
namespace dispatch
{
template
<
typename Strategy,
typename VersionTag = typename Strategy::version_tag
>
struct calculate_point_order
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_TAG, (types<VersionTag>)
);
};
template <typename Strategy>
struct calculate_point_order<Strategy, strategy::point_order::area_tag>
: geometry::detail::calculate_point_order_by_area
{};
template <typename Strategy>
struct calculate_point_order<Strategy, strategy::point_order::azimuth_tag>
: geometry::detail::calculate_point_order_by_azimuth
{};
} // namespace dispatch
namespace detail
{
template <typename Ring, typename Strategy>
inline geometry::order_selector calculate_point_order(Ring const& ring, Strategy const& strategy)
{
concepts::check<Ring>();
return dispatch::calculate_point_order<Strategy>::apply(ring, strategy);
}
template <typename Ring>
inline geometry::order_selector calculate_point_order(Ring const& ring)
{
typedef typename strategy::point_order::services::default_strategy
<
typename geometry::cs_tag<Ring>::type
>::type strategy_type;
concepts::check<Ring>();
return dispatch::calculate_point_order<strategy_type>::apply(ring, strategy_type());
}
} // namespace detail
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_POINT_ORDER_HPP

View File

@@ -71,8 +71,11 @@ protected:
// check if other segments are closer
for (++prev, ++it; it != last; ++prev, ++it)
{
Distance dist = strategy.apply(point, *prev, *it);
if (geometry::math::equals(dist, zero))
Distance const dist = strategy.apply(point, *prev, *it);
// Stop only if we find exactly zero distance
// otherwise it may stop at some very small value and miss the min
if (dist == zero)
{
dist_min = zero;
it_min1 = prev;

View File

@@ -12,11 +12,13 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECTION_CODE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECTION_CODE_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/arithmetic/infinite_line_functions.hpp>
#include <boost/geometry/algorithms/detail/make/make.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
@@ -32,20 +34,6 @@ namespace boost { namespace geometry
namespace detail
{
// TODO: remove
template <std::size_t Index, typename Point1, typename Point2>
inline int sign_of_difference(Point1 const& point1, Point2 const& point2)
{
return
math::equals(geometry::get<Index>(point1), geometry::get<Index>(point2))
?
0
:
(geometry::get<Index>(point1) > geometry::get<Index>(point2) ? 1 : -1);
}
template <typename CSTag>
struct direction_code_impl
{
@@ -57,42 +45,30 @@ struct direction_code_impl<cartesian_tag>
{
template <typename Point1, typename Point2>
static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
Point2 const& p)
Point2 const& point)
{
typedef typename geometry::select_coordinate_type
<
Point1, Point2
>::type calc_t;
if ( (math::equals(geometry::get<0>(segment_b), geometry::get<0>(segment_a))
&& math::equals(geometry::get<1>(segment_b), geometry::get<1>(segment_a)))
|| (math::equals(geometry::get<0>(segment_b), geometry::get<0>(p))
&& math::equals(geometry::get<1>(segment_b), geometry::get<1>(p))) )
typedef model::infinite_line<calc_t> line_type;
// point b is often equal to the specified point, check that first
line_type const q = detail::make::make_infinite_line<calc_t>(segment_b, point);
if (arithmetic::is_degenerate(q))
{
return 0;
}
calc_t x1 = geometry::get<0>(segment_b) - geometry::get<0>(segment_a);
calc_t y1 = geometry::get<1>(segment_b) - geometry::get<1>(segment_a);
calc_t x2 = geometry::get<0>(segment_b) - geometry::get<0>(p);
calc_t y2 = geometry::get<1>(segment_b) - geometry::get<1>(p);
calc_t ax = (std::min)(math::abs(x1), math::abs(x2));
calc_t ay = (std::min)(math::abs(y1), math::abs(y2));
int s1 = 0, s2 = 0;
if (ax >= ay)
line_type const p = detail::make::make_infinite_line<calc_t>(segment_a, segment_b);
if (arithmetic::is_degenerate(p))
{
s1 = x1 > 0 ? 1 : -1;
s2 = x2 > 0 ? 1 : -1;
}
else
{
s1 = y1 > 0 ? 1 : -1;
s2 = y2 > 0 ? 1 : -1;
return 0;
}
return s1 == s2 ? -1 : 1;
// p extends a-b if direction is similar
return arithmetic::similar_direction(p, q) ? 1 : -1;
}
};
@@ -277,4 +253,4 @@ inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECITON_CODE_HPP
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DIRECTION_CODE_HPP

View File

@@ -34,10 +34,10 @@
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp>
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
@@ -59,28 +59,17 @@ struct disjoint_segment
{
typedef typename point_type<Segment1>::type point_type;
// We don't need to rescale to detect disjointness
typedef no_rescale_policy rescale_policy_type;
rescale_policy_type robust_policy;
typedef segment_intersection_points
<
point_type,
typename segment_ratio_type
<
point_type,
rescale_policy_type
>::type
> intersection_return_type;
typedef segment_intersection_points<point_type> intersection_return_type;
typedef policies::relate::segments_intersection_points
<
intersection_return_type
> intersection_policy;
intersection_return_type is = strategy.apply(segment1, segment2,
intersection_policy(),
robust_policy);
detail::segment_as_subrange<Segment1> sub_range1(segment1);
detail::segment_as_subrange<Segment2> sub_range2(segment2);
intersection_return_type is = strategy.apply(sub_range1, sub_range2,
intersection_policy());
return is.count == 0;
}
@@ -105,18 +94,17 @@ struct disjoint_linear
Strategy const& strategy)
{
typedef typename geometry::point_type<Geometry1>::type point_type;
typedef detail::no_rescale_policy rescale_policy_type;
typedef typename geometry::segment_ratio_type
typedef geometry::segment_ratio
<
point_type, rescale_policy_type
>::type segment_ratio_type;
typename coordinate_type<point_type>::type
> ratio_type;
typedef overlay::turn_info
<
point_type,
segment_ratio_type,
ratio_type,
typename detail::get_turns::turn_operation_type
<
Geometry1, Geometry2, segment_ratio_type
Geometry1, Geometry2, ratio_type
>::type
> turn_info_type;
@@ -139,7 +127,7 @@ struct disjoint_linear
Geometry1, Geometry2, assign_disjoint_policy
>
>::apply(0, geometry1, 1, geometry2,
strategy, rescale_policy_type(), turns, interrupt_policy);
strategy, detail::no_rescale_policy(), turns, interrupt_policy);
return !interrupt_policy.has_intersections;
}

View File

@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015, 2016, 2017, 2018.
// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014, 2015, 2016, 2017, 2018, 2019.
// Modifications copyright (c) 2014-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -275,6 +275,15 @@ private:
}
};
struct equals_always_false
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const& )
{
return false;
}
};
}} // namespace detail::equals
#endif // DOXYGEN_NO_DETAIL
@@ -285,81 +294,92 @@ namespace dispatch
{
template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
struct equals<P1, P2, point_tag, point_tag, pointlike_tag, pointlike_tag, DimensionCount, Reverse>
: detail::equals::point_point<0, DimensionCount>
{};
template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, pointlike_tag, pointlike_tag, DimensionCount, Reverse>
: detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
{};
template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
struct equals<Point, MultiPoint, point_tag, multi_point_tag, pointlike_tag, pointlike_tag, DimensionCount, Reverse>
: detail::equals::equals_by_relate<Point, MultiPoint>
{};
template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
struct equals<Box1, Box2, box_tag, box_tag, areal_tag, areal_tag, DimensionCount, Reverse>
: detail::equals::box_box<0, DimensionCount>
{};
template <typename Ring1, typename Ring2, bool Reverse>
struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
struct equals<Ring1, Ring2, ring_tag, ring_tag, areal_tag, areal_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon1, typename Polygon2, bool Reverse>
struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, areal_tag, areal_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon, typename Ring, bool Reverse>
struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
struct equals<Polygon, Ring, polygon_tag, ring_tag, areal_tag, areal_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Ring, typename Box, bool Reverse>
struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
struct equals<Ring, Box, ring_tag, box_tag, areal_tag, areal_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Polygon, typename Box, bool Reverse>
struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
struct equals<Polygon, Box, polygon_tag, box_tag, areal_tag, areal_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>
struct equals<Segment1, Segment2, segment_tag, segment_tag, linear_tag, linear_tag, DimensionCount, Reverse>
: detail::equals::segment_segment
{};
template <typename LineString1, typename LineString2, bool Reverse>
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, linear_tag, linear_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString1, LineString2>
{};
template <typename LineString, typename MultiLineString, bool Reverse>
struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>
struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, linear_tag, linear_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString, MultiLineString>
{};
template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>
struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, linear_tag, linear_tag, 2, Reverse>
: detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
{};
template <typename LineString, typename Segment, bool Reverse>
struct equals<LineString, Segment, linestring_tag, segment_tag, linear_tag, linear_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString, Segment>
{};
template <typename MultiLineString, typename Segment, bool Reverse>
struct equals<MultiLineString, Segment, multi_linestring_tag, segment_tag, linear_tag, linear_tag, 2, Reverse>
: detail::equals::equals_by_relate<MultiLineString, Segment>
{};
template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
struct equals
<
MultiPolygon1, MultiPolygon2,
multi_polygon_tag, multi_polygon_tag,
areal_tag, areal_tag,
2,
Reverse
>
@@ -372,6 +392,7 @@ struct equals
<
Polygon, MultiPolygon,
polygon_tag, multi_polygon_tag,
areal_tag, areal_tag,
2,
Reverse
>
@@ -383,6 +404,7 @@ struct equals
<
MultiPolygon, Ring,
multi_polygon_tag, ring_tag,
areal_tag, areal_tag,
2,
Reverse
>
@@ -390,6 +412,42 @@ struct equals
{};
// NOTE: degenerated linear geometries, e.g. segment or linestring containing
// 2 equal points, are considered to be invalid. Though theoretically
// degenerated segments and linestrings could be treated as points and
// multi-linestrings as multi-points.
// This reasoning could also be applied to boxes.
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, linear_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, linear_tag, pointlike_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, pointlike_tag, areal_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, areal_tag, pointlike_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, linear_tag, areal_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
template <typename Geometry1, typename Geometry2, typename Tag1, typename Tag2, std::size_t DimensionCount>
struct equals<Geometry1, Geometry2, Tag1, Tag2, areal_tag, linear_tag, DimensionCount, false>
: detail::equals::equals_always_false
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015, 2016, 2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014, 2015, 2016, 2017, 2019.
// Modifications copyright (c) 2014-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -52,6 +52,8 @@ template
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type,
typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,
typename CastedTag2 = typename tag_cast<Tag2, pointlike_tag, linear_tag, areal_tag>::type,
std::size_t DimensionCount = dimension<Geometry1>::type::value,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
@@ -64,10 +66,11 @@ template
<
typename Geometry1, typename Geometry2,
typename Tag1, typename Tag2,
typename CastedTag1, typename CastedTag2,
std::size_t DimensionCount
>
struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
: equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
struct equals<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, DimensionCount, true>
: equals<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, DimensionCount, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
@@ -76,6 +79,7 @@ struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
<
Geometry2, Geometry1,
Tag2, Tag1,
CastedTag2, CastedTag1,
DimensionCount,
false
>::apply(g2, g1, strategy);

View File

@@ -247,17 +247,11 @@ inline void block_turns(AngleCollection& sorted, std::size_t cluster_size)
for (typename boost::range_iterator<AngleCollection>::type it = sorted.begin();
it != sorted.end(); ++it)
{
signed_size_type cluster_index = static_cast<signed_size_type>(it->cluster_index);
signed_size_type previous_index = cluster_index - 1;
if (previous_index < 0)
{
previous_index = cluster_size - 1;
}
signed_size_type next_index = cluster_index + 1;
if (next_index >= static_cast<signed_size_type>(cluster_size))
{
next_index = 0;
}
std::size_t const cluster_index = it->cluster_index;
std::size_t const previous_index
= cluster_index == 0 ? cluster_size - 1 : cluster_index - 1;
std::size_t const next_index
= cluster_index + 1 >= cluster_size ? 0 : cluster_index + 1;
if (directions[cluster_index].first
&& directions[cluster_index].second)

View File

@@ -29,7 +29,6 @@
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/strategies/relate.hpp>
@@ -53,13 +52,8 @@ struct self_intersects
<
Geometry, Geometry
>::type strategy_type;
typedef detail::no_rescale_policy rescale_policy_type;
typedef detail::overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
typedef detail::overlay::turn_info<point_type> turn_info;
std::deque<turn_info> turns;
@@ -69,14 +63,13 @@ struct self_intersects
> turn_policy;
strategy_type strategy;
rescale_policy_type robust_policy;
detail::disjoint::disjoint_interrupt_policy policy;
// TODO: skip_adjacent should be set to false
detail::self_get_turn_points::get_turns
<
false, turn_policy
>::apply(geometry, strategy, robust_policy, turns, policy, 0, true);
>::apply(geometry, strategy, detail::no_rescale_policy(), turns, policy, 0, true);
return policy.has_intersections;
}
};

View File

@@ -206,14 +206,7 @@ inline bool has_self_intersections(Linear const& linear, Strategy const& strateg
typedef typename point_type<Linear>::type point_type;
// compute self turns
typedef detail::overlay::turn_info
<
point_type,
geometry::segment_ratio
<
typename geometry::coordinate_type<point_type>::type
>
> turn_info;
typedef detail::overlay::turn_info<point_type> turn_info;
std::deque<turn_info> turns;

View File

@@ -63,7 +63,7 @@ public:
typedef detail::overlay::turn_info
<
point_type,
typename geometry::segment_ratio_type
typename segment_ratio_type
<
point_type,
rescale_policy_type
@@ -87,11 +87,13 @@ public:
is_acceptable_turn<Geometry>
> interrupt_policy;
// Calculate self-turns, skipping adjacent segments
detail::self_get_turn_points::self_turns<false, turn_policy>(geometry,
strategy,
robust_policy,
turns,
interrupt_policy);
interrupt_policy,
0, true);
if (interrupt_policy.has_intersections)
{

View File

@@ -0,0 +1,60 @@
// Boost.Geometry
// Copyright (c) 2019 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_ALGORITHMS_DETAIL_MAKE_MAKE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAKE_MAKE_HPP
#include <boost/geometry/geometries/infinite_line.hpp>
#include <boost/geometry/core/access.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace make
{
template <typename Type, typename Coordinate>
inline
model::infinite_line<Type> make_infinite_line(Coordinate const& x1,
Coordinate const& y1, Coordinate const& x2, Coordinate const& y2)
{
model::infinite_line<Type> result;
result.a = y1 - y2;
result.b = x2 - x1;
result.c = -result.a * x1 - result.b * y1;
return result;
}
template <typename Type, typename Point>
inline
model::infinite_line<Type> make_infinite_line(Point const& a, Point const& b)
{
return make_infinite_line<Type>(geometry::get<0>(a), geometry::get<1>(a),
geometry::get<0>(b), geometry::get<1>(b));
}
template <typename Type, typename Segment>
inline
model::infinite_line<Type> make_infinite_line(Segment const& segment)
{
return make_infinite_line<Type>(geometry::get<0, 0>(segment),
geometry::get<0, 1>(segment),
geometry::get<1, 0>(segment),
geometry::get<1, 1>(segment));
}
}} // namespace detail::make
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAKE_MAKE_HPP

View File

@@ -426,12 +426,6 @@ inline void enrich_intersection_points(Turns& turns,
std::vector<indexed_turn_operation>
> mapped_vector_type;
// As long as turn indexes are not used yet, turns might be erased from
// the vector
// For now start turns are disabled.
// TODO: remove code or fix inconsistencies within validity and relations
// detail::overlay::erase_colocated_start_turns(turns, geometry1, geometry2);
// From here on, turn indexes are used (in clusters, next_index, etc)
// and may only be flagged as discarded

View File

@@ -12,6 +12,8 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/arithmetic/infinite_line_functions.hpp>
#include <boost/geometry/algorithms/detail/make/make.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <cmath>
@@ -100,26 +102,14 @@ struct get_distance_measure<CalculationType, cartesian_tag>
static result_type apply(SegmentPoint const& p1, SegmentPoint const& p2,
Point const& p)
{
typedef CalculationType ct;
// Get the distance measure / side value
// It is not a real distance and purpose is
// to detect small differences in collinearity
// Construct a line in general form (ax + by + c = 0),
// (will be replaced by a general_form structure in next PR)
ct const x1 = geometry::get<0>(p1);
ct const y1 = geometry::get<1>(p1);
ct const x2 = geometry::get<0>(p2);
ct const y2 = geometry::get<1>(p2);
ct const a = y1 - y2;
ct const b = x2 - x1;
ct const c = -a * x1 - b * y1;
// Returns a distance measure
// https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_an_equation
// dividing by sqrt(a*a+b*b) is not necessary for this distance measure,
// it is not a real distance and purpose is to detect small differences
// in collinearity
typedef model::infinite_line<CalculationType> line_type;
line_type const line = detail::make::make_infinite_line<CalculationType>(p1, p2);
result_type result;
result.measure = a * geometry::get<0>(p) + b * geometry::get<1>(p) + c;
result.measure = arithmetic::side_value(line, p);
return result;
}
};

View File

@@ -22,11 +22,10 @@
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/policies/robustness/rescale_policy_tags.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
namespace boost { namespace geometry
{
@@ -56,45 +55,25 @@ struct get_turn_without_info
UniqueSubRange2 const& range_q,
TurnInfo const& ,
Strategy const& strategy,
RobustPolicy const& robust_policy,
RobustPolicy const& ,
OutputIterator out)
{
// Make sure this is only called with no rescaling
BOOST_STATIC_ASSERT((boost::is_same
<
no_rescale_policy_tag,
typename rescale_policy_type<RobustPolicy>::type
>::value));
typedef typename TurnInfo::point_type turn_point_type;
typedef policies::relate::segments_intersection_points
<
segment_intersection_points
<
turn_point_type,
typename geometry::segment_ratio_type
<
turn_point_type, RobustPolicy
>::type
>
segment_intersection_points<turn_point_type>
> policy_type;
typedef model::referring_segment<Point1 const> segment_type1;
typedef model::referring_segment<Point2 const> segment_type2;
Point1 const& pi = range_p.at(0);
Point1 const& pj = range_p.at(1);
Point2 const& qi = range_q.at(0);
Point2 const& qj = range_q.at(1);
segment_type1 p1(pi, pj);
segment_type2 q1(qi, qj);
typedef typename geometry::robust_point_type
<
Point1, RobustPolicy
>::type robust_point_type;
robust_point_type pi_rob, pj_rob, qi_rob, qj_rob;
geometry::recalculate(pi_rob, pi, robust_policy);
geometry::recalculate(pj_rob, pj, robust_policy);
geometry::recalculate(qi_rob, qi, robust_policy);
geometry::recalculate(qj_rob, qj, robust_policy);
typename policy_type::return_type result
= strategy.apply(p1, q1, policy_type(), robust_policy,
pi_rob, pj_rob, qi_rob, qj_rob);
typename policy_type::return_type const result
= strategy.apply(range_p, range_q, policy_type());
for (std::size_t i = 0; i < result.count; i++)
{

View File

@@ -153,12 +153,14 @@ struct base_turn_handler
typename UmbrellaStrategy,
typename TurnInfo
>
static inline void both_collinear(UniqueSubRange1 const& range_p,
static inline void both_collinear(
UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
UmbrellaStrategy const& umbrella_strategy,
UmbrellaStrategy const&,
std::size_t index_p, std::size_t index_q,
TurnInfo& ti)
{
boost::ignore_unused(range_p, range_q);
BOOST_GEOMETRY_ASSERT(IndexP + IndexQ == 1);
BOOST_GEOMETRY_ASSERT(index_p > 0 && index_p <= 2);
BOOST_GEOMETRY_ASSERT(index_q > 0 && index_q <= 2);
@@ -617,133 +619,6 @@ struct equal : public base_turn_handler
}
};
template
<
typename TurnInfo
>
struct start : public base_turn_handler
{
template
<
typename UniqueSubRange1,
typename UniqueSubRange2,
typename IntersectionInfo,
typename DirInfo,
typename SideCalculator,
typename UmbrellaStrategy
>
static inline bool apply(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
TurnInfo& ti,
IntersectionInfo const& info,
DirInfo const& dir_info,
SideCalculator const& side,
UmbrellaStrategy const& )
{
// For now disabled. TODO: remove all code or fix inconsistencies
// within validity and relations
return false;
if (dir_info.opposite)
{
// They should not be collinear
return false;
}
int const side_pj_q1 = side.pj_wrt_q1();
int const side_qj_p1 = side.qj_wrt_p1();
// Get side values at starting point
typedef detail::distance_measure
<
typename select_coordinate_type
<
typename UniqueSubRange1::point_type,
typename UniqueSubRange2::point_type
>::type
> dm_type;
typedef typename UmbrellaStrategy::cs_tag cs_tag;
dm_type const dm_pi_q1 = get_distance_measure<cs_tag>(range_q.at(0), range_q.at(1), range_p.at(0));
dm_type const dm_qi_p1 = get_distance_measure<cs_tag>(range_p.at(0), range_p.at(1), range_q.at(0));
if (dir_info.how_a == -1 && dir_info.how_b == -1)
{
// Both p and q leave
if (dm_pi_q1.is_zero() && dm_qi_p1.is_zero())
{
// Exactly collinear, not necessary to handle it
return false;
}
if (! (dm_pi_q1.is_small() && dm_qi_p1.is_small()))
{
// Not nearly collinear
return false;
}
if (side_qj_p1 == 0)
{
// Collinear is not handled
return false;
}
ui_else_iu(side_qj_p1 == -1, ti);
}
else if (dir_info.how_b == -1)
{
// p --------------->
// |
// | q q leaves
// v
//
if (dm_qi_p1.is_zero() || ! dm_qi_p1.is_small())
{
// Exactly collinear
return false;
}
if (side_qj_p1 == 0)
{
// Collinear is not handled
return false;
}
ui_else_iu(side_qj_p1 == -1, ti);
}
else if (dir_info.how_a == -1)
{
if (dm_pi_q1.is_zero() || ! dm_pi_q1.is_small())
{
// It starts exactly, not necessary to handle it
return false;
}
// p leaves
if (side_pj_q1 == 0)
{
// Collinear is not handled
return false;
}
ui_else_iu(side_pj_q1 == 1, ti);
}
else
{
// Not supported
return false;
}
// Copy intersection point
assign_point(ti, method_start, info, 0);
return true;
}
};
template
<
typename TurnInfo,
@@ -1167,6 +1042,8 @@ struct get_turn_info
switch(method)
{
case 'a' : // "angle"
case 'f' : // "from"
case 's' : // "start"
do_only_convert = true;
break;
@@ -1208,20 +1085,6 @@ struct get_turn_info
*out++ = tp;
}
break;
case 'f' :
case 's' :
{
// "from" or "start" without rescaling, it is in some cases necessary to handle
if (start<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy))
{
*out++ = tp;
}
else
{
do_only_convert = true;
}
}
break;
case 'e':
{
if ( ! inters.d_info().opposite )

View File

@@ -22,7 +22,7 @@
#include <boost/geometry/policies/relate/direction.hpp>
#include <boost/geometry/policies/relate/intersection_points.hpp>
#include <boost/geometry/policies/relate/tupled.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/rescale_policy_tags.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
namespace boost { namespace geometry {
@@ -153,18 +153,20 @@ template
typename UniqueSubRange1, typename UniqueSubRange2,
typename RobustPolicy
>
struct robust_points
struct robust_point_calculator
{
typedef typename geometry::robust_point_type
<
typename UniqueSubRange1::point_type, RobustPolicy
>::type robust_point1_type;
typedef typename geometry::robust_point_type
<
typename UniqueSubRange2::point_type, RobustPolicy
>::type robust_point2_type;
typedef robust_point1_type robust_point2_type;
inline robust_points(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
RobustPolicy const& robust_policy)
inline robust_point_calculator(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
RobustPolicy const& robust_policy)
: m_robust_policy(robust_policy)
, m_range_p(range_p)
, m_range_q(range_q)
@@ -214,18 +216,52 @@ private :
mutable bool m_qk_retrieved;
};
// Default version (empty - specialized below)
template
<
typename UniqueSubRange1, typename UniqueSubRange2,
typename TurnPoint, typename UmbrellaStrategy, typename RobustPolicy>
class intersection_info_base
: private robust_points<UniqueSubRange1, UniqueSubRange2, RobustPolicy>
typename TurnPoint, typename UmbrellaStrategy,
typename RobustPolicy,
typename Tag = typename rescale_policy_type<RobustPolicy>::type
>
class intersection_info_base {};
// Version with rescaling, having robust points
template
<
typename UniqueSubRange1, typename UniqueSubRange2,
typename TurnPoint, typename UmbrellaStrategy,
typename RobustPolicy
>
class intersection_info_base<UniqueSubRange1, UniqueSubRange2,
TurnPoint, UmbrellaStrategy, RobustPolicy, rescale_policy_tag>
{
typedef robust_points<UniqueSubRange1, UniqueSubRange2, RobustPolicy> base;
typedef robust_point_calculator
<
UniqueSubRange1, UniqueSubRange2,
RobustPolicy
>
robust_calc_type;
public:
typedef typename base::robust_point1_type robust_point1_type;
typedef typename base::robust_point2_type robust_point2_type;
typedef segment_intersection_points
<
TurnPoint,
geometry::segment_ratio<boost::long_long_type>
> intersection_point_type;
typedef policies::relate::segments_tupled
<
policies::relate::segments_intersection_points
<
intersection_point_type
>,
policies::relate::segments_direction
> intersection_policy_type;
typedef typename intersection_policy_type::return_type result_type;
typedef typename robust_calc_type::robust_point1_type robust_point1_type;
typedef typename robust_calc_type::robust_point2_type robust_point2_type;
typedef robust_subrange_adapter<robust_point1_type, UniqueSubRange1, RobustPolicy> robust_subrange1;
typedef robust_subrange_adapter<robust_point2_type, UniqueSubRange2, RobustPolicy> robust_subrange2;
@@ -246,28 +282,31 @@ public:
UniqueSubRange2 const& range_q,
UmbrellaStrategy const& umbrella_strategy,
RobustPolicy const& robust_policy)
: base(range_p, range_q, robust_policy)
, m_range_p(range_p)
: m_range_p(range_p)
, m_range_q(range_q)
, m_robust_range_p(range_p, base::m_rpi, base::m_rpj, robust_policy)
, m_robust_range_q(range_q, base::m_rqi, base::m_rqj, robust_policy)
, m_robust_calc(range_p, range_q, robust_policy)
, m_robust_range_p(range_p, m_robust_calc.m_rpi, m_robust_calc.m_rpj, robust_policy)
, m_robust_range_q(range_q, m_robust_calc.m_rqi, m_robust_calc.m_rqj, robust_policy)
, m_side_calc(m_robust_range_p, m_robust_range_q,
umbrella_strategy.get_side_strategy())
, m_result(umbrella_strategy.apply(range_p, range_q,
intersection_policy_type(),
m_robust_range_p, m_robust_range_q))
{}
inline typename UniqueSubRange1::point_type const& pi() const { return m_range_p.at(0); }
inline typename UniqueSubRange2::point_type const& qi() const { return m_range_q.at(0); }
inline bool p_is_last_segment() const { return m_range_p.is_last_segment(); }
inline bool q_is_last_segment() const { return m_range_q.is_last_segment(); }
inline robust_point1_type const& rpi() const { return base::m_rpi; }
inline robust_point1_type const& rpj() const { return base::m_rpj; }
inline robust_point1_type const& rpk() const { return base::get_rpk(); }
inline robust_point1_type const& rpi() const { return m_robust_calc.m_rpi; }
inline robust_point1_type const& rpj() const { return m_robust_calc.m_rpj; }
inline robust_point1_type const& rpk() const { return m_robust_calc.get_rpk(); }
inline robust_point2_type const& rqi() const { return base::m_rqi; }
inline robust_point2_type const& rqj() const { return base::m_rqj; }
inline robust_point2_type const& rqk() const { return base::get_rqk(); }
inline robust_point2_type const& rqi() const { return m_robust_calc.m_rqi; }
inline robust_point2_type const& rqj() const { return m_robust_calc.m_rqj; }
inline robust_point2_type const& rqk() const { return m_robust_calc.get_rqk(); }
inline side_calculator_type const& sides() const { return m_side_calc; }
robust_swapped_side_calculator_type get_swapped_sides() const
{
robust_swapped_side_calculator_type result(
@@ -276,31 +315,49 @@ public:
return result;
}
private :
// Owned by get_turns
UniqueSubRange1 const& m_range_p;
UniqueSubRange2 const& m_range_q;
private :
// Owned by this class
robust_calc_type m_robust_calc;
robust_subrange1 m_robust_range_p;
robust_subrange2 m_robust_range_q;
side_calculator_type m_side_calc;
protected :
result_type m_result;
};
// Version without rescaling
template
<
typename UniqueSubRange1, typename UniqueSubRange2,
typename TurnPoint, typename UmbrellaStrategy
typename TurnPoint, typename UmbrellaStrategy,
typename RobustPolicy
>
class intersection_info_base<UniqueSubRange1, UniqueSubRange2,
TurnPoint, UmbrellaStrategy, detail::no_rescale_policy>
TurnPoint, UmbrellaStrategy, RobustPolicy, no_rescale_policy_tag>
{
public:
typedef segment_intersection_points<TurnPoint> intersection_point_type;
typedef policies::relate::segments_tupled
<
policies::relate::segments_intersection_points
<
intersection_point_type
>,
policies::relate::segments_direction
> intersection_policy_type;
typedef typename intersection_policy_type::return_type result_type;
typedef typename UniqueSubRange1::point_type point1_type;
typedef typename UniqueSubRange2::point_type point2_type;
typedef typename UniqueSubRange1::point_type robust_point1_type;
typedef typename UniqueSubRange2::point_type robust_point2_type;
typedef typename UmbrellaStrategy::cs_tag cs_tag;
typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type;
@@ -315,13 +372,17 @@ public:
intersection_info_base(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
UmbrellaStrategy const& umbrella_strategy,
no_rescale_policy const& /*robust_policy*/)
no_rescale_policy const& )
: m_range_p(range_p)
, m_range_q(range_q)
, m_side_calc(range_p, range_q,
umbrella_strategy.get_side_strategy())
, m_result(umbrella_strategy.apply(range_p, range_q, intersection_policy_type()))
{}
inline bool p_is_last_segment() const { return m_range_p.is_last_segment(); }
inline bool q_is_last_segment() const { return m_range_q.is_last_segment(); }
inline point1_type const& rpi() const { return m_side_calc.get_pi(); }
inline point1_type const& rpj() const { return m_side_calc.get_pj(); }
inline point1_type const& rpk() const { return m_side_calc.get_pk(); }
@@ -340,13 +401,16 @@ public:
return result;
}
protected :
private :
// Owned by get_turns
UniqueSubRange1 const& m_range_p;
UniqueSubRange2 const& m_range_q;
private :
// Owned here, passed by .get_side_strategy()
// Owned by this class
side_calculator_type m_side_calc;
protected :
result_type m_result;
};
@@ -365,37 +429,17 @@ class intersection_info
TurnPoint, UmbrellaStrategy, RobustPolicy> base;
public:
typedef segment_intersection_points
<
TurnPoint,
typename geometry::segment_ratio_type
<
TurnPoint, RobustPolicy
>::type
> intersection_point_type;
typedef typename UniqueSubRange1::point_type point1_type;
typedef typename UniqueSubRange2::point_type point2_type;
// NOTE: formerly defined in intersection_strategies
typedef policies::relate::segments_tupled
<
policies::relate::segments_intersection_points
<
intersection_point_type
>,
policies::relate::segments_direction
> intersection_policy_type;
typedef UmbrellaStrategy intersection_strategy_type;
typedef typename UmbrellaStrategy::side_strategy_type side_strategy_type;
typedef typename UmbrellaStrategy::cs_tag cs_tag;
typedef model::referring_segment<point1_type const> segment_type1;
typedef model::referring_segment<point2_type const> segment_type2;
typedef typename base::side_calculator_type side_calculator_type;
typedef typename base::result_type result_type;
typedef typename intersection_policy_type::return_type result_type;
typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info
typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info
@@ -405,20 +449,13 @@ public:
RobustPolicy const& robust_policy)
: base(range_p, range_q,
umbrella_strategy, robust_policy)
, m_result(umbrella_strategy.apply(
segment_type1(range_p.at(0), range_p.at(1)),
segment_type2(range_q.at(0), range_q.at(1)),
intersection_policy_type(),
robust_policy,
base::rpi(), base::rpj(),
base::rqi(), base::rqj()))
, m_intersection_strategy(umbrella_strategy)
, m_robust_policy(robust_policy)
{}
inline result_type const& result() const { return m_result; }
inline i_info_type const& i_info() const { return m_result.template get<0>(); }
inline d_info_type const& d_info() const { return m_result.template get<1>(); }
inline result_type const& result() const { return base::m_result; }
inline i_info_type const& i_info() const { return base::m_result.template get<0>(); }
inline d_info_type const& d_info() const { return base::m_result.template get<1>(); }
inline side_strategy_type get_side_strategy() const
{
@@ -428,7 +465,7 @@ public:
// TODO: it's more like is_spike_ip_p
inline bool is_spike_p() const
{
if (base::m_range_p.is_last_segment())
if (base::p_is_last_segment())
{
return false;
}
@@ -443,7 +480,7 @@ public:
}
// TODO: why is q used to determine spike property in p?
bool const has_qk = ! base::m_range_q.is_last_segment();
bool const has_qk = ! base::q_is_last_segment();
int const qk_p1 = has_qk ? base::sides().qk_wrt_p1() : 0;
int const qk_p2 = has_qk ? base::sides().qk_wrt_p2() : 0;
@@ -467,7 +504,7 @@ public:
inline bool is_spike_q() const
{
if (base::m_range_q.is_last_segment())
if (base::q_is_last_segment())
{
return false;
}
@@ -481,7 +518,7 @@ public:
}
// TODO: why is p used to determine spike property in q?
bool const has_pk = ! base::m_range_p.is_last_segment();
bool const has_pk = ! base::p_is_last_segment();
int const pk_q1 = has_pk ? base::sides().pk_wrt_q1() : 0;
int const pk_q2 = has_pk ? base::sides().pk_wrt_q2() : 0;
@@ -523,7 +560,6 @@ private:
}
}
result_type m_result;
UmbrellaStrategy const& m_intersection_strategy;
RobustPolicy const& m_robust_policy;
};

View File

@@ -209,7 +209,6 @@ private :
RobustPolicy m_robust_policy;
};
template
<
typename Geometry1, typename Geometry2,

View File

@@ -84,15 +84,6 @@ struct turn_operation_index
signed_size_type op_index; // only 0,1
};
struct is_discarded
{
template <typename Turn>
inline bool operator()(Turn const& turn) const
{
return turn.discarded;
}
};
template <typename Turns>
struct less_by_fraction_and_type
{
@@ -534,80 +525,6 @@ inline segment_identifier get_preceding_segment_id(segment_identifier const& id,
return result;
}
// Turns marked with method <start> can be generated but are often duplicate,
// unless (by floating point precision) the preceding touching turn is just missed.
// This means that all <start> (nearly) colocated with preceding touching turn
// can be deleted. This is done before colocation itself (because in colocated,
// they are only discarded, and that can give issues in traversal)
template <typename Turns, typename Geometry0, typename Geometry1>
inline void erase_colocated_start_turns(Turns& turns,
Geometry0 const& geometry0, Geometry1 const& geometry1)
{
typedef std::pair<segment_identifier, segment_identifier> seg_id_pair;
typedef std::map<seg_id_pair, std::size_t> map_type;
typedef typename boost::range_value<Turns>::type turn_type;
typedef typename boost::range_iterator<Turns const>::type turn_it;
typedef map_type::const_iterator map_it;
// Collect starting turns into map
map_type preceding_segments;
std::size_t turn_index = 0;
for (turn_it it = boost::begin(turns); it != boost::end(turns); ++it, ++turn_index)
{
turn_type const& turn = *it;
if (turn.method == method_start)
{
// Insert identifiers for preceding segments of both operations.
// (For self turns geometry1 == geometry2)
seg_id_pair const pair(
get_preceding_segment_id(turn.operations[0].seg_id, geometry0, geometry1),
get_preceding_segment_id(turn.operations[1].seg_id, geometry0, geometry1));
// There should exist only one turn with such ids
BOOST_GEOMETRY_ASSERT(preceding_segments.find(pair) == preceding_segments.end());
preceding_segments[pair] = turn_index;
}
}
if (preceding_segments.empty())
{
return;
}
// Find touching turns on preceding segment id combinations
bool has_discarded = false;
for (turn_it it = boost::begin(turns); it != boost::end(turns); ++it)
{
turn_type const& turn = *it;
if (turn.method == method_touch)
{
seg_id_pair const pair(turn.operations[0].seg_id,
turn.operations[1].seg_id);
map_it mit = preceding_segments.find(pair);
if (mit != preceding_segments.end())
{
// The found touching turn precedes the found starting turn.
// (To be completely sure we could verify if turn.point is (nearly) equal)
// These turns are duplicate, discard the starting turn.
has_discarded = true;
turn_type& extra_turn = turns[mit->second];
extra_turn.discarded = true;
}
}
}
if (has_discarded)
{
turns.erase(std::remove_if(boost::begin(turns), boost::end(turns),
is_discarded()),
boost::end(turns));
}
}
template
<
overlay_type OverlayType,
@@ -833,7 +750,7 @@ struct is_turn_index
return indexed.turn_index == m_index;
}
std::size_t m_index;
signed_size_type m_index;
};

View File

@@ -35,8 +35,9 @@
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/policies/robustness/rescale_policy_tags.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
@@ -71,52 +72,32 @@ struct intersection_segment_segment_point
>
static inline OutputIterator apply(Segment1 const& segment1,
Segment2 const& segment2,
RobustPolicy const& robust_policy,
RobustPolicy const& ,
OutputIterator out,
Strategy const& strategy)
{
// Make sure this is only called with no rescaling
BOOST_STATIC_ASSERT((boost::is_same
<
no_rescale_policy_tag,
typename rescale_policy_type<RobustPolicy>::type
>::value));
typedef typename point_type<PointOut>::type point_type;
typedef typename geometry::robust_point_type
<
typename geometry::point_type<Segment1>::type,
RobustPolicy
>::type robust_point_type;
// TODO: rescale segment -> robust points
robust_point_type pi_rob, pj_rob, qi_rob, qj_rob;
{
// Workaround:
point_type pi, pj, qi, qj;
assign_point_from_index<0>(segment1, pi);
assign_point_from_index<1>(segment1, pj);
assign_point_from_index<0>(segment2, qi);
assign_point_from_index<1>(segment2, qj);
geometry::recalculate(pi_rob, pi, robust_policy);
geometry::recalculate(pj_rob, pj, robust_policy);
geometry::recalculate(qi_rob, qi, robust_policy);
geometry::recalculate(qj_rob, qj, robust_policy);
}
// Get the intersection point (or two points)
typedef segment_intersection_points
<
point_type,
typename segment_ratio_type
<
point_type, RobustPolicy
>::type
> intersection_return_type;
typedef segment_intersection_points<point_type> intersection_return_type;
typedef policies::relate::segments_intersection_points
<
intersection_return_type
> policy_type;
detail::segment_as_subrange<Segment1> sub_range1(segment1);
detail::segment_as_subrange<Segment2> sub_range2(segment2);
intersection_return_type
is = strategy.apply(segment1, segment2,
policy_type(), robust_policy,
pi_rob, pj_rob, qi_rob, qj_rob);
is = strategy.apply(sub_range1, sub_range2, policy_type());
for (std::size_t i = 0; i < is.count; i++)
{
@@ -144,13 +125,14 @@ struct intersection_linestring_linestring_point
OutputIterator out,
Strategy const& strategy)
{
typedef typename point_type<PointOut>::type point_type;
// Make sure this is only called with no rescaling
BOOST_STATIC_ASSERT((boost::is_same
<
no_rescale_policy_tag,
typename rescale_policy_type<RobustPolicy>::type
>::value));
typedef detail::overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, RobustPolicy>::type
> turn_info;
typedef detail::overlay::turn_info<PointOut> turn_info;
std::deque<turn_info> turns;
geometry::get_intersection_points(linestring1, linestring2,
@@ -408,6 +390,13 @@ struct intersection_of_linestring_with_areal
OutputIterator out,
Strategy const& strategy)
{
// Make sure this is only called with no rescaling
BOOST_STATIC_ASSERT((boost::is_same
<
no_rescale_policy_tag,
typename rescale_policy_type<RobustPolicy>::type
>::value));
if (boost::size(linestring) == 0)
{
return out;
@@ -423,21 +412,26 @@ struct intersection_of_linestring_with_areal
> follower;
typedef typename point_type<LineStringOut>::type point_type;
typedef geometry::segment_ratio
<
typename coordinate_type<point_type>::type
> ratio_type;
#ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
typedef detail::overlay::traversal_turn_info
<
point_type,
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
point_type, ratio_type
> turn_info;
#else
typedef detail::overlay::turn_info
<
point_type,
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type,
ratio_type,
detail::overlay::turn_operation_linear
<
point_type,
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
ratio_type
>
> turn_info;
#endif
@@ -602,19 +596,23 @@ struct intersection_linear_areal_point
OutputIterator out,
Strategy const& strategy)
{
typedef typename geometry::segment_ratio_type
<
PointOut, RobustPolicy
>::type segment_ratio_type;
// Make sure this is only called with no rescaling
BOOST_STATIC_ASSERT((boost::is_same
<
no_rescale_policy_tag,
typename rescale_policy_type<RobustPolicy>::type
>::value));
typedef geometry::segment_ratio<typename geometry::coordinate_type<PointOut>::type> ratio_type;
typedef detail::overlay::turn_info
<
PointOut,
segment_ratio_type,
ratio_type,
detail::overlay::turn_operation_linear
<
PointOut,
segment_ratio_type
ratio_type
>
> turn_info;
@@ -1288,9 +1286,10 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
typedef typename geometry::rescale_policy_type
typedef typename geometry::rescale_overlay_policy_type
<
typename geometry::point_type<Geometry1>::type, // TODO from both
Geometry1,
Geometry2,
typename Strategy::cs_tag
>::type rescale_policy_type;

View File

@@ -287,7 +287,7 @@ struct overlay
typedef detail::overlay::traversal_turn_info
<
point_type,
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
typename segment_ratio_type<point_type, RobustPolicy>::type
> turn_info;
typedef std::deque<turn_info> turn_container_type;
@@ -318,15 +318,20 @@ std::cout << "get turns" << std::endl;
visitor.visit_turns(1, turns);
#if ! defined(BOOST_GEOMETRY_NO_SELF_TURNS)
if (needs_self_turns<Geometry1>::apply(geometry1))
if (! turns.empty() || OverlayType == overlay_dissolve)
{
self_get_turn_points::self_turns<Reverse1, assign_null_policy>(geometry1,
strategy, robust_policy, turns, policy, 0);
}
if (needs_self_turns<Geometry2>::apply(geometry2))
{
self_get_turn_points::self_turns<Reverse2, assign_null_policy>(geometry2,
strategy, robust_policy, turns, policy, 1);
// Calculate self turns if the output contains turns already,
// and if necessary (e.g.: multi-geometry, polygon with interior rings)
if (needs_self_turns<Geometry1>::apply(geometry1))
{
self_get_turn_points::self_turns<Reverse1, assign_null_policy>(geometry1,
strategy, robust_policy, turns, policy, 0);
}
if (needs_self_turns<Geometry2>::apply(geometry2))
{
self_get_turn_points::self_turns<Reverse2, assign_null_policy>(geometry2,
strategy, robust_policy, turns, policy, 1);
}
}
#endif

View File

@@ -0,0 +1,54 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2019-2019 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_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_AS_SUBRANGE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_AS_SUBRANGE_HPP
#include <cstddef>
#include <map>
#include <boost/geometry/core/access.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Segment>
struct segment_as_subrange
{
segment_as_subrange(Segment const& s)
: m_segment(s)
{
geometry::set<0>(m_p1, geometry::get<0, 0>(m_segment));
geometry::set<1>(m_p1, geometry::get<0, 1>(m_segment));
geometry::set<0>(m_p2, geometry::get<1, 0>(m_segment));
geometry::set<1>(m_p2, geometry::get<1, 1>(m_segment));
}
typedef typename geometry::point_type<Segment>::type point_type;
point_type const& at(std::size_t index) const
{
return index == 0 ? m_p1 : m_p2;
}
point_type m_p1, m_p2;
Segment const& m_segment;
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_AS_SUBRANGE_HPP

View File

@@ -16,6 +16,7 @@
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
namespace boost { namespace geometry
{
@@ -33,7 +34,6 @@ enum method_type
method_touch_interior,
method_collinear,
method_equal,
method_start,
method_error
};
@@ -77,7 +77,7 @@ struct turn_operation
template
<
typename Point,
typename SegmentRatio,
typename SegmentRatio = geometry::segment_ratio<typename coordinate_type<Point>::type>,
typename Operation = turn_operation<Point, SegmentRatio>,
typename Container = boost::array<Operation, 2>
>

View File

@@ -3,8 +3,8 @@
// Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015, 2017.
// Modifications copyright (c) 2015-2017 Oracle and/or its affiliates.
// This file was modified by Oracle on 2015, 2017, 2018, 2019.
// Modifications copyright (c) 2015-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
@@ -19,6 +19,8 @@
#include <cstddef>
#include <vector>
#include <boost/range.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/algorithms/assign.hpp>
@@ -30,15 +32,35 @@ namespace boost { namespace geometry
namespace detail { namespace partition
{
template <typename T, bool IsIntegral = boost::is_integral<T>::value>
struct divide_interval
{
static inline T apply(T const& mi, T const& ma)
{
static T const two = 2;
return (mi + ma) / two;
}
};
template <typename T>
struct divide_interval<T, true>
{
static inline T apply(T const& mi, T const& ma)
{
// avoid overflow
return mi / 2 + ma / 2 + (mi % 2 + ma % 2) / 2;
}
};
template <int Dimension, typename Box>
inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
{
typedef typename coordinate_type<Box>::type ctype;
// Divide input box into two parts, e.g. left/right
ctype two = 2;
ctype mid = (geometry::get<min_corner, Dimension>(box)
+ geometry::get<max_corner, Dimension>(box)) / two;
ctype mid = divide_interval<ctype>::apply(
geometry::get<min_corner, Dimension>(box),
geometry::get<max_corner, Dimension>(box));
lower_box = box;
upper_box = box;

View File

@@ -35,26 +35,6 @@ namespace boost { namespace geometry
namespace detail
{
template <typename Point1, typename Point2, typename Point3>
inline bool collinear_point_is_spike_or_equal(Point1 const& last_point,
Point2 const& segment_a,
Point3 const& segment_b)
{
// Check if segment is equal
int const sgn_x1 = sign_of_difference<0>(last_point, segment_b);
int const sgn_y1 = sign_of_difference<1>(last_point, segment_b);
if (sgn_x1 == 0 && sgn_y1 == 0)
{
return true;
}
// Check if segment moves forward
int const sgn_x2 = sign_of_difference<0>(segment_b, segment_a);
int const sgn_y2 = sign_of_difference<1>(segment_b, segment_a);
return sgn_x1 != sgn_x2 || sgn_y1 != sgn_y2;
}
// Checks if a point ("last_point") causes a spike w.r.t.
// the specified two other points (segment_a, segment_b)
//
@@ -81,15 +61,7 @@ inline bool point_is_spike_or_equal(Point1 const& last_point, // prev | back
if (side == 0)
{
// Last point is collinear w.r.t previous segment.
#ifdef BOOST_GEOMETRY_ENABLE_POINT_IS_SPIKE_OR_EQUAL_TEST
bool r1 = collinear_point_is_spike_or_equal(last_point, segment_a, segment_b);
bool r2 = direction_code(segment_a, segment_b, last_point) < 1;
if (r1 != r2)
std::cout << "spike detection failure with: " << r1 << " " << r2 << std::endl;
return r2;
#else
return direction_code<cs_tag>(segment_a, segment_b, last_point) < 1;
#endif
}
return false;
}

View File

@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014, 2015.
// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2015, 2019.
// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,7 +22,6 @@
#include <boost/tuple/tuple.hpp>
#include <boost/geometry/algorithms/detail/relate/result.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
#include <boost/geometry/core/tag.hpp>
@@ -318,9 +317,9 @@ struct static_mask_touches_impl
// Using the above mask the result would be always false
template <typename Geometry1, typename Geometry2>
struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0>
: not_implemented<typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type>
{};
{
typedef geometry::detail::relate::false_mask type;
};
template <typename Geometry1, typename Geometry2>
struct static_mask_touches_type
@@ -377,12 +376,9 @@ template
typename Geometry1, typename Geometry2, std::size_t Dim
>
struct static_mask_crosses_impl<Geometry1, Geometry2, Dim, Dim, false>
: not_implemented
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type
>
{};
{
typedef geometry::detail::relate::false_mask type;
};
// dim(G1) == 1 && dim(G2) == 1 - L/L
template <typename Geometry1, typename Geometry2>
struct static_mask_crosses_impl<Geometry1, Geometry2, 1, 1, false>
@@ -406,12 +402,9 @@ template
std::size_t Dim2 = geometry::topological_dimension<Geometry2>::value
>
struct static_mask_overlaps_impl
: not_implemented
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type
>
{};
{
typedef geometry::detail::relate::false_mask type;
};
// dim(G1) == D && dim(G2) == D - P/P A/A
template <typename Geometry1, typename Geometry2, std::size_t Dim>
struct static_mask_overlaps_impl<Geometry1, Geometry2, Dim, Dim>

View File

@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014, 2015.
// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2015, 2019.
// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -30,25 +30,19 @@ namespace detail { namespace relate {
struct implemented_tag {};
template <template <typename, typename> class StaticMaskTrait,
typename Geometry1,
typename Geometry2>
struct relate_impl
: boost::mpl::if_
template
<
typename Geometry1,
typename Geometry2
>
struct relate_impl_base
: boost::mpl::if_c
<
boost::mpl::or_
boost::is_base_of
<
boost::is_base_of
<
nyi::not_implemented_tag,
StaticMaskTrait<Geometry1, Geometry2>
>,
boost::is_base_of
<
nyi::not_implemented_tag,
dispatch::relate<Geometry1, Geometry2>
>
>,
nyi::not_implemented_tag,
dispatch::relate<Geometry1, Geometry2>
>::value,
not_implemented
<
typename geometry::tag<Geometry1>::type,
@@ -56,6 +50,16 @@ struct relate_impl
>,
implemented_tag
>::type
{};
template
<
typename Geometry1,
typename Geometry2,
typename StaticMask
>
struct relate_impl_dispatch
: relate_impl_base<Geometry1, Geometry2>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
@@ -64,7 +68,7 @@ struct relate_impl
<
Geometry1,
Geometry2,
typename StaticMaskTrait<Geometry1, Geometry2>::type
StaticMask
>::type handler;
dispatch::relate<Geometry1, Geometry2>::apply(g1, g2, handler, strategy);
@@ -73,6 +77,32 @@ struct relate_impl
}
};
template <typename Geometry1, typename Geometry2>
struct relate_impl_dispatch<Geometry1, Geometry2, detail::relate::false_mask>
: relate_impl_base<Geometry1, Geometry2>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const& )
{
return false;
}
};
template
<
template <typename, typename> class StaticMaskTrait,
typename Geometry1,
typename Geometry2
>
struct relate_impl
: relate_impl_dispatch
<
Geometry1,
Geometry2,
typename StaticMaskTrait<Geometry1, Geometry2>::type
>
{};
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL

View File

@@ -3,8 +3,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2018.
// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013-2019.
// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -654,6 +654,10 @@ private:
Mask const& m_mask;
};
// --------------- FALSE MASK ----------------
struct false_mask {};
// --------------- COMPILE-TIME MASK ----------------
// static_check_characters

View File

@@ -21,7 +21,7 @@
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/type_traits/is_base_of.hpp>
@@ -70,17 +70,14 @@ struct get_turns
>
struct turn_info_type
{
typedef typename segment_ratio_type<point1_type, RobustPolicy>::type ratio_type;
typedef overlay::turn_info
<
point1_type,
typename segment_ratio_type<point1_type, RobustPolicy>::type,
ratio_type,
typename detail::get_turns::turn_operation_type
<
Geometry1, Geometry2,
typename segment_ratio_type
<
point1_type, RobustPolicy
>::type
Geometry1, Geometry2, ratio_type
>::type
> type;
};

View File

@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013, 2014, 2015, 2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2019.
// Modifications copyright (c) 2013-2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -254,23 +254,17 @@ struct areal_areal
Geometry2 const& geometry2,
IntersectionStrategy const& strategy)
{
typedef detail::no_rescale_policy rescale_policy_type;
typedef typename geometry::point_type<Geometry1>::type point_type;
typedef detail::overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
typedef detail::overlay::turn_info<point_type> turn_info;
std::deque<turn_info> turns;
detail::touches::areal_interrupt_policy policy;
rescale_policy_type robust_policy;
boost::geometry::get_turns
<
detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
detail::overlay::assign_null_policy
>(geometry1, geometry2, strategy, robust_policy, turns, policy);
>(geometry1, geometry2, strategy, detail::no_rescale_policy(), turns, policy);
return policy.result()
&& ! geometry::detail::touches::rings_containing(geometry1, geometry2, strategy)
@@ -298,8 +292,8 @@ namespace dispatch {
// P/P
template <typename Geometry1, typename Geometry2, typename Tag2>
struct touches<Geometry1, Geometry2, point_tag, Tag2, pointlike_tag, pointlike_tag, false>
template <typename Geometry1, typename Geometry2>
struct touches<Geometry1, Geometry2, point_tag, point_tag, pointlike_tag, pointlike_tag, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const&)
@@ -308,8 +302,18 @@ struct touches<Geometry1, Geometry2, point_tag, Tag2, pointlike_tag, pointlike_t
}
};
template <typename Geometry1, typename Geometry2, typename Tag2>
struct touches<Geometry1, Geometry2, multi_point_tag, Tag2, pointlike_tag, pointlike_tag, false>
template <typename Geometry1, typename Geometry2>
struct touches<Geometry1, Geometry2, point_tag, multi_point_tag, pointlike_tag, pointlike_tag, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const&)
{
return false;
}
};
template <typename Geometry1, typename Geometry2>
struct touches<Geometry1, Geometry2, multi_point_tag, multi_point_tag, pointlike_tag, pointlike_tag, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const&, Geometry2 const&, Strategy const&)
@@ -318,7 +322,7 @@ struct touches<Geometry1, Geometry2, multi_point_tag, Tag2, pointlike_tag, point
}
};
// P/*
// P/L P/A
template <typename Point, typename Geometry, typename Tag2, typename CastedTag2>
struct touches<Point, Geometry, point_tag, Tag2, pointlike_tag, CastedTag2, false>
@@ -335,6 +339,8 @@ struct touches<MultiPoint, MultiGeometry, multi_point_tag, Tag2, pointlike_tag,
>
{};
// L/P A/P
template <typename Geometry, typename MultiPoint, typename Tag1, typename CastedTag1>
struct touches<Geometry, MultiPoint, Tag1, multi_point_tag, CastedTag1, pointlike_tag, false>
: detail::relate::relate_impl
@@ -427,13 +433,8 @@ struct self_touches
<
Geometry, Geometry
>::type strategy_type;
typedef detail::no_rescale_policy rescale_policy_type;
typedef typename geometry::point_type<Geometry>::type point_type;
typedef detail::overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
typedef detail::overlay::turn_info<point_type> turn_info;
typedef detail::overlay::get_turn_info
<
@@ -443,12 +444,11 @@ struct self_touches
std::deque<turn_info> turns;
detail::touches::areal_interrupt_policy policy;
strategy_type strategy;
rescale_policy_type robust_policy;
// TODO: skip_adjacent should be set to false
detail::self_get_turn_points::get_turns
<
false, policy_type
>::apply(geometry, strategy, robust_policy, turns, policy, 0, true);
>::apply(geometry, strategy, detail::no_rescale_policy(), turns, policy, 0, true);
return policy.result();
}

View File

@@ -223,15 +223,21 @@ struct multi_point_multi_geometry
bool found_boundary = false;
int boundaries = 0;
typedef typename box_pair_vector::const_iterator iterator;
for ( iterator box_it = inters_boxes.begin() ; box_it != inters_boxes.end() ; ++box_it )
typedef typename box_pair_vector::const_iterator box_iterator;
for (box_iterator box_it = inters_boxes.begin() ;
box_it != inters_boxes.end() ; ++box_it )
{
int in_val = point_in_geometry(*it, range::at(linear_or_areal, box_it->second), strategy);
int const in_val = point_in_geometry(*it,
range::at(linear_or_areal, box_it->second), strategy);
if (in_val > 0)
{
found_interior = true;
}
else if (in_val == 0)
{
++boundaries;
}
// If the result was set previously (interior or
// interior/boundary found) the only thing that needs to be
@@ -243,12 +249,16 @@ struct multi_point_multi_geometry
}
}
if ( boundaries > 0)
if (boundaries > 0)
{
if (is_linear && boundaries % 2 == 0)
{
found_interior = true;
}
else
{
found_boundary = true;
}
}
// exterior

View File

@@ -109,6 +109,11 @@ struct fe_range_per_segment_with_closure
typedef typename boost::range_iterator<Range>::type iterator_type;
iterator_type it = boost::begin(range);
if (it == boost::end(range))
{
return;
}
iterator_type previous = it++;
while(it != boost::end(range))
{

View File

@@ -84,7 +84,9 @@ struct range_remove_spikes
return;
}
std::deque<point_type> cleaned;
std::vector<point_type> cleaned;
cleaned.reserve(n);
for (typename boost::range_iterator<Range const>::type it = boost::begin(range);
it != boost::end(range); ++it)
{
@@ -102,10 +104,16 @@ struct range_remove_spikes
}
}
typedef typename std::vector<point_type>::iterator cleaned_iterator;
cleaned_iterator cleaned_b = cleaned.begin();
cleaned_iterator cleaned_e = cleaned.end();
std::size_t cleaned_count = cleaned.size();
// For a closed-polygon, remove closing point, this makes checking first point(s) easier and consistent
if ( BOOST_GEOMETRY_CONDITION(geometry::closure<Range>::value == geometry::closed) )
{
cleaned.pop_back();
--cleaned_e;
--cleaned_count;
}
bool found = false;
@@ -113,45 +121,50 @@ struct range_remove_spikes
{
found = false;
// Check for spike in first point
int const penultimate = 2;
while(cleaned.size() >= 3
&& detail::is_spike_or_equal(range::at(cleaned, cleaned.size() - penultimate),
range::back(cleaned),
range::front(cleaned),
while(cleaned_count >= 3
&& detail::is_spike_or_equal(*(cleaned_e - 2), // prev
*(cleaned_e - 1), // back
*(cleaned_b), // front
strategy))
{
cleaned.pop_back();
--cleaned_e;
--cleaned_count;
found = true;
}
// Check for spike in second point
while(cleaned.size() >= 3
&& detail::is_spike_or_equal(range::back(cleaned),
range::front(cleaned),
range::at(cleaned, 1),
while(cleaned_count >= 3
&& detail::is_spike_or_equal(*(cleaned_e - 1), // back
*(cleaned_b), // front
*(cleaned_b + 1), // next
strategy))
{
cleaned.pop_front();
++cleaned_b;
--cleaned_count;
found = true;
}
}
while (found);
if (cleaned.size() == 2)
if (cleaned_count == 2)
{
// Ticket #9871: open polygon with only two points.
// the second point forms, by definition, a spike
cleaned.pop_back();
--cleaned_e;
//--cleaned_count;
}
// Close if necessary
if ( BOOST_GEOMETRY_CONDITION(geometry::closure<Range>::value == geometry::closed) )
{
cleaned.push_back(cleaned.front());
BOOST_GEOMETRY_ASSERT(cleaned_e != cleaned.end());
*cleaned_e = *cleaned_b;
++cleaned_e;
//++cleaned_count;
}
// Copy output
geometry::clear(range);
std::copy(cleaned.begin(), cleaned.end(), range::back_inserter(range));
std::copy(cleaned_b, cleaned_e, range::back_inserter(range));
}
};

View File

@@ -0,0 +1,106 @@
// Boost.Geometry
// Copyright (c) 2018-2019 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_ARITHMETIC_LINE_FUNCTIONS_HPP
#define BOOST_GEOMETRY_ARITHMETIC_LINE_FUNCTIONS_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/config.hpp>
#include <boost/geometry/geometries/infinite_line.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace arithmetic
{
// Calculates intersection point of two infinite lines.
// Returns true if the lines intersect.
// Returns false if lines are parallel (or collinear, possibly opposite)
template <typename Point, typename Type>
inline bool intersection_point(model::infinite_line<Type> const& p,
model::infinite_line<Type> const& q, Point& ip)
{
Type const denominator = p.b * q.a - p.a * q.b;
static Type const zero = 0;
if (math::equals(denominator, zero))
{
// Lines are parallel
return false;
}
// Calculate the intersection coordinates
geometry::set<0>(ip, (p.c * q.b - p.b * q.c) / denominator);
geometry::set<1>(ip, (p.a * q.c - p.c * q.a) / denominator);
return true;
}
//! Return a distance-side-measure for a point to a line
//! Point is located left of the line if value is positive,
//! right of the line is value is negative, and on the line if the value
//! is exactly zero
template <typename Type, typename CoordinateType>
inline
typename select_most_precise<Type, CoordinateType>::type
side_value(model::infinite_line<Type> const& line,
CoordinateType const& x, CoordinateType const& y)
{
// https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_an_equation
// Distance from point to line in general form is given as:
// (a * x + b * y + c) / sqrt(a * a + b * b);
// In most use cases comparisons are enough, saving the sqrt
// and often even the division.
// Also, this gives positive values for points left to the line,
// and negative values for points right to the line.
return line.a * x + line.b * y + line.c;
}
template <typename Type, typename Point>
inline
typename select_most_precise
<
Type,
typename geometry::coordinate_type<Point>::type
>::type
side_value(model::infinite_line<Type> const& line, Point const& p)
{
return side_value(line, geometry::get<0>(p), geometry::get<1>(p));
}
// Returns true for two lines which are supposed to be (close to) collinear
// (which is not checked) and have a similar direction
// (in practice up to 45 degrees, TO BE VERIFIED)
// true: -----------------> p -----------------> q
// false: -----------------> p <----------------- q
template <typename Type>
inline
bool similar_direction(const model::infinite_line<Type>& p,
const model::infinite_line<Type>& q)
{
return p.a * q.a >= 0 && p.b * q.b >= 0;
}
template <typename Type>
inline bool is_degenerate(const model::infinite_line<Type>& line)
{
static Type const zero = 0;
return math::equals(line.a, zero) && math::equals(line.b, zero);
}
} // namespace arithmetic
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ARITHMETIC_LINE_FUNCTIONS_HPP

View File

@@ -1,6 +1,6 @@
// Boost.Geometry
// Copyright (c) 2016-2017 Oracle and/or its affiliates.
// Copyright (c) 2016-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -819,8 +819,14 @@ private:
// Newton-Raphson method
for (int i = 0; i < max_iterations_02; ++i)
{
CT const sin_beta = sin(beta);
CT const cos_beta = cos(beta);
if (math::equals(cos_beta, c0))
{
return false;
}
CT const sin_beta = sin(beta);
CT const cos_beta_sqr = math::sqr(cos_beta);
CT const G = c1 - e_sqr * cos_beta_sqr;
@@ -834,6 +840,10 @@ private:
if (is_beta_ok)
{
CT const H = cos_beta_sqr - geod1.Cj_sqr;
if (math::equals(H, c0))
{
return false;
}
f1 = geod1.Cj / cos_beta * math::sqrt(G / H);
}
else
@@ -849,6 +859,15 @@ private:
if (is_beta_ok)
{
CT const H = cos_beta_sqr - geod2.Cj_sqr;
if (math::equals(H, c0))
{
// NOTE: This may happen for segment nearly
// at the equator. Detected for (radian):
// (-0.0872665 -0.0872665, -0.0872665 0.0872665)
// x
// (0 1.57e-07, -0.392699 1.57e-07)
return false;
}
f2 = geod2.Cj / cos_beta * math::sqrt(G / H);
}
else

View File

@@ -0,0 +1,50 @@
// Boost.Geometry
// Copyright (c) 2018-2019 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_GEOMETRIES_INFINITE_LINE_HPP
#define BOOST_GEOMETRY_GEOMETRIES_INFINITE_LINE_HPP
namespace boost { namespace geometry
{
namespace model
{
//--------------------------------------------------------------------------
// Structure containing an infinite line.
// It is written using "General Form", a*x + b*y + c == 0
// Might be conceptized later. Therefore operations are implemented outside
// the structure itself.
template <typename Type = double>
struct infinite_line
{
infinite_line()
: a(0)
, b(0)
, c(0)
, normalized(false)
{}
// Horizontal: a == 0, for example y-3=0, y==3
// Vertical: b == 0, for example x-2=0, x==2
// Through origin: c == 0
Type a;
Type b;
Type c;
bool normalized;
};
} // namespace model
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_GEOMETRIES_INFINITE_LINE_HPP

View File

@@ -24,7 +24,7 @@ namespace boost { namespace geometry { namespace index { namespace detail {
// Util to distinguish between default and non-default index strategy
template <typename Box, typename Strategy>
inline bool disjoint_box_box(Box const& box1, Box const& box2, Strategy const& strategy)
inline bool disjoint_box_box(Box const& box1, Box const& box2, Strategy const&)
{
return geometry::detail::disjoint::disjoint_box_box(box1, box2,
typename Strategy::disjoint_box_box_strategy_type());

View File

@@ -304,7 +304,7 @@ struct strategy_type< parameters<Parameters, Strategy> >
template <typename Parameters>
struct get_strategy_impl
{
static inline default_strategy apply(Parameters const& parameters)
static inline default_strategy apply(Parameters const&)
{
return default_strategy();
}

View File

@@ -17,7 +17,6 @@
#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
{
@@ -26,7 +25,7 @@ namespace boost { namespace geometry
namespace detail
{
// Probably this will be moved out of namespace detail
// Redudant later.
struct no_rescale_policy
{
static bool const enabled = false;
@@ -51,16 +50,6 @@ struct robust_point_type<Point, detail::no_rescale_policy>
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

View File

@@ -22,7 +22,6 @@
#include <boost/geometry/core/coordinate_type.hpp>
#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>
@@ -77,13 +76,6 @@ struct robust_point_type<Point, detail::robust_policy<FpPoint, IntPoint, Calcula
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

View File

@@ -0,0 +1,43 @@
// Boost.Geometry
// Copyright (c) 2019-2019 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_ROBUSTNESS_RESCALE_POLICY_TYPE_HPP
#define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_TYPE_HPP
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct no_rescale_policy_tag {};
struct rescale_policy_tag {};
template <typename RobustPolicy>
struct rescale_policy_type
{
typedef rescale_policy_tag type;
};
// Specialization
template <>
struct rescale_policy_type<no_rescale_policy>
{
typedef no_rescale_policy_tag type;
};
} // namespace detail
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_RESCALE_POLICY_TYPE_HPP

View File

@@ -12,17 +12,38 @@
#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>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/policies/robustness/rescale_policy_tags.hpp>
namespace boost { namespace geometry
#include <boost/config.hpp>
#include <boost/mpl/if.hpp>
namespace boost { namespace geometry { namespace detail
{
// Meta-function to access segment-ratio for a policy
// Temporary meta-function to access segment-ratio for a policy
template <typename Point, typename Policy>
struct segment_ratio_type {}; // : not_implemented<> {};
struct segment_ratio_type
{
// Type in segment ratio is either the coordinate type, or for
// deprecated robust point types it is a long_long type
typedef typename boost::mpl::if_c
<
boost::is_same
<
typename rescale_policy_type<Policy>::type,
no_rescale_policy_tag
>::value,
typename geometry::coordinate_type<Point>::type,
boost::long_long_type
>::type coordinate_type;
// Define segment ratio based on the coordinate type
typedef geometry::segment_ratio<coordinate_type> type;
};
}} // namespace boost::geometry
}}} // namespace boost::geometry::deatil
#endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_SEGMENT_RATIO_TYPE_HPP

View File

@@ -50,9 +50,8 @@
#include <boost/geometry/strategies/side_info.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/policies/robustness/rescale_policy_tags.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#if defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
# include <boost/geometry/io/wkt/write.hpp>
@@ -226,23 +225,21 @@ struct cartesian_segments
// division.
BOOST_GEOMETRY_ASSERT(ratio.denominator() != 0);
typedef typename promote_integral<CoordinateType>::type promoted_type;
typedef typename promote_integral<CoordinateType>::type calc_type;
promoted_type const numerator
= boost::numeric_cast<promoted_type>(ratio.numerator());
promoted_type const denominator
= boost::numeric_cast<promoted_type>(ratio.denominator());
promoted_type const dx_promoted = boost::numeric_cast<promoted_type>(dx);
promoted_type const dy_promoted = boost::numeric_cast<promoted_type>(dy);
calc_type const numerator
= boost::numeric_cast<calc_type>(ratio.numerator());
calc_type const denominator
= boost::numeric_cast<calc_type>(ratio.denominator());
calc_type const dx_calc = boost::numeric_cast<calc_type>(dx);
calc_type const dy_calc = boost::numeric_cast<calc_type>(dy);
set<0>(point, get<0, 0>(segment) + boost::numeric_cast
<
CoordinateType
>(numerator * dx_promoted / denominator));
set<1>(point, get<0, 1>(segment) + boost::numeric_cast
<
CoordinateType
>(numerator * dy_promoted / denominator));
set<0>(point, get<0, 0>(segment)
+ boost::numeric_cast<CoordinateType>(numerator * dx_calc
/ denominator));
set<1>(point, get<0, 1>(segment)
+ boost::numeric_cast<CoordinateType>(numerator * dy_calc
/ denominator));
}
public :
@@ -303,62 +300,57 @@ struct cartesian_segments
// IntersectionPoint = (x1 + r * dx_a, y1 + r * dy_a)
}
// Relate segments a and b
// Version for non-rescaled policies
template
<
typename Segment1,
typename Segment2,
typename Policy,
typename RobustPolicy
typename UniqueSubRange1,
typename UniqueSubRange2,
typename Policy
>
static inline typename Policy::return_type
apply(Segment1 const& a, Segment2 const& b,
Policy const& policy, RobustPolicy const& robust_policy)
apply(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
Policy const& policy)
{
// type them all as in Segment1 - TODO reconsider this, most precise?
typedef typename geometry::point_type<Segment1>::type point_type;
typedef typename geometry::robust_point_type
<
point_type, RobustPolicy
>::type robust_point_type;
point_type a0, a1, b0, b1;
robust_point_type a0_rob, a1_rob, b0_rob, b1_rob;
detail::assign_point_from_index<0>(a, a0);
detail::assign_point_from_index<1>(a, a1);
detail::assign_point_from_index<0>(b, b0);
detail::assign_point_from_index<1>(b, b1);
geometry::recalculate(a0_rob, a0, robust_policy);
geometry::recalculate(a1_rob, a1, robust_policy);
geometry::recalculate(b0_rob, b0, robust_policy);
geometry::recalculate(b1_rob, b1, robust_policy);
return apply(a, b, policy, robust_policy, a0_rob, a1_rob, b0_rob, b1_rob);
// Pass the same ranges both as normal ranges and as robust ranges
return apply(range_p, range_q, policy, range_p, range_q);
}
// The main entry-routine, calculating intersections of segments a / b
// NOTE: Robust* types may be the same as Segments' point types
// Main entry-routine, calculating intersections of segments p / q
template
<
typename Segment1,
typename Segment2,
typename UniqueSubRange1,
typename UniqueSubRange2,
typename Policy,
typename RobustPolicy,
typename RobustPoint1,
typename RobustPoint2
typename RobustUniqueSubRange1,
typename RobustUniqueSubRange2
>
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)
apply(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
Policy const&,
RobustUniqueSubRange1 const& robust_range_p,
RobustUniqueSubRange2 const& robust_range_q)
{
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
typedef typename UniqueSubRange1::point_type point1_type;
typedef typename UniqueSubRange2::point_type point2_type;
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point1_type>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point2_type>) );
// Get robust points (to be omitted later)
typedef typename RobustUniqueSubRange1::point_type robust_point1_type;
typedef typename RobustUniqueSubRange2::point_type robust_point2_type;
point1_type const& p1 = range_p.at(0);
point1_type const& p2 = range_p.at(1);
point2_type const& q1 = range_q.at(0);
point2_type const& q2 = range_q.at(1);
robust_point1_type const& robust_a1 = robust_range_p.at(0);
robust_point1_type const& robust_a2 = robust_range_p.at(1);
robust_point2_type const& robust_b1 = robust_range_q.at(0);
robust_point2_type const& robust_b2 = robust_range_q.at(1);
using geometry::detail::equals::equals_point_point;
bool const a_is_point = equals_point_point(robust_a1, robust_a2, point_in_point_strategy_type());
@@ -366,8 +358,11 @@ struct cartesian_segments
if(a_is_point && b_is_point)
{
// Take either a or b
model::referring_segment<point1_type const> const d(p1, p2);
return equals_point_point(robust_a1, robust_b2, point_in_point_strategy_type())
? Policy::degenerate(a, true)
? Policy::degenerate(d, true)
: Policy::disjoint()
;
}
@@ -395,26 +390,22 @@ struct cartesian_segments
typedef typename select_most_precise
<
typename geometry::coordinate_type<RobustPoint1>::type,
typename geometry::coordinate_type<RobustPoint2>::type
typename geometry::coordinate_type<robust_point1_type>::type,
typename geometry::coordinate_type<robust_point2_type>::type
>::type robust_coordinate_type;
typedef typename segment_ratio_type
<
typename geometry::point_type<Segment1>::type, // TODO: most precise point?
RobustPolicy
>::type ratio_type;
typedef segment_ratio<robust_coordinate_type> ratio_type;
segment_intersection_info
<
typename select_calculation_type<Segment1, Segment2, CalculationType>::type,
typename select_calculation_type<point1_type, point2_type, 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);
sinfo.dx_a = get<0>(p2) - get<0>(p1); // distance in x-dir
sinfo.dx_b = get<0>(q2) - get<0>(q1);
sinfo.dy_a = get<1>(p2) - get<1>(p1); // distance in y-dir
sinfo.dy_b = get<1>(q2) - get<1>(q1);
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);
@@ -457,6 +448,11 @@ struct cartesian_segments
}
}
// Declare segments, currently necessary for the policies
// (segment_crosses, segment_colinear, degenerate, one_degenerate, etc)
model::referring_segment<point1_type const> const p(p1, p2);
model::referring_segment<point2_type const> const q(q1, q2);
if (collinear)
{
std::pair<bool, bool> const collinear_use_first
@@ -473,21 +469,21 @@ struct cartesian_segments
if (collinear_use_first.first)
{
return relate_collinear<0, Policy, ratio_type>(a, b,
return relate_collinear<0, Policy, ratio_type>(p, q,
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,
return relate_collinear<1, Policy, ratio_type>(p, q,
robust_a1, robust_a2, robust_b1, robust_b2,
a_is_point, b_is_point);
}
}
}
return Policy::segments_crosses(sides, sinfo, a, b);
return Policy::segments_crosses(sides, sinfo, p, q);
}
private:

View File

@@ -0,0 +1,74 @@
// Boost.Geometry
// Copyright (c) 2019, 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_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP
#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP
#include <boost/geometry/strategies/io.hpp>
#include <boost/geometry/strategies/cartesian/point_order.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace io
{
template <typename CalculationType = void>
struct cartesian
{
typedef strategy::point_order::cartesian<CalculationType> point_order_strategy_type;
static inline point_order_strategy_type get_point_order_strategy()
{
return point_order_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();
}
};
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef cartesian<> type;
};
} // namespace services
}} // namespace strategy::io
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_CARTESIAN_IO_HPP

View File

@@ -0,0 +1,48 @@
// Boost.Geometry
// Copyright (c) 2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_ORDER_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_ORDER_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/point_order.hpp>
#include <boost/geometry/strategies/cartesian/area.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace point_order
{
template <typename CalculationType = void>
struct cartesian
: strategy::area::cartesian<CalculationType>
{
typedef area_tag version_tag;
};
namespace services
{
template <>
struct default_strategy<cartesian_tag>
{
typedef cartesian<> type;
};
} // namespace services
}} // namespace strategy::point_order
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_ORDER_HPP

View File

@@ -55,7 +55,7 @@ class WithinStrategyPolygonal
struct checker
{
template <typename ApplyMethod, typename ResultMethod>
static void apply(ApplyMethod const&, ResultMethod const& )
static void apply(ApplyMethod, ResultMethod)
{
typedef typename parameter_type_of
<
@@ -129,7 +129,7 @@ class WithinStrategyPointBox
struct checker
{
template <typename ApplyMethod>
static void apply(ApplyMethod const&)
static void apply(ApplyMethod)
{
typedef typename parameter_type_of
<

View File

@@ -246,44 +246,22 @@ struct geographic_segments
// Relate segments a and b
template
<
typename Segment1,
typename Segment2,
typename Policy,
typename RobustPolicy
typename UniqueSubRange1,
typename UniqueSubRange2,
typename Policy
>
inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
Policy const& policy,
RobustPolicy const& robust_policy) const
inline typename Policy::return_type apply(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
Policy const&) const
{
typedef typename point_type<Segment1>::type point1_t;
typedef typename point_type<Segment2>::type point2_t;
point1_t a1, a2;
point2_t b1, b2;
typedef typename UniqueSubRange1::point_type point1_type;
typedef typename UniqueSubRange2::point_type point2_type;
typedef model::referring_segment<point1_type const> segment_type1;
typedef model::referring_segment<point2_type const> segment_type2;
detail::assign_point_from_index<0>(a, a1);
detail::assign_point_from_index<1>(a, a2);
detail::assign_point_from_index<0>(b, b1);
detail::assign_point_from_index<1>(b, b2);
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point1_type>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point2_type>) );
return apply(a, b, policy, robust_policy, a1, a2, b1, b2);
}
// Relate segments a and b
template
<
typename Segment1,
typename Segment2,
typename Policy,
typename RobustPolicy,
typename Point1,
typename Point2
>
inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
Policy const&, RobustPolicy const&,
Point1 a1, Point1 a2, Point2 b1, Point2 b2) const
{
bool is_a_reversed = get<1>(a1) > get<1>(a2);
bool is_b_reversed = get<1>(b1) > get<1>(b2);
/*
typename coordinate_type<Point1>::type
const a1_lon = get<0>(a1),
@@ -293,18 +271,19 @@ struct geographic_segments
const b2_lon = get<0>(b2);
bool is_a_reversed = a1_lon > a2_lon || a1_lon == a2_lon && get<1>(a1) > get<1>(a2);
bool is_b_reversed = b1_lon > b2_lon || b1_lon == b2_lon && get<1>(b1) > get<1>(b2);
*/
if (is_a_reversed)
{
std::swap(a1, a2);
}
*/
if (is_b_reversed)
{
std::swap(b1, b2);
}
bool const is_p_reversed = get<1>(range_p.at(0)) > get<1>(range_p.at(1));
bool const is_q_reversed = get<1>(range_q.at(0)) > get<1>(range_q.at(1));
return apply<Policy>(a, b, a1, a2, b1, b2, is_a_reversed, is_b_reversed);
// Call apply with original segments and ordered points
return apply<Policy>(segment_type1(range_p.at(0), range_p.at(1)),
segment_type2(range_q.at(0), range_q.at(1)),
range_p.at(is_p_reversed ? 1 : 0),
range_p.at(is_p_reversed ? 0 : 1),
range_q.at(is_q_reversed ? 1 : 0),
range_q.at(is_q_reversed ? 0 : 1),
is_p_reversed, is_q_reversed);
}
private:
@@ -499,7 +478,6 @@ private:
}
// NOTE: this is probably not needed
calc_t const c0 = 0;
int a1_on_b = position_value(c0, dist_a1_b1, dist_a1_b2);
int a2_on_b = position_value(dist_a1_a2, dist_a1_b1, dist_a1_b2);
int b1_on_a = position_value(c0, dist_b1_a1, dist_b1_a2);

View File

@@ -0,0 +1,96 @@
// Boost.Geometry
// Copyright (c) 2019, 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_EXTENSIONS_STRATEGIES_GEOGRAPHIC_IO_HPP
#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_GEOGRAPHIC_IO_HPP
#include <boost/geometry/strategies/io.hpp>
#include <boost/geometry/strategies/geographic/point_order.hpp>
#include <boost/geometry/strategies/geographic/point_in_poly_winding.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace io
{
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
struct geographic
{
typedef strategy::point_order::geographic
<
FormulaPolicy,
Spheroid,
CalculationType
> point_order_strategy_type;
point_order_strategy_type get_point_order_strategy() const
{
return point_order_strategy_type(m_spheroid);
}
template <typename Geometry1, typename Geometry2>
struct point_in_geometry_strategy
{
typedef strategy::within::geographic_winding
<
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type,
FormulaPolicy,
Spheroid,
CalculationType
> type;
};
template <typename Geometry1, typename Geometry2>
typename point_in_geometry_strategy<Geometry1, Geometry2>::type
get_point_in_geometry_strategy() const
{
typedef typename point_in_geometry_strategy
<
Geometry1, Geometry2
>::type strategy_type;
return strategy_type(m_spheroid);
}
geographic()
{}
geographic(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
private:
Spheroid m_spheroid;
};
namespace services
{
template <>
struct default_strategy<geographic_tag>
{
typedef geographic<> type;
};
} // namespace services
}} // namespace strategy::io
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_GEOGRAPHIC_IO_HPP

View File

@@ -0,0 +1,120 @@
// Boost.Geometry
// Copyright (c) 2019, 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_GEOGRAPHIC_POINT_ORDER_HPP
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_POINT_ORDER_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/point_order.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace point_order
{
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
struct geographic
{
typedef azimuth_tag version_tag;
template <typename Geometry>
struct result_type
{
typedef typename geometry::select_calculation_type_alt
<
CalculationType, Geometry
>::type type;
};
geographic()
{}
explicit geographic(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
template <typename Point>
inline bool apply(Point const& p1, Point const& p2,
typename result_type<Point>::type & azi,
typename result_type<Point>::type & razi) const
{
typedef typename result_type<Point>::type calc_t;
if (equals_point_point(p1, p2))
{
return false;
}
formula::result_inverse<calc_t> res = FormulaPolicy::template inverse
<
calc_t, false, true, true, false, false
>::apply(geometry::get_as_radian<0>(p1),
geometry::get_as_radian<1>(p1),
geometry::get_as_radian<0>(p2),
geometry::get_as_radian<1>(p2),
m_spheroid);
azi = res.azimuth;
razi = res.reverse_azimuth;
return true;
}
template <typename Point>
inline typename result_type<Point>::type
apply(Point const& /*p0*/, Point const& /*p1*/, Point const& /*p2*/,
typename result_type<Point>::type const& azi1,
typename result_type<Point>::type const& azi2) const
{
// TODO: support poles
return math::longitude_distance_signed<radian>(azi1, azi2);
}
private:
template <typename Point>
static bool equals_point_point(Point const& p0, Point const& p1)
{
return strategy::within::spherical_point_point::apply(p0, p1);
}
Spheroid m_spheroid;
};
namespace services
{
template <>
struct default_strategy<geographic_tag>
{
typedef geographic<> type;
};
} // namespace services
}} // namespace strategy::point_order
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_POINT_ORDER_HPP

View File

@@ -13,12 +13,9 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP
#define BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP
#if defined(HAVE_MATRIX_AS_STRING)
#include <string>
#endif
#include <cstddef>
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
namespace boost { namespace geometry
@@ -57,7 +54,11 @@ struct fraction_type
\brief return-type for segment-intersection
\note Set in intersection_points.hpp, from segment_intersection_info
*/
template <typename Point, typename SegmentRatio>
template
<
typename Point,
typename SegmentRatio = segment_ratio<typename coordinate_type<Point>::type>
>
struct segment_intersection_points
{
std::size_t count; // The number of intersection points

View File

@@ -63,7 +63,7 @@ private :
typedef segment_intersection_points
<
IntersectionPoint,
typename geometry::segment_ratio_type
typename detail::segment_ratio_type
<
IntersectionPoint, RobustPolicy
>::type

View File

@@ -0,0 +1,42 @@
// Boost.Geometry
// Copyright (c) 2019, 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_EXTENSIONS_STRATEGIES_IO_HPP
#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_IO_HPP
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace io
{
namespace services
{
template <typename CSTag>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_CS
, (types<CSTag>)
);
};
} // namespace services
}} // namespace strategy::io
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_IO_HPP

View File

@@ -0,0 +1,45 @@
// Boost.Geometry
// Copyright (c) 2019, 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_POINT_ORDER_HPP
#define BOOST_GEOMETRY_STRATEGIES_POINT_ORDER_HPP
#include <boost/mpl/assert.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace point_order
{
struct area_tag {};
struct azimuth_tag {};
namespace services
{
template <typename CSTag>
struct default_strategy
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_CS
, (types<CSTag>)
);
};
} // namespace services
}} // namespace strategy::point_order
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_POINT_ORDER_HPP

View File

@@ -252,43 +252,13 @@ struct ecef_segments
// Relate segments a and b
template
<
typename Segment1,
typename Segment2,
typename Policy,
typename RobustPolicy
typename UniqueSubRange1,
typename UniqueSubRange2,
typename Policy
>
static inline typename Policy::return_type
apply(Segment1 const& a, Segment2 const& b,
Policy const& policy, RobustPolicy const& robust_policy)
{
typedef typename point_type<Segment1>::type point1_t;
typedef typename point_type<Segment2>::type point2_t;
point1_t a1, a2;
point2_t b1, b2;
// TODO: use indexed_point_view if possible?
detail::assign_point_from_index<0>(a, a1);
detail::assign_point_from_index<1>(a, a2);
detail::assign_point_from_index<0>(b, b1);
detail::assign_point_from_index<1>(b, b2);
return apply(a, b, policy, robust_policy, a1, a2, b1, b2);
}
// Relate segments a and b
template
<
typename Segment1,
typename Segment2,
typename Policy,
typename RobustPolicy,
typename Point1,
typename Point2
>
static inline typename Policy::return_type
apply(Segment1 const& a, Segment2 const& b,
Policy const&, RobustPolicy const&,
Point1 const& a1, Point1 const& a2, Point2 const& b1, Point2 const& b2)
apply(UniqueSubRange1 const& range_p, UniqueSubRange2 const& range_q,
Policy const&)
{
// For now create it using default constructor. In the future it could
// be stored in strategy. However then apply() wouldn't be static and
@@ -296,8 +266,21 @@ struct ecef_segments
// Initialize explicitly to prevent compiler errors in case of PoD type
CalcPolicy const calc_policy = CalcPolicy();
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment1>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstSegment<Segment2>) );
typedef typename UniqueSubRange1::point_type point1_type;
typedef typename UniqueSubRange2::point_type point2_type;
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point1_type>) );
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point2_type>) );
point1_type const& a1 = range_p.at(0);
point1_type const& a2 = range_p.at(1);
point2_type const& b1 = range_q.at(0);
point2_type const& b2 = range_q.at(1);
typedef model::referring_segment<point1_type const> segment1_type;
typedef model::referring_segment<point2_type const> segment2_type;
segment1_type const a(a1, a2);
segment2_type const b(b1, b2);
// TODO: check only 2 first coordinates here?
bool a_is_point = equals_point_point(a1, a2);
@@ -312,7 +295,7 @@ struct ecef_segments
}
typedef typename select_calculation_type
<Segment1, Segment2, CalculationType>::type calc_t;
<segment1_type, segment2_type, CalculationType>::type calc_t;
calc_t const c0 = 0;
calc_t const c1 = 1;

View File

@@ -0,0 +1,80 @@
// Boost.Geometry
// Copyright (c) 2019, 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_EXTENSIONS_STRATEGIES_SPHERICAL_IO_HPP
#define BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_SPHERICAL_IO_HPP
#include <boost/geometry/strategies/io.hpp>
#include <boost/geometry/strategies/spherical/point_order.hpp>
#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace io
{
template <typename CalculationType = void>
struct spherical
{
typedef strategy::point_order::spherical<CalculationType> point_order_strategy_type;
static inline point_order_strategy_type get_point_order_strategy()
{
return point_order_strategy_type();
}
template <typename Geometry1, typename Geometry2>
struct point_in_geometry_strategy
{
typedef strategy::within::spherical_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();
}
};
namespace services
{
template <>
struct default_strategy<spherical_equatorial_tag>
{
typedef spherical<> type;
};
template <>
struct default_strategy<spherical_polar_tag>
{
typedef spherical<> type;
};
} // namespace services
}} // namespace strategy::io
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_EXTENSIONS_STRATEGIES_SPHERICAL_IO_HPP

View File

@@ -96,8 +96,10 @@ private:
Point1, calculation_type, radian
>::type helper_point1, helper_point2;
Point1 point1_normalized = return_normalized<Point1>(point1);
Point2 point2_normalized = return_normalized<Point2>(point2);
Point1 point1_normalized;
strategy::normalize::spherical_point::apply(point1, point1_normalized);
Point2 point2_normalized;
strategy::normalize::spherical_point::apply(point2, point2_normalized);
geometry::transform(point1_normalized, helper_point1);
geometry::transform(point2_normalized, helper_point2);

View File

@@ -502,7 +502,7 @@ protected:
typedef math::detail::constants_on_spheroid<CalcT, Units> constants;
return constants::half_period() / CalcT(180);
};
}
template <typename Units, typename CalcT>
static inline bool longitudes_equal(CalcT const& lon1, CalcT const& lon2)

View File

@@ -0,0 +1,140 @@
// Boost.Geometry
// Copyright (c) 2019, 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_SPHERICAL_POINT_ORDER_HPP
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_POINT_ORDER_HPP
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/strategies/spherical/area.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/strategies/point_order.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace point_order
{
//template <typename CalculationType = void>
//struct spherical
//{
// typedef azimuth_tag version_tag;
//
// template <typename Geometry>
// struct result_type
// {
// typedef typename geometry::select_calculation_type_alt
// <
// CalculationType, Geometry
// >::type type;
// };
//
// template <typename Point>
// inline bool apply(Point const& p1, Point const& p2,
// typename result_type<Point>::type & azi,
// typename result_type<Point>::type & razi) const
// {
// typedef typename result_type<Point>::type calc_t;
//
// if (equals_point_point(p1, p2))
// {
// return false;
// }
//
// calc_t lon1 = geometry::get_as_radian<0>(p1);
// calc_t lat1 = geometry::get_as_radian<1>(p1);
// calc_t lon2 = geometry::get_as_radian<0>(p2);
// calc_t lat2 = geometry::get_as_radian<1>(p2);
//
// convert_latitudes<Point>(lat1, lat2);
//
// formula::result_spherical<calc_t>
// res = formula::spherical_azimuth<calc_t, true>(lon1, lat1, lon2, lat2);
//
// azi = res.azimuth;
// razi = res.reverse_azimuth;
//
// return true;
// }
//
// template <typename Point>
// inline typename result_type<Point>::type
// apply(Point const& /*p0*/, Point const& /*p1*/, Point const& /*p2*/,
// typename result_type<Point>::type const& azi1,
// typename result_type<Point>::type const& azi2) const
// {
// // TODO: support poles
// return math::longitude_distance_signed<radian>(azi1, azi2);
// }
//
//private:
// template <typename Point>
// static bool equals_point_point(Point const& p0, Point const& p1)
// {
// return strategy::within::spherical_point_point::apply(p0, p1);
// }
//
// template <typename Point, typename CalcT>
// static void convert_latitudes(CalcT & lat1, CalcT & lat2)
// {
// static const bool is_polar = boost::is_same
// <
// typename geometry::cs_tag<Point>::type,
// spherical_polar_tag
// >::value;
//
// if (BOOST_GEOMETRY_CONDITION(is_polar))
// {
// CalcT pi_half = math::half_pi<CalcT>();
// lat1 = pi_half - lat1;
// lat2 = pi_half - lat2;
// }
// }
//};
template <typename CalculationType = void>
struct spherical
: strategy::area::spherical<double, CalculationType>
{
typedef area_tag version_tag;
};
namespace services
{
template <>
struct default_strategy<spherical_equatorial_tag>
{
typedef spherical<> type;
};
/*template <>
struct default_strategy<spherical_polar_tag>
{
typedef spherical<> type;
};*/
} // namespace services
}} // namespace strategy::point_order
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_POINT_ORDER_HPP

View File

@@ -23,8 +23,13 @@
#include <cstddef>
#include <boost/qvm/mat.hpp>
#include <boost/qvm/vec.hpp>
#include <boost/qvm/mat_access.hpp>
#include <boost/qvm/vec_access.hpp>
#include <boost/qvm/mat_operations.hpp>
#include <boost/qvm/vec_mat_operations.hpp>
#include <boost/qvm/map_mat_mat.hpp>
#include <boost/qvm/map_mat_vec.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@@ -41,6 +46,96 @@ namespace boost { namespace geometry
namespace strategy { namespace transform
{
namespace detail { namespace matrix_transformer
{
template
<
typename Point,
std::size_t Dimension = 0,
std::size_t DimensionCount = geometry::dimension<Point>::value
>
struct set_point_from_vec
{
template <typename Vector>
static inline void apply(Point & p, Vector const& v)
{
typedef typename geometry::coordinate_type<Point>::type coord_t;
set<Dimension>(p, boost::numeric_cast<coord_t>(qvm::A<Dimension>(v)));
set_point_from_vec<Point, Dimension + 1, DimensionCount>::apply(p, v);
}
};
template
<
typename Point,
std::size_t DimensionCount
>
struct set_point_from_vec<Point, DimensionCount, DimensionCount>
{
template <typename Vector>
static inline void apply(Point &, Vector const& v) {}
};
template
<
typename Point,
std::size_t Dimension = 0,
std::size_t DimensionCount = geometry::dimension<Point>::value
>
struct set_vec_from_point
{
template <typename Vector>
static inline void apply(Point const& p, Vector & v)
{
qvm::A<Dimension>(v) = get<Dimension>(p);
set_vec_from_point<Point, Dimension + 1, DimensionCount>::apply(p, v);
}
};
template
<
typename Point,
std::size_t DimensionCount
>
struct set_vec_from_point<Point, DimensionCount, DimensionCount>
{
template <typename Vector>
static inline void apply(Point const& p, Vector & v) {}
};
template
<
typename CalculationType,
std::size_t Dimension1,
std::size_t Dimension2
>
class matrix_transformer
{
protected :
typedef CalculationType ct;
typedef boost::qvm::mat<ct, Dimension2 + 1, Dimension1 + 1> matrix_type;
matrix_type m_matrix;
public :
matrix_type const& matrix() const { return m_matrix; }
template <typename P1, typename P2>
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension_greater_equal<P1,Dimension1>();
assert_dimension_greater_equal<P2,Dimension2>();
qvm::vec<ct,Dimension1 + 1> p1temp;
qvm::A<Dimension1>(p1temp) = 1;
qvm::vec<ct,Dimension2 + 1> p2temp;
set_vec_from_point<P1, 0, Dimension1>::apply(p1, p1temp);
p2temp = m_matrix * p1temp;
set_point_from_vec<P2, 0, Dimension2>::apply(p2, p2temp);
return true;
}
};
}} // namespace detail::matrix_transform
/*!
\brief Affine transformation strategy in Cartesian system.
\details The strategy serves as a generic definition of affine transformation matrix
@@ -57,38 +152,41 @@ template
std::size_t Dimension1,
std::size_t Dimension2
>
class matrix_transformer
class matrix_transformer : public detail::matrix_transformer::matrix_transformer<CalculationType, Dimension1, Dimension2>
{
public:
template<typename Matrix>
inline matrix_transformer(Matrix const& matrix)
{
qvm::assign(this->m_matrix, matrix);
}
inline matrix_transformer() {}
};
template <typename CalculationType>
class matrix_transformer<CalculationType, 2, 2>
class matrix_transformer<CalculationType, 2, 2> : public detail::matrix_transformer::matrix_transformer<CalculationType, 2, 2>
{
protected :
typedef CalculationType ct;
typedef boost::qvm::mat<ct, 3, 3> matrix_type;
matrix_type m_matrix;
public :
template<typename Matrix>
inline matrix_transformer(Matrix const& matrix)
{
qvm::assign(this->m_matrix, matrix);
}
inline matrix_transformer() {}
inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
{
qvm::A<0,0>(m_matrix) = m_0_0; qvm::A<0,1>(m_matrix) = m_0_1; qvm::A<0,2>(m_matrix) = m_0_2;
qvm::A<1,0>(m_matrix) = m_1_0; qvm::A<1,1>(m_matrix) = m_1_1; qvm::A<1,2>(m_matrix) = m_1_2;
qvm::A<2,0>(m_matrix) = m_2_0; qvm::A<2,1>(m_matrix) = m_2_1; qvm::A<2,2>(m_matrix) = m_2_2;
qvm::A<0,0>(this->m_matrix) = m_0_0; qvm::A<0,1>(this->m_matrix) = m_0_1; qvm::A<0,2>(this->m_matrix) = m_0_2;
qvm::A<1,0>(this->m_matrix) = m_1_0; qvm::A<1,1>(this->m_matrix) = m_1_1; qvm::A<1,2>(this->m_matrix) = m_1_2;
qvm::A<2,0>(this->m_matrix) = m_2_0; qvm::A<2,1>(this->m_matrix) = m_2_1; qvm::A<2,2>(this->m_matrix) = m_2_2;
}
inline matrix_transformer(matrix_type const& matrix)
: m_matrix(matrix)
{}
inline matrix_transformer() {}
template <typename P1, typename P2>
inline bool apply(P1 const& p1, P2& p2) const
{
@@ -98,79 +196,45 @@ public :
ct const& c1 = get<0>(p1);
ct const& c2 = get<1>(p1);
ct p2x = c1 * qvm::A<0,0>(m_matrix) + c2 * qvm::A<0,1>(m_matrix) + qvm::A<0,2>(m_matrix);
ct p2y = c1 * qvm::A<1,0>(m_matrix) + c2 * qvm::A<1,1>(m_matrix) + qvm::A<1,2>(m_matrix);
typedef typename geometry::coordinate_type<P2>::type ct2;
set<0>(p2, boost::numeric_cast<ct2>(p2x));
set<1>(p2, boost::numeric_cast<ct2>(p2y));
set<0>(p2, boost::numeric_cast<ct2>(c1 * qvm::A<0,0>(this->m_matrix) + c2 * qvm::A<0,1>(this->m_matrix) + qvm::A<0,2>(this->m_matrix)));
set<1>(p2, boost::numeric_cast<ct2>(c1 * qvm::A<1,0>(this->m_matrix) + c2 * qvm::A<1,1>(this->m_matrix) + qvm::A<1,2>(this->m_matrix)));
return true;
}
matrix_type const& matrix() const { return m_matrix; }
};
// It IS possible to go from 3 to 2 coordinates
template <typename CalculationType>
class matrix_transformer<CalculationType, 3, 2> : public matrix_transformer<CalculationType, 2, 2>
class matrix_transformer<CalculationType, 3, 2> : public detail::matrix_transformer::matrix_transformer<CalculationType, 3, 2>
{
typedef CalculationType ct;
typedef boost::qvm::mat<ct, 3, 3> matrix_type;
public :
template<typename Matrix>
inline matrix_transformer(Matrix const& matrix)
{
qvm::assign(this->m_matrix, matrix);
}
inline matrix_transformer() {}
inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
: matrix_transformer<CalculationType, 2, 2>(
m_0_0, m_0_1, m_0_2,
m_1_0, m_1_1, m_1_2,
m_2_0, m_2_1, m_2_2)
{}
inline matrix_transformer(matrix_type const& matrix)
: matrix_transformer<CalculationType, 2,2>(matrix)
{}
inline matrix_transformer()
: matrix_transformer<CalculationType, 2, 2>()
{}
};
template <typename CalculationType>
class matrix_transformer<CalculationType, 3, 3>
{
protected :
typedef CalculationType ct;
typedef boost::qvm::mat<ct, 4, 4> matrix_type;
matrix_type m_matrix;
public :
inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
)
{
qvm::A<0,0>(m_matrix) = m_0_0; qvm::A<0,1>(m_matrix) = m_0_1; qvm::A<0,2>(m_matrix) = m_0_2; qvm::A<0,3>(m_matrix) = m_0_3;
qvm::A<1,0>(m_matrix) = m_1_0; qvm::A<1,1>(m_matrix) = m_1_1; qvm::A<1,2>(m_matrix) = m_1_2; qvm::A<1,3>(m_matrix) = m_1_3;
qvm::A<2,0>(m_matrix) = m_2_0; qvm::A<2,1>(m_matrix) = m_2_1; qvm::A<2,2>(m_matrix) = m_2_2; qvm::A<2,3>(m_matrix) = m_2_3;
qvm::A<3,0>(m_matrix) = m_3_0; qvm::A<3,1>(m_matrix) = m_3_1; qvm::A<3,2>(m_matrix) = m_3_2; qvm::A<3,3>(m_matrix) = m_3_3;
qvm::A<0,0>(this->m_matrix) = m_0_0; qvm::A<0,1>(this->m_matrix) = m_0_1; qvm::A<0,2>(this->m_matrix) = 0; qvm::A<0,3>(this->m_matrix) = m_0_2;
qvm::A<1,0>(this->m_matrix) = m_1_0; qvm::A<1,1>(this->m_matrix) = m_1_1; qvm::A<1,2>(this->m_matrix) = 0; qvm::A<1,3>(this->m_matrix) = m_1_2;
qvm::A<2,0>(this->m_matrix) = m_2_0; qvm::A<2,1>(this->m_matrix) = m_2_1; qvm::A<2,2>(this->m_matrix) = 0; qvm::A<2,3>(this->m_matrix) = m_2_2;
}
inline matrix_transformer(matrix_type const& matrix)
: m_matrix(matrix)
{}
inline matrix_transformer() {}
template <typename P1, typename P2>
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension_greater_equal<P1, 3>();
assert_dimension_greater_equal<P2, 2>();
ct const& c1 = get<0>(p1);
ct const& c2 = get<1>(p1);
ct const& c3 = get<2>(p1);
@@ -178,16 +242,63 @@ public :
typedef typename geometry::coordinate_type<P2>::type ct2;
set<0>(p2, boost::numeric_cast<ct2>(
c1 * qvm::A<0,0>(m_matrix) + c2 * qvm::A<0,1>(m_matrix) + c3 * qvm::A<0,2>(m_matrix) + qvm::A<0,3>(m_matrix)));
c1 * qvm::A<0,0>(this->m_matrix) + c2 * qvm::A<0,1>(this->m_matrix) + c3 * qvm::A<0,2>(this->m_matrix) + qvm::A<0,3>(this->m_matrix)));
set<1>(p2, boost::numeric_cast<ct2>(
c1 * qvm::A<1,0>(m_matrix) + c2 * qvm::A<1,1>(m_matrix) + c3 * qvm::A<1,2>(m_matrix) + qvm::A<1,3>(m_matrix)));
set<2>(p2, boost::numeric_cast<ct2>(
c1 * qvm::A<2,0>(m_matrix) + c2 * qvm::A<2,1>(m_matrix) + c3 * qvm::A<2,2>(m_matrix) + qvm::A<2,3>(m_matrix)));
c1 * qvm::A<1,0>(this->m_matrix) + c2 * qvm::A<1,1>(this->m_matrix) + c3 * qvm::A<1,2>(this->m_matrix) + qvm::A<1,3>(this->m_matrix)));
return true;
}
matrix_type const& matrix() const { return m_matrix; }
};
template <typename CalculationType>
class matrix_transformer<CalculationType, 3, 3> : public detail::matrix_transformer::matrix_transformer<CalculationType, 3, 3>
{
typedef CalculationType ct;
public :
template<typename Matrix>
inline matrix_transformer(Matrix const& matrix)
{
qvm::assign(this->m_matrix, matrix);
}
inline matrix_transformer() {}
inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
)
{
qvm::A<0,0>(this->m_matrix) = m_0_0; qvm::A<0,1>(this->m_matrix) = m_0_1; qvm::A<0,2>(this->m_matrix) = m_0_2; qvm::A<0,3>(this->m_matrix) = m_0_3;
qvm::A<1,0>(this->m_matrix) = m_1_0; qvm::A<1,1>(this->m_matrix) = m_1_1; qvm::A<1,2>(this->m_matrix) = m_1_2; qvm::A<1,3>(this->m_matrix) = m_1_3;
qvm::A<2,0>(this->m_matrix) = m_2_0; qvm::A<2,1>(this->m_matrix) = m_2_1; qvm::A<2,2>(this->m_matrix) = m_2_2; qvm::A<2,3>(this->m_matrix) = m_2_3;
qvm::A<3,0>(this->m_matrix) = m_3_0; qvm::A<3,1>(this->m_matrix) = m_3_1; qvm::A<3,2>(this->m_matrix) = m_3_2; qvm::A<3,3>(this->m_matrix) = m_3_3;
}
template <typename P1, typename P2>
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension_greater_equal<P1, 3>();
assert_dimension_greater_equal<P2, 3>();
ct const& c1 = get<0>(p1);
ct const& c2 = get<1>(p1);
ct const& c3 = get<2>(p1);
typedef typename geometry::coordinate_type<P2>::type ct2;
set<0>(p2, boost::numeric_cast<ct2>(
c1 * qvm::A<0,0>(this->m_matrix) + c2 * qvm::A<0,1>(this->m_matrix) + c3 * qvm::A<0,2>(this->m_matrix) + qvm::A<0,3>(this->m_matrix)));
set<1>(p2, boost::numeric_cast<ct2>(
c1 * qvm::A<1,0>(this->m_matrix) + c2 * qvm::A<1,1>(this->m_matrix) + c3 * qvm::A<1,2>(this->m_matrix) + qvm::A<1,3>(this->m_matrix)));
set<2>(p2, boost::numeric_cast<ct2>(
c1 * qvm::A<2,0>(this->m_matrix) + c2 * qvm::A<2,1>(this->m_matrix) + c3 * qvm::A<2,2>(this->m_matrix) + qvm::A<2,3>(this->m_matrix)));
return true;
}
};
@@ -262,6 +373,21 @@ class scale_transformer
{
};
template
<
typename CalculationType,
std::size_t Dimension1
>
class scale_transformer<CalculationType, Dimension1, Dimension1> : public matrix_transformer<CalculationType, Dimension1, Dimension1>
{
public:
inline scale_transformer(CalculationType const& scale)
{
boost::qvm::set_identity(this->m_matrix);
this->m_matrix*=scale;
qvm::A<Dimension1,Dimension1>(this->m_matrix) = 1;
}
};
template <typename CalculationType>
class scale_transformer<CalculationType, 2, 2> : public matrix_transformer<CalculationType, 2, 2>
@@ -352,11 +478,11 @@ template
std::size_t Dimension2
>
class rad_rotate_transformer
: public matrix_transformer<CalculationType, Dimension1, Dimension2>
: public transform::matrix_transformer<CalculationType, Dimension1, Dimension2>
{
public :
inline rad_rotate_transformer(CalculationType const& angle)
: matrix_transformer<CalculationType, Dimension1, Dimension2>(
: transform::matrix_transformer<CalculationType, Dimension1, Dimension2>(
cos(angle), sin(angle), 0,
-sin(angle), cos(angle), 0,
0, 0, 1)

View File

@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014, 2015, 2016.
// Modifications copyright (c) 2013-2016 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2015, 2016, 2019.
// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -305,7 +305,7 @@ erase(Range & rng,
it = boost::begin(rng)
+ std::distance(boost::const_begin(rng), cit);
return erase(rng, it);
return range::erase(rng, it);
}
/*!
@@ -366,7 +366,7 @@ erase(Range & rng,
last = boost::begin(rng)
+ std::distance(boost::const_begin(rng), clast);
return erase(rng, first, last);
return range::erase(rng, first, last);
}
// back_inserter

View File

@@ -1,8 +1,9 @@
[
{
"key": "geometry/index",
"boost-version": "1.54.0",
"boost-version": "hidden",
"name": "Geometry Index",
"status": "hidden",
"authors": [
"Barend Gehrels",
"Bruno Lalande",

View File

@@ -390,7 +390,7 @@ public :
typedef bg::detail::overlay::turn_info
<
Point,
typename bg::segment_ratio_type<Point, RescalePolicy>::type
typename bg::detail::segment_ratio_type<Point, RescalePolicy>::type
> turn_info;
std::vector<turn_info> turns;

View File

@@ -0,0 +1,79 @@
// Boost.Geometry
// Copyright (c) 2017 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_TEST_CHECK_VALIDITY_HPP
#define BOOST_GEOMETRY_TEST_CHECK_VALIDITY_HPP
#include <boost/foreach.hpp>
#include <boost/geometry/algorithms/is_valid.hpp>
template<typename Geometry, typename G1, typename G2>
inline bool is_output_valid(Geometry const& geometry,
std::string const& case_id,
G1 const& g1, G2 const& g2,
std::string& message)
{
bool const result = bg::is_valid(geometry, message);
if (! result)
{
// Check if input was valid. If not, do not report output validity
if (! bg::is_valid(g1) || ! bg::is_valid(g2))
{
std::cout << "WARNING: Input is not considered as valid; "
<< "this can cause that output is invalid: " << case_id
<< std::endl;
return true;
}
}
return result;
}
template
<
typename Geometry,
typename Tag = typename bg::tag<Geometry>::type
>
struct check_validity
{
template <typename G1, typename G2>
static inline
bool apply(Geometry const& geometry,
std::string const& case_id,
G1 const& g1, G2 const& g2,
std::string& message)
{
return is_output_valid(geometry, case_id, g1, g2, message);
}
};
// Specialization for vector of <geometry> (e.g. rings)
template <typename Geometry>
struct check_validity<Geometry, void>
{
template <typename G1, typename G2>
static inline
bool apply(Geometry const& geometry,
std::string const& case_id,
G1 const& g1, G2 const& g2,
std::string& message)
{
typedef typename boost::range_value<Geometry>::type single_type;
BOOST_FOREACH(single_type const& element, geometry)
{
if (! is_output_valid(element, case_id, g1, g2, message))
{
return false;
}
}
return true;
}
};
#endif // BOOST_GEOMETRY_TEST_CHECK_VALIDITY_HPP

View File

@@ -4,8 +4,8 @@
# Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
#
# This file was modified by Oracle on 2015.
# Modifications copyright (c) 2015 Oracle and/or its affiliates.
# 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
#
@@ -15,8 +15,9 @@
test-suite boost-geometry-algorithms-detail
:
[ run as_range.cpp : : : : algorithms_as_range ]
[ run partition.cpp : : : : algorithms_partition ]
[ run as_range.cpp : : : : algorithms_as_range ]
[ run calculate_point_order.cpp : : : : algorithms_calculate_point_order ]
[ run partition.cpp : : : : algorithms_partition ]
;
build-project sections ;

View File

@@ -0,0 +1,148 @@
// Boost.Geometry
// Unit Test
// Copyright (c) 2019, 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
#include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/detail/calculate_point_order.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/ring.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
#include <boost/geometry/strategies/cartesian/point_order.hpp>
#include <boost/geometry/strategies/geographic/point_order.hpp>
#include <boost/geometry/strategies/spherical/point_order.hpp>
inline const char * order_str(bg::order_selector o)
{
if (o == bg::clockwise)
return "clockwise";
else if (o == bg::counterclockwise)
return "counterclockwise";
else
return "order_undetermined";
}
inline const char * cs_str(bg::cartesian_tag)
{
return "cartesian";
}
inline const char * cs_str(bg::spherical_equatorial_tag)
{
return "spherical_equatorial";
}
inline const char * cs_str(bg::geographic_tag)
{
return "geographic";
}
template <typename Ring>
inline void test_one(Ring const& ring, bg::order_selector expected)
{
typedef typename bg::cs_tag<Ring>::type cs_tag;
bg::order_selector result = bg::detail::calculate_point_order(ring);
BOOST_CHECK_MESSAGE(result == expected, "Expected: " << order_str(expected) << " for " << bg::wkt(ring) << " in " << cs_str(cs_tag()));
if (expected != bg::order_undetermined && result != bg::order_undetermined)
{
Ring ring_rev = ring;
std::reverse(boost::begin(ring_rev), boost::end(ring_rev));
bg::order_selector result_rev = bg::detail::calculate_point_order(ring_rev);
BOOST_CHECK_MESSAGE(result != result_rev, "Invalid order of reversed: " << bg::wkt(ring) << " in " << cs_str(cs_tag()));
}
}
template <typename P>
inline void test_one(std::string const& ring_wkt, bg::order_selector expected)
{
//typedef typename bg::cs_tag<P>::type cs_tag;
bg::model::ring<P> ring;
bg::read_wkt(ring_wkt, ring);
std::size_t n = boost::size(ring);
for (size_t i = 1; i < n; ++i)
{
test_one(ring, expected);
std::rotate(boost::begin(ring), boost::begin(ring) + 1, boost::end(ring));
// it seems that area method doesn't work for invalid "opened" polygons
//if (! boost::is_same<cs_tag, bg::geographic_tag>::value)
{
P p = bg::range::front(ring);
bg::range::push_back(ring, p);
}
}
}
template <typename P>
void test_all()
{
// From correct() test, rings rotated and reversed in test_one()
test_one<P>("POLYGON((0 0,0 1,1 1,1 0,0 0))", bg::clockwise);
test_one<P>("POLYGON((0 0,0 1,1 1,1 0))", bg::clockwise);
test_one<P>("POLYGON((0 0,0 4,4 4,4 0,0 0))", bg::clockwise);
test_one<P>("POLYGON((1 1,2 1,2 2,1 2,1 1))", bg::counterclockwise);
test_one<P>("POLYGON((0 5, 5 5, 5 0, 0 0, 0 5))", bg::clockwise);
test_one<P>("POLYGON((0 5, 0 5, 0 6, 0 6, 0 4, 0 5, 5 5, 5 0, 0 0, 0 6, 0 5))", bg::clockwise);
test_one<P>("POLYGON((2 0, 2 1, 2 -1, 2 0, 1 0, 1 -1, 0 -1, 0 1, 1 1, 1 0, 2 0))", bg::clockwise);
test_one<P>("POLYGON((2 0, 2 1, 2 -1, 2 0, 1 0, 1 -1, 0 -1, 0 1, 1 1, 1 0))", bg::clockwise);
test_one<P>("POLYGON((2 0, 2 1, 3 1, 3 -1, 2 -1, 2 0, 1 0, 1 -1, 0 -1, 0 1, 1 1, 1 0, 2 0))", bg::clockwise);
test_one<P>("POLYGON((0 85, 5 85, 5 84, 0 84, 0 85))", bg::clockwise);
test_one<P>("POLYGON((0 2, 170 2, 170 0, 0 0, 0 2))", bg::clockwise);
test_one<P>("POLYGON((0 2, 170 2, 170 1, 160 1, 10 1, 0 1, 0 2))", bg::clockwise);
test_one<P>("POLYGON((0 2, 170 2, 170 -2, 0 -2, 0 2))", bg::clockwise);
test_one<P>("POLYGON((5 5, 6 5, 6 6, 6 4, 6 5, 5 5, 5 4, 4 4, 4 6, 5 6, 5 5))", bg::clockwise);
test_one<P>("POLYGON((5 5, 6 5, 6 6, 6 4, 6 5, 5 5, 5 6, 4 6, 4 4, 5 4, 5 5))", bg::counterclockwise);
test_one<P>("POLYGON((5 5, 6 5, 6 5, 6 6, 6 5, 6 4, 6 5, 6 5, 5 5, 5 4, 4 4, 4 6, 5 6, 5 5))", bg::clockwise);
// https://github.com/boostorg/geometry/pull/554
test_one<P>("POLYGON((9.8591674311151110 54.602813224425063, 9.8591651519791412 54.602359676428932, 9.8584586199249316 54.602359676428932, 9.8591674311151110 54.602813224425063))",
bg::clockwise);
}
template <typename P>
void test_cartesian()
{
test_one<P>("POLYGON((0 5, 1 5, 1 6, 1 4, 2 4, 0 4, 0 3, 0 5))", bg::clockwise);
}
template <typename P>
void test_spheroidal()
{
test_one<P>("POLYGON((0 5, 1 5, 1 6, 1 4, 0 4, 0 3, 0 5))", bg::clockwise);
test_one<P>("POLYGON((0 45, 120 45, -120 45, 0 45))", bg::counterclockwise);
}
int test_main(int, char* [])
{
test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
test_all<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > >();
test_all<bg::model::point<double, 2, bg::cs::geographic<bg::degree> > >();
test_cartesian<bg::model::point<double, 2, bg::cs::cartesian> >();
test_spheroidal<bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > >();
test_spheroidal<bg::model::point<double, 2, bg::cs::geographic<bg::degree> > >();
return 0;
}

View File

@@ -11,7 +11,6 @@
// http://www.boost.org/users/license.html
#include <iostream>
#define BOOST_GEOMETRY_TEST_DEBUG
#ifndef BOOST_TEST_MODULE
#define BOOST_TEST_MODULE test_distance_spherical_equatorial_pointlike_linear
@@ -278,6 +277,18 @@ void test_distance_point_linestring(Strategy const& strategy)
0.06146397739758279 * r,
0.000944156107132969,
strategy);
//https://github.com/boostorg/geometry/issues/557
tester::apply("p-l-issue557",
"POINT(51.99999790563572 43.71656981636763)",
"LINESTRING(52.0000243071011 43.716569742012496,\
52.0000121532845 43.71656942616241,\
52.0 43.7165690998572,\
51.999987847203 43.7165687638793)",
1.35062e-08 * r,
4.5604e-17,
strategy);
}
//===========================================================================

View File

@@ -42,6 +42,18 @@ void test_all()
, std::sqrt(2.0)
, "LINESTRING(10 1,2 2)"
);
test_geometry<bg::model::linestring<P> >
(
"LINESTRING EMPTY"
, 0
, "LINESTRING()"
, "LINESTRING()"
, ""
, 0
, "LINESTRING()"
);
test_geometry<bg::model::ring<P> >
(
"POLYGON((1 1,1 4,4 4,4 1,1 1))"
@@ -54,6 +66,18 @@ void test_all()
, 4 * 3.0
, "POLYGON((10 1,10 4,4 4,4 1,1 1))"
);
test_geometry<bg::model::ring<P> >
(
"POLYGON EMPTY"
, 0
, "POLYGON(())"
, "POLYGON(())"
, ""
, 0
, "POLYGON(())"
);
test_geometry<bg::model::ring<P, true, false> > // open ring
(
"POLYGON((1 1,1 4,4 4,4 1))"

View File

@@ -19,6 +19,7 @@
#include <boost/test/included/unit_test.hpp>
#include "test_is_valid.hpp"
#include "overlay/overlay_cases.hpp"
#include <boost/geometry/core/coordinate_type.hpp>
@@ -784,6 +785,7 @@ inline void test_open_polygons()
false);
}
template <typename Point>
inline void test_doc_example_polygon()
{
@@ -794,13 +796,16 @@ inline void test_doc_example_polygon()
std::cout << "************************************" << std::endl;
#endif
typedef bg::model::polygon<Point> CCW_CG;
typedef bg::model::polygon<Point> ClockwiseClosedPolygon;
typedef validity_tester_areal<true> tester;
typedef test_valid<tester, CCW_CG> test;
typedef test_valid<tester, ClockwiseClosedPolygon> test;
test::apply("pg-doc",
"POLYGON((0 0,0 10,10 10,10 0,0 0),(0 0,9 1,9 2,0 0),(0 0,2 9,1 9,0 0),(2 9,9 2,9 9,2 9))",
false);
// Containing a self touching point, which should be valid
test::apply("ggl_list_20190307_matthieu_2", ggl_list_20190307_matthieu_2[1], true);
}
BOOST_AUTO_TEST_CASE( test_is_valid_polygon )

View File

@@ -84,7 +84,7 @@ void test_with_point(std::string const& caseid,
typedef bg::detail::overlay::turn_info
<
P,
typename bg::segment_ratio_type<P, rescale_policy_type>::type
typename bg::detail::segment_ratio_type<P, rescale_policy_type>::type
> turn_info;
typedef std::vector<turn_info> tp_vector;
turn_info model;

View File

@@ -80,7 +80,7 @@ struct test_get_turns
typedef bg::detail::overlay::turn_info
<
point_type,
typename bg::segment_ratio_type<point_type, rescale_policy_type>::type
typename bg::detail::segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
std::vector<turn_info> turns;

View File

@@ -25,7 +25,7 @@
#endif
#include <geometry_test_common.hpp>
#include <algorithms/check_validity.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
@@ -433,6 +433,12 @@ void test_overlay(std::string const& caseid,
overlay::apply(g1, g2, robust_policy, std::back_inserter(result),
strategy, visitor);
std::string message;
bool const valid = check_validity<Geometry>::apply(result, caseid, g1, g2, message);
BOOST_CHECK_MESSAGE(valid,
"overlay: " << caseid << " not valid: " << message
<< " type: " << (type_for_assert_message<Geometry, Geometry>()));
BOOST_CHECK_CLOSE(bg::area(result), expected_area, 0.001);
BOOST_CHECK_MESSAGE((bg::num_interior_rings(result) == expected_hole_count),
caseid

View File

@@ -838,6 +838,30 @@ static std::string case_precision_22[2] =
"POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2 3,4.00000000200000017 2.99999999000000006,4 7,2 7))"
};
static std::string case_precision_23[2] =
{
"POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))",
"POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2 3,3.99998999999999993 2.99998999999999993,4 7,2 7))"
};
static std::string case_precision_24[2] =
{
"POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))",
"POLYGON((2 7,4 7,4 3.000001,2 3,2 7))"
};
static std::string case_precision_25[2] =
{
"POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))",
"POLYGON((2 7,4 7,4 3.00001,2 3,2 7))"
};
static std::string case_precision_26[2] =
{
"POLYGON((0 0,0 4,2 4,2 3,4 3,4 0,0 0))",
"POLYGON((-1 -1,-1 8,8 8,8 -1,-1 -1),(2 7,2 3,3.999991 2.999991,4 7,2 7))"
};
// ticket_17 is keyholed, so has a hole formed by an deliberate intersection
// This will fail the intersection/traversal process

View File

@@ -60,22 +60,12 @@ static void test_self_intersection_points(std::string const& case_id,
typename bg::cs_tag<Geometry>::type
>::type strategy_type;
typedef bg::detail::no_rescale_policy rescale_policy_type;
typedef bg::detail::overlay::turn_info
<
point_type,
typename bg::segment_ratio_type
<
point_type, rescale_policy_type
>::type
> turn_info;
typedef bg::detail::overlay::turn_info<point_type> turn_info;
std::vector<turn_info> turns;
strategy_type strategy;
rescale_policy_type rescale_policy
;
// = bg::get_rescale_policy<rescale_policy_type>(geometry);
///bg::get_intersection_points(geometry, turns);
rescale_policy_type rescale_policy;
bg::detail::self_get_turn_points::no_interrupt_policy policy;
bg::self_turns

View File

@@ -137,7 +137,7 @@ std::vector<std::size_t> apply_overlay(
typedef bg::detail::overlay::traversal_turn_info
<
point_type,
typename bg::segment_ratio_type<point_type, RobustPolicy>::type
typename bg::detail::segment_ratio_type<point_type, RobustPolicy>::type
> turn_info;
typedef std::deque<turn_info> turn_container_type;

View File

@@ -74,7 +74,7 @@ std::vector<std::size_t> apply_get_turns(std::string const& case_id,
typedef bg::detail::overlay::turn_info
<
point_type,
typename bg::segment_ratio_type<point_type, RobustPolicy>::type
typename bg::detail::segment_ratio_type<point_type, RobustPolicy>::type
> turn_info;
typedef std::deque<turn_info> turn_container_type;

View File

@@ -171,7 +171,7 @@ void check_geometry_range(Geometry1 const& g1,
typedef bg::detail::no_rescale_policy robust_policy_type;
typedef typename bg::point_type<Geometry2>::type point_type;
typedef typename bg::segment_ratio_type
typedef typename bg::detail::segment_ratio_type
<
point_type, robust_policy_type
>::type segment_ratio_type;

View File

@@ -164,7 +164,7 @@ struct test_traverse
typedef bg::detail::overlay::traversal_turn_info
<
point_type,
typename bg::segment_ratio_type<point_type, rescale_policy_type>::type
typename bg::detail::segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
std::vector<turn_info> turns;

View File

@@ -59,7 +59,7 @@ intersect(Geometry1 const& g1, Geometry2 const& g2, std::string const& name,
typedef bg::detail::overlay::traversal_turn_info
<
point_type,
typename bg::segment_ratio_type<point_type, rescale_policy_type>::type
typename bg::detail::segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
std::vector<turn_info> turns;

View File

@@ -1,50 +0,0 @@
// Boost.Geometry
// Copyright (c) 2017 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_TEST_SETOP_CHECK_VALIDITY_HPP
#define BOOST_GEOMETRY_TEST_SETOP_CHECK_VALIDITY_HPP
#include <boost/foreach.hpp>
#include <boost/geometry/algorithms/is_valid.hpp>
template
<
typename Geometry,
typename Tag = typename bg::tag<Geometry>::type
>
struct check_validity
{
static inline
bool apply(Geometry const& geometry, std::string& message)
{
return bg::is_valid(geometry, message);
}
};
// Specialization for vector of <geometry> (e.g. rings)
template <typename Geometry>
struct check_validity<Geometry, void>
{
static inline
bool apply(Geometry const& geometry, std::string& message)
{
typedef typename boost::range_value<Geometry>::type single_type;
BOOST_FOREACH(single_type const& element, geometry)
{
if (! bg::is_valid(element, message))
{
return false;
}
}
return true;
}
};
#endif // BOOST_GEOMETRY_TEST_SETOP_CHECK_VALIDITY_HPP

View File

@@ -49,9 +49,7 @@
template <typename P>
void test_all()
{
typedef bg::model::box<P> box;
typedef bg::model::polygon<P> polygon;
typedef bg::model::ring<P> ring;
typedef typename bg::coordinate_type<P>::type ct;
@@ -246,6 +244,45 @@ void test_all()
TEST_DIFFERENCE(case_106, 1, 17.5, 2, 32.5, 3);
TEST_DIFFERENCE(case_107, 2, 18.0, 2, 29.0, 4);
TEST_DIFFERENCE(case_precision_1, 1, 14.0, 1, BG_IF_RESCALED(8.00001, 8.0), 1);
TEST_DIFFERENCE(case_precision_2, 1, 14.0, 1, 8.0, 1);
TEST_DIFFERENCE(case_precision_3, 1, 14.0, 1, 8.0, 1);
TEST_DIFFERENCE(case_precision_4, 1, 14.0, 1, 8.0, 1);
#if ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
TEST_DIFFERENCE(case_precision_5, 1, 14.0, 1, 8.0, 1);
TEST_DIFFERENCE(case_precision_6, 0, 0.0, 1, 57.0, 1);
#endif
TEST_DIFFERENCE(case_precision_7, 1, 14.0, 1, 8.0, 1);
TEST_DIFFERENCE(case_precision_8, 0, 0.0, 1, 59.0, 1);
#if ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
TEST_DIFFERENCE(case_precision_9, 0, 0.0, 1, 59.0, 1);
TEST_DIFFERENCE(case_precision_10, 0, 0.0, 1, 59.0, 1);
#endif
TEST_DIFFERENCE(case_precision_11, 0, 0.0, 1, 59.0, 1);
TEST_DIFFERENCE(case_precision_12, 1, 12.0, 0, 0.0, 1);
TEST_DIFFERENCE(case_precision_13, 1, BG_IF_RESCALED(12.00002, 12.0), 0, 0.0, 1);
TEST_DIFFERENCE(case_precision_14, 1, 14.0, 1, 8.0, 1);
TEST_DIFFERENCE(case_precision_15, 0, 0.0, 1, 59.0, 1);
#if ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
TEST_DIFFERENCE(case_precision_16, 0, 0.0, 1, 59.0, 1);
#endif
TEST_DIFFERENCE(case_precision_17, 0, 0.0, 1, 59.0, 1);
TEST_DIFFERENCE(case_precision_18, 0, 0.0, 1, 59.0, 1);
#if ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
TEST_DIFFERENCE(case_precision_19, 0, 0.0, 1, 59.0, 1);
#endif
TEST_DIFFERENCE(case_precision_20, 1, 14.0, 1, 8.0, 1);
TEST_DIFFERENCE(case_precision_21, 1, 14.0, 1, 7.99999, 1);
TEST_DIFFERENCE(case_precision_22, 0, 0.0, 1, 59.0, 1);
#if ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
TEST_DIFFERENCE(case_precision_23, 0, 0.0, 1, 59.0, 1);
#endif
TEST_DIFFERENCE(case_precision_24, 1, 14.0, 1, 8.0, 1);
TEST_DIFFERENCE(case_precision_25, 1, 14.0, 1, 7.99999, 1);
#if ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
TEST_DIFFERENCE(case_precision_26, 0, 0.0, 1, 59.0, 1);
#endif
test_one<polygon, polygon, polygon>("winded",
winded[0], winded[1],
3, 37, 61,
@@ -308,19 +345,19 @@ void test_all()
settings);
}
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
test_one<polygon, polygon, polygon>("geos_1",
geos_1[0], geos_1[1],
21, -1, 0.31640625,
9, -1, 0.01953125);
#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
{
ut_settings settings;
settings.percentage = 0.01;
settings.test_validity = false;
// Excluded this test in the normal suite, it is OK like this for many clang/gcc/msvc
// versions, but NOT OK for many other clang/gcc/msvc versions on other platforms
// It might depend on partition (order)
// 10, -1, 0.02148439); // change in partition might give these results
// SQL Server gives: 0.28937764436705 and 0.000786406897532288 with 44/35 rings
// PostGIS gives: 0.30859375 and 0.033203125 with 35/35 rings
// SQL Server gives: 0.28937764436705 and 0.000786406897532288 with 44/35 rings
// PostGIS gives: 0.30859375 and 0.033203125 with 35/35 rings
TEST_DIFFERENCE_WITH(geos_1,
-1, BG_IF_KRAMER(0.29171, 0.189697476),
-1, BG_IF_KRAMER(0.00076855, 0.000018266),
-1);
}
#endif
{
@@ -367,25 +404,25 @@ void test_all()
if ( BOOST_GEOMETRY_CONDITION((! boost::is_same<ct, float>::value)) )
{
test_one<polygon, polygon, polygon>("ggl_list_20110716_enrico",
ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1],
3, -1, 35723.8506317139,
1, -1, 58456.4964294434,
1, -1, 35723.8506317139 + 58456.4964294434);
TEST_DIFFERENCE(ggl_list_20110716_enrico,
3, 35723.8506317139, // TODO FOR GENERIC, misses one of three outputs
1, 58456.4964294434,
1);
}
#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
#if defined(BOOST_GEOMETRY_USE_RESCALING) \
|| ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE) \
|| defined(BOOST_GEOMETRY_TEST_FAILURES)
{
// symmetric difference is not valid due to robustness issue, it has
// two turns (touch_only) and a midpoint is located in other polygon
ut_settings ignore_validity;
ignore_validity.test_validity = false;
// Symmetric difference should output one polygon
// Using rescaling, it currently outputs two.
ut_settings settings;
settings.test_validity = false;
test_one<polygon, polygon, polygon>("ggl_list_20110820_christophe",
ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1],
1, -1, 2.8570121719168924,
1, -1, 64.498061986388564,
ignore_validity);
TEST_DIFFERENCE_WITH(ggl_list_20110820_christophe,
1, 2.8570121719168924,
1, 64.498061986388564,
BG_IF_RESCALED(2, 1));
}
#endif
@@ -415,7 +452,10 @@ void test_all()
// With rescaling, difference of output a-b and a sym b is invalid
ut_settings settings;
settings.test_validity = BG_IF_RESCALED(false, true);
TEST_DIFFERENCE_WITH(ggl_list_20190307_matthieu_1, 2, 0.18461532, 2, 0.617978, 4);
TEST_DIFFERENCE_WITH(ggl_list_20190307_matthieu_1,
BG_IF_KRAMER(2, 1), 0.18461532,
BG_IF_KRAMER(2, 1), 0.617978,
BG_IF_KRAMER(4, 2));
TEST_DIFFERENCE_WITH(ggl_list_20190307_matthieu_2, 2, 12.357152, 0, 0.0, 2);
}
@@ -443,12 +483,19 @@ void test_all()
2, 12, 0.0451236449624935,
0, 0, 0);
#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
test_one<polygon, polygon, polygon>("ticket_9563",
ticket_9563[0], ticket_9563[1],
0, -1, 0,
6, -1, 20.096189);
{
ut_settings settings;
settings.test_validity = BG_IF_RESCALED(true, false);
#if !defined(BOOST_GEOMETRY_USE_RESCALING) && defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
const int expected_count = 1; // Wrong, considers all consecutive polygons as one
#else
const int expected_count = 6;
#endif
TEST_DIFFERENCE_WITH(ticket_9563,
0, 0,
expected_count, 20.096189,
expected_count);
}
test_one<polygon, polygon, polygon>("ticket_10108_a",
ticket_10108_a[0], ticket_10108_a[1],
@@ -475,7 +522,11 @@ void test_all()
2, 23, 62.25,
0, 0, 0.0);
// Other combi's
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
typedef bg::model::box<P> box;
typedef bg::model::ring<P> ring;
// Other combinations
{
test_one<polygon, polygon, ring>(
"star_ring_ring", example_star, example_ring,
@@ -534,32 +585,32 @@ void test_all()
3, -1, 8.53333333333, 2, -1, 0.53333333333);
}
#endif
// Rescaling generates a very small false polygon
TEST_DIFFERENCE(issue_566_a, 1, 143.662, BG_IF_RESCALED(1, 0),
BG_IF_RESCALED(1.605078e-6, 0.0),
BG_IF_RESCALED(2, 1));
{
ut_settings settings;
#if defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
settings.test_validity = BG_IF_RESCALED(true, false);
#endif
TEST_DIFFERENCE_WITH(issue_566_a, 1, 143.662, BG_IF_RESCALED(1, 0),
BG_IF_RESCALED(1.605078e-6, 0.0),
BG_IF_RESCALED(2, 1));
}
TEST_DIFFERENCE(issue_566_b, 1, 143.662, BG_IF_RESCALED(1, 0),
BG_IF_RESCALED(1.605078e-6, 0.0),
BG_IF_RESCALED(2, 1));
/***
Experimental (cut), does not work:
test_one<polygon, polygon, polygon>(
"polygon_pseudo_line",
"POLYGON((0 0,0 4,4 4,4 0,0 0))",
"POLYGON((2 -2,2 -1,2 6,2 -2))",
5, 22, 1.1901714,
5, 27, 1.6701714);
***/
TEST_DIFFERENCE(mysql_21977775, 2, 160.856568913, 2, 92.3565689126, 4);
TEST_DIFFERENCE(mysql_21965285, 1, 92.0, 1, 14.0, 1);
TEST_DIFFERENCE(mysql_23023665_1, 1, 92.0, 1, 142.5, 2);
TEST_DIFFERENCE(mysql_23023665_2, 1, 96.0, 1, 16.0, 2);
TEST_DIFFERENCE(mysql_23023665_3, 1, 225.0, 1, 66.0, 2);
TEST_DIFFERENCE(mysql_23023665_5, 2, 165.23735, 2, 105.73735, 4);
#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
#if defined(BOOST_GEOMETRY_USE_RESCALING) \
|| ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE) \
|| defined(BOOST_GEOMETRY_TEST_FAILURES)
// Testcases going wrong with Kramer's rule and no rescaling
TEST_DIFFERENCE(mysql_23023665_6, 2, 105.68756, 3, 10.18756, 5);
TEST_DIFFERENCE(mysql_23023665_13, 3, 99.74526, 3, 37.74526, 6);
#endif
@@ -592,7 +643,6 @@ void test_specific()
TEST_DIFFERENCE(ticket_11676, 2, 2537992.5, 2, 294963.5, 3);
}
int test_main(int, char* [])
{
test_all<bg::model::d2::point_xy<double> >();

View File

@@ -157,23 +157,25 @@ void test_areal()
// output is discarded because of zero (rescaled) area
// POSTGIS areas: 3.75893745345145, 2.5810000723917e-15
ut_settings settings;
settings.sym_difference = false; // Validity problem in sym difference
#if defined(BOOST_GEOMETRY_USE_RESCALING)
settings.test_validity = false; // Invalid output in A
TEST_DIFFERENCE_WITH(0, 1, bug_21155501, 1, 3.758937, 0, 0.0, 2);
settings.sym_difference = BG_IF_RESCALED(false, true);
settings.test_validity = BG_IF_RESCALED(false, true);
#if defined(BOOST_GEOMETRY_USE_RESCALING) || ! defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
// No output for B
TEST_DIFFERENCE_WITH(0, 1, bug_21155501, 1, 3.758937, 0, 0.0, 1);
#else
// Very small sliver for B
TEST_DIFFERENCE_WITH(0, 1, bug_21155501, 1, 3.758937, 1, 1.7763568394002505e-15, 2);
#endif
}
#if defined(BOOST_GEOMETRY_USE_RESCALING) || defined(BOOST_GEOMETRY_TEST_FAILURES)
{
// Without rescaling, this one misses one of the output polygons
// With rescaling, it is complete but invalid
ut_settings settings;
settings.percentage = 0.001;
settings.test_validity = false;
TEST_DIFFERENCE_WITH(0, 1, ticket_9081, 2, 0.0907392476356186, 4, 0.126018011439877, 4);
settings.test_validity = BG_IF_RESCALED(false, true);
TEST_DIFFERENCE_WITH(0, 1, ticket_9081, 2, 0.0907392476356186,
4, 0.126018011439877, BG_IF_RESCALED(4, 3));
}
#endif
@@ -317,7 +319,7 @@ void test_areal()
TEST_DIFFERENCE(case_recursive_boxes_60, 6, 5.25, 7, 5.25, 11);
TEST_DIFFERENCE(case_recursive_boxes_61, 2, 1.5, 6, 2.0, 7);
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
// Misses one triangle
// Misses one triangle. It is NOT related to rescaling.
TEST_DIFFERENCE(case_recursive_boxes_62, 5, 5.0, 11, 5.75, 12);
#endif

View File

@@ -19,6 +19,7 @@
#include <iomanip>
#include <geometry_test_common.hpp>
#include <algorithms/check_validity.hpp>
#include "../setop_output_type.hpp"
#include <boost/core/ignore_unused.hpp>
@@ -194,8 +195,9 @@ std::string test_difference(std::string const& caseid, G1 const& g1, G2 const& g
#endif
{
// std::cout << bg::dsv(result) << std::endl;
typedef bg::model::multi_polygon<OutputType> result_type;
std::string message;
bool const valid = bg::is_valid(result, message);
bool const valid = check_validity<result_type>::apply(result, caseid, g1, g2, message);
BOOST_CHECK_MESSAGE(valid,
"difference: " << caseid << " not valid " << message
<< " type: " << (type_for_assert_message<G1, G2>()));

View File

@@ -188,10 +188,13 @@ void test_areal()
settings);
}
test_one<Polygon, Polygon, Polygon>("geos_1",
geos_1[0], geos_1[1],
1, -1, 3461.12321694, // MSVC 14 reports 3461.025390625
ut_settings(0.01, false));
if (! BOOST_GEOMETRY_CONDITION((boost::is_same<ct, float>::value)) )
{
test_one<Polygon, Polygon, Polygon>("geos_1",
geos_1[0], geos_1[1],
1, -1, 3461.12321694, // MSVC 14 reports 3461.025390625
ut_settings(0.01, false));
}
// Expectations:
// In most cases: 0 (no intersection)
@@ -205,7 +208,7 @@ void test_areal()
0, 0, 0.0);
test_one<Polygon, Polygon, Polygon>("geos_4",
geos_4[0], geos_4[1],
1, -1, 0.08368849);
1, -1, 0.08368849, ut_settings(0.01));
if ( BOOST_GEOMETRY_CONDITION(! ccw && open) )
@@ -253,15 +256,17 @@ void test_areal()
TEST_INTERSECTION(ggl_list_20190307_matthieu_1, 2, -1, 0.035136);
TEST_INTERSECTION(ggl_list_20190307_matthieu_2, 1, -1, 3.64285);
#if defined(BOOST_GEOMETRY_USE_RESCALING) || !defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
test_one<Polygon, Polygon, Polygon>("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1],
1, 4, 0.00029437899183903937, ut_settings(0.01));
#endif
test_one<Polygon, Polygon, Polygon>("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1],
1, 0, 2.914213562373);
test_one<Polygon, Polygon, Polygon>("ticket_8254", ticket_8254[0], ticket_8254[1],
1, 4, 3.635930e-08, ut_settings(0.01));
if_typed<ct, float>(0, 1), -1, if_typed<ct, float>(0.0, 3.635930e-08), ut_settings(0.01));
test_one<Polygon, Polygon, Polygon>("ticket_6958", ticket_6958[0], ticket_6958[1],
1, 4, 4.34355e-05, ut_settings(0.01));
if_typed<ct, float>(0, 1), -1, if_typed<ct, float>(0.0, 4.34355e-05), ut_settings(0.01));
test_one<Polygon, Polygon, Polygon>("ticket_8652", ticket_8652[0], ticket_8652[1],
1, 4, 0.0003);
@@ -306,7 +311,7 @@ void test_areal()
test_one<Polygon, Polygon, Polygon>("ticket_11576",
ticket_11576[0], ticket_11576[1],
1, 0, 5.585617332907136e-07);
if_typed<ct, float>(0, 1), -1, if_typed<ct, float>(0.0, 5.585617332907136e-07));
{
// Not yet valid when rescaling is turned off
@@ -370,15 +375,8 @@ void test_areal()
TEST_INTERSECTION(case_precision_9, 1, -1, 14.0);
TEST_INTERSECTION(case_precision_10, 1, -1, 14.0);
TEST_INTERSECTION(case_precision_11, 1, -1, 14.0);
{
ut_settings settings(0.01);
TEST_INTERSECTION_WITH(case_precision_12, 0, 1, 1, -1, 2.0, settings);
TEST_INTERSECTION_WITH(case_precision_13, 0, 1, 1, -1, 2.0, settings);
TEST_INTERSECTION_WITH(case_precision_12, 1, 0, 1, -1, 2.0, settings);
TEST_INTERSECTION_WITH(case_precision_13, 1, 0, 1, -1, 2.0, settings);
}
TEST_INTERSECTION(case_precision_12, 1, -1, 2.0);
TEST_INTERSECTION(case_precision_13, 1, -1, 1.99998);
TEST_INTERSECTION(case_precision_14, 0, -1, 0.0);
TEST_INTERSECTION(case_precision_15, 1, -1, 14.0);
TEST_INTERSECTION(case_precision_16, 1, -1, 14.0);
@@ -388,6 +386,10 @@ void test_areal()
TEST_INTERSECTION(case_precision_20, 0, 0, 0.0);
TEST_INTERSECTION(case_precision_21, 0, 0, 0.0);
TEST_INTERSECTION(case_precision_22, 1, -1, 14.0);
TEST_INTERSECTION(case_precision_23, 1, -1, 14.0);
TEST_INTERSECTION(case_precision_24, 0, 0, 0.0);
TEST_INTERSECTION(case_precision_25, 0, 0, 0.0);
TEST_INTERSECTION(case_precision_26, 1, -1, 14.0);
TEST_INTERSECTION_REV(case_precision_1, 0, 0, 0.0);
TEST_INTERSECTION_REV(case_precision_2, 0, 0, 0.0);
@@ -400,7 +402,8 @@ void test_areal()
TEST_INTERSECTION_REV(case_precision_9, 1, -1, 14.0);
TEST_INTERSECTION_REV(case_precision_10, 1, -1, 14.0);
TEST_INTERSECTION_REV(case_precision_11, 1, -1, 14.0);
TEST_INTERSECTION_REV(case_precision_12, 1, -1, 2.0);
TEST_INTERSECTION_REV(case_precision_13, 1, -1, 1.99998);
TEST_INTERSECTION_REV(case_precision_14, 0, -1, 0.0);
TEST_INTERSECTION_REV(case_precision_15, 1, -1, 14.0);
TEST_INTERSECTION_REV(case_precision_16, 1, -1, 14.0);
@@ -410,6 +413,10 @@ void test_areal()
TEST_INTERSECTION_REV(case_precision_20, 0, 0, 0.0);
TEST_INTERSECTION_REV(case_precision_21, 0, 0, 0.0);
TEST_INTERSECTION_REV(case_precision_22, 1, -1, 14.0);
TEST_INTERSECTION_REV(case_precision_23, 1, -1, 14.0);
TEST_INTERSECTION_REV(case_precision_24, 0, 0, 0.0);
TEST_INTERSECTION_REV(case_precision_25, 0, 0, 0.0);
TEST_INTERSECTION_REV(case_precision_26, 1, -1, 14.0);
test_one<Polygon, Polygon, Polygon>("mysql_21964049",
mysql_21964049[0], mysql_21964049[1],

View File

@@ -40,8 +40,8 @@
#endif
#include <geometry_test_common.hpp>
#include <algorithms/check_validity.hpp>
#include "../setop_output_type.hpp"
#include "../check_validity.hpp"
struct ut_settings
{
@@ -57,17 +57,10 @@ struct ut_settings
};
template
<
typename G1,
typename G2,
typename ResultType,
typename IntersectionOutput
>
typename bg::default_area_result<G1>::type
check_result(
IntersectionOutput const& intersection_output,
template<typename IntersectionOutput, typename G1, typename G2>
void check_result(IntersectionOutput const& intersection_output,
std::string const& caseid,
G1 const& g1, G2 const& g2,
std::size_t expected_count, std::size_t expected_holes_count,
int expected_point_count, double expected_length_or_area,
ut_settings const& settings)
@@ -110,7 +103,9 @@ check_result(
#endif
{
std::string message;
bool const valid = check_validity<ResultType>::apply(intersection_output, message);
bool const valid = check_validity<IntersectionOutput>
::apply(intersection_output, caseid, g1, g2, message);
BOOST_CHECK_MESSAGE(valid,
"intersection: " << caseid << " not valid: " << message
<< " type: " << (type_for_assert_message<G1, G2>()));
@@ -172,7 +167,6 @@ check_result(
}
#endif
return length_or_area;
}
@@ -212,7 +206,7 @@ typename bg::default_area_result<G1>::type test_intersection(std::string const&
result_type intersection_output;
bg::intersection(g1, g2, intersection_output);
check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
check_result(intersection_output, caseid, g1, g2, expected_count,
expected_holes_count, expected_point_count, expected_length_or_area,
settings);
@@ -221,21 +215,21 @@ typename bg::default_area_result<G1>::type test_intersection(std::string const&
intersection_output.clear();
bg::intersection(boost::variant<G1>(g1), g2, intersection_output);
check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
check_result(intersection_output, caseid, g1, g2, expected_count,
expected_holes_count, expected_point_count, expected_length_or_area,
settings);
intersection_output.clear();
bg::intersection(g1, boost::variant<G2>(g2), intersection_output);
check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
check_result(intersection_output, caseid, g1, g2, expected_count,
expected_holes_count, expected_point_count, expected_length_or_area,
settings);
intersection_output.clear();
bg::intersection(boost::variant<G1>(g1), boost::variant<G2>(g2), intersection_output);
check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
check_result(intersection_output, caseid, g1, g2, expected_count,
expected_holes_count, expected_point_count, expected_length_or_area,
settings);
#endif

View File

@@ -18,8 +18,8 @@
#include <fstream>
#include <geometry_test_common.hpp>
#include <algorithms/check_validity.hpp>
#include "../setop_output_type.hpp"
#include "../check_validity.hpp"
#include <boost/core/ignore_unused.hpp>
#include <boost/foreach.hpp>
@@ -130,7 +130,7 @@ void test_union(std::string const& caseid, G1 const& g1, G2 const& g2,
#endif
{
std::string message;
bool const valid = check_validity<result_type>::apply(clip, message);
bool const valid = check_validity<result_type>::apply(clip, caseid, g1, g2, message);
BOOST_CHECK_MESSAGE(valid,
"union: " << caseid << " not valid: " << message
<< " type: " << (type_for_assert_message<G1, G2>()));

View File

@@ -279,6 +279,10 @@ void test_areal()
#endif
TEST_UNION(case_precision_21, 1, 0, -1, 22.0);
TEST_UNION(case_precision_22, 1, 1, -1, 73.0);
TEST_UNION(case_precision_23, 1, 1, -1, 73.0);
TEST_UNION(case_precision_24, 1, 0, -1, 22.0);
TEST_UNION(case_precision_25, 1, 0, -1, 22.0);
TEST_UNION(case_precision_26, 1, 1, -1, 73.0);
TEST_UNION_REV(case_precision_1, 1, 0, -1, 22.0);
TEST_UNION_REV(case_precision_2, 1, 0, -1, 22.0);
@@ -304,6 +308,10 @@ void test_areal()
#endif
TEST_UNION_REV(case_precision_21, 1, 0, -1, 22.0);
TEST_UNION_REV(case_precision_22, 1, 1, -1, 73.0);
TEST_UNION_REV(case_precision_23, 1, 1, -1, 73.0);
TEST_UNION_REV(case_precision_24, 1, 0, -1, 22.0);
TEST_UNION_REV(case_precision_25, 1, 0, -1, 22.0);
TEST_UNION_REV(case_precision_26, 1, 1, -1, 73.0);
/*
test_one<Polygon, Polygon, Polygon>(102,
@@ -446,6 +454,7 @@ void test_areal()
TEST_UNION_REV(issue_566_a, 1, 0, -1, 214.3728);
TEST_UNION_REV(issue_566_b, 1, 0, -1, 214.3728);
if (! BOOST_GEOMETRY_CONDITION((boost::is_same<ct, float>::value)) )
{
ut_settings ignore_validity;
ignore_validity.test_validity = false;
@@ -527,7 +536,7 @@ void test_areal()
1, 0, if_typed_tt<ct>(93, 91), 22.815);
test_one<Polygon, Polygon, Polygon>("buffer_mp2", buffer_mp2[0], buffer_mp2[1],
1, BG_IF_RESCALED(1, 0), 217, 36.752837);
1, BG_IF_RESCALED(1, (if_typed<ct, float>(1, 0))), 217, 36.752837);
test_one<Polygon, Polygon, Polygon>("mysql_21964079_1",
mysql_21964079_1[0], mysql_21964079_1[1],

View File

@@ -1,9 +1,9 @@
# Boost.Geometry (aka GGL, Generic Geometry Library)
# Boost.Geometry
#
# Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
# Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
# Copyright (c) 2015-2017 Adam Wulkiewicz, Lodz, Poland.
# Copyright (c) 2007-2019 Barend Gehrels, Amsterdam, the Netherlands.
# Copyright (c) 2008-2019 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2019 Mateusz Loskot, London, UK.
# Copyright (c) 2015-2019 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
@@ -11,8 +11,9 @@
test-suite boost-geometry-arithmetic
:
[ run general.cpp : : : : arithmetic_general ]
[ run dot_product.cpp : : : : arithmetic_dot_product ]
[ run cross_product.cpp : : : : arithmetic_cross_product ]
[ compile-fail cross_product.cpp : <define>TEST_FAIL_CROSS_PRODUCT : arithmetic_cross_product_cf ]
[ run general.cpp : : : : arithmetic_general ]
[ run dot_product.cpp : : : : arithmetic_dot_product ]
[ run cross_product.cpp : : : : arithmetic_cross_product ]
[ run infinite_line_functions.cpp : : : : arithmetic_infinite_line_functions ]
[ compile-fail cross_product.cpp : <define>TEST_FAIL_CROSS_PRODUCT : arithmetic_cross_product_cf ]
;

View File

@@ -0,0 +1,201 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2018-2019 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)
#include <geometry_test_common.hpp>
#include <boost/geometry/arithmetic/infinite_line_functions.hpp>
#include <boost/geometry/geometries/infinite_line.hpp>
#include <boost/geometry/algorithms/detail/make/make.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
namespace
{
// Boost.Test does not support BOOST_CHECK_CLOSE for integral types
template <typename T>
bool is_small(T const& value)
{
static long double const epsilon = 1.0e-5;
return std::fabs(value) < epsilon;
}
}
template <typename T, typename C>
void verify_point_on_line(bg::model::infinite_line<T> const& line,
C const& x, C const& y)
{
BOOST_CHECK_MESSAGE(is_small(line.a * x + line.b * y + line.c),
"Point is not located on the line");
}
template <typename T>
void test_side_value()
{
typedef bg::model::infinite_line<T> line_type;
// Horizontal line going right
line_type line = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
// Point above (= on left side)
T d = bg::arithmetic::side_value(line, 5, 5);
BOOST_CHECK_MESSAGE(d > 0, "point not on left side");
// Point below (= on right side)
d = bg::arithmetic::side_value(line, 5, -5);
BOOST_CHECK_MESSAGE(d < 0, "point not on right side");
// Diagonal not through origin, from right (down) to left (up)
line = bg::detail::make::make_infinite_line<T>(5, 2, -7, 10);
d = bg::arithmetic::side_value(line, 5, 2);
BOOST_CHECK_MESSAGE(is_small(d), "point not on line");
d = bg::arithmetic::side_value(line, -7, 10);
BOOST_CHECK_MESSAGE(is_small(d), "point not on line");
// vector is (-12, 8), move (-3,2) on the line from (5,2)
d = bg::arithmetic::side_value(line, 2, 4);
BOOST_CHECK_MESSAGE(is_small(d), "point not on line");
// Go perpendicular (2,3) from (2,4) up, so right of the line (negative)
d = bg::arithmetic::side_value(line, 4, 7);
BOOST_CHECK_MESSAGE(d < 0, "point not on right side");
// Go perpendicular (2,3) from (2,4) down, so left of the line (positive)
d = bg::arithmetic::side_value(line, 0, 1);
BOOST_CHECK_MESSAGE(d > 0, "point not on left side");
}
template <typename T>
void test_get_intersection()
{
typedef bg::model::infinite_line<T> line_type;
// Diagonal lines (first is same as in distance measure,
// second is perpendicular and used there for distance measures)
line_type p = bg::detail::make::make_infinite_line<T>(5, 2, -7, 10);
line_type q = bg::detail::make::make_infinite_line<T>(4, 7, 0, 1);
typedef bg::model::point<T, 2, bg::cs::cartesian> point_type;
point_type ip;
BOOST_CHECK(bg::arithmetic::intersection_point(p, q, ip));
BOOST_CHECK_MESSAGE(is_small(bg::get<0>(ip) - 2), "x-coordinate wrong");
BOOST_CHECK_MESSAGE(is_small(bg::get<1>(ip) - 4), "y-coordinate wrong");
verify_point_on_line(p, bg::get<0>(ip), bg::get<1>(ip));
verify_point_on_line(q, bg::get<0>(ip), bg::get<1>(ip));
}
template <typename T>
void test_same_direction()
{
bg::model::infinite_line<T> p, q;
// Exactly opposite, diagonal
p = bg::detail::make::make_infinite_line<T>(2, 1, 12, 11);
q = bg::detail::make::make_infinite_line<T>(12, 11, 2, 1);
BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
// Exactly opposite, horizontal
p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
q = bg::detail::make::make_infinite_line<T>(10, 0, 0, 0);
BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
// Exactly opposite, vertical
p = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
q = bg::detail::make::make_infinite_line<T>(0, 10, 0, 0);
BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
// Exactly equal, diagonal
p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
q = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
BOOST_CHECK(bg::arithmetic::similar_direction(p, q));
// Exactly equal, horizontal
p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
q = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
BOOST_CHECK(bg::arithmetic::similar_direction(p, q));
// Exactly equal, vertical
p = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
q = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
BOOST_CHECK(bg::arithmetic::similar_direction(p, q));
// Coming together, diagonal
p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
q = bg::detail::make::make_infinite_line<T>(20, 20, 10, 10);
BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
// Leaving from common point, diagonal
p = bg::detail::make::make_infinite_line<T>(10, 10, 0, 0);
q = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
// Continuing each other, diagonal
p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
q = bg::detail::make::make_infinite_line<T>(10, 10, 20, 20);
BOOST_CHECK(bg::arithmetic::similar_direction(p, q));
// (Nearly) perpendicular
p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
q = bg::detail::make::make_infinite_line<T>(0, 0, -10, 10);
BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
// 45 deg
p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
q = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
BOOST_CHECK(bg::arithmetic::similar_direction(p, q));
// a bit more than 45 deg
p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
q = bg::detail::make::make_infinite_line<T>(0, 0, -1, 10);
BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
// 135 deg
p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
q = bg::detail::make::make_infinite_line<T>(0, 0, -10, 0);
BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
}
template <typename T>
void test_degenerate()
{
typedef bg::model::infinite_line<T> line_type;
line_type line = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
BOOST_CHECK(! bg::arithmetic::is_degenerate(line));
line = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
BOOST_CHECK(! bg::arithmetic::is_degenerate(line));
line = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
BOOST_CHECK(! bg::arithmetic::is_degenerate(line));
line = bg::detail::make::make_infinite_line<T>(0, 0, 0, 0);
BOOST_CHECK(bg::arithmetic::is_degenerate(line));
}
template <typename T>
void test_all()
{
test_side_value<T>();
test_get_intersection<T>();
test_same_direction<T>();
test_degenerate<T>();
}
int test_main(int, char* [])
{
test_all<double>();
test_all<long double>();
test_all<float>();
test_all<int>();
return 0;
}

View File

@@ -1,7 +1,7 @@
// Boost.Geometry
// Unit Test
// Copyright (c) 2016-2018 Oracle and/or its affiliates.
// Copyright (c) 2016-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -171,6 +171,20 @@ void test_all(expected_results const& results)
#endif
}
void test_bugs()
{
// https://github.com/boostorg/geometry/issues/612
{
double lon, lat;
bg::formula::sjoberg_intersection<double, bg::formula::andoyer_inverse, 1>
::apply(-0.0872665, -0.0872665, -0.0872665, 0.0872665,
0.0, 1.57e-07, -0.392699, 1.57e-07,
lon, lat, bg::srs::spheroid<double>());
check_one("issue 612", lon, -0.087266500535674751);
check_one("issue 612", lat, 1.5892499139622920e-07);
}
}
int test_main(int, char*[])
{
for (size_t i = 0; i < expected_size; ++i)
@@ -178,5 +192,7 @@ int test_main(int, char*[])
test_all(expected[i]);
}
test_bugs();
return 0;
}

View File

@@ -1,7 +1,7 @@
// Boost.Geometry
// Unit Test
// Copyright (c) 2016-2017 Oracle and/or its affiliates.
// Copyright (c) 2016-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -29,6 +29,38 @@ void normalize_deg(double & deg)
::boost::test_tools::check_is_close_t(), M, CHECK, CHECK_MSG, (L)(R)(::boost::math::fpc::percent_tolerance(T)) )
void check_one(std::string const& name, double result, double expected)
{
std::string id = name.empty() ? "" : (name + " : ");
double eps = std::numeric_limits<double>::epsilon();
double abs_result = bg::math::abs(result);
double abs_expected = bg::math::abs(expected);
double res_max = (std::max)(abs_result, abs_expected);
double res_min = (std::min)(abs_result, abs_expected);
if (res_min <= eps) // including 0
{
bool is_close = abs_result <= 30 * eps && abs_expected <= 30 * eps;
BOOST_CHECK_MESSAGE((is_close),
id << std::setprecision(20) << "result {" << result << "} different than expected {" << expected << "}.");
}
else if (res_max > 100 * eps)
{
BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 0.1,
id << std::setprecision(20) << "result {" << result << "} different than expected {" << expected << "}.");
}
else if (res_max > 10 * eps)
{
BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 10,
id << std::setprecision(20) << "result {" << result << "} different than expected {" << expected << "}.");
}
else if (res_max > eps)
{
BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 1000,
id << std::setprecision(20) << "result {" << result << "} different than expected {" << expected << "}.");
}
}
void check_one(std::string const& name,
double result, double expected, double reference, double reference_error,
bool normalize = false, bool check_reference_only = false)
@@ -44,32 +76,7 @@ void check_one(std::string const& name,
if (! check_reference_only)
{
double eps = std::numeric_limits<double>::epsilon();
double abs_result = bg::math::abs(result);
double abs_expected = bg::math::abs(expected);
double res_max = (std::max)(abs_result, abs_expected);
double res_min = (std::min)(abs_result, abs_expected);
if (res_min <= eps) // including 0
{
bool is_close = abs_result <= 30 * eps && abs_expected <= 30 * eps;
BOOST_CHECK_MESSAGE((is_close),
id << std::setprecision(20) << "result {" << result << "} different than expected {" << expected << "}.");
}
else if (res_max > 100 * eps)
{
BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 0.1,
id << std::setprecision(20) << "result {" << result << "} different than expected {" << expected << "}.");
}
else if (res_max > 10 * eps)
{
BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 10,
id << std::setprecision(20) << "result {" << result << "} different than expected {" << expected << "}.");
}
else if (res_max > eps)
{
BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 1000,
id << std::setprecision(20) << "result {" << result << "} different than expected {" << expected << "}.");
}
check_one(name, result, expected);
}
// NOTE: in some cases it probably will be necessary to normalize

View File

@@ -1,9 +1,9 @@
# Boost.Geometry (aka GGL, Generic Geometry Library)
# Boost.Geometry
#
# Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
# Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
# Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
# Copyright (c) 2007-2019 Barend Gehrels, Amsterdam, the Netherlands.
# Copyright (c) 2008-2019 Bruno Lalande, Paris, France.
# Copyright (c) 2009-2019 Mateusz Loskot, London, UK.
# Copyright (c) 2014-2019 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
@@ -27,4 +27,5 @@ test-suite boost-geometry-geometries
[ run custom_linestring.cpp : : : : geometries_custom_linestring ]
[ run initialization.cpp : : : : geometries_initialization ]
[ run segment.cpp : : : : geometries_segment ]
[ run infinite_line.cpp : : : : geometries_infinite_line ]
;

View File

@@ -0,0 +1,90 @@
// Boost.Geometry
// Unit Test
// Copyright (c) 2019 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2019.
// Modifications copyright (c) 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)
#include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/detail/make/make.hpp>
#include <boost/geometry/geometries/infinite_line.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/util/math.hpp>
namespace
{
// Boost.Test does not support BOOST_CHECK_CLOSE for integral types
template <typename T>
bool is_small(T const& value)
{
static long double const epsilon = 1.0e-5;
return bg::math::abs(value) < epsilon;
}
}
template <typename T, typename C>
void verify_point_on_line(bg::model::infinite_line<T> const& line,
C const& x, C const& y)
{
BOOST_CHECK_MESSAGE(is_small(line.a * x + line.b * y + line.c),
"Point is not located on the line");
}
template <typename T>
void test_make()
{
typedef bg::model::infinite_line<T> line_type;
// Horizontal through origin
line_type line = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
verify_point_on_line(line, 0, 0);
verify_point_on_line(line, 10, 0);
// Horizontal line above origin
line = bg::detail::make::make_infinite_line<T>(0, 5, 10, 5);
verify_point_on_line(line, 0, 5);
verify_point_on_line(line, 10, 5);
// Vertical through origin
line = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
verify_point_on_line(line, 0, 0);
verify_point_on_line(line, 0, 10);
// Vertical line left from origin
line = bg::detail::make::make_infinite_line<T>(5, 0, 5, 10);
verify_point_on_line(line, 5, 0);
verify_point_on_line(line, 5, 10);
// Diagonal through origin
line = bg::detail::make::make_infinite_line<T>(0, 0, 8, 10);
verify_point_on_line(line, 0, 0);
verify_point_on_line(line, 8, 10);
// Diagonal not through origin
line = bg::detail::make::make_infinite_line<T>(5, 2, -8, 10);
verify_point_on_line(line, 5, 2);
verify_point_on_line(line, -8, 10);
}
template <typename T>
void test_all()
{
test_make<T>();
}
int test_main(int, char* [])
{
test_all<double>();
test_all<long double>();
test_all<float>();
test_all<int>();
return 0;
}

View File

@@ -167,4 +167,10 @@ struct mathematical_policy
#define BG_IF_RESCALED(a, b) b
#endif
#if defined(BOOST_GEOMETRY_USE_KRAMER_RULE)
#define BG_IF_KRAMER(a, b) a
#else
#define BG_IF_KRAMER(a, b) b
#endif
#endif // GEOMETRY_TEST_GEOMETRY_TEST_COMMON_HPP

View File

@@ -40,6 +40,7 @@ test-suite boost-geometry-strategies
[ run thomas.cpp : : : : strategies_thomas ]
[ run transform_cs.cpp : : : : strategies_transform_cs ]
[ run transformer.cpp : : : : strategies_transformer ]
[ run matrix_transformer.cpp : : : : strategies_matrix_transformer ]
[ run vincenty.cpp : : : : strategies_vincenty ]
[ run winding.cpp : : : : strategies_winding ]
;

View File

@@ -4,6 +4,7 @@
// Copyright (c) 2019 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -57,7 +58,7 @@ void test_all(expected_results const& results)
// WGS84
Spheroid spheroid(6378137.0, 6356752.3142451793);
error errors []
error errors [] =
{
{0.00000001, 0.00000001, 0.00000001, 0.000001}, //vincenty
{0.0002, 0.002, 0.01, 0.2}, //thomas

Some files were not shown because too many files have changed in this diff Show More