Расстояние между центроидом и самой дальней точкой многоугольника


12

У меня есть слой многоугольника села, в котором более 60000 записей. Я рассчитал центр тяжести каждой деревни. Я хочу найти расстояние между центроидом и самым дальним узлом каждого многоугольника. Проверьте изображение ниже для справки. Черные линии - это границы многоугольника. введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь


интересно ... Я только что сделал эту пятницу с Postgis, чтобы создать круг вокруг многоугольника. Мне нужно несколько минут, чтобы найти код, который я использовал .. i.stack.imgur.com/EKnkg.png
kttii

1
Сначала нам может понадобиться узнать, какие программы у вас есть в вашем распоряжении. Кроме того, как вы создали эти центроиды и узлы? (Даже если кажется немного очевидным, что узлы на многоугольниках - это те, которые используются для установки границ ваших фигур, но вы добавили дополнительную точку над этими цифрами?)
Моро Колин

Важно ли расположение центроида? Как вы их создали?
GISGe

Возможный дубликат - gis.stackexchange.com/questions/133099/…
klewis

Если центроид действительно является центральным, то это радиус наименьшего круга с центром в этой точке, который соответствует многоугольнику ( en.wikipedia.org/wiki/Smallest-circle_problem )
Марк Ирландия,

Ответы:



15

Используя PostGIS, я использовал ST_ConvexHull, чтобы упростить полигон для более быстрого результата:

Получите самый дальний пункт:

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;

И если вы заинтересованы в создании круга из центроида:

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;

введите описание изображения здесь


Просто, быстро, эффективно. Спасибо, что опубликовали это, потому что это тоже поможет мне в том, над чем я сейчас работаю.
Моро Колин

@kttii Я не знаю, как использовать PostGIS. Можете ли вы предоставить более простое решение, в arc или mapinfo или qgis
Divya

@kttii Итак, я установил Postgresql. Я скопировал этот точный запрос, но он дал ОШИБКУ: столбец "the_geom" не существует. Что мне делать?
Divya

the_geom должен быть заменен вашим именем поля геометрии. Вам также необходимо поместить свои данные в PostgreSQL. PostgreSQL - это база данных, подобная MSSQL. PostGIS - это расширение для пространственной осведомленности базы данных и обеспечения всех функций ST_.
kttii

@kttii Я обновил имя поля с the_geom до «gid» в моей базе данных. После повторного выполнения запроса я получил эту ОШИБКУ: функция st_convexhull (integer) не существует
Divya

4

Используя следующий код 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)

и этот шейп-файл (с 11 функциями):

введите описание изображения здесь

Я получил слой памяти, где полилинии были расстоянием между центроидом и самой дальней точкой каждого многоугольника (особенность); как это можно увидеть на следующем изображении:

введите описание изображения здесь

На консоли Python QGIS также был напечатан индекс объекта, индекс точки объекта, где расстояние от центроида является максимальным и, наконец, максимальное расстояние.

введите описание изображения здесь


Я не знаю, как использовать PyQGIS. Можете ли вы предоставить более простое решение, в arc или mapinfo или qgis
Divya

1
Попробуйте эту ссылку, чтобы получить помощь по началу работы
kttii

0

Похоже, что вы используете MapInfo, вот функция MapBasic, которую я написал некоторое время назад для внутреннего инструмента, над которым я работал. Он принимает исходный узел (вашу точку центроида) и объект области (многоугольник) в качестве аргументов и возвращает точечный объект в самом дальнем узле многоугольника из исходной точки.

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.