Distance entre le centre de gravité et le point le plus éloigné du polygone


12

J'ai une couche de polygones de village qui compte plus de 6 000 000 enregistrements. J'ai calculé le centroïde de chaque village. Je veux trouver la distance entre le centroïde et le nœud le plus éloigné de chaque polygone. Vérifiez l'image ci-dessous pour référence. Les lignes noires sont les limites des polygones. entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici


intéressant ... Je viens de faire ce vendredi avec des postgis pour produire un cercle autour d'un polygone. J'ai besoin de quelques minutes pour chercher le code que j'ai utilisé .. i.stack.imgur.com/EKnkg.png
kttii

1
D'abord, nous pourrions avoir besoin de savoir quels programmes vous avez à votre disposition. Et comment avez-vous créé ces centroïdes et nœuds? (Même s'il semble un peu évident que les nœuds sur les polygones sont ceux utilisés pour définir les limites de vos formes, mais avez-vous ajouté un point supplémentaire au-dessus de ceux-ci?)
Moreau Colin

L'emplacement du centroïde est-il important? Comment les avez-vous créés?
GISGe


Si le centre de gravité est vraiment central, alors c'est le rayon du plus petit cercle centré sur ce point qui correspond au polygone ( en.wikipedia.org/wiki/Smallest-circle_problem )
Mark Ireland

Réponses:



15

En utilisant PostGIS, j'ai utilisé ST_ConvexHull pour simplifier le polygone pour un résultat plus rapide:

Obtenez le point le plus éloigné:

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;

Et si vous souhaitez créer un cercle à partir du centroïde:

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;

entrez la description de l'image ici


Simple, rapide, efficace. Merci d'avoir posté ceci car cela m'aidera aussi dans ce que je travaille en ce moment.
Moreau Colin

@kttii Je ne sais pas comment utiliser PostGIS. Pouvez-vous fournir une solution plus simple, en arc ou mapinfo ou qgis
Divya

@kttii J'ai donc installé Postgresql. J'ai copié-collé cette requête exacte mais elle a donné une ERREUR: la colonne "the_geom" n'existe pas. Que fais-je?
Divya

the_geom doit être remplacé par le nom de votre champ de géométrie. Vous devrez également mettre vos données dans PostgreSQL. PostgreSQL est une base de données comme MSSQL. PostGIS est une extension pour rendre la base de données sensible à l'espace et fournir toutes les fonctions ST_.
kttii

@kttii J'ai mis à jour le nom du champ de the_geom à "gid" dans ma base de données. Après avoir exécuté à nouveau la requête, j'ai eu cette ERREUR: la fonction st_convexhull (entier) n'existe pas
Divya

4

Utilisation du prochain code 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)

et ce fichier de formes (avec 11 fonctionnalités):

entrez la description de l'image ici

J'ai obtenu une couche de mémoire où les polylignes étaient la distance entre le centre de gravité et le point le plus éloigné de chaque polygone (entité); comme on peut le voir sur l'image suivante:

entrez la description de l'image ici

Sur la console Python de QGIS, il a également été imprimé l'index de l'entité, l'index du point dans l'entité où la distance du centroïde est une distance maximale et, finalement, maximale.

entrez la description de l'image ici


Je ne sais pas comment utiliser PyQGIS. Pouvez-vous fournir une solution plus simple, en arc ou mapinfo ou qgis
Divya

1
Essayez ce lien pour vous aider à démarrer avec PyQgis spatialgalaxy.net/2014/10/09/…
kttii

0

Comme il semble que vous utilisez MapInfo, voici une fonction MapBasic sur laquelle j'ai écrit il y a quelque temps pour un outil interne sur lequel je travaillais. Il prend un nœud source (votre point centroïde) et un objet région (le polygone) comme arguments et renvoie un objet point au nœud le plus éloigné du polygone à partir du point source.

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.