4

I am building some sort of homemade pyQGIS-Buffer-tool as the existing flat-end-buffer-tools are not working for me ( see v.distance.buffer does not create proper buffers with flat endcaps)

Therefore I am looking for a solution how to get the polygon-vertices of my buffer-polygon where the linesegments have an angle <>180° to each other (see image below). enter image description here For start- and endpoint I just make a linear interpolation with 90° angle to the line direction.

Now i wonder how I could get the two points that are marked red in the picture? ( The orange line is my source line I would like to "buffer".) Note: I am not looking for a flat buffer tool but just for a pythonic solution how to get the vertexpoints that are marked in the picture. My first idea was to make parallel lines to my source line, elongate them if nesccessary and find the intersection but this seems a bit cumbersome.

Any ideas how to solve this with pyQGIS or some math.xxx magic?

Here a picture how it looks like at the moment if I just interpolate every vertex 5m with -90° to the line direction:

enter image description here

and here a picture how it should look like: enter image description here

closed as off-topic by mgri, Midavalo Apr 8 '17 at 14:23

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions seeking help to debug/write/improve code must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Providing a clear problem statement and evidence of a code attempt will help others to help you. See: How to create a Minimal, Complete, and Verifiable example." – mgri, Midavalo
If this question can be reworded to fit the rules in the help center, please edit the question.

  • Combining grass:v.parallel and saga:convertlinestopolygons (both processing methods) in a PyQGIS code, it is possible to accomplish this task. Please, see my answer. – xunilk Mar 7 '17 at 19:35
  • Not strictly pyqgis but do these lend any help? 1 2 – GISKid Mar 9 '17 at 15:51
  • In the first figure you marked that you want the distance between the red points and the vertex to be 5m? I'm sure that is not possible if your buffered line runs parallel to the original line with a distance of 5m (right-angled triangle property). Can you clarify this please? – nash Mar 9 '17 at 15:54
  • @nash no, the distance can be more than 5m depending on the angle. Therefore I wrote a questionmark after the 5m but I should replace the image as it's misleading. – markgraeflerland Mar 9 '17 at 16:09
  • 1
    @GISKid I tried all the methods before but they didn't work for my dataset. So I want to write a pythonic solution – markgraeflerland Mar 9 '17 at 16:11
4

Combining grass:v.parallel and saga:convertlinestopolygons (both processing methods) in a PyQGIS code, it is possible to accomplish this task. For this situation:

enter image description here

and this code:

import processing

layer = processing.getObjectFromName('my_line1')

extent = layer.extent()

xmin, ymin, xmax, ymax = extent.toRectF().getCoords()

distance = 5

path = processing.runalg('grass:v.parallel',
                         layer,      #input <ParameterVector>
                         distance,   #distance <ParameterNumber>
                         distance,   #minordistance <ParameterNumber>
                         0,          #angle <ParameterNumber>
                         2,          #side <ParameterSelection>
                         1,          #tolerance <ParameterNumber>
                         False,      #-r <ParameterBoolean>
                         True,       #-b <ParameterBoolean>
                         "%f,%f,%f,%f" % (xmin, xmax, ymin, ymax), #GRASS_REGION_PARAMETER <ParameterExtent>
                         -1,         #GRASS_SNAP_TOLERANCE_PARAMETER <ParameterNumber>
                         0,          #GRASS_MIN_AREA_PARAMETER <ParameterNumber>
                         2,
                         None)

output = QgsVectorLayer(path['output'],
                        'buffer',
                        'ogr')

path = processing.runalg('saga:convertlinestopolygons',
                         output,
                         None)

buffer = QgsVectorLayer(path['POLYGONS'],
                        'buffer',
                        'ogr')

QgsMapLayerRegistry.instance().addMapLayer(buffer)

after running it at the Python Console de PyQGIS, I got:

enter image description here

  • Thanks but i am looking for a solution where I get flat buffers without endcaps. Apart from that i get some strange artefacts if I use v.parallel: i.stack.imgur.com/tgaVT.jpg – markgraeflerland Mar 8 '17 at 8:26
1

The Shapely geometry library has the necessary tools to do what you're looking for. In particular the buffer() function accepts a parameter that tells it to calculate "butt" ends on the lines. Something like this should work:

import shapely.wkb
from shapely.geometry import CAP_STYLE
from shapely.geometry import JOIN_STYLE

# For testing, get the first geometry of the active layer
qgisLine = iface.activeLayer().getFeatures().next().geometry()
line = shapely.wkb.loads(qgisLine.asWkb())

# First parameter is buffer distance.
# "resolution" is ignored in this case, but would be used to
# approximate rounded corners if join_style were different.
poly = line.buffer(5.0, resolution=16, \
    cap_style=CAP_STYLE.flat, \
    join_style=JOIN_STYLE.mitre)

You'd need to add a little bit of Python glue code to convert the poly back to a feature.

Also note that Shapely may not be installed by default. On my (Fedora) machine, I had to install the python-shapely package.

  • Thank, but I am not looking for a flat-end-buffer tool but just for a solution how to get the vertices marked red in my picture. I have already written a QGIS plugin for which I need a pythonic solution to get the marked vertices – markgraeflerland Mar 9 '17 at 19:28

Not the answer you're looking for? Browse other questions tagged or ask your own question.