neu_draw.backends.vector¶
Figure export: each mesh as a transparent image layer, everything else as vectors.
pygfx has no vector output, so this projects with the view’s camera and builds a
Group tree, written as SVG or PDF. Points, skeleton lines
and the legend (as text) are vectors. Meshes stay raster, each rendered alone with a
transparent background: as vectors they would be tens of thousands of depth-sorted
triangles, slow to open and showing seams.
Top-level groups are background, meshes, skeletons, points and legend.
Each drawable is its own group, optionally nested deeper by a groups function:
view.save("fig.svg", groups=lambda d: (d.name.split(" : ")[0],))
The legend splits into panel, group rows and rows, the rows nested by kind and
by the same function applied to each row’s first member.
Occlusion between groups is lost. Meshes are stacked back to front by centre depth and
every vector sits above every mesh, so points behind an opaque mesh show through it; this
reads correctly for the faint meshes it is meant for. Colours are read from the built
materials, so the export matches the canvas, highlights included. Mesh pixels go through
layer_pixels() so they composite in an editor as they do on the canvas.
Attributes¶
Functions¶
|
|
|
A mesh render as a straight-alpha PNG that composites like the canvas does. |
|
World xyz -> |
|
Write the figure to |
Module Contents¶
- neu_draw.backends.vector.figure(view, *, pixel_ratio: float = 2.0, legend: bool = True, size: tuple[int, int] | None = None, groups: Callable[[Any], Sequence[str]] | None = None) tuple[neu_draw.vectorfile.Group, int, int]¶
(tree, width, height)for the view. See the module docstring for the tree.pixel_ratiosets the mesh images’ resolution (2, the default, is twice the logical size, as the canvas renders).sizedefaults to the view’s logical size.groupsmaps a drawable to a tuple of group names to nest it under; it defaults to the scene’sexport_groups. Only visible drawables are exported; the legend keeps every row.
- neu_draw.backends.vector.layer_pixels(rgba: numpy.ndarray, background: Sequence[float]) numpy.ndarray¶
A mesh render as a straight-alpha PNG that composites like the canvas does.
pygfx returns colour premultiplied in linear light, sRGB-encoded (red at alpha 0.5 comes back as (187, 0, 0, 127)), and an editor composites in sRGB, where the GPU composited in linear light. So even the physically correct straight colour,
srgb(linear(v) / alpha), composites too dark: at alpha 0.2 a mid-grey came out at 0.16 against the canvas’s 0.38. Instead this solves for the colourSthat, blended as an SVG viewer blends, reproduces the canvas pixel overbackground(sRGB, 0-1):S * a + bg * (1 - a) == srgb(linear(v) + linear(bg) * (1 - a))
Exact for one layer over the figure’s own background, with alpha raised where the colour alone cannot reach the target. Over stacked layers or a changed background it is close rather than exact.
- neu_draw.backends.vector.project(xyz: numpy.ndarray, matrix: numpy.ndarray, rect: Sequence[float]) tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]¶
World xyz ->
(pixels (N, 2), depth (N,), in_front (N,) bool)insiderect.matrixis the camera’sprojection @ view(pygfx’scamera_matrix, column vectors). Pixel y runs down, as SVG’s does. A point behind the camera has a clipw <= 0and a meaningless divide, so it is flagged rather than drawn mirrored.
- neu_draw.backends.vector.save(view, path: str, **kwargs) str¶
Write the figure to
path,.svgor.pdfby extension.
- neu_draw.backends.vector.DEFAULT_BACKGROUND = (0.0, 0.0, 0.0, 1.0)¶
- neu_draw.backends.vector.KIND_GROUPS¶