// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// Copyright (c) 2016-2017, Oracle and/or its affiliates.
+// Copyright (c) 2016-2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/geographic/area.hpp>
+#include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp>
-#include <boost/geometry/strategies/geographic/envelope_segment.hpp>
+#include <boost/geometry/strategies/geographic/envelope.hpp>
#include <boost/geometry/strategies/geographic/parameters.hpp>
#include <boost/geometry/strategies/geographic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/geographic/side.hpp>
+#include <boost/geometry/strategies/spherical/expand_box.hpp>
+#include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
+#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
#include <boost/geometry/strategies/side_info.hpp>
>
struct geographic_segments
{
+ typedef geographic_tag cs_tag;
+
typedef side::geographic
<
FormulaPolicy, Spheroid, CalculationType
return strategy_type(m_spheroid);
}
- typedef envelope::geographic_segment<FormulaPolicy, Spheroid, CalculationType>
+ typedef envelope::geographic<FormulaPolicy, Spheroid, CalculationType>
envelope_strategy_type;
inline envelope_strategy_type get_envelope_strategy() const
return envelope_strategy_type(m_spheroid);
}
+ typedef expand::geographic_segment<FormulaPolicy, Spheroid, CalculationType>
+ expand_strategy_type;
+
+ inline expand_strategy_type get_expand_strategy() const
+ {
+ return expand_strategy_type(m_spheroid);
+ }
+
+ typedef within::spherical_point_point point_in_point_strategy_type;
+
+ static inline point_in_point_strategy_type get_point_in_point_strategy()
+ {
+ return point_in_point_strategy_type();
+ }
+
+ typedef within::spherical_point_point equals_point_point_strategy_type;
+
+ static inline equals_point_point_strategy_type get_equals_point_point_strategy()
+ {
+ return equals_point_point_strategy_type();
+ }
+
+ typedef disjoint::spherical_box_box disjoint_box_box_strategy_type;
+
+ static inline disjoint_box_box_strategy_type get_disjoint_box_box_strategy()
+ {
+ return disjoint_box_box_strategy_type();
+ }
+
+ typedef disjoint::segment_box_geographic
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ > disjoint_segment_box_strategy_type;
+
+ inline disjoint_segment_box_strategy_type get_disjoint_segment_box_strategy() const
+ {
+ return disjoint_segment_box_strategy_type(m_spheroid);
+ }
+
+ typedef covered_by::spherical_point_box disjoint_point_box_strategy_type;
+ typedef covered_by::spherical_point_box covered_by_point_box_strategy_type;
+ typedef within::spherical_point_box within_point_box_strategy_type;
+ typedef envelope::spherical_box envelope_box_strategy_type;
+ typedef expand::spherical_box expand_box_strategy_type;
+
enum intersection_point_flag { ipi_inters = 0, ipi_at_a1, ipi_at_a2, ipi_at_b1, ipi_at_b2 };
template <typename CoordinateType, typename SegmentRatio>
// Relate segments a and b
template
<
- typename Segment1,
- typename Segment2,
- typename Policy,
- typename RobustPolicy
+ typename UniqueSubRange1,
+ typename UniqueSubRange2,
+ typename Policy
>
- inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
- Policy const& policy,
- RobustPolicy const& robust_policy) const
- {
- typedef typename point_type<Segment1>::type point1_t;
- typedef typename point_type<Segment2>::type point2_t;
- point1_t a1, a2;
- point2_t b1, b2;
-
- detail::assign_point_from_index<0>(a, a1);
- detail::assign_point_from_index<1>(a, a2);
- detail::assign_point_from_index<0>(b, b1);
- detail::assign_point_from_index<1>(b, b2);
-
- return apply(a, b, policy, robust_policy, a1, a2, b1, b2);
- }
-
- // Relate segments a and b
- template
- <
- typename Segment1,
- typename Segment2,
- typename Policy,
- typename RobustPolicy,
- typename Point1,
- typename Point2
- >
- inline typename Policy::return_type apply(Segment1 const& a, Segment2 const& b,
- Policy const&, RobustPolicy const&,
- Point1 a1, Point1 a2, Point2 b1, Point2 b2) const
+ inline typename Policy::return_type apply(UniqueSubRange1 const& range_p,
+ UniqueSubRange2 const& range_q,
+ Policy const&) const
{
- bool is_a_reversed = get<1>(a1) > get<1>(a2);
- bool is_b_reversed = get<1>(b1) > get<1>(b2);
-
- if (is_a_reversed)
- {
- std::swap(a1, a2);
- }
-
- if (is_b_reversed)
- {
- std::swap(b1, b2);
- }
-
- return apply<Policy>(a, b, a1, a2, b1, b2, is_a_reversed, is_b_reversed);
+ typedef typename UniqueSubRange1::point_type point1_type;
+ typedef typename UniqueSubRange2::point_type point2_type;
+ typedef model::referring_segment<point1_type const> segment_type1;
+ typedef model::referring_segment<point2_type const> segment_type2;
+
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point1_type>) );
+ BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<point2_type>) );
+
+ /*
+ typename coordinate_type<Point1>::type
+ const a1_lon = get<0>(a1),
+ const a2_lon = get<0>(a2);
+ typename coordinate_type<Point2>::type
+ const b1_lon = get<0>(b1),
+ const b2_lon = get<0>(b2);
+ bool is_a_reversed = a1_lon > a2_lon || a1_lon == a2_lon && get<1>(a1) > get<1>(a2);
+ bool is_b_reversed = b1_lon > b2_lon || b1_lon == b2_lon && get<1>(b1) > get<1>(b2);
+ */
+
+ bool const is_p_reversed = get<1>(range_p.at(0)) > get<1>(range_p.at(1));
+ bool const is_q_reversed = get<1>(range_q.at(0)) > get<1>(range_q.at(1));
+
+ // Call apply with original segments and ordered points
+ return apply<Policy>(segment_type1(range_p.at(0), range_p.at(1)),
+ segment_type2(range_q.at(0), range_q.at(1)),
+ range_p.at(is_p_reversed ? 1 : 0),
+ range_p.at(is_p_reversed ? 0 : 1),
+ range_q.at(is_q_reversed ? 1 : 0),
+ range_q.at(is_q_reversed ? 0 : 1),
+ is_p_reversed, is_q_reversed);
}
private:
spheroid_type spheroid = formula::unit_spheroid<spheroid_type>(m_spheroid);
// TODO: check only 2 first coordinates here?
- using geometry::detail::equals::equals_point_point;
bool a_is_point = equals_point_point(a1, a2);
bool b_is_point = equals_point_point(b1, b2);
if (res_a1_a2.distance <= res_b1_b2.distance)
{
calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b1, res_a1_b2, dist_a1_a2, dist_a1_b1);
- calculate_collinear_data(a1, a2, b1, b2, res_a1_a2, res_a1_b2, res_a1_b1, dist_a1_a2, dist_a1_b2);
+ calculate_collinear_data(a1, a2, b2, b1, res_a1_a2, res_a1_b2, res_a1_b1, dist_a1_a2, dist_a1_b2);
dist_b1_b2 = dist_a1_b2 - dist_a1_b1;
dist_b1_a1 = -dist_a1_b1;
dist_b1_a2 = dist_a1_a2 - dist_a1_b1;
else
{
calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a1, res_b1_a2, dist_b1_b2, dist_b1_a1);
- calculate_collinear_data(b1, b2, a1, a2, res_b1_b2, res_b1_a2, res_b1_a1, dist_b1_b2, dist_b1_a2);
+ calculate_collinear_data(b1, b2, a2, a1, res_b1_b2, res_b1_a2, res_b1_a1, dist_b1_b2, dist_b1_a2);
dist_a1_a2 = dist_b1_a2 - dist_b1_a1;
dist_a1_b1 = -dist_b1_a1;
dist_a1_b2 = dist_b1_b2 - dist_b1_a1;
}
// NOTE: this is probably not needed
- calc_t const c0 = 0;
int a1_on_b = position_value(c0, dist_a1_b1, dist_a1_b2);
int a2_on_b = position_value(dist_a1_a2, dist_a1_b1, dist_a1_b2);
int b1_on_a = position_value(c0, dist_b1_a1, dist_b1_a2);
// in order to make this independent from is_near()
template <typename Point1, typename Point2, typename ResultInverse, typename CalcT>
static inline bool calculate_collinear_data(Point1 const& a1, Point1 const& a2, // in
- Point2 const& b1, Point2 const& b2, // in
+ Point2 const& b1, Point2 const& /*b2*/, // in
ResultInverse const& res_a1_a2, // in
ResultInverse const& res_a1_b1, // in
ResultInverse const& res_a1_b2, // in
CalcT& dist_a1_a2, // out
- CalcT& dist_a1_bi, // out
+ CalcT& dist_a1_b1, // out
bool degen_neq_coords = false) // in
{
dist_a1_a2 = res_a1_a2.distance;
- dist_a1_bi = res_a1_b1.distance;
+ dist_a1_b1 = res_a1_b1.distance;
if (! same_direction(res_a1_b1.azimuth, res_a1_a2.azimuth))
{
- dist_a1_bi = -dist_a1_bi;
+ dist_a1_b1 = -dist_a1_b1;
}
- // if i1 is close to a1 and b1 or b2 is equal to a1
- if (is_endpoint_equal(dist_a1_bi, a1, b1, b2))
+ // if b1 is close a1
+ if (is_endpoint_equal(dist_a1_b1, a1, b1))
{
- dist_a1_bi = 0;
+ dist_a1_b1 = 0;
return true;
}
- // or i1 is close to a2 and b1 or b2 is equal to a2
- else if (is_endpoint_equal(dist_a1_a2 - dist_a1_bi, a2, b1, b2))
+ // if b1 is close a2
+ else if (is_endpoint_equal(dist_a1_a2 - dist_a1_b1, a2, b1))
{
- dist_a1_bi = dist_a1_a2;
+ dist_a1_b1 = dist_a1_a2;
return true;
}
- // check the other endpoint of a very short segment near the pole
+ // check the other endpoint of degenerated segment near a pole
if (degen_neq_coords)
{
static CalcT const c0 = 0;
if (math::equals(res_a1_b2.distance, c0))
{
- dist_a1_bi = 0;
+ dist_a1_b1 = 0;
return true;
}
else if (math::equals(dist_a1_a2 - res_a1_b2.distance, c0))
{
- dist_a1_bi = dist_a1_a2;
+ dist_a1_b1 = dist_a1_a2;
return true;
}
}
// or i1 is on b
- return segment_ratio<CalcT>(dist_a1_bi, dist_a1_a2).on_segment();
+ return segment_ratio<CalcT>(dist_a1_b1, dist_a1_a2).on_segment();
}
template <typename Point1, typename Point2, typename CalcT, typename ResultInverse, typename Spheroid_>
dist_b1_b2 = res_b1_b2.distance;
// assign the IP if some endpoints overlap
- using geometry::detail::equals::equals_point_point;
if (equals_point_point(a1, b1))
{
lon = a1_lon;
return false;
}
+ typedef typename FormulaPolicy::template inverse<CalcT, true, false, false, false, false> inverse_dist;
+
ip_flag = ipi_inters;
if (is_on_b1)
{
lon = b1_lon;
lat = b1_lat;
+ dist_a1_ip = inverse_dist::apply(a1_lon, a1_lat, lon, lat, spheroid).distance; // for consistency
dist_b1_ip = 0;
ip_flag = ipi_at_b1;
}
{
lon = b2_lon;
lat = b2_lat;
+ dist_a1_ip = inverse_dist::apply(a1_lon, a1_lat, lon, lat, spheroid).distance; // for consistency
dist_b1_ip = res_b1_b2.distance;
ip_flag = ipi_at_b2;
}
lon = a1_lon;
lat = a1_lat;
dist_a1_ip = 0;
+ dist_b1_ip = inverse_dist::apply(b1_lon, b1_lat, lon, lat, spheroid).distance; // for consistency
ip_flag = ipi_at_a1;
}
else if (is_on_a2)
lon = a2_lon;
lat = a2_lat;
dist_a1_ip = res_a1_a2.distance;
+ dist_b1_ip = inverse_dist::apply(b1_lon, b1_lat, lon, lat, spheroid).distance; // for consistency
ip_flag = ipi_at_a2;
}
template <typename CalcT, typename P1, typename P2>
static inline bool is_endpoint_equal(CalcT const& dist,
- P1 const& ai, P2 const& b1, P2 const& b2)
+ P1 const& ai, P2 const& b1)
{
static CalcT const c0 = 0;
- using geometry::detail::equals::equals_point_point;
- return is_near(dist) && (equals_point_point(ai, b1) || equals_point_point(ai, b2) || math::equals(dist, c0));
+ return is_near(dist) && (math::equals(dist, c0) || equals_point_point(ai, b1));
}
template <typename CalcT>
ip_flag;
}
+ template <typename Point1, typename Point2>
+ static inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
+ {
+ return detail::equals::equals_point_point(point1, point2,
+ point_in_point_strategy_type());
+ }
+
private:
Spheroid m_spheroid;
};