Splitted intersection and intersection_inserter

Doing back_inserter now in later phase of dispatch
Added MPL assertions to coordinate system and type
Modified read_wkt with output iterator option

[SVN r67473]
This commit is contained in:
Barend Gehrels
2010-12-28 16:37:11 +00:00
parent f0be3d6d8b
commit 7e96ac247f
5 changed files with 627 additions and 408 deletions

View File

@@ -10,21 +10,9 @@
#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_HPP
#include <cstddef>
#include <boost/mpl/if.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/range/metafunctions.hpp>
#include <boost/geometry/core/is_areal.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/overlay/clip_linestring.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/ranges/segment_range.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/algorithms/intersection_inserter.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
namespace boost { namespace geometry
@@ -36,72 +24,56 @@ namespace detail { namespace intersection
template
<
typename Segment1, typename Segment2,
typename OutputIterator, typename PointOut,
typename Strategy
typename Box1, typename Box2,
typename BoxOut,
typename Strategy,
std::size_t Dimension, std::size_t DimensionCount
>
struct intersection_segment_segment_point
struct intersection_box_box
{
static inline OutputIterator apply(Segment1 const& segment1,
Segment2 const& segment2, OutputIterator out,
static inline bool apply(Box1 const& box1,
Box2 const& box2, BoxOut& box_out,
Strategy const& strategy)
{
typedef typename point_type<PointOut>::type point_type;
typedef typename coordinate_type<BoxOut>::type ct;
// Get the intersection point (or two points)
segment_intersection_points<point_type> is
= strategy::intersection::relate_cartesian_segments
<
policies::relate::segments_intersection_points
<
Segment1,
Segment2,
segment_intersection_points<point_type>
>
>::apply(segment1, segment2);
ct min1 = get<min_corner, Dimension>(box1);
ct min2 = get<min_corner, Dimension>(box2);
ct max1 = get<max_corner, Dimension>(box1);
ct max2 = get<max_corner, Dimension>(box2);
for (std::size_t i = 0; i < is.count; i++)
if (max1 < min2 || max2 < min1)
{
PointOut p;
geometry::copy_coordinates(is.intersections[i], p);
*out++ = p;
return false;
}
return out;
// Set dimensions of output coordinate
set<min_corner, Dimension>(box_out, min1 < min2 ? min2 : min1);
set<max_corner, Dimension>(box_out, max1 > max2 ? max2 : max1);
return intersection_box_box
<
Box1, Box2, BoxOut, Strategy,
Dimension + 1, DimensionCount
>::apply(box1, box2, box_out, strategy);
}
};
template
<
typename Linestring1, typename Linestring2,
typename OutputIterator, typename PointOut,
typename Strategy
typename Box1, typename Box2,
typename BoxOut,
typename Strategy,
std::size_t DimensionCount
>
struct intersection_linestring_linestring_point
struct intersection_box_box<Box1, Box2, BoxOut, Strategy, DimensionCount, DimensionCount>
{
static inline OutputIterator apply(Linestring1 const& linestring1,
Linestring2 const& linestring2, OutputIterator out,
Strategy const& strategy)
static inline bool apply(Box1 const&, Box2 const&, BoxOut&, Strategy const&)
{
typedef typename point_type<PointOut>::type point_type;
typedef detail::overlay::turn_info<point_type> turn_info;
std::deque<turn_info> turns;
geometry::get_intersection_points(linestring1, linestring2, turns);
for (typename boost::range_iterator<std::deque<turn_info> const>::type
it = boost::begin(turns); it != boost::end(turns); ++it)
{
PointOut p;
geometry::copy_coordinates(it->point, p);
*out++ = p;
}
return out;
return true;
}
};
}} // namespace detail::intersection
#endif // DOXYGEN_NO_DETAIL
@@ -111,362 +83,95 @@ struct intersection_linestring_linestring_point
namespace dispatch
{
// By default, all is forwarded to the intersection_inserter-dispatcher
template
<
// tag dispatching:
typename TagIn1, typename TagIn2, typename TagOut,
// orientation
// metafunction finetuning helpers:
bool Areal1, bool Areal2, bool ArealOut,
// real types
typename Tag1, typename Tag2, typename TagOut,
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
typename Strategy
>
struct intersection_inserter
struct intersection
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES_OR_ORIENTATIONS
, (types<Geometry1, Geometry2, GeometryOut>)
);
typedef std::back_insert_iterator<GeometryOut> output_iterator;
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
GeometryOut& geometry_out,
Strategy const& strategy)
{
typedef typename boost::range_value<GeometryOut>::type OneOut;
intersection_inserter
<
Tag1, Tag2, typename geometry::tag<OneOut>::type,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<OneOut>::value,
Geometry1, Geometry2,
detail::overlay::do_reverse<geometry::point_order<Geometry1>::value, false>::value,
detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, false>::value,
false,
output_iterator, OneOut,
Strategy
>::apply(geometry1, geometry2, std::back_inserter(geometry_out), strategy);
return true;
}
};
template
<
typename TagIn1, typename TagIn2, typename TagOut,
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
typename Box1, typename Box2,
typename BoxOut,
typename Strategy
>
struct intersection_inserter
struct intersection
<
TagIn1, TagIn2, TagOut,
true, true, true,
Geometry1, Geometry2,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
box_tag, box_tag, box_tag,
Box1, Box2, BoxOut,
Strategy
> : detail::overlay::overlay
<Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, OutputIterator, GeometryOut, -1, Strategy>
{};
// Any areal type with box:
template
<
typename TagIn, typename TagOut,
typename Geometry, typename Box,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
TagIn, box_tag, TagOut,
true, true, true,
Geometry, Box,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
> : detail::overlay::overlay
<Geometry, Box, Reverse1, Reverse2, ReverseOut, OutputIterator, GeometryOut, -1, Strategy>
{};
template
<
typename Segment1, typename Segment2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
segment_tag, segment_tag, point_tag,
false, false, false,
Segment1, Segment2,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
> : detail::intersection::intersection_segment_segment_point
> : public detail::intersection::intersection_box_box
<
Segment1, Segment2,
OutputIterator, GeometryOut,
Strategy
Box1, Box2, BoxOut,
Strategy,
0, geometry::dimension<Box1>::value
>
{};
template
<
typename Linestring1, typename Linestring2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
linestring_tag, linestring_tag, point_tag,
false, false, false,
Linestring1, Linestring2,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
> : detail::intersection::intersection_linestring_linestring_point
<
Linestring1, Linestring2,
OutputIterator, GeometryOut,
Strategy
>
{};
template
<
typename Linestring, typename Box,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
linestring_tag, box_tag, linestring_tag,
false, true, false,
Linestring, Box,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
>
{
static inline OutputIterator apply(Linestring const& linestring,
Box const& box, OutputIterator out, Strategy const& strategy)
{
typedef typename point_type<GeometryOut>::type point_type;
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
return detail::intersection::clip_range_with_box
<GeometryOut>(box, linestring, out, lb_strategy);
}
};
template
<
typename Segment, typename Box,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
segment_tag, box_tag, linestring_tag,
false, true, false,
Segment, Box,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
>
{
static inline OutputIterator apply(Segment const& segment,
Box const& box, OutputIterator out, Strategy const& strategy)
{
typedef boost::geometry::segment_range<Segment> range_type;
range_type range(segment);
typedef typename point_type<GeometryOut>::type point_type;
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
return detail::intersection::clip_range_with_box
<GeometryOut>(box, range, out, lb_strategy);
}
};
template
<
typename GeometryTag1, typename GeometryTag2, typename GeometryTag3,
bool Areal1, bool Areal2, bool ArealOut,
typename Tag1, typename Tag2, typename TagOut,
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename GeometryOut,
typename Strategy
>
struct intersection_inserter_reversed
struct intersection_reversed
{
static inline OutputIterator apply(Geometry1 const& g1,
Geometry2 const& g2, OutputIterator out,
Strategy const& strategy)
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
GeometryOut& geometry_out,
Strategy const& strategy)
{
return intersection_inserter
return intersection
<
GeometryTag2, GeometryTag1, GeometryTag3,
Areal2, Areal1, ArealOut,
Tag2, Tag1, TagOut,
Geometry2, Geometry1,
Reverse2, Reverse1, ReverseOut,
OutputIterator, GeometryOut,
Strategy
>::apply(g2, g1, out, strategy);
GeometryOut, Strategy
>::apply(geometry2, geometry1, geometry_out, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace intersection
{
template
<
typename GeometryOut,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename Geometry1, typename Geometry2,
typename OutputIterator,
typename Strategy
>
inline OutputIterator inserter(Geometry1 const& geometry1,
Geometry2 const& geometry2,
OutputIterator out,
Strategy const& strategy)
{
return boost::mpl::if_c
<
geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
geometry::dispatch::intersection_inserter_reversed
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
////point_order<Geometry1>::value,
////point_order<Geometry2>::value,
////point_order<GeometryOut>::value,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<GeometryOut>::value,
Geometry1, Geometry2,
overlay::do_reverse<geometry::point_order<Geometry1>::value, Reverse1>::value,
overlay::do_reverse<geometry::point_order<Geometry2>::value, Reverse2>::value,
ReverseOut,
OutputIterator, GeometryOut,
Strategy
>,
geometry::dispatch::intersection_inserter
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
////point_order<Geometry1>::value,
///point_order<Geometry2>::value,
///point_order<GeometryOut>::value,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<GeometryOut>::value,
Geometry1, Geometry2,
overlay::do_reverse<geometry::point_order<Geometry1>::value, Reverse1>::value,
overlay::do_reverse<geometry::point_order<Geometry2>::value, Reverse2>::value,
ReverseOut,
OutputIterator, GeometryOut,
Strategy
>
>::type::apply(geometry1, geometry2, out, strategy);
}
}} // namespace detail::intersection
#endif // DOXYGEN_NO_DETAIL
/*!
\brief \brief_calc2{intersection} \brief_strategy
\ingroup intersection
\details \details_calc2{intersection_inserter, spatial set theoretic intersection}
\brief_strategy. \details_inserter{intersection}
\tparam GeometryOut \tparam_geometry{\p_l_or_c}
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam OutputIterator \tparam_out{\p_l_or_c}
\tparam Strategy Compound strategy for intersection
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param out \param_out{intersection}
\param strategy The strategy
\return \return_out
\qbk{distinguish,with strategy}
\qbk{behavior,[qbk_out __point__]:Calculates intersection points of input geometries}
\qbk{behavior,[qbk_out __linestring__]:Calculates intersection linestrings of input geometries (NYI)}
\qbk{behavior,[qbk_out __polygon__]:Calculates intersection polygons input (multi)polygons and/or boxes}
*/
template
<
typename GeometryOut,
typename Geometry1,
typename Geometry2,
typename OutputIterator,
typename Strategy
>
inline OutputIterator intersection_inserter(Geometry1 const& geometry1,
Geometry2 const& geometry2,
OutputIterator out,
Strategy const& strategy)
{
concept::check<Geometry1 const>();
concept::check<Geometry2 const>();
return detail::intersection::inserter<GeometryOut, false, false, true>(
geometry1, geometry2, out, strategy);
}
/*!
\brief \brief_calc2{intersection}
\ingroup intersection
\details \details_calc2{intersection_inserter, spatial set theoretic intersection}. \details_inserter{intersection}
\tparam GeometryOut \tparam_geometry{\p_l_or_c}
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam OutputIterator \tparam_out{\p_l_or_c}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param out \param_out{intersection}
\return \return_out
\qbk{example,intersection_segment_inserter}
*/
template
<
typename GeometryOut,
typename Geometry1,
typename Geometry2,
typename OutputIterator
>
inline OutputIterator intersection_inserter(Geometry1 const& geometry1,
Geometry2 const& geometry2,
OutputIterator out)
{
concept::check<Geometry1 const>();
concept::check<Geometry2 const>();
typedef strategy_intersection
<
typename cs_tag<GeometryOut>::type,
Geometry1,
Geometry2,
typename geometry::point_type<GeometryOut>::type
> strategy;
return intersection_inserter<GeometryOut>(geometry1, geometry2, out,
strategy());
}
/*!
\brief \brief_calc2{intersection}
\ingroup intersection
@@ -486,30 +191,42 @@ template
<
typename Geometry1,
typename Geometry2,
typename Collection
typename GeometryOut
>
inline void intersection(Geometry1 const& geometry1,
inline bool intersection(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Collection& output_collection)
GeometryOut& geometry_out)
{
concept::check<Geometry1 const>();
concept::check<Geometry2 const>();
typedef typename boost::range_value<Collection>::type geometry_out;
concept::check<geometry_out>();
typedef strategy_intersection
<
typename cs_tag<geometry_out>::type,
typename cs_tag<Geometry1>::type,
Geometry1,
Geometry2,
typename geometry::point_type<geometry_out>::type
typename geometry::point_type<Geometry1>::type
> strategy;
intersection_inserter<geometry_out>(geometry1, geometry2,
std::back_inserter(output_collection),
strategy());
return boost::mpl::if_c
<
geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
dispatch::intersection_reversed
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
Geometry1, Geometry2, GeometryOut, strategy
>,
dispatch::intersection
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
Geometry1, Geometry2, GeometryOut, strategy
>
>::type::apply(geometry1, geometry2, geometry_out, strategy());
}

View File

@@ -0,0 +1,486 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
//
// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
// Copyright Bruno Lalande 2008, 2009
// 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_INTERSECTION_INSERTER_HPP
#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_INSERTER_HPP
#include <cstddef>
#include <boost/mpl/if.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/range/metafunctions.hpp>
#include <boost/geometry/core/is_areal.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/overlay/clip_linestring.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/ranges/segment_range.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace intersection
{
template
<
typename Segment1, typename Segment2,
typename OutputIterator, typename PointOut,
typename Strategy
>
struct intersection_segment_segment_point
{
static inline OutputIterator apply(Segment1 const& segment1,
Segment2 const& segment2, OutputIterator out,
Strategy const& strategy)
{
typedef typename point_type<PointOut>::type point_type;
// Get the intersection point (or two points)
segment_intersection_points<point_type> is
= strategy::intersection::relate_cartesian_segments
<
policies::relate::segments_intersection_points
<
Segment1,
Segment2,
segment_intersection_points<point_type>
>
>::apply(segment1, segment2);
for (std::size_t i = 0; i < is.count; i++)
{
PointOut p;
geometry::copy_coordinates(is.intersections[i], p);
*out++ = p;
}
return out;
}
};
template
<
typename Linestring1, typename Linestring2,
typename OutputIterator, typename PointOut,
typename Strategy
>
struct intersection_linestring_linestring_point
{
static inline OutputIterator apply(Linestring1 const& linestring1,
Linestring2 const& linestring2, OutputIterator out,
Strategy const& strategy)
{
typedef typename point_type<PointOut>::type point_type;
typedef detail::overlay::turn_info<point_type> turn_info;
std::deque<turn_info> turns;
geometry::get_intersection_points(linestring1, linestring2, turns);
for (typename boost::range_iterator<std::deque<turn_info> const>::type
it = boost::begin(turns); it != boost::end(turns); ++it)
{
PointOut p;
geometry::copy_coordinates(it->point, p);
*out++ = p;
}
return out;
}
};
}} // namespace detail::intersection
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{
template
<
// tag dispatching:
typename TagIn1, typename TagIn2, typename TagOut,
// orientation
// metafunction finetuning helpers:
bool Areal1, bool Areal2, bool ArealOut,
// real types
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
typename Strategy
>
struct intersection_inserter
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES_OR_ORIENTATIONS
, (types<Geometry1, Geometry2, GeometryOut>)
);
};
template
<
typename TagIn1, typename TagIn2, typename TagOut,
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
TagIn1, TagIn2, TagOut,
true, true, true,
Geometry1, Geometry2,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
> : detail::overlay::overlay
<Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, OutputIterator, GeometryOut, -1, Strategy>
{};
// Any areal type with box:
template
<
typename TagIn, typename TagOut,
typename Geometry, typename Box,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
TagIn, box_tag, TagOut,
true, true, true,
Geometry, Box,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
> : detail::overlay::overlay
<Geometry, Box, Reverse1, Reverse2, ReverseOut, OutputIterator, GeometryOut, -1, Strategy>
{};
/*// box/box
template
<
typename Box1, typename Box2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator,
typename BoxOut,
typename Strategy
>
struct intersection_inserter
<
box_tag, box_tag, box_tag,
true, true, true,
Box1, Box2,
Reverse1, Reverse2, ReverseOut,
OutputIterator, BoxOut,
Strategy
> : detail::intersection::intersection_box_box
<Box1, Box2, OutputIterator, BoxOut, Strategy>
{};
*/
template
<
typename Segment1, typename Segment2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
segment_tag, segment_tag, point_tag,
false, false, false,
Segment1, Segment2,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
> : detail::intersection::intersection_segment_segment_point
<
Segment1, Segment2,
OutputIterator, GeometryOut,
Strategy
>
{};
template
<
typename Linestring1, typename Linestring2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
linestring_tag, linestring_tag, point_tag,
false, false, false,
Linestring1, Linestring2,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
> : detail::intersection::intersection_linestring_linestring_point
<
Linestring1, Linestring2,
OutputIterator, GeometryOut,
Strategy
>
{};
template
<
typename Linestring, typename Box,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
linestring_tag, box_tag, linestring_tag,
false, true, false,
Linestring, Box,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
>
{
static inline OutputIterator apply(Linestring const& linestring,
Box const& box, OutputIterator out, Strategy const& strategy)
{
typedef typename point_type<GeometryOut>::type point_type;
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
return detail::intersection::clip_range_with_box
<GeometryOut>(box, linestring, out, lb_strategy);
}
};
template
<
typename Segment, typename Box,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Strategy
>
struct intersection_inserter
<
segment_tag, box_tag, linestring_tag,
false, true, false,
Segment, Box,
Reverse1, Reverse2, ReverseOut,
OutputIterator, GeometryOut,
Strategy
>
{
static inline OutputIterator apply(Segment const& segment,
Box const& box, OutputIterator out, Strategy const& strategy)
{
typedef boost::geometry::segment_range<Segment> range_type;
range_type range(segment);
typedef typename point_type<GeometryOut>::type point_type;
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
return detail::intersection::clip_range_with_box
<GeometryOut>(box, range, out, lb_strategy);
}
};
template
<
typename GeometryTag1, typename GeometryTag2, typename GeometryTag3,
bool Areal1, bool Areal2, bool ArealOut,
typename Geometry1, typename Geometry2,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename OutputIterator, typename GeometryOut,
typename Strategy
>
struct intersection_inserter_reversed
{
static inline OutputIterator apply(Geometry1 const& g1,
Geometry2 const& g2, OutputIterator out,
Strategy const& strategy)
{
return intersection_inserter
<
GeometryTag2, GeometryTag1, GeometryTag3,
Areal2, Areal1, ArealOut,
Geometry2, Geometry1,
Reverse2, Reverse1, ReverseOut,
OutputIterator, GeometryOut,
Strategy
>::apply(g2, g1, out, strategy);
}
};
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace intersection
{
template
<
typename GeometryOut,
bool Reverse1, bool Reverse2, bool ReverseOut,
typename Geometry1, typename Geometry2,
typename OutputIterator,
typename Strategy
>
inline OutputIterator inserter(Geometry1 const& geometry1,
Geometry2 const& geometry2,
OutputIterator out,
Strategy const& strategy)
{
return boost::mpl::if_c
<
geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
geometry::dispatch::intersection_inserter_reversed
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<GeometryOut>::value,
Geometry1, Geometry2,
overlay::do_reverse<geometry::point_order<Geometry1>::value, Reverse1>::value,
overlay::do_reverse<geometry::point_order<Geometry2>::value, Reverse2>::value,
ReverseOut,
OutputIterator, GeometryOut,
Strategy
>,
geometry::dispatch::intersection_inserter
<
typename geometry::tag<Geometry1>::type,
typename geometry::tag<Geometry2>::type,
typename geometry::tag<GeometryOut>::type,
geometry::is_areal<Geometry1>::value,
geometry::is_areal<Geometry2>::value,
geometry::is_areal<GeometryOut>::value,
Geometry1, Geometry2,
overlay::do_reverse<geometry::point_order<Geometry1>::value, Reverse1>::value,
overlay::do_reverse<geometry::point_order<Geometry2>::value, Reverse2>::value,
ReverseOut,
OutputIterator, GeometryOut,
Strategy
>
>::type::apply(geometry1, geometry2, out, strategy);
}
}} // namespace detail::intersection
#endif // DOXYGEN_NO_DETAIL
/*!
\brief \brief_calc2{intersection} \brief_strategy
\ingroup intersection
\details \details_calc2{intersection_inserter, spatial set theoretic intersection}
\brief_strategy. \details_inserter{intersection}
\tparam GeometryOut \tparam_geometry{\p_l_or_c}
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam OutputIterator \tparam_out{\p_l_or_c}
\tparam Strategy Compound strategy for intersection
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param out \param_out{intersection}
\param strategy The strategy
\return \return_out
\qbk{distinguish,with strategy}
\qbk{behavior,[qbk_out __point__]:Calculates intersection points of input geometries}
\qbk{behavior,[qbk_out __linestring__]:Calculates intersection linestrings of input geometries (NYI)}
\qbk{behavior,[qbk_out __polygon__]:Calculates intersection polygons input (multi)polygons and/or boxes}
*/
template
<
typename GeometryOut,
typename Geometry1,
typename Geometry2,
typename OutputIterator,
typename Strategy
>
inline OutputIterator intersection_inserter(Geometry1 const& geometry1,
Geometry2 const& geometry2,
OutputIterator out,
Strategy const& strategy)
{
concept::check<Geometry1 const>();
concept::check<Geometry2 const>();
return detail::intersection::inserter<GeometryOut, false, false, true>(
geometry1, geometry2, out, strategy);
}
/*!
\brief \brief_calc2{intersection}
\ingroup intersection
\details \details_calc2{intersection_inserter, spatial set theoretic intersection}. \details_inserter{intersection}
\tparam GeometryOut \tparam_geometry{\p_l_or_c}
\tparam Geometry1 \tparam_geometry
\tparam Geometry2 \tparam_geometry
\tparam OutputIterator \tparam_out{\p_l_or_c}
\param geometry1 \param_geometry
\param geometry2 \param_geometry
\param out \param_out{intersection}
\return \return_out
\qbk{example,intersection_segment_inserter}
*/
template
<
typename GeometryOut,
typename Geometry1,
typename Geometry2,
typename OutputIterator
>
inline OutputIterator intersection_inserter(Geometry1 const& geometry1,
Geometry2 const& geometry2,
OutputIterator out)
{
concept::check<Geometry1 const>();
concept::check<Geometry2 const>();
typedef strategy_intersection
<
typename cs_tag<GeometryOut>::type,
Geometry1,
Geometry2,
typename geometry::point_type<GeometryOut>::type
> strategy;
return intersection_inserter<GeometryOut>(geometry1, geometry2, out,
strategy());
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_INSERTER_HPP

View File

@@ -11,6 +11,7 @@
#define BOOST_GEOMETRY_CORE_COORDINATE_SYSTEM_HPP
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -22,16 +23,22 @@ namespace boost { namespace geometry
namespace traits
{
/*!
\brief Traits class defining the coordinate system of a point, important for strategy selection
\ingroup traits
\par Geometries:
- point
\par Specializations should provide:
- typedef CS type; (cs::cartesian, cs::spherical, etc)
*/
template <typename P>
struct coordinate_system {};
/*!
\brief Traits class defining the coordinate system of a point, important for strategy selection
\ingroup traits
\par Geometries:
- point
\par Specializations should provide:
- typedef CS type; (cs::cartesian, cs::spherical, etc)
*/
template <typename Point>
struct coordinate_system
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Point>)
);
};
} // namespace traits

