Magnifying the Micro with Moiré Patterns

Here I design circular screen patterns that can be used to magnify grid-like stuff, like the pixels on your screen or threads in a cloth via Moiré Patterns, such that you can calculate properties about them with a crude measuring tool like a ruler. At the same time, I present a mathematical formulation of what even are Moiré Patterns. It's a rather ad-hoc formulation, so if there are some things I missed do point it out.

I might write a follow up post where the patterns are printed on transparencies to be used IRL.

Some context: Most of these explorations happened back in 2018 with a friend of mine, Vernice. Me and Vernice even printed out the patterns on transparencies to slap on random things IRL. Unfortunately I don't have the original files and transparencies, neither did I document anything so here I've recreated everything and re-derived the Math and stuff.

What are Moiré Patterns?

Moiré Patterns are these trippy magnified patterns that come from overlapping repeated small screen patterns.

Moire Patterns Wikipedia

If you were to Wikipedia this, which you totally should, you would see that Moiré Patterns are used everywhere, from fraudulent banknote detection to Material Science.

The reason why the effect is amplified is because the small details in the two patterns defer ever so slightly such that the difference builds up over long distances such that the regions that the patterns overlap (lighter regions) are far away from where they don't (darker regions), causing macro bands of light and dark.

This gave us the idea of designing a special kind of screen patterns that would induce Moiré Patterns the amplify micro patterns in a way that can be measured and seen without a microscope.

Design

So due to the goal of designing a screen pattern to be used IRL, there are some crucial design constraints for our screen pattern:

  1. Screen pattern has to be radially symmetrical because the Moiré Patterns that appear are very sensitive to alignment issues. Not a nice thing to deal with IRL.
  2. Screen pattern has to be easily printable. Pattern has to be printable with ~600 dpi without causing Moiré Patterns just from the printing
  3. Screen pattern has to magnify the underlying grid for a wide range of grid sizes. Whether you use it for screens or threads-per-inch on cloth the pattern should allow the means to measure those grids.

In order to start addressing these constraints, it's very useful to form a mathematical formulation of the above problem.

Mathematical Formulation

To satisfy constraint (1), we restricted the screen pattern to consist of only circles sharing the same center. This means our pattern can be described with \(N\) circles centered on the origin with radii \(r_i = f_N(i), |r_i|\le 1, 1 \le i \le N\). Satisfying constraints (2) and (3) simply means an appropriate choice of \(f\).

f choice

Now a good choice of \(f\) will be motivated by 'nice' properties of the resulting Moiré Pattern. This requires a mathematical analysis of the patterns generated by \(f\). To simplify the problem, we shall consider only vertical lines under our pattern:

illustration of vertical lines

Since we'll be working with grids, it'll be easier to work in Cartesian Coordinates. From the image above, you can see that Moiré patterns form from the intersection of our screen pattern and the vertical lines, which causes the lighter regions.

Regions

Looking closer, the Moiré Patterns in the green regions are caused by each circle in our screen pattern intersecting each vertical line. Meanwhile, in the red regions, they are caused by our pattern's circles intersecting every other vertical line.

Let our screen pattern be contained within the square with corners \((-1,-1)\), \((-1,1)\), \((1,1)\), \((1,-1)\). This simply means that \(r_i=f_N(i)\le 1\) as defined earlier. Define \(N\) to be the number of circles in our screen pattern and \(n\) to be the number of vertical lines in a unit horizontal length.

Define \(M(a,b)\), where \(a\) and \(b\) are positive coprime integers, to be the locus of points that represents the Moiré Patterns generated from every \(a\)-th circle in our screen pattern intersecting every \(b\)-th vertical line. With reference to the above image, the Moiré Patterns in the green regions are \(M(1,1)\) and that of the red regions are \(M(2,1)\). Do note that \(M(2,2)\) is equivalent to \(M(1,1)\), and more generally, \(M(a',b') \equiv M(a,b)\) if \(a'b = ab'\)

Say we take a walk from the origin \(O=(0,0)\) to the point \((x,y)\). We would have crossed \(nx\) number of vertical lines, and \(f^{-1}_N(\sqrt{x^2 + y^2})\) circles of our screen pattern. We can hence parameterize \(M(a,b)\) as such:

\displaystyle M(1,1) = \{x,y\in\mathbb{R}, nx-f^{-1}_{N}(\sqrt{x^2+y^2})=j, j \in \mathbb{Z}\} \quad (1)

Which basically says:

During the walk from \(O\) to \((x,y)\), if the number of vertical lines crossed minus the number of circles from the screen pattern crossed is \(j\), and \((x,y)\) is a point of intersection, then \((x,y)\in M(1,1)\)

Now we can extend it to \(M(a,b)\) by adding more lines and circles crossed:

\displaystyle M(a,b) = \{x,y\in\mathbb{R}, anx-f^{-1}_{bN}(\sqrt{x^2+y^2})=j, j \in \mathbb{Z}\} \quad (2)

With this formulation, we can now choose \(f\) such that \(M(a,b)\) is a nice form we can work with.

Choice of \(f\)

