示例#1
0
 def convert(content, style):
     if content.has_form("List", None):
         items = content.leaves
     else:
         items = [content]
     style = style.clone()
     for item in items:
         if item.get_name() == "System`Null":
             continue
         head = item.get_head_name()
         if head in style_and_form_heads:
             style.append(item)
         elif head == "System`StyleBox":
             if len(item.leaves) < 1:
                 raise BoxConstructError
             for element in convert(
                     item.leaves[0],
                     stylebox_style(style, item.leaves[1:])):
                 yield element
         elif head[-3:] == "Box":  # and head[:-3] in element_heads:
             element_class = get_class(head)
             if element_class is not None:
                 options = get_options(head[:-3])
                 if options:
                     data, options = _data_and_options(
                         item.leaves, options)
                     new_item = Expression(head, *data)
                     element = get_class(head)(self, style, new_item,
                                               options)
                 else:
                     element = get_class(head)(self, style, item)
                 yield element
             else:
                 raise BoxConstructError
         elif head == "System`List":
             for element in convert(item, style):
                 yield element
         else:
             raise BoxConstructError
示例#2
0
def _style(graphics, item):
    head = item.get_head_name()
    if head in style_heads:
        klass = get_class(head)
        style = klass.create_as_style(klass, graphics, item)
    elif head in ("System`EdgeForm", "System`FaceForm"):
        style = graphics.get_style_class()(
            graphics, edge=head == "System`EdgeForm", face=head == "System`FaceForm"
        )
        if len(item.leaves) > 1:
            raise BoxConstructError
        if item.leaves:
            if item.leaves[0].has_form("List", None):
                for dir in item.leaves[0].leaves:
                    style.append(dir, allow_forms=False)
            else:
                style.append(item.leaves[0], allow_forms=False)
    else:
        raise BoxConstructError
    return style
示例#3
0
 def create(expr):
     head = expr.get_head_name()
     cls = get_class(head)
     if cls is None:
         raise ColorError
     return cls(expr)
示例#4
0
    def _prepare_elements(self, leaves, options, max_width=None):
        if not leaves:
            raise BoxConstructError

        self.graphics_options = self.get_option_values(leaves[1:], **options)

        background = self.graphics_options["System`Background"]
        if (isinstance(background, Symbol)
                and background.get_name() == "System`Automatic"):
            self.background_color = None
        else:
            self.background_color = _Color.create(background)

        evaluation = options["evaluation"]

        base_width, base_height, size_multiplier, size_aspect = self._get_image_size(
            options, self.graphics_options, max_width)

        # TODO: Handle ImageScaled[], and Scaled[]
        lighting_option = self.graphics_options["System`Lighting"]
        lighting = lighting_option.to_python()  # can take symbols or strings
        self.lighting = []

        if lighting == "System`Automatic":
            self.lighting = [
                {
                    "type": "Ambient",
                    "color": [0.3, 0.2, 0.4]
                },
                {
                    "type": "Directional",
                    "color": [0.8, 0.0, 0.0],
                    "position": [2, 0, 2],
                },
                {
                    "type": "Directional",
                    "color": [0.0, 0.8, 0.0],
                    "position": [2, 2, 2],
                },
                {
                    "type": "Directional",
                    "color": [0.0, 0.0, 0.8],
                    "position": [0, 2, 2],
                },
            ]
        elif lighting == "Neutral":  # Lighting->"Neutral"
            self.lighting = [
                {
                    "type": "Ambient",
                    "color": [0.3, 0.3, 0.3]
                },
                {
                    "type": "Directional",
                    "color": [0.3, 0.3, 0.3],
                    "position": [2, 0, 2],
                },
                {
                    "type": "Directional",
                    "color": [0.3, 0.3, 0.3],
                    "position": [2, 2, 2],
                },
                {
                    "type": "Directional",
                    "color": [0.3, 0.3, 0.3],
                    "position": [0, 2, 2],
                },
            ]
        elif lighting == "System`None":
            pass

        elif isinstance(lighting, list) and all(
                isinstance(light, list) for light in lighting):
            for light in lighting:
                if light[0] in [
                        '"Ambient"', '"Directional"', '"Point"', '"Spot"'
                ]:
                    try:
                        head = light[1].get_head_name()
                    except AttributeError:
                        break
                    color = get_class(head)(light[1])
                    if light[0] == '"Ambient"':
                        self.lighting.append({
                            "type": "Ambient",
                            "color": color.to_rgba()
                        })
                    elif light[0] == '"Directional"':
                        position = [0, 0, 0]
                        if isinstance(light[2], list):
                            if len(light[2]) == 3:
                                position = light[2]
                            if len(light[2]) == 2 and all(  # noqa
                                    isinstance(p, list) and len(p) == 3
                                    for p in light[2]):
                                position = [
                                    light[2][0][i] - light[2][1][i]
                                    for i in range(3)
                                ]
                        self.lighting.append({
                            "type": "Directional",
                            "color": color.to_rgba(),
                            "position": position,
                        })
                    elif light[0] == '"Point"':
                        position = [0, 0, 0]
                        if isinstance(light[2], list) and len(light[2]) == 3:
                            position = light[2]
                        self.lighting.append({
                            "type": "Point",
                            "color": color.to_rgba(),
                            "position": position,
                        })
                    elif light[0] == '"Spot"':
                        position = [0, 0, 1]
                        target = [0, 0, 0]
                        if isinstance(light[2], list):
                            if len(light[2]) == 2:
                                if (isinstance(light[2][0], list)
                                        and len(light[2][0]) == 3  # noqa
                                    ):
                                    position = light[2][0]
                                if (isinstance(light[2][1], list)
                                        and len(light[2][1]) == 3  # noqa
                                    ):
                                    target = light[2][1]
                            if len(light[2]) == 3:
                                position = light[2]
                        angle = light[3]
                        self.lighting.append({
                            "type": "Spot",
                            "color": color.to_rgba(),
                            "position": position,
                            "target": target,
                            "angle": angle,
                        })

        else:
            evaluation.message("Graphics3D", "invlight", lighting_option)

        # ViewPoint Option
        viewpoint_option = self.graphics_options["System`ViewPoint"]
        viewpoint = viewpoint_option.to_python(n_evaluation=evaluation)

        if isinstance(viewpoint, list) and len(viewpoint) == 3:
            if all(isinstance(x, numbers.Real) for x in viewpoint):
                # TODO Infinite coordinates e.g. {0, 0, Infinity}
                pass
        else:
            try:
                viewpoint = {
                    "Above": [0, 0, 2],
                    "Below": [0, 0, -2],
                    "Front": [0, -2, 0],
                    "Back": [0, 2, 0],
                    "Left": [-2, 0, 0],
                    "Right": [2, 0, 0],
                }[viewpoint]
            except KeyError:
                # evaluation.message()
                # TODO
                viewpoint = [1.3, -2.4, 2]

        assert (isinstance(viewpoint, list) and len(viewpoint) == 3
                and all(isinstance(x, numbers.Real) for x in viewpoint))
        self.viewpoint = viewpoint

        # TODO Aspect Ratio
        # aspect_ratio = self.graphics_options['AspectRatio'].to_python()

        boxratios = self.graphics_options["System`BoxRatios"].to_python()
        if boxratios == "System`Automatic":
            boxratios = ["System`Automatic"] * 3
        else:
            boxratios = boxratios
        if not isinstance(boxratios, list) or len(boxratios) != 3:
            raise BoxConstructError

        plot_range = self.graphics_options["System`PlotRange"].to_python()
        if plot_range == "System`Automatic":
            plot_range = ["System`Automatic"] * 3
        if not isinstance(plot_range, list) or len(plot_range) != 3:
            raise BoxConstructError

        elements = Graphics3DElements(leaves[0], evaluation)

        def calc_dimensions(final_pass=True):
            if "System`Automatic" in plot_range:
                xmin, xmax, ymin, ymax, zmin, zmax = elements.extent()
            else:
                xmin = xmax = ymin = ymax = zmin = zmax = None

            try:
                if plot_range[0] == "System`Automatic":
                    if xmin is None and xmax is None:
                        xmin = 0
                        xmax = 1
                    elif xmin == xmax:
                        xmin -= 1
                        xmax += 1
                elif isinstance(plot_range[0], list) and len(
                        plot_range[0]) == 2:
                    xmin, xmax = list(map(float, plot_range[0]))
                    xmin = elements.translate((xmin, 0, 0))[0]
                    xmax = elements.translate((xmax, 0, 0))[0]
                else:
                    raise BoxConstructError

                if plot_range[1] == "System`Automatic":
                    if ymin is None and ymax is None:
                        ymin = 0
                        ymax = 1
                    elif ymin == ymax:
                        ymin -= 1
                        ymax += 1
                elif isinstance(plot_range[1], list) and len(
                        plot_range[1]) == 2:
                    ymin, ymax = list(map(float, plot_range[1]))
                    ymin = elements.translate((0, ymin, 0))[1]
                    ymax = elements.translate((0, ymax, 0))[1]
                else:
                    raise BoxConstructError

                if plot_range[2] == "System`Automatic":
                    if zmin is None and zmax is None:
                        zmin = 0
                        zmax = 1
                    elif zmin == zmax:
                        zmin -= 1
                        zmax += 1
                elif isinstance(plot_range[1], list) and len(
                        plot_range[1]) == 2:
                    zmin, zmax = list(map(float, plot_range[2]))
                    zmin = elements.translate((0, 0, zmin))[2]
                    zmax = elements.translate((0, 0, zmax))[2]
                else:
                    raise BoxConstructError
            except (ValueError, TypeError):
                raise BoxConstructError

            boxscale = [1.0, 1.0, 1.0]
            if boxratios[0] != "System`Automatic":
                boxscale[0] = boxratios[0] / (xmax - xmin)
            if boxratios[1] != "System`Automatic":
                boxscale[1] = boxratios[1] / (ymax - ymin)
            if boxratios[2] != "System`Automatic":
                boxscale[2] = boxratios[2] / (zmax - zmin)

            if final_pass:
                xmin *= boxscale[0]
                xmax *= boxscale[0]
                ymin *= boxscale[1]
                ymax *= boxscale[1]
                zmin *= boxscale[2]
                zmax *= boxscale[2]

                # Rescale lighting
                for i, light in enumerate(self.lighting):
                    if self.lighting[i]["type"] != "Ambient":
                        self.lighting[i]["position"] = [
                            light["position"][j] * boxscale[j]
                            for j in range(3)
                        ]
                    if self.lighting[i]["type"] == "Spot":
                        self.lighting[i]["target"] = [
                            light["target"][j] * boxscale[j] for j in range(3)
                        ]

                # Rescale viewpoint
                self.viewpoint = [
                    vp * max([xmax - xmin, ymax - ymin, zmax - zmin])
                    for vp in self.viewpoint
                ]

            w = 0 if (xmin is None or xmax is None) else xmax - xmin
            h = 0 if (ymin is None or ymax is None) else ymax - ymin

            return xmin, xmax, ymin, ymax, zmin, zmax, boxscale, w, h

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

        axes, ticks, ticks_style = self.create_axes(
            elements,
            self.graphics_options,
            xmin,
            xmax,
            ymin,
            ymax,
            zmin,
            zmax,
            boxscale,
        )

        return elements, axes, ticks, ticks_style, calc_dimensions, boxscale