Tengo una función que crea paneles fotovoltaicos solares representados como polígonos. Básicamente, crea una cuadrícula rectangular donde el usuario puede especificar los siguientes parámetros:
- Longitud
- Anchura
- Distancia horizontal
- Distancia vertical
El código se basa en el complemento FeatureGridCreator pero se centra solo en el aspecto del polígono. Funciona bien en su mayor parte, especialmente cuando se crean polígonos con grandes dimensiones (por ejemplo, 10 m de largo y ancho; 10 m de distancia horizontal y vertical).
Pero noté un par de problemas:
Al especificar polígonos para dimensiones inferiores a 2 m para longitud y anchura, no se crearon polígonos.
Al especificar polígonos con diferentes dimensiones (por ejemplo, 5 m de largo y 7 m de ancho), las dimensiones no eran las mismas cuando se midieron con la herramienta Medir línea . Para estas dimensiones, se demostró que la longitud y el ancho eran de 4 my 6 m respectivamente.
El CRS utilizado tanto para la proyección como para la capa es EPSG: 27700, aunque no hubiera pensado que esto sería un problema.
Entonces, ¿alguien tiene alguna idea de lo que podría estar causando estos problemas? También estoy abierto a sugerencias sobre cómo se podría mejorar el código o incluso reemplazarlo por una mejor alternativa.
Aquí está el código que se puede reproducir en la Consola Python , se debe seleccionar una capa de polígono con un CRS relevante antes de ejecutar la función:
from PyQt4.QtCore import QVariant
from math import ceil
def generate_pv_panels(length, width, distance_x, distance_y):
# Define layer properties
layer = iface.activeLayer()
crs = layer.crs()
memory_lyr = QgsVectorLayer("Polygon?crs=epsg:" + unicode(crs.postgisSrid()) + "&index=yes", "PV panels for " + str(layer.name()), "memory")
QgsMapLayerRegistry.instance().addMapLayer(memory_lyr)
memory_lyr.startEditing()
provider = memory_lyr.dataProvider()
provider.addAttributes([QgsField("ID", QVariant.Int)])
fid = 0
start_x = 0
start_y = 0
# Ensure polygons are not created 'within each other'
if distance_x < (length / 1000):
distance_x = (length / 1000)
if distance_y < (width / 1000):
distance_y = (width / 1000)
fts = []
for f in layer.getFeatures():
fid += 1
bbox = f.geometry().boundingBox()
start_x = bbox.xMinimum() + float(distance_x / 2)
start_y = bbox.yMinimum() + float(distance_y / 2)
for row in range(0, int(ceil(bbox.height() / distance_y))):
for column in range(0, int(ceil(bbox.width() / distance_x))):
fet = QgsFeature()
geom_type = pv_panel_size(length, width, start_x, start_y)
if f.geometry().contains(geom_type):
fet.setGeometry(geom_type)
fet.setAttributes([fid])
fts.append(fet)
start_x += distance_x + (length / 1000)
start_x = bbox.xMinimum() + float(distance_x / 2)
start_y += distance_y + (width / 1000)
provider.addFeatures(fts)
memory_lyr.updateFields()
memory_lyr.commitChanges()
def pv_panel_size(length, width, x, y):
# Length & width measured in mm; x & y measured in m
l = length / 2000
w = width / 2000
return QgsGeometry.fromRect(QgsRectangle(x - l, y - w, x + l, y + w))
generate_pv_panels(10000, 10000, 100, 100)
Gracias a @radouxju , aquí está el código final que también tiene en cuenta que las distancias horizontal y vertical son cero:
Utilizando
generate_pv_panels(5500, 5000, 20, 1)
:Utilizando
generate_pv_panels(5500, 5000, 20, 0)
:fuente