四元数とベクトルとメッシュと面積と

MikuHatsune2016-04-26

3次元物体をあつかっている。
3次元座標を四元数で扱うと回転や行列計算などが簡単らしい。
いま、頂点が三角メッシュ化されて表面が形成されている.obj のうさぎがいるとする。


いま、表面の各三角形の面積の合計が、四元数と疎行列を用いてこんな感じで計算される。

# 特に疎行列において、面単位で不定回数の値加算をするためのユーティリティ関数
my.vector.access <- function(v,a,func=sum,zero=0){
  if(is.vector(v)){
        v <- matrix(v,ncol=1)
    }
    ord <- order(a)
    rle.out <- rle(a[ord])
    num.row <- length(rle.out[[1]])
    num.col <- max(rle.out[[1]])
    tmp1 <- rep(1:num.row,rle.out[[1]])
    tmp2 <- c()
    for(i in 1:num.row){
        tmp2 <- c(tmp2,1:rle.out[[1]][i])
    }
    addr <- tmp1 + num.row*(tmp2-1)
    ret.v <- matrix(0,num.row,ncol(v))
    for(i in 1:ncol(v)){
        if(zero==0){
            tmp.V <- sparseVector(v[ord,i],i=addr,length=num.row*num.col)
            M <- Matrix(tmp.V,num.row,num.col)
        }else{
            M <- matrix(zero,num.row,num.col)
            M[addr] <- v[ord,i]

        }
        ret.v[,i] <- apply(M,1,func)

    }
    return(list(A = rle.out[[2]],V = ret.v))
}

また、三角形の面積は、四元数の積の虚部について絶対値をとって2で割ればよい。

Mod(Im(quanterion1- quanterion0))

 
xyz 座標での三角形が空間上になす平面の面積は、
A=\frac{1}{2}\sqrt{\begin{vmatrix}x_1&y_1&1\\x_2&y_2&1\\x_3&y_3&1\end{vmatrix}^2+\begin{vmatrix}y_1&z_1&1\\y_2&z_2&1\\y_3&z_3&1\end{vmatrix}^2+\begin{vmatrix}z_1&x_1&1\\z_2&x_2&1\\z_3&x_3&1\end{vmatrix}^2}
で与えられるから、8つの三角形を構成している左足の裏を見てみると

i <- 1
bun.v.new <- t(as.matrix(out.series1$v.list[[i]])[2:4,])
plot3d(bun.v.new)
mesh.tri <- tmesh3d(t(bun.v.new),t(bun.f),homogeneous=FALSE)
# 三角形を灰色で塗る
shade3d(mesh.tri,col="gray")
wire3d(mesh.tri)
j <- 337
text3d(bun.v.new[j, ], texts=j, col="blue")

# j 番目の点を構成成分とする三角形を抽出
k <- setdiff(unique(unlist(bun.f[apply(bun.f==j, 1, any),])), j)
# 点に目印をつける
for(l in k) text3d(bun.v.new[l, ], texts=l, col="red")
# 三角形を抽出する
plane <- as.matrix(bun.f[apply(bun.f==j, 1, any),])
# 三角形の面積の計算
tri_area <- rep(0, nrow(plane))
for(p in seq(nrow(plane))){
  hogemat <- as.matrix(bun.v[plane[p,],])
  tri_area[p] <- sqrt(sum(mapply(function(r) det(cbind(hogemat[, c(r, r%%3+1)], 1))^2 ,seq(3))))/2
}


M[j,]
[1] 0.0002846982 0.0002755177 0.0003673656 0.0003241680 0.0004353401
[6] 0.0004162023 0.0003144500 0.0004536900
tri_area
[1] 0.0002846982 0.0002755177 0.0003673656 0.0003241680 0.0004353401
[6] 0.0004162023 0.0003144500 0.0004536900

 
合ってる。
だがしかし、いま行っているC++ によるものとは計算時間ががが