Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:35:22

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
0005 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
0006 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
0007 
0008 // This file was modified by Oracle on 2020-2023.
0009 // Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
0010 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
0011 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0012 
0013 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
0014 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
0015 
0016 // Use, modification and distribution is subject to the Boost Software License,
0017 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0018 // http://www.boost.org/LICENSE_1_0.txt)
0019 
0020 #ifndef BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
0021 #define BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
0022 
0023 #include <type_traits>
0024 
0025 #include <boost/range/begin.hpp>
0026 #include <boost/range/end.hpp>
0027 #include <boost/range/size.hpp>
0028 #include <boost/range/value_type.hpp>
0029 
0030 #include <boost/variant/static_visitor.hpp>
0031 #include <boost/variant/variant_fwd.hpp>
0032 
0033 #include <boost/geometry/algorithms/clear.hpp>
0034 #include "boost/geometry/algorithms/detail/assign_indexed_point.hpp"
0035 #include "boost/geometry/algorithms/detail/assign_values.hpp"
0036 #include <boost/geometry/algorithms/num_interior_rings.hpp>
0037 
0038 #include <boost/geometry/core/cs.hpp>
0039 #include <boost/geometry/core/exterior_ring.hpp>
0040 #include <boost/geometry/core/interior_rings.hpp>
0041 #include <boost/geometry/core/mutable_range.hpp>
0042 #include <boost/geometry/core/tag_cast.hpp>
0043 #include <boost/geometry/core/tags.hpp>
0044 #include <boost/geometry/geometries/concepts/check.hpp>
0045 #include <boost/geometry/strategies/default_strategy.hpp>
0046 #include <boost/geometry/strategies/transform.hpp>
0047 
0048 
0049 namespace boost { namespace geometry
0050 {
0051 
0052 #ifndef DOXYGEN_NO_DETAIL
0053 namespace detail { namespace transform
0054 {
0055 
0056 struct transform_point
0057 {
0058     template <typename Point1, typename Point2, typename Strategy>
0059     static inline bool apply(Point1 const& p1, Point2& p2,
0060                 Strategy const& strategy)
0061     {
0062         return strategy.apply(p1, p2);
0063     }
0064 };
0065 
0066 
0067 struct transform_box
0068 {
0069     template <typename Box1, typename Box2, typename Strategy>
0070     static inline bool apply(Box1 const& b1, Box2& b2,
0071                 Strategy const& strategy)
0072     {
0073         typedef typename point_type<Box1>::type point_type1;
0074         typedef typename point_type<Box2>::type point_type2;
0075 
0076         point_type1 lower_left, upper_right;
0077         geometry::detail::assign::assign_box_2d_corner<min_corner, min_corner>(
0078                     b1, lower_left);
0079         geometry::detail::assign::assign_box_2d_corner<max_corner, max_corner>(
0080                     b1, upper_right);
0081 
0082         point_type2 p1, p2;
0083         if (strategy.apply(lower_left, p1) && strategy.apply(upper_right, p2))
0084         {
0085             // Create a valid box and therefore swap if necessary
0086             typedef typename coordinate_type<point_type2>::type coordinate_type;
0087             coordinate_type x1 = geometry::get<0>(p1)
0088                     , y1  = geometry::get<1>(p1)
0089                     , x2  = geometry::get<0>(p2)
0090                     , y2  = geometry::get<1>(p2);
0091 
0092             if (x1 > x2) { std::swap(x1, x2); }
0093             if (y1 > y2) { std::swap(y1, y2); }
0094 
0095             geometry::set<min_corner, 0>(b2, x1);
0096             geometry::set<min_corner, 1>(b2, y1);
0097             geometry::set<max_corner, 0>(b2, x2);
0098             geometry::set<max_corner, 1>(b2, y2);
0099 
0100             return true;
0101         }
0102         return false;
0103     }
0104 };
0105 
0106 struct transform_box_or_segment
0107 {
0108     template <typename Geometry1, typename Geometry2, typename Strategy>
0109     static inline bool apply(Geometry1 const& source, Geometry2& target,
0110                 Strategy const& strategy)
0111     {
0112         typedef typename point_type<Geometry1>::type point_type1;
0113         typedef typename point_type<Geometry2>::type point_type2;
0114 
0115         point_type1 source_point[2];
0116         geometry::detail::assign_point_from_index<0>(source, source_point[0]);
0117         geometry::detail::assign_point_from_index<1>(source, source_point[1]);
0118 
0119         point_type2 target_point[2];
0120         if (strategy.apply(source_point[0], target_point[0])
0121             && strategy.apply(source_point[1], target_point[1]))
0122         {
0123             geometry::detail::assign_point_to_index<0>(target_point[0], target);
0124             geometry::detail::assign_point_to_index<1>(target_point[1], target);
0125             return true;
0126         }
0127         return false;
0128     }
0129 };
0130 
0131 
0132 template
0133 <
0134     typename PointOut,
0135     typename OutputIterator,
0136     typename Range,
0137     typename Strategy
0138 >
0139 inline bool transform_range_out(Range const& range,
0140     OutputIterator out, Strategy const& strategy)
0141 {
0142     PointOut point_out;
0143     for (auto it = boost::begin(range); it != boost::end(range); ++it)
0144     {
0145         if (! transform_point::apply(*it, point_out, strategy))
0146         {
0147             return false;
0148         }
0149         *out++ = point_out;
0150     }
0151     return true;
0152 }
0153 
0154 
0155 struct transform_polygon
0156 {
0157     template <typename Polygon1, typename Polygon2, typename Strategy>
0158     static inline bool apply(Polygon1 const& poly1, Polygon2& poly2,
0159                 Strategy const& strategy)
0160     {
0161         typedef typename point_type<Polygon2>::type point2_type;
0162 
0163         geometry::clear(poly2);
0164 
0165         if (!transform_range_out<point2_type>(geometry::exterior_ring(poly1),
0166                     range::back_inserter(geometry::exterior_ring(poly2)), strategy))
0167         {
0168             return false;
0169         }
0170 
0171         // Note: here a resizeable container is assumed.
0172         traits::resize
0173             <
0174                 typename std::remove_reference
0175                 <
0176                     typename traits::interior_mutable_type<Polygon2>::type
0177                 >::type
0178             >::apply(geometry::interior_rings(poly2),
0179                      geometry::num_interior_rings(poly1));
0180 
0181         auto const& rings1 = geometry::interior_rings(poly1);
0182         auto&& rings2 = geometry::interior_rings(poly2);
0183 
0184         auto it1 = boost::begin(rings1);
0185         auto it2 = boost::begin(rings2);
0186         for ( ; it1 != boost::end(rings1); ++it1, ++it2)
0187         {
0188             if ( ! transform_range_out<point2_type>(*it1,
0189                                                     range::back_inserter(*it2),
0190                                                     strategy) )
0191             {
0192                 return false;
0193             }
0194         }
0195 
0196         return true;
0197     }
0198 };
0199 
0200 
0201 template <typename Point1, typename Point2>
0202 struct select_strategy
0203 {
0204     typedef typename strategy::transform::services::default_strategy
0205         <
0206             typename cs_tag<Point1>::type,
0207             typename cs_tag<Point2>::type,
0208             typename coordinate_system<Point1>::type,
0209             typename coordinate_system<Point2>::type,
0210             dimension<Point1>::type::value,
0211             dimension<Point2>::type::value,
0212             typename point_type<Point1>::type,
0213             typename point_type<Point2>::type
0214         >::type type;
0215 };
0216 
0217 struct transform_range
0218 {
0219     template <typename Range1, typename Range2, typename Strategy>
0220     static inline bool apply(Range1 const& range1,
0221             Range2& range2, Strategy const& strategy)
0222     {
0223         typedef typename point_type<Range2>::type point_type;
0224 
0225         // Should NOT be done here!
0226         // geometry::clear(range2);
0227         return transform_range_out<point_type>(range1,
0228                 range::back_inserter(range2), strategy);
0229     }
0230 };
0231 
0232 
0233 /*!
0234     \brief Is able to transform any multi-geometry, calling the single-version as policy
0235 */
0236 template <typename Policy>
0237 struct transform_multi
0238 {
0239     template <typename Multi1, typename Multi2, typename S>
0240     static inline bool apply(Multi1 const& multi1, Multi2& multi2, S const& strategy)
0241     {
0242         traits::resize<Multi2>::apply(multi2, boost::size(multi1));
0243 
0244         auto it1 = boost::begin(multi1);
0245         auto it2 = boost::begin(multi2);
0246 
0247         for (; it1 != boost::end(multi1); ++it1, ++it2)
0248         {
0249             if (! Policy::apply(*it1, *it2, strategy))
0250             {
0251                 return false;
0252             }
0253         }
0254 
0255         return true;
0256     }
0257 };
0258 
0259 
0260 }} // namespace detail::transform
0261 #endif // DOXYGEN_NO_DETAIL
0262 
0263 
0264 #ifndef DOXYGEN_NO_DISPATCH
0265 namespace dispatch
0266 {
0267 
0268 template
0269 <
0270     typename Geometry1, typename Geometry2,
0271     typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
0272     typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type
0273 >
0274 struct transform {};
0275 
0276 template <typename Point1, typename Point2>
0277 struct transform<Point1, Point2, point_tag, point_tag>
0278     : detail::transform::transform_point
0279 {
0280 };
0281 
0282 
0283 template <typename Linestring1, typename Linestring2>
0284 struct transform
0285     <
0286         Linestring1, Linestring2,
0287         linestring_tag, linestring_tag
0288     >
0289     : detail::transform::transform_range
0290 {
0291 };
0292 
0293 template <typename Range1, typename Range2>
0294 struct transform<Range1, Range2, ring_tag, ring_tag>
0295     : detail::transform::transform_range
0296 {
0297 };
0298 
0299 template <typename Polygon1, typename Polygon2>
0300 struct transform<Polygon1, Polygon2, polygon_tag, polygon_tag>
0301     : detail::transform::transform_polygon
0302 {
0303 };
0304 
0305 template <typename Box1, typename Box2>
0306 struct transform<Box1, Box2, box_tag, box_tag>
0307     : detail::transform::transform_box
0308 {
0309 };
0310 
0311 template <typename Segment1, typename Segment2>
0312 struct transform<Segment1, Segment2, segment_tag, segment_tag>
0313     : detail::transform::transform_box_or_segment
0314 {
0315 };
0316 
0317 template <typename Multi1, typename Multi2>
0318 struct transform
0319     <
0320         Multi1, Multi2,
0321         multi_tag, multi_tag
0322     >
0323     : detail::transform::transform_multi
0324         <
0325             dispatch::transform
0326                 <
0327                     typename boost::range_value<Multi1>::type,
0328                     typename boost::range_value<Multi2>::type
0329                 >
0330         >
0331 {};
0332 
0333 
0334 } // namespace dispatch
0335 #endif // DOXYGEN_NO_DISPATCH
0336 
0337 
0338 namespace resolve_strategy {
0339 
0340 struct transform
0341 {
0342     template <typename Geometry1, typename Geometry2, typename Strategy>
0343     static inline bool apply(Geometry1 const& geometry1,
0344                              Geometry2& geometry2,
0345                              Strategy const& strategy)
0346     {
0347         concepts::check<Geometry1 const>();
0348         concepts::check<Geometry2>();
0349 
0350         return dispatch::transform<Geometry1, Geometry2>::apply(
0351             geometry1,
0352             geometry2,
0353             strategy
0354         );
0355     }
0356 
0357     template <typename Geometry1, typename Geometry2>
0358     static inline bool apply(Geometry1 const& geometry1,
0359                              Geometry2& geometry2,
0360                              default_strategy)
0361     {
0362         return apply(
0363             geometry1,
0364             geometry2,
0365             typename detail::transform::select_strategy<Geometry1, Geometry2>::type()
0366         );
0367     }
0368 };
0369 
0370 } // namespace resolve_strategy
0371 
0372 
0373 namespace resolve_variant {
0374 
0375 template <typename Geometry1, typename Geometry2>
0376 struct transform
0377 {
0378     template <typename Strategy>
0379     static inline bool apply(Geometry1 const& geometry1,
0380                              Geometry2& geometry2,
0381                              Strategy const& strategy)
0382     {
0383         return resolve_strategy::transform::apply(
0384             geometry1,
0385             geometry2,
0386             strategy
0387         );
0388     }
0389 };
0390 
0391 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
0392 struct transform<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
0393 {
0394     template <typename Strategy>
0395     struct visitor: static_visitor<bool>
0396     {
0397         Geometry2& m_geometry2;
0398         Strategy const& m_strategy;
0399 
0400         visitor(Geometry2& geometry2, Strategy const& strategy)
0401             : m_geometry2(geometry2)
0402             , m_strategy(strategy)
0403         {}
0404 
0405         template <typename Geometry1>
0406         inline bool operator()(Geometry1 const& geometry1) const
0407         {
0408             return transform<Geometry1, Geometry2>::apply(
0409                 geometry1,
0410                 m_geometry2,
0411                 m_strategy
0412             );
0413         }
0414     };
0415 
0416     template <typename Strategy>
0417     static inline bool apply(
0418         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
0419         Geometry2& geometry2,
0420         Strategy const& strategy
0421     )
0422     {
0423         return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
0424     }
0425 };
0426 
0427 } // namespace resolve_variant
0428 
0429 
0430 /*!
0431 \brief Transforms from one geometry to another geometry  \brief_strategy
0432 \ingroup transform
0433 \tparam Geometry1 \tparam_geometry
0434 \tparam Geometry2 \tparam_geometry
0435 \tparam Strategy strategy
0436 \param geometry1 \param_geometry
0437 \param geometry2 \param_geometry
0438 \param strategy The strategy to be used for transformation
0439 \return True if the transformation could be done
0440 
0441 \qbk{distinguish,with strategy}
0442 
0443 \qbk{[include reference/algorithms/transform_with_strategy.qbk]}
0444  */
0445 template <typename Geometry1, typename Geometry2, typename Strategy>
0446 inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,
0447             Strategy const& strategy)
0448 {
0449     return resolve_variant::transform<Geometry1, Geometry2>
0450                           ::apply(geometry1, geometry2, strategy);
0451 }
0452 
0453 
0454 /*!
0455 \brief Transforms from one geometry to another geometry using a strategy
0456 \ingroup transform
0457 \tparam Geometry1 \tparam_geometry
0458 \tparam Geometry2 \tparam_geometry
0459 \param geometry1 \param_geometry
0460 \param geometry2 \param_geometry
0461 \return True if the transformation could be done
0462 
0463 \qbk{[include reference/algorithms/transform.qbk]}
0464  */
0465 template <typename Geometry1, typename Geometry2>
0466 inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2)
0467 {
0468     return geometry::transform(geometry1, geometry2, default_strategy());
0469 }
0470 
0471 
0472 }} // namespace boost::geometry
0473 
0474 
0475 #endif // BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP