blob: 6a48b684a1987debf1b13d3ecad9f73deac24814 [file] [log] [blame]
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2015.
// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// 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_LINEAR_AREAL_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP
#include <iterator>
#include <boost/range.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{
template <typename Geometry1, typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag1OrMulti = typename tag_cast<Tag1, multi_tag>::type>
struct disjoint_no_intersections_policy
{
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
{
typedef typename point_type<Geometry1>::type point1_type;
point1_type p;
geometry::point_on_border(p, g1);
return !geometry::covered_by(p, g2);
}
};
template <typename Geometry1, typename Geometry2, typename Tag1>
struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
{
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
{
// TODO: use partition or rtree on g2
typedef typename boost::range_iterator<Geometry1 const>::type iterator;
for ( iterator it = boost::begin(g1) ; it != boost::end(g1) ; ++it )
{
typedef typename boost::range_value<Geometry1 const>::type value_type;
if ( ! disjoint_no_intersections_policy<value_type const, Geometry2>
::apply(*it, g2) )
{
return false;
}
}
return true;
}
};
template<typename Geometry1, typename Geometry2,
typename NoIntersectionsPolicy
= disjoint_no_intersections_policy<Geometry1, Geometry2> >
struct disjoint_linear_areal
{
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
{
// if there are intersections - return false
if ( !disjoint_linear<Geometry1, Geometry2>::apply(g1, g2) )
{
return false;
}
return NoIntersectionsPolicy::apply(g1, g2);
}
};
template
<
typename Segment,
typename Areal,
typename Tag = typename tag<Areal>::type
>
struct disjoint_segment_areal
: not_implemented<Segment, Areal>
{};
template <typename Segment, typename Polygon>
class disjoint_segment_areal<Segment, Polygon, polygon_tag>
{
private:
template <typename InteriorRings>
static inline
bool check_interior_rings(InteriorRings const& interior_rings,
Segment const& segment)
{
typedef typename boost::range_value<InteriorRings>::type ring_type;
typedef unary_disjoint_geometry_to_query_geometry
<
Segment,
disjoint_range_segment_or_box
<
ring_type, closure<ring_type>::value, Segment
>
> unary_predicate_type;
return check_iterator_range
<
unary_predicate_type
>::apply(boost::begin(interior_rings),
boost::end(interior_rings),
unary_predicate_type(segment));
}
public:
static inline bool apply(Segment const& segment, Polygon const& polygon)
{
typedef typename geometry::ring_type<Polygon>::type ring;
if ( !disjoint_range_segment_or_box
<
ring, closure<Polygon>::value, Segment
>::apply(geometry::exterior_ring(polygon), segment) )
{
return false;
}
if ( !check_interior_rings(geometry::interior_rings(polygon), segment) )
{
return false;
}
typename point_type<Segment>::type p;
detail::assign_point_from_index<0>(segment, p);
return !geometry::covered_by(p, polygon);
}
};
template <typename Segment, typename MultiPolygon>
struct disjoint_segment_areal<Segment, MultiPolygon, multi_polygon_tag>
{
static inline
bool apply(Segment const& segment, MultiPolygon const& multipolygon)
{
return multirange_constant_size_geometry
<
MultiPolygon, Segment
>::apply(multipolygon, segment);
}
};
template <typename Segment, typename Ring>
struct disjoint_segment_areal<Segment, Ring, ring_tag>
{
static inline bool apply(Segment const& segment, Ring const& ring)
{
if ( !disjoint_range_segment_or_box
<
Ring, closure<Ring>::value, Segment
>::apply(ring, segment) )
{
return false;
}
typename point_type<Segment>::type p;
detail::assign_point_from_index<0>(segment, p);
return !geometry::covered_by(p, ring);
}
};
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Linear, typename Areal>
struct disjoint<Linear, Areal, 2, linear_tag, areal_tag, false>
: public detail::disjoint::disjoint_linear_areal<Linear, Areal>
{};
template <typename Areal, typename Linear>
struct disjoint<Areal, Linear, 2, areal_tag, linear_tag, false>
{
static inline
bool apply(Areal const& areal, Linear const& linear)
{
return detail::disjoint::disjoint_linear_areal
<
Linear, Areal
>::apply(linear, areal);
}
};
template <typename Areal, typename Segment>
struct disjoint<Areal, Segment, 2, areal_tag, segment_tag, false>
{
static inline bool apply(Areal const& g1, Segment const& g2)
{
return detail::disjoint::disjoint_segment_areal
<
Segment, Areal
>::apply(g2, g1);
}
};
template <typename Segment, typename Areal>
struct disjoint<Segment, Areal, 2, segment_tag, areal_tag, false>
: detail::disjoint::disjoint_segment_areal<Segment, Areal>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_LINEAR_AREAL_HPP