[Math] 타원의 축 정렬 경계 상자는 어떻게 계산합니까?



Answers

나는 http://www.iquilezles.org/www/articles/ellipses/ellipses.htm 에서 간단한 공식을 발견했다 http://www.iquilezles.org/www/articles/ellipses/ellipses.htm (그리고 z 축은 무시했다.)

나는 이것을 대략 다음과 같이 구현했다.

num ux = ellipse.r1 * cos(ellipse.phi);
num uy = ellipse.r1 * sin(ellipse.phi);
num vx = ellipse.r2 * cos(ellipse.phi+PI/2);
num vy = ellipse.r2 * sin(ellipse.phi+PI/2);

num bbox_halfwidth = sqrt(ux*ux + vx*vx);
num bbox_halfheight = sqrt(uy*uy + vy*vy); 

Point bbox_ul_corner = new Point(ellipse.center.x - bbox_halfwidth, 
                                 ellipse.center.y - bbox_halfheight);

Point bbox_br_corner = new Point(ellipse.center.x + bbox_halfwidth, 
                                 ellipse.center.y + bbox_halfheight);
Question

타원의 주축이 수직 또는 수평 인 경우 경계 상자를 쉽게 계산할 수 있지만 타원을 회전 할 때는 어떻게됩니까?

지금까지 생각할 수있는 유일한 방법은 주변의 모든 점을 계산하고 최대 / 최소 x 및 y 값을 찾는 것입니다. 더 간단한 방법이 있어야하는 것처럼 보입니다.

임의의 각도에서 타원을 설명하는 함수가 있다면 (수학적으로), 그 미분을 사용하여 기울기가 0이거나 정의되지 않은 점을 찾을 수 있지만 찾을 수는 없습니다.

편집 : 명확히하기 위해 축 정렬 경계 상자가 필요합니다. 즉, 타원으로 회전하면 안되지만 경계 상자를 변형하면 x 축과 정렬되어 유지되지 않습니다.




이 코드는 위에 제공된 user1789690 코드를 기반으로하지만, Delphi에서 구현됩니다. 나는 이것을 시험해 보았다. 그리고 내가 말할 수있는 한 그것은 완벽하게 작동한다. 나는 하루 종일 알고리즘이나 코드를 검색하고, 작동하지 않는 코드를 테스트했으며, 결국 위 코드를 찾은 것을 매우 기뻤습니다. 누군가가 이것을 유용하게 찾길 바랍니다. 이 코드는 회전 된 타원의 경계 상자를 계산합니다. 경계 상자는 축 정렬이며 타원과 회전하지 않습니다. 반경은 회전하기 전의 타원에 대한 반경입니다.

type

  TSingleRect = record
    X:      Single;
    Y:      Single;
    Width:  Single;
    Height: Single;
  end;

function GetBoundingBoxForRotatedEllipse(EllipseCenterX, EllipseCenterY, EllipseRadiusX,  EllipseRadiusY, EllipseAngle: Single): TSingleRect;
var
  a: Single;
  b: Single;
  c: Single;
  d: Single;
begin
  a := EllipseRadiusX * Cos(EllipseAngle);
  b := EllipseRadiusY * Sin(EllipseAngle);
  c := EllipseRadiusX * Sin(EllipseAngle);
  d := EllipseRadiusY * Cos(EllipseAngle);
  Result.Width  := Hypot(a, b) * 2;
  Result.Height := Hypot(c, d) * 2;
  Result.X      := EllipseCenterX - Result.Width * 0.5;
  Result.Y      := EllipseCenterY - Result.Height * 0.5;
end;



Brilian Johan Nilsson. 귀하의 코드를 C #으로 복사했습니다 - ellipseAngle은 이제도 단위입니다 :

private static RectangleF EllipseBoundingBox(int ellipseCenterX, int ellipseCenterY, int ellipseRadiusX, int ellipseRadiusY, double ellipseAngle)
{
    double angle = ellipseAngle * Math.PI / 180;
    double a = ellipseRadiusX * Math.Cos(angle);
    double b = ellipseRadiusY * Math.Sin(angle);
    double c = ellipseRadiusX * Math.Sin(angle);
    double d = ellipseRadiusY * Math.Cos(angle);
    double width = Math.Sqrt(Math.Pow(a, 2) + Math.Pow(b, 2)) * 2;
    double height = Math.Sqrt(Math.Pow(c, 2) + Math.Pow(d, 2)) * 2;
    var x= ellipseCenterX - width * 0.5;
    var y= ellipseCenterY + height * 0.5;
    return new Rectangle((int)x, (int)y, (int)width, (int)height);
}



타원이 초점 및 편심 으로 주어지면 (예 : 축 길이, 중심 및 각도로 주어진 경우에 대해서는 사용자 1789690의 답 참조) 수식이 있습니다.

즉, 초점이 (x0, y0) 및 (x1, y1)이고 이심률이 e 인 경우,

bbox_halfwidth  = sqrt(k2*dx2 + (k2-1)*dy2)/2
bbox_halfheight = sqrt((k2-1)*dx2 + k2*dy2)/2

어디에

dx = x1-x0
dy = y1-y0
dx2 = dx*dx
dy2 = dy*dy
k2 = 1.0/(e*e)

나는 user1789690과 Johan Nilsson에 의해 해답을 추출했다.




Links