I am done

This commit is contained in:
2024-10-30 22:14:35 +01:00
parent 720dc28c09
commit 40e2a747cf
36901 changed files with 5011519 additions and 0 deletions

View File

@ -0,0 +1,120 @@
from sympy.core.containers import Tuple
from sympy.core.numbers import (Rational, pi)
from sympy.core.singleton import S
from sympy.core.symbol import (Symbol, symbols)
from sympy.functions.elementary.hyperbolic import asinh
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.geometry import Curve, Line, Point, Ellipse, Ray, Segment, Circle, Polygon, RegularPolygon
from sympy.testing.pytest import raises, slow
def test_curve():
x = Symbol('x', real=True)
s = Symbol('s')
z = Symbol('z')
# this curve is independent of the indicated parameter
c = Curve([2*s, s**2], (z, 0, 2))
assert c.parameter == z
assert c.functions == (2*s, s**2)
assert c.arbitrary_point() == Point(2*s, s**2)
assert c.arbitrary_point(z) == Point(2*s, s**2)
# this is how it is normally used
c = Curve([2*s, s**2], (s, 0, 2))
assert c.parameter == s
assert c.functions == (2*s, s**2)
t = Symbol('t')
# the t returned as assumptions
assert c.arbitrary_point() != Point(2*t, t**2)
t = Symbol('t', real=True)
# now t has the same assumptions so the test passes
assert c.arbitrary_point() == Point(2*t, t**2)
assert c.arbitrary_point(z) == Point(2*z, z**2)
assert c.arbitrary_point(c.parameter) == Point(2*s, s**2)
assert c.arbitrary_point(None) == Point(2*s, s**2)
assert c.plot_interval() == [t, 0, 2]
assert c.plot_interval(z) == [z, 0, 2]
assert Curve([x, x], (x, 0, 1)).rotate(pi/2) == Curve([-x, x], (x, 0, 1))
assert Curve([x, x], (x, 0, 1)).rotate(pi/2, (1, 2)).scale(2, 3).translate(
1, 3).arbitrary_point(s) == \
Line((0, 0), (1, 1)).rotate(pi/2, (1, 2)).scale(2, 3).translate(
1, 3).arbitrary_point(s) == \
Point(-2*s + 7, 3*s + 6)
raises(ValueError, lambda: Curve((s), (s, 1, 2)))
raises(ValueError, lambda: Curve((x, x * 2), (1, x)))
raises(ValueError, lambda: Curve((s, s + t), (s, 1, 2)).arbitrary_point())
raises(ValueError, lambda: Curve((s, s + t), (t, 1, 2)).arbitrary_point(s))
@slow
def test_free_symbols():
a, b, c, d, e, f, s = symbols('a:f,s')
assert Point(a, b).free_symbols == {a, b}
assert Line((a, b), (c, d)).free_symbols == {a, b, c, d}
assert Ray((a, b), (c, d)).free_symbols == {a, b, c, d}
assert Ray((a, b), angle=c).free_symbols == {a, b, c}
assert Segment((a, b), (c, d)).free_symbols == {a, b, c, d}
assert Line((a, b), slope=c).free_symbols == {a, b, c}
assert Curve((a*s, b*s), (s, c, d)).free_symbols == {a, b, c, d}
assert Ellipse((a, b), c, d).free_symbols == {a, b, c, d}
assert Ellipse((a, b), c, eccentricity=d).free_symbols == \
{a, b, c, d}
assert Ellipse((a, b), vradius=c, eccentricity=d).free_symbols == \
{a, b, c, d}
assert Circle((a, b), c).free_symbols == {a, b, c}
assert Circle((a, b), (c, d), (e, f)).free_symbols == \
{e, d, c, b, f, a}
assert Polygon((a, b), (c, d), (e, f)).free_symbols == \
{e, b, d, f, a, c}
assert RegularPolygon((a, b), c, d, e).free_symbols == {e, a, b, c, d}
def test_transform():
x = Symbol('x', real=True)
y = Symbol('y', real=True)
c = Curve((x, x**2), (x, 0, 1))
cout = Curve((2*x - 4, 3*x**2 - 10), (x, 0, 1))
pts = [Point(0, 0), Point(S.Half, Rational(1, 4)), Point(1, 1)]
pts_out = [Point(-4, -10), Point(-3, Rational(-37, 4)), Point(-2, -7)]
assert c.scale(2, 3, (4, 5)) == cout
assert [c.subs(x, xi/2) for xi in Tuple(0, 1, 2)] == pts
assert [cout.subs(x, xi/2) for xi in Tuple(0, 1, 2)] == pts_out
assert Curve((x + y, 3*x), (x, 0, 1)).subs(y, S.Half) == \
Curve((x + S.Half, 3*x), (x, 0, 1))
assert Curve((x, 3*x), (x, 0, 1)).translate(4, 5) == \
Curve((x + 4, 3*x + 5), (x, 0, 1))
def test_length():
t = Symbol('t', real=True)
c1 = Curve((t, 0), (t, 0, 1))
assert c1.length == 1
c2 = Curve((t, t), (t, 0, 1))
assert c2.length == sqrt(2)
c3 = Curve((t ** 2, t), (t, 2, 5))
assert c3.length == -sqrt(17) - asinh(4) / 4 + asinh(10) / 4 + 5 * sqrt(101) / 2
def test_parameter_value():
t = Symbol('t')
C = Curve([2*t, t**2], (t, 0, 2))
assert C.parameter_value((2, 1), t) == {t: 1}
raises(ValueError, lambda: C.parameter_value((2, 0), t))
def test_issue_17997():
t, s = symbols('t s')
c = Curve((t, t**2), (t, 0, 10))
p = Curve([2*s, s**2], (s, 0, 2))
assert c(2) == Point(2, 4)
assert p(1) == Point(2, 1)

View File

@ -0,0 +1,613 @@
from sympy.core import expand
from sympy.core.numbers import (Rational, oo, pi)
from sympy.core.relational import Eq
from sympy.core.singleton import S
from sympy.core.symbol import (Symbol, symbols)
from sympy.functions.elementary.complexes import Abs
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import sec
from sympy.geometry.line import Segment2D
from sympy.geometry.point import Point2D
from sympy.geometry import (Circle, Ellipse, GeometryError, Line, Point,
Polygon, Ray, RegularPolygon, Segment,
Triangle, intersection)
from sympy.testing.pytest import raises, slow
from sympy.integrals.integrals import integrate
from sympy.functions.special.elliptic_integrals import elliptic_e
from sympy.functions.elementary.miscellaneous import Max
def test_ellipse_equation_using_slope():
from sympy.abc import x, y
e1 = Ellipse(Point(1, 0), 3, 2)
assert str(e1.equation(_slope=1)) == str((-x + y + 1)**2/8 + (x + y - 1)**2/18 - 1)
e2 = Ellipse(Point(0, 0), 4, 1)
assert str(e2.equation(_slope=1)) == str((-x + y)**2/2 + (x + y)**2/32 - 1)
e3 = Ellipse(Point(1, 5), 6, 2)
assert str(e3.equation(_slope=2)) == str((-2*x + y - 3)**2/20 + (x + 2*y - 11)**2/180 - 1)
def test_object_from_equation():
from sympy.abc import x, y, a, b, c, d, e
assert Circle(x**2 + y**2 + 3*x + 4*y - 8) == Circle(Point2D(S(-3) / 2, -2), sqrt(57) / 2)
assert Circle(x**2 + y**2 + 6*x + 8*y + 25) == Circle(Point2D(-3, -4), 0)
assert Circle(a**2 + b**2 + 6*a + 8*b + 25, x='a', y='b') == Circle(Point2D(-3, -4), 0)
assert Circle(x**2 + y**2 - 25) == Circle(Point2D(0, 0), 5)
assert Circle(x**2 + y**2) == Circle(Point2D(0, 0), 0)
assert Circle(a**2 + b**2, x='a', y='b') == Circle(Point2D(0, 0), 0)
assert Circle(x**2 + y**2 + 6*x + 8) == Circle(Point2D(-3, 0), 1)
assert Circle(x**2 + y**2 + 6*y + 8) == Circle(Point2D(0, -3), 1)
assert Circle((x - 1)**2 + y**2 - 9) == Circle(Point2D(1, 0), 3)
assert Circle(6*(x**2) + 6*(y**2) + 6*x + 8*y - 25) == Circle(Point2D(Rational(-1, 2), Rational(-2, 3)), 5*sqrt(7)/6)
assert Circle(Eq(a**2 + b**2, 25), x='a', y=b) == Circle(Point2D(0, 0), 5)
raises(GeometryError, lambda: Circle(x**2 + y**2 + 3*x + 4*y + 26))
raises(GeometryError, lambda: Circle(x**2 + y**2 + 25))
raises(GeometryError, lambda: Circle(a**2 + b**2 + 25, x='a', y='b'))
raises(GeometryError, lambda: Circle(x**2 + 6*y + 8))
raises(GeometryError, lambda: Circle(6*(x ** 2) + 4*(y**2) + 6*x + 8*y + 25))
raises(ValueError, lambda: Circle(a**2 + b**2 + 3*a + 4*b - 8))
# .equation() adds 'real=True' assumption; '==' would fail if assumptions differed
x, y = symbols('x y', real=True)
eq = a*x**2 + a*y**2 + c*x + d*y + e
assert expand(Circle(eq).equation()*a) == eq
@slow
def test_ellipse_geom():
x = Symbol('x', real=True)
y = Symbol('y', real=True)
t = Symbol('t', real=True)
y1 = Symbol('y1', real=True)
half = S.Half
p1 = Point(0, 0)
p2 = Point(1, 1)
p4 = Point(0, 1)
e1 = Ellipse(p1, 1, 1)
e2 = Ellipse(p2, half, 1)
e3 = Ellipse(p1, y1, y1)
c1 = Circle(p1, 1)
c2 = Circle(p2, 1)
c3 = Circle(Point(sqrt(2), sqrt(2)), 1)
l1 = Line(p1, p2)
# Test creation with three points
cen, rad = Point(3*half, 2), 5*half
assert Circle(Point(0, 0), Point(3, 0), Point(0, 4)) == Circle(cen, rad)
assert Circle(Point(0, 0), Point(1, 1), Point(2, 2)) == Segment2D(Point2D(0, 0), Point2D(2, 2))
raises(ValueError, lambda: Ellipse(None, None, None, 1))
raises(ValueError, lambda: Ellipse())
raises(GeometryError, lambda: Circle(Point(0, 0)))
raises(GeometryError, lambda: Circle(Symbol('x')*Symbol('y')))
# Basic Stuff
assert Ellipse(None, 1, 1).center == Point(0, 0)
assert e1 == c1
assert e1 != e2
assert e1 != l1
assert p4 in e1
assert e1 in e1
assert e2 in e2
assert 1 not in e2
assert p2 not in e2
assert e1.area == pi
assert e2.area == pi/2
assert e3.area == pi*y1*abs(y1)
assert c1.area == e1.area
assert c1.circumference == e1.circumference
assert e3.circumference == 2*pi*y1
assert e1.plot_interval() == e2.plot_interval() == [t, -pi, pi]
assert e1.plot_interval(x) == e2.plot_interval(x) == [x, -pi, pi]
assert c1.minor == 1
assert c1.major == 1
assert c1.hradius == 1
assert c1.vradius == 1
assert Ellipse((1, 1), 0, 0) == Point(1, 1)
assert Ellipse((1, 1), 1, 0) == Segment(Point(0, 1), Point(2, 1))
assert Ellipse((1, 1), 0, 1) == Segment(Point(1, 0), Point(1, 2))
# Private Functions
assert hash(c1) == hash(Circle(Point(1, 0), Point(0, 1), Point(0, -1)))
assert c1 in e1
assert (Line(p1, p2) in e1) is False
assert e1.__cmp__(e1) == 0
assert e1.__cmp__(Point(0, 0)) > 0
# Encloses
assert e1.encloses(Segment(Point(-0.5, -0.5), Point(0.5, 0.5))) is True
assert e1.encloses(Line(p1, p2)) is False
assert e1.encloses(Ray(p1, p2)) is False
assert e1.encloses(e1) is False
assert e1.encloses(
Polygon(Point(-0.5, -0.5), Point(-0.5, 0.5), Point(0.5, 0.5))) is True
assert e1.encloses(RegularPolygon(p1, 0.5, 3)) is True
assert e1.encloses(RegularPolygon(p1, 5, 3)) is False
assert e1.encloses(RegularPolygon(p2, 5, 3)) is False
assert e2.arbitrary_point() in e2
raises(ValueError, lambda: Ellipse(Point(x, y), 1, 1).arbitrary_point(parameter='x'))
# Foci
f1, f2 = Point(sqrt(12), 0), Point(-sqrt(12), 0)
ef = Ellipse(Point(0, 0), 4, 2)
assert ef.foci in [(f1, f2), (f2, f1)]
# Tangents
v = sqrt(2) / 2
p1_1 = Point(v, v)
p1_2 = p2 + Point(half, 0)
p1_3 = p2 + Point(0, 1)
assert e1.tangent_lines(p4) == c1.tangent_lines(p4)
assert e2.tangent_lines(p1_2) == [Line(Point(Rational(3, 2), 1), Point(Rational(3, 2), S.Half))]
assert e2.tangent_lines(p1_3) == [Line(Point(1, 2), Point(Rational(5, 4), 2))]
assert c1.tangent_lines(p1_1) != [Line(p1_1, Point(0, sqrt(2)))]
assert c1.tangent_lines(p1) == []
assert e2.is_tangent(Line(p1_2, p2 + Point(half, 1)))
assert e2.is_tangent(Line(p1_3, p2 + Point(half, 1)))
assert c1.is_tangent(Line(p1_1, Point(0, sqrt(2))))
assert e1.is_tangent(Line(Point(0, 0), Point(1, 1))) is False
assert c1.is_tangent(e1) is True
assert c1.is_tangent(Ellipse(Point(2, 0), 1, 1)) is True
assert c1.is_tangent(
Polygon(Point(1, 1), Point(1, -1), Point(2, 0))) is False
assert c1.is_tangent(
Polygon(Point(1, 1), Point(1, 0), Point(2, 0))) is False
assert Circle(Point(5, 5), 3).is_tangent(Circle(Point(0, 5), 1)) is False
assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(0, 0)) == \
[Line(Point(0, 0), Point(Rational(77, 25), Rational(132, 25))),
Line(Point(0, 0), Point(Rational(33, 5), Rational(22, 5)))]
assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(3, 4)) == \
[Line(Point(3, 4), Point(4, 4)), Line(Point(3, 4), Point(3, 5))]
assert Circle(Point(5, 5), 2).tangent_lines(Point(3, 3)) == \
[Line(Point(3, 3), Point(4, 3)), Line(Point(3, 3), Point(3, 4))]
assert Circle(Point(5, 5), 2).tangent_lines(Point(5 - 2*sqrt(2), 5)) == \
[Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 - sqrt(2))),
Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 + sqrt(2))), ]
assert Circle(Point(5, 5), 5).tangent_lines(Point(4, 0)) == \
[Line(Point(4, 0), Point(Rational(40, 13), Rational(5, 13))),
Line(Point(4, 0), Point(5, 0))]
assert Circle(Point(5, 5), 5).tangent_lines(Point(0, 6)) == \
[Line(Point(0, 6), Point(0, 7)),
Line(Point(0, 6), Point(Rational(5, 13), Rational(90, 13)))]
# for numerical calculations, we shouldn't demand exact equality,
# so only test up to the desired precision
def lines_close(l1, l2, prec):
""" tests whether l1 and 12 are within 10**(-prec)
of each other """
return abs(l1.p1 - l2.p1) < 10**(-prec) and abs(l1.p2 - l2.p2) < 10**(-prec)
def line_list_close(ll1, ll2, prec):
return all(lines_close(l1, l2, prec) for l1, l2 in zip(ll1, ll2))
e = Ellipse(Point(0, 0), 2, 1)
assert e.normal_lines(Point(0, 0)) == \
[Line(Point(0, 0), Point(0, 1)), Line(Point(0, 0), Point(1, 0))]
assert e.normal_lines(Point(1, 0)) == \
[Line(Point(0, 0), Point(1, 0))]
assert e.normal_lines((0, 1)) == \
[Line(Point(0, 0), Point(0, 1))]
assert line_list_close(e.normal_lines(Point(1, 1), 2), [
Line(Point(Rational(-51, 26), Rational(-1, 5)), Point(Rational(-25, 26), Rational(17, 83))),
Line(Point(Rational(28, 29), Rational(-7, 8)), Point(Rational(57, 29), Rational(-9, 2)))], 2)
# test the failure of Poly.intervals and checks a point on the boundary
p = Point(sqrt(3), S.Half)
assert p in e
assert line_list_close(e.normal_lines(p, 2), [
Line(Point(Rational(-341, 171), Rational(-1, 13)), Point(Rational(-170, 171), Rational(5, 64))),
Line(Point(Rational(26, 15), Rational(-1, 2)), Point(Rational(41, 15), Rational(-43, 26)))], 2)
# be sure to use the slope that isn't undefined on boundary
e = Ellipse((0, 0), 2, 2*sqrt(3)/3)
assert line_list_close(e.normal_lines((1, 1), 2), [
Line(Point(Rational(-64, 33), Rational(-20, 71)), Point(Rational(-31, 33), Rational(2, 13))),
Line(Point(1, -1), Point(2, -4))], 2)
# general ellipse fails except under certain conditions
e = Ellipse((0, 0), x, 1)
assert e.normal_lines((x + 1, 0)) == [Line(Point(0, 0), Point(1, 0))]
raises(NotImplementedError, lambda: e.normal_lines((x + 1, 1)))
# Properties
major = 3
minor = 1
e4 = Ellipse(p2, minor, major)
assert e4.focus_distance == sqrt(major**2 - minor**2)
ecc = e4.focus_distance / major
assert e4.eccentricity == ecc
assert e4.periapsis == major*(1 - ecc)
assert e4.apoapsis == major*(1 + ecc)
assert e4.semilatus_rectum == major*(1 - ecc ** 2)
# independent of orientation
e4 = Ellipse(p2, major, minor)
assert e4.focus_distance == sqrt(major**2 - minor**2)
ecc = e4.focus_distance / major
assert e4.eccentricity == ecc
assert e4.periapsis == major*(1 - ecc)
assert e4.apoapsis == major*(1 + ecc)
# Intersection
l1 = Line(Point(1, -5), Point(1, 5))
l2 = Line(Point(-5, -1), Point(5, -1))
l3 = Line(Point(-1, -1), Point(1, 1))
l4 = Line(Point(-10, 0), Point(0, 10))
pts_c1_l3 = [Point(sqrt(2)/2, sqrt(2)/2), Point(-sqrt(2)/2, -sqrt(2)/2)]
assert intersection(e2, l4) == []
assert intersection(c1, Point(1, 0)) == [Point(1, 0)]
assert intersection(c1, l1) == [Point(1, 0)]
assert intersection(c1, l2) == [Point(0, -1)]
assert intersection(c1, l3) in [pts_c1_l3, [pts_c1_l3[1], pts_c1_l3[0]]]
assert intersection(c1, c2) == [Point(0, 1), Point(1, 0)]
assert intersection(c1, c3) == [Point(sqrt(2)/2, sqrt(2)/2)]
assert e1.intersection(l1) == [Point(1, 0)]
assert e2.intersection(l4) == []
assert e1.intersection(Circle(Point(0, 2), 1)) == [Point(0, 1)]
assert e1.intersection(Circle(Point(5, 0), 1)) == []
assert e1.intersection(Ellipse(Point(2, 0), 1, 1)) == [Point(1, 0)]
assert e1.intersection(Ellipse(Point(5, 0), 1, 1)) == []
assert e1.intersection(Point(2, 0)) == []
assert e1.intersection(e1) == e1
assert intersection(Ellipse(Point(0, 0), 2, 1), Ellipse(Point(3, 0), 1, 2)) == [Point(2, 0)]
assert intersection(Circle(Point(0, 0), 2), Circle(Point(3, 0), 1)) == [Point(2, 0)]
assert intersection(Circle(Point(0, 0), 2), Circle(Point(7, 0), 1)) == []
assert intersection(Ellipse(Point(0, 0), 5, 17), Ellipse(Point(4, 0), 1, 0.2)
) == [Point(5.0, 0, evaluate=False)]
assert intersection(Ellipse(Point(0, 0), 5, 17), Ellipse(Point(4, 0), 0.999, 0.2)) == []
assert Circle((0, 0), S.Half).intersection(
Triangle((-1, 0), (1, 0), (0, 1))) == [
Point(Rational(-1, 2), 0), Point(S.Half, 0)]
raises(TypeError, lambda: intersection(e2, Line((0, 0, 0), (0, 0, 1))))
raises(TypeError, lambda: intersection(e2, Rational(12)))
raises(TypeError, lambda: Ellipse.intersection(e2, 1))
# some special case intersections
csmall = Circle(p1, 3)
cbig = Circle(p1, 5)
cout = Circle(Point(5, 5), 1)
# one circle inside of another
assert csmall.intersection(cbig) == []
# separate circles
assert csmall.intersection(cout) == []
# coincident circles
assert csmall.intersection(csmall) == csmall
v = sqrt(2)
t1 = Triangle(Point(0, v), Point(0, -v), Point(v, 0))
points = intersection(t1, c1)
assert len(points) == 4
assert Point(0, 1) in points
assert Point(0, -1) in points
assert Point(v/2, v/2) in points
assert Point(v/2, -v/2) in points
circ = Circle(Point(0, 0), 5)
elip = Ellipse(Point(0, 0), 5, 20)
assert intersection(circ, elip) in \
[[Point(5, 0), Point(-5, 0)], [Point(-5, 0), Point(5, 0)]]
assert elip.tangent_lines(Point(0, 0)) == []
elip = Ellipse(Point(0, 0), 3, 2)
assert elip.tangent_lines(Point(3, 0)) == \
[Line(Point(3, 0), Point(3, -12))]
e1 = Ellipse(Point(0, 0), 5, 10)
e2 = Ellipse(Point(2, 1), 4, 8)
a = Rational(53, 17)
c = 2*sqrt(3991)/17
ans = [Point(a - c/8, a/2 + c), Point(a + c/8, a/2 - c)]
assert e1.intersection(e2) == ans
e2 = Ellipse(Point(x, y), 4, 8)
c = sqrt(3991)
ans = [Point(-c/68 + a, c*Rational(2, 17) + a/2), Point(c/68 + a, c*Rational(-2, 17) + a/2)]
assert [p.subs({x: 2, y:1}) for p in e1.intersection(e2)] == ans
# Combinations of above
assert e3.is_tangent(e3.tangent_lines(p1 + Point(y1, 0))[0])
e = Ellipse((1, 2), 3, 2)
assert e.tangent_lines(Point(10, 0)) == \
[Line(Point(10, 0), Point(1, 0)),
Line(Point(10, 0), Point(Rational(14, 5), Rational(18, 5)))]
# encloses_point
e = Ellipse((0, 0), 1, 2)
assert e.encloses_point(e.center)
assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10)))
assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0))
assert e.encloses_point(e.center + Point(e.hradius, 0)) is False
assert e.encloses_point(
e.center + Point(e.hradius + Rational(1, 10), 0)) is False
e = Ellipse((0, 0), 2, 1)
assert e.encloses_point(e.center)
assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10)))
assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0))
assert e.encloses_point(e.center + Point(e.hradius, 0)) is False
assert e.encloses_point(
e.center + Point(e.hradius + Rational(1, 10), 0)) is False
assert c1.encloses_point(Point(1, 0)) is False
assert c1.encloses_point(Point(0.3, 0.4)) is True
assert e.scale(2, 3) == Ellipse((0, 0), 4, 3)
assert e.scale(3, 6) == Ellipse((0, 0), 6, 6)
assert e.rotate(pi) == e
assert e.rotate(pi, (1, 2)) == Ellipse(Point(2, 4), 2, 1)
raises(NotImplementedError, lambda: e.rotate(pi/3))
# Circle rotation tests (Issue #11743)
# Link - https://github.com/sympy/sympy/issues/11743
cir = Circle(Point(1, 0), 1)
assert cir.rotate(pi/2) == Circle(Point(0, 1), 1)
assert cir.rotate(pi/3) == Circle(Point(S.Half, sqrt(3)/2), 1)
assert cir.rotate(pi/3, Point(1, 0)) == Circle(Point(1, 0), 1)
assert cir.rotate(pi/3, Point(0, 1)) == Circle(Point(S.Half + sqrt(3)/2, S.Half + sqrt(3)/2), 1)
def test_construction():
e1 = Ellipse(hradius=2, vradius=1, eccentricity=None)
assert e1.eccentricity == sqrt(3)/2
e2 = Ellipse(hradius=2, vradius=None, eccentricity=sqrt(3)/2)
assert e2.vradius == 1
e3 = Ellipse(hradius=None, vradius=1, eccentricity=sqrt(3)/2)
assert e3.hradius == 2
# filter(None, iterator) filters out anything falsey, including 0
# eccentricity would be filtered out in this case and the constructor would throw an error
e4 = Ellipse(Point(0, 0), hradius=1, eccentricity=0)
assert e4.vradius == 1
#tests for eccentricity > 1
raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity = S(3)/2))
raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity=sec(5)))
raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity=S.Pi-S(2)))
#tests for eccentricity = 1
#if vradius is not defined
assert Ellipse(None, 1, None, 1).length == 2
#if hradius is not defined
raises(GeometryError, lambda: Ellipse(None, None, 1, eccentricity = 1))
#tests for eccentricity < 0
raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity = -3))
raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity = -0.5))
def test_ellipse_random_point():
y1 = Symbol('y1', real=True)
e3 = Ellipse(Point(0, 0), y1, y1)
rx, ry = Symbol('rx'), Symbol('ry')
for ind in range(0, 5):
r = e3.random_point()
# substitution should give zero*y1**2
assert e3.equation(rx, ry).subs(zip((rx, ry), r.args)).equals(0)
# test for the case with seed
r = e3.random_point(seed=1)
assert e3.equation(rx, ry).subs(zip((rx, ry), r.args)).equals(0)
def test_repr():
assert repr(Circle((0, 1), 2)) == 'Circle(Point2D(0, 1), 2)'
def test_transform():
c = Circle((1, 1), 2)
assert c.scale(-1) == Circle((-1, 1), 2)
assert c.scale(y=-1) == Circle((1, -1), 2)
assert c.scale(2) == Ellipse((2, 1), 4, 2)
assert Ellipse((0, 0), 2, 3).scale(2, 3, (4, 5)) == \
Ellipse(Point(-4, -10), 4, 9)
assert Circle((0, 0), 2).scale(2, 3, (4, 5)) == \
Ellipse(Point(-4, -10), 4, 6)
assert Ellipse((0, 0), 2, 3).scale(3, 3, (4, 5)) == \
Ellipse(Point(-8, -10), 6, 9)
assert Circle((0, 0), 2).scale(3, 3, (4, 5)) == \
Circle(Point(-8, -10), 6)
assert Circle(Point(-8, -10), 6).scale(Rational(1, 3), Rational(1, 3), (4, 5)) == \
Circle((0, 0), 2)
assert Circle((0, 0), 2).translate(4, 5) == \
Circle((4, 5), 2)
assert Circle((0, 0), 2).scale(3, 3) == \
Circle((0, 0), 6)
def test_bounds():
e1 = Ellipse(Point(0, 0), 3, 5)
e2 = Ellipse(Point(2, -2), 7, 7)
c1 = Circle(Point(2, -2), 7)
c2 = Circle(Point(-2, 0), Point(0, 2), Point(2, 0))
assert e1.bounds == (-3, -5, 3, 5)
assert e2.bounds == (-5, -9, 9, 5)
assert c1.bounds == (-5, -9, 9, 5)
assert c2.bounds == (-2, -2, 2, 2)
def test_reflect():
b = Symbol('b')
m = Symbol('m')
l = Line((0, b), slope=m)
t1 = Triangle((0, 0), (1, 0), (2, 3))
assert t1.area == -t1.reflect(l).area
e = Ellipse((1, 0), 1, 2)
assert e.area == -e.reflect(Line((1, 0), slope=0)).area
assert e.area == -e.reflect(Line((1, 0), slope=oo)).area
raises(NotImplementedError, lambda: e.reflect(Line((1, 0), slope=m)))
assert Circle((0, 1), 1).reflect(Line((0, 0), (1, 1))) == Circle(Point2D(1, 0), -1)
def test_is_tangent():
e1 = Ellipse(Point(0, 0), 3, 5)
c1 = Circle(Point(2, -2), 7)
assert e1.is_tangent(Point(0, 0)) is False
assert e1.is_tangent(Point(3, 0)) is False
assert e1.is_tangent(e1) is True
assert e1.is_tangent(Ellipse((0, 0), 1, 2)) is False
assert e1.is_tangent(Ellipse((0, 0), 3, 2)) is True
assert c1.is_tangent(Ellipse((2, -2), 7, 1)) is True
assert c1.is_tangent(Circle((11, -2), 2)) is True
assert c1.is_tangent(Circle((7, -2), 2)) is True
assert c1.is_tangent(Ray((-5, -2), (-15, -20))) is False
assert c1.is_tangent(Ray((-3, -2), (-15, -20))) is False
assert c1.is_tangent(Ray((-3, -22), (15, 20))) is False
assert c1.is_tangent(Ray((9, 20), (9, -20))) is True
assert c1.is_tangent(Ray((2, 5), (9, 5))) is True
assert c1.is_tangent(Segment((2, 5), (9, 5))) is True
assert e1.is_tangent(Segment((2, 2), (-7, 7))) is False
assert e1.is_tangent(Segment((0, 0), (1, 2))) is False
assert c1.is_tangent(Segment((0, 0), (-5, -2))) is False
assert e1.is_tangent(Segment((3, 0), (12, 12))) is False
assert e1.is_tangent(Segment((12, 12), (3, 0))) is False
assert e1.is_tangent(Segment((-3, 0), (3, 0))) is False
assert e1.is_tangent(Segment((-3, 5), (3, 5))) is True
assert e1.is_tangent(Line((10, 0), (10, 10))) is False
assert e1.is_tangent(Line((0, 0), (1, 1))) is False
assert e1.is_tangent(Line((-3, 0), (-2.99, -0.001))) is False
assert e1.is_tangent(Line((-3, 0), (-3, 1))) is True
assert e1.is_tangent(Polygon((0, 0), (5, 5), (5, -5))) is False
assert e1.is_tangent(Polygon((-100, -50), (-40, -334), (-70, -52))) is False
assert e1.is_tangent(Polygon((-3, 0), (3, 0), (0, 1))) is False
assert e1.is_tangent(Polygon((-3, 0), (3, 0), (0, 5))) is False
assert e1.is_tangent(Polygon((-3, 0), (0, -5), (3, 0), (0, 5))) is False
assert e1.is_tangent(Polygon((-3, -5), (-3, 5), (3, 5), (3, -5))) is True
assert c1.is_tangent(Polygon((-3, -5), (-3, 5), (3, 5), (3, -5))) is False
assert e1.is_tangent(Polygon((0, 0), (3, 0), (7, 7), (0, 5))) is False
assert e1.is_tangent(Polygon((3, 12), (3, -12), (6, 5))) is False
assert e1.is_tangent(Polygon((3, 12), (3, -12), (0, -5), (0, 5))) is False
assert e1.is_tangent(Polygon((3, 0), (5, 7), (6, -5))) is False
assert c1.is_tangent(Segment((0, 0), (-5, -2))) is False
assert e1.is_tangent(Segment((-3, 0), (3, 0))) is False
assert e1.is_tangent(Segment((-3, 5), (3, 5))) is True
assert e1.is_tangent(Polygon((0, 0), (5, 5), (5, -5))) is False
assert e1.is_tangent(Polygon((-100, -50), (-40, -334), (-70, -52))) is False
assert e1.is_tangent(Polygon((-3, -5), (-3, 5), (3, 5), (3, -5))) is True
assert c1.is_tangent(Polygon((-3, -5), (-3, 5), (3, 5), (3, -5))) is False
assert e1.is_tangent(Polygon((3, 12), (3, -12), (0, -5), (0, 5))) is False
assert e1.is_tangent(Polygon((3, 0), (5, 7), (6, -5))) is False
raises(TypeError, lambda: e1.is_tangent(Point(0, 0, 0)))
raises(TypeError, lambda: e1.is_tangent(Rational(5)))
def test_parameter_value():
t = Symbol('t')
e = Ellipse(Point(0, 0), 3, 5)
assert e.parameter_value((3, 0), t) == {t: 0}
raises(ValueError, lambda: e.parameter_value((4, 0), t))
@slow
def test_second_moment_of_area():
x, y = symbols('x, y')
e = Ellipse(Point(0, 0), 5, 4)
I_yy = 2*4*integrate(sqrt(25 - x**2)*x**2, (x, -5, 5))/5
I_xx = 2*5*integrate(sqrt(16 - y**2)*y**2, (y, -4, 4))/4
Y = 3*sqrt(1 - x**2/5**2)
I_xy = integrate(integrate(y, (y, -Y, Y))*x, (x, -5, 5))
assert I_yy == e.second_moment_of_area()[1]
assert I_xx == e.second_moment_of_area()[0]
assert I_xy == e.second_moment_of_area()[2]
#checking for other point
t1 = e.second_moment_of_area(Point(6,5))
t2 = (580*pi, 845*pi, 600*pi)
assert t1==t2
def test_section_modulus_and_polar_second_moment_of_area():
d = Symbol('d', positive=True)
c = Circle((3, 7), 8)
assert c.polar_second_moment_of_area() == 2048*pi
assert c.section_modulus() == (128*pi, 128*pi)
c = Circle((2, 9), d/2)
assert c.polar_second_moment_of_area() == pi*d**3*Abs(d)/64 + pi*d*Abs(d)**3/64
assert c.section_modulus() == (pi*d**3/S(32), pi*d**3/S(32))
a, b = symbols('a, b', positive=True)
e = Ellipse((4, 6), a, b)
assert e.section_modulus() == (pi*a*b**2/S(4), pi*a**2*b/S(4))
assert e.polar_second_moment_of_area() == pi*a**3*b/S(4) + pi*a*b**3/S(4)
e = e.rotate(pi/2) # no change in polar and section modulus
assert e.section_modulus() == (pi*a**2*b/S(4), pi*a*b**2/S(4))
assert e.polar_second_moment_of_area() == pi*a**3*b/S(4) + pi*a*b**3/S(4)
e = Ellipse((a, b), 2, 6)
assert e.section_modulus() == (18*pi, 6*pi)
assert e.polar_second_moment_of_area() == 120*pi
e = Ellipse(Point(0, 0), 2, 2)
assert e.section_modulus() == (2*pi, 2*pi)
assert e.section_modulus(Point(2, 2)) == (2*pi, 2*pi)
assert e.section_modulus((2, 2)) == (2*pi, 2*pi)
def test_circumference():
M = Symbol('M')
m = Symbol('m')
assert Ellipse(Point(0, 0), M, m).circumference == 4 * M * elliptic_e((M ** 2 - m ** 2) / M**2)
assert Ellipse(Point(0, 0), 5, 4).circumference == 20 * elliptic_e(S(9) / 25)
# circle
assert Ellipse(None, 1, None, 0).circumference == 2*pi
# test numerically
assert abs(Ellipse(None, hradius=5, vradius=3).circumference.evalf(16) - 25.52699886339813) < 1e-10
def test_issue_15259():
assert Circle((1, 2), 0) == Point(1, 2)
def test_issue_15797_equals():
Ri = 0.024127189424130748
Ci = (0.0864931002830291, 0.0819863295239654)
A = Point(0, 0.0578591400998346)
c = Circle(Ci, Ri) # evaluated
assert c.is_tangent(c.tangent_lines(A)[0]) == True
assert c.center.x.is_Rational
assert c.center.y.is_Rational
assert c.radius.is_Rational
u = Circle(Ci, Ri, evaluate=False) # unevaluated
assert u.center.x.is_Float
assert u.center.y.is_Float
assert u.radius.is_Float
def test_auxiliary_circle():
x, y, a, b = symbols('x y a b')
e = Ellipse((x, y), a, b)
# the general result
assert e.auxiliary_circle() == Circle((x, y), Max(a, b))
# a special case where Ellipse is a Circle
assert Circle((3, 4), 8).auxiliary_circle() == Circle((3, 4), 8)
def test_director_circle():
x, y, a, b = symbols('x y a b')
e = Ellipse((x, y), a, b)
# the general result
assert e.director_circle() == Circle((x, y), sqrt(a**2 + b**2))
# a special case where Ellipse is a Circle
assert Circle((3, 4), 8).director_circle() == Circle((3, 4), 8*sqrt(2))
def test_evolute():
#ellipse centered at h,k
x, y, h, k = symbols('x y h k',real = True)
a, b = symbols('a b')
e = Ellipse(Point(h, k), a, b)
t1 = (e.hradius*(x - e.center.x))**Rational(2, 3)
t2 = (e.vradius*(y - e.center.y))**Rational(2, 3)
E = t1 + t2 - (e.hradius**2 - e.vradius**2)**Rational(2, 3)
assert e.evolute() == E
#Numerical Example
e = Ellipse(Point(1, 1), 6, 3)
t1 = (6*(x - 1))**Rational(2, 3)
t2 = (3*(y - 1))**Rational(2, 3)
E = t1 + t2 - (27)**Rational(2, 3)
assert e.evolute() == E
def test_svg():
e1 = Ellipse(Point(1, 0), 3, 2)
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"/>'

