Daily Folding Practice
Collaborated with type designer Namju Ok to further develop TypoFold through a deeper understanding of type design.
04.2026 - 05.2026 / Workshop, Computational Design, Interactive Media / Space PADO

Process
About the Collaboration


I collaborated with type designer Namju Ok (@nevi_books). Together, we applied fonts that real designers make and use to TypoFold. This helped me understand how fonts are built and structured, and I used that understanding to improve TypoFold. We worked together for about two months. As an outcome of this collaboration, we ran a free workshop for designers at Space PADO.
Fonts
Four Font Families by Namju Ok
Through this collaboration, I was fortunate to apply four of Namju's font families, 6 styles in total, to TypoFold.
- limnlimn
- Leaves, Fresh
- Stone
- Heavy, Classy
- Arbor
- Regular
- Koshmar
- Regular

The four fonts all look very different, so each one needed its own kind of unfolding. I worked with Namju to go through the glyphs for letters and special characters, font by font. For each glyph, we recorded what type of polyhedron it would become once converted to 3D.
Terms
A Shared Vocabulary
Before describing the types of polyhedra, I want to introduce the terms used in this piece. TypoFold converts 2D glyphs into 3D solids, and then unfolds them back into a flat net. Because of this, no single field's vocabulary was enough to describe the whole process. With Namju's help, I learned the terms used in typography design. In this piece, I describe a glyph's shape using typographic terms, and I describe a polyhedron's structure using terms from GIS and computer graphics. [8]
Glyph
A glyph is an individual character that makes up a font. A single letter can be built from two or more glyphs. Punctuation marks can also count as separate glyphs if they look different, even when they serve the same function. For example, the vertical comma used in vertical writing and the regular comma used in horizontal writing are treated as two different glyphs. [1]
Counter

In type design, the white space enclosed by a stroke is called a counter. There are two broad types of counters. A closed counter is fully enclosed by the stroke and is not connected to the outer margin, as in A, B, D, O, P, Q, and R. An open counter connects to the outer margin through a gap called an aperture, as in C, S, c, and s. [2]
Contour
A contour is an unbroken line made of straight and curved segments. It can be either open or closed. [4] Font files store the contour data that makes up each glyph, and I used opentype.js to convert this data into SVG path strings.
Exterior / Interior ring

Depending on the font format, contours are stored in one of two ways: TrueType (ttf) or PostScript/CFF (otf). [3] Both formats store contours in drawing order, and both use winding direction to decide which region to fill. TrueType draws the outer contour clockwise, while CFF draws it counterclockwise. However, neither format stores which contour sits inside which one. Font renderers use the nonzero rule to fill shapes based on this direction, but since the two formats wind in opposite directions, I decided to determine containment by position instead. To do this, I sample points evenly along each contour and use ray casting to check whether each point falls inside another contour. Then I count how many layers deep each contour sits. An even count means the contour is exterior, and an odd count means it is interior. This follows the same logic as the even-odd fill rule. [7] Note that for fonts whose contours were drawn overlapping each other, the two rules can give different results.
Polyhedron / Polyhedra
Converting a glyph's data to SVG and extruding it with a height value produces a 3D solid. I call this solid a polyhedron. Some glyphs, such as 'i', are made of several separate solids. In these cases, I use the plural form, polyhedra, and treat all the solids from a single glyph as one group.
Font Tree
Types of Polyhedra from a Glyph
Using these terms, I mapped out, as a tree, what kind of polyhedron a glyph becomes once it is converted to 3D. The tree asks two or three questions in sequence. At each leaf, it is decided whether the glyph becomes one Polyhedron or several Polyhedra, and how many exterior and interior rings make up its boundary.

