Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:33:24

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2014-2015 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2014-2015 Bruno Lalande, Paris, France.
0005 // Copyright (c) 2014-2015 Mateusz Loskot, London, UK.
0006 // Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
0007 
0008 // This file was modified by Oracle on 2015-2020.
0009 // Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
0010 
0011 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
0012 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0013 
0014 // Use, modification and distribution is subject to the Boost Software License,
0015 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0016 // http://www.boost.org/LICENSE_1_0.txt)
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 // TEMP
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     // Scale box to integer-range
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; // Define a large range to get precise integer coordinates
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     // Assign input/output minimal points
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     // Get bounding box
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 // NOTE: Actually it should take 2 separate strategies, one for each geometry
0124 // in case one of them was e.g. a Box
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     // Get bounding boxes (when at least one of the geometries is not empty)
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         // The following approach (envelope + expand) may not give the
0158         // optimal MBR when then two geometries are in the spherical
0159         // equatorial or geographic coordinate systems.
0160         // TODO: implement envelope for two (or possibly more geometries)
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 // We rescale only all FP types
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 // Specialization for no-rescaling
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 }} // namespace detail::get_rescale_policy
0272 #endif // DOXYGEN_NO_DETAIL
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     // Default: no rescaling
0330     : public detail::get_rescale_policy::rescale_policy_type
0331         <
0332             typename geometry::point_type<Geometry1>::type,
0333             false
0334         >
0335 {};
0336 
0337 // Areal/areal: get rescale policy based on coordinate type
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 }} // namespace boost::geometry
0414 
0415 
0416 #endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP