폴리 라인의 변곡점을 찾기위한 알고리즘


22

변곡점, 즉 선의 곡선이 시작하고 끝나는 지점을 찾으려고합니다. 이미지를 보면 녹색 선이 도로 또는 개울 일 수 있으며 검은 점은 곡선이 시작하고 끝나는 지점입니다. 여기에 이미지 설명을 입력하십시오

이러한 포인트 생성을 자동화하기위한 상위 단계는 무엇입니까? ArcGIS 데스크탑이 있고 ArcObjects에 매우 편리합니다.


소스 데이터는 선 세그먼트로 만들어진 폴리 라인이며 곡선으로 인접하게하려고합니까, 아니면 이미 호 세그먼트가 있습니까?
— U2ros

현재는 선분으로 구성되어 있습니다.
— Devdatta Tengshe

1
이 질문의 그림은 esri.com/news/arcuser/0110/turning.html에 게시 된 그림과 매우 비슷 합니다.
— whuber

@ whuber : 매우 견실 한 관찰. 그것이 바로 이미지를 만들 때 사용한 데이터 소스였습니다.
— Devdatta Tengshe

답변:


15

곡선이 선분으로 구성되는 경우 해당 선분의 모든 내부 점은 변곡점이므로 흥미롭지 않습니다. 대신, 곡선은 해당 세그먼트 의 정점 에 의해 근사 된 것으로 생각해야합니다 . 이러한 세그먼트를 통해 부분적으로 두 배로 구분 가능한 곡선을 스플라인함으로써 곡률을 계산할 수 있습니다. 엄밀히 말하면 변곡점은 곡률이 0 인 곳입니다.

이 예에서는 곡률이 거의 0 인 긴 스트레치가 있습니다. 이는 지시 된 지점이 저 곡률 영역의 이러한 스트레치의 끝과 비슷해야 함을 시사합니다.

따라서 효과적인 알고리즘은 정점을 스플라인하고, 밀도가 높은 중간 점 세트를 따라 곡률을 계산하고, 0에 가까운 곡률 범위를 식별하고 ( "거의"의미에 대한 합리적인 추정치를 사용하여) 해당 범위의 끝점을 표시합니다. .

다음은 R이러한 아이디어를 설명하기위한 작업 코드입니다. 일련의 좌표로 표현 된 줄 문자열로 시작합시다.

xy <- matrix(c(5,20, 3,18, 2,19, 1.5,16, 5.5,9, 4.5,8, 3.5,12, 2.5,11, 3.5,3, 
               2,3, 2,6, 0,6, 2.5,-4, 4,-5, 6.5,-2, 7.5,-2.5, 7.7,-3.5, 6.5,-8), ncol=2, byrow=TRUE)

x 및 y 좌표를 별도로 스플라인하여 곡선의 매개 변수화를 달성하십시오. (매개 변수는이라고 부릅니다 time.)

n <- dim(xy)[1]
fx <- splinefun(1:n, xy[,1], method="natural")
fy <- splinefun(1:n, xy[,2], method="natural")

플로팅 및 계산을위한 스플라인 보간 :

time <- seq(1,n,length.out=511)
uv <- sapply(time, function(t) c(fx(t), fy(t)))

매개 변수화 된 곡선 의 곡률을 계산하는 함수가 필요합니다 . 스플라인의 1 차 및 2 차 미분 값을 추정해야합니다. 많은 스플라인 (입방 스플라인 등)을 사용하면 쉽게 대수 계산할 수 있습니다. R처음 세 파생 상품을 자동으로 제공합니다. (다른 환경에서는 도함수를 수치 적으로 계산할 수 있습니다.)

curvature <- function(t, fx, fy) {
  # t is an argument to spline functions fx and fy.
  xp <- fx(t,1); yp <- fy(t,1)            # First derivatives
  xpp <- fx(t,2); ypp <- fy(t,2)          # Second derivatives
  v <- sqrt(xp^2 + yp^2)                  # Speed
  (xp*ypp - yp*xpp) / v^3                 # (Signed) curvature
  # (Left turns have positive curvature; right turns, negative.)
}

kappa <- abs(curvature(time, fx, fy))     # Absolute curvature of the data

곡선의 범위에서 곡률 제로에 대한 임계 값 을 추정 할 것을 제안합니다 . 이것은 적어도 좋은 출발점입니다. 곡선의 비틀림에 따라 조정되어야합니다 (즉, 더 긴 곡선 일수록 증가). 나중에 곡률에 따라 플롯을 채색하는 데 사용됩니다.

curvature.zero <- 2*pi / max(range(xy[,1]), range(xy[,2])) # A small threshold
i.col <- 1 + floor(127 * curvature.zero/(curvature.zero + kappa)) 
palette(terrain.colors(max(i.col)))                        # Colors

이제 정점이 스플라인되고 곡률이 계산되었으므로 변곡점을 찾기 만합니다 . 그것들을 나타 내기 위해 정점을 플롯하고 스플라인을 플롯하고 그 위에 변곡점을 표시 할 수 있습니다.

