File indexing completed on 2025-01-18 09:35:36
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
0019 #define BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP
0020
0021
0022 #include <cstddef>
0023 #include <type_traits>
0024
0025 #include <boost/geometry/core/assert.hpp>
0026 #include <boost/geometry/core/config.hpp>
0027 #include <boost/geometry/core/coordinate_promotion.hpp>
0028 #include <boost/geometry/core/tag_cast.hpp>
0029
0030 #include <boost/geometry/algorithms/envelope.hpp>
0031 #include <boost/geometry/algorithms/expand.hpp>
0032 #include <boost/geometry/algorithms/is_empty.hpp>
0033 #include <boost/geometry/algorithms/detail/recalculate.hpp>
0034 #include <boost/geometry/algorithms/detail/get_max_size.hpp>
0035 #include <boost/geometry/core/static_assert.hpp>
0036 #include <boost/geometry/geometries/point.hpp>
0037 #include <boost/geometry/geometries/box.hpp>
0038 #include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
0039 #include <boost/geometry/policies/robustness/rescale_policy.hpp>
0040 #include <boost/geometry/policies/robustness/robust_type.hpp>
0041 #include <boost/geometry/util/type_traits.hpp>
0042
0043
0044 #include <boost/geometry/strategies/envelope/cartesian.hpp>
0045 #include <boost/geometry/strategies/envelope/geographic.hpp>
0046 #include <boost/geometry/strategies/envelope/spherical.hpp>
0047
0048
0049 namespace boost { namespace geometry
0050 {
0051
0052 #ifndef DOXYGEN_NO_DETAIL
0053 namespace detail { namespace get_rescale_policy
0054 {
0055
0056 template
0057 <
0058 typename Box,
0059 typename Point,
0060 typename RobustPoint,
0061 typename Factor
0062 >
0063 inline void scale_box_to_integer_range(Box const& box,
0064 Point& min_point,
0065 RobustPoint& min_robust_point,
0066 Factor& factor)
0067 {
0068
0069 typedef typename promote_floating_point
0070 <
0071 typename geometry::coordinate_type<Point>::type
0072 >::type num_type;
0073 num_type const diff = boost::numeric_cast<num_type>(detail::get_max_size(box));
0074 num_type const range = 10000000.0;
0075 num_type const half = 0.5;
0076 if (math::equals(diff, num_type())
0077 || diff >= range
0078 || ! boost::math::isfinite(diff))
0079 {
0080 factor = 1;
0081 }
0082 else
0083 {
0084 factor = boost::numeric_cast<num_type>(
0085 boost::numeric_cast<boost::long_long_type>(half + range / diff));
0086 BOOST_GEOMETRY_ASSERT(factor >= 1);
0087 }
0088
0089
0090 detail::assign_point_from_index<0>(box, min_point);
0091 num_type const two = 2;
0092 boost::long_long_type const min_coordinate
0093 = boost::numeric_cast<boost::long_long_type>(-range / two);
0094 assign_values(min_robust_point, min_coordinate, min_coordinate);
0095 }
0096
0097 template
0098 <
0099 typename Point, typename RobustPoint, typename Geometry,
0100 typename Factor, typename Strategy
0101 >
0102 static inline void init_rescale_policy(Geometry const& geometry,
0103 Point& min_point,
0104 RobustPoint& min_robust_point,
0105 Factor& factor,
0106 Strategy const& strategy)
0107 {
0108 if (geometry::is_empty(geometry))
0109 {
0110 return;
0111 }
0112
0113
0114 model::box<Point> env = geometry::return_envelope
0115 <
0116 model::box<Point>
0117 >(geometry, strategy);
0118
0119 scale_box_to_integer_range(env, min_point, min_robust_point, factor);
0120 }
0121
0122
0123
0124 template
0125 <
0126 typename Point, typename RobustPoint, typename Geometry1, typename Geometry2,
0127 typename Factor, typename Strategy1, typename Strategy2
0128 >
0129 static inline void init_rescale_policy(Geometry1 const& geometry1,
0130 Geometry2 const& geometry2,
0131 Point& min_point,
0132 RobustPoint& min_robust_point,
0133 Factor& factor,
0134 Strategy1 const& strategy1,
0135 Strategy2 const& strategy2)
0136 {
0137
0138 bool const is_empty1 = geometry::is_empty(geometry1);
0139 bool const is_empty2 = geometry::is_empty(geometry2);
0140 if (is_empty1 && is_empty2)
0141 {
0142 return;
0143 }
0144
0145 model::box<Point> env;
0146 if (is_empty1)
0147 {
0148 geometry::envelope(geometry2, env, strategy2);
0149 }
0150 else if (is_empty2)
0151 {
0152 geometry::envelope(geometry1, env, strategy1);
0153 }
0154 else
0155 {
0156
0157
0158
0159
0160 geometry::envelope(geometry1, env, strategy1);
0161 model::box<Point> env2 = geometry::return_envelope
0162 <
0163 model::box<Point>
0164 >(geometry2, strategy2);
0165 geometry::expand(env, env2, strategy1);
0166 }
0167
0168 scale_box_to_integer_range(env, min_point, min_robust_point, factor);
0169 }
0170
0171
0172 template
0173 <
0174 typename Point,
0175 bool IsFloatingPoint
0176 >
0177 struct rescale_policy_type
0178 {
0179 typedef no_rescale_policy type;
0180 };
0181
0182
0183 template
0184 <
0185 typename Point
0186 >
0187 struct rescale_policy_type<Point, true>
0188 {
0189 typedef typename geometry::coordinate_type<Point>::type coordinate_type;
0190 typedef model::point
0191 <
0192 typename detail::robust_type<coordinate_type>::type,
0193 geometry::dimension<Point>::value,
0194 typename geometry::coordinate_system<Point>::type
0195 > robust_point_type;
0196 typedef typename promote_floating_point<coordinate_type>::type factor_type;
0197 typedef detail::robust_policy<Point, robust_point_type, factor_type> type;
0198 };
0199
0200 template <typename Policy>
0201 struct get_rescale_policy
0202 {
0203 template <typename Geometry, typename Strategy>
0204 static inline Policy apply(Geometry const& geometry,
0205 Strategy const& strategy)
0206 {
0207 typedef typename point_type<Geometry>::type point_type;
0208 typedef typename geometry::coordinate_type<Geometry>::type coordinate_type;
0209 typedef typename promote_floating_point<coordinate_type>::type factor_type;
0210 typedef model::point
0211 <
0212 typename detail::robust_type<coordinate_type>::type,
0213 geometry::dimension<point_type>::value,
0214 typename geometry::coordinate_system<point_type>::type
0215 > robust_point_type;
0216
0217 point_type min_point;
0218 robust_point_type min_robust_point;
0219 factor_type factor;
0220 init_rescale_policy(geometry, min_point, min_robust_point,
0221 factor, strategy);
0222
0223 return Policy(min_point, min_robust_point, factor);
0224 }
0225
0226 template <typename Geometry1, typename Geometry2, typename Strategy1, typename Strategy2>
0227 static inline Policy apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
0228 Strategy1 const& strategy1,
0229 Strategy2 const& strategy2)
0230 {
0231 typedef typename point_type<Geometry1>::type point_type;
0232 typedef typename geometry::coordinate_type<Geometry1>::type coordinate_type;
0233 typedef typename promote_floating_point<coordinate_type>::type factor_type;
0234 typedef model::point
0235 <
0236 typename detail::robust_type<coordinate_type>::type,
0237 geometry::dimension<point_type>::value,
0238 typename geometry::coordinate_system<point_type>::type
0239 > robust_point_type;
0240
0241 point_type min_point;
0242 robust_point_type min_robust_point;
0243 factor_type factor;
0244 init_rescale_policy(geometry1, geometry2, min_point, min_robust_point,
0245 factor, strategy1, strategy2);
0246
0247 return Policy(min_point, min_robust_point, factor);
0248 }
0249 };
0250
0251
0252 template <>
0253 struct get_rescale_policy<no_rescale_policy>
0254 {
0255 template <typename Geometry, typename EnvelopeStrategy>
0256 static inline no_rescale_policy apply(Geometry const& , EnvelopeStrategy const&)
0257 {
0258 return no_rescale_policy();
0259 }
0260
0261 template <typename Geometry1, typename Geometry2, typename EnvelopeStrategy1, typename EnvelopeStrategy2>
0262 static inline no_rescale_policy apply(Geometry1 const& , Geometry2 const& ,
0263 EnvelopeStrategy1 const& , EnvelopeStrategy2 const& )
0264 {
0265 return no_rescale_policy();
0266 }
0267 };
0268
0269
0270 }}
0271 #endif
0272
0273 template
0274 <
0275 typename Point,
0276 typename CSTag = typename geometry::cs_tag<Point>::type
0277 >
0278 struct rescale_policy_type
0279 : public detail::get_rescale_policy::rescale_policy_type
0280 <
0281 Point,
0282 #if defined(BOOST_GEOMETRY_USE_RESCALING)
0283 std::is_floating_point
0284 <
0285 typename geometry::coordinate_type<Point>::type
0286 >::type::value
0287 &&
0288 std::is_same
0289 <
0290 CSTag,
0291 geometry::cartesian_tag
0292 >::value
0293 #else
0294 false
0295 #endif
0296 >
0297 {
0298 BOOST_GEOMETRY_STATIC_ASSERT(
0299 (util::is_point<Point>::value),
0300 "Point type expected.",
0301 Point);
0302 };
0303
0304
0305 template
0306 <
0307 typename Geometry1,
0308 typename Geometry2,
0309 typename CSTag = typename geometry::cs_tag<Geometry1>::type,
0310 typename Tag1 = typename tag_cast
0311 <
0312 typename tag<Geometry1>::type,
0313 box_tag,
0314 pointlike_tag,
0315 linear_tag,
0316 areal_tag
0317 >::type,
0318 typename Tag2 = typename tag_cast
0319 <
0320 typename tag<Geometry2>::type,
0321 box_tag,
0322 pointlike_tag,
0323 linear_tag,
0324 areal_tag
0325 >::type
0326 >
0327 struct rescale_overlay_policy_type
0328
0329 : public detail::get_rescale_policy::rescale_policy_type
0330 <
0331 typename geometry::point_type<Geometry1>::type,
0332 false
0333 >
0334 {};
0335
0336
0337 template
0338 <
0339 typename Geometry1,
0340 typename Geometry2,
0341 typename CSTag
0342 >
0343 struct rescale_overlay_policy_type<Geometry1, Geometry2, CSTag, areal_tag, areal_tag>
0344 : public rescale_policy_type
0345 <
0346 typename geometry::point_type<Geometry1>::type,
0347 CSTag
0348 >
0349 {};
0350
0351
0352 template <typename Policy, typename Geometry>
0353 inline Policy get_rescale_policy(Geometry const& geometry)
0354 {
0355 typename geometry::strategies::envelope::services::default_strategy
0356 <
0357 Geometry,
0358 model::box<typename point_type<Geometry>::type>
0359 >::type strategy;
0360
0361 return detail::get_rescale_policy::get_rescale_policy<Policy>::apply(geometry, strategy);
0362 }
0363
0364 template
0365 <
0366 typename Policy, typename Geometry, typename Strategy,
0367 std::enable_if_t<std::is_void<typename geometry::tag<Strategy>::type>::value, int> = 0
0368 >
0369 inline Policy get_rescale_policy(Geometry const& geometry, Strategy const& strategy)
0370 {
0371 return detail::get_rescale_policy::get_rescale_policy
0372 <
0373 Policy
0374 >::apply(geometry, strategy);
0375 }
0376
0377 template
0378 <
0379 typename Policy, typename Geometry1, typename Geometry2,
0380 std::enable_if_t<! std::is_void<typename geometry::tag<Geometry2>::type>::value, int> = 0
0381 >
0382 inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2)
0383 {
0384 typename geometry::strategies::envelope::services::default_strategy
0385 <
0386 Geometry1,
0387 model::box<typename point_type<Geometry1>::type>
0388 >::type strategy1;
0389 typename geometry::strategies::envelope::services::default_strategy
0390 <
0391 Geometry2,
0392 model::box<typename point_type<Geometry2>::type>
0393 >::type strategy2;
0394
0395 return detail::get_rescale_policy::get_rescale_policy
0396 <
0397 Policy
0398 >::apply(geometry1, geometry2, strategy1, strategy2);
0399 }
0400
0401 template <typename Policy, typename Geometry1, typename Geometry2, typename Strategy>
0402 inline Policy get_rescale_policy(Geometry1 const& geometry1, Geometry2 const& geometry2,
0403 Strategy const& strategy)
0404 {
0405 return detail::get_rescale_policy::get_rescale_policy
0406 <
0407 Policy
0408 >::apply(geometry1, geometry2, strategy, strategy);
0409 }
0410
0411
0412 }}
0413
0414
0415 #endif