1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
7 // This file was modified by Oracle on 2013, 2014.
8 // Modifications copyright (c) 2013, 2014 Oracle and/or its affiliates.
10 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
11 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
13 // Use, modification and distribution is subject to the Boost Software License,
14 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
15 // http://www.boost.org/LICENSE_1_0.txt)
17 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
19 #ifndef BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
20 #define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
25 #include <boost/concept_check.hpp>
26 #include <boost/range.hpp>
27 #include <boost/variant/static_visitor.hpp>
28 #include <boost/variant/apply_visitor.hpp>
29 #include <boost/variant/variant_fwd.hpp>
31 #include <boost/geometry/algorithms/make.hpp>
32 #include <boost/geometry/algorithms/not_implemented.hpp>
34 #include <boost/geometry/core/access.hpp>
35 #include <boost/geometry/core/closure.hpp>
36 #include <boost/geometry/core/cs.hpp>
37 #include <boost/geometry/core/exterior_ring.hpp>
38 #include <boost/geometry/core/interior_rings.hpp>
39 #include <boost/geometry/core/point_order.hpp>
40 #include <boost/geometry/core/ring_type.hpp>
41 #include <boost/geometry/core/interior_rings.hpp>
42 #include <boost/geometry/core/tags.hpp>
44 #include <boost/geometry/geometries/concepts/check.hpp>
45 #include <boost/geometry/strategies/concepts/within_concept.hpp>
46 #include <boost/geometry/strategies/default_strategy.hpp>
47 #include <boost/geometry/strategies/within.hpp>
48 #include <boost/geometry/util/math.hpp>
49 #include <boost/geometry/util/order_as_direction.hpp>
50 #include <boost/geometry/views/closeable_view.hpp>
51 #include <boost/geometry/views/reversible_view.hpp>
53 #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
55 #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
56 #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
59 namespace boost { namespace geometry
62 #ifndef DOXYGEN_NO_DETAIL
63 namespace detail { namespace within {
65 struct use_point_in_geometry
67 template <typename Geometry1, typename Geometry2, typename Strategy>
68 static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
70 return detail::within::point_in_geometry(geometry1, geometry2, strategy) == 1;
76 template <typename Geometry1, typename Geometry2, typename Strategy>
77 static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/)
79 return Strategy::apply(geometry1, geometry2);
83 }} // namespace detail::within
84 #endif // DOXYGEN_NO_DETAIL
86 #ifndef DOXYGEN_NO_DISPATCH
94 typename Tag1 = typename tag<Geometry1>::type,
95 typename Tag2 = typename tag<Geometry2>::type
98 : not_implemented<Tag1, Tag2>
102 template <typename Point, typename Box>
103 struct within<Point, Box, point_tag, box_tag>
105 template <typename Strategy>
106 static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
108 boost::ignore_unused_variable_warning(strategy);
109 return strategy.apply(point, box);
113 template <typename Box1, typename Box2>
114 struct within<Box1, Box2, box_tag, box_tag>
116 template <typename Strategy>
117 static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
119 assert_dimension_equal<Box1, Box2>();
120 boost::ignore_unused_variable_warning(strategy);
121 return strategy.apply(box1, box2);
127 template <typename Point1, typename Point2>
128 struct within<Point1, Point2, point_tag, point_tag>
129 : public detail::within::use_point_in_geometry
132 template <typename Point, typename MultiPoint>
133 struct within<Point, MultiPoint, point_tag, multi_point_tag>
134 : public detail::within::use_point_in_geometry
139 template <typename Point, typename Segment>
140 struct within<Point, Segment, point_tag, segment_tag>
141 : public detail::within::use_point_in_geometry
144 template <typename Point, typename Linestring>
145 struct within<Point, Linestring, point_tag, linestring_tag>
146 : public detail::within::use_point_in_geometry
149 template <typename Point, typename MultiLinestring>
150 struct within<Point, MultiLinestring, point_tag, multi_linestring_tag>
151 : public detail::within::use_point_in_geometry
156 template <typename Point, typename Ring>
157 struct within<Point, Ring, point_tag, ring_tag>
158 : public detail::within::use_point_in_geometry
161 template <typename Point, typename Polygon>
162 struct within<Point, Polygon, point_tag, polygon_tag>
163 : public detail::within::use_point_in_geometry
166 template <typename Point, typename MultiPolygon>
167 struct within<Point, MultiPolygon, point_tag, multi_polygon_tag>
168 : public detail::within::use_point_in_geometry
173 template <typename Linestring1, typename Linestring2>
174 struct within<Linestring1, Linestring2, linestring_tag, linestring_tag>
175 : public detail::within::use_relate
178 template <typename Linestring, typename MultiLinestring>
179 struct within<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
180 : public detail::within::use_relate
183 template <typename MultiLinestring, typename Linestring>
184 struct within<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
185 : public detail::within::use_relate
188 template <typename MultiLinestring1, typename MultiLinestring2>
189 struct within<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
190 : public detail::within::use_relate
195 template <typename Linestring, typename Ring>
196 struct within<Linestring, Ring, linestring_tag, ring_tag>
197 : public detail::within::use_relate
200 template <typename MultiLinestring, typename Ring>
201 struct within<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
202 : public detail::within::use_relate
205 template <typename Linestring, typename Polygon>
206 struct within<Linestring, Polygon, linestring_tag, polygon_tag>
207 : public detail::within::use_relate
210 template <typename MultiLinestring, typename Polygon>
211 struct within<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
212 : public detail::within::use_relate
215 template <typename Linestring, typename MultiPolygon>
216 struct within<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
217 : public detail::within::use_relate
220 template <typename MultiLinestring, typename MultiPolygon>
221 struct within<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
222 : public detail::within::use_relate
227 template <typename Ring1, typename Ring2>
228 struct within<Ring1, Ring2, ring_tag, ring_tag>
229 : public detail::within::use_relate
232 template <typename Ring, typename Polygon>
233 struct within<Ring, Polygon, ring_tag, polygon_tag>
234 : public detail::within::use_relate
237 template <typename Polygon, typename Ring>
238 struct within<Polygon, Ring, polygon_tag, ring_tag>
239 : public detail::within::use_relate
242 template <typename Polygon1, typename Polygon2>
243 struct within<Polygon1, Polygon2, polygon_tag, polygon_tag>
244 : public detail::within::use_relate
247 template <typename Ring, typename MultiPolygon>
248 struct within<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
249 : public detail::within::use_relate
252 template <typename MultiPolygon, typename Ring>
253 struct within<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
254 : public detail::within::use_relate
257 template <typename Polygon, typename MultiPolygon>
258 struct within<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
259 : public detail::within::use_relate
262 template <typename MultiPolygon, typename Polygon>
263 struct within<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
264 : public detail::within::use_relate
267 template <typename MultiPolygon1, typename MultiPolygon2>
268 struct within<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
269 : public detail::within::use_relate
272 } // namespace dispatch
273 #endif // DOXYGEN_NO_DISPATCH
276 namespace resolve_strategy
281 template <typename Geometry1, typename Geometry2, typename Strategy>
282 static inline bool apply(Geometry1 const& geometry1,
283 Geometry2 const& geometry2,
284 Strategy const& strategy)
286 concept::within::check
288 typename tag<Geometry1>::type,
289 typename tag<Geometry2>::type,
290 typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
294 return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
297 template <typename Geometry1, typename Geometry2>
298 static inline bool apply(Geometry1 const& geometry1,
299 Geometry2 const& geometry2,
302 typedef typename point_type<Geometry1>::type point_type1;
303 typedef typename point_type<Geometry2>::type point_type2;
305 typedef typename strategy::within::services::default_strategy
307 typename tag<Geometry1>::type,
308 typename tag<Geometry2>::type,
309 typename tag<Geometry1>::type,
310 typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
313 typename cs_tag<point_type1>::type, spherical_tag
317 typename cs_tag<point_type2>::type, spherical_tag
321 >::type strategy_type;
323 return apply(geometry1, geometry2, strategy_type());
327 } // namespace resolve_strategy
330 namespace resolve_variant
333 template <typename Geometry1, typename Geometry2>
336 template <typename Strategy>
337 static inline bool apply(Geometry1 const& geometry1,
338 Geometry2 const& geometry2,
339 Strategy const& strategy)
341 concept::check<Geometry1 const>();
342 concept::check<Geometry2 const>();
343 assert_dimension_equal<Geometry1, Geometry2>();
345 return resolve_strategy::within::apply(geometry1,
351 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
352 struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
354 template <typename Strategy>
355 struct visitor: boost::static_visitor<bool>
357 Geometry2 const& m_geometry2;
358 Strategy const& m_strategy;
360 visitor(Geometry2 const& geometry2, Strategy const& strategy):
361 m_geometry2(geometry2),
365 template <typename Geometry1>
366 bool operator()(Geometry1 const& geometry1) const
368 return within<Geometry1, Geometry2>::apply(geometry1,
374 template <typename Strategy>
376 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
377 Geometry2 const& geometry2,
378 Strategy const& strategy)
380 return boost::apply_visitor(
381 visitor<Strategy>(geometry2, strategy),
387 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
388 struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
390 template <typename Strategy>
391 struct visitor: boost::static_visitor<bool>
393 Geometry1 const& m_geometry1;
394 Strategy const& m_strategy;
396 visitor(Geometry1 const& geometry1, Strategy const& strategy):
397 m_geometry1(geometry1),
401 template <typename Geometry2>
402 bool operator()(Geometry2 const& geometry2) const
404 return within<Geometry1, Geometry2>::apply(m_geometry1,
410 template <typename Strategy>
412 apply(Geometry1 const& geometry1,
413 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
414 Strategy const& strategy)
416 return boost::apply_visitor(
417 visitor<Strategy>(geometry1, strategy),
424 BOOST_VARIANT_ENUM_PARAMS(typename T1),
425 BOOST_VARIANT_ENUM_PARAMS(typename T2)
428 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
429 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
432 template <typename Strategy>
433 struct visitor: boost::static_visitor<bool>
435 Strategy const& m_strategy;
437 visitor(Strategy const& strategy): m_strategy(strategy) {}
439 template <typename Geometry1, typename Geometry2>
440 bool operator()(Geometry1 const& geometry1,
441 Geometry2 const& geometry2) const
443 return within<Geometry1, Geometry2>::apply(geometry1,
449 template <typename Strategy>
451 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
452 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
453 Strategy const& strategy)
455 return boost::apply_visitor(
456 visitor<Strategy>(strategy),
466 \brief \brief_check12{is completely inside}
468 \details \details_check12{within, is completely inside}.
469 \tparam Geometry1 \tparam_geometry
470 \tparam Geometry2 \tparam_geometry
471 \param geometry1 \param_geometry which might be within the second geometry
472 \param geometry2 \param_geometry which might contain the first geometry
473 \return true if geometry1 is completely contained within geometry2,
475 \note The default strategy is used for within detection
478 \qbk{[include reference/algorithms/within.qbk]}
486 template<typename Geometry1, typename Geometry2>
487 inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
489 return resolve_variant::within
493 >::apply(geometry1, geometry2, default_strategy());
497 \brief \brief_check12{is completely inside} \brief_strategy
499 \details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons
500 \tparam Geometry1 \tparam_geometry
501 \tparam Geometry2 \tparam_geometry
502 \param geometry1 \param_geometry which might be within the second geometry
503 \param geometry2 \param_geometry which might contain the first geometry
504 \param strategy strategy to be used
505 \return true if geometry1 is completely contained within geometry2,
508 \qbk{distinguish,with strategy}
509 \qbk{[include reference/algorithms/within.qbk]}
511 [heading Available Strategies]
512 \* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]
513 \* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]
514 \* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]
518 [within_strategy_output]
522 template<typename Geometry1, typename Geometry2, typename Strategy>
523 inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2,
524 Strategy const& strategy)
526 return resolve_variant::within
530 >::apply(geometry1, geometry2, strategy);
533 }} // namespace boost::geometry
535 #endif // BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP