예제 #1
0
    def path(closed):
        if closed:
            yield "(%s,%s)--(%s,%s)--" % tuple(
                asy_number(t) for t in (x, y, sx, sy))

        yield "arc((%s,%s), (%s, %s), (%s, %s))" % tuple(
            asy_number(t) for t in (x, y, sx, sy, ex, ey))

        if closed:
            yield "--cycle"
예제 #2
0
def _roundbox(self, **options):
    x, y = self.c.pos()
    rx, ry = self.r.pos()
    rx -= x
    ry -= y
    line_width = self.style.get_line_width(face_element=self.face_element)
    pen = asy_create_pens(
        edge_color=self.edge_color,
        face_color=self.face_color,
        stroke_width=line_width,
        is_face_element=self.face_element,
    )
    cmd = "filldraw" if self.face_element else "draw"
    return "%s(ellipse((%s,%s),%s,%s), %s);" % (
        cmd,
        asy_number(x),
        asy_number(y),
        asy_number(rx),
        asy_number(ry),
        pen,
    )
예제 #3
0
    def boxes_to_tex(self, leaves=None, **options) -> str:
        if not leaves:
            leaves = self._leaves
            fields = self._prepare_elements(leaves, options, max_width=450)
            if len(fields) == 2:
                elements, calc_dimensions = fields
            else:
                elements, calc_dimensions = fields[0], fields[-2]

        fields = calc_dimensions()
        if len(fields) == 8:
            xmin, xmax, ymin, ymax, w, h, width, height = fields
            elements.view_width = w

        else:
            assert len(fields) == 9
            xmin, xmax, ymin, ymax, _, _, _, width, height = fields
            elements.view_width = width

        asy_completely_visible = "\n".join(
            lookup_method(element, "asy")(element)
            for element in elements.elements if element.is_completely_visible)

        asy_regular = "\n".join(
            lookup_method(element, "asy")(element)
            for element in elements.elements
            if not element.is_completely_visible)

        asy_box = "box((%s,%s), (%s,%s))" % (
            asy_number(xmin),
            asy_number(ymin),
            asy_number(xmax),
            asy_number(ymax),
        )

        if self.background_color is not None:
            color, opacity = asy_color(self.background_color)
            asy_background = "filldraw(%s, %s);" % (asy_box, color)
        else:
            asy_background = ""

        tex = r"""
\begin{asy}
usepackage("amsmath");
size(%scm, %scm);
%s
%s
clip(%s);
%s
\end{asy}
""" % (
            asy_number(width / 60),
            asy_number(height / 60),
            asy_background,
            asy_regular,
            asy_box,
            asy_completely_visible,
        )

        return tex
예제 #4
0
def rectanglebox(self, **options) -> str:
    line_width = self.style.get_line_width(face_element=True)
    x1, y1 = self.p1.pos()
    x2, y2 = self.p2.pos()
    pens = asy_create_pens(
        self.edge_color, self.face_color, line_width, is_face_element=True
    )
    x1, x2, y1, y2 = asy_number(x1), asy_number(x2), asy_number(y1), asy_number(y2)
    asy = "// RectangleBox\n"
    asy += "filldraw((%s,%s)--(%s,%s)--(%s,%s)--(%s,%s)--cycle, %s);" % (
        x1,
        y1,
        x2,
        y1,
        x2,
        y2,
        x1,
        y2,
        pens,
    )
    # print("### rectanglebox", asy)
    return asy
예제 #5
0
    def create_arc_path(is_closed: bool, yscale: float) -> str:
        """Constructs arc path taking into account whether the path
        is closed and the scaling along the Y dimension (i.e. Mathics
        disks support ellipses.

        An Asymptote string for the path is returned.
        """
        arc_path = ""
        if is_closed:
            arc_path = "(%s,%s)--(%s,%s)--" % tuple(
                asy_number(t) for t in (x, y, sx, sy)
            )

        arc_path += "arc((%s,%s), (%s, %s), (%s, %s))" % tuple(
            asy_number(t) for t in (x, y, sx, sy, ex, ey)
        )

        if is_closed:
            arc_path += "--cycle"

        if yscale != 1.0:
            arc_path = f"yscale({yscale}) * ({arc_path})"

        return arc_path
예제 #6
0
    def boxes_to_tex(self, leaves=None, **options) -> str:
        """This is the top-level function that converts a Mathics Expression
        in to something suitable for LaTeX.  (Yes, the name "tex" is
        perhaps misleading of vague.)

        However right now the only LaTeX support for graphics is via Asymptote and
        that seems to be the package of choice in general for LaTeX.
        """

        if not leaves:
            leaves = self._leaves
            fields = self._prepare_elements(leaves, options, max_width=450)
            if len(fields) == 2:
                elements, calc_dimensions = fields
            else:
                elements, calc_dimensions = fields[0], fields[-2]

        fields = calc_dimensions()
        if len(fields) == 8:
            xmin, xmax, ymin, ymax, w, h, width, height = fields
            elements.view_width = w

        else:
            assert len(fields) == 9
            xmin, xmax, ymin, ymax, _, _, _, width, height = fields
            elements.view_width = width

        asy_completely_visible = "\n".join(
            lookup_method(element, "asy")(element)
            for element in elements.elements if element.is_completely_visible)

        asy_regular = "\n".join(
            lookup_method(element, "asy")(element)
            for element in elements.elements
            if not element.is_completely_visible)

        asy_box = "box((%s,%s), (%s,%s))" % (
            asy_number(xmin),
            asy_number(ymin),
            asy_number(xmax),
            asy_number(ymax),
        )

        if self.background_color is not None:
            color, opacity = asy_color(self.background_color)
            asy_background = "filldraw(%s, %s);" % (asy_box, color)
        else:
            asy_background = ""

        tex = r"""
\begin{asy}
usepackage("amsmath");
size(%scm, %scm);
%s
%s
clip(%s);
%s
\end{asy}
""" % (
            asy_number(width / 60),
            asy_number(height / 60),
            asy_background,
            asy_regular,
            asy_box,
            asy_completely_visible,
        )

        return tex
예제 #7
0
    def boxes_to_tex(self, leaves=None, **options):
        if not leaves:
            leaves = self._leaves

        (
            elements,
            axes,
            ticks,
            ticks_style,
            calc_dimensions,
            boxscale,
        ) = self._prepare_elements(leaves, options, max_width=450)

        elements._apply_boxscaling(boxscale)

        format_fn = lookup_method(elements, "asy")
        if format_fn is not None:
            asy = format_fn(elements)
        else:
            asy = elements.to_asy()

        xmin, xmax, ymin, ymax, zmin, zmax, boxscale, w, h = calc_dimensions()

        # TODO: Intelligently place the axes on the longest non-middle edge.
        # See algorithm used by web graphics in mathics/web/media/graphics.js
        # for details of this. (Projection to sceen etc).

        # Choose axes placement (boundbox edge vertices)
        axes_indices = []
        if axes[0]:
            axes_indices.append(0)
        if axes[1]:
            axes_indices.append(6)
        if axes[2]:
            axes_indices.append(8)

        # Draw boundbox and axes
        boundbox_asy = ""
        boundbox_lines = self.get_boundbox_lines(xmin, xmax, ymin, ymax, zmin,
                                                 zmax)

        for i, line in enumerate(boundbox_lines):
            if i in axes_indices:
                pen = asy_create_pens(edge_color=RGBColor(components=(0, 0, 0,
                                                                      1)),
                                      stroke_width=1.5)
            else:
                pen = asy_create_pens(edge_color=RGBColor(components=(0.4, 0.4,
                                                                      0.4, 1)),
                                      stroke_width=1)

            path = "--".join(["(%.5g,%.5g,%.5g)" % coords for coords in line])
            boundbox_asy += "draw((%s), %s);\n" % (path, pen)

        # TODO: Intelligently draw the axis ticks such that they are always
        # directed inward and choose the coordinate direction which makes the
        # ticks the longest. Again, details in mathics/web/media/graphics.js

        # Draw axes ticks
        ticklength = 0.05 * max([xmax - xmin, ymax - ymin, zmax - zmin])
        pen = asy_create_pens(edge_color=RGBColor(components=(0, 0, 0, 1)),
                              stroke_width=1.2)
        for xi in axes_indices:
            if xi < 4:  # x axis
                for i, tick in enumerate(ticks[0][0]):
                    line = [
                        (tick, boundbox_lines[xi][0][1],
                         boundbox_lines[xi][0][2]),
                        (
                            tick,
                            boundbox_lines[xi][0][1],
                            boundbox_lines[xi][0][2] + ticklength,
                        ),
                    ]

                    path = "--".join(
                        ["({0},{1},{2})".format(*coords) for coords in line])

                    boundbox_asy += "draw(({0}), {1});\n".format(path, pen)
                    boundbox_asy += 'label("{0}",{1},{2});\n'.format(
                        ticks[0][2][i],
                        (tick, boundbox_lines[xi][0][1],
                         boundbox_lines[xi][0][2]),
                        "S",
                    )

                for small_tick in ticks[0][1]:
                    line = [
                        (
                            small_tick,
                            boundbox_lines[xi][0][1],
                            boundbox_lines[xi][0][2],
                        ),
                        (
                            small_tick,
                            boundbox_lines[xi][0][1],
                            boundbox_lines[xi][0][2] + 0.5 * ticklength,
                        ),
                    ]

                    path = "--".join(
                        ["({0},{1},{2})".format(*coords) for coords in line])

                    boundbox_asy += "draw(({0}), {1});\n".format(path, pen)

            if 4 <= xi < 8:  # y axis
                for i, tick in enumerate(ticks[1][0]):
                    line = [
                        (boundbox_lines[xi][0][0], tick,
                         boundbox_lines[xi][0][2]),
                        (
                            boundbox_lines[xi][0][0],
                            tick,
                            boundbox_lines[xi][0][2] - ticklength,
                        ),
                    ]
                    path = "--".join(
                        ["({0},{1},{2})".format(*coords) for coords in line])

                    boundbox_asy += "draw(({0}), {1});\n".format(path, pen)

                    boundbox_asy += 'label("{0}",{1},{2});\n'.format(
                        ticks[1][2][i],
                        (boundbox_lines[xi][0][0], tick,
                         boundbox_lines[xi][0][2]),
                        "NW",
                    )

                for small_tick in ticks[1][1]:
                    line = [
                        (
                            boundbox_lines[xi][0][0],
                            small_tick,
                            boundbox_lines[xi][0][2],
                        ),
                        (
                            boundbox_lines[xi][0][0],
                            small_tick,
                            boundbox_lines[xi][0][2] - 0.5 * ticklength,
                        ),
                    ]
                    path = "--".join(
                        ["({0},{1},{2})".format(*coords) for coords in line])
                    boundbox_asy += "draw(({0}), {1});\n".format(path, pen)
            if 8 <= xi:  # z axis
                for i, tick in enumerate(ticks[2][0]):
                    line = [
                        (boundbox_lines[xi][0][0], boundbox_lines[xi][0][1],
                         tick),
                        (
                            boundbox_lines[xi][0][0],
                            boundbox_lines[xi][0][1] + ticklength,
                            tick,
                        ),
                    ]
                    path = "--".join(
                        ["({0},{1},{2})".format(*coords) for coords in line])
                    boundbox_asy += "draw(({0}), {1});\n".format(path, pen)
                    boundbox_asy += 'label("{0}",{1},{2});\n'.format(
                        ticks[2][2][i],
                        (boundbox_lines[xi][0][0], boundbox_lines[xi][0][1],
                         tick),
                        "W",
                    )
                for small_tick in ticks[2][1]:
                    line = [
                        (
                            boundbox_lines[xi][0][0],
                            boundbox_lines[xi][0][1],
                            small_tick,
                        ),
                        (
                            boundbox_lines[xi][0][0],
                            boundbox_lines[xi][0][1] + 0.5 * ticklength,
                            small_tick,
                        ),
                    ]
                    path = "--".join(
                        ["({0},{1},{2})".format(*coords) for coords in line])
                    boundbox_asy += "draw(({0}), {1});\n".format(path, pen)

        (height, width) = (400, 400)  # TODO: Proper size
        tex = r"""
\begin{{asy}}
import three;
import solids;
size({0}cm, {1}cm);
currentprojection=perspective({2[0]},{2[1]},{2[2]});
currentlight=light(rgb(0.5,0.5,1), specular=red, (2,0,2), (2,2,2), (0,2,2));
{3}
{4}
\end{{asy}}
""".format(
            asy_number(width / 60),
            asy_number(height / 60),
            self.viewpoint,
            asy,
            boundbox_asy,
        )
        return tex