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-2014 Barend Gehrels, Amsterdam, the Netherlands.
0004 
0005 // Use, modification and distribution is subject to the Boost Software License,
0006 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
0010 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP
0011 
0012 #include <boost/geometry/core/assert.hpp>
0013 #include <boost/geometry/core/cs.hpp>
0014 #include <boost/geometry/policies/compare.hpp>
0015 #include <boost/geometry/util/math.hpp>
0016 #include <boost/geometry/util/select_most_precise.hpp>
0017 
0018 #include <boost/geometry/strategies/buffer.hpp>
0019 
0020 
0021 namespace boost { namespace geometry
0022 {
0023 
0024 namespace strategy { namespace buffer
0025 {
0026 
0027 /*!
0028 \brief Let the buffer create sharp corners
0029 \ingroup strategies
0030 \details This strategy can be used as JoinStrategy for the buffer algorithm.
0031     It creates a sharp corners around each convex vertex. It can be applied
0032     for (multi)linestrings and (multi)polygons.
0033     If corners are sharp by themselves, the miters might become very long. Therefore
0034     there is a limit (miter_limit), in terms of the used distance, which limits
0035     their length. The miter is not changed to a bevel form (as done in some
0036     other software), it is just adapted to the specified miter_limit but keeps
0037     its miter form.
0038     If the buffer distance is 5.0, and the miter limit is 2.0, generated points
0039     will be located at a distance of at most 10.0 (2*5) units.
0040     This strategy is only applicable for Cartesian coordinate systems.
0041 
0042 \qbk{
0043 [heading Example]
0044 [buffer_join_miter]
0045 [heading Output]
0046 [$img/strategies/buffer_join_miter.png]
0047 [heading See also]
0048 \* [link geometry.reference.algorithms.buffer.buffer_7_with_strategies buffer (with strategies)]
0049 \* [link geometry.reference.strategies.strategy_buffer_join_round join_round]
0050 }
0051  */
0052 class join_miter
0053 {
0054 public:
0055 
0056     //! \brief Constructs the strategy
0057     //! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
0058     explicit inline join_miter(double miter_limit = 5.0)
0059         : m_miter_limit(valid_limit(miter_limit))
0060     {}
0061 
0062 #ifndef DOXYGEN_SHOULD_SKIP_THIS
0063     //! Fills output_range with a sharp shape around a vertex
0064     template <typename Point, typename DistanceType, typename RangeOut>
0065     inline bool apply(Point const& ip, Point const& vertex,
0066                 Point const& perp1, Point const& perp2,
0067                 DistanceType const& buffer_distance,
0068                 RangeOut& range_out) const
0069     {
0070         geometry::equal_to<Point> equals;
0071         if (equals(ip, vertex))
0072         {
0073             return false;
0074         }
0075         if (equals(perp1, perp2))
0076         {
0077             return false;
0078         }
0079 
0080         typedef typename coordinate_type<Point>::type coordinate_type;
0081         typedef typename geometry::select_most_precise
0082         <
0083             coordinate_type,
0084             double
0085         >::type promoted_type;
0086 
0087         Point p = ip;
0088 
0089         // Check the distance ip-vertex (= miter distance)
0090         // (We calculate it manually (not using Pythagoras strategy) to reuse
0091         //  dx and dy)
0092         promoted_type const dx = get<0>(p) - get<0>(vertex);
0093         promoted_type const dy = get<1>(p) - get<1>(vertex);
0094 
0095         promoted_type const distance = geometry::math::sqrt(dx * dx + dy * dy);
0096 
0097         promoted_type const max_distance
0098             = m_miter_limit * geometry::math::abs(buffer_distance);
0099 
0100         if (distance > max_distance)
0101         {
0102             BOOST_GEOMETRY_ASSERT(distance != 0.0);
0103 
0104             promoted_type const proportion = max_distance / distance;
0105             set<0>(p, get<0>(vertex) + dx * proportion);
0106             set<1>(p, get<1>(vertex) + dy * proportion);
0107         }
0108 
0109         range_out.push_back(perp1);
0110         range_out.push_back(p);
0111         range_out.push_back(perp2);
0112         return true;
0113     }
0114 
0115     template <typename NumericType>
0116     inline NumericType max_distance(NumericType const& distance) const
0117     {
0118         return distance * m_miter_limit;
0119     }
0120 
0121 #endif // DOXYGEN_SHOULD_SKIP_THIS
0122 
0123 private :
0124     double valid_limit(double miter_limit) const
0125     {
0126         if (miter_limit < 1.0)
0127         {
0128             // It should always exceed the buffer distance
0129             miter_limit = 1.0;
0130         }
0131         return miter_limit;
0132     }
0133 
0134     double m_miter_limit;
0135 };
0136 
0137 }} // namespace strategy::buffer
0138 
0139 
0140 }} // namespace boost::geometry
0141 
0142 #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_MITER_HPP