几何学

介绍

SymPy 的几何模块允许用户创建二维几何实体,如线和圆,并查询这些实体的信息。这可能包括询问椭圆的面积、检查一组点是否共线,或找到两条线的交点。该模块的主要用途涉及具有数值的实体,但也可以使用符号表示。

可用实体

以下实体目前在几何模块中可用:

大多数工作将通过这些实体的属性和方法来完成,但存在几种全局方法:

  • intersection(entity1, entity2)

  • are_similar(entity1, entity2)

  • convex_hull(points)

如需查看完整的API列表以及方法及其返回值的说明,请参阅本文档末尾的类列表。

示例用法

以下Python会话展示了如何使用几何模块中的一些功能。

>>> from sympy import *
>>> from sympy.geometry import *
>>> x = Point(0, 0)
>>> y = Point(1, 1)
>>> z = Point(2, 2)
>>> zp = Point(1, 0)
>>> Point.is_collinear(x, y, z)
True
>>> Point.is_collinear(x, y, zp)
False
>>> t = Triangle(zp, y, x)
>>> t.area
1/2
>>> t.medians[x]
Segment2D(Point2D(0, 0), Point2D(1, 1/2))
>>> m = t.medians
>>> intersection(m[x], m[y], m[zp])
[Point2D(2/3, 1/3)]
>>> c = Circle(x, 5)
>>> l = Line(Point(5, -5), Point(5, 5))
>>> c.is_tangent(l) # is l tangent to c?
True
>>> l = Line(x, y)
>>> c.is_tangent(l) # is l tangent to c?
False
>>> intersection(c, l)
[Point2D(-5*sqrt(2)/2, -5*sqrt(2)/2), Point2D(5*sqrt(2)/2, 5*sqrt(2)/2)]

中线的交点

>>> from sympy import symbols
>>> from sympy.geometry import Point, Triangle, intersection

>>> a, b = symbols("a,b", positive=True)

>>> x = Point(0, 0)
>>> y = Point(a, 0)
>>> z = Point(2*a, b)
>>> t = Triangle(x, y, z)

>>> t.area
a*b/2

>>> t.medians[x]
Segment2D(Point2D(0, 0), Point2D(3*a/2, b/2))

>>> intersection(t.medians[x], t.medians[y], t.medians[z])
[Point2D(a, b/3)]

深入的例子:帕普斯六边形定理

来自维基百科([WikiPappus]):

给定一组共线点 \(A\), \(B\), \(C\),以及另一组共线点 \(a\), \(b\), \(c\),那么直线对 \(Ab\)\(aB\)\(Ac\)\(aC\)\(Bc\)\(bC\) 的交点 \(X\), \(Y\), \(Z\) 是共线的。

>>> from sympy import *
>>> from sympy.geometry import *
>>>
>>> l1 = Line(Point(0, 0), Point(5, 6))
>>> l2 = Line(Point(0, 0), Point(2, -2))
>>>
>>> def subs_point(l, val):
...    """Take an arbitrary point and make it a fixed point."""
...    t = Symbol('t', real=True)
...    ap = l.arbitrary_point()
...    return Point(ap.x.subs(t, val), ap.y.subs(t, val))
...
>>> p11 = subs_point(l1, 5)
>>> p12 = subs_point(l1, 6)
>>> p13 = subs_point(l1, 11)
>>>
>>> p21 = subs_point(l2, -1)
>>> p22 = subs_point(l2, 2)
>>> p23 = subs_point(l2, 13)
>>>
>>> ll1 = Line(p11, p22)
>>> ll2 = Line(p11, p23)
>>> ll3 = Line(p12, p21)
>>> ll4 = Line(p12, p23)
>>> ll5 = Line(p13, p21)
>>> ll6 = Line(p13, p22)
>>>
>>> pp1 = intersection(ll1, ll3)[0]
>>> pp2 = intersection(ll2, ll5)[0]
>>> pp3 = intersection(ll4, ll6)[0]
>>>
>>> Point.is_collinear(pp1, pp2, pp3)
True

参考文献

[WikiPappus]

“帕普斯六边形定理” 维基百科,自由的百科全书。网络。2013年4月26日。<https://en.wikipedia.org/wiki/Pappus’s_hexagon_theorem>

杂项笔记

  • PolygonTriangle 的 area 属性可能会返回正值或负值,这取决于点的方向是逆时针还是顺时针。如果你总是想要一个正值,请确保使用 abs 函数。

  • 虽然 Polygon 可以指任何类型的多边形,但代码是为简单多边形编写的。因此,如果处理复杂多边形(边重叠),可能会遇到潜在问题。

  • 由于 SymPy 仍处于起步阶段,某些功能可能无法正确简化,因此某些应该返回 True 的情况(例如,Point.is_collinear)可能实际上不会返回。同样,尝试查找实际相交的实体的交点可能会导致空结果。

未来工作

真理设置表达式

当处理符号实体时,通常会出现无法保证断言的情况。例如,考虑以下代码:

>>> from sympy import *
>>> from sympy.geometry import *
>>> x,y,z = map(Symbol, 'xyz')
>>> p1,p2,p3 = Point(x, y), Point(y, z), Point(2*x*y, y)
>>> Point.is_collinear(p1, p2, p3)
False

尽管结果目前是 False,但这并不总是 正确 的。如果数量 \(z - y - 2*y*z + 2*y**2 == 0\),那么这些点将是共线的。告知用户这一点会非常好,因为这样的数量可能对用户的进一步计算有用,而且至少是值得了解的。这可以通过返回一个对象(例如,GeometryResult)来实现,用户可以使用该对象。实际上,这并不需要大量的工作。

三维及超越

目前,几何模块的一个有限子集已扩展到三维,但这无疑是一个很好的扩展方向。这可能需要相当多的工作,因为所使用的许多算法都是针对二维的。

几何可视化

绘图模块能够绘制几何实体。请参阅绘图模块条目中的 绘制几何实体

子模块