【问题标题】:How do I draw a 3D arrow in R?如何在 R 中绘制 3D 箭头?
【发布时间】:2013-03-15 13:52:17
【问题描述】:

我正在使用 rgl 包来创建我的数据的 3D 图。由于某些原因(3D PCA 双图),我需要向量——带箭头的线段。我被困住了,因为我想用 3D 锥体作为箭头。

不知何故,我无法将我的老旧思想包裹在问题的几何形状上。说,我会用

绘制矢量
segments3d( rbind( c( 0, 0, 0 ), c( 3, 3, 3 ) ) )

即从用户坐标系原点到[3,3,3]的向量。

我想创建一个尖端在 [3,3,3] 的圆锥。圆锥的底部可以形成一个圆形。在 xz 平面(垂直于 y 平面)上画一个半径为 r 的圆很容易:

n <- 10
sin.t <- sin( seq( 0, 2 * pi, len= n ) )
cos.t <- cos( seq( 0, 2 * pi, len= n ) )
r <- 0.1 
xv <- x + r * sin.t
yv <- rep( y, n )
zv <- z + r * cos.t

但是我现在如何转换这些点,使圆现在垂直于向量?并且它的中心距离沿向量方向的尖端 0.2?完成此转换后,我将使用 triangles3d 函数绘制三角形,每个三角形的尖端有一个角,圆的点内有两个顶点。

这是基础数学,我知道 18 岁的我(甚至 28 岁的我)不会有问题。任何钩子(而不是鱼)都将不胜感激。

【问题讨论】:

    标签: r graphics vector 3d


    【解决方案1】:

    在 rgl 的演示中有一个 cone3d 函数。它分别采用底座和尖端。无论如何,您都可以这样做:

    vec=rbind( c( 0, 0, 0 ), c( 3, 3, 3 ) )
    segments3d( vec )
    
    
    cone3d(base=vec[2,]-(vec[1,]+vec[2,]/6), 
         #this makes the head go 1/6th the length of the arrow
           rad=0.5,
           tip=vec[2,],
           col="blue",
           front="lines",
           back="lines")
    

    这里是cone3d函数:

       cone3d <- function(base=c(0,0,0),tip=c(0,0,1),rad=1,n=30,draw.base=TRUE,qmesh=FALSE,
                        trans = par3d("userMatrix"), ...) {
       ax <- tip-base
       if (missing(trans) && !rgl.cur()) trans <- diag(4)
       ### is there a better way?
       if (ax[1]!=0) {
         p1 <- c(-ax[2]/ax[1],1,0)
         p1 <- p1/sqrt(sum(p1^2))
         if (p1[1]!=0) {
           p2 <- c(-p1[2]/p1[1],1,0)
           p2[3] <- -sum(p2*ax)
           p2 <- p2/sqrt(sum(p2^2))
         } else {
           p2 <- c(0,0,1)
         }
       } else if (ax[2]!=0) {
         p1 <- c(0,-ax[3]/ax[2],1)
         p1 <- p1/sqrt(sum(p1^2))
         if (p1[1]!=0) {
           p2 <- c(0,-p1[3]/p1[2],1)
           p2[3] <- -sum(p2*ax)
           p2 <- p2/sqrt(sum(p2^2))
         } else {
           p2 <- c(1,0,0)
         }
       } else {
         p1 <- c(0,1,0); p2 <- c(1,0,0)
       }
       degvec <- seq(0,2*pi,length=n+1)[-1]
       ecoord2 <- function(theta) {
         base+rad*(cos(theta)*p1+sin(theta)*p2)
       }
       i <- rbind(1:n,c(2:n,1),rep(n+1,n))
       v <- cbind(sapply(degvec,ecoord2),tip)
       if (qmesh) 
         ## minor kluge for quads -- draw tip twice
         i <- rbind(i,rep(n+1,n))
       if (draw.base) {
         v <- cbind(v,base)
         i.x <- rbind(c(2:n,1),1:n,rep(n+2,n))
         if (qmesh)  ## add base twice
           i.x <-  rbind(i.x,rep(n+2,n))
         i <- cbind(i,i.x)
       }
       if (qmesh) v <- rbind(v,rep(1,ncol(v))) ## homogeneous
       if (!qmesh)
         triangles3d(v[1,i],v[2,i],v[3,i],...)
       else
         return(rotate3d(qmesh3d(v,i,material=...), matrix=trans))
     }     
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多