test_util.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import pytest
  2. from sympy.core.numbers import Float
  3. from sympy.core.function import (Derivative, Function)
  4. from sympy.core.singleton import S
  5. from sympy.core.symbol import Symbol
  6. from sympy.functions import exp, cos, sin, tan, cosh, sinh
  7. from sympy.functions.elementary.miscellaneous import sqrt
  8. from sympy.geometry import Point, Point2D, Line, Polygon, Segment, convex_hull,\
  9. intersection, centroid, Point3D, Line3D, Ray, Ellipse
  10. from sympy.geometry.util import idiff, closest_points, farthest_points, _ordered_points, are_coplanar
  11. from sympy.solvers.solvers import solve
  12. from sympy.testing.pytest import raises
  13. def test_idiff():
  14. x = Symbol('x', real=True)
  15. y = Symbol('y', real=True)
  16. t = Symbol('t', real=True)
  17. f = Function('f')
  18. g = Function('g')
  19. # the use of idiff in ellipse also provides coverage
  20. circ = x**2 + y**2 - 4
  21. ans = -3*x*(x**2/y**2 + 1)/y**3
  22. assert ans == idiff(circ, y, x, 3), idiff(circ, y, x, 3)
  23. assert ans == idiff(circ, [y], x, 3)
  24. assert idiff(circ, y, x, 3) == ans
  25. explicit = 12*x/sqrt(-x**2 + 4)**5
  26. assert ans.subs(y, solve(circ, y)[0]).equals(explicit)
  27. assert True in [sol.diff(x, 3).equals(explicit) for sol in solve(circ, y)]
  28. assert idiff(x + t + y, [y, t], x) == -Derivative(t, x) - 1
  29. assert idiff(f(x) * exp(f(x)) - x * exp(x), f(x), x) == (x + 1)*exp(x)*exp(-f(x))/(f(x) + 1)
  30. assert idiff(f(x) - y * exp(x), [f(x), y], x) == (y + Derivative(y, x))*exp(x)
  31. assert idiff(f(x) - y * exp(x), [y, f(x)], x) == -y + Derivative(f(x), x)*exp(-x)
  32. assert idiff(f(x) - g(x), [f(x), g(x)], x) == Derivative(g(x), x)
  33. # this should be fast
  34. fxy = y - (-10*(-sin(x) + 1/x)**2 + tan(x)**2 + 2*cosh(x/10))
  35. assert idiff(fxy, y, x) == -20*sin(x)*cos(x) + 2*tan(x)**3 + \
  36. 2*tan(x) + sinh(x/10)/5 + 20*cos(x)/x - 20*sin(x)/x**2 + 20/x**3
  37. def test_intersection():
  38. assert intersection(Point(0, 0)) == []
  39. raises(TypeError, lambda: intersection(Point(0, 0), 3))
  40. assert intersection(
  41. Segment((0, 0), (2, 0)),
  42. Segment((-1, 0), (1, 0)),
  43. Line((0, 0), (0, 1)), pairwise=True) == [
  44. Point(0, 0), Segment((0, 0), (1, 0))]
  45. assert intersection(
  46. Line((0, 0), (0, 1)),
  47. Segment((0, 0), (2, 0)),
  48. Segment((-1, 0), (1, 0)), pairwise=True) == [
  49. Point(0, 0), Segment((0, 0), (1, 0))]
  50. assert intersection(
  51. Line((0, 0), (0, 1)),
  52. Segment((0, 0), (2, 0)),
  53. Segment((-1, 0), (1, 0)),
  54. Line((0, 0), slope=1), pairwise=True) == [
  55. Point(0, 0), Segment((0, 0), (1, 0))]
  56. R = 4.0
  57. c = intersection(
  58. Ray(Point2D(0.001, -1),
  59. Point2D(0.0008, -1.7)),
  60. Ellipse(center=Point2D(0, 0), hradius=R, vradius=2.0), pairwise=True)[0].coordinates
  61. assert c == pytest.approx(
  62. Point2D(0.000714285723396502, -1.99999996811224, evaluate=False).coordinates)
  63. # check this is responds to a lower precision parameter
  64. R = Float(4, 5)
  65. c2 = intersection(
  66. Ray(Point2D(0.001, -1),
  67. Point2D(0.0008, -1.7)),
  68. Ellipse(center=Point2D(0, 0), hradius=R, vradius=2.0), pairwise=True)[0].coordinates
  69. assert c2 == pytest.approx(
  70. Point2D(0.000714285723396502, -1.99999996811224, evaluate=False).coordinates)
  71. assert c[0]._prec == 53
  72. assert c2[0]._prec == 20
  73. def test_convex_hull():
  74. raises(TypeError, lambda: convex_hull(Point(0, 0), 3))
  75. points = [(1, -1), (1, -2), (3, -1), (-5, -2), (15, -4)]
  76. assert convex_hull(*points, **{"polygon": False}) == (
  77. [Point2D(-5, -2), Point2D(1, -1), Point2D(3, -1), Point2D(15, -4)],
  78. [Point2D(-5, -2), Point2D(15, -4)])
  79. def test_centroid():
  80. p = Polygon((0, 0), (10, 0), (10, 10))
  81. q = p.translate(0, 20)
  82. assert centroid(p, q) == Point(20, 40)/3
  83. p = Segment((0, 0), (2, 0))
  84. q = Segment((0, 0), (2, 2))
  85. assert centroid(p, q) == Point(1, -sqrt(2) + 2)
  86. assert centroid(Point(0, 0), Point(2, 0)) == Point(2, 0)/2
  87. assert centroid(Point(0, 0), Point(0, 0), Point(2, 0)) == Point(2, 0)/3
  88. def test_farthest_points_closest_points():
  89. from sympy.core.random import randint
  90. from sympy.utilities.iterables import subsets
  91. for how in (min, max):
  92. if how == min:
  93. func = closest_points
  94. else:
  95. func = farthest_points
  96. raises(ValueError, lambda: func(Point2D(0, 0), Point2D(0, 0)))
  97. # 3rd pt dx is close and pt is closer to 1st pt
  98. p1 = [Point2D(0, 0), Point2D(3, 0), Point2D(1, 1)]
  99. # 3rd pt dx is close and pt is closer to 2nd pt
  100. p2 = [Point2D(0, 0), Point2D(3, 0), Point2D(2, 1)]
  101. # 3rd pt dx is close and but pt is not closer
  102. p3 = [Point2D(0, 0), Point2D(3, 0), Point2D(1, 10)]
  103. # 3rd pt dx is not closer and it's closer to 2nd pt
  104. p4 = [Point2D(0, 0), Point2D(3, 0), Point2D(4, 0)]
  105. # 3rd pt dx is not closer and it's closer to 1st pt
  106. p5 = [Point2D(0, 0), Point2D(3, 0), Point2D(-1, 0)]
  107. # duplicate point doesn't affect outcome
  108. dup = [Point2D(0, 0), Point2D(3, 0), Point2D(3, 0), Point2D(-1, 0)]
  109. # symbolic
  110. x = Symbol('x', positive=True)
  111. s = [Point2D(a) for a in ((x, 1), (x + 3, 2), (x + 2, 2))]
  112. for points in (p1, p2, p3, p4, p5, dup, s):
  113. d = how(i.distance(j) for i, j in subsets(set(points), 2))
  114. ans = a, b = list(func(*points))[0]
  115. assert a.distance(b) == d
  116. assert ans == _ordered_points(ans)
  117. # if the following ever fails, the above tests were not sufficient
  118. # and the logical error in the routine should be fixed
  119. points = set()
  120. while len(points) != 7:
  121. points.add(Point2D(randint(1, 100), randint(1, 100)))
  122. points = list(points)
  123. d = how(i.distance(j) for i, j in subsets(points, 2))
  124. ans = a, b = list(func(*points))[0]
  125. assert a.distance(b) == d
  126. assert ans == _ordered_points(ans)
  127. # equidistant points
  128. a, b, c = (
  129. Point2D(0, 0), Point2D(1, 0), Point2D(S.Half, sqrt(3)/2))
  130. ans = {_ordered_points((i, j))
  131. for i, j in subsets((a, b, c), 2)}
  132. assert closest_points(b, c, a) == ans
  133. assert farthest_points(b, c, a) == ans
  134. # unique to farthest
  135. points = [(1, 1), (1, 2), (3, 1), (-5, 2), (15, 4)]
  136. assert farthest_points(*points) == {
  137. (Point2D(-5, 2), Point2D(15, 4))}
  138. points = [(1, -1), (1, -2), (3, -1), (-5, -2), (15, -4)]
  139. assert farthest_points(*points) == {
  140. (Point2D(-5, -2), Point2D(15, -4))}
  141. assert farthest_points((1, 1), (0, 0)) == {
  142. (Point2D(0, 0), Point2D(1, 1))}
  143. raises(ValueError, lambda: farthest_points((1, 1)))
  144. def test_are_coplanar():
  145. a = Line3D(Point3D(5, 0, 0), Point3D(1, -1, 1))
  146. b = Line3D(Point3D(0, -2, 0), Point3D(3, 1, 1))
  147. c = Line3D(Point3D(0, -1, 0), Point3D(5, -1, 9))
  148. d = Line(Point2D(0, 3), Point2D(1, 5))
  149. assert are_coplanar(a, b, c) == False
  150. assert are_coplanar(a, d) == False