物体の体積と表面積を計算したい。
三角メッシュ化されていれば、表面の三角形を足せば表面積はどうにかなる。
問題は体積。
The GNU Triangulated Surface Library(GTS)というもので計算できるっぽい。
sudo apt-get install libgts-dev
Python でも使えるようになっている。しかし、pip でインストールできなかったのでソースからインストールする。
例によって説明など存在しない。
GTS が使うのはgts ファイルという、こんな感じのファイル。
一辺10の正四面体の頂点、辺、三角形の数と
座標
エッジグラフ
エッジで構成される三角形
をひたすら並べている。
8 18 12 0 0 0 10 0 0 10 10 0 0 10 0 0 0 10 10 0 10 10 10 10 0 10 10 1 2 2 3 3 4 4 1 5 6 6 7 7 8 8 5 1 5 2 6 3 7 4 8 1 6 2 7 3 8 4 5 1 3 5 7 13 1 10 13 5 9 14 2 11 14 6 10 15 3 12 15 7 11 16 4 9 16 8 12 17 2 1 17 4 3 18 5 6 18 7 8
# Python 2.7 import gts f = "cube.gts" g = open(f) s = gts.read(g) # gts 読み込み s.volume() # 体積 s.area() # 表面積
問題はgts ファイルというやつで、obj ファイルからの変換がめんどくさい。
gtsの変換プログラム作ったよというメーリスも動かない。
Rvcg パッケージには、vcgGetEdge(mesh3d obj) という関数があって、三角形エッジをグラフにしてくれるが、これを使って上のcubeをいじってみると
library(Rvcg) e <- vcgGetEdge(mesh.tri) edge <- mapply(function(x) which(sapply(apply(t(mesh.tri$it), 1, setdiff, e[x, 1:2]), length) == 1), seq(nrow(e))) r <- vector("list", max(edge)) for(i in seq(ncol(edge))){ r[edge[,i]] <- lapply(r[edge[,i]], c, i) } r <- do.call(rbind.data.frame, r) colnames(r) <- NULL
こんなファイルになる。番号が少し入れ替わる。
8 18 12 0 0 0 10 0 0 10 10 0 0 10 0 0 0 10 10 0 10 10 10 10 0 10 10 1 2 1 3 1 4 1 5 1 6 2 3 2 6 2 7 3 4 3 7 3 8 4 5 4 8 5 6 5 7 5 8 6 7 7 8 1 5 7 4 5 14 6 8 10 7 8 17 9 11 13 10 11 18 3 4 12 12 13 16 1 2 6 2 3 9 14 15 17 15 16 18
これを使ってpython gts をやってみると、area() はできるが volume() で
RuntimeError: Surface is not orientable
と言われてエラー。
それでは世の中に転がっているものから obj → gts 変換をしようとして、Hira 3D viewerというものでobj ファイル読み込みからのgts 出力をしてみるのだが、gts で頂点が重複して出力されるのでどうにもならん。
だがしかし、GUI で体積は計算できる。
がんばって変換スクリプト書くしかなさそう。
と思っていたら計算できるっぽい。これとかこれとか。
4点,
,
,
で作られる四面体をひたすら足せばいいっぽくて、この物体の体積は
と、行列式で求められる。
sum(mapply(function(x) det(bun.v[bun.f[x,],])/6, seq(nrow(bun.f))))