Wenn die Kurve aus Liniensegmenten besteht, sind alle inneren Punkte dieser Segmente Wendepunkte, was nicht interessant ist. Stattdessen sollte die Kurve als durch die Scheitelpunkte dieser Segmente angenähert angesehen werden . Indem wir eine stückweise doppelt differenzierbare Kurve durch diese Segmente splitten, können wir die Krümmung berechnen. Ein Wendepunkt ist dann genau genommen ein Ort, an dem die Krümmung Null ist.
Im Beispiel gibt es längere Strecken, in denen die Krümmung nahezu Null ist. Dies legt nahe, dass die angezeigten Punkte die Enden solcher Strecken von Regionen mit niedriger Krümmung approximieren sollten.
Ein effektiver Algorithmus wird daher die Eckpunkte splitten, die Krümmung entlang eines dichten Satzes von Zwischenpunkten berechnen, Bereiche mit einer Krümmung nahe Null identifizieren (unter Verwendung einer vernünftigen Schätzung dessen, was es bedeutet, "nahe" zu sein) und die Endpunkte dieser Bereiche markieren .
Im folgenden Arbeitscode R
werden diese Ideen veranschaulicht. Beginnen wir mit einer Zeilenfolge, die als eine Folge von Koordinaten ausgedrückt wird:
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)
Spline die x- und y- Koordinaten getrennt , um eine Parametrisierung der Kurve zu erreichen. (Der Parameter wird aufgerufen time
.)
n <- dim(xy)[1]
fx <- splinefun(1:n, xy[,1], method="natural")
fy <- splinefun(1:n, xy[,2], method="natural")
Interpolieren Sie die Splines zum Zeichnen und Berechnen:
time <- seq(1,n,length.out=511)
uv <- sapply(time, function(t) c(fx(t), fy(t)))
Wir benötigen eine Funktion, um die Krümmung einer parametrisierten Kurve zu berechnen . Es muss die erste und die zweite Ableitung des Splines geschätzt werden. Bei vielen Splines (z. B. kubischen Splines) ist dies eine einfache algebraische Berechnung. R
Liefert die ersten drei Ableitungen automatisch. (In anderen Umgebungen kann es sinnvoll sein, die Ableitungen numerisch zu berechnen.)
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
Ich schlage vor, eine Schwelle für die Krümmung Null in Bezug auf die Ausdehnung der Kurve zu schätzen . Dies ist zumindest ein guter Ausgangspunkt; es sollte entsprechend der Tortuosität der Kurve angepasst werden (dh für längere Kurven erhöht). Dies wird später zum Färben der Diagramme entsprechend der Krümmung verwendet.
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
Nachdem die Scheitelpunkte gekerbt und die Krümmung berechnet wurden, müssen nur noch die Wendepunkte gefunden werden . Um sie zu zeigen, können wir die Eckpunkte zeichnen, den Spline zeichnen und die Wendepunkte darauf markieren.
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)
Die offenen Punkte sind die ursprünglichen Eckpunkte in xy
und die schwarzen Punkte sind die Wendepunkte, die mit diesem Algorithmus automatisch identifiziert werden. Da die Krümmung an den Endpunkten der Kurve nicht zuverlässig berechnet werden kann, sind diese Punkte nicht besonders markiert.