- 昨日の記事は、まあ、ユーティリティ関数をいじるだけ、今日はユーティリティ関数にコメントを加えたり、少し、いろいろと書いておこう
- 2次元平面の曲線を、球面に変換する
my.circle <- function(X){
x1 <- X[1,1]
x2 <- X[2,1]
x3 <- X[3,1]
y1 <- X[1,2]
y2 <- X[2,2]
y3 <- X[3,2]
rot <- 0
if(y2-y1 ==0){
rot <- 1
x1 <- X[1,2]
x2 <- X[2,2]
x3 <- X[3,2]
y1 <- X[1,1]
y2 <- X[2,1]
y3 <- X[3,1]
}
x <- 1/2 * 1/(y1*(x2-x3)+y2*(x3-x1)+y3*(x1-x2)) * ((y1-y2)*(y2-y3)*(y3-y1)-((y2-y3)*x1^2+(y3-y1)*x2^2+(y1-y2)*x3^2))
y <- -(x2-x1)/(y2-y1)*(x-(x1+x2)/2) + (y1+y2)/2
ctr <- c(x,y)
if(rot==1){
ctr <- c(y,x)
}
tmp <- (t(t(X)-ctr))
angles <- Arg(tmp[,1] + 1i*tmp[,2])
angles[which(angles<0)] <- angles[which(angles<0)] + 2*pi
angle.dir <- 1
if(angles[2] > angles[1]){
if(angles[3] > angles[2]){
}else{
if(angles[3] < angles[1]){
angles[3] <- angles[3] + 2*pi
}else{
angle.dir <- -1
angles[2] <- angles[2] - 2*pi
angles[3] <- angles[3] - 2*pi
}
}
}else{
if(angles[3] < angles[2]){
angle.dir <- -1
}else{
if(angles[3] > angles[1]){
angle.dir <- -1
angles[3] <- angles[3] - 2*pi
}else{
angles[2] <- angles[2] + 2*pi
angles[3] <- angles[3] + 2*pi
}
}
}
R <- sqrt(sum((X[1,]-ctr)^2))
return(list(ctr=ctr,R=R,angles=angles,angle.dir=angle.dir))
}
n2sphere <- function(x){
r <- sqrt(sum(x^2))
z <- r^2/(r^2+1)
k <- sqrt(z*(1-z))
ret <- c(k/r*x,z)
ret
}
sphere2n <- function(x){
ret <- rep(0,length(x)-1)
if(x[length(x)]==1){
ret <- rep(Inf,length(ret))
}else{
tmp <- x
tmp[length(x)] <- -(tmp[length(x)]-1)
ret <- tmp[1:(length(x)-1)]/tmp[length(x)]
}
return(ret)
}
t <- seq(from=0,to=1,length=10000)*50
x <- exp(0.1*t)
y <- exp(0.1*t)*cos(1*t)
X <- cbind(x,y)
plot(X)
library(rgl)
n.r <- 1000
R <- matrix(rnorm(n.r*3),ncol=3)
R <- R/sqrt(apply(R^2,1,sum))/2
R[,3] <- R[,3]+0.5
plot3d(R)
X. <- t(apply(X,1,n2sphere))
points3d(X.,col=2)
X. <- t(apply(X,1,n2sphere))
X.. <- t(apply(X.,1,sphere2n))
plot(X..)
- (0,0,0.5)を中心とする半径0.5の球上の3点
my.perpendic <- function(X){
n <- length(X[1,])
tmp.m <- X[,1:(n-1)]
if(det(tmp.m)!=0){
ret <- solve(tmp.m) %*% ((-1)*X[,n])
ret <- c(ret,1)
}else{
tmp.m <- X[,2:n]
ret <- solve(tmp.m) %*% ((-1)*X[,1])
ret <- c(1,ret)
}
ret/sqrt(sum(ret^2))
}
my.circle.sphere <- function(X){
v1 <- X[1,]-X[3,]
v2 <- X[2,]-X[3,]
v1 <- v1/sqrt(sum(v1^2))
v2 <- v2/sqrt(sum(v2^2))
tmp.X <- rbind(v1,v2)
v3 <- my.perpendic(tmp.X)
v2. <- my.perpendic(rbind(v1,v3))
R <- sqrt(sum(X[1,]^2))
M <- cbind(v1,v2.,v3)
ip <- sum(v3 * X[1,]/R)
return(list(M=M,r=sqrt(1-ip^2),z=ip))
}
X <- matrix(rnorm(6),ncol=2)
X2 <- t(apply(X,1,n2sphere))
X2[,3] <- X2[,3] - 0.5
X2 <- X2 * 2
tmp.out <- my.circle.sphere(X2)
t <- seq(from=0,to=1,length=100)*2*pi
x <- tmp.out$r*cos(t)
y <- tmp.out$r*sin(t)
z <- rep(tmp.out$z,length(t))
XYZ <- cbind(x,y,z)
XYZ. <- t(tmp.out$M %*% t(XYZ))
plot3d(XYZ.)
points3d(X2,col=2,size=20)
- 一般にベクトル空間に3点あれば、その3点を通る円は確定する。3点を通る円の「第1点」から「第2点」までに円弧を引いてみよう
my.circle.n <- function(X,n=100){
v1.ori <- X[1,]-X[3,]
v2.ori <- X[2,]-X[3,]
v1 <- v1.ori/sqrt(sum(v1.ori^2))
v2 <- v2.ori/sqrt(sum(v2.ori^2))
tmp.X <- rbind(v1,v2)
v3 <- my.perpendic(tmp.X)
v2. <- my.perpendic(rbind(v1,v3))
M <- rbind(v1,v2.,v3)
coords <- M %*% cbind(v1.ori,v2.ori)
Y <- rbind(t(coords[1:2,1:2]),c(0,0))
out <- my.circle(Y)
ctr <- c(out$ctr,0)
t <- seq(from=out$angles[1],to=out$angles[2],length=100)
x <- out$R*cos(t)+out$ctr[1]
y <- out$R*sin(t)+out$ctr[2]
tmp2 <-t(t(M) %*% rbind(x,y,rep(0,length(t))) + X[3,])
tmp2
}
X <- diag(rep(1,3))
X <- matrix(rnorm(9),3,3)
out <- my.circle.n(X)
plot3d(out)
points3d(X,col=2,size=5)
my.rotation.2vec <- function(v1,v2,theta=seq(from=0,to=1,length=100)*2*pi){
L1 <- sqrt(sum(v1^2))
L2 <- sqrt(sum(v2^2))
v1. <- v1/L1
v2. <- v2/L2plot.sphere.curve <- function(X,X.line=TRUE,Ctr=TRUE,Ctr.curve=TRUE,Circle=TRUE,n.r=1000,n.t=50,z0=TRUE,alphar=0.3,alphaz0=0.3){
n.pt <- length(X[,1])
X. <- t(apply(X,1,n2sphere))
R <- matrix(rnorm(n.r*3),ncol=3)
R <- R/sqrt(apply(R^2,1,sum))/2
R[,3] <- R[,3]+0.5
R <- rbind(R,c(0,0,-0.1))
circles <- list()
X.. <- X.
X..[,3] <- X..[,3] - 0.5
X.. <- X.. * 2
for(i in 1:(n.pt-2)){
circles[[i]] <- my.circle.sphere(X..[i:(i+2),])
}
ctr <- matrix(0,length(circles),3)
t <- seq(from=0,to=1,length=n.t)*2*pi
cic <- list()
for(i in 1:length(ctr[,1])){
ctr[i,] <- circles[[i]]$M[,3]*circles[[i]]$z
tmp <- cbind(circles[[i]]$r*cos(t),circles[[i]]$r*sin(t),rep(circles[[i]]$z,length(t)))
tmp <- t(circles[[i]]$M %*% t(tmp))
cic[[i]] <- tmp
cic[[i]] <- cic[[i]]/2
cic[[i]][,3] <- cic[[i]][,3] + 0.5
}
ctr. <- ctr/2
ctr.[,3] <- ctr.[,3] + 0.5
plot3d(R,alpha=alphar)
if(z0){
planes3d(0,0,1,0,alpha=0.3)
}
if(Ctr){
points3d(ctr.,col=3,size=5)
}
if(Ctr.curve){
for(i in 1:(length(ctr.[,1])-1)){
tmp.X <- rbind(ctr.[i,],ctr.[i+1,],c(0,0,0.5))
out <- my.circle.n(tmp.X)
lines3d(out,col=4)
}
}
if(Circle){
for(i in 1:length(cic)){
lines3d(cic[[i]],col=6)
}
}
points3d(X.,col=2,size=5)
if(X.line){
lines3d(X.,col=2)
}
plot(X,pch=20,type="b")
points(t(apply(ctr.,1,sphere2n)),col=2)
for(i in 1:length(cic)){
points(t(apply(cic[[i]],1,sphere2n)),col=3,type="l")
}
lines(t(apply(ctr.,1,sphere2n)),col=2)
}
v3. <- v2.-sum(v1.*v2.)*v1.
v3. <- v3./sqrt(sum(v3.^2))
x <- y <- rep(0,length(theta))
x <- cos(theta)
y <- sin(theta)
m <- cbind(v1.,v3.)
tmp <- t(m %*% rbind(x,y))
print(L1)
tmp * L1
}
v1 <- c(1,0,0)
v2 <- c(0,0,1)
X <- my.rotation.2vec(v1,v2)
plot3d(X)
- さて。
- 曲線を反映する2次元平面の点列が得られたとき、それを3次元球面に移して、その上での曲線ととらえつつ、滑らかに移行するように、曲率中心を「合い隣り合う2点の球面上に対応する2点を通る2つの球面上の円を取り、その2円のうちの第一のものから第二のものへと、その2点を通るままに移行させることを考える。そのような円の中心はもちろん連続的に変化する。その様子を描く関数

