Tengo algunos edificios que fueron rápidamente digitalizados a partir de una imagen aérea. Como puedes ver, la mayoría de los polígonos no son rectangulares. ¿Cómo puedo modificar los polígonos para hacerlos más rectangulares? ¿Hay alguna ecuación que pueda resolver un rectángulo a partir de un grupo de puntos? No quiero volver a digitalizar los polígonos. Se supone que los polígonos representan edificios. Estoy usando Qgis.
Respuestas
¿Demasiados anuncios?El siguiente código usa la geometría analítica para cambiar cada polígono cuasi rectangular en rectangular y podría ser usado:
layer = iface.activeLayer()
feats = [ feat for feat in layer.getFeatures() ]
n = len(feats)
crs = layer.crs()
epsg = crs.postgisSrid()
uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"
mem_layer = QgsVectorLayer(uri,
'rectangle',
'memory')
prov = mem_layer.dataProvider()
for feature in feats:
geom = feature.geometry()
xmin, ymin, xmax, ymax = geom.boundingBox().toRectF().getCoords()
points = feature.geometry().asPolygon()[0]
for i in range(len(points)-1):
if points[i][1] == ymax and points[i+1][1] < points[i][1]:
idx = i
if points[i][1] == ymax and points[i-1][1] < points[i][1]:
idx = i-1
rectangle = []
#x,y coordinates of first point
x1 = points[idx][0]
y1 = points[idx][1]
rectangle.append(QgsPoint(x1,y1))
#x,y coordinates of second point
x2 = points[idx+1][0]
y2 = points[idx+1][1]
rectangle.append(QgsPoint(x2,y2))
#slope for first line
m1 = (y2 - y1) / (x2 - x1)
#intercept at origin for first line
int1 = y1 - m1 * x1
#slope for second line
m2 = m1
#x,y coordinates of third point
x3 = points[idx+2][0]
y3 = points[idx+2][1]
#intercept at origin for second line
int2 = y3 - m2 * x3
#first perpendicular
m3 = -1/m1
#intercept at origin for second line
int3 = y2 - m3 * x2
#intersect point
x4 = (int3 - int2)/(m2 - m3)
y4 = m3*x4 + int3
rectangle.append(QgsPoint(x4, y4))
#second perpendicular
m4 = -1/m1
#intercept at origin for second perpendicular
int4 = y1 - m4 * x1
#intersect point
x5 = (int4 - int2)/(m2 - m4)
y5 = m4*x5 + int4
rectangle.extend([QgsPoint(x5, y5),QgsPoint(x1, y1)])
polygon = []
polygon.append(rectangle)
geom = QgsGeometry.fromPolygon(polygon)
feat = QgsFeature()
feat.setAttributes([i])
feat.setGeometry(geom)
prov.addFeatures( [feat] )
QgsMapLayerRegistry.instance().addMapLayer(mem_layer)
Lo probé con el shapefile de la siguiente imagen:
Después de ejecutar el código en la consola Python de QGIS que obtuve:
Puedes intentar usar el siguiente enfoque que cambia la geometría basada en el cuadro delimitador y el ángulo del primer borde digitalizado. Por supuesto, puedes alterar el ángulo con el del borde más largo o algo así. Sólo funciona bien cuando tus polígonos ya son casi rectangulares (como parece).
La entrada en la consola en Qgis y la capa debe ser seleccionada y editada:
import shapely
from shapely import affinity
from shapely.wkb import loads
layer = qgis.utils.iface.activeLayer()
for feature in layer.getFeatures():
azimuth = feature.geometry().vertexAt(0).azimuth(feature.geometry().vertexAt(1))
bbox = QgsGeometry.fromRect(feature.geometry().boundingBox())
input = loads(bbox.asWkb())
shape = shapely.geometry.asShape(input)
rotated = affinity.rotate(shape, azimuth-90.0)
new_geom = QgsGeometry.fromWkt(rotated.wkt)
layer.changeGeometry(feature.id(),new_geom)
Para cada polígono de 4 vértices:
Calcule una estimación del centro del rectángulo, C, como la media de los 4 vértices.
Calcular una estimación de la longitud diagonal del rectángulo, R, como la media de las cuatro distancias desde el centro estimado hasta cada punto multiplicada por dos.
Calcular una estimación del ángulo de rotación del rectángulo tomando la media del ángulo de la línea entre los puntos 1 y 3 y entre los puntos 2 y 4. O posiblemente la media de (la media del ángulo entre (1 y C) y (C y 3)) y (la media del ángulo entre (2 y C) y (4 y C). Básicamente una estimación del ángulo a mitad de camino entre las dos diagonales.
Calcular la relación de aspecto del rectángulo calculando el promedio de los ángulos sin signo de una línea desde cada punto hasta el punto central y el ángulo de rotación. Así que si el rectángulo es cuadrado, esto es 45 grados.
Calcular los cuatro puntos a partir del conocimiento del centro, la longitud diagonal, la relación de aspecto y el ángulo de rotación.
Creo que esto es robusto para cualquier arreglo convexo de cuatro puntos... No sé qué podría hacer si se le da un polígono cóncavo...
Si hay alguna posibilidad de que puedas descargar tus datos de muestra, podría intentar codificar esto en ....