Day 13 – Working with Geometry: numpy & matplotlib
📐 Day 13 – Working with Geometry: numpy & matplotlib
1. Learning Objectives
By the end of Day 13, you will be able to:
- Use numpy to create and manipulate arrays of coordinates efficiently.
- Compute distances, centroids, and transformations (translation, rotation) using numpy.
- Use matplotlib to create 2D plots of column grids, floor plans, and structural node diagrams.
- Visualise simple engineering data like beam deflection curves.
- Save plots as image files for reports.
2. Concept Explanation
2.1 Why numpy & matplotlib in AEC?
numpy provides fast, vectorised operations on arrays – essential when working with thousands of coordinates (point clouds, mesh vertices, column grids).
matplotlib is the standard Python plotting library. Use it to:
- Plot column grids and floor plans.
- Visualise deflection shapes, stress contours, or temperature distributions.
- Create publication‑ready figures for reports.
2.2 numpy Basics
import numpy as np
# Creating arrays
points = np.array([[0.0, 0.0],
[6.0, 0.0],
[6.0, 8.0],
[0.0, 8.0]]) # shape (4, 2)
# Array properties
print(points.shape) # (4, 2)
print(points.ndim) # 2
print(points[0]) # [0. 0.]
print(points[:, 0]) # all x coordinates: [0. 6. 6. 0.]
# Vectorised operations
translated = points + np.array([2.0, 3.0]) # adds to every row
print(translated)
# Compute distances between consecutive points
deltas = np.diff(points, axis=0) # shape (3, 2)
distances = np.sqrt(np.sum(deltas**2, axis=1))
print(distances) # [6. 8. 6.] (edge lengths)
# Centroid (mean of all points)
centroid = np.mean(points, axis=0) # [3. 4.]
2.3 matplotlib Basics
import matplotlib.pyplot as plt
# Simple line plot
x = np.linspace(0, 6, 100) # 100 points from 0 to 6
y = x**2 / 8 # parabola – approximate deflection shape?
plt.plot(x, y, 'b-', label='Deflection curve')
plt.xlabel('Span (m)')
plt.ylabel('Deflection (mm)')
plt.title('Beam Deflection')
plt.grid(True)
plt.legend()
plt.show() # displays the plot
# To save: plt.savefig('deflection.png', dpi=300)
2.4 Plotting Points and Shapes
# Scatter plot of column grid
x_coords = points[:, 0]
y_coords = points[:, 1]
plt.figure(figsize=(6, 4))
plt.scatter(x_coords, y_coords, color='red', s=100, label='Columns')
plt.xlabel('X (m)')
plt.ylabel('Y (m)')
plt.title('Column Grid')
plt.grid(True, linestyle='--', alpha=0.7)
plt.axis('equal') # equal aspect ratio
plt.legend()
plt.show()
3. Code Examples
Example 1: Column grid with labels
import numpy as np
import matplotlib.pyplot as plt
# Generate a 4x3 column grid (x spacing 6m, y spacing 8m)
x_pos = np.arange(0, 4) * 6.0 # [0, 6, 12, 18]
y_pos = np.arange(0, 3) * 8.0 # [0, 8, 16]
# Create meshgrid
X, Y = np.meshgrid(x_pos, y_pos) # X and Y are 3x4 arrays
columns_x = X.flatten()
columns_y = Y.flatten()
plt.figure(figsize=(8, 5))
plt.scatter(columns_x, columns_y, color='navy', s=120, zorder=5)
# Label each column
for i, (x, y) in enumerate(zip(columns_x, columns_y)):
plt.text(x + 0.3, y + 0.3, f'C{i+1}', fontsize=8)
plt.xlabel('X (m)')
plt.ylabel('Y (m)')
plt.title('4×3 Column Grid (x-spacing=6m, y-spacing=8m)')
plt.axis('equal')
plt.grid(True, linestyle=':', alpha=0.6)
plt.show()
Example 2: Polyline (floor outline) with numpy
# Storey floor outline (rectangular with a notch)
outline = np.array([
[0.0, 0.0],
[12.0, 0.0],
[12.0, 8.0],
[8.0, 8.0],
[8.0, 4.0],
[4.0, 4.0],
[4.0, 8.0],
[0.0, 8.0],
[0.0, 0.0] # close the polygon
])
# Plot
plt.figure(figsize=(7, 5))
plt.plot(outline[:, 0], outline[:, 1], 'k-', linewidth=2, label='Floor outline')
plt.fill(outline[:, 0], outline[:, 1], alpha=0.2, color='gray')
plt.xlabel('X (m)')
plt.ylabel('Y (m)')
plt.title('Floor Plate with Notch')
plt.axis('equal')
plt.grid(True, linestyle=':', alpha=0.5)
plt.legend()
plt.show()
Example 3: Beam deflection curve visualisation
import numpy as np
import matplotlib.pyplot as plt
# Parameters
L = 6.0 # span in m
w = 25.0 # UDL in kN/m
E = 200000.0 # MPa
I = 120e6 # mm⁴
# Deflection formula: v(x) = w*x*(L^3 - 2*L*x^2 + x^3) / (24*E*I)
# Units: w in kN/m, L in m, but we convert to N and mm
w_n_mm = w * 1000 / 1000 # N/mm (1 kN/m = 1 N/mm)
L_mm = L * 1000 # mm
x_mm = np.linspace(0, L_mm, 200) # positions along span (mm)
v_mm = (w_n_mm * x_mm * (L_mm**3 - 2 * L_mm * x_mm**2 + x_mm**3)) / (24 * E * I)
plt.figure(figsize=(8, 4))
plt.plot(x_mm / 1000, v_mm, 'b-', linewidth=2, label='Deflection')
plt.axhline(0, color='gray', linestyle='--', linewidth=1)
plt.xlabel('Position along span (m)')
plt.ylabel('Deflection (mm)')
plt.title(f'Beam Deflection (span={L}m, UDL={w}kN/m)')
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
Example 4: Multiple subplots for design comparison
import numpy as np
import matplotlib.pyplot as plt
# Compare deflection for two different sections
L = 6.0
w = 25.0
E = 200000.0
sections = [
{"name": "UB 406×178×60", "I": 216e6},
{"name": "UB 533×210×82", "I": 475e6},
]
x = np.linspace(0, L*1000, 200)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
for i, sec in enumerate(sections):
I_val = sec["I"]
v = (w*1000/1000 * x * ( (L*1000)**3 - 2*(L*1000)*x**2 + x**3 )) / (24 * E * I_val)
ax1.plot(x/1000, v, label=sec["name"])
ax1.set_xlabel('Span (m)')
ax1.set_ylabel('Deflection (mm)')
ax1.set_title('Deflection Comparison')
ax1.legend()
ax1.grid(True)
# Bar chart of max deflection
max_defs = [np.max(abs(v)) for v in [ ... ]] # need to compute
# Simpler: compute outside and plot
max_defs = []
for sec in sections:
v = (w*1000/1000 * x * ( (L*1000)**3 - 2*(L*1000)*x**2 + x**3 )) / (24 * E * sec["I"])
max_defs.append(np.max(np.abs(v)))
names = [s["name"] for s in sections]
ax2.bar(names, max_defs, color=['steelblue', 'seagreen'])
ax2.set_ylabel('Max Deflection (mm)')
ax2.set_title('Maximum Deflection')
ax2.grid(axis='y', linestyle=':', alpha=0.6)
plt.tight_layout()
plt.show()
4. Hands‑on Exercises (3–5 Problems)
Problem 1 – Rectangle coordinates
Create a numpy array representing the four corners of a rectangle 10m x 6m, starting at (0,0). Print the array and compute its perimeter.
Problem 2 – Translate a floor outline
Given a floor outline as a numpy array (e.g., the notched polygon from Example 2), translate it by (3.0, 2.5) and plot both original and translated outlines.
Problem 3 – Column grid scatter plot
Create a 5×4 column grid (x spacing 7.5m, y spacing 9.0m). Plot the columns as red circles, add grid lines, and label the first and last column.
Problem 4 – Simple deflection plot
Using the deflection formula from Example 3, plot the deflection for a beam with:
- Span = 8.0 m
- UDL = 30 kN/m
- E = 200000 MPa
- I = 350e6 mm⁴
Plot and label. What is the maximum deflection? (Read from plot or compute using np.max).
Solutions (attempt first):
# P1
import numpy as np
rect = np.array([[0,0], [10,0], [10,6], [0,6]])
print(rect)
# perimeter: sum of edge lengths
edges = np.diff(np.vstack([rect, rect[0]]), axis=0)
perim = np.sum(np.sqrt(np.sum(edges**2, axis=1)))
print(f"Perimeter: {perim:.1f} m")
# P2
outline = np.array([[0,0],[12,0],[12,8],[8,8],[8,4],[4,4],[4,8],[0,8],[0,0]])
shift = np.array([3.0, 2.5])
outline_shifted = outline + shift
import matplotlib.pyplot as plt
plt.plot(outline[:,0], outline[:,1], 'b-', label='Original')
plt.plot(outline_shifted[:,0], outline_shifted[:,1], 'r-', label='Shifted')
plt.axis('equal'); plt.grid(True); plt.legend(); plt.show()
# P3
x = np.arange(5) * 7.5
y = np.arange(4) * 9.0
X, Y = np.meshgrid(x, y)
plt.scatter(X, Y, c='red', s=80)
plt.text(X[0,0], Y[0,0], 'C1', fontsize=10)
plt.text(X[-1,-1], Y[-1,-1], f'C{X.size}', fontsize=10)
plt.xlabel('X (m)'); plt.ylabel('Y (m)')
plt.title('5×4 Column Grid')
plt.axis('equal'); plt.grid(True, linestyle=':'); plt.show()
# P4
import numpy as np, matplotlib.pyplot as plt
L = 8.0; w = 30.0; E = 200000.0; I = 350e6
x = np.linspace(0, L*1000, 200)
v = (w*1000/1000 * x * ((L*1000)**3 - 2*L*1000*x**2 + x**3)) / (24 * E * I)
plt.plot(x/1000, v)
plt.xlabel('Span (m)'); plt.ylabel('Deflection (mm)')
plt.title('Beam Deflection')
plt.grid(True); plt.show()
print(f"Max deflection: {np.max(np.abs(v)):.2f} mm")
5. Applied Challenge Task
Task: Structural Grid and Load Diagram Generator
Design a script that:
Generates a structural grid based on user input:
- Number of bays in X and Y directions.
- Bay spacing in X and Y (metres).
Plots the column grid as a scatter plot with column labels.
Draws grid lines between columns (using
plt.plotandnp.meshgrid).Overlays a simple load diagram:
- Randomly assign a "load zone" colour to each bay (e.g., low/medium/high load) using a colour map.
- Use
plt.fillto shade each bay based on load intensity (usingplt.colormaps).
Annotates the total number of columns and total floor area on the plot.
Saves the figure as
structural_grid.png.
Why this matters:
Visualising structural grids and load distributions is a common task in early design stages. This exercise integrates numpy array operations with matplotlib visualisation – skills you'll use daily in computational design.
6. Brief Review Summary
numpy provides fast array operations for coordinates.
np.array,np.meshgrid,np.diff,np.mean, vectorised arithmetic.
matplotlib creates publication‑quality plots.
plt.plot,plt.scatter,plt.fill,plt.text,plt.subplots.- Use
plt.axis('equal')for correct aspect ratio. - Save figures with
plt.savefig().
Combine numpy + matplotlib to visualise AEC geometry: column grids, floor plates, deflection curves.
Vectorised operations avoid slow Python loops – critical for large models.
Key takeaway:
You can now generate and visualise geometry programmatically. This is the foundation for parametric design and automated engineering diagrams.
7. Preview of Next Topic (Day 14)
Tomorrow we’ll cover Basic Classes and Objects – the heart of Object‑Oriented Programming (OOP).
You’ll learn:
- Defining a
Beamclass with attributes (span, load, material) and methods (moment, shear). - Creating multiple beam instances and storing them in lists.
- Using
__init__,__str__, and properties. - Practical example: a
Roomclass that computes area and volume, and aBuildingclass that manages floors.
OOP will transform how you structure your AEC code – making it more intuitive, scalable, and aligned with how we think about building components.

Comments
Post a Comment