원뿔을 평면으로 잘랐을 때 나타나는 곡선인 conic section은 직교 좌표계에서 $(x, y)$에 대한 2차 형식으로 쓰인다.

$$ F(x, y)= ax^2 + bxy + cy^2 + dx +ey + f = 0$$

이 conic section이 타원을 기술할 때 parameter {$a, b, c, d, e, f$}를 이용해서 타원의 중심, 장축과 단축의 길이, 그리고 회전각에 대한 공식을 구해보자. 2차 항을 행렬을 써서 표현하면

$$(x, y) \left(\begin{matrix}a & b/2 \\ b/2 & c\end{matrix} \right)\left( \begin{matrix} x\\y\end{matrix}\right) +\cdots =0$$

따라서, 적절한 회전 변환을 하면 두 좌표의 곱으로 주어지는 $xy$-항을 없앨 수 있다. 회전 변환을 시행하면 행렬은 eigenvalue를 성분으로 하는 대각 행렬이 된다. 회전 변환이 determinant를 보존하므로 determinant는 행렬의 두 eigenvalue의 곱으로 주어짐을 알 수 있다.

\begin{gather} \begin{pmatrix} a & b/2 \\ b/2 & c \end{pmatrix} \Longrightarrow \begin{pmatrix} \lambda_1 & 0 \\ 0 & \lambda_2 \end{pmatrix}  \quad \text{det} = ac - b^2/4\end{gather}

회전 후의 방정식이 타원의 방정식(원점이 이동된)을 기술하기 위해서는 $\text{det}>0$ 이어야 한다 (회전시킨 후 식에서 $x^2$과 $y^2$의 계수는 두 eigenvalue로 주어지므로 같은 부호를 가져야 한다.)

$$  F=\text{ellipse} \Leftrightarrow b^2 -4ac <0$$

conic section $F$가 타원을 기술한다면, 다음과 같이 평행이동을 시켜서 타원의 중심 $(x_0, y_0)$이 원점에 놓이게 하고, 회전변환을 시켜서 $xy$ 항을 없애도록 하자.

$$ x\to x_0 + x \cos \theta - y \sin \theta , \quad y\to y_0 + x \sin \theta + y \cos \theta$$

$F$에 적용해서 $xy$-항이 없어지는 조건과 1차 항이 사라지도록 하는 조건을 찾으면 타원의 중심 $(x_0, y_0)$와 회전각 $\theta$가 아래처럼 주어짐을 알 수 있다:

\begin{gather}  \tan 2\theta = \frac{b}{a-c} \\  \\  \text{ellipse center: }~( x_0, y_0) =\begin{pmatrix} \frac{2cd-be}{b^2 -4ac} , \frac{2ae -bd}{b^2 -4ac} \end{pmatrix} \end{gather}

그리고, $x^2$와 $y^2$의 계수는 두 eigenvalue를 주어진다.

$$ \lambda_{1,2} = \frac{a+c \mp \sqrt{(a-c)^2 +b^2}}{ 2}$$

eigevalue의 제곱근의 역수가 각각 장축과 단축의 반지름을 결정하므로 음수가 되어서는 안된다(0인 경우는 직선임). 이는 대칭행렬의 고유값이 항상 0보다 작지 않다는 사실에서 기인한다.  두 eigenvalue는 위에서 구한 회전각 $\theta$를 이용해서 표현하면,

$$\lambda_1 = a\cos^2 \theta + b \cos \theta\sin \theta + c \sin^2 \theta$$

$$\lambda_2 = a\sin^2 \theta - b \cos \theta\sin \theta + c \cos^2 \theta$$

위의 회전변환식을 대입했을 떄 나머지 상수항은 (첫 번째 =은 계산해서 확인할 수 있음)

$$ ax_0^2 + b x_0 y_0^2 + cy_0^2 + dx_0 +e y_0 +f = f - (ax_0^2 + b x_0 y_0 + c y_0^2)\equiv -\text{scale}^{-1}$$

로 주어짐을 알 수 있다. 따라서 회전시킨 타원은 표준형 꼴

$$ \lambda_1 x^2 + \lambda_2 y^2 = \text{scale}^{-1} $$

로 표현된다. 이 표준형 타원의 장축과 단축의 반지름은 각각($\lambda_1 \le \lambda_2$ 인 경우)

$$r_\text{major}=\sqrt{ \frac{\text{scale}^{-1}}{\lambda_1}} , \quad r_\text{minor} = \sqrt{\frac{\text{scale}^{-1}}{\lambda_2} }$$ 로 주어진다.

// conic_params(a, b, c, d, e, f);
// ellipse_params(major_axis, minor_axis, center_x, center_y, tilt_angle);
bool conic_to_ellipse(double conic_param[6], double ellipse_param[5]) {
    const double a = conic_param[0];
    const double b = conic_param[1];
    const double c = conic_param[2];
    const double d = conic_param[3];
    const double e = conic_param[4];
    const double f = conic_param[5];
    //get ellipse orientation
    const double theta = 0.5 * atan2(b, a - c);
    //get scaled major/minor axes
    const double ct = cos(theta);
    const double st = sin(theta);
    const double ap = a * ct * ct + b * ct * st + c * st * st;
    const double cp = a * st * st - b * ct * st + c * ct * ct;
    //get translations
    const double cx = (2 * c * d - b * e) / (b * b - 4 * a * c);
    const double cy = (2 * a * e - b * d) / (b * b - 4 * a * c);
    //get scale factor
    const double val = a * cx * cx + b * cx * cy + c * cy * cy;
    const double scale_inv = val - f;
    if (scale_inv / ap <= 0 || scale_inv / cp <= 0) {
        //TRACE("Error! ellipse parameters are imaginary\n");
        return 0;
    }
    ellipse_param[0] = sqrt(scale_inv / ap);
    ellipse_param[1] = sqrt(scale_inv / cp);
    ellipse_param[2] = cx;
    ellipse_param[3] = cy;
    ellipse_param[4] = theta;
    return 1;
};

 
 
 
 
 
 
 
 
 
 
 
728x90
Posted by helloktk
,