def conic_coeff(variables, equation): if total_degree(equation) != 2: raise ValueError() x = variables[0] y = variables[1] equation = expand(equation) a = equation.coeff(x**2) b = equation.coeff(x * y) c = equation.coeff(y**2) d = equation.coeff(x, 1).coeff(y, 0) e = equation.coeff(y, 1).coeff(x, 0) f = equation.coeff(x, 0).coeff(y, 0) return a, b, c, d, e, f
def multiplicity(self, point): """ Returns the multiplicity of a singular point on the region. A singular point (x,y) of region is said to be of multiplicity m if all the partial derivatives off to order m - 1 vanish there. Examples ======== >>> from sympy.abc import x, y, z >>> from sympy.vector import ImplicitRegion >>> I = ImplicitRegion((x, y, z), x**2 + y**3 - z**4) >>> I.singular_points() {(0, 0, 0)} >>> I.multiplicity((0, 0, 0)) 2 """ if isinstance(point, Point): point = point.args modified_eq = self.equation for i, var in enumerate(self.variables): modified_eq = modified_eq.subs(var, var + point[i]) modified_eq = expand(modified_eq) if len(modified_eq.args) != 0: terms = modified_eq.args m = min([total_degree(term) for term in terms]) else: terms = modified_eq m = total_degree(terms) return m
def degree(self): return total_degree(self.equation)
def rational_parametrization(self, parameters=('t', 's'), reg_point=None): """ Returns the rational parametrization of implict region. Examples ======== >>> from sympy import Eq >>> from sympy.abc import x, y, z, s, t >>> from sympy.vector import ImplicitRegion >>> parabola = ImplicitRegion((x, y), y**2 - 4*x) >>> parabola.rational_parametrization() (4/t**2, 4/t) >>> circle = ImplicitRegion((x, y), Eq(x**2 + y**2, 4)) >>> circle.rational_parametrization() (4*t/(t**2 + 1), 4*t**2/(t**2 + 1) - 2) >>> I = ImplicitRegion((x, y), x**3 + x**2 - y**2) >>> I.rational_parametrization() (t**2 - 1, t*(t**2 - 1)) >>> cubic_curve = ImplicitRegion((x, y), x**3 + x**2 - y**2) >>> cubic_curve.rational_parametrization(parameters=(t)) (t**2 - 1, t*(t**2 - 1)) >>> sphere = ImplicitRegion((x, y, z), x**2 + y**2 + z**2 - 4) >>> sphere.rational_parametrization(parameters=(t, s)) (-2 + 4/(s**2 + t**2 + 1), 4*s/(s**2 + t**2 + 1), 4*t/(s**2 + t**2 + 1)) For some conics, regular_points() is unable to find a point on curve. To calulcate the parametric representation in such cases, user need to determine a point on the region and pass it using reg_point. >>> c = ImplicitRegion((x, y), (x - 1/2)**2 + (y)**2 - (1/4)**2) >>> c.rational_parametrization(reg_point=(3/4, 0)) (0.75 - 0.5/(t**2 + 1), -0.5*t/(t**2 + 1)) References ========== - Christoph M. Hoffmann, "Conversion Methods between Parametric and Implicit Curves and Surfaces", Purdue e-Pubs, 1990. Available: https://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1827&context=cstech """ equation = self.equation degree = self.degree if degree == 1: if len(self.variables) == 1: return (equation, ) elif len(self.variables) == 2: x, y = self.variables y_par = list(solveset(equation, y))[0] return x, y_par else: raise NotImplementedError() point = () # Finding the (n - 1) fold point of the monoid of degree if degree == 2: # For degree 2 curves, either a regular point or a singular point can be used. if reg_point is not None: # Using point provided by the user as regular point point = reg_point else: if len(self.singular_points()) != 0: point = list(self.singular_points())[0] else: point = self.regular_point() if len(self.singular_points()) != 0: singular_points = self.singular_points() for spoint in singular_points: syms = Tuple(*spoint).free_symbols rep = {s: 2 for s in syms} if len(syms) != 0: spoint = tuple(s.subs(rep) for s in spoint) if self.multiplicity(spoint) == degree - 1: point = spoint break if len(point) == 0: # The region in not a monoid raise NotImplementedError() modified_eq = equation # Shifting the region such that fold point moves to origin for i, var in enumerate(self.variables): modified_eq = modified_eq.subs(var, var + point[i]) modified_eq = expand(modified_eq) hn = hn_1 = 0 for term in modified_eq.args: if total_degree(term) == degree: hn += term else: hn_1 += term hn_1 = -1 * hn_1 if not isinstance(parameters, tuple): parameters = (parameters, ) if len(self.variables) == 2: parameter1 = parameters[0] if parameter1 == 's': # To avoid name conflict between parameters s = _symbol('s_', real=True) else: s = _symbol('s', real=True) t = _symbol(parameter1, real=True) hn = hn.subs({self.variables[0]: s, self.variables[1]: t}) hn_1 = hn_1.subs({self.variables[0]: s, self.variables[1]: t}) x_par = (s * (hn_1 / hn)).subs(s, 1) + point[0] y_par = (t * (hn_1 / hn)).subs(s, 1) + point[1] return x_par, y_par elif len(self.variables) == 3: parameter1, parameter2 = parameters if parameter1 == 'r' or parameter2 == 'r': # To avoid name conflict between parameters r = _symbol('r_', real=True) else: r = _symbol('r', real=True) s = _symbol(parameter2, real=True) t = _symbol(parameter1, real=True) hn = hn.subs({ self.variables[0]: r, self.variables[1]: s, self.variables[2]: t }) hn_1 = hn_1.subs({ self.variables[0]: r, self.variables[1]: s, self.variables[2]: t }) x_par = (r * (hn_1 / hn)).subs(r, 1) + point[0] y_par = (s * (hn_1 / hn)).subs(r, 1) + point[1] z_par = (t * (hn_1 / hn)).subs(r, 1) + point[2] return x_par, y_par, z_par raise NotImplementedError()