View File

@@ -10,6 +10,7 @@
#define BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/geometry/core/point_type.hpp>
@@ -30,8 +31,14 @@ namespace traits
\par Specializations should provide:
- typedef T type; (double,float,int,etc)
*/
template <typename P>
struct coordinate_type {};
template <typename Point>
struct coordinate_type
{
BOOST_MPL_ASSERT_MSG
(
false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Point>)
);
};
} // namespace traits

View File

@@ -29,6 +29,7 @@
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/geometry_id.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -692,20 +693,21 @@ Small example showing how to use read_wkt with an output iterator
\line {
\until }
*/
template <typename Point, typename OutputIterator>
template <typename Geometry, typename OutputIterator>
inline void read_wkt(std::string const& wkt, OutputIterator out)
{
geometry::concept::check<Point>();
geometry::concept::check<Geometry>();
// Todo: maybe take this from the string, or do not call initialize, such that
// any coordinate string is parsed and outputted
std::string const& tag = "linestring";
typedef typename point_type<Geometry>::type point_type;
std::string const& tag =
geometry_id<Geometry>::value == 2 ? "linestring" : "polygon";
detail::wkt::tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
detail::wkt::tokenizer::iterator it;
if (detail::wkt::initialize<Point>(tokens, tag, wkt, it))
if (detail::wkt::initialize<point_type>(tokens, tag, wkt, it))
{
detail::wkt::container_inserter<Point>::apply(it, tokens.end(), wkt, out);
detail::wkt::container_inserter<point_type>::apply(it, tokens.end(), wkt, out);
}
}