It seems that the choice of \(f_N(i) = \sqrt{\frac{i}{N}}\) is really nice, because \(f^{-1}\) removes the \(\sqrt{\quad}\) in equation \((2)\). However, IMO it's worthwhile to consider other power terms as well because of their mathematical properties. Here are some interesting ones that you can try to derive as an exercise:

\begin{aligned}
&f_N(i) = \sqrt{\frac{i}{N}}&: \quad& M(a,b) \text{ are circles} \\
&f_N(i) = \frac{i}{N}&: \quad& M(a,b) \text{ are the conic sections} \\
&f_N(i) = \left(\frac{i}{N}\right)^2&: \quad& M(a,b) \text{ are the elliptic curves}
\end{aligned}

Circles are obviously way easier to deal with IRL so \(f_N(i) = \sqrt{\frac{i}{N}}\) is chosen. You can easily show that the circles of \(M(a,b)\) have centers \(\displaystyle P(a,b)=\frac{an}{2bN}\) and \(\displaystyle j \le \left\lfloor \frac{a^2n^2}{4bN} \right\rfloor\)

With that, here are some plots (generated programmatically):

Plot

Extending to a Grid

This is where it gets difficult to illustrate with curated images, since with increasing detail, Moiré Patterns will be created simply from displaying the pattern on your screen due to the discrete pixels aliasing the image. Aliasing at the pixel's edges causes a sort of lightening effect, which is amplified by the screen pattern, manifesting as extra circles you can see. I would be exploiting this to illustrate the Moiré Patterns.

Do note that, depending on the scale of the image on your screen, the circles of the Moiré Pattern would appear differently.

Here you can see why it is necessary that these images are in SVG, since other formats like png and jpg would cause Moiré Patterns to appear from the discretization step.

grid moire

Upon extending to a grid, you can see the circles of the Moiré Pattern on the vertical axis as well. The circles seem to appear on many diagonals, not just in the 8 cardinal directions. In fact, you can show that there is a bijection from \(\mathbb{Q}^2\) to the centers of all the circles of the Moiré Pattern. These are caused by the corners of the grid patterns, or your screen's pixels, aliasing the screen patterns.

corners forming lines

Analysis of these additional circles aren't needed in using the screen patterns though, so that's where the analysis stops.

Measuring My Screen's Resolution

I'll be using this SVG to measure my laptop's screen resolution with a \(30\text{cm}\) ruler. It is exactly the same as the above SVG except there are now red markings that help me align my ruler. Here, I'm using \(N=300\). From now on, I will only be concerned about Moiré Patterns appearing on the horizontal.

In order to use the pattern, there are 2 things to know about Moiré Patterns IRL:

  1. The most obvious Moiré Patterns are \(M(1,b)\) where \(b\) is a small integer
  2. If the most obvious Moiré Pattern is \(M(1,b)\), the second is \(M(1,b+1)\)

I scaled the SVG such that the edge of the pattern to the center fills most of my screen. I can't screenshot what I did here since Moiré Patterns appear just from screenshotting. I then measured relevant lengths in \(\text{cm}\) with a ruler

Length Measurement (cm)
Laptop Screen Width \(W\) 29.40
Laptop Screen Height \(H\) 16.45
Pattern's Radius \(R\) 26.00
\(r_1\) 24.55
\(r_2\) 18.45

Where \(r_1\) and \(r_2\) are the distance from the first and second most prominent circle centers to the center of the pattern.

With the 2 assumptions above, it can be found that the Moiré Pattern corresponding with \(r_1\)  and \(r_2\) are \(M(1,b_1)\) and \(M(1,b_1+1)\), where \(b_1=\left\lfloor\frac{r_2}{r_1-r_2}\right\rceil=3\).

The number of pixels per \(\text{cm}\) can be calculated as:

\displaystyle d_\text{cm} = \frac{N}{R^2}[b_1(r_1+r_2)+r_2] = \frac{N}{R^2}\left[\left\lfloor\frac{r_2}{r_1-r_2}\right\rceil(r_1+r_2)+r_2\right]

Hence my laptop's screen resolutions are:

\begin{aligned}
&\text{Width Resolution} &=& \quad Wd_\text{cm} \approx 1937 \\
&\text{Height Resolution} &=& \quad Hd_\text{cm} \approx 1084
\end{aligned}

Considering my actual screen resolution is the standard \(1920\times 1080\), my calculations are only off by a few pixels, with an error of \(\approx 0.2\%\). This is very very small considering I used a ruler with a measurement error of \(0.5mm\)!

I highly suggest trying out the formula above and see for yourself.

Concluding Stuff

So yay we measured properties of very small stuff by magnifying them with Moiré Patterns!

There are some more analysis I didn't document here. For instance, the radius of the circles of \(M(a,b)\) are actually very sensitive to alignment. If you were to do this IRL, you would see \(M(a,b)\) spasm with the slightest movement. However, the centers of \(M(a,b)\) are very stable, which is what is used here.

In the future I might write about some stuff me and Vernice found when trying out these patterns IRL back in 2018, including the Thread Per Inch (TPI) scam. Chances are, the TPI advertised on your bedsheets are very very off.

Here are the SVGs if you are interested in seeing what happens when \(f\) is chosen differently: