File indexing completed on 2025-01-18 09:35:22
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
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
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
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
0226
0227 return transform_range_out<point_type>(range1,
0228 range::back_inserter(range2), strategy);
0229 }
0230 };
0231
0232
0233
0234
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 }}
0261 #endif
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 }
0335 #endif
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 }
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 }
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
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
0456
0457
0458
0459
0460
0461
0462
0463
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 }}
0473
0474
0475 #endif