2

I'm trying to create a model on QGIS 2.18.4 which will allow me to create multiple fixed distance buffers on a selected point(500m, 1km, 2km, 3km,...,50km) with a few clicks, rather than having to do it one by one using the MMQGIS Create Buffer function.

Because I'm working on WGS84, my solution below reprojects the selected point to World Equidistant Conic which uses meters as its distance unit. I then create the buffers, then reproject the created buffers back to WGS84.

Screenshot of my model

My question is, why does my final output appear different from when I create it with MMQGIS? (See screenshot of Singapore below. Purple circle is a 5km buffer I've created using MMQGIS, and the blue circle is what I've created using my model.) I've looked at the MMQGIS python code (see code below) and it appears to apply the same workflow and CRS I've used in my model.

Screenshot of outputs

def mmqgis_buffer_geometry(geometry, meters):
if meters <= 0:
    return None

# To approximate meaningful meter distances independent of the original CRS,
# the geometry is transformed to an azimuthal equidistant projection
# with the center of the polygon as the origin. After buffer creation,
# the buffer is transformed to WGS 84 and returned. While this may introduce
# some deviation from the original CRS, buffering is assumed in practice
# to be a fairly inexact operation that can tolerate such deviation

wgs84 = QgsCoordinateReferenceSystem()
wgs84.createFromProj4("+proj=longlat +datum=WGS84 +no_defs")

latitude = str(geometry.centroid().asPoint().y())
longitude = str(geometry.centroid().asPoint().x())

#proj4 = "+proj=aeqd +lat_0=" + str(geometry.centroid().asPoint().y()) + \
#   " +lon_0=" + str(geometry.centroid().asPoint().x()) + \
#   " +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"

# For some reason, Azimuthal Equidistant transformation noticed to not be
# working on 10 July 2014. World Equidistant Conic works, but there may be errors.
proj4 = "+proj=eqdc +lat_0=0 +lon_0=0 +lat_1=60 +lat_2=60 " + \
    "+x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"

azimuthal_equidistant = QgsCoordinateReferenceSystem()
azimuthal_equidistant.createFromProj4(proj4)

transform = QgsCoordinateTransform(wgs84, azimuthal_equidistant)
geometry.transform(transform)

newgeometry = geometry.buffer(meters, 7)

wgs84 = QgsCoordinateReferenceSystem()
wgs84.createFromProj4("+proj=longlat +datum=WGS84 +no_defs")

transform = QgsCoordinateTransform(azimuthal_equidistant, wgs84)
newgeometry.transform(transform)

return newgeometry


def mmqgis_buffer_point(point, meters, edges, rotation_degrees):
if (meters <= 0) or (edges < 3):
    return None

# Points are treated separately from other geometries so that discrete
# edges can be supplied for non-circular buffers that are not supported
# by the QgsGeometry.buffer() function

wgs84 = QgsCoordinateReferenceSystem()
wgs84.createFromProj4("+proj=longlat +datum=WGS84 +no_defs")

# print "Point " + unicode(point.x()) + ", " + unicode(point.y()) + " meters " + unicode(meters)

polyline = []
for edge in range(0, edges + 1):
    degrees = ((float(edge) * 360.0 / float(edges)) + rotation_degrees) % 360
    polyline.append(mmqgis_endpoint(point, meters, degrees))

return QgsGeometry.fromPolygon([polyline])

Why is this happening? What can I do to get the same result as when using MMQGIS?

2
  • In which CRS is your image and which one of the buffers has the correct width?
    – user30184
    Jan 12, 2018 at 7:13
  • @user30184 The image is in wgs84. The purple buffer (created with MMQGIS) has the right width.
    – sjp_1989
    Jan 12, 2018 at 7:19

1 Answer 1

0

I think the difference is that the MMQGIS code takes the shapes centeroid as the origin for reprojection, whereas your model will take the north and south poles. Therefore, you'd only get a truly circular buffer at the equator.

Instead try projecting to SVY21 / Singapore TM EPSG: 3414, a Cartesian coordinate system for Singapore that uses meters as it's units. Then reproject back to WGS84

3
  • That seems to work, but my next question would be: where in the MMQGIS code does it do what you said it does? It appears that in the past the plugin was reprojecting to Azimuthal Equidistant with the geometry centroid as the origin, but now it appears to be using World Equidistant Conic using the poles.
    – sjp_1989
    Jan 15, 2018 at 1:13
  • I misread the code the first time. There is a separate function for buffering points {mmqgis_buffer_point(point, meters, edges, rotation_degrees)}. This doesn't use any of the re-projection code Jan 15, 2018 at 9:13
  • Ah yes, upon closer inspection, it appears there is another function which uses the Haversine formula to calculate the points along the buffer line, then joins the points together! I should be able to throw something together using this. Thanks!
    – sjp_1989
    Jan 16, 2018 at 3:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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