1. How many connected components?
The first question is how many separate components make up the glyph. A glyph with a single component, like 'I' or 'O', becomes one Polyhedron. A glyph like 'i', where the body and the dot are separate, becomes several Polyhedra. Even the same letter 'i' can become one Polyhedron or several Polyhedra, depending on how the font draws it. When a glyph has several Polyhedra, the net splits into that many separate pieces.
2. Any Closed Counters?
The second question is whether the glyph has any closed counters. A glyph with no closed counters has its boundary defined by the exterior ring alone. A glyph with closed counters gets one interior ring for each counter. For example, 'O' is a Polyhedron with one exterior ring and one interior ring, and 'B' has one exterior ring and two interior rings.
3. Any Nested Exterior Rings?
When a glyph has several components and a closed counter, I check whether another component sits inside the hole. This kind of component is called an exterior ring at depth 2. Even though it looks like a single shape from the outside, it is not connected to the outer component. Because of this, it becomes a separate Polyhedron. Arbor's '0' is a good example. It is made of three Polyhedra: the outer ring, the center dot, and the top bar. Here, the center dot is the nested exterior ring.
Edge case: Pinch point
Some glyphs have a contour that touches another contour, or touches itself, at a single point. I first noticed this in the horse-shaped dingbat in Stone Heavy and Classy. However, once I checked every glyph across all four fonts, I found that this was more common than I expected. There were three ways this contact could happen.
- (a) A contour touching itself: Stone's horse
- (b) Two different exterior rings touching: limnlimn i, l, y
- (c) An exterior ring touching an interior ring: limnlimn k
Whether this kind of contact is allowed in a 2D polygon depends on the data model. OGC Simple Features allows two different rings to touch at a point, but it does not allow a ring to touch itself. [5] Esri's model, on the other hand, allows a ring to touch itself too. [6] Either way, once the shape is extruded, that point becomes a non-manifold edge shared by four side faces. [9] I call these points pinch points, and I cut the connection they create. However, cutting the connection does not always split the net into two pieces. For Stone's horse and limnlimn i, the letterform is divided into two faces on either side of the contact point, so cutting the connection produces two Polyhedra. limnlimn k is different. Its counter touches the outer contour, but the letterform itself stays in one piece, so I treat it as a single Polyhedron. In this case, cutting the connection only keeps the outer wall and the counter wall from mixing together.


