Case Study 2 — CAD and the Architect's Drawing: When You Want Flatness

Field: computer-aided design (CAD), architecture, and engineering. A deliberate contrast with Case Study 1: where a game wants perspective realism, a CAD system wants orthographic precision — the same transformation machinery, used for the opposite visual goal.

The problem

An architect models a building once, in three dimensions, but must produce many flat drawings from it: a top-down floor plan, a front elevation, a side elevation. Crucially, those drawings must preserve true measurements — a wall that is six meters long must read as six meters on the plan, at the drawing's scale, regardless of where it sits in depth. A perspective view, with its distant-things-shrink behavior, would ruin this: two identical windows at different depths would draw at different sizes, and you could not measure off the drawing. So CAD leans on the projection a game avoids — orthographic — and on precise composition of placement transforms. This case study shows the same Chapter 12 matrices serving accuracy rather than illusion.

The building is assembled from reusable components — beams, panels, windows — each authored once as a simple shape in its own local coordinates, then placed many times by model matrices. This is identical in spirit to the game's barrels, and it is why CAD, like games, is built on homogeneous transformation matrices: one component definition, many placements, each a $4\times 4$ matrix.

Step 1 — Placing a component with a model matrix

Consider a structural beam, authored as a unit cube, that the engineer wants to be $2\,\text{m}$ long ($x$), $1\,\text{m}$ tall ($y$), and $0.5\,\text{m}$ deep ($z$), positioned with its corner at world $(3, 2, 0)$. The model matrix is a scale followed by a translation (no rotation this time):

$$M = T(3, 2, 0)\, S(2, 1, 0.5).$$

# Place a 2m x 1m x 0.5m beam (authored as a unit cube) at world (3, 2, 0).
import numpy as np
def T3(tx,ty,tz):
    M = np.eye(4); M[0,3],M[1,3],M[2,3] = tx,ty,tz; return M
def S3(sx,sy,sz): return np.diag([sx,sy,sz,1.0])

M = T3(3,2,0) @ S3(2,1,0.5)
print(np.round(M, 4))
print("far corner (1,1,1) -> world:", (M @ np.array([1,1,1,1.0])))
[[2.  0.  0.  3. ]
 [0.  1.  0.  2. ]
 [0.  0.  0.5 0. ]
 [0.  0.  0.  1. ]]
far corner (1,1,1) -> world: [5.  3.  0.5 1. ]

The beam's near corner (its local origin) sits at world $(3, 2, 0)$, and its far corner $(1,1,1)$ stretches to $(5, 3, 0.5)$ — two meters along $x$, one along $y$, half a meter in $z$, exactly the dimensions requested. The diagonal of the scale block carries the real-world sizes; the fourth column carries the position. Critically — and unlike a game — these are physical units: meters, not arbitrary art units, because CAD output must be dimensionally exact.

Step 2 — Rotating a component (and why order still matters)

Now the engineer rotates a second, identical beam by $90°$ about the vertical ($z$) axis before placing it at the same corner — a beam turned to run crosswise. The model matrix is $M' = T(3,2,0)\,R_z(90°)\,S(2,1,0.5)$:

# A second beam, rotated 90 deg about z, same scale, same placement corner.
def Rz(t): c,s=np.cos(t),np.sin(t); return np.array([[c,-s,0,0],[s,c,0,0],[0,0,1,0],[0,0,0,1]],float)
M2 = T3(3,2,0) @ Rz(np.radians(90)) @ S3(2,1,0.5)
print(np.round(M2, 4))
print("far corner (1,1,1) -> world:", np.round(M2 @ np.array([1,1,1,1.0]), 4))
[[ 0.  -1.   0.   3. ]
 [ 2.   0.   0.   2. ]
 [ 0.   0.   0.5  0. ]
 [ 0.   0.   0.   1. ]]
far corner (1,1,1) -> world: [2. 4. 0.5 1.]

The rotated beam's far corner now lands at $(2, 4, 0.5)$ instead of $(5, 3, 0.5)$: the $2\,\text{m}$ length that ran along $x$ now runs along $y$, exactly as a $90°$ turn about the vertical axis should do. Note that because we scaled first and rotated second (rightmost acts first, §12.5), the beam was sized while axis-aligned and then turned as a rigid whole — the natural authoring order. Had the engineer accidentally composed $S\,R_z$ instead of $R_z\,S$, a non-uniform scale after rotation would have skewed the beam into a parallelepiped, a classic CAD modeling bug. The order-matters discipline of §12.6 is not academic here; it is the difference between a rectangular beam and a sheared one.

