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>
28 #include <boost/variant/apply_visitor.hpp>
29 #include <boost/variant/static_visitor.hpp>
30 #include <boost/variant/variant_fwd.hpp>
32 #include <boost/geometry/algorithms/make.hpp>
33 #include <boost/geometry/algorithms/not_implemented.hpp>
35 #include <boost/geometry/core/access.hpp>
36 #include <boost/geometry/core/closure.hpp>
37 #include <boost/geometry/core/cs.hpp>
38 #include <boost/geometry/core/exterior_ring.hpp>
39 #include <boost/geometry/core/interior_rings.hpp>
40 #include <boost/geometry/core/point_order.hpp>
41 #include <boost/geometry/core/ring_type.hpp>
42 #include <boost/geometry/core/interior_rings.hpp>
43 #include <boost/geometry/core/tags.hpp>
45 #include <boost/geometry/geometries/concepts/check.hpp>
46 #include <boost/geometry/strategies/concepts/within_concept.hpp>
47 #include <boost/geometry/strategies/default_strategy.hpp>
48 #include <boost/geometry/strategies/within.hpp>
49 #include <boost/geometry/util/math.hpp>
50 #include <boost/geometry/util/order_as_direction.hpp>
51 #include <boost/geometry/views/closeable_view.hpp>
52 #include <boost/geometry/views/reversible_view.hpp>
54 #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
56 #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
57 #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
60 namespace boost { namespace geometry
63 #ifndef DOXYGEN_NO_DETAIL
64 namespace detail { namespace within {
66 struct use_point_in_geometry
68 template <typename Geometry1, typename Geometry2, typename Strategy>
69 static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
71 return detail::within::point_in_geometry(geometry1, geometry2, strategy) == 1;
77 template <typename Geometry1, typename Geometry2, typename Strategy>
78 static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& /*strategy*/)
80 return Strategy::apply(geometry1, geometry2);
84 }} // namespace detail::within
85 #endif // DOXYGEN_NO_DETAIL
87 #ifndef DOXYGEN_NO_DISPATCH
95 typename Tag1 = typename tag<Geometry1>::type,
96 typename Tag2 = typename tag<Geometry2>::type
99 : not_implemented<Tag1, Tag2>
103 template <typename Point, typename Box>
104 struct within<Point, Box, point_tag, box_tag>
106 template <typename Strategy>
107 static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
109 boost::ignore_unused_variable_warning(strategy);
110 return strategy.apply(point, box);
114 template <typename Box1, typename Box2>
115 struct within<Box1, Box2, box_tag, box_tag>
117 template <typename Strategy>
118 static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
120 assert_dimension_equal<Box1, Box2>();
121 boost::ignore_unused_variable_warning(strategy);
122 return strategy.apply(box1, box2);
128 template <typename Point1, typename Point2>
129 struct within<Point1, Point2, point_tag, point_tag>
130 : public detail::within::use_point_in_geometry
133 template <typename Point, typename MultiPoint>
134 struct within<Point, MultiPoint, point_tag, multi_point_tag>
135 : public detail::within::use_point_in_geometry
140 template <typename Point, typename Segment>
141 struct within<Point, Segment, point_tag, segment_tag>
142 : public detail::within::use_point_in_geometry
145 template <typename Point, typename Linestring>
146 struct within<Point, Linestring, point_tag, linestring_tag>
147 : public detail::within::use_point_in_geometry
150 template <typename Point, typename MultiLinestring>
151 struct within<Point, MultiLinestring, point_tag, multi_linestring_tag>
152 : public detail::within::use_point_in_geometry
157 template <typename Point, typename Ring>
158 struct within<Point, Ring, point_tag, ring_tag>
159 : public detail::within::use_point_in_geometry
162 template <typename Point, typename Polygon>
163 struct within<Point, Polygon, point_tag, polygon_tag>
164 : public detail::within::use_point_in_geometry
167 template <typename Point, typename MultiPolygon>
168 struct within<Point, MultiPolygon, point_tag, multi_polygon_tag>
169 : public detail::within::use_point_in_geometry
174 template <typename Linestring1, typename Linestring2>
175 struct within<Linestring1, Linestring2, linestring_tag, linestring_tag>
176 : public detail::within::use_relate
179 template <typename Linestring, typename MultiLinestring>
180 struct within<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
181 : public detail::within::use_relate
184 template <typename MultiLinestring, typename Linestring>
185 struct within<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
186 : public detail::within::use_relate
189 template <typename MultiLinestring1, typename MultiLinestring2>
190 struct within<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
191 : public detail::within::use_relate
196 template <typename Linestring, typename Ring>
197 struct within<Linestring, Ring, linestring_tag, ring_tag>
198 : public detail::within::use_relate
201 template <typename MultiLinestring, typename Ring>
202 struct within<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
203 : public detail::within::use_relate
206 template <typename Linestring, typename Polygon>
207 struct within<Linestring, Polygon, linestring_tag, polygon_tag>
208 : public detail::within::use_relate
211 template <typename MultiLinestring, typename Polygon>
212 struct within<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
213 : public detail::within::use_relate
216 template <typename Linestring, typename MultiPolygon>
217 struct within<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
218 : public detail::within::use_relate
221 template <typename MultiLinestring, typename MultiPolygon>
222 struct within<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
223 : public detail::within::use_relate
228 template <typename Ring1, typename Ring2>
229 struct within<Ring1, Ring2, ring_tag, ring_tag>
230 : public detail::within::use_relate
233 template <typename Ring, typename Polygon>
234 struct within<Ring, Polygon, ring_tag, polygon_tag>
235 : public detail::within::use_relate
238 template <typename Polygon, typename Ring>
239 struct within<Polygon, Ring, polygon_tag, ring_tag>
240 : public detail::within::use_relate
243 template <typename Polygon1, typename Polygon2>
244 struct within<Polygon1, Polygon2, polygon_tag, polygon_tag>
245 : public detail::within::use_relate
248 template <typename Ring, typename MultiPolygon>
249 struct within<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
250 : public detail::within::use_relate
253 template <typename MultiPolygon, typename Ring>
254 struct within<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
255 : public detail::within::use_relate
258 template <typename Polygon, typename MultiPolygon>
259 struct within<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
260 : public detail::within::use_relate
263 template <typename MultiPolygon, typename Polygon>
264 struct within<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
265 : public detail::within::use_relate
268 template <typename MultiPolygon1, typename MultiPolygon2>
269 struct within<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
270 : public detail::within::use_relate
273 } // namespace dispatch
274 #endif // DOXYGEN_NO_DISPATCH
277 namespace resolve_strategy
282 template <typename Geometry1, typename Geometry2, typename Strategy>
283 static inline bool apply(Geometry1 const& geometry1,
284 Geometry2 const& geometry2,
285 Strategy const& strategy)
287 concepts::within::check
289 typename tag<Geometry1>::type,
290 typename tag<Geometry2>::type,
291 typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
295 return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
298 template <typename Geometry1, typename Geometry2>
299 static inline bool apply(Geometry1 const& geometry1,
300 Geometry2 const& geometry2,
303 typedef typename point_type<Geometry1>::type point_type1;
304 typedef typename point_type<Geometry2>::type point_type2;
306 typedef typename strategy::within::services::default_strategy
308 typename tag<Geometry1>::type,
309 typename tag<Geometry2>::type,
310 typename tag<Geometry1>::type,
311 typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
314 typename cs_tag<point_type1>::type, spherical_tag
318 typename cs_tag<point_type2>::type, spherical_tag
322 >::type strategy_type;
324 return apply(geometry1, geometry2, strategy_type());
328 } // namespace resolve_strategy
331 namespace resolve_variant
334 template <typename Geometry1, typename Geometry2>
337 template <typename Strategy>
338 static inline bool apply(Geometry1 const& geometry1,
339 Geometry2 const& geometry2,
340 Strategy const& strategy)
342 concepts::check<Geometry1 const>();
343 concepts::check<Geometry2 const>();
344 assert_dimension_equal<Geometry1, Geometry2>();
346 return resolve_strategy::within::apply(geometry1,
352 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
353 struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
355 template <typename Strategy>
356 struct visitor: boost::static_visitor<bool>
358 Geometry2 const& m_geometry2;
359 Strategy const& m_strategy;
361 visitor(Geometry2 const& geometry2, Strategy const& strategy)
362 : m_geometry2(geometry2)
363 , m_strategy(strategy)
366 template <typename Geometry1>
367 bool operator()(Geometry1 const& geometry1) const
369 return within<Geometry1, Geometry2>::apply(geometry1,
375 template <typename Strategy>
377 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
378 Geometry2 const& geometry2,
379 Strategy const& strategy)
381 return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
386 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
387 struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
389 template <typename Strategy>
390 struct visitor: boost::static_visitor<bool>
392 Geometry1 const& m_geometry1;
393 Strategy const& m_strategy;
395 visitor(Geometry1 const& geometry1, Strategy const& strategy)
396 : m_geometry1(geometry1)
397 , m_strategy(strategy)
400 template <typename Geometry2>
401 bool operator()(Geometry2 const& geometry2) const
403 return within<Geometry1, Geometry2>::apply(m_geometry1,
409 template <typename Strategy>
411 apply(Geometry1 const& geometry1,
412 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
413 Strategy const& strategy)
415 return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
422 BOOST_VARIANT_ENUM_PARAMS(typename T1),
423 BOOST_VARIANT_ENUM_PARAMS(typename T2)
426 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
427 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
430 template <typename Strategy>
431 struct visitor: boost::static_visitor<bool>
433 Strategy const& m_strategy;
435 visitor(Strategy const& strategy): m_strategy(strategy) {}
437 template <typename Geometry1, typename Geometry2>
438 bool operator()(Geometry1 const& geometry1,
439 Geometry2 const& geometry2) const
441 return within<Geometry1, Geometry2>::apply(geometry1,
447 template <typename Strategy>
449 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
450 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
451 Strategy const& strategy)
453 return boost::apply_visitor(visitor<Strategy>(strategy),
463 \brief \brief_check12{is completely inside}
465 \details \details_check12{within, is completely inside}.
466 \tparam Geometry1 \tparam_geometry
467 \tparam Geometry2 \tparam_geometry
468 \param geometry1 \param_geometry which might be within the second geometry
469 \param geometry2 \param_geometry which might contain the first geometry
470 \return true if geometry1 is completely contained within geometry2,
472 \note The default strategy is used for within detection
475 \qbk{[include reference/algorithms/within.qbk]}
483 template<typename Geometry1, typename Geometry2>
484 inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
486 return resolve_variant::within
490 >::apply(geometry1, geometry2, default_strategy());
494 \brief \brief_check12{is completely inside} \brief_strategy
496 \details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons
497 \tparam Geometry1 \tparam_geometry
498 \tparam Geometry2 \tparam_geometry
499 \param geometry1 \param_geometry which might be within the second geometry
500 \param geometry2 \param_geometry which might contain the first geometry
501 \param strategy strategy to be used
502 \return true if geometry1 is completely contained within geometry2,
505 \qbk{distinguish,with strategy}
506 \qbk{[include reference/algorithms/within.qbk]}
508 [heading Available Strategies]
509 \* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]
510 \* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]
511 \* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]
515 [within_strategy_output]
519 template<typename Geometry1, typename Geometry2, typename Strategy>
520 inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2,
521 Strategy const& strategy)
523 return resolve_variant::within
527 >::apply(geometry1, geometry2, strategy);
530 }} // namespace boost::geometry
532 #endif // BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP