Tworzysz równo odległe punkty w QGIS?

22

Próbuję utworzyć punkty (nowa warstwa) w określonej odległości wzdłuż drogi (istniejąca warstwa) w QGIS. Tworzenie regularnych punktów co metr na poziomie hrabstwa za pomocą ArcGIS Desktop? daje rozwiązanie dla ArcGIS. Jak to osiągnąć w QGIS? Dodawanie punktów do warstwy wektorów punktowych za pomocą QGIS? wyjaśnia, jak tworzyć punkty, ale nie robi nic z odległości.


(Zastosowałem proponowane rozwiązania z różnymi miarami długości, ponieważ nie znałem konwersji) Rozwiązanie @ Nathans działało do pewnego stopnia, dostałem ...

wprowadź opis zdjęcia tutaj. Tutaj rzut tych równo odległych punktów różni się od pierwotnej linii.

Mam sugestię @ underdark

ten obrazgdzie punkty nie wydają się być w równej odległości. Wydaje mi się, że w obu przypadkach występuje problem z projekcją, którego nie rozumiem.

Stat-R
źródło
2
Kilka punktów. Po pierwsze, linia musi być w rzutowanym CRS (nie lat / lon). Po drugie, czy twoja linia to prawdziwa polilinia? Nie sądzę, aby jakakolwiek metoda działała poprawnie na linii zawierającej ciąg pojedynczych linii. Nacięcie.
nhopton
Również z moim kodem nie musisz dzwonić na import locatelinię więcej niż raz. Po prostu zadzwoń raz, a będziesz mógł dzwonić locate.pointsAlongLine(30)tyle, ile potrzebujesz
Nathan W
Inną metodą (biorąc pod uwagę, że Sextant, jak sugerują niektóre odpowiedzi tutaj, jest tylko QGIS <2.0), jest również użycie wtyczki o nazwie QChainage.
andy

Odpowiedzi:

14

Uwaga: dostępna jest teraz wtyczka QGIS QChainage. Robi to wszystko i jeszcze więcej. Poniższy kod jest nieaktualny w przypadku QGIS 2.0 i nowszych wersji.

Oto kod Pythona, który możesz umieścić w pliku i użyć w QGIS:

QGIS ma w sobie metodę API do wykonywania odwołań do liniowej, jednak nie mogłem go poprawnie uruchomić, ale skontaktuję się z autorem kodu i sprawdzę, czy zrobiłem coś złego.

Na razie będziesz potrzebować zgrabnej biblioteki Pythona, którą i tak powinieneś zainstalować, ponieważ dobrze jest mieć ją przy sobie. Ma również świetną dokumentację na stronie http://toblerity.github.com/shapely/manual.html

To jest sekcja, której używam w poniższym przykładzie http://toblerity.github.com/shapely/manual.html#interoperation .

Większość następującego kodu to prosty kod QGIS, który po prostu tworzy funkcje, warstwy, konwertuje z wkb i wkt iz powrotem. Bit rdzenia to taki, point = line.interpolate(currentdistance)który zwraca punkt w pewnej odległości wzdłuż linii. Po prostu owijamy to w pętlę, dopóki nie zabraknie linii.

import qgis
from qgis.core import *
from PyQt4.QtCore import QVariant
from shapely.wkb import loads
from shapely.wkt import dumps

vl = None
pr = None

def createPointsAt(distance, geom):
    if distance > geom.length():
        print "No Way Man!"
        return

    length = geom.length()
    currentdistance = distance
    feats = []  

    while currentdistance < length: 
        line = loads(geom.asWkb())
        point = line.interpolate(currentdistance)
        fet = QgsFeature()
        fet.setAttributeMap( { 0 : currentdistance } )
        qgsgeom = QgsGeometry.fromWkt(dumps(point))
        fet.setGeometry(qgsgeom)
        feats.append(fet)
        currentdistance = currentdistance + distance

    pr.addFeatures(feats)
    vl.updateExtents()

def pointsAlongLine(distance):
    global vl
    vl = QgsVectorLayer("Point", "distance nodes", "memory")
    global pr
    pr = vl.dataProvider()  
    pr.addAttributes( [ QgsField("distance", QVariant.Int) ] )
    layer = qgis.utils.iface.mapCanvas().currentLayer()
    for feature in layer.selectedFeatures():
        geom = feature.geometry()
        createPointsAt(distance, geom)

    QgsMapLayerRegistry.instance().addMapLayer(vl)

Skopiuj i wklej powyższy kod do pliku, nazwałem mój locate.py, w ~./qgis/pythonkatalogu (ponieważ znajduje się on w ścieżce Pythona) i po prostu zrób to w konsoli Pythona w QGIS.

 import locate
 locate.pointsAlongLine(30)

Spowoduje to utworzenie nowej warstwy punktowej z punktami co 30 metrów wzdłuż wybranych linii:

wprowadź opis zdjęcia tutaj

Uwaga: kod jest dość zgrubny i może wymagać trochę czyszczenia.

EDYCJA: Ostatnia wersja QGIS może teraz robić to natywnie.

Zmień pętlę while createPointsAtna:

 while currentdistance < length: 
    point = geom.interpolate(distance)
    fet = QgsFeature()
    fet.setAttributeMap( { 0 : currentdistance } )
    fet.setGeometry(point)
    feats.append(fet)
    currentdistance = currentdistance + distance

i możesz usunąć

from shapely.wkb import loads
from shapely.wkt import dumps
Nathan W.
źródło
Dzięki @Nathan. Nie mogłem uzyskać pakietu Shapely dla mojego pytona. Zainstalowałem Python 2.7, ale Shapely instalator mówi, że Python 2.7 nie ma w moim rejestrze. Czy istnieje inny sposób instalacji Shapely.
Stat-R
Śledziłem stackoverflow.com/questions/3652625/… i wpisałem powyższe dwie linie do wywołania locatei korzystania z niego, ale nadal nie dostałem równo odległych punktów. Ponadto jestem neofitą w Pythonie, więc nie zrozumiałem, gdzie uruchomić kod (1) python w katalogu qgis lub (2), że w C: \ Python27 \?
Stat-R
Na jakim systemie operacyjnym jesteś?
Nathan W
Windows 7 Professional
Stat-R
utwórz plik python, C:\Users\{you user name}\.qgis\pythona następnie uruchom ponownie QGIS, jeśli jest otwarty, i przejdź do `Plugins-> Python Console . Load a line layer, select a line a call import locate` ilocate.pointsAlongLine(30)
Nathan W
5

Możesz użyć narzędzia QGIS GRASS plugin v.to.points do tworzenia punktów wzdłuż linii w regularnych odstępach czasu

# convert line to points; dmax = distance between points
v.to.points -i -v -t in=road out=road_pts type=line dmax=90
podmrok
źródło
Użyłem dmax jako 100, a wynikowe prognozy dla każdego są następujące. (Nie wiem, jak sam przypisuje się CRS.)CRS of Original Shape file, the line = EPSG:26915 - NAD83 / UTM zone 15N, CRS of Grass line vector obtained using v.in.ogr = EPSG:4269 - NAD83, CRS of Grass points vector obtained using v.to.points = EPSG:4326 - WGS 84
Stat-R
Teraz też tak: QGIS -> Sextante -> GRASS -> v.to.points
markusN
5

Jeśli chcesz narysować pikietaż w ustalonych odstępach wzdłuż linii drogi, możesz użyć do tego wtyczki „Profil z linii”. Potrzebujesz DEM pod warstwą linii drogi, ale procedura jest szybka i bardzo prosta. Nacięcie.

wprowadź opis zdjęcia tutaj

nhopton
źródło
to też całkiem dobra i łatwa metoda, dzięki!
Shepherdjo
2

Uwaga: model danych Shapely (Python) / GEOS (C ++) jest zdefiniowany w płaszczyźnie. Więc jeśli twoje punkty składają się z pozycji GPS (szerokość, długość), użycie tej shapely.geometry.LineString.interpolate(distance)metody wyświetli pozycję GPS w odległości euklidesowej wzdłuż podanej LineString.

Shapely's interpolate()jest oparty na geos::linearref::LengthIndexedLineklasie GEOS przy użyciu tej extractPointmetody.

Podobno jednakowa interpolacja w płaszczyźnie szerokość-długość geograficzna jest wystarczająca do zastosowań uwzględniających stosunkowo małe odległości. Zasadniczo należy jednak wziąć pod uwagę odległość na kuli dla aplikacji GIS (zgodnie z definicją w WGS84 ).

Mogę wymyślić dwa obejścia za pomocą modułu Shapely:

  • LineStringwszystkie właściwości mają podane punkty i krzywe interpolowane liniowo wzdłuż nich. Być może możesz napisać element, który uzyskuje dostęp do interpolowanych krzywych i zaimplementować następującą całkę liniową, zastępując odległość euklidesową. Podoba mi się to podejście, ponieważ stosując ciągłą krzywą fragmentaryczną pożądane punkty można uzyskać, obliczając przecięcia sąsiednich okręgów wzdłuż krzywej z promieniem r = radian_measure(arc_length) = arc_length / R, gdzie R jest równe promieniowi Ziemi w danej pozycji.
  • zakoduj własną metodę interpolacji (bez dotykania kodu Shapely) za pomocą odpowiedniej funkcji odległości (np. formuła haversine).

Aby to osiągnąć, chciałbym odnieść się do następującego pytania StackOverflow, aw szczególności tej odpowiedzi :

Możliwe jest generowanie jednakowo odległych punktów wzdłuż krzywej. Ale musi być więcej definicji tego, czego chcesz, aby uzyskać prawdziwą odpowiedź. Przepraszamy, ale kod, który napisałem dla tego zadania, znajduje się w MATLAB, ale mogę opisać ogólne pomysły. Istnieją trzy możliwości.

Po pierwsze, czy punkty muszą być naprawdę w równej odległości od sąsiadów pod względem prostej odległości euklidesowej? W tym celu należałoby znaleźć przecięcie w dowolnym punkcie krzywej z okręgiem o stałym promieniu. Następnie wystarczy przejść wzdłuż krzywej.

Następnie, jeśli planujesz odległość jako średnią odległość wzdłuż samej krzywej, jeśli krzywa jest częściowo liniowa, problem jest znowu łatwy do zrobienia. Wystarczy przejść wzdłuż krzywej, ponieważ odległość na odcinku linii jest łatwa do zmierzenia.

Wreszcie, jeśli zamierzasz, aby krzywa była splajnem sześciennym, znowu nie jest to niewiarygodnie trudne, ale wymaga nieco więcej pracy. Sztuczka polega na:

  • Oblicz kawałek liniowej długości łuku od punktu do punktu wzdłuż krzywej. Nazwij to t. Wygeneruj parę splajnów sześciennych, x (t), y (t).

  • Rozróżnij xiy jako funkcje t. Ponieważ są to segmenty sześcienne, jest to łatwe. Funkcje pochodne będą fragmentarycznie
    kwadratowe.

  • Użyj solvera ody, aby poruszać się wzdłuż krzywej, integrując funkcję różniczkowej długości fali. W MATLAB ODE45 działało dobrze.

W ten sposób integruje się

sqrt((x')^2 + (y')^2)

Ponownie, w MATLAB, ODE45 można ustawić, aby zidentyfikować te lokalizacje, w których funkcja przecina określone określone punkty.

Jeśli twoje umiejętności MATLAB są wystarczające, możesz spojrzeć na kod w interparc, aby uzyskać więcej wyjaśnień. Jest to dość dobrze skomentowany kod.

3 : http://www.mathworks.com/matlabcentral/fileexchange/34874-interparc

Patryk
źródło
1

Sextante ma narzędzie, które może Ci pomóc. Sextante można pobrać z repozytorium wtyczek Qgis.

Poszukaj:
„Narzędzia do warstw linii”
„Linie do wyrównanych punktów”

Klewis
źródło
Ta wtyczka nie wydaje się być dostępna dla QGIS 2 lub 3.
Martin Burch