def getNextRegularFunctionParameters(self, lmin, lmax, fun, df, xunit=1, yunit=1): """ Return a value 'nl' of the parameter such that the integral of 'fun' from 'lmin' to 'nl' is 'df'. `lmax` - is the maximal value of the parameter. If the interval [lmin,lmax] reveals to be too small, return 'None' """ # Vcurve is the curve as visually seen taking the dilatation # into account. from yanntricks.src.Constructors import phyFunction from yanntricks.src.Constructors import ParametricCurve x = var('x') Vf1 = phyFunction(self.f1(xunit * x)) Vf2 = phyFunction(self.f2(yunit * x)) Vcurve = ParametricCurve(Vf1, Vf2) prop_precision = float(df) / 100 # precision of the interval if prop_precision == 0: raise ValueError("prop_precision is zero.") # We'll perform a dichotomy method. # 'too_large' is a value of the parameter we know to be too large # 'too_small' is a value of the parameter we know to be too small # 'ell' is the median value on which the condition is tested. # The dichotomy method consist to make 'too_large' or 'too_small' become 'ell' and to recalculate a new 'ell' too_small = lmin too_large = lmax if Vcurve.getFunctionIntegral(fun, too_small, too_large) < df: return None max_iter = 100 done_iter = 0 while done_iter < max_iter: ell = (too_large + too_small) / 2 done_iter += 1 integral = Vcurve.getFunctionIntegral(fun, lmin, ell) if abs(integral - df) < prop_precision: return ell if integral > df: too_large = ell if integral < df: too_small = ell raise ShouldNotHappenException("I give up with this dichotomy")
def reverse(self): """ return the curve in the inverse sense but on the same interval EXAMPLE:: sage: from yanntricks import * sage: x=var('x') sage: curve=ParametricCurve(cos(x),sin(x)).graph(0,2*pi).reverse() sage: print curve <The parametric curve given by x(t)=cos(2*pi - t) y(t)=sin(2*pi - t) between 0 and 2*pi> """ from yanntricks.src.Constructors import ParametricCurve x = var('x') a = self.llamI b = self.llamF f1 = self.f1.sage(x=b - (x - a)) f2 = self.f2.sage(x=b - (x - a)) curve = ParametricCurve(f1, f2).graph(a, b) curve.f1.nul_function = self.f1.nul_function curve.f2.nul_function = self.f2.nul_function return curve
def visualParametricCurve(self, xunit, yunit): from yanntricks.src.Constructors import ParametricCurve from yanntricks.src.Constructors import phyFunction x = var('x') Vf1 = phyFunction(self.f1(xunit * x)) Vf2 = phyFunction(self.f2(yunit * x)) return ParametricCurve(Vf1, Vf2)
def parametric_curve(self): """ Return the parametric curve corresponding to `self`. The starting point is `self.I` and the parameters is the arc length. The parameter is positive on the side of `self.B` and negative on the opposite side. EXAMPLES:: sage: from yanntricks import * sage: segment=Segment(Point(0,0),Point(1,1)) sage: curve=segment.parametric_curve() sage: print curve(0) <Point(0,0)> sage: print curve(1) <Point(1/2*sqrt(2),1/2*sqrt(2))> sage: print curve(segment.length) <Point(1,1)> """ from yanntricks.src.Constructors import phyFunction from yanntricks.src.Constructors import ParametricCurve x = var('x') l = self.length f1 = phyFunction(self.I.x+x*(self.F.x-self.I.x)/l) f2 = phyFunction(self.I.y+x*(self.F.y-self.I.y)/l) return ParametricCurve(f1, f2, (0, l))
def rotate(self, theta): """ Return a new ParametricCurve which graph is rotated by <theta> with respect to self. theta is given in degree. """ from yanntricks.src.Constructors import ParametricCurve from yanntricks.src.radian_unit import radian alpha = radian(theta) g1 = cos(alpha) * self.f1 + sin(alpha) * self.f2 g2 = -sin(alpha) * self.f1 + cos(alpha) * self.f2 return ParametricCurve(g1, g2)
def get_normal_vector(self, xx): """ return a normalized normal vector to the graph of the function at xx The direction of the vector is outside INPUT: - ``x`` - a number, the position at which we want the normal vector OUTPUT: a vector EXAMPLES: sage: from yanntricks import * sage: x=var('x') sage: f=phyFunction(x**2) sage: print f.get_normal_vector(0) <vector I=<Point(0,0)> F=<Point(0,-1)>> """ from yanntricks.src.Constructors import ParametricCurve x = var('x') F = ParametricCurve(x, self) return F.get_normal_vector(xx)
def parametric_curve(self, a=None, b=None): """ Return the parametric curve associated to the circle. If optional arguments <a> and <b> are given, return the corresponding graph between the values a and b of the angle. The parameter of the curve is the angle in radian. """ from yanntricks.src.Constructors import ParametricCurve from yanntricks.src.Constructors import phyFunction from yanntricks.src.Exceptions import MissingPictureException if self._parametric_curve is None: x = var('x') if self.visual is True: if self.pspict is None: raise MissingPictureException( "You are trying to draw something with 'visual==True' when not giving a pspict." ) f1 = phyFunction(self.center.x + self.radius * cos(x) / self.pspict.xunit) f2 = phyFunction(self.center.y + self.radius * sin(x) / self.pspict.yunit) else: f1 = phyFunction(self.center.x + self.radius * cos(x)) f2 = phyFunction(self.center.y + self.radius * sin(x)) try: ai = self.angleI.radian af = self.angleF.radian except AttributeError: ai = self.angleI af = self.angleF self._parametric_curve = ParametricCurve(f1, f2, (ai, af)) curve = self._parametric_curve # The following is the typical line that is replaced by the decorator # 'copy_parameters' # curve.parameters=self.parameters.copy() if a == None: return curve else: return curve.graph(a, b)
def parametric_curve(self): """ return a parametric curve with the same graph as `self`. """ from yanntricks.src.Constructors import phyFunction from yanntricks.src.Constructors import ParametricCurve if self._parametric_curve: return self._parametric_curve x = var('x') curve = ParametricCurve(phyFunction(x), self, (self.mx, self.Mx)) curve.parameters = self.parameters.copy() curve.linear_plotpoints = self.linear_plotpoints curve.curvature_plotpoints = self.curvature_plotpoints curve.added_plotpoints = self.added_plotpoints curve._representativeParameters = self._representativeParameters self._parametric_curve = curve return curve
def derivative(self, n=1): """ Return the parametric curve given by the derivative. (f1,f2) -> (f1',f2'). INPUT: - ``n`` - an integer (default=1). If the optional parameter `n` is given, give higher order derivatives. If n=0, return self. EXAMPLES:: sage: from yanntricks import * sage: x=var('x') sage: f1=phyFunction(cos(2*x)) sage: f2=phyFunction(x*exp(2*x)) sage: F=ParametricCurve(f1,f2) sage: print F.derivative() <The parametric curve given by x(t)=-2*sin(2*t) y(t)=2*t*e^(2*t) + e^(2*t) between None and None> sage: print F.derivative(3) <The parametric curve given by x(t)=8*sin(2*t) y(t)=8*t*e^(2*t) + 12*e^(2*t) between None and None> """ from yanntricks.src.Constructors import ParametricCurve try: return self._derivative_dict[n] except KeyError: pass if n == 1: self._derivative_dict[1] = ParametricCurve(self.f1.derivative(), self.f2.derivative()) else: self._derivative_dict[n] = self.derivative(n - 1).derivative() return self._derivative_dict[n]
def graph(self, mx, Mx): from yanntricks.src.Constructors import ParametricCurve gr = ParametricCurve(self.f1, self.f2, (mx, Mx)) gr.parameters = self.parameters.copy() return gr