Source code for plato.draw.matplotlib.Lines

from matplotlib.path import Path
from matplotlib.patches import PathPatch
import numpy as np

from ... import math
from ... import mesh
from ... import draw
from .internal import PatchUser

[docs]class Lines(draw.Lines, PatchUser): __doc__ = draw.Lines.__doc__ def _render_patches(self, axes, aa_pixel_size=0, rotation=(1, 0, 0, 0), ambient_light=0, directional_light=(-.1, -.25, -1), **kwargs): rotation = np.asarray(rotation) start_points, end_points, widths, colors = mesh.unfoldProperties([ self.start_points, self.end_points, self.widths, self.colors]) # rotate into scene orientation start_points = math.quatrot(rotation[np.newaxis], start_points) end_points = math.quatrot(rotation[np.newaxis], end_points) midpoints = 0.5*(start_points + end_points) zs = midpoints[:, 2] # calculate the vector perpendicular to each line segment deltas = end_points[:, :2] - start_points[:, :2] perps = np.array([-deltas[:, 1], deltas[:, 0]]).T perps /= np.linalg.norm(perps, axis=-1, keepdims=True) perps *= 0.5*widths perps[np.any(np.logical_not(np.isfinite(perps)), axis=-1)] = (1, 0) # angle of the vector perpendicular to each line segment angles = np.arctan2(perps[:, 1], perps[:, 0]) + np.pi angles[np.logical_not(np.isfinite(angles))] = 0 angles_degrees = angles*180/np.pi # construct rectangles with offset vertices rectangles = [start_points[:, :2] - perps, end_points[:, :2] - perps, end_points[:, :2] + perps, start_points[:, :2] + perps] if aa_pixel_size: for elt in rectangles: elt -= midpoints[:, :2] elt += np.sign(elt)*aa_pixel_size elt += midpoints[:, :2] patches = [] for (z, angle, width, start, end, a, b, c, d) in zip( zs, angles_degrees, widths[:, 0], start_points[:, :2], end_points[:, :2], *rectangles): arc = Path.arc(angle, angle + 180) commands = [Path.MOVETO, Path.LINETO] vertices = [a, b] for (pos, cmd) in arc.iter_segments(): cmd = cmd if cmd != Path.MOVETO else Path.LINETO if cmd == Path.STOP: continue pos = pos.reshape((-1, 2))*width*0.5 commands.extend(pos.shape[0]*[cmd]) vertices.extend(end[np.newaxis] + pos) commands.append(Path.LINETO) vertices.append(c) commands.append(Path.LINETO) vertices.append(d) for (pos, cmd) in arc.iter_segments(): cmd = cmd if cmd != Path.MOVETO else Path.LINETO if cmd == Path.STOP: continue pos = pos.reshape((-1, 2))*width*0.5 commands.extend(pos.shape[0]*[cmd]) vertices.extend(start[np.newaxis] - pos) commands.append(Path.CLOSEPOLY) vertices.append(a) path = Path(vertices, commands) patches.append(PathPatch(path, zorder=z)) return [(patches, colors)]