Closed. This question needs to be more focused。它当前不接受答案。












想改善这个问题吗?更新问题,使其仅关注editing this post的一个问题。

5年前关闭。



Improve this question




我想用C++做到这一点。我有两个想法可以做到这一点:
  • 将一对椭圆作为两个不同参数的参数方程,我可以根据两个参数得到两个方程。这对方程是非线性的,都是切线,正弦和余弦的函数。我主要使用的Geant4仅具有多项式
  • 使用几何库可以解决此问题。我查看了Boost几何,但是文档(对我而言)是不一致的。话虽如此,它似乎更针对于计算几何。也许当我只想做X时,我就要求它做Y。

  • 怎么可能呢?在python中,它是如此简单,我可以在睡眠中做到这一点。任何见解将不胜感激。自从我开始使用C++以来,感觉要选择使用的库本身就是一场巨大的战斗。

    最佳答案

    我有一些建议。您可以尝试使用LibreCAD,它具有一个求解两个椭圆的公切线的求解器,但我对API一无所知。求解器求解四次方程,这是您天真的尝试找到两个椭圆的公切线时所获得的结果。

    如果想自己动手,只需一点理论(“圆锥曲线范围”),就可以用线性代数(即找到3x3矩阵的逆矩阵)加上求解二次方程和一个三次方程式来完成的任务。它是这样的:

    您可以以矩阵方程的形式表示任何圆锥(例如椭圆)

            [m00 m01 m02] [x]
    [x,y,z] [m10 m11 m12] [y] = 0
            [m20 m21 m22] [z]
    

    矩阵M是对称的,而[x,y,z]是齐次坐标的;只是想z=1。我们可以将该等式写为X M X^T = 0,其中X^TX的转置。

    平面中的线可以以lx+my+nz=0的形式编写,因此具有“线坐标” (l,m,n)

    可以用这种表示法非常简单地表达与上述圆锥曲线相切的线的集合。令A为矩阵M的逆。然后到圆锥线的切线
            [a00 a01 a02] (l)
    (l,m,n) [a10 a11 a12] (m) = 0
            [a20 a21 a22] (n)
    

    现在假设我们有第二个圆锥体,其矩阵为N,而N具有反B。公切线将满足上述等式和等式
            [b00 b01 b02] (l)
    (l,m,n) [b10 b11 b12] (m) = 0
            [b20 b21 b22] (n)
    

    实际上,我们可以将后一个方程式中的矩阵与t标量相乘,并且仍然保持:
              [b00 b01 b02] (l)
    (l,m,n) t [b10 b11 b12] (m) = 0
              [b20 b21 b22] (n)
    

    将第一个圆锥形的切线方程添加到第二个圆锥形的上述方程中,我们得到矩阵方程L (A + tB) L^T = 0。因此,两个圆锥的任何公共(public)切线都是A + tB中的每个圆锥的公共(public)切线。

    现在有了一个简化的大主意:我们可以在该范围内找到一些非常特殊的圆锥形,即“退化”圆锥形,它们是成对的点。由于公共(public)切线必须穿过所有圆锥形,因此,它们必须穿过退化的圆锥形。但是很容易找到通过简并圆锥曲线的线,因为这样的圆锥曲线只是点对!

    您可以通过求解三次方程det(A + tB) = 0来找到退化圆锥,其中det()是3x3矩阵的行列式。立方可以通过卡尔达诺公式或变体以封闭形式求解,或者如果需要的话可以通过数值求解。一旦找到使简锥化的t的值,就可以将方程L (A + tB) L^T = 0分解为两个线性因子。每个线性因子xl + ym + zn = 0都以齐次坐标[x,y,z]或笛卡尔坐标(x/z,y/z)定义一个点。您应该以这种方式获得三个点对(六个点)。通过某些点对上的线会给您四个(最多)切线。

    这是一个简单的示例(两个椭圆的中心都在原点处):找到x^2+2y^2=3x^2+14y^2=7的公共(public)切线。矩阵形式的圆锥是
            [1 0  0] [x]               [1  0  0] [x]
    [x,y,z] [0 2  0] [y] = 0,  [x,y,z] [0 14  0] [y] = 0
            [0 0 -3] [z]               [0  0 -7] [z]
    

    切线由
            [6 0  0] (l)               [14 0  0] (l)
    (l,m,n) [0 3  0] (m) = 0,  (l,m,n) [ 0 1  0] (m) = 0
            [0 0 -2] (n)               [ 0 0 -2] (n)
    

    请注意,我已将反矩阵乘以标量,只是使条目为整数而不是有理数。您不必这样做,但是它使手动计算变得更加容易。将第二个矩阵乘以一个额外的标量t可得出
            [6+14t 0    0   ] (l)
    (l,m,n) [0     3+t  0   ] (m) = 0
            [0     0   -2-2t] (n)
    

    圆锥形在(6+14t)(3+t)(-2-2t)=0时(即t=-3/7, -3, -1时)退化。当t=-3/7我们得到
    18/7 m^2 - 8/7 n^2 = 2/7 (9 m^2 - 4 n^2) = 2/7 (3m - 2n)(3m + 2n) = 0
    

    这对应于具有齐次坐标[x,y,z] = [0,3,-2][0,3,2]的点,换言之,对应于具有笛卡尔坐标(0,-3/2)(0,3/2)的点。

    t=-3时,我们得到-36l^2 + 4n^2 = (6l+2n)(-6l+2n) = 0,指向[6,0,2][-6,0,2]或在笛卡尔坐标中(3,0)(-3,0)。最后,当t=1时,我们获得与oj​​it_code和-8l^2 + 2m^2 = 2(2l+m)(-2l+m) = 0点(它们是无穷远点)相对应的[2,1,0]

    暂时避免使用无穷大的点,只是因为它们使用起来有些困难,我们通过以下几对点获得了四行:
    {(0,-3/2),(-3,0)}, {(0,-3/2),(3,0)}, {(0,3/2),(-3,0)}, {(0,3/2),(3,0)}
    

    这给了我们两个椭圆的四个正切线。

    c++ - 在C++中找到一对椭圆的公切线的首选方法-LMLPHP

    从图片中您可以看到,公共(public)切线也通过了无穷大[-2,1,0][2,1,0]处的点,即成对的平行线具有[-2,1,0]1/2斜率。

    那不漂亮吗?

    关于c++ - 在C++中找到一对椭圆的公切线的首选方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31668231/

    10-15 05:47