예제 #1
0
    def get_point(self, llam, advised=True):
        """
        Return the point on the curve for the value llam of the parameter.

        Add the attribute advised_mark_angle which gives the normal
        exterior angle at the given point.
        If you want to put a mark on the point P (obtained by get_point),
        you should consider to write
            P.put_mark(r,P.advised_mark_angle,text)
        The so build angle is somewhat "optimal" for a visual point 
        of view. The attribute self.get_point(llam).advised_mark_angle 
        is given in degree.

        The advised angle is given in degree.

        The optional boolean argument <advised> serves to avoid infinite
        loops because we use get_point in get_normal_vector.
        """
        from yanntricks.src.AngleMeasure import AngleMeasure
        if isinstance(llam, AngleMeasure):
            llam = llam.radian
        P = Point(self.f1(llam), self.f2(llam))
        if advised:
            P._advised_mark_angle = self.get_normal_vector(llam).angle()
        return P
    def bounding_box(self, pspict=None):
        """
        Return the bounding box of the interpolation curve

        EXAMPLES::

        sage: from yanntricks import *
        sage: print InterpolationCurve([Point(0,0),Point(1,1)]).bounding_box()
        <BoundingBox xmin=0.0,xmax=1.0; ymin=0.0,ymax=1.0>

        sage: C=Circle(Point(0,0),1)
        sage: n=400
        sage: print InterpolationCurve([C.get_point(i*SR(360)/n,advised=False) for i in range(n)]).bounding_box()
        <BoundingBox xmin=-1.0,xmax=1.0; ymin=-1.0,ymax=1.0>

        NOTE::

        Since the bounding box is computed from the give points while the curve is an interpolation,
        this bounding box is incorrect to the extend that \pscurve does not remains in the convex hull
        of the given points.

        EXAMPLE:
        sage: F=InterpolationCurve([Point(-1,1),Point(1,1),Point(1,-1),Point(-1,-1)])
        sage: print F.bounding_box()
        <BoundingBox xmin=-1.0,xmax=1.0; ymin=-1.0,ymax=1.0>

        """
        from yanntricks.src.point import Point
        from yanntricks.src.BoundingBox import BoundingBox
        bb = BoundingBox(Point(self.xmin(), self.ymin()),
                         Point(self.xmax(), self.ymax()))
        return bb
예제 #3
0
    def __call__(self, a, b=None):
        """
        return the affine vector at point (a,b).

        INPUT:

        - ``a,b`` - numbers.

        OUTPUT:
        an affine vector based on (a,b).

        EXAMPLES::

            sage: from yanntricks import *
            sage: x,y=var('x,y')
            sage: F=VectorField(x**2,y**3)
            sage: print F(1,2)
            <vector I=<Point(1,2)> F=<Point(2,10)>>

            sage: P=Point(3,4)
            sage: print F(P)
            <vector I=<Point(3,4)> F=<Point(12,68)>>

        """
        from yanntricks.src.affine_vector import AffineVector
        if b is not None:
            P = Point(a, b)
        else:
            P = a
        vx = self.fx(x=P.x, y=P.y)
        vy = self.fy(x=P.x, y=P.y)
        return AffineVector(P, Point(P.x + vx, P.y + vy))
예제 #4
0
def general_function_get_point(fun, x, advised=True):
    """
    Return a point on the graph of the function.

    Return a point on the graph of the function with the given
    x, i.e. it returns 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.
    """
    from yanntricks.src.point import Point
    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  # pylint:disable=protected-access
    return P
