経験のある人がxyzデータからシェープファイルを準備する方法を手伝ってくれることを願っています。よく準備されたデータセットの素晴らしい例を見ることができます ここ チュリュモフゲラシメンコ彗星の場合 シェープファイル を作成する前の手順は提供されていません。
特定のXYZ座標のセットにサーフェスを適用する方法をよりよく理解しようとしています。 Rパッケージ「rgl」ではデカルト座標の使用は簡単ですが、ラップアラウンドする形状はより難しいようです。 [〜#〜] qhull [〜#〜] 関数へのインターフェースを提供するRパッケージgeometry
を見つけました。これを使用して、ドロネー三角形分割ファセットを計算してみました。これをrgl
にプロットできます。これらのファセットが計算される最大距離を制御するために、関数delaunayn
に関連付けられているオプションのいくつかを理解できません。ここにいる誰かが、xyzデータから表面構造を改善するためのアイデアを持っていることを願っています。
_library(onion)
library(rgl)
library(geometry)
data(bunny)
#XYZ point plot
open3d()
points3d(bunny, col=8, size=0.1)
#rgl.snapshot("3d_bunny_points.png")
#Facets following Delaunay triangulation
tc.bunny <- delaunayn(bunny)
open3d()
tetramesh(tc.bunny, bunny, alpha=0.25, col=8)
#rgl.snapshot("3d_bunny_facets.png")
_
この回答 QhullのR実装に問題がある可能性があると私は信じています。また、さまざまな設定(delaunayn(bunny, options="Qt")
など)を試しましたが、ほとんど効果がありませんでした。 Qhullオプションの概要 ここ
これは、球の追加の(より単純な)例です。ここでも、ファセットの計算で最も近い隣接する頂点が常に見つかるとは限りません(ボールを回転させると、いくつかのファセットが内部を横切っているのがわかります)。
_library(rgl)
library(geometry)
set.seed(1)
n <- 10
rho <- 1
theta <- seq(0, 2*pi,, n) # azimuthal coordinate running from 0 to 2*pi
phi <- seq(0, pi,, n) # polar coordinate running from 0 to pi (colatitude)
grd <- expand.grid(theta=theta, phi=phi)
x <- rho * cos(grd$theta) * sin(grd$phi)
y <- rho * sin(grd$theta) * sin(grd$phi)
z <- rho * cos(grd$phi)
set.seed(1)
xyz <- cbind(x,y,z)
tbr = t(surf.tri(xyz, delaunayn(xyz)))
open3d()
rgl.triangles(xyz[tbr,1], xyz[tbr,2], xyz[tbr,3], col = 5, alpha=0.5)
rgl.snapshot("ball.png")
_
これは、カーネル密度推定とcontour3d
のmisc3d
関数を使用したアプローチです。きちんと機能するlevels
の値が見つかるまで遊んでみました。完全に正確というわけではありませんが、物事を微調整して、より良い、より正確な表面を得ることができる場合があります。 8GBを超えるメモリがある場合は、ここで行った以上にn
を増やすことができる場合があります。
library(rgl)
library(misc3d)
library(onion); data(bunny)
# the larger the n, the longer it takes, the more RAM you need
bunny.dens <- kde3d(bunny[,1],bunny[,2],bunny[,3], n=150,
lims=c(-.1,.2,-.1,.2,-.1,.2)) # I chose lim values manually
contour3d(bunny.dens$d, level = 600,
color = "pink", color2 = "green", smooth=500)
rgl.viewpoint(zoom=.75)
右の画像は下から見たもので、別のビューを示しています。
kde3d
のn
に大きな値を使用できますが、時間がかかり、配列が大きくなりすぎるとRAMが不足する可能性があります。また、別の帯域幅を試してください(ここではデフォルトが使用されています)。このアプローチは Rでの等値面の計算と表示-Feng&Tierney 2008 から採用しました。
Rvcg
パッケージを使用した非常に類似した等値面アプローチ:
library(Rvcg)
library(rgl)
library(misc3d)
library(onion); data(bunny)
bunny.dens <- kde3d(bunny[,1],bunny[,2],bunny[,3], n=150,
lims=c(-.1,.2,-.1,.2,-.1,.2)) # I chose lim values manually
bunny.mesh <- vcgIsosurface(bunny.dens$d, threshold=600)
shade3d(vcgSmooth(bunny.mesh,"HC",iteration=3),col="pink") # do a little smoothing
これは密度推定ベースのアプローチであるため、バニーの密度を上げることで、それをもう少し活用できます。ここでもn=400
を使用しています。コストは計算時間の大幅な増加ですが、結果として得られるサーフェスはhareより優れています。
bunny.dens <- kde3d(rep(bunny[,1], 10), # increase density.
rep(bunny[,2], 10),
rep(bunny[,3], 10), n=400,
lims=c(-.1,.2,-.1,.2,-.1,.2))
bunny.mesh <- vcgIsosurface(bunny.dens$d, threshold=600)
shade3d(vcgSmooth(bunny.mesh,"HC",iteration=1), col="pink")
より優れた、より効率的な表面再構成方法(パワークラスト、ポアソン表面再構成、ボールピボットアルゴリズムなど)が存在しますが、Rで実装されている方法はまだわかりません。
これは、関連するStack Overflowの投稿で、いくつかの優れた情報とチェックアウトするリンク(コードへのリンクを含む)があります: Dポイントクラウドからの表面再構成のための堅牢なアルゴリズム? 。
alphashape3d
パッケージを使用して1つの可能な解決策を見つけたと思います。与えられたデータセットの距離に関連するalpha
の許容値を取得するために、少し遊んでいなければなりませんでした(たとえば、sd
のbunny
は私にいくつかの洞察を与えました)。プロットを支配しないように、頂点とエッジの線の幅をより適切に制御する方法をまだ模索していますが、これはおそらくrgl
の設定に関連しています。
library(onion)
library(rgl)
library(geometry)
library(alphashape3d)
data(bunny)
apply(bunny,2,sd)
alphabunny <- ashape3d(bunny, alpha = 0.003)
bg3d(1)
plot.ashape3d(alphabunny, col=c(5,5,5), lwd=0.001, size=0, transparency=rep(0.5,3), indexAlpha = "all")
plot.ashape3d
関数を調整するだけで、エッジと頂点を削除できました。
plot.ashape3d.2 <- function (x, clear = TRUE, col = c(2, 2, 2), byComponents = FALSE,
indexAlpha = 1, transparency = 1, walpha = FALSE, ...)
{
as3d <- x
triangles <- as3d$triang
edges <- as3d$Edge
vertex <- as3d$vertex
x <- as3d$x
if (class(indexAlpha) == "character")
if (indexAlpha == "ALL" | indexAlpha == "all")
indexAlpha = 1:length(as3d$alpha)
if (any(indexAlpha > length(as3d$alpha)) | any(indexAlpha <=
0)) {
if (max(indexAlpha) > length(as3d$alpha))
error = max(indexAlpha)
else error = min(indexAlpha)
stop(paste("indexAlpha out of bound : valid range = 1:",
length(as3d$alpha), ", problematic value = ", error,
sep = ""), call. = TRUE)
}
if (clear) {
rgl.clear()
}
if (byComponents) {
components = components_ashape3d(as3d, indexAlpha)
if (length(indexAlpha) == 1)
components = list(components)
indexComponents = 0
for (iAlpha in indexAlpha) {
if (iAlpha != indexAlpha[1])
rgl.open()
if (walpha)
title3d(main = paste("alpha =", as3d$alpha[iAlpha]))
cat("Device ", rgl.cur(), " : alpha = ", as3d$alpha[iAlpha],
"\n")
indexComponents = indexComponents + 1
components[[indexComponents]][components[[indexComponents]] ==
-1] = 0
colors = c("#000000", sample(Rainbow(max(components[[indexComponents]]))))
tr <- t(triangles[triangles[, 8 + iAlpha] == 2 |
triangles[, 8 + iAlpha] == 3, c("tr1", "tr2",
"tr3")])
if (length(tr) != 0)
rgl.triangles(x[tr, 1], x[tr, 2], x[tr, 3], col = colors[1 +
components[[indexComponents]][tr]], alpha = transparency,
...)
}
}
else {
for (iAlpha in indexAlpha) {
if (iAlpha != indexAlpha[1])
rgl.open()
if (walpha)
title3d(main = paste("alpha =", as3d$alpha[iAlpha]))
cat("Device ", rgl.cur(), " : alpha = ", as3d$alpha[iAlpha],
"\n")
tr <- t(triangles[triangles[, 8 + iAlpha] == 2 |
triangles[, 8 + iAlpha] == 3, c("tr1", "tr2",
"tr3")])
if (length(tr) != 0)
rgl.triangles(x[tr, 1], x[tr, 2], x[tr, 3], col = col[1],
, alpha = transparency, ...)
}
}
}
alphabunny <- ashape3d(bunny, alpha = c(0.003))
plot.ashape3d.2(alphabunny, col=5, indexAlpha = "all", transparency=1)
bg3d(1)
パッケージRvcg
は2016年7月にバージョン0.14に更新され、ボールピボット面の再構成が追加されました。関数はvcgBallPivoting
です:
library(Rvcg) # needs to be >= version 0.14
library(rgl)
library(onion); data(bunny)
# default parameters
bunnybp <- vcgBallPivoting(bunny, radius = 0.0022, clustering = 0.2, angle = pi/2)
shade3d(bunnybp, col = Rainbow(1000), specular = "black")
shade3d(bunnybp, col = "pink", specular = "black") # easier to see problem areas.
ボールのピボットとデフォルトのパラメータ設定はスタンフォードバニーには完璧ではなく(コメントのcuttlefish44で指摘されているようにradius = 0.0022
はデフォルトのradius = 0
よりも優れています)、表面にいくつかのギャップが残っています。実際のバニーにはベースに2つの穴があり、スキャンの制限によって他のいくつかの穴が発生します(ここで説明するように: https://graphics.stanford.edu/software/scanview/models/bunny.html )。より良いパラメータを見つけることができるかもしれません、そしてvcgBallPivoting
(私のマシンでは〜0.5秒)を使うのは非常に速いです、しかしギャップを埋めるために追加の努力/方法が必要かもしれません。