Chapter IV.


Flat-foldable origami crease patterns are two-colorable.


An origami model is a graph.

These object-oriented style objects are each tailored to a specific use; the graph is the most general. It simply binds graph functions as object methods.

var origami = ear.graph()

The crease pattern has 2D line and shape drawing methods and maintains the graph is planar.

var origami = ear.cp()

The origami object is basically a foldable sheet of paper, it starts with a square boundary.

var origami = ear.origami()
var origami = ear.origami()

Both origami and crease pattern's prototype is graph; and graph's prototype is the default Javascript object prototype.

Crease Pattern

Crease patterns are like 2D canvases to draw on. A few drawing primitives are provided.

The graph maintains planarity, so a few things are taken care of for you:

var cp = ear.cp()

Each shape method returns the indices of the edges in the graph. This allows you to alter things afterwards, like assignment or foldAngle.

The 3D visualization above is Origami Simulator.

Creases are not generally decided by random placements of lines, more often creases are uncovered in the geometry in the origami.


ear.axiom(number, params)

The seven origami axioms are the different ways to make a crease exactly in place.

fold two points together

Axiom #
ear.axiom(2, params)

Each axiom takes a certain combination of points and lines.

{ points: [], lines: [] }

Where points can be arrays or x,y objects, and lines are objects with a vector and origin.

  points: [
    [0.8, 0.75],
    { x: 0.5, y: 0.22 }
  lines: [
    { vector: [0.75, 0.25], origin: [0.5, 0.5] }

Or use Rabbit Ear's vector and line types.

Some axioms have multiple solutions; the axiom method returns an array containing anywhere between 0 to 3 lines.

Folding with Axioms

In practice, axioms should only be constructible if all necessary geometry lies on the paper.

fold two points together

Axiom #
ear.axiom.test(number, params, boundary)

boundary can be either a polygon or a FOLD graph.

The test method returns an array of true or false which aligns with the array of lines the axiom method returns.

Axioms can fail in two ways: they can fail the boundary test, or they can be non-constructible due to their input parameters. Not all can fail the latter, but Axiom 5 can be a good example of it.

Single Vertex


Kawasaki's Theorem


For a vertex to be flat-foldable, the sum of alternating sector angles must be 180°. This implies an even number of creases.

Given an odd number of creases, we can ask the computer to find creases that can satisfy a solution.

The number of results will be less than or equal to the number of input creases.


Only one result is required to be added to the set of input creases, and Kawasaki's theorem will be satisfied.

However, this set of results also has the property that any number of them can be added to the input set and Kawasaki's theorem will be satisfied (as long the total number of creases is even).

Vectors or radians parameters must be sorted before calling these methods.

  .map(i => vectors[i])
  .map(i => angles[i])

Sort radially 2D vectors or vectors as radians.

Given a crease pattern template like this origami twist, if we maintain the graph structure, we can use Kawasaki alone to create variation in form.

var valleys = ear.single.kawasaki_solutions(mountains)

Kawasaki's theorem alone cannot determine flat-foldability; we must also at least consider mountain/valley assignment.

Maekawa's theorem

For a vertex to be flat-foldable, the number of mountain and valley creases should differ by 2.

This method will replace all unassigned creases "U" with mountain or valley, returning all permutations that satisfy Maekawa's Theorem.

ear.single.maekawa_assignments(["M", "U", "U", "U"])
  ["M", "V", "V", "V"],
  ["M", "V", "M", "M"],
  ["M", "M", "V", "M"],
  ["M", "M", "M", "V"],

Kawasaki and Maekawa's Theorems make it easy to check if a vertex fails flat-foldability.

To determine success we need to study how the paper looks when folded; we need a layer arrangement where layers don't intersect each other.

Layer order

Given a single-vertex crease pattern with mountain/valley assignments, this recursive layer solver will uncover all possible layer ordering when collapsed, or will determine if a solution or no solution is possible.

Toggle the sectors, but make sure mountain and valley differ by 2.

The smallest sector (top-right) must be surrounded by a mountain and a valley.

ear.single.sectors_layer(sectors, assignments)

If a solution is possible, the layer solver will assign each sector a z-index. Positive values are closer to the viewer.

[4, 0, 2, 7, 6, 1, 5, 3]

The indices match your input sectors, each value is the z-layer. (the first sector is on the 4th z-layer)

Because one single-vertex can have multiple valid layer arrangements, the layer solver returns an array of solutions.

All together

ear.single.layer_solver(sectors, assignments)

Finally, the layer solver goes one step beyond sectors layer, where sectors_layer requires a valid assignments argument, layer_solver allows the inclusion of unassigned "U" creases and the layer solver will fill in the blanks.

var fourth = ear.single.kawasaki_solutions(three_vectors)
var sectors = []
ear.single.layer_solver(sectors, ["U", "U", "U", "U"])

First, the fourth crease (bottom-left) is added dynamically to satisfy Kawasaki's theorem. Then, the layer solver determines all four mountain valley assignments and the layer order.

4-vertex fold angles

ear.single.fold_angles4(sectors, assignments)

Degree 4 vertices are special cases where the continuous folding motion can be calculated.

Not the end

...and more to come! The library is growing. Follow the Github for up to date development progress.