View File

@ -0,0 +1,120 @@
from sympy.core.numbers import (Rational, pi)
from sympy.core.singleton import S
from sympy.core.symbol import Symbol
from sympy.geometry import (Circle, Ellipse, Point, Line, Parabola,
Polygon, Ray, RegularPolygon, Segment, Triangle, Plane, Curve)
from sympy.geometry.entity import scale, GeometryEntity
from sympy.testing.pytest import raises
def test_entity():
x = Symbol('x', real=True)
y = Symbol('y', real=True)
assert GeometryEntity(x, y) in GeometryEntity(x, y)
raises(NotImplementedError, lambda: Point(0, 0) in GeometryEntity(x, y))
assert GeometryEntity(x, y) == GeometryEntity(x, y)
assert GeometryEntity(x, y).equals(GeometryEntity(x, y))
c = Circle((0, 0), 5)
assert GeometryEntity.encloses(c, Point(0, 0))
assert GeometryEntity.encloses(c, Segment((0, 0), (1, 1)))
assert GeometryEntity.encloses(c, Line((0, 0), (1, 1))) is False
assert GeometryEntity.encloses(c, Circle((0, 0), 4))
assert GeometryEntity.encloses(c, Polygon(Point(0, 0), Point(1, 0), Point(0, 1)))
assert GeometryEntity.encloses(c, RegularPolygon(Point(8, 8), 1, 3)) is False
def test_svg():
a = Symbol('a')
b = Symbol('b')
d = Symbol('d')
entity = Circle(Point(a, b), d)
assert entity._repr_svg_() is None
entity = Circle(Point(0, 0), S.Infinity)
assert entity._repr_svg_() is None
def test_subs():
x = Symbol('x', real=True)
y = Symbol('y', real=True)
p = Point(x, 2)
q = Point(1, 1)
r = Point(3, 4)
for o in [p,
Segment(p, q),
Ray(p, q),
Line(p, q),
Triangle(p, q, r),
RegularPolygon(p, 3, 6),
Polygon(p, q, r, Point(5, 4)),
Circle(p, 3),
Ellipse(p, 3, 4)]:
assert 'y' in str(o.subs(x, y))
assert p.subs({x: 1}) == Point(1, 2)
assert Point(1, 2).subs(Point(1, 2), Point(3, 4)) == Point(3, 4)
assert Point(1, 2).subs((1, 2), Point(3, 4)) == Point(3, 4)
assert Point(1, 2).subs(Point(1, 2), Point(3, 4)) == Point(3, 4)
assert Point(1, 2).subs({(1, 2)}) == Point(2, 2)
raises(ValueError, lambda: Point(1, 2).subs(1))
raises(ValueError, lambda: Point(1, 1).subs((Point(1, 1), Point(1,
2)), 1, 2))
def test_transform():
assert scale(1, 2, (3, 4)).tolist() == \
[[1, 0, 0], [0, 2, 0], [0, -4, 1]]
def test_reflect_entity_overrides():
x = Symbol('x', real=True)
y = Symbol('y', real=True)
b = Symbol('b')
m = Symbol('m')
l = Line((0, b), slope=m)
p = Point(x, y)
r = p.reflect(l)
c = Circle((x, y), 3)
cr = c.reflect(l)
assert cr == Circle(r, -3)
assert c.area == -cr.area
pent = RegularPolygon((1, 2), 1, 5)
slope = S.ComplexInfinity
while slope is S.ComplexInfinity:
slope = Rational(*(x._random()/2).as_real_imag())
l = Line(pent.vertices[1], slope=slope)
rpent = pent.reflect(l)
assert rpent.center == pent.center.reflect(l)
rvert = [i.reflect(l) for i in pent.vertices]
for v in rpent.vertices:
for i in range(len(rvert)):
ri = rvert[i]
if ri.equals(v):
rvert.remove(ri)
break
assert not rvert
assert pent.area.equals(-rpent.area)
def test_geometry_EvalfMixin():
x = pi
t = Symbol('t')
for g in [
Point(x, x),
Plane(Point(0, x, 0), (0, 0, x)),
Curve((x*t, x), (t, 0, x)),
Ellipse((x, x), x, -x),
Circle((x, x), x),
Line((0, x), (x, 0)),
Segment((0, x), (x, 0)),
Ray((0, x), (x, 0)),
Parabola((0, x), Line((-x, 0), (x, 0))),
Polygon((0, 0), (0, x), (x, 0), (x, x)),
RegularPolygon((0, x), x, 4, x),
Triangle((0, 0), (x, 0), (x, x)),
]:
assert str(g).replace('pi', '3.1') == str(g.n(2))

View File

@ -0,0 +1,38 @@
from sympy.core.numbers import Rational
from sympy.core.singleton import S
from sympy.geometry import Circle, Line, Point, Polygon, Segment
from sympy.sets import FiniteSet, Union, Intersection, EmptySet
def test_booleans():
""" test basic unions and intersections """
half = S.Half
p1, p2, p3, p4 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1)])
p5, p6, p7 = map(Point, [(3, 2), (1, -1), (0, 2)])
l1 = Line(Point(0,0), Point(1,1))
l2 = Line(Point(half, half), Point(5,5))
l3 = Line(p2, p3)
l4 = Line(p3, p4)
poly1 = Polygon(p1, p2, p3, p4)
poly2 = Polygon(p5, p6, p7)
poly3 = Polygon(p1, p2, p5)
assert Union(l1, l2).equals(l1)
assert Intersection(l1, l2).equals(l1)
assert Intersection(l1, l4) == FiniteSet(Point(1,1))
assert Intersection(Union(l1, l4), l3) == FiniteSet(Point(Rational(-1, 3), Rational(-1, 3)), Point(5, 1))
assert Intersection(l1, FiniteSet(Point(7,-7))) == EmptySet
assert Intersection(Circle(Point(0,0), 3), Line(p1,p2)) == FiniteSet(Point(-3,0), Point(3,0))
assert Intersection(l1, FiniteSet(p1)) == FiniteSet(p1)
assert Union(l1, FiniteSet(p1)) == l1
fs = FiniteSet(Point(Rational(1, 3), 1), Point(Rational(2, 3), 0), Point(Rational(9, 5), Rational(1, 5)), Point(Rational(7, 3), 1))
# test the intersection of polygons
assert Intersection(poly1, poly2) == fs
# make sure if we union polygons with subsets, the subsets go away
assert Union(poly1, poly2, fs) == Union(poly1, poly2)
# make sure that if we union with a FiniteSet that isn't a subset,
# that the points in the intersection stop being listed
assert Union(poly1, FiniteSet(Point(0,0), Point(3,5))) == Union(poly1, FiniteSet(Point(3,5)))
# intersect two polygons that share an edge
assert Intersection(poly1, poly3) == Union(FiniteSet(Point(Rational(3, 2), 1), Point(2, 1)), Segment(Point(0, 0), Point(1, 0)))

