mirror of
https://github.com/boostorg/geometry.git
synced 2026-01-29 19:42:10 +00:00
Merge branch 'develop' into bg-prepare
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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]
|
||||
[/=================]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
60
include/boost/geometry/algorithms/detail/make/make.hpp
Normal file
60
include/boost/geometry/algorithms/detail/make/make.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -209,7 +209,6 @@ private :
|
||||
RobustPolicy m_robust_policy;
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
typename Geometry1, typename Geometry2,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
106
include/boost/geometry/arithmetic/infinite_line_functions.hpp
Normal file
106
include/boost/geometry/arithmetic/infinite_line_functions.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
50
include/boost/geometry/geometries/infinite_line.hpp
Normal file
50
include/boost/geometry/geometries/infinite_line.hpp
Normal 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
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
74
include/boost/geometry/strategies/cartesian/io.hpp
Normal file
74
include/boost/geometry/strategies/cartesian/io.hpp
Normal 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
|
||||
48
include/boost/geometry/strategies/cartesian/point_order.hpp
Normal file
48
include/boost/geometry/strategies/cartesian/point_order.hpp
Normal 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
|
||||
@@ -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
|
||||
<
|
||||
|
||||
@@ -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);
|
||||
|
||||
96
include/boost/geometry/strategies/geographic/io.hpp
Normal file
96
include/boost/geometry/strategies/geographic/io.hpp
Normal 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
|
||||
120
include/boost/geometry/strategies/geographic/point_order.hpp
Normal file
120
include/boost/geometry/strategies/geographic/point_order.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -63,7 +63,7 @@ private :
|
||||
typedef segment_intersection_points
|
||||
<
|
||||
IntersectionPoint,
|
||||
typename geometry::segment_ratio_type
|
||||
typename detail::segment_ratio_type
|
||||
<
|
||||
IntersectionPoint, RobustPolicy
|
||||
>::type
|
||||
|
||||
42
include/boost/geometry/strategies/io.hpp
Normal file
42
include/boost/geometry/strategies/io.hpp
Normal 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
|
||||
45
include/boost/geometry/strategies/point_order.hpp
Normal file
45
include/boost/geometry/strategies/point_order.hpp
Normal 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
|
||||
@@ -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;
|
||||
|
||||
80
include/boost/geometry/strategies/spherical/io.hpp
Normal file
80
include/boost/geometry/strategies/spherical/io.hpp
Normal 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
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
140
include/boost/geometry/strategies/spherical/point_order.hpp
Normal file
140
include/boost/geometry/strategies/spherical/point_order.hpp
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
79
test/algorithms/check_validity.hpp
Normal file
79
test/algorithms/check_validity.hpp
Normal 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
|
||||
@@ -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 ;
|
||||
|
||||
148
test/algorithms/detail/calculate_point_order.cpp
Normal file
148
test/algorithms/detail/calculate_point_order.cpp
Normal 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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
@@ -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))"
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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> >();
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>()));
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>()));
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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 ]
|
||||
;
|
||||
|
||||
201
test/arithmetic/infinite_line_functions.cpp
Executable file
201
test/arithmetic/infinite_line_functions.cpp
Executable 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ]
|
||||
;
|
||||
|
||||
90
test/geometries/infinite_line.cpp
Executable file
90
test/geometries/infinite_line.cpp
Executable 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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 ]
|
||||
;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user