Re: [Boost-users] [boost.geometry] buffer distance strategies

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [boost.geometry] buffer distance strategies

Barend
Hi,

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
>

Thanks for your question ahd the link to the paper. Very interesting. I
had various scenarios in mind but not yet this one. It should be
possible, the input for the distance strategy is the point which is
buffered at that moment. But I have to check. I'll come back to this.

Regards, Barend

_______________________________________________
Geometry mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/geometry
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [boost.geometry] buffer distance strategies

Barend
Hi Grzegorz,

gchlebus wrote On 28-10-2014 17:24:
> Hi,
>
> any ideas how one could implement this anisotropic distance strategy? I gave
> a bit thought to this and I think, that to make this anisotropic approach
> working as described in the paper one would have also to implement a new
> EndStrategy, namely, an elliptic one.

Sure! You asked this 4 days before and I answered you:

> Thanks for your question ahd the link to the paper. Very interesting.
> I had various scenarios in mind but not yet this one. It should be
> possible, the input for the distance strategy is the point which is
> buffered at that moment. But I have to check. I'll come back to this.

So I'll come back to this ;-) It is possible. I was writing example-code
for this question, you will get the answer tomorrow.

Yes, you will need indeed other strategies than distance too.

Regards, Barend

_______________________________________________
Geometry mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/geometry
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [boost.geometry] buffer distance strategies

Barend
In reply to this post by Barend
Hi Grzegorz,


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.

Regards, Barend


_______________________________________________
Geometry mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/geometry

buffer_point_circle.cpp (6K) Download Attachment
bufferpol.svg (10K) Download Attachment
buffer.svg (16K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [boost.geometry] buffer distance strategies

Barend
Hi Grzegorz,



2014-10-29 23:18 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:


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


_______________________________________________
Geometry mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/geometry
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [boost.geometry] buffer distance strategies

Barend
Hi Grzegorz,

gchlebus wrote On 6-11-2014 19:08:


2014-11-04 17:23 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:
Hi Grzegorz,



2014-10-29 23:18 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:


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



_______________________________________________
Geometry mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/geometry
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [boost.geometry] buffer distance strategies

Barend
Gu Grzegorz,

gchlebus wrote On 8-11-2014 2:33:

2014-11-07 19:30 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:
Hi Grzegorz,

gchlebus wrote On 6-11-2014 19:08:


2014-11-04 17:23 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:

Hi Grzegorz,



2014-10-29 23:18 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:


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 mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/geometry
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [boost.geometry] buffer distance strategies

Barend
Hi Grzegorz,


gchlebus wrote On 12-11-2014 21:52:
2014-11-08 11:53 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:
Gu Grzegorz,

gchlebus wrote On 8-11-2014 2:33:

2014-11-07 19:30 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:

Hi Grzegorz,

gchlebus wrote On 6-11-2014 19:08:


2014-11-04 17:23 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:

Hi Grzegorz,



2014-10-29 23:18 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:


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 mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/geometry
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [boost.geometry] buffer distance strategies

Barend
Hi Grzegorz,


gchlebus wrote On 13-11-2014 18:39:
Hi Barend,

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


2014-11-12 22:07 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:

Hi Grzegorz,


gchlebus wrote On 12-11-2014 21:52:
2014-11-08 11:53 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:

Gu Grzegorz,

gchlebus wrote On 8-11-2014 2:33:

2014-11-07 19:30 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:

Hi Grzegorz,

gchlebus wrote On 6-11-2014 19:08:


2014-11-04 17:23 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:

Hi Grzegorz,



2014-10-29 23:18 GMT+01:00 Barend Gehrels [via Boost] <[hidden email]>:


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


_______________________________________________
Geometry mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/geometry