Exemplo n.º 1
0
def general_function_get_point(fun,x,advised=True):
    """
    Return a point on the graph of the function with the given x, i.e. it return the point (x,f(x)).

    Also set an attribute advised_mark_angle to the point. This angle is the normal exterior to the graph; visually this is usually the best place to put a mark. Typically you use this as
    P=f.get_point(3)
    P.mark(radius,P.advised_mark_angle,"$P$")

    NOTE:
    If you don't plan to put a mark on the point, you are invited
    to use advised=False in order to speed up the computations.
    """
    P = Point(float(x),fun(x))
    if advised :
        try :
            ca = fun.derivative()(x) 
        except TypeError:    # Sage cannot derivate the function
            print ("I'm not able to compute derivative of {0}.\
            You should pass advised=False".format(fun))
        else :
            angle_n=degree(atan(ca)+pi/2)
            if fun.derivative(2)(x) > 0:
                angle_n=angle_n+180
            P._advised_mark_angle=angle_n
    return P
Exemplo n.º 2
0
 def _sage_(self):
     import sage.all as sage
     return sage.atan(self.args[0]._sage_())
Exemplo n.º 3
0
 def _sage_(self):
     import sage.all as sage
     return sage.atan(self.args[0]._sage_())
def visualPolarCoordinates(r, theta, xunit=1, yunit=1):
    """
    return the polar coordinated that you have to give
    in such a way the it *visually* appears `(r,theta)`
    when `xunit` and `yunit` are given.

    The input and output angles are in radian.

    INPUT:

    - ``r`` - the distance you want to see.

    - ``theta`` - the angle you want to see (radian or AngleMeasure).
                    If the angle is passed as 'AngleMeasure', the answer
                    will also be AngleMeasure

    - ``xunit`` - the dilatation factor in the `x` direction.

    - ``yunit`` - the dilatation factor in the `y` direction.

    OUTPUT:

    a tuple `(distance,angle)`

    EXAMPLES::

        sage: from yanntricks.SmallComputations import *
        sage: polar_with_dilatation(2,pi,2,1)
        (1, pi)
        sage: polar_with_dilatation(1,pi/4,2,2)
        (1/2, 1/4*pi)

    Notice the difference between::

        sage: polar_with_dilatation(1,pi/2,2,1/2)
        (2, 1/2*pi)

    and::

        sage: polar_with_dilatation(1,pi/2,2,0.5)
        (2.00000000000000, 1/2*pi)
    """
    from yanntricks.src.MathStructures import AngleMeasure

    arg_is_angle_measure = False
    orig_theta = theta
    if isinstance(theta, AngleMeasure):
        theta = numerical_approx(theta.radian)
        arg_is_angle_measure = True
    else:
        theta = numerical_approx(theta)

    if cos(theta) == 0:
        return (r / yunit, orig_theta)
    if cos(theta) == 1:
        return (r / xunit, orig_theta)
    if cos(theta) == -1:
        return (r / xunit, orig_theta)

    # For Sage, atan : R -> [-pi/2,pi/2]
    # thus one has to check the angle after having done atan( ... tan(...)  )
    # Here we assume that the deformed angle is next to the original one
    if xunit == yunit:
        alpha = theta
    else:
        alpha = atan((xunit / yunit) * tan(theta))
        if theta > pi / 2 and theta < 3 * pi / 2:
            alpha = alpha + pi

    rp = (r / xunit) * (cos(theta) / cos(alpha))

    if rp < 0:
        rp = -rp
        alpha = alpha + pi
    if arg_is_angle_measure:
        alpha = AngleMeasure(value_radian=alpha)
    return (rp, alpha)
Exemplo n.º 5
0
 def tangent_angle(self, llam):
     """"Return the angle of the tangent (radian)"""
     dx = self.f1.derivative()(llam)
     dy = self.f2.derivative()(llam)
     ca = dy / dx
     return atan(ca)
