Brand
Kreis is German for circle. The logo is a circle drawn in one brush stroke, then read by a pixel grid, by a small program that takes a single number. Try it below; the rest of the page explains how it works.
Try it
Change the seed for another draw of the same logo, or move the chosen values to see what each one does. The derived values follow on their own.
Derived: W/R = π × 30/360 = 0.262 · mean radius 19.0 · stroke 10.0 cells
This page's header uses seed 3025991444.
The idea
Kreis is German for circle, and it is my family name, so the logo is a circle. More precisely, it is an ensō: a circle painted in a single brush stroke and left slightly open, a common motif in Japanese calligraphy. I borrowed three of its rules and nothing else: one stroke, no correction, an opening.
The other half of the idea is the pixel grid. A brush stroke is continuous; a grid only knows whole cells, inked or not. The logo is what you get when a grid reads a brush stroke. That pairing, a human gesture captured by a system that only understands exact values, is also a fair summary of my work.
The logo is not a drawing. It is generated by a small program from one input, a number called the seed. Every page of this site draws its own.
How it is drawn
- The canvas is a grid of 64 by 64 cells.
- The path is a circle centred on the canvas, its outer edge at three quarters of the canvas width. It starts at one o’clock and runs clockwise all the way round to twelve o’clock. The missing hour is the opening.
- The brush has a width that changes along the path: wide where it lands, thin where it lifts (the formula is below).
- Inking: a cell is inked if its centre falls inside the brush. There is no anti-aliasing and no grey: each cell is on or off.
- Grain: a smooth noise field nudges the brush edge in or out, so that the edge looks hand-made rather than computed.
- Clean-up: a lone cell with no inked neighbour is removed.
The seed controls only the random parts: where the grain falls, how the width varies along the stroke, and a small shift of the whole circle. The same seed always gives the same logo.
The numbers, and where they come from
The aim was to choose as few numbers as possible and derive the rest. Three values are derived.
The stroke width follows from the opening. The opening should be exactly as wide as the stroke is thick: wider, and the gap would read as a notch in a closed ring; narrower, and the circle would not hold together. With R the mean radius and W the half width of the stroke, and an opening of one twelfth of the circle:
2W = 2(pi)R / 12 so W / R = pi / 12 = 0.2618...
With the outer edge at three quarters of the canvas, this gives, on the 64 grid:
| cells | |
|---|---|
| mean radius | 19 |
| half width | 5 |
| inner edge | 14 |
| outer edge | 24 |
| arc of the opening | 10 |
| width of the stroke | 10 |
The brush profile follows from three conditions. The width, relative to its
nominal value, is 4/3 where the brush lands (t = 0), 1/3 where it lifts (t = 1)
and exactly 1 halfway (t = 1/2). A profile of the form 4/3 - t^p meets the
first two for any p; the third sets p, because 4/3 - (1/2)^p = 1 gives
(1/2)^p = 1/3:
width(t) = 4/3 - t^log2(3)
(An earlier version used 3/2 for the exponent, which put the midpoint at 0.98 instead of 1.)
The path stops short by the width of the brush tips. A brush tip is round, so each end of the stroke extends half a width beyond the end of the path. The first version measured the opening between the ends of the path, and the tips nearly closed it. The opening is now measured between the ends of the ink, and the path is shortened accordingly.
One behaviour is not programmed at all. Near the end the stroke is down to about three cells, and the same grain that only roughens the edge at the start now breaks through it, so the stroke frays as a dry brush would. Nothing in the code says to do that; it follows from the width.
What is derived and what is chosen
| Value | Status | Why |
|---|---|---|
| stroke width | derived | equal to the opening |
| brush profile | derived | three conditions on the width |
| length of the path | derived | the size of the brush tips |
| grid of 64 | convention | 2⁶, and a favicon is 64 pixels: one cell per pixel |
| opening of 30° | convention | one hour on a clock face |
| grain, ½ | set by eye | moves the edge by at most a quarter of the half width |
| breathing, ⅙ | set by eye | how much the width varies along the stroke |
| offset, 3% | set by eye | a hand rarely lands a circle dead centre |
Five numbers are chosen, against eight independent settings in the first prototype. The demonstration above lets you change exactly these five, plus the seed; the derived values follow.
How the site uses it
The logo in the header is generated when the site is built, one per page, as a single SVG path of about one and a half kilobytes. It needs no JavaScript. Touch it and a short script draws a new one, in 32 steps, in the order the brush laid them down. It always takes the colour of the text: black on white, white on black.
The generator is about three hundred lines of TypeScript, in this site’s repository, which is private.