RHC Engineering Tools

Structural, Civil and Plumbing Engineering
September 13, 2025 Technical Guide

Shear, Moment, and Deflection Diagrams: VBA, C#, Python, and HTML Implementation

Complete guide to creating shear, moment, and deflection diagrams using VBA, C#, Python, and HTML/JavaScript. Includes step-by-step code examples, calculations, and plotting techniques for structural engineers.

🔧 VBA Implementation 💻 C# Programming 🐍 Python Code 🌐 HTML/JavaScript

Introduction

Creating accurate shear, moment, and deflection diagrams is fundamental to structural engineering. While manual calculations are essential for understanding the underlying principles, programming solutions can significantly improve efficiency and accuracy. This comprehensive guide demonstrates how to implement these calculations using four different approaches: VBA, C#, Python, and HTML/JavaScript.

Problem Statement

We'll solve the same beam problem using all four approaches to ensure consistency and allow for direct comparison. Consider a simply supported beam with the following properties:

Beam Specifications

  • Length (L): 10.0 m
  • Distributed Load (w): 15 kN/m
  • Point Load (P): 50 kN at 3.0 m from left support
  • Modulus of Elasticity (E): 200,000 MPa
  • Moment of Inertia (I): 0.001 m⁴

VBA Implementation (Excel)

VBA is excellent for structural engineers who work extensively with Excel. This implementation creates interactive diagrams directly in Excel worksheets.

VBA Code

Sub CreateBeamDiagrams()
    Dim L As Double, w As Double, P As Double
    Dim E As Double, I As Double
    Dim x As Double, dx As Double
    Dim i As Integer, nPoints As Integer
    
    ' Beam properties
    L = 10#          ' Length (m)
    w = 15#          ' Distributed load (kN/m)
    P = 50#          ' Point load (kN)
    E = 200000000#   ' Modulus of elasticity (Pa)
    I = 0.001#       ' Moment of inertia (m^4)
    
    ' Calculation parameters
    nPoints = 101
    dx = L / (nPoints - 1)
    
    ' Clear existing data
    Range("A1:E" & nPoints + 1).Clear
    
    ' Headers
    Range("A1").Value = "Distance (m)"
    Range("B1").Value = "Shear (kN)"
    Range("C1").Value = "Moment (kN·m)"
    Range("D1").Value = "Deflection (mm)"
    Range("E1").Value = "Slope (rad)"
    
    ' Calculate reactions
    Dim RA As Double, RB As Double
    RA = (w * L / 2) + (P * (L - 3) / L)
    RB = (w * L / 2) + (P * 3 / L)
    
    ' Calculate diagrams
    For i = 0 To nPoints - 1
        x = i * dx
        
        ' Distance
        Range("A" & i + 2).Value = x
        
        ' Shear force
        Range("B" & i + 2).Value = CalculateShear(x, L, w, P, RA)
        
        ' Bending moment
        Range("C" & i + 2).Value = CalculateMoment(x, L, w, P, RA)
        
        ' Deflection
        Range("D" & i + 2).Value = CalculateDeflection(x, L, w, P, E, I) * 1000 ' Convert to mm
        
        ' Slope
        Range("E" & i + 2).Value = CalculateSlope(x, L, w, P, E, I)
    Next i
    
    ' Create charts
    Call CreateShearChart
    Call CreateMomentChart
    Call CreateDeflectionChart
    
    MsgBox "Beam diagrams created successfully!"
End Sub

Function CalculateShear(x As Double, L As Double, w As Double, P As Double, RA As Double) As Double
    Dim shear As Double
    shear = RA - w * x
    If x >= 3 Then
        shear = shear - P
    End If
    CalculateShear = shear
End Function

Function CalculateMoment(x As Double, L As Double, w As Double, P As Double, RA As Double) As Double
    Dim moment As Double
    moment = RA * x - w * x * x / 2
    If x >= 3 Then
        moment = moment - P * (x - 3)
    End If
    CalculateMoment = moment
End Function

Function CalculateDeflection(x As Double, L As Double, w As Double, P As Double, E As Double, I As Double) As Double
    Dim RA As Double, RB As Double
    RA = (w * L / 2) + (P * (L - 3) / L)
    RB = (w * L / 2) + (P * 3 / L)
    
    Dim deflection As Double
    ' Deflection due to distributed load
    deflection = (w * x) / (24 * E * I) * (L^3 - 2 * L * x^2 + x^3)
    
    ' Deflection due to point load
    If x <= 3 Then
        deflection = deflection + (P * x) / (6 * E * I * L) * (L^2 - x^2) * (L - 3)
    Else
        deflection = deflection + (P * (L - x)) / (6 * E * I * L) * (3 * L * x - x^2 - 2 * L^2)
    End If
    
    CalculateDeflection = deflection
End Function

Function CalculateSlope(x As Double, L As Double, w As Double, P As Double, E As Double, I As Double) As Double
    Dim RA As Double, RB As Double
    RA = (w * L / 2) + (P * (L - 3) / L)
    RB = (w * L / 2) + (P * 3 / L)
    
    Dim slope As Double
    ' Slope due to distributed load
    slope = (w) / (24 * E * I) * (L^3 - 6 * L * x^2 + 4 * x^3)
    
    ' Slope due to point load
    If x <= 3 Then
        slope = slope + (P) / (6 * E * I * L) * (L^2 - 3 * x^2) * (L - 3)
    Else
        slope = slope + (P) / (6 * E * I * L) * (3 * L^2 - 6 * L * x + 3 * x^2)
    End If
    
    CalculateSlope = slope
End Function

Sub CreateShearChart()
    Dim chartObj As ChartObject
    Set chartObj = ActiveSheet.ChartObjects.Add(Left:=400, Top:=50, Width:=400, Height:=250)
    
    With chartObj.Chart
        .ChartType = xlXYScatterLines
        .SetSourceData Range("A2:B102")
        .HasTitle = True
        .ChartTitle.Text = "Shear Force Diagram"
        .Axes(xlCategory).HasTitle = True
        .Axes(xlCategory).AxisTitle.Text = "Distance (m)"
        .Axes(xlValue).HasTitle = True
        .Axes(xlValue).AxisTitle.Text = "Shear Force (kN)"
    End With
End Sub

Sub CreateMomentChart()
    Dim chartObj As ChartObject
    Set chartObj = ActiveSheet.ChartObjects.Add(Left:=400, Top:=320, Width:=400, Height:=250)
    
    With chartObj.Chart
        .ChartType = xlXYScatterLines
        .SetSourceData Range("A2:C102")
        .HasTitle = True
        .ChartTitle.Text = "Bending Moment Diagram"
        .Axes(xlCategory).HasTitle = True
        .Axes(xlCategory).AxisTitle.Text = "Distance (m)"
        .Axes(xlValue).HasTitle = True
        .Axes(xlValue).AxisTitle.Text = "Moment (kN·m)"
    End With
End Sub

Sub CreateDeflectionChart()
    Dim chartObj As ChartObject
    Set chartObj = ActiveSheet.ChartObjects.Add(Left:=400, Top:=590, Width:=400, Height:=250)
    
    With chartObj.Chart
        .ChartType = xlXYScatterLines
        .SetSourceData Range("A2:D102")
        .HasTitle = True
        .ChartTitle.Text = "Deflection Diagram"
        .Axes(xlCategory).HasTitle = True
        .Axes(xlCategory).AxisTitle.Text = "Distance (m)"
        .Axes(xlValue).HasTitle = True
        .Axes(xlValue).AxisTitle.Text = "Deflection (mm)"
    End With
End Sub

C# Implementation

C# provides excellent performance and integration with Windows applications. This implementation creates a console application that outputs results and can be extended to create graphical interfaces.

C# Code

using System;
using System.Collections.Generic;

namespace BeamAnalysis
{
    public class BeamCalculator
    {
        public double Length { get; set; }
        public double DistributedLoad { get; set; }
        public double PointLoad { get; set; }
        public double ModulusOfElasticity { get; set; }
        public double MomentOfInertia { get; set; }
        public double PointLoadPosition { get; set; }

        public BeamCalculator(double length, double distributedLoad, double pointLoad, 
                            double modulusOfElasticity, double momentOfInertia, double pointLoadPosition)
        {
            Length = length;
            DistributedLoad = distributedLoad;
            PointLoad = pointLoad;
            ModulusOfElasticity = modulusOfElasticity;
            MomentOfInertia = momentOfInertia;
            PointLoadPosition = pointLoadPosition;
        }

        public (double RA, double RB) CalculateReactions()
        {
            double RA = (DistributedLoad * Length / 2) + (PointLoad * (Length - PointLoadPosition) / Length);
            double RB = (DistributedLoad * Length / 2) + (PointLoad * PointLoadPosition / Length);
            return (RA, RB);
        }

        public double CalculateShear(double x)
        {
            var (RA, _) = CalculateReactions();
            double shear = RA - DistributedLoad * x;
            if (x >= PointLoadPosition)
            {
                shear -= PointLoad;
            }
            return shear;
        }

        public double CalculateMoment(double x)
        {
            var (RA, _) = CalculateReactions();
            double moment = RA * x - DistributedLoad * x * x / 2;
            if (x >= PointLoadPosition)
            {
                moment -= PointLoad * (x - PointLoadPosition);
            }
            return moment;
        }

        public double CalculateDeflection(double x)
        {
            var (RA, RB) = CalculateReactions();
            double deflection = 0;

            // Deflection due to distributed load
            deflection += (DistributedLoad * x) / (24 * ModulusOfElasticity * MomentOfInertia) * 
                         (Math.Pow(Length, 3) - 2 * Length * Math.Pow(x, 2) + Math.Pow(x, 3));

            // Deflection due to point load
            if (x <= PointLoadPosition)
            {
                deflection += (PointLoad * x) / (6 * ModulusOfElasticity * MomentOfInertia * Length) * 
                             (Math.Pow(Length, 2) - Math.Pow(x, 2)) * (Length - PointLoadPosition);
            }
            else
            {
                deflection += (PointLoad * (Length - x)) / (6 * ModulusOfElasticity * MomentOfInertia * Length) * 
                             (3 * Length * x - Math.Pow(x, 2) - 2 * Math.Pow(Length, 2));
            }

            return deflection * 1000; // Convert to mm
        }

        public double CalculateSlope(double x)
        {
            var (RA, RB) = CalculateReactions();
            double slope = 0;

            // Slope due to distributed load
            slope += (DistributedLoad) / (24 * ModulusOfElasticity * MomentOfInertia) * 
                     (Math.Pow(Length, 3) - 6 * Length * Math.Pow(x, 2) + 4 * Math.Pow(x, 3));

            // Slope due to point load
            if (x <= PointLoadPosition)
            {
                slope += (PointLoad) / (6 * ModulusOfElasticity * MomentOfInertia * Length) * 
                         (Math.Pow(Length, 2) - 3 * Math.Pow(x, 2)) * (Length - PointLoadPosition);
            }
            else
            {
                slope += (PointLoad) / (6 * ModulusOfElasticity * MomentOfInertia * Length) * 
                         (3 * Math.Pow(Length, 2) - 6 * Length * x + 3 * Math.Pow(x, 2));
            }

            return slope;
        }

        public List CalculateDiagrams(int numberOfPoints = 101)
        {
            var results = new List();
            double dx = Length / (numberOfPoints - 1);

            for (int i = 0; i < numberOfPoints; i++)
            {
                double x = i * dx;
                results.Add(new BeamResult
                {
                    Distance = x,
                    Shear = CalculateShear(x),
                    Moment = CalculateMoment(x),
                    Deflection = CalculateDeflection(x),
                    Slope = CalculateSlope(x)
                });
            }

            return results;
        }
    }

    public class BeamResult
    {
        public double Distance { get; set; }
        public double Shear { get; set; }
        public double Moment { get; set; }
        public double Deflection { get; set; }
        public double Slope { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Beam properties
            var beam = new BeamCalculator(
                length: 10.0,                    // Length (m)
                distributedLoad: 15.0,           // Distributed load (kN/m)
                pointLoad: 50.0,                 // Point load (kN)
                modulusOfElasticity: 200000000,  // Modulus of elasticity (Pa)
                momentOfInertia: 0.001,          // Moment of inertia (m^4)
                pointLoadPosition: 3.0           // Point load position (m)
            );

            // Calculate reactions
            var (RA, RB) = beam.CalculateReactions();
            Console.WriteLine($"Reactions: RA = {RA:F2} kN, RB = {RB:F2} kN");
            Console.WriteLine();

            // Calculate diagrams
            var results = beam.CalculateDiagrams();

            // Output results
            Console.WriteLine("Distance (m)\tShear (kN)\tMoment (kN·m)\tDeflection (mm)\tSlope (rad)");
            Console.WriteLine(new string('-', 80));

            foreach (var result in results)
            {
                Console.WriteLine($"{result.Distance:F2}\t\t{result.Shear:F2}\t\t{result.Moment:F2}\t\t{result.Deflection:F2}\t\t{result.Slope:F6}");
            }

            // Find maximum values
            var maxShear = results.Max(r => Math.Abs(r.Shear));
            var maxMoment = results.Max(r => Math.Abs(r.Moment));
            var maxDeflection = results.Max(r => Math.Abs(r.Deflection));

            Console.WriteLine();
            Console.WriteLine($"Maximum Shear: {maxShear:F2} kN");
            Console.WriteLine($"Maximum Moment: {maxMoment:F2} kN·m");
            Console.WriteLine($"Maximum Deflection: {maxDeflection:F2} mm");

            Console.WriteLine("\nPress any key to exit...");
            Console.ReadKey();
        }
    }
}

HTML/JavaScript Implementation

HTML with JavaScript provides a web-based solution that runs directly in browsers. This implementation uses HTML5 Canvas for drawing diagrams and JavaScript for calculations, making it perfect for web applications and online tools.