Technical Challenge
Choosing a Spanning Tree for Unfolding
Earlier I classified glyph types by their number of connected components and their number of exterior and interior rings. Now I want to explain how I designed the unfolding for each type.
- Dual graph
- A graph with one vertex for each face of a planar graph G. An edge connects two faces that share an edge. Here, each face of the solid's surface becomes a point, and faces that share an edge are connected by a line.
- Spanning tree
- A spanning subgraph is a subgraph that includes every vertex. A spanning tree is a spanning subgraph that is also a tree, meaning it has no cycles but still connects every vertex. In the net, the edges that are kept become fold lines, and the edges that are removed become cut lines.
- Chord
- An edge that connects two vertices on a cycle without itself being part of that cycle.
Step 1. Unfolding the side faces: choosing which edges to cut
To flatten a solid, you need to decide which edges to cut and which edges to fold. To handle this with computation, I split the solid's surface into flat faces and build a dual graph G = (V, E). Here, V is the set of faces, and E is the set of face pairs that share an edge. An edge's weight w(e) is the length of the shared edge. There are several ways to produce a net, such as star unfolding, source unfolding, and cut locus unfolding. However, this piece only covers edge unfolding, which cuts strictly along the edges of the solid.
An edge unfolding is the same as choosing one spanning tree T from this dual graph G. Every face, except the root, rotates flat around the edge it shares with its parent in T. A different T produces a different layout, and it also changes the chance of overlap. In other words, the question of how to unfold a solid is the same as the question of which spanning tree to choose.
For glyphs without a pinch point, this choice was never a problem. Each side face only has two neighbors, the ones directly before and after it. Because of this, the graph made only from side faces is simply a collection of cycles. With one exterior ring and one interior ring, you get two side-face strips. A cycle's spanning tree is just the cycle with one edge removed. No matter which edge is removed, the result is always a single strip. Only the position of the cut changes, and the strip never overlaps itself.
Where the overlap came from
The problem appeared in glyphs with a pinch point. At this point, four side faces share a single vertical edge. As a result, two faces that would normally be reached only by going most of the way around the contour suddenly become direct neighbors. In graph terms, this creates a chord across the cycle. The faces meeting at that point each gain one extra neighbor, so their degree increases to 3.
The key point here is that BFS does not choose this shortcut because it prefers to. It simply has no other choice. TypoFold builds its spanning tree using BFS, or breadth-first search. This method attaches the faces closest to the start face first, so every face ends up connected to the start by the fewest possible steps. Let's look at a case with 24 faces, where face 0 is the start and a chord links face 5 and face 15.
| Distance to face 15 without the chord | min(15, 24 − 15) = 9 |
| With the chord | d(5) + 1 = 6 |
Since 6 is less than 9, the chord lies on the shortest path. By definition, BFS produces a shortest-path tree, so it cannot avoid using this chord. The moment the chord is used as a fold axis, though, the layout breaks. When a strip is unfolded in a single line, each face's position is set by its cumulative width along the contour. This means that face 15 ends up in the slot that should belong to face 6, which is the face right after face 5 on the contour. Face 15's subtree then keeps unfolding in that direction. At the same time, the subtree that continues from face 6 demands the same slot. As a result, the two subtrees overlap.
The fix: removing the chord
I considered weighting the edges by the length of the shared edge. However, in a solid extruded to a uniform height, every edge shared between side faces has the same thickness, so this weighting did not help at all. Instead, I left BFS as it was. I simply removed the problem connection from the graph before the search even began.
When a contour touches itself at a point p, the four side faces that meet there share the same vertical edge. As a result, they are all treated as neighbors of one another. This false connection binds together side walls that should actually unfold separately.
So which of the four side faces at p were originally connected to each other? The clue lies in the top and bottom faces. At p, the top faces only touch at a single vertex. Since TypoFold only treats two faces as neighbors when they share an edge, meaning they share at least two vertices, the top face never uses p as a connection point. Because of this, I can temporarily remove the four side faces at p from the graph and compute the connected components. This reveals, through the top face, which component each side face originally belonged to. I then check which component each of the four side faces is attached to. I reconnect only the pairs that belong to the same component, and I cut the rest.
At first, I tried pairing side faces that were simply close to each other, but this approach failed. Near a pinch point, physical closeness does not tell you which component a face belongs to. Relying on the top and bottom faces, which were already correctly split, turned out to be the more stable approach.

The outcome falls into two cases, depending on the shape of the top face. For glyphs like Stone's horse or limnlimn i, the top face splits into two pieces at p. In these cases, the graph also splits into two components, which gives two separate nets. These two nets are folded individually and then glued together. For glyphs like limnlimn k, the counter touches the outer contour, but the top face stays in one piece. In this case, the net also stays as a single piece. However, the outer wall and the counter wall still separate from each other at this point. So the counter wall is dropped from the net under the same rule used in Step 3, and it unfolds in the same way 'O' does.

Before cutting the chord. Two subtrees claim the same slot and overlap.

After cutting the chord. Split into two components, unfolding without overlap.
Step 2. Where to attach the top and bottom faces
Once the entire side-face strip is unfolded, the top and bottom faces remain. These two faces touch the whole perimeter of side faces, so there are as many possible fold edges as there are side faces in the strip. Unlike the side faces, which only ever had one neighbor in front and one behind, here there are a lot of options.
Which side face it is attached to determines where the top and bottom face rotate into place. For glyphs with a concave outline, an arbitrary choice can swing the face right over the strip that is already unfolded, causing an overlap.
So, for this step, I measured the overlap area directly, using bounding boxes. For each candidate side face, I calculate the smallest rectangle that would enclose the top face if it were unfolded along that axis. I then compare this rectangle with the rectangle that encloses the whole strip that has already been unfolded, and I choose whichever candidate produces the smallest overlap area. With the side faces, the indirect method of using edge length did not work. Here, though, I am measuring the exact quantity I care about, so this method stays reliable no matter how many candidates there are.
This comparison is only an approximation, though. It compares bounding rectangles rather than each face's actual shape. Because of this, a long, winding strip can make the rectangle much larger than the strip itself. As a result, an empty space can sometimes be misjudged as overlapping. In addition, the bottom face is chosen without knowing where the top face has already landed, so the two faces can still end up overlapping each other. When every candidate overlaps, I simply choose whichever one produces the smallest overlap.