View File

@ -0,0 +1,861 @@
from sympy.core.numbers import (Float, Rational, oo, pi)
from sympy.core.relational import Eq
from sympy.core.singleton import S
from sympy.core.symbol import (Symbol, symbols)
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import (acos, cos, sin)
from sympy.sets import EmptySet
from sympy.simplify.simplify import simplify
from sympy.functions.elementary.trigonometric import tan
from sympy.geometry import (Circle, GeometryError, Line, Point, Ray,
Segment, Triangle, intersection, Point3D, Line3D, Ray3D, Segment3D,
Point2D, Line2D, Plane)
from sympy.geometry.line import Undecidable
from sympy.geometry.polygon import _asa as asa
from sympy.utilities.iterables import cartes
from sympy.testing.pytest import raises, warns
x = Symbol('x', real=True)
y = Symbol('y', real=True)
z = Symbol('z', real=True)
k = Symbol('k', real=True)
x1 = Symbol('x1', real=True)
y1 = Symbol('y1', real=True)
t = Symbol('t', real=True)
a, b = symbols('a,b', real=True)
m = symbols('m', real=True)
def test_object_from_equation():
from sympy.abc import x, y, a, b
assert Line(3*x + y + 18) == Line2D(Point2D(0, -18), Point2D(1, -21))
assert Line(3*x + 5 * y + 1) == Line2D(
Point2D(0, Rational(-1, 5)), Point2D(1, Rational(-4, 5)))
assert Line(3*a + b + 18, x="a", y="b") == Line2D(
Point2D(0, -18), Point2D(1, -21))
assert Line(3*x + y) == Line2D(Point2D(0, 0), Point2D(1, -3))
assert Line(x + y) == Line2D(Point2D(0, 0), Point2D(1, -1))
assert Line(Eq(3*a + b, -18), x="a", y=b) == Line2D(
Point2D(0, -18), Point2D(1, -21))
# issue 22361
assert Line(x - 1) == Line2D(Point2D(1, 0), Point2D(1, 1))
assert Line(2*x - 2, y=x) == Line2D(Point2D(0, 1), Point2D(1, 1))
assert Line(y) == Line2D(Point2D(0, 0), Point2D(1, 0))
assert Line(2*y, x=y) == Line2D(Point2D(0, 0), Point2D(0, 1))
assert Line(y, x=y) == Line2D(Point2D(0, 0), Point2D(0, 1))
raises(ValueError, lambda: Line(x / y))
raises(ValueError, lambda: Line(a / b, x='a', y='b'))
raises(ValueError, lambda: Line(y / x))
raises(ValueError, lambda: Line(b / a, x='a', y='b'))
raises(ValueError, lambda: Line((x + 1)**2 + y))
def feq(a, b):
"""Test if two floating point values are 'equal'."""
t_float = Float("1.0E-10")
return -t_float < a - b < t_float
def test_angle_between():
a = Point(1, 2, 3, 4)
b = a.orthogonal_direction
o = a.origin
assert feq(Line.angle_between(Line(Point(0, 0), Point(1, 1)),
Line(Point(0, 0), Point(5, 0))).evalf(), pi.evalf() / 4)
assert Line(a, o).angle_between(Line(b, o)) == pi / 2
z = Point3D(0, 0, 0)
assert Line3D.angle_between(Line3D(z, Point3D(1, 1, 1)),
Line3D(z, Point3D(5, 0, 0))) == acos(sqrt(3) / 3)
# direction of points is used to determine angle
assert Line3D.angle_between(Line3D(z, Point3D(1, 1, 1)),
Line3D(Point3D(5, 0, 0), z)) == acos(-sqrt(3) / 3)
def test_closing_angle():
a = Ray((0, 0), angle=0)
b = Ray((1, 2), angle=pi/2)
assert a.closing_angle(b) == -pi/2
assert b.closing_angle(a) == pi/2
assert a.closing_angle(a) == 0
def test_smallest_angle():
a = Line(Point(1, 1), Point(1, 2))
b = Line(Point(1, 1),Point(2, 3))
assert a.smallest_angle_between(b) == acos(2*sqrt(5)/5)
def test_svg():
a = Line(Point(1, 1),Point(1, 2))
assert a._svg() == '<path fill-rule="evenodd" fill="#66cc99" stroke="#555555" stroke-width="2.0" opacity="0.6" d="M 1.00000000000000,1.00000000000000 L 1.00000000000000,2.00000000000000" marker-start="url(#markerReverseArrow)" marker-end="url(#markerArrow)"/>'
a = Segment(Point(1, 0),Point(1, 1))
assert a._svg() == '<path fill-rule="evenodd" fill="#66cc99" stroke="#555555" stroke-width="2.0" opacity="0.6" d="M 1.00000000000000,0 L 1.00000000000000,1.00000000000000" />'
a = Ray(Point(2, 3), Point(3, 5))
assert a._svg() == '<path fill-rule="evenodd" fill="#66cc99" stroke="#555555" stroke-width="2.0" opacity="0.6" d="M 2.00000000000000,3.00000000000000 L 3.00000000000000,5.00000000000000" marker-start="url(#markerCircle)" marker-end="url(#markerArrow)"/>'
def test_arbitrary_point():
l1 = Line3D(Point3D(0, 0, 0), Point3D(1, 1, 1))
l2 = Line(Point(x1, x1), Point(y1, y1))
assert l2.arbitrary_point() in l2
assert Ray((1, 1), angle=pi / 4).arbitrary_point() == \
Point(t + 1, t + 1)
assert Segment((1, 1), (2, 3)).arbitrary_point() == Point(1 + t, 1 + 2 * t)
assert l1.perpendicular_segment(l1.arbitrary_point()) == l1.arbitrary_point()
assert Ray3D((1, 1, 1), direction_ratio=[1, 2, 3]).arbitrary_point() == \
Point3D(t + 1, 2 * t + 1, 3 * t + 1)
assert Segment3D(Point3D(0, 0, 0), Point3D(1, 1, 1)).midpoint == \
Point3D(S.Half, S.Half, S.Half)
assert Segment3D(Point3D(x1, x1, x1), Point3D(y1, y1, y1)).length == sqrt(3) * sqrt((x1 - y1) ** 2)
assert Segment3D((1, 1, 1), (2, 3, 4)).arbitrary_point() == \
Point3D(t + 1, 2 * t + 1, 3 * t + 1)
raises(ValueError, (lambda: Line((x, 1), (2, 3)).arbitrary_point(x)))
def test_are_concurrent_2d():
l1 = Line(Point(0, 0), Point(1, 1))
l2 = Line(Point(x1, x1), Point(x1, 1 + x1))
assert Line.are_concurrent(l1) is False
assert Line.are_concurrent(l1, l2)
assert Line.are_concurrent(l1, l1, l1, l2)
assert Line.are_concurrent(l1, l2, Line(Point(5, x1), Point(Rational(-3, 5), x1)))
assert Line.are_concurrent(l1, Line(Point(0, 0), Point(-x1, x1)), l2) is False
def test_are_concurrent_3d():
p1 = Point3D(0, 0, 0)
l1 = Line(p1, Point3D(1, 1, 1))
parallel_1 = Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0))
parallel_2 = Line3D(Point3D(0, 1, 0), Point3D(1, 1, 0))
assert Line3D.are_concurrent(l1) is False
assert Line3D.are_concurrent(l1, Line(Point3D(x1, x1, x1), Point3D(y1, y1, y1))) is False
assert Line3D.are_concurrent(l1, Line3D(p1, Point3D(x1, x1, x1)),
Line(Point3D(x1, x1, x1), Point3D(x1, 1 + x1, 1))) is True
assert Line3D.are_concurrent(parallel_1, parallel_2) is False
def test_arguments():
"""Functions accepting `Point` objects in `geometry`
should also accept tuples, lists, and generators and
automatically convert them to points."""
from sympy.utilities.iterables import subsets
singles2d = ((1, 2), [1, 3], Point(1, 5))
doubles2d = subsets(singles2d, 2)
l2d = Line(Point2D(1, 2), Point2D(2, 3))
singles3d = ((1, 2, 3), [1, 2, 4], Point(1, 2, 6))
doubles3d = subsets(singles3d, 2)
l3d = Line(Point3D(1, 2, 3), Point3D(1, 1, 2))
singles4d = ((1, 2, 3, 4), [1, 2, 3, 5], Point(1, 2, 3, 7))
doubles4d = subsets(singles4d, 2)
l4d = Line(Point(1, 2, 3, 4), Point(2, 2, 2, 2))
# test 2D
test_single = ['contains', 'distance', 'equals', 'parallel_line', 'perpendicular_line', 'perpendicular_segment',
'projection', 'intersection']
for p in doubles2d:
Line2D(*p)
for func in test_single:
for p in singles2d:
getattr(l2d, func)(p)
# test 3D
for p in doubles3d:
Line3D(*p)
for func in test_single:
for p in singles3d:
getattr(l3d, func)(p)
# test 4D
for p in doubles4d:
Line(*p)
for func in test_single:
for p in singles4d:
getattr(l4d, func)(p)
def test_basic_properties_2d():
p1 = Point(0, 0)
p2 = Point(1, 1)
p10 = Point(2000, 2000)
p_r3 = Ray(p1, p2).random_point()
p_r4 = Ray(p2, p1).random_point()
l1 = Line(p1, p2)
l3 = Line(Point(x1, x1), Point(x1, 1 + x1))
l4 = Line(p1, Point(1, 0))
r1 = Ray(p1, Point(0, 1))
r2 = Ray(Point(0, 1), p1)
s1 = Segment(p1, p10)
p_s1 = s1.random_point()
assert Line((1, 1), slope=1) == Line((1, 1), (2, 2))
assert Line((1, 1), slope=oo) == Line((1, 1), (1, 2))
assert Line((1, 1), slope=oo).bounds == (1, 1, 1, 2)
assert Line((1, 1), slope=-oo) == Line((1, 1), (1, 2))
assert Line(p1, p2).scale(2, 1) == Line(p1, Point(2, 1))
assert Line(p1, p2) == Line(p1, p2)
assert Line(p1, p2) != Line(p2, p1)
assert l1 != Line(Point(x1, x1), Point(y1, y1))
assert l1 != l3
assert Line(p1, p10) != Line(p10, p1)
assert Line(p1, p10) != p1
assert p1 in l1 # is p1 on the line l1?
assert p1 not in l3
assert s1 in Line(p1, p10)
assert Ray(Point(0, 0), Point(0, 1)) in Ray(Point(0, 0), Point(0, 2))
assert Ray(Point(0, 0), Point(0, 2)) in Ray(Point(0, 0), Point(0, 1))
assert Ray(Point(0, 0), Point(0, 2)).xdirection == S.Zero
assert Ray(Point(0, 0), Point(1, 2)).xdirection == S.Infinity
assert Ray(Point(0, 0), Point(-1, 2)).xdirection == S.NegativeInfinity
assert Ray(Point(0, 0), Point(2, 0)).ydirection == S.Zero
assert Ray(Point(0, 0), Point(2, 2)).ydirection == S.Infinity
assert Ray(Point(0, 0), Point(2, -2)).ydirection == S.NegativeInfinity
assert (r1 in s1) is False
assert Segment(p1, p2) in s1
assert Ray(Point(x1, x1), Point(x1, 1 + x1)) != Ray(p1, Point(-1, 5))
assert Segment(p1, p2).midpoint == Point(S.Half, S.Half)
assert Segment(p1, Point(-x1, x1)).length == sqrt(2 * (x1 ** 2))
assert l1.slope == 1
assert l3.slope is oo
assert l4.slope == 0
assert Line(p1, Point(0, 1)).slope is oo
assert Line(r1.source, r1.random_point()).slope == r1.slope
assert Line(r2.source, r2.random_point()).slope == r2.slope
assert Segment(Point(0, -1), Segment(p1, Point(0, 1)).random_point()).slope == Segment(p1, Point(0, 1)).slope
assert l4.coefficients == (0, 1, 0)
assert Line((-x, x), (-x + 1, x - 1)).coefficients == (1, 1, 0)
assert Line(p1, Point(0, 1)).coefficients == (1, 0, 0)
# issue 7963
r = Ray((0, 0), angle=x)
assert r.subs(x, 3 * pi / 4) == Ray((0, 0), (-1, 1))
assert r.subs(x, 5 * pi / 4) == Ray((0, 0), (-1, -1))
assert r.subs(x, -pi / 4) == Ray((0, 0), (1, -1))
assert r.subs(x, pi / 2) == Ray((0, 0), (0, 1))
assert r.subs(x, -pi / 2) == Ray((0, 0), (0, -1))
for ind in range(0, 5):
assert l3.random_point() in l3
assert p_r3.x >= p1.x and p_r3.y >= p1.y
assert p_r4.x <= p2.x and p_r4.y <= p2.y
assert p1.x <= p_s1.x <= p10.x and p1.y <= p_s1.y <= p10.y
assert hash(s1) != hash(Segment(p10, p1))
assert s1.plot_interval() == [t, 0, 1]
assert Line(p1, p10).plot_interval() == [t, -5, 5]
assert Ray((0, 0), angle=pi / 4).plot_interval() == [t, 0, 10]
def test_basic_properties_3d():
p1 = Point3D(0, 0, 0)
p2 = Point3D(1, 1, 1)
p3 = Point3D(x1, x1, x1)
p5 = Point3D(x1, 1 + x1, 1)
l1 = Line3D(p1, p2)
l3 = Line3D(p3, p5)
r1 = Ray3D(p1, Point3D(-1, 5, 0))
r3 = Ray3D(p1, p2)
s1 = Segment3D(p1, p2)
assert Line3D((1, 1, 1), direction_ratio=[2, 3, 4]) == Line3D(Point3D(1, 1, 1), Point3D(3, 4, 5))
assert Line3D((1, 1, 1), direction_ratio=[1, 5, 7]) == Line3D(Point3D(1, 1, 1), Point3D(2, 6, 8))
assert Line3D((1, 1, 1), direction_ratio=[1, 2, 3]) == Line3D(Point3D(1, 1, 1), Point3D(2, 3, 4))
assert Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)).direction_cosine == [1, 0, 0]
assert Line3D(Line3D(p1, Point3D(0, 1, 0))) == Line3D(p1, Point3D(0, 1, 0))
assert Ray3D(Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0))) == Ray3D(p1, Point3D(1, 0, 0))
assert Line3D(p1, p2) != Line3D(p2, p1)
assert l1 != l3
assert l1 != Line3D(p3, Point3D(y1, y1, y1))
assert r3 != r1
assert Ray3D(Point3D(0, 0, 0), Point3D(1, 1, 1)) in Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 2))
assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 2)) in Ray3D(Point3D(0, 0, 0), Point3D(1, 1, 1))
assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 2)).xdirection == S.Infinity
assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 2)).ydirection == S.Infinity
assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 2)).zdirection == S.Infinity
assert Ray3D(Point3D(0, 0, 0), Point3D(-2, 2, 2)).xdirection == S.NegativeInfinity
assert Ray3D(Point3D(0, 0, 0), Point3D(2, -2, 2)).ydirection == S.NegativeInfinity
assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, -2)).zdirection == S.NegativeInfinity
assert Ray3D(Point3D(0, 0, 0), Point3D(0, 2, 2)).xdirection == S.Zero
assert Ray3D(Point3D(0, 0, 0), Point3D(2, 0, 2)).ydirection == S.Zero
assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 0)).zdirection == S.Zero
assert p1 in l1
assert p1 not in l3
assert l1.direction_ratio == [1, 1, 1]
assert s1.midpoint == Point3D(S.Half, S.Half, S.Half)
# Test zdirection
assert Ray3D(p1, Point3D(0, 0, -1)).zdirection is S.NegativeInfinity
def test_contains():
p1 = Point(0, 0)
r = Ray(p1, Point(4, 4))
r1 = Ray3D(p1, Point3D(0, 0, -1))
r2 = Ray3D(p1, Point3D(0, 1, 0))
r3 = Ray3D(p1, Point3D(0, 0, 1))
l = Line(Point(0, 1), Point(3, 4))
# Segment contains
assert Point(0, (a + b) / 2) in Segment((0, a), (0, b))
assert Point((a + b) / 2, 0) in Segment((a, 0), (b, 0))
assert Point3D(0, 1, 0) in Segment3D((0, 1, 0), (0, 1, 0))
assert Point3D(1, 0, 0) in Segment3D((1, 0, 0), (1, 0, 0))
assert Segment3D(Point3D(0, 0, 0), Point3D(1, 0, 0)).contains([]) is True
assert Segment3D(Point3D(0, 0, 0), Point3D(1, 0, 0)).contains(
Segment3D(Point3D(2, 2, 2), Point3D(3, 2, 2))) is False
# Line contains
assert l.contains(Point(0, 1)) is True
assert l.contains((0, 1)) is True
assert l.contains((0, 0)) is False
# Ray contains
assert r.contains(p1) is True
assert r.contains((1, 1)) is True
assert r.contains((1, 3)) is False
assert r.contains(Segment((1, 1), (2, 2))) is True
assert r.contains(Segment((1, 2), (2, 5))) is False
assert r.contains(Ray((2, 2), (3, 3))) is True
assert r.contains(Ray((2, 2), (3, 5))) is False
assert r1.contains(Segment3D(p1, Point3D(0, 0, -10))) is True
assert r1.contains(Segment3D(Point3D(1, 1, 1), Point3D(2, 2, 2))) is False
assert r2.contains(Point3D(0, 0, 0)) is True
assert r3.contains(Point3D(0, 0, 0)) is True
assert Ray3D(Point3D(1, 1, 1), Point3D(1, 0, 0)).contains([]) is False
assert Line3D((0, 0, 0), (x, y, z)).contains((2 * x, 2 * y, 2 * z))
with warns(UserWarning, test_stacklevel=False):
assert Line3D(p1, Point3D(0, 1, 0)).contains(Point(1.0, 1.0)) is False
with warns(UserWarning, test_stacklevel=False):
assert r3.contains(Point(1.0, 1.0)) is False
def test_contains_nonreal_symbols():
u, v, w, z = symbols('u, v, w, z')
l = Segment(Point(u, w), Point(v, z))
p = Point(u*Rational(2, 3) + v/3, w*Rational(2, 3) + z/3)
assert l.contains(p)
def test_distance_2d():
p1 = Point(0, 0)
p2 = Point(1, 1)
half = S.Half
s1 = Segment(Point(0, 0), Point(1, 1))
s2 = Segment(Point(half, half), Point(1, 0))
r = Ray(p1, p2)
assert s1.distance(Point(0, 0)) == 0
assert s1.distance((0, 0)) == 0
assert s2.distance(Point(0, 0)) == 2 ** half / 2
assert s2.distance(Point(Rational(3) / 2, Rational(3) / 2)) == 2 ** half
assert Line(p1, p2).distance(Point(-1, 1)) == sqrt(2)
assert Line(p1, p2).distance(Point(1, -1)) == sqrt(2)
assert Line(p1, p2).distance(Point(2, 2)) == 0
assert Line(p1, p2).distance((-1, 1)) == sqrt(2)
assert Line((0, 0), (0, 1)).distance(p1) == 0
assert Line((0, 0), (0, 1)).distance(p2) == 1
assert Line((0, 0), (1, 0)).distance(p1) == 0
assert Line((0, 0), (1, 0)).distance(p2) == 1
assert r.distance(Point(-1, -1)) == sqrt(2)
assert r.distance(Point(1, 1)) == 0
assert r.distance(Point(-1, 1)) == sqrt(2)
assert Ray((1, 1), (2, 2)).distance(Point(1.5, 3)) == 3 * sqrt(2) / 4
assert r.distance((1, 1)) == 0
def test_dimension_normalization():
with warns(UserWarning, test_stacklevel=False):
assert Ray((1, 1), (2, 1, 2)) == Ray((1, 1, 0), (2, 1, 2))
def test_distance_3d():
p1, p2 = Point3D(0, 0, 0), Point3D(1, 1, 1)
p3 = Point3D(Rational(3) / 2, Rational(3) / 2, Rational(3) / 2)
s1 = Segment3D(Point3D(0, 0, 0), Point3D(1, 1, 1))
s2 = Segment3D(Point3D(S.Half, S.Half, S.Half), Point3D(1, 0, 1))
r = Ray3D(p1, p2)
assert s1.distance(p1) == 0
assert s2.distance(p1) == sqrt(3) / 2
assert s2.distance(p3) == 2 * sqrt(6) / 3
assert s1.distance((0, 0, 0)) == 0
assert s2.distance((0, 0, 0)) == sqrt(3) / 2
assert s1.distance(p1) == 0
assert s2.distance(p1) == sqrt(3) / 2
assert s2.distance(p3) == 2 * sqrt(6) / 3
assert s1.distance((0, 0, 0)) == 0
assert s2.distance((0, 0, 0)) == sqrt(3) / 2
# Line to point
assert Line3D(p1, p2).distance(Point3D(-1, 1, 1)) == 2 * sqrt(6) / 3
assert Line3D(p1, p2).distance(Point3D(1, -1, 1)) == 2 * sqrt(6) / 3
assert Line3D(p1, p2).distance(Point3D(2, 2, 2)) == 0
assert Line3D(p1, p2).distance((2, 2, 2)) == 0
assert Line3D(p1, p2).distance((1, -1, 1)) == 2 * sqrt(6) / 3
assert Line3D((0, 0, 0), (0, 1, 0)).distance(p1) == 0
assert Line3D((0, 0, 0), (0, 1, 0)).distance(p2) == sqrt(2)
assert Line3D((0, 0, 0), (1, 0, 0)).distance(p1) == 0
assert Line3D((0, 0, 0), (1, 0, 0)).distance(p2) == sqrt(2)
# Line to line
assert Line3D((0, 0, 0), (1, 0, 0)).distance(Line3D((0, 0, 0), (0, 1, 2))) == 0
assert Line3D((0, 0, 0), (1, 0, 0)).distance(Line3D((0, 0, 0), (1, 0, 0))) == 0
assert Line3D((0, 0, 0), (1, 0, 0)).distance(Line3D((10, 0, 0), (10, 1, 2))) == 0
assert Line3D((0, 0, 0), (1, 0, 0)).distance(Line3D((0, 1, 0), (0, 1, 1))) == 1
# Line to plane
assert Line3D((0, 0, 0), (1, 0, 0)).distance(Plane((2, 0, 0), (0, 0, 1))) == 0
assert Line3D((0, 0, 0), (1, 0, 0)).distance(Plane((0, 1, 0), (0, 1, 0))) == 1
assert Line3D((0, 0, 0), (1, 0, 0)).distance(Plane((1, 1, 3), (1, 0, 0))) == 0
# Ray to point
assert r.distance(Point3D(-1, -1, -1)) == sqrt(3)
assert r.distance(Point3D(1, 1, 1)) == 0
assert r.distance((-1, -1, -1)) == sqrt(3)
assert r.distance((1, 1, 1)) == 0
assert Ray3D((0, 0, 0), (1, 1, 2)).distance((-1, -1, 2)) == 4 * sqrt(3) / 3
assert Ray3D((1, 1, 1), (2, 2, 2)).distance(Point3D(1.5, -3, -1)) == Rational(9) / 2
assert Ray3D((1, 1, 1), (2, 2, 2)).distance(Point3D(1.5, 3, 1)) == sqrt(78) / 6
def test_equals():
p1 = Point(0, 0)
p2 = Point(1, 1)
l1 = Line(p1, p2)
l2 = Line((0, 5), slope=m)
l3 = Line(Point(x1, x1), Point(x1, 1 + x1))
assert l1.perpendicular_line(p1.args).equals(Line(Point(0, 0), Point(1, -1)))
assert l1.perpendicular_line(p1).equals(Line(Point(0, 0), Point(1, -1)))
assert Line(Point(x1, x1), Point(y1, y1)).parallel_line(Point(-x1, x1)). \
equals(Line(Point(-x1, x1), Point(-y1, 2 * x1 - y1)))
assert l3.parallel_line(p1.args).equals(Line(Point(0, 0), Point(0, -1)))
assert l3.parallel_line(p1).equals(Line(Point(0, 0), Point(0, -1)))
assert (l2.distance(Point(2, 3)) - 2 * abs(m + 1) / sqrt(m ** 2 + 1)).equals(0)
assert Line3D(p1, Point3D(0, 1, 0)).equals(Point(1.0, 1.0)) is False
assert Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)).equals(Line3D(Point3D(-5, 0, 0), Point3D(-1, 0, 0))) is True
assert Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)).equals(Line3D(p1, Point3D(0, 1, 0))) is False
assert Ray3D(p1, Point3D(0, 0, -1)).equals(Point(1.0, 1.0)) is False
assert Ray3D(p1, Point3D(0, 0, -1)).equals(Ray3D(p1, Point3D(0, 0, -1))) is True
assert Line3D((0, 0), (t, t)).perpendicular_line(Point(0, 1, 0)).equals(
Line3D(Point3D(0, 1, 0), Point3D(S.Half, S.Half, 0)))
assert Line3D((0, 0), (t, t)).perpendicular_segment(Point(0, 1, 0)).equals(Segment3D((0, 1), (S.Half, S.Half)))
assert Line3D(p1, Point3D(0, 1, 0)).equals(Point(1.0, 1.0)) is False
def test_equation():
p1 = Point(0, 0)
p2 = Point(1, 1)
l1 = Line(p1, p2)
l3 = Line(Point(x1, x1), Point(x1, 1 + x1))
assert simplify(l1.equation()) in (x - y, y - x)
assert simplify(l3.equation()) in (x - x1, x1 - x)
assert simplify(l1.equation()) in (x - y, y - x)
assert simplify(l3.equation()) in (x - x1, x1 - x)
assert Line(p1, Point(1, 0)).equation(x=x, y=y) == y
assert Line(p1, Point(0, 1)).equation() == x
assert Line(Point(2, 0), Point(2, 1)).equation() == x - 2
assert Line(p2, Point(2, 1)).equation() == y - 1
assert Line3D(Point(x1, x1, x1), Point(y1, y1, y1)
).equation() == (-x + y, -x + z)
assert Line3D(Point(1, 2, 3), Point(2, 3, 4)
).equation() == (-x + y - 1, -x + z - 2)
assert Line3D(Point(1, 2, 3), Point(1, 3, 4)
).equation() == (x - 1, -y + z - 1)
assert Line3D(Point(1, 2, 3), Point(2, 2, 4)
).equation() == (y - 2, -x + z - 2)
assert Line3D(Point(1, 2, 3), Point(2, 3, 3)
).equation() == (-x + y - 1, z - 3)
assert Line3D(Point(1, 2, 3), Point(1, 2, 4)
).equation() == (x - 1, y - 2)
assert Line3D(Point(1, 2, 3), Point(1, 3, 3)
).equation() == (x - 1, z - 3)
assert Line3D(Point(1, 2, 3), Point(2, 2, 3)
).equation() == (y - 2, z - 3)
def test_intersection_2d():
p1 = Point(0, 0)
p2 = Point(1, 1)
p3 = Point(x1, x1)
p4 = Point(y1, y1)
l1 = Line(p1, p2)
l3 = Line(Point(0, 0), Point(3, 4))
r1 = Ray(Point(1, 1), Point(2, 2))
r2 = Ray(Point(0, 0), Point(3, 4))
r4 = Ray(p1, p2)
r6 = Ray(Point(0, 1), Point(1, 2))
r7 = Ray(Point(0.5, 0.5), Point(1, 1))
s1 = Segment(p1, p2)
s2 = Segment(Point(0.25, 0.25), Point(0.5, 0.5))
s3 = Segment(Point(0, 0), Point(3, 4))
assert intersection(l1, p1) == [p1]
assert intersection(l1, Point(x1, 1 + x1)) == []
assert intersection(l1, Line(p3, p4)) in [[l1], [Line(p3, p4)]]
assert intersection(l1, l1.parallel_line(Point(x1, 1 + x1))) == []
assert intersection(l3, l3) == [l3]
assert intersection(l3, r2) == [r2]
assert intersection(l3, s3) == [s3]
assert intersection(s3, l3) == [s3]
assert intersection(Segment(Point(-10, 10), Point(10, 10)), Segment(Point(-5, -5), Point(-5, 5))) == []
assert intersection(r2, l3) == [r2]
assert intersection(r1, Ray(Point(2, 2), Point(0, 0))) == [Segment(Point(1, 1), Point(2, 2))]
assert intersection(r1, Ray(Point(1, 1), Point(-1, -1))) == [Point(1, 1)]
assert intersection(r1, Segment(Point(0, 0), Point(2, 2))) == [Segment(Point(1, 1), Point(2, 2))]
assert r4.intersection(s2) == [s2]
assert r4.intersection(Segment(Point(2, 3), Point(3, 4))) == []
assert r4.intersection(Segment(Point(-1, -1), Point(0.5, 0.5))) == [Segment(p1, Point(0.5, 0.5))]
assert r4.intersection(Ray(p2, p1)) == [s1]
assert Ray(p2, p1).intersection(r6) == []
assert r4.intersection(r7) == r7.intersection(r4) == [r7]
assert Ray3D((0, 0), (3, 0)).intersection(Ray3D((1, 0), (3, 0))) == [Ray3D((1, 0), (3, 0))]
assert Ray3D((1, 0), (3, 0)).intersection(Ray3D((0, 0), (3, 0))) == [Ray3D((1, 0), (3, 0))]
assert Ray(Point(0, 0), Point(0, 4)).intersection(Ray(Point(0, 1), Point(0, -1))) == \
[Segment(Point(0, 0), Point(0, 1))]
assert Segment3D((0, 0), (3, 0)).intersection(
Segment3D((1, 0), (2, 0))) == [Segment3D((1, 0), (2, 0))]
assert Segment3D((1, 0), (2, 0)).intersection(
Segment3D((0, 0), (3, 0))) == [Segment3D((1, 0), (2, 0))]
assert Segment3D((0, 0), (3, 0)).intersection(
Segment3D((3, 0), (4, 0))) == [Point3D((3, 0))]
assert Segment3D((0, 0), (3, 0)).intersection(
Segment3D((2, 0), (5, 0))) == [Segment3D((2, 0), (3, 0))]
assert Segment3D((0, 0), (3, 0)).intersection(
Segment3D((-2, 0), (1, 0))) == [Segment3D((0, 0), (1, 0))]
assert Segment3D((0, 0), (3, 0)).intersection(
Segment3D((-2, 0), (0, 0))) == [Point3D(0, 0)]
assert s1.intersection(Segment(Point(1, 1), Point(2, 2))) == [Point(1, 1)]
assert s1.intersection(Segment(Point(0.5, 0.5), Point(1.5, 1.5))) == [Segment(Point(0.5, 0.5), p2)]
assert s1.intersection(Segment(Point(4, 4), Point(5, 5))) == []
assert s1.intersection(Segment(Point(-1, -1), p1)) == [p1]
assert s1.intersection(Segment(Point(-1, -1), Point(0.5, 0.5))) == [Segment(p1, Point(0.5, 0.5))]
assert s1.intersection(Line(Point(1, 0), Point(2, 1))) == []
assert s1.intersection(s2) == [s2]
assert s2.intersection(s1) == [s2]
assert asa(120, 8, 52) == \
Triangle(
Point(0, 0),
Point(8, 0),
Point(-4 * cos(19 * pi / 90) / sin(2 * pi / 45),
4 * sqrt(3) * cos(19 * pi / 90) / sin(2 * pi / 45)))
assert Line((0, 0), (1, 1)).intersection(Ray((1, 0), (1, 2))) == [Point(1, 1)]
assert Line((0, 0), (1, 1)).intersection(Segment((1, 0), (1, 2))) == [Point(1, 1)]
assert Ray((0, 0), (1, 1)).intersection(Ray((1, 0), (1, 2))) == [Point(1, 1)]
assert Ray((0, 0), (1, 1)).intersection(Segment((1, 0), (1, 2))) == [Point(1, 1)]
assert Ray((0, 0), (10, 10)).contains(Segment((1, 1), (2, 2))) is True
assert Segment((1, 1), (2, 2)) in Line((0, 0), (10, 10))
assert s1.intersection(Ray((1, 1), (4, 4))) == [Point(1, 1)]
# This test is disabled because it hangs after rref changes which simplify
# intermediate results and return a different representation from when the
# test was written.
# # 16628 - this should be fast
# p0 = Point2D(Rational(249, 5), Rational(497999, 10000))
# p1 = Point2D((-58977084786*sqrt(405639795226) + 2030690077184193 +
# 20112207807*sqrt(630547164901) + 99600*sqrt(255775022850776494562626))
# /(2000*sqrt(255775022850776494562626) + 1991998000*sqrt(405639795226)
# + 1991998000*sqrt(630547164901) + 1622561172902000),
# (-498000*sqrt(255775022850776494562626) - 995999*sqrt(630547164901) +
# 90004251917891999 +
# 496005510002*sqrt(405639795226))/(10000*sqrt(255775022850776494562626)
# + 9959990000*sqrt(405639795226) + 9959990000*sqrt(630547164901) +
# 8112805864510000))
# p2 = Point2D(Rational(497, 10), Rational(-497, 10))
# p3 = Point2D(Rational(-497, 10), Rational(-497, 10))
# l = Line(p0, p1)
# s = Segment(p2, p3)
# n = (-52673223862*sqrt(405639795226) - 15764156209307469 -
# 9803028531*sqrt(630547164901) +
# 33200*sqrt(255775022850776494562626))
# d = sqrt(405639795226) + 315274080450 + 498000*sqrt(
# 630547164901) + sqrt(255775022850776494562626)
# assert intersection(l, s) == [
# Point2D(n/d*Rational(3, 2000), Rational(-497, 10))]
def test_line_intersection():
# see also test_issue_11238 in test_matrices.py
x0 = tan(pi*Rational(13, 45))
x1 = sqrt(3)
x2 = x0**2
x, y = [8*x0/(x0 + x1), (24*x0 - 8*x1*x2)/(x2 - 3)]
assert Line(Point(0, 0), Point(1, -sqrt(3))).contains(Point(x, y)) is True
def test_intersection_3d():
p1 = Point3D(0, 0, 0)
p2 = Point3D(1, 1, 1)
l1 = Line3D(p1, p2)
l2 = Line3D(Point3D(0, 0, 0), Point3D(3, 4, 0))
r1 = Ray3D(Point3D(1, 1, 1), Point3D(2, 2, 2))
r2 = Ray3D(Point3D(0, 0, 0), Point3D(3, 4, 0))
s1 = Segment3D(Point3D(0, 0, 0), Point3D(3, 4, 0))
assert intersection(l1, p1) == [p1]
assert intersection(l1, Point3D(x1, 1 + x1, 1)) == []
assert intersection(l1, l1.parallel_line(p1)) == [Line3D(Point3D(0, 0, 0), Point3D(1, 1, 1))]
assert intersection(l2, r2) == [r2]
assert intersection(l2, s1) == [s1]
assert intersection(r2, l2) == [r2]
assert intersection(r1, Ray3D(Point3D(1, 1, 1), Point3D(-1, -1, -1))) == [Point3D(1, 1, 1)]
assert intersection(r1, Segment3D(Point3D(0, 0, 0), Point3D(2, 2, 2))) == [
Segment3D(Point3D(1, 1, 1), Point3D(2, 2, 2))]
assert intersection(Ray3D(Point3D(1, 0, 0), Point3D(-1, 0, 0)), Ray3D(Point3D(0, 1, 0), Point3D(0, -1, 0))) \
== [Point3D(0, 0, 0)]
assert intersection(r1, Ray3D(Point3D(2, 2, 2), Point3D(0, 0, 0))) == \
[Segment3D(Point3D(1, 1, 1), Point3D(2, 2, 2))]
assert intersection(s1, r2) == [s1]
assert Line3D(Point3D(4, 0, 1), Point3D(0, 4, 1)).intersection(Line3D(Point3D(0, 0, 1), Point3D(4, 4, 1))) == \
[Point3D(2, 2, 1)]
assert Line3D((0, 1, 2), (0, 2, 3)).intersection(Line3D((0, 1, 2), (0, 1, 1))) == [Point3D(0, 1, 2)]
assert Line3D((0, 0), (t, t)).intersection(Line3D((0, 1), (t, t))) == \
[Point3D(t, t)]
assert Ray3D(Point3D(0, 0, 0), Point3D(0, 4, 0)).intersection(Ray3D(Point3D(0, 1, 1), Point3D(0, -1, 1))) == []
def test_is_parallel():
p1 = Point3D(0, 0, 0)
p2 = Point3D(1, 1, 1)
p3 = Point3D(x1, x1, x1)
l2 = Line(Point(x1, x1), Point(y1, y1))
l2_1 = Line(Point(x1, x1), Point(x1, 1 + x1))
assert Line.is_parallel(Line(Point(0, 0), Point(1, 1)), l2)
assert Line.is_parallel(l2, Line(Point(x1, x1), Point(x1, 1 + x1))) is False
assert Line.is_parallel(l2, l2.parallel_line(Point(-x1, x1)))
assert Line.is_parallel(l2_1, l2_1.parallel_line(Point(0, 0)))
assert Line3D(p1, p2).is_parallel(Line3D(p1, p2)) # same as in 2D
assert Line3D(Point3D(4, 0, 1), Point3D(0, 4, 1)).is_parallel(Line3D(Point3D(0, 0, 1), Point3D(4, 4, 1))) is False
assert Line3D(p1, p2).parallel_line(p3) == Line3D(Point3D(x1, x1, x1),
Point3D(x1 + 1, x1 + 1, x1 + 1))
assert Line3D(p1, p2).parallel_line(p3.args) == \
Line3D(Point3D(x1, x1, x1), Point3D(x1 + 1, x1 + 1, x1 + 1))
assert Line3D(Point3D(4, 0, 1), Point3D(0, 4, 1)).is_parallel(Line3D(Point3D(0, 0, 1), Point3D(4, 4, 1))) is False
def test_is_perpendicular():
p1 = Point(0, 0)
p2 = Point(1, 1)
l1 = Line(p1, p2)
l2 = Line(Point(x1, x1), Point(y1, y1))
l1_1 = Line(p1, Point(-x1, x1))
# 2D
assert Line.is_perpendicular(l1, l1_1)
assert Line.is_perpendicular(l1, l2) is False
p = l1.random_point()
assert l1.perpendicular_segment(p) == p
# 3D
assert Line3D.is_perpendicular(Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)),
Line3D(Point3D(0, 0, 0), Point3D(0, 1, 0))) is True
assert Line3D.is_perpendicular(Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)),
Line3D(Point3D(0, 1, 0), Point3D(1, 1, 0))) is False
assert Line3D.is_perpendicular(Line3D(Point3D(0, 0, 0), Point3D(1, 1, 1)),
Line3D(Point3D(x1, x1, x1), Point3D(y1, y1, y1))) is False
def test_is_similar():
p1 = Point(2000, 2000)
p2 = p1.scale(2, 2)
r1 = Ray3D(Point3D(1, 1, 1), Point3D(1, 0, 0))
r2 = Ray(Point(0, 0), Point(0, 1))
s1 = Segment(Point(0, 0), p1)
assert s1.is_similar(Segment(p1, p2))
assert s1.is_similar(r2) is False
assert r1.is_similar(Line3D(Point3D(1, 1, 1), Point3D(1, 0, 0))) is True
assert r1.is_similar(Line3D(Point3D(0, 0, 0), Point3D(0, 1, 0))) is False
def test_length():
s2 = Segment3D(Point3D(x1, x1, x1), Point3D(y1, y1, y1))
assert Line(Point(0, 0), Point(1, 1)).length is oo
assert s2.length == sqrt(3) * sqrt((x1 - y1) ** 2)
assert Line3D(Point3D(0, 0, 0), Point3D(1, 1, 1)).length is oo
def test_projection():
p1 = Point(0, 0)
p2 = Point3D(0, 0, 0)
p3 = Point(-x1, x1)
l1 = Line(p1, Point(1, 1))
l2 = Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0))
l3 = Line3D(p2, Point3D(1, 1, 1))
r1 = Ray(Point(1, 1), Point(2, 2))
s1 = Segment(Point2D(0, 0), Point2D(0, 1))
s2 = Segment(Point2D(1, 0), Point2D(2, 1/2))
assert Line(Point(x1, x1), Point(y1, y1)).projection(Point(y1, y1)) == Point(y1, y1)
assert Line(Point(x1, x1), Point(x1, 1 + x1)).projection(Point(1, 1)) == Point(x1, 1)
assert Segment(Point(-2, 2), Point(0, 4)).projection(r1) == Segment(Point(-1, 3), Point(0, 4))
assert Segment(Point(0, 4), Point(-2, 2)).projection(r1) == Segment(Point(0, 4), Point(-1, 3))
assert s2.projection(s1) == EmptySet
assert l1.projection(p3) == p1
assert l1.projection(Ray(p1, Point(-1, 5))) == Ray(Point(0, 0), Point(2, 2))
assert l1.projection(Ray(p1, Point(-1, 1))) == p1
assert r1.projection(Ray(Point(1, 1), Point(-1, -1))) == Point(1, 1)
assert r1.projection(Ray(Point(0, 4), Point(-1, -5))) == Segment(Point(1, 1), Point(2, 2))
assert r1.projection(Segment(Point(-1, 5), Point(-5, -10))) == Segment(Point(1, 1), Point(2, 2))
assert r1.projection(Ray(Point(1, 1), Point(-1, -1))) == Point(1, 1)
assert r1.projection(Ray(Point(0, 4), Point(-1, -5))) == Segment(Point(1, 1), Point(2, 2))
assert r1.projection(Segment(Point(-1, 5), Point(-5, -10))) == Segment(Point(1, 1), Point(2, 2))
assert l3.projection(Ray3D(p2, Point3D(-1, 5, 0))) == Ray3D(Point3D(0, 0, 0), Point3D(Rational(4, 3), Rational(4, 3), Rational(4, 3)))
assert l3.projection(Ray3D(p2, Point3D(-1, 1, 1))) == Ray3D(Point3D(0, 0, 0), Point3D(Rational(1, 3), Rational(1, 3), Rational(1, 3)))
assert l2.projection(Point3D(5, 5, 0)) == Point3D(5, 0)
assert l2.projection(Line3D(Point3D(0, 1, 0), Point3D(1, 1, 0))).equals(l2)
def test_perpendicular_line():
# 3d - requires a particular orthogonal to be selected
p1, p2, p3 = Point(0, 0, 0), Point(2, 3, 4), Point(-2, 2, 0)
l = Line(p1, p2)
p = l.perpendicular_line(p3)
assert p.p1 == p3
assert p.p2 in l
# 2d - does not require special selection
p1, p2, p3 = Point(0, 0), Point(2, 3), Point(-2, 2)
l = Line(p1, p2)
p = l.perpendicular_line(p3)
assert p.p1 == p3
# p is directed from l to p3
assert p.direction.unit == (p3 - l.projection(p3)).unit
def test_perpendicular_bisector():
s1 = Segment(Point(0, 0), Point(1, 1))
aline = Line(Point(S.Half, S.Half), Point(Rational(3, 2), Rational(-1, 2)))
on_line = Segment(Point(S.Half, S.Half), Point(Rational(3, 2), Rational(-1, 2))).midpoint
assert s1.perpendicular_bisector().equals(aline)
assert s1.perpendicular_bisector(on_line).equals(Segment(s1.midpoint, on_line))
assert s1.perpendicular_bisector(on_line + (1, 0)).equals(aline)
def test_raises():
d, e = symbols('a,b', real=True)
s = Segment((d, 0), (e, 0))
raises(TypeError, lambda: Line((1, 1), 1))
raises(ValueError, lambda: Line(Point(0, 0), Point(0, 0)))
raises(Undecidable, lambda: Point(2 * d, 0) in s)
raises(ValueError, lambda: Ray3D(Point(1.0, 1.0)))
raises(ValueError, lambda: Line3D(Point3D(0, 0, 0), Point3D(0, 0, 0)))
raises(TypeError, lambda: Line3D((1, 1), 1))
raises(ValueError, lambda: Line3D(Point3D(0, 0, 0)))
raises(TypeError, lambda: Ray((1, 1), 1))
raises(GeometryError, lambda: Line(Point(0, 0), Point(1, 0))
.projection(Circle(Point(0, 0), 1)))
def test_ray_generation():
assert Ray((1, 1), angle=pi / 4) == Ray((1, 1), (2, 2))
assert Ray((1, 1), angle=pi / 2) == Ray((1, 1), (1, 2))
assert Ray((1, 1), angle=-pi / 2) == Ray((1, 1), (1, 0))
assert Ray((1, 1), angle=-3 * pi / 2) == Ray((1, 1), (1, 2))
assert Ray((1, 1), angle=5 * pi / 2) == Ray((1, 1), (1, 2))
assert Ray((1, 1), angle=5.0 * pi / 2) == Ray((1, 1), (1, 2))
assert Ray((1, 1), angle=pi) == Ray((1, 1), (0, 1))
assert Ray((1, 1), angle=3.0 * pi) == Ray((1, 1), (0, 1))
assert Ray((1, 1), angle=4.0 * pi) == Ray((1, 1), (2, 1))
assert Ray((1, 1), angle=0) == Ray((1, 1), (2, 1))
assert Ray((1, 1), angle=4.05 * pi) == Ray(Point(1, 1),
Point(2, -sqrt(5) * sqrt(2 * sqrt(5) + 10) / 4 - sqrt(
2 * sqrt(5) + 10) / 4 + 2 + sqrt(5)))
assert Ray((1, 1), angle=4.02 * pi) == Ray(Point(1, 1),
Point(2, 1 + tan(4.02 * pi)))
assert Ray((1, 1), angle=5) == Ray((1, 1), (2, 1 + tan(5)))
assert Ray3D((1, 1, 1), direction_ratio=[4, 4, 4]) == Ray3D(Point3D(1, 1, 1), Point3D(5, 5, 5))
assert Ray3D((1, 1, 1), direction_ratio=[1, 2, 3]) == Ray3D(Point3D(1, 1, 1), Point3D(2, 3, 4))
assert Ray3D((1, 1, 1), direction_ratio=[1, 1, 1]) == Ray3D(Point3D(1, 1, 1), Point3D(2, 2, 2))
def test_issue_7814():
circle = Circle(Point(x, 0), y)
line = Line(Point(k, z), slope=0)
_s = sqrt((y - z)*(y + z))
assert line.intersection(circle) == [Point2D(x + _s, z), Point2D(x - _s, z)]
def test_issue_2941():
def _check():
for f, g in cartes(*[(Line, Ray, Segment)] * 2):
l1 = f(a, b)
l2 = g(c, d)
assert l1.intersection(l2) == l2.intersection(l1)
# intersect at end point
c, d = (-2, -2), (-2, 0)
a, b = (0, 0), (1, 1)
_check()
# midline intersection
c, d = (-2, -3), (-2, 0)
_check()
def test_parameter_value():
t = Symbol('t')
p1, p2 = Point(0, 1), Point(5, 6)
l = Line(p1, p2)
assert l.parameter_value((5, 6), t) == {t: 1}
raises(ValueError, lambda: l.parameter_value((0, 0), t))
def test_bisectors():
r1 = Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0))
r2 = Line3D(Point3D(0, 0, 0), Point3D(0, 1, 0))
bisections = r1.bisectors(r2)
assert bisections == [Line3D(Point3D(0, 0, 0), Point3D(1, 1, 0)),
Line3D(Point3D(0, 0, 0), Point3D(1, -1, 0))]
ans = [Line3D(Point3D(0, 0, 0), Point3D(1, 0, 1)),
Line3D(Point3D(0, 0, 0), Point3D(-1, 0, 1))]
l1 = (0, 0, 0), (0, 0, 1)
l2 = (0, 0), (1, 0)
for a, b in cartes((Line, Segment, Ray), repeat=2):
assert a(*l1).bisectors(b(*l2)) == ans
def test_issue_8615():
a = Line3D(Point3D(6, 5, 0), Point3D(6, -6, 0))
b = Line3D(Point3D(6, -1, 19/10), Point3D(6, -1, 0))
assert a.intersection(b) == [Point3D(6, -1, 0)]
def test_issue_12598():
r1 = Ray(Point(0, 1), Point(0.98, 0.79).n(2))
r2 = Ray(Point(0, 0), Point(0.71, 0.71).n(2))
assert str(r1.intersection(r2)[0]) == 'Point2D(0.82, 0.82)'
l1 = Line((0, 0), (1, 1))
l2 = Segment((-1, 1), (0, -1)).n(2)
assert str(l1.intersection(l2)[0]) == 'Point2D(-0.33, -0.33)'
l2 = Segment((-1, 1), (-1/2, 1/2)).n(2)
assert not l1.intersection(l2)

