Source code for pylib.geometry_plot_pylab

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Geometry plotter using pylab (matplotlib).

:Date: 2019-12-23

.. module:: geometry_plot_pylab
  :platform: *nix, Windows
  :synopsis: Geometry plotting (pylab).

.. moduleauthor:: Daniel Weschke <daniel.weschke@directbox.de>
"""
import math
# This import registers the 3D projection, but is otherwise unused.
from mpl_toolkits.mplot3d import Axes3D
assert Axes3D  # silence pyflakes
import pylab
pylab.style.use('dark_background')
pylab.rcParams['text.color'] = 'grey'      # lightgrey
pylab.rcParams['axes.edgecolor'] = 'grey'  # lightgrey
pylab.rcParams['grid.color'] = 'grey'      # lightgrey
pylab.rcParams['xtick.color'] = 'grey'     # lightgrey
pylab.rcParams['ytick.color'] = 'grey'     # lightgrey
pylab.rcParams['axes3d.grid'] = False
# default for dark_background cycler(
# 'color', ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd',
#           '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'])
pylab.rcParams['axes.prop_cycle'] = pylab.cycler(
  "color", ['#3498DB', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd',
            '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'])

# remove f for fullscreen toggle, default ['f', 'ctrl+f']
pylab.rcParams['keymap.fullscreen'] = ['ctrl+f']
# remove L for log/lin toggle, default ['k', 'L']
pylab.rcParams['keymap.xscale'] = ['k']
# remove l for log/lin toggle, default ['l']
pylab.rcParams['keymap.yscale'] = []

from pylab import mean
from .geometry import CS

# type of ax
# - matplotlib.axes._subplots.Axes3DSubplot)
# - matplotlib.axes.Axes
# - pylab.Axes

[docs]def set_aspect_equal(ax): '''Make axes of 3D plot have equal scale so that spheres appear as spheres, cubes as cubes, etc.. This is one possible solution to Matplotlib's ax.set_aspect('equal') and ax.axis('equal') not working for 3D. :param ax: a pylab axis :type ax: pylab.Axes Source: https://stackoverflow.com/a/35126679 ''' if ax.name == '3d': xlim = ax.get_xlim3d() ylim = ax.get_ylim3d() zlim = ax.get_zlim3d() xmean = mean(xlim) ymean = mean(ylim) zmean = mean(zlim) plot_radius = max([abs(lim - mean_) for lims, mean_ in ((xlim, xmean), (ylim, ymean), (zlim, zmean)) for lim in lims]) ax.set_xlim3d([xmean - plot_radius, xmean + plot_radius]) ax.set_ylim3d([ymean - plot_radius, ymean + plot_radius]) ax.set_zlim3d([zmean - plot_radius, zmean + plot_radius]) else: ax.axis('equal')
[docs]def plot_post(ax): if isinstance(ax, pylab.Axes): ax = [ax] for axi in ax: if axi.name == '3d': #axi.w_xaxis.set_pane_color((0, 0, 0, 0)) #axi.w_yaxis.set_pane_color((0, 0, 0, 0)) #axi.w_zaxis.set_pane_color((0, 0, 0, 0)) axi.w_xaxis.pane.fill = False axi.w_yaxis.pane.fill = False axi.w_zaxis.pane.fill = False set_aspect_equal(axi)
[docs]def wireframe3d(world): fig = pylab.figure() ax = fig.add_subplot(111, projection='3d') [ax.plot(*i, 'C0') for i in world.wireframes_xyz()] plot_post(ax)
[docs]def cad_wireframe(world, centering=True): """ Graphical projections * Parallel projections * Orthographic * Multiview * \* First-angle * Third-angle * Plan Elevation * Axonometric * \* Isometric * Dimetric * Trimetri * Oblique * Carbinet * Cavalier * Military * Top-down * Perspective projections * 1-point * 2-point * 3-point * Curvilinear """ if centering: world.center() fig = pylab.figure('geometry-cad') fig.clf() ax = fig.add_subplot(111) pylab.axis('off') pylab.subplots_adjust(left=0, right=1, top=1, bottom=0) lps = [ax.plot(*i, 'C0')[0] for i in world.wireframes_xy()] plot_post(ax) # 'rotate: ←left, right, up, down, ctrl+left, ctrl+right\n' + # 'pan: shift+left, shift+right, shift+up, shift+down\n' + # 'zoom: ctrl+up, ctrl+down\n' + # 'view: f (front), l (left), r (right), t (top), b (bottom)\n' + # ' i (isometric), d (dimetric)', h_open = pylab.text( 0+.01, 1-.015, 'rotate: [←], [→], [↑], [↓], [Ctrl][←], [Ctrl][→]\n' + 'pan: [Shift][←], [Shift][→], [Shift][↑], [Shift][↓]\n' + 'zoom: [Ctrl][↑], [Ctrl][↓]\n' + 'view: [f]ront, [l]eft, [r]ight, [t]op, [b]ottom\n' + ' [i]sometric, [d]imetric', color='#2280c0', horizontalalignment='left', verticalalignment='top', transform=fig.transFigure, bbox=dict(facecolor='black', edgecolor='#196090', alpha=0.5), family='monospace' ) h_close = pylab.text( 0+.01, 1-.015, '[h]elp', color='#2280c0', horizontalalignment='left', verticalalignment='top', transform=fig.transFigure, bbox=dict(facecolor='black', edgecolor='#196090', alpha=0.5), family='monospace', visible=False ) def press(event, world, lps, h_open, h_close): #print('key pressed:', event.key) #sys.stdout.flush() if event.key in [ 'left', 'right', 'up', 'down', 'f', 't', 'b', 'l', 'r', 'i', 'd', 'shift+left', 'shift+right', 'shift+up', 'shift+down', 'ctrl+up', 'ctrl+down', 'ctrl+left', 'ctrl+right']: d = world.space_diagonal() if event.key == 'left': world.rotate_y(-math.pi/180*10) elif event.key == 'right': world.rotate_y(+math.pi/180*10) elif event.key == 'up': world.rotate_x(-math.pi/180*10) elif event.key == 'down': world.rotate_x(+math.pi/180*10) elif event.key == 'f': world.cs(CS()) if centering: world.center() elif event.key == 't': world.cs(CS.x90()) if centering: world.center() elif event.key == 'b': world.cs(CS.xm90()) if centering: world.center() elif event.key == 'l': world.cs(CS.y90()) if centering: world.center() elif event.key == 'r': world.cs(CS.ym90()) if centering: world.center() elif event.key == 'i': #theta_y = -math.pi/2/3 #theta_x = math.pi/2/3 theta_y = -math.pi/2/2 theta_x = math.asin(math.tan(math.pi/2/3)) world.cs(CS().rotate_y(theta_y).rotate_x(theta_x)) if centering: world.center() elif event.key == 'd': #theta_x = math.asin(math.tan(math.pi/2/3/2)) theta_y = -math.pi/2/2 theta_x = math.atan(1/2) world.cs(CS().rotate_y(theta_y).rotate_x(theta_x)) if centering: world.center() elif event.key == 'shift+left': world.translate(-0.1*d, 0, 0) elif event.key == 'shift+right': world.translate(0.1*d, 0, 0) elif event.key == 'shift+up': world.translate(0, 0.1*d, 0) elif event.key == 'shift+down': world.translate(0, -0.1*d, 0) elif event.key == 'ctrl+left': world.rotate_z(+math.pi/180*10) elif event.key == 'ctrl+right': world.rotate_z(-math.pi/180*10) elif event.key == 'ctrl+up': world.scale(1.1) elif event.key == 'ctrl+down': world.scale(0.9) for i, j in zip(lps, world.wireframes_xy()): i.set_data(j) if event.key == 'h': visible = h_open.get_visible() h_open.set_visible(not visible) h_close.set_visible(visible) fig.canvas.draw() def onresize(event, w): r = 2 * w.space_diagonal()/2 pylab.xlim((-r, r)) pylab.ylim((-r, r)) fig.canvas.mpl_connect('key_press_event', lambda event: press(event, world, lps, h_open, h_close)) fig.canvas.mpl_connect('resize_event', lambda event: onresize(event, world)) pylab.show()