Skip to content

Commit

Permalink
Merge pull request #19580 from friyaz/parametricregion
Browse files Browse the repository at this point in the history
Modified API of ParametricIntegral class
  • Loading branch information
Upabjojr committed Jun 18, 2020
2 parents 4a0e1f0 + c28300c commit 8229061
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 59 deletions.
2 changes: 1 addition & 1 deletion sympy/core/tests/test_args.py
Expand Up @@ -4922,7 +4922,7 @@ def test_sympy__vector__orienters__QuaternionOrienter():
def test_sympy__vector__parametricregion__ParametricRegion():
from sympy.abc import t
from sympy.vector.parametricregion import ParametricRegion
assert _test_args(ParametricRegion(t, (t, t**3), {t: (0, 2)}))
assert _test_args(ParametricRegion((t, t**3), (t, 0, 2)))


def test_sympy__vector__scalar__BaseScalar():
Expand Down
84 changes: 44 additions & 40 deletions sympy/vector/parametricregion.py
@@ -1,6 +1,5 @@
from sympy.core.basic import Basic
from sympy.core.containers import Dict, Tuple
from sympy.vector.coordsysrect import CoordSys3D
from sympy.core.containers import Tuple

class ParametricRegion(Basic):
"""
Expand All @@ -13,68 +12,73 @@ class ParametricRegion(Basic):
>>> from sympy.abc import r, theta, t, a, b, x, y
>>> from sympy.vector import ParametricRegion
>>> ParametricRegion(t, (t, t**2), limits={t: (-1, 2)})
ParametricRegion((t,), (t, t**2), {t: (-1, 2)})
>>> ParametricRegion((x, y), (x, y), {x: (3, 4), y: (5, 6)})
ParametricRegion((x, y), (x, y), {x: (3, 4), y: (5, 6)})
>>> ParametricRegion((r, theta), (r*cos(theta), r*sin(theta)), {r: (-2, 2), theta: (0, pi)})
ParametricRegion((r, theta), (r*cos(theta), r*sin(theta)), {r: (-2, 2), theta: (0, pi)})
>>> ParametricRegion(t, (a*cos(t), b*sin(t)))
ParametricRegion((t,), (a*cos(t), b*sin(t)), {})
>>> ParametricRegion((t, t**2), (t, -1, 2))
ParametricRegion((t, t**2), (t, -1, 2))
>>> ParametricRegion((x, y), (x, 3, 4), (y, 5, 6))
ParametricRegion((x, y), (x, 3, 4), (y, 5, 6))
>>> ParametricRegion((r*cos(theta), r*sin(theta)), (r, -2, 2), (theta, 0, pi))
ParametricRegion((r*cos(theta), r*sin(theta)), (r, -2, 2), (theta, 0, pi))
>>> ParametricRegion((a*cos(t), b*sin(t)), t)
ParametricRegion((a*cos(t), b*sin(t)), t)
>>> circle = ParametricRegion((r, theta), (r*cos(theta), r*sin(theta)), {theta: (0, pi)})
>>> circle = ParametricRegion((r*cos(theta), r*sin(theta)), r, (theta, 0, pi))
>>> circle.parameters
(r, theta)
>>> circle.definition
(r*cos(theta), r*sin(theta))
>>> circle.limits
{theta: (0, pi)}
Dimension of a parametric region determines whether a region is a curve, surface
or volume region. It does not represent its dimensions in space.
>>> circle.dimensions
1
Parameters
==========
parameters_or_coordsys : parameter or a tuple of parameters or a CoordSys3d object.
When a CoordSys3d object is passed, its base scalars are used as parameters.
definition : tuple to define base scalars in terms of parameters.
limits : dict to define bounds of each parameter.
Each Key of dictionary should be parameter and value
is a tuple to represent corresponding lower and upper bound.`
bounds : Parameter or a tuple of length 3 to define parameter and
corresponding lower and upper bound
"""
def __new__(cls, parameters_or_coordsys, definition, limits=None):

if isinstance(parameters_or_coordsys, CoordSys3D):
parameters = parameters_or_coordsys.base_scalars()
elif not (isinstance(parameters_or_coordsys, tuple) or isinstance(parameters_or_coordsys, Tuple)):
parameters = (parameters_or_coordsys,)
else:
parameters = parameters_or_coordsys
def __new__(cls, definition, *bounds):
parameters = ()
limits = {}

if not isinstance(bounds, Tuple):
bounds = Tuple(*bounds)

for bound in bounds:
if isinstance(bound, tuple) or isinstance(bound, Tuple):
if len(bound) != 3:
raise ValueError("Tuple should be in the form (parameter, lowerbound, upperbound)")
parameters += (bound[0],)
limits[bound[0]] = (bound[1], bound[2])
else:
parameters += (bound,)

if not (isinstance(definition, tuple) or isinstance(definition, Tuple)):
definition = (definition,)

if limits is None:
limits = {}
obj = super().__new__(cls, Tuple(*definition), *bounds)
obj._parameters = parameters
obj._limits = limits

for parameter, bounds in limits.items():
if parameter not in parameters:
raise ValueError("%s is not listed in parameter tuple" % parameter)
if len(bounds) != 2:
raise ValueError("Bounds should be in the form (lower_bound, upper_bound)")

