Boost logo

Geometry :

Subject: Re: [geometry] [Boost-users] [boost.geometry] buffer distance strategies
From: Barend Gehrels (barend_at_[hidden])
Date: 2014-11-08 05:58:04


Gu Grzegorz,

gchlebus wrote On 8-11-2014 2:33:
>
> 2014-11-07 19:30 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]
> </user/SendEmail.jtp?type=node&node=4668825&i=0>>:
>
> Hi Grzegorz,
>
> gchlebus wrote On 6-11-2014 19:08:
>>
>>
>> 2014-11-04 17:23 GMT+01:00 Barend Gehrels [via Boost] <[hidden
>> email] <http://user/SendEmail.jtp?type=node&node=4668774&i=0>>:
>>
>> Hi Grzegorz,
>>
>>
>>>
>>> 2014-10-29 23:18 GMT+01:00 Barend Gehrels [via Boost]
>>> <[hidden email]
>>> <http://user/SendEmail.jtp?type=node&node=4668617&i=0>>:
>>>
>>>
>>>
>>> gchlebus wrote On 24-10-2014 16:44:
>>>
>>> > Hi,
>>> >
>>> > I am wondering whether it would be possible to achieve
>>> anisotropic buffering
>>> > (distances in neg x, pos x, neg y, pos y can have
>>> different values) of a
>>> > polygon using the buffer function with
>>> custom-implemented distance strategy.
>>> > What I want to achieve is presented on the figure 2-b
>>> in the following
>>> > paper:
>>> >
>>> http://itcnt05.itc.nl/agile_old/Conference/mallorca2002/proceedings/posters/p_molina.pdf
>>> >
>>> > I would be grateful to hear from you whether it is doable, and if
>>> positive,
>>> > how one could implement such a custom distance strategy.
>>> The current distance strategy has (currently) no means
>>> to get the angle,
>>> or a vector of the new point to be buffered. We can
>>> consider adding that.
>>>
>>> However, by writing custom strategies for join, side,
>>> point (for
>>> point-buffers) and possibly end (for line-buffers) you
>>> should be able to
>>> create this, because these have this information.
>>>
>>> Attached a program doing similar things with polygons
>>> and points (I vary
>>> the distance based on angle - you will have to do
>>> something with your
>>> anistropic model).
>>>
>>> The output is also attached.
>>>
>>> The program defines three custom strategies, all based
>>> on the same
>>> mechanism, to create interesting output.
>>> I did not do the end-strategy but that would look
>>> similar, you can look
>>> at the provided end-strategy (round) and apply the same
>>> function.
>>>
>>
>>
>> gchlebus wrote On 31-10-2014 18:13:
>>> I really appreciate your example code, it helped me a lot.
>>> Attached you can find my source code.
>>> In my implementation of the anisotropic buffering I didn't
>>> know how to make use of the distance strategy, as it was
>>> possible to make it work using only side and join strategies.
>>> I encountered strange behavior when changing number of
>>> points describing a full circle. Using 360 points produced a
>>> good output, whereas 90 points caused only the second
>>> polygon to be buffered (see attached figures). I would be
>>> thankful if you could help me to resolve this issue as well
>>> as for any remarks to my code.
>>>
>>
>> I could reproduce this. Basically the join-strategy should
>> always include points perp1 and perp2 (these are the two
>> points perpendicular to the two sides which the join-strategy
>> joints). Either they are re-calculated, or they can be just
>> added to begin and end. So I did the last option, and that
>> piece of code now looks like:
>>
>> double const angle_increment = 2.0 * M_PI /
>> double(point_count);
>> double alpha = angle1 - angle_increment;
>> * range_out.push_back(perp1);**// added
>> * for (int i = 0; alpha >= angle2 && i < point_count;
>> i++, alpha -= angle_increment)
>> {
>> pdd v = getPointOnEllipse(alpha);
>> Point p;
>> bg::set<0>(p, bg::get<0>(vertex) + v.first);
>> bg::set<1>(p, bg::get<1>(vertex) + v.second);
>> range_out.push_back(p);
>> }
>> * range_out.push_back(perp2);**// added*
>>
>> My sample code of course also suffered from that, so I added
>> it there too if I use it in the future.
>>
>> I tested your algorithm with various points and distances and
>> it now seems always OK.
>>
>> You ask for remarks on your code: it looks good ;-) one
>> thing, many terms are recalculated such as
>> pow(xPos*tan(alpha), 2)); or just tan(alpha), I usually store
>> these into variables, to avoid expensive recalculations of
>> the same terms, though maybe they are optimized by the compiler.
>>
>> Regards, Barend
>>
>>
>> P.S. this list discourages top-postings
>>
>>
>> Hallo Barend,
>>
>> I corrected the join strategy, but still the buffering doesn't
>> work in all cases as expected. When using xPos = 1, and other
>> values equal 0, the buffered polygon contains a hole (see
>> xPos1.svg), whereas setting xPos to 2 produces a correct result
>> (xPos2.svg). Do you know how to fix it? I attached also main.cpp,
>> as I changed the code a bit and it contains the polygon for which
>> causes the strange behavior.
>>
>
>
> That is most probably caused by an error in some of your calculations:
>
> The line y = sqrt(yPos2 * (1 - pow(x, 2) / xNeg2));
> causes a NAN for this input:
>
> alpha about PI
> then xNeg2 = 0.010000000000000002
> and x = -0.10000000000000002
> and yPos2 = 0.010000000000000002
>
> This adds a weird line containing NAN to the join, causing the
> buffer process fail.
> I got this using these parameters:
> double xPos = 1.0, xNeg = 0.1, yPos = 0.1, yNeg = 0.1;
>
> and not the parameters you have (that was fine for me).
>
> I think you should make the calculations full-proof first...
>
> For example add a line in the join-strategy:
> std::cout << i << " "<< angle1 << " " << angle2 << " " <<
> v.first << " " << v.second << std::endl;
>
>
> Regards, Barend
>
>
> Thanks, I'll try to improve my calculations.
> By the way, I was playing with different strategies combinations and I
> found out that when using only boost buffer strategies:
> double points_per_circle = 36;
> double distance = 130;
> bg::strategy::buffer::distance_symmetric<double>
> distance_strategy(distance);
> bg::strategy::buffer::end_flat end_strategy;
> bg::strategy::buffer::point_circle point_strat(points_per_circle);
> bg::strategy::buffer::side_straight sideStrat;
> bg::strategy::buffer::join_round joinStrat(points_per_circle);
>
> the buffer function can still fail (produce no output) when the
> distance is higher than 128 (e.g, 128, 130, 150, 300, 400). But this
> happens up to a certain value, where the buffer function starts
> producing a correct output (e.g., distances 900, 1000).
>

Hmm, I see (starting at different values, but I can reproduce).

I created a ticket, will be looked at. Thanks for reporting.
https://svn.boost.org/trac/boost/ticket/10770

Barend



Geometry list run by mateusz at loskot.net