Esempio n. 1
0
    def _bounding_box(self, pspict=None):
        """
        return the bounding box of the point including its mark

        A small box of radius 0.1 (modulo xunit,yunit[1]) is given in any case.
        You need to provide a pspict in order to compute the size since
        it can vary from the place in your document you place the figure.

        [1] If you dont't know what is the "bounding box", or if you don't wan
        t to fine tune it, you don't care.
        """
        from yanntricks.src.BoundingBox import BoundingBox
        if pspict == None:
            print("You should consider to give a Picture as argument. \
                    Otherwise the boundig box of %s could be bad" % str(self))
            xunit = 1
            yunit = 1
        else:
            xunit = pspict.xunit
            yunit = pspict.yunit
        Xradius = 0.1 / xunit
        Yradius = 0.1 / yunit
        bb = BoundingBox(Point(self.x - Xradius, self.y - Yradius),
                         Point(self.x + Xradius, self.y + Yradius))
        for obj in self.added_objects[pspict]:
            bb.append(obj, pspict)
        return bb
Esempio n. 2
0
 def _bounding_box(self, pspict=None):
     from yanntricks.src.BoundingBox import BoundingBox
     from yanntricks.src.segment import Segment
     if pspict == None:
         raise ValueError("You have to provide a pspict")
     bb = BoundingBox()
     bb.append(self.curve1, pspict)
     bb.append(self.curve2, pspict)
     return bb
Esempio n. 3
0
 def getSecondBox(self, pspict):
     from yanntricks.src.BoundingBox import BoundingBox
     bb = BoundingBox()
     bb.append(self.getLine(1).getSecondBox(pspict), pspict=pspict)
     bb.append(self.getLine(self.nlines).getSecondBox(pspict),
               pspict=pspict)
     bb.append(self.getColumn(1).getSecondBox(pspict), pspict=pspict)
     bb.append(self.getColumn(self.ncolumns).getSecondBox(pspict),
               pspict=pspict)
     return bb
Esempio n. 4
0
    def _bounding_box(self, pspict=None):
        """
        Return the bounding box of the implicit curve.

        This is NOT the bounding box got that one could expect
        using Sage's plotting system
        implicit_plot(f,xrange,yrange).get_minmax_data()

        Instead the bounding box returned here only contains the points that
        are actually plotted. In the following example, we know that the ymax
        has to be half the sqrt of the radius (and not the 5 given in yrange).

        EXAMPLES::

            sage: from yanntricks import *
            sage: x,y=var('x,y')
            sage: f=x**2+2*y**2
            sage: G=ImplicitCurve(f==sqrt(2),(x,-5,5),(y,-5,5),plot_points=200)
            sage: print G.bounding_box()
            <BoundingBox xmin=-1.188,xmax=1.188; ymin=-0.841,ymax=0.841>
        """
        from yanntricks.src.BoundingBox import BoundingBox
        bb = BoundingBox(Point(self.xmin(), self.ymin()),
                         Point(self.xmax(), self.ymax()))
        return bb
Esempio n. 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"
Esempio n. 6
0
 def _math_bounding_box(self, pspict=None):
     from yanntricks.src.BoundingBox import BoundingBox
     xmin = self.get_minmax_data(self.mx, self.Mx)["xmin"]
     xmax = self.get_minmax_data(self.mx, self.Mx)["xmax"]
     ymin = self.get_minmax_data(self.mx, self.Mx)["ymin"]
     ymax = self.get_minmax_data(self.mx, self.Mx)["ymax"]
     return BoundingBox(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
Esempio n. 7
0
 def getSecondBox(self, pspict):
     from yanntricks.src.BoundingBox import BoundingBox
     xmin = min([el.getSecondBox(pspict).xmin for el in self])
     ymin = min([el.getSecondBox(pspict).ymin for el in self])
     xmax = max([el.getSecondBox(pspict).xmax for el in self])
     ymax = max([el.getSecondBox(pspict).ymax for el in self])
     return BoundingBox(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
    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
Esempio n. 9
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
Esempio n. 10
0
 def getSecondBox(self, pspict):
     from yanntricks.src.BoundingBox import BoundingBox
     first_box = self.getFirstBox(pspict)
     xmin = first_box.xmin - MATRIX_ELEMENT_SECOND_BOX_X_BORDER
     xmax = first_box.xmax + MATRIX_ELEMENT_SECOND_BOX_X_BORDER
     ymin = first_box.ymin - MATRIX_ELEMENT_SECOND_BOX_Y_BORDER
     ymax = first_box.ymax + MATRIX_ELEMENT_SECOND_BOX_Y_BORDER
     return BoundingBox(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
Esempio n. 11
0
 def getFirstBox(self, pspict):
     from yanntricks.src.BoundingBox import BoundingBox
     text_box = self.getTextBox(pspict)
     xmin = text_box.xmin - MATRIX_ELEMENT_FIRST_BOX_X_BORDER
     xmax = text_box.xmax + MATRIX_ELEMENT_FIRST_BOX_X_BORDER
     ymin = text_box.ymin - MATRIX_ELEMENT_FIRST_BOX_Y_BORDER
     ymax = text_box.ymax + MATRIX_ELEMENT_FIRST_BOX_Y_BORDER
     return BoundingBox(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
Esempio n. 12
0
 def getTextBox(self, pspict):
     from yanntricks.src.BoundingBox import BoundingBox
     text_width, text_height = self.getTextSize(pspict)
     xmin = self.central_point.x - text_width / 2
     xmax = self.central_point.x + text_width / 2
     ymin = self.central_point.y - text_height / 2
     ymax = self.central_point.y + text_height / 2
     return BoundingBox(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
 def _bounding_box(self, pspict=None):
     from yanntricks.src.BoundingBox import BoundingBox
     if self.do_cut_y and len(self.pieces) > 0:
         # In this case, we will in any case look for the
         # bounding boxes
         # of the pieces.
         # Notice that it can happen that self.do_cut_y=True but
         # that only one piece is found.
         return BoundingBox()
     return self.parametric_curve().bounding_box()
Esempio n. 14
0
    def _math_bounding_box(self, pspict=None):
        from yanntricks.src.BoundingBox import BoundingBox
        BB = BoundingBox()
        BB.append(self.single_axeX.bounding_box(pspict), pspict)
        BB.append(self.single_axeY.bounding_box(pspict), pspict)

        if self.pspict:
            BB.append(self.pspict.math_bounding_box(), pspict)
        # Updates the single axes taking the content of pspict into account.
        self.add_bounding_box(BB, pspict)
        BB.check_too_large()
        return BB
Esempio n. 15
0
    def _math_bounding_box(self, pspict=None):
        ##
        #   Return a bounding box which include itself and that's it.

        # Here one cannot use BoundingBox(self.point,self.point) because
        # it creates infinite loop.
        from yanntricks.src.BoundingBox import BoundingBox
        bb = BoundingBox(xmin=self.point.x,
                         xmax=self.point.x,
                         ymin=self.point.y,
                         ymax=self.point.y)
        return bb
Esempio n. 16
0
def Rectangle(*args, **arg):
    """
    INPUT:

    - ``NW,SE`` - the North-West corner and South-East corner

    Alternatively, you can pass a bounding box as unique argument.

    Still alternatively, you can pass xmin,ymin,xmax,ymax
    """
    from yanntricks.src.BoundingBox import BoundingBox
    if len(args) == 2:
        NW = args[0]
        SE = args[1]
    if len(args) == 1:
        NW = args[0].NW()
        SE = args[0].SE()
    if "xmin" in arg:
        bb = BoundingBox(xmin=arg["xmin"],
                         ymin=arg["ymin"],
                         xmax=arg["xmax"],
                         ymax=arg["ymax"])
        # TODO : I should be able to pass directly the dictionary to BoundingBox
        NW = bb.getVertex("NW")
        SE = bb.getVertex("SE")
    if "mx" in arg:
        bb = BoundingBox(xmin=arg["mx"],
                         ymin=arg["my"],
                         xmax=arg["Mx"],
                         ymax=arg["My"])
        # TODO : I should be able to pass directly the dictionary to BoundingBox
        NW = bb.getVertex("NW")
        SE = bb.getVertex("SE")
    from yanntricks.src.RectangleGraph import RectangleGraph
    return RectangleGraph(NW, SE)
Esempio n. 17
0
 def _bounding_box(self, pspict):
     from yanntricks.src.BoundingBox import BoundingBox
     bb = BoundingBox()
     bb.addX(self.minimum)
     bb.addX(self.maximum)
     bb.addY(self.delta_y - self.h / 2)
     bb.addY(self.delta_y + self.h / 2)
     return bb
Esempio n. 18
0
 def _bounding_box(self, pspict=None):
     from yanntricks.src.BoundingBox import BoundingBox
     bb = BoundingBox()
     for s in self.c1:
         bb.append(s, pspict)
     for s in self.c2:
         bb.append(s, pspict)
     return bb
Esempio n. 19
0
    def _bounding_box(self, pspict=None):
        """
        return the bounding box of the axes.

        If `self` is a default axe, it take into account the
        content of the pspicture and update the mx,my of the
        single axes X and Y.
        """
        from yanntricks.src.BoundingBox import BoundingBox
        BB = BoundingBox()
        BB.append(self.single_axeX.bounding_box(pspict), pspict)
        BB.append(self.single_axeY.bounding_box(pspict), pspict)

        if self.pspict:
            BB.append(self.pspict.math_bounding_box(), pspict)
        # Update the single axes taking the content of pspict into account.
        self.add_bounding_box(BB, pspict)
        BB.check_too_large()
        return BB
Esempio n. 20
0
 def _math_bounding_box(self, pspict):
     # pylint: disable=unused-argument
     # The math_bounding box does not take into account the things
     # that are inside the picture (not even if this are default axes)
     from yanntricks.src.BoundingBox import BoundingBox
     bb = BoundingBox()
     for x, _ in self.axes_unit.place_list(self.mx,
                                           self.Mx,
                                           self.Dx,
                                           self.mark_origin):
         P = (x*self.base).F
         bb.addX(P.x)
         bb.addY(P.y)
     return bb
 def _math_bounding_box(self,pspict):
     from yanntricks.src.BoundingBox import BoundingBox
     bb=BoundingBox()
     for l in self.lines_list:
         bb.append(l,pspict)
     return bb
Esempio n. 22
0
 def _bounding_box(self, pspict):
     from yanntricks.src.BoundingBox import BoundingBox
     from yanntricks.src.conversion_angles import simplify_degree
     a = simplify_degree(self.angleI, keep_max=True, number=True)
     b = simplify_degree(self.angleF, keep_max=True, number=True)
     if self.angleI < self.angleF:
         angleI = min(a, b)
         angleF = max(a, b)
     else:
         angleI = max(a, b)
         angleF = min(a, b) + 360
     pI = self.get_point(angleI)
     pF = self.get_point(angleF)
     bb = BoundingBox(self.center, self.center)
     bb.append(pI, pspict)
     bb.append(pF, pspict)
     if angleI == 0:
         bb.addX(self.center.x + self.radius)
     if angleI < 90 and angleF > 90:
         bb.addY(self.center.y + self.radius)
     if angleI < 180 and angleF > 180:
         bb.addX(self.center.x - self.radius)
     if angleI < 270 and angleF > 270:
         bb.addY(self.center.y - self.radius)
     return bb
Esempio n. 23
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)
Esempio n. 24
0
class Picture:
    r"""
    Describe a Picture

    METHODS:

    - `self.latex_code()` - contains the tikz code of what has
    to be between \begin{tikz} and \end{tikz}. This is not
    the environment itself, neither the definition of xunit, yunit.

    The name of the pspict is used to produce intermediate
    filesnames, and other names.
    """
    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)

    def tikz_code(self):
        """
        It also remove the tikz externalize file.
        """
        self.create_latex_code(language="tikz", pspict=self)
        add_latex_line_entete(self)
        self.add_latex_line(
            "\\tikzsetnextfilename{{{0}}}".format(self.tikzfile.from_sage()),
            "BEGIN PSPICTURE")
        self.add_latex_line(
            "\\begin{{tikzpicture}}[xscale={0},"
            "yscale={1},inner sep=2.25pt,outer sep=0pt]".format(1, 1),
            "BEGIN PSPICTURE")
        self.add_latex_line("\\end{tikzpicture}", "END PSPICTURE")

        self.xsize = self.bounding_box(pspict=self).xsize()
        self.ysize = self.bounding_box(pspict=self).ysize()
        return self.separator_list.code()

    def visual_xsize(self):
        return numerical_approx(self.xsize * self.xunit)

    def visual_ysize(self):
        return numerical_approx(self.ysize * self.yunit)

    def create_latex_code(self, language=None, pspict=None):
        """
        Fix the bounding box and create the separator "PSTRICKS CODE".

        NOTES :

        - This function is not supposed to be used twice. In fact, this is
          supposed to be called only from `lazy_attributes`

        """
        # Here we are supposed to be  sure of the xunit, yunit,
        # so we can compute the BB's needed for the points with marks.
        # For the same reason, all the marks that were asked
        # to be drawn are added now.
        # Most of the difficulty is when the user uses
        # picture.dilatation_X and Y with different coefficients.
        # TODO : take it into account.

        list_to_be_drawn = [a for a in self.record_draw_graph if a.take_graph]

        list_used_separators = []

        # STEP : update the bounding box
        for x in list_to_be_drawn:
            self.BB.append(x.graph, self)

            # The math_BB is updated in DrawGraph    February 21, 2015
            # This allow to enlarge the BB by hand with something like
            #    pspict.math_BB.ymax+=1
            # placed after DrawGraph

        # STEP : add the LaTeX code of each element
        for x in list_to_be_drawn:
            graph = x.graph

            # If the graph is a bounding box of a mark, we recompute it
            # because a dilatation of the figure could have
            # changed the bounding box.
            # Same for the bounding box of the pspicture,
            # since it is not know before now
            if isinstance(graph, BoundingBox):
                if graph.mother:
                    print("I'm drawing the bounding box of ", graph.mother)
                    graph = graph.mother.bounding_box(self)
            separator_name = x.separator_name
            try:
                self.add_latex_line(ligne=graph.latex_code(
                    language=self.language, pspict=self),
                                    separator_name=separator_name)
                list_used_separators.append(separator_name)
            except AttributeError as data:
                if not "latex_code" in dir(graph):
                    print(
                        "yanntricks error: object %s has no pstricks_code method"
                        % (str(graph)))
                raise
        self.separator_list.fusion(list_used_separators, "PSTRICKS CODE")

    def test_dilatation_first(self, fact):
        """
        Return True if nothing is already done on the picture.

        The dilatation has to be the first information given
        to a pictute. The aim of this function is to raise an
        exception when one tries to use
        pspict.dilatation(...)
        after having used 'DrawGraphs'
        """
        if self.record_draw_graph and fact != 1:
            raise ShouldNotHappenException(
                "Dilatation has to be "
                "given right after the creation of the picture.")

    def dilatation(self, fact):
        self.dilatation_X(fact)
        self.dilatation_Y(fact)

    def dilatation_X(self, fact):
        self.test_dilatation_first(fact)
        self.xunit = self.xunit * fact

    def dilatation_Y(self, fact):
        self.test_dilatation_first(fact)
        self.yunit = self.yunit * fact

    def rotation(self, angle):
        self.rotation_angle = angle

    def math_bounding_box(self, pspict=None):
        """
        Update and return the math bounding box of the picture.
        """
        pspict = pspict or self
        math_list = [x.graph for x in self.record_draw_graph]
        math_list.extend(self.record_force_math_bounding_box)
        for a in [g for g in math_list if g.take_math_BB]:
            self.math_BB.AddBB(a.math_bounding_box(pspict=pspict))
        return self.math_BB

    def bounding_box(self, pspict=None):
        """Update and return the bounding box of the picture."""
        # The math bounding box of the picture has to be computed in the
        # function 'DrawDefaultAxes'. But the axes themselves have
        # to be taken into account in the bounding box of the picture.
        pspict = pspict or self

        self.BB.append(self.math_bounding_box(), pspict=pspict)

        def condition(x):
            if x.take_BB:
                return True
            if x.take_math_BB:
                return True
            return False

        for a in sublist(self.record_draw_graph, condition):
            self.BB.AddBB(a.graph.bounding_box(pspict=pspict))
        return self.BB

    def DrawBoundingBox(self, obj=None):
        """Draw the bounding box of the object.

        Draw the bounding box of the object when it
        has a method bounding_box

        If not, assume that the object is the bounding box to be drawn.
        If no object are given, draw its own bounding box
        """
        if not obj:
            obj = self
        self.record_bounding_box.append(obj)

    def deal_with_graph(self, gr, separator_name):
        from yanntricks.src.ObjectGraph import AddedObjects
        if isinstance(gr, AddedObjects):
            self.DrawGraphs(gr[self])
            return None
        if isinstance(gr, collections.Iterable):
            for h in gr:
                self.DrawGraphs(h, separator_name=separator_name)
            return None
        self._DrawGraph(gr, separator_name=separator_name)
        return None

    def DrawGraphs(self, *args, **arg):
        """
        The function DrawGraphs basically takes a list of objects and performs
        different kind of operation following the type of each "object" :

        If the object it iterable, its elements are re-passed to DrawGraphs
        If the object is an instance of "ObjectGraph", it is passed to
        _DrawGraph
        If the object is 'AddedObject', the list corresponding to 'self' is
        re-passed to DrawGraphs.

    """
        if "separator_name" not in arg:
            separator_name = "DEFAULT"
        else:
            separator_name = arg["separator_name"]

        # Here is why objects intended to be drawn cannot be iterable.
        # Position 30282-11562
        for gr in args:
            self.deal_with_graph(gr, separator_name)

    def _DrawGraph(self, graph, separator_name=None):
        """
        Draw an object of type `<Something>Graph`.

        More generally, it can draw anything that has the methods

            1. bounding_box
            2. tikz_code

        The first one should return a bounding box and the
        second one should return a valid tikz code as string.

        NOTE:

        More precisely, it does not draw the object now, but it
        adds it (and its mark if applicable) to
        `self.record_draw_graph` which is the list of objects
        to be drawn. Thus it is still possible to modify the
        object later (even if extremely discouraged).
        """
        from yanntricks.src.ObjectGraph import ObjectGraph
        if not isinstance(graph, ObjectGraph):
            raise NotObjectGraphException(graph)

        if isinstance(graph, phyFunctionGraph):
            if graph.mx is None or graph.Mx is None:
                raise TypeError("You cannot draw phyFunction but only graph.")
        if separator_name is None:
            try:
                separator_name = graph.separator_name
            except AttributeError:
                separator_name = "DEFAULT"
        x = DrawElement(graph, separator_name)
        self.record_draw_graph.append(x)

        # If an object has a mark, it the latter is already
        # in the 'added_objects' list and the mark is already passed
        # to a DrawGraph. Adding here the mark to the "record_draw_graph"
        # list make pass twice by the computation of its bounding box
        # (and draw it twice)
        # Augustus 8, 2016
        # See position 3598-30738

        graph.conclude(self)
        self.math_BB.append(graph, self)
        graph._draw_added_objects(self)  # pylint:disable=protected-access
        graph.action_on_pspict(pspict=self)

    def DrawDefaultAxes(self):
        """
        This function computes the bounding box of the axes and add
        them to the list to be drawn.

        The length of the axes is computed here
        (via self.math_bounding_box).

        Sometimes you want the axes to be slightly larger. You can impose
        the length of the axes.
        """
        self.axes.BB = self.math_bounding_box(pspict=self)
        self.DrawGraphs(self.axes)

    def DrawDefaultGrid(self):
        self.grid.BB = self.math_bounding_box(pspict=self)
        Dx = self.grid.Dx
        Dy = self.grid.Dy
        # Make the grid end on its "big" subdivisions.
        from yanntricks.src.SmallComputations import MultipleLower
        from yanntricks.src.SmallComputations import MultipleBigger
        self.grid.BB.xmin = MultipleLower(self.grid.BB.xmin, Dx)
        self.grid.BB.xmax = MultipleBigger(self.grid.BB.xmax, Dx)
        self.grid.BB.ymin = MultipleLower(self.grid.BB.ymin, Dy)
        self.grid.BB.ymax = MultipleBigger(self.grid.BB.ymax, Dy)
        self.DrawGraphs(self.grid)

    def get_box_size(self, tex_expression, default_value="0pt"):
        return self.auxiliary_file.get_box_size(tex_expression, default_value)

    def add_latex_line(self,
                       ligne,
                       separator_name="DEFAULT",
                       add_line_jump=True):
        """
        Add a line in the pstricks code.

        The optional argument <position> is the name of a
        marker like %GRID, %AXES, ...
        """
        if separator_name is None:
            separator_name = "DEFAULT"
        self.separator_list[separator_name].add_latex_line(
            ligne, add_line_jump=add_line_jump)

    def force_math_bounding_box(self, g):
        """
        Add an object to the math bounding box of the pspicture.

        This object will not be drawn, but the axes and the grid
        will take it into account.
        """
        self.record_force_math_bounding_box.append(g)

    def test_if_test_file_is_present(self):
        from yanntricks.src.SmallComputations import Fichier
        test_file = Fichier("test_pspict_LaTeX_%s.tmp" % (self.name))
        return os.path.isfile(test_file.filename)

    def latex_code(self):
        """Return the LaTeX code of the pspicture"""
        self.add_latex_line(self.auxiliary_file.open_latex_code(),
                            "OPEN_WRITE_AND_LABEL")
        self.add_latex_line(self.auxiliary_file.latex_code(),
                            "WRITE_AND_LABEL")
        self.add_latex_line(self.auxiliary_file.close_latex_code(),
                            "CLOSE_WRITE_AND_LABEL")
        if self.language == "tikz":
            return self.tikz_code()
        raise NameError(f"Unknown language {self.language}."
                        f" tikz is the only one.")
 def _math_bounding_box(self, pspict=None):
     from yanntricks.src.BoundingBox import BoundingBox
     return BoundingBox()
Esempio n. 26
0
 def _math_bounding_box(self, pspict=None):
     from yanntricks.src.BoundingBox import BoundingBox
     BB = BoundingBox()
     BB.append(self.single_axeX.math_bounding_box(pspict), pspict=pspict)
     BB.append(self.single_axeY.math_bounding_box(pspict), pspict=pspict)
     return BB
Esempio n. 27
0
 def _bounding_box(self, pspict):
     from yanntricks.src.BoundingBox import BoundingBox
     if self.in_bounding_box:
         return BoundingBox(self.I, self.F)
     return BoundingBox()
Esempio n. 28
0
 def _math_bounding_box(self, pspict=None):
     # a text has no math_bounding_box because the axes do not want to fit them.
     # return self.mark.math_bounding_box(pspict)         # June 1, 2015
     from yanntricks.src.BoundingBox import BoundingBox
     return BoundingBox()
Esempio n. 29
0
 def _bounding_box(self, pspict=None):
     from yanntricks.src.BoundingBox import BoundingBox
     bb = BoundingBox()
     for v in self.draw_vectors:
         bb.append(v, pspict)
     return bb
Esempio n. 30
0
 def _math_bounding_box(self, pspict=None):
     from yanntricks.src.BoundingBox import BoundingBox
     if self.in_math_bounding_box:
         return self.bounding_box(pspict)
     return BoundingBox()