Centroid ile çokgenin en uzak noktası arasındaki mesafe


12

6,00.000'den fazla kaydı olan bir köy çokgen katmanım var. Her köyün sentroidini hesapladım. Her çokgenin centroid ve en uzak düğümü arasındaki mesafeyi bulmak istiyorum. Referans için aşağıdaki resme bakın. Siyah çizgiler çokgen sınırlardır. resim açıklamasını buraya girin

resim açıklamasını buraya girin

resim açıklamasını buraya girin


ilginç ... Bu cuma sadece bir çokgenin etrafında bir daire oluşturmak için postgis ile yaptım. Kullandığım
kttii

1
Öncelikle emrinizde olan programları bilmemiz gerekebilir. Ayrıca, bunun sentroidlerini ve düğümlerini nasıl yarattınız? (Çokgenler üzerindeki düğümlerin, şekillerinizin sınırlarını ayarlamak için kullanılanlar olduğu biraz açık gibi görünse de, bu noktaların üzerine ek nokta eklediniz mi?)
Moreau Colin

Centroidin yeri önemli mi? Onları nasıl yarattın?
GISGe


Eğer sentroid gerçekten merkezi ise, o zaman çokgene uyan en küçük dairenin yarıçapıdır ( en.wikipedia.org/wiki/Smallest-circle_problem )
Mark Ireland

Yanıtlar:



15

PostGIS kullanarak, daha hızlı bir sonuç için çokgeni basitleştirmek için ST_ConvexHull kullandım:

En uzak noktayı alın:

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;

Ve eğer sentroidden bir Çember oluşturmak istiyorsanız:

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;

resim açıklamasını buraya girin


Basit, hızlı, verimli. Bunu yayınladığınız için teşekkür ederim, çünkü bu şu anda üzerinde çalıştığım şeyde bana yardımcı olacak.
Moreau Colin

@kttii PostGIS'i nasıl kullanacağımı bilmiyorum. Ark veya mapinfo veya qgis'de daha basit bir çözüm sunabilir misiniz?
Divya

@kttii Bu yüzden Postgresql'i kurdum. Bu tam sorguyu kopyaladım ama bir HATA verdi: sütun "the_geom" yok. Ben ne yaparım?
Divya

the_geom yerine geometri alan adınız kullanılmalıdır. Verilerinizi PostgreSQL'e de koymanız gerekir. PostgreSQL, MSSQL gibi bir veritabanıdır. PostGIS, veritabanını mekansal olarak bilinçlendirmek ve tüm ST_ işlevlerini sağlamak için bir uzantıdır.
kttii

@kttii Veritabanımdaki alan adını the_geom'dan "gid" olarak güncelledim. Sorguyu yeniden çalıştırdıktan sonra, bu HATA var: işlev st_convexhull (integer) mevcut değil
Divya

4

Sonraki PyQGIS kodunu kullanarak :

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)

ve bu şekil dosyası (11 özellikli):

resim açıklamasını buraya girin

Polinillerin her bir çokgenin (özellik) centroid ve en uzak noktası arasındaki mesafe olduğu bir bellek katmanım var; bir sonraki resimde görülebileceği için:

resim açıklamasını buraya girin

QGIS Python Konsolu'nda, özellik indeksi, sentroidden uzaklığın maksimum ve son olarak maksimum mesafe olduğu özellikteki nokta indeksi de yazdırıldı.

resim açıklamasını buraya girin


PyQGIS'i nasıl kullanacağımı bilmiyorum. Ark veya mapinfo veya qgis'de daha basit bir çözüm sunabilir misiniz?
Divya

1
PyQgis'i kullanmaya başlama
kttii

0

MapInfo kullandığınız gibi, işte çalıştığım bir şirket içi araç için bir süre önce yazdığım bir MapBasic işlevi. Bir kaynak düğümü (sentroid noktanız) ve bir bölge nesnesini (çokgen) bağımsız değişken olarak alır ve çokgendeki en uzak düğümde kaynak noktasından bir nokta nesnesi döndürür.

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.