Boost logo

Boost Users :

Subject: Re: [Boost-users] [boost.geometry] buffer distance strategies
From: gchlebus (gchlebus_at_[hidden])
Date: 2014-11-13 12:39:47


Hi Barend,

2014-11-12 22:21 GMT+01:00 Grzegorz Chlebus <gchlebus_at_[hidden]>:

>
>
> 2014-11-12 22:07 GMT+01:00 Barend Gehrels [via Boost] <
> ml-node+s2283326n4669041h98_at_[hidden]>:
>
> Hi Grzegorz,
>>
>>
>> gchlebus wrote On 12-11-2014 21:52:
>>
>> 2014-11-08 11:53 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]
>> <http://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
>>
>>
>
> Hi Barend,
>
> sure, I downloaded the geometry lib from the develop branch, but still
> buffer returns an empty geometry (using xNeg = 1, others 0).
> I've ran my code also for big distances, and it works perfectly. Good job!
>
> Best,
> Grzegorz
>

I made today an interesting observation. It seems that the buffer function
has a problem when the extents (xNeg, xPos, yNeg, yPos) are zero. Taking my
last example, setting xNeg to 1 and others to 1e-3 makes the buffer work.

Best,
Grzegorz

--
View this message in context: http://boost.2283326.n4.nabble.com/boost-geometry-buffer-distance-strategies-tp4668469p4669068.html
Sent from the Boost - Users mailing list archive at Nabble.com.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net