chore: 添加虚拟环境到仓库
- 添加 backend_service/venv 虚拟环境 - 包含所有Python依赖包 - 注意:虚拟环境约393MB,包含12655个文件
This commit is contained in:
@@ -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)
|
||||
@@ -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"/>'
|
||||
@@ -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(TypeError, 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))
|
||||
@@ -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)))
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
@@ -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))
|
||||
@@ -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, 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]
|
||||
@@ -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 triangle
|
||||
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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user