Attached to an arbitrary side face. The top face swings over the already-unfolded strip and overlaps it.

Attached to the least-overlapping side face. It lands in a spot that does not overlap the strip.
Step 3. Excluding the inner wall of a hole
Glyphs with holes have their side faces split into several cycles. 'O' has one cycle running around the outer contour and one cycle running around the inside of the hole. 'B' has two holes, so it has three cycles in total. Only the cycle that forms the outer wall is unfolded into the net. The inner wall of the hole is removed from the net only, not from the 3D model.
The problem is that nothing at the 3D stage records which cycle is the outer wall. At the 2D stage, I distinguished exterior from interior based on which contour contained which. However, this information is not carried over when several contours are merged into one 3D solid. Because of this, I currently treat whichever cycle has the most side faces as the outer wall. This is based on the assumption that a longer outer contour will also have more faces than the hole.
However, this assumption does not hold. The number of side faces depends more on how finely a curve is subdivided into segments than on how long the contour actually is. Point density varies a lot from font to font. Built in the same way, Stone's 'O' has only 16 side faces, while Arbor's 'G' has 517. Even within a single letter, if the hole's curve is subdivided more finely than the outer contour, the hole wall can be mistakenly chosen as the outer wall. The most reliable fix is to compare each cycle's footprint on the XZ plane, using its bounding-box area, and then choose whichever cycle is largest as the outer wall. This measure does not depend on how finely the curve was subdivided at all.

Step 4. Stacking multiple components vertically
Each component gets its own reference face and its own net. I then measure each net's fully unfolded size and stack them vertically so that none of them overlap.

Nets by type
| Type | Examples | Net |
|---|---|---|
| A. Simple | I, L | The side faces unfold into a single strip, with the top and bottom faces each attached at one spot. |
| B. n holes | O, B | The side faces split into 1 + (number of holes) cycles. Only the largest cycle is unfolded, and the hole walls are excluded. The top and bottom faces unfold still showing their holes. |
| C. Multiple components | i, ㅃ | Each component gets its own independent net, and the nets are stacked vertically. |
| D. An island inside a hole | Arbor “0” | Same as C. Each component gets its own net. |
| E. Pinch | Stone’s horse, limnlimn k | The false connection created at the contact point is cut first. If the top face also splits, as with Stone's horse, the glyph is treated as two components, the same as type C. If the top face stays whole, as with limnlimn k, it stays a single net, the same as type B. |
Overlap
Choosing a cutting tree that never overlaps is, in general, a difficult problem. It is still not known whether a non-overlapping edge unfolding always exists for convex polyhedra. This is known as Dürer's conjecture, and it remains unsolved. [10] For non-convex polyhedra, there are known examples where overlap cannot be avoided, no matter how the edges are cut. [11] Because of this, instead of simulating spanning trees directly, I check for overlap on the glyph itself. Going forward, I would like to generalize this approach, so that nets can also be generated for 3D solids beyond simple prisms.
References
- [1] Typography Dictionary — Glyph
- [2] Wikipedia — Counter (typography)
- [3] Microsoft — OpenType spec, glyf table
- [4] FontForge — More on glyphs
- [5] OGC — Simple Feature Access, Part 1
- [6] Esri — ArcSDE 10.0 SDK, Geometry types
- [7] Wikipedia — Even–odd rule
- [8] OGC — CityGML 3.0 Conceptual Model (ISO 19107)
- [9] MeshLib — Non-Manifold vs. Manifold Mesh
- [10] Open Problem Garden — Dürer’s Conjecture
- [11] Bern, Demaine, Eppstein, Kuo, Mantler, Snoeyink — Ununfoldable Polyhedra with Convex Faces (2003)
Archive
Installation views














