예제 #1
0
def arcbox(self, **options) -> str:
    """
    Aymptote formatting for arc of a circle.
    """
    if self.arc is None:
        # We have a doughnut graph and this is the inner blank hole of that.
        # It is an empty circle
        return _roundbox(self, **options)

    x, y, rx, ry, sx, sy, ex, ey, large_arc = self._arc_params()

    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"

    l = 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=l,
        is_face_element=self.face_element,
    )
    command = "filldraw" if self.face_element else "draw"
    asy = "%s(%s, %s);" % (command, "".join(path(self.face_element)), pen)
    # print("### arcbox", asy)
    return asy
예제 #2
0
def line3dbox(self, **options) -> str:
    # l = self.style.get_line_width(face_element=False)
    pen = asy_create_pens(edge_color=self.edge_color, stroke_width=1)

    return "".join("draw({0}, {1});".format(
        "--".join("({0},{1},{2})".format(*coords.pos()[0]) for coords in line),
        pen,
    ) for line in self.lines)
예제 #3
0
def arrow_box(self, **options) -> str:
    width = self.style.get_line_width(face_element=False)
    pen = asy_create_pens(edge_color=self.edge_color, stroke_width=width)
    polyline = self.curve.make_draw_asy(pen)

    arrow_pen = asy_create_pens(face_color=self.edge_color, stroke_width=width)

    def polygon(points):
        yield "filldraw("
        yield "--".join(["(%.5g,%5g)" % xy for xy in points])
        yield "--cycle, % s);" % arrow_pen

    extent = self.graphics.view_width or 0
    default_arrow = self._default_arrow(polygon)
    custom_arrow = self._custom_arrow("asy", _ASYTransform)
    asy = "".join(self._draw(polyline, default_arrow, custom_arrow, extent))
    # print("### arrowbox", asy)
    return asy
예제 #4
0
def linebox(self) -> str:
    line_width = self.style.get_line_width(face_element=False)
    pen = asy_create_pens(edge_color=self.edge_color, stroke_width=line_width)
    asy = ""
    for line in self.lines:
        path = "--".join(["(%.5g,%5g)" % coords.pos() for coords in line])
        asy += "draw(%s, %s);" % (path, pen)
    # print("### linebox", asy)
    return asy
예제 #5
0
def point3dbox(self, **options) -> str:
    face_color = self.face_color

    # Tempoary bug fix: default Point color should be black not white
    if list(face_color.to_rgba()[:3]) == [1, 1, 1]:
        face_color = RGBColor(components=(0, 0, 0, face_color.to_rgba()[3]))

    pen = asy_create_pens(face_color=face_color, is_face_element=False)

    return "".join(f"path3 g={0}--cycle;dot(g, {pen});".format("--".join(
        "(%.5g,%.5g,%.5g)" % coords.pos()[0] for coords in line))
                   for line in self.lines)
예제 #6
0
def bezier_curve_box(self, **options) -> str:
    line_width = self.style.get_line_width(face_element=False)
    pen = asy_create_pens(edge_color=self.edge_color, stroke_width=line_width)

    asy = ""
    for line in self.lines:
        for path in asy_bezier(
            (self.spline_degree, [xy.pos() for xy in line])):
            if path[:2] == "..":
                path = "(0.,0.)" + path
            asy += "draw(%s, %s);" % (path, pen)
    return asy
예제 #7
0
def arcbox(self, **options) -> str:
    """
    Aymptote formatting for an arc of a circle or an ellipse.
    """
    if self.arc is None:
        # We have a doughnut graph and this is the inner blank hole of that.
        # It is an empty circle
        return _roundbox(self, **options)

    x, y, rx, ry, sx, sy, ex, ey, large_arc = self._arc_params()

    ry = max(ry, 0.1)  # Avoid division by 0
    yscale = ry / rx

    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

    l = 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=l,
        is_face_element=self.face_element,
    )
    command = "filldraw" if self.face_element else "draw"
    arc_path = create_arc_path(self.face_element, yscale)
    asy = f"""// ArcBox
{command}({arc_path}, {pen});"""
    # print("### arcbox", asy)
    return asy
예제 #8
0
def filled_curve_box(self, **options) -> str:
    line_width = self.style.get_line_width(face_element=False)
    pen = asy_create_pens(edge_color=self.edge_color, stroke_width=line_width)

    if not pen:
        pen = "currentpen"

    def components():
        for component in self.components:
            transformed = [(k, [xy.pos() for xy in p]) for k, p in component]
            yield "fill(%s--cycle, %s);" % ("".join(asy_bezier(*transformed)), pen)

    return "".join(components())
예제 #9
0
def insetbox(self, **options) -> str:
    x, y = self.pos.pos()
    content = self.content.boxes_to_tex(evaluation=self.graphics.evaluation)
    pen = asy_create_pens(edge_color=self.color)
    asy = 'label("$%s$", (%s,%s), (%s,%s), %s);' % (
        content,
        x,
        y,
        -self.opos[0],
        -self.opos[1],
        pen,
    )
    return asy
예제 #10
0
def bezier_curve_box(self, **options) -> str:
    """
    Asymptote formatter for BezerCurveBox.
    """
    line_width = self.style.get_line_width(face_element=False)
    pen = asy_create_pens(edge_color=self.edge_color, stroke_width=line_width)

    asy = "// BezierCurveBox\n"
    asy += asy_add_graph_import(self)
    asy += asy_add_bezier_fn(self)
    for i, line in enumerate(self.lines):
        pts = [str(xy.pos()) for xy in line]
        for j in range(1, len(pts) - 1, 3):
            triple = ", ".join(pts[j - 1 : j + 3])
            asy += """pair[] P%d_%d={%s};\n""" % (i, j, triple)
            asy += """pair G%d_%d(real t){return Bezier(P%d_%d,t);}\n""" % (i, j, i, j)
            asy += """draw(shift(0, -2)*graph(G%d_%d,0,1,350), %s);\n""" % (i, j, pen)
    # print("BezierCurveBox: " asy)
    return asy
예제 #11
0
def polygonbox(self, **options) -> str:
    line_width = self.style.get_line_width(face_element=True)
    if self.vertex_colors is None:
        face_color = self.face_color
    else:
        face_color = None
    pens = asy_create_pens(
        edge_color=self.edge_color,
        face_color=face_color,
        stroke_width=line_width,
        is_face_element=True,
    )
    asy = ""
    if self.vertex_colors is not None:
        paths = []
        colors = []
        edges = []
        for index, line in enumerate(self.lines):
            paths.append(
                "--".join(["(%.5g,%.5g)" % coords.pos()
                           for coords in line]) + "--cycle")

            # ignore opacity
            colors.append(",".join(
                [asy_color(color)[0] for color in self.vertex_colors[index]]))

            edges.append(",".join(["0"] + ["1"] *
                                  (len(self.vertex_colors[index]) - 1)))

        asy += "gouraudshade(%s, new pen[] {%s}, new int[] {%s});" % (
            "^^".join(paths),
            ",".join(colors),
            ",".join(edges),
        )
    if pens and pens != "nullpen":
        for line in self.lines:
            path = (
                "--".join(["(%.5g,%.5g)" % coords.pos()
                           for coords in line]) + "--cycle")
            asy += "filldraw(%s, evenodd+%s);" % (path, pens)

    # print("### polygonbox", asy)
    return asy
예제 #12
0
def pointbox(self, **options) -> str:

    point_size, _ = self.style.get_style(PointSize, face_element=False)
    if point_size is None:
        point_size = PointSize(self.graphics, value=DEFAULT_POINT_FACTOR)

    # We'll use the heuristic that the default line width is 1 should correspond
    # to the DEFAULT_POINT_FACTOR
    dotfactor = INVERSE_POINT_FACTOR * point_size.value
    pen = asy_create_pens(face_color=self.face_color,
                          is_face_element=False,
                          dotfactor=dotfactor)

    asy = ""
    for line in self.lines:
        for coords in line:
            asy += "dot(%s, %s);" % (coords.pos(), pen)

    # print("### pointbox", asy)
    return asy
예제 #13
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,
    )
예제 #14
0
def arrow3dbox(self, **options) -> str:
    """
    Aymptote 3D formatter for Arrow3DBox
    """

    # Set style parameters.
    pen = asy_create_pens(edge_color=self.edge_color, stroke_width=1)

    # Draw lines between all points except the last.
    lines_str = "--".join(
        ["({0},{1},{2})".format(*(coords.pos()[0])) for coords in self.lines[0][:-1]]
    )
    asy = f"draw({lines_str}, {pen});\n"

    # Draw an arrow between the penultimate and the last point.
    last_line_str = "--".join(
        ["({0},{1},{2})".format(*(coords.pos()[0])) for coords in self.lines[0][-2:]]
    )
    asy += f"draw(({last_line_str}), {pen}, Arrow3);\n"

    # print(asy)
    return asy
예제 #15
0
def polygon3dbox(self, **options) -> str:
    l = self.style.get_line_width(face_element=True)
    if self.vertex_colors is None:
        face_color = self.face_color
    else:
        face_color = None
    pen = asy_create_pens(
        edge_color=self.edge_color,
        face_color=face_color,
        stroke_width=l,
        is_face_element=True,
    )

    asy = ""
    for line in self.lines:
        asy += ("path3 g=" + "--".join(
            ["(%.5g,%.5g,%.5g)" % coords.pos()[0]
             for coords in line]) + "--cycle;")
        asy += "draw(surface(g), %s);" % (pen)

    # print("### polygon3dbox", asy)
    return asy
예제 #16
0
def point3dbox(self, **options) -> str:
    """
    Aymptote 3D formatter for Point3DBox
    """
    face_color = self.face_color

    # Tempoary bug fix: default Point color should be black not white
    if list(face_color.to_rgba()[:3]) == [1, 1, 1]:
        face_color = RGBColor(components=(0, 0, 0, face_color.to_rgba()[3]))

    pen = asy_create_pens(face_color=face_color, is_face_element=False)
    points = []
    for line in self.lines:
        point_coords = "--".join(
            "(%.5g,%.5g,%.5g)" % coords.pos()[0] for coords in line
        )
        point = f"path3 g={point_coords}--cycle;dot(g, {pen});\n"
        points.append(point)

    asy = "// Point3DBox\n" + "\n".join(points)
    # print asy
    return asy
예제 #17
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
예제 #18
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