3 // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
6 // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
8 // This file was modified by Oracle on 2013-2017.
9 // Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
12 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
14 // Use, modification and distribution is subject to the Boost Software License,
15 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
16 // http://www.boost.org/LICENSE_1_0.txt)
18 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP
19 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP
25 #include <boost/numeric/conversion/cast.hpp>
27 #include <boost/geometry/util/math.hpp>
28 #include <boost/geometry/util/calculation_type.hpp>
30 #include <boost/geometry/core/access.hpp>
31 #include <boost/geometry/core/tags.hpp>
32 #include <boost/geometry/core/coordinate_dimension.hpp>
33 #include <boost/geometry/core/point_type.hpp>
35 #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
37 #include <boost/geometry/strategies/disjoint.hpp>
40 namespace boost { namespace geometry { namespace strategy { namespace disjoint
46 template <std::size_t I>
47 struct compute_tmin_tmax_per_dim
49 template <typename SegmentPoint, typename Box, typename RelativeDistance>
50 static inline void apply(SegmentPoint const& p0,
51 SegmentPoint const& p1,
53 RelativeDistance& ti_min,
54 RelativeDistance& ti_max,
55 RelativeDistance& diff)
57 typedef typename coordinate_type<Box>::type box_coordinate_type;
58 typedef typename coordinate_type
61 >::type point_coordinate_type;
63 RelativeDistance c_p0 = boost::numeric_cast
66 >( geometry::get<I>(p0) );
68 RelativeDistance c_p1 = boost::numeric_cast
71 >( geometry::get<I>(p1) );
73 RelativeDistance c_b_min = boost::numeric_cast
76 >( geometry::get<geometry::min_corner, I>(box) );
78 RelativeDistance c_b_max = boost::numeric_cast
81 >( geometry::get<geometry::max_corner, I>(box) );
83 if ( geometry::get<I>(p1) >= geometry::get<I>(p0) )
86 ti_min = c_b_min - c_p0;
87 ti_max = c_b_max - c_p0;
92 ti_min = c_p0 - c_b_max;
93 ti_max = c_p0 - c_b_min;
101 typename RelativeDistance,
102 typename SegmentPoint,
105 std::size_t Dimension
107 struct disjoint_segment_box_impl
109 template <typename RelativeDistancePair>
110 static inline bool apply(SegmentPoint const& p0,
111 SegmentPoint const& p1,
113 RelativeDistancePair& t_min,
114 RelativeDistancePair& t_max)
116 RelativeDistance ti_min, ti_max, diff;
118 compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff);
120 if ( geometry::math::equals(diff, 0) )
122 if ( (geometry::math::equals(t_min.second, 0)
123 && t_min.first > ti_max)
125 (geometry::math::equals(t_max.second, 0)
126 && t_max.first < ti_min)
128 (math::sign(ti_min) * math::sign(ti_max) > 0) )
134 RelativeDistance t_min_x_diff = t_min.first * diff;
135 RelativeDistance t_max_x_diff = t_max.first * diff;
137 if ( t_min_x_diff > ti_max * t_min.second
138 || t_max_x_diff < ti_min * t_max.second )
143 if ( ti_min * t_min.second > t_min_x_diff )
145 t_min.first = ti_min;
148 if ( ti_max * t_max.second < t_max_x_diff )
150 t_max.first = ti_max;
154 if ( t_min.first > t_min.second || t_max.first < 0 )
159 return disjoint_segment_box_impl
166 >::apply(p0, p1, box, t_min, t_max);
173 typename RelativeDistance,
174 typename SegmentPoint,
176 std::size_t Dimension
178 struct disjoint_segment_box_impl
180 RelativeDistance, SegmentPoint, Box, 0, Dimension
183 static inline bool apply(SegmentPoint const& p0,
184 SegmentPoint const& p1,
187 std::pair<RelativeDistance, RelativeDistance> t_min, t_max;
188 RelativeDistance diff;
190 compute_tmin_tmax_per_dim<0>::apply(p0, p1, box,
191 t_min.first, t_max.first, diff);
193 if ( geometry::math::equals(diff, 0) )
195 if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
196 if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
198 if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
204 if ( t_min.first > diff || t_max.first < 0 )
209 t_min.second = t_max.second = diff;
211 return disjoint_segment_box_impl
213 RelativeDistance, SegmentPoint, Box, 1, Dimension
214 >::apply(p0, p1, box, t_min, t_max);
221 typename RelativeDistance,
222 typename SegmentPoint,
224 std::size_t Dimension
226 struct disjoint_segment_box_impl
228 RelativeDistance, SegmentPoint, Box, Dimension, Dimension
231 template <typename RelativeDistancePair>
232 static inline bool apply(SegmentPoint const&, SegmentPoint const&,
234 RelativeDistancePair&, RelativeDistancePair&)
240 } // namespace detail
242 // NOTE: This may be temporary place for this or corresponding strategy
243 // It seems to be more appropriate to implement the opposite of it
244 // e.g. intersection::segment_box because in disjoint() algorithm
245 // other strategies that are used are intersection and covered_by strategies.
248 template <typename Segment, typename Box>
249 struct point_in_geometry_strategy
250 : services::default_strategy
252 typename point_type<Segment>::type,
257 template <typename Segment, typename Box>
258 static inline typename point_in_geometry_strategy<Segment, Box>::type
259 get_point_in_geometry_strategy()
261 typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
263 return strategy_type();
266 template <typename Segment, typename Box>
267 static inline bool apply(Segment const& segment, Box const& box)
269 assert_dimension_equal<Segment, Box>();
271 typedef typename util::calculation_type::geometric::binary
274 >::type relative_distance_type;
276 typedef typename point_type<Segment>::type segment_point_type;
277 segment_point_type p0, p1;
278 geometry::detail::assign_point_from_index<0>(segment, p0);
279 geometry::detail::assign_point_from_index<1>(segment, p1);
281 return detail::disjoint_segment_box_impl
283 relative_distance_type, segment_point_type, Box,
284 0, dimension<Box>::value
285 >::apply(p0, p1, box);
290 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
296 // Currently used in all coordinate systems
298 template <typename Linear, typename Box, typename LinearTag>
299 struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2>
301 typedef disjoint::segment_box type;
304 template <typename Box, typename Linear, typename LinearTag>
305 struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1>
307 typedef disjoint::segment_box type;
311 } // namespace services
314 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
317 }}}} // namespace boost::geometry::strategy::disjoint
320 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP