Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r73321 - in trunk/boost/geometry: algorithms multi/algorithms
From: barend.gehrels_at_[hidden]
Date: 2011-07-24 05:39:51


Author: barendgehrels
Date: 2011-07-24 05:39:47 EDT (Sun, 24 Jul 2011)
New Revision: 73321
URL: http://svn.boost.org/trac/boost/changeset/73321

Log:
Supported convert (and therefore also assign) for many (the most useful) other combinations now (e.g. polygon/polygon with different point-types)
Added:
   trunk/boost/geometry/multi/algorithms/convert.hpp (contents, props changed)
Text files modified:
   trunk/boost/geometry/algorithms/assign.hpp | 134 ++--------------------
   trunk/boost/geometry/algorithms/convert.hpp | 231 ++++++++++++++++++++++++++++++---------
   2 files changed, 194 insertions(+), 171 deletions(-)

Modified: trunk/boost/geometry/algorithms/assign.hpp
==============================================================================
--- trunk/boost/geometry/algorithms/assign.hpp (original)
+++ trunk/boost/geometry/algorithms/assign.hpp 2011-07-24 05:39:47 EDT (Sun, 24 Jul 2011)
@@ -25,6 +25,8 @@
 #include <boost/numeric/conversion/cast.hpp>
 #include <boost/type_traits.hpp>
 
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
 #include <boost/geometry/algorithms/detail/assign_values.hpp>
 #include <boost/geometry/algorithms/convert.hpp>
 
