mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-11 21:44:04 +00:00
Merge branch 'develop' of https://github.com/boostorg/geometry into feature/envelope_and_expand_for_spherical_cs
This commit is contained in:
commit
e66f255acf
@ -27,6 +27,8 @@
|
|||||||
* Added rtree const_iterator, begin(), end() and the support for Boost.Range.
|
* Added rtree const_iterator, begin(), end() and the support for Boost.Range.
|
||||||
* The support for C++11 `std::initializer_list` in geometries models.
|
* The support for C++11 `std::initializer_list` in geometries models.
|
||||||
* Disjoint and intersects support the following geometry combinations: multipoint/linestring, multipoint/multilinestring
|
* Disjoint and intersects support the following geometry combinations: multipoint/linestring, multipoint/multilinestring
|
||||||
|
* Intersection has been implemented for combinations of pointlike and linear geometries
|
||||||
|
* Added implementation for difference(pointlike, linear)
|
||||||
|
|
||||||
[*Improvements]
|
[*Improvements]
|
||||||
|
|
||||||
|
@ -225,7 +225,6 @@ void test_all()
|
|||||||
test_forward<bg::projections::eck5_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 2);
|
test_forward<bg::projections::eck5_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 2);
|
||||||
|
|
||||||
test_forward<bg::projections::eck6_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m");
|
test_forward<bg::projections::eck6_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m");
|
||||||
test_forward<bg::projections::eck6_ellipsoid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 18);
|
|
||||||
|
|
||||||
test_forward<bg::projections::eqc_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 5);
|
test_forward<bg::projections::eqc_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 5);
|
||||||
test_forward<bg::projections::eqdc_ellipsoid>(amsterdam, utrecht, "+ellps=WGS84 +units=m +lat_1=60 +lat_2=0");
|
test_forward<bg::projections::eqdc_ellipsoid>(amsterdam, utrecht, "+ellps=WGS84 +units=m +lat_1=60 +lat_2=0");
|
||||||
@ -241,7 +240,6 @@ void test_all()
|
|||||||
test_forward<bg::projections::gins8_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 7);
|
test_forward<bg::projections::gins8_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 7);
|
||||||
|
|
||||||
test_forward<bg::projections::gn_sinu_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m +m=0.5 +n=1.785");
|
test_forward<bg::projections::gn_sinu_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m +m=0.5 +n=1.785");
|
||||||
test_forward<bg::projections::gn_sinu_ellipsoid>(amsterdam, utrecht, "+ellps=WGS84 +units=m +m=0.5 +n=1.785", 18);
|
|
||||||
|
|
||||||
test_forward<bg::projections::gnom_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 50);
|
test_forward<bg::projections::gnom_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 50);
|
||||||
test_forward<bg::projections::goode_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m");
|
test_forward<bg::projections::goode_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m");
|
||||||
@ -267,7 +265,6 @@ void test_all()
|
|||||||
test_forward<bg::projections::mbtfpp_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m");
|
test_forward<bg::projections::mbtfpp_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m");
|
||||||
test_forward<bg::projections::mbtfpq_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 2);
|
test_forward<bg::projections::mbtfpq_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 2);
|
||||||
|
|
||||||
test_forward<bg::projections::mbtfps_ellipsoid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 18);
|
|
||||||
test_forward<bg::projections::mbtfps_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m");
|
test_forward<bg::projections::mbtfps_spheroid>(amsterdam, utrecht, "+ellps=WGS84 +units=m");
|
||||||
|
|
||||||
test_forward<bg::projections::merc_ellipsoid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 22);
|
test_forward<bg::projections::merc_ellipsoid>(amsterdam, utrecht, "+ellps=WGS84 +units=m", 22);
|
||||||
|
@ -383,6 +383,7 @@ inline void buffer_point(Point const& point, Collection& collection,
|
|||||||
std::vector<OutputPointType> range_out;
|
std::vector<OutputPointType> range_out;
|
||||||
point_strategy.apply(point, distance_strategy, range_out);
|
point_strategy.apply(point, distance_strategy, range_out);
|
||||||
collection.add_piece(strategy::buffer::buffered_point, range_out, false);
|
collection.add_piece(strategy::buffer::buffered_point, range_out, false);
|
||||||
|
collection.set_piece_center(point);
|
||||||
collection.finish_ring();
|
collection.finish_ring();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFER_POLICIES_HPP
|
||||||
|
|
||||||
|
#define BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
@ -122,6 +123,10 @@ struct buffer_turn_info
|
|||||||
|
|
||||||
intersection_location_type location;
|
intersection_location_type location;
|
||||||
|
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
robust_point_type rob_pi, rob_pj, rob_qi, rob_qj;
|
||||||
|
#endif
|
||||||
|
|
||||||
int count_within;
|
int count_within;
|
||||||
|
|
||||||
bool within_original;
|
bool within_original;
|
||||||
@ -130,7 +135,9 @@ struct buffer_turn_info
|
|||||||
|
|
||||||
int count_on_offsetted;
|
int count_on_offsetted;
|
||||||
int count_on_helper;
|
int count_on_helper;
|
||||||
|
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
int count_within_near_offsetted;
|
int count_within_near_offsetted;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool remove_on_multi;
|
bool remove_on_multi;
|
||||||
|
|
||||||
@ -147,7 +154,9 @@ struct buffer_turn_info
|
|||||||
, count_in_original(0)
|
, count_in_original(0)
|
||||||
, count_on_offsetted(0)
|
, count_on_offsetted(0)
|
||||||
, count_on_helper(0)
|
, count_on_helper(0)
|
||||||
|
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
, count_within_near_offsetted(0)
|
, count_within_near_offsetted(0)
|
||||||
|
#endif
|
||||||
, remove_on_multi(false)
|
, remove_on_multi(false)
|
||||||
, count_on_occupied(0)
|
, count_on_occupied(0)
|
||||||
, count_on_multi(0)
|
, count_on_multi(0)
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
#include <boost/geometry/core/coordinate_type.hpp>
|
#include <boost/geometry/core/coordinate_type.hpp>
|
||||||
#include <boost/geometry/core/point_type.hpp>
|
#include <boost/geometry/core/point_type.hpp>
|
||||||
|
|
||||||
|
#include <boost/geometry/algorithms/comparable_distance.hpp>
|
||||||
#include <boost/geometry/algorithms/covered_by.hpp>
|
#include <boost/geometry/algorithms/covered_by.hpp>
|
||||||
#include <boost/geometry/algorithms/envelope.hpp>
|
#include <boost/geometry/algorithms/envelope.hpp>
|
||||||
|
#include <boost/geometry/algorithms/is_convex.hpp>
|
||||||
|
|
||||||
#include <boost/geometry/strategies/buffer.hpp>
|
#include <boost/geometry/strategies/buffer.hpp>
|
||||||
|
|
||||||
@ -126,6 +128,11 @@ struct buffered_piece_collection
|
|||||||
typedef geometry::model::ring<robust_point_type> robust_ring_type;
|
typedef geometry::model::ring<robust_point_type> robust_ring_type;
|
||||||
typedef geometry::model::box<robust_point_type> robust_box_type;
|
typedef geometry::model::box<robust_point_type> robust_box_type;
|
||||||
|
|
||||||
|
typedef typename default_comparable_distance_result
|
||||||
|
<
|
||||||
|
robust_point_type
|
||||||
|
>::type robust_comparable_radius_type;
|
||||||
|
|
||||||
typedef typename strategy::side::services::default_strategy
|
typedef typename strategy::side::services::default_strategy
|
||||||
<
|
<
|
||||||
typename cs_tag<point_type>::type
|
typename cs_tag<point_type>::type
|
||||||
@ -191,13 +198,13 @@ struct buffered_piece_collection
|
|||||||
std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end
|
std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool is_convex;
|
||||||
bool is_monotonic_increasing[2]; // 0=x, 1=y
|
bool is_monotonic_increasing[2]; // 0=x, 1=y
|
||||||
bool is_monotonic_decreasing[2]; // 0=x, 1=y
|
bool is_monotonic_decreasing[2]; // 0=x, 1=y
|
||||||
|
|
||||||
// Monotonic sections of pieces around points
|
// Monotonic sections of pieces around points
|
||||||
std::vector<section_type> sections;
|
std::vector<section_type> sections;
|
||||||
|
|
||||||
|
|
||||||
// Robust representations
|
// Robust representations
|
||||||
// 3: complete ring
|
// 3: complete ring
|
||||||
robust_ring_type robust_ring;
|
robust_ring_type robust_ring;
|
||||||
@ -206,6 +213,27 @@ struct buffered_piece_collection
|
|||||||
robust_box_type robust_offsetted_envelope;
|
robust_box_type robust_offsetted_envelope;
|
||||||
|
|
||||||
std::vector<robust_turn> robust_turns; // Used only in insert_rescaled_piece_turns - we might use a map instead
|
std::vector<robust_turn> robust_turns; // Used only in insert_rescaled_piece_turns - we might use a map instead
|
||||||
|
|
||||||
|
robust_point_type robust_center;
|
||||||
|
robust_comparable_radius_type robust_min_comparable_radius;
|
||||||
|
robust_comparable_radius_type robust_max_comparable_radius;
|
||||||
|
|
||||||
|
piece()
|
||||||
|
: type(strategy::buffer::piece_type_unknown)
|
||||||
|
, index(-1)
|
||||||
|
, left_index(-1)
|
||||||
|
, right_index(-1)
|
||||||
|
, last_segment_index(-1)
|
||||||
|
, offsetted_count(-1)
|
||||||
|
, is_convex(false)
|
||||||
|
, robust_min_comparable_radius(0)
|
||||||
|
, robust_max_comparable_radius(0)
|
||||||
|
{
|
||||||
|
is_monotonic_increasing[0] = false;
|
||||||
|
is_monotonic_increasing[1] = false;
|
||||||
|
is_monotonic_decreasing[0] = false;
|
||||||
|
is_monotonic_decreasing[1] = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct robust_original
|
struct robust_original
|
||||||
@ -444,6 +472,7 @@ struct buffered_piece_collection
|
|||||||
{
|
{
|
||||||
it->location = inside_buffer;
|
it->location = inside_buffer;
|
||||||
}
|
}
|
||||||
|
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
if (it->count_within_near_offsetted > 0)
|
if (it->count_within_near_offsetted > 0)
|
||||||
{
|
{
|
||||||
// Within can have in rare cases a rounding issue. We don't discard this
|
// Within can have in rare cases a rounding issue. We don't discard this
|
||||||
@ -451,6 +480,7 @@ struct buffered_piece_collection
|
|||||||
// will never start a new ring from this type of points.
|
// will never start a new ring from this type of points.
|
||||||
it->selectable_start = false;
|
it->selectable_start = false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,6 +574,7 @@ struct buffered_piece_collection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
// Insert all rescaled turn-points into these rings, to form a
|
// Insert all rescaled turn-points into these rings, to form a
|
||||||
// reliable integer-based ring. All turns can be compared (inside) to this
|
// reliable integer-based ring. All turns can be compared (inside) to this
|
||||||
// rings to see if they are inside.
|
// rings to see if they are inside.
|
||||||
@ -582,6 +613,7 @@ struct buffered_piece_collection
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(assert_indices_in_robust_rings());
|
BOOST_ASSERT(assert_indices_in_robust_rings());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t Dimension>
|
template <std::size_t Dimension>
|
||||||
@ -606,6 +638,8 @@ struct buffered_piece_collection
|
|||||||
pc.is_monotonic_decreasing[0] = true;
|
pc.is_monotonic_decreasing[0] = true;
|
||||||
pc.is_monotonic_decreasing[1] = true;
|
pc.is_monotonic_decreasing[1] = true;
|
||||||
|
|
||||||
|
pc.is_convex = geometry::is_convex(pc.robust_ring);
|
||||||
|
|
||||||
if (pc.offsetted_count < 2)
|
if (pc.offsetted_count < 2)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -621,7 +655,6 @@ struct buffered_piece_collection
|
|||||||
current = next;
|
current = next;
|
||||||
++next;
|
++next;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void determine_properties()
|
void determine_properties()
|
||||||
@ -658,7 +691,31 @@ struct buffered_piece_collection
|
|||||||
geometry::sectionalize<false, dimensions>(pc.robust_ring,
|
geometry::sectionalize<false, dimensions>(pc.robust_ring,
|
||||||
detail::no_rescale_policy(), pc.sections);
|
detail::no_rescale_policy(), pc.sections);
|
||||||
|
|
||||||
// TODO (next phase) determine min/max radius
|
// Determine min/max radius
|
||||||
|
typedef geometry::model::referring_segment<robust_point_type const>
|
||||||
|
robust_segment_type;
|
||||||
|
|
||||||
|
typename robust_ring_type::const_iterator current = pc.robust_ring.begin();
|
||||||
|
typename robust_ring_type::const_iterator next = current + 1;
|
||||||
|
|
||||||
|
for (int i = 1; i < pc.offsetted_count; i++)
|
||||||
|
{
|
||||||
|
robust_segment_type s(*current, *next);
|
||||||
|
robust_comparable_radius_type const d
|
||||||
|
= geometry::comparable_distance(pc.robust_center, s);
|
||||||
|
|
||||||
|
if (i == 1 || d < pc.robust_min_comparable_radius)
|
||||||
|
{
|
||||||
|
pc.robust_min_comparable_radius = d;
|
||||||
|
}
|
||||||
|
if (i == 1 || d > pc.robust_max_comparable_radius)
|
||||||
|
{
|
||||||
|
pc.robust_max_comparable_radius = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = next;
|
||||||
|
++next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prepare_buffered_point_pieces()
|
inline void prepare_buffered_point_pieces()
|
||||||
@ -772,6 +829,13 @@ struct buffered_piece_collection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void set_piece_center(point_type const& center)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(! m_pieces.empty());
|
||||||
|
geometry::recalculate(m_pieces.back().robust_center, center,
|
||||||
|
m_robust_policy);
|
||||||
|
}
|
||||||
|
|
||||||
inline void finish_ring(bool is_interior = false, bool has_interiors = false)
|
inline void finish_ring(bool is_interior = false, bool has_interiors = false)
|
||||||
{
|
{
|
||||||
if (m_first_piece_index == -1)
|
if (m_first_piece_index == -1)
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
|
#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
|
||||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||||
#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>
|
#include <boost/geometry/algorithms/detail/sections/section_functions.hpp>
|
||||||
|
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace boost { namespace geometry
|
namespace boost { namespace geometry
|
||||||
@ -28,6 +29,31 @@ namespace detail { namespace buffer
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
struct buffer_assign_turn
|
||||||
|
{
|
||||||
|
static bool const include_no_turn = false;
|
||||||
|
static bool const include_degenerate = false;
|
||||||
|
static bool const include_opposite = false;
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename Info,
|
||||||
|
typename Point1,
|
||||||
|
typename Point2,
|
||||||
|
typename IntersectionInfo
|
||||||
|
>
|
||||||
|
static inline void apply(Info& info, Point1 const& p1, Point2 const& p2, IntersectionInfo const& iinfo)
|
||||||
|
{
|
||||||
|
info.rob_pi = iinfo.rpi();
|
||||||
|
info.rob_pj = iinfo.rpj();
|
||||||
|
info.rob_qi = iinfo.rqi();
|
||||||
|
info.rob_qj = iinfo.rqj();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
template
|
template
|
||||||
<
|
<
|
||||||
typename Pieces,
|
typename Pieces,
|
||||||
@ -204,7 +230,11 @@ class piece_turn_visitor
|
|||||||
// and iterating in sync with them...
|
// and iterating in sync with them...
|
||||||
typedef detail::overlay::get_turn_info
|
typedef detail::overlay::get_turn_info
|
||||||
<
|
<
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
buffer_assign_turn
|
||||||
|
#else
|
||||||
detail::overlay::assign_null_policy
|
detail::overlay::assign_null_policy
|
||||||
|
#endif
|
||||||
> turn_policy;
|
> turn_policy;
|
||||||
|
|
||||||
turn_policy::apply(*prev1, *it1, *next1,
|
turn_policy::apply(*prev1, *it1, *next1,
|
||||||
|
@ -25,6 +25,11 @@
|
|||||||
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
|
||||||
#include <boost/geometry/policies/compare.hpp>
|
#include <boost/geometry/policies/compare.hpp>
|
||||||
#include <boost/geometry/strategies/buffer.hpp>
|
#include <boost/geometry/strategies/buffer.hpp>
|
||||||
|
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
|
||||||
|
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
#include <boost/geometry/strategies/cartesian/side_of_intersection.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace boost { namespace geometry
|
namespace boost { namespace geometry
|
||||||
@ -89,8 +94,10 @@ enum analyse_result
|
|||||||
analyse_disjoint,
|
analyse_disjoint,
|
||||||
analyse_within,
|
analyse_within,
|
||||||
analyse_on_original_boundary,
|
analyse_on_original_boundary,
|
||||||
analyse_on_offsetted,
|
analyse_on_offsetted
|
||||||
analyse_near_offsetted
|
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
, analyse_near_offsetted
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Point>
|
template <typename Point>
|
||||||
@ -112,6 +119,31 @@ inline analyse_result check_segment(Point const& previous,
|
|||||||
Point const& current, Turn const& turn,
|
Point const& current, Turn const& turn,
|
||||||
bool from_monotonic)
|
bool from_monotonic)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||||
|
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||||
|
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||||
|
segment_type const r(previous, current);
|
||||||
|
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||||
|
turn.robust_point);
|
||||||
|
|
||||||
|
if (side == 0)
|
||||||
|
{
|
||||||
|
return analyse_on_offsetted;
|
||||||
|
}
|
||||||
|
if (side == -1 && from_monotonic)
|
||||||
|
{
|
||||||
|
return analyse_within;
|
||||||
|
}
|
||||||
|
if (side == 1 && from_monotonic)
|
||||||
|
{
|
||||||
|
return analyse_disjoint;
|
||||||
|
}
|
||||||
|
return analyse_continue;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
typedef typename strategy::side::services::default_strategy
|
typedef typename strategy::side::services::default_strategy
|
||||||
<
|
<
|
||||||
typename cs_tag<Point>::type
|
typename cs_tag<Point>::type
|
||||||
@ -156,6 +188,7 @@ inline analyse_result check_segment(Point const& previous,
|
|||||||
|
|
||||||
// Not monotonic, on left or right side: continue analysing
|
// Not monotonic, on left or right side: continue analysing
|
||||||
return analyse_continue;
|
return analyse_continue;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -169,14 +202,22 @@ public :
|
|||||||
typedef typename Turn::robust_point_type point_type;
|
typedef typename Turn::robust_point_type point_type;
|
||||||
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
typedef typename geometry::coordinate_type<point_type>::type coordinate_type;
|
||||||
|
|
||||||
coordinate_type const point_y = geometry::get<1>(turn.robust_point);
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
typedef geometry::model::referring_segment<point_type const> segment_type;
|
||||||
|
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||||
|
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||||
|
#else
|
||||||
typedef strategy::within::winding<point_type> strategy_type;
|
typedef strategy::within::winding<point_type> strategy_type;
|
||||||
|
|
||||||
typename strategy_type::state_type state;
|
typename strategy_type::state_type state;
|
||||||
strategy_type strategy;
|
strategy_type strategy;
|
||||||
boost::ignore_unused(strategy);
|
boost::ignore_unused(strategy);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BOOST_ASSERT(! piece.sections.empty());
|
||||||
|
|
||||||
|
coordinate_type const point_y = geometry::get<1>(turn.robust_point);
|
||||||
|
|
||||||
for (std::size_t s = 0; s < piece.sections.size(); s++)
|
for (std::size_t s = 0; s < piece.sections.size(); s++)
|
||||||
{
|
{
|
||||||
section_type const& section = piece.sections[s];
|
section_type const& section = piece.sections[s];
|
||||||
@ -191,6 +232,38 @@ public :
|
|||||||
point_type const& previous = piece.robust_ring[i - 1];
|
point_type const& previous = piece.robust_ring[i - 1];
|
||||||
point_type const& current = piece.robust_ring[i];
|
point_type const& current = piece.robust_ring[i];
|
||||||
|
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
|
||||||
|
// First check if it is in range - if it is not, the
|
||||||
|
// expensive side_of_intersection does not need to be
|
||||||
|
// applied
|
||||||
|
coordinate_type y1 = geometry::get<1>(previous);
|
||||||
|
coordinate_type y2 = geometry::get<1>(current);
|
||||||
|
|
||||||
|
if (y1 > y2)
|
||||||
|
{
|
||||||
|
std::swap(y1, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (point_y >= y1 - 1 && point_y <= y2 + 1)
|
||||||
|
{
|
||||||
|
segment_type const r(previous, current);
|
||||||
|
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||||
|
turn.robust_point);
|
||||||
|
|
||||||
|
// Sections are monotonic in y-dimension
|
||||||
|
if (side == 1)
|
||||||
|
{
|
||||||
|
// Left on segment
|
||||||
|
return analyse_disjoint;
|
||||||
|
}
|
||||||
|
else if (side == 0)
|
||||||
|
{
|
||||||
|
// Collinear - TODO: check if really on segment
|
||||||
|
return analyse_on_offsetted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
analyse_result code = check_segment(previous, current, turn, false);
|
analyse_result code = check_segment(previous, current, turn, false);
|
||||||
if (code != analyse_continue)
|
if (code != analyse_continue)
|
||||||
{
|
{
|
||||||
@ -200,10 +273,15 @@ public :
|
|||||||
// Get the state (to determine it is within), we don't have
|
// Get the state (to determine it is within), we don't have
|
||||||
// to cover the on-segment case (covered above)
|
// to cover the on-segment case (covered above)
|
||||||
strategy.apply(turn.robust_point, previous, current, state);
|
strategy.apply(turn.robust_point, previous, current, state);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
// It is nowhere outside, and not on segment, so it is within
|
||||||
|
return analyse_within;
|
||||||
|
#else
|
||||||
int const code = strategy.result(state);
|
int const code = strategy.result(state);
|
||||||
if (code == 1)
|
if (code == 1)
|
||||||
{
|
{
|
||||||
@ -216,6 +294,7 @@ public :
|
|||||||
|
|
||||||
// Should normally not occur - on-segment is covered
|
// Should normally not occur - on-segment is covered
|
||||||
return analyse_unknown;
|
return analyse_unknown;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -228,6 +307,48 @@ class analyse_turn_wrt_piece
|
|||||||
bool is_original,
|
bool is_original,
|
||||||
Point const& offsetted)
|
Point const& offsetted)
|
||||||
{
|
{
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
typedef geometry::model::referring_segment<Point const> segment_type;
|
||||||
|
segment_type const p(turn.rob_pi, turn.rob_pj);
|
||||||
|
segment_type const q(turn.rob_qi, turn.rob_qj);
|
||||||
|
segment_type const r(s1, s2);
|
||||||
|
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||||
|
turn.robust_point);
|
||||||
|
|
||||||
|
if (side == 1)
|
||||||
|
{
|
||||||
|
// left of segment
|
||||||
|
return analyse_disjoint;
|
||||||
|
}
|
||||||
|
else if (side == 0)
|
||||||
|
{
|
||||||
|
// If is collinear, either on segment or before/after
|
||||||
|
typedef geometry::model::box<Point> box_type;
|
||||||
|
|
||||||
|
box_type box;
|
||||||
|
geometry::assign_inverse(box);
|
||||||
|
geometry::expand(box, s1);
|
||||||
|
geometry::expand(box, s2);
|
||||||
|
|
||||||
|
if (geometry::covered_by(turn.robust_point, box))
|
||||||
|
{
|
||||||
|
// Points on helper-segments are considered as within
|
||||||
|
// Points on original boundary are processed differently
|
||||||
|
return is_original
|
||||||
|
? analyse_on_original_boundary
|
||||||
|
: analyse_within;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is collinear but not on the segment. Because these
|
||||||
|
// segments are convex, it is outside
|
||||||
|
// Unless the offsetted ring is collinear or concave w.r.t.
|
||||||
|
// helper-segment but that scenario is not yet supported
|
||||||
|
return analyse_disjoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
// right of segment
|
||||||
|
return analyse_continue;
|
||||||
|
#else
|
||||||
typedef typename strategy::side::services::default_strategy
|
typedef typename strategy::side::services::default_strategy
|
||||||
<
|
<
|
||||||
typename cs_tag<Point>::type
|
typename cs_tag<Point>::type
|
||||||
@ -276,6 +397,7 @@ class analyse_turn_wrt_piece
|
|||||||
|
|
||||||
// right of segment
|
// right of segment
|
||||||
return analyse_continue;
|
return analyse_continue;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Turn, typename Piece>
|
template <typename Turn, typename Piece>
|
||||||
@ -492,6 +614,60 @@ class turn_in_piece_visitor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
template <typename Turn, typename Piece>
|
||||||
|
static inline int turn_in_convex_piece(Turn const& turn,
|
||||||
|
Piece const& piece)
|
||||||
|
{
|
||||||
|
typedef typename Turn::robust_point_type point_type;
|
||||||
|
typedef typename Piece::piece_robust_ring_type ring_type;
|
||||||
|
typedef geometry::model::referring_segment<point_type const> segment;
|
||||||
|
|
||||||
|
segment const p(turn.rob_pi, turn.rob_pj);
|
||||||
|
segment const q(turn.rob_qi, turn.rob_qj);
|
||||||
|
|
||||||
|
typedef typename boost::range_iterator<ring_type const>::type iterator_type;
|
||||||
|
iterator_type it = boost::begin(piece.robust_ring);
|
||||||
|
iterator_type end = boost::end(piece.robust_ring);
|
||||||
|
|
||||||
|
// A robust ring is always closed, and always clockwise
|
||||||
|
for (iterator_type previous = it++; it != end; ++previous, ++it)
|
||||||
|
{
|
||||||
|
geometry::equal_to<point_type> comparator;
|
||||||
|
if (comparator(*previous, *it))
|
||||||
|
{
|
||||||
|
// Points are the same
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
segment r(*previous, *it);
|
||||||
|
|
||||||
|
int const side = strategy::side::side_of_intersection::apply(p, q, r,
|
||||||
|
turn.robust_point);
|
||||||
|
|
||||||
|
if (side == 1)
|
||||||
|
{
|
||||||
|
// IP is left of segment, so it is outside
|
||||||
|
return -1; // outside
|
||||||
|
}
|
||||||
|
else if (side == 0)
|
||||||
|
{
|
||||||
|
// IP is collinear with segment. TODO: we should analyze this further
|
||||||
|
// For now we use the fallback point
|
||||||
|
if (in_box(*previous, *it, turn.robust_point))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return -1; // outside
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1; // inside
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -530,12 +706,37 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: mutable_piece to make some on-demand preparations in analyse
|
// TODO: mutable_piece to make some on-demand preparations in analyse
|
||||||
|
Turn& mutable_turn = m_turns[turn.turn_index];
|
||||||
|
|
||||||
|
if (piece.type == geometry::strategy::buffer::buffered_point)
|
||||||
|
{
|
||||||
|
// Optimization for buffer around points: if distance from center
|
||||||
|
// is not between min/max radius, the result is clear
|
||||||
|
typedef typename default_comparable_distance_result
|
||||||
|
<
|
||||||
|
typename Turn::robust_point_type
|
||||||
|
>::type distance_type;
|
||||||
|
|
||||||
|
distance_type const cd
|
||||||
|
= geometry::comparable_distance(piece.robust_center,
|
||||||
|
turn.robust_point);
|
||||||
|
|
||||||
|
if (cd < piece.robust_min_comparable_radius)
|
||||||
|
{
|
||||||
|
mutable_turn.count_within++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cd > piece.robust_max_comparable_radius)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
analyse_result analyse_code =
|
analyse_result analyse_code =
|
||||||
piece.type == geometry::strategy::buffer::buffered_point
|
piece.type == geometry::strategy::buffer::buffered_point
|
||||||
? analyse_turn_wrt_point_piece::apply(turn, piece)
|
? analyse_turn_wrt_point_piece::apply(turn, piece)
|
||||||
: analyse_turn_wrt_piece::apply(turn, piece);
|
: analyse_turn_wrt_piece::apply(turn, piece);
|
||||||
|
|
||||||
Turn& mutable_turn = m_turns[turn.turn_index];
|
|
||||||
switch(analyse_code)
|
switch(analyse_code)
|
||||||
{
|
{
|
||||||
case analyse_disjoint :
|
case analyse_disjoint :
|
||||||
@ -549,16 +750,32 @@ public:
|
|||||||
case analyse_within :
|
case analyse_within :
|
||||||
mutable_turn.count_within++;
|
mutable_turn.count_within++;
|
||||||
return;
|
return;
|
||||||
|
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
case analyse_near_offsetted :
|
case analyse_near_offsetted :
|
||||||
mutable_turn.count_within_near_offsetted++;
|
mutable_turn.count_within_near_offsetted++;
|
||||||
return;
|
return;
|
||||||
|
#endif
|
||||||
default :
|
default :
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this point_in_geometry is a performance-bottleneck here and
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
// will be replaced completely by extending analyse_piece functionality
|
// We don't know (yet)
|
||||||
|
int geometry_code = 0;
|
||||||
|
if (piece.is_convex)
|
||||||
|
{
|
||||||
|
geometry_code = turn_in_convex_piece(turn, piece);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: this point_in_geometry is a performance-bottleneck here and
|
||||||
|
// will be replaced completely by extending analyse_piece functionality
|
||||||
|
geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
|
||||||
|
}
|
||||||
|
#else
|
||||||
int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
|
int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (geometry_code == 1)
|
if (geometry_code == 1)
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||||
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||||
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland
|
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland
|
||||||
|
|
||||||
// This file was modified by Oracle on 2013-2014.
|
// This file was modified by Oracle on 2013, 2014, 2015.
|
||||||
// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
|
// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
|
||||||
|
|
||||||
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||||
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||||
@ -23,11 +23,19 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <boost/type_traits/is_same.hpp>
|
||||||
|
|
||||||
#include <boost/geometry/core/access.hpp>
|
#include <boost/geometry/core/access.hpp>
|
||||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
#include <boost/geometry/core/radian_access.hpp>
|
||||||
|
#include <boost/geometry/core/coordinate_system.hpp>
|
||||||
|
#include <boost/geometry/core/coordinate_type.hpp>
|
||||||
|
#include <boost/geometry/core/cs.hpp>
|
||||||
#include <boost/geometry/core/tags.hpp>
|
#include <boost/geometry/core/tags.hpp>
|
||||||
|
|
||||||
|
#include <boost/geometry/util/condition.hpp>
|
||||||
#include <boost/geometry/util/math.hpp>
|
#include <boost/geometry/util/math.hpp>
|
||||||
|
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
|
||||||
|
#include <boost/geometry/util/select_most_precise.hpp>
|
||||||
|
|
||||||
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
|
||||||
|
|
||||||
@ -40,12 +48,103 @@ namespace boost { namespace geometry
|
|||||||
namespace detail { namespace disjoint
|
namespace detail { namespace disjoint
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class point_point_on_spheroid
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename Units,
|
||||||
|
typename CoordinateType1,
|
||||||
|
typename CoordinateType2
|
||||||
|
>
|
||||||
|
static inline bool apply_same_units(CoordinateType1& lon1,
|
||||||
|
CoordinateType1& lat1,
|
||||||
|
CoordinateType2& lon2,
|
||||||
|
CoordinateType2& lat2)
|
||||||
|
{
|
||||||
|
math::normalize_spheroidal_coordinates<Units>(lon1, lat1);
|
||||||
|
math::normalize_spheroidal_coordinates<Units>(lon2, lat2);
|
||||||
|
|
||||||
|
return ! math::equals(lat1, lat2) || ! math::equals(lon1, lon2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename Point1, typename Point2>
|
||||||
|
static inline bool apply(Point1 const& p1, Point2 const& p2)
|
||||||
|
{
|
||||||
|
typedef typename coordinate_type<Point1>::type coordinate_type1;
|
||||||
|
typedef typename coordinate_type<Point2>::type coordinate_type2;
|
||||||
|
|
||||||
|
typedef typename coordinate_system<Point1>::type::units units1;
|
||||||
|
typedef typename coordinate_system<Point2>::type::units units2;
|
||||||
|
|
||||||
|
if (BOOST_GEOMETRY_CONDITION((boost::is_same<units1, units2>::value)))
|
||||||
|
{
|
||||||
|
coordinate_type1 lon1 = geometry::get<0>(p1);
|
||||||
|
coordinate_type1 lat1 = geometry::get<1>(p1);
|
||||||
|
coordinate_type2 lon2 = geometry::get<0>(p2);
|
||||||
|
coordinate_type2 lat2 = geometry::get<1>(p2);
|
||||||
|
|
||||||
|
return apply_same_units<units1>(lon1, lat1, lon2, lat2);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef typename geometry::select_most_precise
|
||||||
|
<
|
||||||
|
typename fp_coordinate_type<Point1>::type,
|
||||||
|
typename fp_coordinate_type<Point2>::type
|
||||||
|
>::type calculation_type;
|
||||||
|
|
||||||
|
calculation_type lon1 = get_as_radian<0>(p1);
|
||||||
|
calculation_type lat1 = get_as_radian<1>(p1);
|
||||||
|
|
||||||
|
calculation_type lon2 = get_as_radian<0>(p2);
|
||||||
|
calculation_type lat2 = get_as_radian<1>(p2);
|
||||||
|
|
||||||
|
return apply_same_units<radian>(lon1, lat1, lon2, lat2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename Point1, typename Point2,
|
||||||
|
std::size_t Dimension, std::size_t DimensionCount,
|
||||||
|
typename CSTag1 = typename cs_tag<Point1>::type,
|
||||||
|
typename CSTag2 = CSTag1
|
||||||
|
>
|
||||||
|
struct point_point
|
||||||
|
: point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>
|
||||||
|
{};
|
||||||
|
|
||||||
template
|
template
|
||||||
<
|
<
|
||||||
typename Point1, typename Point2,
|
typename Point1, typename Point2,
|
||||||
std::size_t Dimension, std::size_t DimensionCount
|
std::size_t Dimension, std::size_t DimensionCount
|
||||||
>
|
>
|
||||||
struct point_point
|
struct point_point
|
||||||
|
<
|
||||||
|
Point1, Point2, Dimension, DimensionCount, spherical_equatorial_tag
|
||||||
|
> : point_point_on_spheroid
|
||||||
|
{};
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename Point1, typename Point2,
|
||||||
|
std::size_t Dimension, std::size_t DimensionCount
|
||||||
|
>
|
||||||
|
struct point_point
|
||||||
|
<
|
||||||
|
Point1, Point2, Dimension, DimensionCount, geographic_tag
|
||||||
|
> : point_point_on_spheroid
|
||||||
|
{};
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename Point1, typename Point2,
|
||||||
|
std::size_t Dimension, std::size_t DimensionCount
|
||||||
|
>
|
||||||
|
struct point_point<Point1, Point2, Dimension, DimensionCount, cartesian_tag>
|
||||||
{
|
{
|
||||||
static inline bool apply(Point1 const& p1, Point2 const& p2)
|
static inline bool apply(Point1 const& p1, Point2 const& p2)
|
||||||
{
|
{
|
||||||
@ -61,9 +160,11 @@ struct point_point
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename Point1, typename Point2, std::size_t DimensionCount>
|
template <typename Point1, typename Point2, std::size_t DimensionCount>
|
||||||
struct point_point<Point1, Point2, DimensionCount, DimensionCount>
|
struct point_point
|
||||||
|
<
|
||||||
|
Point1, Point2, DimensionCount, DimensionCount, cartesian_tag
|
||||||
|
>
|
||||||
{
|
{
|
||||||
static inline bool apply(Point1 const& , Point2 const& )
|
static inline bool apply(Point1 const& , Point2 const& )
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
|
|
||||||
|
// This file was modified by Oracle on 2015.
|
||||||
|
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
|
||||||
|
|
||||||
|
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||||
|
|
||||||
// Use, modification and distribution is subject to the Boost Software License,
|
// Use, modification and distribution is subject to the Boost Software License,
|
||||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -160,10 +165,12 @@ template
|
|||||||
typename OutputLinestring,
|
typename OutputLinestring,
|
||||||
typename OutputIterator,
|
typename OutputIterator,
|
||||||
typename Range,
|
typename Range,
|
||||||
|
typename RobustPolicy,
|
||||||
typename Box,
|
typename Box,
|
||||||
typename Strategy
|
typename Strategy
|
||||||
>
|
>
|
||||||
OutputIterator clip_range_with_box(Box const& b, Range const& range,
|
OutputIterator clip_range_with_box(Box const& b, Range const& range,
|
||||||
|
RobustPolicy const&,
|
||||||
OutputIterator out, Strategy const& strategy)
|
OutputIterator out, Strategy const& strategy)
|
||||||
{
|
{
|
||||||
if (boost::begin(range) == boost::end(range))
|
if (boost::begin(range) == boost::end(range))
|
||||||
|
@ -410,13 +410,13 @@ struct intersection_insert
|
|||||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||||
static inline OutputIterator apply(Linestring const& linestring,
|
static inline OutputIterator apply(Linestring const& linestring,
|
||||||
Box const& box,
|
Box const& box,
|
||||||
RobustPolicy const& ,
|
RobustPolicy const& robust_policy,
|
||||||
OutputIterator out, Strategy const& )
|
OutputIterator out, Strategy const& )
|
||||||
{
|
{
|
||||||
typedef typename point_type<GeometryOut>::type point_type;
|
typedef typename point_type<GeometryOut>::type point_type;
|
||||||
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
|
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
|
||||||
return detail::intersection::clip_range_with_box
|
return detail::intersection::clip_range_with_box
|
||||||
<GeometryOut>(box, linestring, out, lb_strategy);
|
<GeometryOut>(box, linestring, robust_policy, out, lb_strategy);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -488,7 +488,7 @@ struct intersection_insert
|
|||||||
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
|
||||||
static inline OutputIterator apply(Segment const& segment,
|
static inline OutputIterator apply(Segment const& segment,
|
||||||
Box const& box,
|
Box const& box,
|
||||||
RobustPolicy const& ,// TODO: propagate to clip_range_with_box
|
RobustPolicy const& robust_policy,
|
||||||
OutputIterator out, Strategy const& )
|
OutputIterator out, Strategy const& )
|
||||||
{
|
{
|
||||||
geometry::segment_view<Segment> range(segment);
|
geometry::segment_view<Segment> range(segment);
|
||||||
@ -496,7 +496,7 @@ struct intersection_insert
|
|||||||
typedef typename point_type<GeometryOut>::type point_type;
|
typedef typename point_type<GeometryOut>::type point_type;
|
||||||
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
|
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
|
||||||
return detail::intersection::clip_range_with_box
|
return detail::intersection::clip_range_with_box
|
||||||
<GeometryOut>(box, range, out, lb_strategy);
|
<GeometryOut>(box, range, robust_policy, out, lb_strategy);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,6 +14,10 @@
|
|||||||
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
|
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
|
||||||
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
|
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_LESS_HPP
|
||||||
|
|
||||||
|
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||||
|
#include <boost/geometry/core/coordinate_type.hpp>
|
||||||
|
#include <boost/geometry/util/math.hpp>
|
||||||
|
|
||||||
namespace boost { namespace geometry
|
namespace boost { namespace geometry
|
||||||
{
|
{
|
||||||
|
|
||||||
|
160
include/boost/geometry/algorithms/is_convex.hpp
Normal file
160
include/boost/geometry/algorithms/is_convex.hpp
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
|
// Copyright (c) 2015 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_IS_CONVEX_HPP
|
||||||
|
#define BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP
|
||||||
|
|
||||||
|
|
||||||
|
#include <boost/geometry/core/access.hpp>
|
||||||
|
#include <boost/geometry/core/closure.hpp>
|
||||||
|
#include <boost/geometry/core/cs.hpp>
|
||||||
|
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||||
|
#include <boost/geometry/core/point_type.hpp>
|
||||||
|
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
|
||||||
|
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
|
||||||
|
#include <boost/geometry/strategies/side.hpp>
|
||||||
|
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||||
|
#include <boost/geometry/views/detail/normalized_view.hpp>
|
||||||
|
|
||||||
|
namespace boost { namespace geometry
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_NO_DETAIL
|
||||||
|
namespace detail { namespace is_convex
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ring_is_convex
|
||||||
|
{
|
||||||
|
template <typename Ring>
|
||||||
|
static inline bool apply(Ring const& ring)
|
||||||
|
{
|
||||||
|
typedef typename geometry::point_type<Ring>::type point_type;
|
||||||
|
typedef typename strategy::side::services::default_strategy
|
||||||
|
<
|
||||||
|
typename cs_tag<point_type>::type
|
||||||
|
>::type side_strategy_type;
|
||||||
|
|
||||||
|
std::size_t n = boost::size(ring);
|
||||||
|
if (boost::size(ring) < core_detail::closure::minimum_ring_size
|
||||||
|
<
|
||||||
|
geometry::closure<Ring>::value
|
||||||
|
>::value)
|
||||||
|
{
|
||||||
|
// (Too) small rings are considered as non-concave, is convex
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk in clockwise direction, consider ring as closed
|
||||||
|
// (though closure is not important in this algorithm - any dupped
|
||||||
|
// point is skipped)
|
||||||
|
typedef detail::normalized_view<Ring const> view_type;
|
||||||
|
view_type view(ring);
|
||||||
|
|
||||||
|
typedef geometry::ever_circling_range_iterator<view_type const> it_type;
|
||||||
|
it_type previous(view);
|
||||||
|
it_type current(view);
|
||||||
|
current++;
|
||||||
|
|
||||||
|
std::size_t index = 1;
|
||||||
|
while (equals::equals_point_point(*current, *previous) && index < n)
|
||||||
|
{
|
||||||
|
current++;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == n)
|
||||||
|
{
|
||||||
|
// All points are apparently equal
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
it_type next = current;
|
||||||
|
next++;
|
||||||
|
while (equals::equals_point_point(*current, *next))
|
||||||
|
{
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have now three different points on the ring
|
||||||
|
// Walk through all points, use a counter because of the ever-circling
|
||||||
|
// iterator
|
||||||
|
for (std::size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
int const side = side_strategy_type::apply(*previous, *current, *next);
|
||||||
|
if (side == 1)
|
||||||
|
{
|
||||||
|
// Next is on the left side of clockwise ring:
|
||||||
|
// the piece is not convex
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = current;
|
||||||
|
current = next;
|
||||||
|
|
||||||
|
// Advance next to next different point
|
||||||
|
// (because there are non-equal points, this loop is not infinite)
|
||||||
|
next++;
|
||||||
|
while (equals::equals_point_point(*current, *next))
|
||||||
|
{
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}} // namespace detail::is_convex
|
||||||
|
#endif // DOXYGEN_NO_DETAIL
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_NO_DISPATCH
|
||||||
|
namespace dispatch
|
||||||
|
{
|
||||||
|
|
||||||
|
template
|
||||||
|
<
|
||||||
|
typename Geometry,
|
||||||
|
typename Tag = typename tag<Geometry>::type
|
||||||
|
>
|
||||||
|
struct is_convex : not_implemented<Tag>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <typename Box>
|
||||||
|
struct is_convex<Box, box_tag>
|
||||||
|
{
|
||||||
|
static inline bool apply(Box const& )
|
||||||
|
{
|
||||||
|
// Any box is convex (TODO: consider spherical boxes)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Box>
|
||||||
|
struct is_convex<Box, ring_tag> : detail::is_convex::ring_is_convex
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace dispatch
|
||||||
|
#endif // DOXYGEN_NO_DISPATCH
|
||||||
|
|
||||||
|
// TODO: variants
|
||||||
|
|
||||||
|
// TODO: documentation / qbk
|
||||||
|
template<typename Geometry>
|
||||||
|
inline bool is_convex(Geometry const& geometry)
|
||||||
|
{
|
||||||
|
return dispatch::is_convex<Geometry>::apply(geometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}} // namespace boost::geometry
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP
|
@ -1,8 +1,13 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
// 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.
|
||||||
|
|
||||||
|
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||||
|
|
||||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||||
@ -47,7 +52,8 @@ struct degree_radian_converter
|
|||||||
return boost::numeric_cast
|
return boost::numeric_cast
|
||||||
<
|
<
|
||||||
coordinate_type
|
coordinate_type
|
||||||
>(geometry::get<Dimension>(geometry) * geometry::math::d2r);
|
>(geometry::get<Dimension>(geometry)
|
||||||
|
* math::d2r<coordinate_type>());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void set(Geometry& geometry, coordinate_type const& radians)
|
static inline void set(Geometry& geometry, coordinate_type const& radians)
|
||||||
@ -55,7 +61,7 @@ struct degree_radian_converter
|
|||||||
geometry::set<Dimension>(geometry, boost::numeric_cast
|
geometry::set<Dimension>(geometry, boost::numeric_cast
|
||||||
<
|
<
|
||||||
coordinate_type
|
coordinate_type
|
||||||
>(radians * geometry::math::r2d));
|
>(radians * math::r2d<coordinate_type>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -419,12 +419,14 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
public :
|
public :
|
||||||
virtual projection<Geographic, Cartesian>* create_new(const Parameters& par) const
|
virtual projection<Geographic, Cartesian>* create_new(const Parameters& par) const
|
||||||
{
|
{
|
||||||
if (! par.es)
|
bool const guam = pj_param(par.params, "bguam").i;
|
||||||
return new base_v_fi<aeqd_spheroid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
|
||||||
else if (pj_param(par.params, "bguam").i)
|
if (par.es && ! guam)
|
||||||
|
return new base_v_fi<aeqd_ellipsoid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
||||||
|
else if (par.es && guam)
|
||||||
return new base_v_fi<aeqd_guam<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
return new base_v_fi<aeqd_guam<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
||||||
else
|
else
|
||||||
return new base_v_fi<aeqd_ellipsoid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
return new base_v_fi<aeqd_spheroid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -213,9 +213,9 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
\image html ex_gn_sinu.gif
|
\image html ex_gn_sinu.gif
|
||||||
*/
|
*/
|
||||||
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
|
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
|
||||||
struct gn_sinu_ellipsoid : public detail::gn_sinu::base_gn_sinu_ellipsoid<Geographic, Cartesian, Parameters>
|
struct gn_sinu_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid<Geographic, Cartesian, Parameters>
|
||||||
{
|
{
|
||||||
inline gn_sinu_ellipsoid(const Parameters& par) : detail::gn_sinu::base_gn_sinu_ellipsoid<Geographic, Cartesian, Parameters>(par)
|
inline gn_sinu_spheroid(const Parameters& par) : detail::gn_sinu::base_gn_sinu_spheroid<Geographic, Cartesian, Parameters>(par)
|
||||||
{
|
{
|
||||||
detail::gn_sinu::setup_gn_sinu(this->m_par, this->m_proj_parm);
|
detail::gn_sinu::setup_gn_sinu(this->m_par, this->m_proj_parm);
|
||||||
}
|
}
|
||||||
@ -243,70 +243,6 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief Eckert VI projection
|
|
||||||
\ingroup projections
|
|
||||||
\tparam Geographic latlong point type
|
|
||||||
\tparam Cartesian xy point type
|
|
||||||
\tparam Parameters parameter type
|
|
||||||
\par Projection characteristics
|
|
||||||
- Pseudocylindrical
|
|
||||||
- Spheroid
|
|
||||||
\par Example
|
|
||||||
\image html ex_eck6.gif
|
|
||||||
*/
|
|
||||||
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
|
|
||||||
struct eck6_ellipsoid : public detail::gn_sinu::base_gn_sinu_ellipsoid<Geographic, Cartesian, Parameters>
|
|
||||||
{
|
|
||||||
inline eck6_ellipsoid(const Parameters& par) : detail::gn_sinu::base_gn_sinu_ellipsoid<Geographic, Cartesian, Parameters>(par)
|
|
||||||
{
|
|
||||||
detail::gn_sinu::setup_eck6(this->m_par, this->m_proj_parm);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief McBryde-Thomas Flat-Polar Sinusoidal projection
|
|
||||||
\ingroup projections
|
|
||||||
\tparam Geographic latlong point type
|
|
||||||
\tparam Cartesian xy point type
|
|
||||||
\tparam Parameters parameter type
|
|
||||||
\par Projection characteristics
|
|
||||||
- Pseudocylindrical
|
|
||||||
- Spheroid
|
|
||||||
\par Example
|
|
||||||
\image html ex_mbtfps.gif
|
|
||||||
*/
|
|
||||||
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
|
|
||||||
struct mbtfps_ellipsoid : public detail::gn_sinu::base_gn_sinu_ellipsoid<Geographic, Cartesian, Parameters>
|
|
||||||
{
|
|
||||||
inline mbtfps_ellipsoid(const Parameters& par) : detail::gn_sinu::base_gn_sinu_ellipsoid<Geographic, Cartesian, Parameters>(par)
|
|
||||||
{
|
|
||||||
detail::gn_sinu::setup_mbtfps(this->m_par, this->m_proj_parm);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief General Sinusoidal Series projection
|
|
||||||
\ingroup projections
|
|
||||||
\tparam Geographic latlong point type
|
|
||||||
\tparam Cartesian xy point type
|
|
||||||
\tparam Parameters parameter type
|
|
||||||
\par Projection characteristics
|
|
||||||
- Pseudocylindrical
|
|
||||||
- Spheroid
|
|
||||||
- m= n=
|
|
||||||
\par Example
|
|
||||||
\image html ex_gn_sinu.gif
|
|
||||||
*/
|
|
||||||
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
|
|
||||||
struct gn_sinu_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid<Geographic, Cartesian, Parameters>
|
|
||||||
{
|
|
||||||
inline gn_sinu_spheroid(const Parameters& par) : detail::gn_sinu::base_gn_sinu_spheroid<Geographic, Cartesian, Parameters>(par)
|
|
||||||
{
|
|
||||||
detail::gn_sinu::setup_gn_sinu(this->m_par, this->m_proj_parm);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Sinusoidal (Sanson-Flamsteed) projection
|
\brief Sinusoidal (Sanson-Flamsteed) projection
|
||||||
\ingroup projections
|
\ingroup projections
|
||||||
|
@ -56,11 +56,11 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
static const double DEG144 = 2.51327412287183459075;
|
static const double DEG144 = 2.51327412287183459075;
|
||||||
static const double DEG36 = 0.62831853071795864768;
|
static const double DEG36 = 0.62831853071795864768;
|
||||||
static const double DEG108 = 1.88495559215387594306;
|
static const double DEG108 = 1.88495559215387594306;
|
||||||
static const double DEG180 = M_PI;
|
static const double DEG180 = boost::math::constants::pi<double>();
|
||||||
static const double ISEA_SCALE = 0.8301572857837594396028083;
|
static const double ISEA_SCALE = 0.8301572857837594396028083;
|
||||||
static const double V_LAT = 0.46364760899944494524;
|
static const double V_LAT = 0.46364760899944494524;
|
||||||
static const double RAD2DEG = (180.0/M_PI);
|
static const double RAD2DEG = (180.0/boost::math::constants::pi<double>());
|
||||||
static const double DEG2RAD = (M_PI/180.0);
|
static const double DEG2RAD = (boost::math::constants::pi<double>()/180.0);
|
||||||
static const double E_RAD = 0.91843818702186776133;
|
static const double E_RAD = 0.91843818702186776133;
|
||||||
static const double F_RAD = 0.18871053072122403508;
|
static const double F_RAD = 0.18871053072122403508;
|
||||||
static const double TABLE_G = 0.6615845383;
|
static const double TABLE_G = 0.6615845383;
|
||||||
@ -116,7 +116,7 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
int ix, iy, iz, s;
|
int ix, iy, iz, s;
|
||||||
struct hex h;
|
struct hex h;
|
||||||
|
|
||||||
x = x / cos(30 * M_PI / 180.0); /* rotated X coord */
|
x = x / cos(30 * boost::math::constants::pi<double>() / 180.0); /* rotated X coord */
|
||||||
y = y - x / 2.0; /* adjustment for rotated X */
|
y = y - x / 2.0; /* adjustment for rotated X */
|
||||||
|
|
||||||
/* adjust for actual hexwidth */
|
/* adjust for actual hexwidth */
|
||||||
@ -215,7 +215,7 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* sqrt(5)/M_PI */
|
/* sqrt(5)/boost::math::constants::pi<double>() */
|
||||||
|
|
||||||
/* 26.565051177 degrees */
|
/* 26.565051177 degrees */
|
||||||
|
|
||||||
@ -409,7 +409,7 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
/* TODO I don't know why we do this. It's not in snyder */
|
/* TODO I don't know why we do this. It's not in snyder */
|
||||||
/* maybe because we should have picked a better vertex */
|
/* maybe because we should have picked a better vertex */
|
||||||
if (Az < 0.0) {
|
if (Az < 0.0) {
|
||||||
Az += 2.0 * M_PI;
|
Az += 2.0 * boost::math::constants::pi<double>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Az_adjust_multiples = 0;
|
Az_adjust_multiples = 0;
|
||||||
@ -447,7 +447,7 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
H = acos(sin(Az) * sin(G) * cos(g) - cos(Az) * cos(G));
|
H = acos(sin(Az) * sin(G) * cos(g) - cos(Az) * cos(G));
|
||||||
|
|
||||||
/* eq 7 */
|
/* eq 7 */
|
||||||
/* Ag = (Az + G + H - DEG180) * M_PI * R * R / DEG180; */
|
/* Ag = (Az + G + H - DEG180) * boost::math::constants::pi<double>() * R * R / DEG180; */
|
||||||
Ag = Az + G + H - DEG180;
|
Ag = Az + G + H - DEG180;
|
||||||
|
|
||||||
/* eq 8 */
|
/* eq 8 */
|
||||||
@ -523,11 +523,11 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
|
|
||||||
/* normalize longitude */
|
/* normalize longitude */
|
||||||
/* TODO can we just do a modulus ? */
|
/* TODO can we just do a modulus ? */
|
||||||
lambdap = fmod(lambdap, 2 * M_PI);
|
lambdap = fmod(lambdap, 2 * boost::math::constants::pi<double>());
|
||||||
while (lambdap > M_PI)
|
while (lambdap > boost::math::constants::pi<double>())
|
||||||
lambdap -= 2 * M_PI;
|
lambdap -= 2 * boost::math::constants::pi<double>();
|
||||||
while (lambdap < -M_PI)
|
while (lambdap < -boost::math::constants::pi<double>())
|
||||||
lambdap += 2 * M_PI;
|
lambdap += 2 * boost::math::constants::pi<double>();
|
||||||
|
|
||||||
phip = asin(sin_phip);
|
phip = asin(sin_phip);
|
||||||
|
|
||||||
@ -543,19 +543,19 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
{
|
{
|
||||||
struct isea_geo npt;
|
struct isea_geo npt;
|
||||||
|
|
||||||
np->lon += M_PI;
|
np->lon += boost::math::constants::pi<double>();
|
||||||
npt = snyder_ctran(np, pt);
|
npt = snyder_ctran(np, pt);
|
||||||
np->lon -= M_PI;
|
np->lon -= boost::math::constants::pi<double>();
|
||||||
|
|
||||||
npt.lon -= (M_PI - lon0 + np->lon);
|
npt.lon -= (boost::math::constants::pi<double>() - lon0 + np->lon);
|
||||||
|
|
||||||
npt.lon += M_PI;
|
npt.lon += boost::math::constants::pi<double>();
|
||||||
/* normalize longitude */
|
/* normalize longitude */
|
||||||
npt.lon = fmod(npt.lon, 2 * M_PI);
|
npt.lon = fmod(npt.lon, 2 * boost::math::constants::pi<double>());
|
||||||
while (npt.lon > M_PI)
|
while (npt.lon > boost::math::constants::pi<double>())
|
||||||
npt.lon -= 2 * M_PI;
|
npt.lon -= 2 * boost::math::constants::pi<double>();
|
||||||
while (npt.lon < -M_PI)
|
while (npt.lon < -boost::math::constants::pi<double>())
|
||||||
npt.lon += 2 * M_PI;
|
npt.lon += 2 * boost::math::constants::pi<double>();
|
||||||
|
|
||||||
return npt;
|
return npt;
|
||||||
}
|
}
|
||||||
@ -601,7 +601,7 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
{
|
{
|
||||||
if (!g)
|
if (!g)
|
||||||
return 0;
|
return 0;
|
||||||
g->o_lat = M_PI / 2.0;
|
g->o_lat = boost::math::constants::pi<double>() / 2.0;
|
||||||
g->o_lon = 0.0;
|
g->o_lon = 0.0;
|
||||||
g->o_az = 0;
|
g->o_az = 0;
|
||||||
return 1;
|
return 1;
|
||||||
@ -637,9 +637,9 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
|
|
||||||
double x, y;
|
double x, y;
|
||||||
|
|
||||||
rad = -degrees * M_PI / 180.0;
|
rad = -degrees * boost::math::constants::pi<double>() / 180.0;
|
||||||
while (rad >= 2.0 * M_PI) rad -= 2.0 * M_PI;
|
while (rad >= 2.0 * boost::math::constants::pi<double>()) rad -= 2.0 * boost::math::constants::pi<double>();
|
||||||
while (rad <= -2.0 * M_PI) rad += 2.0 * M_PI;
|
while (rad <= -2.0 * boost::math::constants::pi<double>()) rad += 2.0 * boost::math::constants::pi<double>();
|
||||||
|
|
||||||
x = pt->x * cos(rad) + pt->y * sin(rad);
|
x = pt->x * cos(rad) + pt->y * sin(rad);
|
||||||
y = -pt->x * sin(rad) + pt->y * cos(rad);
|
y = -pt->x * sin(rad) + pt->y * cos(rad);
|
||||||
@ -676,7 +676,7 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
isea_rotate(pt, downtri ? 240.0 : 60.0);
|
isea_rotate(pt, downtri ? 240.0 : 60.0);
|
||||||
if (downtri) {
|
if (downtri) {
|
||||||
pt->x += 0.5;
|
pt->x += 0.5;
|
||||||
/* pt->y += cos(30.0 * M_PI / 180.0); */
|
/* pt->y += cos(30.0 * boost::math::constants::pi<double>() / 180.0); */
|
||||||
pt->y += .86602540378443864672;
|
pt->y += .86602540378443864672;
|
||||||
}
|
}
|
||||||
return quad;
|
return quad;
|
||||||
@ -697,7 +697,7 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
sidelength = (pow(2.0, g->resolution) + 1.0) / 2.0;
|
sidelength = (pow(2.0, g->resolution) + 1.0) / 2.0;
|
||||||
|
|
||||||
/* apex to base is cos(30deg) */
|
/* apex to base is cos(30deg) */
|
||||||
hexwidth = cos(M_PI / 6.0) / sidelength;
|
hexwidth = cos(boost::math::constants::pi<double>() / 6.0) / sidelength;
|
||||||
|
|
||||||
/* TODO I think sidelength is always x.5, so
|
/* TODO I think sidelength is always x.5, so
|
||||||
* (int)sidelength * 2 + 1 might be just as good
|
* (int)sidelength * 2 + 1 might be just as good
|
||||||
|
@ -292,6 +292,7 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
detail::ob_tran::par_ob_tran<Geographic, Cartesian> proj_parm;
|
detail::ob_tran::par_ob_tran<Geographic, Cartesian> proj_parm;
|
||||||
Parameters p = par;
|
Parameters p = par;
|
||||||
double phip = setup_ob_tran(p, proj_parm, false);
|
double phip = setup_ob_tran(p, proj_parm, false);
|
||||||
|
|
||||||
if (fabs(phip) > detail::ob_tran::TOL)
|
if (fabs(phip) > detail::ob_tran::TOL)
|
||||||
return new base_v_fi<ob_tran_oblique<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
return new base_v_fi<ob_tran_oblique<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
||||||
else
|
else
|
||||||
|
@ -360,29 +360,6 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief Universal Polar Stereographic projection
|
|
||||||
\ingroup projections
|
|
||||||
\tparam Geographic latlong point type
|
|
||||||
\tparam Cartesian xy point type
|
|
||||||
\tparam Parameters parameter type
|
|
||||||
\par Projection characteristics
|
|
||||||
- Azimuthal
|
|
||||||
- Spheroid
|
|
||||||
- Ellipsoid
|
|
||||||
- south
|
|
||||||
\par Example
|
|
||||||
\image html ex_ups.gif
|
|
||||||
*/
|
|
||||||
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
|
|
||||||
struct ups_ellipsoid : public detail::stere::base_stere_ellipsoid<Geographic, Cartesian, Parameters>
|
|
||||||
{
|
|
||||||
inline ups_ellipsoid(const Parameters& par) : detail::stere::base_stere_ellipsoid<Geographic, Cartesian, Parameters>(par)
|
|
||||||
{
|
|
||||||
detail::stere::setup_ups(this->m_par, this->m_proj_parm);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Stereographic projection
|
\brief Stereographic projection
|
||||||
\ingroup projections
|
\ingroup projections
|
||||||
@ -406,6 +383,29 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Universal Polar Stereographic projection
|
||||||
|
\ingroup projections
|
||||||
|
\tparam Geographic latlong point type
|
||||||
|
\tparam Cartesian xy point type
|
||||||
|
\tparam Parameters parameter type
|
||||||
|
\par Projection characteristics
|
||||||
|
- Azimuthal
|
||||||
|
- Spheroid
|
||||||
|
- Ellipsoid
|
||||||
|
- south
|
||||||
|
\par Example
|
||||||
|
\image html ex_ups.gif
|
||||||
|
*/
|
||||||
|
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
|
||||||
|
struct ups_ellipsoid : public detail::stere::base_stere_ellipsoid<Geographic, Cartesian, Parameters>
|
||||||
|
{
|
||||||
|
inline ups_ellipsoid(const Parameters& par) : detail::stere::base_stere_ellipsoid<Geographic, Cartesian, Parameters>(par)
|
||||||
|
{
|
||||||
|
detail::stere::setup_ups(this->m_par, this->m_proj_parm);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Universal Polar Stereographic projection
|
\brief Universal Polar Stereographic projection
|
||||||
\ingroup projections
|
\ingroup projections
|
||||||
@ -453,7 +453,10 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
public :
|
public :
|
||||||
virtual projection<Geographic, Cartesian>* create_new(const Parameters& par) const
|
virtual projection<Geographic, Cartesian>* create_new(const Parameters& par) const
|
||||||
{
|
{
|
||||||
return new base_v_fi<ups_ellipsoid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
if (par.es)
|
||||||
|
return new base_v_fi<ups_ellipsoid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
||||||
|
else
|
||||||
|
return new base_v_fi<ups_spheroid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -284,28 +284,6 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief Universal Transverse Mercator (UTM) projection
|
|
||||||
\ingroup projections
|
|
||||||
\tparam Geographic latlong point type
|
|
||||||
\tparam Cartesian xy point type
|
|
||||||
\tparam Parameters parameter type
|
|
||||||
\par Projection characteristics
|
|
||||||
- Cylindrical
|
|
||||||
- Spheroid
|
|
||||||
- zone= south
|
|
||||||
\par Example
|
|
||||||
\image html ex_utm.gif
|
|
||||||
*/
|
|
||||||
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
|
|
||||||
struct utm_ellipsoid : public detail::tmerc::base_tmerc_ellipsoid<Geographic, Cartesian, Parameters>
|
|
||||||
{
|
|
||||||
inline utm_ellipsoid(const Parameters& par) : detail::tmerc::base_tmerc_ellipsoid<Geographic, Cartesian, Parameters>(par)
|
|
||||||
{
|
|
||||||
detail::tmerc::setup_utm(this->m_par, this->m_proj_parm);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Transverse Mercator projection
|
\brief Transverse Mercator projection
|
||||||
\ingroup projections
|
\ingroup projections
|
||||||
@ -328,6 +306,28 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Universal Transverse Mercator (UTM) projection
|
||||||
|
\ingroup projections
|
||||||
|
\tparam Geographic latlong point type
|
||||||
|
\tparam Cartesian xy point type
|
||||||
|
\tparam Parameters parameter type
|
||||||
|
\par Projection characteristics
|
||||||
|
- Cylindrical
|
||||||
|
- Spheroid
|
||||||
|
- zone= south
|
||||||
|
\par Example
|
||||||
|
\image html ex_utm.gif
|
||||||
|
*/
|
||||||
|
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
|
||||||
|
struct utm_ellipsoid : public detail::tmerc::base_tmerc_ellipsoid<Geographic, Cartesian, Parameters>
|
||||||
|
{
|
||||||
|
inline utm_ellipsoid(const Parameters& par) : detail::tmerc::base_tmerc_ellipsoid<Geographic, Cartesian, Parameters>(par)
|
||||||
|
{
|
||||||
|
detail::tmerc::setup_utm(this->m_par, this->m_proj_parm);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Universal Transverse Mercator (UTM) projection
|
\brief Universal Transverse Mercator (UTM) projection
|
||||||
\ingroup projections
|
\ingroup projections
|
||||||
@ -374,7 +374,10 @@ namespace boost { namespace geometry { namespace projections
|
|||||||
public :
|
public :
|
||||||
virtual projection<Geographic, Cartesian>* create_new(const Parameters& par) const
|
virtual projection<Geographic, Cartesian>* create_new(const Parameters& par) const
|
||||||
{
|
{
|
||||||
return new base_v_fi<utm_ellipsoid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
if (par.es)
|
||||||
|
return new base_v_fi<utm_ellipsoid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
||||||
|
else
|
||||||
|
return new base_v_fi<utm_spheroid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ struct project_inverse_transformer
|
|||||||
{
|
{
|
||||||
// Latlong (LL -> XY) will be projected, rest will be copied.
|
// Latlong (LL -> XY) will be projected, rest will be copied.
|
||||||
// So first copy third or higher dimensions
|
// So first copy third or higher dimensions
|
||||||
geometry::detail::convert::point_to_point<Cartesian, LatLong, 2,
|
geometry::detail::conversion::point_to_point<Cartesian, LatLong, 2,
|
||||||
geometry::dimension<Cartesian>::value> ::copy(p1, p2);
|
geometry::dimension<Cartesian>::value> ::apply(p1, p2);
|
||||||
return m_prj->inverse(p1, p2);
|
return m_prj->inverse(p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,8 @@ enum piece_type
|
|||||||
buffered_round_end,
|
buffered_round_end,
|
||||||
buffered_flat_end,
|
buffered_flat_end,
|
||||||
buffered_point,
|
buffered_point,
|
||||||
buffered_concave // always on the inside
|
buffered_concave, // always on the inside
|
||||||
|
piece_type_unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,8 +13,13 @@
|
|||||||
#include <boost/geometry/arithmetic/determinant.hpp>
|
#include <boost/geometry/arithmetic/determinant.hpp>
|
||||||
#include <boost/geometry/core/access.hpp>
|
#include <boost/geometry/core/access.hpp>
|
||||||
#include <boost/geometry/core/coordinate_type.hpp>
|
#include <boost/geometry/core/coordinate_type.hpp>
|
||||||
|
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
||||||
|
#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
|
||||||
#include <boost/geometry/util/math.hpp>
|
#include <boost/geometry/util/math.hpp>
|
||||||
|
|
||||||
|
#include <boost/math/common_factor_ct.hpp>
|
||||||
|
#include <boost/math/common_factor_rt.hpp>
|
||||||
|
#include <boost/multiprecision/cpp_int.hpp>
|
||||||
|
|
||||||
namespace boost { namespace geometry
|
namespace boost { namespace geometry
|
||||||
{
|
{
|
||||||
@ -29,15 +34,74 @@ namespace strategy { namespace side
|
|||||||
// It can be used for either integer (rescaled) points, and also for FP
|
// It can be used for either integer (rescaled) points, and also for FP
|
||||||
class side_of_intersection
|
class side_of_intersection
|
||||||
{
|
{
|
||||||
|
private :
|
||||||
|
template <typename T, typename U>
|
||||||
|
static inline
|
||||||
|
int sign_of_product(T const& a, U const& b)
|
||||||
|
{
|
||||||
|
return a == 0 || b == 0 ? 0
|
||||||
|
: a > 0 && b > 0 ? 1
|
||||||
|
: a < 0 && b < 0 ? 1
|
||||||
|
: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline
|
||||||
|
int sign_of_compare(T const& a, T const& b, T const& c, T const& d)
|
||||||
|
{
|
||||||
|
// Both a*b and c*d are positive
|
||||||
|
// We have to judge if a*b > c*d
|
||||||
|
|
||||||
|
using namespace boost::multiprecision;
|
||||||
|
cpp_int const lab = cpp_int(a) * cpp_int(b);
|
||||||
|
cpp_int const lcd = cpp_int(c) * cpp_int(d);
|
||||||
|
|
||||||
|
return lab > lcd ? 1
|
||||||
|
: lab < lcd ? -1
|
||||||
|
: 0
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline
|
||||||
|
int sign_of_addition_of_two_products(T const& a, T const& b, T const& c, T const& d)
|
||||||
|
{
|
||||||
|
// sign of a*b+c*d, 1 if positive, -1 if negative, else 0
|
||||||
|
int const ab = sign_of_product(a, b);
|
||||||
|
int const cd = sign_of_product(c, d);
|
||||||
|
if (ab == 0)
|
||||||
|
{
|
||||||
|
return cd;
|
||||||
|
}
|
||||||
|
if (cd == 0)
|
||||||
|
{
|
||||||
|
return ab;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ab == cd)
|
||||||
|
{
|
||||||
|
// Both positive or both negative
|
||||||
|
return ab;
|
||||||
|
}
|
||||||
|
|
||||||
|
// One is positive, one is negative, both are non zero
|
||||||
|
// If ab is positive, we have to judge if a*b > -c*d (then 1 because sum is positive)
|
||||||
|
// If ab is negative, we have to judge if c*d > -a*b (idem)
|
||||||
|
return ab == 1
|
||||||
|
? sign_of_compare(a, b, -c, d)
|
||||||
|
: sign_of_compare(c, d, -a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public :
|
public :
|
||||||
|
|
||||||
// Calculates the side of the intersection-point (if any) of
|
// Calculates the side of the intersection-point (if any) of
|
||||||
// of segment a//b w.r.t. segment c
|
// of segment a//b w.r.t. segment c
|
||||||
// This is calculated without (re)calculating the IP itself again and fully
|
// This is calculated without (re)calculating the IP itself again and fully
|
||||||
// based on integer mathematics
|
// based on integer mathematics
|
||||||
template <typename T, typename Segment>
|
template <typename T, typename Segment, typename Point>
|
||||||
static inline T side_value(Segment const& a, Segment const& b,
|
static inline T side_value(Segment const& a, Segment const& b,
|
||||||
Segment const& c)
|
Segment const& c, Point const& fallback_point)
|
||||||
{
|
{
|
||||||
// The first point of the three segments is reused several times
|
// The first point of the three segments is reused several times
|
||||||
T const ax = get<0, 0>(a);
|
T const ax = get<0, 0>(a);
|
||||||
@ -67,9 +131,15 @@ public :
|
|||||||
if (d == zero)
|
if (d == zero)
|
||||||
{
|
{
|
||||||
// There is no IP of a//b, they are collinear or parallel
|
// There is no IP of a//b, they are collinear or parallel
|
||||||
// We don't have to divide but we can already conclude the side-value
|
// Assuming they intersect (this method should be called for
|
||||||
// is meaningless and the resulting determinant will be 0
|
// segments known to intersect), they are collinear and overlap.
|
||||||
return zero;
|
// They have one or two intersection points - we don't know and
|
||||||
|
// have to rely on the fallback intersection point
|
||||||
|
|
||||||
|
Point c1, c2;
|
||||||
|
geometry::detail::assign_point_from_index<0>(c, c1);
|
||||||
|
geometry::detail::assign_point_from_index<1>(c, c2);
|
||||||
|
return side_by_triangle<>::apply(c1, c2, fallback_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cramer's rule: da (see cart_intersect.hpp)
|
// Cramer's rule: da (see cart_intersect.hpp)
|
||||||
@ -82,7 +152,9 @@ public :
|
|||||||
// IP is at (ax + (da/d) * dx_a, ay + (da/d) * dy_a)
|
// IP is at (ax + (da/d) * dx_a, ay + (da/d) * dy_a)
|
||||||
// Side of IP is w.r.t. c is: determinant(dx_c, dy_c, ipx-cx, ipy-cy)
|
// Side of IP is w.r.t. c is: determinant(dx_c, dy_c, ipx-cx, ipy-cy)
|
||||||
// We replace ipx by expression above and multiply each term by d
|
// We replace ipx by expression above and multiply each term by d
|
||||||
T const result = geometry::detail::determinant<T>
|
|
||||||
|
#ifdef BOOST_GEOMETRY_SIDE_OF_INTERSECTION_DEBUG
|
||||||
|
T const result1 = geometry::detail::determinant<T>
|
||||||
(
|
(
|
||||||
dx_c * d, dy_c * d,
|
dx_c * d, dy_c * d,
|
||||||
d * (ax - cx) + dx_a * da, d * (ay - cy) + dy_a * da
|
d * (ax - cx) + dx_a * da, d * (ay - cy) + dy_a * da
|
||||||
@ -93,15 +165,51 @@ public :
|
|||||||
// Therefore, the sign is always the same as that result, and the
|
// Therefore, the sign is always the same as that result, and the
|
||||||
// resulting side (left,right,collinear) is the same
|
// resulting side (left,right,collinear) is the same
|
||||||
|
|
||||||
|
// The first row we divide again by d because of determinant multiply rule
|
||||||
|
T const result2 = d * geometry::detail::determinant<T>
|
||||||
|
(
|
||||||
|
dx_c, dy_c,
|
||||||
|
d * (ax - cx) + dx_a * da, d * (ay - cy) + dy_a * da
|
||||||
|
);
|
||||||
|
// Write out:
|
||||||
|
T const result3 = d * (dx_c * (d * (ay - cy) + dy_a * da)
|
||||||
|
- dy_c * (d * (ax - cx) + dx_a * da));
|
||||||
|
// Write out in braces:
|
||||||
|
T const result4 = d * (dx_c * d * (ay - cy) + dx_c * dy_a * da
|
||||||
|
- dy_c * d * (ax - cx) - dy_c * dx_a * da);
|
||||||
|
// Write in terms of d * XX + da * YY
|
||||||
|
T const result5 = d * (d * (dx_c * (ay - cy) - dy_c * (ax - cx))
|
||||||
|
+ da * (dx_c * dy_a - dy_c * dx_a));
|
||||||
|
|
||||||
|
//return result;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// We consider the results separately
|
||||||
|
// (in the end we only have to return the side-value 1,0 or -1)
|
||||||
|
|
||||||
|
// To avoid multiplications we judge the product (easy, avoids *d)
|
||||||
|
// and the sign of p*q+r*s (more elaborate)
|
||||||
|
T const result = sign_of_product
|
||||||
|
(
|
||||||
|
d,
|
||||||
|
sign_of_addition_of_two_products
|
||||||
|
(
|
||||||
|
d, dx_c * (ay - cy) - dy_c * (ax - cx),
|
||||||
|
da, dx_c * dy_a - dy_c * dx_a
|
||||||
|
)
|
||||||
|
);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Segment>
|
template <typename Segment, typename Point>
|
||||||
static inline int apply(Segment const& a, Segment const& b, Segment const& c)
|
static inline int apply(Segment const& a, Segment const& b,
|
||||||
|
Segment const& c,
|
||||||
|
Point const& fallback_point)
|
||||||
{
|
{
|
||||||
typedef typename geometry::coordinate_type<Segment>::type coordinate_type;
|
typedef typename geometry::coordinate_type<Segment>::type coordinate_type;
|
||||||
coordinate_type const s = side_value<coordinate_type>(a, b, c);
|
coordinate_type const s = side_value<coordinate_type>(a, b, c, fallback_point);
|
||||||
coordinate_type const zero = coordinate_type();
|
coordinate_type const zero = coordinate_type();
|
||||||
return math::equals(s, zero) ? 0
|
return math::equals(s, zero) ? 0
|
||||||
: s > zero ? 1
|
: s > zero ? 1
|
||||||
|
@ -372,11 +372,16 @@ public :
|
|||||||
typedef typename return_type<Point, PointOfSegment>::type return_type;
|
typedef typename return_type<Point, PointOfSegment>::type return_type;
|
||||||
|
|
||||||
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
|
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
|
||||||
std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " " << crs_AD * geometry::math::r2d << std::endl;
|
std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " "
|
||||||
std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " " << crs_AB * geometry::math::r2d << std::endl;
|
<< crs_AD * geometry::math::r2d<return_type>() << std::endl;
|
||||||
std::cout << "Course " << dsv(sp2) << " to " << dsv(p) << " " << crs_BD * geometry::math::r2d << std::endl;
|
std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " "
|
||||||
std::cout << "Projection AD-AB " << projection1 << " : " << d_crs1 * geometry::math::r2d << std::endl;
|
<< crs_AB * geometry::math::r2d<return_type>() << std::endl;
|
||||||
std::cout << "Projection BD-BA " << projection2 << " : " << d_crs2 * geometry::math::r2d << std::endl;
|
std::cout << "Course " << dsv(sp2) << " to " << dsv(p) << " "
|
||||||
|
<< crs_BD * geometry::math::r2d << std::endl;
|
||||||
|
std::cout << "Projection AD-AB " << projection1 << " : "
|
||||||
|
<< d_crs1 * geometry::math::r2d<return_type>() << std::endl;
|
||||||
|
std::cout << "Projection BD-BA " << projection2 << " : "
|
||||||
|
<< d_crs2 * geometry::math::r2d<return_type>() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// http://williams.best.vwh.net/avform.htm#XTE
|
// http://williams.best.vwh.net/avform.htm#XTE
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
// 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.
|
||||||
|
|
||||||
|
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||||
|
|
||||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||||
@ -28,6 +33,7 @@
|
|||||||
#include <boost/geometry/strategies/transform.hpp>
|
#include <boost/geometry/strategies/transform.hpp>
|
||||||
|
|
||||||
#include <boost/geometry/util/math.hpp>
|
#include <boost/geometry/util/math.hpp>
|
||||||
|
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||||
|
|
||||||
namespace boost { namespace geometry
|
namespace boost { namespace geometry
|
||||||
@ -130,7 +136,15 @@ struct degree_radian_vv
|
|||||||
assert_dimension<P1, 2>();
|
assert_dimension<P1, 2>();
|
||||||
assert_dimension<P2, 2>();
|
assert_dimension<P2, 2>();
|
||||||
|
|
||||||
detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
|
typedef typename promote_floating_point
|
||||||
|
<
|
||||||
|
typename select_coordinate_type<P1, P2>::type
|
||||||
|
>::type calculation_type;
|
||||||
|
|
||||||
|
detail::transform_coordinates
|
||||||
|
<
|
||||||
|
P1, P2, 0, 2, F
|
||||||
|
>::transform(p1, p2, math::d2r<calculation_type>());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -143,7 +157,16 @@ struct degree_radian_vv_3
|
|||||||
assert_dimension<P1, 3>();
|
assert_dimension<P1, 3>();
|
||||||
assert_dimension<P2, 3>();
|
assert_dimension<P2, 3>();
|
||||||
|
|
||||||
detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
|
typedef typename promote_floating_point
|
||||||
|
<
|
||||||
|
typename select_coordinate_type<P1, P2>::type
|
||||||
|
>::type calculation_type;
|
||||||
|
|
||||||
|
detail::transform_coordinates
|
||||||
|
<
|
||||||
|
P1, P2, 0, 2, F
|
||||||
|
>::transform(p1, p2, math::d2r<calculation_type>());
|
||||||
|
|
||||||
// Copy height or other third dimension
|
// Copy height or other third dimension
|
||||||
set<2>(p2, get<2>(p1));
|
set<2>(p2, get<2>(p1));
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||||
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
// 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.
|
||||||
|
|
||||||
|
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||||
|
|
||||||
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
||||||
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
||||||
@ -40,6 +45,7 @@
|
|||||||
#include <boost/geometry/core/coordinate_dimension.hpp>
|
#include <boost/geometry/core/coordinate_dimension.hpp>
|
||||||
#include <boost/geometry/core/cs.hpp>
|
#include <boost/geometry/core/cs.hpp>
|
||||||
#include <boost/geometry/util/math.hpp>
|
#include <boost/geometry/util/math.hpp>
|
||||||
|
#include <boost/geometry/util/promote_floating_point.hpp>
|
||||||
#include <boost/geometry/util/select_coordinate_type.hpp>
|
#include <boost/geometry/util/select_coordinate_type.hpp>
|
||||||
#include <boost/geometry/util/select_most_precise.hpp>
|
#include <boost/geometry/util/select_most_precise.hpp>
|
||||||
|
|
||||||
@ -340,7 +346,8 @@ struct as_radian<degree>
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
static inline T get(T const& value)
|
static inline T get(T const& value)
|
||||||
{
|
{
|
||||||
return value * math::d2r;
|
typedef typename promote_floating_point<T>::type promoted_type;
|
||||||
|
return value * math::d2r<promoted_type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -493,9 +493,20 @@ inline bool larger(T1 const& a, T2 const& b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T d2r()
|
||||||
|
{
|
||||||
|
static T const conversion_coefficient = geometry::math::pi<T>() / T(180.0);
|
||||||
|
return conversion_coefficient;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T r2d()
|
||||||
|
{
|
||||||
|
static T const conversion_coefficient = T(180.0) / geometry::math::pi<T>();
|
||||||
|
return conversion_coefficient;
|
||||||
|
}
|
||||||
|
|
||||||
double const d2r = geometry::math::pi<double>() / 180.0;
|
|
||||||
double const r2d = 1.0 / d2r;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Calculates the haversine of an angle
|
\brief Calculates the haversine of an angle
|
||||||
|
254
include/boost/geometry/util/normalize_spheroidal_coordinates.hpp
Normal file
254
include/boost/geometry/util/normalize_spheroidal_coordinates.hpp
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
|
||||||
|
// Copyright (c) 2015, Oracle and/or its affiliates.
|
||||||
|
|
||||||
|
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||||
|
|
||||||
|
// Licensed under the Boost Software License version 1.0.
|
||||||
|
// http://www.boost.org/users/license.html
|
||||||
|
|
||||||
|
#ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
|
||||||
|
#define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <boost/geometry/core/cs.hpp>
|
||||||
|
#include <boost/geometry/util/math.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace boost { namespace geometry
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace math
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_NO_DETAIL
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
template <typename CoordinateType, typename Units>
|
||||||
|
struct constants_on_spheroid
|
||||||
|
{
|
||||||
|
static inline CoordinateType period()
|
||||||
|
{
|
||||||
|
return math::two_pi<CoordinateType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType half_period()
|
||||||
|
{
|
||||||
|
return math::pi<CoordinateType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType min_longitude()
|
||||||
|
{
|
||||||
|
static CoordinateType const minus_pi = -math::pi<CoordinateType>();
|
||||||
|
return minus_pi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType max_longitude()
|
||||||
|
{
|
||||||
|
return math::pi<CoordinateType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType min_latitude()
|
||||||
|
{
|
||||||
|
static CoordinateType const minus_half_pi
|
||||||
|
= -math::half_pi<CoordinateType>();
|
||||||
|
return minus_half_pi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType max_latitude()
|
||||||
|
{
|
||||||
|
return math::half_pi<CoordinateType>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename CoordinateType>
|
||||||
|
struct constants_on_spheroid<CoordinateType, degree>
|
||||||
|
{
|
||||||
|
static inline CoordinateType period()
|
||||||
|
{
|
||||||
|
return CoordinateType(360.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType half_period()
|
||||||
|
{
|
||||||
|
return CoordinateType(180.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType min_longitude()
|
||||||
|
{
|
||||||
|
return CoordinateType(-180.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType max_longitude()
|
||||||
|
{
|
||||||
|
return CoordinateType(180.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType min_latitude()
|
||||||
|
{
|
||||||
|
return CoordinateType(-90.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType max_latitude()
|
||||||
|
{
|
||||||
|
return CoordinateType(90.0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Units, typename CoordinateType>
|
||||||
|
class normalize_spheroidal_coordinates
|
||||||
|
{
|
||||||
|
typedef constants_on_spheroid<CoordinateType, Units> constants;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static inline CoordinateType normalize_up(CoordinateType const& value)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
math::mod(value + constants::half_period(), constants::period())
|
||||||
|
- constants::half_period();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CoordinateType normalize_down(CoordinateType const& value)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
math::mod(value - constants::half_period(), constants::period())
|
||||||
|
+ constants::half_period();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static inline void apply(CoordinateType& longitude,
|
||||||
|
CoordinateType& latitude,
|
||||||
|
bool normalize_poles = true)
|
||||||
|
{
|
||||||
|
|
||||||
|
// first normalize latitude
|
||||||
|
if (math::larger(latitude, constants::half_period()))
|
||||||
|
{
|
||||||
|
latitude = normalize_up(latitude);
|
||||||
|
}
|
||||||
|
else if (math::smaller(latitude, -constants::half_period()))
|
||||||
|
{
|
||||||
|
latitude = normalize_down(latitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix latitude range
|
||||||
|
if (latitude < constants::min_latitude())
|
||||||
|
{
|
||||||
|
latitude = -constants::half_period() - latitude;
|
||||||
|
longitude -= constants::half_period();
|
||||||
|
}
|
||||||
|
else if (latitude > constants::max_latitude())
|
||||||
|
{
|
||||||
|
latitude = constants::half_period() - latitude;
|
||||||
|
longitude -= constants::half_period();
|
||||||
|
}
|
||||||
|
|
||||||
|
// now normalize longitude
|
||||||
|
if (math::equals(longitude, -constants::half_period())
|
||||||
|
|| math::equals(longitude, constants::half_period()))
|
||||||
|
{
|
||||||
|
longitude = constants::half_period();
|
||||||
|
}
|
||||||
|
else if (longitude > constants::half_period())
|
||||||
|
{
|
||||||
|
longitude = normalize_up(longitude);
|
||||||
|
if (math::equals(longitude, -constants::half_period()))
|
||||||
|
{
|
||||||
|
longitude = constants::half_period();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (longitude < -constants::half_period())
|
||||||
|
{
|
||||||
|
longitude = normalize_down(longitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally normalize poles
|
||||||
|
if (normalize_poles)
|
||||||
|
{
|
||||||
|
if (math::equals(math::abs(latitude), constants::max_latitude()))
|
||||||
|
{
|
||||||
|
// for the north and south pole we set the longitude to 0
|
||||||
|
// (works for both radians and degrees)
|
||||||
|
longitude = CoordinateType(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(! math::larger(constants::min_latitude(), latitude));
|
||||||
|
BOOST_ASSERT(! math::larger(latitude, constants::max_latitude()));
|
||||||
|
|
||||||
|
BOOST_ASSERT(math::smaller(constants::min_longitude(), longitude));
|
||||||
|
BOOST_ASSERT(! math::larger(longitude, constants::max_longitude()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
#endif // DOXYGEN_NO_DETAIL
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Units, typename CoordinateType>
|
||||||
|
inline CoordinateType min_longitude()
|
||||||
|
{
|
||||||
|
return detail::constants_on_spheroid
|
||||||
|
<
|
||||||
|
CoordinateType, Units
|
||||||
|
>::min_longitude();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Units, typename CoordinateType>
|
||||||
|
inline CoordinateType max_longitude()
|
||||||
|
{
|
||||||
|
return detail::constants_on_spheroid
|
||||||
|
<
|
||||||
|
CoordinateType, Units
|
||||||
|
>::max_longitude();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Units, typename CoordinateType>
|
||||||
|
inline CoordinateType min_latitude()
|
||||||
|
{
|
||||||
|
return detail::constants_on_spheroid
|
||||||
|
<
|
||||||
|
CoordinateType, Units
|
||||||
|
>::min_latitude();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Units, typename CoordinateType>
|
||||||
|
inline CoordinateType max_latitude()
|
||||||
|
{
|
||||||
|
return detail::constants_on_spheroid
|
||||||
|
<
|
||||||
|
CoordinateType, Units
|
||||||
|
>::max_latitude();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Short utility to normalize the coordinates on a spheroid
|
||||||
|
\tparam Units The units of the coordindate system in the spheroid
|
||||||
|
\tparam CoordinateType The type of the coordinates
|
||||||
|
\param longitude Longitude
|
||||||
|
\param latitude Latitude
|
||||||
|
\ingroup utility
|
||||||
|
*/
|
||||||
|
template <typename Units, typename CoordinateType>
|
||||||
|
inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
|
||||||
|
CoordinateType& latitude)
|
||||||
|
{
|
||||||
|
detail::normalize_spheroidal_coordinates
|
||||||
|
<
|
||||||
|
Units, CoordinateType
|
||||||
|
>::apply(longitude, latitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace math
|
||||||
|
|
||||||
|
|
||||||
|
}} // namespace boost::geometry
|
||||||
|
|
||||||
|
#endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
|
@ -30,6 +30,7 @@ test-suite boost-geometry-algorithms
|
|||||||
[ run expand.cpp ]
|
[ run expand.cpp ]
|
||||||
[ run expand_on_spheroid.cpp ]
|
[ run expand_on_spheroid.cpp ]
|
||||||
[ run for_each.cpp ]
|
[ run for_each.cpp ]
|
||||||
|
[ run is_convex.cpp ]
|
||||||
[ run is_simple.cpp ]
|
[ run is_simple.cpp ]
|
||||||
[ run is_valid.cpp ]
|
[ run is_valid.cpp ]
|
||||||
[ run is_valid_failure.cpp ]
|
[ run is_valid_failure.cpp ]
|
||||||
|
@ -203,9 +203,10 @@ void test_all()
|
|||||||
double const d15 = 1.5;
|
double const d15 = 1.5;
|
||||||
test_one<linestring, polygon>("mysql_report_2015_03_02c_asym1", mysql_report_2015_03_02c, join_round(7), end_round(7), 39.714, d10, d15);
|
test_one<linestring, polygon>("mysql_report_2015_03_02c_asym1", mysql_report_2015_03_02c, join_round(7), end_round(7), 39.714, d10, d15);
|
||||||
test_one<linestring, polygon>("mysql_report_2015_03_02c_asym2", mysql_report_2015_03_02c, join_round(7), end_round(7), 46.116, d15, d10);
|
test_one<linestring, polygon>("mysql_report_2015_03_02c_asym2", mysql_report_2015_03_02c, join_round(7), end_round(7), 46.116, d15, d10);
|
||||||
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
|
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
double const d100 = 10;
|
double const d100 = 10;
|
||||||
test_one<linestring, polygon>("mysql_report_2015_04_01", mysql_report_2015_04_01, join_round(32), end_round(32), 1.0/*NON ZERO*/, d100);
|
test_one<linestring, polygon>("mysql_report_2015_04_01", mysql_report_2015_04_01, join_round(32), end_round(32), 632.234, d100);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,9 @@ void test_all()
|
|||||||
test_one<multi_linestring_type, polygon>("mikado4_small", mikado4, join_round32, end_flat, 1930.785, 10.0);
|
test_one<multi_linestring_type, polygon>("mikado4_small", mikado4, join_round32, end_flat, 1930.785, 10.0);
|
||||||
|
|
||||||
#ifdef BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS
|
#ifdef BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS
|
||||||
test_one<multi_linestring_type, polygon>("mysql_15_04_10", mysql_15_04_10, join_round32, end_round32, 29151950703.779/*something big*/, 0x98);
|
// Cause of failure: coordinates vary so much that
|
||||||
|
// length = geometry::math::sqrt(dx * dx + dy * dy); returns a value of inf for length
|
||||||
|
test_one<multi_linestring_type, polygon>("mysql_15_04_10", mysql_15_04_10, join_round32, end_round32, 99999.999, 0.98);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ void test_all()
|
|||||||
typedef bg::model::polygon<P, Clockwise> polygon;
|
typedef bg::model::polygon<P, Clockwise> polygon;
|
||||||
typedef bg::model::multi_point<P> multi_point_type;
|
typedef bg::model::multi_point<P> multi_point_type;
|
||||||
|
|
||||||
bg::strategy::buffer::join_miter join_miter;
|
bg::strategy::buffer::join_round join;
|
||||||
bg::strategy::buffer::end_flat end_flat;
|
bg::strategy::buffer::end_flat end_flat;
|
||||||
typedef bg::strategy::buffer::distance_symmetric
|
typedef bg::strategy::buffer::distance_symmetric
|
||||||
<
|
<
|
||||||
@ -40,41 +40,39 @@ void test_all()
|
|||||||
|
|
||||||
double const pi = boost::geometry::math::pi<double>();
|
double const pi = boost::geometry::math::pi<double>();
|
||||||
|
|
||||||
test_one<multi_point_type, polygon>("simplex1", simplex, join_miter, end_flat, 2.0 * pi, 1.0, 1.0);
|
test_one<multi_point_type, polygon>("simplex1", simplex, join, end_flat, 2.0 * pi, 1.0, 1.0);
|
||||||
test_one<multi_point_type, polygon>("simplex2", simplex, join_miter, end_flat, 22.8372, 2.0, 2.0);
|
test_one<multi_point_type, polygon>("simplex2", simplex, join, end_flat, 22.8372, 2.0, 2.0);
|
||||||
test_one<multi_point_type, polygon>("simplex3", simplex, join_miter, end_flat, 44.5692, 3.0, 3.0);
|
test_one<multi_point_type, polygon>("simplex3", simplex, join, end_flat, 44.5692, 3.0, 3.0);
|
||||||
|
|
||||||
test_one<multi_point_type, polygon>("three1", three, join_miter, end_flat, 3.0 * pi, 1.0, 1.0);
|
test_one<multi_point_type, polygon>("three1", three, join, end_flat, 3.0 * pi, 1.0, 1.0);
|
||||||
test_one<multi_point_type, polygon>("three2", three, join_miter, end_flat, 36.7592, 2.0, 2.0);
|
test_one<multi_point_type, polygon>("three2", three, join, end_flat, 36.7592, 2.0, 2.0);
|
||||||
test_one<multi_point_type, polygon>("three19", three, join_miter, end_flat, 33.6914, 1.9, 1.9);
|
test_one<multi_point_type, polygon>("three19", three, join, end_flat, 33.6914, 1.9, 1.9);
|
||||||
test_one<multi_point_type, polygon>("three21", three, join_miter, end_flat, 39.6394, 2.1, 2.1);
|
test_one<multi_point_type, polygon>("three21", three, join, end_flat, 39.6394, 2.1, 2.1);
|
||||||
test_one<multi_point_type, polygon>("three3", three, join_miter, end_flat, 65.533, 3.0, 3.0);
|
test_one<multi_point_type, polygon>("three3", three, join, end_flat, 65.533, 3.0, 3.0);
|
||||||
|
|
||||||
test_one<multi_point_type, polygon>("multipoint_a", multipoint_a, join_miter, end_flat, 2049.98, 14.0, 14.0);
|
|
||||||
test_one<multi_point_type, polygon>("multipoint_b", multipoint_b, join_miter, end_flat, 7109.88, 15.0, 15.0);
|
|
||||||
test_one<multi_point_type, polygon>("multipoint_b1", multipoint_b, join_miter, end_flat, 6911.89, 14.7, 14.7);
|
|
||||||
test_one<multi_point_type, polygon>("multipoint_b2", multipoint_b, join_miter, end_flat, 7174.79, 15.1, 15.1);
|
|
||||||
|
|
||||||
|
test_one<multi_point_type, polygon>("multipoint_a", multipoint_a, join, end_flat, 2049.98, 14.0, 14.0);
|
||||||
|
test_one<multi_point_type, polygon>("multipoint_b", multipoint_b, join, end_flat, 7109.88, 15.0, 15.0);
|
||||||
|
test_one<multi_point_type, polygon>("multipoint_b1", multipoint_b, join, end_flat, 6911.89, 14.7, 14.7);
|
||||||
|
test_one<multi_point_type, polygon>("multipoint_b2", multipoint_b, join, end_flat, 7174.79, 15.1, 15.1);
|
||||||
|
|
||||||
// Grid tests
|
// Grid tests
|
||||||
{
|
{
|
||||||
bg::strategy::buffer::point_square point_strategy;
|
bg::strategy::buffer::point_square point_strategy;
|
||||||
|
|
||||||
|
|
||||||
test_with_custom_strategies<multi_point_type, polygon>("grid_a50",
|
test_with_custom_strategies<multi_point_type, polygon>("grid_a50",
|
||||||
grid_a, join_miter, end_flat,
|
grid_a, join, end_flat,
|
||||||
distance_strategy(0.5), side_strategy, point_strategy, 7.0);
|
distance_strategy(0.5), side_strategy, point_strategy, 7.0);
|
||||||
|
|
||||||
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
test_with_custom_strategies<multi_point_type, polygon>("grid_a54",
|
test_with_custom_strategies<multi_point_type, polygon>("grid_a54",
|
||||||
grid_a, join_miter, end_flat,
|
grid_a, join, end_flat,
|
||||||
distance_strategy(0.54), side_strategy, point_strategy, 99);
|
distance_strategy(0.54), side_strategy, point_strategy, 7.819);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test_with_custom_strategies<multi_point_type, polygon>("mysql_report_2015_02_25_1_800",
|
test_with_custom_strategies<multi_point_type, polygon>("mysql_report_2015_02_25_1_800",
|
||||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
mysql_report_2015_02_25_1, join, end_flat,
|
||||||
distance_strategy(6051788), side_strategy,
|
distance_strategy(6051788), side_strategy,
|
||||||
bg::strategy::buffer::point_circle(800), 115057490003226.125, 1.0);
|
bg::strategy::buffer::point_circle(800), 115057490003226.125, 1.0);
|
||||||
}
|
}
|
||||||
@ -92,7 +90,7 @@ void test_many_points_per_circle()
|
|||||||
typedef bg::model::polygon<P, false> polygon;
|
typedef bg::model::polygon<P, false> polygon;
|
||||||
typedef bg::model::multi_point<P> multi_point_type;
|
typedef bg::model::multi_point<P> multi_point_type;
|
||||||
|
|
||||||
bg::strategy::buffer::join_miter join_miter;
|
bg::strategy::buffer::join_round join;
|
||||||
bg::strategy::buffer::end_flat end_flat;
|
bg::strategy::buffer::end_flat end_flat;
|
||||||
typedef bg::strategy::buffer::distance_symmetric
|
typedef bg::strategy::buffer::distance_symmetric
|
||||||
<
|
<
|
||||||
@ -104,41 +102,62 @@ void test_many_points_per_circle()
|
|||||||
|
|
||||||
double const tolerance = 1.0;
|
double const tolerance = 1.0;
|
||||||
|
|
||||||
|
// Area should be somewhat larger (~>) than pi*distance^2
|
||||||
|
// 6051788: area ~> 115058122875258
|
||||||
|
|
||||||
// Strategies with many points, which are (very) slow in debug mode
|
// Strategies with many points, which are (very) slow in debug mode
|
||||||
test_with_custom_strategies<multi_point_type, polygon>(
|
test_with_custom_strategies<multi_point_type, polygon>(
|
||||||
"mysql_report_2015_02_25_1_8000",
|
"mysql_report_2015_02_25_1_8000",
|
||||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
mysql_report_2015_02_25_1, join, end_flat,
|
||||||
distance_strategy(6051788), side_strategy, point_circle(8000),
|
distance_strategy(6051788), side_strategy, point_circle(8000),
|
||||||
115058661065242.812, tolerance);
|
115058661065242.812, tolerance);
|
||||||
|
|
||||||
test_with_custom_strategies<multi_point_type, polygon>(
|
test_with_custom_strategies<multi_point_type, polygon>(
|
||||||
"mysql_report_2015_02_25_1",
|
"mysql_report_2015_02_25_1",
|
||||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
mysql_report_2015_02_25_1, join, end_flat,
|
||||||
distance_strategy(6051788), side_strategy, point_circle(83585),
|
distance_strategy(6051788), side_strategy, point_circle(83585),
|
||||||
115058672785611.219, tolerance);
|
115058672785611.219, tolerance);
|
||||||
|
|
||||||
// Takes about 20 seconds in release mode
|
// Takes about 7 seconds in release mode
|
||||||
test_with_custom_strategies<multi_point_type, polygon>(
|
test_with_custom_strategies<multi_point_type, polygon>(
|
||||||
"mysql_report_2015_02_25_1_250k",
|
"mysql_report_2015_02_25_1_250k",
|
||||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
mysql_report_2015_02_25_1, join, end_flat,
|
||||||
distance_strategy(6051788), side_strategy, point_circle(250000),
|
distance_strategy(6051788), side_strategy, point_circle(250000),
|
||||||
115058672880671.531, tolerance);
|
115058672880671.531, tolerance);
|
||||||
|
|
||||||
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
|
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_SLOW_TESTS)
|
||||||
// Takes too long, TODO improve turn_in_piece_visitor
|
// Takes about 110 seconds in release mode
|
||||||
test_with_custom_strategies<multi_point_type, polygon>(
|
test_with_custom_strategies<multi_point_type, polygon>(
|
||||||
"mysql_report_2015_02_25_1",
|
"mysql_report_2015_02_25_1_800k",
|
||||||
mysql_report_2015_02_25_1, join_miter, end_flat,
|
mysql_report_2015_02_25_1, join, end_flat,
|
||||||
distance_strategy(6051788), side_strategy, point_circle(800000),
|
distance_strategy(6051788), side_strategy, point_circle(800000),
|
||||||
115058672799999.999, tolerance); // area to be determined
|
115058672871849.219, tolerance);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// 5666962: area ~> 100890546298964
|
||||||
test_with_custom_strategies<multi_point_type, polygon>(
|
test_with_custom_strategies<multi_point_type, polygon>(
|
||||||
"mysql_report_2015_02_25_2",
|
"mysql_report_2015_02_25_2",
|
||||||
mysql_report_2015_02_25_2, join_miter, end_flat,
|
mysql_report_2015_02_25_2, join, end_flat,
|
||||||
distance_strategy(5666962), side_strategy, point_circle(46641),
|
distance_strategy(5666962), side_strategy, point_circle(46641),
|
||||||
100891031341757.344, tolerance);
|
100891031341757.344, tolerance);
|
||||||
|
|
||||||
|
// Multipoint b with large distances/many points
|
||||||
|
// Area ~> pi * 10x
|
||||||
|
test_with_custom_strategies<multi_point_type, polygon>(
|
||||||
|
"multipoint_b_50k",
|
||||||
|
multipoint_b, join, end_flat,
|
||||||
|
distance_strategy(1000000), side_strategy, point_circle(50000),
|
||||||
|
3141871558215.26465, tolerance);
|
||||||
|
|
||||||
|
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_SLOW_TESTS)
|
||||||
|
// Tests optimization min/max radius
|
||||||
|
// Takes about 55 seconds in release mode
|
||||||
|
test_with_custom_strategies<multi_point_type, polygon>(
|
||||||
|
"multipoint_b_500k",
|
||||||
|
multipoint_b, join, end_flat,
|
||||||
|
distance_strategy(10000000), side_strategy, point_circle(500000),
|
||||||
|
314162054419515.562, tolerance);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_main(int, char* [])
|
int test_main(int, char* [])
|
||||||
|
@ -413,7 +413,11 @@ void test_all()
|
|||||||
test_one<multi_polygon_type, polygon_type>("rt_p22", rt_p22, join_miter, end_flat, 26.5711, 1.0);
|
test_one<multi_polygon_type, polygon_type>("rt_p22", rt_p22, join_miter, end_flat, 26.5711, 1.0);
|
||||||
|
|
||||||
test_one<multi_polygon_type, polygon_type>("rt_q1", rt_q1, join_miter, end_flat, 27, 1.0);
|
test_one<multi_polygon_type, polygon_type>("rt_q1", rt_q1, join_miter, end_flat, 27, 1.0);
|
||||||
|
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
// Fails because all IP's on external borders are now selectable, two are on top of each other
|
||||||
|
// and this should be fixed differently
|
||||||
test_one<multi_polygon_type, polygon_type>("rt_q2", rt_q2, join_miter, end_flat, 26.4853, 1.0);
|
test_one<multi_polygon_type, polygon_type>("rt_q2", rt_q2, join_miter, end_flat, 26.4853, 1.0);
|
||||||
|
#endif
|
||||||
test_one<multi_polygon_type, polygon_type>("rt_q2", rt_q2, join_miter, end_flat, 0.9697, -0.25);
|
test_one<multi_polygon_type, polygon_type>("rt_q2", rt_q2, join_miter, end_flat, 0.9697, -0.25);
|
||||||
|
|
||||||
test_one<multi_polygon_type, polygon_type>("rt_r", rt_r, join_miter, end_flat, 21.0761, 1.0);
|
test_one<multi_polygon_type, polygon_type>("rt_r", rt_r, join_miter, end_flat, 21.0761, 1.0);
|
||||||
@ -449,8 +453,8 @@ void test_all()
|
|||||||
test_one<multi_polygon_type, polygon_type>("rt_u11_50", rt_u11, join_miter, end_flat, 0.04289, -0.50);
|
test_one<multi_polygon_type, polygon_type>("rt_u11_50", rt_u11, join_miter, end_flat, 0.04289, -0.50);
|
||||||
test_one<multi_polygon_type, polygon_type>("rt_u11_25", rt_u11, join_miter, end_flat, 10.1449, -0.25);
|
test_one<multi_polygon_type, polygon_type>("rt_u11_25", rt_u11, join_miter, end_flat, 10.1449, -0.25);
|
||||||
|
|
||||||
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
|
#if defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
test_one<multi_polygon_type, polygon_type>("rt_u12", rt_u12, join_miter, end_flat, 999, 1.0);
|
test_one<multi_polygon_type, polygon_type>("rt_u12", rt_u12, join_miter, end_flat, 142.1348, 1.0);
|
||||||
test_one<multi_polygon_type, polygon_type>("rt_u13", rt_u13, join_miter, end_flat, 115.4853, 1.0);
|
test_one<multi_polygon_type, polygon_type>("rt_u13", rt_u13, join_miter, end_flat, 115.4853, 1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
// Unit Test
|
// Unit Test Helper
|
||||||
|
|
||||||
// Copyright (c) 2010-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
// Copyright (c) 2010-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
// Use, modification and distribution is subject to the Boost Software License,
|
// Use, modification and distribution is subject to the Boost Software License,
|
||||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@ -10,29 +10,18 @@
|
|||||||
#ifndef BOOST_GEOMETRY_TEST_BUFFER_HPP
|
#ifndef BOOST_GEOMETRY_TEST_BUFFER_HPP
|
||||||
#define BOOST_GEOMETRY_TEST_BUFFER_HPP
|
#define BOOST_GEOMETRY_TEST_BUFFER_HPP
|
||||||
|
|
||||||
|
#if defined(TEST_WITH_SVG)
|
||||||
|
// Define before including any buffer headerfile
|
||||||
|
#define BOOST_GEOMETRY_BUFFER_USE_HELPER_POINTS
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
#if defined(TEST_WITH_SVG)
|
|
||||||
#define BOOST_GEOMETRY_BUFFER_USE_HELPER_POINTS
|
|
||||||
|
|
||||||
// Uncomment next lines if you want to have a zoomed view
|
|
||||||
// #define BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
|
||||||
|
|
||||||
// If possible define box before including this unit with the right view
|
|
||||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
|
||||||
# ifndef BOOST_GEOMETRY_BUFFER_TEST_SVG_ALTERNATE_BOX
|
|
||||||
# define BOOST_GEOMETRY_BUFFER_TEST_SVG_ALTERNATE_BOX "BOX(0 0,100 100)"
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TEST_WITH_SVG
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <geometry_test_common.hpp>
|
#include <geometry_test_common.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include <boost/geometry/algorithms/envelope.hpp>
|
#include <boost/geometry/algorithms/envelope.hpp>
|
||||||
#include <boost/geometry/algorithms/area.hpp>
|
#include <boost/geometry/algorithms/area.hpp>
|
||||||
#include <boost/geometry/algorithms/buffer.hpp>
|
#include <boost/geometry/algorithms/buffer.hpp>
|
||||||
@ -57,296 +46,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#if defined(TEST_WITH_SVG)
|
#if defined(TEST_WITH_SVG)
|
||||||
|
# include <test_buffer_svg.hpp>
|
||||||
#include <boost/geometry/io/svg/svg_mapper.hpp>
|
# include <test_buffer_svg_per_turn.hpp>
|
||||||
|
|
||||||
|
|
||||||
inline char piece_type_char(bg::strategy::buffer::piece_type const& type)
|
|
||||||
{
|
|
||||||
using namespace bg::strategy::buffer;
|
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
case buffered_segment : return 's';
|
|
||||||
case buffered_join : return 'j';
|
|
||||||
case buffered_round_end : return 'r';
|
|
||||||
case buffered_flat_end : return 'f';
|
|
||||||
case buffered_point : return 'p';
|
|
||||||
case buffered_concave : return 'c';
|
|
||||||
default : return '?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Geometry, typename Mapper, typename RescalePolicy>
|
|
||||||
void post_map(Geometry const& geometry, Mapper& mapper, RescalePolicy const& rescale_policy)
|
|
||||||
{
|
|
||||||
typedef typename bg::point_type<Geometry>::type point_type;
|
|
||||||
typedef bg::detail::overlay::turn_info
|
|
||||||
<
|
|
||||||
point_type,
|
|
||||||
typename bg::segment_ratio_type<point_type, RescalePolicy>::type
|
|
||||||
> turn_info;
|
|
||||||
|
|
||||||
std::vector<turn_info> turns;
|
|
||||||
|
|
||||||
bg::detail::self_get_turn_points::no_interrupt_policy policy;
|
|
||||||
bg::self_turns
|
|
||||||
<
|
|
||||||
bg::detail::overlay::assign_null_policy
|
|
||||||
>(geometry, rescale_policy, turns, policy);
|
|
||||||
|
|
||||||
BOOST_FOREACH(turn_info const& turn, turns)
|
|
||||||
{
|
|
||||||
mapper.map(turn.point, "fill:rgb(255,128,0);stroke:rgb(0,0,100);stroke-width:1", 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename SvgMapper, typename Box, typename Tag>
|
|
||||||
struct svg_visitor
|
|
||||||
{
|
|
||||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
|
||||||
Box m_alternate_box;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class si
|
|
||||||
{
|
|
||||||
private :
|
|
||||||
bg::segment_identifier m_id;
|
|
||||||
|
|
||||||
public :
|
|
||||||
inline si(bg::segment_identifier const& id)
|
|
||||||
: m_id(id)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template <typename Char, typename Traits>
|
|
||||||
inline friend std::basic_ostream<Char, Traits>& operator<<(
|
|
||||||
std::basic_ostream<Char, Traits>& os,
|
|
||||||
si const& s)
|
|
||||||
{
|
|
||||||
os << s.m_id.multi_index << "." << s.m_id.segment_index;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
SvgMapper& m_mapper;
|
|
||||||
|
|
||||||
svg_visitor(SvgMapper& mapper)
|
|
||||||
: m_mapper(mapper)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template <typename Turns>
|
|
||||||
inline void map_turns(Turns const& turns, bool label_good_turns, bool label_wrong_turns)
|
|
||||||
{
|
|
||||||
namespace bgdb = boost::geometry::detail::buffer;
|
|
||||||
typedef typename boost::range_value<Turns const>::type turn_type;
|
|
||||||
typedef typename turn_type::point_type point_type;
|
|
||||||
typedef typename turn_type::robust_point_type robust_point_type;
|
|
||||||
|
|
||||||
std::map<robust_point_type, int, bg::less<robust_point_type> > offsets;
|
|
||||||
|
|
||||||
for (typename boost::range_iterator<Turns const>::type it =
|
|
||||||
boost::begin(turns); it != boost::end(turns); ++it)
|
|
||||||
{
|
|
||||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
|
||||||
if (bg::disjoint(it->point, m_alternate_box))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool is_good = true;
|
|
||||||
char color = 'g';
|
|
||||||
std::string fill = "fill:rgb(0,255,0);";
|
|
||||||
switch(it->location)
|
|
||||||
{
|
|
||||||
case bgdb::inside_buffer :
|
|
||||||
fill = "fill:rgb(255,0,0);";
|
|
||||||
color = 'r';
|
|
||||||
is_good = false;
|
|
||||||
break;
|
|
||||||
case bgdb::location_discard :
|
|
||||||
fill = "fill:rgb(0,0,255);";
|
|
||||||
color = 'b';
|
|
||||||
is_good = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!it->selectable_start)
|
|
||||||
{
|
|
||||||
fill = "fill:rgb(255,192,0);";
|
|
||||||
color = 'o'; // orange
|
|
||||||
}
|
|
||||||
if (it->blocked())
|
|
||||||
{
|
|
||||||
fill = "fill:rgb(128,128,128);";
|
|
||||||
color = '-';
|
|
||||||
is_good = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fill += "fill-opacity:0.7;";
|
|
||||||
|
|
||||||
m_mapper.map(it->point, fill, 4);
|
|
||||||
|
|
||||||
if ((label_good_turns && is_good) || (label_wrong_turns && ! is_good))
|
|
||||||
{
|
|
||||||
std::ostringstream out;
|
|
||||||
out << it->turn_index
|
|
||||||
<< " " << it->operations[0].piece_index << "/" << it->operations[1].piece_index
|
|
||||||
<< " " << si(it->operations[0].seg_id) << "/" << si(it->operations[1].seg_id)
|
|
||||||
|
|
||||||
// If you want to see travel information
|
|
||||||
<< std::endl
|
|
||||||
<< " nxt " << it->operations[0].enriched.travels_to_ip_index
|
|
||||||
<< "/" << it->operations[1].enriched.travels_to_ip_index
|
|
||||||
<< " or " << it->operations[0].enriched.next_ip_index
|
|
||||||
<< "/" << it->operations[1].enriched.next_ip_index
|
|
||||||
//<< " frac " << it->operations[0].fraction
|
|
||||||
|
|
||||||
// If you want to see robust-point coordinates (e.g. to find duplicates)
|
|
||||||
// << std::endl
|
|
||||||
// << " " << bg::get<0>(it->robust_point) << " , " << bg::get<1>(it->robust_point)
|
|
||||||
|
|
||||||
<< std::endl;
|
|
||||||
out << " " << bg::method_char(it->method)
|
|
||||||
<< ":" << bg::operation_char(it->operations[0].operation)
|
|
||||||
<< "/" << bg::operation_char(it->operations[1].operation);
|
|
||||||
out << " "
|
|
||||||
<< (it->count_on_offsetted > 0 ? "b" : "") // b: offsetted border
|
|
||||||
<< (it->count_within_near_offsetted > 0 ? "n" : "")
|
|
||||||
<< (it->count_within > 0 ? "w" : "")
|
|
||||||
<< (it->count_on_helper > 0 ? "h" : "")
|
|
||||||
<< (it->count_on_multi > 0 ? "m" : "")
|
|
||||||
;
|
|
||||||
|
|
||||||
offsets[it->get_robust_point()] += 10;
|
|
||||||
int offset = offsets[it->get_robust_point()];
|
|
||||||
|
|
||||||
m_mapper.text(it->point, out.str(), "fill:rgb(0,0,0);font-family='Arial';font-size:9px;", 5, offset);
|
|
||||||
|
|
||||||
offsets[it->get_robust_point()] += 25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Pieces, typename OffsettedRings>
|
|
||||||
inline void map_pieces(Pieces const& pieces,
|
|
||||||
OffsettedRings const& offsetted_rings,
|
|
||||||
bool do_pieces, bool do_indices)
|
|
||||||
{
|
|
||||||
typedef typename boost::range_value<Pieces const>::type piece_type;
|
|
||||||
typedef typename boost::range_value<OffsettedRings const>::type ring_type;
|
|
||||||
|
|
||||||
for(typename boost::range_iterator<Pieces const>::type it = boost::begin(pieces);
|
|
||||||
it != boost::end(pieces);
|
|
||||||
++it)
|
|
||||||
{
|
|
||||||
const piece_type& piece = *it;
|
|
||||||
bg::segment_identifier seg_id = piece.first_seg_id;
|
|
||||||
if (seg_id.segment_index < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ring_type corner;
|
|
||||||
|
|
||||||
|
|
||||||
ring_type const& ring = offsetted_rings[seg_id.multi_index];
|
|
||||||
|
|
||||||
std::copy(boost::begin(ring) + seg_id.segment_index,
|
|
||||||
boost::begin(ring) + piece.last_segment_index,
|
|
||||||
std::back_inserter(corner));
|
|
||||||
std::copy(boost::begin(piece.helper_points),
|
|
||||||
boost::end(piece.helper_points),
|
|
||||||
std::back_inserter(corner));
|
|
||||||
|
|
||||||
if (corner.empty())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
|
||||||
if (bg::disjoint(corner, m_alternate_box))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (do_pieces)
|
|
||||||
{
|
|
||||||
std::string style = "opacity:0.3;stroke:rgb(0,0,0);stroke-width:1;";
|
|
||||||
m_mapper.map(corner,
|
|
||||||
piece.type == bg::strategy::buffer::buffered_segment
|
|
||||||
? style + "fill:rgb(255,128,0);"
|
|
||||||
: style + "fill:rgb(255,0,0);");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (do_indices)
|
|
||||||
{
|
|
||||||
// Label starting piece_index / segment_index
|
|
||||||
typedef typename bg::point_type<ring_type>::type point_type;
|
|
||||||
|
|
||||||
std::ostringstream out;
|
|
||||||
out << piece.index << " (" << piece_type_char(piece.type) << ") " << piece.first_seg_id.segment_index << ".." << piece.last_segment_index - 1;
|
|
||||||
point_type label_point = bg::return_centroid<point_type>(corner);
|
|
||||||
|
|
||||||
if ((piece.type == bg::strategy::buffer::buffered_concave
|
|
||||||
|| piece.type == bg::strategy::buffer::buffered_flat_end)
|
|
||||||
&& corner.size() >= 2u)
|
|
||||||
{
|
|
||||||
bg::set<0>(label_point, (bg::get<0>(corner[0]) + bg::get<0>(corner[1])) / 2.0);
|
|
||||||
bg::set<1>(label_point, (bg::get<1>(corner[0]) + bg::get<1>(corner[1])) / 2.0);
|
|
||||||
}
|
|
||||||
m_mapper.text(label_point, out.str(), "fill:rgb(255,0,0);font-family='Arial';font-size:10px;", 5, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TraversedRings>
|
|
||||||
inline void map_traversed_rings(TraversedRings const& traversed_rings)
|
|
||||||
{
|
|
||||||
for(typename boost::range_iterator<TraversedRings const>::type it
|
|
||||||
= boost::begin(traversed_rings); it != boost::end(traversed_rings); ++it)
|
|
||||||
{
|
|
||||||
m_mapper.map(*it, "opacity:0.4;fill:none;stroke:rgb(0,255,0);stroke-width:2");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OffsettedRings>
|
|
||||||
inline void map_offsetted_rings(OffsettedRings const& offsetted_rings)
|
|
||||||
{
|
|
||||||
for(typename boost::range_iterator<OffsettedRings const>::type it
|
|
||||||
= boost::begin(offsetted_rings); it != boost::end(offsetted_rings); ++it)
|
|
||||||
{
|
|
||||||
if (it->discarded())
|
|
||||||
{
|
|
||||||
m_mapper.map(*it, "opacity:0.4;fill:none;stroke:rgb(255,0,0);stroke-width:2");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_mapper.map(*it, "opacity:0.4;fill:none;stroke:rgb(0,0,255);stroke-width:2");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename PieceCollection>
|
|
||||||
inline void apply(PieceCollection const& collection, int phase)
|
|
||||||
{
|
|
||||||
// Comment next return if you want to see pieces, turns, etc.
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(phase == 0)
|
|
||||||
{
|
|
||||||
map_pieces(collection.m_pieces, collection.offsetted_rings, true, true);
|
|
||||||
map_turns(collection.m_turns, true, false);
|
|
||||||
}
|
|
||||||
#if !defined(BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX)
|
|
||||||
if (phase == 1)
|
|
||||||
{
|
|
||||||
// map_traversed_rings(collection.traversed_rings);
|
|
||||||
// map_offsetted_rings(collection.offsetted_rings);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -472,40 +173,25 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
|||||||
|
|
||||||
//std::cout << complete.str() << std::endl;
|
//std::cout << complete.str() << std::endl;
|
||||||
|
|
||||||
|
#if defined(TEST_WITH_SVG_PER_TURN)
|
||||||
|
save_turns_visitor<point_type> visitor;
|
||||||
|
#elif defined(TEST_WITH_SVG)
|
||||||
|
|
||||||
|
buffer_svg_mapper<point_type> buffer_mapper(complete.str());
|
||||||
|
|
||||||
std::ostringstream filename;
|
std::ostringstream filename;
|
||||||
filename << "buffer_" << complete.str() << ".svg";
|
filename << "buffer_" << complete.str() << ".svg";
|
||||||
|
|
||||||
#if defined(TEST_WITH_SVG)
|
|
||||||
std::ofstream svg(filename.str().c_str());
|
std::ofstream svg(filename.str().c_str());
|
||||||
typedef bg::svg_mapper<point_type> mapper_type;
|
typedef bg::svg_mapper<point_type> mapper_type;
|
||||||
mapper_type mapper(svg, 1000, 1000);
|
mapper_type mapper(svg, 1000, 800);
|
||||||
|
|
||||||
svg_visitor<mapper_type, bg::model::box<point_type>, tag> visitor(mapper);
|
svg_visitor<mapper_type, bg::model::box<point_type> > visitor(mapper);
|
||||||
|
|
||||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
|
||||||
// Create a zoomed-in view
|
|
||||||
bg::model::box<point_type> alternate_box;
|
|
||||||
bg::read_wkt(BOOST_GEOMETRY_BUFFER_TEST_SVG_ALTERNATE_BOX, alternate_box);
|
|
||||||
mapper.add(alternate_box);
|
|
||||||
|
|
||||||
// Take care non-visible elements are skipped
|
|
||||||
visitor.m_alternate_box = alternate_box;
|
|
||||||
#else
|
|
||||||
|
|
||||||
{
|
|
||||||
bg::model::box<point_type> box = envelope;
|
|
||||||
if (distance_strategy.negative())
|
|
||||||
{
|
|
||||||
bg::buffer(box, box, 1.0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bg::buffer(box, box, 1.1 * distance_strategy.max_distance(join_strategy, end_strategy));
|
|
||||||
}
|
|
||||||
mapper.add(box);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
buffer_mapper.prepare(mapper, visitor, envelope,
|
||||||
|
distance_strategy.negative()
|
||||||
|
? 1.0
|
||||||
|
: 1.1 * distance_strategy.max_distance(join_strategy, end_strategy)
|
||||||
|
);
|
||||||
#else
|
#else
|
||||||
bg::detail::buffer::visit_pieces_default_policy visitor;
|
bg::detail::buffer::visit_pieces_default_policy visitor;
|
||||||
#endif
|
#endif
|
||||||
@ -557,14 +243,22 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
|||||||
|
|
||||||
if (check_self_intersections)
|
if (check_self_intersections)
|
||||||
{
|
{
|
||||||
// Be sure resulting polygon does not contain
|
try
|
||||||
// self-intersections
|
{
|
||||||
BOOST_CHECK_MESSAGE
|
bool has_self_ips = bg::detail::overlay::has_self_intersections(buffered,
|
||||||
(
|
rescale_policy, false);
|
||||||
! bg::detail::overlay::has_self_intersections(buffered,
|
// Be sure resulting polygon does not contain
|
||||||
rescale_policy, false),
|
// self-intersections
|
||||||
complete.str() << " output is self-intersecting. "
|
BOOST_CHECK_MESSAGE
|
||||||
);
|
(
|
||||||
|
! has_self_ips,
|
||||||
|
complete.str() << " output is self-intersecting. "
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
BOOST_MESSAGE("Exception in checking self-intersections");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,48 +273,28 @@ void test_buffer(std::string const& caseid, Geometry const& geometry,
|
|||||||
// BOOST_CHECK_MESSAGE(bg::intersects(buffered) == false, complete.str() << " intersects");
|
// BOOST_CHECK_MESSAGE(bg::intersects(buffered) == false, complete.str() << " intersects");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(TEST_WITH_SVG)
|
#if defined(TEST_WITH_SVG_PER_TURN)
|
||||||
bool const areal = boost::is_same
|
|
||||||
<
|
|
||||||
typename bg::tag_cast<tag, bg::areal_tag>::type, bg::areal_tag
|
|
||||||
>::type::value;
|
|
||||||
|
|
||||||
// Map input geometry in green
|
|
||||||
if (areal)
|
|
||||||
{
|
{
|
||||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX_FOR_INPUT
|
// Create a per turn visitor to map per turn, and buffer again with it
|
||||||
// Assuming input is areal
|
per_turn_visitor<point_type> ptv(complete.str(), visitor.get_points());
|
||||||
bg::model::multi_polygon<GeometryOut> clipped;
|
bg::detail::buffer::buffer_inserter<GeometryOut>(geometry,
|
||||||
bg::intersection(geometry, alternate_box, clipped);
|
std::back_inserter(buffered),
|
||||||
mapper.map(clipped, "opacity:0.5;fill:rgb(0,128,0);stroke:rgb(0,64,0);stroke-width:2");
|
distance_strategy,
|
||||||
#else
|
side_strategy,
|
||||||
mapper.map(geometry, "opacity:0.5;fill:rgb(0,128,0);stroke:rgb(0,64,0);stroke-width:2");
|
join_strategy,
|
||||||
|
end_strategy,
|
||||||
|
point_strategy,
|
||||||
|
rescale_policy,
|
||||||
|
ptv);
|
||||||
|
ptv.map_input_output(geometry, buffered, distance_strategy.negative());
|
||||||
|
// self_ips NYI here
|
||||||
|
}
|
||||||
|
#elif defined(TEST_WITH_SVG)
|
||||||
|
buffer_mapper.map_input_output(mapper, geometry, buffered, distance_strategy.negative());
|
||||||
|
buffer_mapper.map_self_ips(mapper, buffered, rescale_policy);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: clip input points/linestring
|
|
||||||
mapper.map(geometry, "opacity:0.5;stroke:rgb(0,128,0);stroke-width:10");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Map buffer in yellow (inflate) and with orange-dots (deflate)
|
|
||||||
std::string style = distance_strategy.negative()
|
|
||||||
? "opacity:0.4;fill:rgb(255,255,192);stroke:rgb(255,128,0);stroke-width:3"
|
|
||||||
: "opacity:0.4;fill:rgb(255,255,128);stroke:rgb(0,0,0);stroke-width:3";
|
|
||||||
|
|
||||||
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
|
||||||
// Clip output multi-polygon with box
|
|
||||||
bg::model::multi_polygon<GeometryOut> clipped;
|
|
||||||
bg::intersection(buffered, alternate_box, clipped);
|
|
||||||
mapper.map(clipped, style);
|
|
||||||
#else
|
|
||||||
mapper.map(buffered, style);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
post_map(buffered, mapper, rescale_policy);
|
|
||||||
#endif // TEST_WITH_SVG
|
|
||||||
|
|
||||||
|
// Check for self-intersections
|
||||||
if (self_ip_count != NULL)
|
if (self_ip_count != NULL)
|
||||||
{
|
{
|
||||||
std::size_t count = 0;
|
std::size_t count = 0;
|
||||||
|
468
test/algorithms/buffer/test_buffer_svg.hpp
Normal file
468
test/algorithms/buffer/test_buffer_svg.hpp
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
// Unit Test Helper
|
||||||
|
|
||||||
|
// Copyright (c) 2010-2015 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_BUFFER_SVG_HPP
|
||||||
|
#define BOOST_GEOMETRY_TEST_BUFFER_SVG_HPP
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
// Uncomment next lines if you want to have a zoomed view
|
||||||
|
//#define BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
||||||
|
|
||||||
|
// If possible define box before including this unit with the right view
|
||||||
|
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
||||||
|
# ifndef BOOST_GEOMETRY_BUFFER_TEST_SVG_ALTERNATE_BOX
|
||||||
|
# define BOOST_GEOMETRY_BUFFER_TEST_SVG_ALTERNATE_BOX "BOX(0 0,100 100)"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/geometry/io/svg/svg_mapper.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
inline char piece_type_char(bg::strategy::buffer::piece_type const& type)
|
||||||
|
{
|
||||||
|
using namespace bg::strategy::buffer;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case buffered_segment : return 's';
|
||||||
|
case buffered_join : return 'j';
|
||||||
|
case buffered_round_end : return 'r';
|
||||||
|
case buffered_flat_end : return 'f';
|
||||||
|
case buffered_point : return 'p';
|
||||||
|
case buffered_concave : return 'c';
|
||||||
|
default : return '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename SvgMapper, typename Box>
|
||||||
|
class svg_visitor
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
svg_visitor(SvgMapper& mapper)
|
||||||
|
: m_mapper(mapper)
|
||||||
|
, m_zoom(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void set_alternate_box(Box const& box)
|
||||||
|
{
|
||||||
|
m_alternate_box = box;
|
||||||
|
m_zoom = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PieceCollection>
|
||||||
|
inline void apply(PieceCollection const& collection, int phase)
|
||||||
|
{
|
||||||
|
// Comment next return if you want to see pieces, turns, etc.
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(phase == 0)
|
||||||
|
{
|
||||||
|
map_pieces(collection.m_pieces, collection.offsetted_rings, true, true);
|
||||||
|
map_turns(collection.m_turns, true, false);
|
||||||
|
}
|
||||||
|
if (phase == 1 && ! m_zoom)
|
||||||
|
{
|
||||||
|
// map_traversed_rings(collection.traversed_rings);
|
||||||
|
// map_offsetted_rings(collection.offsetted_rings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private :
|
||||||
|
class si
|
||||||
|
{
|
||||||
|
private :
|
||||||
|
bg::segment_identifier m_id;
|
||||||
|
|
||||||
|
public :
|
||||||
|
inline si(bg::segment_identifier const& id)
|
||||||
|
: m_id(id)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename Char, typename Traits>
|
||||||
|
inline friend std::basic_ostream<Char, Traits>& operator<<(
|
||||||
|
std::basic_ostream<Char, Traits>& os,
|
||||||
|
si const& s)
|
||||||
|
{
|
||||||
|
os << s.m_id.multi_index << "." << s.m_id.segment_index;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Turns>
|
||||||
|
inline void map_turns(Turns const& turns, bool label_good_turns, bool label_wrong_turns)
|
||||||
|
{
|
||||||
|
namespace bgdb = boost::geometry::detail::buffer;
|
||||||
|
typedef typename boost::range_value<Turns const>::type turn_type;
|
||||||
|
typedef typename turn_type::point_type point_type;
|
||||||
|
typedef typename turn_type::robust_point_type robust_point_type;
|
||||||
|
|
||||||
|
std::map<robust_point_type, int, bg::less<robust_point_type> > offsets;
|
||||||
|
|
||||||
|
for (typename boost::range_iterator<Turns const>::type it =
|
||||||
|
boost::begin(turns); it != boost::end(turns); ++it)
|
||||||
|
{
|
||||||
|
if (m_zoom && bg::disjoint(it->point, m_alternate_box))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_good = true;
|
||||||
|
char color = 'g';
|
||||||
|
std::string fill = "fill:rgb(0,255,0);";
|
||||||
|
switch(it->location)
|
||||||
|
{
|
||||||
|
case bgdb::inside_buffer :
|
||||||
|
fill = "fill:rgb(255,0,0);";
|
||||||
|
color = 'r';
|
||||||
|
is_good = false;
|
||||||
|
break;
|
||||||
|
case bgdb::location_discard :
|
||||||
|
fill = "fill:rgb(0,0,255);";
|
||||||
|
color = 'b';
|
||||||
|
is_good = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!it->selectable_start)
|
||||||
|
{
|
||||||
|
fill = "fill:rgb(255,192,0);";
|
||||||
|
color = 'o'; // orange
|
||||||
|
}
|
||||||
|
if (it->blocked())
|
||||||
|
{
|
||||||
|
fill = "fill:rgb(128,128,128);";
|
||||||
|
color = '-';
|
||||||
|
is_good = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fill += "fill-opacity:0.7;";
|
||||||
|
|
||||||
|
m_mapper.map(it->point, fill, 4);
|
||||||
|
|
||||||
|
if ((label_good_turns && is_good) || (label_wrong_turns && ! is_good))
|
||||||
|
{
|
||||||
|
std::ostringstream out;
|
||||||
|
out << it->turn_index
|
||||||
|
<< " " << it->operations[0].piece_index << "/" << it->operations[1].piece_index
|
||||||
|
<< " " << si(it->operations[0].seg_id) << "/" << si(it->operations[1].seg_id)
|
||||||
|
|
||||||
|
// If you want to see travel information
|
||||||
|
<< std::endl
|
||||||
|
<< " nxt " << it->operations[0].enriched.travels_to_ip_index
|
||||||
|
<< "/" << it->operations[1].enriched.travels_to_ip_index
|
||||||
|
<< " or " << it->operations[0].enriched.next_ip_index
|
||||||
|
<< "/" << it->operations[1].enriched.next_ip_index
|
||||||
|
//<< " frac " << it->operations[0].fraction
|
||||||
|
|
||||||
|
// If you want to see robust-point coordinates (e.g. to find duplicates)
|
||||||
|
// << std::endl
|
||||||
|
// << " " << bg::get<0>(it->robust_point) << " , " << bg::get<1>(it->robust_point)
|
||||||
|
|
||||||
|
<< std::endl;
|
||||||
|
out << " " << bg::method_char(it->method)
|
||||||
|
<< ":" << bg::operation_char(it->operations[0].operation)
|
||||||
|
<< "/" << bg::operation_char(it->operations[1].operation);
|
||||||
|
out << " "
|
||||||
|
<< (it->count_on_offsetted > 0 ? "b" : "") // b: offsetted border
|
||||||
|
#if ! defined(BOOST_GEOMETRY_BUFFER_USE_SIDE_OF_INTERSECTION)
|
||||||
|
<< (it->count_within_near_offsetted > 0 ? "n" : "")
|
||||||
|
#endif
|
||||||
|
<< (it->count_within > 0 ? "w" : "")
|
||||||
|
<< (it->count_on_helper > 0 ? "h" : "")
|
||||||
|
<< (it->count_on_multi > 0 ? "m" : "")
|
||||||
|
;
|
||||||
|
|
||||||
|
offsets[it->get_robust_point()] += 10;
|
||||||
|
int offset = offsets[it->get_robust_point()];
|
||||||
|
|
||||||
|
m_mapper.text(it->point, out.str(), "fill:rgb(0,0,0);font-family='Arial';font-size:9px;", 5, offset);
|
||||||
|
|
||||||
|
offsets[it->get_robust_point()] += 25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Pieces, typename OffsettedRings>
|
||||||
|
inline void map_pieces(Pieces const& pieces,
|
||||||
|
OffsettedRings const& offsetted_rings,
|
||||||
|
bool do_pieces, bool do_indices)
|
||||||
|
{
|
||||||
|
typedef typename boost::range_value<Pieces const>::type piece_type;
|
||||||
|
typedef typename boost::range_value<OffsettedRings const>::type ring_type;
|
||||||
|
|
||||||
|
for(typename boost::range_iterator<Pieces const>::type it = boost::begin(pieces);
|
||||||
|
it != boost::end(pieces);
|
||||||
|
++it)
|
||||||
|
{
|
||||||
|
const piece_type& piece = *it;
|
||||||
|
bg::segment_identifier seg_id = piece.first_seg_id;
|
||||||
|
if (seg_id.segment_index < 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ring_type corner;
|
||||||
|
|
||||||
|
|
||||||
|
ring_type const& ring = offsetted_rings[seg_id.multi_index];
|
||||||
|
|
||||||
|
std::copy(boost::begin(ring) + seg_id.segment_index,
|
||||||
|
boost::begin(ring) + piece.last_segment_index,
|
||||||
|
std::back_inserter(corner));
|
||||||
|
std::copy(boost::begin(piece.helper_points),
|
||||||
|
boost::end(piece.helper_points),
|
||||||
|
std::back_inserter(corner));
|
||||||
|
|
||||||
|
if (corner.empty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m_zoom && bg::disjoint(corner, m_alternate_box))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_zoom && do_pieces)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::string style = "opacity:0.3;stroke:rgb(0,0,0);stroke-width:1;";
|
||||||
|
typedef typename bg::point_type<Box>::type point_type;
|
||||||
|
bg::model::multi_polygon<bg::model::polygon<point_type> > clipped;
|
||||||
|
bg::intersection(ring, m_alternate_box, clipped);
|
||||||
|
m_mapper.map(clipped,
|
||||||
|
piece.type == bg::strategy::buffer::buffered_segment
|
||||||
|
? style + "fill:rgb(255,128,0);"
|
||||||
|
: style + "fill:rgb(255,0,0);");
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cout << "Error for piece " << piece.index << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (do_pieces)
|
||||||
|
{
|
||||||
|
std::string style = "opacity:0.3;stroke:rgb(0,0,0);stroke-width:1;";
|
||||||
|
m_mapper.map(corner,
|
||||||
|
piece.type == bg::strategy::buffer::buffered_segment
|
||||||
|
? style + "fill:rgb(255,128,0);"
|
||||||
|
: style + "fill:rgb(255,0,0);");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_indices)
|
||||||
|
{
|
||||||
|
// Label starting piece_index / segment_index
|
||||||
|
typedef typename bg::point_type<ring_type>::type point_type;
|
||||||
|
|
||||||
|
std::ostringstream out;
|
||||||
|
out << piece.index << " (" << piece_type_char(piece.type) << ") " << piece.first_seg_id.segment_index << ".." << piece.last_segment_index - 1;
|
||||||
|
point_type label_point = bg::return_centroid<point_type>(corner);
|
||||||
|
|
||||||
|
if ((piece.type == bg::strategy::buffer::buffered_concave
|
||||||
|
|| piece.type == bg::strategy::buffer::buffered_flat_end)
|
||||||
|
&& corner.size() >= 2u)
|
||||||
|
{
|
||||||
|
bg::set<0>(label_point, (bg::get<0>(corner[0]) + bg::get<0>(corner[1])) / 2.0);
|
||||||
|
bg::set<1>(label_point, (bg::get<1>(corner[0]) + bg::get<1>(corner[1])) / 2.0);
|
||||||
|
}
|
||||||
|
m_mapper.text(label_point, out.str(), "fill:rgb(255,0,0);font-family='Arial';font-size:10px;", 5, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TraversedRings>
|
||||||
|
inline void map_traversed_rings(TraversedRings const& traversed_rings)
|
||||||
|
{
|
||||||
|
for(typename boost::range_iterator<TraversedRings const>::type it
|
||||||
|
= boost::begin(traversed_rings); it != boost::end(traversed_rings); ++it)
|
||||||
|
{
|
||||||
|
m_mapper.map(*it, "opacity:0.4;fill:none;stroke:rgb(0,255,0);stroke-width:2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OffsettedRings>
|
||||||
|
inline void map_offsetted_rings(OffsettedRings const& offsetted_rings)
|
||||||
|
{
|
||||||
|
for(typename boost::range_iterator<OffsettedRings const>::type it
|
||||||
|
= boost::begin(offsetted_rings); it != boost::end(offsetted_rings); ++it)
|
||||||
|
{
|
||||||
|
if (it->discarded())
|
||||||
|
{
|
||||||
|
m_mapper.map(*it, "opacity:0.4;fill:none;stroke:rgb(255,0,0);stroke-width:2");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_mapper.map(*it, "opacity:0.4;fill:none;stroke:rgb(0,0,255);stroke-width:2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SvgMapper& m_mapper;
|
||||||
|
Box m_alternate_box;
|
||||||
|
bool m_zoom;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Point>
|
||||||
|
class buffer_svg_mapper
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
buffer_svg_mapper(std::string const& casename)
|
||||||
|
: m_casename(casename)
|
||||||
|
, m_zoom(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename Mapper, typename Visitor, typename Envelope>
|
||||||
|
void prepare(Mapper& mapper, Visitor& visitor, Envelope const& envelope, double box_buffer_distance)
|
||||||
|
{
|
||||||
|
#ifdef BOOST_GEOMETRY_BUFFER_TEST_SVG_USE_ALTERNATE_BOX
|
||||||
|
// Create a zoomed-in view
|
||||||
|
bg::read_wkt(BOOST_GEOMETRY_BUFFER_TEST_SVG_ALTERNATE_BOX, alternate_box);
|
||||||
|
mapper.add(alternate_box);
|
||||||
|
|
||||||
|
// Take care non-visible elements are skipped
|
||||||
|
visitor.m_alternate_box = alternate_box;
|
||||||
|
m_zoom = true;
|
||||||
|
#else
|
||||||
|
bg::model::box<Point> box = envelope;
|
||||||
|
bg::buffer(box, box, box_buffer_distance);
|
||||||
|
mapper.add(box);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
boost::ignore_unused(visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_alternate_box(bg::model::box<Point> const& box)
|
||||||
|
{
|
||||||
|
m_alternate_box = box;
|
||||||
|
m_zoom = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Mapper, typename Geometry, typename GeometryBuffer>
|
||||||
|
void map_input_output(Mapper& mapper, Geometry const& geometry,
|
||||||
|
GeometryBuffer const& buffered, bool negative)
|
||||||
|
{
|
||||||
|
bool const areal = boost::is_same
|
||||||
|
<
|
||||||
|
typename bg::tag_cast
|
||||||
|
<
|
||||||
|
typename bg::tag<Geometry>::type,
|
||||||
|
bg::areal_tag
|
||||||
|
>::type, bg::areal_tag
|
||||||
|
>::type::value;
|
||||||
|
|
||||||
|
if (m_zoom)
|
||||||
|
{
|
||||||
|
map_io_zoomed(mapper, geometry, buffered, negative, areal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
map_io(mapper, geometry, buffered, negative, areal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Mapper, typename Geometry, typename RescalePolicy>
|
||||||
|
void map_self_ips(Mapper& mapper, Geometry const& geometry, RescalePolicy const& rescale_policy)
|
||||||
|
{
|
||||||
|
typedef bg::detail::overlay::turn_info
|
||||||
|
<
|
||||||
|
Point,
|
||||||
|
typename bg::segment_ratio_type<Point, RescalePolicy>::type
|
||||||
|
> turn_info;
|
||||||
|
|
||||||
|
std::vector<turn_info> turns;
|
||||||
|
|
||||||
|
bg::detail::self_get_turn_points::no_interrupt_policy policy;
|
||||||
|
bg::self_turns
|
||||||
|
<
|
||||||
|
bg::detail::overlay::assign_null_policy
|
||||||
|
>(geometry, rescale_policy, turns, policy);
|
||||||
|
|
||||||
|
BOOST_FOREACH(turn_info const& turn, turns)
|
||||||
|
{
|
||||||
|
mapper.map(turn.point, "fill:rgb(255,128,0);stroke:rgb(0,0,100);stroke-width:1", 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
template <typename Mapper, typename Geometry, typename GeometryBuffer>
|
||||||
|
void map_io(Mapper& mapper, Geometry const& geometry,
|
||||||
|
GeometryBuffer const& buffered, bool negative, bool areal)
|
||||||
|
{
|
||||||
|
// Map input geometry in green
|
||||||
|
if (areal)
|
||||||
|
{
|
||||||
|
mapper.map(geometry, "opacity:0.5;fill:rgb(0,128,0);stroke:rgb(0,64,0);stroke-width:2");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: clip input points/linestring
|
||||||
|
mapper.map(geometry, "opacity:0.5;stroke:rgb(0,128,0);stroke-width:10");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Map buffer in yellow (inflate) and with orange-dots (deflate)
|
||||||
|
std::string style = negative
|
||||||
|
? "opacity:0.4;fill:rgb(255,255,192);stroke:rgb(255,128,0);stroke-width:3"
|
||||||
|
: "opacity:0.4;fill:rgb(255,255,128);stroke:rgb(0,0,0);stroke-width:3";
|
||||||
|
|
||||||
|
mapper.map(buffered, style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Mapper, typename Geometry, typename GeometryBuffer>
|
||||||
|
void map_io_zoomed(Mapper& mapper, Geometry const& geometry,
|
||||||
|
GeometryBuffer const& buffered, bool negative, bool areal)
|
||||||
|
{
|
||||||
|
// Map input geometry in green
|
||||||
|
if (areal)
|
||||||
|
{
|
||||||
|
// Assuming input is areal
|
||||||
|
GeometryBuffer clipped;
|
||||||
|
// TODO: the next line does NOT compile for multi-point, TODO: implement that line
|
||||||
|
// bg::intersection(geometry, m_alternate_box, clipped);
|
||||||
|
mapper.map(clipped, "opacity:0.5;fill:rgb(0,128,0);stroke:rgb(0,64,0);stroke-width:2");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: clip input (multi)point/linestring
|
||||||
|
mapper.map(geometry, "opacity:0.5;stroke:rgb(0,128,0);stroke-width:10");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Map buffer in yellow (inflate) and with orange-dots (deflate)
|
||||||
|
std::string style = negative
|
||||||
|
? "opacity:0.4;fill:rgb(255,255,192);stroke:rgb(255,128,0);stroke-width:3"
|
||||||
|
: "opacity:0.4;fill:rgb(255,255,128);stroke:rgb(0,0,0);stroke-width:3";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Clip output multi-polygon with box
|
||||||
|
GeometryBuffer clipped;
|
||||||
|
bg::intersection(buffered, m_alternate_box, clipped);
|
||||||
|
mapper.map(clipped, style);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cout << "Error for buffered output " << m_casename << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bg::model::box<Point> m_alternate_box;
|
||||||
|
bool m_zoom;
|
||||||
|
std::string m_casename;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
164
test/algorithms/buffer/test_buffer_svg_per_turn.hpp
Normal file
164
test/algorithms/buffer/test_buffer_svg_per_turn.hpp
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
// Unit Test Helper
|
||||||
|
|
||||||
|
// Copyright (c) 2010-2015 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_BUFFER_SVG_PER_TURN_HPP
|
||||||
|
#define BOOST_GEOMETRY_TEST_BUFFER_SVG_PER_TURN_HPP
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <test_buffer_svg.hpp>
|
||||||
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
|
|
||||||
|
template <typename Point>
|
||||||
|
class save_turns_visitor
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
typedef std::vector<std::pair<Point, int> > vector_type;
|
||||||
|
|
||||||
|
template <typename Turns>
|
||||||
|
inline void get_turns(Turns const& turns)
|
||||||
|
{
|
||||||
|
for (typename boost::range_iterator<Turns const>::type it =
|
||||||
|
boost::begin(turns); it != boost::end(turns); ++it)
|
||||||
|
{
|
||||||
|
m_points.push_back(std::make_pair(it->point, it->turn_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PieceCollection>
|
||||||
|
inline void apply(PieceCollection const& collection, int phase)
|
||||||
|
{
|
||||||
|
if (phase == 0)
|
||||||
|
{
|
||||||
|
get_turns(collection.m_turns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector_type const& get_points() { return m_points; }
|
||||||
|
|
||||||
|
private :
|
||||||
|
vector_type m_points;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Point>
|
||||||
|
class mapper_visitor
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
mapper_visitor(std::string const& complete, int index, Point const& point)
|
||||||
|
: m_filename(get_filename(complete, index))
|
||||||
|
, m_svg(m_filename.c_str())
|
||||||
|
, m_mapper(m_svg, 1000, 800)
|
||||||
|
, m_visitor(m_mapper)
|
||||||
|
, m_buffer_mapper(m_filename)
|
||||||
|
{
|
||||||
|
box_type box;
|
||||||
|
double half_size = 75.0; // specific for multi_point buffer
|
||||||
|
bg::set<bg::min_corner, 0>(box, bg::get<0>(point) - half_size);
|
||||||
|
bg::set<bg::min_corner, 1>(box, bg::get<1>(point) - half_size);
|
||||||
|
bg::set<bg::max_corner, 0>(box, bg::get<0>(point) + half_size);
|
||||||
|
bg::set<bg::max_corner, 1>(box, bg::get<1>(point) + half_size);
|
||||||
|
|
||||||
|
m_mapper.add(box);
|
||||||
|
m_visitor.set_alternate_box(box);
|
||||||
|
m_buffer_mapper.set_alternate_box(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is used in a ptr vector
|
||||||
|
virtual ~mapper_visitor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PieceCollection>
|
||||||
|
inline void apply(PieceCollection const& collection, int phase)
|
||||||
|
{
|
||||||
|
m_visitor.apply(collection, phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Geometry, typename GeometryBuffer>
|
||||||
|
void map_input_output(Geometry const& geometry,
|
||||||
|
GeometryBuffer const& buffered, bool negative)
|
||||||
|
{
|
||||||
|
m_buffer_mapper.map_input_output(m_mapper, geometry, buffered, negative);
|
||||||
|
}
|
||||||
|
|
||||||
|
private :
|
||||||
|
std::string get_filename(std::string const& complete, int index)
|
||||||
|
{
|
||||||
|
std::ostringstream filename;
|
||||||
|
filename << "buffer_per_turn_" << complete << "_" << index << ".svg";
|
||||||
|
return filename.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef bg::svg_mapper<Point> mapper_type;
|
||||||
|
typedef bg::model::box<Point> box_type;
|
||||||
|
|
||||||
|
std::string m_filename;
|
||||||
|
std::ofstream m_svg;
|
||||||
|
mapper_type m_mapper;
|
||||||
|
svg_visitor<mapper_type, box_type> m_visitor;
|
||||||
|
buffer_svg_mapper<Point> m_buffer_mapper;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Point>
|
||||||
|
class per_turn_visitor
|
||||||
|
{
|
||||||
|
// Both fstreams and svg mappers are non-copyable,
|
||||||
|
// therefore we need to use dynamic memory
|
||||||
|
typedef boost::ptr_vector<mapper_visitor<Point> > container_type;
|
||||||
|
container_type mappers;
|
||||||
|
|
||||||
|
public :
|
||||||
|
|
||||||
|
typedef std::pair<Point, int> pair_type;
|
||||||
|
typedef std::vector<pair_type> vector_type;
|
||||||
|
|
||||||
|
per_turn_visitor(std::string const& complete_caseid,
|
||||||
|
vector_type const& points)
|
||||||
|
{
|
||||||
|
namespace bg = boost::geometry;
|
||||||
|
|
||||||
|
if (points.size() > 100u)
|
||||||
|
{
|
||||||
|
// Defensive check. Too much intersections. Don't create anything
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH(pair_type const& p, points)
|
||||||
|
{
|
||||||
|
mappers.push_back(new mapper_visitor<Point>(complete_caseid, p.second, p.first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PieceCollection>
|
||||||
|
inline void apply(PieceCollection const& collection, int phase)
|
||||||
|
{
|
||||||
|
for(typename container_type::iterator it = mappers.begin();
|
||||||
|
it != mappers.end(); ++it)
|
||||||
|
{
|
||||||
|
it->apply(collection, phase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Geometry, typename GeometryBuffer>
|
||||||
|
void map_input_output(Geometry const& geometry,
|
||||||
|
GeometryBuffer const& buffered, bool negative)
|
||||||
|
{
|
||||||
|
for(typename container_type::iterator it = mappers.begin();
|
||||||
|
it != mappers.end(); ++it)
|
||||||
|
{
|
||||||
|
it->map_input_output(geometry, buffered, negative);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BOOST_GEOMETRY_TEST_BUFFER_SVG_PER_TURN_HPP
|
@ -122,19 +122,19 @@ void test_distance_point_segment(Strategy const& strategy)
|
|||||||
#endif
|
#endif
|
||||||
typedef test_distance_of_geometries<point_type, segment_type> tester;
|
typedef test_distance_of_geometries<point_type, segment_type> tester;
|
||||||
|
|
||||||
|
double const d2r = bg::math::d2r<double>();
|
||||||
|
|
||||||
tester::apply("p-s-01",
|
tester::apply("p-s-01",
|
||||||
"POINT(0 0)",
|
"POINT(0 0)",
|
||||||
"SEGMENT(2 0,3 0)",
|
"SEGMENT(2 0,3 0)",
|
||||||
2.0 * bg::math::d2r * strategy.radius(),
|
2.0 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 2.0 * d2r * strategy.radius()),
|
||||||
2.0 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-s-02",
|
tester::apply("p-s-02",
|
||||||
"POINT(2.5 3)",
|
"POINT(2.5 3)",
|
||||||
"SEGMENT(2 0,3 0)",
|
"SEGMENT(2 0,3 0)",
|
||||||
3.0 * bg::math::d2r * strategy.radius(),
|
3.0 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 3.0 * d2r * strategy.radius()),
|
||||||
3.0 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-s-03",
|
tester::apply("p-s-03",
|
||||||
"POINT(2 0)",
|
"POINT(2 0)",
|
||||||
@ -163,44 +163,38 @@ void test_distance_point_segment(Strategy const& strategy)
|
|||||||
tester::apply("p-s-07",
|
tester::apply("p-s-07",
|
||||||
"POINT(90 1e-3)",
|
"POINT(90 1e-3)",
|
||||||
"SEGMENT(0.5 0,175.5 0)",
|
"SEGMENT(0.5 0,175.5 0)",
|
||||||
1e-3 * bg::math::d2r * strategy.radius(),
|
1e-3 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 1e-3 * d2r * strategy.radius()),
|
||||||
1e-3 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-s-08",
|
tester::apply("p-s-08",
|
||||||
"POINT(90 1e-4)",
|
"POINT(90 1e-4)",
|
||||||
"SEGMENT(0.5 0,175.5 0)",
|
"SEGMENT(0.5 0,175.5 0)",
|
||||||
1e-4 * bg::math::d2r * strategy.radius(),
|
1e-4 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 1e-4 * d2r * strategy.radius()),
|
||||||
1e-4 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-s-09",
|
tester::apply("p-s-09",
|
||||||
"POINT(90 1e-5)",
|
"POINT(90 1e-5)",
|
||||||
"SEGMENT(0.5 0,175.5 0)",
|
"SEGMENT(0.5 0,175.5 0)",
|
||||||
1e-5 * bg::math::d2r * strategy.radius(),
|
1e-5 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 1e-5 * d2r * strategy.radius()),
|
||||||
1e-5 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-s-10",
|
tester::apply("p-s-10",
|
||||||
"POINT(90 1e-6)",
|
"POINT(90 1e-6)",
|
||||||
"SEGMENT(0.5 0,175.5 0)",
|
"SEGMENT(0.5 0,175.5 0)",
|
||||||
1e-6 * bg::math::d2r * strategy.radius(),
|
1e-6 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 1e-6 * d2r * strategy.radius()),
|
||||||
1e-6 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-s-11",
|
tester::apply("p-s-11",
|
||||||
"POINT(90 1e-7)",
|
"POINT(90 1e-7)",
|
||||||
"SEGMENT(0.5 0,175.5 0)",
|
"SEGMENT(0.5 0,175.5 0)",
|
||||||
1e-7 * bg::math::d2r * strategy.radius(),
|
1e-7 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 1e-7 * d2r * strategy.radius()),
|
||||||
1e-7 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-s-12",
|
tester::apply("p-s-12",
|
||||||
"POINT(90 1e-8)",
|
"POINT(90 1e-8)",
|
||||||
"SEGMENT(0.5 0,175.5 0)",
|
"SEGMENT(0.5 0,175.5 0)",
|
||||||
1e-8 * bg::math::d2r * strategy.radius(),
|
1e-8 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 1e-8 * d2r * strategy.radius()),
|
||||||
1e-8 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,26 +209,25 @@ void test_distance_point_linestring(Strategy const& strategy)
|
|||||||
#endif
|
#endif
|
||||||
typedef test_distance_of_geometries<point_type, linestring_type> tester;
|
typedef test_distance_of_geometries<point_type, linestring_type> tester;
|
||||||
|
|
||||||
|
double const d2r = bg::math::d2r<double>();
|
||||||
|
|
||||||
tester::apply("p-l-01",
|
tester::apply("p-l-01",
|
||||||
"POINT(0 0)",
|
"POINT(0 0)",
|
||||||
"LINESTRING(2 0,2 0)",
|
"LINESTRING(2 0,2 0)",
|
||||||
2.0 * bg::math::d2r * strategy.radius(),
|
2.0 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 2.0 * d2r * strategy.radius()),
|
||||||
2.0 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-l-02",
|
tester::apply("p-l-02",
|
||||||
"POINT(0 0)",
|
"POINT(0 0)",
|
||||||
"LINESTRING(2 0,3 0)",
|
"LINESTRING(2 0,3 0)",
|
||||||
2.0 * bg::math::d2r * strategy.radius(),
|
2.0 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 2.0 * d2r * strategy.radius()),
|
||||||
2.0 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-l-03",
|
tester::apply("p-l-03",
|
||||||
"POINT(2.5 3)",
|
"POINT(2.5 3)",
|
||||||
"LINESTRING(2 0,3 0)",
|
"LINESTRING(2 0,3 0)",
|
||||||
3.0 * bg::math::d2r * strategy.radius(),
|
3.0 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 3.0 * d2r * strategy.radius()),
|
||||||
3.0 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-l-04",
|
tester::apply("p-l-04",
|
||||||
"POINT(2 0)",
|
"POINT(2 0)",
|
||||||
@ -254,9 +247,8 @@ void test_distance_point_linestring(Strategy const& strategy)
|
|||||||
tester::apply("p-l-07",
|
tester::apply("p-l-07",
|
||||||
"POINT(7.5 10)",
|
"POINT(7.5 10)",
|
||||||
"LINESTRING(1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 0)",
|
"LINESTRING(1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 0)",
|
||||||
10.0 * bg::math::d2r * strategy.radius(),
|
10.0 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 10.0 * d2r * strategy.radius()),
|
||||||
10.0 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-l-08",
|
tester::apply("p-l-08",
|
||||||
"POINT(7.5 10)",
|
"POINT(7.5 10)",
|
||||||
@ -282,19 +274,19 @@ void test_distance_point_multilinestring(Strategy const& strategy)
|
|||||||
point_type, multi_linestring_type
|
point_type, multi_linestring_type
|
||||||
> tester;
|
> tester;
|
||||||
|
|
||||||
|
double const d2r = bg::math::d2r<double>();
|
||||||
|
|
||||||
tester::apply("p-ml-01",
|
tester::apply("p-ml-01",
|
||||||
"POINT(0 0)",
|
"POINT(0 0)",
|
||||||
"MULTILINESTRING((-5 0,-3 0),(2 0,3 0))",
|
"MULTILINESTRING((-5 0,-3 0),(2 0,3 0))",
|
||||||
2.0 * bg::math::d2r * strategy.radius(),
|
2.0 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 2.0 * d2r * strategy.radius()),
|
||||||
2.0 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-ml-02",
|
tester::apply("p-ml-02",
|
||||||
"POINT(2.5 3)",
|
"POINT(2.5 3)",
|
||||||
"MULTILINESTRING((-5 0,-3 0),(2 0,3 0))",
|
"MULTILINESTRING((-5 0,-3 0),(2 0,3 0))",
|
||||||
3.0 * bg::math::d2r * strategy.radius(),
|
3.0 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 3.0 * d2r * strategy.radius()),
|
||||||
3.0 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-ml-03",
|
tester::apply("p-ml-03",
|
||||||
"POINT(2 0)",
|
"POINT(2 0)",
|
||||||
@ -431,6 +423,8 @@ void test_distance_multipoint_segment(Strategy const& strategy)
|
|||||||
#endif
|
#endif
|
||||||
typedef test_distance_of_geometries<multi_point_type, segment_type> tester;
|
typedef test_distance_of_geometries<multi_point_type, segment_type> tester;
|
||||||
|
|
||||||
|
double d2r = bg::math::d2r<double>();
|
||||||
|
|
||||||
tester::apply("mp-s-01",
|
tester::apply("mp-s-01",
|
||||||
"MULTIPOINT(0 0,1 0,0 1,1 1)",
|
"MULTIPOINT(0 0,1 0,0 1,1 1)",
|
||||||
"SEGMENT(2 0,0 2)",
|
"SEGMENT(2 0,0 2)",
|
||||||
@ -442,9 +436,8 @@ void test_distance_multipoint_segment(Strategy const& strategy)
|
|||||||
tester::apply("mp-s-02",
|
tester::apply("mp-s-02",
|
||||||
"MULTIPOINT(0 0,1 0,0 1,1 1)",
|
"MULTIPOINT(0 0,1 0,0 1,1 1)",
|
||||||
"SEGMENT(0 -3,1 -10)",
|
"SEGMENT(0 -3,1 -10)",
|
||||||
3.0 * bg::math::d2r * strategy.radius(),
|
3.0 * d2r * strategy.radius(),
|
||||||
to_comparable(strategy,
|
to_comparable(strategy, 3.0 * d2r * strategy.radius()),
|
||||||
3.0 * bg::math::d2r * strategy.radius()),
|
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("mp-s-03",
|
tester::apply("mp-s-03",
|
||||||
"MULTIPOINT(0 0,1 0,0 1,1 1)",
|
"MULTIPOINT(0 0,1 0,0 1,1 1)",
|
||||||
|
@ -89,7 +89,7 @@ void test_distance_point_point(Strategy const& strategy,
|
|||||||
"POINT(180 -10)",
|
"POINT(180 -10)",
|
||||||
(is_comparable_strategy
|
(is_comparable_strategy
|
||||||
? 1.0
|
? 1.0
|
||||||
: (180.0 * bg::math::d2r * strategy.radius())),
|
: (bg::math::pi<double>() * strategy.radius())),
|
||||||
1.0,
|
1.0,
|
||||||
strategy);
|
strategy);
|
||||||
tester::apply("p-p-04",
|
tester::apply("p-p-04",
|
||||||
@ -97,7 +97,7 @@ void test_distance_point_point(Strategy const& strategy,
|
|||||||
"POINT(180 0)",
|
"POINT(180 0)",
|
||||||
(is_comparable_strategy
|
(is_comparable_strategy
|
||||||
? 1.0
|
? 1.0
|
||||||
: (180.0 * bg::math::d2r * strategy.radius())),
|
: (bg::math::pi<double>() * strategy.radius())),
|
||||||
1.0,
|
1.0,
|
||||||
strategy);
|
strategy);
|
||||||
}
|
}
|
||||||
|
61
test/algorithms/is_convex.cpp
Normal file
61
test/algorithms/is_convex.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
// Unit Test
|
||||||
|
|
||||||
|
// Copyright (c) 2015 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 <cstddef>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/geometry/algorithms/is_convex.hpp>
|
||||||
|
|
||||||
|
#include <geometry_test_common.hpp>
|
||||||
|
|
||||||
|
#include <boost/geometry/algorithms/correct.hpp>
|
||||||
|
#include <boost/geometry/io/wkt/wkt.hpp>
|
||||||
|
#include <boost/geometry/strategies/strategies.hpp>
|
||||||
|
#include <boost/geometry/geometries/point_xy.hpp>
|
||||||
|
#include <boost/geometry/geometries/ring.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Geometry>
|
||||||
|
void test_one(std::string const& case_id, std::string const& wkt, bool expected)
|
||||||
|
{
|
||||||
|
Geometry geometry;
|
||||||
|
bg::read_wkt(wkt, geometry);
|
||||||
|
bg::correct(geometry);
|
||||||
|
|
||||||
|
bool detected = bg::is_convex(geometry);
|
||||||
|
BOOST_CHECK_MESSAGE(detected == expected,
|
||||||
|
"Not as expected, case: " << case_id
|
||||||
|
<< " / expected: " << expected
|
||||||
|
<< " / detected: " << detected);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename P>
|
||||||
|
void test_all()
|
||||||
|
{
|
||||||
|
// rectangular, with concavity
|
||||||
|
std::string const concave1 = "polygon((1 1, 1 4, 3 4, 3 3, 4 3, 4 4, 5 4, 5 1, 1 1))";
|
||||||
|
std::string const triangle = "polygon((1 1, 1 4, 5 1, 1 1))";
|
||||||
|
|
||||||
|
test_one<bg::model::ring<P> >("triangle", triangle, true);
|
||||||
|
test_one<bg::model::ring<P> >("concave1", concave1, false);
|
||||||
|
test_one<bg::model::ring<P, false, false> >("triangle", triangle, true);
|
||||||
|
test_one<bg::model::ring<P, false, false> >("concave1", concave1, false);
|
||||||
|
|
||||||
|
test_one<bg::model::box<P> >("box", "box(0 0,2 2)", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int test_main(int, char* [])
|
||||||
|
{
|
||||||
|
test_all<bg::model::d2::point_xy<int> >();
|
||||||
|
test_all<bg::model::d2::point_xy<double> >();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
# Boost.Geometry (aka GGL, Generic Geometry Library)
|
# Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
#
|
#
|
||||||
# Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
# Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
|
||||||
# Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
|
# Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
|
||||||
# Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
|
# Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
|
||||||
#
|
#
|
||||||
# This file was modified by Oracle on 2014.
|
# This file was modified by Oracle on 2014, 2015.
|
||||||
# Modifications copyright (c) 2014, Oracle and/or its affiliates.
|
# Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
|
||||||
#
|
#
|
||||||
# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||||
# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
# Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
|
||||||
@ -19,6 +19,7 @@ test-suite boost-geometry-algorithms-relational
|
|||||||
[ run covered_by.cpp ]
|
[ run covered_by.cpp ]
|
||||||
[ run crosses.cpp ]
|
[ run crosses.cpp ]
|
||||||
[ run equals.cpp ]
|
[ run equals.cpp ]
|
||||||
|
[ run equals_on_spheroid.cpp ]
|
||||||
[ run intersects.cpp ]
|
[ run intersects.cpp ]
|
||||||
[ run multi_covered_by.cpp ]
|
[ run multi_covered_by.cpp ]
|
||||||
[ run multi_equals.cpp ]
|
[ run multi_equals.cpp ]
|
||||||
|
183
test/algorithms/relational_operations/equals_on_spheroid.cpp
Normal file
183
test/algorithms/relational_operations/equals_on_spheroid.cpp
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
||||||
|
// Unit test
|
||||||
|
|
||||||
|
// Copyright (c) 2015, Oracle and/or its affiliates.
|
||||||
|
|
||||||
|
// Licensed under the Boost Software License version 1.0.
|
||||||
|
// http://www.boost.org/users/license.html
|
||||||
|
|
||||||
|
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
||||||
|
|
||||||
|
#ifndef BOOST_TEST_MODULE
|
||||||
|
#define BOOST_TEST_MODULE test_equals_on_spheroid
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <boost/test/included/unit_test.hpp>
|
||||||
|
|
||||||
|
#include "test_equals.hpp"
|
||||||
|
|
||||||
|
#include <boost/geometry/geometries/geometries.hpp>
|
||||||
|
|
||||||
|
#include <boost/geometry/core/cs.hpp>
|
||||||
|
|
||||||
|
namespace bgm = bg::model;
|
||||||
|
|
||||||
|
template <typename P1, typename P2 = P1>
|
||||||
|
struct test_point_point
|
||||||
|
{
|
||||||
|
static inline void apply(std::string const& header)
|
||||||
|
{
|
||||||
|
std::string const str = header + "-";
|
||||||
|
|
||||||
|
test_geometry<P1, P2>(str + "pp_01", "POINT(0 0)", "POINT(0 0)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_02", "POINT(0 0)", "POINT(10 0)", false);
|
||||||
|
|
||||||
|
// points whose longitudes differ by 360 degrees
|
||||||
|
test_geometry<P1, P2>(str + "pp_03", "POINT(0 0)", "POINT(360 0)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_04", "POINT(10 0)", "POINT(370 0)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_05", "POINT(10 0)", "POINT(-350 0)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_06", "POINT(180 10)", "POINT(-180 10)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_06a", "POINT(540 10)", "POINT(-540 10)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_06b", "POINT(540 370)", "POINT(-540 -350)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_06c", "POINT(1260 370)", "POINT(-1260 -350)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_06d", "POINT(2340 370)", "POINT(-2340 -350)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_06e", "POINT(-180 10)", "POINT(-540 10)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_06f", "POINT(180 10)", "POINT(-540 10)", true);
|
||||||
|
|
||||||
|
// north & south pole
|
||||||
|
test_geometry<P1, P2>(str + "pp_07", "POINT(0 90)", "POINT(0 90)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_07a", "POINT(0 450)", "POINT(10 -270)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_07b", "POINT(0 270)", "POINT(10 90)", false);
|
||||||
|
test_geometry<P1, P2>(str + "pp_07c", "POINT(0 -450)", "POINT(10 90)", false);
|
||||||
|
test_geometry<P1, P2>(str + "pp_08", "POINT(0 90)", "POINT(10 90)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_09", "POINT(0 90)", "POINT(0 -90)", false);
|
||||||
|
test_geometry<P1, P2>(str + "pp_10", "POINT(0 -90)", "POINT(0 -90)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_11", "POINT(0 -90)", "POINT(10 -90)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_11a", "POINT(0 -90)", "POINT(10 90)", false);
|
||||||
|
test_geometry<P1, P2>(str + "pp_12", "POINT(0 -90)", "POINT(0 -85)", false);
|
||||||
|
test_geometry<P1, P2>(str + "pp_13", "POINT(0 90)", "POINT(0 85)", false);
|
||||||
|
test_geometry<P1, P2>(str + "pp_14", "POINT(0 90)", "POINT(10 85)", false);
|
||||||
|
|
||||||
|
// symmetric wrt prime meridian
|
||||||
|
test_geometry<P1, P2>(str + "pp_15", "POINT(-10 45)", "POINT(10 45)", false);
|
||||||
|
test_geometry<P1, P2>(str + "pp_16", "POINT(-170 45)", "POINT(170 45)", false);
|
||||||
|
|
||||||
|
// other points
|
||||||
|
test_geometry<P1, P2>(str + "pp_17", "POINT(-10 45)", "POINT(10 -45)", false);
|
||||||
|
test_geometry<P1, P2>(str + "pp_18", "POINT(-10 -45)", "POINT(10 45)", false);
|
||||||
|
test_geometry<P1, P2>(str + "pp_19", "POINT(10 -135)", "POINT(10 45)", false);
|
||||||
|
test_geometry<P1, P2>(str + "pp_20", "POINT(190 135)", "POINT(10 45)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_21", "POINT(190 150)", "POINT(10 30)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_21a", "POINT(-170 150)", "POINT(10 30)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_22", "POINT(190 -135)", "POINT(10 -45)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_23", "POINT(190 -150)", "POINT(10 -30)", true);
|
||||||
|
test_geometry<P1, P2>(str + "pp_23a", "POINT(-170 -150)", "POINT(10 -30)", true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename P>
|
||||||
|
void test_segment_segment(std::string const& header)
|
||||||
|
{
|
||||||
|
typedef bgm::segment<P> seg;
|
||||||
|
|
||||||
|
std::string const str = header + "-";
|
||||||
|
|
||||||
|
test_geometry<seg, seg>(str + "ss_01",
|
||||||
|
"SEGMENT(10 0,180 0)",
|
||||||
|
"SEGMENT(10 0,-180 0)",
|
||||||
|
true);
|
||||||
|
test_geometry<seg, seg>(str + "ss_02",
|
||||||
|
"SEGMENT(0 90,180 0)",
|
||||||
|
"SEGMENT(10 90,-180 0)",
|
||||||
|
true);
|
||||||
|
test_geometry<seg, seg>(str + "ss_03",
|
||||||
|
"SEGMENT(0 90,0 -90)",
|
||||||
|
"SEGMENT(10 90,20 -90)",
|
||||||
|
true);
|
||||||
|
test_geometry<seg, seg>(str + "ss_04",
|
||||||
|
"SEGMENT(10 80,10 -80)",
|
||||||
|
"SEGMENT(10 80,20 -80)",
|
||||||
|
false);
|
||||||
|
test_geometry<seg, seg>(str + "ss_05",
|
||||||
|
"SEGMENT(170 10,-170 10)",
|
||||||
|
"SEGMENT(170 10,350 10)",
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( equals_point_point_se )
|
||||||
|
{
|
||||||
|
typedef bg::cs::spherical_equatorial<bg::degree> cs_type;
|
||||||
|
|
||||||
|
test_point_point<bgm::point<int, 2, cs_type> >::apply("se");
|
||||||
|
test_point_point<bgm::point<double, 2, cs_type> >::apply("se");
|
||||||
|
test_point_point<bgm::point<long double, 2, cs_type> >::apply("se");
|
||||||
|
|
||||||
|
// mixed point types
|
||||||
|
test_point_point
|
||||||
|
<
|
||||||
|
bgm::point<double, 2, cs_type>, bgm::point<int, 2, cs_type>
|
||||||
|
>::apply("se");
|
||||||
|
|
||||||
|
test_point_point
|
||||||
|
<
|
||||||
|
bgm::point<double, 2, cs_type>, bgm::point<long double, 2, cs_type>
|
||||||
|
>::apply("se");
|
||||||
|
|
||||||
|
#if defined(HAVE_TTMATH)
|
||||||
|
test_point_point<bgm::point<ttmath_big, 2, cs_type> >::apply("se");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( equals_point_point_geo )
|
||||||
|
{
|
||||||
|
typedef bg::cs::geographic<bg::degree> cs_type;
|
||||||
|
|
||||||
|
test_point_point<bgm::point<int, 2, cs_type> >::apply("geo");
|
||||||
|
test_point_point<bgm::point<double, 2, cs_type> >::apply("geo");
|
||||||
|
test_point_point<bgm::point<long double, 2, cs_type> >::apply("geo");
|
||||||
|
|
||||||
|
// mixed point types
|
||||||
|
test_point_point
|
||||||
|
<
|
||||||
|
bgm::point<double, 2, cs_type>, bgm::point<int, 2, cs_type>
|
||||||
|
>::apply("se");
|
||||||
|
|
||||||
|
test_point_point
|
||||||
|
<
|
||||||
|
bgm::point<double, 2, cs_type>, bgm::point<long double, 2, cs_type>
|
||||||
|
>::apply("se");
|
||||||
|
|
||||||
|
#if defined(HAVE_TTMATH)
|
||||||
|
test_point_point<bgm::point<ttmath_big, 2, cs_type> >::apply("geo");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( equals_segment_segment_se )
|
||||||
|
{
|
||||||
|
typedef bg::cs::spherical_equatorial<bg::degree> cs_type;
|
||||||
|
|
||||||
|
test_segment_segment<bgm::point<int, 2, cs_type> >("se");
|
||||||
|
test_segment_segment<bgm::point<double, 2, cs_type> >("se");
|
||||||
|
test_segment_segment<bgm::point<long double, 2, cs_type> >("se");
|
||||||
|
|
||||||
|
#if defined(HAVE_TTMATH)
|
||||||
|
test_segment_segment<bgm::point<ttmath_big, 2, cs_type> >("se");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( equals_segment_segment_geo )
|
||||||
|
{
|
||||||
|
typedef bg::cs::geographic<bg::degree> cs_type;
|
||||||
|
|
||||||
|
test_segment_segment<bgm::point<int, 2, cs_type> >("geo");
|
||||||
|
test_segment_segment<bgm::point<double, 2, cs_type> >("geo");
|
||||||
|
test_segment_segment<bgm::point<long double, 2, cs_type> >("geo");
|
||||||
|
|
||||||
|
#if defined(HAVE_TTMATH)
|
||||||
|
test_segment_segment<bgm::point<ttmath_big, 2, cs_type> >("geo");
|
||||||
|
#endif
|
||||||
|
}
|
@ -434,6 +434,38 @@ void test_areal_linear()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Linestring, typename Box>
|
||||||
|
void test_linear_box()
|
||||||
|
{
|
||||||
|
typedef bg::model::multi_linestring<Linestring> multi_linestring_type;
|
||||||
|
|
||||||
|
test_one_lp<Linestring, Box, Linestring>
|
||||||
|
("case-l-b-01",
|
||||||
|
"BOX(-10 -10,10 10)",
|
||||||
|
"LINESTRING(-20 -20, 0 0,20 20)",
|
||||||
|
1, 3, 20 * sqrt(2.0));
|
||||||
|
|
||||||
|
test_one_lp<Linestring, Box, Linestring>
|
||||||
|
("case-l-b-02",
|
||||||
|
"BOX(-10 -10,10 10)",
|
||||||
|
"LINESTRING(-20 -20, 20 20)",
|
||||||
|
1, 2, 20.0 * sqrt(2.0));
|
||||||
|
|
||||||
|
test_one_lp<Linestring, Box, Linestring>
|
||||||
|
("case-l-b-02",
|
||||||
|
"BOX(-10 -10,10 10)",
|
||||||
|
"LINESTRING(-20 -20, 20 20,15 0,0 -15)",
|
||||||
|
2, 4, 25.0 * sqrt(2.0));
|
||||||
|
|
||||||
|
test_one_lp<Linestring, Box, multi_linestring_type>
|
||||||
|
("case-ml-b-01",
|
||||||
|
"BOX(-10 -10,10 10)",
|
||||||
|
"MULTILINESTRING((-20 -20, 20 20),(0 -15,15 0))",
|
||||||
|
2, 4, 25.0 * sqrt(2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename P>
|
template <typename P>
|
||||||
void test_all()
|
void test_all()
|
||||||
{
|
{
|
||||||
@ -456,6 +488,8 @@ void test_all()
|
|||||||
test_areal_linear<polygon_ccw_open, linestring>();
|
test_areal_linear<polygon_ccw_open, linestring>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
test_linear_box<linestring, box>();
|
||||||
|
|
||||||
// Test polygons clockwise and counter clockwise
|
// Test polygons clockwise and counter clockwise
|
||||||
test_areal<polygon>();
|
test_areal<polygon>();
|
||||||
|
|
||||||
|
@ -130,24 +130,34 @@ int test_main(int, char* [])
|
|||||||
test_all<bg::model::d2::point_xy<int>, bg::model::d2::point_xy<float> >(1.0);
|
test_all<bg::model::d2::point_xy<int>, bg::model::d2::point_xy<float> >(1.0);
|
||||||
|
|
||||||
test_all<bg::model::point<double, 2, bg::cs::spherical<bg::degree> >,
|
test_all<bg::model::point<double, 2, bg::cs::spherical<bg::degree> >,
|
||||||
bg::model::point<double, 2, bg::cs::spherical<bg::radian> > >(bg::math::d2r);
|
bg::model::point<double, 2, bg::cs::spherical<bg::radian> > >(bg::math::d2r<double>());
|
||||||
test_all<bg::model::point<double, 2, bg::cs::spherical<bg::radian> >,
|
test_all<bg::model::point<double, 2, bg::cs::spherical<bg::radian> >,
|
||||||
bg::model::point<double, 2, bg::cs::spherical<bg::degree> > >(bg::math::r2d);
|
bg::model::point<double, 2, bg::cs::spherical<bg::degree> > >(bg::math::r2d<double>());
|
||||||
|
|
||||||
test_all<bg::model::point<int, 2, bg::cs::spherical<bg::degree> >,
|
test_all<bg::model::point<int, 2, bg::cs::spherical<bg::degree> >,
|
||||||
bg::model::point<float, 2, bg::cs::spherical<bg::radian> > >(bg::math::d2r);
|
bg::model::point<float, 2, bg::cs::spherical<bg::radian> > >(bg::math::d2r<float>());
|
||||||
|
|
||||||
test_transformations<float, bg::degree>(4, 52, 1);
|
test_transformations<float, bg::degree>(4, 52, 1);
|
||||||
test_transformations<double, bg::degree>(4, 52, 1);
|
test_transformations<double, bg::degree>(4, 52, 1);
|
||||||
|
|
||||||
test_transformations<float, bg::radian>(3 * bg::math::d2r, 51 * bg::math::d2r, 1);
|
test_transformations
|
||||||
test_transformations<double, bg::radian>(3 * bg::math::d2r, 51 * bg::math::d2r, 1);
|
<
|
||||||
|
float, bg::radian
|
||||||
|
>(3 * bg::math::d2r<float>(), 51 * bg::math::d2r<float>(), 1);
|
||||||
|
|
||||||
|
test_transformations
|
||||||
|
<
|
||||||
|
double, bg::radian
|
||||||
|
>(3 * bg::math::d2r<double>(), 51 * bg::math::d2r<double>(), 1);
|
||||||
|
|
||||||
#if defined(HAVE_TTMATH)
|
#if defined(HAVE_TTMATH)
|
||||||
typedef bg::model::d2::point_xy<ttmath_big > PT;
|
typedef bg::model::d2::point_xy<ttmath_big > PT;
|
||||||
test_all<PT, PT>();
|
test_all<PT, PT>();
|
||||||
test_transformations<ttmath_big, bg::degree>(4, 52, 1);
|
test_transformations<ttmath_big, bg::degree>(4, 52, 1);
|
||||||
test_transformations<ttmath_big, bg::radian>(3 * bg::math::d2r, 51 * bg::math::d2r, 1);
|
test_transformations
|
||||||
|
<
|
||||||
|
ttmath_big, bg::radian
|
||||||
|
>(3 * bg::math::d2r<ttmath_big>(), 51 * bg::math::d2r<ttmath_big>(), 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -19,9 +19,13 @@ namespace bg = boost::geometry;
|
|||||||
|
|
||||||
int test_main(int, char* [])
|
int test_main(int, char* [])
|
||||||
{
|
{
|
||||||
typedef bg::model::d2::point_xy<int> point;
|
typedef bg::model::d2::point_xy<boost::long_long_type> point;
|
||||||
typedef bg::model::segment<point> segment;
|
typedef bg::model::segment<point> segment;
|
||||||
|
|
||||||
|
typedef bg::strategy::side::side_of_intersection side;
|
||||||
|
|
||||||
|
point no_fb(-99, -99);
|
||||||
|
|
||||||
segment a(point(20, 10), point(10, 20));
|
segment a(point(20, 10), point(10, 20));
|
||||||
|
|
||||||
segment b1(point(11, 16), point(20, 14)); // IP with a: (14.857, 15.143)
|
segment b1(point(11, 16), point(20, 14)); // IP with a: (14.857, 15.143)
|
||||||
@ -31,27 +35,70 @@ int test_main(int, char* [])
|
|||||||
segment c2(point(15, 16), point(14, 8));
|
segment c2(point(15, 16), point(14, 8));
|
||||||
segment c3(point(15, 16), point(15, 8));
|
segment c3(point(15, 16), point(15, 8));
|
||||||
|
|
||||||
typedef bg::strategy::side::side_of_intersection side;
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 1, side::apply(a, b1, c1));
|
BOOST_CHECK_EQUAL( 1, side::apply(a, b1, c1, no_fb));
|
||||||
BOOST_CHECK_EQUAL(-1, side::apply(a, b1, c2));
|
BOOST_CHECK_EQUAL(-1, side::apply(a, b1, c2, no_fb));
|
||||||
BOOST_CHECK_EQUAL(-1, side::apply(a, b1, c3));
|
BOOST_CHECK_EQUAL(-1, side::apply(a, b1, c3, no_fb));
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 1, side::apply(a, b2, c1));
|
BOOST_CHECK_EQUAL( 1, side::apply(a, b2, c1, no_fb));
|
||||||
BOOST_CHECK_EQUAL( 1, side::apply(a, b2, c2));
|
BOOST_CHECK_EQUAL( 1, side::apply(a, b2, c2, no_fb));
|
||||||
BOOST_CHECK_EQUAL( 0, side::apply(a, b2, c3));
|
BOOST_CHECK_EQUAL( 0, side::apply(a, b2, c3, no_fb));
|
||||||
|
|
||||||
// Check internal calculation-method:
|
// Collinear cases
|
||||||
BOOST_CHECK_EQUAL(-1400, side::side_value<int>(a, b1, c2));
|
// 1: segments intersecting are collinear (with a fallback point):
|
||||||
BOOST_CHECK_EQUAL( 2800, side::side_value<int>(a, b1, c1));
|
{
|
||||||
|
point fb(5, 5);
|
||||||
|
segment col1(point(0, 5), point(5, 5));
|
||||||
|
segment col2(point(5, 5), point(10, 5)); // One IP with col1 at (5,5)
|
||||||
|
segment col3(point(5, 0), point(5, 5));
|
||||||
|
BOOST_CHECK_EQUAL( 0, side::apply(col1, col2, col3, fb));
|
||||||
|
}
|
||||||
|
// 2: segment of side calculation collinear with one of the segments
|
||||||
|
{
|
||||||
|
point fb(5, 5);
|
||||||
|
segment col1(point(0, 5), point(10, 5));
|
||||||
|
segment col2(point(5, 5), point(5, 12)); // IP with col1 at (5,5)
|
||||||
|
segment col3(point(5, 1), point(5, 5)); // collinear with col2
|
||||||
|
BOOST_CHECK_EQUAL( 0, side::apply(col1, col2, col3, fb));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
point fb(5, 5);
|
||||||
|
segment col1(point(10, 5), point(0, 5));
|
||||||
|
segment col2(point(5, 5), point(5, 12)); // IP with col1 at (5,5)
|
||||||
|
segment col3(point(5, 1), point(5, 5)); // collinear with col2
|
||||||
|
BOOST_CHECK_EQUAL( 0, side::apply(col1, col2, col3, fb));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
point fb(5, 5);
|
||||||
|
segment col1(point(0, 5), point(10, 5));
|
||||||
|
segment col2(point(5, 12), point(5, 5)); // IP with col1 at (5,5)
|
||||||
|
segment col3(point(5, 1), point(5, 5)); // collinear with col2
|
||||||
|
BOOST_CHECK_EQUAL( 0, side::apply(col1, col2, col3, fb));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL (2800, side::side_value<int>(a, b1, c1));
|
{
|
||||||
BOOST_CHECK_EQUAL(-1400, side::side_value<int>(a, b1, c2));
|
point fb(517248, -517236);
|
||||||
BOOST_CHECK_EQUAL(-5600, side::side_value<int>(a, b1, c3));
|
segment col1(point(-172408, -517236), point(862076, -517236));
|
||||||
|
segment col2(point(517248, -862064), point(517248, -172408));
|
||||||
|
segment col3(point(517248, -172408), point(517248, -517236));
|
||||||
|
BOOST_CHECK_EQUAL( 0, side::apply(col1, col2, col3, fb));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
point fb(-221647, -830336);
|
||||||
|
segment col1(point(-153817, -837972), point(-222457, -830244));
|
||||||
|
segment col2(point(-221139, -833615), point(-290654, -384388));
|
||||||
|
segment col3(point(-255266, -814663), point(-264389, -811197));
|
||||||
|
BOOST_CHECK_EQUAL(1, side::apply(col1, col2, col3, fb)); // Left of segment...
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(12800, side::side_value<int>(a, b2, c1));
|
|
||||||
BOOST_CHECK_EQUAL( 6400, side::side_value<int>(a, b2, c2));
|
{
|
||||||
BOOST_CHECK_EQUAL( 0, side::side_value<int>(a, b2, c3));
|
point fb(27671131, 30809240);
|
||||||
|
segment col1(point(27671116, 30809247), point(27675474, 30807351));
|
||||||
|
segment col2(point(27666779, 30811130), point(27671139, 30809237));
|
||||||
|
segment col3(point(27671122, 30809244), point(27675480, 30807348));
|
||||||
|
BOOST_CHECK_EQUAL(1, side::apply(col1, col2, col3, fb)); // Left of segment...
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: we might add a check calculating the IP, determining the side
|
// TODO: we might add a check calculating the IP, determining the side
|
||||||
// with the normal side strategy, and verify the results are equal
|
// with the normal side strategy, and verify the results are equal
|
||||||
|
@ -121,24 +121,27 @@ void test_vincenty(double lon1, double lat1, double lon2, double lat2,
|
|||||||
|
|
||||||
// formula
|
// formula
|
||||||
{
|
{
|
||||||
bg::detail::vincenty_inverse<calc_t> vi(lon1 * bg::math::d2r,
|
double const d2r = bg::math::d2r<double>();
|
||||||
lat1 * bg::math::d2r,
|
double const r2d = bg::math::r2d<double>();
|
||||||
lon2 * bg::math::d2r,
|
|
||||||
lat2 * bg::math::d2r,
|
bg::detail::vincenty_inverse<calc_t> vi(lon1 * d2r,
|
||||||
|
lat1 * d2r,
|
||||||
|
lon2 * d2r,
|
||||||
|
lat2 * d2r,
|
||||||
spheroid);
|
spheroid);
|
||||||
calc_t dist = vi.distance();
|
calc_t dist = vi.distance();
|
||||||
calc_t az12 = vi.azimuth12();
|
calc_t az12 = vi.azimuth12();
|
||||||
calc_t az21 = vi.azimuth21();
|
calc_t az21 = vi.azimuth21();
|
||||||
|
|
||||||
calc_t az12_deg = az12 * bg::math::r2d;
|
calc_t az12_deg = az12 * r2d;
|
||||||
calc_t az21_deg = az21 * bg::math::r2d;
|
calc_t az21_deg = az21 * r2d;
|
||||||
|
|
||||||
BOOST_CHECK_CLOSE(dist, calc_t(expected_distance), tolerance);
|
BOOST_CHECK_CLOSE(dist, calc_t(expected_distance), tolerance);
|
||||||
check_deg("az12_deg", az12_deg, calc_t(expected_azimuth_12), tolerance, error);
|
check_deg("az12_deg", az12_deg, calc_t(expected_azimuth_12), tolerance, error);
|
||||||
check_deg("az21_deg", az21_deg, calc_t(expected_azimuth_21), tolerance, error);
|
check_deg("az21_deg", az21_deg, calc_t(expected_azimuth_21), tolerance, error);
|
||||||
|
|
||||||
bg::detail::vincenty_direct<calc_t> vd(lon1 * bg::math::d2r,
|
bg::detail::vincenty_direct<calc_t> vd(lon1 * d2r,
|
||||||
lat1 * bg::math::d2r,
|
lat1 * d2r,
|
||||||
dist,
|
dist,
|
||||||
az12,
|
az12,
|
||||||
spheroid);
|
spheroid);
|
||||||
@ -146,9 +149,9 @@ void test_vincenty(double lon1, double lat1, double lon2, double lat2,
|
|||||||
calc_t direct_lat2 = vd.lat2();
|
calc_t direct_lat2 = vd.lat2();
|
||||||
calc_t direct_az21 = vd.azimuth21();
|
calc_t direct_az21 = vd.azimuth21();
|
||||||
|
|
||||||
calc_t direct_lon2_deg = direct_lon2 * bg::math::r2d;
|
calc_t direct_lon2_deg = direct_lon2 * r2d;
|
||||||
calc_t direct_lat2_deg = direct_lat2 * bg::math::r2d;
|
calc_t direct_lat2_deg = direct_lat2 * r2d;
|
||||||
calc_t direct_az21_deg = direct_az21 * bg::math::r2d;
|
calc_t direct_az21_deg = direct_az21 * r2d;
|
||||||
|
|
||||||
check_deg("direct_lon2_deg", direct_lon2_deg, calc_t(lon2), tolerance, error);
|
check_deg("direct_lon2_deg", direct_lon2_deg, calc_t(lon2), tolerance, error);
|
||||||
check_deg("direct_lat2_deg", direct_lat2_deg, calc_t(lat2), tolerance, error);
|
check_deg("direct_lat2_deg", direct_lat2_deg, calc_t(lat2), tolerance, error);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user