add read me
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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