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


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)

xy 좌표를 별도로 스플라인하여 곡선의 매개 변수화를 달성하십시오. (매개 변수는이라고 부릅니다 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.