Source code for k3d.factory.geometry

"""Factory functions for geometric objects."""

import numpy as np
import six
from typing import Any
from typing import Dict as TypingDict
from typing import List as TypingList
from typing import Optional, Tuple, Union

from .common import _default_color, default_colormap
from ..helpers import check_attribute_color_range
from ..objects import STL, Line, Lines, Mesh, Surface
from ..transform import process_transform_arguments

# Type aliases for better readability
ArrayLike = Union[TypingList, np.ndarray, Tuple]
ColorMap = Union[TypingList[TypingList[float]], TypingDict[str, Any], np.ndarray]
ColorRange = TypingList[float]


[docs] def lines( vertices: ArrayLike, indices: ArrayLike, indices_type: str = "triangle", color: int = _default_color, colors: TypingList[int] = None, # lgtm [py/similar-function] attribute: ArrayLike = None, color_map: Optional[ColorMap] = None, color_range: ColorRange = None, width: float = 0.01, shader: str = "thick", shininess: float = 50.0, radial_segments: int = 8, opacity: float = 1.0, name: Optional[str] = None, group: Optional[str] = None, custom_data: Optional[TypingDict[str, Any]] = None, compression_level: int = 0, **kwargs: Any, ) -> Lines: """ Create a Line drawable for plotting segments and polylines. Parameters ---------- vertices : array_like Array with (x, y, z) coordinates of segment endpoints. indices : array_like Array of vertex indices: int pair or triple of indices from vertices array. indices_type : {'segment', 'triangle'}, optional Interpretation of indices array. 'segment' for pairs, 'triangle' for triples. Default is 'triangle'. color : int, optional Packed RGB color of the lines (0xff0000 is red, 0xff is blue) when `colors` is empty. Default is _default_color. colors : array_like, optional Array of int: packed RGB colors (0xff0000 is red, 0xff is blue) when attribute, color_map and color_range are empty. Default is []. attribute : array_like, optional Array of float attribute for the color mapping, corresponding to each vertex. Default is []. color_map : list, optional A list of float quadruplets (attribute value, R, G, B), sorted by attribute value. The first quadruplet should have value 0.0, the last 1.0; R, G, B are RGB color components in the range 0.0 to 1.0. Default is default_colormap. color_range : list, optional A pair [min_value, max_value], which determines the levels of color attribute mapped to 0 and 1 in the color map respectively. Default is []. width : float, optional Thickness of the lines. Default is 0.01. shader : {'simple', 'thick', 'mesh'}, optional Display style (name of the shader used) of the lines. Default is 'thick'. shininess : float, optional Shininess of object material. Default is 50.0. radial_segments : int, optional Number of segmented faces around the circumference of the tube. Default is 8. opacity : float, optional Opacity of lines. Default is 1.0. name : str, optional A name of the object. Default is None. group : str, optional A name of a group. Default is None. custom_data : dict, optional An object with custom data attached to object. Default is None. compression_level : int, optional Level of compression [-1, 9]. Default is 0. **kwargs Additional keyword arguments passed to process_transform_arguments. Returns ------- Lines The created Lines drawable object. """ if colors is None: colors = [] if attribute is None: attribute = [] if color_range is None: color_range = [] if color_map is None: color_map = default_colormap color_map = ( np.array(color_map, np.float32) if type(color_map) is not dict else color_map ) attribute = ( np.array(attribute, np.float32) if type(attribute) is not dict else attribute ) color_range = check_attribute_color_range(attribute, color_range) return process_transform_arguments( Lines( vertices=vertices, indices=indices, indices_type=indices_type, color=color, width=width, shader=shader, shininess=shininess, radial_segments=radial_segments, colors=colors, attribute=attribute, color_map=color_map, color_range=color_range, opacity=opacity, name=name, group=group, custom_data=custom_data, compression_level=compression_level, ), **kwargs, )
[docs] def line( vertices: ArrayLike, color: int = _default_color, colors: TypingList[int] = None, # lgtm [py/similar-function] attribute: ArrayLike = None, color_map: Optional[ColorMap] = None, color_range: ColorRange = None, width: float = 0.01, opacity: float = 1.0, shader: str = "thick", shininess: float = 50.0, radial_segments: int = 8, name: Optional[str] = None, group: Optional[str] = None, custom_data: Optional[TypingDict[str, Any]] = None, compression_level: int = 0, **kwargs: Any, ) -> Line: """ Create a Line drawable for plotting segments and polylines. Parameters ---------- vertices : array_like Array with (x, y, z) coordinates of segment endpoints. color : int, optional Hex color of the lines when `colors` is empty, by default _default_color. colors : list, optional Array of Hex colors when attribute, color_map and color_range are empty, by default []. attribute : list, optional List of values used to apply `color_map`, by default []. color_map : list, optional List of `float` quadruplets (attribute value, R, G, B) sorted by attribute value, by default None. The first quadruplet should have value 0.0, the last 1.0; R, G, B are RGB color components in the range 0.0 to 1.0. color_range : list, optional [min_value, max_value] pair determining the levels of color attribute mapped to 0 and 1 in the colormap, by default []. width : float, optional Thickness of the lines, by default 0.01. shader : {'simple', 'thick', 'mesh'}, optional Display style of the lines, by default 'thick'. shininess : float, optional Shininess of object material, by default 50.0. radial_segments : int, optional Number of segmented faces around the circumference of the tube, by default 8. name : str, optional Object name, by default None. group : str, optional Name of a group, by default None. custom_data : dict, optional An object with custom data attached to object, by default None. compression_level : int, optional Level of data compression [-1, 9], by default 0. **kwargs Additional keyword arguments passed to process_transform_arguments. Returns ------- Line The created Line drawable object. """ if colors is None: colors = [] if attribute is None: attribute = [] if color_range is None: color_range = [] if color_map is None: color_map = default_colormap color_map = ( np.array(color_map, np.float32) if type(color_map) is not dict else color_map ) attribute = ( np.array(attribute, np.float32) if type(attribute) is not dict else attribute ) color_range = check_attribute_color_range(attribute, color_range) return process_transform_arguments( Line( vertices=vertices, color=color, width=width, shader=shader, radial_segments=radial_segments, colors=colors, attribute=attribute, color_map=color_map, color_range=color_range, opacity=opacity, name=name, group=group, custom_data=custom_data, compression_level=compression_level, ), **kwargs, )
[docs] def mesh( vertices: ArrayLike, indices: ArrayLike, normals: ArrayLike = None, color: int = _default_color, colors: TypingList[int] = None, attribute: ArrayLike = None, color_map: Optional[ColorMap] = None, # lgtm [py/similar-function] color_range: ColorRange = None, wireframe: bool = False, flat_shading: bool = True, shininess: float = 50.0, opacity: float = 1.0, texture: Optional[bytes] = None, texture_file_format: Optional[str] = None, volume: ArrayLike = None, volume_bounds: ArrayLike = None, opacity_function: ArrayLike = None, side: str = "front", uvs: Optional[ArrayLike] = None, slice_planes: ArrayLike = None, name: Optional[str] = None, group: Optional[str] = None, custom_data: Optional[TypingDict[str, Any]] = None, compression_level: int = 0, triangles_attribute: ArrayLike = None, **kwargs: Any, ) -> Mesh: """Create a Mesh drawable from 3D triangles. Parameters ---------- vertices : array_like Array of triangle vertices, `float` (x, y, z) coordinate triplets. indices : array_like Array of vertex indices. `int` triplets of indices from vertices array. normals: array_like, optional Array of vertex normals: float (x, y, z) coordinate triples. Normals are used when flat_shading is false. If the normals are not specified here, normals will be automatically computed. color : int, optional Hex color of the vertices when `colors` is empty, by default _default_color. colors : list, optional Array of Hex colors when attribute, color_map and color_range are empty, by default []. attribute: list, optional List of values used to apply `color_map`, by default []. color_map : list, optional List of `float` quadruplets (attribute value, R, G, B) sorted by attribute value, by default None. The first quadruplet should have value 0.0, the last 1.0; R, G, B are RGB color components in the range 0.0 to 1.0. color_range : list, optional [min_value, max_value] pair determining the levels of color attribute mapped to 0 and 1 in the colormap, by default []. wireframe : bool, optional Display the mesh as wireframe, by default False. flat_shading : bool, optional Display the mesh with flat shading, by default True. shininess: `float`. Shininess of object material. opacity : float, optional Opacity of the mesh, by default 1.0. texture : bytes, optional Image data in a specific format, by default None. texture_file_format : str, optional Format of the data, , by default None. It should be the second part of MIME format of type 'image/',e.g. 'jpeg', 'png', 'gif', 'tiff'. volume : list, optional 3D array of `float`, by default []. volume_bounds : list, optional 6-element tuple specifying the bounds of the volume data (x0, x1, y0, y1, z0, z1), by default []. opacity_function : list, optional `float` tuples (attribute value, opacity) sorted by attribute value, by default []. The first tuples should have value 0.0, the last 1.0; opacity is in the range 0.0 to 1.0. side : {'front', 'back', 'double'}, optional Side to render, by default "front". uvs : array_like, optional float uvs for the texturing corresponding to each vertex, by default None. name : str, optional Object name, by default None. group : str, optional Name of a group, by default None. custom_data: `dict` A object with custom data attached to object. compression_level : int, optional Level of data compression [-1, 9], by default 0. triangles_attribute : list, optional _description_, by default [] **kwargs For other keyword-only arguments, see :ref:`process_transform_arguments`. Returns ------- Mesh Mesh Drawable """ # Ensure arraylike attributes are initialized as [] if None if colors is None: colors = [] if slice_planes is None: slice_planes = [] if normals is None: normals = [] if attribute is None: attribute = [] if triangles_attribute is None: triangles_attribute = [] if volume is None: volume = [] if volume_bounds is None: volume_bounds = [] if opacity_function is None: opacity_function = [] if uvs is None: uvs = [] if color_map is None: color_map = default_colormap color_map = ( np.array(color_map, np.float32) if type(color_map) is not dict else color_map ) uvs = np.array(uvs, np.float32) if type(uvs) is not dict else color_map attribute = ( np.array(attribute, np.float32) if type(attribute) is not dict else attribute ) normals = np.array(normals, np.float32) if type(normals) is not dict else normals triangles_attribute = ( np.array(triangles_attribute, np.float32) if type(triangles_attribute) is not dict else triangles_attribute ) volume_bounds = ( np.array(volume_bounds, np.float32) if type(volume_bounds) is not dict else volume_bounds ) if len(attribute) > 0: color_range = check_attribute_color_range(attribute, color_range) if len(triangles_attribute) > 0: color_range = check_attribute_color_range(triangles_attribute, color_range) if len(volume) > 0: color_range = check_attribute_color_range(volume, color_range) return process_transform_arguments( Mesh( vertices=vertices, indices=indices, normals=normals, color=color, colors=colors, attribute=attribute, triangles_attribute=triangles_attribute, color_map=color_map, color_range=color_range, wireframe=wireframe, flat_shading=flat_shading, shininess=shininess, opacity=opacity, volume=volume, volume_bounds=volume_bounds, opacity_function=opacity_function, side=side, texture=texture, uvs=uvs, texture_file_format=texture_file_format, slice_planes=slice_planes, name=name, group=group, custom_data=custom_data, compression_level=compression_level, ), **kwargs, )
# noinspection PyShadowingNames
[docs] def stl( stl: Union[str, bytes], color: int = _default_color, wireframe: bool = False, flat_shading: bool = True, shininess: float = 50.0, name: Optional[str] = None, group: Optional[str] = None, custom_data: Optional[TypingDict[str, Any]] = None, compression_level: int = 0, **kwargs: Any, ) -> STL: """Create an STL drawable for data in STereoLitograpy format. Parameters ---------- stl : `str` or `bytes` STL data in either ASCII STL (`str`) or Binary STL (`bytes`). color : int, optional Hex color of the mesh, by default _default_color. wireframe : bool, optional Display the mesh as wireframe, by default False. flat_shading : bool, optional Display the mesh with flat shading, by default True. shininess: `float`. Shininess of object material. name : str, optional Object name, by default None. group : str, optional Name of a group, by default None. custom_data: `dict` A object with custom data attached to object. compression_level : int, optional Level of data compression [-1, 9], by default 0. **kwargs For other keyword-only arguments, see :ref:`process_transform_arguments`. Returns ------- STL STL Drawable. """ plain = isinstance(stl, six.string_types) return process_transform_arguments( STL( text=stl if plain else None, binary=stl if not plain else None, color=color, wireframe=wireframe, flat_shading=flat_shading, shininess=shininess, name=name, group=group, custom_data=custom_data, compression_level=compression_level, ), **kwargs, )
[docs] def surface( heights: ArrayLike, color: int = _default_color, wireframe: bool = False, flat_shading: bool = True, shininess: float = 50.0, attribute: ArrayLike = None, color_map: Optional[ColorMap] = None, color_range: ColorRange = None, opacity: float = 1.0, name: Optional[str] = None, group: Optional[str] = None, custom_data: Optional[TypingDict[str, Any]] = None, compression_level: int = 0, **kwargs: Any, ) -> Surface: """Create a Surface drawable. Plot a 2d function: z = f(x, y). The default domain of the scalar field is -0.5 < x, y < 0.5. If the domain should be different, the bounding box needs to be transformed using `kwargs` - ``surface(..., bounds=[-1, 1, -1, 1])`` - ``surface(..., xmin=-10, xmax=10, ymin=-4, ymax=4)`` Parameters ---------- heights : array_like Array of `float` values. color : int, optional Hex color of the surface, by default _default_color. wireframe : bool, optional Display the mesh as wireframe, by default False. flat_shading : bool, optional Display the mesh with flat shading, by default True. shininess: `float`. Shininess of object material. attribute: list, optional List of values used to apply `color_map`, by default []. opacity: `float`. Opacity of surface. color_map : list, optional List of `float` quadruplets (attribute value, R, G, B) sorted by attribute value, by default None. The first quadruplet should have value 0.0, the last 1.0; R, G, B are RGB color components in the range 0.0 to 1.0. color_range : list, optional [min_value, max_value] pair determining the levels of color attribute mapped to 0 and 1 in the colormap, by default []. name : str, optional Object name, by default None. group : str, optional Name of a group, by default None. custom_data: `dict` A object with custom data attached to object. compression_level : int, optional Level of data compression [-1, 9], by default 0. **kwargs For other keyword-only arguments, see :ref:`process_transform_arguments`. Returns ------- Surface Surface Drawable. """ if attribute is None: attribute = [] if color_range is None: color_range = [] if color_map is None: color_map = default_colormap color_map = np.array(color_map, np.float32) attribute = np.array(attribute, np.float32) color_range = check_attribute_color_range(attribute, color_range) return process_transform_arguments( Surface( heights=heights, color=color, wireframe=wireframe, flat_shading=flat_shading, shininess=shininess, attribute=attribute, color_map=color_map, color_range=color_range, opacity=opacity, name=name, group=group, custom_data=custom_data, compression_level=compression_level, ), **kwargs, )