Rotar un vectorial tipo polígono, dados el ángulo y el eje de rotación, con PyQGIS

Uno de los aspectos que generalmente NO se encuentran implementados por default en los SIG son las características tipo CAD; como por ejemplo rotar capas vectoriales. Para este tipo de procedimientos, en los SIG, se emplean los conceptos del álgebra lineal donde primero es necesario realizar una translación del eje de coordenadas (0,0) al eje de rotación. Después, se lleva a cabo la rotación para cada punto individual y, finalmente, la recomposición de cada punto rotado al sistema de referencia con eje (0,0); dependiendo del tipo de geometría considerado (punto, línea o polígono).

En nuestro curso de PyQGIS, abordaremos todas las cuestiones fundamentales relativas al manejo de datos Raster con Python y QGIS. Además, también tratamos la temática relativa a PyQGIS para el manejo de datos vectoriales y una introducción a la creación de plugins mediante el ‘Plugin Builder’.

PRÓXIMA SESIÓN EL 20 DE OCTUBRE

Si se quiere, por ejemplo, implementar la rotación de un vectorial tipo polígono en PyQGIS hay que establecer el eje de rotación (un QgsPoint) y el ángulo a rotar. Como lo usual es suministrar este valor en grados sexasegimales hay que establecer la conversión de éstos a radianes para ser empleados en las correspondientes funciones trigonométricas que dan cuenta de la rotación.

A continuación, se itera sobre cada rasgo para obtener su geometría y, en consecuencia, los QgsPoint sobre los cuales aplicar la función de rotación; que también sistematiza los cambios del sistema de referencia que haya lugar. Para la recomposición de los puntos se considera una lista anidada con el formato requerido para un vectorial tipo polígono y se pasa como parámetro a una función, junto con el sistema de referencia para las coordenadas, para producir una memory layer. El código propuesto es el siguiente:

from math import sin, cos, pi

def rotatePoints(axis, r_angle, points):
        
    points_rot = []
    
    for point in points:
        tr = QgsPoint( point.x() - axis.x(), point.y() - axis.y() )
        xrot = tr.x()*cos(r_angle*(pi/180)) - tr.y()*sin(r_angle*(pi/180))  
        yrot = tr.x()*sin(r_angle*(pi/180)) + tr.y()*cos(r_angle*(pi/180)) 
        xnew = xrot + axis.x()
        ynew = yrot + axis.y()
        points_rot.append(QgsPoint(xnew,ynew))
        
    return points_rot

def createPolygonMemoryLayer(epsg, pol_rot):
    CRS = QgsCoordinateReferenceSystem(epsg)

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

    mem_layer = QgsVectorLayer(uri,
                               "Polygon",
                               "memory")

    QgsMapLayerRegistry.instance().addMapLayer(mem_layer)
 
    mem_layer.startEditing()
        
    feature = [] 

    n = len(pol_rot)
        
    #Set feature
    for i in range(n):
        feat = QgsFeature()
        feature.append(feat)
        
    #Set geometry
    for i in range(n):
        feature[i].setGeometry(QgsGeometry.fromPolygon(pol_rot[i]))
        #set attributes values
        feature[i].setAttributes([i])
        mem_layer.addFeature(feature[i], True)

    #stop editing and save changes
    mem_layer.commitChanges()

#Code starts here

layer = iface.activeLayer()

crs = layer.crs()
epsg = crs.postgisSrid()

features = layer.getFeatures()

geom = []

for feature in features:
    geom.append(feature.geometry().asPolygon())
    
points = geom

n = layer.featureCount()

pol_rot = [[] for i in range(n)]

axis = QgsPoint(416047.568418, 4443411.85665)

r_angle = 70
    
for i in range(n):
    points_rot = rotatePoints(axis, r_angle, points[i][0])
    pol_rot[i].append(points_rot)

createPolygonMemoryLayer(epsg, pol_rot)

El código anterior se ejecuta siempre en la Python Console para un eje y un ángulo de rotación fijos de (416047.568418, 4443411.85665) y 70 grados; respectivamente. El resultado sobre una rejilla de 12 filas x 25 columnas (300 features) se tiene en la imagen siguiente:

rotado1

Observe que en la tabla de atributos de la memory layer se han seleccionado algunos rasgos al azar para corroborar que la recomposición de ésta se ejecuto de manera satisfactoria.

Por otra parte, este código se incluyó en un plugin para generalizar el mismo proceso; tal como se visualiza en la imagen a continuación:

rotados2

Aquí podemos cambiar a voluntad el eje (que puede ser capturado también con un simple click del ratón) y el ángulo de rotación.

En nuestro curso de PyQGIS se contemplan con detalle el desarrollo de éste y otros plugins mediante el empleo de ‘Plugin Builder’.

PRÓXIMA SESIÓN EL 20 DE OCTUBRE

Esta entrada fue publicada en PyQGIS, QGIS, SIG, Software Libre. Guarda el enlace permanente.

2 respuestas a Rotar un vectorial tipo polígono, dados el ángulo y el eje de rotación, con PyQGIS

  1. Pingback: Rotar un vectorial tipo línea, dados el ángulo y el eje de rotación, con PyQGIS | El Blog de José Guerrero

  2. Pingback: Rotación de archivos vectoriales con método ‘rotate’ de QgsGeometry en PyQGIS | El Blog de José Guerrero

Responder

Por favor, inicia sesión con uno de estos métodos para publicar tu comentario:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s