Exemplo n.º 6
0
    def _getOCvector(self, dimx, dimy, pspict=None):
        """
        Return a vector 
        O -> central point of the box
        such that the box of size (dimx,dimy) will not intersect the lines
        of the angle self.

          In fact we use this vector to translate from the mark_point 
          (not the center of the angle).
          Thus we are sure that the mark will in the same time
          - not intersect the lines
          - be further than the code.
        """
        from yanntricks.src.affine_vector import AffineVector
        from yanntricks.src.point import Point
        if 0 < self.angleA.degree < 90 and 0 < self.angleB.degree < 90:
            # In this case, the mark will be attached
            # - by the upper left to the line OB (let X be that point)
            # - by the lower right to the line OA   (let Y be that point)
            # We consider 'd', the diagonal of the mark that join OA to OB
            # The triangle OXY has angle 'alpha' at O and 'beta' at Y.
            # We consider the altitude 'h' of OXY from X.
            # Let 'sigma' be the angle made by the diagonal of the box.
            # beta = self.angleA + sigma
            # Using Pythagoras'theorem and some trigonometry,
            # we can determine all the lengths and angles.
            # The one we are interested in is OX. Trigonometry then
            # provides the coordinates of X.
            # Then the center of the mark's box is easy to compute
            # as a translation by (dimx/2 , -dimy/2)

            d = sqrt(dimx**2 + dimy**2)  # diagonal of the box
            sigma = arctan(dimy / dimx)
            beta = self.angleA.radian + sigma

            alpha = self.measure.radian

            h = d * sin(beta)
            l = h / sin(alpha)  # length OX

            # Here are the coordinates of X (with respect to O)
            x = l * cos(self.angleB.radian)
            y = l * sin(self.angleB.radian)

            # This is the vector O->central_point

            return AffineVector(self.O, Point(x + dimx / 2, y - dimy / 2))

        # In each case, the returned vector is the vector
        #  O -> center of the box containing the text.
        if 0 < self.angleA.degree < 90 and (self.angleB.degree == 90
                                            or self.angleB.radian == pi / 2):
            y = dimx / tan(self.measure.radian)
            Q = self.O + (0, y)
            return AffineVector(self.O, Q + (dimx / 2, dimy / 2))

        if 0 < self.angleA.degree < 90 and 90 < self.angleB.degree < 180:
            h = dimx * sin(self.angleA.radian)
            l = h / sin(self.measure.radian)
            gamma = pi - self.angleB.radian
            x = l * cos(gamma)
            y = l * sin(gamma)

            Q = self.O + (-x, y)  # lower left angle of the box
            return AffineVector(self.O, Q + (dimx / 2, dimy / 2))

        if (self.angleA.radian == pi / 2
                or self.angleA.degree == 90) and 90 < self.angleB.degree < 180:
            l = dimx / tan(self.measure.radian)
            Q = self.O + (0, l)
            return AffineVector(self.O, Q + (-dimx / 2, dimy / 2))

        if 90 < self.angleA.degree < 180 and 90 < self.angleB.degree < 180:

            d = sqrt(dimx**2 + dimy**2)
            beta = pi - self.angleB.radian
            alpha = atan(dimy / dimx)
            gamma = alpha + beta
            sigma = pi - self.measure.radian - gamma
            h = d * sin(sigma)
            l = h / sin(self.measure.radian)
            x = l * cos(beta)
            y = l * sin(beta)
            Q = self.O + (-x, y)
            return AffineVector(self.O, Q + (dimx / 2, dimy / 2))

        if 90 < self.angleA.degree < 180 and (self.angleB.degree == 180
                                              or self.angleB.radian == pi):
            l = dimy / sin(self.measure.radian)
            x = l * cos(self.measure.radian)
            y = dimy
            Q = self.O + (-x, y)
            return AffineVector(self.O, Q + (-dimx / 2, -dimy / 2))

        if 90 < self.angleA.degree < 180 and 180 < self.angleB.degree < 270:
            alpha = 3 * pi / 2 - self.angleB.radian
            h = dimy * sin(alpha)
            l = h / sin(self.measure.radian)
            gamma = self.angleA.radian - pi / 2
            x = l * sin(gamma)
            y = l * cos(gamma)
            Q = self.O + (-x, y)
            return AffineVector(self.O, Q + (-dimx / 2, -dimy / 2))

        if (self.angleA.degree == 180 or self.angleA.radian
                == pi) and 180 < self.angleB.degree < 270:
            alpha = pi / 2 - self.measure.radian
            x = dimy * tan(alpha)
            Q = self.O + (-x, 0)
            return AffineVector(self.O, Q + (-dimx / 2, -dimy / 2))

        if 180 < self.angleA.degree < 270 and \
                (self.angleB.degree == 270 or self.angleB.radian == 3*pi/2):
            y = dimx / tan(self.measure.radian)
            Q = self.O + (0, -y)
            return AffineVector(self.O, Q + (-dimx / 2, -dimy / 2))

        if 270 < self.angleA.degree < 360 and 0 < self.angleB.degree < 90:
            alpha = self.angleB.radian
            l = dimy * cos(alpha)
            beta = pi / 2 - alpha
            x = l * sin(beta)
            y = l * cos(beta)
            Q = self.O + (x, y)
            return AffineVector(self.O, Q + (dimx / 2, -dimy / 2))

        if (self.angleA.radian == 3*pi/2 or self.angleA.degree == 270) and \
                270 < self.angleB.degree < 360:
            l = dimx / tan(self.measure.radian)
            x = 0
            y = l
            Q = self.O + (x, -y)
            return AffineVector(self.O, Q + (dimx / 2, -dimy / 2))

        if 180 < self.angleA.degree < 270 and 180 < self.angleB.degree < 270:
            d = sqrt(dimx**2 + dimy**2)
            alpha = atan(dimy / dimx)
            beta = self.angleA.radian - pi
            gamma = alpha + beta
            h = d * sin(gamma)

            l = h / sin(self.measure.radian)
            sigma = 3 * pi / 2 - self.angleB.radian
            x = l * sin(sigma)
            y = l * cos(sigma)
            Q = self.O + (-x, -y)
            return AffineVector(self.O, Q + (-dimx / 2, dimy / 2))

        if 180 < self.angleA.degree < 270 and 270 < self.angleB.degree < 360:
            alpha = pi / 2 - (self.angleA.radian - pi)
            beta = self.measure.radian - alpha
            h = dimx / (tan(alpha) + tan(beta))
            d1 = h * tan(alpha)
            Q = self.O + (-d1, -h)

            return AffineVector(self.O, Q + (dimx / 2, -dimy / 2))
        if 270 < self.angleA.degree < 360 and 270 < self.angleB.degree < 360:
            alpha = 2 * pi - self.angleA.radian
            beta = arctan(dimy / dimx)
            sigma = alpha + beta
            d = sqrt(dimx**2 + dimy**2)
            h = d * sin(sigma)
            l = h / sin(self.measure.radian)
            gamma = self.angleA.radian - 3 * pi / 2
            x = l * sin(gamma)
            y = l * cos(gamma)
            Q = self.O + (x, -y)
            return AffineVector(self.O, Q + (dimx / 2, dimy / 2))

        if 270 < self.angleA.degree < 360 and (self.angleB.degree == 360
                                               or self.angleB.radian == 2 * pi
                                               or self.angleB.radian == 0
                                               or self.angleB.degree == 0):
            l = dimy / tan(self.measure.radian)
            Q = self.O + (l, 0)
            return AffineVector(self.O, Q + (dimx / 2, -dimy / 2))

        if 260 < self.angleA.degree < 360 and (self.angleB.degree > 360
                                               or 0 < self.angleB.degree < 90):
            alpha = self.angleA.radian - pi / 2
            h = dimy * sin(alpha)
            l = h / sin(self.measure.radian)
            beta = pi / 2 - self.angleB.radian
            x = l * sin(beta)
            y = l * cos(beta)
            Q = self.O + (x, y)
            return AffineVector(self.O, Q + (dimx / 2, -dimy / 2))

        # For the next few ones, the box touch the angles' vertex.
        # Thus we add a (0.1,0.1). If not, the mark touches the
        # arc circle.

        if 180 < self.angleA.degree < 270 and self.angleB.degree == 0:
            Q = self.O + (0.1, -0.1)
            return AffineVector(self.O, Q + (dimx / 2, -dimy / 2))

        if 270 <= self.angleA.degree <= 360 and 90 <= self.angleB.degree <= 180:
            Q = self.O + (0.1, 0.1)
            return AffineVector(self.O, Q + (dimx / 2, dimy / 2))

        if (self.angleA.degree == 0 or self.angleA.radian
                == 0) and 90 <= self.angleB.degree <= 180:
            Q = self.O + (0.1, 0.1)
            return AffineVector(self.O, Q + (dimx / 2, dimy / 2))

        if (self.angleA.degree == 180 or self.angleA.radian
                == pi) and 270 <= self.angleB.degree <= 360:
            Q = self.O + (-0.1, -0.1)
            return AffineVector(self.O, Q + (-dimx / 2, -dimy / 2))

        if 0 <= self.angleA.degree <= 90 and 180 <= self.angleB.degree <= 270:
            Q = self.O + (-0.1, 0.1)
            return AffineVector(self.O, Q + (-dimx / 2, dimy / 2))

        if self.angleA.degree == 0 or self.angleA.radian == 0:
            x = dimy / tan(self.measure.radian)
            K = self.O + (x + dimx / 2, dimy / 2)
            return AffineVector(self.O, K)

        raise ValueError("Not yet implemented for angles :",
                         numerical_approx(self.angleA.degree),
                         numerical_approx(self.angleB.degree))