예제 #5
0
 def __init__(self, bb=None):
     from yanntricks.src.BoundingBox import BoundingBox
     if bb is None:
         bb = BoundingBox()
     ObjectGraph.__init__(self, self)
     self.BB = bb
     self.separator_name = "GRID"
     # Default values, have to be integer.
     self.add_option({"Dx": 1, "Dy": 1})
     self.Dx = self.options.DicoOptions["Dx"]
     self.Dy = self.options.DicoOptions["Dy"]
     self.num_subX = 2
     self.num_subY = 2
     self.draw_border = False
     self.draw_horizontal_grid = True
     self.draw_vertical_grid = True
     self.main_horizontal = Segment(Point(0, 1), Point(1, 1))
     self.main_horizontal.parameters.color = "gray"
     self.main_horizontal.parameters.style = "solid"
     self.main_vertical = Segment(Point(0, 1), Point(1, 1))
     self.main_vertical.parameters.color = "gray"
     self.main_vertical.parameters.style = "solid"
     self.sub_vertical = Segment(Point(0, 1), Point(1, 1))
     self.sub_vertical.parameters.color = "gray"
     self.sub_vertical.parameters.style = "dotted"
     self.sub_horizontal = Segment(Point(0, 1), Point(1, 1))
     self.sub_horizontal.parameters.color = "gray"
     self.sub_horizontal.parameters.style = "dotted"
     self.border = Segment(Point(0, 1), Point(1, 1))
     self.border.parameters.color = "gray"
     self.border.parameters.style = "dotted"
 def get_tangent_vector(self, x, advised=False, numerical=False):
     """Return a tangent vector at the point (x,f(x))."""
     from yanntricks.src.point import Point
     ca = self.derivative()(x, numerical=numerical)
     v = Point(1, ca).normalize().origin(self.get_point(x, advised))
     v.in_math_bounding_box = False
     return v
예제 #7
0
    def __init__(self, op, P, a, b, c):
        from yanntricks.src.segment import Segment
        from yanntricks.src.point import Point
        ObjectGraph.__init__(self, self)
        self.op = op
        self.P = P
        self.Px = P[0]
        self.Py = P[1]
        self.a = a
        self.b = b
        self.c = c
        self.transparent = True

        self.A = [
            Point(self.Px, self.Py + b),
            Point(self.Px + a, self.Py + b),
            Point(self.Px + a, self.Py),
            Point(self.Px, self.Py)
        ]

        # The points on the first and second rectangle
        self.c1 = [self.op.point(P.x, P.y, 0) for P in self.A]
        self.c2 = [self.op.point(P.x, P.y, self.c) for P in self.A]

        self.A = self.c1[0]
        self.B = self.c1[1]
        self.C = self.c1[2]
        self.D = self.c1[3]
        self.E = self.c2[0]
        self.F = self.c2[1]
        self.G = self.c2[2]
        self.H = self.c2[3]

        for P in self.c1:
            P.parameters.symbol = ""
        for P in self.c2:
            P.parameters.symbol = ""

        # The edges.
        self.segP = [
            Segment(self.c1[i], self.c2[i]) for i in range(0, len(self.c1))
        ]
        self.segc1 = [
            Segment(self.c1[i], self.c1[(i + 1) % len(self.c1)])
            for i in range(0, len(self.c1))
        ]
        self.segc2 = [
            Segment(self.c2[i], self.c2[(i + 1) % len(self.c2)])
            for i in range(0, len(self.c2))
        ]

        if op.alpha < 90:
            self.segP[3].parameters.style = "dashed"
            self.segc2[2].parameters.style = "dashed"
            self.segc2[3].parameters.style = "dashed"
        else:
            self.segP[2].parameters.style = "dashed"
            self.segc2[2].parameters.style = "dashed"
            self.segc2[1].parameters.style = "dashed"
예제 #8
0
 def _bounding_box(self, pspict=None):
     from yanntricks.src.BoundingBox import BoundingBox
     xmin = self.xmin(self.llamI, self.llamF)
     xmax = self.xmax(self.llamI, self.llamF)
     ymin = self.ymin(self.llamI, self.llamF)
     ymax = self.ymax(self.llamI, self.llamF)
     bb = BoundingBox(Point(xmin, ymin), Point(xmax, ymax))
     return bb
예제 #9
0
 def getVertex(self, pos):
     from yanntricks.src.point import Point
     if pos == "NE":
         return Point(self.xmax, self.ymax)
     if pos == "NW":
         return Point(self.xmin, self.ymax)
     if pos == "SE":
         return Point(self.xmax, self.ymin)
     if pos == "SW":
         return Point(self.xmin, self.ymin)
