Более

Найдите точку, которая находится между двумя параллельными линиями

Найдите точку, которая находится между двумя параллельными линиями


Я столкнулся с одной проблемой в ArcGIS. Я работаю над навигационной базой данных. В нашей базе данных однополосные улицы представлены одной линией, а многополосная улица (улица с разделителем в центре) представлена ​​двумя параллельными линиями (красные линии на рисунке).

У меня есть шейп файл точек, некоторые точки которого попадают внутрь многополосной улицы, а некоторые - снаружи.

Я хочу создать скрипт ArcPy, который будет находить точки, попадающие в многополосные улицы. т.е. между этими параллельными линиями (отмеченными на рисунке).

Я не знаю, как этого добиться. Может ли кто-нибудь мне помочь?

Я сделал несколько упражнений и обнаружил, что создание буфера на одной стороне линии может создавать внутри многополосного многоугольника (показано на рисунке).

но теперь проблема в том, что многоугольник фактически пересекает линию (т. е. перекрывает многополосную границу). так он поймает ненужные точки. есть ли способ выровнять этот многоугольник с линией улицы?

Примечание: интегрировать здесь не получится, потому что она также перемещает линию улиц. мне нужно просто выровнять многоугольник по линии улицы.


Я бы попробовал ниже алгоритм arcpy (даже ручной!) -

  1. Найдите правильную ширину двух полос движения - здесь вам может потребоваться сгруппировать улицы одинаковой ширины и выполнить процедуру, описанную ниже, для каждого кластера.
  2. Создайте буфер для обеих линий в обоих направлениях (вправо и влево) с этой шириной (или немного меньше, чтобы обеспечить зону дороги).
  3. Запустите инструмент Intersection, чтобы получить область перекрытия.
  4. Запустите Select by location, чтобы выбрать точки, которые попадают внутрь этого многоугольника.

Я бы сказал, что это геометрическое упражнение.

КОД ПСЕВДО:

  • Для каждой точки (черная точка) найдите ближайшую дорогу и найдите проекцию точки на этой дороге (красная точка).
  • Нарисуйте короткую линию (пунктирную) в противоположном направлении, начиная с черной точки.
  • Найдите, есть ли пересечение между короткой линией и дорогой с таким же названием, синяя звезда. Если есть, то черная точка - это то, что нам нужно.

Как видно, есть особые случаи - обведены черными точками:

  1. Очень извилистая дорога в 1 линию. Этого можно избежать, если а) работать только с двухрядными дорогами или б) убедиться, что FID дорог, пересекающих красную точку и звезду, разные. Однако, если у извилистой дороги есть перекресток с другой дорогой в одну линию, это может не сработать.
  2. Черная точка находится на продолжении ровно перпендикулярной дороги в 1 линию. В этом случае есть шанс, что дорога с 1 полосой движения может быть выбрана в качестве ближайшего соседа.
  3. Черная точка сидит на линии.

Все вышеперечисленные случаи очень маловероятны, тем не менее кажется, что наиболее безопасным вариантом является работа только с двухполосными дорогами, то есть экспорт их в отдельный класс пространственных объектов. Случай 3 - забавный, оставим его на волю случая, потому что кратчайшее расстояние до линии никогда не бывает истинным нулем, поэтому можно найти «противоположное» направление луча, соединяющего 2 точки.

Реализация Python:

import arcpy, traceback, os, sys from arcpy import env env.overwriteoutput = True # что нужно изменить --------- maxD = 30 mxd = arcpy.mapping.MapDocument ("CURRENT") pointLR = arcpy.mapping .ListLayers (mxd, "NODES") [0] lineLR = arcpy.mapping.ListLayers (mxd, "LINKS") [0] sjOneToMany = r'D:  scratch  sj2.shp 'RDNAME = "street" # - ----------------------- dDest = arcpy.Describe (lineLR) SR = dDest.spatialReference try: def showPyMessage (): arcpy.AddMessage (str (time .ctime ()) + "-" + сообщение) g = arcpy.Geometry () geometryList = arcpy.CopyFeatures_management (pointLR, g) n = len (geometryList) endPoint = arcpy.Point () arcpy.SpatialJoin_analysis (pointLR, lineLR, sjOneToMany, "JOIN_ONE_TO_MANY", "KEEP_COMMON", "", "WITHIN_A_DISTANCE", maxD) initFidList = (- 1,) для fid в диапазоне (n): TARGET_FID "=% s"% str (fid) nearTable = arcpy.da .TableToNumPyArray (sjOneToMany, ("TARGET_FID", "JOIN_FID"), query) if len (nearTable) <2: continue fidLines = [int (row [1]) для строки в nearTable] FID "in% s"% str ( кортеж (fidLines)) listOfLines = {} blackPoint = geometryLis t [fid] с arcpy.da.SearchCursor (lineLR, ("FID", "Shape @", "STREET"), query) как строки: dMin = 100000 для строки в строках: shp = row [1]; dCur = blackPoint.distanceTo (shp) listOfLines [row [0]] = row [-2:] если dCur

Есть другое возможное решение, возможно, более элегантное. Это включает в себя триангуляцию. Сообщите мне, если это интересно, и я обновлю свой ответ


Поскольку улицы параллельны, я предположил, что они были созданы с помощьюКопировать параллельноинструмент на панели инструментов Правка, таким образом, пара линий будет иметь одинаковое направление. Затем мы можем перебрать координаты первой строки и добавить их к многоугольнику, а затем перебрать обеспечить регресс второй линии. Определенно есть лучший способ подойти к парам линий захвата; подход OID работает, но он не очень хорош.

импорт коллекций import arcpy FC = "fc" points = "points" pgons = "pgons" arcpy.env.overwriteOutput = True def buildpoly (oid_coords): #create ddict формы OID: ddict = collections.defaultdict (list) для k, v в oid_coords: ddict [k] .append (v) line1, line2 = ddict.keys () # Предположим, что параллельные линии имеют одинаковое направление, поэтому переверните вторую arr = arcpy .Array () arr.extend (arcpy.Point (* pt) for pt in ddict [line1]) arr.extend (arcpy.Point (* pt) for pt in ddict [line2] [:: - 1]) return arcpy .Polygon (arr) #id - это целочисленное поле, которое объединяет параллельные линии в пары unique = list (set (t [0] for t in arcpy.da.SearchCursor (FC, "id"))) polygons = [] for uni in уникальный: polygons.append (buildpoly ([r вместо r в строке] для строки в arcpy.da.SearchCursor (FC, ["OID @", "SHAPE @ XY"], "id = {}". format (uni) , explode_to_points = True))) arcpy.CopyFeatures_management (многоугольники, pgons)

Оттуда это вызов Intersect / Select Layer by location / what have you. Обратите внимание, чтоSмногоугольник не идеальной формы, так как я нарисовал его от руки, и есть несколько дуг, которыеexplode_to_pointsне обрабатывается должным образом. Просто беги Уплотнить или эквивалент.


Смотреть видео: Euklid - en parallel linje gennem et punkt