กำลังมองหาวิธีการแบบ pythonic ในการคำนวณความยาวของ WKT linestring


13

ผมก็ไม่พอใจมากกับการคำนวณความยาวของ LineStrings ใน WGS84 ในไมล์ มันทำให้ฉันสงสัยว่ามีวิธีที่สะดวกกว่าในการคำนวณความยาวของ WKT ที่เปล่งออกมาตาม SRID ที่กำหนดหรือไม่

ฉันมีสิ่งที่ชอบในใจ:

srid="WGS84"
line="LINESTRING(3.0 4.0, 3.1 4.1)"
print length(line, srid)

ฉันกำลังมองหาคำตอบที่ถูกต้องไม่ใช่การsin\cosประมาณ

ความคิดใด ๆ


tomkralidis, นี่คือเว็บไซต์ GIS คำตอบของคุณไม่สนใจว่านี่เป็นระยะห่างระหว่างพิกัดทางภูมิศาสตร์ (ค้นหา SRID) หุ่นดีในตัวของมันเองไม่สามารถคำนวณระยะทางทางภูมิศาสตร์เนื่องจากไม่มีความรู้เกี่ยวกับการฉายแผนที่

คำตอบ:


18

geopyโมดูลให้สูตร Vincentyซึ่งมีระยะทางที่ทรงรีที่ถูกต้อง จับคู่สิ่งนี้กับการwktโหลดในหุ่นดีและคุณมีรหัสที่เรียบง่ายพอสมควร:

from geopy import distance
from shapely.wkt import loads

line_wkt="LINESTRING(3.0 4.0, 3.1 4.1)"

# a number of other elipsoids are supported
distance.VincentyDistance.ELLIPSOID = 'WGS-84'
d = distance.distance

line = loads(line_wkt)

# convert the coordinates to xy array elements, compute the distance
dist = d(line.xy[0], line.xy[1])

print dist.meters

1
+1 จะมี +10 ถ้าทำได้ บันทึกชั่วโมงการเขียนโปรแกรมของทีม
Adam Matan

วิธีการนี้แตกต่างจาก @tomkralidis หรือไม่หากคำตอบของพิกัดอินพุตอยู่ใน WGS-84 แล้ว?
LarsVegas

1
@ LarsVegas ใช่หุ่นดีจัดการพิกัดระนาบเท่านั้น - ดังนั้นมันจะวัดระยะทางอย่างแม่นยำในพื้นที่ที่คาดการณ์ แต่ไม่ใช่ทางภูมิศาสตร์ (เช่น WGS-1984)
scw

4

คุณสามารถใช้คุณสมบัติความยาวของ Shapely ได้เช่น:

from shapely.wkt import loads

l=loads('LINESTRING(3.0 4.0, 3.1 4.1)')
print l.length

โปรดทราบว่าความยาวของตัวอย่างนี้จะไม่มีความหมายเนื่องจากเป็นระบบพิกัดทางภูมิศาสตร์ (WGS84)
Mike T


2

ไปงานปาร์ตี้สาย แต่หวังว่าจะเป็นประโยชน์ เมื่อสร้างคำตอบของ SCWโดยใช้ geopy ฉันได้เขียนฟังก์ชั่นเล็ก ๆ ที่ใช้ในการคำนวณหาวัตถุ LineString ที่มีรูปร่างดีซึ่งมีพิกัดจำนวนมากโดยพลการ มันใช้ตัวpairsวนซ้ำจาก Stackoverflow

คุณสมบัติหลัก: เอกสารที่ยาวกว่าตัวอย่างมาก

def line_length(line):
    """Calculate length of a line in meters, given in geographic coordinates.
    Args:
        line: a shapely LineString object with WGS 84 coordinates
    Returns:
        Length of line in meters
    """
    # Swap shapely (lonlat) to geopy (latlon) points
    latlon = lambda lonlat: (lonlat[1], lonlat[0])
    total_length = sum(distance(latlon(a), latlon(b)).meters
                       for (a, b) in pairs(line.coords))
    return round(total_length, 0)


def pairs(lst):
    """Iterate over a list in overlapping pairs without wrap-around.

    Args:
        lst: an iterable/list

    Returns:
        Yields a pair of consecutive elements (lst[k], lst[k+1]) of lst. Last 
        call yields the last two elements.

    Example:
        lst = [4, 7, 11, 2]
        pairs(lst) yields (4, 7), (7, 11), (11, 2)

    Source:
        /programming/1257413/1257446#1257446
    """
    i = iter(lst)
    prev = i.next()
    for item in i:
        yield prev, item
        prev = item

1
นี่เป็นสิ่งที่ผิด: geopy.distance.d Distance ยอมรับพิกัดใน (y, x) แต่รูปร่างที่ดีคือ "ลำดับที่สั่งตั้งแต่ 2 หรือมากกว่า (x, y [, z])" ดังนั้นจึงต้องใช้ฟังก์ชันผู้ช่วยของ geopy lonlat () .
Martin Burch

@MartinBurch: อุ๊ยคุณพูดถูก สิ่งที่น่ารังเกียจไม่ได้เป็น[, z]เช่นนั้น แต่การโต้แย้งเปลี่ยน(y, x)ไป(x, y)เป็นสิ่งที่จำเป็น ขอบคุณที่จำได้ คุณช่วยลูกตาได้ไหมว่าการแก้ไขนี้ดูมีข้อบกพร่องน้อยลงหรือไม่
ojdo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.