예제 #10
0
    def __init__(self, P, text, hide=True):
        from yanntricks.src.Constructors import Mark
        from yanntricks.src.Constructors import Rectangle
        ObjectGraph.__init__(self, self)
        self.P = P
        self.text = text
        self.mark = Mark(self, 0, 0, self.text)
        self.hide = hide

        # This is fake; just to have an object to act on.
        self.rectangle = Rectangle(Point(0, 0), Point(1, 1))
        self.rectangle.parameters.filled()
        self.rectangle.parameters.fill.color = "white"
        self.rectangle.parameters.style = "none"
def test_vector_equality():
    echo_function("test_vector_equality")

    A = Point(1, 1)
    B = Point(2, -3)

    vv = AffineVector(A, B)
    ww = AffineVector(A, B)

    echo_single_test("Two trivial equalities")
    assert_equal(vv, vv)
    assert_equal(ww, ww)

    echo_single_test("One less trivial equalities")
    assert_equal(vv, ww)
예제 #12
0
def polar_to_visual_polar(r, theta, pspict=None):
    """
    From '(r,theta)', return the (s,alpha) such that the point
    (s,alpha) visually appears as (r,theta).
    """
    P = visual_polar(Point(0, 0), r, theta, pspict)
    return P.polar_coordinates()
예제 #13
0
def PolarSegment(P, r, theta):
    """
    return a segment on the base point P (class Point) of 
    length r and angle theta (degree)
    """
    alpha = radian(theta)
    return Segment(P, Point(P.x + r * cos(alpha), P.y + r * sin(alpha)))
예제 #14
0
    def get_tangent_vector(self, llam, advised=False):
        """
        returns the tangent vector to the curve for the value of the parameter given by llam.
           The vector is normed to 1.

        INPUT::

        - ``llam`` - the value of the parameter on which we want the tangent.

        - ``advised`` - (default = False) if True, the initial point is returned with its
                        advised_mark_angle. This takes quite a long time of computation
                        (and creates infinite loops in some circumstances)

        EXAMPLES::

            sage: from yanntricks import *
            sage: F=ParametricCurve(x,x**2)
            sage: print F.get_tangent_vector(0)
            <vector I=<Point(0,0)> F=<Point(1,0)>>
            sage: print F.get_tangent_vector(1)
            <vector I=<Point(1,1)> F=<Point(1/5*sqrt(5) + 1,2/5*sqrt(5) + 1)>>
        """
        from yanntricks.src.Constructors import AffineVector
        initial = self.get_point(llam, advised)
        return AffineVector(
            initial,
            Point(initial.x + self.derivative().f1(llam),
                  initial.y + self.derivative().f2(llam))).normalize()
예제 #15
0
 def action_on_pspict(self, pspict):
     from yanntricks.src.SmallComputations import MainGridArray
     from yanntricks.src.SmallComputations import SubGridArray
     a = []
     # ++++++++++++ Border ++++++++
     if self.draw_border:
         # Right border
         if self.draw_vertical_grid:
             if self.BB.xmax != int(self.BB.xmax):
                 S = self.BB.east_segment()
                 S.merge_options(self.border)
                 a.append(S)
         # Left border
         if self.draw_vertical_grid:
             if self.BB.xmin != int(self.BB.xmin):
                 S = self.BB.west_segment()
                 S.merge_options(self.border)
                 a.append(S)
         # Upper border
         if self.draw_horizontal_grid:
             if self.BB.ymax != int(self.BB.ymax):
                 S = self.BB.north_segment()
                 S.merge_options(self.border)
                 a.append(S)
         # Lower border
         if self.draw_horizontal_grid:
             if self.BB.ymin != int(self.BB.ymin):
                 S = self.BB.south_segment()
                 S.merge_options(self.border)
                 a.append(S)
     if self.draw_vertical_grid:
         # ++++++++++++ Principal vertical lines ++++++++
         for x in MainGridArray(self.BB.xmin, self.BB.xmax, self.Dx):
             S = Segment(Point(x, self.BB.ymin), Point(x, self.BB.ymax))
             S.merge_options(self.main_vertical)
             a.append(S)
         # ++++++++++++ The vertical sub grid ++++++++
         if self.num_subX != 0:
             for x in SubGridArray(self.BB.xmin, self.BB.xmax, self.Dx,
                                   self.num_subX):
                 S = Segment(Point(x, self.BB.ymin), Point(x, self.BB.ymax))
                 S.merge_options(self.sub_vertical)
                 a.append(S)
     if self.draw_horizontal_grid:
         # ++++++++++++ The horizontal sub grid ++++++++
         if self.num_subY != 0:
             for y in SubGridArray(self.BB.ymin, self.BB.ymax, self.Dy,
                                   self.num_subY):
                 S = Segment(Point(self.BB.xmin, y), Point(self.BB.xmax, y))
                 S.merge_options(self.sub_horizontal)
                 a.append(S)
         # ++++++++++++ Principal horizontal lines ++++++++
         for y in MainGridArray(self.BB.ymin, self.BB.ymax, self.Dy):
             S = Segment(Point(self.BB.xmin, y), Point(self.BB.xmax, y))
             S.merge_options(self.main_horizontal)
             a.append(S)
     pspict.DrawGraphs(a, separator_name=self.separator_name)
 def F(self):
     from yanntricks.src.point import Point
     if not self.do_cut_y:
         Mx = self.Mx
     else:
         Mx = self.pieces[0].Mx
     P = Point(Mx, self(Mx))
     return P
예제 #17
0
def Vector(A, B=None):
    """
    Return an affine vector from (0,0) to the given point.

    Vector(3,4)
    Vector(P)  # If 'P' is a point
    Vector(t)  # if 't' is a tuple of two numbers
    """
    O = Point(0, 0)
    if isinstance(A, Point):
        return AffineVector(O, A)
    if isinstance(A, tuple):
        if len(A) != 2:
            raise TypeError(f"You can define a vector from a tuple "
                            f"of length 2, not {len(A)}")
        return AffineVector(O, Point(A[0], A[1]))
    return AffineVector(Point(0, 0), Point(A, B))
 def I(self):
     from yanntricks.src.point import Point
     if not self.do_cut_y:
         mx = self.mx
     else:
         mx = self.pieces[0].mx
     P = Point(mx, self(mx))
     return P
예제 #19
0
    def decomposition(self, seg):
        # we make the computations with vectors based at (0,0)
        # and then translate the answer.
        from yanntricks.src.Constructors import Vector
        s0 = self.fix_origin(Point(0, 0))
        if isinstance(seg, AffineVector):
            v = seg.segment()
        seg0 = seg.fix_origin(Point(0, 0))

        A = s0.F.projection(seg0)
        paral0 = Vector(A)

        perp0 = s0 - paral0

        ans_paral = paral0.fix_origin(self.I)
        ans_perp = perp0.fix_origin(self.I)

        return ans_perp, ans_paral
예제 #20
0
    def __neg__(self):
        """
        return -self. 

        That is an affine vector attached to the same point, but
        with the opposite direction.
        """
        nx = self.I.x - self.Dx
        ny = self.I.y - self.Dy
        return AffineVector(self.I, Point(nx, ny))
예제 #21
0
    def visual_angleIF(self, pspict):
        from yanntricks.src.point import Point
        from yanntricks.src.AngleMeasure import AngleMeasure
        aI1 = visual_polar_coordinates(
            Point(cos(self.angleI.radian), sin(self.angleI.radian)),
            pspict).measure
        aF1 = visual_polar_coordinates(
            Point(cos(self.angleF.radian), sin(self.angleF.radian)),
            pspict).measure

        a = numerical_approx(aI1.degree)
        b = numerical_approx(aF1.degree)
        if a > b:
            a = a - 360
            aI2 = AngleMeasure(value_degree=a)
        else:
            aI2 = aI1
        aF2 = aF1
        return aI2, aF2
예제 #22
0
 def get_osculating_circle(self, llam):
     """Return the osculating circle to the parametric curve."""
     from yanntricks.src.Constructors import CircleOA
     P = self.get_point(llam)
     first = self.get_derivative(llam, 1)
     second = self.get_derivative(llam, 2)
     coefficient = (first.x**2+first.y**2) / \
         (first.x*second.y-second.x*first.y)
     Ox = P.x - first.y * coefficient
     Oy = P.y + first.x * coefficient
     center = Point(Ox, Oy)
     return CircleOA(center, P)
