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