]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/strategies/cartesian/distance_projected_point.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / geometry / strategies / cartesian / distance_projected_point.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
3// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
4// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands.
5// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
6
92f5a8d4
TL
7// This file was modified by Oracle on 2014, 2018, 2019.
8// Modifications copyright (c) 2014-2019, Oracle and/or its affiliates.
7c673cae
FG
9
10// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
92f5a8d4 11// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
7c673cae
FG
12
13// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
15
16// Use, modification and distribution is subject to the Boost Software License,
17// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18// http://www.boost.org/LICENSE_1_0.txt)
19
20#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
21#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
22
23
24#include <boost/concept_check.hpp>
92f5a8d4 25#include <boost/core/ignore_unused.hpp>
7c673cae
FG
26#include <boost/mpl/if.hpp>
27#include <boost/type_traits/is_void.hpp>
28
29#include <boost/geometry/core/access.hpp>
30#include <boost/geometry/core/point_type.hpp>
31
32#include <boost/geometry/algorithms/convert.hpp>
33#include <boost/geometry/arithmetic/arithmetic.hpp>
34#include <boost/geometry/arithmetic/dot_product.hpp>
35
36#include <boost/geometry/strategies/tags.hpp>
37#include <boost/geometry/strategies/distance.hpp>
38#include <boost/geometry/strategies/default_distance_result.hpp>
39#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
92f5a8d4
TL
40#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
41#include <boost/geometry/strategies/cartesian/intersection.hpp>
7c673cae
FG
42
43#include <boost/geometry/util/select_coordinate_type.hpp>
44
45// Helper geometry (projected point on line)
46#include <boost/geometry/geometries/point.hpp>
47
48
49namespace boost { namespace geometry
50{
51
52
53namespace strategy { namespace distance
54{
55
56/*!
57\brief Strategy for distance point to segment
58\ingroup strategies
59\details Calculates distance using projected-point method, and (optionally) Pythagoras
60\author Adapted from: http://geometryalgorithms.com/Archive/algorithm_0102/algorithm_0102.htm
61\tparam CalculationType \tparam_calculation
62\tparam Strategy underlying point-point distance strategy
63\par Concepts for Strategy:
64- cartesian_distance operator(Point,Point)
65\note If the Strategy is a "comparable::pythagoras", this strategy
66 automatically is a comparable projected_point strategy (so without sqrt)
67
68\qbk{
69[heading See also]
70[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
71}
72
73*/
74template
75<
76 typename CalculationType = void,
77 typename Strategy = pythagoras<CalculationType>
78>
79class projected_point
80{
81public :
92f5a8d4
TL
82 typedef within::cartesian_point_point equals_point_point_strategy_type;
83
84 typedef intersection::cartesian_segments
85 <
86 CalculationType
87 > relate_segment_segment_strategy_type;
88
89 static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy()
90 {
91 return relate_segment_segment_strategy_type();
92 }
93
94 typedef within::cartesian_winding
95 <
96 void, void, CalculationType
97 > point_in_geometry_strategy_type;
98
99 static inline point_in_geometry_strategy_type get_point_in_geometry_strategy()
100 {
101 return point_in_geometry_strategy_type();
102 }
103
7c673cae
FG
104 // The three typedefs below are necessary to calculate distances
105 // from segments defined in integer coordinates.
106
107 // Integer coordinates can still result in FP distances.
108 // There is a division, which must be represented in FP.
109 // So promote.
110 template <typename Point, typename PointOfSegment>
111 struct calculation_type
112 : promote_floating_point
113 <
114 typename strategy::distance::services::return_type
115 <
116 Strategy,
117 Point,
118 PointOfSegment
119 >::type
120 >
121 {};
122
7c673cae
FG
123 template <typename Point, typename PointOfSegment>
124 inline typename calculation_type<Point, PointOfSegment>::type
125 apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
126 {
127 assert_dimension_equal<Point, PointOfSegment>();
128
129 typedef typename calculation_type<Point, PointOfSegment>::type calculation_type;
130
131 // A projected point of points in Integer coordinates must be able to be
132 // represented in FP.
133 typedef model::point
134 <
135 calculation_type,
136 dimension<PointOfSegment>::value,
137 typename coordinate_system<PointOfSegment>::type
138 > fp_point_type;
139
140 // For convenience
141 typedef fp_point_type fp_vector_type;
142
143 /*
144 Algorithm [p: (px,py), p1: (x1,y1), p2: (x2,y2)]
145 VECTOR v(x2 - x1, y2 - y1)
146 VECTOR w(px - x1, py - y1)
147 c1 = w . v
148 c2 = v . v
149 b = c1 / c2
150 RETURN POINT(x1 + b * vx, y1 + b * vy)
151 */
152
153 // v is multiplied below with a (possibly) FP-value, so should be in FP
154 // For consistency we define w also in FP
155 fp_vector_type v, w, projected;
156
157 geometry::convert(p2, v);
158 geometry::convert(p, w);
159 geometry::convert(p1, projected);
160 subtract_point(v, projected);
161 subtract_point(w, projected);
162
163 Strategy strategy;
92f5a8d4 164 boost::ignore_unused(strategy);
7c673cae
FG
165
166 calculation_type const zero = calculation_type();
167 calculation_type const c1 = dot_product(w, v);
168 if (c1 <= zero)
169 {
170 return strategy.apply(p, p1);
171 }
172 calculation_type const c2 = dot_product(v, v);
173 if (c2 <= c1)
174 {
175 return strategy.apply(p, p2);
176 }
177
178 // See above, c1 > 0 AND c2 > c1 so: c2 != 0
179 calculation_type const b = c1 / c2;
180
181 multiply_value(v, b);
182 add_point(projected, v);
183
184 return strategy.apply(p, projected);
185 }
92f5a8d4
TL
186
187 template <typename CT>
188 inline CT vertical_or_meridian(CT const& lat1, CT const& lat2) const
189 {
190 return lat1 - lat2;
191 }
192
7c673cae
FG
193};
194
195#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
196namespace services
197{
198
199template <typename CalculationType, typename Strategy>
200struct tag<projected_point<CalculationType, Strategy> >
201{
202 typedef strategy_tag_distance_point_segment type;
203};
204
205
206template <typename CalculationType, typename Strategy, typename P, typename PS>
207struct return_type<projected_point<CalculationType, Strategy>, P, PS>
208 : projected_point<CalculationType, Strategy>::template calculation_type<P, PS>
209{};
210
211
212
213template <typename CalculationType, typename Strategy>
214struct comparable_type<projected_point<CalculationType, Strategy> >
215{
216 // Define a projected_point strategy with its underlying point-point-strategy
217 // being comparable
218 typedef projected_point
219 <
220 CalculationType,
221 typename comparable_type<Strategy>::type
222 > type;
223};
224
225
226template <typename CalculationType, typename Strategy>
227struct get_comparable<projected_point<CalculationType, Strategy> >
228{
229 typedef typename comparable_type
230 <
231 projected_point<CalculationType, Strategy>
232 >::type comparable_type;
233public :
234 static inline comparable_type apply(projected_point<CalculationType, Strategy> const& )
235 {
236 return comparable_type();
237 }
238};
239
240
241template <typename CalculationType, typename Strategy, typename P, typename PS>
242struct result_from_distance<projected_point<CalculationType, Strategy>, P, PS>
243{
244private :
245 typedef typename return_type<projected_point<CalculationType, Strategy>, P, PS>::type return_type;
246public :
247 template <typename T>
248 static inline return_type apply(projected_point<CalculationType, Strategy> const& , T const& value)
249 {
250 Strategy s;
251 return result_from_distance<Strategy, P, PS>::apply(s, value);
252 }
253};
254
255
256// Get default-strategy for point-segment distance calculation
257// while still have the possibility to specify point-point distance strategy (PPS)
258// It is used in algorithms/distance.hpp where users specify PPS for distance
259// of point-to-segment or point-to-linestring.
260// Convenient for geographic coordinate systems especially.
261template <typename Point, typename PointOfSegment, typename Strategy>
262struct default_strategy
263 <
264 point_tag, segment_tag, Point, PointOfSegment,
265 cartesian_tag, cartesian_tag, Strategy
266 >
267{
268 typedef strategy::distance::projected_point
269 <
270 void,
271 typename boost::mpl::if_
272 <
273 boost::is_void<Strategy>,
274 typename default_strategy
275 <
276 point_tag, point_tag, Point, PointOfSegment,
277 cartesian_tag, cartesian_tag
278 >::type,
279 Strategy
280 >::type
281 > type;
282};
283
284template <typename PointOfSegment, typename Point, typename Strategy>
285struct default_strategy
286 <
287 segment_tag, point_tag, PointOfSegment, Point,
288 cartesian_tag, cartesian_tag, Strategy
289 >
290{
291 typedef typename default_strategy
292 <
293 point_tag, segment_tag, Point, PointOfSegment,
294 cartesian_tag, cartesian_tag, Strategy
295 >::type type;
296};
297
298
299} // namespace services
300#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
301
302
303}} // namespace strategy::distance
304
305
306}} // namespace boost::geometry
307
308
309#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP