Source code for glyphx.line3d

"""GlyphX Line3DSeries — connected polyline in 3D space."""
from __future__ import annotations

from .projection3d import Camera3D, normalize, _format_3d_tick
from .utils         import svg_escape


[docs] class Line3DSeries: """ 3D line chart — a connected polyline through 3D coordinates. Args: x, y, z: Path coordinates (same length, connected in order). color: Line color. width: Stroke width in pixels. linestyle: ``"solid"``, ``"dashed"``, ``"dotted"``. label: Legend label. """ _DASH = {"solid": "", "dashed": "6,3", "dotted": "2,2"} def __init__( self, x, y, z, color: str = "#dc2626", width: float = 2.0, linestyle: str = "solid", label: str | None = None, ) -> None: self.x = list(x) self.y = list(y) self.z = list(z) self.color = color self.width = float(width) self.linestyle = linestyle self.label = label self.threshold = None self.last_downsample_info = None self.css_class = f"series3d-{id(self) % 100000}"
[docs] def to_svg(self, cam: Camera3D, x_range, y_range, z_range) -> str: from .downsample import lttb_3d, _ds_comment, AUTO_THRESHOLD # LTTB on camera-projected screen coordinates for large 3D lines _thresh = self.threshold if self.threshold is not None else AUTO_THRESHOLD x_plot, y_plot, z_plot = self.x, self.y, self.z if len(x_plot) > _thresh: _orig_n = len(x_plot) x_plot, y_plot, z_plot = lttb_3d( x_plot, y_plot, z_plot, cam=cam, threshold=_thresh ) self.last_downsample_info = { 'algorithm': 'lttb-3D', 'original_n': _orig_n, 'thinned_n': len(x_plot), } else: self.last_downsample_info = None xn, *_ = normalize(x_plot) yn, *_ = normalize(y_plot) zn, *_ = normalize(z_plot) pts = [cam.project(x, y, z) for x, y, z in zip(xn, yn, zn)] pts_str = " ".join(f"{p.px:.1f},{p.py:.1f}" for p in pts) dash = self._DASH.get(self.linestyle, "") return ( f'<polyline points="{pts_str}" fill="none" ' f'stroke="{self.color}" stroke-width="{self.width}" ' f'stroke-dasharray="{dash}" ' f'data-label="{svg_escape(self.label or "")}"/>' )
[docs] def to_threejs_data(self) -> dict: return { "type": "line", "x": self.x, "y": self.y, "z": self.z, "color": self.color, "width": self.width, "label": self.label or "", }