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
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
def create(expr): head = expr.get_head_name() cls = get_class(head) if cls is None: raise ColorError return cls(expr)
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