conic section은 직교좌표계에서 (x, y)에 대한 2차식으로 쓰여진다;



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



따라서, 적절한 회전변환을 하면 두 좌표의 곱으로 주어지는 xy-항을 없앨 수 있다.  회전변환은 행렬의 determinant를 보존하고, 그 값은 행렬의 두 eigenvalue의 곱으로 쓰여진다.



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



conic section F가 타원을 기술한다면, 다음과 같이 평행이동 및 회전(rigid transformation)변환을 해서 타원의 중심과 회전각도를 얻을 수 있다



이 식을 대입해서  xy-항이 없어지는 조건과 1차 항이 없어지는 조건을 사용하면


그리고, x와 y의 제곱의 계수는


이 eigenvalue는 위에서 구한 회전각도를 이용해서 표현이 가능하다:



나머지 상수항은



로 주어짐을 알 수있다. 따라서 타원의 각축의 길이는



로 주어진다.

// 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 imagina\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;

};

Posted by helloktk

댓글을 달아 주세요