// Boost.Geometry // Copyright (c) 2016-2017, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP #define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP #include #include #include namespace boost { namespace geometry { namespace strategy { namespace intersection { template struct great_elliptic_segments_calc_policy : spherical_segments_calc_policy { explicit great_elliptic_segments_calc_policy(Spheroid const& spheroid = Spheroid()) : m_spheroid(spheroid) {} template Point from_cart3d(Point3d const& point_3d) const { return formula::cart3d_to_geo(point_3d, m_spheroid); } template Point3d to_cart3d(Point const& point) const { return formula::geo_to_cart3d(point, m_spheroid); } // relate_xxx_calc_policy must live londer than plane because it contains // Spheroid object and plane keeps the reference to that object. template struct plane { typedef typename coordinate_type::type coord_t; // not normalized plane(Point3d const& p1, Point3d const& p2) : normal(cross_product(p1, p2)) {} int side_value(Point3d const& pt) const { return formula::sph_side_value(normal, pt); } coord_t cos_angle_between(Point3d const& p1, Point3d const& p2) const { Point3d v1 = p1; detail::vec_normalize(v1); Point3d v2 = p2; detail::vec_normalize(v2); return dot_product(v1, v2); } coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const { coord_t const c0 = 0; Point3d v1 = p1; detail::vec_normalize(v1); Point3d v2 = p2; detail::vec_normalize(v2); is_forward = dot_product(normal, cross_product(v1, v2)) >= c0; return dot_product(v1, v2); } Point3d normal; }; template plane get_plane(Point3d const& p1, Point3d const& p2) const { return plane(p1, p2); } template bool intersection_points(plane const& plane1, plane const& plane2, Point3d & ip1, Point3d & ip2) const { typedef typename coordinate_type::type coord_t; Point3d id = cross_product(plane1.normal, plane2.normal); // NOTE: the length should be greater than 0 at this point // NOTE: no need to normalize in this case ip1 = formula::projected_to_surface(id, m_spheroid); ip2 = ip1; multiply_value(ip2, coord_t(-1)); return true; } private: Spheroid m_spheroid; }; template struct experimental_elliptic_segments_calc_policy { explicit experimental_elliptic_segments_calc_policy(Spheroid const& spheroid = Spheroid()) : m_spheroid(spheroid) {} template Point from_cart3d(Point3d const& point_3d) const { return formula::cart3d_to_geo(point_3d, m_spheroid); } template Point3d to_cart3d(Point const& point) const { return formula::geo_to_cart3d(point, m_spheroid); } // relate_xxx_calc_policy must live londer than plane because it contains // Spheroid object and plane keeps the reference to that object. template struct plane { typedef typename coordinate_type::type coord_t; // not normalized plane(Point3d const& p1, Point3d const& p2, Spheroid const& spheroid) : m_spheroid(spheroid) { formula::experimental_elliptic_plane(p1, p2, origin, normal, m_spheroid); } int side_value(Point3d const& pt) const { return formula::elliptic_side_value(origin, normal, pt); } coord_t cos_angle_between(Point3d const& p1, Point3d const& p2) const { Point3d const v1 = normalized_vec(p1); Point3d const v2 = normalized_vec(p2); return dot_product(v1, v2); } coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const { coord_t const c0 = 0; Point3d const v1 = normalized_vec(p1); Point3d const v2 = normalized_vec(p2); is_forward = dot_product(normal, cross_product(v1, v2)) >= c0; return dot_product(v1, v2); } Point3d origin; Point3d normal; private: Point3d normalized_vec(Point3d const& p) const { Point3d v = p; subtract_point(v, origin); detail::vec_normalize(v); return v; } Spheroid const& m_spheroid; }; template plane get_plane(Point3d const& p1, Point3d const& p2) const { return plane(p1, p2, m_spheroid); } template bool intersection_points(plane const& plane1, plane const& plane2, Point3d & ip1, Point3d & ip2) const { return formula::planes_spheroid_intersection(plane1.origin, plane1.normal, plane2.origin, plane2.normal, ip1, ip2, m_spheroid); } private: Spheroid m_spheroid; }; template < typename Spheroid = srs::spheroid, typename CalculationType = void > struct great_elliptic_segments : ecef_segments < great_elliptic_segments_calc_policy, CalculationType > {}; template < typename Spheroid = srs::spheroid, typename CalculationType = void > struct experimental_elliptic_segments : ecef_segments < experimental_elliptic_segments_calc_policy, CalculationType > {}; }} // namespace strategy::intersection }} // namespace boost::geometry #endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP