In the following I've assumed that the lines the OP is concerned with are beams loaded only in nodes, justifying the use of cubic splines.
The function displ
below computes the displaced position of 31 points (possibly overdone) along the line in terms of the undeformed and deformed nodal positions and the nodal rotations, applying an optional scaling factor to the transversal displacements. It returns a (2, 31)
array of displaced beam positions in the global coordinate system.
from numpy import linspace
_s = linspace(0, 1, 31) # non-dimensional abscissa
_s0, _s1 = (_s-1)**2*_s, (_s-1)*_s**2 # cubic splines for unit rotations
def displ(X0, Y0, X1, Y1,
x0, y0, x1, y1,
φ0, φ1,
f=1.0,
ξ=_s, ξ0=_s0, ξ1=_s1):
from numpy import arctan2 as atan2, array, cos, sin, sqrt
# rigid slopes before and after
Θ, θ = atan2(Y1-Y0, X1-X0), atan2(y1-y0, x1-x0)
# rigid rotation (difference in slopes, after - before)
δ = θ - Θ
# end rotations not explained by the rigid rotation
dφ0, dφ1 = φ0-δ, φ1-δ
# transversal displacements, ξ0 and ξ1 are the proper cubic splines
ν = dφ0*ξ0 + dφ1*ξ1
# deformed length, sine and cosine for projection
l = sqrt((x1-x0)**2+(y1-y0)**2)
cs, sn = cos(θ), sin(θ)
# u, axial displacement, u = l*ξ
# v, transversal disp.t, v = l*ν
# dx, dy = T @ {u,v}
x0y0 = array((x0, y0), dtype=float)[:,None]
return x0y0+l*array(((cs,-sn),(sn,cs)))@array((ξ, f*ν)) # shape(2,31)
To check the correctness of the implementation and show the usage I've written a short program using displ
to show 4 arbitrarily deformed shapes.
import matplotlib.pyplot as plt
X0, Y0, x0, y0 = 0.0, 0.0, 0.0, 0.0
# X1 Y1 x1 y1 f0 f1
args_list = [( 0, 5, 0.2, 4.8, 0.17, 0.12),
( 5, 0, 5.2, -0.2, -.14, 0.18),
( 5, 5, 5.2, 4.7, 0.18, -.22),
( 5, -5, 4.7, -5.3, -.20, 0.00)]
fig, axes = plt.subplots(2, 2, constrained_layout=1)
for ax, (X1, Y1, x1, y1, f0, f1) in zip(axes.flatten(), args_list):
ax.set_title('φ₀ = %+4.2f, φ₁ = %+4.2f'%(f0, f1))
ax.plot((X0, X1), (Y0, Y1), alpha=0.35)
ax.plot(*displ(X0, Y0, X1, Y1, x0, y0, x1, y1, f0, f1))
ax.set_aspect(1)
ax.grid(1)
plt.show()
