m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

596 lines
25 KiB

6 months ago
  1. from sympy.core.numbers import (Rational, oo, pi)
  2. from sympy.core.relational import Eq
  3. from sympy.core.singleton import S
  4. from sympy.core.symbol import (Symbol, symbols)
  5. from sympy.functions.elementary.complexes import Abs
  6. from sympy.functions.elementary.miscellaneous import sqrt
  7. from sympy.functions.elementary.trigonometric import sec
  8. from sympy.geometry.line import Segment2D
  9. from sympy.geometry.point import Point2D
  10. from sympy.geometry import (Circle, Ellipse, GeometryError, Line, Point,
  11. Polygon, Ray, RegularPolygon, Segment,
  12. Triangle, intersection)
  13. from sympy.testing.pytest import raises, slow
  14. from sympy.integrals.integrals import integrate
  15. from sympy.functions.special.elliptic_integrals import elliptic_e
  16. from sympy.functions.elementary.miscellaneous import Max
  17. def test_ellipse_equation_using_slope():
  18. from sympy.abc import x, y
  19. e1 = Ellipse(Point(1, 0), 3, 2)
  20. assert str(e1.equation(_slope=1)) == str((-x + y + 1)**2/8 + (x + y - 1)**2/18 - 1)
  21. e2 = Ellipse(Point(0, 0), 4, 1)
  22. assert str(e2.equation(_slope=1)) == str((-x + y)**2/2 + (x + y)**2/32 - 1)
  23. e3 = Ellipse(Point(1, 5), 6, 2)
  24. assert str(e3.equation(_slope=2)) == str((-2*x + y - 3)**2/20 + (x + 2*y - 11)**2/180 - 1)
  25. def test_object_from_equation():
  26. from sympy.abc import x, y, a, b
  27. assert Circle(x**2 + y**2 + 3*x + 4*y - 8) == Circle(Point2D(S(-3) / 2, -2),
  28. sqrt(57) / 2)
  29. assert Circle(x**2 + y**2 + 6*x + 8*y + 25) == Circle(Point2D(-3, -4), 0)
  30. assert Circle(a**2 + b**2 + 6*a + 8*b + 25, x='a', y='b') == Circle(Point2D(-3, -4), 0)
  31. assert Circle(x**2 + y**2 - 25) == Circle(Point2D(0, 0), 5)
  32. assert Circle(x**2 + y**2) == Circle(Point2D(0, 0), 0)
  33. assert Circle(a**2 + b**2, x='a', y='b') == Circle(Point2D(0, 0), 0)
  34. assert Circle(x**2 + y**2 + 6*x + 8) == Circle(Point2D(-3, 0), 1)
  35. assert Circle(x**2 + y**2 + 6*y + 8) == Circle(Point2D(0, -3), 1)
  36. assert Circle(6*(x**2) + 6*(y**2) + 6*x + 8*y - 25) == Circle(Point2D(Rational(-1, 2), Rational(-2, 3)), 5*sqrt(37)/6)
  37. assert Circle(Eq(a**2 + b**2, 25), x='a', y=b) == Circle(Point2D(0, 0), 5)
  38. raises(GeometryError, lambda: Circle(x**2 + y**2 + 3*x + 4*y + 26))
  39. raises(GeometryError, lambda: Circle(x**2 + y**2 + 25))
  40. raises(GeometryError, lambda: Circle(a**2 + b**2 + 25, x='a', y='b'))
  41. raises(GeometryError, lambda: Circle(x**2 + 6*y + 8))
  42. raises(GeometryError, lambda: Circle(6*(x ** 2) + 4*(y**2) + 6*x + 8*y + 25))
  43. raises(ValueError, lambda: Circle(a**2 + b**2 + 3*a + 4*b - 8))
  44. @slow
  45. def test_ellipse_geom():
  46. x = Symbol('x', real=True)
  47. y = Symbol('y', real=True)
  48. t = Symbol('t', real=True)
  49. y1 = Symbol('y1', real=True)
  50. half = S.Half
  51. p1 = Point(0, 0)
  52. p2 = Point(1, 1)
  53. p4 = Point(0, 1)
  54. e1 = Ellipse(p1, 1, 1)
  55. e2 = Ellipse(p2, half, 1)
  56. e3 = Ellipse(p1, y1, y1)
  57. c1 = Circle(p1, 1)
  58. c2 = Circle(p2, 1)
  59. c3 = Circle(Point(sqrt(2), sqrt(2)), 1)
  60. l1 = Line(p1, p2)
  61. # Test creation with three points
  62. cen, rad = Point(3*half, 2), 5*half
  63. assert Circle(Point(0, 0), Point(3, 0), Point(0, 4)) == Circle(cen, rad)
  64. assert Circle(Point(0, 0), Point(1, 1), Point(2, 2)) == Segment2D(Point2D(0, 0), Point2D(2, 2))
  65. raises(ValueError, lambda: Ellipse(None, None, None, 1))
  66. raises(ValueError, lambda: Ellipse())
  67. raises(GeometryError, lambda: Circle(Point(0, 0)))
  68. raises(GeometryError, lambda: Circle(Symbol('x')*Symbol('y')))
  69. # Basic Stuff
  70. assert Ellipse(None, 1, 1).center == Point(0, 0)
  71. assert e1 == c1
  72. assert e1 != e2
  73. assert e1 != l1
  74. assert p4 in e1
  75. assert e1 in e1
  76. assert e2 in e2
  77. assert 1 not in e2
  78. assert p2 not in e2
  79. assert e1.area == pi
  80. assert e2.area == pi/2
  81. assert e3.area == pi*y1*abs(y1)
  82. assert c1.area == e1.area
  83. assert c1.circumference == e1.circumference
  84. assert e3.circumference == 2*pi*y1
  85. assert e1.plot_interval() == e2.plot_interval() == [t, -pi, pi]
  86. assert e1.plot_interval(x) == e2.plot_interval(x) == [x, -pi, pi]
  87. assert c1.minor == 1
  88. assert c1.major == 1
  89. assert c1.hradius == 1
  90. assert c1.vradius == 1
  91. assert Ellipse((1, 1), 0, 0) == Point(1, 1)
  92. assert Ellipse((1, 1), 1, 0) == Segment(Point(0, 1), Point(2, 1))
  93. assert Ellipse((1, 1), 0, 1) == Segment(Point(1, 0), Point(1, 2))
  94. # Private Functions
  95. assert hash(c1) == hash(Circle(Point(1, 0), Point(0, 1), Point(0, -1)))
  96. assert c1 in e1
  97. assert (Line(p1, p2) in e1) is False
  98. assert e1.__cmp__(e1) == 0
  99. assert e1.__cmp__(Point(0, 0)) > 0
  100. # Encloses
  101. assert e1.encloses(Segment(Point(-0.5, -0.5), Point(0.5, 0.5))) is True
  102. assert e1.encloses(Line(p1, p2)) is False
  103. assert e1.encloses(Ray(p1, p2)) is False
  104. assert e1.encloses(e1) is False
  105. assert e1.encloses(
  106. Polygon(Point(-0.5, -0.5), Point(-0.5, 0.5), Point(0.5, 0.5))) is True
  107. assert e1.encloses(RegularPolygon(p1, 0.5, 3)) is True
  108. assert e1.encloses(RegularPolygon(p1, 5, 3)) is False
  109. assert e1.encloses(RegularPolygon(p2, 5, 3)) is False
  110. assert e2.arbitrary_point() in e2
  111. raises(ValueError, lambda: Ellipse(Point(x, y), 1, 1).arbitrary_point(parameter='x'))
  112. # Foci
  113. f1, f2 = Point(sqrt(12), 0), Point(-sqrt(12), 0)
  114. ef = Ellipse(Point(0, 0), 4, 2)
  115. assert ef.foci in [(f1, f2), (f2, f1)]
  116. # Tangents
  117. v = sqrt(2) / 2
  118. p1_1 = Point(v, v)
  119. p1_2 = p2 + Point(half, 0)
  120. p1_3 = p2 + Point(0, 1)
  121. assert e1.tangent_lines(p4) == c1.tangent_lines(p4)
  122. assert e2.tangent_lines(p1_2) == [Line(Point(Rational(3, 2), 1), Point(Rational(3, 2), S.Half))]
  123. assert e2.tangent_lines(p1_3) == [Line(Point(1, 2), Point(Rational(5, 4), 2))]
  124. assert c1.tangent_lines(p1_1) != [Line(p1_1, Point(0, sqrt(2)))]
  125. assert c1.tangent_lines(p1) == []
  126. assert e2.is_tangent(Line(p1_2, p2 + Point(half, 1)))
  127. assert e2.is_tangent(Line(p1_3, p2 + Point(half, 1)))
  128. assert c1.is_tangent(Line(p1_1, Point(0, sqrt(2))))
  129. assert e1.is_tangent(Line(Point(0, 0), Point(1, 1))) is False
  130. assert c1.is_tangent(e1) is True
  131. assert c1.is_tangent(Ellipse(Point(2, 0), 1, 1)) is True
  132. assert c1.is_tangent(
  133. Polygon(Point(1, 1), Point(1, -1), Point(2, 0))) is True
  134. assert c1.is_tangent(
  135. Polygon(Point(1, 1), Point(1, 0), Point(2, 0))) is False
  136. assert Circle(Point(5, 5), 3).is_tangent(Circle(Point(0, 5), 1)) is False
  137. assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(0, 0)) == \
  138. [Line(Point(0, 0), Point(Rational(77, 25), Rational(132, 25))),
  139. Line(Point(0, 0), Point(Rational(33, 5), Rational(22, 5)))]
  140. assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(3, 4)) == \
  141. [Line(Point(3, 4), Point(4, 4)), Line(Point(3, 4), Point(3, 5))]
  142. assert Circle(Point(5, 5), 2).tangent_lines(Point(3, 3)) == \
  143. [Line(Point(3, 3), Point(4, 3)), Line(Point(3, 3), Point(3, 4))]
  144. assert Circle(Point(5, 5), 2).tangent_lines(Point(5 - 2*sqrt(2), 5)) == \
  145. [Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 - sqrt(2))),
  146. Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 + sqrt(2))), ]
  147. assert Circle(Point(5, 5), 5).tangent_lines(Point(4, 0)) == \
  148. [Line(Point(4, 0), Point(Rational(40, 13), Rational(5, 13))),
  149. Line(Point(4, 0), Point(5, 0))]
  150. assert Circle(Point(5, 5), 5).tangent_lines(Point(0, 6)) == \
  151. [Line(Point(0, 6), Point(0, 7)),
  152. Line(Point(0, 6), Point(Rational(5, 13), Rational(90, 13)))]
  153. # for numerical calculations, we shouldn't demand exact equality,
  154. # so only test up to the desired precision
  155. def lines_close(l1, l2, prec):
  156. """ tests whether l1 and 12 are within 10**(-prec)
  157. of each other """
  158. return abs(l1.p1 - l2.p1) < 10**(-prec) and abs(l1.p2 - l2.p2) < 10**(-prec)
  159. def line_list_close(ll1, ll2, prec):
  160. return all(lines_close(l1, l2, prec) for l1, l2 in zip(ll1, ll2))
  161. e = Ellipse(Point(0, 0), 2, 1)
  162. assert e.normal_lines(Point(0, 0)) == \
  163. [Line(Point(0, 0), Point(0, 1)), Line(Point(0, 0), Point(1, 0))]
  164. assert e.normal_lines(Point(1, 0)) == \
  165. [Line(Point(0, 0), Point(1, 0))]
  166. assert e.normal_lines((0, 1)) == \
  167. [Line(Point(0, 0), Point(0, 1))]
  168. assert line_list_close(e.normal_lines(Point(1, 1), 2), [
  169. Line(Point(Rational(-51, 26), Rational(-1, 5)), Point(Rational(-25, 26), Rational(17, 83))),
  170. Line(Point(Rational(28, 29), Rational(-7, 8)), Point(Rational(57, 29), Rational(-9, 2)))], 2)
  171. # test the failure of Poly.intervals and checks a point on the boundary
  172. p = Point(sqrt(3), S.Half)
  173. assert p in e
  174. assert line_list_close(e.normal_lines(p, 2), [
  175. Line(Point(Rational(-341, 171), Rational(-1, 13)), Point(Rational(-170, 171), Rational(5, 64))),
  176. Line(Point(Rational(26, 15), Rational(-1, 2)), Point(Rational(41, 15), Rational(-43, 26)))], 2)
  177. # be sure to use the slope that isn't undefined on boundary
  178. e = Ellipse((0, 0), 2, 2*sqrt(3)/3)
  179. assert line_list_close(e.normal_lines((1, 1), 2), [
  180. Line(Point(Rational(-64, 33), Rational(-20, 71)), Point(Rational(-31, 33), Rational(2, 13))),
  181. Line(Point(1, -1), Point(2, -4))], 2)
  182. # general ellipse fails except under certain conditions
  183. e = Ellipse((0, 0), x, 1)
  184. assert e.normal_lines((x + 1, 0)) == [Line(Point(0, 0), Point(1, 0))]
  185. raises(NotImplementedError, lambda: e.normal_lines((x + 1, 1)))
  186. # Properties
  187. major = 3
  188. minor = 1
  189. e4 = Ellipse(p2, minor, major)
  190. assert e4.focus_distance == sqrt(major**2 - minor**2)
  191. ecc = e4.focus_distance / major
  192. assert e4.eccentricity == ecc
  193. assert e4.periapsis == major*(1 - ecc)
  194. assert e4.apoapsis == major*(1 + ecc)
  195. assert e4.semilatus_rectum == major*(1 - ecc ** 2)
  196. # independent of orientation
  197. e4 = Ellipse(p2, major, minor)
  198. assert e4.focus_distance == sqrt(major**2 - minor**2)
  199. ecc = e4.focus_distance / major
  200. assert e4.eccentricity == ecc
  201. assert e4.periapsis == major*(1 - ecc)
  202. assert e4.apoapsis == major*(1 + ecc)
  203. # Intersection
  204. l1 = Line(Point(1, -5), Point(1, 5))
  205. l2 = Line(Point(-5, -1), Point(5, -1))
  206. l3 = Line(Point(-1, -1), Point(1, 1))
  207. l4 = Line(Point(-10, 0), Point(0, 10))
  208. pts_c1_l3 = [Point(sqrt(2)/2, sqrt(2)/2), Point(-sqrt(2)/2, -sqrt(2)/2)]
  209. assert intersection(e2, l4) == []
  210. assert intersection(c1, Point(1, 0)) == [Point(1, 0)]
  211. assert intersection(c1, l1) == [Point(1, 0)]
  212. assert intersection(c1, l2) == [Point(0, -1)]
  213. assert intersection(c1, l3) in [pts_c1_l3, [pts_c1_l3[1], pts_c1_l3[0]]]
  214. assert intersection(c1, c2) == [Point(0, 1), Point(1, 0)]
  215. assert intersection(c1, c3) == [Point(sqrt(2)/2, sqrt(2)/2)]
  216. assert e1.intersection(l1) == [Point(1, 0)]
  217. assert e2.intersection(l4) == []
  218. assert e1.intersection(Circle(Point(0, 2), 1)) == [Point(0, 1)]
  219. assert e1.intersection(Circle(Point(5, 0), 1)) == []
  220. assert e1.intersection(Ellipse(Point(2, 0), 1, 1)) == [Point(1, 0)]
  221. assert e1.intersection(Ellipse(Point(5, 0), 1, 1)) == []
  222. assert e1.intersection(Point(2, 0)) == []
  223. assert e1.intersection(e1) == e1
  224. assert intersection(Ellipse(Point(0, 0), 2, 1), Ellipse(Point(3, 0), 1, 2)) == [Point(2, 0)]
  225. assert intersection(Circle(Point(0, 0), 2), Circle(Point(3, 0), 1)) == [Point(2, 0)]
  226. assert intersection(Circle(Point(0, 0), 2), Circle(Point(7, 0), 1)) == []
  227. assert intersection(Ellipse(Point(0, 0), 5, 17), Ellipse(Point(4, 0), 1, 0.2)) == [Point(5, 0)]
  228. assert intersection(Ellipse(Point(0, 0), 5, 17), Ellipse(Point(4, 0), 0.999, 0.2)) == []
  229. assert Circle((0, 0), S.Half).intersection(
  230. Triangle((-1, 0), (1, 0), (0, 1))) == [
  231. Point(Rational(-1, 2), 0), Point(S.Half, 0)]
  232. raises(TypeError, lambda: intersection(e2, Line((0, 0, 0), (0, 0, 1))))
  233. raises(TypeError, lambda: intersection(e2, Rational(12)))
  234. raises(TypeError, lambda: Ellipse.intersection(e2, 1))
  235. # some special case intersections
  236. csmall = Circle(p1, 3)
  237. cbig = Circle(p1, 5)
  238. cout = Circle(Point(5, 5), 1)
  239. # one circle inside of another
  240. assert csmall.intersection(cbig) == []
  241. # separate circles
  242. assert csmall.intersection(cout) == []
  243. # coincident circles
  244. assert csmall.intersection(csmall) == csmall
  245. v = sqrt(2)
  246. t1 = Triangle(Point(0, v), Point(0, -v), Point(v, 0))
  247. points = intersection(t1, c1)
  248. assert len(points) == 4
  249. assert Point(0, 1) in points
  250. assert Point(0, -1) in points
  251. assert Point(v/2, v/2) in points
  252. assert Point(v/2, -v/2) in points
  253. circ = Circle(Point(0, 0), 5)
  254. elip = Ellipse(Point(0, 0), 5, 20)
  255. assert intersection(circ, elip) in \
  256. [[Point(5, 0), Point(-5, 0)], [Point(-5, 0), Point(5, 0)]]
  257. assert elip.tangent_lines(Point(0, 0)) == []
  258. elip = Ellipse(Point(0, 0), 3, 2)
  259. assert elip.tangent_lines(Point(3, 0)) == \
  260. [Line(Point(3, 0), Point(3, -12))]
  261. e1 = Ellipse(Point(0, 0), 5, 10)
  262. e2 = Ellipse(Point(2, 1), 4, 8)
  263. a = Rational(53, 17)
  264. c = 2*sqrt(3991)/17
  265. ans = [Point(a - c/8, a/2 + c), Point(a + c/8, a/2 - c)]
  266. assert e1.intersection(e2) == ans
  267. e2 = Ellipse(Point(x, y), 4, 8)
  268. c = sqrt(3991)
  269. ans = [Point(-c/68 + a, c*Rational(2, 17) + a/2), Point(c/68 + a, c*Rational(-2, 17) + a/2)]
  270. assert [p.subs({x: 2, y:1}) for p in e1.intersection(e2)] == ans
  271. # Combinations of above
  272. assert e3.is_tangent(e3.tangent_lines(p1 + Point(y1, 0))[0])
  273. e = Ellipse((1, 2), 3, 2)
  274. assert e.tangent_lines(Point(10, 0)) == \
  275. [Line(Point(10, 0), Point(1, 0)),
  276. Line(Point(10, 0), Point(Rational(14, 5), Rational(18, 5)))]
  277. # encloses_point
  278. e = Ellipse((0, 0), 1, 2)
  279. assert e.encloses_point(e.center)
  280. assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10)))
  281. assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0))
  282. assert e.encloses_point(e.center + Point(e.hradius, 0)) is False
  283. assert e.encloses_point(
  284. e.center + Point(e.hradius + Rational(1, 10), 0)) is False
  285. e = Ellipse((0, 0), 2, 1)
  286. assert e.encloses_point(e.center)
  287. assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10)))
  288. assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0))
  289. assert e.encloses_point(e.center + Point(e.hradius, 0)) is False
  290. assert e.encloses_point(
  291. e.center + Point(e.hradius + Rational(1, 10), 0)) is False
  292. assert c1.encloses_point(Point(1, 0)) is False
  293. assert c1.encloses_point(Point(0.3, 0.4)) is True
  294. assert e.scale(2, 3) == Ellipse((0, 0), 4, 3)
  295. assert e.scale(3, 6) == Ellipse((0, 0), 6, 6)
  296. assert e.rotate(pi) == e
  297. assert e.rotate(pi, (1, 2)) == Ellipse(Point(2, 4), 2, 1)
  298. raises(NotImplementedError, lambda: e.rotate(pi/3))
  299. # Circle rotation tests (Issue #11743)
  300. # Link - https://github.com/sympy/sympy/issues/11743
  301. cir = Circle(Point(1, 0), 1)
  302. assert cir.rotate(pi/2) == Circle(Point(0, 1), 1)
  303. assert cir.rotate(pi/3) == Circle(Point(S.Half, sqrt(3)/2), 1)
  304. assert cir.rotate(pi/3, Point(1, 0)) == Circle(Point(1, 0), 1)
  305. assert cir.rotate(pi/3, Point(0, 1)) == Circle(Point(S.Half + sqrt(3)/2, S.Half + sqrt(3)/2), 1)
  306. def test_construction():
  307. e1 = Ellipse(hradius=2, vradius=1, eccentricity=None)
  308. assert e1.eccentricity == sqrt(3)/2
  309. e2 = Ellipse(hradius=2, vradius=None, eccentricity=sqrt(3)/2)
  310. assert e2.vradius == 1
  311. e3 = Ellipse(hradius=None, vradius=1, eccentricity=sqrt(3)/2)
  312. assert e3.hradius == 2
  313. # filter(None, iterator) filters out anything falsey, including 0
  314. # eccentricity would be filtered out in this case and the constructor would throw an error
  315. e4 = Ellipse(Point(0, 0), hradius=1, eccentricity=0)
  316. assert e4.vradius == 1
  317. #tests for eccentricity > 1
  318. raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity = S(3)/2))
  319. raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity=sec(5)))
  320. raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity=S.Pi-S(2)))
  321. #tests for eccentricity = 1
  322. #if vradius is not defined
  323. assert Ellipse(None, 1, None, 1).length == 2
  324. #if hradius is not defined
  325. raises(GeometryError, lambda: Ellipse(None, None, 1, eccentricity = 1))
  326. #tests for eccentricity < 0
  327. raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity = -3))
  328. raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity = -0.5))
  329. def test_ellipse_random_point():
  330. y1 = Symbol('y1', real=True)
  331. e3 = Ellipse(Point(0, 0), y1, y1)
  332. rx, ry = Symbol('rx'), Symbol('ry')
  333. for ind in range(0, 5):
  334. r = e3.random_point()
  335. # substitution should give zero*y1**2
  336. assert e3.equation(rx, ry).subs(zip((rx, ry), r.args)).equals(0)
  337. # test for the case with seed
  338. r = e3.random_point(seed=1)
  339. assert e3.equation(rx, ry).subs(zip((rx, ry), r.args)).equals(0)
  340. def test_repr():
  341. assert repr(Circle((0, 1), 2)) == 'Circle(Point2D(0, 1), 2)'
  342. def test_transform():
  343. c = Circle((1, 1), 2)
  344. assert c.scale(-1) == Circle((-1, 1), 2)
  345. assert c.scale(y=-1) == Circle((1, -1), 2)
  346. assert c.scale(2) == Ellipse((2, 1), 4, 2)
  347. assert Ellipse((0, 0), 2, 3).scale(2, 3, (4, 5)) == \
  348. Ellipse(Point(-4, -10), 4, 9)
  349. assert Circle((0, 0), 2).scale(2, 3, (4, 5)) == \
  350. Ellipse(Point(-4, -10), 4, 6)
  351. assert Ellipse((0, 0), 2, 3).scale(3, 3, (4, 5)) == \
  352. Ellipse(Point(-8, -10), 6, 9)
  353. assert Circle((0, 0), 2).scale(3, 3, (4, 5)) == \
  354. Circle(Point(-8, -10), 6)
  355. assert Circle(Point(-8, -10), 6).scale(Rational(1, 3), Rational(1, 3), (4, 5)) == \
  356. Circle((0, 0), 2)
  357. assert Circle((0, 0), 2).translate(4, 5) == \
  358. Circle((4, 5), 2)
  359. assert Circle((0, 0), 2).scale(3, 3) == \
  360. Circle((0, 0), 6)
  361. def test_bounds():
  362. e1 = Ellipse(Point(0, 0), 3, 5)
  363. e2 = Ellipse(Point(2, -2), 7, 7)
  364. c1 = Circle(Point(2, -2), 7)
  365. c2 = Circle(Point(-2, 0), Point(0, 2), Point(2, 0))
  366. assert e1.bounds == (-3, -5, 3, 5)
  367. assert e2.bounds == (-5, -9, 9, 5)
  368. assert c1.bounds == (-5, -9, 9, 5)
  369. assert c2.bounds == (-2, -2, 2, 2)
  370. def test_reflect():
  371. b = Symbol('b')
  372. m = Symbol('m')
  373. l = Line((0, b), slope=m)
  374. t1 = Triangle((0, 0), (1, 0), (2, 3))
  375. assert t1.area == -t1.reflect(l).area
  376. e = Ellipse((1, 0), 1, 2)
  377. assert e.area == -e.reflect(Line((1, 0), slope=0)).area
  378. assert e.area == -e.reflect(Line((1, 0), slope=oo)).area
  379. raises(NotImplementedError, lambda: e.reflect(Line((1, 0), slope=m)))
  380. assert Circle((0, 1), 1).reflect(Line((0, 0), (1, 1))) == Circle(Point2D(1, 0), -1)
  381. def test_is_tangent():
  382. e1 = Ellipse(Point(0, 0), 3, 5)
  383. c1 = Circle(Point(2, -2), 7)
  384. assert e1.is_tangent(Point(0, 0)) is False
  385. assert e1.is_tangent(Point(3, 0)) is False
  386. assert e1.is_tangent(e1) is True
  387. assert e1.is_tangent(Ellipse((0, 0), 1, 2)) is False
  388. assert e1.is_tangent(Ellipse((0, 0), 3, 2)) is True
  389. assert c1.is_tangent(Ellipse((2, -2), 7, 1)) is True
  390. assert c1.is_tangent(Circle((11, -2), 2)) is True
  391. assert c1.is_tangent(Circle((7, -2), 2)) is True
  392. assert c1.is_tangent(Ray((-5, -2), (-15, -20))) is False
  393. assert c1.is_tangent(Ray((-3, -2), (-15, -20))) is False
  394. assert c1.is_tangent(Ray((-3, -22), (15, 20))) is False
  395. assert c1.is_tangent(Ray((9, 20), (9, -20))) is True
  396. assert e1.is_tangent(Segment((2, 2), (-7, 7))) is False
  397. assert e1.is_tangent(Segment((0, 0), (1, 2))) is False
  398. assert c1.is_tangent(Segment((0, 0), (-5, -2))) is False
  399. assert e1.is_tangent(Segment((3, 0), (12, 12))) is False
  400. assert e1.is_tangent(Segment((12, 12), (3, 0))) is False
  401. assert e1.is_tangent(Segment((-3, 0), (3, 0))) is False
  402. assert e1.is_tangent(Segment((-3, 5), (3, 5))) is True
  403. assert e1.is_tangent(Line((10, 0), (10, 10))) is False
  404. assert e1.is_tangent(Line((0, 0), (1, 1))) is False
  405. assert e1.is_tangent(Line((-3, 0), (-2.99, -0.001))) is False
  406. assert e1.is_tangent(Line((-3, 0), (-3, 1))) is True
  407. assert e1.is_tangent(Polygon((0, 0), (5, 5), (5, -5))) is False
  408. assert e1.is_tangent(Polygon((-100, -50), (-40, -334), (-70, -52))) is False
  409. assert e1.is_tangent(Polygon((-3, 0), (3, 0), (0, 1))) is False
  410. assert e1.is_tangent(Polygon((-3, 0), (3, 0), (0, 5))) is False
  411. assert e1.is_tangent(Polygon((-3, 0), (0, -5), (3, 0), (0, 5))) is False
  412. assert e1.is_tangent(Polygon((-3, -5), (-3, 5), (3, 5), (3, -5))) is True
  413. assert c1.is_tangent(Polygon((-3, -5), (-3, 5), (3, 5), (3, -5))) is False
  414. assert e1.is_tangent(Polygon((0, 0), (3, 0), (7, 7), (0, 5))) is False
  415. assert e1.is_tangent(Polygon((3, 12), (3, -12), (6, 5))) is True
  416. assert e1.is_tangent(Polygon((3, 12), (3, -12), (0, -5), (0, 5))) is False
  417. assert e1.is_tangent(Polygon((3, 0), (5, 7), (6, -5))) is False
  418. raises(TypeError, lambda: e1.is_tangent(Point(0, 0, 0)))
  419. raises(TypeError, lambda: e1.is_tangent(Rational(5)))
  420. def test_parameter_value():
  421. t = Symbol('t')
  422. e = Ellipse(Point(0, 0), 3, 5)
  423. assert e.parameter_value((3, 0), t) == {t: 0}
  424. raises(ValueError, lambda: e.parameter_value((4, 0), t))
  425. @slow
  426. def test_second_moment_of_area():
  427. x, y = symbols('x, y')
  428. e = Ellipse(Point(0, 0), 5, 4)
  429. I_yy = 2*4*integrate(sqrt(25 - x**2)*x**2, (x, -5, 5))/5
  430. I_xx = 2*5*integrate(sqrt(16 - y**2)*y**2, (y, -4, 4))/4
  431. Y = 3*sqrt(1 - x**2/5**2)
  432. I_xy = integrate(integrate(y, (y, -Y, Y))*x, (x, -5, 5))
  433. assert I_yy == e.second_moment_of_area()[1]
  434. assert I_xx == e.second_moment_of_area()[0]
  435. assert I_xy == e.second_moment_of_area()[2]
  436. #checking for other point
  437. t1 = e.second_moment_of_area(Point(6,5))
  438. t2 = (580*pi, 845*pi, 600*pi)
  439. assert t1==t2
  440. def test_section_modulus_and_polar_second_moment_of_area():
  441. d = Symbol('d', positive=True)
  442. c = Circle((3, 7), 8)
  443. assert c.polar_second_moment_of_area() == 2048*pi
  444. assert c.section_modulus() == (128*pi, 128*pi)
  445. c = Circle((2, 9), d/2)
  446. assert c.polar_second_moment_of_area() == pi*d**3*Abs(d)/64 + pi*d*Abs(d)**3/64
  447. assert c.section_modulus() == (pi*d**3/S(32), pi*d**3/S(32))
  448. a, b = symbols('a, b', positive=True)
  449. e = Ellipse((4, 6), a, b)
  450. assert e.section_modulus() == (pi*a*b**2/S(4), pi*a**2*b/S(4))
  451. assert e.polar_second_moment_of_area() == pi*a**3*b/S(4) + pi*a*b**3/S(4)
  452. e = e.rotate(pi/2) # no change in polar and section modulus
  453. assert e.section_modulus() == (pi*a**2*b/S(4), pi*a*b**2/S(4))
  454. assert e.polar_second_moment_of_area() == pi*a**3*b/S(4) + pi*a*b**3/S(4)
  455. e = Ellipse((a, b), 2, 6)
  456. assert e.section_modulus() == (18*pi, 6*pi)
  457. assert e.polar_second_moment_of_area() == 120*pi
  458. e = Ellipse(Point(0, 0), 2, 2)
  459. assert e.section_modulus() == (2*pi, 2*pi)
  460. assert e.section_modulus(Point(2, 2)) == (2*pi, 2*pi)
  461. assert e.section_modulus((2, 2)) == (2*pi, 2*pi)
  462. def test_circumference():
  463. M = Symbol('M')
  464. m = Symbol('m')
  465. assert Ellipse(Point(0, 0), M, m).circumference == 4 * M * elliptic_e((M ** 2 - m ** 2) / M**2)
  466. assert Ellipse(Point(0, 0), 5, 4).circumference == 20 * elliptic_e(S(9) / 25)
  467. # circle
  468. assert Ellipse(None, 1, None, 0).circumference == 2*pi
  469. # test numerically
  470. assert abs(Ellipse(None, hradius=5, vradius=3).circumference.evalf(16) - 25.52699886339813) < 1e-10
  471. def test_issue_15259():
  472. assert Circle((1, 2), 0) == Point(1, 2)
  473. def test_issue_15797_equals():
  474. Ri = 0.024127189424130748
  475. Ci = (0.0864931002830291, 0.0819863295239654)
  476. A = Point(0, 0.0578591400998346)
  477. c = Circle(Ci, Ri) # evaluated
  478. assert c.is_tangent(c.tangent_lines(A)[0]) == True
  479. assert c.center.x.is_Rational
  480. assert c.center.y.is_Rational
  481. assert c.radius.is_Rational
  482. u = Circle(Ci, Ri, evaluate=False) # unevaluated
  483. assert u.center.x.is_Float
  484. assert u.center.y.is_Float
  485. assert u.radius.is_Float
  486. def test_auxiliary_circle():
  487. x, y, a, b = symbols('x y a b')
  488. e = Ellipse((x, y), a, b)
  489. # the general result
  490. assert e.auxiliary_circle() == Circle((x, y), Max(a, b))
  491. # a special case where Ellipse is a Circle
  492. assert Circle((3, 4), 8).auxiliary_circle() == Circle((3, 4), 8)
  493. def test_director_circle():
  494. x, y, a, b = symbols('x y a b')
  495. e = Ellipse((x, y), a, b)
  496. # the general result
  497. assert e.director_circle() == Circle((x, y), sqrt(a**2 + b**2))
  498. # a special case where Ellipse is a Circle
  499. assert Circle((3, 4), 8).director_circle() == Circle((3, 4), 8*sqrt(2))
  500. def test_evolute():
  501. #ellipse centered at h,k
  502. x, y, h, k = symbols('x y h k',real = True)
  503. a, b = symbols('a b')
  504. e = Ellipse(Point(h, k), a, b)
  505. t1 = (e.hradius*(x - e.center.x))**Rational(2, 3)
  506. t2 = (e.vradius*(y - e.center.y))**Rational(2, 3)
  507. E = t1 + t2 - (e.hradius**2 - e.vradius**2)**Rational(2, 3)
  508. assert e.evolute() == E
  509. #Numerical Example
  510. e = Ellipse(Point(1, 1), 6, 3)
  511. t1 = (6*(x - 1))**Rational(2, 3)
  512. t2 = (3*(y - 1))**Rational(2, 3)
  513. E = t1 + t2 - (27)**Rational(2, 3)
  514. assert e.evolute() == E
  515. def test_svg():
  516. e1 = Ellipse(Point(1, 0), 3, 2)
  517. assert e1._svg(2, "#FFAAFF") == '<ellipse fill="#FFAAFF" stroke="#555555" stroke-width="4.0" opacity="0.6" cx="1.00000000000000" cy="0" rx="3.00000000000000" ry="2.00000000000000"/>'