Пакет misc3d
обеспечивает отличную реализацию алгоритма движущихся кубов, позволяя строить неявные поверхности.
Например, давайте построим циклический цикл Дюпена:
a = 0.94; mu = 0.56; c = 0.34 # cyclide parameters
f <- function(x, y, z, a, c, mu){ # implicit equation f(x,y,z)=0
b <- sqrt(a^2-c^2)
(x^2+y^2+z^2-mu^2+b^2)^2 - 4*(a*x-c*mu)^2 - 4*b^2*y^2
}
# define the "voxel"
nx <- 50; ny <- 50; nz <- 25
x <- seq(-c-mu-a, abs(mu-c)+a, length=nx)
y <- seq(-mu-a, mu+a, length=ny)
z <- seq(-mu-c, mu+c, length=nz)
g <- expand.grid(x=x, y=y, z=z)
voxel <- array(with(g, f(x,y,z,a,c,mu)), c(nx,ny,nz))
# plot the surface
library(misc3d)
surf <- computeContour3d(voxel, level=0, x=x, y=y, z=z)
drawScene.rgl(makeTriangles(surf))
Хорошо, за исключением того, что поверхность не гладкая.
Документация drawScene.rgl
гласит: «Объектно-ориентированные функции рендеринга, такие как сглаживание и материал, управляются установкой в объектах». Я не знаю, что это значит. Как получить гладкую поверхность?
У меня есть решение, но не простое: это решение состоит в построении объекта mesh3d
из выходных данных computeContour3d
и включении нормалей поверхности в этот mesh3d
.
Нормы поверхности неявной поверхности, определяемой f(x,y,z)=0
, просто задаются градиентом f
. Нетрудно получить градиент для этого примера.
gradient <- function(xyz,a,c,mu){
x <- xyz[1]; y <- xyz[2]; z <- xyz[3]
b <- sqrt(a^2-c^2)
c(
2*(2*x)*(x^2+y^2+z^2-mu^2+b^2) - 8*a*(a*x-c*mu),
2*(2*y)*(x^2+y^2+z^2-mu^2+b^2) - 8*b^2*y,
2*(2*z)*(x^2+y^2+z^2-mu^2+b^2)
)
}
Тогда нормали вычисляются следующим образом:
normals <- apply(surf, 1, function(xyz){
gradient(xyz,a,c,mu)
})
Теперь мы готовы сделать объект mesh3d
:
mesh <- list(vb = rbind(t(surf),1),
it = matrix(1:nrow(surf), nrow=3),
primitivetype = "triangle",
normals = rbind(-normals,1))
class(mesh) <- c("mesh3d", "shape3d")
И, наконец, нанести на карту rgl
:
library(rgl)
shade3d(mesh, color="red")
Хорошо, поверхность теперь гладкая.
Но есть ли более простой способ получить гладкую поверхность, без создания объекта mesh3d
? Что они означают в документации: «Объектно-ориентированные функции рендеринга, такие как сглаживание и материал, управляются настройкой в объектах.» ?