@@ -122,124 +124,6 @@
>::apply(geometry);
 }
 
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail
-{
-// Note: this is moved to namespace detail because the names and parameter orders
-// are not yet 100% clear.
-
-/*!
-\brief Assign the four points of a 2D box
-\ingroup assign
-\note The order is crucial. Most logical is LOWER, UPPER and sub-order LEFT, RIGHT
- so this is how it is implemented.
-\tparam Box \tparam_box
-\tparam Point \tparam_point
-\param box \param_box
-\param lower_left point being assigned to lower left coordinates of the box
-\param lower_right point being assigned to lower right coordinates of the box
-\param upper_left point being assigned to upper left coordinates of the box
-\param upper_right point being assigned to upper right coordinates of the box
-
-\qbk{
-[heading Example]
-[assign_box_corners] [assign_box_corners_output]
-}
-*/
-template <typename Box, typename Point>
-inline void assign_box_corners(Box const& box,
- Point& lower_left, Point& lower_right,
- Point& upper_left, Point& upper_right)
-{
- concept::check<Box const>();
- concept::check<Point>();
-
- detail::assign::assign_box_2d_corner
- <min_corner, min_corner>(box, lower_left);
- detail::assign::assign_box_2d_corner
- <max_corner, min_corner>(box, lower_right);
- detail::assign::assign_box_2d_corner
- <min_corner, max_corner>(box, upper_left);
- detail::assign::assign_box_2d_corner
- <max_corner, max_corner>(box, upper_right);
-}
-
-template <bool Reverse, typename Box, typename Range>
-inline void assign_box_corners_oriented(Box const& box, Range& corners)
-{
- if (Reverse)
- {
- // make counterclockwise ll,lr,ur,ul
- assign_box_corners(box, corners[0], corners[1], corners[3], corners[2]);
- }
- else
- {
- // make clockwise ll,ul,ur,lr
- assign_box_corners(box, corners[0], corners[3], corners[1], corners[2]);
- }
-}
-
-
-/*!
-\brief Assign a box or segment with the value of a point
-\ingroup assign
-\tparam Index indicates which box-corner, min_corner (0) or max_corner (1)
- or which point of segment (0/1)
-\tparam Point \tparam_point
-\tparam Geometry \tparam_box_or_segment
-\param point \param_point
-\param geometry \param_box_or_segment
-
-\qbk{
-[heading Example]
-[assign_point_to_index] [assign_point_to_index_output]
-}
-*/
-template <std::size_t Index, typename Geometry, typename Point>
-inline void assign_point_to_index(Point const& point, Geometry& geometry)
-{
- concept::check<Point const>();
- concept::check<Geometry>();
-
- detail::assign::assign_point_to_index
- <
- Geometry, Point, Index, 0, dimension<Geometry>::type::value
- >::apply(point, geometry);
-}
-
-
-/*!
-\brief Assign a point with a point of a box or segment
-\ingroup assign
-\tparam Index indicates which box-corner, min_corner (0) or max_corner (1)
- or which point of segment (0/1)
-\tparam Geometry \tparam_box_or_segment
-\tparam Point \tparam_point
-\param geometry \param_box_or_segment
-\param point \param_point
-
-\qbk{
-[heading Example]
-[assign_point_from_index] [assign_point_from_index_output]
-}
-*/
-template <std::size_t Index, typename Point, typename Geometry>
-inline void assign_point_from_index(Geometry const& geometry, Point& point)
-{
- concept::check<Geometry const>();
- concept::check<Point>();
-
- detail::assign::assign_point_from_index
- <
- Geometry, Point, Index, 0, dimension<Geometry>::type::value
- >::apply(geometry, point);
-}
-
-} // namespace detail
-#endif // DOXYGEN_NO_DETAIL
-
-
 /*!
 \brief Assigns one geometry to another geometry
 \details The assign algorithm assigns one geometry, e.g. a BOX, to another geometry, e.g. a RING. This only
@@ -263,8 +147,22 @@
 {
     concept::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();
 
+ BOOST_MPL_ASSERT_MSG
+ (
+ (point_order<Geometry1>::value == point_order<Geometry2>::value),
+ ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER
+ , (types<Geometry1, Geometry2>)
+ );
+ BOOST_MPL_ASSERT_MSG
+ (
+ (closure<Geometry1>::value == closure<Geometry2>::value),
+ ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_CLOSURE
+ , (types<Geometry1, Geometry2>)
+ );
+
     dispatch::convert
         <
+ false,
             typename tag<Geometry2>::type,
             typename tag<Geometry1>::type,
             dimension<Geometry1>::type::value,

Modified: trunk/boost/geometry/algorithms/convert.hpp
==============================================================================
--- trunk/boost/geometry/algorithms/convert.hpp (original)
+++ trunk/boost/geometry/algorithms/convert.hpp 2011-07-24 05:39:47 EDT (Sun, 24 Jul 2011)
@@ -11,8 +11,8 @@
 // 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_CONVERT_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_HPP
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
 
 
 #include <cstddef>
@@ -25,9 +25,16 @@
 #include <boost/geometry/algorithms/clear.hpp>
 #include <boost/geometry/algorithms/for_each.hpp>
 #include <boost/geometry/algorithms/detail/assign_values.hpp>
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
 
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
 #include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/point_order.hpp>
 #include <boost/geometry/geometries/concepts/check.hpp>
 
 
@@ -76,6 +83,123 @@
     {}
 };
 
+template <typename Box, typename Range, bool Close, bool Reverse>
+struct box_to_range
+{
+ static inline void apply(Box const& box, Range& range)
+ {
+ traits::resize<Range>::apply(range, Close ? 5 : 4);
+ assign_box_corners_oriented<Reverse>(box, range);
+ if (Close)
+ {
+ range[4] = range[0];
+ }
+ }
+};
+
+template <typename Segment, typename Range>
+struct segment_to_range
+{
+ static inline void apply(Segment const& segment, Range& range)
+ {
+ traits::resize<Range>::apply(range, 2);
+
+ typename boost::range_iterator<Range>::type it = boost::begin(range);
+
+ assign_point_from_index<0>(segment, *it);
+ ++it;
+ assign_point_from_index<1>(segment, *it);
+ }
+};
+
+template
+<
+ typename Range1,
+ typename Range2,
+ bool Reverse = false
+>
+struct range_to_range
+{
+ typedef typename reversible_view
+ <
+ Range1 const,
+ Reverse ? iterate_reverse : iterate_forward
+ >::type rview_type;
+ typedef typename closeable_view
+ <
+ rview_type const,
+ geometry::closure<Range1>::value
+ >::type view_type;
+
+ static inline void apply(Range1 const& source, Range2& destination)
+ {
+ geometry::clear(destination);
+
+ rview_type rview(source);
+
+ // We consider input always as closed, and skip last
+ // point for open output.
+ view_type view(rview);
+
+ int n = boost::size(view);
+ if (geometry::closure<Range2>::value == geometry::open)
+ {
+ n--;
+ }
+
+ int i = 0;
+ for (typename boost::range_iterator<view_type const>::type it
+ = boost::begin(view);
+ it != boost::end(view) && i < n;
+ ++it, ++i)
+ {
+ geometry::append(destination, *it);
+ }
+ }
+};
+
+template <typename Polygon1, typename Polygon2>
+struct polygon_to_polygon
+{
+ typedef range_to_range
+ <
+ typename geometry::ring_type<Polygon1>::type,
+ typename geometry::ring_type<Polygon2>::type,
+ geometry::point_order<Polygon1>::value
+ != geometry::point_order<Polygon2>::value
+ > per_ring;
+
+ static inline void apply(Polygon1 const& source, Polygon2& destination)
+ {
+ // Clearing managed per ring, and in the resizing of interior rings
+
+ per_ring::apply(geometry::exterior_ring(source),
+ geometry::exterior_ring(destination));
+
+ // Container should be resizeable
+ traits::resize
+ <
+ typename boost::remove_reference
+ <
+ typename traits::interior_mutable_type<Polygon2>::type
+ >::type
+ >::apply(interior_rings(destination), num_interior_rings(source));
+
+ typename interior_return_type<Polygon1 const>::type rings_source
+ = interior_rings(source);
+ typename interior_return_type<Polygon2>::type rings_dest
+ = interior_rings(destination);
+
+ BOOST_AUTO_TPL(it_source, boost::begin(rings_source));
+ BOOST_AUTO_TPL(it_dest, boost::begin(rings_dest));
+
+ for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)
+ {
+ per_ring::apply(*it_source, *it_dest);
+ }
+ }
+};
+
 
 }} // namespace detail::conversion
 #endif // DOXYGEN_NO_DETAIL
@@ -87,12 +211,18 @@
 
 template
 <
+ bool UseAssignment,
     typename Tag1, typename Tag2,
     std::size_t DimensionCount,
     typename Geometry1, typename Geometry2
>
 struct convert
 {
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES
+ , (types<Geometry1, Geometry2>)
+ );
 };
 
 
@@ -102,10 +232,9 @@
     std::size_t DimensionCount,
     typename Geometry1, typename Geometry2
>
-struct convert<Tag, Tag, DimensionCount, Geometry1, Geometry2>
+struct convert<true, Tag, Tag, DimensionCount, Geometry1, Geometry2>
 {
- // Same geometry type -> copy coordinates from G1 to G2
- // Actually: we try now to just copy it
+ // Same geometry type -> copy whole geometry
     static inline void apply(Geometry1 const& source, Geometry2& destination)
     {
         destination = source;
@@ -118,57 +247,51 @@
     std::size_t DimensionCount,
     typename Geometry1, typename Geometry2
>
-struct convert<point_tag, point_tag, DimensionCount, Geometry1, Geometry2>
+struct convert<false, point_tag, point_tag, DimensionCount, Geometry1, Geometry2>
     : detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>
 {};
 
+template <std::size_t DimensionCount, typename Segment, typename LineString>
+struct convert<false, segment_tag, linestring_tag, DimensionCount, Segment, LineString>
+ : detail::conversion::segment_to_range<Segment, LineString>
+{};
 
-template <std::size_t DimensionCount, typename Ring1, typename Ring2>
-struct convert<ring_tag, ring_tag, DimensionCount, Ring1, Ring2>
-{
- static inline void apply(Ring1 const& source, Ring2& destination)
- {
- geometry::clear(destination);
- for (typename boost::range_iterator<Ring1 const>::type it
- = boost::begin(source);
- it != boost::end(source);
- ++it)
- {
- geometry::append(destination, *it);
- }
- }
-};
-
-
-template <typename Box, typename Ring>
-struct convert<box_tag, ring_tag, 2, Box, Ring>
-{
- static inline void apply(Box const& box, Ring& ring)
- {
- // go from box to ring -> add coordinates in correct order
- geometry::clear(ring);
- typename point_type<Box>::type point;
-
- geometry::assign_values(point, get<min_corner, 0>(box), get<min_corner, 1>(box));
- geometry::append(ring, point);
 
- geometry::assign_values(point, get<min_corner, 0>(box), get<max_corner, 1>(box));
- geometry::append(ring, point);
+template <std::size_t DimensionCount, typename Ring1, typename Ring2>
+struct convert<false, ring_tag, ring_tag, DimensionCount, Ring1, Ring2>
+ : detail::conversion::range_to_range
+ <
+ Ring1,
+ Ring2,
+ geometry::point_order<Ring1>::value
+ != geometry::point_order<Ring2>::value
+ >
+{};
 
- geometry::assign_values(point, get<max_corner, 0>(box), get<max_corner, 1>(box));
- geometry::append(ring, point);
+template <std::size_t DimensionCount, typename LineString1, typename LineString2>
+struct convert<false, linestring_tag, linestring_tag, DimensionCount, LineString1, LineString2>
+ : detail::conversion::range_to_range<LineString1, LineString2>
+{};
 
- geometry::assign_values(point, get<max_corner, 0>(box), get<min_corner, 1>(box));
- geometry::append(ring, point);
+template <std::size_t DimensionCount, typename Polygon1, typename Polygon2>
+struct convert<false, polygon_tag, polygon_tag, DimensionCount, Polygon1, Polygon2>
+ : detail::conversion::polygon_to_polygon<Polygon1, Polygon2>
+{};
 
- geometry::assign_values(point, get<min_corner, 0>(box), get<min_corner, 1>(box));
- geometry::append(ring, point);
- }
-};
+template <typename Box, typename Ring>
+struct convert<false, box_tag, ring_tag, 2, Box, Ring>
+ : detail::conversion::box_to_range
+ <
+ Box,
+ Ring,
+ geometry::closure<Ring>::value == closed,
+ geometry::point_order<Ring>::value == counterclockwise
+ >
+{};
 
 
 template <typename Box, typename Polygon>
-struct convert<box_tag, polygon_tag, 2, Box, Polygon>
+struct convert<false, box_tag, polygon_tag, 2, Box, Polygon>
 {
     static inline void apply(Box const& box, Polygon& polygon)
     {
@@ -176,7 +299,7 @@
 
         convert
             <
- box_tag, ring_tag,
+ false, box_tag, ring_tag,
                 2, Box, ring_type
>::apply(box, exterior_ring(polygon));
     }
@@ -184,7 +307,7 @@
 
 
 template <typename Point, std::size_t DimensionCount, typename Box>
-struct convert<point_tag, box_tag, DimensionCount, Point, Box>
+struct convert<false, point_tag, box_tag, DimensionCount, Point, Box>
 {
     static inline void apply(Point const& point, Box& box)
     {
@@ -201,14 +324,14 @@
 
 
 template <typename Ring, std::size_t DimensionCount, typename Polygon>
-struct convert<ring_tag, polygon_tag, DimensionCount, Ring, Polygon>
+struct convert<false, ring_tag, polygon_tag, DimensionCount, Ring, Polygon>
 {
     static inline void apply(Ring const& ring, Polygon& polygon)
     {
         typedef typename ring_type<Polygon>::type ring_type;
         convert
             <
- ring_tag, ring_tag, DimensionCount,
+ false, ring_tag, ring_tag, DimensionCount,
                 Ring, ring_type
>::apply(ring, exterior_ring(polygon));
     }
@@ -216,7 +339,7 @@
 
 
 template <typename Polygon, std::size_t DimensionCount, typename Ring>
-struct convert<polygon_tag, ring_tag, DimensionCount, Polygon, Ring>
+struct convert<false, polygon_tag, ring_tag, DimensionCount, Polygon, Ring>
 {
     static inline void apply(Polygon const& polygon, Ring& ring)
     {
@@ -224,6 +347,7 @@
 
         convert
             <
+ false,
                 ring_tag, ring_tag, DimensionCount,
                 ring_type, Ring
>::apply(exterior_ring(polygon), ring);
@@ -254,8 +378,9 @@
 
     dispatch::convert
         <
- typename tag<Geometry1>::type,
- typename tag<Geometry2>::type,
+ boost::is_same<Geometry1, Geometry2>::value, // && boost::has_assign<Geometry2>::value,
+ typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
+ typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
             dimension<Geometry1>::type::value,
             Geometry1,
             Geometry2
@@ -266,4 +391,4 @@
 }} // namespace boost::geometry
 
 
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_HPP
+#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP

Added: trunk/boost/geometry/multi/algorithms/convert.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/geometry/multi/algorithms/convert.hpp 2011-07-24 05:39:47 EDT (Sun, 24 Jul 2011)
@@ -0,0 +1,133 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/convert.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace conversion
+{
+
+template <typename Single, typename Multi, typename Policy>
+struct single_to_multi
+{
+ static inline void apply(Single const& single, Multi& multi)
+ {
+ traits::resize<Multi>::apply(multi, 1);
+ Policy::apply(single, *boost::begin(multi));
+ }
+};
+
+
+
+template <typename Multi1, typename Multi2, typename Policy>
+struct multi_to_multi
+{
+ static inline void apply(Multi1 const& multi1, Multi2& multi2)
+ {
+ traits::resize<Multi2>::apply(multi2, boost::size(multi1));
+
+ typename boost::range_iterator<Multi1 const>::type it1
+ = boost::begin(multi1);
+ typename boost::range_iterator<Multi2>::type it2
+ = boost::begin(multi2);
+
+ for (; it1 != boost::end(multi1); ++it1, ++it2)
+ {
+ Policy::apply(*it1, *it2);
+ }
+ }
+};
+
+
+}} // namespace detail::convert
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// Dispatch for multi <-> multi, specifying their single-version as policy.
+// Note that, even if the multi-types are mutually different, their single
+// version types might be the same and therefore we call boost::is_same again
+
+template <std::size_t DimensionCount, typename Multi1, typename Multi2>
+struct convert<false, multi_tag, multi_tag, DimensionCount, Multi1, Multi2>
+ : detail::conversion::multi_to_multi
+ <
+ Multi1,
+ Multi2,
+ convert
+ <
+ boost::is_same
+ <
+ typename boost::range_value<Multi1>::type,
+ typename boost::range_value<Multi2>::type
+ >::value,
+ typename single_tag_of
+ <
+ typename tag<Multi1>::type
+ >::type,
+ typename single_tag_of
+ <
+ typename tag<Multi2>::type
+ >::type,
+ DimensionCount,
+ typename boost::range_value<Multi1>::type,
+ typename boost::range_value<Multi2>::type
+ >
+ >
+{};
+
+template <std::size_t DimensionCount, typename SingleTag, typename Single, typename Multi>
+struct convert<false, SingleTag, multi_tag, DimensionCount, Single, Multi>
+ : detail::conversion::single_to_multi
+ <
+ Single,
+ Multi,
+ convert
+ <
+ false,
+ typename tag<Single>::type,
+ typename single_tag_of
+ <
+ typename tag<Multi>::type
+ >::type,
+ DimensionCount,
+ Single,
+ typename boost::range_value<Multi>::type
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk