Przypisywanie identyfikatorów punktów do odpowiednich początkowych i końcowych atrybutów polilinii?

9

Mam dwa pliki kształtów, Point i Polyline. Próbuję zapełnić moją warstwę polilinii identyfikatorem danych punktowych (systemID), w którym linie zaczynają się tam, gdzie kończą; na przykład. utwórz dwie kolumny (od i do). Linie mają już przypisany kierunek przepływu. Korzystam z narzędzi ArcHydro, ale Arcpy też jest w porządku.

W ArcHydro próbowałem użyć narzędzi atrybutów> Wygeneruj z / do węzłów dla linii, ale tworzy wartości dla Do i Od, które nie pochodzą z moich danych punktowych. Inną moją alternatywą było użycie funkcji do wierzchołków i połączenie wyniku z moją tabelą danych punktów, aby uzyskać identyfikator systemowy. Ale wtedy musiałbym również zaktualizować warstwę polilinii. Jestem pewien, że jest na to łatwiejszy sposób.

Uwaga: nie wszystkie linie mają punkty w wierzchołkach, puste wartości są dla nich odpowiednie.

JrUser
źródło
Więc twoje punkty mają pole „systemID”, które musi iść w FNode, pola TNode na poliliniach ... prawda?
Michael Stimson,
Gdzieś tutaj jest takie pytanie z odpowiedzią, która w zasadzie linia do punktu zaczyna się i kończy jako osobne klasy obiektów, przecina dwie (indywidualnie) z danymi punktów, aby uzyskać identyfikatory, a następnie łączy je przestrzennie z powrotem z liniami za pomocą linii Identyfikator i przypisanie do poprawnego pola początkowego lub końcowego (może tam być pole do obliczenia). Ale nie mogę tego teraz znaleźć. Znalazłem go, szukając tego .
Chris W,
Oto on: gis.stackexchange.com/questions/85082 I było to Feature Vertices do punktów, a nie linia lub operacje do punktów. Prawie to, o czym wspomniałeś na końcu pytania.
Chris W,
@ChrisW, naprawdę podoba mi się odpowiedź FelixIP na tę. To tylko dwa sprzężenia atrybutów.
Michael Stimson,

Odpowiedzi:

12

Czasami lepiej nie używać gotowego rozwiązania. Właśnie dlatego sugeruję

  1. Wypełnij pola X i Y w warstwie węzłów, przekonwertuj je na liczby całkowite, powiedzmy cm. Utwórz pole ciągu i zapełnij je, łącząc reprezentacje ciągów liczb całkowitych.
  2. Zrób podobne rzeczy w tabeli łączy dla pierwszego punktu w kształcie.
  3. Połącz tabelę węzłów z linkami za pomocą ostatnio utworzonych pól i przenieś ID węzła do pola FROM.

Idź 2, ale użyj ostatniego punktu, aby przypisać TO nodeID

FelixIP
źródło
Lubię to! Pole obliczyć coś w rodzaju str (okrągły (! Shape! .FirstPoint.X, 3)) + "," + str (okrągły (! Shape! .FirstPoint.Y, 3)) (parser Pythona) dla z węzła, str (okrągły (! Shape! .LastPoint.X, 3)) + "," + str (okrągły (! Shape! .LastPoint.Y, 3)) dla węzła, następnie podobny do punktu (jako tekst), a następnie połącz ... Doskonały sposób łączenia przestrzennego bez bólu Felix! Zaokrąglić do bardziej znaczących cyfr dla danych geograficznych (takich jak 7 lub 8).
Michael Stimson,
Niezwykle szybki również w środowisku skryptowym, w którym słownik zastępuje powolne łączenie tabel
FelixIP
Int (X * 100), jeśli są wyświetlane w metrach. Alternatywnie użyj kodu Michaela
FelixIP
Zdecydowanie prostsze niż metoda w pytaniu, do którego odsyłam powyżej. Mniej kroków, mniej narzędzi i brak ograniczeń poziomu licencji. Ciekawy pomysł, aby przekształcić połączenie przestrzenne w zwykłe połączenie atrybutu.
Chris W
1

Zrobiłem to samo kilka miesięcy temu. Użyłem arcpy, ale skrypt jest o wiele za długi, aby opublikować tutaj, więc dam ci zarys tego, co zrobiłem.

  1. Użyłem łączenia przestrzennego, aby wykryć, które punkty / węzły znajdują się w obrębie określonego elementu linii.

  2. Ponieważ połączenie przestrzenne nie bierze pod uwagę kierunku przepływu, użyłem łuku, aby ustalić, który był punktem początkowym, a który końcowym. Udało mi się to zrobić za pomocą arcpy opisać funkcja ekstraktu koordynować informacje o wierzchołkach Początek / Koniec funkcji linii i porównano je z wartościami współrzędnych podłączonych punktów.

  3. Wreszcie, kiedy już się zorientowałem, które punkty do / z których są, użyłem funkcji setValue do wypełnienia pól do / z w oryginalnym zestawie danych polilinii.

Oczywiście jest w tym nieco więcej, ale nakreśliłem główne punkty.

Geord359
źródło
W mojej sieci geometrycznej kierunek przepływu może być w dowolnym z głównych kierunków. Nie mogłem ustalić kierunku przepływu na podstawie porównania surowych współrzędnych, chyba że użyłem rastra kierunku przepływu lub czegoś równoważnego. Nawet to może być problematyczne, ponieważ czasami rury są nachylone w stosunku do naturalnych konturów lub woda jest pompowana pod górę. Jak możesz mieć pewność, że kierunek przepływu jest prawidłowy?
Priscilla
1

Zainspirowałem się @FelixIP, ale chciałem napisać rozwiązanie bez łączenia lub tworzenia dodatkowych plików, ponieważ moja sieć jest dość duża z 400 kB + potokami i 500 kB + węzłami.

Geometryczna budowa sieci wymusza współbieżność X, Y węzłów i końców rur. Możesz uzyskać dostęp do tych lokalizacji za pomocą żetonów kształtów w arkadowych kursorach i dopasować je. Żetony kształtów dla linii zwracają tablicę wierzchołków w kolejności, w której zostały narysowane. W mojej sieci kolejność rysowania rur jest w dużym stopniu kontrolowana, ponieważ używamy tego do ustalania kierunków przepływu. Tak więc pierwszy wierzchołek jest początkiem potoku, a ostatni wierzchołek jest końcem potoku.

Odniesienie: ASSETID = identyfikator potoku, UNITID = identyfikator węzła na początku potoku, UNITID2 = identyfikator węzła na końcu potoku.

nodes = "mergeNodes"
pipes = "SEWER_1"

nodeDict = {}
pipeDict = {}

#populate node dictionary with X,Y as the key and node ID as the value
for node in arcpy.da.SearchCursor(nodes, ["UNITID", "SHAPE@XY"]):
    nodeDict[(node[1][0], node[1][1])] = node[0]

#populate pipe dictionary with pipe ID as the key and list of X,Y as values 
#vertices populated in the order that the line was draw
#so that [0] is the first vertex and [-1] is the final vertex
for pipe in arcpy.da.SearchCursor(pipes, ["ASSETID", "SHAPE@"]):
    for arrayOb in pipe[1]:
        for point in arrayOb:
            if pipe[0] in pipeDict:
                pipeDict[pipe[0]].append((point.X, point.Y))
            else: 
                pipeDict[pipe[0]] = [(point.X, point.Y)]

#populate UNITID with the first vertex of the line
#populate UNITID2 with the final vertex of the line
with arcpy.da.UpdateCursor(pipes, ["ASSETID", "UNITID", "UNITID2"]) as cur:
    for pipe in cur:
        if pipeDict[pipe[0]][0] in nodeDict:
            pipe[1] = nodeDict[pipeDict[pipe[0]][0]]
        if pipeDict[pipe[0]][-1] in nodeDict:
            pipe[2] = nodeDict[pipeDict[pipe[0]][-1]]
        cur.updateRow(pipe)
Priscilla
źródło
To 90% tego, co robię, ale nie przeglądam potoków dwa razy, ponieważ słownik węzłów jest już dostępny.
FelixIP