Closed. This question needs to be more focused。它当前不接受答案。
想改善这个问题吗?更新问题,使其仅关注editing this post的一个问题。
5年前关闭。
Improve this question
我想用C++做到这一点。我有两个想法可以做到这一点:
将一对椭圆作为两个不同参数的参数方程,我可以根据两个参数得到两个方程。这对方程是非线性的,都是切线,正弦和余弦的函数。我主要使用的Geant4仅具有多项式 使用几何库可以解决此问题。我查看了Boost几何,但是文档(对我而言)是不一致的。话虽如此,它似乎更针对于计算几何。也许当我只想做X时,我就要求它做Y。
怎么可能呢?在python中,它是如此简单,我可以在睡眠中做到这一点。任何见解将不胜感激。自从我开始使用C++以来,感觉要选择使用的库本身就是一场巨大的战斗。
矩阵
平面中的线可以以
可以用这种表示法非常简单地表达与上述圆锥曲线相切的线的集合。令
现在假设我们有第二个圆锥体,其矩阵为
实际上,我们可以将后一个方程式中的矩阵与
将第一个圆锥形的切线方程添加到第二个圆锥形的上述方程中,我们得到矩阵方程
现在有了一个简化的大主意:我们可以在该范围内找到一些非常特殊的圆锥形,即“退化”圆锥形,它们是成对的点。由于公共(public)切线必须穿过所有圆锥形,因此,它们必须穿过退化的圆锥形。但是很容易找到通过简并圆锥曲线的线,因为这样的圆锥曲线只是点对!
您可以通过求解三次方程
这是一个简单的示例(两个椭圆的中心都在原点处):找到
切线由
请注意,我已将反矩阵乘以标量,只是使条目为整数而不是有理数。您不必这样做,但是它使手动计算变得更加容易。将第二个矩阵乘以一个额外的标量
圆锥形在
这对应于具有齐次坐标
当
暂时避免使用无穷大的点,只是因为它们使用起来有些困难,我们通过以下几对点获得了四行:
这给了我们两个椭圆的四个正切线。
从图片中您可以看到,公共(public)切线也通过了无穷大
那不漂亮吗?
想改善这个问题吗?更新问题,使其仅关注editing this post的一个问题。
5年前关闭。
Improve this question
我想用C++做到这一点。我有两个想法可以做到这一点:
怎么可能呢?在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^T
是X
的转置。平面中的线可以以
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=3
和x^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
时,我们获得与ojit_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)}
这给了我们两个椭圆的四个正切线。
从图片中您可以看到,公共(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