Mais

Descubra o ponto que fica entre duas linhas paralelas


Estou enfrentando um problema no ArcGIS. Eu trabalho em um banco de dados de navegação. Em nosso banco de dados, as ruas de faixa única são representadas por uma única linha, enquanto uma rua de várias faixas (rua com divisória no centro) é representada por duas linhas paralelas (linhas vermelhas na imagem).

Eu tenho um shapefile de ponto com alguns pontos caindo dentro da rua de várias pistas e alguns fora.

Eu quero criar um script ArcPy que encontre os pontos que caem dentro de Multi-Lane Streets. ou seja, entre essas linhas paralelas (marcadas na imagem).

Eu não sei como conseguir isso, alguém pode me ajudar?

Eu fiz alguns exercícios sobre ele e descobri que a criação de buffer em um lado da linha pode criar dentro do polígono Multi-Lane (mostrado na imagem).

mas agora o problema é que o polígono está realmente cruzando a linha (ou seja, sobrepondo o limite de várias faixas). então ele pegará pontos desnecessários. existe alguma maneira de alinhar este polígono à linha da rua?

Nota: integrar não funcionará aqui, porque também move a linha da rua. eu preciso apenas alinhar o polígono ao longo da linha da rua.


Eu tentaria o algoritmo arcpy (mesmo manual!) Abaixo

  1. Encontre a largura adequada das duas ruas de faixa - aqui você pode precisar agrupar ruas com a mesma largura e seguir o procedimento abaixo para cada agrupamento.
  2. Crie o buffer de ambas as linhas em ambas as direções (direita e esquerda) com essa largura (ou um pouco menos que isso - para garantir a área da estrada).
  3. Execute a ferramenta Intersection para obter a região sobreposta.
  4. Execute Selecione por local para selecionar os pontos que caem dentro deste polígono.

Eu diria que este é um exercício geométrico.

PSEUDO-CÓDIGO:

  • Para cada ponto (ponto preto) encontre a estrada mais próxima e encontre a projeção do ponto nesta estrada (ponto vermelho).
  • Desenhe uma linha curta (tracejada) na direção oposta, começando no ponto preto
  • Descubra se há interseção entre a linha curta e a estrada com o mesmo nome, estrela azul. Se houver um, o ponto preto é aquele que buscamos.

Como se pode ver, existem casos especiais - pontos pretos circulados:

  1. Estrada de 1 linha muito sinuosa. Isso pode ser eliminado a) trabalhando apenas com estradas de 2 linhas ou b) certificando-se de que os FIDs das estradas que cruzam o ponto vermelho e a estrela sejam diferentes. No entanto, se a estrada sinuosa tiver um cruzamento com outra estrada de 1 linha, isso pode não funcionar.
  2. O ponto preto está situado na extensão de uma estrada exatamente perpendicular de 1 linha. Nesse caso, há uma chance de que 1 via de faixa possa ser escolhida como a vizinha mais próxima.
  3. O ponto preto fica na linha.

Todos os casos acima são muito improváveis, no entanto, parece que a opção mais segura é trabalhar apenas com estradas de 2 linhas, ou seja, exportá-los para uma classe de recurso separada. O caso 3 é engraçado, vamos deixá-lo ao acaso, porque a menor distância até a linha nunca é zero verdadeiro, portanto, a direção 'oposta' do raio conectando 2 pontos pode ser encontrada.

Implementação Python:

import arcpy, traceback, os, sys from arcpy import env.overwriteoutput = True # coisas a alterar --------- 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 = "rua" # - ----------------------- dDest = arcpy.Describe (lineLR) SR = dDest.spatialReference try: def showPyMessage (): arcpy.AddMessage (str (time .ctime ()) + "-" + mensagem) 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,) para fid no intervalo (n): TARGET_FID "=% s"% str (fid) nearTable = arcpy.da .TableToNumPyArray (sjOneToMany, ("TARGET_FID", "JOIN_FID"), consulta) if len (nearTable) <2: continue fidLines = [int (linha [1]) para linha em nearTable] FID "em% s"% str ( tupla (fidLines)) listOfLines = {} blackPoint = geometryLis t [fid] com arcpy.da.SearchCursor (lineLR, ("FID", "Shape @", "STREET"), consulta) como linhas: dMin = 100000 para linha em linhas: shp = linha [1]; dCur = blackPoint.distanceTo (shp) listOfLines [linha [0]] = linha [-2:] se dCur

Existe outra solução possível, talvez mais elegante. Envolve triangulação. Avise-me se for de interesse e atualizarei minha resposta


Como as ruas são paralelas, presumi que foram criadas com oCopiar Paraleloferramenta na barra de ferramentas Editar, fazendo com que o par de linhas tenha a mesma direção. Podemos, então, iterar sobre as coordenadas da primeira linha e adicioná-las a um polígono e, em seguida, iterar sobre o marcha ré da segunda linha. Definitivamente, há uma maneira melhor de abordar pares de linhas agarradas; a abordagem OID funciona, mas não é muito bonita.

importar coleções import arcpy FC = "fc" points = "points" pgons = "pgons" arcpy.env.overwriteOutput = True def buildpoly (oid_coords): #create ddict do formulário OID: ddict = coleções.defaultdict (lista) para k, v em oid_coords: ddict [k] .append (v) linha1, linha2 = ddict.keys () # Assuma que as linhas paralelas têm a mesma direção, então inverta o segundo arr = arc .Array () arr.extend (arcpy.Point (* pt) para pt em ddict [linha1]) arr.extend (arcpy.Point (* pt) para pt em ddict [linha2] [:: - 1]) return arcpy .Polygon (arr) #id é um campo inteiro que emparelha linhas paralelas unique = list (set (t [0] for t in arcpy.da.SearchCursor (FC, "id"))) polygons = [] para uni in exclusivo: polygons.append (buildpoly ([r para r na linha] para linha em arcpy.da.SearchCursor (FC, ["OID @", "SHAPE @ XY"], "id = {}". formato (uni) , explode_to_points = True))) arcpy.CopyFeatures_management (polígonos, pgons)

A partir daí, é uma chamada para Intersect / Select Layer por local / o que você quiser. Observe que oSpolígono em forma não é perfeito, pois eu o desenhei à mão livre e há alguns arcos queexplode_to_pointsnão manuseia corretamente. Apenas corra Densificar ou equivalente.


Assista o vídeo: Euklid - en parallel linje gennem et punkt (Outubro 2021).