Khi đường cong bao gồm các đoạn đường, thì tất cả các điểm bên trong của các đoạn đó là các điểm uốn, điều này không thú vị. Thay vào đó, đường cong nên được coi là gần đúng bởi các đỉnh của các đoạn đó. Bằng cách chia một đường cong có thể phân biệt hai lần qua các phân đoạn đó, sau đó chúng ta có thể tính toán độ cong. Một điểm uốn, nói đúng ra, sau đó là một nơi mà độ cong bằng không.
Trong ví dụ này có những đoạn dài kéo dài trong đó độ cong gần như bằng không. Điều này cho thấy rằng các điểm được chỉ định phải xấp xỉ các đầu của các khu vực có độ cong thấp như vậy.
Do đó, một thuật toán hiệu quả sẽ chia các đỉnh, tính toán độ cong dọc theo một tập hợp các điểm trung gian dày đặc, xác định các phạm vi độ cong gần bằng 0 (sử dụng một số ước tính hợp lý về ý nghĩa của "gần") và đánh dấu các điểm cuối của các phạm vi đó .
Đây là R
mã làm việc để minh họa những ý tưởng này. Hãy bắt đầu với một chuỗi dòng được biểu thị dưới dạng một chuỗi tọa độ:
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)
Tách các tọa độ x và y riêng biệt để đạt được tham số đường cong. (Tham số sẽ được gọi time
.)
n <- dim(xy)[1]
fx <- splinefun(1:n, xy[,1], method="natural")
fy <- splinefun(1:n, xy[,2], method="natural")
Nội suy các spline cho âm mưu và tính toán:
time <- seq(1,n,length.out=511)
uv <- sapply(time, function(t) c(fx(t), fy(t)))
Chúng ta cần một hàm để tính độ cong của đường cong tham số. Nó cần ước tính các dẫn xuất thứ nhất và thứ hai của spline. Với nhiều spline (chẳng hạn như splines khối), đây là một phép tính đại số dễ dàng. R
cung cấp ba dẫn xuất đầu tiên tự động. (Trong các môi trường khác, người ta có thể muốn tính toán các đạo hàm bằng số.)
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
Tôi đề xuất để ước tính một ngưỡng cho độ cong bằng không về phạm vi của đường cong. Điều này ít nhất là một điểm khởi đầu tốt; nó nên được điều chỉnh theo độ cong của đường cong (nghĩa là tăng cho các đường cong dài hơn). Điều này sau đó sẽ được sử dụng để tô màu các ô theo độ cong.
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
Bây giờ các đỉnh đã được chia và độ cong được tính toán, nó vẫn chỉ để tìm các điểm uốn . Để hiển thị chúng, chúng ta có thể vẽ các đỉnh, vẽ đồ thị và đánh dấu các điểm uốn trên nó.
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)
Các điểm mở là các đỉnh ban đầu xy
và các điểm đen là các điểm uốn được xác định tự động với thuật toán này. Bởi vì độ cong không thể được tính toán một cách đáng tin cậy tại các điểm cuối của đường cong, những điểm đó không được đánh dấu đặc biệt.