1 // Boost.Geometry 2 3 // Copyright (c) 2016-2017, Oracle and/or its affiliates. 4 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 5 6 // Use, modification and distribution is subject to the Boost Software License, 7 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 // http://www.boost.org/LICENSE_1_0.txt) 9 10 #ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP 11 #define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP 12 13 14 #include <boost/geometry/srs/spheroid.hpp> 15 16 #include <boost/geometry/formulas/geographic.hpp> 17 18 #include <boost/geometry/strategies/spherical/intersection.hpp> 19 20 21 namespace boost { namespace geometry 22 { 23 24 namespace strategy { namespace intersection 25 { 26 27 template <typename Spheroid> 28 struct great_elliptic_segments_calc_policy 29 : spherical_segments_calc_policy 30 { great_elliptic_segments_calc_policyboost::geometry::strategy::intersection::great_elliptic_segments_calc_policy31 explicit great_elliptic_segments_calc_policy(Spheroid const& spheroid = Spheroid()) 32 : m_spheroid(spheroid) 33 {} 34 35 template <typename Point, typename Point3d> 36 Point from_cart3d(Point3d const& point_3d) const 37 { 38 return formula::cart3d_to_geo<Point>(point_3d, m_spheroid); 39 } 40 41 template <typename Point3d, typename Point> 42 Point3d to_cart3d(Point const& point) const 43 { 44 return formula::geo_to_cart3d<Point3d>(point, m_spheroid); 45 } 46 47 // relate_xxx_calc_policy must live londer than plane because it contains 48 // Spheroid object and plane keeps the reference to that object. 49 template <typename Point3d> 50 struct plane 51 { 52 typedef typename coordinate_type<Point3d>::type coord_t; 53 54 // not normalized planeboost::geometry::strategy::intersection::great_elliptic_segments_calc_policy::plane55 plane(Point3d const& p1, Point3d const& p2) 56 : normal(cross_product(p1, p2)) 57 {} 58 side_valueboost::geometry::strategy::intersection::great_elliptic_segments_calc_policy::plane59 int side_value(Point3d const& pt) const 60 { 61 return formula::sph_side_value(normal, pt); 62 } 63 cos_angle_betweenboost::geometry::strategy::intersection::great_elliptic_segments_calc_policy::plane64 coord_t cos_angle_between(Point3d const& p1, Point3d const& p2) const 65 { 66 Point3d v1 = p1; 67 detail::vec_normalize(v1); 68 Point3d v2 = p2; 69 detail::vec_normalize(v2); 70 71 return dot_product(v1, v2); 72 } 73 cos_angle_betweenboost::geometry::strategy::intersection::great_elliptic_segments_calc_policy::plane74 coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const 75 { 76 coord_t const c0 = 0; 77 78 Point3d v1 = p1; 79 detail::vec_normalize(v1); 80 Point3d v2 = p2; 81 detail::vec_normalize(v2); 82 83 is_forward = dot_product(normal, cross_product(v1, v2)) >= c0; 84 return dot_product(v1, v2); 85 } 86 87 Point3d normal; 88 }; 89 90 template <typename Point3d> get_planeboost::geometry::strategy::intersection::great_elliptic_segments_calc_policy91 plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2) const 92 { 93 return plane<Point3d>(p1, p2); 94 } 95 96 template <typename Point3d> intersection_pointsboost::geometry::strategy::intersection::great_elliptic_segments_calc_policy97 bool intersection_points(plane<Point3d> const& plane1, 98 plane<Point3d> const& plane2, 99 Point3d & ip1, Point3d & ip2) const 100 { 101 typedef typename coordinate_type<Point3d>::type coord_t; 102 103 Point3d id = cross_product(plane1.normal, plane2.normal); 104 // NOTE: the length should be greater than 0 at this point 105 // NOTE: no need to normalize in this case 106 107 ip1 = formula::projected_to_surface(id, m_spheroid); 108 109 ip2 = ip1; 110 multiply_value(ip2, coord_t(-1)); 111 112 return true; 113 } 114 115 private: 116 Spheroid m_spheroid; 117 }; 118 119 template <typename Spheroid> 120 struct experimental_elliptic_segments_calc_policy 121 { experimental_elliptic_segments_calc_policyboost::geometry::strategy::intersection::experimental_elliptic_segments_calc_policy122 explicit experimental_elliptic_segments_calc_policy(Spheroid const& spheroid = Spheroid()) 123 : m_spheroid(spheroid) 124 {} 125 126 template <typename Point, typename Point3d> 127 Point from_cart3d(Point3d const& point_3d) const 128 { 129 return formula::cart3d_to_geo<Point>(point_3d, m_spheroid); 130 } 131 132 template <typename Point3d, typename Point> 133 Point3d to_cart3d(Point const& point) const 134 { 135 return formula::geo_to_cart3d<Point3d>(point, m_spheroid); 136 } 137 138 // relate_xxx_calc_policy must live londer than plane because it contains 139 // Spheroid object and plane keeps the reference to that object. 140 template <typename Point3d> 141 struct plane 142 { 143 typedef typename coordinate_type<Point3d>::type coord_t; 144 145 // not normalized planeboost::geometry::strategy::intersection::experimental_elliptic_segments_calc_policy::plane146 plane(Point3d const& p1, Point3d const& p2, Spheroid const& spheroid) 147 : m_spheroid(spheroid) 148 { 149 formula::experimental_elliptic_plane(p1, p2, origin, normal, m_spheroid); 150 } 151 side_valueboost::geometry::strategy::intersection::experimental_elliptic_segments_calc_policy::plane152 int side_value(Point3d const& pt) const 153 { 154 return formula::elliptic_side_value(origin, normal, pt); 155 } 156 cos_angle_betweenboost::geometry::strategy::intersection::experimental_elliptic_segments_calc_policy::plane157 coord_t cos_angle_between(Point3d const& p1, Point3d const& p2) const 158 { 159 Point3d const v1 = normalized_vec(p1); 160 Point3d const v2 = normalized_vec(p2); 161 return dot_product(v1, v2); 162 } 163 cos_angle_betweenboost::geometry::strategy::intersection::experimental_elliptic_segments_calc_policy::plane164 coord_t cos_angle_between(Point3d const& p1, Point3d const& p2, bool & is_forward) const 165 { 166 coord_t const c0 = 0; 167 168 Point3d const v1 = normalized_vec(p1); 169 Point3d const v2 = normalized_vec(p2); 170 171 is_forward = dot_product(normal, cross_product(v1, v2)) >= c0; 172 return dot_product(v1, v2); 173 } 174 175 Point3d origin; 176 Point3d normal; 177 178 private: normalized_vecboost::geometry::strategy::intersection::experimental_elliptic_segments_calc_policy::plane179 Point3d normalized_vec(Point3d const& p) const 180 { 181 Point3d v = p; 182 subtract_point(v, origin); 183 detail::vec_normalize(v); 184 return v; 185 } 186 187 Spheroid const& m_spheroid; 188 }; 189 190 template <typename Point3d> get_planeboost::geometry::strategy::intersection::experimental_elliptic_segments_calc_policy191 plane<Point3d> get_plane(Point3d const& p1, Point3d const& p2) const 192 { 193 return plane<Point3d>(p1, p2, m_spheroid); 194 } 195 196 template <typename Point3d> intersection_pointsboost::geometry::strategy::intersection::experimental_elliptic_segments_calc_policy197 bool intersection_points(plane<Point3d> const& plane1, 198 plane<Point3d> const& plane2, 199 Point3d & ip1, Point3d & ip2) const 200 { 201 return formula::planes_spheroid_intersection(plane1.origin, plane1.normal, 202 plane2.origin, plane2.normal, 203 ip1, ip2, m_spheroid); 204 } 205 206 private: 207 Spheroid m_spheroid; 208 }; 209 210 211 template 212 < 213 typename Spheroid = srs::spheroid<double>, 214 typename CalculationType = void 215 > 216 struct great_elliptic_segments 217 : ecef_segments 218 < 219 great_elliptic_segments_calc_policy<Spheroid>, 220 CalculationType 221 > 222 {}; 223 224 template 225 < 226 typename Spheroid = srs::spheroid<double>, 227 typename CalculationType = void 228 > 229 struct experimental_elliptic_segments 230 : ecef_segments 231 < 232 experimental_elliptic_segments_calc_policy<Spheroid>, 233 CalculationType 234 > 235 {}; 236 237 238 }} // namespace strategy::intersection 239 240 }} // namespace boost::geometry 241 242 243 #endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_INTERSECTION_ELLIPTIC_HPP 244