Distancia entre el centroide y el punto más alejado del polígono

12

Tengo una capa de polígono de pueblo que tiene más de 6,00,000 registros. He calculado el centroide de cada pueblo. Quiero encontrar la distancia entre el centroide y el nodo más alejado de cada polígono. Verifique la imagen a continuación para referencia. Las líneas negras son límites poligonales. ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Divya
fuente
interesante ... Acabo de hacer este viernes con postgis para producir un círculo alrededor de un polígono. Necesito unos minutos para buscar el código que usé .. i.stack.imgur.com/EKnkg.png
kttii
1
Primero, es posible que necesitemos saber qué programas tiene a su disposición. Además, ¿cómo creaste estos centroides y nodos? (Incluso si parece un poco obvio que los nodos en los polígonos son los que se usan para establecer los límites de sus formas, pero ¿agregó un punto adicional encima de estos?)
Moreau Colin
¿Es importante la ubicación del centroide? ¿Cómo los creaste?
GISGe
Posible duplicado - gis.stackexchange.com/questions/133099/…
klewis
Si el centroide es verdaderamente central, entonces es el radio del círculo más pequeño centrado en ese punto que se ajusta al polígono ( en.wikipedia.org/wiki/Smallest-circle_problem )
Mark Ireland

Respuestas:

15

Usando PostGIS, usé ST_ConvexHull para simplificar el polígono para un resultado más rápido:

Obtenga el punto más alejado:

SELECT Villages_v4_Trial_region.geom as FarPoint from (
SELECT ST_PointN(ST_ExteriorRing(ST_ConvexHull(Villages_v4_Trial_region.geom)),
generate_series(1, ST_NPoints(ST_ExteriorRing(ST_ConvexHull(Villages_v4_Trial_region.geom))))) as points, 
geom
FROM Villages_v4_Trial_region
ORDER BY ST_MaxDistance(points,ST_Centroid(Villages_v4_Trial_region.geom)) DESC
LIMIT 1;

Y si está interesado en crear un círculo desde el centroide:

SELECT ST_Buffer(Center,ST_Distance(Center,FarPoint)) as Circle
FROM (
SELECT Villages_v4_Trial_region.geom as FarPoint, Center from (
    SELECT ST_PointN(ST_ExteriorRing(ST_ConvexHull(Villages_v4_Trial_region.geom)),
    generate_series(1, ST_NPoints(ST_ExteriorRing(ST_ConvexHull(Villages_v4_Trial_region.geom))))) as points,
    ST_Centroid(Villages_v4_Trial_region.geom) as Center, 
    geom
    FROM Villages_v4_Trial_region
    ) as Villages_v4_Trial_region
    ORDER BY ST_MaxDistance(points,Center) DESC
    LIMIT 1) as foo;

ingrese la descripción de la imagen aquí

kttii
fuente
Simple, rápido, eficiente. Gracias por publicar esto porque esto también me ayudará en lo que estoy trabajando en este momento.
Moreau Colin
@kttii No sé cómo usar PostGIS. ¿Puede proporcionar una solución más simple, en arco o información de mapa o qgis
Divya
@kttii Así que instalé Postgresql. Copié y pegué esta consulta exacta pero dio un ERROR: la columna "the_geom" no existe. ¿Qué debo hacer?
Divya
the_geom debe ser reemplazado por su nombre de campo de geometría. Tendría que poner sus datos en PostgreSQL también. PostgreSQL es una base de datos como MSSQL. PostGIS es una extensión para hacer que la base de datos sea espacialmente consciente y proporcionar todas las funciones ST_.
kttii
@kttii Actualicé el nombre del campo de the_geom a "gid" en mi base de datos. Después de ejecutar la consulta nuevamente, obtuve este ERROR: la función st_convexhull (entero) no existe
Divya
4

Usando el siguiente código PyQGIS :

from math import sqrt

layer = iface.activeLayer()

feats = [ feat for feat in layer.getFeatures() ]

n = len(feats)

centroids = [ feat.geometry().centroid().asPoint() for feat in feats ]
polygons = [ feat.geometry().asPolygon()[0] for feat in feats ]

lengths = []

for i, pol in enumerate(polygons):
    max_dist = 0
    idx_j = 0
    for j, point in enumerate(pol):
        dist = sqrt(centroids[i].sqrDist(point))
        if dist > max_dist:
            max_dist = dist
            idx_j = j
    print i, idx_j, max_dist
    lengths.append([centroids[i], pol[idx_j]])

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

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

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

prov = mem_layer.dataProvider()

feats = [ QgsFeature() for i in range(n) ]

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

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

y este archivo de forma (con 11 características):

ingrese la descripción de la imagen aquí

Obtuve una capa de memoria donde las polilíneas eran la distancia entre el centroide y el punto más alejado de cada polígono (entidad); como se puede observar en la siguiente imagen:

ingrese la descripción de la imagen aquí

En la consola Python de QGIS, también se imprimió el índice de característica, el índice de punto en característica donde la distancia desde el centroide es máxima y, finalmente, la distancia máxima.

ingrese la descripción de la imagen aquí

xunilk
fuente
No sé cómo usar PyQGIS. ¿Puede proporcionar una solución más simple, en arco o información de mapa o qgis
Divya
1
Pruebe este enlace para obtener ayuda para comenzar a usar PyQgis spatialgalaxy.net/2014/10/09/…
kttii
0

Como parece que estás usando MapInfo, aquí hay una función MapBasic que escribí hace un tiempo para una herramienta interna en la que estaba trabajando. Toma un nodo de origen (su punto centroide) y un objeto de región (el polígono) como argumentos y devuelve un objeto de punto en el nodo más alejado del polígono desde el punto de origen.

Function GetFurthest(ByVal oNode1 as Object, ByVal oObj as Object) as Object

Dim sourceE,sourceN,East,North,Longest,Dist as Float,
    nNodes,nPolys,i,j as SmallInt,
    oNode2 as Object

    sourceE = CentroidX(oNode1)
    sourceN = CentroidY(oNode1)
    Longest = 0

    nPolys = ObjectInfo(oObj,OBJ_INFO_NPOLYGONS)
    For i = 1 to nPolys
        nNodes = ObjectInfo(oObj,OBJ_INFO_NPOLYGONS+nPolys)
        For j = 1 to nNodes
            East = ObjectNodeX(oObj,i,j)
            North = ObjectNodeY(oObj,i,j)
            Dist = Distance(sourceE,sourceN,East,North,"m")
            If Dist > Longest then
                Longest = Dist
                oNode2 = CreatePoint(East,North)
            End if
        Next
    Next

    GetFurthest = oNode2

End Function
Tocino
fuente