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