View File

@ -0,0 +1,143 @@
from sympy.core.numbers import (Rational, oo)
from sympy.core.singleton import S
from sympy.core.symbol import symbols
from sympy.functions.elementary.complexes import sign
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.geometry.ellipse import (Circle, Ellipse)
from sympy.geometry.line import (Line, Ray2D, Segment2D)
from sympy.geometry.parabola import Parabola
from sympy.geometry.point import (Point, Point2D)
from sympy.testing.pytest import raises
from sympy.abc import x, y
def test_parabola_geom():
a, b = symbols('a b')
p1 = Point(0, 0)
p2 = Point(3, 7)
p3 = Point(0, 4)
p4 = Point(6, 0)
p5 = Point(a, a)
d1 = Line(Point(4, 0), Point(4, 9))
d2 = Line(Point(7, 6), Point(3, 6))
d3 = Line(Point(4, 0), slope=oo)
d4 = Line(Point(7, 6), slope=0)
d5 = Line(Point(b, a), slope=oo)
d6 = Line(Point(a, b), slope=0)
half = S.Half
pa1 = Parabola(None, d2)
pa2 = Parabola(directrix=d1)
pa3 = Parabola(p1, d1)
pa4 = Parabola(p2, d2)
pa5 = Parabola(p2, d4)
pa6 = Parabola(p3, d2)
pa7 = Parabola(p2, d1)
pa8 = Parabola(p4, d1)
pa9 = Parabola(p4, d3)
pa10 = Parabola(p5, d5)
pa11 = Parabola(p5, d6)
d = Line(Point(3, 7), Point(2, 9))
pa12 = Parabola(Point(7, 8), d)
pa12r = Parabola(Point(7, 8).reflect(d), d)
raises(ValueError, lambda:
Parabola(Point(7, 8, 9), Line(Point(6, 7), Point(7, 7))))
raises(ValueError, lambda:
Parabola(Point(0, 2), Line(Point(7, 2), Point(6, 2))))
raises(ValueError, lambda: Parabola(Point(7, 8), Point(3, 8)))
# Basic Stuff
assert pa1.focus == Point(0, 0)
assert pa1.ambient_dimension == S(2)
assert pa2 == pa3
assert pa4 != pa7
assert pa6 != pa7
assert pa6.focus == Point2D(0, 4)
assert pa6.focal_length == 1
assert pa6.p_parameter == -1
assert pa6.vertex == Point2D(0, 5)
assert pa6.eccentricity == 1
assert pa7.focus == Point2D(3, 7)
assert pa7.focal_length == half
assert pa7.p_parameter == -half
assert pa7.vertex == Point2D(7*half, 7)
assert pa4.focal_length == half
assert pa4.p_parameter == half
assert pa4.vertex == Point2D(3, 13*half)
assert pa8.focal_length == 1
assert pa8.p_parameter == 1
assert pa8.vertex == Point2D(5, 0)
assert pa4.focal_length == pa5.focal_length
assert pa4.p_parameter == pa5.p_parameter
assert pa4.vertex == pa5.vertex
assert pa4.equation() == pa5.equation()
assert pa8.focal_length == pa9.focal_length
assert pa8.p_parameter == pa9.p_parameter
assert pa8.vertex == pa9.vertex
assert pa8.equation() == pa9.equation()
assert pa10.focal_length == pa11.focal_length == sqrt((a - b) ** 2) / 2 # if a, b real == abs(a - b)/2
assert pa11.vertex == Point(*pa10.vertex[::-1]) == Point(a,
a - sqrt((a - b)**2)*sign(a - b)/2) # change axis x->y, y->x on pa10
aos = pa12.axis_of_symmetry
assert aos == Line(Point(7, 8), Point(5, 7))
assert pa12.directrix == Line(Point(3, 7), Point(2, 9))
assert pa12.directrix.angle_between(aos) == S.Pi/2
assert pa12.eccentricity == 1
assert pa12.equation(x, y) == (x - 7)**2 + (y - 8)**2 - (-2*x - y + 13)**2/5
assert pa12.focal_length == 9*sqrt(5)/10
assert pa12.focus == Point(7, 8)
assert pa12.p_parameter == 9*sqrt(5)/10
assert pa12.vertex == Point2D(S(26)/5, S(71)/10)
assert pa12r.focal_length == 9*sqrt(5)/10
assert pa12r.focus == Point(-S(1)/5, S(22)/5)
assert pa12r.p_parameter == -9*sqrt(5)/10
assert pa12r.vertex == Point(S(8)/5, S(53)/10)
def test_parabola_intersection():
l1 = Line(Point(1, -2), Point(-1,-2))
l2 = Line(Point(1, 2), Point(-1,2))
l3 = Line(Point(1, 0), Point(-1,0))
p1 = Point(0,0)
p2 = Point(0, -2)
p3 = Point(120, -12)
parabola1 = Parabola(p1, l1)
# parabola with parabola
assert parabola1.intersection(parabola1) == [parabola1]
assert parabola1.intersection(Parabola(p1, l2)) == [Point2D(-2, 0), Point2D(2, 0)]
assert parabola1.intersection(Parabola(p2, l3)) == [Point2D(0, -1)]
assert parabola1.intersection(Parabola(Point(16, 0), l1)) == [Point2D(8, 15)]
assert parabola1.intersection(Parabola(Point(0, 16), l1)) == [Point2D(-6, 8), Point2D(6, 8)]
assert parabola1.intersection(Parabola(p3, l3)) == []
# parabola with point
assert parabola1.intersection(p1) == []
assert parabola1.intersection(Point2D(0, -1)) == [Point2D(0, -1)]
assert parabola1.intersection(Point2D(4, 3)) == [Point2D(4, 3)]
# parabola with line
assert parabola1.intersection(Line(Point2D(-7, 3), Point(12, 3))) == [Point2D(-4, 3), Point2D(4, 3)]
assert parabola1.intersection(Line(Point(-4, -1), Point(4, -1))) == [Point(0, -1)]
assert parabola1.intersection(Line(Point(2, 0), Point(0, -2))) == [Point2D(2, 0)]
raises(TypeError, lambda: parabola1.intersection(Line(Point(0, 0, 0), Point(1, 1, 1))))
# parabola with segment
assert parabola1.intersection(Segment2D((-4, -5), (4, 3))) == [Point2D(0, -1), Point2D(4, 3)]
assert parabola1.intersection(Segment2D((0, -5), (0, 6))) == [Point2D(0, -1)]
assert parabola1.intersection(Segment2D((-12, -65), (14, -68))) == []
# parabola with ray
assert parabola1.intersection(Ray2D((-4, -5), (4, 3))) == [Point2D(0, -1), Point2D(4, 3)]
assert parabola1.intersection(Ray2D((0, 7), (1, 14))) == [Point2D(14 + 2*sqrt(57), 105 + 14*sqrt(57))]
assert parabola1.intersection(Ray2D((0, 7), (0, 14))) == []
# parabola with ellipse/circle
assert parabola1.intersection(Circle(p1, 2)) == [Point2D(-2, 0), Point2D(2, 0)]
assert parabola1.intersection(Circle(p2, 1)) == [Point2D(0, -1)]
assert parabola1.intersection(Ellipse(p2, 2, 1)) == [Point2D(0, -1)]
assert parabola1.intersection(Ellipse(Point(0, 19), 5, 7)) == []
assert parabola1.intersection(Ellipse((0, 3), 12, 4)) == [
Point2D(0, -1),
Point2D(-4*sqrt(17)/3, Rational(59, 9)),
Point2D(4*sqrt(17)/3, Rational(59, 9))]
# parabola with unsupported type
raises(TypeError, lambda: parabola1.intersection(2))

