Re: [R] adding 3D arrows to 3D plots

2010-01-10 Thread Barry Rowlingson
Have a go with this:

arrow3d - function(p0=c(0,1,0),p1=c(1,1,1),s=0.1,theta=pi/4,n=3,...){
 ##p0: start point
 ##p1: end point
 ## s: length of barb as fraction of line length
 ## theta: opening angle of barbs
 ## n: number of barbs
 ##   ...: args passed to lines3d for line styling

 require(geometry)
 require(rgl)

 ## rotational angles of barbs
 phi=seq(0,2*pi,len=n+1)[-1]

 ## length of line
 lp = sqrt(sum((p1-p0)^2))

 ## point down the line where the barb ends line up
 cpt=(1-(s*lp*cos(theta)))*(p1-p0)

 ## draw the main line
 line = lines3d(c(p0[1],p1[1]),c(p0[2],p1[2]),c(p0[3],p1[3]),...)

 ## need to find a right-angle to the line. So create a random point:
 rpt = jitter(c(
   runif(1,min(p0[1],p1[1]),max(p0[1],p1[1])),
   runif(1,min(p0[2],p1[2]),max(p0[2],p1[2])),
   runif(1,min(p0[3],p1[3]),max(p0[3],p1[3]))
   ))

 ## and if it's NOT on the line the cross-product gives us a vector
at right angles:
 r = extprod3d(p1-p0,rpt)
 ## normalise it:
 r = r / sqrt(sum(r^2))

 ## now compute the barb end points and draw:
 pts = list()
 for(i in 1:length(phi)){
   ptb=rotate3d(r,phi[i],(p1-p0)[1],(p1-p0)[2],(p1-p0)[3])
   lines3d(
   c(p1[1],cpt[1]+p0[1]+lp*s*sin(theta)*ptb[1]),
   c(p1[2],cpt[2]+p0[2]+lp*s*sin(theta)*ptb[2]),
   c(p1[3],cpt[3]+p0[3]+lp*s*sin(theta)*ptb[3]),
   ...
   )
 }
 return(line)
}

This creates a line with 'n' arrow barbs at one end, equally spaced
when you look at the line end-on. The barb length is 's' times the
length of the line, and the opening angle is theta. Just do arrow3d()
to get something.

Might be useful, plus I wanted to brush up on my vector geometry anyway...

Barry

__
R-help@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.


Re: [R] adding 3D arrows to 3D plots

2010-01-10 Thread Peter Ehlers

Cool, Barry.
I set n=30, col=red and stuck it into my daiquiri!

 -Peter Ehlers

Barry Rowlingson wrote:

Have a go with this:

arrow3d - function(p0=c(0,1,0),p1=c(1,1,1),s=0.1,theta=pi/4,n=3,...){
 ##p0: start point
 ##p1: end point
 ## s: length of barb as fraction of line length
 ## theta: opening angle of barbs
 ## n: number of barbs
 ##   ...: args passed to lines3d for line styling

 require(geometry)
 require(rgl)

 ## rotational angles of barbs
 phi=seq(0,2*pi,len=n+1)[-1]

 ## length of line
 lp = sqrt(sum((p1-p0)^2))

 ## point down the line where the barb ends line up
 cpt=(1-(s*lp*cos(theta)))*(p1-p0)

 ## draw the main line
 line = lines3d(c(p0[1],p1[1]),c(p0[2],p1[2]),c(p0[3],p1[3]),...)

 ## need to find a right-angle to the line. So create a random point:
 rpt = jitter(c(
   runif(1,min(p0[1],p1[1]),max(p0[1],p1[1])),
   runif(1,min(p0[2],p1[2]),max(p0[2],p1[2])),
   runif(1,min(p0[3],p1[3]),max(p0[3],p1[3]))
   ))

 ## and if it's NOT on the line the cross-product gives us a vector
at right angles:
 r = extprod3d(p1-p0,rpt)
 ## normalise it:
 r = r / sqrt(sum(r^2))

 ## now compute the barb end points and draw:
 pts = list()
 for(i in 1:length(phi)){
   ptb=rotate3d(r,phi[i],(p1-p0)[1],(p1-p0)[2],(p1-p0)[3])
   lines3d(
   c(p1[1],cpt[1]+p0[1]+lp*s*sin(theta)*ptb[1]),
   c(p1[2],cpt[2]+p0[2]+lp*s*sin(theta)*ptb[2]),
   c(p1[3],cpt[3]+p0[3]+lp*s*sin(theta)*ptb[3]),
   ...
   )
 }
 return(line)
}

This creates a line with 'n' arrow barbs at one end, equally spaced
when you look at the line end-on. The barb length is 's' times the
length of the line, and the opening angle is theta. Just do arrow3d()
to get something.

Might be useful, plus I wanted to brush up on my vector geometry anyway...

Barry

__
R-help@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.




--
Peter Ehlers
University of Calgary
403.202.3921

__
R-help@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.


Re: [R] adding 3D arrows to 3D plots

2010-01-07 Thread Duncan Murdoch

Eben J. Gering wrote:

Greetings,

I would like to add 3D arrows (i.e. arrow-headed vectors linking X1Y1Z1 to X2,Y2,Z2) to a 3D plot; ideally the sort of plot that can be rotated interactively.  Is this possible using plot3d, or another 3d plotter in R?  
While it is easy to draw segments in plot3d (e.g. below), I haven't figured out how to add arrow heads, or to create 3d arrows from scratch.  


##two headless segments:
library(rgl)
matrix(1:2,2,3)-segment1
matrix(1:3,2,3)-segment2
plot3d(segment2,type=l,col=red,xlim=c(0,3),ylim=c(0,3),zlim=c(0,3))
plot3d(segment1,type=l,add=TRUE,col=blue)

  


There isn't any current code to do that in rgl, but if you have a 
particular shape of arrow in mind, you could probably draw it with some 
combination of functions.  The main problem is that I've never seen any 
very appealing rotatable 3d arrows.  There's a Matlab function to draw 
some here:  
http://www.mathworks.com/matlabcentral/fileexchange/8396-draw-3d-arrows; 
it could probably be translated into rgl if you wanted that.


Duncan Murdoch

__
R-help@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.


[R] adding 3D arrows to 3D plots

2010-01-06 Thread Eben J. Gering
Greetings,

I would like to add 3D arrows (i.e. arrow-headed vectors linking X1Y1Z1 to 
X2,Y2,Z2) to a 3D plot; ideally the sort of plot that can be rotated 
interactively.  Is this possible using plot3d, or another 3d plotter in R?  
While it is easy to draw segments in plot3d (e.g. below), I haven't figured out 
how to add arrow heads, or to create 3d arrows from scratch.  

##two headless segments:
library(rgl)
matrix(1:2,2,3)-segment1
matrix(1:3,2,3)-segment2
plot3d(segment2,type=l,col=red,xlim=c(0,3),ylim=c(0,3),zlim=c(0,3))
plot3d(segment1,type=l,add=TRUE,col=blue)


thanks for any assistance,
-Eben J. Gering
Graduate Student, Section of Integrative Biology
The University of Texas at Austin
__
R-help@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.