Merge pull request #397 from awulkiew/feature/relops_multi_point

Add missing relational operations for MultiPoint/Geometry
This commit is contained in:
Adam Wulkiewicz 2017-05-23 13:24:19 +02:00 committed by GitHub
commit 1a605740cc
44 changed files with 4637 additions and 2820 deletions

View File

@ -20,453 +20,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
#include <cstddef>
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace covered_by {
struct use_point_in_geometry
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
return detail::within::point_in_geometry(geometry1, geometry2, strategy) >= 0;
}
};
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
typedef typename detail::de9im::static_mask_covered_by_type
<
Geometry1, Geometry2
>::type covered_by_mask;
return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
}
};
}} // namespace detail::covered_by
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type
>
struct covered_by
: not_implemented<Tag1, Tag2>
{};
template <typename Point, typename Box>
struct covered_by<Point, Box, point_tag, box_tag>
{
template <typename Strategy>
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
{
::boost::ignore_unused_variable_warning(strategy);
return strategy.apply(point, box);
}
};
template <typename Box1, typename Box2>
struct covered_by<Box1, Box2, box_tag, box_tag>
{
template <typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{
assert_dimension_equal<Box1, Box2>();
::boost::ignore_unused_variable_warning(strategy);
return strategy.apply(box1, box2);
}
};
// P/P
template <typename Point1, typename Point2>
struct covered_by<Point1, Point2, point_tag, point_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename MultiPoint>
struct covered_by<Point, MultiPoint, point_tag, multi_point_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename MultiPoint, typename Point>
struct covered_by<MultiPoint, Point, multi_point_tag, point_tag>
: public detail::within::multi_point_point
{};
template <typename MultiPoint1, typename MultiPoint2>
struct covered_by<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag>
: public detail::within::multi_point_multi_point
{};
// P/L
template <typename Point, typename Segment>
struct covered_by<Point, Segment, point_tag, segment_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename Linestring>
struct covered_by<Point, Linestring, point_tag, linestring_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename MultiLinestring>
struct covered_by<Point, MultiLinestring, point_tag, multi_linestring_tag>
: public detail::covered_by::use_point_in_geometry
{};
// P/A
template <typename Point, typename Ring>
struct covered_by<Point, Ring, point_tag, ring_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename Polygon>
struct covered_by<Point, Polygon, point_tag, polygon_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename MultiPolygon>
struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>
: public detail::covered_by::use_point_in_geometry
{};
// L/L
template <typename Linestring1, typename Linestring2>
struct covered_by<Linestring1, Linestring2, linestring_tag, linestring_tag>
: public detail::covered_by::use_relate
{};
template <typename Linestring, typename MultiLinestring>
struct covered_by<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename Linestring>
struct covered_by<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring1, typename MultiLinestring2>
struct covered_by<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
: public detail::covered_by::use_relate
{};
// L/A
template <typename Linestring, typename Ring>
struct covered_by<Linestring, Ring, linestring_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename Ring>
struct covered_by<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Linestring, typename Polygon>
struct covered_by<Linestring, Polygon, linestring_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename Polygon>
struct covered_by<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename Linestring, typename MultiPolygon>
struct covered_by<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename MultiPolygon>
struct covered_by<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
// A/A
template <typename Ring1, typename Ring2>
struct covered_by<Ring1, Ring2, ring_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Ring, typename Polygon>
struct covered_by<Ring, Polygon, ring_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename Polygon, typename Ring>
struct covered_by<Polygon, Ring, polygon_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Polygon1, typename Polygon2>
struct covered_by<Polygon1, Polygon2, polygon_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename Ring, typename MultiPolygon>
struct covered_by<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiPolygon, typename Ring>
struct covered_by<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Polygon, typename MultiPolygon>
struct covered_by<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiPolygon, typename Polygon>
struct covered_by<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiPolygon1, typename MultiPolygon2>
struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy {
struct covered_by
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::within::check
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
Strategy
>();
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
assert_dimension_equal<Geometry1, Geometry2>();
return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1,
geometry2,
strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::covered_by::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return covered_by::apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct covered_by
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_strategy::covered_by
::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2), m_strategy(strategy) {}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return covered_by<Geometry1, Geometry2>
::apply(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1), m_strategy(strategy) {}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return covered_by<Geometry1, Geometry2>
::apply(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template <
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct covered_by<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return covered_by<Geometry1, Geometry2>
::apply(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
} // namespace resolve_variant
/*!
\brief \brief_check12{is inside or on border}
\ingroup covered_by
\details \details_check12{covered_by, is inside or on border}.
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
\param geometry2 \param_geometry which might cover the first geometry
\return true if geometry1 is inside of or on the border of geometry2,
else false
\note The default strategy is used for covered_by detection
\qbk{[include reference/algorithms/covered_by.qbk]}
*/
template<typename Geometry1, typename Geometry2>
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::covered_by<Geometry1, Geometry2>
::apply(geometry1, geometry2, default_strategy());
}
/*!
\brief \brief_check12{is inside or on border} \brief_strategy
\ingroup covered_by
\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
\param geometry2 \param_geometry which might cover the first geometry
\param strategy strategy to be used
\return true if geometry1 is inside of or on the border of geometry2,
else false
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/covered_by.qbk]}
*/
template<typename Geometry1, typename Geometry2, typename Strategy>
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::covered_by<Geometry1, Geometry2>
::apply(geometry1, geometry2, strategy);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP

View File

@ -0,0 +1,280 @@
// 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, 2014, 2017.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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_COVERED_BY_IMPLEMENTATION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP
#include <cstddef>
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
#include <boost/geometry/algorithms/detail/within/implementation.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace covered_by {
struct use_point_in_geometry
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
return detail::within::point_in_geometry(geometry1, geometry2, strategy) >= 0;
}
};
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
typedef typename detail::de9im::static_mask_covered_by_type
<
Geometry1, Geometry2
>::type covered_by_mask;
return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
}
};
}} // namespace detail::covered_by
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Point, typename Box>
struct covered_by<Point, Box, point_tag, box_tag>
{
template <typename Strategy>
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
{
::boost::ignore_unused_variable_warning(strategy);
return strategy.apply(point, box);
}
};
template <typename Box1, typename Box2>
struct covered_by<Box1, Box2, box_tag, box_tag>
{
template <typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{
assert_dimension_equal<Box1, Box2>();
::boost::ignore_unused_variable_warning(strategy);
return strategy.apply(box1, box2);
}
};
// P/P
template <typename Point1, typename Point2>
struct covered_by<Point1, Point2, point_tag, point_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename MultiPoint>
struct covered_by<Point, MultiPoint, point_tag, multi_point_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename MultiPoint, typename Point>
struct covered_by<MultiPoint, Point, multi_point_tag, point_tag>
: public detail::within::multi_point_point
{};
template <typename MultiPoint1, typename MultiPoint2>
struct covered_by<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag>
: public detail::within::multi_point_multi_point
{};
// P/L
template <typename Point, typename Segment>
struct covered_by<Point, Segment, point_tag, segment_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename Linestring>
struct covered_by<Point, Linestring, point_tag, linestring_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename MultiLinestring>
struct covered_by<Point, MultiLinestring, point_tag, multi_linestring_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename MultiPoint, typename Segment>
struct covered_by<MultiPoint, Segment, multi_point_tag, segment_tag>
: public detail::within::multi_point_single_geometry<false>
{};
template <typename MultiPoint, typename Linestring>
struct covered_by<MultiPoint, Linestring, multi_point_tag, linestring_tag>
: public detail::within::multi_point_single_geometry<false>
{};
template <typename MultiPoint, typename MultiLinestring>
struct covered_by<MultiPoint, MultiLinestring, multi_point_tag, multi_linestring_tag>
: public detail::within::multi_point_multi_geometry<false>
{};
// P/A
template <typename Point, typename Ring>
struct covered_by<Point, Ring, point_tag, ring_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename Polygon>
struct covered_by<Point, Polygon, point_tag, polygon_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename Point, typename MultiPolygon>
struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>
: public detail::covered_by::use_point_in_geometry
{};
template <typename MultiPoint, typename Ring>
struct covered_by<MultiPoint, Ring, multi_point_tag, ring_tag>
: public detail::within::multi_point_single_geometry<false>
{};
template <typename MultiPoint, typename Polygon>
struct covered_by<MultiPoint, Polygon, multi_point_tag, polygon_tag>
: public detail::within::multi_point_single_geometry<false>
{};
template <typename MultiPoint, typename MultiPolygon>
struct covered_by<MultiPoint, MultiPolygon, multi_point_tag, multi_polygon_tag>
: public detail::within::multi_point_multi_geometry<false>
{};
// L/L
template <typename Linestring1, typename Linestring2>
struct covered_by<Linestring1, Linestring2, linestring_tag, linestring_tag>
: public detail::covered_by::use_relate
{};
template <typename Linestring, typename MultiLinestring>
struct covered_by<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename Linestring>
struct covered_by<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring1, typename MultiLinestring2>
struct covered_by<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
: public detail::covered_by::use_relate
{};
// L/A
template <typename Linestring, typename Ring>
struct covered_by<Linestring, Ring, linestring_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename Ring>
struct covered_by<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Linestring, typename Polygon>
struct covered_by<Linestring, Polygon, linestring_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename Polygon>
struct covered_by<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename Linestring, typename MultiPolygon>
struct covered_by<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiLinestring, typename MultiPolygon>
struct covered_by<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
// A/A
template <typename Ring1, typename Ring2>
struct covered_by<Ring1, Ring2, ring_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Ring, typename Polygon>
struct covered_by<Ring, Polygon, ring_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename Polygon, typename Ring>
struct covered_by<Polygon, Ring, polygon_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Polygon1, typename Polygon2>
struct covered_by<Polygon1, Polygon2, polygon_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename Ring, typename MultiPolygon>
struct covered_by<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiPolygon, typename Ring>
struct covered_by<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
: public detail::covered_by::use_relate
{};
template <typename Polygon, typename MultiPolygon>
struct covered_by<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiPolygon, typename Polygon>
struct covered_by<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
: public detail::covered_by::use_relate
{};
template <typename MultiPolygon1, typename MultiPolygon2>
struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
: public detail::covered_by::use_relate
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_HPP

View File

@ -0,0 +1,261 @@
// 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, 2014, 2017.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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_COVERED_BY_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/within/interface.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type
>
struct covered_by
: not_implemented<Tag1, Tag2>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy {
struct covered_by
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::within::check
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
Strategy
>();
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
assert_dimension_equal<Geometry1, Geometry2>();
return dispatch::covered_by<Geometry1, Geometry2>::apply(geometry1,
geometry2,
strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::covered_by::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return covered_by::apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct covered_by
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_strategy::covered_by
::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2), m_strategy(strategy) {}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return covered_by<Geometry1, Geometry2>
::apply(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1), m_strategy(strategy) {}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return covered_by<Geometry1, Geometry2>
::apply(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template <
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct covered_by<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return covered_by<Geometry1, Geometry2>
::apply(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
} // namespace resolve_variant
/*!
\brief \brief_check12{is inside or on border}
\ingroup covered_by
\details \details_check12{covered_by, is inside or on border}.
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
\param geometry2 \param_geometry which might cover the first geometry
\return true if geometry1 is inside of or on the border of geometry2,
else false
\note The default strategy is used for covered_by detection
\qbk{[include reference/algorithms/covered_by.qbk]}
*/
template<typename Geometry1, typename Geometry2>
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::covered_by<Geometry1, Geometry2>
::apply(geometry1, geometry2, default_strategy());
}
/*!
\brief \brief_check12{is inside or on border} \brief_strategy
\ingroup covered_by
\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry which might be inside or on the border of the second geometry
\param geometry2 \param_geometry which might cover the first geometry
\param strategy strategy to be used
\return true if geometry1 is inside of or on the border of geometry2,
else false
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/covered_by.qbk]}
*/
template<typename Geometry1, typename Geometry2, typename Strategy>
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::covered_by<Geometry1, Geometry2>
::apply(geometry1, geometry2, strategy);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP

View File

@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013-2014.
// Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
// This file was modified by Oracle on 2013-2017.
// Modifications copyright (c) 2013-2017, 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

View File

@ -31,7 +31,9 @@
#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
@ -141,11 +143,7 @@ private:
static inline bool apply(Box const& box, Point const& point)
{
// The default strategy is enough in this case
typedef typename strategy::disjoint::services::default_strategy
<
Point, Box
>::type strategy_type;
return ! dispatch::disjoint<Point, Box>::apply(point, box, strategy_type());
return ! detail::disjoint::disjoint_point_box(point, box);
}
};
@ -252,6 +250,176 @@ public:
};
template <typename MultiPoint, typename SingleGeometry>
class multi_point_single_geometry
{
public:
template <typename Strategy>
static inline bool apply(MultiPoint const& multi_point, SingleGeometry const& single_geometry, Strategy const& strategy)
{
typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<SingleGeometry>::type point2_type;
typedef model::box<point2_type> box2_type;
box2_type box2;
geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy());
geometry::detail::expand_by_epsilon(box2);
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
{
// The default strategy is enough for Point/Box
if (! detail::disjoint::disjoint_point_box(*it, box2)
&& ! dispatch::disjoint<point1_type, SingleGeometry>::apply(*it, single_geometry, strategy))
{
return false;
}
}
return true;
}
template <typename Strategy>
static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point, Strategy const& strategy)
{
return apply(multi_point, single_geometry, strategy);
}
};
template <typename MultiPoint, typename MultiGeometry>
class multi_point_multi_geometry
{
private:
struct expand_box_point
{
template <typename Box, typename Point>
static inline void apply(Box& total, Point const& point)
{
geometry::expand(total, point);
}
};
struct expand_box_box_pair
{
template <typename Box, typename BoxPair>
inline void apply(Box& total, BoxPair const& box_pair) const
{
geometry::expand(total, box_pair.first);
}
};
struct overlaps_box_point
{
template <typename Box, typename Point>
static inline bool apply(Box const& box, Point const& point)
{
// The default strategy is enough for Point/Box
return ! detail::disjoint::disjoint_point_box(point, box);
}
};
struct overlaps_box_box_pair
{
template <typename Box, typename BoxPair>
inline bool apply(Box const& box, BoxPair const& box_pair) const
{
// The default strategy is enough for Box/Box
return ! detail::disjoint::disjoint_box_box(box_pair.first, box);
}
};
template <typename PtSegStrategy>
class item_visitor_type
{
public:
item_visitor_type(MultiGeometry const& multi_geometry,
PtSegStrategy const& strategy)
: m_intersection_found(false)
, m_multi_geometry(multi_geometry)
, m_strategy(strategy)
{}
template <typename Point, typename BoxPair>
inline bool apply(Point const& point, BoxPair const& box_pair)
{
typedef typename boost::range_value<MultiGeometry>::type single_type;
// The default strategy is enough for Point/Box
if (! m_intersection_found
&& ! detail::disjoint::disjoint_point_box(point, box_pair.first)
&& ! dispatch::disjoint<Point, single_type>::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy))
{
m_intersection_found = true;
return false;
}
return true;
}
inline bool intersection_found() const { return m_intersection_found; }
private:
bool m_intersection_found;
MultiGeometry const& m_multi_geometry;
PtSegStrategy const& m_strategy;
};
// structs for partition -- end
public:
template <typename Strategy>
static inline bool apply(MultiPoint const& multi_point, MultiGeometry const& multi_geometry, Strategy const& strategy)
{
typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<MultiGeometry>::type point2_type;
typedef model::box<point1_type> box1_type;
typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type;
typename Strategy::envelope_strategy_type const
envelope_strategy = strategy.get_envelope_strategy();
std::size_t count2 = boost::size(multi_geometry);
std::vector<box_pair_type> boxes(count2);
for (std::size_t i = 0 ; i < count2 ; ++i)
{
geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy);
geometry::detail::expand_by_epsilon(boxes[i].first);
boxes[i].second = i;
}
item_visitor_type<Strategy> visitor(multi_geometry, strategy);
geometry::partition
<
box1_type
>::apply(multi_point, boxes, visitor,
expand_box_point(),
overlaps_box_point(),
expand_box_box_pair(),
overlaps_box_box_pair());
return ! visitor.intersection_found();
}
template <typename Strategy>
static inline bool apply(MultiGeometry const& multi_geometry, MultiPoint const& multi_point, Strategy const& strategy)
{
return apply(multi_point, multi_geometry, strategy);
}
};
template <typename MultiPoint, typename Areal, typename Tag = typename tag<Areal>::type>
struct multipoint_areal
: multi_point_single_geometry<MultiPoint, Areal>
{};
template <typename MultiPoint, typename Areal>
struct multipoint_areal<MultiPoint, Areal, multi_polygon_tag>
: multi_point_multi_geometry<MultiPoint, Areal>
{};
}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL
@ -336,6 +504,22 @@ struct disjoint
{};
template <typename Areal, typename MultiPoint, std::size_t DimensionCount>
struct disjoint
<
Areal, MultiPoint, DimensionCount, areal_tag, multi_point_tag, false
> : detail::disjoint::multipoint_areal<MultiPoint, Areal>
{};
template <typename MultiPoint, typename Areal, std::size_t DimensionCount>
struct disjoint
<
MultiPoint, Areal, DimensionCount, multi_point_tag, areal_tag, false
> : detail::disjoint::multipoint_areal<MultiPoint, Areal>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

View File

@ -0,0 +1,397 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015, 2016, 2017.
// Modifications copyright (c) 2014-2017 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_EQUALS_IMPLEMENTATION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP
#include <cstddef>
#include <vector>
#include <boost/range.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
// For trivial checks
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/length.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace equals
{
template
<
std::size_t Dimension,
std::size_t DimensionCount
>
struct point_point
{
template <typename Point1, typename Point2, typename Strategy>
static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy)
{
return ! detail::disjoint::point_point
<
Point1, Point2,
Dimension, DimensionCount
>::apply(point1, point2, strategy);
}
};
template
<
std::size_t Dimension,
std::size_t DimensionCount
>
struct box_box
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{
if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
|| !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
{
return false;
}
return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy);
}
};
template <std::size_t DimensionCount>
struct box_box<DimensionCount, DimensionCount>
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& , Box2 const& , Strategy const& )
{
return true;
}
};
struct segment_segment
{
template <typename Segment1, typename Segment2, typename Strategy>
static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& )
{
return equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1),
indexed_point_view<Segment2 const, 0>(segment2) )
? equals::equals_point_point(
indexed_point_view<Segment1 const, 1>(segment1),
indexed_point_view<Segment2 const, 1>(segment2) )
: ( equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1),
indexed_point_view<Segment2 const, 1>(segment2) )
&& equals::equals_point_point(
indexed_point_view<Segment1 const, 1>(segment1),
indexed_point_view<Segment2 const, 0>(segment2) )
);
}
};
struct area_check
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return geometry::math::equals(
geometry::area(geometry1,
strategy.template get_area_strategy<Geometry1>()),
geometry::area(geometry2,
strategy.template get_area_strategy<Geometry2>()));
}
};
struct length_check
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return geometry::math::equals(
geometry::length(geometry1,
strategy.template get_distance_strategy<Geometry1>()),
geometry::length(geometry2,
strategy.template get_distance_strategy<Geometry2>()));
}
};
template <typename Geometry1, typename Geometry2, typename IntersectionStrategy>
struct collected_vector
{
typedef typename geometry::select_most_precise
<
typename select_coordinate_type
<
Geometry1, Geometry2
>::type,
double
>::type calculation_type;
typedef geometry::collected_vector
<
calculation_type,
Geometry1,
typename IntersectionStrategy::side_strategy_type
> type;
};
template <typename TrivialCheck>
struct equals_by_collection
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
if (! TrivialCheck::apply(geometry1, geometry2, strategy))
{
return false;
}
typedef typename collected_vector
<
Geometry1, Geometry2, Strategy
>::type collected_vector_type;
std::vector<collected_vector_type> c1, c2;
geometry::collect_vectors(c1, geometry1);
geometry::collect_vectors(c2, geometry2);
if (boost::size(c1) != boost::size(c2))
{
return false;
}
std::sort(c1.begin(), c1.end());
std::sort(c2.begin(), c2.end());
// Just check if these vectors are equal.
return std::equal(c1.begin(), c1.end(), c2.begin());
}
};
template<typename Geometry1, typename Geometry2>
struct equals_by_relate
: detail::relate::relate_impl
<
detail::de9im::static_mask_equals_type,
Geometry1,
Geometry2
>
{};
// If collect_vectors which is a SideStrategy-dispatched optimization
// is implemented in a way consistent with the Intersection/Side Strategy
// then collect_vectors is used, otherwise relate is used.
// NOTE: the result could be conceptually different for invalid
// geometries in different coordinate systems because collect_vectors
// and relate treat invalid geometries differently.
template<typename TrivialCheck>
struct equals_by_collection_or_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
typedef typename boost::is_base_of
<
nyi::not_implemented_tag,
typename collected_vector
<
Geometry1, Geometry2, Strategy
>::type
>::type enable_relate_type;
return apply(geometry1, geometry2, strategy, enable_relate_type());
}
private:
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
boost::false_type /*enable_relate*/)
{
return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
boost::true_type /*enable_relate*/)
{
return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
}
};
}} // namespace detail::equals
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
: detail::equals::point_point<0, DimensionCount>
{};
template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
: detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
{};
template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
: detail::equals::equals_by_relate<Point, MultiPoint>
{};
template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
: detail::equals::box_box<0, DimensionCount>
{};
template <typename Ring1, typename Ring2, bool Reverse>
struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon1, typename Polygon2, bool Reverse>
struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon, typename Ring, bool Reverse>
struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Ring, typename Box, bool Reverse>
struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Polygon, typename Box, bool Reverse>
struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>
: detail::equals::segment_segment
{};
template <typename LineString1, typename LineString2, bool Reverse>
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString1, LineString2>
{};
template <typename LineString, typename MultiLineString, bool Reverse>
struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString, MultiLineString>
{};
template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>
: detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
{};
template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
struct equals
<
MultiPolygon1, MultiPolygon2,
multi_polygon_tag, multi_polygon_tag,
2,
Reverse
>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon, typename MultiPolygon, bool Reverse>
struct equals
<
Polygon, MultiPolygon,
polygon_tag, multi_polygon_tag,
2,
Reverse
>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename MultiPolygon, typename Ring, bool Reverse>
struct equals
<
MultiPolygon, Ring,
multi_polygon_tag, ring_tag,
2,
Reverse
>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_HPP

View File

@ -0,0 +1,317 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015, 2016, 2017.
// Modifications copyright (c) 2014-2017 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_EQUALS_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP
#include <cstddef>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type,
std::size_t DimensionCount = dimension<Geometry1>::type::value,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct equals: not_implemented<Tag1, Tag2>
{};
// If reversal is needed, perform it
template
<
typename Geometry1, typename Geometry2,
typename Tag1, typename Tag2,
std::size_t DimensionCount
>
struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
: equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
return equals
<
Geometry2, Geometry1,
Tag2, Tag1,
DimensionCount,
false
>::apply(g2, g1, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
struct equals
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return dispatch::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::relate::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return dispatch::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct equals
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check_concepts_and_equal_dimensions
<
Geometry1 const,
Geometry2 const
>();
return resolve_strategy::equals
::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
, m_strategy(strategy)
{}
template <typename Geometry1>
inline bool operator()(Geometry1 const& geometry1) const
{
return equals<Geometry1, Geometry2>
::apply(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy
)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
, m_strategy(strategy)
{}
template <typename Geometry2>
inline bool operator()(Geometry2 const& geometry2) const
{
return equals<Geometry1, Geometry2>
::apply(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(
Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy
)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template <
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct equals<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
struct visitor: static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
inline bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return equals<Geometry1, Geometry2>
::apply(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy
)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
} // namespace resolve_variant
/*!
\brief \brief_check{are spatially equal}
\details \details_check12{equals, is spatially equal}. Spatially equal means
that the same point set is included. A box can therefore be spatially equal
to a ring or a polygon, or a linestring can be spatially equal to a
multi-linestring or a segment. This only works theoretically, not all
combinations are implemented yet.
\ingroup equals
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Equals}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{equals}
\return \return_check2{are spatially equal}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/equals.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool equals(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
/*!
\brief \brief_check{are spatially equal}
\details \details_check12{equals, is spatially equal}. Spatially equal means
that the same point set is included. A box can therefore be spatially equal
to a ring or a polygon, or a linestring can be spatially equal to a
multi-linestring or a segment. This only works theoretically, not all
combinations are implemented yet.
\ingroup equals
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{are spatially equal}
\qbk{[include reference/algorithms/equals.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::equals<Geometry1, Geometry2>
::apply(geometry1, geometry2, default_strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_INTERFACE_HPP

View File

@ -0,0 +1,88 @@
// 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.
// This file was modified by Oracle on 2013-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, 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_INTERSECTS_IMPLEMENTATION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_IMPLEMENTATION_HPP
#include <deque>
#include <boost/geometry/algorithms/detail/intersects/interface.hpp>
#include <boost/geometry/algorithms/detail/disjoint/implementation.hpp>
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/strategies/relate.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace intersects
{
template <typename Geometry>
struct self_intersects
{
static bool apply(Geometry const& geometry)
{
concepts::check<Geometry const>();
typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename strategy::relate::services::default_strategy
<
Geometry, Geometry
>::type strategy_type;
typedef detail::no_rescale_policy rescale_policy_type;
typedef detail::overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
std::deque<turn_info> turns;
typedef detail::overlay::get_turn_info
<
detail::overlay::assign_null_policy
> turn_policy;
strategy_type strategy;
rescale_policy_type robust_policy;
detail::disjoint::disjoint_interrupt_policy policy;
detail::self_get_turn_points::get_turns
<
turn_policy
>::apply(geometry, strategy, robust_policy, turns, policy, 0);
return policy.has_intersections;
}
};
}} // namespace detail::intersects
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_IMPLEMENTATION_HPP

View File

@ -0,0 +1,115 @@
// 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.
// This file was modified by Oracle on 2013-2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, 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_INTERSECTS_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_INTERFACE_HPP
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace intersects
{
// Forward declaration
template <typename Geometry>
struct self_intersects;
}} // namespace detail::intersects
#endif // DOXYGEN_NO_DETAIL
/*!
\brief \brief_check{has at least one intersection (crossing or self-tangency)}
\note This function can be called for one geometry (self-intersection) and
also for two geometries (intersection)
\ingroup intersects
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\return \return_check{is self-intersecting}
\qbk{distinguish,one geometry}
\qbk{[def __one_parameter__]}
\qbk{[include reference/algorithms/intersects.qbk]}
*/
template <typename Geometry>
inline bool intersects(Geometry const& geometry)
{
return detail::intersects::self_intersects<Geometry>::apply(geometry);
}
/*!
\brief \brief_check2{have at least one intersection}
\ingroup intersects
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Intersects}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{intersects}
\return \return_check2{intersect each other}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/intersects.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool intersects(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return ! geometry::disjoint(geometry1, geometry2, strategy);
}
/*!
\brief \brief_check2{have at least one intersection}
\ingroup intersects
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{intersect each other}
\qbk{distinguish,two geometries}
\qbk{[include reference/algorithms/intersects.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool intersects(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return ! geometry::disjoint(geometry1, geometry2);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTS_INTERFACE_HPP

View File

@ -0,0 +1,156 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014, 2015, 2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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_OVERLAPS_IMPLEMENTATION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_IMPLEMENTATION_HPP
#include <cstddef>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlaps
{
template
<
std::size_t Dimension,
std::size_t DimensionCount
>
struct box_box_loop
{
template <typename Box1, typename Box2>
static inline void apply(Box1 const& b1, Box2 const& b2,
bool& overlaps, bool& one_in_two, bool& two_in_one)
{
assert_dimension_equal<Box1, Box2>();
typedef typename coordinate_type<Box1>::type coordinate_type1;
typedef typename coordinate_type<Box2>::type coordinate_type2;
coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
// We might use the (not yet accepted) Boost.Interval
// submission in the future
// If:
// B1: |-------|
// B2: |------|
// in any dimension -> no overlap
if (max1 <= min2 || min1 >= max2)
{
overlaps = false;
return;
}
// If:
// B1: |--------------------|
// B2: |-------------|
// in all dimensions -> within, then no overlap
// B1: |--------------------|
// B2: |-------------|
// this is "within-touch" -> then no overlap. So use < and >
if (min1 < min2 || max1 > max2)
{
one_in_two = false;
}
// Same other way round
if (min2 < min1 || max2 > max1)
{
two_in_one = false;
}
box_box_loop
<
Dimension + 1,
DimensionCount
>::apply(b1, b2, overlaps, one_in_two, two_in_one);
}
};
template
<
std::size_t DimensionCount
>
struct box_box_loop<DimensionCount, DimensionCount>
{
template <typename Box1, typename Box2>
static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&)
{
}
};
struct box_box
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
{
bool overlaps = true;
bool within1 = true;
bool within2 = true;
box_box_loop
<
0,
dimension<Box1>::type::value
>::apply(b1, b2, overlaps, within1, within2);
/*
\see http://docs.codehaus.org/display/GEOTDOC/02+Geometry+Relationships#02GeometryRelationships-Overlaps
where is stated that "inside" is not an "overlap",
this is true and is implemented as such.
*/
return overlaps && ! within1 && ! within2;
}
};
}} // namespace detail::overlaps
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Box1, typename Box2>
struct overlaps<Box1, Box2, box_tag, box_tag>
: detail::overlaps::box_box
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_IMPLEMENTATION_HPP

View File

@ -0,0 +1,124 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014, 2015, 2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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_OVERLAPS_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_INTERFACE_HPP
#include <cstddef>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/strategies/relate.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type
>
struct overlaps
: detail::relate::relate_impl
<
detail::de9im::static_mask_overlaps_type,
Geometry1,
Geometry2
>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
/*!
\brief \brief_check2{overlap}
\ingroup overlaps
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Overlaps}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{overlaps}
\return \return_check2{overlap}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/overlaps.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool overlaps(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return dispatch::overlaps
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, strategy);
}
/*!
\brief \brief_check2{overlap}
\ingroup overlaps
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{overlap}
\qbk{[include reference/algorithms/overlaps.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
typedef typename strategy::relate::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return dispatch::overlaps
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, strategy_type());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAPS_INTERFACE_HPP

View File

@ -23,6 +23,7 @@
#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp>
#include <boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp>
#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
#include <boost/geometry/strategies/intersection.hpp>
@ -81,6 +82,16 @@ struct relate<Geometry, Point, Tag1, point_tag, TopDim1, 0, true>
: detail::relate::geometry_point<Geometry, Point>
{};
template <typename MultiPoint, typename Geometry, typename Tag2, int TopDim2>
struct relate<MultiPoint, Geometry, multi_point_tag, Tag2, 0, TopDim2, false>
: detail::relate::multi_point_geometry<MultiPoint, Geometry>
{};
template <typename Geometry, typename MultiPoint, typename Tag1, int TopDim1>
struct relate<Geometry, MultiPoint, Tag1, multi_point_tag, TopDim1, 0, false>
: detail::relate::geometry_multi_point<Geometry, MultiPoint>
{};
template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
struct relate<Linear1, Linear2, Tag1, Tag2, 1, 1, true>

View File

@ -0,0 +1,568 @@
// Boost.Geometry
// Copyright (c) 2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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_RELATE_MULTI_POINT_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_MULTI_POINT_GEOMETRY_HPP
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/algorithms/detail/relate/result.hpp>
#include <boost/geometry/algorithms/detail/relate/topology_check.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/core/is_areal.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/index/rtree.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace relate
{
template
<
typename Geometry,
typename Tag = typename tag<Geometry>::type
>
struct multi_point_geometry_eb
{
template <typename MultiPoint>
static inline bool apply(MultiPoint const& ,
detail::relate::topology_check<Geometry> const& )
{
return true;
}
};
template <typename Geometry>
struct multi_point_geometry_eb<Geometry, linestring_tag>
{
template <typename Points>
struct boundary_visitor
{
boundary_visitor(Points const& points)
: m_points(points)
, m_boundary_found(false)
{}
template <typename Point>
struct find_pred
{
find_pred(Point const& point)
: m_point(point)
{}
template <typename Pt>
bool operator()(Pt const& pt) const
{
return detail::equals::equals_point_point(pt, m_point);
}
Point const& m_point;
};
template <typename Point>
bool apply(Point const& boundary_point)
{
if (std::find_if(m_points.begin(), m_points.end(), find_pred<Point>(boundary_point)) == m_points.end())
{
m_boundary_found = true;
return false;
}
return true;
}
bool result() const { return m_boundary_found; }
private:
Points const& m_points;
bool m_boundary_found;
};
template <typename MultiPoint>
static inline bool apply(MultiPoint const& multi_point,
detail::relate::topology_check<Geometry> const& tc)
{
boundary_visitor<MultiPoint> visitor(multi_point);
tc.for_each_boundary_point(visitor);
return visitor.result();
}
};
template <typename Geometry>
struct multi_point_geometry_eb<Geometry, multi_linestring_tag>
{
template <typename Points>
struct boundary_visitor
{
boundary_visitor(Points const& points)
: m_points(points)
, m_boundary_found(false)
{}
template <typename Point>
bool apply(Point const& boundary_point)
{
if (! std::binary_search(m_points.begin(), m_points.end(), boundary_point, relate::less()))
{
m_boundary_found = true;
return false;
}
return true;
}
bool result() const { return m_boundary_found; }
private:
Points const& m_points;
bool m_boundary_found;
};
template <typename MultiPoint>
static inline bool apply(MultiPoint const& multi_point,
detail::relate::topology_check<Geometry> const& tc)
{
typedef typename boost::range_value<MultiPoint>::type point_type;
typedef std::vector<point_type> points_type;
points_type points(boost::begin(multi_point), boost::end(multi_point));
std::sort(points.begin(), points.end(), relate::less());
boundary_visitor<points_type> visitor(points);
tc.for_each_boundary_point(visitor);
return visitor.result();
}
};
// SingleGeometry - Linear or Areal
template <typename MultiPoint, typename SingleGeometry, bool Transpose = false>
struct multi_point_single_geometry
{
static const bool interruption_enabled = true;
template <typename Result, typename Strategy>
static inline void apply(MultiPoint const& multi_point,
SingleGeometry const& single_geometry,
Result & result,
Strategy const& strategy)
{
typedef typename point_type<SingleGeometry>::type point2_type;
typedef model::box<point2_type> box2_type;
box2_type box2;
geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy());
geometry::detail::expand_by_epsilon(box2);
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
{
if (! (relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result)
|| relate::may_update<interior, exterior, '0', Transpose>(result) ) )
{
break;
}
// The default strategy is enough for Point/Box
if (detail::disjoint::disjoint_point_box(*it, box2))
{
relate::set<interior, exterior, '0', Transpose>(result);
}
else
{
int in_val = detail::within::point_in_geometry(*it, single_geometry, strategy);
if (in_val > 0) // within
{
relate::set<interior, interior, '0', Transpose>(result);
}
else if (in_val == 0)
{
relate::set<interior, boundary, '0', Transpose>(result);
}
else // in_val < 0 - not within
{
relate::set<interior, exterior, '0', Transpose>(result);
}
}
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
{
return;
}
}
typedef detail::relate::topology_check<SingleGeometry> tc_t;
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
|| relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
{
tc_t tc(single_geometry);
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
&& tc.has_interior() )
{
// TODO: this is not true if a linestring is degenerated to a point
// then the interior has topological dimension = 0, not 1
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
}
if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result)
&& tc.has_boundary() )
{
if (multi_point_geometry_eb<SingleGeometry>::apply(multi_point, tc))
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
}
relate::set<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
}
};
// MultiGeometry - Linear or Areal
// part of the algorithm calculating II and IB when no IE has to be calculated
// using partition()
template <typename MultiPoint, typename MultiGeometry, bool Transpose>
class multi_point_multi_geometry_ii_ib
{
struct expand_box_point
{
template <typename Box, typename Point>
static inline void apply(Box& total, Point const& point)
{
geometry::expand(total, point);
}
};
struct expand_box_box_pair
{
template <typename Box, typename BoxPair>
static inline void apply(Box& total, BoxPair const& box_pair)
{
geometry::expand(total, box_pair.first);
}
};
struct overlaps_box_point
{
template <typename Box, typename Point>
static inline bool apply(Box const& box, Point const& point)
{
// The default strategy is enough for Point/Box
return ! detail::disjoint::disjoint_point_box(point, box);
}
};
struct overlaps_box_box_pair
{
template <typename Box, typename BoxPair>
static inline bool apply(Box const& box, BoxPair const& box_pair)
{
// The default strategy is enough for Box/Box
return ! detail::disjoint::disjoint_box_box(box_pair.first, box);
}
};
template <typename Result, typename PtSegStrategy>
class item_visitor_type
{
public:
item_visitor_type(MultiGeometry const& multi_geometry,
detail::relate::topology_check<MultiGeometry> const& tc,
Result & result,
PtSegStrategy const& strategy)
: m_multi_geometry(multi_geometry)
, m_tc(tc)
, m_result(result)
, m_strategy(strategy)
{}
template <typename Point, typename BoxPair>
inline bool apply(Point const& point, BoxPair const& box_pair)
{
// The default strategy is enough for Point/Box
if (! detail::disjoint::disjoint_point_box(point, box_pair.first))
{
typename boost::range_value<MultiGeometry>::type const&
single = range::at(m_multi_geometry, box_pair.second);
int in_val = detail::within::point_in_geometry(point, single, m_strategy);
if (in_val > 0) // within
{
relate::set<interior, interior, '0', Transpose>(m_result);
}
else if (in_val == 0)
{
if (m_tc.check_boundary_point(point))
relate::set<interior, boundary, '0', Transpose>(m_result);
else
relate::set<interior, interior, '0', Transpose>(m_result);
}
}
if ( BOOST_GEOMETRY_CONDITION(m_result.interrupt) )
{
return false;
}
if (! (relate::may_update<interior, interior, '0', Transpose>(m_result)
|| relate::may_update<interior, boundary, '0', Transpose>(m_result) ) )
{
return false;
}
return true;
}
private:
MultiGeometry const& m_multi_geometry;
detail::relate::topology_check<MultiGeometry> const& m_tc;
Result & m_result;
PtSegStrategy const& m_strategy;
};
public:
typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<MultiGeometry>::type point2_type;
typedef model::box<point1_type> box1_type;
typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type;
template <typename Result, typename Strategy>
static inline void apply(MultiPoint const& multi_point,
MultiGeometry const& multi_geometry,
std::vector<box_pair_type> const& boxes,
detail::relate::topology_check<MultiGeometry> const& tc,
Result & result,
Strategy const& strategy)
{
item_visitor_type<Result, Strategy> visitor(multi_geometry, tc, result, strategy);
geometry::partition
<
box1_type
>::apply(multi_point, boxes, visitor,
expand_box_point(),
overlaps_box_point(),
expand_box_box_pair(),
overlaps_box_box_pair());
}
};
// MultiGeometry - Linear or Areal
// part of the algorithm calculating II, IB and IE
// using rtree
template <typename MultiPoint, typename MultiGeometry, bool Transpose>
struct multi_point_multi_geometry_ii_ib_ie
{
typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<MultiGeometry>::type point2_type;
typedef model::box<point1_type> box1_type;
typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type;
typedef std::vector<box_pair_type> boxes_type;
typedef typename boxes_type::const_iterator boxes_iterator;
template <typename Result, typename Strategy>
static inline void apply(MultiPoint const& multi_point,
MultiGeometry const& multi_geometry,
std::vector<box_pair_type> const& boxes,
detail::relate::topology_check<MultiGeometry> const& tc,
Result & result,
Strategy const& strategy)
{
index::rtree<box_pair_type, index::rstar<4> > rt(boxes.begin(), boxes.end());
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
{
if (! (relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result)
|| relate::may_update<interior, exterior, '0', Transpose>(result) ) )
{
return;
}
typename boost::range_value<MultiPoint>::type const& point = *it;
boxes_type boxes_found;
rt.query(index::intersects(point), std::back_inserter(boxes_found));
bool found_ii_or_ib = false;
for (boxes_iterator bi = boxes_found.begin() ; bi != boxes_found.end() ; ++bi)
{
typename boost::range_value<MultiGeometry>::type const&
single = range::at(multi_geometry, bi->second);
int in_val = detail::within::point_in_geometry(point, single, strategy);
if (in_val > 0) // within
{
relate::set<interior, interior, '0', Transpose>(result);
found_ii_or_ib = true;
}
else if (in_val == 0) // on boundary of single
{
if (tc.check_boundary_point(point))
relate::set<interior, boundary, '0', Transpose>(result);
else
relate::set<interior, interior, '0', Transpose>(result);
found_ii_or_ib = true;
}
}
// neither interior nor boundary found -> exterior
if (found_ii_or_ib == false)
{
relate::set<interior, exterior, '0', Transpose>(result);
}
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
{
return;
}
}
}
};
// MultiGeometry - Linear or Areal
template <typename MultiPoint, typename MultiGeometry, bool Transpose = false>
struct multi_point_multi_geometry
{
static const bool interruption_enabled = true;
template <typename Result, typename Strategy>
static inline void apply(MultiPoint const& multi_point,
MultiGeometry const& multi_geometry,
Result & result,
Strategy const& strategy)
{
typedef typename point_type<MultiGeometry>::type point2_type;
typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type;
typename Strategy::envelope_strategy_type const
envelope_strategy = strategy.get_envelope_strategy();
std::size_t count2 = boost::size(multi_geometry);
std::vector<box_pair_type> boxes(count2);
for (std::size_t i = 0 ; i < count2 ; ++i)
{
geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy);
geometry::detail::expand_by_epsilon(boxes[i].first);
boxes[i].second = i;
}
typedef detail::relate::topology_check<MultiGeometry> tc_t;
tc_t tc(multi_geometry);
if ( relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result)
|| relate::may_update<interior, exterior, '0', Transpose>(result) )
{
// If there is no need to calculate IE, use partition
if (! relate::may_update<interior, exterior, '0', Transpose>(result) )
{
multi_point_multi_geometry_ii_ib<MultiPoint, MultiGeometry, Transpose>
::apply(multi_point, multi_geometry, boxes, tc, result, strategy);
}
else // otherwise use rtree
{
multi_point_multi_geometry_ii_ib_ie<MultiPoint, MultiGeometry, Transpose>
::apply(multi_point, multi_geometry, boxes, tc, result, strategy);
}
}
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
{
return;
}
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
|| relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
{
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
&& tc.has_interior() )
{
// TODO: this is not true if a linestring is degenerated to a point
// then the interior has topological dimension = 0, not 1
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
}
if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result)
&& tc.has_boundary() )
{
if (multi_point_geometry_eb<MultiGeometry>::apply(multi_point, tc))
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
}
relate::set<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
}
};
template
<
typename MultiPoint, typename Geometry,
bool Transpose = false,
bool isMulti = boost::is_same
<
typename tag_cast
<
typename tag<Geometry>::type, multi_tag
>::type,
multi_tag
>::value
>
struct multi_point_geometry
: multi_point_single_geometry<MultiPoint, Geometry, Transpose>
{};
template <typename MultiPoint, typename Geometry, bool Transpose>
struct multi_point_geometry<MultiPoint, Geometry, Transpose, true>
: multi_point_multi_geometry<MultiPoint, Geometry, Transpose>
{};
// transposed result of multi_point_geometry
template <typename Geometry, typename MultiPoint>
struct geometry_multi_point
{
static const bool interruption_enabled = true;
template <typename Result, typename Strategy>
static inline void apply(Geometry const& geometry, MultiPoint const& multi_point,
Result & result, Strategy const& strategy)
{
multi_point_geometry<MultiPoint, Geometry, true>::apply(multi_point, geometry, result, strategy);
}
};
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_MULTI_POINT_GEOMETRY_HPP

View File

@ -60,29 +60,27 @@ struct point_geometry
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
// the point is on the boundary
if ( pig == 0 )
typedef detail::relate::topology_check<Geometry> tc_t;
if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
|| relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
{
// NOTE: even for MLs, if there is at least one boundary point,
// somewhere there must be another one
// check if there are other boundaries outside
typedef detail::relate::topology_check<Geometry> tc_t;
//tc_t tc(geometry, point);
//if ( tc.has_interior )
// the point is on the boundary
if ( pig == 0 )
{
// NOTE: even for MLs, if there is at least one boundary point,
// somewhere there must be another one
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
//if ( tc.has_boundary )
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
else
{
// check if there is a boundary in Geometry
typedef detail::relate::topology_check<Geometry> tc_t;
tc_t tc(geometry);
if ( tc.has_interior )
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
if ( tc.has_boundary )
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
else
{
// check if there is a boundary in Geometry
tc_t tc(geometry);
if ( tc.has_interior() )
relate::set<exterior, interior, tc_t::interior, Transpose>(result);
if ( tc.has_boundary() )
relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
}
}
}
};

View File

@ -165,22 +165,41 @@ struct multipoint_multipoint
}
}
// TODO: ADD A CHECK TO THE RESULT INDICATING IF THE FIRST AND/OR SECOND GEOMETRY MUST BE ANALYSED
// The geometry containing smaller number of points will be analysed first
if ( boost::size(multi_point1) < boost::size(multi_point2) )
{
search_both<false>(multi_point1, multi_point2, result);
}
else
{
search_both<true>(multi_point2, multi_point1, result);
}
// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
// so if e.g. only I/I must be analysed we musn't check the other MPt
relate::set<exterior, exterior, result_dimension<MultiPoint1>::value>(result);
}
// TODO: Also, the geometry with the smaller number of points may be analysed first
//if ( boost::size(multi_point1) < boost::size(multi_point2) )
template <bool Transpose, typename MPt1, typename MPt2, typename Result>
static inline void search_both(MPt1 const& first_sorted_mpt, MPt2 const& first_iterated_mpt,
Result & result)
{
if ( relate::may_update<interior, interior, '0'>(result)
|| relate::may_update<interior, exterior, '0'>(result)
|| relate::may_update<exterior, interior, '0'>(result) )
{
// NlogN + MlogN
bool is_disjoint = search<Transpose>(first_sorted_mpt, first_iterated_mpt, result);
// NlogN + MlogN
bool all_handled = search<false>(multi_point1, multi_point2, result);
if ( BOOST_GEOMETRY_CONDITION(all_handled || result.interrupt) )
return;
if ( BOOST_GEOMETRY_CONDITION(is_disjoint || result.interrupt) )
return;
}
// MlogM + NlogM
search<true>(multi_point2, multi_point1, result);
if ( relate::may_update<interior, interior, '0'>(result)
|| relate::may_update<interior, exterior, '0'>(result)
|| relate::may_update<exterior, interior, '0'>(result) )
{
// MlogM + NlogM
search<! Transpose>(first_iterated_mpt, first_sorted_mpt, result);
}
}
template <bool Transpose,
@ -215,9 +234,6 @@ struct multipoint_multipoint
break;
}
// an optimization
bool all_handled = false;
if ( found_inside ) // some point of MP2 is equal to some of MP1
{
// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
@ -234,14 +250,10 @@ struct multipoint_multipoint
{
relate::set<interior, exterior, '0', Transpose>(result);
relate::set<exterior, interior, '0', Transpose>(result);
// if no point is intersecting the other MPt then we musn't analyse the reversed case
all_handled = true;
}
relate::set<exterior, exterior, result_dimension<point_type>::value, Transpose>(result);
return all_handled;
// if no point is intersecting the other MPt then we musn't analyse the reversed case
return ! found_inside;
}
};

View File

@ -1,22 +1,23 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014, Oracle and/or its affiliates.
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TOPOLOGY_CHECK_HPP
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
#include <boost/geometry/util/has_nan_coordinate.hpp>
#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry {
@ -51,31 +52,63 @@ struct topology_check<Linestring, linestring_tag>
static const char interior = '1';
static const char boundary = '0';
bool has_interior;
bool has_boundary;
topology_check(Linestring const& ls)
: m_ls(ls)
, m_is_initialized(false)
{}
bool has_interior() const
{
init(ls, 0); /*dummy param*/
init();
return m_has_interior;
}
template <typename IgnoreBoundaryPoint>
topology_check(Linestring const& ls, IgnoreBoundaryPoint const& ibp)
bool has_boundary() const
{
init(ls, ibp); /*dummy param, won't be used*/
init();
return m_has_boundary;
}
// Even if some point is on the boundary, if the Linestring has the boundary,
// there will be second boundary point different than IgnoreBoundaryPoint
template <typename IgnoreBoundaryPoint>
void init(Linestring const& ls, IgnoreBoundaryPoint const&)
/*template <typename Point>
bool check_boundary_point(Point const& point) const
{
std::size_t count = boost::size(ls);
has_interior = count > 0;
init();
return m_has_boundary
&& ( equals::equals_point_point(point, range::front(m_ls))
|| equals::equals_point_point(point, range::back(m_ls)) );
}*/
template <typename Visitor>
void for_each_boundary_point(Visitor & visitor) const
{
init();
if (m_has_boundary)
{
if (visitor.apply(range::front(m_ls)))
visitor.apply(range::back(m_ls));
}
}
private:
void init() const
{
if (m_is_initialized)
return;
std::size_t count = boost::size(m_ls);
m_has_interior = count > 0;
// NOTE: Linestring with all points equal is treated as 1d linear ring
has_boundary = count > 1
&& ! detail::equals::equals_point_point(range::front(ls), range::back(ls));
m_has_boundary = count > 1
&& ! detail::equals::equals_point_point(range::front(m_ls), range::back(m_ls));
m_is_initialized = true;
}
Linestring const& m_ls;
mutable bool m_is_initialized;
mutable bool m_has_interior;
mutable bool m_has_boundary;
};
template <typename MultiLinestring>
@ -84,29 +117,56 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
static const char interior = '1';
static const char boundary = '0';
bool has_interior;
bool has_boundary;
topology_check(MultiLinestring const& mls)
: m_mls(mls)
, m_is_initialized(false)
{}
bool has_interior() const
{
init(mls, not_ignoring_counter());
init();
return m_has_interior;
}
template <typename IgnoreBoundaryPoint>
topology_check(MultiLinestring const& mls, IgnoreBoundaryPoint const& ibp)
bool has_boundary() const
{
init(mls, ignoring_counter<IgnoreBoundaryPoint>(ibp));
init();
return m_has_boundary;
}
template <typename OddCounter>
void init(MultiLinestring const& mls, OddCounter const& odd_counter)
template <typename Point>
bool check_boundary_point(Point const& point) const
{
typedef typename geometry::point_type<MultiLinestring>::type point_type;
std::vector<point_type> endpoints;
endpoints.reserve(boost::size(mls) * 2);
init();
if (! m_has_boundary)
return false;
std::size_t count = count_equal(m_endpoints.begin(), m_endpoints.end(), point);
return count % 2 != 0; // odd count -> boundary
}
template <typename Visitor>
void for_each_boundary_point(Visitor & visitor) const
{
init();
if (m_has_boundary)
{
for_each_boundary_point(m_endpoints.begin(), m_endpoints.end(), visitor);
}
}
private:
void init() const
{
if (m_is_initialized)
return;
m_endpoints.reserve(boost::size(m_mls) * 2);
typedef typename boost::range_iterator<MultiLinestring const>::type ls_iterator;
for ( ls_iterator it = boost::begin(mls) ; it != boost::end(mls) ; ++it )
for ( ls_iterator it = boost::begin(m_mls) ; it != boost::end(m_mls) ; ++it )
{
typename boost::range_reference<MultiLinestring const>::type
ls = *it;
@ -115,7 +175,7 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
if (count > 0)
{
has_interior = true;
m_has_interior = true;
}
if (count > 1)
@ -138,62 +198,59 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
// is not used anywhere in the code, still it's safer this way
if (! geometry::has_nan_coordinate(front_pt))
{
endpoints.push_back(front_pt);
m_endpoints.push_back(front_pt);
}
if (! geometry::has_nan_coordinate(back_pt))
{
endpoints.push_back(back_pt);
m_endpoints.push_back(back_pt);
}
}
}
}
has_boundary = false;
m_has_boundary = false;
if ( !endpoints.empty() )
if (! m_endpoints.empty() )
{
std::sort(endpoints.begin(), endpoints.end(), geometry::less<point_type>());
has_boundary = odd_counter(endpoints.begin(), endpoints.end());
std::sort(m_endpoints.begin(), m_endpoints.end(), relate::less());
m_has_boundary = find_odd_count(m_endpoints.begin(), m_endpoints.end());
}
m_is_initialized = true;
}
struct not_ignoring_counter
template <typename It, typename Point>
static inline std::size_t count_equal(It first, It last, Point const& point)
{
template <typename It>
bool operator()(It first, It last) const
{
return find_odd_count(first, last);
}
};
template <typename Point>
struct ignoring_counter
{
ignoring_counter(Point const& pt) : m_pt(pt) {}
template <typename It>
bool operator()(It first, It last) const
{
typedef typename std::iterator_traits<It>::value_type point_type;
std::pair<It, It> ignore_range
= std::equal_range(first, last, m_pt,
geometry::less<point_type>());
if ( find_odd_count(first, ignore_range.first) )
return true;
return find_odd_count(ignore_range.second, last);
}
Point const& m_pt;
};
std::pair<It, It> rng = std::equal_range(first, last, point, relate::less());
return (std::size_t)std::distance(rng.first, rng.second);
}
template <typename It>
static inline bool find_odd_count(It first, It last)
{
if ( first == last )
interrupting_visitor visitor;
for_each_boundary_point(first, last, visitor);
return visitor.found;
}
struct interrupting_visitor
{
bool found;
interrupting_visitor() : found(false) {}
template <typename Point>
bool apply(Point const&)
{
found = true;
return false;
}
};
template <typename It, typename Visitor>
static void for_each_boundary_point(It first, It last, Visitor& visitor)
{
if ( first == last )
return;
std::size_t count = 1;
It prev = first;
@ -203,8 +260,14 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
// the end of the equal points subrange
if ( ! equals::equals_point_point(*first, *prev) )
{
// odd count -> boundary
if ( count % 2 != 0 )
return true;
{
if (! visitor.apply(*prev))
{
return;
}
}
count = 1;
}
@ -214,8 +277,22 @@ struct topology_check<MultiLinestring, multi_linestring_tag>
}
}
return count % 2 != 0;
// odd count -> boundary
if ( count % 2 != 0 )
{
visitor.apply(*prev);
}
}
private:
MultiLinestring const& m_mls;
mutable bool m_is_initialized;
mutable bool m_has_interior;
mutable bool m_has_boundary;
typedef typename geometry::point_type<MultiLinestring>::type point_type;
mutable std::vector<point_type> m_endpoints;
};
template <typename Ring>
@ -223,12 +300,11 @@ struct topology_check<Ring, ring_tag>
{
static const char interior = '2';
static const char boundary = '1';
static const bool has_interior = true;
static const bool has_boundary = true;
topology_check(Ring const&) {}
template <typename P>
topology_check(Ring const&, P const&) {}
static bool has_interior() { return true; }
static bool has_boundary() { return true; }
};
template <typename Polygon>
@ -236,12 +312,11 @@ struct topology_check<Polygon, polygon_tag>
{
static const char interior = '2';
static const char boundary = '1';
static const bool has_interior = true;
static const bool has_boundary = true;
topology_check(Polygon const&) {}
template <typename P>
topology_check(Polygon const&, P const&) {}
static bool has_interior() { return true; }
static bool has_boundary() { return true; }
};
template <typename MultiPolygon>
@ -249,12 +324,13 @@ struct topology_check<MultiPolygon, multi_polygon_tag>
{
static const char interior = '2';
static const char boundary = '1';
static const bool has_interior = true;
static const bool has_boundary = true;
topology_check(MultiPolygon const&) {}
template <typename P>
topology_check(MultiPolygon const&, P const&) {}
static bool has_interior() { return true; }
static bool has_boundary() { return true; }
template <typename Point>
static bool check_boundary_point(Point const& ) { return true; }
};
}} // namespace detail::relate

