2

我需要找到一条线(其原点是椭圆的中心)与二维椭圆相交的点...我可以很容易地在圆上找到一个点,因为我知道角度 F 和圆的半径(R):

x = x0 + R * cosF
y = y0 + R * sinF

但是我只是不知道我应该如何处理椭圆......我知道它的尺寸(A&B),但是找到参数T的方法是什么?!

x = x0 + A * cosT
y = y0 + B * sinT

据我了解,参数 T(T 角)与 F 角相差不远(在某些情况下约为 +-15 度),但我就是不知道如何计算它!!!

如果有好心人,请帮我解决这个问题...

4

4 回答 4

8

椭圆的标准方程,位于 0,0,为:

1 = (x)^2 / (a)    +  (y)^2 / (b)

其中 a 为横轴直径的 1/2,b 为纵轴直径的 1/2。

你有一条线,假设一个方程:

y = (m)(x - x0) + y0

所以,让我们即插即用!

1 = (x)^2 / (a)   +   (m(x - x0) + y0)^2 / (b)

1 = x^2 / a  +  (mx + (y0 - mx0))^2 / b

1 = x^2 / a  +  (m^2 * x^2 + 2mx*(y0 - mx0) + (y0 - mx0)^2) / b

1 = x^2 / a  + (m^2 x^2) / b + (2mx*(y0 - mx0) + (y0^2 - 2y0mx0 + m^2*x0^2)) / b

1 = ((x^2 * b) / (a * b)) + ((m^2 * x^2 * a) / (a * b)) + (2mxy0 - 2m^2xx0)/b + (y0^2 - 2y0mx0 + m^2*x0^2)/b

1 = ((bx^2 + am^2x^2)/(ab)) + (x*(2my0 - 2m^2x0))/b + (y0^2 - 2y0mx0 + m^2*x0^2)/b

0 = x^2*((b + a*m^2)/(ab)) + x*((2my0 - 2m^2x0)/b) + (((y0^2 - 2y0mx0 + m^2*x0^2)/b) - 1)

最后一个方程遵循标准二次方程的形式。

因此,只需使用二次公式:

((b + a*m^2)/(ab))
((2my0 - 2m^2x0)/b)
and 
(((y0^2 - 2y0mx0 + m^2*x0^2)/b) - 1)

获取交叉点的 X 值;然后,将这些值代入原始直线方程以获得 Y 值。

祝你好运!

于 2012-05-21T21:18:54.590 回答
3

不要这样做。而是检查形成椭圆和形成直线的方程并求解集合:

椭圆: (x/a)^2 + (y/b)^2 = 1 你的线: y = cx

您知道 a、b 和 c,因此找到解决方案将很容易。您会找到两种解决方案,因为该线两次穿过椭圆。

编辑:注意我把你的椭圆中心移到了(0,0)。它使一切变得更容易。只需将 (x0,y0) 添加到解决方案中。

于 2012-05-21T21:05:10.000 回答
1

我为您的问题编写了 C# 代码,希望对您有所帮助。此代码中的距离函数计算空间中两点之间的欧几里得距离。

wX表示椭圆的水平无线电并wY表示垂直无线电。

private PointF LineIntersectEllipse(PointF A, PointF B, float wX, float wY)
{
      double dx = B.X - A.X;
      double dy = B.Y - A.Y;
      double theta = Math.Atan2(dy, dx);
      double r = distance(A, B) - ((wX * wY) / Math.Sqrt(Math.Pow(wY * Math.Cos(theta), 2) + Math.Pow(wX * Math.Sin(theta), 2)));
      return PointF((float)(A.X + r * Math.Cos(theta)), (float)(A.Y + r * Math.Sin(theta)));
}
于 2014-09-06T19:36:55.900 回答
1

预览

public Hits<float2> EllipseLineIntersection ( float rx , float ry , float2 p1 , float2 p2 )
{
    Hits<float2> hits = default(Hits<float2>);
    float2 p3, p4;
    Rect rect = default(Rect);
    {
        rect.xMin = math.min(p1.x,p2.x);
        rect.xMax = math.max(p1.x,p2.x);
        rect.yMin = math.min(p1.y,p2.y);
        rect.yMax = math.max(p1.y,p2.y);
    }

    float s = ( p2.y - p1.y )/( p2.x - p1.x );
    float si = p2.y - ( s * p2.x );
    float a = ( ry*ry )+( rx*rx * s*s );
    float b = 2f * rx*rx * si * s;
    float c = rx*rx * si*si - rx*rx * ry*ry;

    float radicand_sqrt = math.sqrt( ( b*b )-( 4f * a * c) );
    p3.x = ( -b - radicand_sqrt )/( 2f*a );
    p4.x = ( -b + radicand_sqrt )/( 2f*a );
    p3.y = s*p3.x + si;
    p4.y = s*p4.x + si;

    if( rect.Contains(p3) ) hits.Push( p3 );
    if( rect.Contains(p4) ) hits.Push( p4 );
    return hits;
}
public struct Hits<T>
{
    public byte count;
    public T point0, point1;
    public void Push ( T val )
    {
        if( count==0 ) { point0 = val; count ++; }
        else if( count==1 ) { point1 = val; count ++; }
        else print("This structure can only fit 2 values");
    }
}
于 2020-05-13T20:51:43.540 回答