View File

@ -0,0 +1,268 @@
from sympy.core.numbers import (Rational, pi)
from sympy.core.singleton import S
from sympy.core.symbol import (Dummy, symbols)
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import (asin, cos, sin)
from sympy.geometry import Line, Point, Ray, Segment, Point3D, Line3D, Ray3D, Segment3D, Plane, Circle
from sympy.geometry.util import are_coplanar
from sympy.testing.pytest import raises
def test_plane():
x, y, z, u, v = symbols('x y z u v', real=True)
p1 = Point3D(0, 0, 0)
p2 = Point3D(1, 1, 1)
p3 = Point3D(1, 2, 3)
pl3 = Plane(p1, p2, p3)
pl4 = Plane(p1, normal_vector=(1, 1, 1))
pl4b = Plane(p1, p2)
pl5 = Plane(p3, normal_vector=(1, 2, 3))
pl6 = Plane(Point3D(2, 3, 7), normal_vector=(2, 2, 2))
pl7 = Plane(Point3D(1, -5, -6), normal_vector=(1, -2, 1))
pl8 = Plane(p1, normal_vector=(0, 0, 1))
pl9 = Plane(p1, normal_vector=(0, 12, 0))
pl10 = Plane(p1, normal_vector=(-2, 0, 0))
pl11 = Plane(p2, normal_vector=(0, 0, 1))
l1 = Line3D(Point3D(5, 0, 0), Point3D(1, -1, 1))
l2 = Line3D(Point3D(0, -2, 0), Point3D(3, 1, 1))
l3 = Line3D(Point3D(0, -1, 0), Point3D(5, -1, 9))
raises(ValueError, lambda: Plane(p1, p1, p1))
assert Plane(p1, p2, p3) != Plane(p1, p3, p2)
assert Plane(p1, p2, p3).is_coplanar(Plane(p1, p3, p2))
assert Plane(p1, p2, p3).is_coplanar(p1)
assert Plane(p1, p2, p3).is_coplanar(Circle(p1, 1)) is False
assert Plane(p1, normal_vector=(0, 0, 1)).is_coplanar(Circle(p1, 1))
assert pl3 == Plane(Point3D(0, 0, 0), normal_vector=(1, -2, 1))
assert pl3 != pl4
assert pl4 == pl4b
assert pl5 == Plane(Point3D(1, 2, 3), normal_vector=(1, 2, 3))
assert pl5.equation(x, y, z) == x + 2*y + 3*z - 14
assert pl3.equation(x, y, z) == x - 2*y + z
assert pl3.p1 == p1
assert pl4.p1 == p1
assert pl5.p1 == p3
assert pl4.normal_vector == (1, 1, 1)
assert pl5.normal_vector == (1, 2, 3)
assert p1 in pl3
assert p1 in pl4
assert p3 in pl5
assert pl3.projection(Point(0, 0)) == p1
p = pl3.projection(Point3D(1, 1, 0))
assert p == Point3D(Rational(7, 6), Rational(2, 3), Rational(1, 6))
assert p in pl3
l = pl3.projection_line(Line(Point(0, 0), Point(1, 1)))
assert l == Line3D(Point3D(0, 0, 0), Point3D(Rational(7, 6), Rational(2, 3), Rational(1, 6)))
assert l in pl3
# get a segment that does not intersect the plane which is also
# parallel to pl3's normal veector
t = Dummy()
r = pl3.random_point()
a = pl3.perpendicular_line(r).arbitrary_point(t)
s = Segment3D(a.subs(t, 1), a.subs(t, 2))
assert s.p1 not in pl3 and s.p2 not in pl3
assert pl3.projection_line(s).equals(r)
assert pl3.projection_line(Segment(Point(1, 0), Point(1, 1))) == \
Segment3D(Point3D(Rational(5, 6), Rational(1, 3), Rational(-1, 6)), Point3D(Rational(7, 6), Rational(2, 3), Rational(1, 6)))
assert pl6.projection_line(Ray(Point(1, 0), Point(1, 1))) == \
Ray3D(Point3D(Rational(14, 3), Rational(11, 3), Rational(11, 3)), Point3D(Rational(13, 3), Rational(13, 3), Rational(10, 3)))
assert pl3.perpendicular_line(r.args) == pl3.perpendicular_line(r)
assert pl3.is_parallel(pl6) is False
assert pl4.is_parallel(pl6)
assert pl3.is_parallel(Line(p1, p2))
assert pl6.is_parallel(l1) is False
assert pl3.is_perpendicular(pl6)
assert pl4.is_perpendicular(pl7)
assert pl6.is_perpendicular(pl7)
assert pl6.is_perpendicular(pl4) is False
assert pl6.is_perpendicular(l1) is False
assert pl6.is_perpendicular(Line((0, 0, 0), (1, 1, 1)))
assert pl6.is_perpendicular((1, 1)) is False
assert pl6.distance(pl6.arbitrary_point(u, v)) == 0
assert pl7.distance(pl7.arbitrary_point(u, v)) == 0
assert pl6.distance(pl6.arbitrary_point(t)) == 0
assert pl7.distance(pl7.arbitrary_point(t)) == 0
assert pl6.p1.distance(pl6.arbitrary_point(t)).simplify() == 1
assert pl7.p1.distance(pl7.arbitrary_point(t)).simplify() == 1
assert pl3.arbitrary_point(t) == Point3D(-sqrt(30)*sin(t)/30 + \
2*sqrt(5)*cos(t)/5, sqrt(30)*sin(t)/15 + sqrt(5)*cos(t)/5, sqrt(30)*sin(t)/6)
assert pl3.arbitrary_point(u, v) == Point3D(2*u - v, u + 2*v, 5*v)
assert pl7.distance(Point3D(1, 3, 5)) == 5*sqrt(6)/6
assert pl6.distance(Point3D(0, 0, 0)) == 4*sqrt(3)
assert pl6.distance(pl6.p1) == 0
assert pl7.distance(pl6) == 0
assert pl7.distance(l1) == 0
assert pl6.distance(Segment3D(Point3D(2, 3, 1), Point3D(1, 3, 4))) == \
pl6.distance(Point3D(1, 3, 4)) == 4*sqrt(3)/3
assert pl6.distance(Segment3D(Point3D(1, 3, 4), Point3D(0, 3, 7))) == \
pl6.distance(Point3D(0, 3, 7)) == 2*sqrt(3)/3
assert pl6.distance(Segment3D(Point3D(0, 3, 7), Point3D(-1, 3, 10))) == 0
assert pl6.distance(Segment3D(Point3D(-1, 3, 10), Point3D(-2, 3, 13))) == 0
assert pl6.distance(Segment3D(Point3D(-2, 3, 13), Point3D(-3, 3, 16))) == \
pl6.distance(Point3D(-2, 3, 13)) == 2*sqrt(3)/3
assert pl6.distance(Plane(Point3D(5, 5, 5), normal_vector=(8, 8, 8))) == sqrt(3)
assert pl6.distance(Ray3D(Point3D(1, 3, 4), direction_ratio=[1, 0, -3])) == 4*sqrt(3)/3
assert pl6.distance(Ray3D(Point3D(2, 3, 1), direction_ratio=[-1, 0, 3])) == 0
assert pl6.angle_between(pl3) == pi/2
assert pl6.angle_between(pl6) == 0
assert pl6.angle_between(pl4) == 0
assert pl7.angle_between(Line3D(Point3D(2, 3, 5), Point3D(2, 4, 6))) == \
-asin(sqrt(3)/6)
assert pl6.angle_between(Ray3D(Point3D(2, 4, 1), Point3D(6, 5, 3))) == \
asin(sqrt(7)/3)
assert pl7.angle_between(Segment3D(Point3D(5, 6, 1), Point3D(1, 2, 4))) == \
asin(7*sqrt(246)/246)
assert are_coplanar(l1, l2, l3) is False
assert are_coplanar(l1) is False
assert are_coplanar(Point3D(2, 7, 2), Point3D(0, 0, 2),
Point3D(1, 1, 2), Point3D(1, 2, 2))
assert are_coplanar(Plane(p1, p2, p3), Plane(p1, p3, p2))
assert Plane.are_concurrent(pl3, pl4, pl5) is False
assert Plane.are_concurrent(pl6) is False
raises(ValueError, lambda: Plane.are_concurrent(Point3D(0, 0, 0)))
raises(ValueError, lambda: Plane((1, 2, 3), normal_vector=(0, 0, 0)))
assert pl3.parallel_plane(Point3D(1, 2, 5)) == Plane(Point3D(1, 2, 5), \
normal_vector=(1, -2, 1))
# perpendicular_plane
p = Plane((0, 0, 0), (1, 0, 0))
# default
assert p.perpendicular_plane() == Plane(Point3D(0, 0, 0), (0, 1, 0))
# 1 pt
assert p.perpendicular_plane(Point3D(1, 0, 1)) == \
Plane(Point3D(1, 0, 1), (0, 1, 0))
# pts as tuples
assert p.perpendicular_plane((1, 0, 1), (1, 1, 1)) == \
Plane(Point3D(1, 0, 1), (0, 0, -1))
# more than two planes
raises(ValueError, lambda: p.perpendicular_plane((1, 0, 1), (1, 1, 1), (1, 1, 0)))
a, b = Point3D(0, 0, 0), Point3D(0, 1, 0)
Z = (0, 0, 1)
p = Plane(a, normal_vector=Z)
# case 4
assert p.perpendicular_plane(a, b) == Plane(a, (1, 0, 0))
n = Point3D(*Z)
# case 1
assert p.perpendicular_plane(a, n) == Plane(a, (-1, 0, 0))
# case 2
assert Plane(a, normal_vector=b.args).perpendicular_plane(a, a + b) == \
Plane(Point3D(0, 0, 0), (1, 0, 0))
# case 1&3
assert Plane(b, normal_vector=Z).perpendicular_plane(b, b + n) == \
Plane(Point3D(0, 1, 0), (-1, 0, 0))
# case 2&3
assert Plane(b, normal_vector=b.args).perpendicular_plane(n, n + b) == \
Plane(Point3D(0, 0, 1), (1, 0, 0))
p = Plane(a, normal_vector=(0, 0, 1))
assert p.perpendicular_plane() == Plane(a, normal_vector=(1, 0, 0))
assert pl6.intersection(pl6) == [pl6]
assert pl4.intersection(pl4.p1) == [pl4.p1]
assert pl3.intersection(pl6) == [
Line3D(Point3D(8, 4, 0), Point3D(2, 4, 6))]
assert pl3.intersection(Line3D(Point3D(1,2,4), Point3D(4,4,2))) == [
Point3D(2, Rational(8, 3), Rational(10, 3))]
assert pl3.intersection(Plane(Point3D(6, 0, 0), normal_vector=(2, -5, 3))
) == [Line3D(Point3D(-24, -12, 0), Point3D(-25, -13, -1))]
assert pl6.intersection(Ray3D(Point3D(2, 3, 1), Point3D(1, 3, 4))) == [
Point3D(-1, 3, 10)]
assert pl6.intersection(Segment3D(Point3D(2, 3, 1), Point3D(1, 3, 4))) == []
assert pl7.intersection(Line(Point(2, 3), Point(4, 2))) == [
Point3D(Rational(13, 2), Rational(3, 4), 0)]
r = Ray(Point(2, 3), Point(4, 2))
assert Plane((1,2,0), normal_vector=(0,0,1)).intersection(r) == [
Ray3D(Point(2, 3), Point(4, 2))]
assert pl9.intersection(pl8) == [Line3D(Point3D(0, 0, 0), Point3D(12, 0, 0))]
assert pl10.intersection(pl11) == [Line3D(Point3D(0, 0, 1), Point3D(0, 2, 1))]
assert pl4.intersection(pl8) == [Line3D(Point3D(0, 0, 0), Point3D(1, -1, 0))]
assert pl11.intersection(pl8) == []
assert pl9.intersection(pl11) == [Line3D(Point3D(0, 0, 1), Point3D(12, 0, 1))]
assert pl9.intersection(pl4) == [Line3D(Point3D(0, 0, 0), Point3D(12, 0, -12))]
assert pl3.random_point() in pl3
assert pl3.random_point(seed=1) in pl3
# test geometrical entity using equals
assert pl4.intersection(pl4.p1)[0].equals(pl4.p1)
assert pl3.intersection(pl6)[0].equals(Line3D(Point3D(8, 4, 0), Point3D(2, 4, 6)))
pl8 = Plane((1, 2, 0), normal_vector=(0, 0, 1))
assert pl8.intersection(Line3D(p1, (1, 12, 0)))[0].equals(Line((0, 0, 0), (0.1, 1.2, 0)))
assert pl8.intersection(Ray3D(p1, (1, 12, 0)))[0].equals(Ray((0, 0, 0), (1, 12, 0)))
assert pl8.intersection(Segment3D(p1, (21, 1, 0)))[0].equals(Segment3D(p1, (21, 1, 0)))
assert pl8.intersection(Plane(p1, normal_vector=(0, 0, 112)))[0].equals(pl8)
assert pl8.intersection(Plane(p1, normal_vector=(0, 12, 0)))[0].equals(
Line3D(p1, direction_ratio=(112 * pi, 0, 0)))
assert pl8.intersection(Plane(p1, normal_vector=(11, 0, 1)))[0].equals(
Line3D(p1, direction_ratio=(0, -11, 0)))
assert pl8.intersection(Plane(p1, normal_vector=(1, 0, 11)))[0].equals(
Line3D(p1, direction_ratio=(0, 11, 0)))
assert pl8.intersection(Plane(p1, normal_vector=(-1, -1, -11)))[0].equals(
Line3D(p1, direction_ratio=(1, -1, 0)))
assert pl3.random_point() in pl3
assert len(pl8.intersection(Ray3D(Point3D(0, 2, 3), Point3D(1, 0, 3)))) == 0
# check if two plane are equals
assert pl6.intersection(pl6)[0].equals(pl6)
assert pl8.equals(Plane(p1, normal_vector=(0, 12, 0))) is False
assert pl8.equals(pl8)
assert pl8.equals(Plane(p1, normal_vector=(0, 0, -12)))
assert pl8.equals(Plane(p1, normal_vector=(0, 0, -12*sqrt(3))))
assert pl8.equals(p1) is False
# issue 8570
l2 = Line3D(Point3D(Rational(50000004459633, 5000000000000),
Rational(-891926590718643, 1000000000000000),
Rational(231800966893633, 100000000000000)),
Point3D(Rational(50000004459633, 50000000000000),
Rational(-222981647679771, 250000000000000),
Rational(231800966893633, 100000000000000)))
p2 = Plane(Point3D(Rational(402775636372767, 100000000000000),
Rational(-97224357654973, 100000000000000),
Rational(216793600814789, 100000000000000)),
(-S('9.00000087501922'), -S('4.81170658872543e-13'),
S('0.0')))
assert str([i.n(2) for i in p2.intersection(l2)]) == \
'[Point3D(4.0, -0.89, 2.3)]'
def test_dimension_normalization():
A = Plane(Point3D(1, 1, 2), normal_vector=(1, 1, 1))
b = Point(1, 1)
assert A.projection(b) == Point(Rational(5, 3), Rational(5, 3), Rational(2, 3))
a, b = Point(0, 0), Point3D(0, 1)
Z = (0, 0, 1)
p = Plane(a, normal_vector=Z)
assert p.perpendicular_plane(a, b) == Plane(Point3D(0, 0, 0), (1, 0, 0))
assert Plane((1, 2, 1), (2, 1, 0), (3, 1, 2)
).intersection((2, 1)) == [Point(2, 1, 0)]
def test_parameter_value():
t, u, v = symbols("t, u v")
p1, p2, p3 = Point(0, 0, 0), Point(0, 0, 1), Point(0, 1, 0)
p = Plane(p1, p2, p3)
assert p.parameter_value((0, -3, 2), t) == {t: asin(2*sqrt(13)/13)}
assert p.parameter_value((0, -3, 2), u, v) == {u: 3, v: 2}
assert p.parameter_value(p1, t) == p1
raises(ValueError, lambda: p.parameter_value((1, 0, 0), t))
raises(ValueError, lambda: p.parameter_value(Line(Point(0, 0), Point(1, 1)), t))
raises(ValueError, lambda: p.parameter_value((0, -3, 2), t, 1))

