Skip to content

Commit

Permalink
[buffer] make miter_limit flexibel and correct IP to exactly that limit
Browse files Browse the repository at this point in the history
  • Loading branch information
barendgehrels committed Jul 20, 2014
1 parent 804fea1 commit 77b2723
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 22 deletions.
56 changes: 36 additions & 20 deletions include/boost/geometry/strategies/cartesian/buffer_join_miter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ namespace strategy { namespace buffer
\details This strategy can be used as JoinStrategy for the buffer algorithm.
It creates a sharp corners around each convex vertex. It can be applied
for (multi)linestrings and (multi)polygons.
If corners are sharp by themselves, the miters might become very long. Therefore
there is a limit (miter_limit), in terms of the used distance, which limits
their length. The miter is not changed to a bevel form (as done in some
other software), it is just adapted to the specified miter_limit but keeps
its miter form.
This strategy is only applicable for Cartesian coordinate systems.
\qbk{
Expand All @@ -47,12 +52,11 @@ namespace strategy { namespace buffer
class join_miter
{
public:
//! Constructs the strategy
inline join_miter()
{}

//! Constructs the strategy with a (currently dummy) integer
explicit inline join_miter(int)
//! \brief Constructs the strategy
//! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
explicit inline join_miter(double miter_limit = 5.0)
: m_miter_limit(valid_limit(miter_limit))
{}

#ifndef DOXYGEN_SHOULD_SKIP_THIS
Expand All @@ -78,25 +82,24 @@ class join_miter

Point p = ip;

// Normalize it and give it X*dist.
coordinate_type const dx = get<0>(ip) - get<0>(vertex);
coordinate_type const dy = get<1>(ip) - get<1>(vertex);

promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy);

BOOST_ASSERT(length != 0.0); // because ip/vertex are not equal
// Check the distance ip-vertex (= miter distance)
// (We calculate it manually (not using Pythagoras strategy) to reuse
// dx and dy)
coordinate_type const dx = get<0>(p) - get<0>(vertex);
coordinate_type const dy = get<1>(p) - get<1>(vertex);

// TODO: make max-mitre-limit flexible
promoted_type const ten = 10.0;
promoted_type const zero_seven = 0.7;
promoted_type const distance = geometry::math::sqrt(dx * dx + dy * dy);

promoted_type const max = ten * geometry::math::abs(buffer_distance);
promoted_type const max_distance
= m_miter_limit * geometry::math::abs(buffer_distance);

if (length > max)
if (distance > max_distance)
{
promoted_type const prop = zero_seven * buffer_distance / length;
set<0>(p, get<0>(vertex) + dx * prop);
set<1>(p, get<1>(vertex) + dy * prop);
BOOST_ASSERT(distance != 0.0);

promoted_type const proportion = max_distance / distance;
set<0>(p, get<0>(vertex) + dx * proportion);
set<1>(p, get<1>(vertex) + dy * proportion);
}

range_out.push_back(perp1);
Expand All @@ -105,6 +108,19 @@ class join_miter
return true;
}
#endif // DOXYGEN_SHOULD_SKIP_THIS

private :
double valid_limit(double miter_limit) const
{
if (miter_limit < 1.0)
{
// It should always exceed the buffer distance
miter_limit = 1.0;
}
return miter_limit;
}

double m_miter_limit;
};

}} // namespace strategy::buffer
Expand Down
4 changes: 2 additions & 2 deletions test/algorithms/buffer/polygon_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void test_all()
{
typedef bg::model::polygon<P> polygon_type;

bg::strategy::buffer::join_miter join_miter;
bg::strategy::buffer::join_miter join_miter(10.0);
bg::strategy::buffer::join_round join_round(100);
bg::strategy::buffer::end_flat end_flat;
bg::strategy::buffer::end_round end_round(100);
Expand Down Expand Up @@ -277,7 +277,7 @@ void test_all()
test_one<polygon_type, polygon_type>("parcel1_20", parcel1, join_round, end_flat, 11648.0537185668945, 20.0);
test_one<polygon_type, polygon_type>("parcel1_20", parcel1, join_miter, end_flat, 14184.0223083496094, 20.0);
test_one<polygon_type, polygon_type>("parcel1_30", parcel1, join_round, end_flat, 16350.3611068725586, 30.0);
test_one<polygon_type, polygon_type>("parcel1_30", parcel1, join_miter, end_flat, 22046.5098342895508, 30.0);
test_one<polygon_type, polygon_type>("parcel1_30", parcel1, join_miter, end_flat, 22417.8007659912109, 30.0);

test_one<polygon_type, polygon_type>("parcel2_10", parcel2, join_round, end_flat, 5000.85063171386719, 10.0);
test_one<polygon_type, polygon_type>("parcel2_10", parcel2, join_miter, end_flat, 5091.12226867675781, 10.0);
Expand Down

0 comments on commit 77b2723

Please sign in to comment.