parabola.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. """Parabolic geometrical entity.
  2. Contains
  3. * Parabola
  4. """
  5. from sympy.core import S
  6. from sympy.core.sorting import ordered
  7. from sympy.core.symbol import _symbol, symbols
  8. from sympy.geometry.entity import GeometryEntity, GeometrySet
  9. from sympy.geometry.point import Point, Point2D
  10. from sympy.geometry.line import Line, Line2D, Ray2D, Segment2D, LinearEntity3D
  11. from sympy.geometry.ellipse import Ellipse
  12. from sympy.functions import sign
  13. from sympy.simplify import simplify
  14. from sympy.solvers.solvers import solve
  15. class Parabola(GeometrySet):
  16. """A parabolic GeometryEntity.
  17. A parabola is declared with a point, that is called 'focus', and
  18. a line, that is called 'directrix'.
  19. Only vertical or horizontal parabolas are currently supported.
  20. Parameters
  21. ==========
  22. focus : Point
  23. Default value is Point(0, 0)
  24. directrix : Line
  25. Attributes
  26. ==========
  27. focus
  28. directrix
  29. axis of symmetry
  30. focal length
  31. p parameter
  32. vertex
  33. eccentricity
  34. Raises
  35. ======
  36. ValueError
  37. When `focus` is not a two dimensional point.
  38. When `focus` is a point of directrix.
  39. NotImplementedError
  40. When `directrix` is neither horizontal nor vertical.
  41. Examples
  42. ========
  43. >>> from sympy import Parabola, Point, Line
  44. >>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7,8)))
  45. >>> p1.focus
  46. Point2D(0, 0)
  47. >>> p1.directrix
  48. Line2D(Point2D(5, 8), Point2D(7, 8))
  49. """
  50. def __new__(cls, focus=None, directrix=None, **kwargs):
  51. if focus:
  52. focus = Point(focus, dim=2)
  53. else:
  54. focus = Point(0, 0)
  55. directrix = Line(directrix)
  56. if (directrix.slope != 0 and directrix.slope != S.Infinity):
  57. raise NotImplementedError('The directrix must be a horizontal'
  58. ' or vertical line')
  59. if directrix.contains(focus):
  60. raise ValueError('The focus must not be a point of directrix')
  61. return GeometryEntity.__new__(cls, focus, directrix, **kwargs)
  62. @property
  63. def ambient_dimension(self):
  64. """Returns the ambient dimension of parabola.
  65. Returns
  66. =======
  67. ambient_dimension : integer
  68. Examples
  69. ========
  70. >>> from sympy import Parabola, Point, Line
  71. >>> f1 = Point(0, 0)
  72. >>> p1 = Parabola(f1, Line(Point(5, 8), Point(7, 8)))
  73. >>> p1.ambient_dimension
  74. 2
  75. """
  76. return 2
  77. @property
  78. def axis_of_symmetry(self):
  79. """The axis of symmetry of the parabola.
  80. Returns
  81. =======
  82. axis_of_symmetry : Line
  83. See Also
  84. ========
  85. sympy.geometry.line.Line
  86. Examples
  87. ========
  88. >>> from sympy import Parabola, Point, Line
  89. >>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8)))
  90. >>> p1.axis_of_symmetry
  91. Line2D(Point2D(0, 0), Point2D(0, 1))
  92. """
  93. return self.directrix.perpendicular_line(self.focus)
  94. @property
  95. def directrix(self):
  96. """The directrix of the parabola.
  97. Returns
  98. =======
  99. directrix : Line
  100. See Also
  101. ========
  102. sympy.geometry.line.Line
  103. Examples
  104. ========
  105. >>> from sympy import Parabola, Point, Line
  106. >>> l1 = Line(Point(5, 8), Point(7, 8))
  107. >>> p1 = Parabola(Point(0, 0), l1)
  108. >>> p1.directrix
  109. Line2D(Point2D(5, 8), Point2D(7, 8))
  110. """
  111. return self.args[1]
  112. @property
  113. def eccentricity(self):
  114. """The eccentricity of the parabola.
  115. Returns
  116. =======
  117. eccentricity : number
  118. A parabola may also be characterized as a conic section with an
  119. eccentricity of 1. As a consequence of this, all parabolas are
  120. similar, meaning that while they can be different sizes,
  121. they are all the same shape.
  122. See Also
  123. ========
  124. https://en.wikipedia.org/wiki/Parabola
  125. Examples
  126. ========
  127. >>> from sympy import Parabola, Point, Line
  128. >>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8)))
  129. >>> p1.eccentricity
  130. 1
  131. Notes
  132. -----
  133. The eccentricity for every Parabola is 1 by definition.
  134. """
  135. return S.One
  136. def equation(self, x='x', y='y'):
  137. """The equation of the parabola.
  138. Parameters
  139. ==========
  140. x : str, optional
  141. Label for the x-axis. Default value is 'x'.
  142. y : str, optional
  143. Label for the y-axis. Default value is 'y'.
  144. Returns
  145. =======
  146. equation : SymPy expression
  147. Examples
  148. ========
  149. >>> from sympy import Parabola, Point, Line
  150. >>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8)))
  151. >>> p1.equation()
  152. -x**2 - 16*y + 64
  153. >>> p1.equation('f')
  154. -f**2 - 16*y + 64
  155. >>> p1.equation(y='z')
  156. -x**2 - 16*z + 64
  157. """
  158. x = _symbol(x, real=True)
  159. y = _symbol(y, real=True)
  160. if (self.axis_of_symmetry.slope == 0):
  161. t1 = 4 * (self.p_parameter) * (x - self.vertex.x)
  162. t2 = (y - self.vertex.y)**2
  163. else:
  164. t1 = 4 * (self.p_parameter) * (y - self.vertex.y)
  165. t2 = (x - self.vertex.x)**2
  166. return t1 - t2
  167. @property
  168. def focal_length(self):
  169. """The focal length of the parabola.
  170. Returns
  171. =======
  172. focal_lenght : number or symbolic expression
  173. Notes
  174. =====
  175. The distance between the vertex and the focus
  176. (or the vertex and directrix), measured along the axis
  177. of symmetry, is the "focal length".
  178. See Also
  179. ========
  180. https://en.wikipedia.org/wiki/Parabola
  181. Examples
  182. ========
  183. >>> from sympy import Parabola, Point, Line
  184. >>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8)))
  185. >>> p1.focal_length
  186. 4
  187. """
  188. distance = self.directrix.distance(self.focus)
  189. focal_length = distance/2
  190. return focal_length
  191. @property
  192. def focus(self):
  193. """The focus of the parabola.
  194. Returns
  195. =======
  196. focus : Point
  197. See Also
  198. ========
  199. sympy.geometry.point.Point
  200. Examples
  201. ========
  202. >>> from sympy import Parabola, Point, Line
  203. >>> f1 = Point(0, 0)
  204. >>> p1 = Parabola(f1, Line(Point(5, 8), Point(7, 8)))
  205. >>> p1.focus
  206. Point2D(0, 0)
  207. """
  208. return self.args[0]
  209. def intersection(self, o):
  210. """The intersection of the parabola and another geometrical entity `o`.
  211. Parameters
  212. ==========
  213. o : GeometryEntity, LinearEntity
  214. Returns
  215. =======
  216. intersection : list of GeometryEntity objects
  217. Examples
  218. ========
  219. >>> from sympy import Parabola, Point, Ellipse, Line, Segment
  220. >>> p1 = Point(0,0)
  221. >>> l1 = Line(Point(1, -2), Point(-1,-2))
  222. >>> parabola1 = Parabola(p1, l1)
  223. >>> parabola1.intersection(Ellipse(Point(0, 0), 2, 5))
  224. [Point2D(-2, 0), Point2D(2, 0)]
  225. >>> parabola1.intersection(Line(Point(-7, 3), Point(12, 3)))
  226. [Point2D(-4, 3), Point2D(4, 3)]
  227. >>> parabola1.intersection(Segment((-12, -65), (14, -68)))
  228. []
  229. """
  230. x, y = symbols('x y', real=True)
  231. parabola_eq = self.equation()
  232. if isinstance(o, Parabola):
  233. if o in self:
  234. return [o]
  235. else:
  236. return list(ordered([Point(i) for i in solve([parabola_eq, o.equation()], [x, y])]))
  237. elif isinstance(o, Point2D):
  238. if simplify(parabola_eq.subs([(x, o._args[0]), (y, o._args[1])])) == 0:
  239. return [o]
  240. else:
  241. return []
  242. elif isinstance(o, (Segment2D, Ray2D)):
  243. result = solve([parabola_eq, Line2D(o.points[0], o.points[1]).equation()], [x, y])
  244. return list(ordered([Point2D(i) for i in result if i in o]))
  245. elif isinstance(o, (Line2D, Ellipse)):
  246. return list(ordered([Point2D(i) for i in solve([parabola_eq, o.equation()], [x, y])]))
  247. elif isinstance(o, LinearEntity3D):
  248. raise TypeError('Entity must be two dimensional, not three dimensional')
  249. else:
  250. raise TypeError('Wrong type of argument were put')
  251. @property
  252. def p_parameter(self):
  253. """P is a parameter of parabola.
  254. Returns
  255. =======
  256. p : number or symbolic expression
  257. Notes
  258. =====
  259. The absolute value of p is the focal length. The sign on p tells
  260. which way the parabola faces. Vertical parabolas that open up
  261. and horizontal that open right, give a positive value for p.
  262. Vertical parabolas that open down and horizontal that open left,
  263. give a negative value for p.
  264. See Also
  265. ========
  266. http://www.sparknotes.com/math/precalc/conicsections/section2.rhtml
  267. Examples
  268. ========
  269. >>> from sympy import Parabola, Point, Line
  270. >>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8)))
  271. >>> p1.p_parameter
  272. -4
  273. """
  274. if self.axis_of_symmetry.slope == 0:
  275. x = self.directrix.coefficients[2]
  276. p = sign(self.focus.args[0] + x)
  277. else:
  278. y = self.directrix.coefficients[2]
  279. p = sign(self.focus.args[1] + y)
  280. return p * self.focal_length
  281. @property
  282. def vertex(self):
  283. """The vertex of the parabola.
  284. Returns
  285. =======
  286. vertex : Point
  287. See Also
  288. ========
  289. sympy.geometry.point.Point
  290. Examples
  291. ========
  292. >>> from sympy import Parabola, Point, Line
  293. >>> p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7, 8)))
  294. >>> p1.vertex
  295. Point2D(0, 4)
  296. """
  297. focus = self.focus
  298. if (self.axis_of_symmetry.slope == 0):
  299. vertex = Point(focus.args[0] - self.p_parameter, focus.args[1])
  300. else:
  301. vertex = Point(focus.args[0], focus.args[1] - self.p_parameter)
  302. return vertex