View File

@ -0,0 +1,481 @@
from sympy.core.basic import Basic
from sympy.core.numbers import (I, Rational, pi)
from sympy.core.parameters import evaluate
from sympy.core.singleton import S
from sympy.core.symbol import Symbol
from sympy.core.sympify import sympify
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.geometry import Line, Point, Point2D, Point3D, Line3D, Plane
from sympy.geometry.entity import rotate, scale, translate, GeometryEntity
from sympy.matrices import Matrix
from sympy.utilities.iterables import subsets, permutations, cartes
from sympy.utilities.misc import Undecidable
from sympy.testing.pytest import raises, warns
def test_point():
x = Symbol('x', real=True)
y = Symbol('y', real=True)
x1 = Symbol('x1', real=True)
x2 = Symbol('x2', real=True)
y1 = Symbol('y1', real=True)
y2 = Symbol('y2', real=True)
half = S.Half
p1 = Point(x1, x2)
p2 = Point(y1, y2)
p3 = Point(0, 0)
p4 = Point(1, 1)
p5 = Point(0, 1)
line = Line(Point(1, 0), slope=1)
assert p1 in p1
assert p1 not in p2
assert p2.y == y2
assert (p3 + p4) == p4
assert (p2 - p1) == Point(y1 - x1, y2 - x2)
assert -p2 == Point(-y1, -y2)
raises(TypeError, lambda: Point(1))
raises(ValueError, lambda: Point([1]))
raises(ValueError, lambda: Point(3, I))
raises(ValueError, lambda: Point(2*I, I))
raises(ValueError, lambda: Point(3 + I, I))
assert Point(34.05, sqrt(3)) == Point(Rational(681, 20), sqrt(3))
assert Point.midpoint(p3, p4) == Point(half, half)
assert Point.midpoint(p1, p4) == Point(half + half*x1, half + half*x2)
assert Point.midpoint(p2, p2) == p2
assert p2.midpoint(p2) == p2
assert p1.origin == Point(0, 0)
assert Point.distance(p3, p4) == sqrt(2)
assert Point.distance(p1, p1) == 0
assert Point.distance(p3, p2) == sqrt(p2.x**2 + p2.y**2)
raises(TypeError, lambda: Point.distance(p1, 0))
raises(TypeError, lambda: Point.distance(p1, GeometryEntity()))
# distance should be symmetric
assert p1.distance(line) == line.distance(p1)
assert p4.distance(line) == line.distance(p4)
assert Point.taxicab_distance(p4, p3) == 2
assert Point.canberra_distance(p4, p5) == 1
raises(ValueError, lambda: Point.canberra_distance(p3, p3))
p1_1 = Point(x1, x1)
p1_2 = Point(y2, y2)
p1_3 = Point(x1 + 1, x1)
assert Point.is_collinear(p3)
with warns(UserWarning, test_stacklevel=False):
assert Point.is_collinear(p3, Point(p3, dim=4))
assert p3.is_collinear()
assert Point.is_collinear(p3, p4)
assert Point.is_collinear(p3, p4, p1_1, p1_2)
assert Point.is_collinear(p3, p4, p1_1, p1_3) is False
assert Point.is_collinear(p3, p3, p4, p5) is False
raises(TypeError, lambda: Point.is_collinear(line))
raises(TypeError, lambda: p1_1.is_collinear(line))
assert p3.intersection(Point(0, 0)) == [p3]
assert p3.intersection(p4) == []
assert p3.intersection(line) == []
with warns(UserWarning, test_stacklevel=False):
assert Point.intersection(Point(0, 0, 0), Point(0, 0)) == [Point(0, 0, 0)]
x_pos = Symbol('x', positive=True)
p2_1 = Point(x_pos, 0)
p2_2 = Point(0, x_pos)
p2_3 = Point(-x_pos, 0)
p2_4 = Point(0, -x_pos)
p2_5 = Point(x_pos, 5)
assert Point.is_concyclic(p2_1)
assert Point.is_concyclic(p2_1, p2_2)
assert Point.is_concyclic(p2_1, p2_2, p2_3, p2_4)
for pts in permutations((p2_1, p2_2, p2_3, p2_5)):
assert Point.is_concyclic(*pts) is False
assert Point.is_concyclic(p4, p4 * 2, p4 * 3) is False
assert Point(0, 0).is_concyclic((1, 1), (2, 2), (2, 1)) is False
assert Point.is_concyclic(Point(0, 0, 0, 0), Point(1, 0, 0, 0), Point(1, 1, 0, 0), Point(1, 1, 1, 0)) is False
assert p1.is_scalar_multiple(p1)
assert p1.is_scalar_multiple(2*p1)
assert not p1.is_scalar_multiple(p2)
assert Point.is_scalar_multiple(Point(1, 1), (-1, -1))
assert Point.is_scalar_multiple(Point(0, 0), (0, -1))
# test when is_scalar_multiple can't be determined
raises(Undecidable, lambda: Point.is_scalar_multiple(Point(sympify("x1%y1"), sympify("x2%y2")), Point(0, 1)))
assert Point(0, 1).orthogonal_direction == Point(1, 0)
assert Point(1, 0).orthogonal_direction == Point(0, 1)
assert p1.is_zero is None
assert p3.is_zero
assert p4.is_zero is False
assert p1.is_nonzero is None
assert p3.is_nonzero is False
assert p4.is_nonzero
assert p4.scale(2, 3) == Point(2, 3)
assert p3.scale(2, 3) == p3
assert p4.rotate(pi, Point(0.5, 0.5)) == p3
assert p1.__radd__(p2) == p1.midpoint(p2).scale(2, 2)
assert (-p3).__rsub__(p4) == p3.midpoint(p4).scale(2, 2)
assert p4 * 5 == Point(5, 5)
assert p4 / 5 == Point(0.2, 0.2)
assert 5 * p4 == Point(5, 5)
raises(ValueError, lambda: Point(0, 0) + 10)
# Point differences should be simplified
assert Point(x*(x - 1), y) - Point(x**2 - x, y + 1) == Point(0, -1)
a, b = S.Half, Rational(1, 3)
assert Point(a, b).evalf(2) == \
Point(a.n(2), b.n(2), evaluate=False)
raises(ValueError, lambda: Point(1, 2) + 1)
# test project
assert Point.project((0, 1), (1, 0)) == Point(0, 0)
assert Point.project((1, 1), (1, 0)) == Point(1, 0)
raises(ValueError, lambda: Point.project(p1, Point(0, 0)))
# test transformations
p = Point(1, 0)
assert p.rotate(pi/2) == Point(0, 1)
assert p.rotate(pi/2, p) == p
p = Point(1, 1)
assert p.scale(2, 3) == Point(2, 3)
assert p.translate(1, 2) == Point(2, 3)
assert p.translate(1) == Point(2, 1)
assert p.translate(y=1) == Point(1, 2)
assert p.translate(*p.args) == Point(2, 2)
# Check invalid input for transform
raises(ValueError, lambda: p3.transform(p3))
raises(ValueError, lambda: p.transform(Matrix([[1, 0], [0, 1]])))
# test __contains__
assert 0 in Point(0, 0, 0, 0)
assert 1 not in Point(0, 0, 0, 0)
# test affine_rank
assert Point.affine_rank() == -1
def test_point3D():
x = Symbol('x', real=True)
y = Symbol('y', real=True)
x1 = Symbol('x1', real=True)
x2 = Symbol('x2', real=True)
x3 = Symbol('x3', real=True)
y1 = Symbol('y1', real=True)
y2 = Symbol('y2', real=True)
y3 = Symbol('y3', real=True)
half = S.Half
p1 = Point3D(x1, x2, x3)
p2 = Point3D(y1, y2, y3)
p3 = Point3D(0, 0, 0)
p4 = Point3D(1, 1, 1)
p5 = Point3D(0, 1, 2)
assert p1 in p1
assert p1 not in p2
assert p2.y == y2
assert (p3 + p4) == p4
assert (p2 - p1) == Point3D(y1 - x1, y2 - x2, y3 - x3)
assert -p2 == Point3D(-y1, -y2, -y3)
assert Point(34.05, sqrt(3)) == Point(Rational(681, 20), sqrt(3))
assert Point3D.midpoint(p3, p4) == Point3D(half, half, half)
assert Point3D.midpoint(p1, p4) == Point3D(half + half*x1, half + half*x2,
half + half*x3)
assert Point3D.midpoint(p2, p2) == p2
assert p2.midpoint(p2) == p2
assert Point3D.distance(p3, p4) == sqrt(3)
assert Point3D.distance(p1, p1) == 0
assert Point3D.distance(p3, p2) == sqrt(p2.x**2 + p2.y**2 + p2.z**2)
p1_1 = Point3D(x1, x1, x1)
p1_2 = Point3D(y2, y2, y2)
p1_3 = Point3D(x1 + 1, x1, x1)
Point3D.are_collinear(p3)
assert Point3D.are_collinear(p3, p4)
assert Point3D.are_collinear(p3, p4, p1_1, p1_2)
assert Point3D.are_collinear(p3, p4, p1_1, p1_3) is False
assert Point3D.are_collinear(p3, p3, p4, p5) is False
assert p3.intersection(Point3D(0, 0, 0)) == [p3]
assert p3.intersection(p4) == []
assert p4 * 5 == Point3D(5, 5, 5)
assert p4 / 5 == Point3D(0.2, 0.2, 0.2)
assert 5 * p4 == Point3D(5, 5, 5)
raises(ValueError, lambda: Point3D(0, 0, 0) + 10)
# Test coordinate properties
assert p1.coordinates == (x1, x2, x3)
assert p2.coordinates == (y1, y2, y3)
assert p3.coordinates == (0, 0, 0)
assert p4.coordinates == (1, 1, 1)
assert p5.coordinates == (0, 1, 2)
assert p5.x == 0
assert p5.y == 1
assert p5.z == 2
# Point differences should be simplified
assert Point3D(x*(x - 1), y, 2) - Point3D(x**2 - x, y + 1, 1) == \
Point3D(0, -1, 1)
a, b, c = S.Half, Rational(1, 3), Rational(1, 4)
assert Point3D(a, b, c).evalf(2) == \
Point(a.n(2), b.n(2), c.n(2), evaluate=False)
raises(ValueError, lambda: Point3D(1, 2, 3) + 1)
# test transformations
p = Point3D(1, 1, 1)
assert p.scale(2, 3) == Point3D(2, 3, 1)
assert p.translate(1, 2) == Point3D(2, 3, 1)
assert p.translate(1) == Point3D(2, 1, 1)
assert p.translate(z=1) == Point3D(1, 1, 2)
assert p.translate(*p.args) == Point3D(2, 2, 2)
# Test __new__
assert Point3D(0.1, 0.2, evaluate=False, on_morph='ignore').args[0].is_Float
# Test length property returns correctly
assert p.length == 0
assert p1_1.length == 0
assert p1_2.length == 0
# Test are_colinear type error
raises(TypeError, lambda: Point3D.are_collinear(p, x))
# Test are_coplanar
assert Point.are_coplanar()
assert Point.are_coplanar((1, 2, 0), (1, 2, 0), (1, 3, 0))
assert Point.are_coplanar((1, 2, 0), (1, 2, 3))
with warns(UserWarning, test_stacklevel=False):
raises(ValueError, lambda: Point2D.are_coplanar((1, 2), (1, 2, 3)))
assert Point3D.are_coplanar((1, 2, 0), (1, 2, 3))
assert Point.are_coplanar((0, 0, 0), (1, 1, 0), (1, 1, 1), (1, 2, 1)) is False
planar2 = Point3D(1, -1, 1)
planar3 = Point3D(-1, 1, 1)
assert Point3D.are_coplanar(p, planar2, planar3) == True
assert Point3D.are_coplanar(p, planar2, planar3, p3) == False
assert Point.are_coplanar(p, planar2)
planar2 = Point3D(1, 1, 2)
planar3 = Point3D(1, 1, 3)
assert Point3D.are_coplanar(p, planar2, planar3) # line, not plane
plane = Plane((1, 2, 1), (2, 1, 0), (3, 1, 2))
assert Point.are_coplanar(*[plane.projection(((-1)**i, i)) for i in range(4)])
# all 2D points are coplanar
assert Point.are_coplanar(Point(x, y), Point(x, x + y), Point(y, x + 2)) is True
# Test Intersection
assert planar2.intersection(Line3D(p, planar3)) == [Point3D(1, 1, 2)]
# Test Scale
assert planar2.scale(1, 1, 1) == planar2
assert planar2.scale(2, 2, 2, planar3) == Point3D(1, 1, 1)
assert planar2.scale(1, 1, 1, p3) == planar2
# Test Transform
identity = Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
assert p.transform(identity) == p
trans = Matrix([[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 1], [0, 0, 0, 1]])
assert p.transform(trans) == Point3D(2, 2, 2)
raises(ValueError, lambda: p.transform(p))
raises(ValueError, lambda: p.transform(Matrix([[1, 0], [0, 1]])))
# Test Equals
assert p.equals(x1) == False
# Test __sub__
p_4d = Point(0, 0, 0, 1)
with warns(UserWarning, test_stacklevel=False):
assert p - p_4d == Point(1, 1, 1, -1)
p_4d3d = Point(0, 0, 1, 0)
with warns(UserWarning, test_stacklevel=False):
assert p - p_4d3d == Point(1, 1, 0, 0)
def test_Point2D():
# Test Distance
p1 = Point2D(1, 5)
p2 = Point2D(4, 2.5)
p3 = (6, 3)
assert p1.distance(p2) == sqrt(61)/2
assert p2.distance(p3) == sqrt(17)/2
# Test coordinates
assert p1.x == 1
assert p1.y == 5
assert p2.x == 4
assert p2.y == S(5)/2
assert p1.coordinates == (1, 5)
assert p2.coordinates == (4, S(5)/2)
# test bounds
assert p1.bounds == (1, 5, 1, 5)
def test_issue_9214():
p1 = Point3D(4, -2, 6)
p2 = Point3D(1, 2, 3)
p3 = Point3D(7, 2, 3)
assert Point3D.are_collinear(p1, p2, p3) is False
def test_issue_11617():
p1 = Point3D(1,0,2)
p2 = Point2D(2,0)
with warns(UserWarning, test_stacklevel=False):
assert p1.distance(p2) == sqrt(5)
def test_transform():
p = Point(1, 1)
assert p.transform(rotate(pi/2)) == Point(-1, 1)
assert p.transform(scale(3, 2)) == Point(3, 2)
assert p.transform(translate(1, 2)) == Point(2, 3)
assert Point(1, 1).scale(2, 3, (4, 5)) == \
Point(-2, -7)
assert Point(1, 1).translate(4, 5) == \
Point(5, 6)
def test_concyclic_doctest_bug():
p1, p2 = Point(-1, 0), Point(1, 0)
p3, p4 = Point(0, 1), Point(-1, 2)
assert Point.is_concyclic(p1, p2, p3)
assert not Point.is_concyclic(p1, p2, p3, p4)
def test_arguments():
"""Functions accepting `Point` objects in `geometry`
should also accept tuples and lists and
automatically convert them to points."""
singles2d = ((1,2), [1,2], Point(1,2))
singles2d2 = ((1,3), [1,3], Point(1,3))
doubles2d = cartes(singles2d, singles2d2)
p2d = Point2D(1,2)
singles3d = ((1,2,3), [1,2,3], Point(1,2,3))
doubles3d = subsets(singles3d, 2)
p3d = Point3D(1,2,3)
singles4d = ((1,2,3,4), [1,2,3,4], Point(1,2,3,4))
doubles4d = subsets(singles4d, 2)
p4d = Point(1,2,3,4)
# test 2D
test_single = ['distance', 'is_scalar_multiple', 'taxicab_distance', 'midpoint', 'intersection', 'dot', 'equals', '__add__', '__sub__']
test_double = ['is_concyclic', 'is_collinear']
for p in singles2d:
Point2D(p)
for func in test_single:
for p in singles2d:
getattr(p2d, func)(p)
for func in test_double:
for p in doubles2d:
getattr(p2d, func)(*p)
# test 3D
test_double = ['is_collinear']
for p in singles3d:
Point3D(p)
for func in test_single:
for p in singles3d:
getattr(p3d, func)(p)
for func in test_double:
for p in doubles3d:
getattr(p3d, func)(*p)
# test 4D
test_double = ['is_collinear']
for p in singles4d:
Point(p)
for func in test_single:
for p in singles4d:
getattr(p4d, func)(p)
for func in test_double:
for p in doubles4d:
getattr(p4d, func)(*p)
# test evaluate=False for ops
x = Symbol('x')
a = Point(0, 1)
assert a + (0.1, x) == Point(0.1, 1 + x, evaluate=False)
a = Point(0, 1)
assert a/10.0 == Point(0, 0.1, evaluate=False)
a = Point(0, 1)
assert a*10.0 == Point(0.0, 10.0, evaluate=False)
# test evaluate=False when changing dimensions
u = Point(.1, .2, evaluate=False)
u4 = Point(u, dim=4, on_morph='ignore')
assert u4.args == (.1, .2, 0, 0)
assert all(i.is_Float for i in u4.args[:2])
# and even when *not* changing dimensions
assert all(i.is_Float for i in Point(u).args)
# never raise error if creating an origin
assert Point(dim=3, on_morph='error')
# raise error with unmatched dimension
raises(ValueError, lambda: Point(1, 1, dim=3, on_morph='error'))
# test unknown on_morph
raises(ValueError, lambda: Point(1, 1, dim=3, on_morph='unknown'))
# test invalid expressions
raises(TypeError, lambda: Point(Basic(), Basic()))
def test_unit():
assert Point(1, 1).unit == Point(sqrt(2)/2, sqrt(2)/2)
def test_dot():
raises(TypeError, lambda: Point(1, 2).dot(Line((0, 0), (1, 1))))
def test__normalize_dimension():
assert Point._normalize_dimension(Point(1, 2), Point(3, 4)) == [
Point(1, 2), Point(3, 4)]
assert Point._normalize_dimension(
Point(1, 2), Point(3, 4, 0), on_morph='ignore') == [
Point(1, 2, 0), Point(3, 4, 0)]
def test_issue_22684():
# Used to give an error
with evaluate(False):
Point(1, 2)
def test_direction_cosine():
p1 = Point3D(0, 0, 0)
p2 = Point3D(1, 1, 1)
assert p1.direction_cosine(Point3D(1, 0, 0)) == [1, 0, 0]
assert p1.direction_cosine(Point3D(0, 1, 0)) == [0, 1, 0]
assert p1.direction_cosine(Point3D(0, 0, pi)) == [0, 0, 1]
assert p1.direction_cosine(Point3D(5, 0, 0)) == [1, 0, 0]
assert p1.direction_cosine(Point3D(0, sqrt(3), 0)) == [0, 1, 0]
assert p1.direction_cosine(Point3D(0, 0, 5)) == [0, 0, 1]
assert p1.direction_cosine(Point3D(2.4, 2.4, 0)) == [sqrt(2)/2, sqrt(2)/2, 0]
assert p1.direction_cosine(Point3D(1, 1, 1)) == [sqrt(3) / 3, sqrt(3) / 3, sqrt(3) / 3]
assert p1.direction_cosine(Point3D(-12, 0 -15)) == [-4*sqrt(41)/41, -5*sqrt(41)/41, 0]
assert p2.direction_cosine(Point3D(0, 0, 0)) == [-sqrt(3) / 3, -sqrt(3) / 3, -sqrt(3) / 3]
assert p2.direction_cosine(Point3D(1, 1, 12)) == [0, 0, 1]
assert p2.direction_cosine(Point3D(12, 1, 12)) == [sqrt(2) / 2, 0, sqrt(2) / 2]

View File

@ -0,0 +1,676 @@
from sympy.core.numbers import (Float, Rational, oo, pi)
from sympy.core.singleton import S
from sympy.core.symbol import (Symbol, symbols)
from sympy.functions.elementary.complexes import Abs
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import (acos, cos, sin)
from sympy.functions.elementary.trigonometric import tan
from sympy.geometry import (Circle, Ellipse, GeometryError, Point, Point2D,
Polygon, Ray, RegularPolygon, Segment, Triangle,
are_similar, convex_hull, intersection, Line, Ray2D)
from sympy.testing.pytest import raises, slow, warns
from sympy.core.random import verify_numerically
from sympy.geometry.polygon import rad, deg
from sympy.integrals.integrals import integrate
from sympy.utilities.iterables import rotate_left
def feq(a, b):
"""Test if two floating point values are 'equal'."""
t_float = Float("1.0E-10")
return -t_float < a - b < t_float
@slow
def test_polygon():
x = Symbol('x', real=True)
y = Symbol('y', real=True)
q = Symbol('q', real=True)
u = Symbol('u', real=True)
v = Symbol('v', real=True)
w = Symbol('w', real=True)
x1 = Symbol('x1', real=True)
half = S.Half
a, b, c = Point(0, 0), Point(2, 0), Point(3, 3)
t = Triangle(a, b, c)
assert Polygon(Point(0, 0)) == Point(0, 0)
assert Polygon(a, Point(1, 0), b, c) == t
assert Polygon(Point(1, 0), b, c, a) == t
assert Polygon(b, c, a, Point(1, 0)) == t
# 2 "remove folded" tests
assert Polygon(a, Point(3, 0), b, c) == t
assert Polygon(a, b, Point(3, -1), b, c) == t
# remove multiple collinear points
assert Polygon(Point(-4, 15), Point(-11, 15), Point(-15, 15),
Point(-15, 33/5), Point(-15, -87/10), Point(-15, -15),
Point(-42/5, -15), Point(-2, -15), Point(7, -15), Point(15, -15),
Point(15, -3), Point(15, 10), Point(15, 15)) == \
Polygon(Point(-15, -15), Point(15, -15), Point(15, 15), Point(-15, 15))
p1 = Polygon(
Point(0, 0), Point(3, -1),
Point(6, 0), Point(4, 5),
Point(2, 3), Point(0, 3))
p2 = Polygon(
Point(6, 0), Point(3, -1),
Point(0, 0), Point(0, 3),
Point(2, 3), Point(4, 5))
p3 = Polygon(
Point(0, 0), Point(3, 0),
Point(5, 2), Point(4, 4))
p4 = Polygon(
Point(0, 0), Point(4, 4),
Point(5, 2), Point(3, 0))
p5 = Polygon(
Point(0, 0), Point(4, 4),
Point(0, 4))
p6 = Polygon(
Point(-11, 1), Point(-9, 6.6),
Point(-4, -3), Point(-8.4, -8.7))
p7 = Polygon(
Point(x, y), Point(q, u),
Point(v, w))
p8 = Polygon(
Point(x, y), Point(v, w),
Point(q, u))
p9 = Polygon(
Point(0, 0), Point(4, 4),
Point(3, 0), Point(5, 2))
p10 = Polygon(
Point(0, 2), Point(2, 2),
Point(0, 0), Point(2, 0))
p11 = Polygon(Point(0, 0), 1, n=3)
p12 = Polygon(Point(0, 0), 1, 0, n=3)
p13 = Polygon(
Point(0, 0),Point(8, 8),
Point(23, 20),Point(0, 20))
p14 = Polygon(*rotate_left(p13.args, 1))
r = Ray(Point(-9, 6.6), Point(-9, 5.5))
#
# General polygon
#
assert p1 == p2
assert len(p1.args) == 6
assert len(p1.sides) == 6
assert p1.perimeter == 5 + 2*sqrt(10) + sqrt(29) + sqrt(8)
assert p1.area == 22
assert not p1.is_convex()
assert Polygon((-1, 1), (2, -1), (2, 1), (-1, -1), (3, 0)
).is_convex() is False
# ensure convex for both CW and CCW point specification
assert p3.is_convex()
assert p4.is_convex()
dict5 = p5.angles
assert dict5[Point(0, 0)] == pi / 4
assert dict5[Point(0, 4)] == pi / 2
assert p5.encloses_point(Point(x, y)) is None
assert p5.encloses_point(Point(1, 3))
assert p5.encloses_point(Point(0, 0)) is False
assert p5.encloses_point(Point(4, 0)) is False
assert p1.encloses(Circle(Point(2.5, 2.5), 5)) is False
assert p1.encloses(Ellipse(Point(2.5, 2), 5, 6)) is False
assert p5.plot_interval('x') == [x, 0, 1]
assert p5.distance(
Polygon(Point(10, 10), Point(14, 14), Point(10, 14))) == 6 * sqrt(2)
assert p5.distance(
Polygon(Point(1, 8), Point(5, 8), Point(8, 12), Point(1, 12))) == 4
with warns(UserWarning, \
match="Polygons may intersect producing erroneous output"):
Polygon(Point(0, 0), Point(1, 0), Point(1, 1)).distance(
Polygon(Point(0, 0), Point(0, 1), Point(1, 1)))
assert hash(p5) == hash(Polygon(Point(0, 0), Point(4, 4), Point(0, 4)))
assert hash(p1) == hash(p2)
assert hash(p7) == hash(p8)
assert hash(p3) != hash(p9)
assert p5 == Polygon(Point(4, 4), Point(0, 4), Point(0, 0))
assert Polygon(Point(4, 4), Point(0, 4), Point(0, 0)) in p5
assert p5 != Point(0, 4)
assert Point(0, 1) in p5
assert p5.arbitrary_point('t').subs(Symbol('t', real=True), 0) == \
Point(0, 0)
raises(ValueError, lambda: Polygon(
Point(x, 0), Point(0, y), Point(x, y)).arbitrary_point('x'))
assert p6.intersection(r) == [Point(-9, Rational(-84, 13)), Point(-9, Rational(33, 5))]
assert p10.area == 0
assert p11 == RegularPolygon(Point(0, 0), 1, 3, 0)
assert p11 == p12
assert p11.vertices[0] == Point(1, 0)
assert p11.args[0] == Point(0, 0)
p11.spin(pi/2)
assert p11.vertices[0] == Point(0, 1)
#
# Regular polygon
#
p1 = RegularPolygon(Point(0, 0), 10, 5)
p2 = RegularPolygon(Point(0, 0), 5, 5)
raises(GeometryError, lambda: RegularPolygon(Point(0, 0), Point(0,
1), Point(1, 1)))
raises(GeometryError, lambda: RegularPolygon(Point(0, 0), 1, 2))
raises(ValueError, lambda: RegularPolygon(Point(0, 0), 1, 2.5))
assert p1 != p2
assert p1.interior_angle == pi*Rational(3, 5)
assert p1.exterior_angle == pi*Rational(2, 5)
assert p2.apothem == 5*cos(pi/5)
assert p2.circumcenter == p1.circumcenter == Point(0, 0)
assert p1.circumradius == p1.radius == 10
assert p2.circumcircle == Circle(Point(0, 0), 5)
assert p2.incircle == Circle(Point(0, 0), p2.apothem)
assert p2.inradius == p2.apothem == (5 * (1 + sqrt(5)) / 4)
p2.spin(pi / 10)
dict1 = p2.angles
assert dict1[Point(0, 5)] == 3 * pi / 5
assert p1.is_convex()
assert p1.rotation == 0
assert p1.encloses_point(Point(0, 0))
assert p1.encloses_point(Point(11, 0)) is False
assert p2.encloses_point(Point(0, 4.9))
p1.spin(pi/3)
assert p1.rotation == pi/3
assert p1.vertices[0] == Point(5, 5*sqrt(3))
for var in p1.args:
if isinstance(var, Point):
assert var == Point(0, 0)
else:
assert var in (5, 10, pi / 3)
assert p1 != Point(0, 0)
assert p1 != p5
# while spin works in place (notice that rotation is 2pi/3 below)
# rotate returns a new object
p1_old = p1
assert p1.rotate(pi/3) == RegularPolygon(Point(0, 0), 10, 5, pi*Rational(2, 3))
assert p1 == p1_old
assert p1.area == (-250*sqrt(5) + 1250)/(4*tan(pi/5))
assert p1.length == 20*sqrt(-sqrt(5)/8 + Rational(5, 8))
assert p1.scale(2, 2) == \
RegularPolygon(p1.center, p1.radius*2, p1._n, p1.rotation)
assert RegularPolygon((0, 0), 1, 4).scale(2, 3) == \
Polygon(Point(2, 0), Point(0, 3), Point(-2, 0), Point(0, -3))
assert repr(p1) == str(p1)
#
# Angles
#
angles = p4.angles
assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483"))
assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544"))
assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388"))
assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449"))
angles = p3.angles
assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483"))
assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544"))
assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388"))
assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449"))
# https://github.com/sympy/sympy/issues/24885
interior_angles_sum = sum(p13.angles.values())
assert feq(interior_angles_sum, (len(p13.angles) - 2)*pi )
interior_angles_sum = sum(p14.angles.values())
assert feq(interior_angles_sum, (len(p14.angles) - 2)*pi )
#
# Triangle
#
p1 = Point(0, 0)
p2 = Point(5, 0)
p3 = Point(0, 5)
t1 = Triangle(p1, p2, p3)
t2 = Triangle(p1, p2, Point(Rational(5, 2), sqrt(Rational(75, 4))))
t3 = Triangle(p1, Point(x1, 0), Point(0, x1))
s1 = t1.sides
assert Triangle(p1, p2, p1) == Polygon(p1, p2, p1) == Segment(p1, p2)
raises(GeometryError, lambda: Triangle(Point(0, 0)))
# Basic stuff
assert Triangle(p1, p1, p1) == p1
assert Triangle(p2, p2*2, p2*3) == Segment(p2, p2*3)
assert t1.area == Rational(25, 2)
assert t1.is_right()
assert t2.is_right() is False
assert t3.is_right()
assert p1 in t1
assert t1.sides[0] in t1
assert Segment((0, 0), (1, 0)) in t1
assert Point(5, 5) not in t2
assert t1.is_convex()
assert feq(t1.angles[p1].evalf(), pi.evalf()/2)
assert t1.is_equilateral() is False
assert t2.is_equilateral()
assert t3.is_equilateral() is False
assert are_similar(t1, t2) is False
assert are_similar(t1, t3)
assert are_similar(t2, t3) is False
assert t1.is_similar(Point(0, 0)) is False
assert t1.is_similar(t2) is False
# Bisectors
bisectors = t1.bisectors()
assert bisectors[p1] == Segment(
p1, Point(Rational(5, 2), Rational(5, 2)))
assert t2.bisectors()[p2] == Segment(
Point(5, 0), Point(Rational(5, 4), 5*sqrt(3)/4))
p4 = Point(0, x1)
assert t3.bisectors()[p4] == Segment(p4, Point(x1*(sqrt(2) - 1), 0))
ic = (250 - 125*sqrt(2))/50
assert t1.incenter == Point(ic, ic)
# Inradius
assert t1.inradius == t1.incircle.radius == 5 - 5*sqrt(2)/2
assert t2.inradius == t2.incircle.radius == 5*sqrt(3)/6
assert t3.inradius == t3.incircle.radius == x1**2/((2 + sqrt(2))*Abs(x1))
# Exradius
assert t1.exradii[t1.sides[2]] == 5*sqrt(2)/2
# Excenters
assert t1.excenters[t1.sides[2]] == Point2D(25*sqrt(2), -5*sqrt(2)/2)
# Circumcircle
assert t1.circumcircle.center == Point(2.5, 2.5)
# Medians + Centroid
m = t1.medians
assert t1.centroid == Point(Rational(5, 3), Rational(5, 3))
assert m[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2)))
assert t3.medians[p1] == Segment(p1, Point(x1/2, x1/2))
assert intersection(m[p1], m[p2], m[p3]) == [t1.centroid]
assert t1.medial == Triangle(Point(2.5, 0), Point(0, 2.5), Point(2.5, 2.5))
# Nine-point circle
assert t1.nine_point_circle == Circle(Point(2.5, 0),
Point(0, 2.5), Point(2.5, 2.5))
assert t1.nine_point_circle == Circle(Point(0, 0),
Point(0, 2.5), Point(2.5, 2.5))
# Perpendicular
altitudes = t1.altitudes
assert altitudes[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2)))
assert altitudes[p2].equals(s1[0])
assert altitudes[p3] == s1[2]
assert t1.orthocenter == p1
t = S('''Triangle(
Point(100080156402737/5000000000000, 79782624633431/500000000000),
Point(39223884078253/2000000000000, 156345163124289/1000000000000),
Point(31241359188437/1250000000000, 338338270939941/1000000000000000))''')
assert t.orthocenter == S('''Point(-780660869050599840216997'''
'''79471538701955848721853/80368430960602242240789074233100000000000000,'''
'''20151573611150265741278060334545897615974257/16073686192120448448157'''
'''8148466200000000000)''')
# Ensure
assert len(intersection(*bisectors.values())) == 1
assert len(intersection(*altitudes.values())) == 1
assert len(intersection(*m.values())) == 1
# Distance
p1 = Polygon(
Point(0, 0), Point(1, 0),
Point(1, 1), Point(0, 1))
p2 = Polygon(
Point(0, Rational(5)/4), Point(1, Rational(5)/4),
Point(1, Rational(9)/4), Point(0, Rational(9)/4))
p3 = Polygon(
Point(1, 2), Point(2, 2),
Point(2, 1))
p4 = Polygon(
Point(1, 1), Point(Rational(6)/5, 1),
Point(1, Rational(6)/5))
pt1 = Point(half, half)
pt2 = Point(1, 1)
'''Polygon to Point'''
assert p1.distance(pt1) == half
assert p1.distance(pt2) == 0
assert p2.distance(pt1) == Rational(3)/4
assert p3.distance(pt2) == sqrt(2)/2
'''Polygon to Polygon'''
# p1.distance(p2) emits a warning
with warns(UserWarning, \
match="Polygons may intersect producing erroneous output"):
assert p1.distance(p2) == half/2
assert p1.distance(p3) == sqrt(2)/2
# p3.distance(p4) emits a warning
with warns(UserWarning, \
match="Polygons may intersect producing erroneous output"):
assert p3.distance(p4) == (sqrt(2)/2 - sqrt(Rational(2)/25)/2)
def test_convex_hull():
p = [Point(-5, -1), Point(-2, 1), Point(-2, -1), Point(-1, -3), \
Point(0, 0), Point(1, 1), Point(2, 2), Point(2, -1), Point(3, 1), \
Point(4, -1), Point(6, 2)]
ch = Polygon(p[0], p[3], p[9], p[10], p[6], p[1])
#test handling of duplicate points
p.append(p[3])
#more than 3 collinear points
another_p = [Point(-45, -85), Point(-45, 85), Point(-45, 26), \
Point(-45, -24)]
ch2 = Segment(another_p[0], another_p[1])
assert convex_hull(*another_p) == ch2
assert convex_hull(*p) == ch
assert convex_hull(p[0]) == p[0]
assert convex_hull(p[0], p[1]) == Segment(p[0], p[1])
# no unique points
assert convex_hull(*[p[-1]]*3) == p[-1]
# collection of items
assert convex_hull(*[Point(0, 0), \
Segment(Point(1, 0), Point(1, 1)), \
RegularPolygon(Point(2, 0), 2, 4)]) == \
Polygon(Point(0, 0), Point(2, -2), Point(4, 0), Point(2, 2))
def test_encloses():
# square with a dimpled left side
s = Polygon(Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1), \
Point(S.Half, S.Half))
# the following is True if the polygon isn't treated as closing on itself
assert s.encloses(Point(0, S.Half)) is False
assert s.encloses(Point(S.Half, S.Half)) is False # it's a vertex
assert s.encloses(Point(Rational(3, 4), S.Half)) is True
def test_triangle_kwargs():
assert Triangle(sss=(3, 4, 5)) == \
Triangle(Point(0, 0), Point(3, 0), Point(3, 4))
assert Triangle(asa=(30, 2, 30)) == \
Triangle(Point(0, 0), Point(2, 0), Point(1, sqrt(3)/3))
assert Triangle(sas=(1, 45, 2)) == \
Triangle(Point(0, 0), Point(2, 0), Point(sqrt(2)/2, sqrt(2)/2))
assert Triangle(sss=(1, 2, 5)) is None
assert deg(rad(180)) == 180
def test_transform():
pts = [Point(0, 0), Point(S.Half, Rational(1, 4)), Point(1, 1)]
pts_out = [Point(-4, -10), Point(-3, Rational(-37, 4)), Point(-2, -7)]
assert Triangle(*pts).scale(2, 3, (4, 5)) == Triangle(*pts_out)
assert RegularPolygon((0, 0), 1, 4).scale(2, 3, (4, 5)) == \
Polygon(Point(-2, -10), Point(-4, -7), Point(-6, -10), Point(-4, -13))
# Checks for symmetric scaling
assert RegularPolygon((0, 0), 1, 4).scale(2, 2) == \
RegularPolygon(Point2D(0, 0), 2, 4, 0)
def test_reflect():
x = Symbol('x', real=True)
y = Symbol('y', real=True)
b = Symbol('b')
m = Symbol('m')
l = Line((0, b), slope=m)
p = Point(x, y)
r = p.reflect(l)
dp = l.perpendicular_segment(p).length
dr = l.perpendicular_segment(r).length
assert verify_numerically(dp, dr)
assert Polygon((1, 0), (2, 0), (2, 2)).reflect(Line((3, 0), slope=oo)) \
== Triangle(Point(5, 0), Point(4, 0), Point(4, 2))
assert Polygon((1, 0), (2, 0), (2, 2)).reflect(Line((0, 3), slope=oo)) \
== Triangle(Point(-1, 0), Point(-2, 0), Point(-2, 2))
assert Polygon((1, 0), (2, 0), (2, 2)).reflect(Line((0, 3), slope=0)) \
== Triangle(Point(1, 6), Point(2, 6), Point(2, 4))
assert Polygon((1, 0), (2, 0), (2, 2)).reflect(Line((3, 0), slope=0)) \
== Triangle(Point(1, 0), Point(2, 0), Point(2, -2))
def test_bisectors():
p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1)
p = Polygon(Point(0, 0), Point(2, 0), Point(1, 1), Point(0, 3))
q = Polygon(Point(1, 0), Point(2, 0), Point(3, 3), Point(-1, 5))
poly = Polygon(Point(3, 4), Point(0, 0), Point(8, 7), Point(-1, 1), Point(19, -19))
t = Triangle(p1, p2, p3)
assert t.bisectors()[p2] == Segment(Point(1, 0), Point(0, sqrt(2) - 1))
assert p.bisectors()[Point2D(0, 3)] == Ray2D(Point2D(0, 3), \
Point2D(sin(acos(2*sqrt(5)/5)/2), 3 - cos(acos(2*sqrt(5)/5)/2)))
assert q.bisectors()[Point2D(-1, 5)] == \
Ray2D(Point2D(-1, 5), Point2D(-1 + sqrt(29)*(5*sin(acos(9*sqrt(145)/145)/2) + \
2*cos(acos(9*sqrt(145)/145)/2))/29, sqrt(29)*(-5*cos(acos(9*sqrt(145)/145)/2) + \
2*sin(acos(9*sqrt(145)/145)/2))/29 + 5))
assert poly.bisectors()[Point2D(-1, 1)] == Ray2D(Point2D(-1, 1), \
Point2D(-1 + sin(acos(sqrt(26)/26)/2 + pi/4), 1 - sin(-acos(sqrt(26)/26)/2 + pi/4)))
def test_incenter():
assert Triangle(Point(0, 0), Point(1, 0), Point(0, 1)).incenter \
== Point(1 - sqrt(2)/2, 1 - sqrt(2)/2)
def test_inradius():
assert Triangle(Point(0, 0), Point(4, 0), Point(0, 3)).inradius == 1
def test_incircle():
assert Triangle(Point(0, 0), Point(2, 0), Point(0, 2)).incircle \
== Circle(Point(2 - sqrt(2), 2 - sqrt(2)), 2 - sqrt(2))
def test_exradii():
t = Triangle(Point(0, 0), Point(6, 0), Point(0, 2))
assert t.exradii[t.sides[2]] == (-2 + sqrt(10))
def test_medians():
t = Triangle(Point(0, 0), Point(1, 0), Point(0, 1))
assert t.medians[Point(0, 0)] == Segment(Point(0, 0), Point(S.Half, S.Half))
def test_medial():
assert Triangle(Point(0, 0), Point(1, 0), Point(0, 1)).medial \
== Triangle(Point(S.Half, 0), Point(S.Half, S.Half), Point(0, S.Half))
def test_nine_point_circle():
assert Triangle(Point(0, 0), Point(1, 0), Point(0, 1)).nine_point_circle \
== Circle(Point2D(Rational(1, 4), Rational(1, 4)), sqrt(2)/4)
def test_eulerline():
assert Triangle(Point(0, 0), Point(1, 0), Point(0, 1)).eulerline \
== Line(Point2D(0, 0), Point2D(S.Half, S.Half))
assert Triangle(Point(0, 0), Point(10, 0), Point(5, 5*sqrt(3))).eulerline \
== Point2D(5, 5*sqrt(3)/3)
assert Triangle(Point(4, -6), Point(4, -1), Point(-3, 3)).eulerline \
== Line(Point2D(Rational(64, 7), 3), Point2D(Rational(-29, 14), Rational(-7, 2)))
def test_intersection():
poly1 = Triangle(Point(0, 0), Point(1, 0), Point(0, 1))
poly2 = Polygon(Point(0, 1), Point(-5, 0),
Point(0, -4), Point(0, Rational(1, 5)),
Point(S.Half, -0.1), Point(1, 0), Point(0, 1))
assert poly1.intersection(poly2) == [Point2D(Rational(1, 3), 0),
Segment(Point(0, Rational(1, 5)), Point(0, 0)),
Segment(Point(1, 0), Point(0, 1))]
assert poly2.intersection(poly1) == [Point(Rational(1, 3), 0),
Segment(Point(0, 0), Point(0, Rational(1, 5))),
Segment(Point(1, 0), Point(0, 1))]
assert poly1.intersection(Point(0, 0)) == [Point(0, 0)]
assert poly1.intersection(Point(-12, -43)) == []
assert poly2.intersection(Line((-12, 0), (12, 0))) == [Point(-5, 0),
Point(0, 0), Point(Rational(1, 3), 0), Point(1, 0)]
assert poly2.intersection(Line((-12, 12), (12, 12))) == []
assert poly2.intersection(Ray((-3, 4), (1, 0))) == [Segment(Point(1, 0),
Point(0, 1))]
assert poly2.intersection(Circle((0, -1), 1)) == [Point(0, -2),
Point(0, 0)]
assert poly1.intersection(poly1) == [Segment(Point(0, 0), Point(1, 0)),
Segment(Point(0, 1), Point(0, 0)), Segment(Point(1, 0), Point(0, 1))]
assert poly2.intersection(poly2) == [Segment(Point(-5, 0), Point(0, -4)),
Segment(Point(0, -4), Point(0, Rational(1, 5))),
Segment(Point(0, Rational(1, 5)), Point(S.Half, Rational(-1, 10))),
Segment(Point(0, 1), Point(-5, 0)),
Segment(Point(S.Half, Rational(-1, 10)), Point(1, 0)),
Segment(Point(1, 0), Point(0, 1))]
assert poly2.intersection(Triangle(Point(0, 1), Point(1, 0), Point(-1, 1))) \
== [Point(Rational(-5, 7), Rational(6, 7)), Segment(Point2D(0, 1), Point(1, 0))]
assert poly1.intersection(RegularPolygon((-12, -15), 3, 3)) == []
def test_parameter_value():
t = Symbol('t')
sq = Polygon((0, 0), (0, 1), (1, 1), (1, 0))
assert sq.parameter_value((0.5, 1), t) == {t: Rational(3, 8)}
q = Polygon((0, 0), (2, 1), (2, 4), (4, 0))
assert q.parameter_value((4, 0), t) == {t: -6 + 3*sqrt(5)} # ~= 0.708
raises(ValueError, lambda: sq.parameter_value((5, 6), t))
raises(ValueError, lambda: sq.parameter_value(Circle(Point(0, 0), 1), t))
def test_issue_12966():
poly = Polygon(Point(0, 0), Point(0, 10), Point(5, 10), Point(5, 5),
Point(10, 5), Point(10, 0))
t = Symbol('t')
pt = poly.arbitrary_point(t)
DELTA = 5/poly.perimeter
assert [pt.subs(t, DELTA*i) for i in range(int(1/DELTA))] == [
Point(0, 0), Point(0, 5), Point(0, 10), Point(5, 10),
Point(5, 5), Point(10, 5), Point(10, 0), Point(5, 0)]
def test_second_moment_of_area():
x, y = symbols('x, y')
# triangle
p1, p2, p3 = [(0, 0), (4, 0), (0, 2)]
p = (0, 0)
# equation of hypotenuse
eq_y = (1-x/4)*2
I_yy = integrate((x**2) * (integrate(1, (y, 0, eq_y))), (x, 0, 4))
I_xx = integrate(1 * (integrate(y**2, (y, 0, eq_y))), (x, 0, 4))
I_xy = integrate(x * (integrate(y, (y, 0, eq_y))), (x, 0, 4))
triangle = Polygon(p1, p2, p3)
assert (I_xx - triangle.second_moment_of_area(p)[0]) == 0
assert (I_yy - triangle.second_moment_of_area(p)[1]) == 0
assert (I_xy - triangle.second_moment_of_area(p)[2]) == 0
# rectangle
p1, p2, p3, p4=[(0, 0), (4, 0), (4, 2), (0, 2)]
I_yy = integrate((x**2) * integrate(1, (y, 0, 2)), (x, 0, 4))
I_xx = integrate(1 * integrate(y**2, (y, 0, 2)), (x, 0, 4))
I_xy = integrate(x * integrate(y, (y, 0, 2)), (x, 0, 4))
rectangle = Polygon(p1, p2, p3, p4)
assert (I_xx - rectangle.second_moment_of_area(p)[0]) == 0
assert (I_yy - rectangle.second_moment_of_area(p)[1]) == 0
assert (I_xy - rectangle.second_moment_of_area(p)[2]) == 0
r = RegularPolygon(Point(0, 0), 5, 3)
assert r.second_moment_of_area() == (1875*sqrt(3)/S(32), 1875*sqrt(3)/S(32), 0)
def test_first_moment():
a, b = symbols('a, b', positive=True)
# rectangle
p1 = Polygon((0, 0), (a, 0), (a, b), (0, b))
assert p1.first_moment_of_area() == (a*b**2/8, a**2*b/8)
assert p1.first_moment_of_area((a/3, b/4)) == (-3*a*b**2/32, -a**2*b/9)
p1 = Polygon((0, 0), (40, 0), (40, 30), (0, 30))
assert p1.first_moment_of_area() == (4500, 6000)
# triangle
p2 = Polygon((0, 0), (a, 0), (a/2, b))
assert p2.first_moment_of_area() == (4*a*b**2/81, a**2*b/24)
assert p2.first_moment_of_area((a/8, b/6)) == (-25*a*b**2/648, -5*a**2*b/768)
p2 = Polygon((0, 0), (12, 0), (12, 30))
assert p2.first_moment_of_area() == (S(1600)/3, -S(640)/3)
def test_section_modulus_and_polar_second_moment_of_area():
a, b = symbols('a, b', positive=True)
x, y = symbols('x, y')
rectangle = Polygon((0, b), (0, 0), (a, 0), (a, b))
assert rectangle.section_modulus(Point(x, y)) == (a*b**3/12/(-b/2 + y), a**3*b/12/(-a/2 + x))
assert rectangle.polar_second_moment_of_area() == a**3*b/12 + a*b**3/12
convex = RegularPolygon((0, 0), 1, 6)
assert convex.section_modulus() == (Rational(5, 8), sqrt(3)*Rational(5, 16))
assert convex.polar_second_moment_of_area() == 5*sqrt(3)/S(8)
concave = Polygon((0, 0), (1, 8), (3, 4), (4, 6), (7, 1))
assert concave.section_modulus() == (Rational(-6371, 429), Rational(-9778, 519))
assert concave.polar_second_moment_of_area() == Rational(-38669, 252)
def test_cut_section():
# concave polygon
p = Polygon((-1, -1), (1, Rational(5, 2)), (2, 1), (3, Rational(5, 2)), (4, 2), (5, 3), (-1, 3))
l = Line((0, 0), (Rational(9, 2), 3))
p1 = p.cut_section(l)[0]
p2 = p.cut_section(l)[1]
assert p1 == Polygon(
Point2D(Rational(-9, 13), Rational(-6, 13)), Point2D(1, Rational(5, 2)), Point2D(Rational(24, 13), Rational(16, 13)),
Point2D(Rational(12, 5), Rational(8, 5)), Point2D(3, Rational(5, 2)), Point2D(Rational(24, 7), Rational(16, 7)),
Point2D(Rational(9, 2), 3), Point2D(-1, 3), Point2D(-1, Rational(-2, 3)))
assert p2 == Polygon(Point2D(-1, -1), Point2D(Rational(-9, 13), Rational(-6, 13)), Point2D(Rational(24, 13), Rational(16, 13)),
Point2D(2, 1), Point2D(Rational(12, 5), Rational(8, 5)), Point2D(Rational(24, 7), Rational(16, 7)), Point2D(4, 2), Point2D(5, 3),
Point2D(Rational(9, 2), 3), Point2D(-1, Rational(-2, 3)))
# convex polygon
p = RegularPolygon(Point2D(0, 0), 6, 6)
s = p.cut_section(Line((0, 0), slope=1))
assert s[0] == Polygon(Point2D(-3*sqrt(3) + 9, -3*sqrt(3) + 9), Point2D(3, 3*sqrt(3)),
Point2D(-3, 3*sqrt(3)), Point2D(-6, 0), Point2D(-9 + 3*sqrt(3), -9 + 3*sqrt(3)))
assert s[1] == Polygon(Point2D(6, 0), Point2D(-3*sqrt(3) + 9, -3*sqrt(3) + 9),
Point2D(-9 + 3*sqrt(3), -9 + 3*sqrt(3)), Point2D(-3, -3*sqrt(3)), Point2D(3, -3*sqrt(3)))
# case where line does not intersects but coincides with the edge of polygon
a, b = 20, 10
t1, t2, t3, t4 = [(0, b), (0, 0), (a, 0), (a, b)]
p = Polygon(t1, t2, t3, t4)
p1, p2 = p.cut_section(Line((0, b), slope=0))
assert p1 == None
assert p2 == Polygon(Point2D(0, 10), Point2D(0, 0), Point2D(20, 0), Point2D(20, 10))
p3, p4 = p.cut_section(Line((0, 0), slope=0))
assert p3 == Polygon(Point2D(0, 10), Point2D(0, 0), Point2D(20, 0), Point2D(20, 10))
assert p4 == None
# case where the line does not intersect with a polygon at all
raises(ValueError, lambda: p.cut_section(Line((0, a), slope=0)))
def test_type_of_triangle():
# Isoceles triangle
p1 = Polygon(Point(0, 0), Point(5, 0), Point(2, 4))
assert p1.is_isosceles() == True
assert p1.is_scalene() == False
assert p1.is_equilateral() == False
# Scalene triangle
p2 = Polygon (Point(0, 0), Point(0, 2), Point(4, 0))
assert p2.is_isosceles() == False
assert p2.is_scalene() == True
assert p2.is_equilateral() == False
# Equilateral triagle
p3 = Polygon(Point(0, 0), Point(6, 0), Point(3, sqrt(27)))
assert p3.is_isosceles() == True
assert p3.is_scalene() == False
assert p3.is_equilateral() == True
def test_do_poly_distance():
# Non-intersecting polygons
square1 = Polygon (Point(0, 0), Point(0, 1), Point(1, 1), Point(1, 0))
triangle1 = Polygon(Point(1, 2), Point(2, 2), Point(2, 1))
assert square1._do_poly_distance(triangle1) == sqrt(2)/2
# Polygons which sides intersect
square2 = Polygon(Point(1, 0), Point(2, 0), Point(2, 1), Point(1, 1))
with warns(UserWarning, \
match="Polygons may intersect producing erroneous output", test_stacklevel=False):
assert square1._do_poly_distance(square2) == 0
# Polygons which bodies intersect
triangle2 = Polygon(Point(0, -1), Point(2, -1), Point(S.Half, S.Half))
with warns(UserWarning, \
match="Polygons may intersect producing erroneous output", test_stacklevel=False):
assert triangle2._do_poly_distance(square1) == 0

