Boost logo

Boost Users :

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


Hi Grzegorz,

gchlebus wrote On 13-11-2014 18:39:
> Hi Barend,
>
> 2014-11-12 22:21 GMT+01:00 Grzegorz Chlebus <[hidden email]
> </user/SendEmail.jtp?type=node&node=4669068&i=0>>:
>
>
>
> 2014-11-12 22:07 GMT+01:00 Barend Gehrels [via Boost] <[hidden
> email] </user/SendEmail.jtp?type=node&node=4669068&i=1>>:
>
> 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.

Sure - thanks for sending me, that saves me time to find it out.
Buffer-distance 0 is not supported (yet). Some GIS packages use that to
clean a polygon, but we have designed dissolve for that. We might
support it later but currently, indeed, as you found out, it will not
work. I hope small distances are OK for your application, for now.

Negative distances should work if used in the distance-policy, making
the polygon smaller, but I don't think that it will work currently out
of the box if you mix negative and positive distances in one
join-strategy...

Regards, Barend



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