lunes, 13 de noviembre de 2017

Generando buffer con ecuaciones paramétricas de la circunferencia y PyQGIS

En el artículo anterior se consideró como un ejercicio de programación la generación de un buffer empleando las ecuaciones cartesianas de la circunferencia. En este se van a emplear las ecuaciones paramétricas más que todo para ver que nos estamos "perdiendo" a la hora de usar las aplicaciones ya disponibles en los SIGs.

El código completo se encuentra a continuación:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
from math import pi, cos, sin

pt = (392127.908689, 4449521.71257)
r = 100

x0 = pt[0]
y0 = pt[1]

interv = 2*pi

parts = 20

add = interv/parts

t = 0

t_values = [ 0 ]

for i in range(parts-1):
    t += add
    t_values.append(t)

points = [ QgsPoint( x0 + r*cos(t), y0 + r*sin(t)) for t in t_values ]

epsg = 32612

uri = "Point?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'point',
                           'memory')

prov = mem_layer.dataProvider()

feats = [ QgsFeature() for i in range(len(points)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromPoint(points[i]))

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

points.append(points[0])

uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'line',
                           'memory')

prov = mem_layer.dataProvider()

line = [ points ]

feats = [ QgsFeature() for i in range(len(line)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromPolyline(line[i]))

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'polygon',
                           'memory')

prov = mem_layer.dataProvider()

polygon = [ [ points ] ]

feats = [ QgsFeature() for i in range(len(polygon)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromPolygon(polygon[i]))

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

y permite dividir radialmente una circunferencia de radio 100 metros y centro (392127.908689, 4449521.71257) en 20 partes iguales.

Después de ejecutado en la Python Console de QGIS se observa el siguiente resultado para las memory layers de puntos y circunferencia:


y este otro para la capa tipo polígono:


En la imagen anterior se puede observar claramente que no es una circunferencia perfecta sino mas bien un polígono de 20 lados.

Si se reduce el número de partes a 6 se obtiene un hexágono:


y a 5 un pentágono rotado [360/5]/4 grados con relación al simétrico (obtenido mediante un plugin especial); tal como se observa en la imagen siguiente:


Cuando la partición es par no hace falta rotación para obtener un polígono simétrico. Cuando es impar si queremos un polígono simétrico entonces hay que rotarlo [360/#partes]/4 grados en sentido horario o antihorario; dependiendo de si se quiere "apoyado" sobre un lado o sobre un vértice.


No hay comentarios: