给定R中的一般方程,如何绘制椭圆?

Man*_*ath 6 math plot r ellipse

椭圆一般方程:

a * x ^ 2 + b * y ^ 2 + c * x * y + d * x + e * y + f = 0
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

San*_*Dey 9

我们可以从parametrican的方程开始ellipse(以下来自维基百科),我们需要 5 个参数:中心(xc, yc)(h,k)另一种表示法、轴长度a, b和 x 轴与主轴之间的角度phitau另一种表示法。

在此处输入图片说明

xc <- 1 # center x_c or h
yc <- 2 # y_c or k
a <- 5 # major axis length
b <- 2 # minor axis length
phi <- pi/3 # angle of major axis with x axis phi or tau

t <- seq(0, 2*pi, 0.01) 
x <- xc + a*cos(t)*cos(phi) - b*sin(t)*sin(phi)
y <- yc + a*cos(t)*cos(phi) + b*sin(t)*cos(phi)
plot(x,y,pch=19, col='blue')
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

现在,如果我们想从cartesian conic等式开始,这是一个两步过程。

  1. cartesian方程转换为polar( parametric),形式我们可以使用以下方程首先使用下图中的 5 个方程(取自http://www.cs.cornell.edu/cv/OtherPdf/Ellipse. pdf,详细的数学可以在那里找到)。

  2. 使用获得的参数绘制椭圆,如上所示。

在此处输入图片说明

对于步骤 (1),我们可以使用以下代码(当我们知道时A,B,C,D,E,F):

M0 <- matrix(c(F,D/2,E/2, D/2, A, B/2, E/2, B/2, C), nrow=3, byrow=TRUE)
M <- matrix(c(A,B/2,B/2,C), nrow=2)
lambda <- eigen(M)$values
abs(lambda - A)
abs(lambda - C) 

# assuming abs(lambda[1] - A) < abs(lambda[1] - C), if not, swap lambda[1] and lambda[2] in the following equations:

a <- sqrt(-det(M0)/(det(M)*lambda[1]))  
b <- sqrt(-det(M0)/(det(M)*lambda[2]))
xc <- (B*E-2*C*D)/(4*A*C-B^2)
yc <- (B*D-2*A*E)/(4*A*C-B^2)
phi <- pi/2 - atan((A-C)/B)*2
Run Code Online (Sandbox Code Playgroud)

对于步骤 (2),使用以下代码:

t <- seq(0, 2*pi, 0.01) 
x <- xc + a*cos(t)*cos(phi) - b*sin(t)*sin(phi)
y <- yc + a*cos(t)*cos(phi) + b*sin(t)*cos(phi)
plot(x,y,pch=19, col='blue')
Run Code Online (Sandbox Code Playgroud)

  • 关于代码本身的三个备注:`y &lt;- yc + a * cos(t) * sin(phi) + b * sin(t) * cos(phi)` 和 `phi &lt;- (pi/2 - atan(( AC)/B))/2` 和 `xc &lt;- (B*E-2*C*D)/(4*A*CB^2)` (2认同)
  • 对于第2步,我相信你有一个拼写错误,它应该是: `y &lt;- yc + a*cos(t)*sin(phi) + b*sin(t)*cos(phi)` (2认同)

李哲源*_*李哲源 8

另一个答案向您展示了当您知道椭圆的中心轴和长轴时如何绘制椭圆。但它们从一般椭圆方程中并不明显。所以在这里,我将从头开始。

省略数学推导,您需要从以下等式中求解中心:

在此处输入图片说明

在此处输入图片说明

(哎呀:应该是“生成v”而不是“生成u”;我无法修复它,因为原来的 LaTeX 现在丢失了,我不想再次输入...)

这是一个 R 函数来做到这一点:

plot.ellipse <- function (a, b, c, d, e, f, n.points = 1000) {
  ## solve for centre
  A <- matrix(c(a, c / 2, c / 2, b), 2L)
  B <- c(-d / 2, -e / 2)
  mu <- solve(A, B)
  ## generate points on circle
  r <- sqrt(a * mu[1] ^ 2 + b * mu[2] ^ 2 + c * mu[1] * mu[2] - f)
  theta <- seq(0, 2 * pi, length = n.points)
  v <- rbind(r * cos(theta), r * sin(theta))
  ## transform for points on ellipse
  z <- backsolve(chol(A), v) + mu
  ## plot points
  plot(t(z), type = "l")
  }
Run Code Online (Sandbox Code Playgroud)

几点说明:

  1. 参数有一些条件,a, b, ..., f以确保方程是椭圆而不是其他东西(比如抛物线)。因此,不要传入任意参数值进行测试。其实从等式中可以大致看出这样的需求。例如,矩阵A必须是正定的,所以a > 0det(A) > 0; 还有,r ^ 2 > 0
  2. 我使用了 Cholesky 分解,因为这是我的最爱。然而,最美妙的结果来自于特征分解。这部分我不再赘述。如果您对此感兴趣,请阅读我的另一个答案在椭圆协方差图上获得椭圆的顶点(由car::ellipse。有漂亮的图来说明 Cholesky 分解和 Eigen 分解的几何。