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