obj = super().__new__(cls, Tuple(*parameters), Tuple(*definition), Dict(limits))
return obj

@property
def limits(self):
return self.args[2]
def definition(self):
return self.args[0]

@property
def definition(self):
return self.args[1]
def limits(self):
return self._limits

@property
def parameters(self):
return self.args[0]
return self._parameters

@property
def dimensions(self):
return len(self.limits)
47 changes: 29 additions & 18 deletions sympy/vector/tests/test_parametricregion.py
Expand Up @@ -2,55 +2,66 @@
from sympy.vector.coordsysrect import CoordSys3D
from sympy.vector.parametricregion import ParametricRegion
from sympy.testing.pytest import raises
from sympy.abc import a, b, r, t, z, theta, phi
from sympy.abc import a, b, r, t, x, y, z, theta, phi

C = CoordSys3D('C')

def test_parametricregion():

point = ParametricRegion((), (3, 4), {})
point = ParametricRegion((3, 4))
assert point.definition == (3, 4)
assert point.parameters == ()
assert point.limits == {}
assert point.dimensions == 0

# line x = y
line_xy = ParametricRegion(C, (C.y), limits={C.y: (-3, 3)})
assert line_xy .definition == (C.y,)
assert line_xy.parameters == (C.x, C.y, C.z)
line_xy = ParametricRegion((y, y), (y, 1, 5))
assert line_xy .definition == (y, y)
assert line_xy.parameters == (y,)
assert line_xy.dimensions == 1

# line y = z
line_yz = ParametricRegion((t), (C.x,t,t), limits={t: (1, 2)})
assert line_yz.definition == (C.x,t,t)
assert line_yz.parameters == (t,)
line_yz = ParametricRegion((x,t,t), x, (t, 1, 2))
assert line_yz.definition == (x,t,t)
assert line_yz.parameters == (x, t)
assert line_yz.limits == {t: (1, 2)}
assert line_yz.dimensions == 1

p1 = ParametricRegion((a, b), (9*a, -16*b), limits={a: (0, 2), b: (-1, 5)})
p1 = ParametricRegion((9*a, -16*b), (a, 0, 2), (b, -1, 5))
assert p1.definition == (9*a, -16*b)
assert p1.parameters == (a, b)
assert p1.limits == {a: (0, 2), b: (-1, 5)}
assert p1.dimensions == 2

p2 = ParametricRegion(t, (t, t**3))
p2 = ParametricRegion((t, t**3), t)
assert p2.parameters == (t,)
assert p2.limits == {}
assert p2.dimensions == 0

circle = ParametricRegion((r, theta), (r*cos(theta), r*sin(theta)), {theta: (0, 2*pi)})
circle = ParametricRegion((r*cos(theta), r*sin(theta)), r, (theta, 0, 2*pi))
assert circle.definition == (r*cos(theta), r*sin(theta))
assert circle.dimensions == 1

halfdisc = ParametricRegion((r, theta), (r*cos(theta), r* sin(theta)), {r: (-2, 2), theta: (0, pi)})
halfdisc = ParametricRegion((r*cos(theta), r* sin(theta)), (r, -2, 2), (theta, 0, pi))
assert halfdisc.definition == (r*cos(theta), r*sin(theta))
assert halfdisc.parameters == (r, theta)
assert halfdisc.limits == {r: (-2, 2), theta: (0, pi)}
assert halfdisc.dimensions == 2

ellipse = ParametricRegion(t, (a*cos(t), b*sin(t)), {t: (0, 8)})
ellipse = ParametricRegion((a*cos(t), b*sin(t)), (t, 0, 8))
assert ellipse.parameters == (t,)
assert ellipse.limits == {t: (0, 8)}
assert ellipse.dimensions == 1

cylinder = ParametricRegion((r, theta, z), (cos(theta), r*sin(theta), C.z), {theta: (0, 2*pi), z: (0, 4)})
cylinder = ParametricRegion((r*cos(theta), r*sin(theta), z), (r, 0, 1), (theta, 0, 2*pi), (z, 0, 4))
assert cylinder.parameters == (r, theta, z)
assert cylinder.dimensions == 3

sphere = ParametricRegion((r, theta, phi), (r*sin(phi)*cos(theta),r*sin(phi)*sin(theta), r*cos(phi)),
{theta: ( 0, 2*pi), phi: ( 0, pi)})
sphere = ParametricRegion((r*sin(phi)*cos(theta),r*sin(phi)*sin(theta), r*cos(phi)),
r, (theta, 0, 2*pi), (phi, 0, pi))
assert sphere.definition == (r*sin(phi)*cos(theta),r*sin(phi)*sin(theta), r*cos(phi))
assert sphere.parameters == (r, theta, phi)
assert sphere.dimensions == 2

raises(ValueError, lambda: ParametricRegion((t), (a*t**2, 2*a*t), {a: (-2, 2)}))
raises(ValueError, lambda: ParametricRegion((a, b), (a**2, sin(b)), {a: (2, 4, 6)}))
raises(ValueError, lambda: ParametricRegion((a*t**2, 2*a*t), (a, -2)))
raises(ValueError, lambda: ParametricRegion((a, b), (a**2, sin(b)), (a, 2, 4, 6)))

0 comments on commit 8229061

Please sign in to comment.