Chris Parmer — home

Shear force and bending moment diagram

Structural Engineering

Example from the compendium of canonical charts

Structural Engineering — Shear force and bending moment diagram

Python Code

"""Structural Engineering — Shear force and bending moment diagram."""


import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots

L = 6.0   # beam length (m)
w = 5.0   # UDL (kN/m)


def generate():
    x = np.linspace(0, L, 300)

    # Simply-supported beam with UDL
    R = w * L / 2          # reaction at each support
    V = R - w * x          # shear force
    M = R * x - w * x**2 / 2  # bending moment

    M_max = w * L**2 / 8   # at midspan

    fig = make_subplots(
        rows=2, cols=1,
        shared_xaxes=True,
        vertical_spacing=0.10,
        subplot_titles=["Shear Force Diagram", "Bending Moment Diagram"],
    )

    # Row 1: Shear force
    fig.add_trace(go.Scatter(
        x=x, y=V,
        mode="lines",
        line=dict(color=VIOLET, width=2.5),
        fill="tozeroy",
        fillcolor="rgba(132, 94, 238, 0.18)",
        name="Shear V(x)",
        hovertemplate="x=%{x:.2f} m<br>V=%{y:.2f} kN<extra></extra>",
    ), row=1, col=1)

    # Annotate peak shear at x=0 and x=L
    fig.add_annotation(x=0, y=R, text=f"+{R:.1f} kN", showarrow=True,
                       arrowhead=2, ax=30, ay=-20, row=1, col=1,
                       font=dict(size=10))
    fig.add_annotation(x=L, y=-R, text=f"−{R:.1f} kN", showarrow=True,
                       arrowhead=2, ax=-30, ay=20, row=1, col=1,
                       font=dict(size=10))

    # Row 2: Bending moment (sagging positive, plotted downward convention — use positive)
    fig.add_trace(go.Scatter(
        x=x, y=M,
        mode="lines",
        line=dict(color=GREEN, width=2.5),
        fill="tozeroy",
        fillcolor="rgba(85, 182, 133, 0.18)",
        name="Moment M(x)",
        hovertemplate="x=%{x:.2f} m<br>M=%{y:.2f} kN·m<extra></extra>",
    ), row=2, col=1)

    # Annotate max moment at midspan
    fig.add_annotation(
        x=L/2, y=M_max,
        text=f"M<sub>max</sub> = wL²/8 = {M_max:.1f} kN·m",
        showarrow=True, arrowhead=2,
        ax=0, ay=-35,
        row=2, col=1,
        font=dict(size=11),
    )

    fig.update_xaxes(title_text="Position (m)", row=2, col=1)
    fig.update_yaxes(title_text="Shear (kN)", row=1, col=1)
    fig.update_yaxes(title_text="Moment (kN·m)", row=2, col=1)

    fig.update_layout(
        legend=dict(orientation="h", y=-0.12),
        margin=dict(t=70, b=60, l=80, r=40),
        annotations=fig.layout.annotations + (
            dict(
                x=0.5, y=1.04, xref="paper", yref="paper",
                text=f"Simply-supported beam: L={L} m, w={w} kN/m (UDL)",
                showarrow=False, font=dict(size=11, color="#60646c"),
            ),
        ),
    )
    return fig


if __name__ == "__main__":
    generate()

Made with Plotly