Source code for sectionproperties.post.post

import contextlib
import numpy as np
import matplotlib.pyplot as plt
from rich.console import Console
from rich.table import Table
from sectionproperties.pre.pre import DEFAULT_MATERIAL


[docs]@contextlib.contextmanager def plotting_context( ax=None, pause=True, title="", filename="", render=True, axis_index=None, **kwargs ): """Executes code required to set up a matplotlib figure. :param ax: Axes object on which to plot :type ax: :class:`matplotlib.axes.Axes` :param bool pause: If set to true, the figure pauses the script until the window is closed. If set to false, the script continues immediately after the window is rendered. :param string title: Plot title :param string filename: Pass a non-empty string or path to save the image as. If this option is used, the figure is closed after the file is saved. :param bool render: If set to False, the image is not displayed. This may be useful if the figure or axes will be embedded or further edited before being displayed. :param axis_index: If more than 1 axes is created by subplot, then this is the axis to plot on. This may be a tuple if a 2D array of plots is returned. The default value of None will select the top left plot. :type axis_index: Union[None, int, Tuple(int)] :param kwargs: Passed to :func:`matplotlib.pyplot.subplots` """ if filename: render = False if ax is None: if not render: plt.ioff() elif pause: plt.ioff() else: plt.ion() ax_supplied = False (fig, ax) = plt.subplots(**kwargs) try: if axis_index is None: axis_index = (0,) * ax.ndim ax = ax[axis_index] except (AttributeError, TypeError): pass # only 1 axis, not an array except IndexError as exc: raise ValueError( f"axis_index={axis_index} is not compatible with arguments to subplots: {kwargs}" ) from exc else: fig = ax.get_figure() ax_supplied = True if not render: plt.ioff() yield fig, ax ax.set_title(title) plt.tight_layout() ax.set_aspect("equal", anchor="C") # if no axes was supplied, finish the plot and return the figure and axes if ax_supplied: # if an axis was supplied, don't continue with displaying or configuring the plot return if filename: fig.savefig(filename, dpi=fig.dpi) plt.close(fig) # close the figure to free the memory return # if the figure was to be saved, then don't show it also if render: if pause: plt.show() else: plt.draw() plt.pause(0.001)
[docs]def draw_principal_axis(ax, phi, cx, cy): """ Draws the principal axis on a plot. :param ax: Axes object on which to plot :type ax: :class:`matplotlib.axes.Axes` :param float phi: Principal axis angle in radians :param float cx: x-location of the centroid :param float cy: y-location of the centroid """ # get current axis limits (xmin, xmax) = ax.get_xlim() (ymin, ymax) = ax.get_ylim() lims = [xmin, xmax, ymin, ymax] # form rotation matrix R = np.array([[np.cos(phi), -np.sin(phi)], [np.sin(phi), np.cos(phi)]]) # get basis vectors in the directions of the principal axes x11_basis = R.dot(np.array([1, 0])) y22_basis = R.dot(np.array([0, 1])) def add_point(vec, basis, centroid, num, denom): """Adds a point to the list *vec* if there is an intersection.""" if denom != 0: point = basis * num / denom + centroid vec.append([point[0], point[1]]) def get_principal_points(basis, lims, centroid): """Determines the intersections of the principal axis with the four lines defining a bounding box around the limits of the cross-section. The middle two intersection points are returned for plotting. :param basis: Basis (unit) vector in the direction of the principal axis :type basis: :class:`numpy.ndarray` :param lims: Tuple containing the axis limits *(xmin, xmax, ymin, ymax)* :type lims: tuple(float, float, float, float) :param centroid: Centroid *(cx, cy)* of the cross-section, through which the principal axis passes :type centroid: list[float, float] """ pts = [] # initialise list containing the intersection points # add intersection points to the list add_point(pts, basis, centroid, lims[0] - centroid[0], basis[0]) add_point(pts, basis, centroid, lims[1] - centroid[0], basis[0]) add_point(pts, basis, centroid, lims[2] - centroid[1], basis[1]) add_point(pts, basis, centroid, lims[3] - centroid[1], basis[1]) # sort point vector pts = np.array(pts) pts = pts[pts[:, 0].argsort()] # stackoverflow sort numpy array by col # if there are four points, take the middle two points if len(pts) == 4: return pts[1:3, :] return pts # get intersection points for the 11 and 22 axes x11 = get_principal_points(x11_basis, lims, [cx, cy]) y22 = get_principal_points(y22_basis, lims, [cx, cy]) # plot the principal axis ax.plot(x11[:, 0], x11[:, 1], "k--", alpha=0.5, label="11-axis") ax.plot(y22[:, 0], y22[:, 1], "k-.", alpha=0.5, label="22-axis")