Chcę napisać w Pythonie program który skonwertuje mi dane przestrzenne w mało standardowym formacie na typowy ESRI shapefile. Chcę użyć do tego biblioteki pyshp.
Dane o geometrii polylinii mam zapisane w pliku formacie jak poniżej, gdzie w nawiasach podane są rozdzielone przecinkami współrzędne poszczególnych punktów polylinii. Nie ma ograniczenia co do ilości punktów.
Data=(49.76045,19.04358),(49.76073,19.04294),(49.76094,19.04155)
funkcja pyshp zapisująca polylinię jako parametrów oczekuje wg. przykładu z dokumentacji czegoś takiego, o ile dobrze rozumiem to lista:
w.line(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]])
Jak zgodnie z zasadami sztuki zrobić taką konwersję?
Nie wiem, czy dobrze rozumiem pytanie, bo nie wiem jak się mają wartości 49.76045
itd. do wartości 1
, 5
, 3
...?
@koszalek-opalek: taki przykład tylko podał.
Nie trzeba przeliczać, to tylko przykład (akurat w dokumentacji pyshp był na liczbach całkowitych, realne dane są typu float).
Czyli z tego:
Data=(49.76045,19.04358),(49.76073,19.04294),(49.76094,19.04155)
ma wyjść:
w.line(parts=[[[49.76045,19.04358],[49.76073,19.04294],[49.76094,19.04155]]])
?
To może tak:
list(map(lambda x:list(map(float, (x.split(')', 1)[0].split(',')))), dane.split('(')[1:]))
Da Ci to listę par:
[[49.76045, 19.04358], [49.76073, 19.04294], [49.76094, 19.04155]]
a reszta to już chyba prosta.
Dziękuje, wydawało się że to rozwiązuje problem, jednak okazuje się że pyshp nie przyjmuje listy w takim formacie. Próbowałem czegoś takiego:
import shapefile
w = shapefile.Writer(shapefile.POLYLINE)
w.autoBalance = 1
dane="(49.76045,19.04358),(49.76073,19.04294),(49.76094,19.04155)"
punkty=list(map(lambda x:list(map(float, (x.split(')', 1)[0].split(',')))), dane.split('(')[1:]))
w.line(parts=punkty)
w.save("output.shp")
i nie działa, wyrzuca bład TypeError: 'float' object is not iterable.
W międzyczasie znalazłem opis podobnego problemu: https://gis.stackexchange.com/questions/74767/creating-polyline-from-gml-using-pyshp i drugie podane w nim rozwiązanie działa.
import shapefile
w = shapefile.Writer(shapefile.POLYLINE)
w.autoBalance = 1
coords=[["49.76045","19.04358"],["49.76073","19.04294"],["49.76094","19.04155"]]
line_parts = []
line = []
for x,y in coords:
line.append([float(x),float(y)])
line_parts.append(line)
w.line(parts=line_parts)
w.save("output.shp")
Czyli teraz pytanie brzmi, jak skonwertować string na listę taką jak coords, albo od razu line_parts z przykładu?
W Twoim powinno być chyba parts=[punkty]
-- myślałem, że to oczywiste... U mnie było mniej nawiasów... :)
koszalek-opalek napisał(a):
W Twoim powinno być chyba
parts=[punkty]
-- myślałem, że to oczywiste... U mnie było mniej nawiasów... :)
Dziękuję za pomoc, problem rozwiązany :)
To jeszcze dopytam, czy przy konwersji można jednocześnie w jakiś prosty sposób zamieniać miejscami kolejność elementów w parach? Czyli żeby z:
Data=(49.76045,19.04358),(49.76073,19.04294),(49.76094,19.04155)
wyszło:
w.line(parts=[[[19.04358,49.76045],[19.04294,49.76073],[19.04155,49.76094]]])
Dodaj reversed
w odpowiednim miejscu:
list(map(lambda x:list(map(float, reversed((x.split(')', 1)[0].split(','))))), dane.split('(')[1:]))