Buffer polygon from a LineString

222 views
Skip to first unread message

Daryl Wilding-McBride

unread,
Apr 25, 2012, 1:44:57 AM4/25/12
to RGeo-Users
Hello,

I have a LineString and I want to create a polygon from a buffer
around it. I believe this is what the method 'buffer' should do.
However, I get this error when I call it:
"Method Geometry#buffer not defined."

Am I missing something?

Regards,
Daryl.

Daniel Azuma

unread,
Apr 25, 2012, 8:19:09 AM4/25/12
to RGeo-Users

Hi Daryl,

This is because only certain factories implement the buffer method (since it's a geometrically complicated computation). The Geos factory (for flat coordinate systems) does it, as does the simple_mercator factory and the projected geometric factory. But the simple_cartesian and simple_spherical factories do not.

If you're using simple_mercator or projected geometric factories and you're still getting this error, make sure that you have libgeos properly installed. Check RGeo::Geos.supported? to determine whether RGeo can find Geos. If you know libgeos is installed but RGeo can't find it, then you might need to tell RGeo where libgeos is when you install the rgeo gem:

gem install rgeo -- --with-geos-dir=/geos/install/prefix

Alternatively, if you're using JRuby, then you need to use ffi-geos to access geos. Make sure the ffi-geos gem is installed.

Daniel

Daryl Wilding-McBride

unread,
May 1, 2012, 6:43:38 AM5/1/12
to RGeo-Users
That works very nicely now - thanks Daniel.

Daryl Wilding-McBride

unread,
May 1, 2012, 8:12:19 AM5/1/12
to RGeo-Users
Hi Daniel,

For this code:

require 'rgeo'
factory = ::RGeo::Geographic.simple_mercator_factory()
p1 = factory.point(1,1)
p2 = factory.point(2,2)
p3 = factory.point(3,3)
line = factory.line_string([p1,p2,p3])
polygon = line.buffer(2)
polygon.to_s

I see this displayed:

"POLYGON ((1.99998729171068 2.00001269216625, 2.99998728977535
3.00001268056335, 3.00001269796555 3.00001269280565, 3.00001271022465
2.99998731943648, 2.00001271022465 1.99998730976965, 1.00001270635418
0.999987300095933, 0.999987298161415 0.999987295581046,
0.999987293645824 1.00001269990402, 1.99998729171068
2.00001269216625))"

How do I get a Ruby object (e.g. a 2-element array for x and y) for
each of the polygon's points?

Thanks,
Daryl.

On Apr 25, 10:19 pm, Daniel Azuma <daz...@gmail.com> wrote:

Daniel Azuma

unread,
May 1, 2012, 2:32:22 PM5/1/12
to RGeo-Users
If you need the points along the outer edge of a polygon, do this:

points = polygon.exterior_ring.points

Returns an array of Point objects that respond to #x and #y. So you can:

points.map{ |p| [p.x, p.y] }

Also, note that the first and last point in the array will be the same (i.e. to "close" the LineString into a loop). So to avoid that repeat:

points[0..-2].map{ |p| [p.x, p.y] }

One other thing you might want to consider. A buffer is generally a polygon approximation (because the "true" shape almost always has curved boundaries). Use the :buffer_resolution argument to the factory to control how fine buffer approximations are. It defaults to 1, which is pretty coarse. (With a resolution of 1, a buffer around a point would have 4 sides.) You may want to choose a higher resolution, depending on your application, e.g.

factory = RGeo::Geographic.simple_mercator_factory(:buffer_resolution => 8)

Daniel

Daryl Wilding-McBride

unread,
May 4, 2012, 8:34:28 PM5/4/12
to RGeo-Users
That's very helpful Daniel - thank you. I tried your suggested
buffer_resolution and it creates a beautiful polygon.
Reply all
Reply to author
Forward
0 new messages