ระยะห่างระหว่างเซนทรอยด์กับจุดที่เป็นรูปหลายเหลี่ยมมากที่สุด


12

ฉันมีเลเยอร์รูปหลายเหลี่ยมของหมู่บ้านซึ่งมีมากกว่า 6,00,000 บันทึก ฉันคำนวณ centroid ของแต่ละหมู่บ้าน ฉันต้องการค้นหาระยะทางระหว่างเซนทรอยด์และโหนดที่ไกลที่สุดของรูปหลายเหลี่ยมแต่ละอัน ตรวจสอบภาพด้านล่างสำหรับการอ้างอิง เส้นสีดำเป็นขอบเขตรูปหลายเหลี่ยม ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่


ที่น่าสนใจ ... ฉันเพิ่งทำวันศุกร์กับไปรษณีย์เพื่อสร้างวงกลมรอบรูปหลายเหลี่ยม ฉันต้องใช้เวลาสองสามนาทีเพื่อค้นหารหัสที่ฉันใช้ .. i.stack.imgur.com/EKnkg.png
kttii

1
ก่อนอื่นเราอาจจำเป็นต้องรู้โปรแกรมที่คุณมีให้ นอกจากนี้คุณสร้าง centroids และโหนดเหล่านี้ได้อย่างไร (แม้ว่ามันจะค่อนข้างชัดเจนว่าโหนดในรูปหลายเหลี่ยมเป็นสิ่งที่ใช้ในการกำหนดขอบเขตของรูปร่างของคุณ แต่คุณเพิ่มจุด aditionnal ด้านบนของ thoses?)
Moreau Colin

ที่ตั้งของเซนทรอยด์นั้นสำคัญหรือไม่? คุณสร้างได้อย่างไร
GISGe

สำเนาซ้ำที่เป็นไปได้ - gis.stackexchange.com/questions/133099/…
klewis

ถ้าเซนทรอยด์เป็นศูนย์กลางอย่างแท้จริงนั่นก็คือรัศมีของวงกลมที่เล็กที่สุดที่อยู่ตรงกลางของจุดนั้นที่เหมาะกับรูปหลายเหลี่ยม ( en.wikipedia.org/wiki/Smallest-circle_problem )
Mark Ireland

คำตอบ:


3

ดูเหมือนว่าคุณกำลังทำงานกับ MapInfo "เครื่องคำนวณระยะทาง" (ค้นหาในเครื่องมือจัดการ) มีตัวเลือกมากมายและฉันคิดว่ามันสามารถจัดการงานนี้ได้เช่นกัน มีบทความเกี่ยวกับที่นี่: http://web.pb.com/mapinfopro-jul-2013/Toolbox-Distance-Calculator


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;

และถ้าคุณสนใจที่จะสร้าง Circle จาก Centroid:

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;

ป้อนคำอธิบายรูปภาพที่นี่


ง่ายรวดเร็วมีประสิทธิภาพ ขอบคุณสำหรับการโพสต์สิ่งนี้เพราะมันจะช่วยฉันด้วยในสิ่งที่ฉันกำลังทำอยู่ตอนนี้
Moreau Colin

@kttii ฉันไม่รู้วิธีใช้ PostGIS คุณสามารถให้วิธีแก้ปัญหาที่ง่ายกว่าในส่วนโค้งหรือ mapinfo หรือ qgis ได้ไหม
Divya

@kttii ดังนั้นฉันจึงติดตั้ง Postgresql ฉันคัดลอกแบบสอบถามที่แน่นอนนี้แล้ว แต่มันทำให้คอลัมน์ข้อผิดพลาด: "the_geom" ไม่มีอยู่ ฉันจะทำอย่างไร
Divya

the_geom ควรถูกแทนที่ด้วยชื่อฟิลด์เรขาคณิตของคุณ คุณจะต้องใส่ข้อมูลของคุณลงใน PostgreSQL เช่นกัน PostgreSQL เป็นฐานข้อมูลเช่น MSSQL PostGIS เป็นส่วนเสริมเพื่อให้ฐานข้อมูลรับรู้เชิงพื้นที่และจัดเตรียมฟังก์ชัน ST_ ทั้งหมด
kttii

@kttii ฉันอัปเดตชื่อฟิลด์จาก the_geom เป็น "gid" ในฐานข้อมูลของฉัน หลังจากเรียกใช้แบบสอบถามอีกครั้งฉันได้รับข้อผิดพลาดนี้: ฟังก์ชัน st_convexhull (จำนวนเต็ม) ไม่มีอยู่จริง
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)

และ shapefile นี้ (ด้วยคุณสมบัติ 11 ประการ):

ป้อนคำอธิบายรูปภาพที่นี่

ฉันได้รับเลเยอร์หน่วยความจำที่ polylines มีระยะห่างระหว่างเซนทรอยด์และจุดที่ไกลที่สุดของรูปหลายเหลี่ยมแต่ละอัน (คุณสมบัติ); ตามที่สามารถสังเกตได้ในภาพถัดไป:

ป้อนคำอธิบายรูปภาพที่นี่

ที่ Python Console ของ QGIS มันก็พิมพ์ดัชนีของคุณสมบัติดัชนีของจุดในคุณสมบัติที่ระยะทางจากเซนทรอยด์เป็นระยะสูงสุดและในที่สุดระยะทางสูงสุด

ป้อนคำอธิบายรูปภาพที่นี่


ฉันไม่รู้วิธีใช้ PyQGIS คุณสามารถให้วิธีแก้ปัญหาที่ง่ายกว่าในส่วนโค้งหรือ mapinfo หรือ qgis ได้ไหม
Divya

1
ลองลิงค์นี้เพื่อขอความช่วยเหลือในการเริ่มต้นกับ PyQgis spatialgalaxy.net/2014/10/09/…
kttii

0

ดูเหมือนว่าคุณกำลังใช้ MapInfo นี่คือฟังก์ชั่น MapBasic ที่ฉันเขียนกลับไปหาเครื่องมือภายในที่ฉันใช้งานอยู่ มันต้องใช้โหนดต้นทาง (จุด centroid ของคุณ) และวัตถุภูมิภาค (รูปหลายเหลี่ยม) เป็นอาร์กิวเมนต์และส่งกลับวัตถุจุดที่โหนดที่อยู่ไกลที่สุดในรูปหลายเหลี่ยมจากจุดต้นทาง

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.