예제 #23
0
def test_imaginary_part_point(P, epsilon=0.0001):
    """
    Return the tuple '(isreal,P)'.

    The same description of 'test_imaginary_part'
    """
    from yanntricks.src.point import Point
    realx, x = test_imaginary_part(P.x, epsilon)
    realy, y = test_imaginary_part(P.y, epsilon)
    on = False
    if realx and realy:
        on = True
    return on, Point(x, y)
예제 #24
0
def SurfaceUnderFunction(f, mx, Mx):
    """
    Represent a surface under a function.

    This is a particular case of SurfaceBetweenFunctions when
    the second function is the y=0 axis.

    The function `f` becomes `self.f1` while self.f2 will be the
    function 0 (this is a consequence of inheritance).
    The function f will also be recorded as self.f.

    INPUT:

    - ``f`` - a function
    - ``mx,Mx`` - initial and final values 

    EXAMPLES:

    .. literalinclude:: yanntricksSurfaceFunction.py
    .. image:: Picture_FIGLabelFigSurfaceFunctionPICTSurfaceFunction-for_eps.png


    .. literalinclude:: yanntricksChiSquaresQuantile.py
    .. image:: Picture_FIGLabelFigChiSquaresQuantilePICTChiSquaresQuantile-for_eps.png

    """
    from yanntricks.src.NonAnalytic import NonAnalyticFunctionGraph
    from yanntricks.src.segment import Segment
    from yanntricks.src.SurfacesGraph import SurfaceBetweenLines
    if isinstance(f, NonAnalyticFunctionGraph):
        line1 = Segment(Point(mx, 0), Point(Mx, 0))
        line2 = f.parametric_curve(mx, Mx)
        surf = SurfaceBetweenLines(line1, line2)
        return surf
    f2 = phyFunction(0)
    f2.nul_function = True  # See 2252914222
    return SurfaceBetweenFunctions(f, f2, mx=mx, Mx=Mx)
예제 #25
0
def visual_polar_coordinates(P, pspict=None):
    """
    return the visual polar coordinates of 'P'
    """
    if pspict is None:
        return P.polar_coordinates()
    if isinstance(pspict, list):
        xu = pspict[0].xunit
        yu = pspict[0].xunit
        xunits = [psp.xunit == xu for psp in pspict]
        yunits = [psp.yunit == yu for psp in pspict]
        if sum(xunits) == len(xunits) and sum(yunits) == len(yunits):
            xunit = xu
            yunit = yu
        else:
            print(
                "Probably more than one picture with different dilatations ..."
            )
            raise ValueError
    else:
        xunit = pspict.xunit
        yunit = pspict.yunit
    Q = Point(xunit * P.x, yunit * P.y)
    return Q.polar_coordinates()
예제 #26
0
def PolarPoint(r, theta):
    """
    return the point at polar coordinates (r,theta).

    INPUT:

    - ``r`` - the distance from origine
    - ``theta`` - the angle

    EXAMPLES::

        sage: from yanntricks import *
        sage: print PolarPoint(2,45)
        <Point(sqrt(2),sqrt(2))>
    """
    return Point(r * cos(radian(theta)), r * sin(radian(theta)))
def test_visual_length():
    echo_function("test_visual_length")

    with SilentOutput():
        pspict, fig = SinglePicture("ZZTHooTeGyMT")

    v = AffineVector(Point(0, 0), Point(0, sin(0.5 * pi)))
    w = visual_length(v, 0.1, pspict=pspict)
    ans = AffineVector(Point(0, 0), Point(0, 0.1))

    echo_single_test("positive")
    assert_equal(w, ans)

    echo_single_test("negative")
    v = AffineVector(Point(0, 0), Point(0, -sin(0.5 * pi)))
    w = visual_length(v, 0.1, pspict=pspict)
    ans = AffineVector(Point(0, 0), Point(0, -0.1))
    assert_equal(w, ans)
