Back to home page

EIC code displayed by LXR

 
 

    


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

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/type_traits.hpp>
0042 
0043 // TEMP
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     // Scale box to integer-range
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; // Define a large range to get precise integer coordinates
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     // Assign input/output minimal points
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     // Get bounding box
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 // NOTE: Actually it should take 2 separate strategies, one for each geometry
0123 // in case one of them was e.g. a Box
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     // Get bounding boxes (when at least one of the geometries is not empty)
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         // The following approach (envelope + expand) may not give the
0157         // optimal MBR when then two geometries are in the spherical
0158         // equatorial or geographic coordinate systems.
0159         // TODO: implement envelope for two (or possibly more geometries)
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 // We rescale only all FP types
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 // Specialization for no-rescaling
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 }} // namespace detail::get_rescale_policy
0271 #endif // DOXYGEN_NO_DETAIL
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     // Default: no rescaling
0329     : public detail::get_rescale_policy::rescale_policy_type
0330         <
0331             typename geometry::point_type<Geometry1>::type,
0332             false
0333         >
0334 {};
0335 
0336 // Areal/areal: get rescale policy based on coordinate type
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 }} // namespace boost::geometry
0413 
0414 
0415 #endif // BOOST_GEOMETRY_POLICIES_ROBUSTNESS_GET_RESCALE_POLICY_HPP