Mengapa Shapely's gertakan (GEO snaps) tidak berfungsi seperti yang diharapkan?

14

Saya mencoba untuk mengambil dua baris satu sama lain menggunakan Shapely / Geopandas tetapi hasil gertakan sangat aneh. Saya mencoba :

import geopandas as gpd
from shapely.geometry import *
from shapely.ops import snap

lines1 = gpd.GeoDataFrame.from_file('lines1.shp')
lines1 = lines1.to_crs({'init': 'epsg:2227'})
lines2 = gpd.GeoDataFrame.from_file('lines2.shp')
lines2 = lines2.to_crs({'init': 'epsg:2227'})
res = lines1
lines2_union = lines2.geometry.unary_union
res.geometry = res.geometry.apply(lambda x: snap(x, lines2_union, 14))
res.to_file('result.shp', driver="ESRI Shapefile")

Dan dapatkan hasil ini:

lines1 = garis merah

lines2 = garis hitam

Sebelum gertakan

Setelah gertakan (dengan 14 sebagai toleransi): garis biru adalah hasil gertakan

Dalam hal ini, garis-garisnya terpotong dengan benar Setelah gertakan

Contoh lain di mana itu tidak berfungsi seperti yang diharapkan: (sebelum gertakan) Sebelum gertakan

Dan inilah hasilnya setelah patah. Hanya sebagian yang tersentak ke garis hitam (sisi selatan). Meskipun garis aslinya cukup dekat dan dalam 14 kaki Setelah gertakan

Jika saya meningkatkan toleransi, saya mendapatkan output yang salah, kira-kira seperti ini (setelah mendefinisikan 20 sebagai toleransi dari gertakan, garis hijau adalah hasilnya):

Setelah 20 sebagai toleransi

Adakah ide mengapa gertakan tidak berfungsi dengan baik? Ada saran tentang cara mengatasi masalah ini?

GeoSal
sumber
@ gen Anda harus mengonversi komentar Anda menjadi jawaban yang saya kira.
nmtoken
Bisakah Anda membagikan data atau bagiannya untuk mereproduksi masalah ini?
bugmenot123
2
Panduan Pengguna Shapely 1.6 yang Disediakan: "Fungsi snap () di shapely.ops menjentikkan simpul dalam satu geometri ke simpul dalam geometri kedua dengan toleransi yang diberikan." Seperti yang saya pahami, itu tidak terkunci geometri yang dekat satu sama lain, itu mematahkan simpul mereka dekat satu sama lain. Jadi, jika ada geometri yang dekat dengan geometri lain, itu mematahkan simpul mereka dalam ambang.
Kadir Şahbaz

Jawaban:

6

The shapely.ops.snapFungsi terkunci ke simpul dari geometri saja.

Lihat ilustrasi di bawah ini. Di sebelah kiri, simpul merah berada dalam toleransi gertakan ke simpul biru, sehingga akan patah. Di sebelah kanan titik merah berada di luar toleransi gertakan (meskipun lebih dekat ke tepi!).

menjentikkan visualisasi toleransi

Shapely tidak menyediakan algoritma untuk menjentikkan simpul ke tepi. Seharusnya tidak terlalu sulit untuk menulis satu menggunakan shapely.ops.nearest_points. Sesuatu seperti ini (tidak diuji, dan tidak terlalu efisien):

from shapely.ops import nearest_points

def snap(g1, g2, threshold):
    coordinates = []
    for x, y in g1.coords:  # for each vertex in the first line
        point = Point(x, y)
        p1, p2 = nearest_points(point, g2)  # find the nearest point on the second line
        if p1.distance(p2 <= threshold):
            # it's within the snapping tolerance, use the snapped vertex
            coordinates.append(p2.coords[0])
        else:
            # it's too far, use the original vertex
            coordinates.append((x, y))
    # convert coordinates back to a LineString and return
    return LineString(coordinates)
Snorfalorpagus
sumber
Sangat keren tapi saya pikir if p1.distance(p2 <= threshold):seharusnyaif p1.distance(p2) <= threshold:
chrislarson