View File

@ -0,0 +1,459 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013, 2014, 2015, 2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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_TOUCHES_IMPLEMENTATION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_IMPLEMENTATION_HPP
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/algorithms/detail/touches/interface.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/num_geometries.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace touches
{
// Box/Box
template
<
std::size_t Dimension,
std::size_t DimensionCount
>
struct box_box_loop
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& b1, Box2 const& b2, bool & touch)
{
typedef typename coordinate_type<Box1>::type coordinate_type1;
typedef typename coordinate_type<Box2>::type coordinate_type2;
coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
// TODO assert or exception?
//BOOST_GEOMETRY_ASSERT(min1 <= max1 && min2 <= max2);
if (max1 < min2 || max2 < min1)
{
return false;
}
if (max1 == min2 || max2 == min1)
{
touch = true;
}
return box_box_loop
<
Dimension + 1,
DimensionCount
>::apply(b1, b2, touch);
}
};
template
<
std::size_t DimensionCount
>
struct box_box_loop<DimensionCount, DimensionCount>
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& , Box2 const&, bool &)
{
return true;
}
};
struct box_box
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
{
BOOST_STATIC_ASSERT((boost::is_same
<
typename geometry::coordinate_system<Box1>::type,
typename geometry::coordinate_system<Box2>::type
>::value
));
assert_dimension_equal<Box1, Box2>();
bool touches = false;
bool ok = box_box_loop
<
0,
dimension<Box1>::type::value
>::apply(b1, b2, touches);
return ok && touches;
}
};
// Areal/Areal
struct areal_interrupt_policy
{
static bool const enabled = true;
bool found_touch;
bool found_not_touch;
// dummy variable required by self_get_turn_points::get_turns
static bool const has_intersections = false;
inline bool result()
{
return found_touch && !found_not_touch;
}
inline areal_interrupt_policy()
: found_touch(false), found_not_touch(false)
{}
template <typename Range>
inline bool apply(Range const& range)
{
// if already rejected (temp workaround?)
if ( found_not_touch )
return true;
typedef typename boost::range_iterator<Range const>::type iterator;
for ( iterator it = boost::begin(range) ; it != boost::end(range) ; ++it )
{
if ( it->has(overlay::operation_intersection) )
{
found_not_touch = true;
return true;
}
switch(it->method)
{
case overlay::method_crosses:
found_not_touch = true;
return true;
case overlay::method_equal:
// Segment spatially equal means: at the right side
// the polygon internally overlaps. So return false.
found_not_touch = true;
return true;
case overlay::method_touch:
case overlay::method_touch_interior:
case overlay::method_collinear:
if ( ok_for_touch(*it) )
{
found_touch = true;
}
else
{
found_not_touch = true;
return true;
}
break;
case overlay::method_none :
case overlay::method_disjoint :
case overlay::method_error :
break;
}
}
return false;
}
template <typename Turn>
inline bool ok_for_touch(Turn const& turn)
{
return turn.both(overlay::operation_union)
|| turn.both(overlay::operation_blocked)
|| turn.combination(overlay::operation_union, overlay::operation_blocked)
;
}
};
template<typename Geometry, typename PointInRingStrategy>
struct check_each_ring_for_within
{
bool has_within;
Geometry const& m_geometry;
PointInRingStrategy const& m_strategy;
inline check_each_ring_for_within(Geometry const& g, PointInRingStrategy const& strategy)
: has_within(false)
, m_geometry(g)
, m_strategy(strategy)
{}
template <typename Range>
inline void apply(Range const& range)
{
typename geometry::point_type<Range>::type p;
geometry::point_on_border(p, range);
if ( !has_within && geometry::within(p, m_geometry, m_strategy) )
{
has_within = true;
}
}
};
template <typename FirstGeometry, typename SecondGeometry, typename IntersectionStrategy>
inline bool rings_containing(FirstGeometry const& geometry1,
SecondGeometry const& geometry2,
IntersectionStrategy const& strategy)
{
// NOTE: This strategy could be defined inside IntersectionStrategy
typedef typename IntersectionStrategy::template point_in_geometry_strategy
<
FirstGeometry, SecondGeometry
>::type point_in_ring_strategy_type;
point_in_ring_strategy_type point_in_ring_strategy
= strategy.template get_point_in_geometry_strategy<FirstGeometry, SecondGeometry>();
check_each_ring_for_within
<
FirstGeometry, point_in_ring_strategy_type
> checker(geometry1, point_in_ring_strategy);
geometry::detail::for_each_range(geometry2, checker);
return checker.has_within;
}
template <typename Geometry1, typename Geometry2>
struct areal_areal
{
template <typename IntersectionStrategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
IntersectionStrategy const& strategy)
{
typedef detail::no_rescale_policy rescale_policy_type;
typedef typename geometry::point_type<Geometry1>::type point_type;
typedef detail::overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
std::deque<turn_info> turns;
detail::touches::areal_interrupt_policy policy;
rescale_policy_type robust_policy;
boost::geometry::get_turns
<
detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
detail::overlay::assign_null_policy
>(geometry1, geometry2, strategy, robust_policy, turns, policy);
return policy.result()
&& ! geometry::detail::touches::rings_containing(geometry1, geometry2, strategy)
&& ! geometry::detail::touches::rings_containing(geometry2, geometry1, strategy);
}
};
// P/*
struct use_point_in_geometry
{
template <typename Point, typename Geometry, typename Strategy>
static inline bool apply(Point const& point, Geometry const& geometry, Strategy const& strategy)
{
return detail::within::point_in_geometry(point, geometry, strategy) == 0;
}
};
}}
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch {
// P/P
template <typename Geometry1, typename Geometry2, typename Tag2>
struct touches<Geometry1, Geometry2, point_tag, Tag2, pointlike_tag, pointlike_tag, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const&)
{
return false;
}
};
template <typename Geometry1, typename Geometry2, typename Tag2>
struct touches<Geometry1, Geometry2, multi_point_tag, Tag2, pointlike_tag, pointlike_tag, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const&, Geometry2 const&, Strategy const&)
{
return false;
}
};
// P/*
template <typename Point, typename Geometry, typename Tag2, typename CastedTag2>
struct touches<Point, Geometry, point_tag, Tag2, pointlike_tag, CastedTag2, false>
: detail::touches::use_point_in_geometry
{};
template <typename MultiPoint, typename MultiGeometry, typename Tag2, typename CastedTag2>
struct touches<MultiPoint, MultiGeometry, multi_point_tag, Tag2, pointlike_tag, CastedTag2, false>
: detail::relate::relate_impl
<
detail::de9im::static_mask_touches_type,
MultiPoint,
MultiGeometry
>
{};
template <typename Geometry, typename MultiPoint, typename Tag1, typename CastedTag1>
struct touches<Geometry, MultiPoint, Tag1, multi_point_tag, CastedTag1, pointlike_tag, false>
: detail::relate::relate_impl
<
detail::de9im::static_mask_touches_type,
Geometry,
MultiPoint
>
{};
// Box/Box
template <typename Box1, typename Box2, typename CastedTag1, typename CastedTag2>
struct touches<Box1, Box2, box_tag, box_tag, CastedTag1, CastedTag2, false>
: detail::touches::box_box
{};
template <typename Box1, typename Box2>
struct touches<Box1, Box2, box_tag, box_tag, areal_tag, areal_tag, false>
: detail::touches::box_box
{};
// L/L
template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
struct touches<Linear1, Linear2, Tag1, Tag2, linear_tag, linear_tag, false>
: detail::relate::relate_impl
<
detail::de9im::static_mask_touches_type,
Linear1,
Linear2
>
{};
// L/A
template <typename Linear, typename Areal, typename Tag1, typename Tag2>
struct touches<Linear, Areal, Tag1, Tag2, linear_tag, areal_tag, false>
: detail::relate::relate_impl
<
detail::de9im::static_mask_touches_type,
Linear,
Areal
>
{};
// A/L
template <typename Linear, typename Areal, typename Tag1, typename Tag2>
struct touches<Areal, Linear, Tag1, Tag2, areal_tag, linear_tag, false>
: detail::relate::relate_impl
<
detail::de9im::static_mask_touches_type,
Areal,
Linear
>
{};
// A/A
template <typename Areal1, typename Areal2, typename Tag1, typename Tag2>
struct touches<Areal1, Areal2, Tag1, Tag2, areal_tag, areal_tag, false>
: detail::relate::relate_impl
<
detail::de9im::static_mask_touches_type,
Areal1,
Areal2
>
{};
template <typename Areal1, typename Areal2>
struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false>
: detail::touches::areal_areal<Areal1, Areal2>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_variant {
template <typename Geometry>
struct self_touches
{
static bool apply(Geometry const& geometry)
{
concepts::check<Geometry const>();
typedef typename strategy::relate::services::default_strategy
<
Geometry, Geometry
>::type strategy_type;
typedef detail::no_rescale_policy rescale_policy_type;
typedef typename geometry::point_type<Geometry>::type point_type;
typedef detail::overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
typedef detail::overlay::get_turn_info
<
detail::overlay::assign_null_policy
> policy_type;
std::deque<turn_info> turns;
detail::touches::areal_interrupt_policy policy;
strategy_type strategy;
rescale_policy_type robust_policy;
detail::self_get_turn_points::get_turns
<
policy_type
>::apply(geometry, strategy, robust_policy, turns, policy, 0);
return policy.result();
}
};
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_IMPLEMENTATION_HPP

View File

@ -0,0 +1,321 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2013, 2014, 2015, 2017.
// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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_TOUCHES_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP
#include <deque>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/relate.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch {
// TODO: Since CastedTags are used is Reverse needed?
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type,
typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,
typename CastedTag2 = typename tag_cast<Tag2, pointlike_tag, linear_tag, areal_tag>::type,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct touches
: not_implemented<Tag1, Tag2>
{};
// If reversal is needed, perform it
template
<
typename Geometry1, typename Geometry2,
typename Tag1, typename Tag2,
typename CastedTag1, typename CastedTag2
>
struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>
: touches<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
return touches<Geometry2, Geometry1>::apply(g2, g1, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
struct touches
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return dispatch::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::relate::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return dispatch::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct touches
{
template <typename Strategy>
static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return resolve_strategy::touches::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
, m_strategy(strategy)
{}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
, m_strategy(strategy)
{}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)>
struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
template <typename Geometry>
struct self_touches;
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
struct visitor: boost::static_visitor<bool>
{
template <typename Geometry>
bool operator()(Geometry const& geometry) const
{
return self_touches<Geometry>::apply(geometry);
}
};
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
{
return boost::apply_visitor(visitor(), geometry);
}
};
} // namespace resolve_variant
/*!
\brief \brief_check{has at least one touching point (self-tangency)}
\note This function can be called for one geometry (self-tangency) and
also for two geometries (touch)
\ingroup touches
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\return \return_check{is self-touching}
\qbk{distinguish,one geometry}
\qbk{[def __one_parameter__]}
\qbk{[include reference/algorithms/touches.qbk]}
*/
template <typename Geometry>
inline bool touches(Geometry const& geometry)
{
return resolve_variant::self_touches<Geometry>::apply(geometry);
}
/*!
\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
\ingroup touches
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{touch each other}
\qbk{distinguish,two geometries}
\qbk{[include reference/algorithms/touches.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, default_strategy());
}
/*!
\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
\ingroup touches
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Touches}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{touches}
\return \return_check2{touch each other}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/touches.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool touches(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TOUCHES_INTERFACE_HPP

View File

@ -0,0 +1,306 @@
// 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, 2014, 2017.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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_WITHIN_IMPLEMENTATION_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_IMPLEMENTATION_HPP
#include <cstddef>
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/within/interface.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/order_as_direction.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/views/reversible_view.hpp>
#include <boost/geometry/algorithms/detail/within/multi_point.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
#include <deque>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within {
struct use_point_in_geometry
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
return detail::within::point_in_geometry(geometry1, geometry2, strategy) == 1;
}
};
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
typedef typename detail::de9im::static_mask_within_type
<
Geometry1, Geometry2
>::type within_mask;
return geometry::relate(geometry1, geometry2, within_mask(), strategy);
}
};
}} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template <typename Point, typename Box>
struct within<Point, Box, point_tag, box_tag>
{
template <typename Strategy>
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
{
boost::ignore_unused_variable_warning(strategy);
return strategy.apply(point, box);
}
};
template <typename Box1, typename Box2>
struct within<Box1, Box2, box_tag, box_tag>
{
template <typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{
assert_dimension_equal<Box1, Box2>();
boost::ignore_unused_variable_warning(strategy);
return strategy.apply(box1, box2);
}
};
// P/P
template <typename Point1, typename Point2>
struct within<Point1, Point2, point_tag, point_tag>
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename MultiPoint>
struct within<Point, MultiPoint, point_tag, multi_point_tag>
: public detail::within::use_point_in_geometry
{};
template <typename MultiPoint, typename Point>
struct within<MultiPoint, Point, multi_point_tag, point_tag>
: public detail::within::multi_point_point
{};
template <typename MultiPoint1, typename MultiPoint2>
struct within<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag>
: public detail::within::multi_point_multi_point
{};
// P/L
template <typename Point, typename Segment>
struct within<Point, Segment, point_tag, segment_tag>
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename Linestring>
struct within<Point, Linestring, point_tag, linestring_tag>
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename MultiLinestring>
struct within<Point, MultiLinestring, point_tag, multi_linestring_tag>
: public detail::within::use_point_in_geometry
{};
template <typename MultiPoint, typename Segment>
struct within<MultiPoint, Segment, multi_point_tag, segment_tag>
: public detail::within::multi_point_single_geometry<true>
{};
template <typename MultiPoint, typename Linestring>
struct within<MultiPoint, Linestring, multi_point_tag, linestring_tag>
: public detail::within::multi_point_single_geometry<true>
{};
template <typename MultiPoint, typename MultiLinestring>
struct within<MultiPoint, MultiLinestring, multi_point_tag, multi_linestring_tag>
: public detail::within::multi_point_multi_geometry<true>
{};
// P/A
template <typename Point, typename Ring>
struct within<Point, Ring, point_tag, ring_tag>
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename Polygon>
struct within<Point, Polygon, point_tag, polygon_tag>
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename MultiPolygon>
struct within<Point, MultiPolygon, point_tag, multi_polygon_tag>
: public detail::within::use_point_in_geometry
{};
template <typename MultiPoint, typename Ring>
struct within<MultiPoint, Ring, multi_point_tag, ring_tag>
: public detail::within::multi_point_single_geometry<true>
{};
template <typename MultiPoint, typename Polygon>
struct within<MultiPoint, Polygon, multi_point_tag, polygon_tag>
: public detail::within::multi_point_single_geometry<true>
{};
template <typename MultiPoint, typename MultiPolygon>
struct within<MultiPoint, MultiPolygon, multi_point_tag, multi_polygon_tag>
: public detail::within::multi_point_multi_geometry<true>
{};
// L/L
template <typename Linestring1, typename Linestring2>
struct within<Linestring1, Linestring2, linestring_tag, linestring_tag>
: public detail::within::use_relate
{};
template <typename Linestring, typename MultiLinestring>
struct within<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename Linestring>
struct within<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring1, typename MultiLinestring2>
struct within<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
: public detail::within::use_relate
{};
// L/A
template <typename Linestring, typename Ring>
struct within<Linestring, Ring, linestring_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename Ring>
struct within<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename Linestring, typename Polygon>
struct within<Linestring, Polygon, linestring_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename Polygon>
struct within<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename Linestring, typename MultiPolygon>
struct within<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename MultiPolygon>
struct within<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
// A/A
template <typename Ring1, typename Ring2>
struct within<Ring1, Ring2, ring_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename Ring, typename Polygon>
struct within<Ring, Polygon, ring_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename Polygon, typename Ring>
struct within<Polygon, Ring, polygon_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename Polygon1, typename Polygon2>
struct within<Polygon1, Polygon2, polygon_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename Ring, typename MultiPolygon>
struct within<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiPolygon, typename Ring>
struct within<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename Polygon, typename MultiPolygon>
struct within<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiPolygon, typename Polygon>
struct within<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiPolygon1, typename MultiPolygon2>
struct within<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
}} // namespace boost::geometry
#include <boost/geometry/index/rtree.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_IMPLEMENTATION_HPP

View File

@ -0,0 +1,304 @@
// 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, 2014, 2017.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, 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_WITHIN_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP
#include <boost/concept_check.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/concepts/within_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type
>
struct within
: not_implemented<Tag1, Tag2>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
struct within
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::within::check
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
Strategy
>();
return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::within::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct within
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
assert_dimension_equal<Geometry1, Geometry2>();
return resolve_strategy::within::apply(geometry1,
geometry2,
strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
, m_strategy(strategy)
{}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return within<Geometry1, Geometry2>::apply(geometry1,
m_geometry2,
m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
, m_strategy(strategy)
{}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return within<Geometry1, Geometry2>::apply(m_geometry1,
geometry2,
m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
geometry2
);
}
};
template <
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct within<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return within<Geometry1, Geometry2>::apply(geometry1,
geometry2,
m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy),
geometry1,
geometry2);
}
};
}
/*!
\brief \brief_check12{is completely inside}
\ingroup within
\details \details_check12{within, is completely inside}.
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry which might be within the second geometry
\param geometry2 \param_geometry which might contain the first geometry
\return true if geometry1 is completely contained within geometry2,
else false
\note The default strategy is used for within detection
\qbk{[include reference/algorithms/within.qbk]}
\qbk{
[heading Example]
[within]
[within_output]
}
*/
template<typename Geometry1, typename Geometry2>
inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::within
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, default_strategy());
}
/*!
\brief \brief_check12{is completely inside} \brief_strategy
\ingroup within
\details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry which might be within the second geometry
\param geometry2 \param_geometry which might contain the first geometry
\param strategy strategy to be used
\return true if geometry1 is completely contained within geometry2,
else false
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/within.qbk]}
\qbk{
[heading Available Strategies]
\* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]
\* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]
\* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]
[heading Example]
[within_strategy]
[within_strategy_output]
}
*/
template<typename Geometry1, typename Geometry2, typename Strategy>
inline bool within(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::within
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, strategy);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_INTERFACE_HPP

