]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / distance / segment_to_box.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
1e59de90 3// Copyright (c) 2014-2021 Oracle and/or its affiliates.
7c673cae 4
92f5a8d4 5// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
7c673cae 6// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
92f5a8d4 7// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
7c673cae
FG
8
9// Licensed under the Boost Software License version 1.0.
10// http://www.boost.org/users/license.html
11
12#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
13#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
14
15#include <cstddef>
7c673cae 16#include <functional>
20effc67 17#include <type_traits>
7c673cae
FG
18#include <vector>
19
20#include <boost/core/ignore_unused.hpp>
7c673cae 21#include <boost/numeric/conversion/cast.hpp>
7c673cae 22
7c673cae
FG
23#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
24#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
92f5a8d4
TL
25#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
26#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
7c673cae 27#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
1e59de90
TL
28#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
29#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
92f5a8d4 30#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
7c673cae 31#include <boost/geometry/algorithms/dispatch/distance.hpp>
92f5a8d4 32#include <boost/geometry/algorithms/not_implemented.hpp>
7c673cae 33
1e59de90
TL
34#include <boost/geometry/core/access.hpp>
35#include <boost/geometry/core/assert.hpp>
36#include <boost/geometry/core/closure.hpp>
37#include <boost/geometry/core/coordinate_dimension.hpp>
38#include <boost/geometry/core/point_type.hpp>
39#include <boost/geometry/core/tags.hpp>
40
92f5a8d4
TL
41#include <boost/geometry/policies/compare.hpp>
42
43#include <boost/geometry/util/calculation_type.hpp>
44#include <boost/geometry/util/condition.hpp>
45#include <boost/geometry/util/has_nan_coordinate.hpp>
46#include <boost/geometry/util/math.hpp>
47
48#include <boost/geometry/strategies/disjoint.hpp>
49#include <boost/geometry/strategies/distance.hpp>
50#include <boost/geometry/strategies/tags.hpp>
7c673cae 51
7c673cae
FG
52namespace boost { namespace geometry
53{
54
55
56#ifndef DOXYGEN_NO_DETAIL
57namespace detail { namespace distance
58{
59
60
1e59de90
TL
61template <typename Segment, typename Box, typename Strategy>
62inline bool intersects_segment_box(Segment const& segment, Box const& box,
63 Strategy const& strategy)
92f5a8d4 64{
1e59de90 65 return ! detail::disjoint::disjoint_segment_box::apply(segment, box, strategy);
92f5a8d4
TL
66}
67
1e59de90
TL
68// TODO: segment_to_box_2D_generic is not used anymore. Remove?
69
70// TODO: Furthermore this utility can potentially use different strategy than
71// the one that was passed into bg::distance() but it seems this is by design.
92f5a8d4 72
7c673cae
FG
73template
74<
75 typename Segment,
76 typename Box,
1e59de90
TL
77 typename Strategies,
78 bool UsePointBoxStrategy = false // use only PointSegment strategy
7c673cae
FG
79>
80class segment_to_box_2D_generic
81{
82private:
83 typedef typename point_type<Segment>::type segment_point;
84 typedef typename point_type<Box>::type box_point;
85
1e59de90 86 typedef distance::strategy_t<box_point, Segment, Strategies> ps_strategy_type;
7c673cae
FG
87
88 typedef detail::closest_feature::point_to_point_range
89 <
90 segment_point,
91 std::vector<box_point>,
1e59de90 92 open
7c673cae 93 > point_to_point_range;
7c673cae
FG
94
95public:
1e59de90
TL
96 // TODO: Or should the return type be defined by sb_strategy_type?
97 typedef distance::return_t<box_point, Segment, Strategies> return_type;
7c673cae
FG
98
99 static inline return_type apply(Segment const& segment,
100 Box const& box,
1e59de90 101 Strategies const& strategies,
7c673cae
FG
102 bool check_intersection = true)
103 {
1e59de90 104 if (check_intersection && intersects_segment_box(segment, box, strategies))
7c673cae 105 {
1e59de90 106 return return_type(0);
7c673cae
FG
107 }
108
7c673cae
FG
109 // get segment points
110 segment_point p[2];
111 detail::assign_point_from_index<0>(segment, p[0]);
112 detail::assign_point_from_index<1>(segment, p[1]);
113
114 // get box points
115 std::vector<box_point> box_points(4);
116 detail::assign_box_corners_oriented<true>(box, box_points);
117
1e59de90
TL
118 ps_strategy_type const strategy = strategies.distance(dummy_point(), dummy_segment());
119
120 auto const cstrategy = strategy::distance::services::get_comparable
121 <
122 ps_strategy_type
123 >::apply(strategy);
124
125 distance::creturn_t<box_point, Segment, Strategies> cd[6];
7c673cae
FG
126 for (unsigned int i = 0; i < 4; ++i)
127 {
128 cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
129 }
130
131 std::pair
132 <
133 typename std::vector<box_point>::const_iterator,
134 typename std::vector<box_point>::const_iterator
135 > bit_min[2];
136
137 bit_min[0] = point_to_point_range::apply(p[0],
138 box_points.begin(),
139 box_points.end(),
140 cstrategy,
141 cd[4]);
142 bit_min[1] = point_to_point_range::apply(p[1],
143 box_points.begin(),
144 box_points.end(),
145 cstrategy,
146 cd[5]);
147
148 unsigned int imin = 0;
149 for (unsigned int i = 1; i < 6; ++i)
150 {
151 if (cd[i] < cd[imin])
152 {
153 imin = i;
154 }
155 }
156
1e59de90 157 if (BOOST_GEOMETRY_CONDITION(is_comparable<ps_strategy_type>::value))
7c673cae
FG
158 {
159 return cd[imin];
160 }
161
162 if (imin < 4)
163 {
1e59de90 164 return strategy.apply(box_points[imin], p[0], p[1]);
7c673cae
FG
165 }
166 else
167 {
168 unsigned int bimin = imin - 4;
1e59de90 169 return strategy.apply(p[bimin],
7c673cae
FG
170 *bit_min[bimin].first,
171 *bit_min[bimin].second);
172 }
173 }
174};
175
176
177template
178<
179 typename Segment,
180 typename Box,
1e59de90 181 typename Strategies
7c673cae 182>
1e59de90 183class segment_to_box_2D_generic<Segment, Box, Strategies, true> // Use both PointSegment and PointBox strategies
7c673cae
FG
184{
185private:
186 typedef typename point_type<Segment>::type segment_point;
187 typedef typename point_type<Box>::type box_point;
188
1e59de90
TL
189 typedef distance::strategy_t<box_point, Segment, Strategies> ps_strategy_type;
190 typedef distance::strategy_t<segment_point, Box, Strategies> pb_strategy_type;
7c673cae
FG
191
192public:
1e59de90
TL
193 // TODO: Or should the return type be defined by sb_strategy_type?
194 typedef distance::return_t<box_point, Segment, Strategies> return_type;
195
7c673cae
FG
196 static inline return_type apply(Segment const& segment,
197 Box const& box,
1e59de90 198 Strategies const& strategies,
7c673cae
FG
199 bool check_intersection = true)
200 {
1e59de90 201 if (check_intersection && intersects_segment_box(segment, box, strategies))
7c673cae 202 {
1e59de90 203 return return_type(0);
7c673cae
FG
204 }
205
7c673cae
FG
206 // get segment points
207 segment_point p[2];
208 detail::assign_point_from_index<0>(segment, p[0]);
209 detail::assign_point_from_index<1>(segment, p[1]);
210
211 // get box points
212 std::vector<box_point> box_points(4);
213 detail::assign_box_corners_oriented<true>(box, box_points);
1e59de90
TL
214
215 distance::creturn_t<box_point, Segment, Strategies> cd[6];
216
217 ps_strategy_type ps_strategy = strategies.distance(dummy_point(), dummy_segment());
218 auto const ps_cstrategy = strategy::distance::services::get_comparable
219 <
220 ps_strategy_type
221 >::apply(ps_strategy);
222 boost::ignore_unused(ps_strategy, ps_cstrategy);
223
7c673cae
FG
224 for (unsigned int i = 0; i < 4; ++i)
225 {
1e59de90 226 cd[i] = ps_cstrategy.apply(box_points[i], p[0], p[1]);
7c673cae
FG
227 }
228
1e59de90
TL
229 pb_strategy_type const pb_strategy = strategies.distance(dummy_point(), dummy_box());
230 auto const pb_cstrategy = strategy::distance::services::get_comparable
231 <
232 pb_strategy_type
233 >::apply(pb_strategy);
234 boost::ignore_unused(pb_strategy, pb_cstrategy);
235
7c673cae
FG
236 cd[4] = pb_cstrategy.apply(p[0], box);
237 cd[5] = pb_cstrategy.apply(p[1], box);
238
239 unsigned int imin = 0;
240 for (unsigned int i = 1; i < 6; ++i)
241 {
242 if (cd[i] < cd[imin])
243 {
244 imin = i;
245 }
246 }
247
7c673cae
FG
248 if (imin < 4)
249 {
1e59de90
TL
250 if (is_comparable<ps_strategy_type>::value)
251 {
252 return cd[imin];
253 }
254
255 return ps_strategy.apply(box_points[imin], p[0], p[1]);
7c673cae
FG
256 }
257 else
258 {
1e59de90
TL
259 if (is_comparable<pb_strategy_type>::value)
260 {
261 return cd[imin];
262 }
263
264 return pb_strategy.apply(p[imin - 4], box);
7c673cae
FG
265 }
266 }
267};
268
269
270
271
272template
273<
274 typename ReturnType,
275 typename SegmentPoint,
276 typename BoxPoint,
1e59de90 277 typename Strategies
7c673cae
FG
278>
279class segment_to_box_2D
280{
281private:
282 template <typename Result>
283 struct cast_to_result
284 {
285 template <typename T>
286 static inline Result apply(T const& t)
287 {
288 return boost::numeric_cast<Result>(t);
289 }
290 };
291
292
293 template <typename T, bool IsLess /* true */>
294 struct compare_less_equal
295 {
296 typedef compare_less_equal<T, !IsLess> other;
297
298 template <typename T1, typename T2>
299 inline bool operator()(T1 const& t1, T2 const& t2) const
300 {
301 return std::less_equal<T>()(cast_to_result<T>::apply(t1),
302 cast_to_result<T>::apply(t2));
303 }
304 };
305
306 template <typename T>
307 struct compare_less_equal<T, false>
308 {
309 typedef compare_less_equal<T, true> other;
310
311 template <typename T1, typename T2>
312 inline bool operator()(T1 const& t1, T2 const& t2) const
313 {
314 return std::greater_equal<T>()(cast_to_result<T>::apply(t1),
315 cast_to_result<T>::apply(t2));
316 }
317 };
318
319
320 template <typename LessEqual>
321 struct other_compare
322 {
323 typedef typename LessEqual::other type;
324 };
325
326
327 // it is assumed here that p0 lies to the right of the box (so the
328 // entire segment lies to the right of the box)
329 template <typename LessEqual>
330 struct right_of_box
331 {
332 static inline ReturnType apply(SegmentPoint const& p0,
333 SegmentPoint const& p1,
334 BoxPoint const& bottom_right,
335 BoxPoint const& top_right,
1e59de90 336 Strategies const& strategies)
7c673cae 337 {
7c673cae
FG
338 // the implementation below is written for non-negative slope
339 // segments
340 //
341 // for negative slope segments swap the roles of bottom_right
342 // and top_right and use greater_equal instead of less_equal.
343
344 typedef cast_to_result<ReturnType> cast;
345
346 LessEqual less_equal;
347
1e59de90 348 auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
92f5a8d4
TL
349
350 if (less_equal(geometry::get<1>(bottom_right), geometry::get<1>(p0)))
7c673cae 351 {
92f5a8d4
TL
352 //if p0 is in box's band
353 if (less_equal(geometry::get<1>(p0), geometry::get<1>(top_right)))
354 {
355 // segment & crosses band (TODO:merge with box-box dist)
356 if (math::equals(geometry::get<0>(p0), geometry::get<0>(p1)))
357 {
358 SegmentPoint high = geometry::get<1>(p1) > geometry::get<1>(p0) ? p1 : p0;
359 if (less_equal(geometry::get<1>(high), geometry::get<1>(top_right)))
360 {
361 return cast::apply(ps_strategy.apply(high, bottom_right, top_right));
362 }
363 return cast::apply(ps_strategy.apply(top_right, p0, p1));
364 }
365 return cast::apply(ps_strategy.apply(p0, bottom_right, top_right));
366 }
367 // distance is realized between the top-right
368 // corner of the box and the segment
369 return cast::apply(ps_strategy.apply(top_right, p0, p1));
7c673cae
FG
370 }
371 else
372 {
373 // distance is realized between the bottom-right
374 // corner of the box and the segment
375 return cast::apply(ps_strategy.apply(bottom_right, p0, p1));
376 }
377 }
378 };
379
7c673cae
FG
380 // it is assumed here that p0 lies above the box (so the
381 // entire segment lies above the box)
92f5a8d4 382
7c673cae
FG
383 template <typename LessEqual>
384 struct above_of_box
385 {
92f5a8d4 386
7c673cae
FG
387 static inline ReturnType apply(SegmentPoint const& p0,
388 SegmentPoint const& p1,
389 BoxPoint const& top_left,
1e59de90 390 Strategies const& strategies)
7c673cae 391 {
1e59de90 392 return apply(p0, p1, p0, top_left, strategies);
92f5a8d4 393 }
7c673cae 394
92f5a8d4
TL
395 static inline ReturnType apply(SegmentPoint const& p0,
396 SegmentPoint const& p1,
397 SegmentPoint const& p_max,
398 BoxPoint const& top_left,
1e59de90 399 Strategies const& strategies)
92f5a8d4 400 {
1e59de90
TL
401 auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
402
7c673cae 403 typedef cast_to_result<ReturnType> cast;
7c673cae
FG
404 LessEqual less_equal;
405
92f5a8d4
TL
406 // p0 is above the upper segment of the box (and inside its band)
407 // then compute the vertical (i.e. meridian for spherical) distance
408 if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p_max)))
7c673cae 409 {
1e59de90 410 ReturnType diff = ps_strategy.vertical_or_meridian(
92f5a8d4
TL
411 geometry::get_as_radian<1>(p_max),
412 geometry::get_as_radian<1>(top_left));
413
7c673cae
FG
414 return strategy::distance::services::result_from_distance
415 <
1e59de90
TL
416 std::remove_const_t<decltype(ps_strategy)>,
417 SegmentPoint, BoxPoint
418 >::apply(ps_strategy, math::abs(diff));
7c673cae
FG
419 }
420
421 // p0 is to the left of the box, but p1 is above the box
422 // in this case the distance is realized between the
423 // top-left corner of the box and the segment
1e59de90 424 return cast::apply(ps_strategy.apply(top_left, p0, p1));
7c673cae
FG
425 }
426 };
427
7c673cae
FG
428 template <typename LessEqual>
429 struct check_right_left_of_box
430 {
431 static inline bool apply(SegmentPoint const& p0,
432 SegmentPoint const& p1,
433 BoxPoint const& top_left,
434 BoxPoint const& top_right,
435 BoxPoint const& bottom_left,
436 BoxPoint const& bottom_right,
1e59de90 437 Strategies const& strategies,
7c673cae
FG
438 ReturnType& result)
439 {
440 // p0 lies to the right of the box
441 if (geometry::get<0>(p0) >= geometry::get<0>(top_right))
442 {
443 result = right_of_box
444 <
445 LessEqual
446 >::apply(p0, p1, bottom_right, top_right,
1e59de90 447 strategies);
7c673cae
FG
448 return true;
449 }
450
451 // p1 lies to the left of the box
452 if (geometry::get<0>(p1) <= geometry::get<0>(bottom_left))
453 {
454 result = right_of_box
455 <
456 typename other_compare<LessEqual>::type
457 >::apply(p1, p0, top_left, bottom_left,
1e59de90 458 strategies);
7c673cae
FG
459 return true;
460 }
461
462 return false;
463 }
464 };
465
7c673cae
FG
466 template <typename LessEqual>
467 struct check_above_below_of_box
468 {
469 static inline bool apply(SegmentPoint const& p0,
470 SegmentPoint const& p1,
471 BoxPoint const& top_left,
472 BoxPoint const& top_right,
473 BoxPoint const& bottom_left,
474 BoxPoint const& bottom_right,
1e59de90 475 Strategies const& strategies,
7c673cae
FG
476 ReturnType& result)
477 {
92f5a8d4
TL
478 typedef compare_less_equal<ReturnType, false> GreaterEqual;
479
7c673cae
FG
480 // the segment lies below the box
481 if (geometry::get<1>(p1) < geometry::get<1>(bottom_left))
482 {
1e59de90
TL
483 auto const sb_strategy = strategies.distance(dummy_segment(), dummy_box());
484
485 // TODO: this strategy calls this algorithm's again, specifically:
486 // geometry::detail::distance::segment_to_box_2D<>::call_above_of_box
487 // If possible rewrite them to avoid this.
488 // For now just pass umbrella strategy.
92f5a8d4
TL
489 result = sb_strategy.template segment_below_of_box
490 <
491 LessEqual,
492 ReturnType
493 >(p0, p1,
494 top_left, top_right,
1e59de90
TL
495 bottom_left, bottom_right,
496 strategies);
7c673cae
FG
497 return true;
498 }
499
500 // the segment lies above the box
501 if (geometry::get<1>(p0) > geometry::get<1>(top_right))
502 {
92f5a8d4
TL
503 result = (std::min)(above_of_box
504 <
505 LessEqual
1e59de90 506 >::apply(p0, p1, top_left, strategies),
92f5a8d4
TL
507 above_of_box
508 <
509 GreaterEqual
1e59de90 510 >::apply(p1, p0, top_right, strategies));
7c673cae
FG
511 return true;
512 }
513 return false;
514 }
515 };
516
517 struct check_generic_position
518 {
519 static inline bool apply(SegmentPoint const& p0,
520 SegmentPoint const& p1,
7c673cae
FG
521 BoxPoint const& corner1,
522 BoxPoint const& corner2,
1e59de90 523 Strategies const& strategies,
7c673cae
FG
524 ReturnType& result)
525 {
1e59de90
TL
526 auto const side_strategy = strategies.side();
527 auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
7c673cae 528
92f5a8d4 529 typedef cast_to_result<ReturnType> cast;
7c673cae 530 ReturnType diff1 = cast::apply(geometry::get<1>(p1))
92f5a8d4 531 - cast::apply(geometry::get<1>(p0));
7c673cae 532
92f5a8d4
TL
533 int sign = diff1 < 0 ? -1 : 1;
534 if (side_strategy.apply(p0, p1, corner1) * sign < 0)
7c673cae
FG
535 {
536 result = cast::apply(ps_strategy.apply(corner1, p0, p1));
537 return true;
538 }
92f5a8d4 539 if (side_strategy.apply(p0, p1, corner2) * sign > 0)
7c673cae
FG
540 {
541 result = cast::apply(ps_strategy.apply(corner2, p0, p1));
542 return true;
543 }
544 return false;
545 }
546 };
547
548 static inline ReturnType
549 non_negative_slope_segment(SegmentPoint const& p0,
550 SegmentPoint const& p1,
551 BoxPoint const& top_left,
552 BoxPoint const& top_right,
553 BoxPoint const& bottom_left,
554 BoxPoint const& bottom_right,
1e59de90 555 Strategies const& strategies)
7c673cae
FG
556 {
557 typedef compare_less_equal<ReturnType, true> less_equal;
558
559 // assert that the segment has non-negative slope
560 BOOST_GEOMETRY_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1))
561 && geometry::get<1>(p0) < geometry::get<1>(p1))
562 ||
563 ( geometry::get<0>(p0) < geometry::get<0>(p1)
564 && geometry::get<1>(p0) <= geometry::get<1>(p1) )
565 || geometry::has_nan_coordinate(p0)
566 || geometry::has_nan_coordinate(p1));
567
568 ReturnType result(0);
569
570 if (check_right_left_of_box
571 <
572 less_equal
573 >::apply(p0, p1,
574 top_left, top_right, bottom_left, bottom_right,
1e59de90 575 strategies, result))
7c673cae
FG
576 {
577 return result;
578 }
579
580 if (check_above_below_of_box
581 <
582 less_equal
583 >::apply(p0, p1,
584 top_left, top_right, bottom_left, bottom_right,
1e59de90 585 strategies, result))
7c673cae
FG
586 {
587 return result;
588 }
589
590 if (check_generic_position::apply(p0, p1,
7c673cae 591 top_left, bottom_right,
1e59de90 592 strategies, result))
7c673cae
FG
593 {
594 return result;
595 }
596
597 // in all other cases the box and segment intersect, so return 0
598 return result;
599 }
600
601
602 static inline ReturnType
603 negative_slope_segment(SegmentPoint const& p0,
604 SegmentPoint const& p1,
605 BoxPoint const& top_left,
606 BoxPoint const& top_right,
607 BoxPoint const& bottom_left,
608 BoxPoint const& bottom_right,
1e59de90 609 Strategies const& strategies)
7c673cae
FG
610 {
611 typedef compare_less_equal<ReturnType, false> greater_equal;
612
613 // assert that the segment has negative slope
614 BOOST_GEOMETRY_ASSERT( ( geometry::get<0>(p0) < geometry::get<0>(p1)
615 && geometry::get<1>(p0) > geometry::get<1>(p1) )
616 || geometry::has_nan_coordinate(p0)
617 || geometry::has_nan_coordinate(p1) );
618
619 ReturnType result(0);
620
621 if (check_right_left_of_box
622 <
623 greater_equal
624 >::apply(p0, p1,
625 bottom_left, bottom_right, top_left, top_right,
1e59de90 626 strategies, result))
7c673cae
FG
627 {
628 return result;
629 }
630
631 if (check_above_below_of_box
632 <
633 greater_equal
634 >::apply(p1, p0,
635 top_right, top_left, bottom_right, bottom_left,
1e59de90 636 strategies, result))
7c673cae
FG
637 {
638 return result;
639 }
640
641 if (check_generic_position::apply(p0, p1,
642 bottom_left, top_right,
1e59de90 643 strategies, result))
7c673cae
FG
644 {
645 return result;
646 }
647
648 // in all other cases the box and segment intersect, so return 0
649 return result;
650 }
651
652public:
653 static inline ReturnType apply(SegmentPoint const& p0,
654 SegmentPoint const& p1,
655 BoxPoint const& top_left,
656 BoxPoint const& top_right,
657 BoxPoint const& bottom_left,
658 BoxPoint const& bottom_right,
1e59de90 659 Strategies const& strategies)
7c673cae 660 {
1e59de90 661 BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, typename Strategies::cs_tag>()(p0, p1))
7c673cae
FG
662 || geometry::has_nan_coordinate(p0)
663 || geometry::has_nan_coordinate(p1) );
664
665 if (geometry::get<0>(p0) < geometry::get<0>(p1)
666 && geometry::get<1>(p0) > geometry::get<1>(p1))
667 {
668 return negative_slope_segment(p0, p1,
669 top_left, top_right,
670 bottom_left, bottom_right,
1e59de90 671 strategies);
7c673cae
FG
672 }
673
674 return non_negative_slope_segment(p0, p1,
675 top_left, top_right,
676 bottom_left, bottom_right,
1e59de90 677 strategies);
7c673cae 678 }
7c673cae 679
92f5a8d4
TL
680 template <typename LessEqual>
681 static inline ReturnType call_above_of_box(SegmentPoint const& p0,
682 SegmentPoint const& p1,
683 SegmentPoint const& p_max,
684 BoxPoint const& top_left,
1e59de90 685 Strategies const& strategies)
92f5a8d4 686 {
1e59de90 687 return above_of_box<LessEqual>::apply(p0, p1, p_max, top_left, strategies);
92f5a8d4 688 }
7c673cae 689
92f5a8d4
TL
690 template <typename LessEqual>
691 static inline ReturnType call_above_of_box(SegmentPoint const& p0,
692 SegmentPoint const& p1,
693 BoxPoint const& top_left,
1e59de90 694 Strategies const& strategies)
92f5a8d4 695 {
1e59de90 696 return above_of_box<LessEqual>::apply(p0, p1, top_left, strategies);
92f5a8d4
TL
697 }
698};
7c673cae 699
92f5a8d4 700//=========================================================================
7c673cae
FG
701
702template
703<
704 typename Segment,
705 typename Box,
706 typename std::size_t Dimension,
1e59de90 707 typename Strategies
7c673cae
FG
708>
709class segment_to_box
710 : not_implemented<Segment, Box>
711{};
712
713
714template
715<
716 typename Segment,
717 typename Box,
1e59de90 718 typename Strategies
7c673cae 719>
1e59de90 720class segment_to_box<Segment, Box, 2, Strategies>
7c673cae 721{
1e59de90 722 typedef distance::strategy_t<Segment, Box, Strategies> strategy_type;
7c673cae 723
7c673cae 724public:
1e59de90 725 typedef distance::return_t<Segment, Box, Strategies> return_type;
7c673cae
FG
726
727 static inline return_type apply(Segment const& segment,
728 Box const& box,
1e59de90 729 Strategies const& strategies)
7c673cae 730 {
1e59de90
TL
731 typedef typename point_type<Segment>::type segment_point;
732 typedef typename point_type<Box>::type box_point;
733
7c673cae
FG
734 segment_point p[2];
735 detail::assign_point_from_index<0>(segment, p[0]);
736 detail::assign_point_from_index<1>(segment, p[1]);
737
1e59de90 738 if (detail::equals::equals_point_point(p[0], p[1], strategies))
7c673cae 739 {
7c673cae
FG
740 return dispatch::distance
741 <
742 segment_point,
743 Box,
1e59de90
TL
744 Strategies
745 >::apply(p[0], box, strategies);
7c673cae
FG
746 }
747
748 box_point top_left, top_right, bottom_left, bottom_right;
749 detail::assign_box_corners(box, bottom_left, bottom_right,
750 top_left, top_right);
751
1e59de90
TL
752 strategy_type::mirror(p[0], p[1],
753 bottom_left, bottom_right,
754 top_left, top_right);
92f5a8d4 755
1e59de90 756 typedef geometry::less<segment_point, -1, typename Strategies::cs_tag> less_type;
92f5a8d4 757 if (less_type()(p[0], p[1]))
7c673cae
FG
758 {
759 return segment_to_box_2D
760 <
761 return_type,
762 segment_point,
763 box_point,
1e59de90 764 Strategies
7c673cae
FG
765 >::apply(p[0], p[1],
766 top_left, top_right, bottom_left, bottom_right,
1e59de90 767 strategies);
7c673cae
FG
768 }
769 else
770 {
771 return segment_to_box_2D
772 <
773 return_type,
774 segment_point,
775 box_point,
1e59de90 776 Strategies
7c673cae
FG
777 >::apply(p[1], p[0],
778 top_left, top_right, bottom_left, bottom_right,
1e59de90 779 strategies);
7c673cae
FG
780 }
781 }
782};
783
784
785}} // namespace detail::distance
786#endif // DOXYGEN_NO_DETAIL
787
788
789#ifndef DOXYGEN_NO_DISPATCH
790namespace dispatch
791{
792
793
1e59de90 794template <typename Segment, typename Box, typename Strategies>
7c673cae
FG
795struct distance
796 <
1e59de90 797 Segment, Box, Strategies, segment_tag, box_tag,
92f5a8d4 798 strategy_tag_distance_segment_box, false
7c673cae
FG
799 >
800{
1e59de90
TL
801 static inline auto apply(Segment const& segment, Box const& box,
802 Strategies const& strategies)
7c673cae
FG
803 {
804 assert_dimension_equal<Segment, Box>();
805
7c673cae
FG
806 return detail::distance::segment_to_box
807 <
808 Segment,
809 Box,
810 dimension<Segment>::value,
1e59de90
TL
811 Strategies
812 >::apply(segment, box, strategies);
7c673cae
FG
813 }
814};
815
816
817
818} // namespace dispatch
819#endif // DOXYGEN_NO_DISPATCH
820
821
822}} // namespace boost::geometry
823
824
825#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP