Geometry¶
Introduction¶
The geometry module for SymPy allows one to create two-dimensional geometrical entities, such as lines and circles, and query for information about these entities. This could include asking the area of an ellipse, checking for collinearity of a set of points, or finding the intersection between two lines. The primary use case of the module involves entities with numerical values, but it is possible to also use symbolic representations.
Available Entities¶
The following entities are currently available in the geometry module:
Most of the work one will do will be through the properties and methods of these entities, but several global methods exist:
intersection(entity1, entity2)
are_similar(entity1, entity2)
convex_hull(points)
For a full API listing and an explanation of the methods and their return values please see the list of classes at the end of this document.
Example Usage¶
The following Python session gives one an idea of how to work with some of the geometry module.
>>> 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)]
Intersection of medians¶
>>> 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)]
An in-depth example: Pappus’ Hexagon Theorem¶
From Wikipedia ([WikiPappus]):
Given one set of collinear points \(A\), \(B\), \(C\), and another set of collinear points \(a\), \(b\), \(c\), then the intersection points \(X\), \(Y\), \(Z\) of line pairs \(Ab\) and \(aB\), \(Ac\) and \(aC\), \(Bc\) and \(bC\) are collinear.
>>> 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
References¶
“Pappus’s Hexagon Theorem” Wikipedia, the Free Encyclopedia. Web. 26 Apr. 2013. <https://en.wikipedia.org/wiki/Pappus’s_hexagon_theorem>
Miscellaneous Notes¶
The area property of
Polygon
andTriangle
may return a positive or negative value, depending on whether or not the points are oriented counter-clockwise or clockwise, respectively. If you always want a positive value be sure to use theabs
function.Although
Polygon
can refer to any type of polygon, the code has been written for simple polygons. Hence, expect potential problems if dealing with complex polygons (overlapping sides).Since SymPy is still in its infancy some things may not simplify properly and hence some things that should return
True
(e.g.,Point.is_collinear
) may not actually do so. Similarly, attempting to find the intersection of entities that do intersect may result in an empty result.
Future Work¶
Truth Setting Expressions¶
When one deals with symbolic entities, it often happens that an assertion cannot be guaranteed. For example, consider the following code:
>>> 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
Even though the result is currently False
, this is not always true. If the
quantity \(z - y - 2*y*z + 2*y**2 == 0\) then the points will be collinear. It
would be really nice to inform the user of this because such a quantity may be
useful to a user for further calculation and, at the very least, being nice to
know. This could be potentially done by returning an object (e.g.,
GeometryResult) that the user could use. This actually would not involve an
extensive amount of work.
Three Dimensions and Beyond¶
Currently a limited subset of the geometry module has been extended to three dimensions, but it certainly would be a good addition to extend more. This would probably involve a fair amount of work since many of the algorithms used are specific to two dimensions.
Geometry Visualization¶
The plotting module is capable of plotting geometric entities. See Plotting Geometric Entities in the plotting module entry.
Submodules¶
- Entities
- Utils
- Points
Point
Point.affine_rank()
Point.ambient_dimension
Point.are_coplanar()
Point.canberra_distance()
Point.distance()
Point.dot()
Point.equals()
Point.intersection()
Point.is_collinear()
Point.is_concyclic()
Point.is_nonzero
Point.is_scalar_multiple()
Point.is_zero
Point.length
Point.midpoint()
Point.origin
Point.orthogonal_direction
Point.project()
Point.taxicab_distance()
Point.unit
Point2D
Point3D
- Lines
LinearEntity
LinearEntity.ambient_dimension
LinearEntity.angle_between()
LinearEntity.arbitrary_point()
LinearEntity.are_concurrent()
LinearEntity.bisectors()
LinearEntity.contains()
LinearEntity.direction
LinearEntity.intersection()
LinearEntity.is_parallel()
LinearEntity.is_perpendicular()
LinearEntity.is_similar()
LinearEntity.length
LinearEntity.p1
LinearEntity.p2
LinearEntity.parallel_line()
LinearEntity.perpendicular_line()
LinearEntity.perpendicular_segment()
LinearEntity.points
LinearEntity.projection()
LinearEntity.random_point()
LinearEntity.smallest_angle_between()
Line
Ray
Segment
LinearEntity2D
Line2D
Ray2D
Segment2D
LinearEntity3D
Line3D
Ray3D
Segment3D
- Curves
- Ellipses
Ellipse
Ellipse.apoapsis
Ellipse.arbitrary_point()
Ellipse.area
Ellipse.auxiliary_circle()
Ellipse.bounds
Ellipse.center
Ellipse.circumference
Ellipse.director_circle()
Ellipse.eccentricity
Ellipse.encloses_point()
Ellipse.equation()
Ellipse.evolute()
Ellipse.foci
Ellipse.focus_distance
Ellipse.hradius
Ellipse.intersection()
Ellipse.is_tangent()
Ellipse.major
Ellipse.minor
Ellipse.normal_lines()
Ellipse.periapsis
Ellipse.plot_interval()
Ellipse.polar_second_moment_of_area()
Ellipse.random_point()
Ellipse.reflect()
Ellipse.rotate()
Ellipse.scale()
Ellipse.second_moment_of_area()
Ellipse.section_modulus()
Ellipse.semilatus_rectum
Ellipse.tangent_lines()
Ellipse.vradius
Circle
- Polygons
Polygon
Polygon.angles
Polygon.arbitrary_point()
Polygon.area
Polygon.bisectors()
Polygon.bounds
Polygon.centroid
Polygon.cut_section()
Polygon.distance()
Polygon.encloses_point()
Polygon.first_moment_of_area()
Polygon.intersection()
Polygon.is_convex()
Polygon.perimeter
Polygon.plot_interval()
Polygon.polar_second_moment_of_area()
Polygon.second_moment_of_area()
Polygon.section_modulus()
Polygon.sides
Polygon.vertices
RegularPolygon
RegularPolygon.angles
RegularPolygon.apothem
RegularPolygon.area
RegularPolygon.args
RegularPolygon.center
RegularPolygon.centroid
RegularPolygon.circumcenter
RegularPolygon.circumcircle
RegularPolygon.circumradius
RegularPolygon.encloses_point()
RegularPolygon.exterior_angle
RegularPolygon.incircle
RegularPolygon.inradius
RegularPolygon.interior_angle
RegularPolygon.length
RegularPolygon.radius
RegularPolygon.reflect()
RegularPolygon.rotate()
RegularPolygon.rotation
RegularPolygon.scale()
RegularPolygon.spin()
RegularPolygon.vertices
Triangle
Triangle.altitudes
Triangle.bisectors()
Triangle.circumcenter
Triangle.circumcircle
Triangle.circumradius
Triangle.eulerline
Triangle.excenters
Triangle.exradii
Triangle.incenter
Triangle.incircle
Triangle.inradius
Triangle.is_equilateral()
Triangle.is_isosceles()
Triangle.is_right()
Triangle.is_scalene()
Triangle.is_similar()
Triangle.medial
Triangle.medians
Triangle.nine_point_circle
Triangle.orthocenter
Triangle.vertices
- Plane
Plane
Plane.angle_between()
Plane.arbitrary_point()
Plane.are_concurrent()
Plane.distance()
Plane.equals()
Plane.equation()
Plane.intersection()
Plane.is_coplanar()
Plane.is_parallel()
Plane.is_perpendicular()
Plane.normal_vector
Plane.p1
Plane.parallel_plane()
Plane.parameter_value()
Plane.perpendicular_line()
Plane.perpendicular_plane()
Plane.projection()
Plane.projection_line()
Plane.random_point()