예제 #28
0
    def graph(self, xvalues=None, yvalues=None, draw_points=None):
        """
        return a graph of self with the given points

        INPUT:

        - ``xvalues`` - tuple (x,mx,My,n) interval and number of points with respect to X.

        - ``yvalues`` - tuple (y,my,My,n) interval and number of points with respect to Y.

        - ``draw_points`` - (defaulf : empty list) a list of points.

        If xvalues is given, then yvalues has to be given.

        OUTPUT:

        object VectorFieldGraph.

        EXAMPLES::

            sage: from yanntricks.BasicGeometricObjects import *
            sage: x,y=var('x,y')
            sage: F=VectorField(x,y).graph(xvalues=(x,-2,2,3),yvalues=(y,-10,10,3),draw_points=[Point(100,100)])
            sage: print F.draw_points[0]
            <Point(100,100)>
            sage: print len(F.draw_points)
            10
        """
        if draw_points is None:
            draw_points = []
        if xvalues is not None:
            mx = xvalues[1]
            Mx = xvalues[2]
            nx = xvalues[3]
            my = yvalues[1]
            My = yvalues[2]
            ny = yvalues[3]
            from numpy import linspace
            pos_x = linspace(mx, Mx, nx)
            pos_y = linspace(my, numerical_approx(My), ny)
            for xx in pos_x:
                for yy in pos_y:
                    draw_points.append(Point(xx, yy))
        return VectorFieldGraph(self, draw_points=draw_points)
예제 #29
0
    def __init__(self, name="CAN_BE_A_PROBLEM_IF_TRY_TO_PRODUCE_EPS_OR_PDF"):
        r"""

        - `self.BB` is the bounding box for LaTeX purpose.

        - `self.math_BB` is the bounding box of objects that
           are "mathematically relevant". This bounding box does
           not take into account marks of points and thinks like
           that. This is the bounding box that is going to be used
           for the axes and the grid.
        When a graph object has a method math_bounding_box,
        this is the one taken into account in the math_BB here.
        """
        from yanntricks.src.GridGraph import Grid
        from yanntricks.src.AxesGraph import Axes
        self.paths = PathsKeeper()
        self.name = name
        # for the intermediate files.

        # A comment. This is not used to create the picture;
        # the purpose is to remember a specific feature to be
        # tested when recompiling.
        self.comment = ""

        self.tikzfile = self.paths.create("sage_dir", f"tikz{self.name}")

        self.mother = None
        self.figure_mother = None
        self.language = "tikz"
        self.pstricks_code_list = []
        self.newwriteDone = False

        # self.interWriteFile is redefined in MultiplePictures

        self.record_marks = []
        self.record_bounding_box = []
        self.record_draw_graph = []
        self.record_draw_bb = []
        self.record_force_math_bounding_box = []
        # self.record_math_BB=[]
        # self.record_BB=[]
        self.counterDone = False
        self.newlengthDone = False
        self.listePoint = []
        self.xunit = 1
        self.yunit = 1
        self.xsize = None
        self.ysize = None
        self.rotation_angle = None
        self.LabelSep = 1
        self.BB = BoundingBox(mother=self)
        self.math_BB = BoundingBox(is_math=True)
        # self.BB and self.math_BB serve to add some objects by hand.
        # If you need the bounding box, use self.bounding_box()
        # or self.math_bounding_box()
        self.axes = Axes(Point(0, 0), BoundingBox(), pspict=self)
        self.single_axeX = self.axes.single_axeX
        self.single_axeY = self.axes.single_axeY
        self.single_axeX.pspict = self
        self.single_axeY.pspict = self
        self.draw_default_axes = False

        self.mx_acceptable_BB = -100
        self.my_acceptable_BB = -100
        self.Mx_acceptable_BB = 100
        self.My_acceptable_BB = 100

        self.grid = Grid(BoundingBox())

        # The order of declaration is important, because
        # it is recorded in the Separator.number attribute.
        self.separator_list = init_picture_separator_list()
        self.entete_position = "ENTETE PSPICTURE"

        self.auxiliary_file = AuxFile(self.name, picture=self)
예제 #30
0
 def get_point(self, x, advised=False):
     from yanntricks.src.point import Point
     return Point(self.f1(x), self.f2(x))