plot(xy, asp=1, xlab="x",ylab="y", type="n")
tmp <- sapply(2:length(kappa), function(i) lines(rbind(uv[,i-1],uv[,i]), lwd=2, col=i.col[i]))
points(t(sapply(time[diff(kappa < curvature.zero/2) != 0], 
       function(t) c(fx(t), fy(t)))), pch=19, col="Black")
points(xy)

음모

열린 점은 원래 정점 xy이고 검은 점은이 알고리즘으로 자동 식별되는 변곡점입니다. 커브의 끝점에서 곡률을 안정적으로 계산할 수 없으므로 해당 점은 특별히 표시되지 않습니다.


어쩌면 내가 사용한 용어가 잘못되었을 수도 있습니다. 당신이 가정 한 것은 정확히 내가 원하는 것입니다. 당신의 대답은 유망 해 보이며, Shapefile을 처리하려면 R과 협력해야합니다.
— Devdatta Tengshe

3

Densify 도구를 사용할 수 있습니다 . 이 경우 각도별로 밀도를 선택하고 다음으로 직선으로 허용되는 최대 각도를 선택하십시오. 그런 다음 정점에서 스플릿 라인 도구에 결과 라인을 적용합니다 . 마지막으로 shape_length가 최소 도로 길이보다 작은 선을 삭제하십시오.

여기에 이미지 설명을 입력하십시오

이 그림에서 우리는 세 단계를 봅니다.

1- 각도를 사용하여 선의 밀도를 높입니다. 매개 변수로 10도를 사용했으며 분할 선을 사용했습니다. 그림에서 곡선은 초기 단계에 있습니다.

arcpy.Densify_edit("line" , "ANGLE" , "","",10)
arcpy.SplitLine_management("line" , "line_split")

2- shape_length가 중복되지 않는 세그먼트를 선택하십시오. 표에서 볼 수 있듯이 중복 길이를 선택하지 않았습니다. 그런 다음 새 피쳐 클래스로 선택합니다.

arcpy.Select_analysis("line_split" , "line_split_selected")

3- 우리는 변곡점 인 선의 가장자리에있는 정점을 추출했습니다.

arcpy.FeatureVerticesToPoints_management("line_split_selected" , "line_split_pnt" , "DANGLE")

다른 답변과 관련하여 동일한 의견과 질문이 있습니다. 좋은 생각이지만 동시에 원하는 결과를 얻을지 또는 임계 각도를 선택 해야하는지 확실하지 않습니다. 독자가이 제안이 실제로 무엇을 평가할 수 있도록 결과의 그림을 제공 할 수 있습니까? ESRI 소프트웨어를 솔루션의 일부로 추천 할 때는 작업 예제를 제공하는 것이 특히 중요합니다. 알고리즘은 일반적으로 문서화되어 있지 않으므로 수행중인 작업을 정확히 알 수 없기 때문입니다.
— whuber

그것이 작동하는 솔루션임을 확신하려면 테스트해야하지만 테스트 할 수 없으며 데이터가 누락되어 ESRI에서 제안한 도구가 예상대로 작동한다고 가정하지만이 답변은 추가 테스트를받습니다.
— geogeek

우리는 그들에게 아이디어의 이름을
— 지정할 수

1
그런 다음 주석으로 옮기시겠습니까? BTW, 데이터를 테스트하려면 시작하기 위해 내 답변에 게시 한 좌표를 질문의 그림에 가깝기 때문에 사용할 수 있습니다. 그러나 왜 편리한 지리 데이터를 사용하지 않습니까?
— whuber

2
예, 실제로이 솔루션은 직선을 추출하는 데 더 효과적입니다.
— geogeek

1

원래 줄의 최대 오프셋이 있는 일반화 도구를 매개 변수로 사용할 수 있으므로 자신의 상황에 맞는 오프셋을 선택할 수 있습니다.

여기에 이미지 설명을 입력하십시오

원래 줄의 이름을 "line_cur"로 일반화 한 줄을 "line_gen"으로 지정하면 "line_gen"을 기준으로 "line_cur"를자를 수 있습니다. 결과는 "line_cur"의 직선 세그먼트입니다. 그런 다음 최소 도로 길이보다 큰 Shape_length를 선택하는 sql 쿼리로 삭제하여 매우 짧은 세그먼트를 정리할 수 있습니다.


좋은 생각입니다. 그러나 실제로 실제로 얼마나 잘 작동하는지는 확실하지 않습니다. 발견 된 변곡점을 보여주는 예를 보여줄 수 있습니까?
— whuber

나는 그림을 포함하도록 편집을했다. 그림은이 도구가 직선으로 고정 된 선을 만드는 방법을 설명한다. 그래서 우리는 오래된 직선으로 클립을 만들어서 오래된 직선 세그먼트를 추출해야한다
— geogeek

귀하의 질문에 답변 할 수있는 것이 확실하지 않습니까?
— geogeek

그림에 식별 된 변곡점이 보이지 않습니다. 그들이 정확히 어디에 있었습니까? 그리고 일반화에 대한 내성을 어떻게 선택해야합니까?
— whuber

테스트를 수행하려면 데이터가 필요하지만 실험을 통해 허용 오차를 선택해야한다고 생각합니다.
— geogeek
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.