Spaces:
Sleeping
Sleeping
"""Parabolic geometrical entity. | |
Contains | |
* Parabola | |
""" | |
from sympy.core import S | |
from sympy.core.sorting import ordered | |
from sympy.core.symbol import _symbol, symbols | |
from sympy.geometry.entity import GeometryEntity, GeometrySet | |
from sympy.geometry.point import Point, Point2D | |
from sympy.geometry.line import Line, Line2D, Ray2D, Segment2D, LinearEntity3D | |
from sympy.geometry.ellipse import Ellipse | |
from sympy.functions import sign | |
from sympy.simplify import simplify | |
from sympy.solvers.solvers import solve | |
class Parabola(GeometrySet): | |
"""A parabolic GeometryEntity. | |
A parabola is declared with a point, that is called 'focus', and | |
a line, that is called 'directrix'. | |
Only vertical or horizontal parabolas are currently supported. | |
Parameters | |
========== | |
focus : Point | |
Default value is Point(0, 0) | |
directrix : Line | |
Attributes | |
========== | |
focus | |
directrix | |
axis of symmetry | |
focal length | |
p parameter | |
vertex | |
eccentricity | |
Raises | |
====== | |
ValueError | |
When `focus` is not a two dimensional point. | |
When `focus` is a point of directrix. | |
NotImplementedError | |
When `directrix` is neither horizontal nor vertical. | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Line | |
>>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7,8))) | |
>>> p1.focus | |
Point2D(0, 0) | |
>>> p1.directrix | |
Line2D(Point2D(5, 8), Point2D(7, 8)) | |
""" | |
def __new__(cls, focus=None, directrix=None, **kwargs): | |
if focus: | |
focus = Point(focus, dim=2) | |
else: | |
focus = Point(0, 0) | |
directrix = Line(directrix) | |
if directrix.contains(focus): | |
raise ValueError('The focus must not be a point of directrix') | |
return GeometryEntity.__new__(cls, focus, directrix, **kwargs) | |
def ambient_dimension(self): | |
"""Returns the ambient dimension of parabola. | |
Returns | |
======= | |
ambient_dimension : integer | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Line | |
>>> f1 = Point(0, 0) | |
>>> p1 = Parabola(f1, Line(Point(5, 8), Point(7, 8))) | |
>>> p1.ambient_dimension | |
2 | |
""" | |
return 2 | |
def axis_of_symmetry(self): | |
"""Return the axis of symmetry of the parabola: a line | |
perpendicular to the directrix passing through the focus. | |
Returns | |
======= | |
axis_of_symmetry : Line | |
See Also | |
======== | |
sympy.geometry.line.Line | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Line | |
>>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8))) | |
>>> p1.axis_of_symmetry | |
Line2D(Point2D(0, 0), Point2D(0, 1)) | |
""" | |
return self.directrix.perpendicular_line(self.focus) | |
def directrix(self): | |
"""The directrix of the parabola. | |
Returns | |
======= | |
directrix : Line | |
See Also | |
======== | |
sympy.geometry.line.Line | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Line | |
>>> l1 = Line(Point(5, 8), Point(7, 8)) | |
>>> p1 = Parabola(Point(0, 0), l1) | |
>>> p1.directrix | |
Line2D(Point2D(5, 8), Point2D(7, 8)) | |
""" | |
return self.args[1] | |
def eccentricity(self): | |
"""The eccentricity of the parabola. | |
Returns | |
======= | |
eccentricity : number | |
A parabola may also be characterized as a conic section with an | |
eccentricity of 1. As a consequence of this, all parabolas are | |
similar, meaning that while they can be different sizes, | |
they are all the same shape. | |
See Also | |
======== | |
https://en.wikipedia.org/wiki/Parabola | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Line | |
>>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8))) | |
>>> p1.eccentricity | |
1 | |
Notes | |
----- | |
The eccentricity for every Parabola is 1 by definition. | |
""" | |
return S.One | |
def equation(self, x='x', y='y'): | |
"""The equation of the parabola. | |
Parameters | |
========== | |
x : str, optional | |
Label for the x-axis. Default value is 'x'. | |
y : str, optional | |
Label for the y-axis. Default value is 'y'. | |
Returns | |
======= | |
equation : SymPy expression | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Line | |
>>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8))) | |
>>> p1.equation() | |
-x**2 - 16*y + 64 | |
>>> p1.equation('f') | |
-f**2 - 16*y + 64 | |
>>> p1.equation(y='z') | |
-x**2 - 16*z + 64 | |
""" | |
x = _symbol(x, real=True) | |
y = _symbol(y, real=True) | |
m = self.directrix.slope | |
if m is S.Infinity: | |
t1 = 4 * (self.p_parameter) * (x - self.vertex.x) | |
t2 = (y - self.vertex.y)**2 | |
elif m == 0: | |
t1 = 4 * (self.p_parameter) * (y - self.vertex.y) | |
t2 = (x - self.vertex.x)**2 | |
else: | |
a, b = self.focus | |
c, d = self.directrix.coefficients[:2] | |
t1 = (x - a)**2 + (y - b)**2 | |
t2 = self.directrix.equation(x, y)**2/(c**2 + d**2) | |
return t1 - t2 | |
def focal_length(self): | |
"""The focal length of the parabola. | |
Returns | |
======= | |
focal_lenght : number or symbolic expression | |
Notes | |
===== | |
The distance between the vertex and the focus | |
(or the vertex and directrix), measured along the axis | |
of symmetry, is the "focal length". | |
See Also | |
======== | |
https://en.wikipedia.org/wiki/Parabola | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Line | |
>>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8))) | |
>>> p1.focal_length | |
4 | |
""" | |
distance = self.directrix.distance(self.focus) | |
focal_length = distance/2 | |
return focal_length | |
def focus(self): | |
"""The focus of the parabola. | |
Returns | |
======= | |
focus : Point | |
See Also | |
======== | |
sympy.geometry.point.Point | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Line | |
>>> f1 = Point(0, 0) | |
>>> p1 = Parabola(f1, Line(Point(5, 8), Point(7, 8))) | |
>>> p1.focus | |
Point2D(0, 0) | |
""" | |
return self.args[0] | |
def intersection(self, o): | |
"""The intersection of the parabola and another geometrical entity `o`. | |
Parameters | |
========== | |
o : GeometryEntity, LinearEntity | |
Returns | |
======= | |
intersection : list of GeometryEntity objects | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Ellipse, Line, Segment | |
>>> p1 = Point(0,0) | |
>>> l1 = Line(Point(1, -2), Point(-1,-2)) | |
>>> parabola1 = Parabola(p1, l1) | |
>>> parabola1.intersection(Ellipse(Point(0, 0), 2, 5)) | |
[Point2D(-2, 0), Point2D(2, 0)] | |
>>> parabola1.intersection(Line(Point(-7, 3), Point(12, 3))) | |
[Point2D(-4, 3), Point2D(4, 3)] | |
>>> parabola1.intersection(Segment((-12, -65), (14, -68))) | |
[] | |
""" | |
x, y = symbols('x y', real=True) | |
parabola_eq = self.equation() | |
if isinstance(o, Parabola): | |
if o in self: | |
return [o] | |
else: | |
return list(ordered([Point(i) for i in solve( | |
[parabola_eq, o.equation()], [x, y], set=True)[1]])) | |
elif isinstance(o, Point2D): | |
if simplify(parabola_eq.subs([(x, o._args[0]), (y, o._args[1])])) == 0: | |
return [o] | |
else: | |
return [] | |
elif isinstance(o, (Segment2D, Ray2D)): | |
result = solve([parabola_eq, | |
Line2D(o.points[0], o.points[1]).equation()], | |
[x, y], set=True)[1] | |
return list(ordered([Point2D(i) for i in result if i in o])) | |
elif isinstance(o, (Line2D, Ellipse)): | |
return list(ordered([Point2D(i) for i in solve( | |
[parabola_eq, o.equation()], [x, y], set=True)[1]])) | |
elif isinstance(o, LinearEntity3D): | |
raise TypeError('Entity must be two dimensional, not three dimensional') | |
else: | |
raise TypeError('Wrong type of argument were put') | |
def p_parameter(self): | |
"""P is a parameter of parabola. | |
Returns | |
======= | |
p : number or symbolic expression | |
Notes | |
===== | |
The absolute value of p is the focal length. The sign on p tells | |
which way the parabola faces. Vertical parabolas that open up | |
and horizontal that open right, give a positive value for p. | |
Vertical parabolas that open down and horizontal that open left, | |
give a negative value for p. | |
See Also | |
======== | |
https://www.sparknotes.com/math/precalc/conicsections/section2/ | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Line | |
>>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8))) | |
>>> p1.p_parameter | |
-4 | |
""" | |
m = self.directrix.slope | |
if m is S.Infinity: | |
x = self.directrix.coefficients[2] | |
p = sign(self.focus.args[0] + x) | |
elif m == 0: | |
y = self.directrix.coefficients[2] | |
p = sign(self.focus.args[1] + y) | |
else: | |
d = self.directrix.projection(self.focus) | |
p = sign(self.focus.x - d.x) | |
return p * self.focal_length | |
def vertex(self): | |
"""The vertex of the parabola. | |
Returns | |
======= | |
vertex : Point | |
See Also | |
======== | |
sympy.geometry.point.Point | |
Examples | |
======== | |
>>> from sympy import Parabola, Point, Line | |
>>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8))) | |
>>> p1.vertex | |
Point2D(0, 4) | |
""" | |
focus = self.focus | |
m = self.directrix.slope | |
if m is S.Infinity: | |
vertex = Point(focus.args[0] - self.p_parameter, focus.args[1]) | |
elif m == 0: | |
vertex = Point(focus.args[0], focus.args[1] - self.p_parameter) | |
else: | |
vertex = self.axis_of_symmetry.intersection(self)[0] | |
return vertex | |