변곡점, 즉 선의 곡선이 시작하고 끝나는 지점을 찾으려고합니다. 이미지를 보면 녹색 선이 도로 또는 개울 일 수 있으며 검은 점은 곡선이 시작하고 끝나는 지점입니다.
이러한 포인트 생성을 자동화하기위한 상위 단계는 무엇입니까? ArcGIS 데스크탑이 있고 ArcObjects에 매우 편리합니다.
변곡점, 즉 선의 곡선이 시작하고 끝나는 지점을 찾으려고합니다. 이미지를 보면 녹색 선이 도로 또는 개울 일 수 있으며 검은 점은 곡선이 시작하고 끝나는 지점입니다.
이러한 포인트 생성을 자동화하기위한 상위 단계는 무엇입니까? ArcGIS 데스크탑이 있고 ArcObjects에 매우 편리합니다.
답변:
곡선이 선분으로 구성되는 경우 해당 선분의 모든 내부 점은 변곡점이므로 흥미롭지 않습니다. 대신, 곡선은 해당 세그먼트 의 정점 에 의해 근사 된 것으로 생각해야합니다 . 이러한 세그먼트를 통해 부분적으로 두 배로 구분 가능한 곡선을 스플라인함으로써 곡률을 계산할 수 있습니다. 엄밀히 말하면 변곡점은 곡률이 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
이고 검은 점은이 알고리즘으로 자동 식별되는 변곡점입니다. 커브의 끝점에서 곡률을 안정적으로 계산할 수 없으므로 해당 점은 특별히 표시되지 않습니다.
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")
원래 줄의 최대 오프셋이 있는 일반화 도구를 매개 변수로 사용할 수 있으므로 자신의 상황에 맞는 오프셋을 선택할 수 있습니다.
원래 줄의 이름을 "line_cur"로 일반화 한 줄을 "line_gen"으로 지정하면 "line_gen"을 기준으로 "line_cur"를자를 수 있습니다. 결과는 "line_cur"의 직선 세그먼트입니다. 그런 다음 최소 도로 길이보다 큰 Shape_length를 선택하는 sql 쿼리로 삭제하여 매우 짧은 세그먼트를 정리할 수 있습니다.