计算交比
Computing the cross ratio
我想在python中写一个函数来计算四个投影点的交叉比,我想知道是否有一个优雅简洁的实现来处理无限的情况。
交叉比率的简单实现如下所示:
ratio = lambda a,b,c: (a-c)/(b-c)
cross_ratio = lambda a,b,c,d: ratio(a,b,c)/ratio(a,b,d)
但是当其中一个输入是 Infinity 时,这会失败。这不应该发生,而是我们希望无穷大 "cancel out each other" 并给我们一个简单的比率。
例如Infinity, 0, 1, -1
的交叉比应该是-1
.
此外,我想处理以两个数字的比率表示的点数。因此 (1 1)
将是数字 1
,而 (1,0)
将代表 Infinity
,等等
我总是可以退回到案例定义并凑合使用,但我觉得这可能是一个学习好的设计的好机会。
我正在使用 Python 2.7 和 Sagemath 模块。关于如何实施这个的任何建议?
我会试试这个:
def det2(a, b): return a[0]*b[1] - a[1]*b[0]
def cr2(a, b, c, d): return vector([det2(a,c)*det2(b,d), det2(a,d)*det2(b,c)])
这将在输入上使用齐次坐标,因此您将输入二元向量。它还会 return 它的结果是齐次坐标,作为二元向量,因此您可以获得无限交叉比的清晰描述。如果您需要将结果作为某个字段的元素,只需使用除法而不是向量构造函数:
def cr2(a, b, c, d): return (det2(a,c)*det2(b,d))/(det2(a,d)*det2(b,c))
我在公式中加了后缀2
,因为我个人经常需要平面共线的四个点的交比。在那种情况下,我会使用
def det3(a, b, c):
return matrix([a,b,c]).det() # Or spell this out, if you prefer
def cr3(a, b, c, d, x):
return vector([det3(a,c,x)*det3(b,d,x), det3(a,d,x)* det3(b,c,x)])
现在让 x
是 不 与 a,b,c,d
共线的任何点,您就可以得到这四个点的交比。或者更一般地说,如果 a,b,c,d
不共线,您将得到连接它们与 x
的四条线的交叉比,这对许多场景很有用,其中许多场景涉及二次曲线。
最好是使用投影线。
此处的文档包含有用的提示:
http://doc.sagemath.org/html/en/reference/schemes/sage/schemes/projective/projective_space.html
这是交叉比率的实现,并附有示例。
sage: P = ProjectiveSpace(1, QQ)
sage: oo, zero, one = P(1, 0), P(0, 1), P(1, 1)
sage: tm = P.point_transformation_matrix
sage: def cross_ratio(a, b, c, d):
....: a, b, c, d = P(a), P(b), P(c), P(d)
....: m = tm([a, b, c], [oo, zero, one])
....: return P(list(m*vector(list(d))))
....:
sage: cross_ratio(oo, zero, one, 1/2)
(1/2 : 1)
sage: cross_ratio(1, 2, 3, 4)
(4/3 : 1)
我想在python中写一个函数来计算四个投影点的交叉比,我想知道是否有一个优雅简洁的实现来处理无限的情况。
交叉比率的简单实现如下所示:
ratio = lambda a,b,c: (a-c)/(b-c)
cross_ratio = lambda a,b,c,d: ratio(a,b,c)/ratio(a,b,d)
但是当其中一个输入是 Infinity 时,这会失败。这不应该发生,而是我们希望无穷大 "cancel out each other" 并给我们一个简单的比率。
例如Infinity, 0, 1, -1
的交叉比应该是-1
.
此外,我想处理以两个数字的比率表示的点数。因此 (1 1)
将是数字 1
,而 (1,0)
将代表 Infinity
,等等
我总是可以退回到案例定义并凑合使用,但我觉得这可能是一个学习好的设计的好机会。
我正在使用 Python 2.7 和 Sagemath 模块。关于如何实施这个的任何建议?
我会试试这个:
def det2(a, b): return a[0]*b[1] - a[1]*b[0]
def cr2(a, b, c, d): return vector([det2(a,c)*det2(b,d), det2(a,d)*det2(b,c)])
这将在输入上使用齐次坐标,因此您将输入二元向量。它还会 return 它的结果是齐次坐标,作为二元向量,因此您可以获得无限交叉比的清晰描述。如果您需要将结果作为某个字段的元素,只需使用除法而不是向量构造函数:
def cr2(a, b, c, d): return (det2(a,c)*det2(b,d))/(det2(a,d)*det2(b,c))
我在公式中加了后缀2
,因为我个人经常需要平面共线的四个点的交比。在那种情况下,我会使用
def det3(a, b, c):
return matrix([a,b,c]).det() # Or spell this out, if you prefer
def cr3(a, b, c, d, x):
return vector([det3(a,c,x)*det3(b,d,x), det3(a,d,x)* det3(b,c,x)])
现在让 x
是 不 与 a,b,c,d
共线的任何点,您就可以得到这四个点的交比。或者更一般地说,如果 a,b,c,d
不共线,您将得到连接它们与 x
的四条线的交叉比,这对许多场景很有用,其中许多场景涉及二次曲线。
最好是使用投影线。
此处的文档包含有用的提示: http://doc.sagemath.org/html/en/reference/schemes/sage/schemes/projective/projective_space.html
这是交叉比率的实现,并附有示例。
sage: P = ProjectiveSpace(1, QQ)
sage: oo, zero, one = P(1, 0), P(0, 1), P(1, 1)
sage: tm = P.point_transformation_matrix
sage: def cross_ratio(a, b, c, d):
....: a, b, c, d = P(a), P(b), P(c), P(d)
....: m = tm([a, b, c], [oo, zero, one])
....: return P(list(m*vector(list(d))))
....:
sage: cross_ratio(oo, zero, one, 1/2)
(1/2 : 1)
sage: cross_ratio(1, 2, 3, 4)
(4/3 : 1)