Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
0005 
0006 // This file was modified by Oracle on 2015.
0007 // Modifications copyright (c) 2015, Oracle and/or its affiliates.
0008 
0009 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
0010 
0011 // Use, modification and distribution is subject to the Boost Software License,
0012 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0013 // http://www.boost.org/LICENSE_1_0.txt)
0014 
0015 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
0016 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
0017 
0018 #include <algorithm>
0019 
0020 #include <boost/geometry/core/cs.hpp>
0021 #include <boost/geometry/policies/compare.hpp>
0022 #include <boost/geometry/strategies/buffer.hpp>
0023 #include <boost/geometry/util/math.hpp>
0024 #include <boost/geometry/util/select_most_precise.hpp>
0025 
0026 #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
0027 #include <iostream>
0028 #include <boost/geometry/io/wkt/wkt.hpp>
0029 #endif
0030 
0031 
0032 namespace boost { namespace geometry
0033 {
0034 
0035 
0036 namespace strategy { namespace buffer
0037 {
0038 
0039 /*!
0040 \brief Let the buffer create rounded corners
0041 \ingroup strategies
0042 \details This strategy can be used as JoinStrategy for the buffer algorithm.
0043     It creates a rounded corners around each convex vertex. It can be applied
0044     for (multi)linestrings and (multi)polygons.
0045     This strategy is only applicable for Cartesian coordinate systems.
0046 
0047 \qbk{
0048 [heading Example]
0049 [buffer_join_round]
0050 [heading Output]
0051 [$img/strategies/buffer_join_round.png]
0052 [heading See also]
0053 \* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
0054 \* [link geometry.reference.strategies.strategy_buffer_join_miter join_miter]
0055 }
0056  */
0057 class join_round
0058 {
0059 public :
0060 
0061     //! \brief Constructs the strategy
0062     //! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
0063     explicit inline join_round(std::size_t points_per_circle = default_points_per_circle)
0064         : m_points_per_circle(get_point_count_for_join(points_per_circle))
0065     {}
0066 
0067 private :
0068     template
0069     <
0070         typename PromotedType,
0071         typename Point,
0072         typename DistanceType,
0073         typename RangeOut
0074     >
0075     inline void generate_points(Point const& vertex,
0076                 Point const& perp1, Point const& perp2,
0077                 DistanceType const& buffer_distance,
0078                 RangeOut& range_out) const
0079     {
0080         PromotedType const dx1 = get<0>(perp1) - get<0>(vertex);
0081         PromotedType const dy1 = get<1>(perp1) - get<1>(vertex);
0082         PromotedType const dx2 = get<0>(perp2) - get<0>(vertex);
0083         PromotedType const dy2 = get<1>(perp2) - get<1>(vertex);
0084 
0085         PromotedType const two_pi = geometry::math::two_pi<PromotedType>();
0086 
0087         PromotedType const angle1 = atan2(dy1, dx1);
0088         PromotedType angle2 = atan2(dy2, dx2);
0089         while (angle2 > angle1)
0090         {
0091             angle2 -= two_pi;
0092         }
0093         PromotedType const angle_diff = angle1 - angle2;
0094 
0095         // Divide the angle into an integer amount of steps to make it
0096         // visually correct also for a low number of points / circle
0097 
0098         // If a full circle is divided into 3 parts (e.g. angle is 125),
0099         // the one point in between must still be generated
0100         // The calculation below:
0101         // - generates 1 point  in between for an angle of 125 based on 3 points
0102         // - generates 0 points in between for an angle of 90  based on 4 points
0103 
0104         std::size_t const n = (std::max)(static_cast<std::size_t>(
0105             ceil(m_points_per_circle * angle_diff / two_pi)), std::size_t(1));
0106 
0107         PromotedType const diff = angle_diff / static_cast<PromotedType>(n);
0108         PromotedType a = angle1 - diff;
0109 
0110         // Walk to n - 1 to avoid generating the last point
0111         for (std::size_t i = 0; i < n - 1; i++, a -= diff)
0112         {
0113             Point p;
0114             set<0>(p, get<0>(vertex) + buffer_distance * cos(a));
0115             set<1>(p, get<1>(vertex) + buffer_distance * sin(a));
0116             range_out.push_back(p);
0117         }
0118     }
0119 
0120 public :
0121 
0122 
0123 #ifndef DOXYGEN_SHOULD_SKIP_THIS
0124     //! Fills output_range with a rounded shape around a vertex
0125     template <typename Point, typename DistanceType, typename RangeOut>
0126     inline bool apply(Point const& ip, Point const& vertex,
0127                 Point const& perp1, Point const& perp2,
0128                 DistanceType const& buffer_distance,
0129                 RangeOut& range_out) const
0130     {
0131         typedef typename coordinate_type<Point>::type coordinate_type;
0132         typedef typename boost::range_value<RangeOut>::type output_point_type;
0133 
0134         typedef typename geometry::select_most_precise
0135             <
0136                 typename geometry::select_most_precise
0137                     <
0138                         coordinate_type,
0139                         typename geometry::coordinate_type<output_point_type>::type
0140                     >::type,
0141                 double
0142             >::type promoted_type;
0143 
0144         geometry::equal_to<Point> equals;
0145         if (equals(perp1, perp2))
0146         {
0147             boost::ignore_unused(ip);
0148 #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
0149             std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;
0150 #endif
0151             return false;
0152         }
0153 
0154         range_out.push_back(perp1);
0155         generate_points<promoted_type>(vertex, perp1, perp2, geometry::math::abs(buffer_distance), range_out);
0156         range_out.push_back(perp2);
0157         return true;
0158     }
0159 
0160     template <typename NumericType>
0161     static inline NumericType max_distance(NumericType const& distance)
0162     {
0163         return distance;
0164     }
0165 
0166 #endif // DOXYGEN_SHOULD_SKIP_THIS
0167 
0168 private :
0169     std::size_t m_points_per_circle;
0170 };
0171 
0172 
0173 }} // namespace strategy::buffer
0174 
0175 }} // namespace boost::geometry
0176 
0177 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP