Boost logo

Geometry :

Subject: Re: [geometry] [Boost-users] [boost.geometry] buffer distance strategies
From: Barend Gehrels (barend_at_[hidden])
Date: 2014-11-12 16:12:41


Hi Grzegorz,

gchlebus wrote On 12-11-2014 21:52:
> 2014-11-08 11:53 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]
> </user/SendEmail.jtp?type=node&node=4669040&i=0>>:
>
> Gu Grzegorz,
>
> gchlebus wrote On 8-11-2014 2:33:
>>
>> 2014-11-07 19:30 GMT+01:00 Barend Gehrels [via Boost] <[hidden
>> email] <http://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
>
>
> Hi Barend,
>
> I'm glad that I could help.
> Anyway, I fixed the bug with NAN, but still when using (e.g. xNeg = 1,
> other 0) the buffer produces no output. I am really wondering, how it
> could work on your machine.
> I printed the values used by join and side strategies and they seem to
> be fine (no NANs or other strange values) - see attached log.txt and
> updated main.cpp used to produce the log file.
>
> I've compiled my code using msvc 12.0 and gcc 4.8.

Which branch or version of Boost do you use?

In the meantime, I managed to fix the bug you reported, and it is
committed today.

Sorry for my question, but could you try it again with the latest branch
"develop" from github ?

Regards, Barend



Geometry list run by mateusz at loskot.net