plot.sphere.curve <- function(X,X.line=TRUE,Ctr=TRUE,Ctr.curve=TRUE,Circle=TRUE,n.r=1000,n.t=50,z0=TRUE,alphar=0.3,alphaz0=0.3){
n.pt <- length(X[,1])
X. <- t(apply(X,1,n2sphere))
R <- matrix(rnorm(n.r*3),ncol=3)
R <- R/sqrt(apply(R^2,1,sum))/2
R[,3] <- R[,3]+0.5
R <- rbind(R,c(0,0,-0.1))
circles <- list()
X.. <- X.
X..[,3] <- X..[,3] - 0.5
X.. <- X.. * 2
for(i in 1:(n.pt-2)){
circles[[i]] <- my.circle.sphere(X..[i:(i+2),])
}
ctr <- matrix(0,length(circles),3)
t <- seq(from=0,to=1,length=n.t)*2*pi
cic <- list()
for(i in 1:length(ctr[,1])){
ctr[i,] <- circles[[i]]$M[,3]*circles[[i]]$z
tmp <- cbind(circles[[i]]$r*cos(t),circles[[i]]$r*sin(t),rep(circles[[i]]$z,length(t)))
tmp <- t(circles[[i]]$M %*% t(tmp))
cic[[i]] <- tmp
cic[[i]] <- cic[[i]]/2
cic[[i]][,3] <- cic[[i]][,3] + 0.5
}
ctr. <- ctr/2
ctr.[,3] <- ctr.[,3] + 0.5
plot3d(R,alpha=alphar)
if(z0){
planes3d(0,0,1,0,alpha=0.3)
}
if(Ctr){
points3d(ctr.,col=3,size=5)
}
if(Ctr.curve){
for(i in 1:(length(ctr.[,1])-1)){
tmp.X <- rbind(ctr.[i,],ctr.[i+1,],c(0,0,0.5))
out <- my.circle.n(tmp.X)
lines3d(out,col=4)
}
}
if(Circle){
for(i in 1:length(cic)){
lines3d(cic[[i]],col=6)
}
}
points3d(X.,col=2,size=5)
if(X.line){
lines3d(X.,col=2)
}
plot(X,pch=20,type="b")
points(t(apply(ctr.,1,sphere2n)),col=2)
for(i in 1:length(cic)){
points(t(apply(cic[[i]],1,sphere2n)),col=3,type="l")
}
lines(t(apply(ctr.,1,sphere2n)),col=2)
}
t <- seq(from=0,to=3,length=200)
t <- t[-1]
x <- exp(t)*cos(10*t)
y <- exp(t)*sin(10*t)
X <- cbind(x,y)
plot(X,type="b")
plot.sphere.curve(X,Circle=FALSE)