[R] rgl how to plot a cylinder like arrow3d?
René Mayer
mayer at psychologie.tu-dresden.de
Tue Aug 9 13:26:07 CEST 2011
Thanks Duncan!
yes! this works;
I paste the code in case someone wants to draw
3d-vectors with cylinders and cones.
René
vector3D=function(start=c(0,0,0), end, mycol='green', cone.length=0.1, ... ){
# ... cylinder as basis-vector
c=cylinder3d(rbind( c(start), # start
c(0,0,1)), # end
radius = 0.4,
e1=cbind(0, 0, 1),
e2=cbind(1, 0, 0),
sides=10
)
# ... rotate cylinder horizontally and scale it
len=sqrt(sum(abs(end)*abs(end)))
c=scale3d(c,0.1,0.1,len-cone.length)
# ... Duncan Murdoch's code snipe
rotation <-
rgl:::GramSchmidt(end-start+c(1,0,0),end-start+c(0,1,0),end-start,
order=c(3,1,2))
c <- rotate3d(c, matrix=rotation)
shade3d(addNormals(c), col=mycol)
# ... cone3d from rgl-demos
q1 <- cone3d(qmesh=T,trans=diag(4)) # height=1,radius=1, base at (0,0,0)
q1=translate3d(scale3d(q1,0.15,0.15,1.4),0,0,len-cone.length)
q1=rotate3d(q1, matrix=rotation) # hinlegen ... negative rotation ==
zeigerrrichtung
shade3d(q1,col=mycol) # verschachtelt aufrufen
}
open3d()
vector3D(start=c(0,0,0),end=data[,1], 'red');
vector3D(start=c(0,0,0),end=data[,2],'green')
arrow3d(c(0,0,0),data[,1],color='red');arrow3d(c(0,0,0),data[,2],
color='green')
axes3d(c('x','y','z'));title3d('main','sub','X','Y','Z');box3d()
> On 11-08-09 5:22 AM, René Mayer wrote:
>> Dear List,
>> I'm trying to draw vector in XYZ with rgl under use of a cylinder3d.
>> Therefore I scale and rotate a basis-cylinder).
>> However, somehow the rotation is wrong as
>> verified by overplotting arrow3d().
>> Where is my mistake?
>
> I would guess it is in assuming that theta can be computed on the
> original vector, not on the rotated one: rotating about the Y axis
> changes end[1].
>
> I usually use a Gram-Schmidt type calculation to do this sort of
> thing. The undocumented rgl:::GramSchmidt function does this for
> 3x3 matrices, orthogonalizing by row. So you could replace all 3 of
> your rotations (including the first one) by this:
>
> rotation <-
> rgl:::GramSchmidt(end-start+c(1,0,0),end-start+c(0,1,0),end-start,
> order=c(3,1,2))
> c <- rotate3d(c, matrix=rotation)
>
> (I notice you also forgot to translate the cylinders to start; this
> doesn't matter in your example, but would if you had a non-zero
> origin.)
>
> One problem with this kind of display is that it assumes the
> coordinates are all of equal range. If you try plotting one of
> these vectors when the range of x, y and z are drastically
> different, the cylinders will look really strange.
>
> Duncan Murdoch
>
>>
>> library(heplots)
>> library(rgl)
>>
>> # ... 2 vectors
>> data=data.frame(row.names=c('X','Y','Z'), x1=c(2,1,5),y=c(4,3,2))
>>
>> vector3D=function(start=c(0,0,0), end, mycol='green'){
>> # ... cylinder as basis-vector
>> c=cylinder3d(rbind( c(start), # start
>> c(0,0,1)), # end
>> radius = 0.2,
>> e1=cbind(0, 0, 1),
>> e2=cbind(1, 0, 0),
>> sides=10
>> )
>>
>> # ... rotate cylinder horizontally and scale it
>> len=sqrt(sum(abs(end)*abs(end)))
>> c=scale3d(c,0.1,0.1,len)
>> c=rotate3d(c,-(pi/2),0,1,0)
>>
>> # ... rotation angles
>> theta = atan2(end[2],end[1]) # angle in yx-plane for Z-achses rotation
>> phi = atan2(end[3],sqrt(end[1]^2+end[1]^2)) # angle in zx for Y-achses
>> rotation
>>
>> # ... rotation
>> c=rotate3d(c,phi,0,1,0) # Y-achses rotation
>> c=rotate3d(c, -theta,0,0,1) # Z-achses rotation
>> shade3d(addNormals(c), col=mycol)
>> }
>>
>> open3d()
>> vector3D(start=c(0,0,0),end=data[,1], 'red');
>> vector3D(start=c(0,0,0),end=data[,2],'green')
>> arrow3d(c(0,0,0),data[,1],color='red');arrow3d(c(0,0,0),data[,2],
>> color='green')
>> axes3d(c('x','y','z'));title3d('main','sub','X','Y','Z');box3d()
>>
>> thanks,
>> René
>>
>> ______________________________________________
>> R-help at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>
>
More information about the R-help
mailing list