Published on October 13, 2025

Code Marathon - Steel Building

In this code marathon I graphically modeled a steel building in 3D with pure code, i.e. without using any CAD software or modeling framework.

Start Line

I started with a test case by defining a ten-story steel moment-frame building made up of 4x4 rectangular bays, each 10m in the east–west and 8m in the north–south direction, for an overall footprint of 40x32m. The first story is 5.5m high with upper stories at 4.0m, reaching a roof height of 41.5m. Lateral resistance is provided by moment frames along all perimeter lines: row A and E in the east–west direction and columns 1 and 5 in the north–south direction. Interior framing consists of gravity-only beams with pinned connections. Columns are continuous through all stories with splices located at the mid point between floors.

A plan view of the structure shows a 5x5 grid of nodes forming 4 bays

The structure was loosely based on a paper by A. Kaveh et. al. [1].

I also created a member-by-member plan where the member sizes were chosen somewhat arbitrarily based on quick research, erring on the side of undersized to make potential future analysis more interesting.

Section (elevation) view of rows A and E
Section (elevation) view of rows B, C, and D

Section (elevation) view of columns 1 and 5
Section (elevation) view of columns 2, 3, and 4.

I set a goal finish of 3 hours, which is about a 7 min/mile pace. For this first code marathon I also created a little timing applet that starts a clock and counts up the miles based on the goal pace.

Mile 1: Project Setup

First I set up a boilerplate vue project with create vue@latest opting for a bare Typescript preset. I set up a router and some global styles for development flexibility.

I also imported Babylonjs and got a basic canvas with cameras, lights, and a floor. I tried to get a 1mx1m grid on the ground but couldn't get it working quickly enough.

Figuring out the ground grid

This is also where I locked in the unit scale where 1 world unit is 1 meter.

Mile 4: Steel profile Generation

I briefly pondered if I should make a wireframe model of the structure first and then replace the wires with actual steel members later, but quickly decided to skip that step given the time crunch.

So I decided the first step should be creating the steel profiles.

Before the marathon started, I created a dataset of American (AISC) steel profiles by collecting publicly available data and forming it into a normalized JSON array. The data was poorly normalized so I used a quick JS script to clean it up and process it so that each member had the following shape:

typescript
export type AmericanWideFlangeProfile = {
  name: string;
  depthIn: number;
  widthIn: number;
  webThicknessIn: number;
  flangeThicknessIn: number;
  linearWeightLbfPerFoot: number;
  areaIn2: number;
  secondMomentXxIn4: number;
  secondMomentYyIn4: number;
  sectionModulusXxIn3: number;
  sectionModulusYyIn3: number;
  radiusOfGyrationXxIn: number;
  radiusOfGyrationYyIn: number;
  colorRgb?: [number, number, number]; // Normalized 0-1
};

I created a new route for a separate testing interface that could draw a beam mesh given a profile and length.

To construct the profile shape from the data, I quickly figured out the coordinates for each point in the profile.

Figuring out coordinate of each point on the steel profile relative to the origin

I used babylon's built in extrusion mesh builder to then construct the mesh based on the profile points.

The first mesh of a beam successfully drawn

A W14x455 steel profile 6 meters long

A W14x455 steel profile 6 meters long drawn in the applet I created

Mile 13: Member Placement

Once I had a reliable way to create the steel members, I got started on assembling them into a building based on the plan.

First I made sure to carefully define the coordinate system. I define +x as east, +z and north, and +y as positive elevation.

Setting up a coordinate system

I decided on a row by row approach. Each row is drawn floor by floor, and each floor is drawn west to east. This places the origin point of the building at the south west corner.

I started with all the columns.

The outside columns drawn

I did the outside columns first (rows 1 and 5) to validate the row drawing function. Then did the rest.

All the columns draw out

Then I did the beams. It's fun how one tiny error can throw the whole things off and create surprising and sometimes interesting results.

The beams got misplaced at first

All the beams in the rows correctly placed

The only thing missing now are the beams that go between the rows.

The building complete

The code for the drawing functions is below. It's pretty messy but thats what makes a code marathon fun.

Finish

I ended up going overtime by about 45 minutes. The stream lasted for a total of 3 hours and 47 minutes.

The steel building complete, a full view

Another view of the complete building

A closeup shot of the building

Conclusion

I had a lot of fun with this challenge although the stream itself was a fail. There was no audio for a significant portion due to an OBS misconfiguration, and my webcam also dropped out.

I'll probably spin off the steel member generator as an applet on this site, and definitely upload the JSON steel profile data somewhere on this site too.

For the next stream, I want to do a truss bridge and run analysis on it. But who knows? I might come back to play with this building some more.

Live Stream

The live stream is unlisted on my channel because of the audio issues, but you can still watch it here:

Sources

  1. A. Kaveh, M. Fahimi Farzam, and M. Kalateh Ahani, “Optimum design of steel frame structures considering construction cost and seismic damage,” Smart Structures and Systems, vol. 16, no. 1, pp. 1–26, Jul. 2015, doi: 10.12989/sss.2015.16.1.001.

© 2024 Erik Nakamura. All rights reserved.

Use of this content is subject to the terms described in the license section of the about page.