diff --git a/include/boost/geometry/algorithms/covered_by.hpp b/include/boost/geometry/algorithms/covered_by.hpp index 01405d81b..d685885b9 100644 --- a/include/boost/geometry/algorithms/covered_by.hpp +++ b/include/boost/geometry/algorithms/covered_by.hpp @@ -4,6 +4,9 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// This file was modified by Oracle on 2013. +// Modifications copyright (c) 2013, Oracle and/or its affiliates. + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -77,14 +80,7 @@ struct covered_by template static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy) { - return detail::within::point_in_ring - < - Point, - Ring, - order_as_direction::value>::value, - geometry::closure::value, - Strategy - >::apply(point, ring, strategy) >= 0; + return detail::within::point_in_geometry(point, ring, strategy) >= 0; } }; @@ -94,14 +90,7 @@ struct covered_by template static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy) { - return detail::within::point_in_polygon - < - Point, - Polygon, - order_as_direction::value>::value, - geometry::closure::value, - Strategy - >::apply(point, polygon, strategy) >= 0; + return detail::within::point_in_geometry(point, polygon, strategy) >= 0; } }; diff --git a/include/boost/geometry/algorithms/detail/disjoint.hpp b/include/boost/geometry/algorithms/detail/disjoint.hpp index f25e8a843..d8b921096 100644 --- a/include/boost/geometry/algorithms/detail/disjoint.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint.hpp @@ -4,6 +4,9 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// This file was modified by Oracle on 2013. +// Modifications copyright (c) 2013, Oracle and/or its affiliates. + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -30,6 +33,7 @@ #include +#include namespace boost { namespace geometry @@ -65,38 +69,6 @@ struct disjoint_interrupt_policy -template -< - typename Point1, typename Point2, - std::size_t Dimension, std::size_t DimensionCount -> -struct point_point -{ - static inline bool apply(Point1 const& p1, Point2 const& p2) - { - if (! geometry::math::equals(get(p1), get(p2))) - { - return true; - } - return point_point - < - Point1, Point2, - Dimension + 1, DimensionCount - >::apply(p1, p2); - } -}; - - -template -struct point_point -{ - static inline bool apply(Point1 const& , Point2 const& ) - { - return false; - } -}; - - template < typename Point, typename Box, @@ -318,44 +290,10 @@ inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2) } - -/*! - \brief Internal utility function to detect of points are disjoint - \note To avoid circular references - */ -template -inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2) -{ - return point_point - < - Point1, Point2, - 0, dimension::type::value - >::apply(point1, point2); -} - - }} // namespace detail::disjoint #endif // DOXYGEN_NO_DETAIL -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace equals -{ - -/*! - \brief Internal utility function to detect of points are disjoint - \note To avoid circular references - */ -template -inline bool equals_point_point(Point1 const& point1, Point2 const& point2) -{ - return ! detail::disjoint::disjoint_point_point(point1, point2); -} - - -}} // namespace detail::equals -#endif // DOXYGEN_NO_DETAIL - }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_HPP diff --git a/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp b/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp new file mode 100644 index 000000000..0f7d27a24 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/disjoint/point_point.hpp @@ -0,0 +1,106 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2013. +// Modifications copyright (c) 2013, Oracle and/or its affiliates. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP + +#include + +#include +#include + +#include + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace disjoint +{ + +template +< + typename Point1, typename Point2, + std::size_t Dimension, std::size_t DimensionCount +> +struct point_point +{ + static inline bool apply(Point1 const& p1, Point2 const& p2) + { + if (! geometry::math::equals(get(p1), get(p2))) + { + return true; + } + return point_point + < + Point1, Point2, + Dimension + 1, DimensionCount + >::apply(p1, p2); + } +}; + + +template +struct point_point +{ + static inline bool apply(Point1 const& , Point2 const& ) + { + return false; + } +}; + + +/*! + \brief Internal utility function to detect of points are disjoint + \note To avoid circular references + */ +template +inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2) +{ + return point_point + < + Point1, Point2, + 0, dimension::type::value + >::apply(point1, point2); +} + + +}} // namespace detail::disjoint +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace equals +{ + +/*! + \brief Internal utility function to detect of points are disjoint + \note To avoid circular references + */ +template +inline bool equals_point_point(Point1 const& point1, Point2 const& point2) +{ + return ! detail::disjoint::disjoint_point_point(point1, point2); +} + + +}} // namespace detail::equals +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_POINT_HPP diff --git a/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp new file mode 100644 index 000000000..8630bd9ce --- /dev/null +++ b/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp @@ -0,0 +1,249 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2013. +// Modifications copyright (c) 2013, Oracle and/or its affiliates. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP + +#include + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace within { + +template inline +int point_in_range(Point const& point, Range const& range, Strategy const& strategy) +{ + typedef typename boost::range_iterator::type iterator_type; + typename Strategy::state_type state; + iterator_type it = boost::begin(range); + iterator_type end = boost::end(range); + + bool stop = false; + for ( iterator_type previous = it++ ; + it != end && ! stop ; + ++previous, ++it ) + { + if ( ! strategy.apply(point, *previous, *it, state) ) + { + stop = true; + } + } + + return strategy.result(state); +} + +// checks the relation between a point P and geometry G +// returns 1 if P is in the interior of G +// returns 0 if P is on the boundry of G +// returns -1 if P is in the exterior of G + +template ::type> +struct point_in_geometry_dispatch +{ + BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (T)); +}; + +template +struct point_in_geometry_dispatch +{ + template static inline + int apply(Point const& pt, Linestring const& ls, Strategy const& strategy) + { + std::size_t count = boost::size(ls); + if ( 2 <= count ) + { + if ( 0 != detail::within::point_in_range(pt, ls, strategy) ) + return -1; + + // if the linestring doesn't have a boundary + if ( detail::equals::equals_point_point(*boost::begin(ls), *(--boost::end(ls))) ) + return 1; + // else if the point is equal to the one of the terminal points + else if ( detail::equals::equals_point_point(pt, *boost::begin(ls)) + || detail::equals::equals_point_point(pt, *(--boost::end(ls))) ) + return 0; + else + return 1; + } + else if ( 1 == count + && detail::equals::equals_point_point(pt, *boost::begin(ls)) ) + return 0; + + return -1; + } +}; + +template +struct point_in_geometry_dispatch +{ + template static inline + int apply(Point const& point, Ring const& ring, Strategy const& strategy) + { + static const iterate_direction direction = order_as_direction::value>::value; + static const closure_selector closure = geometry::closure::value; + + if (int(boost::size(ring)) + < core_detail::closure::minimum_ring_size::value) + { + return -1; + } + + typedef typename reversible_view::type rev_view_type; + typedef typename closeable_view + < + rev_view_type const, closure + >::type cl_view_type; + typedef typename boost::range_iterator::type iterator_type; + + rev_view_type rev_view(ring); + cl_view_type view(rev_view); + + return point_in_range(point, view, strategy); + } +}; + +//// Polygon: in exterior ring, and if so, not within interior ring(s) +template +struct point_in_geometry_dispatch +{ + template + static inline int apply(Point const& point, Polygon const& poly, + Strategy const& strategy) + { + int const code = point_in_geometry_dispatch + < + typename ring_type::type + >::apply(point, exterior_ring(poly), strategy); + + if (code == 1) + { + typename interior_return_type::type rings + = interior_rings(poly); + for (BOOST_AUTO_TPL(it, boost::begin(rings)); + it != boost::end(rings); + ++it) + { + int const interior_code = point_in_geometry_dispatch + < + typename ring_type::type + >::apply(point, *it, strategy); + + if (interior_code != -1) + { + // If 0, return 0 (touch) + // If 1 (inside hole) return -1 (outside polygon) + // If -1 (outside hole) check other holes if any + return -interior_code; + } + } + } + return code; + } +}; + +template +struct point_in_geometry_dispatch +{ + template static inline + int apply(P const& p, G const& g, S const& s) + { + // For invalid multipolygons + //int res = -1; // outside + + typedef typename boost::range_value::type polygon_type; + typedef typename boost::range_const_iterator::type iterator; + for ( iterator it = boost::begin(g) ; it != boost::end(g) ; ++it ) + { + int pip = detail::within::point_in_geometry_dispatch::apply(p, *it, s); + + if ( 1 == pip ) // inside polygon + return 1; + // Only for valid multi-polygons + if ( 0 == pip ) + return 0; + // For invalid multi-polygons + //if ( res < pip ) // point must be inside at least one polygon + // res = pip; + } + + //return res; // for invalid multipolygons + return -1; // for valid multipolygons + } +}; + +template +struct point_in_geometry_dispatch +{ + template static inline + int apply(P const& p, G const& g, S const& s) + { + int pip = -1; // outside + + typedef typename boost::range_value::type linestring_type; + typedef typename boost::range_value::type point_type; + typedef typename boost::range_iterator::type iterator; + iterator it = boost::begin(g); + for ( ; it != boost::end(g) ; ++it ) + { + pip = detail::within::point_in_geometry_dispatch::apply(p, *it, s); + + if ( 0 <= pip ) + break; + } + + // outside + if ( pip < 0 ) + return -1; + + unsigned boundaries = pip == 0 ? 1 : 0; + + for ( ; it != boost::end(g) ; ++it ) + { + if ( boost::size(*it) < 2 ) + continue; + + point_type const& front = *boost::begin(*it); + point_type const& back = *(--boost::end(*it)); + // is closed_ring + if ( detail::equals::equals_point_point(front, back) ) + continue; + if ( detail::equals::equals_point_point(p, front) + || detail::equals::equals_point_point(p, back) ) + ++boundaries; + } + + return boundaries % 2 ? 1 : 0; + } +}; + +// 1 - in the interior +// 0 - in the boundry +// -1 - in the exterior +template inline +int point_in_geometry(P const& p, G const& g, Strategy const& strategy) +{ + BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategyPolygonal) ); + + return point_in_geometry_dispatch::apply(p, g, strategy); +} + +}} // namespace detail::within +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP diff --git a/include/boost/geometry/algorithms/detail/within/within_no_turns.hpp b/include/boost/geometry/algorithms/detail/within/within_no_turns.hpp new file mode 100644 index 000000000..98c64a2ed --- /dev/null +++ b/include/boost/geometry/algorithms/detail/within/within_no_turns.hpp @@ -0,0 +1,200 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2013. +// Modifications copyright (c) 2013, Oracle and/or its affiliates. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP + +#include + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace within { + +// returns true if G1 is within G2 +// this function should be called only if there are no intersection points +// otherwise it may return invalid result +// e.g. when non-first point of G1 is outside G2 or when some rings of G1 are the same as rings of G2 + +template ::type, typename T2 = typename geometry::tag::type> +struct within_no_turns_dispatch +{ + template static inline + bool apply(G1 const& g1, G2 const& g2, S const& s) + { + typedef typename geometry::point_type::type point1_type; + point1_type p; + if ( !geometry::point_on_border(p, g1) ) + return false; + + return point_in_geometry(p, g2, s) >= 0; + } +}; + +template +struct within_no_turns_dispatch +{ + template static inline + bool apply(G1 const& g1, G2 const& g2, S const& s) + { + typedef typename geometry::point_type::type point1_type; + typedef typename geometry::point_type::type point2_type; + point1_type p; + if ( !geometry::point_on_border(p, g1) ) + return false; + // check if one of ring points is outside the polygon + if ( point_in_geometry(p, g2, s) < 0 ) + return false; + // Now check if holes of G2 aren't inside G1 + typedef typename boost::range_const_iterator::type>::type It; + for ( It it = boost::begin(geometry::interior_rings(g2)) ; it != boost::end(geometry::interior_rings(g2)) ; ++it ) + { + point2_type p; + if ( !geometry::point_on_border(p, *it) ) + return false; + if ( point_in_geometry(p, g1, s) > 0 ) + return false; + } + return true; + } +}; + +template +struct within_no_turns_dispatch +{ + template static inline + bool apply(G1 const& g1, G2 const& g2, S const& s) + { + typedef typename geometry::point_type::type point1_type; + typedef typename geometry::point_type::type point2_type; + point1_type p; + if ( !geometry::point_on_border(p, g1) ) + return false; + // check if one of ring points is outside the polygon + if ( point_in_geometry(p, g2, s) < 0 ) + return false; + // Now check if holes of G2 aren't inside G1 + typedef typename boost::range_const_iterator::type>::type It2; + for ( It2 it = boost::begin(geometry::interior_rings(g2)) ; it != boost::end(geometry::interior_rings(g2)) ; ++it ) + { + point2_type p2; + if ( !geometry::point_on_border(p2, *it) ) + return false; + // if the hole of G2 is inside G1 + if ( point_in_geometry(p2, g1, s) > 0 ) + { + // if it's also inside one of the G1 holes, it's ok + bool ok = false; + typedef typename boost::range_const_iterator::type>::type It1; + for ( It1 it1 = boost::begin(geometry::interior_rings(g1)) ; it1 != boost::end(geometry::interior_rings(g1)) ; ++it1 ) + { + if ( point_in_geometry(p2, *it1, s) < 0 ) + { + ok = true; + break; + } + } + if ( !ok ) + return false; + } + } + return true; + } +}; + +// TODO: later move it to directory boost/geometry/multi/algorithms/detail/within + +template ::type, + typename T2 = typename geometry::tag::type, + bool IsMulti1 = boost::is_base_of::value, + bool IsMulti2 = boost::is_base_of::value> +struct within_no_turns_multi_dispatch +{ + template static inline + bool apply(G1 const& g1, G2 const& g2, S const& s) + { + return within_no_turns_dispatch::apply(g1, g2, s); + } +}; + +template +struct within_no_turns_multi_dispatch +{ + template static inline + bool apply(G1 const& g1, G2 const& g2, S const& s) + { + // All values of G1 must be inside G2 + typedef typename boost::range_value::type V1; + typedef typename boost::range_const_iterator::type It; + for ( It it = boost::begin(g1) ; it != boost::end(g1) ; ++it ) + { + if ( !within_no_turns_dispatch::apply(*it, g2, s) ) + return false; + } + return true; + } +}; + +template +struct within_no_turns_multi_dispatch +{ + template static inline + bool apply(G1 const& g1, G2 const& g2, S const& s) + { + // G1 must be within at least one value of G2 + typedef typename boost::range_value::type P2; + typedef typename boost::range_const_iterator::type It; + for ( It it = boost::begin(g2) ; it != boost::end(g2) ; ++it ) + { + if ( within_no_turns_dispatch::apply(g1, *it, s) ) + return true; + } + return false; + } +}; + +template +struct within_no_turns_multi_dispatch +{ + template static inline + bool apply(G1 const& g1, G2 const& g2, S const& s) + { + // each value of G1 must be inside at least one value of G2 + typedef typename boost::range_value::type V1; + typedef typename boost::range_const_iterator::type It; + for ( It it = boost::begin(g1) ; it != boost::end(g1) ; ++it ) + { + if ( !within_no_turns_multi_dispatch::apply(*it, g2, s) ) + return false; + } + return true; + } +}; + +template inline +bool within_no_turns(G1 const& g1, G2 const& g2, S const& s) +{ + return within_no_turns_multi_dispatch::apply(g1, g2, s); +} + +}} // namespace detail::within +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_WITHIN_NO_TURNS_HPP diff --git a/include/boost/geometry/algorithms/within.hpp b/include/boost/geometry/algorithms/within.hpp index 4eec6a43d..513402844 100644 --- a/include/boost/geometry/algorithms/within.hpp +++ b/include/boost/geometry/algorithms/within.hpp @@ -4,6 +4,9 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// This file was modified by Oracle on 2013. +// Modifications copyright (c) 2013, Oracle and/or its affiliates. + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -46,125 +49,11 @@ #include #include +#include namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace within -{ - - -template -< - typename Point, - typename Ring, - iterate_direction Direction, - closure_selector Closure, - typename Strategy -> -struct point_in_ring -{ - BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategyPolygonal) ); - - static inline int apply(Point const& point, Ring const& ring, - Strategy const& strategy) - { - boost::ignore_unused_variable_warning(strategy); - if (int(boost::size(ring)) - < core_detail::closure::minimum_ring_size::value) - { - return -1; - } - - typedef typename reversible_view::type rev_view_type; - typedef typename closeable_view - < - rev_view_type const, Closure - >::type cl_view_type; - typedef typename boost::range_iterator::type iterator_type; - - rev_view_type rev_view(ring); - cl_view_type view(rev_view); - typename Strategy::state_type state; - iterator_type it = boost::begin(view); - iterator_type end = boost::end(view); - - bool stop = false; - for (iterator_type previous = it++; - it != end && ! stop; - ++previous, ++it) - { - if (! strategy.apply(point, *previous, *it, state)) - { - stop = true; - } - } - - return strategy.result(state); - } -}; - - -// Polygon: in exterior ring, and if so, not within interior ring(s) -template -< - typename Point, - typename Polygon, - iterate_direction Direction, - closure_selector Closure, - typename Strategy -> -struct point_in_polygon -{ - BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategyPolygonal) ); - - static inline int apply(Point const& point, Polygon const& poly, - Strategy const& strategy) - { - int const code = point_in_ring - < - Point, - typename ring_type::type, - Direction, - Closure, - Strategy - >::apply(point, exterior_ring(poly), strategy); - - if (code == 1) - { - typename interior_return_type::type rings - = interior_rings(poly); - for (BOOST_AUTO_TPL(it, boost::begin(rings)); - it != boost::end(rings); - ++it) - { - int const interior_code = point_in_ring - < - Point, - typename ring_type::type, - Direction, - Closure, - Strategy - >::apply(point, *it, strategy); - - if (interior_code != -1) - { - // If 0, return 0 (touch) - // If 1 (inside hole) return -1 (outside polygon) - // If -1 (outside hole) check other holes if any - return -interior_code; - } - } - } - return code; - } -}; - -}} // namespace detail::within -#endif // DOXYGEN_NO_DETAIL - - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { @@ -211,14 +100,7 @@ struct within template static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy) { - return detail::within::point_in_ring - < - Point, - Ring, - order_as_direction::value>::value, - geometry::closure::value, - Strategy - >::apply(point, ring, strategy) == 1; + return detail::within::point_in_geometry(point, ring, strategy) == 1; } }; @@ -228,14 +110,7 @@ struct within template static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy) { - return detail::within::point_in_polygon - < - Point, - Polygon, - order_as_direction::value>::value, - geometry::closure::value, - Strategy - >::apply(point, polygon, strategy) == 1; + return detail::within::point_in_geometry(point, polygon, strategy) == 1; } }; diff --git a/include/boost/geometry/multi/algorithms/detail/point_on_border.hpp b/include/boost/geometry/multi/algorithms/detail/point_on_border.hpp index dd3bcd5d1..c42ce7881 100644 --- a/include/boost/geometry/multi/algorithms/detail/point_on_border.hpp +++ b/include/boost/geometry/multi/algorithms/detail/point_on_border.hpp @@ -4,6 +4,9 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// This file was modified by Oracle on 2013. +// Modifications copyright (c) 2013, Oracle and/or its affiliates. + // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. diff --git a/include/boost/geometry/multi/algorithms/detail/within/point_in_geometry.hpp b/include/boost/geometry/multi/algorithms/detail/within/point_in_geometry.hpp new file mode 100644 index 000000000..adba08594 --- /dev/null +++ b/include/boost/geometry/multi/algorithms/detail/within/point_in_geometry.hpp @@ -0,0 +1,104 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP +#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP + +#include + +namespace boost { namespace geometry { + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace within { + +template +struct point_in_geometry_dispatch +{ + template static inline + int apply(P const& p, G const& g, S const& s) + { + // For invalid multipolygons + //int res = -1; // outside + + typedef typename boost::range_value::type polygon_type; + typedef typename boost::range_const_iterator::type iterator; + for ( iterator it = boost::begin(g) ; it != boost::end(g) ; ++it ) + { + int pip = detail::within::point_in_geometry_dispatch::apply(p, *it, s); + + if ( 1 == pip ) // inside polygon + return 1; + // Only for valid multi-polygons + if ( 0 == pip ) + return 0; + // For invalid multi-polygons + //if ( res < pip ) // point must be inside at least one polygon + // res = pip; + } + + //return res; // for invalid multipolygons + return -1; // for valid multipolygons + } +}; + +template +struct point_in_geometry_dispatch +{ + template static inline + int apply(P const& p, G const& g, S const& s) + { + int pip = -1; // outside + + typedef typename boost::range_value::type linestring_type; + typedef typename boost::range_value::type point_type; + typedef typename boost::range_iterator::type iterator; + iterator it = boost::begin(g); + for ( ; it != boost::end(g) ; ++it ) + { + pip = detail::within::point_in_geometry_dispatch::apply(p, *it, s); + + if ( 0 <= pip ) + break; + } + + // outside + if ( pip < 0 ) + return -1; + + unsigned boundaries = pip == 0 ? 1 : 0; + + for ( ; it != boost::end(g) ; ++it ) + { + if ( boost::size(*it) < 2 ) + continue; + + point_type const& front = *boost::begin(*it); + point_type const& back = *(--boost::end(*it)); + // is closed_ring + if ( detail::equals::equals_point_point(front, back) ) + continue; + if ( detail::equals::equals_point_point(p, front) + || detail::equals::equals_point_point(p, back) ) + ++boundaries; + } + + return boundaries % 2 ? 1 : 0; + } +}; + +}} // namespace detail::within +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_WITHIN_POINT_IN_GEOMETRY_HPP diff --git a/include/boost/geometry/multi/multi.hpp b/include/boost/geometry/multi/multi.hpp index df10392cb..a9de82da2 100644 --- a/include/boost/geometry/multi/multi.hpp +++ b/include/boost/geometry/multi/multi.hpp @@ -49,6 +49,8 @@ #include #include +#include + #include #include #include