Step 3 — Orthographic projection: the architect's flat, true drawing

To produce the top-down floor plan, the CAD system projects orthographically along the vertical axis: keep $(x, y)$, drop $z$. This is the singular, flattening projection of §12.7.1 — and here its very flatness is the feature, because it preserves distances within the drawing plane.

# Top-down floor plan: orthographic projection (drop z). Measurements are preserved.
corner = M @ np.array([1,1,1,1.0])          # beam far corner in world
print("top view (x, y):", corner[:2])       # (5, 3): z discarded, x and y exact
# Confirm a 2m edge still measures 2m after placement + projection:
p0 = (M @ np.array([0,0,0,1.0]))[:2]         # near corner, top view
p1 = (M @ np.array([1,0,0,1.0]))[:2]         # 2m along the beam, top view
print("edge endpoints:", p0, p1, " length:", np.linalg.norm(p1 - p0))
top view (x, y): [5. 3.]
edge endpoints: [3. 2.] [5. 2.]  length: 2.0

The beam's $2\,\text{m}$ edge measures exactly $2.0$ on the floor plan — no foreshortening, no depth-dependent shrink. An architect can lay a scale ruler on this drawing and read true dimensions, because orthographic projection discards depth without distorting the surviving two dimensions. A front elevation would instead drop $y$ (keep $x, z$); a side elevation drops $x$ (keep $y, z$). Three orthographic projections along the three axes give the three standard engineering views, each metrically faithful, all from the same 3D model and the same transformation toolkit.

Compare this directly to Case Study 1's game, which divided by depth to make far things small. Same pipeline — model matrix to place, then projection to flatten — but a different projection matrix yields the opposite visual contract: the game trades measurement for realism; the CAD drawing trades realism for measurement. Choosing the projection is choosing what your flat image is for.

Step 4 — A perspective preview for the client

Of course the architect also wants a pretty, realistic rendering to show the client — and that view uses perspective, exactly as the game did, by dividing by depth. The remarkable thing is that switching between the engineer's precise floor plan and the client's photorealistic walkthrough requires changing only the projection matrix at the end of the pipeline; the model matrices that place every beam, panel, and window are identical in both. This is the deep economy of the rendering pipeline: place the world once with model and view matrices, then choose your lens. Orthographic for the blueprint, perspective for the showcase, the same scene underneath.

Why this matters

CAD, architectural visualization, and mechanical engineering software all rest on the identical foundation as games and film — homogeneous $4\times 4$ matrices composing rotation, scaling, and translation, then a projection to a flat output — but they reveal a facet a game hides: that the choice of projection encodes the purpose of the image. The game in Case Study 1 needed perspective's $1/z$ to fake depth; the architect in this case study needs orthographic projection's flatness to preserve truth. Both are one matrix swap apart in the same pipeline.

The reusable-component pattern — author once in local coordinates, place many times with model matrices — is also why parametric CAD scales to buildings with millions of parts: each part carries its own transform, and assemblies compose those transforms hierarchically, just like the scene graph of §12.6's Real-World Application. And the order-matters lesson bites with physical consequences: a scale composed on the wrong side of a rotation does not merely look wrong, it produces a part with incorrect dimensions that could be manufactured and fail. Linear algebra here is not decoration; it is load-bearing, in the literal sense. The same Chapter 12 matrices that entertain in a game certify in engineering — a vivid reminder that linear algebra is the most applied branch of pure mathematics.

Try it yourself

  1. Produce all three standard engineering views of the unrotated beam: top (drop $z$), front (drop $y$), side (drop $x$). Confirm each view shows the beam's true extent in its two surviving dimensions ($2 \times 1$, $2 \times 0.5$, and $1 \times 0.5$ respectively).
  2. Deliberately compose the model matrix in the wrong order, $S(2,1,0.5)\,R_z(90°)$ instead of $R_z(90°)\,S(2,1,0.5)$, and apply it to the beam's corners. Show that the result is a skewed (non-rectangular) shape, and explain via §12.6 why scaling non-uniformly after rotating shears the object.
  3. Render the rotated beam with perspective projection (divide by depth) from a camera, then with orthographic projection. Measure a known $2\,\text{m}$ edge in each image and confirm only the orthographic one preserves the true length.
  4. Build a tiny "assembly" of two beams forming an L-shape, each with its own model matrix, and a single shared view matrix. Pan the camera (change the view matrix only) and confirm both beams move together while their relative geometry stays fixed — the scene-graph idea in miniature.