Присвоение идентификаторов точек соответствующим начальным и конечным атрибутам полилинии?

9

У меня есть два шейп-файла, Point и Polyline. Я пытаюсь заполнить свой слой полилинии идентификатором точечных данных (systemID), где линии начинаются там, где они заканчиваются; например. создать две колонки (от и до). На линии уже назначено направление потока. Я использую инструменты ArcHydro, но Arcpy тоже подойдет.

В ArcHydro я пытался использовать Атрибуты Инструменты> Создать От / К узлам для линий, но он создает значения для Кому и От, которые не из моих точечных данных. Другой моей альтернативой было использование Feature to Vertic и объединение результата с моей таблицей данных точек для получения systemID. Но тогда мне бы пришлось обновить слой полилинии. Я уверен, что есть более простой способ сделать это.

Примечание: не все линии имеют точки в вершинах, пустые значения подходят для них.

JrUser
источник
Таким образом, у ваших точек есть поле 'systemID', которое должно быть указано в полях FNode, TNode в полилиниях ... это правильно?
Майкл Стимсон
Где-то здесь есть такой вопрос с ответом, который в основном состоит из начала и конца точки в виде отдельных классов объектов, пересекает два (индивидуально) с вашими точечными данными, чтобы получить идентификаторы, а затем пространственно соединяет их обратно с линиями, используя линию Идентификатор и присвоение правильного начального или конечного поля (это может быть поле для вычисления там). Я не могу найти это прямо сейчас, хотя. Нашел, пока копался в этом .
Крис W
Вот оно: gis.stackexchange.com/questions/85082 И это были вершины объектов для точек, а не линии или объекты для точек. В значительной степени то, что вы упоминаете в конце вопроса.
Крис W
@ChrisW, мне очень нравится ответ FelixIP на этот вопрос. Это только два атрибута соединения.
Майкл Стимсон

Ответы:

12

Иногда лучше не использовать готовое решение. Вот почему я предлагаю

  1. Заполните поля X и Y в слое узла, преобразуйте их в целые числа, скажем, см. Создайте строковое поле и заполните его, объединяя строковые представления целых чисел.
  2. Сделайте аналогичную вещь в таблице ссылок для первой точки в форме.
  3. Соедините таблицу узлов с ссылками, используя последние созданные поля, и перенесите nodeID в поле FROM.

Переходите к 2, но используйте последнюю точку для назначения идентификатора узла

FelixIP
источник
Нравится! Поле вычисляет что-то вроде str (round (! Shape! .FirstPoint.X, 3)) + "," + str (round (! Shape! .FirstPoint.Y, 3)) (анализатор Python) для узла from, str (round (! Shape! .LastPoint.X, 3)) + "," + str (round (! Shape! .LastPoint.Y, 3)) для узла, затем аналогично точке (как текст), затем присоединитесь ... Отличный способ пространственного соединения без боли Феликса! Округление до более значимых цифр для географических данных (например, 7 или 8).
Майкл Стимсон
Очень быстро, а также в среде сценариев, где словарь заменяет медленное объединение таблиц
FelixIP
Int (X * 100), если они проецируются в метрах. Альтернативно используйте код Майкла
FelixIP
Определенно проще, чем метод в вопросе, с которым я связан выше. Меньше шагов, меньше инструментов и никаких ограничений на уровень лицензии. Интересная идея превратить пространственное объединение в обычное соединение атрибутов.
Крис W
1

Я сделал то же самое несколько месяцев назад. Я использовал arcpy, но сценарий слишком длинный для публикации здесь, поэтому я дам вам общее представление о том, что я сделал.

  1. Я использовал пространственное соединение, чтобы определить, какие точки / узлы были в пределах определенного линейного объекта.

  2. Поскольку пространственное объединение не учитывает направление потока, я использовал arcpy, чтобы определить, какая была начальная точка, а какая конечной. Я смог сделать это с помощью функции описания arcpy, чтобы извлечь информацию о координатах для начальных / конечных вершин линейного объекта, и сравнил их со значениями координат связанных точек.

  3. Наконец, как только я выяснил, какие из точек to / from были какие, я использовал функцию setValue, чтобы заполнить поля to / from в исходном наборе данных полилинии.

Очевидно, здесь есть кое-что еще, но я обрисовал основные моменты.

Geord359
источник
В моей геометрической сети направление потока может быть любым из основных направлений. Я не мог определить направление потока из сравнения необработанных координат, если бы я не использовал растр направления потока или что-то подобное. Даже это может быть проблематично, потому что иногда трубы наклонены к естественным контурам, или вода качается в гору. Как вы можете быть уверены, что ваше направление потока правильное?
Присцилла
1

Я был вдохновлен @FelixIP, но я хотел написать решение без объединений или создания дополнительных файлов, так как моя сеть довольно большая с 400K + каналами и 500K + узлами.

Построение геометрической сети приводит к совпадению X, Y узлов и концов трубы. Вы можете получить доступ к этим местам с помощью жетонов формы в дугообразных курсорах и сопоставить их. Токены формы для линий возвращают массив вершин в том порядке, в котором они были нарисованы. В моей сети порядок отрисовки труб в значительной степени контролируется, потому что мы используем его для установки направлений потока. Итак, первая вершина является началом трубы, а последняя вершина является концом трубы.

Ссылка: ASSETID = идентификатор канала, UNITID = идентификатор узла в начале канала, UNITID2 = идентификатор узла в конце канала.

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)
Присцилла
источник
Это 90% того, что я делаю, но я не пересекаю каналы дважды, потому что словарь узлов уже доступен.
FelixIP