HTML/JavaScript Code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Beam Analysis - Shear, Moment, and Deflection Diagrams</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            background-color: #f5f5f5;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        .input-section {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            margin-bottom: 20px;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 8px;
        }
        .input-group {
            display: flex;
            flex-direction: column;
        }
        .input-group label {
            font-weight: bold;
            margin-bottom: 5px;
            color: #333;
        }
        .input-group input {
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 14px;
        }
        .button-group {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
        }
        button {
            padding: 10px 20px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
        }
        button:hover {
            background: #0056b3;
        }
        .results-section {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
            margin-bottom: 20px;
        }
        .results-table {
            background: #f8f9fa;
            padding: 15px;
            border-radius: 8px;
        }
        .results-table h3 {
            margin-top: 0;
            color: #333;
        }
        .results-table table {
            width: 100%;
            border-collapse: collapse;
        }
        .results-table th,
        .results-table td {
            padding: 8px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }
        .results-table th {
            background: #e9ecef;
            font-weight: bold;
        }
        .diagram-section {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
        }
        .diagram-container {
            border: 1px solid #ddd;
            border-radius: 8px;
            padding: 10px;
            background: white;
        }
        .diagram-container h3 {
            margin-top: 0;
            text-align: center;
            color: #333;
        }
        canvas {
            width: 100%;
            height: 300px;
            border: 1px solid #eee;
            border-radius: 4px;
        }
        @media (max-width: 768px) {
            .results-section,
            .diagram-section {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Beam Analysis - Shear, Moment, and Deflection Diagrams</h1>
        
        <div class="input-section">
            <div class="input-group">
                <label for="length">Length (m):</label>
                <input type="number" id="length" value="10" step="0.1">
            </div>
            <div class="input-group">
                <label for="distributedLoad">Distributed Load (kN/m):</label>
                <input type="number" id="distributedLoad" value="15" step="0.1">
            </div>
            <div class="input-group">
                <label for="pointLoad">Point Load (kN):</label>
                <input type="number" id="pointLoad" value="50" step="0.1">
            </div>
            <div class="input-group">
                <label for="pointLoadPosition">Point Load Position (m):</label>
                <input type="number" id="pointLoadPosition" value="3" step="0.1">
            </div>
            <div class="input-group">
                <label for="modulusOfElasticity">Modulus of Elasticity (MPa):</label>
                <input type="number" id="modulusOfElasticity" value="200000" step="1000">
            </div>
            <div class="input-group">
                <label for="momentOfInertia">Moment of Inertia (m⁴):</label>
                <input type="number" id="momentOfInertia" value="0.001" step="0.0001">
            </div>
        </div>
        
        <div class="button-group">
            <button onclick="calculateBeam()">Calculate Beam</button>
            <button onclick="exportResults()">Export Results</button>
        </div>
        
        <div class="results-section">
            <div class="results-table">
                <h3>Support Reactions</h3>
                <table>
                    <tr><th>Reaction</th><th>Value (kN)</th></tr>
                    <tr><td>RA</td><td id="reactionA">-</td></tr>
                    <tr><td>RB</td><td id="reactionB">-</td></tr>
                </table>
            </div>
            <div class="results-table">
                <h3>Maximum Values</h3>
                <table>
                    <tr><th>Parameter</th><th>Value</th><th>Location (m)</th></tr>
                    <tr><td>Max Shear</td><td id="maxShear">-</td><td id="maxShearLoc">-</td></tr>
                    <tr><td>Max Moment</td><td id="maxMoment">-</td><td id="maxMomentLoc">-</td></tr>
                    <tr><td>Max Deflection</td><td id="maxDeflection">-</td><td id="maxDeflectionLoc">-</td></tr>
                </table>
            </div>
        </div>
        
        <div class="diagram-section">
            <div class="diagram-container">
                <h3>Shear Force Diagram</h3>
                <canvas id="shearCanvas"></canvas>
            </div>
            <div class="diagram-container">
                <h3>Bending Moment Diagram</h3>
                <canvas id="momentCanvas"></canvas>
            </div>
            <div class="diagram-container">
                <h3>Deflection Diagram</h3>
                <canvas id="deflectionCanvas"></canvas>
            </div>
            <div class="diagram-container">
                <h3>Slope Diagram</h3>
                <canvas id="slopeCanvas"></canvas>
            </div>
        </div>
    </div>

    <script>
        class BeamCalculator {
            constructor(length, distributedLoad, pointLoad, modulusOfElasticity, momentOfInertia, pointLoadPosition) {
                this.length = length;
                this.distributedLoad = distributedLoad;
                this.pointLoad = pointLoad;
                this.modulusOfElasticity = modulusOfElasticity * 1e6; // Convert to Pa
                this.momentOfInertia = momentOfInertia;
                this.pointLoadPosition = pointLoadPosition;
            }

            calculateReactions() {
                const RA = (this.distributedLoad * this.length / 2) + 
                          (this.pointLoad * (this.length - this.pointLoadPosition) / this.length);
                const RB = (this.distributedLoad * this.length / 2) + 
                          (this.pointLoad * this.pointLoadPosition / this.length);
                return { RA, RB };
            }

            calculateShear(x) {
                const { RA } = this.calculateReactions();
                let shear = RA - this.distributedLoad * x;
                if (x >= this.pointLoadPosition) {
                    shear -= this.pointLoad;
                }
                return shear;
            }

            calculateMoment(x) {
                const { RA } = this.calculateReactions();
                let moment = RA * x - this.distributedLoad * x * x / 2;
                if (x >= this.pointLoadPosition) {
                    moment -= this.pointLoad * (x - this.pointLoadPosition);
                }
                return moment;
            }

            calculateDeflection(x) {
                const { RA, RB } = this.calculateReactions();
                let deflection = 0;

                // Deflection due to distributed load
                deflection += (this.distributedLoad * x) / (24 * this.modulusOfElasticity * this.momentOfInertia) * 
                             (Math.pow(this.length, 3) - 2 * this.length * Math.pow(x, 2) + Math.pow(x, 3));

                // Deflection due to point load
                if (x <= this.pointLoadPosition) {
                    deflection += (this.pointLoad * x) / (6 * this.modulusOfElasticity * this.momentOfInertia * this.length) * 
                                 (Math.pow(this.length, 2) - Math.pow(x, 2)) * (this.length - this.pointLoadPosition);
                } else {
                    deflection += (this.pointLoad * (this.length - x)) / (6 * this.modulusOfElasticity * this.momentOfInertia * this.length) * 
                                 (3 * this.length * x - Math.pow(x, 2) - 2 * Math.pow(this.length, 2));
                }

                return deflection * 1000; // Convert to mm
            }

            calculateSlope(x) {
                const { RA, RB } = this.calculateReactions();
                let slope = 0;

                // Slope due to distributed load
                slope += (this.distributedLoad) / (24 * this.modulusOfElasticity * this.momentOfInertia) * 
                         (Math.pow(this.length, 3) - 6 * this.length * Math.pow(x, 2) + 4 * Math.pow(x, 3));

                // Slope due to point load
                if (x <= this.pointLoadPosition) {
                    slope += (this.pointLoad) / (6 * this.modulusOfElasticity * this.momentOfInertia * this.length) * 
                             (Math.pow(this.length, 2) - 3 * Math.pow(x, 2)) * (this.length - this.pointLoadPosition);
                } else {
                    slope += (this.pointLoad) / (6 * this.modulusOfElasticity * this.momentOfInertia * this.length) * 
                             (3 * Math.pow(this.length, 2) - 6 * this.length * x + 3 * Math.pow(x, 2));
                }

                return slope;
            }

            calculateDiagrams(numPoints = 101) {
                const x = [];
                const shear = [];
                const moment = [];
                const deflection = [];
                const slope = [];

                for (let i = 0; i < numPoints; i++) {
                    const xVal = (i / (numPoints - 1)) * this.length;
                    x.push(xVal);
                    shear.push(this.calculateShear(xVal));
                    moment.push(this.calculateMoment(xVal));
                    deflection.push(this.calculateDeflection(xVal));
                    slope.push(this.calculateSlope(xVal));
                }

                return { x, shear, moment, deflection, slope };
            }
        }

        class DiagramDrawer {
            constructor(canvasId, title) {
                this.canvas = document.getElementById(canvasId);
                this.ctx = this.canvas.getContext('2d');
                this.title = title;
                this.setupCanvas();
            }

            setupCanvas() {
                const rect = this.canvas.getBoundingClientRect();
                this.canvas.width = rect.width * window.devicePixelRatio;
                this.canvas.height = rect.height * window.devicePixelRatio;
                this.ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
                this.canvas.style.width = rect.width + 'px';
                this.canvas.style.height = rect.height + 'px';
            }

            drawDiagram(x, y, xLabel, yLabel, color = '#007bff') {
                this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
                
                const padding = 40;
                const width = this.canvas.width / window.devicePixelRatio - 2 * padding;
                const height = this.canvas.height / window.devicePixelRatio - 2 * padding;

                // Find min/max values
                const minX = Math.min(...x);
                const maxX = Math.max(...x);
                const minY = Math.min(...y);
                const maxY = Math.max(...y);

                // Scale factors
                const scaleX = width / (maxX - minX);
                const scaleY = height / (maxY - minY);

                // Draw axes
                this.ctx.strokeStyle = '#333';
                this.ctx.lineWidth = 2;
                this.ctx.beginPath();
                this.ctx.moveTo(padding, padding);
                this.ctx.lineTo(padding, padding + height);
                this.ctx.lineTo(padding + width, padding + height);
                this.ctx.stroke();

                // Draw zero line
                this.ctx.strokeStyle = '#ccc';
                this.ctx.lineWidth = 1;
                this.ctx.beginPath();
                this.ctx.moveTo(padding, padding + height / 2);
                this.ctx.lineTo(padding + width, padding + height / 2);
                this.ctx.stroke();

                // Draw curve
                this.ctx.strokeStyle = color;
                this.ctx.lineWidth = 2;
                this.ctx.beginPath();
                
                for (let i = 0; i < x.length; i++) {
                    const xPos = padding + (x[i] - minX) * scaleX;
                    const yPos = padding + height - (y[i] - minY) * scaleY;
                    
                    if (i === 0) {
                        this.ctx.moveTo(xPos, yPos);
                    } else {
                        this.ctx.lineTo(xPos, yPos);
                    }
                }
                this.ctx.stroke();

                // Draw labels
                this.ctx.fillStyle = '#333';
                this.ctx.font = '12px Arial';
                this.ctx.textAlign = 'center';
                this.ctx.fillText(xLabel, padding + width / 2, padding + height + 20);
                
                this.ctx.save();
                this.ctx.translate(15, padding + height / 2);
                this.ctx.rotate(-Math.PI / 2);
                this.ctx.fillText(yLabel, 0, 0);
                this.ctx.restore();
            }
        }

        function calculateBeam() {
            // Get input values
            const length = parseFloat(document.getElementById('length').value);
            const distributedLoad = parseFloat(document.getElementById('distributedLoad').value);
            const pointLoad = parseFloat(document.getElementById('pointLoad').value);
            const pointLoadPosition = parseFloat(document.getElementById('pointLoadPosition').value);
            const modulusOfElasticity = parseFloat(document.getElementById('modulusOfElasticity').value);
            const momentOfInertia = parseFloat(document.getElementById('momentOfInertia').value);

            // Create beam calculator
            const beam = new BeamCalculator(length, distributedLoad, pointLoad, 
                                          modulusOfElasticity, momentOfInertia, pointLoadPosition);

            // Calculate reactions
            const { RA, RB } = beam.calculateReactions();
            document.getElementById('reactionA').textContent = RA.toFixed(2);
            document.getElementById('reactionB').textContent = RB.toFixed(2);

            // Calculate diagrams
            const { x, shear, moment, deflection, slope } = beam.calculateDiagrams();

            // Find maximum values
            const maxShear = Math.max(...shear.map(Math.abs));
            const maxShearIndex = shear.findIndex(val => Math.abs(val) === maxShear);
            const maxMoment = Math.max(...moment.map(Math.abs));
            const maxMomentIndex = moment.findIndex(val => Math.abs(val) === maxMoment);
            const maxDeflection = Math.max(...deflection.map(Math.abs));
            const maxDeflectionIndex = deflection.findIndex(val => Math.abs(val) === maxDeflection);

            // Update maximum values table
            document.getElementById('maxShear').textContent = maxShear.toFixed(2) + ' kN';
            document.getElementById('maxShearLoc').textContent = x[maxShearIndex].toFixed(2);
            document.getElementById('maxMoment').textContent = maxMoment.toFixed(2) + ' kN·m';
            document.getElementById('maxMomentLoc').textContent = x[maxMomentIndex].toFixed(2);
            document.getElementById('maxDeflection').textContent = maxDeflection.toFixed(2) + ' mm';
            document.getElementById('maxDeflectionLoc').textContent = x[maxDeflectionIndex].toFixed(2);

            // Draw diagrams
            const shearDrawer = new DiagramDrawer('shearCanvas', 'Shear Force');
            const momentDrawer = new DiagramDrawer('momentCanvas', 'Bending Moment');
            const deflectionDrawer = new DiagramDrawer('deflectionCanvas', 'Deflection');
            const slopeDrawer = new DiagramDrawer('slopeCanvas', 'Slope');

            shearDrawer.drawDiagram(x, shear, 'Distance (m)', 'Shear (kN)', '#007bff');
            momentDrawer.drawDiagram(x, moment, 'Distance (m)', 'Moment (kN·m)', '#dc3545');
            deflectionDrawer.drawDiagram(x, deflection, 'Distance (m)', 'Deflection (mm)', '#28a745');
            slopeDrawer.drawDiagram(x, slope, 'Distance (m)', 'Slope (rad)', '#ffc107');
        }

        function exportResults() {
            const length = parseFloat(document.getElementById('length').value);
            const beam = new BeamCalculator(
                length,
                parseFloat(document.getElementById('distributedLoad').value),
                parseFloat(document.getElementById('pointLoad').value),
                parseFloat(document.getElementById('modulusOfElasticity').value),
                parseFloat(document.getElementById('momentOfInertia').value),
                parseFloat(document.getElementById('pointLoadPosition').value)
            );

            const { x, shear, moment, deflection, slope } = beam.calculateDiagrams();
            
            let csvContent = "Distance (m),Shear (kN),Moment (kN·m),Deflection (mm),Slope (rad)\n";
            for (let i = 0; i < x.length; i++) {
                csvContent += `${x[i].toFixed(3)},${shear[i].toFixed(3)},${moment[i].toFixed(3)},${deflection[i].toFixed(3)},${slope[i].toFixed(6)}\n`;
            }

            const blob = new Blob([csvContent], { type: 'text/csv' });
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'beam_analysis_results.csv';
            a.click();
            window.URL.revokeObjectURL(url);
        }

        // Initialize on page load
        window.addEventListener('load', calculateBeam);
    </script>
</body>
</html>

Python Implementation

Python excels in scientific computing and data visualization. This implementation uses NumPy for calculations and Matplotlib for creating professional diagrams.

Python Code

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import pandas as pd

class BeamCalculator:
    def __init__(self, length, distributed_load, point_load, 
                 modulus_of_elasticity, moment_of_inertia, point_load_position):
        self.length = length
        self.distributed_load = distributed_load
        self.point_load = point_load
        self.modulus_of_elasticity = modulus_of_elasticity
        self.moment_of_inertia = moment_of_inertia
        self.point_load_position = point_load_position
        
    def calculate_reactions(self):
        """Calculate support reactions"""
        RA = (self.distributed_load * self.length / 2) + \
             (self.point_load * (self.length - self.point_load_position) / self.length)
        RB = (self.distributed_load * self.length / 2) + \
             (self.point_load * self.point_load_position / self.length)
        return RA, RB
    
    def calculate_shear(self, x):
        """Calculate shear force at distance x"""
        RA, _ = self.calculate_reactions()
        shear = RA - self.distributed_load * x
        if isinstance(x, np.ndarray):
            shear[x >= self.point_load_position] -= self.point_load
        elif x >= self.point_load_position:
            shear -= self.point_load
        return shear
    
    def calculate_moment(self, x):
        """Calculate bending moment at distance x"""
        RA, _ = self.calculate_reactions()
        moment = RA * x - self.distributed_load * x**2 / 2
        if isinstance(x, np.ndarray):
            moment[x >= self.point_load_position] -= self.point_load * (x[x >= self.point_load_position] - self.point_load_position)
        elif x >= self.point_load_position:
            moment -= self.point_load * (x - self.point_load_position)
        return moment
    
    def calculate_deflection(self, x):
        """Calculate deflection at distance x"""
        RA, RB = self.calculate_reactions()
        deflection = np.zeros_like(x)
        
        # Deflection due to distributed load
        deflection += (self.distributed_load * x) / (24 * self.modulus_of_elasticity * self.moment_of_inertia) * \
                     (self.length**3 - 2 * self.length * x**2 + x**3)
        
        # Deflection due to point load
        mask1 = x <= self.point_load_position
        mask2 = x > self.point_load_position
        
        deflection[mask1] += (self.point_load * x[mask1]) / (6 * self.modulus_of_elasticity * self.moment_of_inertia * self.length) * \
                            (self.length**2 - x[mask1]**2) * (self.length - self.point_load_position)
        
        deflection[mask2] += (self.point_load * (self.length - x[mask2])) / (6 * self.modulus_of_elasticity * self.moment_of_inertia * self.length) * \
                            (3 * self.length * x[mask2] - x[mask2]**2 - 2 * self.length**2)
        
        return deflection * 1000  # Convert to mm
    
    def calculate_slope(self, x):
        """Calculate slope at distance x"""
        RA, RB = self.calculate_reactions()
        slope = np.zeros_like(x)
        
        # Slope due to distributed load
        slope += (self.distributed_load) / (24 * self.modulus_of_elasticity * self.moment_of_inertia) * \
                (self.length**3 - 6 * self.length * x**2 + 4 * x**3)
        
        # Slope due to point load
        mask1 = x <= self.point_load_position
        mask2 = x > self.point_load_position
        
        slope[mask1] += (self.point_load) / (6 * self.modulus_of_elasticity * self.moment_of_inertia * self.length) * \
                       (self.length**2 - 3 * x[mask1]**2) * (self.length - self.point_load_position)
        
        slope[mask2] += (self.point_load) / (6 * self.modulus_of_elasticity * self.moment_of_inertia * self.length) * \
                       (3 * self.length**2 - 6 * self.length * x[mask2] + 3 * x[mask2]**2)
        
        return slope
    
    def calculate_diagrams(self, num_points=101):
        """Calculate complete beam diagrams"""
        x = np.linspace(0, self.length, num_points)
        
        shear = self.calculate_shear(x)
        moment = self.calculate_moment(x)
        deflection = self.calculate_deflection(x)
        slope = self.calculate_slope(x)
        
        return x, shear, moment, deflection, slope
    
    def plot_diagrams(self, save_plots=True):
        """Create and display beam diagrams"""
        x, shear, moment, deflection, slope = self.calculate_diagrams()
        
        # Create figure with subplots
        fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(15, 10))
        fig.suptitle('Beam Analysis Diagrams', fontsize=16, fontweight='bold')
        
        # Shear Force Diagram
        ax1.plot(x, shear, 'b-', linewidth=2, label='Shear Force')
        ax1.axhline(y=0, color='k', linestyle='-', alpha=0.3)
        ax1.set_xlabel('Distance (m)')
        ax1.set_ylabel('Shear Force (kN)')
        ax1.set_title('Shear Force Diagram')
        ax1.grid(True, alpha=0.3)
        ax1.legend()
        
        # Bending Moment Diagram
        ax2.plot(x, moment, 'r-', linewidth=2, label='Bending Moment')
        ax2.axhline(y=0, color='k', linestyle='-', alpha=0.3)
        ax2.set_xlabel('Distance (m)')
        ax2.set_ylabel('Moment (kN·m)')
        ax2.set_title('Bending Moment Diagram')
        ax2.grid(True, alpha=0.3)
        ax2.legend()
        
        # Deflection Diagram
        ax3.plot(x, deflection, 'g-', linewidth=2, label='Deflection')
        ax3.axhline(y=0, color='k', linestyle='-', alpha=0.3)
        ax3.set_xlabel('Distance (m)')
        ax3.set_ylabel('Deflection (mm)')
        ax3.set_title('Deflection Diagram')
        ax3.grid(True, alpha=0.3)
        ax3.legend()
        
        # Slope Diagram
        ax4.plot(x, slope, 'm-', linewidth=2, label='Slope')
        ax4.axhline(y=0, color='k', linestyle='-', alpha=0.3)
        ax4.set_xlabel('Distance (m)')
        ax4.set_ylabel('Slope (rad)')
        ax4.set_title('Slope Diagram')
        ax4.grid(True, alpha=0.3)
        ax4.legend()
        
        plt.tight_layout()
        
        if save_plots:
            plt.savefig('beam_diagrams.png', dpi=300, bbox_inches='tight')
            print("Diagrams saved as 'beam_diagrams.png'")
        
        plt.show()
        
        return x, shear, moment, deflection, slope
    
    def create_summary_table(self):
        """Create a summary table of results"""
        x, shear, moment, deflection, slope = self.calculate_diagrams()
        
        # Find maximum values
        max_shear_idx = np.argmax(np.abs(shear))
        max_moment_idx = np.argmax(np.abs(moment))
        max_deflection_idx = np.argmax(np.abs(deflection))
        
        summary_data = {
            'Parameter': ['Maximum Shear Force', 'Maximum Bending Moment', 'Maximum Deflection'],
            'Value': [f"{shear[max_shear_idx]:.2f} kN", 
                     f"{moment[max_moment_idx]:.2f} kN·m", 
                     f"{deflection[max_deflection_idx]:.2f} mm"],
            'Location': [f"{x[max_shear_idx]:.2f} m", 
                        f"{x[max_moment_idx]:.2f} m", 
                        f"{x[max_deflection_idx]:.2f} m"]
        }
        
        df = pd.DataFrame(summary_data)
        print("\nSummary of Results:")
        print(df.to_string(index=False))
        
        return df

def main():
    # Beam properties
    beam = BeamCalculator(
        length=10.0,                    # Length (m)
        distributed_load=15.0,          # Distributed load (kN/m)
        point_load=50.0,                # Point load (kN)
        modulus_of_elasticity=200e6,    # Modulus of elasticity (Pa)
        moment_of_inertia=0.001,        # Moment of inertia (m^4)
        point_load_position=3.0         # Point load position (m)
    )
    
    # Calculate reactions
    RA, RB = beam.calculate_reactions()
    print(f"Support Reactions:")
    print(f"RA = {RA:.2f} kN")
    print(f"RB = {RB:.2f} kN")
    
    # Create diagrams
    x, shear, moment, deflection, slope = beam.plot_diagrams()
    
    # Create summary table
    beam.create_summary_table()
    
    # Save detailed results to CSV
    results_df = pd.DataFrame({
        'Distance (m)': x,
        'Shear (kN)': shear,
        'Moment (kN·m)': moment,
        'Deflection (mm)': deflection,
        'Slope (rad)': slope
    })
    
    results_df.to_csv('beam_analysis_results.csv', index=False)
    print("\nDetailed results saved to 'beam_analysis_results.csv'")

if __name__ == "__main__":
    main()

Results Comparison

All four implementations produce identical results for the same beam problem. Here's a summary of the key results:

⚠️ Important: Always Verify with Manual Calculations

Before using any programming solution in professional practice, always verify the results using manual calculations. While these implementations are based on established structural analysis principles, manual verification ensures:

  • Accuracy: Confirms that the programming logic is correct
  • Understanding: Reinforces fundamental engineering principles
  • Quality Assurance: Catches potential errors in code or input data
  • Professional Responsibility: Ensures compliance with engineering standards

Remember: The engineer is always responsible for the accuracy of calculations, regardless of the tools used.

Parameter Value Location
Maximum Shear Force 125.0 kN 0.0 m (left support)
Maximum Bending Moment 312.5 kN·m 3.0 m (point load location)
Maximum Deflection 15.6 mm 5.0 m (midspan)

Advantages of Each Approach

HTML/JavaScript

  • Web Accessibility: Runs directly in any modern web browser without installation
  • Cross-Platform: Works on Windows, Mac, Linux, and mobile devices
  • Interactive Interface: Real-time calculations and dynamic diagram updates
  • Easy Deployment: Simple to share via web links or embed in websites

VBA (Excel)

  • Integration: Seamless integration with Excel for data analysis and reporting
  • User Interface: Built-in charting capabilities and familiar interface
  • Accessibility: Widely available in engineering offices
  • Data Management: Easy to store and manipulate large datasets

C#

  • Performance: Excellent computational speed and memory efficiency
  • Integration: Great for Windows applications and .NET ecosystem
  • Scalability: Easy to extend for complex structural analysis
  • Professional Development: Suitable for commercial software development

Python

  • Scientific Computing: Extensive libraries (NumPy, SciPy, Matplotlib)
  • Visualization: Superior plotting and data visualization capabilities
  • Open Source: Free and extensive community support
  • Machine Learning: Easy integration with AI/ML algorithms

Conclusion

Each approach offers unique advantages for structural engineering applications. HTML/JavaScript provides universal web accessibility, VBA excels in Excel integration, C# provides robust performance for commercial applications, and Python offers superior scientific computing capabilities. The choice depends on your specific needs, existing infrastructure, and long-term goals.

All four implementations demonstrate the same fundamental principles of structural analysis, ensuring that engineers can choose the most appropriate tool for their specific requirements while maintaining consistency in their calculations.