View File

@ -16,8 +16,25 @@
#include <vector>
#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/algorithms/detail/relate/less.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
namespace boost { namespace geometry {
@ -27,9 +44,10 @@ namespace detail { namespace within {
struct multi_point_point
{
template <typename MultiPoint, typename Point, typename Strategy> static inline
bool apply(MultiPoint const& multi_point, Point const& point,
Strategy const& strategy)
template <typename MultiPoint, typename Point, typename Strategy>
static inline bool apply(MultiPoint const& multi_point,
Point const& point,
Strategy const& strategy)
{
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
@ -48,9 +66,10 @@ struct multi_point_point
// NOTE: currently the strategy is ignored, math::equals() is used inside relate::less
struct multi_point_multi_point
{
template <typename MultiPoint1, typename MultiPoint2, typename Strategy> static inline
bool apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2,
Strategy const& /*strategy*/)
template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
static inline bool apply(MultiPoint1 const& multi_point1,
MultiPoint2 const& multi_point2,
Strategy const& /*strategy*/)
{
typedef typename boost::range_value<MultiPoint2>::type point2_type;
@ -59,6 +78,8 @@ struct multi_point_multi_point
std::vector<point2_type> points2(boost::begin(multi_point2), boost::end(multi_point2));
std::sort(points2.begin(), points2.end(), less);
bool result = false;
typedef typename boost::range_const_iterator<MultiPoint1>::type iterator;
for ( iterator it = boost::begin(multi_point1) ; it != boost::end(multi_point1) ; ++it )
{
@ -66,17 +87,182 @@ struct multi_point_multi_point
{
return false;
}
else
{
result = true;
}
}
// all points of MultiPoint1 inside MultiPoint2
return true;
return result;
}
};
// TODO: the complexity could be lesser
// the second geometry could be "prepared"/sorted
// For Linear geometries partition could be used
// For Areal geometries point_in_geometry() would have to call the winding
// strategy differently, currently it linearly calls the strategy for each
// segment. So the segments would have to be sorted in a way consistent with
// the strategy and then the strategy called only for the segments in range.
template <bool Within>
struct multi_point_single_geometry
{
template <typename MultiPoint, typename LinearOrAreal, typename Strategy>
static inline bool apply(MultiPoint const& multi_point,
LinearOrAreal const& linear_or_areal,
Strategy const& strategy)
{
typedef typename boost::range_value<MultiPoint>::type point1_type;
typedef typename point_type<LinearOrAreal>::type point2_type;
typedef model::box<point2_type> box2_type;
// Create envelope of geometry
box2_type box;
geometry::envelope(linear_or_areal, box, strategy.get_envelope_strategy());
geometry::detail::expand_by_epsilon(box);
typedef typename strategy::covered_by::services::default_strategy
<
point1_type, box2_type
>::type point_in_box_type;
// Test each Point with envelope and then geometry if needed
// If in the exterior, break
bool result = false;
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
{
int in_val = 0;
// exterior of box and of geometry
if (! point_in_box_type::apply(*it, box)
|| (in_val = point_in_geometry(*it, linear_or_areal, strategy)) < 0)
{
result = false;
break;
}
// interior : interior/boundary
if (Within ? in_val > 0 : in_val >= 0)
{
result = true;
}
}
return result;
}
};
// TODO: same here, probably the complexity could be lesser
template <bool Within>
struct multi_point_multi_geometry
{
template <typename MultiPoint, typename LinearOrAreal, typename Strategy>
static inline bool apply(MultiPoint const& multi_point,
LinearOrAreal const& linear_or_areal,
Strategy const& strategy)
{
typedef typename point_type<LinearOrAreal>::type point2_type;
typedef model::box<point2_type> box2_type;
static const bool is_linear = is_same
<
typename tag_cast
<
typename tag<LinearOrAreal>::type,
linear_tag
>::type,
linear_tag
>::value;
typename Strategy::envelope_strategy_type const
envelope_strategy = strategy.get_envelope_strategy();
// TODO: box pairs could be constructed on the fly, inside the rtree
// Prepare range of envelopes and ids
std::size_t count2 = boost::size(linear_or_areal);
typedef std::pair<box2_type, std::size_t> box_pair_type;
typedef std::vector<box_pair_type> box_pair_vector;
box_pair_vector boxes(count2);
for (std::size_t i = 0 ; i < count2 ; ++i)
{
geometry::envelope(linear_or_areal, boxes[i].first, envelope_strategy);
geometry::detail::expand_by_epsilon(boxes[i].first);
boxes[i].second = i;
}
// Create R-tree
index::rtree<box_pair_type, index::rstar<4> > rtree(boxes.begin(), boxes.end());
// For each point find overlapping envelopes and test corresponding single geometries
// If a point is in the exterior break
bool result = false;
typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
{
// TODO: investigate the possibility of using satisfies
// TODO: investigate the possibility of using iterative queries (optimization below)
box_pair_vector inters_boxes;
rtree.query(index::intersects(*it), std::back_inserter(inters_boxes));
bool found_interior = false;
bool found_boundary = false;
int boundaries = 0;
typedef typename box_pair_vector::const_iterator iterator;
for ( iterator box_it = inters_boxes.begin() ; box_it != inters_boxes.end() ; ++box_it )
{
int in_val = point_in_geometry(*it, range::at(linear_or_areal, box_it->second), strategy);
if (in_val > 0)
found_interior = true;
else if (in_val == 0)
++boundaries;
// If the result was set previously (interior or
// interior/boundary found) the only thing that needs to be
// done for other points is to make sure they're not
// overlapping the exterior no need to analyse boundaries.
if (result && in_val >= 0)
{
break;
}
}
if ( boundaries > 0)
{
if (is_linear && boundaries % 2 == 0)
found_interior = true;
else
found_boundary = true;
}
// exterior
if (! found_interior && ! found_boundary)
{
result = false;
break;
}
// interior : interior/boundary
if (Within ? found_interior : (found_interior || found_boundary))
{
result = true;
}
}
return result;
}
};
}} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_MULTI_POINT_HPP

View File

@ -22,644 +22,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
#include <cstddef>
#include <vector>
#include <boost/range.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/geometry_id.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
// For trivial checks
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/length.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/views/detail/indexed_point_view.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace equals
{
template
<
std::size_t Dimension,
std::size_t DimensionCount
>
struct point_point
{
template <typename Point1, typename Point2, typename Strategy>
static inline bool apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy)
{
return ! detail::disjoint::point_point
<
Point1, Point2,
Dimension, DimensionCount
>::apply(point1, point2, strategy);
}
};
template
<
std::size_t Dimension,
std::size_t DimensionCount
>
struct box_box
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{
if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
|| !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
{
return false;
}
return box_box<Dimension + 1, DimensionCount>::apply(box1, box2, strategy);
}
};
template <std::size_t DimensionCount>
struct box_box<DimensionCount, DimensionCount>
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& , Box2 const& , Strategy const& )
{
return true;
}
};
struct segment_segment
{
template <typename Segment1, typename Segment2, typename Strategy>
static inline bool apply(Segment1 const& segment1, Segment2 const& segment2, Strategy const& )
{
return equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1),
indexed_point_view<Segment2 const, 0>(segment2) )
? equals::equals_point_point(
indexed_point_view<Segment1 const, 1>(segment1),
indexed_point_view<Segment2 const, 1>(segment2) )
: ( equals::equals_point_point(
indexed_point_view<Segment1 const, 0>(segment1),
indexed_point_view<Segment2 const, 1>(segment2) )
&& equals::equals_point_point(
indexed_point_view<Segment1 const, 1>(segment1),
indexed_point_view<Segment2 const, 0>(segment2) )
);
}
};
struct area_check
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return geometry::math::equals(
geometry::area(geometry1,
strategy.template get_area_strategy<Geometry1>()),
geometry::area(geometry2,
strategy.template get_area_strategy<Geometry2>()));
}
};
struct length_check
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return geometry::math::equals(
geometry::length(geometry1,
strategy.template get_distance_strategy<Geometry1>()),
geometry::length(geometry2,
strategy.template get_distance_strategy<Geometry2>()));
}
};
template <typename Geometry1, typename Geometry2, typename IntersectionStrategy>
struct collected_vector
{
typedef typename geometry::select_most_precise
<
typename select_coordinate_type
<
Geometry1, Geometry2
>::type,
double
>::type calculation_type;
typedef geometry::collected_vector
<
calculation_type,
Geometry1,
typename IntersectionStrategy::side_strategy_type
> type;
};
template <typename TrivialCheck>
struct equals_by_collection
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
if (! TrivialCheck::apply(geometry1, geometry2, strategy))
{
return false;
}
typedef typename collected_vector
<
Geometry1, Geometry2, Strategy
>::type collected_vector_type;
std::vector<collected_vector_type> c1, c2;
geometry::collect_vectors(c1, geometry1);
geometry::collect_vectors(c2, geometry2);
if (boost::size(c1) != boost::size(c2))
{
return false;
}
std::sort(c1.begin(), c1.end());
std::sort(c2.begin(), c2.end());
// Just check if these vectors are equal.
return std::equal(c1.begin(), c1.end(), c2.begin());
}
};
template<typename Geometry1, typename Geometry2>
struct equals_by_relate
: detail::relate::relate_impl
<
detail::de9im::static_mask_equals_type,
Geometry1,
Geometry2
>
{};
// If collect_vectors which is a SideStrategy-dispatched optimization
// is implemented in a way consistent with the Intersection/Side Strategy
// then collect_vectors is used, otherwise relate is used.
// NOTE: the result could be coneptually different for invalid
// geometries in different coordinate systems because collect_vectors
// and relate treat invalid geometries differently.
template<typename TrivialCheck>
struct equals_by_collection_or_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
typedef typename boost::is_base_of
<
nyi::not_implemented_tag,
typename collected_vector
<
Geometry1, Geometry2, Strategy
>::type
>::type enable_relate_type;
return apply(geometry1, geometry2, strategy, enable_relate_type());
}
private:
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
boost::false_type /*enable_relate*/)
{
return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy,
boost::true_type /*enable_relate*/)
{
return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
}
};
}} // namespace detail::equals
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type,
std::size_t DimensionCount = dimension<Geometry1>::type::value,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct equals: not_implemented<Tag1, Tag2>
{};
// If reversal is needed, perform it
template
<
typename Geometry1, typename Geometry2,
typename Tag1, typename Tag2,
std::size_t DimensionCount
>
struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
: equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
return equals
<
Geometry2, Geometry1,
Tag2, Tag1,
DimensionCount,
false
>::apply(g2, g1, strategy);
}
};
template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
: detail::equals::point_point<0, DimensionCount>
{};
template <typename MultiPoint1, typename MultiPoint2, std::size_t DimensionCount, bool Reverse>
struct equals<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag, DimensionCount, Reverse>
: detail::equals::equals_by_relate<MultiPoint1, MultiPoint2>
{};
template <typename MultiPoint, typename Point, std::size_t DimensionCount, bool Reverse>
struct equals<Point, MultiPoint, point_tag, multi_point_tag, DimensionCount, Reverse>
: detail::equals::equals_by_relate<Point, MultiPoint>
{};
template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
: detail::equals::box_box<0, DimensionCount>
{};
template <typename Ring1, typename Ring2, bool Reverse>
struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon1, typename Polygon2, bool Reverse>
struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon, typename Ring, bool Reverse>
struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Ring, typename Box, bool Reverse>
struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Polygon, typename Box, bool Reverse>
struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
: detail::equals::equals_by_collection<detail::equals::area_check>
{};
template <typename Segment1, typename Segment2, std::size_t DimensionCount, bool Reverse>
struct equals<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, Reverse>
: detail::equals::segment_segment
{};
template <typename LineString1, typename LineString2, bool Reverse>
struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString1, LineString2>
{};
template <typename LineString, typename MultiLineString, bool Reverse>
struct equals<LineString, MultiLineString, linestring_tag, multi_linestring_tag, 2, Reverse>
: detail::equals::equals_by_relate<LineString, MultiLineString>
{};
template <typename MultiLineString1, typename MultiLineString2, bool Reverse>
struct equals<MultiLineString1, MultiLineString2, multi_linestring_tag, multi_linestring_tag, 2, Reverse>
: detail::equals::equals_by_relate<MultiLineString1, MultiLineString2>
{};
template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
struct equals
<
MultiPolygon1, MultiPolygon2,
multi_polygon_tag, multi_polygon_tag,
2,
Reverse
>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename Polygon, typename MultiPolygon, bool Reverse>
struct equals
<
Polygon, MultiPolygon,
polygon_tag, multi_polygon_tag,
2,
Reverse
>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
template <typename MultiPolygon, typename Ring, bool Reverse>
struct equals
<
MultiPolygon, Ring,
multi_polygon_tag, ring_tag,
2,
Reverse
>
: detail::equals::equals_by_collection_or_relate<detail::equals::area_check>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
struct equals
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return dispatch::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::relate::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return dispatch::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct equals
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check_concepts_and_equal_dimensions
<
Geometry1 const,
Geometry2 const
>();
return resolve_strategy::equals
::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
, m_strategy(strategy)
{}
template <typename Geometry1>
inline bool operator()(Geometry1 const& geometry1) const
{
return equals<Geometry1, Geometry2>
::apply(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy
)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
, m_strategy(strategy)
{}
template <typename Geometry2>
inline bool operator()(Geometry2 const& geometry2) const
{
return equals<Geometry1, Geometry2>
::apply(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(
Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy
)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template <
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct equals<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
struct visitor: static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
inline bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return equals<Geometry1, Geometry2>
::apply(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy
)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
} // namespace resolve_variant
/*!
\brief \brief_check{are spatially equal}
\details \details_check12{equals, is spatially equal}. Spatially equal means
that the same point set is included. A box can therefore be spatially equal
to a ring or a polygon, or a linestring can be spatially equal to a
multi-linestring or a segment. This only works theoretically, not all
combinations are implemented yet.
\ingroup equals
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Equals}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{equals}
\return \return_check2{are spatially equal}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/equals.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool equals(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::equals
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
/*!
\brief \brief_check{are spatially equal}
\details \details_check12{equals, is spatially equal}. Spatially equal means
that the same point set is included. A box can therefore be spatially equal
to a ring or a polygon, or a linestring can be spatially equal to a
multi-linestring or a segment. This only works theoretically, not all
combinations are implemented yet.
\ingroup equals
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{are spatially equal}
\qbk{[include reference/algorithms/equals.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::equals<Geometry1, Geometry2>
::apply(geometry1, geometry2, default_strategy());
}
}} // namespace boost::geometry
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/algorithms/detail/equals/implementation.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP

View File

@ -21,120 +21,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP
#include <deque>
#include <boost/geometry/algorithms/detail/intersects/interface.hpp>
#include <boost/geometry/algorithms/detail/intersects/implementation.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
#include <boost/geometry/strategies/relate.hpp>
namespace boost { namespace geometry
{
/*!
\brief \brief_check{has at least one intersection (crossing or self-tangency)}
\note This function can be called for one geometry (self-intersection) and
also for two geometries (intersection)
\ingroup intersects
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\return \return_check{is self-intersecting}
\qbk{distinguish,one geometry}
\qbk{[def __one_parameter__]}
\qbk{[include reference/algorithms/intersects.qbk]}
*/
template <typename Geometry>
inline bool intersects(Geometry const& geometry)
{
concepts::check<Geometry const>();
typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename strategy::relate::services::default_strategy
<
Geometry, Geometry
>::type strategy_type;
typedef detail::no_rescale_policy rescale_policy_type;
typedef detail::overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
std::deque<turn_info> turns;
typedef detail::overlay::get_turn_info
<
detail::overlay::assign_null_policy
> turn_policy;
strategy_type strategy;
rescale_policy_type robust_policy;
detail::disjoint::disjoint_interrupt_policy policy;
detail::self_get_turn_points::get_turns
<
turn_policy
>::apply(geometry, strategy, robust_policy, turns, policy, 0);
return policy.has_intersections;
}
/*!
\brief \brief_check2{have at least one intersection}
\ingroup intersects
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Intersects}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{intersects}
\return \return_check2{intersect each other}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/intersects.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool intersects(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return ! geometry::disjoint(geometry1, geometry2, strategy);
}
/*!
\brief \brief_check2{have at least one intersection}
\ingroup intersects
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{intersect each other}
\qbk{distinguish,two geometries}
\qbk{[include reference/algorithms/intersects.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool intersects(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return ! geometry::disjoint(geometry1, geometry2);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP

View File

@ -20,214 +20,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP
#include <cstddef>
#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
#include <boost/geometry/algorithms/detail/overlaps/implementation.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlaps
{
template
<
std::size_t Dimension,
std::size_t DimensionCount
>
struct box_box_loop
{
template <typename Box1, typename Box2>
static inline void apply(Box1 const& b1, Box2 const& b2,
bool& overlaps, bool& one_in_two, bool& two_in_one)
{
assert_dimension_equal<Box1, Box2>();
typedef typename coordinate_type<Box1>::type coordinate_type1;
typedef typename coordinate_type<Box2>::type coordinate_type2;
coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
// We might use the (not yet accepted) Boost.Interval
// submission in the future
// If:
// B1: |-------|
// B2: |------|
// in any dimension -> no overlap
if (max1 <= min2 || min1 >= max2)
{
overlaps = false;
return;
}
// If:
// B1: |--------------------|
// B2: |-------------|
// in all dimensions -> within, then no overlap
// B1: |--------------------|
// B2: |-------------|
// this is "within-touch" -> then no overlap. So use < and >
if (min1 < min2 || max1 > max2)
{
one_in_two = false;
}
// Same other way round
if (min2 < min1 || max2 > max1)
{
two_in_one = false;
}
box_box_loop
<
Dimension + 1,
DimensionCount
>::apply(b1, b2, overlaps, one_in_two, two_in_one);
}
};
template
<
std::size_t DimensionCount
>
struct box_box_loop<DimensionCount, DimensionCount>
{
template <typename Box1, typename Box2>
static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&)
{
}
};
struct box_box
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
{
bool overlaps = true;
bool within1 = true;
bool within2 = true;
box_box_loop
<
0,
dimension<Box1>::type::value
>::apply(b1, b2, overlaps, within1, within2);
/*
\see http://docs.codehaus.org/display/GEOTDOC/02+Geometry+Relationships#02GeometryRelationships-Overlaps
where is stated that "inside" is not an "overlap",
this is true and is implemented as such.
*/
return overlaps && ! within1 && ! within2;
}
};
}} // namespace detail::overlaps
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type
>
struct overlaps
: detail::relate::relate_impl
<
detail::de9im::static_mask_overlaps_type,
Geometry1,
Geometry2
>
{};
template <typename Box1, typename Box2>
struct overlaps<Box1, Box2, box_tag, box_tag>
: detail::overlaps::box_box
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
/*!
\brief \brief_check2{overlap}
\ingroup overlaps
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Overlaps}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{overlaps}
\return \return_check2{overlap}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/overlaps.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool overlaps(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return dispatch::overlaps
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, strategy);
}
/*!
\brief \brief_check2{overlap}
\ingroup overlaps
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{overlap}
\qbk{[include reference/algorithms/overlaps.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
typedef typename strategy::relate::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return dispatch::overlaps
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, strategy_type());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP

View File

@ -21,687 +21,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
#include <deque>
#include <boost/geometry/algorithms/detail/touches/interface.hpp>
#include <boost/geometry/algorithms/detail/touches/implementation.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/num_geometries.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace touches
{
// Box/Box
template
<
std::size_t Dimension,
std::size_t DimensionCount
>
struct box_box_loop
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& b1, Box2 const& b2, bool & touch)
{
typedef typename coordinate_type<Box1>::type coordinate_type1;
typedef typename coordinate_type<Box2>::type coordinate_type2;
coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
// TODO assert or exception?
//BOOST_GEOMETRY_ASSERT(min1 <= max1 && min2 <= max2);
if (max1 < min2 || max2 < min1)
{
return false;
}
if (max1 == min2 || max2 == min1)
{
touch = true;
}
return box_box_loop
<
Dimension + 1,
DimensionCount
>::apply(b1, b2, touch);
}
};
template
<
std::size_t DimensionCount
>
struct box_box_loop<DimensionCount, DimensionCount>
{
template <typename Box1, typename Box2>
static inline bool apply(Box1 const& , Box2 const&, bool &)
{
return true;
}
};
struct box_box
{
template <typename Box1, typename Box2, typename Strategy>
static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& /*strategy*/)
{
BOOST_STATIC_ASSERT((boost::is_same
<
typename geometry::coordinate_system<Box1>::type,
typename geometry::coordinate_system<Box2>::type
>::value
));
assert_dimension_equal<Box1, Box2>();
bool touches = false;
bool ok = box_box_loop
<
0,
dimension<Box1>::type::value
>::apply(b1, b2, touches);
return ok && touches;
}
};
// Areal/Areal
struct areal_interrupt_policy
{
static bool const enabled = true;
bool found_touch;
bool found_not_touch;
// dummy variable required by self_get_turn_points::get_turns
static bool const has_intersections = false;
inline bool result()
{
return found_touch && !found_not_touch;
}
inline areal_interrupt_policy()
: found_touch(false), found_not_touch(false)
{}
template <typename Range>
inline bool apply(Range const& range)
{
// if already rejected (temp workaround?)
if ( found_not_touch )
return true;
typedef typename boost::range_iterator<Range const>::type iterator;
for ( iterator it = boost::begin(range) ; it != boost::end(range) ; ++it )
{
if ( it->has(overlay::operation_intersection) )
{
found_not_touch = true;
return true;
}
switch(it->method)
{
case overlay::method_crosses:
found_not_touch = true;
return true;
case overlay::method_equal:
// Segment spatially equal means: at the right side
// the polygon internally overlaps. So return false.
found_not_touch = true;
return true;
case overlay::method_touch:
case overlay::method_touch_interior:
case overlay::method_collinear:
if ( ok_for_touch(*it) )
{
found_touch = true;
}
else
{
found_not_touch = true;
return true;
}
break;
case overlay::method_none :
case overlay::method_disjoint :
case overlay::method_error :
break;
}
}
return false;
}
template <typename Turn>
inline bool ok_for_touch(Turn const& turn)
{
return turn.both(overlay::operation_union)
|| turn.both(overlay::operation_blocked)
|| turn.combination(overlay::operation_union, overlay::operation_blocked)
;
}
};
template<typename Geometry, typename PointInRingStrategy>
struct check_each_ring_for_within
{
bool has_within;
Geometry const& m_geometry;
PointInRingStrategy const& m_strategy;
inline check_each_ring_for_within(Geometry const& g, PointInRingStrategy const& strategy)
: has_within(false)
, m_geometry(g)
, m_strategy(strategy)
{}
template <typename Range>
inline void apply(Range const& range)
{
typename geometry::point_type<Range>::type p;
geometry::point_on_border(p, range);
if ( !has_within && geometry::within(p, m_geometry, m_strategy) )
{
has_within = true;
}
}
};
template <typename FirstGeometry, typename SecondGeometry, typename IntersectionStrategy>
inline bool rings_containing(FirstGeometry const& geometry1,
SecondGeometry const& geometry2,
IntersectionStrategy const& strategy)
{
// NOTE: This strategy could be defined inside IntersectionStrategy
typedef typename IntersectionStrategy::template point_in_geometry_strategy
<
FirstGeometry, SecondGeometry
>::type point_in_ring_strategy_type;
point_in_ring_strategy_type point_in_ring_strategy
= strategy.template get_point_in_geometry_strategy<FirstGeometry, SecondGeometry>();
check_each_ring_for_within
<
FirstGeometry, point_in_ring_strategy_type
> checker(geometry1, point_in_ring_strategy);
geometry::detail::for_each_range(geometry2, checker);
return checker.has_within;
}
template <typename Geometry1, typename Geometry2>
struct areal_areal
{
template <typename IntersectionStrategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
IntersectionStrategy const& strategy)
{
typedef detail::no_rescale_policy rescale_policy_type;
typedef typename geometry::point_type<Geometry1>::type point_type;
typedef detail::overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
std::deque<turn_info> turns;
detail::touches::areal_interrupt_policy policy;
rescale_policy_type robust_policy;
boost::geometry::get_turns
<
detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
detail::overlay::assign_null_policy
>(geometry1, geometry2, strategy, robust_policy, turns, policy);
return policy.result()
&& ! geometry::detail::touches::rings_containing(geometry1, geometry2, strategy)
&& ! geometry::detail::touches::rings_containing(geometry2, geometry1, strategy);
}
};
// P/*
struct use_point_in_geometry
{
template <typename Point, typename Geometry, typename Strategy>
static inline bool apply(Point const& point, Geometry const& geometry, Strategy const& strategy)
{
return detail::within::point_in_geometry(point, geometry, strategy) == 0;
}
};
}}
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch {
// TODO: Since CastedTags are used is Reverse needed?
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type,
typename CastedTag1 = typename tag_cast<Tag1, pointlike_tag, linear_tag, areal_tag>::type,
typename CastedTag2 = typename tag_cast<Tag2, pointlike_tag, linear_tag, areal_tag>::type,
bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
>
struct touches
: not_implemented<Tag1, Tag2>
{};
// If reversal is needed, perform it
template
<
typename Geometry1, typename Geometry2,
typename Tag1, typename Tag2,
typename CastedTag1, typename CastedTag2
>
struct touches<Geometry1, Geometry2, Tag1, Tag2, CastedTag1, CastedTag2, true>
: touches<Geometry2, Geometry1, Tag2, Tag1, CastedTag2, CastedTag1, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
return touches<Geometry2, Geometry1>::apply(g2, g1, strategy);
}
};
// P/P
template <typename Geometry1, typename Geometry2, typename Tag2>
struct touches<Geometry1, Geometry2, point_tag, Tag2, pointlike_tag, pointlike_tag, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const& , Geometry2 const& , Strategy const&)
{
return false;
}
};
template <typename Geometry1, typename Geometry2, typename Tag2>
struct touches<Geometry1, Geometry2, multi_point_tag, Tag2, pointlike_tag, pointlike_tag, false>
{
template <typename Strategy>
static inline bool apply(Geometry1 const&, Geometry2 const&, Strategy const&)
{
return false;
}
};
// P/*
template <typename Point, typename Geometry, typename Tag2, typename CastedTag2>
struct touches<Point, Geometry, point_tag, Tag2, pointlike_tag, CastedTag2, false>
: detail::touches::use_point_in_geometry
{};
// TODO: support touches(MPt, Linear/Areal)
// Box/Box
template <typename Box1, typename Box2, typename CastedTag1, typename CastedTag2>
struct touches<Box1, Box2, box_tag, box_tag, CastedTag1, CastedTag2, false>
: detail::touches::box_box
{};
template <typename Box1, typename Box2>
struct touches<Box1, Box2, box_tag, box_tag, areal_tag, areal_tag, false>
: detail::touches::box_box
{};
// L/L
template <typename Linear1, typename Linear2, typename Tag1, typename Tag2>
struct touches<Linear1, Linear2, Tag1, Tag2, linear_tag, linear_tag, false>
: detail::relate::relate_impl
<
detail::de9im::static_mask_touches_type,
Linear1,
Linear2
>
{};
// L/A
template <typename Linear, typename Areal, typename Tag1, typename Tag2>
struct touches<Linear, Areal, Tag1, Tag2, linear_tag, areal_tag, false>
: detail::relate::relate_impl
<
detail::de9im::static_mask_touches_type,
Linear,
Areal
>
{};
// A/L
template <typename Linear, typename Areal, typename Tag1, typename Tag2>
struct touches<Areal, Linear, Tag1, Tag2, areal_tag, linear_tag, false>
: detail::relate::relate_impl
<
detail::de9im::static_mask_touches_type,
Areal,
Linear
>
{};
// A/A
template <typename Areal1, typename Areal2, typename Tag1, typename Tag2>
struct touches<Areal1, Areal2, Tag1, Tag2, areal_tag, areal_tag, false>
: detail::relate::relate_impl
<
detail::de9im::static_mask_touches_type,
Areal1,
Areal2
>
{};
template <typename Areal1, typename Areal2>
struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false>
: detail::touches::areal_areal<Areal1, Areal2>
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
struct touches
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return dispatch::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::relate::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return dispatch::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant {
template <typename Geometry1, typename Geometry2>
struct touches
{
template <typename Strategy>
static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
return resolve_strategy::touches::apply(geometry1, geometry2, strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
, m_strategy(strategy)
{}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
, m_strategy(strategy)
{}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)>
struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
}
};
template <typename Strategy>
static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
}
};
template <typename Geometry>
struct self_touches
{
static bool apply(Geometry const& geometry)
{
concepts::check<Geometry const>();
typedef typename strategy::relate::services::default_strategy
<
Geometry, Geometry
>::type strategy_type;
typedef detail::no_rescale_policy rescale_policy_type;
typedef typename geometry::point_type<Geometry>::type point_type;
typedef detail::overlay::turn_info
<
point_type,
typename segment_ratio_type<point_type, rescale_policy_type>::type
> turn_info;
typedef detail::overlay::get_turn_info
<
detail::overlay::assign_null_policy
> policy_type;
std::deque<turn_info> turns;
detail::touches::areal_interrupt_policy policy;
strategy_type strategy;
rescale_policy_type robust_policy;
detail::self_get_turn_points::get_turns
<
policy_type
>::apply(geometry, strategy, robust_policy, turns, policy, 0);
return policy.result();
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
struct visitor: boost::static_visitor<bool>
{
template <typename Geometry>
bool operator()(Geometry const& geometry) const
{
return self_touches<Geometry>::apply(geometry);
}
};
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
{
return boost::apply_visitor(visitor(), geometry);
}
};
} // namespace resolve_variant
/*!
\brief \brief_check{has at least one touching point (self-tangency)}
\note This function can be called for one geometry (self-tangency) and
also for two geometries (touch)
\ingroup touches
\tparam Geometry \tparam_geometry
\param geometry \param_geometry
\return \return_check{is self-touching}
\qbk{distinguish,one geometry}
\qbk{[def __one_parameter__]}
\qbk{[include reference/algorithms/touches.qbk]}
*/
template <typename Geometry>
inline bool touches(Geometry const& geometry)
{
return resolve_variant::self_touches<Geometry>::apply(geometry);
}
/*!
\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
\ingroup touches
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\return \return_check2{touch each other}
\qbk{distinguish,two geometries}
\qbk{[include reference/algorithms/touches.qbk]}
*/
template <typename Geometry1, typename Geometry2>
inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, default_strategy());
}
/*!
\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
\ingroup touches
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam Strategy \tparam_strategy{Touches}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param strategy \param_strategy{touches}
\return \return_check2{touch each other}
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/touches.qbk]}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
inline bool touches(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP

View File

@ -20,515 +20,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
#include <cstddef>
#include <boost/geometry/algorithms/detail/within/interface.hpp>
#include <boost/geometry/algorithms/detail/within/implementation.hpp>
#include <boost/concept_check.hpp>
#include <boost/range.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/make.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/concepts/within_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/within.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/order_as_direction.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/views/reversible_view.hpp>
#include <boost/geometry/algorithms/detail/within/multi_point.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
#include <deque>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace within {
struct use_point_in_geometry
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
return detail::within::point_in_geometry(geometry1, geometry2, strategy) == 1;
}
};
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
typedef typename detail::de9im::static_mask_within_type
<
Geometry1, Geometry2
>::type within_mask;
return geometry::relate(geometry1, geometry2, within_mask(), strategy);
}
};
}} // namespace detail::within
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
typename Geometry1,
typename Geometry2,
typename Tag1 = typename tag<Geometry1>::type,
typename Tag2 = typename tag<Geometry2>::type
>
struct within
: not_implemented<Tag1, Tag2>
{};
template <typename Point, typename Box>
struct within<Point, Box, point_tag, box_tag>
{
template <typename Strategy>
static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
{
boost::ignore_unused_variable_warning(strategy);
return strategy.apply(point, box);
}
};
template <typename Box1, typename Box2>
struct within<Box1, Box2, box_tag, box_tag>
{
template <typename Strategy>
static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
{
assert_dimension_equal<Box1, Box2>();
boost::ignore_unused_variable_warning(strategy);
return strategy.apply(box1, box2);
}
};
// P/P
template <typename Point1, typename Point2>
struct within<Point1, Point2, point_tag, point_tag>
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename MultiPoint>
struct within<Point, MultiPoint, point_tag, multi_point_tag>
: public detail::within::use_point_in_geometry
{};
template <typename MultiPoint, typename Point>
struct within<MultiPoint, Point, multi_point_tag, point_tag>
: public detail::within::multi_point_point
{};
template <typename MultiPoint1, typename MultiPoint2>
struct within<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag>
: public detail::within::multi_point_multi_point
{};
// P/L
template <typename Point, typename Segment>
struct within<Point, Segment, point_tag, segment_tag>
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename Linestring>
struct within<Point, Linestring, point_tag, linestring_tag>
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename MultiLinestring>
struct within<Point, MultiLinestring, point_tag, multi_linestring_tag>
: public detail::within::use_point_in_geometry
{};
// P/A
template <typename Point, typename Ring>
struct within<Point, Ring, point_tag, ring_tag>
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename Polygon>
struct within<Point, Polygon, point_tag, polygon_tag>
: public detail::within::use_point_in_geometry
{};
template <typename Point, typename MultiPolygon>
struct within<Point, MultiPolygon, point_tag, multi_polygon_tag>
: public detail::within::use_point_in_geometry
{};
// L/L
template <typename Linestring1, typename Linestring2>
struct within<Linestring1, Linestring2, linestring_tag, linestring_tag>
: public detail::within::use_relate
{};
template <typename Linestring, typename MultiLinestring>
struct within<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename Linestring>
struct within<MultiLinestring, Linestring, multi_linestring_tag, linestring_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring1, typename MultiLinestring2>
struct within<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
: public detail::within::use_relate
{};
// L/A
template <typename Linestring, typename Ring>
struct within<Linestring, Ring, linestring_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename Ring>
struct within<MultiLinestring, Ring, multi_linestring_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename Linestring, typename Polygon>
struct within<Linestring, Polygon, linestring_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename Polygon>
struct within<MultiLinestring, Polygon, multi_linestring_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename Linestring, typename MultiPolygon>
struct within<Linestring, MultiPolygon, linestring_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiLinestring, typename MultiPolygon>
struct within<MultiLinestring, MultiPolygon, multi_linestring_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
// A/A
template <typename Ring1, typename Ring2>
struct within<Ring1, Ring2, ring_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename Ring, typename Polygon>
struct within<Ring, Polygon, ring_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename Polygon, typename Ring>
struct within<Polygon, Ring, polygon_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename Polygon1, typename Polygon2>
struct within<Polygon1, Polygon2, polygon_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename Ring, typename MultiPolygon>
struct within<Ring, MultiPolygon, ring_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiPolygon, typename Ring>
struct within<MultiPolygon, Ring, multi_polygon_tag, ring_tag>
: public detail::within::use_relate
{};
template <typename Polygon, typename MultiPolygon>
struct within<Polygon, MultiPolygon, polygon_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiPolygon, typename Polygon>
struct within<MultiPolygon, Polygon, multi_polygon_tag, polygon_tag>
: public detail::within::use_relate
{};
template <typename MultiPolygon1, typename MultiPolygon2>
struct within<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon_tag>
: public detail::within::use_relate
{};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
namespace resolve_strategy
{
struct within
{
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::within::check
<
typename tag<Geometry1>::type,
typename tag<Geometry2>::type,
typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
Strategy
>();
return dispatch::within<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
}
template <typename Geometry1, typename Geometry2>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
default_strategy)
{
typedef typename strategy::within::services::default_strategy
<
Geometry1,
Geometry2
>::type strategy_type;
return apply(geometry1, geometry2, strategy_type());
}
};
} // namespace resolve_strategy
namespace resolve_variant
{
template <typename Geometry1, typename Geometry2>
struct within
{
template <typename Strategy>
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
assert_dimension_equal<Geometry1, Geometry2>();
return resolve_strategy::within::apply(geometry1,
geometry2,
strategy);
}
};
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry2 const& m_geometry2;
Strategy const& m_strategy;
visitor(Geometry2 const& geometry2, Strategy const& strategy)
: m_geometry2(geometry2)
, m_strategy(strategy)
{}
template <typename Geometry1>
bool operator()(Geometry1 const& geometry1) const
{
return within<Geometry1, Geometry2>::apply(geometry1,
m_geometry2,
m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
geometry1);
}
};
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Geometry1 const& m_geometry1;
Strategy const& m_strategy;
visitor(Geometry1 const& geometry1, Strategy const& strategy)
: m_geometry1(geometry1)
, m_strategy(strategy)
{}
template <typename Geometry2>
bool operator()(Geometry2 const& geometry2) const
{
return within<Geometry1, Geometry2>::apply(m_geometry1,
geometry2,
m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(Geometry1 const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
geometry2
);
}
};
template <
BOOST_VARIANT_ENUM_PARAMS(typename T1),
BOOST_VARIANT_ENUM_PARAMS(typename T2)
>
struct within<
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
>
{
template <typename Strategy>
struct visitor: boost::static_visitor<bool>
{
Strategy const& m_strategy;
visitor(Strategy const& strategy): m_strategy(strategy) {}
template <typename Geometry1, typename Geometry2>
bool operator()(Geometry1 const& geometry1,
Geometry2 const& geometry2) const
{
return within<Geometry1, Geometry2>::apply(geometry1,
geometry2,
m_strategy);
}
};
template <typename Strategy>
static inline bool
apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
Strategy const& strategy)
{
return boost::apply_visitor(visitor<Strategy>(strategy),
geometry1,
geometry2);
}
};
}
/*!
\brief \brief_check12{is completely inside}
\ingroup within
\details \details_check12{within, is completely inside}.
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry which might be within the second geometry
\param geometry2 \param_geometry which might contain the first geometry
\return true if geometry1 is completely contained within geometry2,
else false
\note The default strategy is used for within detection
\qbk{[include reference/algorithms/within.qbk]}
\qbk{
[heading Example]
[within]
[within_output]
}
*/
template<typename Geometry1, typename Geometry2>
inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
return resolve_variant::within
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, default_strategy());
}
/*!
\brief \brief_check12{is completely inside} \brief_strategy
\ingroup within
\details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\param geometry1 \param_geometry which might be within the second geometry
\param geometry2 \param_geometry which might contain the first geometry
\param strategy strategy to be used
\return true if geometry1 is completely contained within geometry2,
else false
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/within.qbk]}
\qbk{
[heading Available Strategies]
\* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]
\* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]
\* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]
[heading Example]
[within_strategy]
[within_strategy_output]
}
*/
template<typename Geometry1, typename Geometry2, typename Strategy>
inline bool within(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
return resolve_variant::within
<
Geometry1,
Geometry2
>::apply(geometry1, geometry2, strategy);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP

View File

@ -2,7 +2,7 @@
//
// boxes union/intersection area/volume
//
// Copyright (c) 2011-2016 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -11,8 +11,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/strategies/intersection_strategies.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp>
#include <boost/geometry/index/detail/algorithms/content.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
@ -23,11 +24,19 @@ namespace boost { namespace geometry { namespace index { namespace detail {
template <typename Box>
inline typename default_content_result<Box>::type intersection_content(Box const& box1, Box const& box2)
{
if ( geometry::intersects(box1, box2) )
bool const intersects = ! geometry::detail::disjoint::box_box<Box, Box>::apply(box1, box2);
if ( intersects )
{
Box box_intersection;
if ( geometry::intersection(box1, box2, box_intersection) )
return detail::content(box_intersection);
bool const ok = geometry::detail::intersection::intersection_box_box
<
0, geometry::dimension<Box>::value
>::apply(box1, box2, 0, box_intersection, 0);
if ( ok )
{
return index::detail::content(box_intersection);
}
}
return 0;
}

View File

@ -2,7 +2,7 @@
//
// n-dimensional box-linestring intersection
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -11,8 +11,12 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP
#include <boost/geometry/index/detail/algorithms/segment_intersection.hpp>
#include <boost/geometry/strategies/default_length_result.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
namespace dispatch {

View File

@ -2,7 +2,7 @@
//
// R-tree removing visitor implementation
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -13,7 +13,7 @@
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
namespace boost { namespace geometry { namespace index {

View File

@ -9,7 +9,7 @@
#ifndef BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP
#define BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/index/indexable.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {

View File

@ -1,6 +1,6 @@
// Boost.Geometry Index
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -10,6 +10,7 @@
#define BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
#include <boost/mpl/assert.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/geometry/index/detail/is_indexable.hpp>

View File

@ -3,7 +3,7 @@
// R-tree implementation
//
// Copyright (c) 2008 Federico J. Fernandez.
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -21,20 +21,18 @@
// Boost.Geometry
#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/algorithms/detail/intersects/interface.hpp>
#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
#include <boost/geometry/algorithms/detail/touches/interface.hpp>
#include <boost/geometry/algorithms/detail/within/interface.hpp>
#include <boost/geometry/algorithms/centroid.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/overlaps.hpp>
#include <boost/geometry/algorithms/touches.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/strategies/strategies.hpp>
// Boost.Geometry.Index
#include <boost/geometry/index/detail/config_begin.hpp>
@ -145,7 +143,8 @@ compared left-to-right.
\tparam Allocator The allocator used to allocate/deallocate memory,
construct/destroy nodes and Values.
*/
template <
template
<
typename Value,
typename Parameters,
typename IndexableGetter = index::indexable<Value>,
@ -2222,9 +2221,6 @@ struct range_mutable_iterator
} // namespace boost
// TODO: don't include the implementation at the end of the file
#include <boost/geometry/algorithms/detail/comparable_distance/implementation.hpp>
#include <boost/geometry/index/detail/config_end.hpp>
#endif // BOOST_GEOMETRY_INDEX_RTREE_HPP

View File

@ -473,28 +473,44 @@ private:
namespace services
{
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
typedef winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
typedef winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
typedef winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
typedef winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
} // namespace services
@ -509,28 +525,44 @@ struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linea
namespace strategy { namespace covered_by { namespace services
{
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
typedef within::winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, spherical_tag, spherical_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
typedef within::winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
typedef within::winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
template <typename Point, typename Geometry, typename AnyTag>
struct default_strategy<Point, Geometry, point_tag, AnyTag, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, spherical_tag, spherical_tag>
{
typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
typedef within::winding
<
typename geometry::point_type<PointLike>::type,
typename geometry::point_type<Geometry>::type
> type;
};
}}} // namespace strategy::covered_by::services

View File

@ -6,10 +6,11 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014, Oracle and/or its affiliates.
// This file was modified by Oracle on 2014, 2017.
// Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, 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.
@ -27,6 +28,7 @@
#include <geometry_test_common.hpp>
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/algorithms/make.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.hpp>

View File

@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@ -37,6 +38,8 @@
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/strategies/strategies.hpp>
#include <from_wkt.hpp>
#include <string_from_type.hpp>

View File

@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@ -36,6 +37,8 @@
#include <boost/geometry/algorithms/distance.hpp>
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/strategies/strategies.hpp>
#include <from_wkt.hpp>
#include <string_from_type.hpp>

View File

@ -19,6 +19,7 @@
#include <boost/foreach.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/make.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>

View File

@ -3,6 +3,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2017.
// Modifications copyright (c) 2017, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// 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)
@ -19,6 +23,7 @@
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_relative_order.hpp>
#include <boost/geometry/algorithms/make.hpp>
#include <boost/geometry/geometries/point_xy.hpp>

View File

@ -68,6 +68,37 @@ void test_all()
test_geometry<P, mls>("POINT(0 0)", "MULTILINESTRING((0 0,1 1,2 2),(0 0,0 1))", true);
test_geometry<P, mls>("POINT(0 0)", "MULTILINESTRING((0 0,1 1,2 2),(0 0,0 1),(0 0,1 0))", true);
// multi_point/segment
typedef bg::model::multi_point<P> mpt;
test_geometry<mpt, seg>("MULTIPOINT(0 0, 1 1)", "LINESTRING(0 0, 2 2)", true);
// multi_point/linestring
test_geometry<mpt, ls>("MULTIPOINT(0 0, 2 2)", "LINESTRING(0 0, 2 2)", true);
test_geometry<mpt, ls>("MULTIPOINT(1 1, 3 3)", "LINESTRING(0 0, 2 2)", false);
// multi_point/multi_linestring
test_geometry<mpt, mls>("MULTIPOINT(0 0, 1 1)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 3))", true);
test_geometry<mpt, mls>("MULTIPOINT(0 0, 2 2)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 3))", true);
test_geometry<mpt, mls>("MULTIPOINT(0 0, 3 3)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 3))", true);
test_geometry<mpt, mls>("MULTIPOINT(1 1, 4 4)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 3))", false);
// point/A
typedef bg::model::ring<P> ring;
typedef bg::model::polygon<P> poly;
typedef bg::model::multi_polygon<poly> mpoly;
test_geometry<P, ring>("POINT(1 1)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", true);
test_geometry<P, poly>("POINT(1 1)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", true);
test_geometry<P, mpoly>("POINT(1 1)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((2 2,2 3,3 3,3 2,2 2)))", true);
// multi_point/A
test_geometry<mpt, ring>("MULTIPOINT(0 0, 1 1)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", true);
test_geometry<mpt, poly>("MULTIPOINT(0 0, 2 2)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", true);
test_geometry<mpt, poly>("MULTIPOINT(1 1, 3 3)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", false);
test_geometry<mpt, mpoly>("MULTIPOINT(0 0, 1 1)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((2 2,2 3,3 3,3 2,2 2)))", true);
test_geometry<mpt, mpoly>("MULTIPOINT(0 0, 2 2)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((2 2,2 3,3 3,3 2,2 2)))", true);
test_geometry<mpt, mpoly>("MULTIPOINT(0 0, 3 3)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((2 2,2 3,3 3,3 2,2 2)))", true);
test_geometry<mpt, mpoly>("MULTIPOINT(1 1, 4 4)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((2 2,2 3,3 3,3 2,2 2)))", false);
typedef bg::model::box<P> box_type;
test_geometry<P, box_type>("POINT(1 1)", "BOX(0 0,2 2)", true);

View File

@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.
// This file was modified by Oracle on 2014, 2017.
// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -16,24 +16,31 @@
template <typename P>
void test_pl()
{
/*typedef bg::model::multi_point<P> mpt;
typedef bg::model::multi_point<P> mpt;
typedef bg::model::linestring<P> ls;
typedef bg::model::multi_linestring<ls> mls;
// not implemented yet
test_geometry<mpt, ls>("MULTIPOINT(0 0,1 1)", "LINESTRING(0 0,1 0,3 3)", true);
test_geometry<mpt, ls>("MULTIPOINT(0 0,1 1)", "LINESTRING(0 0,1 1,3 3)", false);*/
test_geometry<mpt, ls>("MULTIPOINT(1 0,1 1)", "LINESTRING(0 0,1 0,3 3)", true);
test_geometry<mpt, ls>("MULTIPOINT(0 0,1 1)", "LINESTRING(0 0,1 0,3 3)", false);
test_geometry<mpt, ls>("MULTIPOINT(0 0,1 1)", "LINESTRING(0 0,1 1,3 3)", false);
test_geometry<mpt, mls>("MULTIPOINT(0 0,3 0)", "MULTILINESTRING((0 0,0 1,1 1),(1 1,1 0,0 0))", true);
test_geometry<mpt, mls>("MULTIPOINT(0 0,1 1)", "MULTILINESTRING((0 0,0 1,1 1),(1 1,1 0,0 0))", false);
}
template <typename P>
void test_pa()
{
/*typedef bg::model::multi_point<P> mpt;
typedef bg::model::multi_point<P> mpt;
typedef bg::model::polygon<P> poly;
typedef bg::model::multi_polygon<poly> mpoly;
// not implemented yet
test_geometry<mpt, poly>("MULTIPOINT(0 0,6 6)", "POLYGON((0 0,0 5,5 5,5 0,0 0))", true);
test_geometry<mpt, poly>("MULTIPOINT(0 0,1 1)", "POLYGON((0 0,0 5,5 5,5 0,0 0))", false);*/
test_geometry<mpt, poly>("MULTIPOINT(1 1,6 6)", "POLYGON((0 0,0 5,5 5,5 0,0 0))", true);
test_geometry<mpt, poly>("MULTIPOINT(0 0,6 6)", "POLYGON((0 0,0 5,5 5,5 0,0 0))", false);
test_geometry<mpt, poly>("MULTIPOINT(0 0,1 1)", "POLYGON((0 0,0 5,5 5,5 0,0 0))", false);
test_geometry<mpt, mpoly>("MULTIPOINT(0 0,1 1)", "MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((5 5,5 9,9 9,9 5,5 5)))", false);
test_geometry<mpt, mpoly>("MULTIPOINT(1 1,1 6)", "MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0)),((5 5,5 9,9 9,9 5,5 5)))", true);
}
template <typename P>

View File

@ -1,12 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2015, Oracle and/or its affiliates.
// Copyright (c) 2014-2017, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_TEST_MODULE
#define BOOST_TEST_MODULE test_disjoint_coverage
@ -211,22 +212,22 @@ inline void test_multipoint_polygon()
tester::apply("mp-pg-01",
from_wkt<MP>("MULTIPOINT(0 0,1 0)"),
from_wkt<PL>("POLYGON(((0 0,1 0,0 1)))"),
from_wkt<PL>("POLYGON((0 0,1 0,0 1))"),
false);
tester::apply("mp-pg-02",
from_wkt<MP>("MULTIPOINT(0 0,2 0)"),
from_wkt<PL>("POLYGON(((0 0,1 0,0 1)))"),
from_wkt<PL>("POLYGON((0 0,1 0,0 1))"),
false);
tester::apply("mp-pg-03",
from_wkt<MP>("MULTIPOINT(1 1,2 0)"),
from_wkt<PL>("POLYGON(((0 0,1 0,0 1)))"),
from_wkt<PL>("POLYGON((0 0,1 0,0 1))"),
true);
tester::apply("mp-pg-04",
from_wkt<MP>("MULTIPOINT(1 1,2 3)"),
from_wkt<PL>("POLYGON(((0 0,1 0,0 1)))"),
from_wkt<PL>("POLYGON((0 0,1 0,0 1))"),
true);
}
@ -241,22 +242,22 @@ inline void test_multipoint_multipolygon()
tester::apply("mp-mp-01",
from_wkt<MP>("MULTIPOINT(0 0,2 0)"),
from_wkt<MPL>("MULTIPOLYGON((0 0,1 0,0 1)),(2 0,3 0,2 1))"),
from_wkt<MPL>("MULTIPOLYGON(((0 0,1 0,0 1)),((2 0,3 0,2 1)))"),
false);
tester::apply("mp-mp-02",
from_wkt<MP>("MULTIPOINT(0 0,1 0)"),
from_wkt<MPL>("MULTIPOLYGON((0 0,1 0,0 1)),(2 0,3 0,2 1))"),
from_wkt<MPL>("MULTIPOLYGON(((0 0,1 0,0 1)),((2 0,3 0,2 1)))"),
false);
tester::apply("mp-mp-03",
from_wkt<MP>("MULTIPOINT(1 1,2 0)"),
from_wkt<MPL>("MULTIPOLYGON((0 0,1 0,0 1)),(2 0,3 0,2 1))"),
from_wkt<MPL>("MULTIPOLYGON(((0 0,1 0,0 1)),((2 0,3 0,2 1)))"),
false);
tester::apply("mp-mp-04",
from_wkt<MP>("MULTIPOINT(1 1,2 3)"),
from_wkt<MPL>("MULTIPOLYGON((0 0,1 0,0 1)),(2 0,3 0,2 1))"),
from_wkt<MPL>("MULTIPOLYGON(((0 0,1 0,0 1)),((2 0,3 0,2 1)))"),
true);
}
@ -272,10 +273,10 @@ inline void test_pointlike_areal()
test_point_ring<point_type>();
test_point_box<point_type>();
// not implemented yet
// test_multipoint_polygon<point_type>();
// test_multipoint_multipolygon<point_type>();
// test_multipoint_ring<point_type>();
test_multipoint_polygon<point_type>();
test_multipoint_multipolygon<point_type>();
test_multipoint_ring<point_type>();
test_multipoint_box<point_type>();
}

View File

@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014, 2015.
// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
// This file was modified by Oracle on 2013, 2014, 2015, 2017.
// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -65,6 +65,9 @@ void test_point_linestring()
{
typedef bg::model::linestring<P> ls;
// degenerated
//test_geometry<P, ls>("POINT(0 0)", "LINESTRING(0 0)", "0FFFFFFF2");
test_geometry<P, ls>("POINT(0 0)", "LINESTRING(0 0, 2 2, 3 2)", "F0FFFF102");
test_geometry<P, ls>("POINT(1 1)", "LINESTRING(0 0, 2 2, 3 2)", "0FFFFF102");
test_geometry<P, ls>("POINT(3 2)", "LINESTRING(0 0, 2 2, 3 2)", "F0FFFF102");
@ -112,14 +115,127 @@ void test_point_multilinestring()
}
}
template <typename P>
void test_multipoint_linestring()
{
typedef bg::model::multi_point<P> mpt;
typedef bg::model::linestring<P> ls;
// degenerated
//test_geometry<mpt, ls>("MULTIPOINT(0 0)", "LINESTRING(0 0)", "0FFFFFFF2");
test_geometry<mpt, ls>("MULTIPOINT(0 0)", "LINESTRING(0 0, 2 2, 3 2)", "F0FFFF102");
test_geometry<mpt, ls>("MULTIPOINT(0 0, 1 1)", "LINESTRING(0 0, 2 2, 3 2)", "00FFFF102");
test_geometry<mpt, ls>("MULTIPOINT(0 0, 1 1, 3 3)", "LINESTRING(0 0, 2 2, 3 2)", "000FFF102");
test_geometry<mpt, ls>("MULTIPOINT(0 0, 3 3)", "LINESTRING(0 0, 2 2, 3 2)", "F00FFF102");
test_geometry<mpt, ls>("MULTIPOINT(1 1, 3 3)", "LINESTRING(0 0, 2 2, 3 2)", "0F0FFF102");
test_geometry<mpt, ls>("MULTIPOINT(0 0, 1 1)", "LINESTRING(0 0, 2 2, 3 2, 0 0)", "0FFFFF1F2");
test_geometry<mpt, ls>("MULTIPOINT(0 0, 3 3)", "LINESTRING(0 0, 2 2, 3 2, 0 0)", "0F0FFF1F2");
test_geometry<mpt, ls>("MULTIPOINT(0 0)", "LINESTRING(0 0, 2 2)", "F0FFFF102");
test_geometry<mpt, ls>("MULTIPOINT(2 2)", "LINESTRING(0 0, 2 2)", "F0FFFF102");
test_geometry<mpt, ls>("MULTIPOINT(0 0, 2 2)", "LINESTRING(0 0, 2 2)", "F0FFFF1F2");
test_geometry<mpt, ls>("MULTIPOINT(0 0, 1 1, 0 1, 2 2)", "LINESTRING(0 0, 2 2)", "000FFF1F2");
}
template <typename P>
void test_multipoint_multilinestring()
{
typedef bg::model::multi_point<P> mpt;
typedef bg::model::linestring<P> ls;
typedef bg::model::multi_linestring<ls> mls;
test_geometry<mpt, mls>("MULTIPOINT(0 0)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 2))", "F0FFFF102");
test_geometry<mpt, mls>("MULTIPOINT(0 0, 1 1)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 2))", "00FFFF102");
test_geometry<mpt, mls>("MULTIPOINT(0 0, 1 1, 3 3)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 2))", "000FFF102");
test_geometry<mpt, mls>("MULTIPOINT(0 0, 3 3)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 2))", "F00FFF102");
test_geometry<mpt, mls>("MULTIPOINT(1 1, 3 3)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 2))", "0F0FFF102");
test_geometry<mpt, mls>("MULTIPOINT(0 0, 1 1)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 2, 0 0))", "0FFFFF1F2");
test_geometry<mpt, mls>("MULTIPOINT(0 0, 3 3)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 2, 0 0))", "0F0FFF1F2");
test_geometry<mpt, mls>("MULTIPOINT(0 0,1 1)", "MULTILINESTRING((0 0,0 1,1 1),(1 1,1 0,0 0))", "0FFFFF1F2");
test_geometry<mpt, mls>("MULTIPOINT(0 0)", "MULTILINESTRING((0 0,1 1),(1 1,2 2))", "F0FFFF102");
test_geometry<mpt, mls>("MULTIPOINT(0 0, 1 1)", "MULTILINESTRING((0 0,1 1),(1 1,2 2))", "00FFFF102");
test_geometry<mpt, mls>("MULTIPOINT(0 0, 1 1, 2 2)", "MULTILINESTRING((0 0,1 1),(1 1,2 2))", "00FFFF1F2");
test_geometry<mpt, mls>("MULTIPOINT(0 0, 2 2)", "MULTILINESTRING((0 0,1 1),(1 1,2 2))", "F0FFFF1F2");
}
template <typename P>
void test_point_ring_polygon()
{
typedef bg::model::ring<P> ring;
typedef bg::model::polygon<P> poly;
test_geometry<P, ring>("POINT(0 0)", "POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))", "F0FFFF212");
test_geometry<P, poly>("POINT(1 1)", "POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))", "0FFFFF212");
test_geometry<P, poly>("POINT(1 3)", "POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))", "FF0FFF212");
}
template <typename P>
void test_point_multipolygon()
{
typedef bg::model::polygon<P> poly;
typedef bg::model::multi_polygon<poly> mpoly;
test_geometry<P, mpoly>("POINT(0 0)", "MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)),((5 5, 5 9, 9 9, 9 5, 5 5)))", "F0FFFF212");
test_geometry<P, mpoly>("POINT(1 1)", "MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)),((5 5, 5 9, 9 9, 9 5, 5 5)))", "0FFFFF212");
test_geometry<P, mpoly>("POINT(5 5)", "MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)),((5 5, 5 9, 9 9, 9 5, 5 5)))", "F0FFFF212");
test_geometry<P, mpoly>("POINT(6 6)", "MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)),((5 5, 5 9, 9 9, 9 5, 5 5)))", "0FFFFF212");
test_geometry<P, mpoly>("POINT(1 6)", "MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)),((5 5, 5 9, 9 9, 9 5, 5 5)))", "FF0FFF212");
}
template <typename P>
void test_multipoint_ring_polygon()
{
typedef bg::model::multi_point<P> mpt;
typedef bg::model::ring<P> ring;
typedef bg::model::polygon<P> poly;
test_geometry<mpt, ring>("MULTIPOINT(0 0)", "POLYGON((0 0, 0 3, 3 3, 3 0, 0 0))", "F0FFFF212");
test_geometry<mpt, ring>("MULTIPOINT(0 0, 1 1)", "POLYGON((0 0, 0 3, 3 3, 3 0, 0 0))", "00FFFF212");
test_geometry<mpt, ring>("MULTIPOINT(0 0, 1 1, 4 4)", "POLYGON((0 0, 0 3, 3 3, 3 0, 0 0))", "000FFF212");
test_geometry<mpt, ring>("MULTIPOINT(1 1, 4 4)", "POLYGON((0 0, 0 3, 3 3, 3 0, 0 0))", "0F0FFF212");
test_geometry<mpt, poly>("MULTIPOINT(2 2)", "POLYGON((0 0, 0 4, 4 4, 4 0, 0 0),(1 1, 3 1, 3 3, 1 3, 1 1))", "FF0FFF212");
test_geometry<mpt, poly>("MULTIPOINT(0 0, 1 1)", "POLYGON((0 0, 0 4, 4 4, 4 0, 0 0),(1 1, 3 1, 3 3, 1 3, 1 1))", "F0FFFF212");
test_geometry<mpt, poly>("MULTIPOINT(0 0, 1 1, 2 2)", "POLYGON((0 0, 0 4, 4 4, 4 0, 0 0),(1 1, 3 1, 3 3, 1 3, 1 1))", "F00FFF212");
test_geometry<mpt, poly>("MULTIPOINT(2 2, 4 4)", "POLYGON((0 0, 0 5, 5 5, 5 0, 0 0),(1 1, 3 1, 3 3, 1 3, 1 1))", "0F0FFF212");
}
template <typename P>
void test_multipoint_multipolygon()
{
typedef bg::model::multi_point<P> mpt;
typedef bg::model::polygon<P> poly;
typedef bg::model::multi_polygon<poly> mpoly;
test_geometry<mpt, mpoly>("MULTIPOINT(0 0)", "MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)),((5 5, 5 9, 9 9, 9 5, 5 5)))", "F0FFFF212");
test_geometry<mpt, mpoly>("MULTIPOINT(0 0, 1 1)", "MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)),((5 5, 5 9, 9 9, 9 5, 5 5)))", "00FFFF212");
test_geometry<mpt, mpoly>("MULTIPOINT(1 1, 5 5)", "MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)),((5 5, 5 9, 9 9, 9 5, 5 5)))", "00FFFF212");
test_geometry<mpt, mpoly>("MULTIPOINT(1 6, 6 6)", "MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)),((5 5, 5 9, 9 9, 9 5, 5 5)))", "0F0FFF212");
test_geometry<mpt, mpoly>("MULTIPOINT(0 0, 1 6)", "MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)),((5 5, 5 9, 9 9, 9 5, 5 5)))", "F00FFF212");
}
template <typename P>
void test_all()
{
test_point_point<P>();
test_point_multipoint<P>();
test_multipoint_multipoint<P>();
test_point_linestring<P>();
test_point_multilinestring<P>();
test_multipoint_linestring<P>();
test_multipoint_multilinestring<P>();
test_point_ring_polygon<P>();
test_point_multipolygon<P>();
test_multipoint_ring_polygon<P>();
test_multipoint_multipolygon<P>();
}
int test_main( int , char* [] )

View File

@ -16,6 +16,7 @@
template <typename P>
void test_all()
{
typedef bg::model::multi_point<P> mpoint;
typedef bg::model::ring<P> ring;
typedef bg::model::polygon<P> polygon;
typedef bg::model::linestring<P> linestring;
@ -152,6 +153,10 @@ void test_all()
test_touches<P, mlinestring>("POINT(0 0)", "MULTILINESTRING((0 0, 2 2, 10 2),(5 5, 6 6))", true);
test_touches<P, mlinestring>("POINT(0 0)", "MULTILINESTRING((0 0, 2 2, 10 2),(0 0, 6 6))", false);
// MultiPoint-Polygon
test_touches<mpoint, ring>("MULTIPOINT(40 50, 30 50)", "POLYGON((40 40,40 60,60 60,60 40,40 40))", true);
test_touches<mpoint, polygon>("MULTIPOINT(40 50, 50 50)", "POLYGON((40 40,40 60,60 60,60 40,40 40))", false);
// Linestring-Linestring
test_touches<linestring, linestring>("LINESTRING(0 0,2 0)", "LINESTRING(0 0,0 2)", true);
test_touches<linestring, linestring>("LINESTRING(0 0,2 0)", "LINESTRING(2 0,2 2)", true);

View File

@ -45,6 +45,7 @@ void test_p_p()
template <typename P>
void test_p_l()
{
typedef bg::model::multi_point<P> mpt;
typedef bg::model::segment<P> seg;
typedef bg::model::linestring<P> ls;
typedef bg::model::multi_linestring<ls> mls;
@ -65,11 +66,23 @@ void test_p_l()
test_geometry<P, mls>("POINT(1 1)", "MULTILINESTRING((0 0, 1 1),(1 1, 2 2))", true);
test_geometry<P, mls>("POINT(1 1)", "MULTILINESTRING((0 0, 1 1),(2 2, 3 3))", false);
test_geometry<mpt, seg>("MULTIPOINT(0 0, 1 1)", "LINESTRING(0 0, 2 2)", true);
test_geometry<mpt, ls>("MULTIPOINT(0 0, 2 2)", "LINESTRING(0 0, 2 2)", false);
test_geometry<mpt, ls>("MULTIPOINT(1 1, 3 3)", "LINESTRING(0 0, 2 2)", false);
test_geometry<mpt, mls>("MULTIPOINT(0 0, 1 1)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 3))", true);
test_geometry<mpt, mls>("MULTIPOINT(0 0, 2 2)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 3))", true);
test_geometry<mpt, mls>("MULTIPOINT(0 0, 3 3)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 3))", false);
test_geometry<mpt, mls>("MULTIPOINT(1 1, 4 4)", "MULTILINESTRING((0 0, 2 2),(2 2, 3 3))", false);
}
template <typename P>
void test_p_a()
{
typedef bg::model::multi_point<P> mpt;
typedef bg::model::ring<P> ring;
typedef bg::model::polygon<P> poly;
typedef bg::model::multi_polygon<poly> mpoly;
@ -116,6 +129,16 @@ void test_p_a()
"POLYGON((0 5, 5 0, 6 1, 5 2, 8 4, 5 6, 6 7, 5 8, 6 9, 5 10, 0 5))", true);
test_geometry<P, poly>("POINT(4 6)",
"POLYGON((5 0, 0 5, 1 6, 2 5, 4 8, 6 5, 7 6, 8 5, 9 6, 10 5, 5 0))", true);
test_geometry<mpt, ring>("MULTIPOINT(0 0, 1 1)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", true);
test_geometry<mpt, poly>("MULTIPOINT(0 0, 2 2)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", false);
test_geometry<mpt, poly>("MULTIPOINT(1 1, 3 3)", "POLYGON((0 0,0 2,2 2,2 0,0 0))", false);
test_geometry<mpt, mpoly>("MULTIPOINT(0 0, 1 1)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((2 2,2 3,3 3,3 2,2 2)))", true);
test_geometry<mpt, mpoly>("MULTIPOINT(0 0, 2 2)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((2 2,2 3,3 3,3 2,2 2)))", false);
test_geometry<mpt, mpoly>("MULTIPOINT(0 0, 3 3)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((2 2,2 3,3 3,3 2,2 2)))", false);
test_geometry<mpt, mpoly>("MULTIPOINT(1 1, 4 4)", "MULTIPOLYGON(((0 0,0 2,2 2,2 0,0 0)),((2 2,2 3,3 3,3 2,2 2)))", false);
}
template <typename P>