View File

@ -0,0 +1,170 @@
import pytest
from sympy.core.numbers import Float
from sympy.core.function import (Derivative, Function)
from sympy.core.singleton import S
from sympy.core.symbol import Symbol
from sympy.functions import exp, cos, sin, tan, cosh, sinh
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.geometry import Point, Point2D, Line, Polygon, Segment, convex_hull,\
intersection, centroid, Point3D, Line3D, Ray, Ellipse
from sympy.geometry.util import idiff, closest_points, farthest_points, _ordered_points, are_coplanar
from sympy.solvers.solvers import solve
from sympy.testing.pytest import raises
def test_idiff():
x = Symbol('x', real=True)
y = Symbol('y', real=True)
t = Symbol('t', real=True)
f = Function('f')
g = Function('g')
# the use of idiff in ellipse also provides coverage
circ = x**2 + y**2 - 4
ans = -3*x*(x**2/y**2 + 1)/y**3
assert ans == idiff(circ, y, x, 3), idiff(circ, y, x, 3)
assert ans == idiff(circ, [y], x, 3)
assert idiff(circ, y, x, 3) == ans
explicit = 12*x/sqrt(-x**2 + 4)**5
assert ans.subs(y, solve(circ, y)[0]).equals(explicit)
assert True in [sol.diff(x, 3).equals(explicit) for sol in solve(circ, y)]
assert idiff(x + t + y, [y, t], x) == -Derivative(t, x) - 1
assert idiff(f(x) * exp(f(x)) - x * exp(x), f(x), x) == (x + 1)*exp(x)*exp(-f(x))/(f(x) + 1)
assert idiff(f(x) - y * exp(x), [f(x), y], x) == (y + Derivative(y, x))*exp(x)
assert idiff(f(x) - y * exp(x), [y, f(x)], x) == -y + Derivative(f(x), x)*exp(-x)
assert idiff(f(x) - g(x), [f(x), g(x)], x) == Derivative(g(x), x)
# this should be fast
fxy = y - (-10*(-sin(x) + 1/x)**2 + tan(x)**2 + 2*cosh(x/10))
assert idiff(fxy, y, x) == -20*sin(x)*cos(x) + 2*tan(x)**3 + \
2*tan(x) + sinh(x/10)/5 + 20*cos(x)/x - 20*sin(x)/x**2 + 20/x**3
def test_intersection():
assert intersection(Point(0, 0)) == []
raises(TypeError, lambda: intersection(Point(0, 0), 3))
assert intersection(
Segment((0, 0), (2, 0)),
Segment((-1, 0), (1, 0)),
Line((0, 0), (0, 1)), pairwise=True) == [
Point(0, 0), Segment((0, 0), (1, 0))]
assert intersection(
Line((0, 0), (0, 1)),
Segment((0, 0), (2, 0)),
Segment((-1, 0), (1, 0)), pairwise=True) == [
Point(0, 0), Segment((0, 0), (1, 0))]
assert intersection(
Line((0, 0), (0, 1)),
Segment((0, 0), (2, 0)),
Segment((-1, 0), (1, 0)),
Line((0, 0), slope=1), pairwise=True) == [
Point(0, 0), Segment((0, 0), (1, 0))]
R = 4.0
c = intersection(
Ray(Point2D(0.001, -1),
Point2D(0.0008, -1.7)),
Ellipse(center=Point2D(0, 0), hradius=R, vradius=2.0), pairwise=True)[0].coordinates
assert c == pytest.approx(
Point2D(0.000714285723396502, -1.99999996811224, evaluate=False).coordinates)
# check this is responds to a lower precision parameter
R = Float(4, 5)
c2 = intersection(
Ray(Point2D(0.001, -1),
Point2D(0.0008, -1.7)),
Ellipse(center=Point2D(0, 0), hradius=R, vradius=2.0), pairwise=True)[0].coordinates
assert c2 == pytest.approx(
Point2D(0.000714285723396502, -1.99999996811224, evaluate=False).coordinates)
assert c[0]._prec == 53
assert c2[0]._prec == 20
def test_convex_hull():
raises(TypeError, lambda: convex_hull(Point(0, 0), 3))
points = [(1, -1), (1, -2), (3, -1), (-5, -2), (15, -4)]
assert convex_hull(*points, **{"polygon": False}) == (
[Point2D(-5, -2), Point2D(1, -1), Point2D(3, -1), Point2D(15, -4)],
[Point2D(-5, -2), Point2D(15, -4)])
def test_centroid():
p = Polygon((0, 0), (10, 0), (10, 10))
q = p.translate(0, 20)
assert centroid(p, q) == Point(20, 40)/3
p = Segment((0, 0), (2, 0))
q = Segment((0, 0), (2, 2))
assert centroid(p, q) == Point(1, -sqrt(2) + 2)
assert centroid(Point(0, 0), Point(2, 0)) == Point(2, 0)/2
assert centroid(Point(0, 0), Point(0, 0), Point(2, 0)) == Point(2, 0)/3
def test_farthest_points_closest_points():
from sympy.core.random import randint
from sympy.utilities.iterables import subsets
for how in (min, max):
if how == min:
func = closest_points
else:
func = farthest_points
raises(ValueError, lambda: func(Point2D(0, 0), Point2D(0, 0)))
# 3rd pt dx is close and pt is closer to 1st pt
p1 = [Point2D(0, 0), Point2D(3, 0), Point2D(1, 1)]
# 3rd pt dx is close and pt is closer to 2nd pt
p2 = [Point2D(0, 0), Point2D(3, 0), Point2D(2, 1)]
# 3rd pt dx is close and but pt is not closer
p3 = [Point2D(0, 0), Point2D(3, 0), Point2D(1, 10)]
# 3rd pt dx is not closer and it's closer to 2nd pt
p4 = [Point2D(0, 0), Point2D(3, 0), Point2D(4, 0)]
# 3rd pt dx is not closer and it's closer to 1st pt
p5 = [Point2D(0, 0), Point2D(3, 0), Point2D(-1, 0)]
# duplicate point doesn't affect outcome
dup = [Point2D(0, 0), Point2D(3, 0), Point2D(3, 0), Point2D(-1, 0)]
# symbolic
x = Symbol('x', positive=True)
s = [Point2D(a) for a in ((x, 1), (x + 3, 2), (x + 2, 2))]
for points in (p1, p2, p3, p4, p5, dup, s):
d = how(i.distance(j) for i, j in subsets(set(points), 2))
ans = a, b = list(func(*points))[0]
assert a.distance(b) == d
assert ans == _ordered_points(ans)
# if the following ever fails, the above tests were not sufficient
# and the logical error in the routine should be fixed
points = set()
while len(points) != 7:
points.add(Point2D(randint(1, 100), randint(1, 100)))
points = list(points)
d = how(i.distance(j) for i, j in subsets(points, 2))
ans = a, b = list(func(*points))[0]
assert a.distance(b) == d
assert ans == _ordered_points(ans)
# equidistant points
a, b, c = (
Point2D(0, 0), Point2D(1, 0), Point2D(S.Half, sqrt(3)/2))
ans = {_ordered_points((i, j))
for i, j in subsets((a, b, c), 2)}
assert closest_points(b, c, a) == ans
assert farthest_points(b, c, a) == ans
# unique to farthest
points = [(1, 1), (1, 2), (3, 1), (-5, 2), (15, 4)]
assert farthest_points(*points) == {
(Point2D(-5, 2), Point2D(15, 4))}
points = [(1, -1), (1, -2), (3, -1), (-5, -2), (15, -4)]
assert farthest_points(*points) == {
(Point2D(-5, -2), Point2D(15, -4))}
assert farthest_points((1, 1), (0, 0)) == {
(Point2D(0, 0), Point2D(1, 1))}
raises(ValueError, lambda: farthest_points((1, 1)))
def test_are_coplanar():
a = Line3D(Point3D(5, 0, 0), Point3D(1, -1, 1))
b = Line3D(Point3D(0, -2, 0), Point3D(3, 1, 1))
c = Line3D(Point3D(0, -1, 0), Point3D(5, -1, 9))
d = Line(Point2D(0, 3), Point2D(1, 5))
assert are_coplanar(a, b, c) == False
assert are_coplanar(a, d) == False