Spinoza’s Ethics was published in 1677. It is often obscure and difficult. However certain passages seem very modern and relevant to our world today. This is one of my favorites (from the Appendix to Part 1):

“Every individual devised different methods of worshipping God as he thought fit in order that God should love him beyond others and direct the whole of Nature so as to serve his blind cupidity and insatiable greed. Thus it was that this misconception developed into superstition and became deep-rooted in the minds of men, and it was for this reason that every man strove most earnestly to understand and to explain the final causes(*) of all things. But in seeking to show that Nature does nothing in vain – that is, nothing that is not to man’s advantage – they seem to have show only this, that Nature and the gods are as crazy as mankind.

Consider, I pray, what has been the upshot. Among so many of Nature’s blessings they were bound to discover quite a number of disasters, such as storms, earthquakes, diseases and so forth, and they maintained that these occurred because the gods were angry at the wrongs done to them by men, or the faults committed in the course of their worship. And although daily experience cried out against this and showed by any number of examples that blessings and disasters befall the godly and the ungodly alike without discrimination, they did not on that account abandon their ingrained prejudice. For they found it easier to regard this fact as one among other mysteries they could not understand and thus maintain their innate condition of ignorance rather than to demolish in its entirety the theory they had constructed and devise a new one. Hence they made it axiomatic that the judgement of the gods is far beyond man’s understanding. Indeed, it is for this reason, and this reason only, that truth might have evaded mankind forever had not Mathematics, which is concerned not with ends but only with the essences and properties of figures, revealed to men a different standard of truth.”

(Spinoza, Complete Works, Edited by Michael Morgan, pages 239-240.)

Spinoza definitely did NOT believe that “everything happens for a reason” as one hears quoted so often today in pop culture. Mathematics is not concerned with ends and thus presents a different standard of truth.

(*) By ‘final cause’ he means the purpose. This is Aristotle’s final cause.


Deleuze Notes: The 3 Synthesis

More notes on the book L’Anti-Oedipe by Gilles Deleuze and Félix Guattari:

The authors posit an immanent criteria of desiring-production that permits a definition of legitimate uses which they call the 3 syntheses.

1 – Synthèse Connective or Production de production

  • Concerns Libido
  • Partial and non-specific as opposed to Oedipal which is global and specific.
  • The BwO is anti-production. An example is the machine paranoiaque which repulses organs.
  • The operative phrase is ‘et puis’. ‘and then’.

2 – Synthèse Disjonctive or Production d’enregistrement

  • Concerns the Numen
  • Inclusive and non-restrictive.
  • The operative phrase is ‘soit..soit’ or ‘either this .. or that’.
  • The BwO attracts desiring machines, fetisches.
  • This is the Genéalogie Schizophrénique.

The example of the CSO they use is the role of capital in capitalism. It records the ‘plus value’ created by labor and seems by some magic to have been the agent when it fact it just records.

The act of recording (enregistrement) makes the BwO appear to be productive. They use a play on words: miraculant to indicate miraculous creation. (The cul in miraculant is part of the pun of course).

3 – Machine Miraculante. Production de consommation/consumation.

  • Concerns Volupté. or Enjoyment, perhaps.
  • Nomadic and polyvocal.
  • The operative phrase is “C’est donc”, or “C’était donc ça”. Which I think means “ah, that’s what it was all along” in this context.
  • The BwO as egg.
  • This is the phase where the subject appears. In the prior 2 phrases it is all machines. The subject appears in relationships of various intensities.

Diagramming it out

There are legitimate and illegitimate uses of the 3 Synthèses. And the authors have a very schematic way of treating this, which makes it amenable to being a diagram:

This diagram is based on Adelheid Mers’ 3 line matrix template.

The above is mostly dealt with in Chapter 2 of L’Anti-Oedipe.


Deleuze Notes: Body Without Organs

I’m reading “L’Anti-Oedipe” (A-O) by Deleuze and Guattari. These are some notes for myself. They may be total rubbish; I’m just trying to organize my thoughts.

So the Body Without Organs (Corps Sans Organes) or BwO, is everywhere in A-O, and in the subsequent book, a Thousand Plateaus. It really seems to be a cluster of concepts and it seems like D&G’s notion of it might have evolved over time.

The idea of the BwO struck me ever since I first heard of it in Deleuze’s “To Have Done with Judgement”.[1]  The title of the essay comes from Antonin Artaud’s banned play “To Have Done With the Judgement of God”, wherein Artaud first uses the term “Body Without Organs”:

“When you will have made him a body without organs,
then you will have delivered him from all his automatic reactions
and restored him to his true freedom.”[9]

Artaud struggled with drugs and mental illness, and much of the BwO concept in A-O in A Thousand Plateaus seems to involve sexual and pharmacological experimentation as a way to change the programmed responses that the organs impose on our bodies. One thinks of Rimbaud’s “dérèglement des sens” in this regard as well. And there is discussion of how society uses language and word order to program our responses which goes back to Levi-Strauss and others. A Thousand Plateaus even dwells extensively on Carlos Castenada, at which point it is all becoming rather embarrassing and one wonders if there is anything  worth salvaging in the BwO. (William Burroughs is also cited).

But there is more here than the old hippie dream that hedonism can be spiritually liberating.  Bordieu and Foucault and others discussed how societies and families and schools control the body to control the individual. They control the body through the organs. Without organs there is no control. Definitely in Artaud but also with D&G there is this notion of restructuring the organs to liberate experience. (D&G’s discussion of sexual multiplicities can be understood in this context: restructuring the organs).

But this is still an understanding that is focused on the individual. There is a physical body that has to be reconfigured to free the … self? What is being freed exactly? Remember that for D&G, desiring machines are primordial. The unconscious is made of desiring machines. So if we consider the unconscious to exist in the brain which in turn exists in the body, we have a completely different world view from D&G, an inverted view. Instead: “The body is the object of reproduction… it is not the subject. The only subject of reproduction is the unconscious… Sexuality does not exist in the service of generation, rather the generation of the body is in the service of sexuality which is used by the unconscious to produce itself.” [2][3] So they are not focused on the self, but on the unconscious. What is being freed (or decoded) is flows of desire in the unconscious.

But we are still nonetheless in the realm of psychology, the individual. But D&G generalize this: Organs are desiring machines. Reconfiguring organs corresponds to decoding the flows of desire. This generalization allows us to speak of a BwO for the socius (society, roughly). Thus these concepts are generalized from the individual to society and this is useful in their synthesis of the psychic and the social, of Freud and Marx.

The organs are the ‘coded flows of desire’ that the socius writes (enregistre) on the BwO (I think). Decoding the flows is the job of capitalism and/or schizophrenia. When capitalism decodes the flows it extracts a plus-value (profit), and the deterritorialzed (decoded) flows make up the full body of the socius. The schizophrenic takes a nomadic approach and heads straight for the naked BwO.

What is this talk of ‘full’ and ‘naked’ BwO? The BwO is immanent in Spinoza’s sense: the idea of one immanent substance that all reality is made of. D&G speak of the “naked BwO” as a limit, something that can be approached asymptotically but never attained. They distinguish the naked BwO from the full BwO, or fully-clothed BwO. “The socius – the earth, the body of the despot, capital/money – are the fully-clothed bodies. They are like a BwO, a fully naked body: but this naked body is a limit, at the end, not at the origin. The [naked] BwO haunts these other forms of the socius.”[4]

Thus there are 2 kinds of BwO, a ‘full body’ and a ‘naked’ body. Sometimes BwO refers to the full body and other times to the naked body.

The Full BwO:

The full body is a paranoiac machine that repulses organs.[5] The full body is a social creation, the socius. Capital in capitalism is an example of a full BwO.  “Capital is indeed the body without organs of the capitalist, or rather of the capitalist being. But as such, it is not only the fluid and petrified substance of money, for it will give to the sterility of money the form whereby money produces money. It produces surplus value, just as the body without organs reproduces itself, puts forth shoots, and branches out to the farthest corners of the universe. It makes the machine responsible for producing a relative surplus value, while embodying itself in the machine as fixed capital. Machines and agents cling so closely to capital that their very functioning appears to be miraculated by it. Everything seems objectively to be produced by capital as quasi cause.” [6]

The Naked BwO:

The body without organs, the unproductive, the unconsumable, serves as a surface for the recording of the entire process of production of desire, so that desiring-machines seem to emanate from it in the apparent objective movement that establishes a relationship between the machines and the body without organs… Doubtless the former paranoiac machine continues to exist in the form of mocking voices that attempt to “de-miraculate” (demiracu-ler) the organs… But the essential thing is the establishment of an enchanted recording or inscribing surface that arrogates to itself all the productive forces and all the organs of  production, and that acts as a quasi cause by communicating the apparent movement (the fetish) to them. So true is it that the schizo practices political economy, and that all sexuality is a matter of economy.” [7]

And finally…

“The body without organs is not the proof of an original nothingness, nor is it what remains of a lost totality. Above all, it is not a projection; it has nothing whatsoever to do with the body itself, or with an image of the body. It is the body without an image. This imageless, organless body, the nonproductive, exists right there where it is produced, in the third stage of the binary-linear series.” [8]

There are hundreds of other pages on the BwO in Anti-Oedipus alone, and there is much more to it.

[1] This is a magnificent philosophical essay that is really a piece or art or prose poetry. When we read it, we understand how to read Deleuze: which is as a great philosophical prose poet. He even tells us how to read him: “For reading a text is never a scholarly exercise in search of what is signified, still less a highly textual exercise in search of a signifier. Rather it is a productive use of the literary machine, a montage of desiring-machines, a schizoid exercise that extracts from the text its revolutionary force.” (A-O, page 106.)

[2] L’A-O, page 131. My v loose translation.

[3] In L’A-O, page 396, the authors discuss how the unconscious reproduces. “The  signifying chain of the unconscious, Numen, is not used to decipher or discover codes of desire, but rather to transmit entirely decoded flows of desire, Libido, and to find in that desire that which scrambles all the codes and undoes all the territories.” and “This chain is how the gene of the unconscious, which is always a subject, reproduces itself.” A very beautiful dynamic described there.

[4] L’A-O, page 338.

[5] Anti-Oedipus (A-O), English version, translated from the French by Robert Hurley, Mark Seem, and Helen R. Lane, page 5.

[6] A-O, page 10

[7] A-O, page 11

[8] A-O page 8

[9] https://en.wikipedia.org/wiki/Body_without_organs


Deleuze Notes: Desiring Production, Desiring Machines, Coding and Decoding of Fluxes

A starting point for understanding Anti-Oedipus are the 2 concepts of Desiring-Production and Desiring-Machines. The concept of ‘fluxes’ or flows is close to desiring-production and from there one discusses how flows are ‘coded’ and ‘decoded’. Deleuze and Guattari see history from the point of view of how societies code and decode these flows, with capitalism being a superb machine for decoding flows. D&G view the psychic and the social as interpenetrating, thus they have a lengthy discussion of the relationship between schizophrenia and capitalism (hence the subtitle of this book).

So the ideas that must be clearly understood to get a foot-hold on this book are: desiring-production, desiring-machines, fluxes, coding, decoding, deterritorialization.


The key term of Anti-Oedipus is “desiring-production,” which crisscrosses Marx and Freud, putting desire in the eco-social realm of production and production in the unconscious realm of desire.

Deleuze and Guattari will call desiring-production a “universal primary process” underlying the seemingly separate natural, social and psychological realms. Desiring-production is thus not anthropocentric; it is the very heart of the world. Besides its universal scope, we need to realize two things about desiring-production right away: (1) there is no subject that lies behind the production, that performs the production; and (2) the “desire” in desiring-production is not oriented to making up a lack, but is purely positive. Desiring-production is autonomous, self- constituting, and creative: it is the natura naturans of Spinoza or the will-to-power of Nietzsche.


The highlights are mine. They are key points. In fact a ‘subject’ only occurs in the 3rd synthesis, the Machine Miraculante, the production of consumption/consumation. See my previous post on this.

“Desire does not lack anything; it does not lack its object. It is, rather, the subject that is missing in desire, or desire that lacks a fixed subject; there is no fixed subject unless there is repression. Desire and its object are one and the same thing: the machine, as a machine of a machine. Desire is a machine, and the object of desire is another machine connected to it”.[8]

Deleuze: “The great discovery of psychoanalysis was that of the production of desire, of the productions of the unconscious.” [7]

“the unconscious does not mean anything…. the unconscious constructs machines, which are machines of desire… The unconscious does not speak, it engineers. It is not expressive or representative, but productive. A symbol is nothing other than a social machine that functions as a desiring-machine, a desiring-machine that functions within the social machine, an investment of the social machine by desire.”


Deleuze and Guattari oppose the Freudian conception of the unconscious as a representational “theater”, instead favoring a productive “factory” model: desire is not an imaginary force based on lack, but a real, productive force. They describe the machinic nature of desire as a kind of “desiring-machine” that functions as a circuit breaker in a larger “circuit” of various other machines to which it is connected. Meanwhile, the desiring-machine is also producing a flow of desire from itself. Deleuze and Guattari conceptualize a multi-functional universe composed of such machines all connected to each other: “There are no desiring-machines that exist outside the social machines that they form on a large scale; and no social machines without the desiring machines that inhabit them on a small scale[1].” Desiring-production is explosive: “there is no desiring-machine capable of being assembled without demolishing entire social sectors”.

The concept of desiring-production is part of Deleuze and Guattari’s more general appropriation of Friedrich Nietzsche’s formulation of the Will to Power. In both concepts, a pleasurable force of appropriation of what is outside oneself, incorporating into oneself what is other than oneself, characterizes the essential process of all life. Similarly, a kind of reverse force of “forgetting” in Nietzsche and the body without organs in Deleuze and Guattari disavows the Will to Power and desiring-production, attempting to realize the ideal of an hermetic subject.


Deleuze: “Desiring-machines are … the microphysics of the unconscious, the elements of the microunconscious. “[9]

Coding and Decoding the Flux

So we have the Desiring Production and Desiring Machines interrupting flows and producing flows.

There is a great article in the revue Cités, by Charles Ramond that lays out very clearly the core concepts of ‘coding’, ‘decoding’ and so forth. You should read the article (in french), but here is my very loose translation of some excerpts:

For Deleuze and Guattari, reality is made of fluxes, (or flows) in the most vague sense of that term: forces, élans, moving objects, and above-all: ‘desires’. So the fluxes are are a form of universal energy (that we could also call ‘production’). One can find equivalents to this notion in some of Deleuze’s favorite authors: Bergson, Spinoza (“the effort to preserve the being”), and Nietzche’s Dionysus. These fluxes don’t exist on their own, they are always presented as framed, or informed, or structured, or to use Deleuze’s term: ‘coded’…. In the same manner as Lacan and Freud refer to the ‘real’ which doesn’t appear directly but only if ‘coded’ by the imagination, or in a dream….

So this idea is rather simple and natural. There is an interpenetrating duality between the ‘flux’ on one hand: fluid, free, creative – but which which, left to itself, represents the risk of shapelessness and chaos. And on the other hand: the rigid, the framework, the structure, the law, the “code” (which often means something like a “law”, for example in “Civil Code”), which comes to frame and hinder to a certain extent this “power” (another Spinozist name for the Deleuzian “fluxes”), which is both a life force and a force for the destruction of “codes”.

A society, like an individual, can live and survive only in the “coding” of “flows”. … It seems to the authors that humanity has progressed, albeit in a non-linear way, towards the current capitalist situation, that is to say towards a complete, destructive decoding of fluxes. There is a fairly widespread and fairly intuitive perception of capitalism in its essence as a regime or a type of economic, political and social functioning in which the old, traditional “codes” collapse. What we sometimes call “globalization”, the [modern, technological world] that promises us a quasi-ubiquity, allows us to detach ourselves more and more from the “earth”, to fly to heaven as gods, or to become “deterritorialized”, to use Deleuze’s term. Capitalism and globalization indeed appear as a sort of generalized “decoding” of “flows” (nothing must be opposed to the circulation of flows and to their free propagation): frontiers, customs, laws or local customs become, in a capitalistic world, archaisms destined to be suppressed or folklorized.

Now, the “schizo”, breaking the old codes, the old laws, the old conventions, “decodes the fluxes”. In a coded system, he will usually be held for “crazy”. On the contrary, Deleuze and Guattari prefer to see a “prophet”, that is to say a “creator”, capable of bringing out the future in the present, like Artaud, Beckett, Van Gogh, Chaplin, Proust, Hölderlin, Turner, or Balzac.

Which brings us finally to the “Body without Organs” (Le Corps Sans Oganes). I will discuss this in my next post.

But his quote from Deleuze directly, illustrates the relationship between the Body without Organs and the deterritorialized socius.

“The body without organs is the deterritorialized socius, the wilderness where the decoded flows run free, the end of the world, the apocalypse. …[This is] what all societies dread absolutely as their most profound negative: namely, the decoded flows of desire.”[4]

[1] https://plato.stanford.edu/entries/deleuze/

[2] https://en.wikipedia.org/wiki/Desiring-production

[3] Ramond Charles, « Deleuze : schizophrénie, capitalisme et mondialisation », Cités, 2010/1 (n° 41), p. 99-113. DOI : 10.3917/cite.041.0099. URL : https://www.cairn.info/revue-cites-2010-1.htm-page-99.htm

[4] A-O, english pdf. page 176 on.

[5] Ibid, page 19.

[7] A-O, english pdf, page 24.

[8] Ibid, page 26.

[9] Ibid, page page 183.


The Mercator Projection

The much-maligned Mercator Projection is indeed by unsuitable for maps (famously it renders Greenland as large as Africa when in fact it is as large as Saudi Arabia):

What is rarely mentioned is that the Mercator projection is infinite. That is, if you extended it further north and further south the magnification would become more and more extreme. David Swart has a TedX video on it and has worked extensively with its mathematics. He has also created many amazing and whimsical projections.

Drew Roos has written a program (here) that demonstrates this. Here is an example:

So the above projection is the same view as the first one except, a) it is turned on its side, and b) it extends much further – getting asymptotically closer to the north pole on the right and the south pole on the left with higher and higher degrees of magnification.

Since his images come from Google there is a limit to how much magnification he can do. But you can certainly zoom in as far as Google can (to the city block say).

There is no reason the north and south poles have to be, um, at the poles. We can choose any pair of antipodes to be poles. For instance here is what it looks like if we put the Arc De Triomphe at the north pole.

Note the radiating spokes of the streets emanating from Place de L’Etoile.

Apparently Angor Wat is exactly antipodal to a town in Chincha Province, Peru:

And Wellington, NZ is antipodal to Alaejos Spain:

And Hong Kong is antipodal to La Quiaca Argentina:

Anyhow play with it yourself here: https://mrgris.com/projects/merc-extreme/

The site antipodesmap.com was useful for finding interesting antipodal pairs.

And do check out that video by David Swart for all the details.

The map at the top is from the Wikipedia article on the Mercator Projection.


Dolly Zoom using Möbius Transforms

Dolly zoom is the technique of zooming/panning a camera while a dolly moves the subject towards or away from the camera. The combined effect is that the subject doesn’t change size but the background moves in a weird way that distorts perspective. This effect was pioneered in the movie Vertigo but has been used countless times since. I first noticed it in Spike Lee’s “Do the Right Thing”.

Some time ago, Henry Segerman posted a video showing how to generate a similar effect with 360 video.

He achieved this effect using Möbius transforms. There is a unique Möbius transformation mapping any 3 points to any other 3 points. So you can use such a transform to keep the same 3 points fixed no matter what!

That was something I wanted to experiment with. Here is what I came up with first:

On the left is an equirectangular projection of a 360 still I took on my rooftop. I superimposed the 3 Nyan cats wandering around the image. On the right is the same video, BUT I keep the cats’ locations fixed using a Möbius transform and the world has to adjust around them.

So on the left the world stays fixed and the cats move. On the right the cats stay fixed and the world moves. If you don’t believe that the cats stay still just put your finger on one and you’ll see that while it might shrink or grow or flip, it always stays under your finger.

The change in perspectives in the above Nyan Cat video are weird and dramatic indeed. But since the cats are all in a line the equator doesn’t move. In this next video the cats move at different latitudes for more dramatic ‘tiny world‘ effects:



Remember that Möbius transforms are possible with spherical (360) images because we identify the image sphere with the Riemann sphere, as I covered in an earlier note. Thus when I speak of an equator or latitude I am referring to the sphere of the image from the camera of course.

Aside: I find it quite natural to read equirectangular images now. The fact is, it is inconvenient to always be scrolling left, right up and down in order to view a real 360 image. An equirectangular projection has all the same information but requires less work. I wonder if this will become a common way for people to understand images. There is nothing special about the perspective and projection we’ve been using since the Renaissance.

Finally, let’s try the same effect on a video with people instead of Nyan Cats:


One effect I love: when 2 people meet, the algo has to flip the whole picture upside down to preserve spacing.


3-Sphere notes


A rotation in 2 dimensions leaves one single point stationary. A rotation in 3 dimensions leaves an axis stationary. A rotation in 4 dimensions leaves a plane stationary. So in 4d everything rotates around a plane. Now we can additionally choose to rotate that stationary plane, thereby doing 2 planar rotations at once. I believe this is what is referred to as an isoclinic or Clifford rotation, whereby you have a pair of rotating orthogonal 2 planes that intersect only at one point. [3]

Hopf Circles, Hopf Fibrations, Hopf Links

The intersection of a complex line in C² containing the origin, with S³  is a circle. This is true for every line passing through the origin whose equation is of the form z2=a*z1 where a is a complex number and z2 and z1 are the coordinates of C². By ‘line’ we mean one-dimensional subspace which we can think of as a plane. Thus there is a circle in S³ for each complex number a (including the case where a is infinite). The sphere S³  is therefore filled with circles, one for each point of S², that is, for each complex number a. (The as fill all of  C¹ which we can identify with the Riemann Sphere). As Thurston says “exactly one Hopf circle passes through each point of S³” and “the three-sphere is a two-sphere’s worth of circles”.[4]

(Note: A complex line in C² is a one dimensional subspace thereof. We can visualize a complex line in C² by imagining a plane in R⁴, but not all planes in R⁴ are one dimensional subspaces of C². [1])

The Hopf fibration is this map from the unit 3-sphere to the unit 2-sphere. (This is different than stereographic project to R³!).

  1. The inverse image of each point on the 2-sphere is a circle. Thus, these images decompose the 3-sphere into a continuous family of circles, and each two distinct circles form a Hopf link. The linking is what makes the fibration a non-trivial fibration.[9]
  2. The inverse image of a circle of latitude on S2 under the fiber map is a torus, and these project to nested toruses in R³ which fill space. The individual fibers link to Villarceau circles on these tori with the exception of the circle through the projection point and the one through its opposite point: the former maps to a straight line, the latter to a unit circle perpendicular to, and centered on, this line, which may be viewed as a degenerate torus whose radius has shrunken to zero. Every other fiber image encircles the line as well, and so, by symmetry, each circle is linked through every circle, both in R3 and in S3. Two such linking circles form a Hopf link in R3 [10]

The n-dimensional complex project space CPⁿ is the set of all complex lines on Cⁿ⁺¹ passing through the origin. [2]  Thus C² projects to CP¹, the Riemann sphere.  Homogenous coordinates represent the same point in the projective space. As we saw above a=z2/z1, and each value of a specifies a different set of homogeneous coordinates, therefore a line through the origin of C²  maps to a point in CP¹. CP¹ is the set of all complex one-dimensional subspaces of C². A fancier way to say it, as Wikipedia does is: “CP1 is the quotient of C2\{0} by the equivalence relation which identifies (z0z1) with (λ z0λ z1) for any nonzero complex number λ. On any complex line in C2 there is a circle of unit norm, and so the restriction of the quotient map to the points of unit norm is a fibration of S3 over CP1.”

Stereographic Projection from  to  R³

So the Hopf fibration can be thought of as a map from S³  to CP1, or to S². But that is not really a visualization tool at all, it is just a map. To visualize entities embedded in S³ we can stereographically project to  R³. I’m not going to summarize how to do that, because it is in a million places on the web, e.g. [7].

Under stereographic projection of S³ to R³,

  1. Radial planes in R³ correspond to 2-spheres through N (the north pole, i.e. infinity in R³) in S³.
  2. The equator of S³ projects to a sphere , S², of radius 1 centered at the origin of R³.

I initially confused Hopf Circles with Great circles and C² with R⁴. Not every  two dimensional plane in R⁴ is a one dimensional subspace of C² . Any plane in R⁴ that goes through the origin intersects S³ in a great circle. But Hopf circles are the intersections of complex lines with S³. Note that unlike for S², two great circles need not intersect in S³.

Entities embedded in

  1. Clifford Torus.

This is a flat torus that lives in R⁴ and is embedded in S³. “Flat” means it has zero Gaussian curvature everywhere. By “embedded in S³”, we mean that all points on the surface are unit distance from the origin. So both of these statements are mind-bending but also strangely intuitive. If you use the standard formula for a Clifford Torus and perform stereographic projection:

// Clifford Torus Parameterization
var f=1/Math.sqrt(2);
var xx=f*Math.cos(u);
var yy=f*Math.sin(u);
var zz=f*Math.cos(v);
var rr=f*Math.sin(v);
// Stereographic projection:
var x=xx/(1-rr);
var y=yy/(1-rr);
var z=zz/(1-rr);

you get… a donut:

However, if you rotate the projection point:

var xx = Math.cos(u+theta) *Math.cos(v+phi);
var yy = Math.cos(u+theta) *Math.sin(v+phi);
var zz = Math.sin(u+theta) *Math.cos(v+phi);
var rr = Math.sin(u+theta) *Math.sin(v+phi);

you get something that looks like a plane with handles:

I got these formulas from “Sculptures in S3” by Saul Schleimer and Henry Segerman, which is a very interesting paper with many practical (as in fun) applications.

This plane with handles has more structure than it seem, so I left some gaps in the surface which brings out the structure more:

A Clifford torus divides the 3-sphere into 2 solid tori. This was hard for me to grasp initially. But if you consider the surface of the donut above (the Clifford torus is a surface), it in-fact divides R³ into 2 solid tori.  It is clear that the inside of the donut is a solid torus, but the outside is also a solid torus in the pre-image of the projection, i.e. in S³. Perhaps a little sloppy, but that’s the intuition.

There are other fun parameterizations in the Segerman/Schleimer paper. Here are a few I coded up:

Inverted (3,11) Torus Knot from Robert Woodley on Vimeo.


Trefoil on S3 from Robert Woodley on Vimeo.


Trefoil on S3, II. from Robert Woodley on Vimeo.

[1] https://math.stackexchange.com/questions/1265551/how-to-verify-whether-r2-is-a-subspace-of-the-complex-vector-space-c2

[2] http://www.math.poly.edu/courses/projective_geometry/chapter_three/node1.html

[3] http://eusebeia.dyndns.org/4d/vis/10-rot-1

[4] Three-dimensional Geometry and Topology, Volume 1. page 103.

[5] http://emerald.tufts.edu/~gwalsh01/dissertationfinal.pdf

[6]Topology, Geometry, and Gauge Fields, Foundations – Gregory Naber, page 17.

[7] Sculptures in S3. Saul Schleimer and Henry Segerman. https://arxiv.org/pdf/1204.4952.pdf

[8] https://en.wikipedia.org/wiki/Villarceau_circles

[9] https://en.wikipedia.org/wiki/Hopf_link

[10] https://en.wikipedia.org/wiki/Hopf_fibration


Intuition for Semi-Direct Products

Example 1: C3⋊C2 = S3

You can’t do the complicated stuff with being clear on the simple stuff. So to clarify semi-direct products lets start with pretty much the simplest case.

C3xC2 = C6 is a direct product. Thus, C3 and C2 are normal subgroups of the cyclic group C6 which has order 6.

C3⋊C2 = S3 is a semi-direct product. Only C3 is a subgroup of the symmetric group S3 which also has order 6.

C6 and S3 are the only 2 groups of order 6.

C3 has 2 automorphisms, the identity automorphism: {e ↦ e, y ↦ y, y²  ↦ y² } and a bijective one: {e ↦ e, y ↦y², y²  ↦ y }

The identity automorphism is used in the first, direct product, case to build C6.

The bijective automorphism of C3 is used to build S3. The second Cayley diagram below for S3 shows how C2 is used to map the identity automorphism to the bijective one via a semi-direct product. The inner circle goes in the reverse direction of the outer circle.

Here is the Cayley diagram for C6  from the great free program Group Explorer:

FIgure 1

And for S3:

Figure 2

Generators for S3 are r³= f²= 1. And fr=r²f.

S3 is isomorphic to the dihedral group of same order, sometimes called D3, sometimes called D6.

So that’s the simple case. Let’s move up to the a larger example: A4.

Example 2: (C2×C2)⋊C3 = A4

(C2×C2) is the Klein 4 group, aka V4. V4 is normal in A4, so the semi-direct product of v4⋊C3 will involve an automorphism of V4 by C3.

The automorphism group of V4 is isomorphic to S3:

Figure 3


This arrangement shows the isomorphism to S3 clearly:

Figure 4

So we’re looking for an intuition of the semi-direct product, V4⋊C3 = A4. S3 has C3 as a subgroup (as we saw in the first part of this post), so there are two homomorphisms from C3 to S3, those would be the outer ring and the inner ring in Figure 4, or the left and right columns respectively in Figure 3. Choosing the injective one (the inner ring) gives us A4 which might be portrayed something like this:

Figure 5

The point of Figure 4 is to provide an intuition showing that A4 is the semi-direct product of C3 and the injective automorphism of V4. I don’t find the wiring diagrams of the V4 automorphisms in Figure 3 very intuitive, but Figures 4 demonstrates that there are 2 possibilities when choosing the automorphisms, one choice (the outer ring in Figure 4) leads to a direct product, the other choice leads to the semi-direct product A4 as shown in Figure 5.



[1] Algebra: Chapter 0, Part 0. By Paolo Aluffi. Page 232.

[2] http://www.weddslist.com/groups/building/sdp.html

[3] Visual Group Theory by Nathan Carter

[4] Slides by Matthew Macauley, Clemson University. Notes for Math 4120.  http://www.math.clemson.edu/~macaule/classes/m17_math4120/index.html


Intuitions for SU(2) and SO(3)

This article is about a single strange topic which doesn’t have a pithy title but which manifests in several areas:

  • Gimbal Lock
  • Orientation Entanglement
  • Quantum Mechanics
  • The theory of rotation groups

The underlying concepts that relate these topics comes from Group Theory/Abstract Algebra. I understood the algebra behind these concepts but had little or no intuition for them. When that happens I feel like the algebra is worthless, or a kind of trick. Intuition is key. So after grappling for a week with these concepts I have some intuitions which is what this article is about. I’m not sure a mathematician would agree with everything here, and I’d love to have such feedback, but by writing this I’m able to organize my thoughts in some sort of coherent manner.

Perhaps it is simplest to start with a topic that confronts anyone who does even a little graphics programming: Gimbal Lock.

When you first start working with a framework like three.js and you need to rotate an object, it is natural to turn to Euler angles, invented by the great man himself. Euler angles are a set of 3 angles that describe the orientation of a rigid body in a fixed coordinate system. The three angles are sometimes called yaw, pitch and roll. Or heading, elevation and bank. The first angle might rotate the object around the X-axis, the second around its (new) Y-axis and the third around its (new) Z-axis. There are several different ways to define these angles, but however you define them, there are always 3 angles. They are widely used in graphics programming to rotate objects.

Euler angles example from Wikipedia page on same.[1]

Gimbals are mechanical devices. A single gimbal allows rotation around a single axis. A set of 3 orthogonally nested gimbals extends this to 3 separate axes. In an inertial system, the 3 gimbal system senses rotation about all axes of 3 dimensional space. They have been used in ships, airplanes and rockets.

Gimbal with 3 axes of rotation. From Wikipedia.[2]

However, they suffer from a flaw called Gimbal Lock whereby in certain orientations, when 2 gimbals rotate around the same axis, the system loses one degree of freedom. The term Gimbal Lock comes from the world of mechanical engineering. Mathematicians refer to it as a singularity. What this means is that sometimes when you reach a certain point in your rotation, you can’t go any further by incrementing the Euler angles and you have to do a 180 degree flip. Here is an example of that 180 degree flip in a simple three.js animation. The viewer is doing a polar orbit and must execute a flip at each pole:

Note: This is not a purely abstract problem of graphics programming. It had real world consequences: The threat of Gimbal lock famously occurred during both Apollo 11 and Apollo 13.  The Apollo 11 spacecraft actually had to execute such a 180 degree flip to avoid it. It was an especially dangerous threat to Apollo 13 right after the initial explosion when the spacecraft was pitching about wildly.[3]

Schematic of the DSKY interface used in Apollo spacecraft. Notice the ‘Gimbal Lock’ light in the 2nd row, 2nd column.

Back to programming. The usual advice if you want to avoid 180 degree flips in your computer game is to stop using Euler Angles and to start using Quaternions instead. Libraries like three.js offer both methods.

So why do Euler angles suffer from Gimbal lock and Quaternions do not? To answer that, let’s first try to get a deeper understanding of rotations in 3 dimensions.

There is a mathematical group called SU(2) defined as follows:

This group will be very relevant to this discussion because it turns out that SU(2) is isomorphic to the 3-sphere, S³, as is demonstrated here in wikipedia. This is totally intuitive since SU(2) describes a sphere in C² space, i.e. in 2-dimensional complex space. What is 2-dimensional complex space? Well, one dimensional complex space (C¹) is usually drawn as a plane with the imaginary axis being the vertical axis and the real axis being the horizontal axis. Mathematicians might say that C¹ is diffeomorphic to R², i.e. we can think of it as being 2 dimensional. So we can think of C² as being 4 dimensional, it is diffeomorphic to R⁴. The fact that SU(2) is a unitary matrix with determinant = 1 (|α|²+|β|² = 1, as stated above) means it maps to a sphere in 4 dimensional space, aka S³. So that’s the intuition.

This is relevant because SU(2) is also isomorphic to the subgroup of quaternions of norm 1. They describe the same rotational space.

So SU(2) is isomorphic to S³. It is also isomporphic to the group of unit quaternions. So that’s why quaternions can describe all 3-D rotations without singularities and why SO(3) cannot.

So that’s why quaternions work, but why don’t Euler angles work? Why do they have a singularity?

Euler’s rotation theorem states that any rotation in 3 dimensions can be described by a rotation of some angle around some axis. We can specify the axis of such a rotation using 2 angles, and the radius of the axis vector specifies the angle of rotation around the axis. (You may remember a similar representation of the angular velocity vector from freshman physics.)  The union of these vectors form a ball with radius of π. Negative rotations correspond to vectors of negative length. A vector of radius π represents the same Euler rotation as a vector of radius -π. So antipodal points on the surface of this solid 3d sphere are identified.

Euler angles are a map onto the group SO(3), the group of all rotations about the origin of three-dimensional Euclidean space R3 under the operation of composition. There are many ways to map onto SO(3), Euler angles are just one way. But all maps onto SO(3) suffer from a similar parameterization problem as Euler angles do. [4]

What is this SO(3) group then? It is a normal subgroup of O(3), the group of 3×3 orthogonal matrices, but with determinant equal to 1:

O(3) = {A ∈ GL(3) | A -1= AT  }

So, SO(3) = { A ∈ O(3) | det(A) = 1 }

Now what is the relation between SU(2) and SO(3)? SU(2) is a ‘double cover’ of SO(3). SU(2)/{±I} and SO(3) are isomorphic. That means that every point in SO(3) maps to 2 points in SU(2). The effect of the double cover is to identify antipodal points in SO(3).

Another way to look at it: A sphere (S²) can be seen as the union of 2 discs (D²) joined at the equator of the sphere. So a 3-sphere  (S³) can be seen as the union of 2 balls (D³). The ball representing SO(3) described in the previous paragraph on Euler rotations is only one such ball. We need another ball.

I find SO(3) to be really strange. On the one hand it is the most intuitive space for us to work with. We intuitively understand 3-D rotations and Euler angles. A child could understand them. A (normal) child could not understand quaternions. Yet simple as it seems SO(3) is full of strange phenomena/singularities like Gimbal lock and exhibits weird rotation behavior like the plate trick or the Dirac belt trick:

Dirac Belt Trick [5]


Let us linger on the Dirac belt trick for a second. This is an example of orientation entanglement. If the object you are rotating in 3-d space is embedded in a fixed framework like a room, then after one rotation of 360 degrees, the orientation of your object is entangled with respect to the room. You have to turn the object an additional 360 degrees to untangle it.

This is because SO(3) is not simply connected. It is not simply connected because antipodal points are identified. SU(2) is simply connected. But since SO(3) = SU(2)/{±I}, antipodal points in SO(3) are identified and it is not simply connected. I think of it this way: SU(2) represents 2 Spheres: S2+ and S2-. Taking the quotient identifies these 2 spheres via the antipodes.

How can we get an intuition for this statement: The identification of the antipodes in SO(3) means SO(3) is not simply connected? This is discussed in many places, I quote one example here:

“in the ball with antipodal surface points identified, consider the path running from the “north pole” straight through the interior down to the south pole. This is a closed loop, since the north pole and the south pole are identified. This loop cannot be shrunk to a point, since no matter how you deform the loop, the start and end point have to remain antipodal, or else the loop will “break open”. In terms of rotations, this loop represents a continuous sequence of rotations about the z-axis starting and ending at the identity rotation (i.e. a series of rotation through an angle φ where φ runs from 0 to )” https://en.wikipedia.org/wiki/Rotation_group_SO(3)

That article goes onto explain why with an additional rotation you get a closed loop.

Because SO(3) is not simply connected, problems will always occur when trying to parameterize this space of 3D rotations. Gimbal lock is an example of a problem caused by trying to parameterize SO(3).

The fact that SU(2) is a double cover of SO(3)  has some deep applications to physics. “Quantum mechanical spin is not described by a vector as in classical angular momentum. It is described by a complex-valued vector with two components called a spinor. There are subtle differences between the behavior of spinors and vectors under coordinate rotations, stemming from the behavior of a vector space over a complex field.”[6] In other words the spinor Spin(3) is isomorphic to SU(2). Physicists use Pauli Matrices as generators of SU(2). If you “rotate” an electron through an angle of 2π it is not the same as what you started with. Fermions have spin of 1/2. This is related to the fact that electrons are described by representations of SU(2) and not SO(3).  It takes a rotation of 720 degrees for a fermion to return to its original state.

I hope the intuitions described above are not too sloppy, and that I haven’t mixed geometry and topology in a way that is unacceptable.

Addendum 1:

Another way to state Euler’s Rotation Theorem: If A is an element of SO(3) where A ≠ I, then A has a one dimensional eigenspace. This is not to say that A does not also have a two-dimensional eigenspace but that A must have a one-dimensional eigenspace. It is this eigenspace that is known as the axis of rotation. https://en.wikipedia.org/wiki/Orientation_(geometry)

Addendum 2:

“A 2×2 matrix with complex entries represents an element of U(2) iff U*U=1. So the determinant detU is a complex number of modulus 1. The group U(1) consists of all complex numbers of modulus 1, which allows us to rephrase the previous finding as follows: Taking the determinant is a group homomorphism, det: U(2) → U(1). Indeed detUV = detUdetV and det1 = 1. The kernel of the group homomorphism det is a subgroup of U(2)”. https://en.wikipedia.org/wiki/Unitary_group

That subgroup is SU(2). So: U(2) = U(1) × SU(2). Or alternatively, U(2) = S3×S¹

U(1) is a circle. So we’re factoring out a whole circle to get SU(2).

It appears that U(2) can’t be identified with a manifold, see here: https://math.stackexchange.com/a/843892

Identifying SU(2) with S3 makes it much easier to think about. The fact that it is simply connected is obvious for instance.



[1] By Euler2.gif: Juansempere derivative work: Xavax (This file was derived from Euler2.gif:) [CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0) or GFDL (http://www.gnu.org/copyleft/fdl.html)], via Wikimedia Commons. From: https://en.wikipedia.org/wiki/Euler_angles

[2] By Lookang many thanks to Fu-Kwun Hwang and author of Easy Java Simulation = Francisco Esquembre (Own work) [CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons. From: https://en.wikipedia.org/wiki/Gimbal

[3] “https://www.universetoday.com/119984/13-more-things-that-saved-apollo-13-part-9-avoiding-gimbal-lock/”

[4] https://en.wikipedia.org/wiki/Rotation_group_SO(3)

[5] By JasonHise (Own work) [CC0], via Wikimedia Commons. https://commons.wikimedia.org/wiki/File%3ABelt_Trick.gif

[6] https://en.wikipedia.org/wiki/Spin-%C2%BD#Complex_phase

Other references:





Tetrahedral symmetry

I was curious how one would go about rendering a triangle group using Möbius transforms. It took a while! I wanted to jot down the underlying theory so I wouldn’t forget it later. Perhaps these notes will be of interest to others as well. Here goes:

Given a triangle with angles π/l, π/m, π/n, you can tile a plane if 1/l + 1/m + 1/n = 1. For instance if l,m,n = 2, 4, and 4 respectively, then the sum of the angles of the triangle is π/2 + π/4 + π/4 = π, and you can tile a plane with isosceles right triangles which would look something like this [1]:

A (2,4,4) tiling of the plane.

That’s what a tiling of a Euclidean plane looks like. What does a tiling of a sphere look like?

The sum of the angles of a spherical triangle is always greater than π. There are only a few values for l,m,n that form a pattern covering the sphere just once without any overlaps or gaps. The possible values for (l,m,n) are[2]:

(p p 1), (p 2 2), (3 3 2), (4 3 2), (5 3 2).

The sides of these triangles form great circles or geodesics.

Let’s look in detail at the (3 3 2) tiling. This fundamental region is a triangle with angles: π/3, π/3, π/2. This is another isosceles right triangle. The total sum of the angles is 7π/6. The area of a single triangle (for sphere radius = 1) is π/6. Since the total area of the unit sphere is 4π, it will take 24 of our triangles to the tile the sphere. If we did so, we’d get a result like this:

A (2,3,3) tiling of the plane.

There are 6 points where 4 vertices (each of angle π/2) meet, and 8 points where 6 vertices (each of angle π/3) meet. The symmetries consist of rotations and reflections.

Rotations: there are 3 axes with order 2 rotation and 4 axes with order 3 rotation (antipodal points share an axis). And we count the identity (no rotation) as one of the rotations. So altogether:

  • 1 identity rotation (no rotation)
  • 4×2 rotations, (not 4×3 since we don’t want to double count the identity),
  • 3×1 rotations, (not 3×2 since we don’t want to double count the identity),

1 + 4×2 + 3×1 = 12 rotational symmetries altogether.

Reflections: The illustration immediately below shows 3 possible reflection planes for our tiling. But this is not all of the possible planes of reflection of course. Each plane in the illustration corresponds to one of the great circles (aka geodesics) traced out by the sides of the triangles: each such great circle is a plane of rotation. There are 6 of these great circles in this tiling. To these 6 reflections are added 6 so-called roto-reflections, in which, using the same 6 planes, a rotation by π is followed by a reflection.

3 of the 12 possible reflection symmetry planes for the (3,2,2) triangle tiling.

The group of 12 rotations and 12 reflections corresponds to the group S4, which is of order 4! = 24.

So what about tetrahedrons? At some point this article has to mention tetrahedrons, given the title.

Wikipedia says: “A regular tetrahedron has 12 rotational (or orientation-preserving) symmetries, and a symmetry order of 24 including transformations that combine a reflection and a rotation.

The group of all symmetries is isomorphic to the group S4, the symmetric group of permutations of four objects, since there is exactly one such symmetry for each permutation of the vertices of the tetrahedron.

And indeed the following diagram also from wikipedia [4] shows that the rotations and reflections of a tetrahedron correspond exactly to those of the (3,3,2) triangle group that we have been working with.

The proper rotations, (order-3 rotation on a vertex and face, and order-2 on two edges) and reflection plane (through two faces and one edge) in the symmetry group of the regular tetrahedron.

This tetrahedral group “arises if we inscribe a regular tetrahedron in a sphere and mark its vertices together with the projections of the centers of the faces and the midpoints of the edges on the the sphere, the center of projection being the center of the sphere.”[3] That article goes on to say that the defining relations of the group are:

L²=M²=N²=1,  (LM)³=(MN)³=(NL)²=1

where L, M, N are the reflections in the side of the (3,3,2) triangle.

So to summarize, there are 24 symmetries of the (3,3,2) triangle group and these consist of 12 rotations and 12 reflections.

Now, rotations are orientation-preserving transformations, whereas reflections are orientation-reversing motions. Triangle groups are not examples of Keinian groups. Kleinian groups are groups of möbius transformations, which are orientation-preserving.[5]

Triangle groups were studied first in the 19th century and the study of Kleinian groups and eventually hyperbolic geometry grew out of those foundations. So lets pursue this analysis into the world of Kleinian groups.

Every group of motions, which is generated by reflections has a subgroup of index two. This subgroup consists of directly conformal motions, that is of, möbius transformations.“[5]

If we throw out the reflections, we are left with a set of 12 rotations. This subgroup is isomorphic with A4, the alternating group of permutations of four symbols. Wikipedia says: “The set of orientation-preserving symmetries forms a group referred to as the alternating subgroup A4 of S4″.

Generators for A4 satisfy these relations:

u³ = v³ = (uv)² = I

We can generate A4 with two three-cycles [6]:

U = (123), and V=(124).

It is interesting to work out all the permutations of these generators and see that there are indeed only 12 of them:

Generators Result Already Seen?
I 1234
U 2314
V 2431
UU 3124
UV 4321
VU 3412
VV 4132
UUU 1234 I
UUV 3241
UVU 4132 VV
UVV 1342
VUU 1423
VUV 3124 UU
VVU 4213
VVV 1234 I
UVVU 2143
VUVU 1234 (VU)^2=I
VVUU 4321 UV

So the elements of the A4 group in terms of our generators is: I, U, V, UU, UV, VU, VV, UUV, VVU, UVV, VUU, UVVU.

Nomenclature seems inconsistent across writers, but lets call the tetrahedral group that is isomorphic with S4, T*(3,3,2). And the tetrahedral group that is isomorphic with A4, we’ll call T(3,3,2). As above, the defining relations of T(3,3,2) are

u³ = v³ = (uv)² = 1,

where u = LM and v = MN and  L, M, N are the reflections in the side of the (2,3,3) triangle [3].

From [3], we get some sample values for U and V:

Finding an appropriate fundamental domain was not easy, but a triangle with vertices at these corners works:
[0, -x + xi, x+xi]
where x= -0.366025393.

In spherical coordinates (phi, theta) these corners correspond to:

[(0,0), (-PI/4,len), (+PI/4,len)]
where len = acos((cos(PI/3.)+cos(PI/3.)*cos(PI/2.))/(sin(PI/3.)*sin(PI/2.))) = 0.955316618 rad.

Given this fundamental domain and the list of generators above, we can finally tile the Riemann Sphere with (2,3,3) tirangles using Möbius transformations! The fact that we are using only the orientation preserving symmetries means we get a triangle tiling that covers half of the sphere and leaves empty space elsewhere:

3,3,2 Triangle tiling on the Riemann Sphere, as well as an equirectangular projection of same. Rotated using Möbius transformations. You can explore it further here.

So to summarize, the triangle tiling was formed by repeatedly applying the 2 Möbius transformations to the given fundamental domain in the 12 combinations indicated by A4 symmetry. Implementation note: we are rotating this sphere not by rotating the camera or the mesh, but again by applying Möbius transformations to the texture as discussed in this article, which is why the equirectangular projection to the right in the picture above is morphing in that weird way.

Addendum 1: The A4 Group

The A4 group is of order 12. It has the following non-trivial subgroups:

  1. Three groups of order 2, isomorphic to Z2.
  2. Four groups of order 3, isomorphic to Z3.
  3. One group of order 4, isomorphic to the Klein 4 group: V4. Also isomorphic to the dihedral group D2.

Lets linger on the V4 group for a second.  If you stretch a tetrahedron like this:

It no longer displays A4 symmetry. You’ll never find an axis that you can rotate by an angle of 2π/3 and have it look the same. But it still displays V4 symmetry, the symmetry of a baseball for instance [9]:



Conjugacy Classes of A4

There are 4 conjugacy classes of A4:
1. One class containing the identity.
2. One class containing the three 180 degree rotations through opposite edges.
3. One class for the four forward rotations of π/3 around each corner.
4. One class for the four reverse rotations of  π/3 around each corner.
Note that classes 3 and 4 are merged in S4 but disjoint in A4 because A4 does not have a reflection.[8]

If the identity is { 1, 2, 3, 4},
Class 2 consists of these permutations:
{ (2 1 4 3), (3 4 1 2), (4 3 2 1) }
Class 3 consists of these permutations:
{ (2 3 1 4), (1 4 2 3), (3 2 4 1), (4 1 3 2) }
Class 4 consists of these permutations:
{ (3 1 2 4), (1 3 4 2), (4 2 1 3), (2 4 3 1) }
To visualize this, label the vertices of the tetrahedron 1,2,3 and 4 in any order. Then the numbers listed in the conjugacy class are the permutations of the vertices for that class.

You could also label the permutations using our generators:
The identity is I,
Class 2 consists of these permutations:

{ UVVU, VU, UV }

Class 3 consists of these permutations:

{ U, VUU, UUV, VV}

Class 4 consists of these permutations:

{ UU, UVV, VVU, V }


Note, the transformation of U is a rotation around vertex 4 and the V transformation is a rotation around vertex 3.

Normal Subgroups:

A normal subgroup must be a combination of conjugacy classes. These are our conjugacy classes (from above):

e – the identity element

x, y, z – 180 degree flips

a, b, c, d – 120-degree clockwise rotations

a², b², c², d² – 120-degree counterclockwise rotations.

The number of elements in each class are 1, 3, 4, and 4 respectively. By LaGrange’s theorem the order of a subgroup must divide the order of the group. The only non-trivial combination of classes that meets that constraint is {e, x, y, z} which is V4.   But that on its own is not enough to determine normalcy. However this observation from Armstrong [10] helps: “If H is a subgroup of G, then each conjugate gHgis also a subgroup of G and has and has the same order as H. Therefore, if G has no other subgroup of the same order as H, then H must be a normal subgroup of G.” So V4 is a normal subgroup of A4.

Since it is normal, we can take a quotient, i.e.:

C3 = A4/V4

A4 = V4⋊C3

This is a semi-direct product because C3 is not normal in A4. Details:

V4 is normal in A4. C3 is not normal in A4. Since |V4| and |C3| are relatively prime, we have V4 ∩ C3 = {e}. Lets refer to A4, V4 and C3 as G, N and H respectively. Every element in G is uniquely expressible in the form nh. The uniqueness follows from N ∩ H = {e}.  Since N is normal in G, for each h ∈ H we have an automorphism of N given by n ↦ hnh.  In other words, the automorphism is the inner automorphism of h restricted to N.

I’m not sure why it is so important to mention the automorphism. The semi-direct product is a product of a normal group and a non-normal group – that seems to be the main point. Update: I got a deeper understanding of the role automorphism groups in semi-direct products and wrote about it here.

For the Klein 4 group V4 we have the relations a² = b²=1 and ab=ba. For C3 we have c³=1. Due to the inner automorphism, we can also state that cac = ab and cbc = a, for the appropriate choice of a and b.[11]

I am assured in many places that that last presentation represents a group that is isomorphic to A4 though I don’t really see it. But we already know we’re working with A4.


Addendum 2:

In the first chapter of the book Finite Möbius Groups, Minimal Immersions of Spheres, and Moduli, Gabor Toth works out a set of Möbius transforms corresponding to all 3 polyhedral symmetry groups. These are different from the ones I used above. Here I apply his tetrahedral rotations to a so-called 360 photo (taken on a Ricoh Theta):

And just for kicks, here is the same process applied to another photo using his octahedral symmetries:

Octahedral symmetries are double those of the tetrahedron which makes intuitive sense when you consider that you can fit 2 tetrahedrons in a cube, e.g. [7]:

[1] https://commons.wikimedia.org/wiki/File:Tile_V488_bicolor.svg#/media/File:Tile_V488_bicolor.svg

[2] Coxeter, H. S. M. (1974) Regular Complex Polytopes, Cambridge Unitvesity Press, London. Page 19.

[3] Noneuclidean Tesselations and Their Groups. Academic Press, Oct 18, 1974. Page 73 on.

[4] By I, Cronholm144, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=2295116

[5] Geometry of Group Representations: Proceedings of the AMS-IMS-SIAM Joint Summer Research Conference Held July 5-11, 1987 with Support from the National Science Foundation. William Mark Goldman, Andy R. Magid. American Mathematical Soc., 1988 – Mathematics. Page 4.

[6] http://www.math.uconn.edu/~kconrad/blurbs/grouptheory/genset.pdf

[7] By Steelpillow (Own work) [CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

[8] http://www.math.uconn.edu/~kconrad/blurbs/grouptheory/conjclass.pdf

[9] By Tage Olsin – Cropped from Image:Baseball.jpg by Tage Olsin, CC BY-SA 2.0, https://commons.wikimedia.org/w/index.php?curid=2345172

[10] M.A. Armstrong, Groups And Symmetry. Page 114.

[11] http://sierra.nmsu.edu/morandi/notes/semidirect.pdf, page 3.


Congruence Group Γ(2)

Modular Group Γ(1) generated the hyperbolic tessellations seen previously. Its generators are:

S: z\mapsto -1/z

T: z\mapsto z+1

Or in matrix form:  [0,1;-1,0], [1,1;1,0].

The Congruence Group Γ(2) can be generated by these matrices:

[1,2;0,1], [1,0;-2,1]

The tiling looks like this:

You can view a version I wrote in Three.js/WebGl here. You can spin it and pan and zoom. It is clear in this version that the tessellation lives on the upper-half plane of the Reimann sphere.

As before the orange region is the fundamental domain. It and all of the tiles are 4 sided and touch the rim at 4 points. Here is another representation of the fundamental domain from Wolfram Alpha[1]:

The 4 corners of this fundamental domain are -1, 0, 1, and ∞. The red letters indicate the effect of the initial tiling of 1 letter words (e.g. T, T¯¹, S, S¯¹). These areas correspond to the yellow quadrilaterals in the tiling above.

The imaginary axis cutting the fundamental domain in two is an additional axis of symmetry we could impose on the tiling. Then it would look just like the Farey graph depicted in the previous post and the disk would be tiled by ideal triangles. Ideal triangles in hyperbolic space have interesting properties (to quote wikipedia)[3]:

  • All ideal triangles are congruent to each other.
  • The interior angles of an ideal triangle are all zero.
  • An ideal triangle has infinite perimeter.
  • An ideal triangle is the largest possible triangle in hyperbolic geometry.

The Modular Necklace

If you have read the book “Indra’s Pearls” you will be familiar with a similar tiling which they describe as “The modular necklace”:

“A modular necklace is a tangent chain of four circles in which adjacent disks are paired by two transformations a and b… The transformations a, b, and ab are all parabolic and S = Fix(a), Q = Fix(b), a(P)=R, b(R) = P so that P = Fix(ba) and R = Fix(ab)… The four points P, Q, R and S always lie on a circle (or line) which is the limit set of the group. The limit circle is perpendicular to all circles in the chain. Both inner and outer tiles have their sides matched in the same way and the surfaces made by gluing up these tiles are each spheres with three punctures or cusps.”[2]

Following their naming, P, Q, R and S are the tangency points of the four circles a, A, b, andwhich are positioned where the letters T, T¯¹, S, S¯¹ are in the diagram above, respectively. The möbius transform corresponds to T and the möbius transform b corresponds to S.

If we look at the tiling this way, then it makes no sense to restrict ourself to the upper half plane and the limit set is very clear:

Another point of view on the same tiling:


[1] Weisstein, Eric W. “Modular Group Lambda.” From MathWorld–A Wolfram Web Resource. http://mathworld.wolfram.com/ModularGroupLambda.html

[2] “Indra’s Pearls: The Vision of Felix Klein”. By David Mumford, Caroline Series, David Wright. Page 214.

[3] https://en.wikipedia.org/wiki/Ideal_triangle


Ford Circles and Farey Graphs

Here is an image of a tessellation or tiling of the upper half-plane. Under some group of symmetries, an initial triangle (for instance the one in orange) covers the plane without overlaps. (The initial triangle is not ideal because only one of its angles is 0). The group of symmetries used are those of the modular group. See my previous post where I go into this in greater detail.

Tessellation of the upper half plane using the symmetries of the Modular Group.

Note that each triangle has a vertex on the rim of the circle. The rim of the circle is the real projective number line.

The orange initial triangle, aka the fundamental domain, is touching the real number line at the point of infinity. The green triangle right below the orange triangle touches the real number line at the point 0. The green triangle = S(orange triangle), where S -> -1/z. Every other vertex touching the rim of the disc can be obtained by applying some combination of S and T. (T->z+1).

Ford Circles

Lets start with 2 circles, one with a radius=1 touching at 0. Another is a line, Im(z) = 1 (a circle with an infinite radius that is). These are the 2 large circles in the picture below. If we then apply S and T repeatedly we get the Ford circles.

The set of points where the circles touch the real number line is the set of rational numbers, Q. This is the same set of points where the vertexes of the tessellated initial triangles touch the rim.

From [4], I learned the following interesting facts:

  1. The circle touching the real axis at the reduced fraction a/c has radius 1/2c². This  explains why the circles for reduced fraction a/c and a’/c have the same radius.
  2. The circles touching z = a/c and z = b/d > a/c are tangential to each other because ad − bc = 1. Such circles are images of the 2 initial circles touching z = 0 and z = ∞ under SL(2, Z) (determinant = 1).
  3. The circle between these tangential circles touches at (a+b)/(c+d). Because the latter circle is the image of the circle between the circles touching z = 0 and z = ∞, namely the circle touching z = 1, under

f(z)={\frac {az+b}{cz+d}} .

The formula (a+b)/(c+d) is the formula for calculating a mediant between 2 Farey neighborsa/b and c/d.

Ford Circles


“The Farey graph is the PSL(2,Z) images of the imaginary axis, and so contains all of Q* as its points at infinity. It is not hard to see that p/q and r/s are connected by an edge iff ps-qr = +/-1, so it is in some sense a geometric recording of the matrix group.” [1]

Here the images of the imaginary axis are highlighted and the Farey graph is evident:

Farey Graph

[1] http://mduchin.math.tufts.edu/notes/hyp-groups-course.pdf

[2] “Indra’s Pearls”, pages 210-213.

[3] http://homepages.warwick.ac.uk/~masbb/HypGeomandCntdFractions-2.pdf

[4] http://www.maths.ed.ac.uk/~aar/Whittaker2012A


Tessellation of the Hyperbolic Plane on the Riemann Sphere

I’m interested in learning more about the modular group and this article looking into hyperbolic tessellations represents my initial efforts to collect my thoughts on the topic.

We are familiar with hyperbolic tessellations from the artwork of M.C. Escher and from numerous renderings of the Poincare Disk (which was really invented by Beltrami, not Poincaré):



The disk model is not the only model of hyperbolic space. There is also the Klein model, the hyperboloid model, and the upper half plane model, and probably some others. Let’s consider the upper half plane model. One way to look at the Poincaré half plane model is as a view on that part of complex plane where the imaginary part is positive. So we’re only considering half of the complex plane, the upper half. Here is what a tiling of the upper half plane looks like:



By Fropuff (from en wikipedia) [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0/)], via Wikimedia Commons


To quote wikipedia: “The projective linear group PGL(2,C) acts on the Riemann sphere by the Möbius transformations. The subgroup that maps the upper half-plane, H, onto itself is PSL(2,R)”. So Möbius transformations with real coefficients preserve the upper half-plane. That means that any such transformation will keep all points that are already on the upper half-plane on the upper half plane. (And incidentally, the real numbers are mapped to themselves).

If we look at the upper half plane model this way (as the upper half of the complex plane), then when we render it on the Riemann Sphere, it looks like this:

In this depiction, the tiled portion is the upper half plane. The red hemisphere is not the upper half plane, it is the lower half plane. The green axis points to (∞, ∞i), the blue axis intercepts the sphere at (-1,0i) and the red axis intercepts the sphere at (0,-i).

The tessellation depicted above is of the modular group, PSL(2,Z), where Z indicates the set of integers. So in other words the modular group Γ is those mobius transformations with integer coefficients and unit determinant. It is a subgroup of PSL(2,R) (but not a normal subgroup).

To quote wikipedia again:

“The modular group can be shown to be generated by the two transformations

    S: z -> -1/z
    T: z -> z + 1

so that every element in the modular group can be represented (in a non-unique way) by the composition of powers of S and T. Geometrically, S represents inversion in the unit circle followed by reflection with respect to the imaginary axis, while T represents a unit translation to the right.” z is a complex number of course. And as mentioned above, S and T are Möbius transforms with integer coefficients and determinant = 1.

So we can use those 2 transformations and apply them over and over. What region should we start with as our initial tile (or to use the technical terminology: what fundamental domain should we choose?). A common choice is depicted in the grey region in the upper half plane figure above. It is that region where |z| is > 1 and |Re(z)| < 1/2. The orange triangle in the spherical tiling above is the very same region.

You can view my Three.js version of this tessellation here where you can spin and zoom it as you please.

Note that we are drawing this diagram using WebGL shaders. Pixel shaders (aka fragment shaders) are called once for each pixel. In our case a pixel maps to a complex coordinate. So our code is called repeatedly and handed a different complex coordinate on each call. The pixel shader has to decide what color to use for this given pixel/complex coordinate. So it has to do the Möbius transforms in reverse. (I discuss this issue in greater detail here). This shows how the tesselation works [3]:

Thus, in code, the logic is:

 if |z| < 1 then apply S-1 else if Re(z) < -.5 apply T, else T-1


(remember we’re doing everything backwards because we’re working with pixel shaders).

By a suitable placement of the camera you can get a view that looks just like the Poincaré disk:

This provides an intuition for believing that there is a simple mapping from the upper half plane model to the disk model, and indeed there is, it is called the Cayley transform.


Rational Numbers, Q

In case it wasn’t clear, the rim of the upper half plane is the projective real line (the real line plus a point at infinity).  The upper half plane h = { x + iy : y > 0}.  The triangles in the tesselation are called ideal triangles since they are each bounded by three sides and have two endpoints in h but one “endpoint” not in h: the third endpoint is either a rational number on the x-axis or is ∞.

“Note that any member of the modular group maps the projectively extended real line one-to-one to itself, and furthermore bijectively maps the projectively extended rational line (the rationals with infinity) to itself, the irrationals to the irrationals, the transcendental numbers to the transcendental numbers, the non-real numbers to the non-real numbers, the upper half-plane to the upper half-plane, et cetera.”[6]

In the same article it mentions that the modular group never takes an irreducible fraction to a reducible one, which explains its relevance to Farey graphs and Ford circles which I explain in my next post.

Thus given our choice of fundamental domain, the points where the tessellations of the fundamental domain hit the boundary are those points s ∈ R ∪ {∞} that are fixed by a parabolic element of Γ. The points are precisely Q ∪ {∞}, where Q stands for the set of rational numbers. The parabolic element is the transform T above. You can tell it is parabolic because the Trace of the 2×2 matrix corresponding to the Möbius transform for T is 2.

For z ∈ SL2(R), z is parabolic if z can be conjugated to T . Any parabolic element z generates an infinite discrete subgroup of SL2(R) consisting solely of parabolic elements; and z fixes no points of H and a unique point of P1(R). The parabolic points for SL2(Z) are P1(Q). [4]

The fundamental domain in orange above has one point on the real axis. Each transformation in the tessellation moves that point around the rim and generates a new rational number.

Hyperbolic Tesselations

So what does this have to do with hyperbolic tesselations? We’ve explained how a special set of Möbius transformations, those that generate the modular group, can tile the upper half plane. The upper half plane is a model of hyperbolic geometry. This was the famous insight that came to Poincaré in a flash:

“At that moment which I put my foot on the step the idea came to me, without anything in my former thoughts seeming to have paved the way for it, that the transformations I had used to define the Fuscian functions were identical with those of non-Euclidean geometry” L’Invention Mathématique, Henri Poincaré

Or as wikipedia says: “Möbius transformations are also isometries of the hyperbolic plane“. This seems a strange statement. Möbius transformations are conformal on the complex plane: they preserve angles, but the don’t preserve lengths. Isometry means ‘length preserving’. This is possible because in hyperbolic space, in marked contrast to Euclidean space, equal angles guarantee that corresponding side lengths are equal in the hyperbolic metric.[1] A hyperbolic triangle’s size is determined by its angles.

Algebraic vs Geometric

The matrices [0,1,-1,0] and [1,1,1,0] generate SL(2Z). Both matrices have determinant = 1. That means they are volume and orientation preserving.

The analogous Möbius transforms:

    S: z -> -1/z
    T: z -> z + 1
generate the modular group. They are not volume preserving in the upper half plane but they are in the hyperbolic plane: all tiles are the same size in the hyperbolic plane.

And finally….

As a final note, since we’re working with the Riemann sphere we can do all sorts of fun mappings from 360 video footage, as I detailed elsewhere. So piping video through the tessellation gives you:


Video 5 from Robert Woodley on Vimeo.



[1] http://www.mathematica-journal.com/issue/v9i3/contents/ModularGroup/ModularGroup.pdf

[2] https://math.dartmouth.edu/~m125x15/quat-book-chap29-072315.pdf

[3] http://www.math.uconn.edu/~kconrad/blurbs/grouptheory/SL(2,Z).pdf

[4] https://homepages.warwick.ac.uk/~masiao/modforms/examples2.pdf

[5] http://www.math.cornell.edu/~hatcher/TN/TNch1.pdf

[6] https://en.wikipedia.org/wiki/Modular_group


Möbius Transformations on Spherical Photos and Videos

Spherical Video presents some interesting challenges, for instance, how do you zoom? Or how do you rotate on any arbitrary axis? As the mathematician Henry Segerman pointed out in a post for EleVR, you can achieve both of the above using Möbius transformations. The transformations are conformal (they preserve angles), and they map circles to circles (considering a line to be a circle of infinite radius). Professor Segerman’s work is the inspiration for the project I am describing here.

I wrote an implementation using Möbius transformations to manipulate spherical images in WebGL/Three.js. The implementation is here. Click on the ‘?’ for help or watch this video.

So what is going on here?

The mathematical procedure:

Spherical cameras such as the Ricoh Theta save images in an equirectangular format. This is then wrapped around a sphere to give the spherical effect. (With three.js you create a material whose texture is the saved image from the Theta and then create a mesh using this material and a sphere geometry.) The X and Y of the equirectangular format map to the longitude and latitude of the sphere.

The Riemann sphere is a representation of the complex plane as a sphere using reverse stereographic projection. Möbius transformations are transformations of the complex plane. Our three.js sphere is a normal sphere in 3-d cartesian space (R3); each point on its surface has an (x,y,z) coordinate where x, y and z are real numbers. We can convert our x,y,z point to a point in the complex plane if we take our sphere to be a Riemann sphere. Or in jargon we can say equivalently:  P¹(C) is diffeomorphic to the sphere S². The formulas are here (and elsewhere).

So for instance the south pole is (0,0,-1) in cartesian/R3 space and (0,0i) in complex space. The north pole is (0,0,1) in cartesian space/R3 and (∞, ∞i) in complex space. (The Reimann sphere is really the complex plane plus one point which is the point at the north pole, but I digress).

The technical procedure:

To implement our transformations, we are going to move pixels around on the texture. We can only do this in the shader since doing it in javascript would be way to slow. Specifically we are going to do it in the fragment shader. Our vertex shader will be short and boring, doing only what is necessary to build the sphere’s vertices. Nothing special there. The fragment shader is where the work is done.

The fragment shader is called when the graphics layer needs to know what color to put at a given UV coordinate. We will pluck that pixel from our transformed texture. The steps to execute on each call to the fragment shader are:

1 – Get the UV coordinates. ‘UV’ is industry nomenclature for the X and Y coordinates of the texture that the graphics layer is trying to draw.

2 – We know that the rectangular texture must map to a sphere. The top of the rectangle maps to the north pole, the bottom to the south pole. So we can calculate the X, Y, and Z coordinate of the sphere corresponding to the UV coordinate. That is, we know which point of the sphere we are drawing.

3 – This sphere is also a Riemann sphere as mentioned above, so we calculate the point (a + bi) on the complex plane corresponding to the cartesian point (X,Y,Z) on the sphere, using the formulas mentioned above.

4 – We now know our location on the complex plane and we apply as many transformations as we’d like. When we are done we have our new complex point (c + di).

5 – We reverse the above steps and calculate the cartesian X,Y,Z corresponding to (c + di). Then we calculate the UV corresponding to this X,Y,Z and we use the color at that pixel, UV.

The only Möbius transformations I’ve implemented for now are those to do rotation and zoom. By default the fixed points are antipodal though you can explicitly set the fixed points using the Epsilon 1 and Epsilon 2 buttons. The video linked to above gives a good overview of what all the different buttons do.

This is a rotation around 2 non-antipodal fixed points:


In addition to Möbius transforms to do rotation and zoom, there are some other complex transformation options.


You may have noticed that we start with the point on the complex plane (a + bi) for which we need a pixel. We then transform (a + bi) into (c + di) to get the pixel we will draw. Thus the transformation is really a reverse transformation.

Infinities of volleyball players on North Avenue Beach (Works at 60FPS on video!):

This article by Henry Segerman gives a comprehensive overview of the math behind these transformations and includes more examples of other transformations you can do.


Thought Bubbles

A window is a two-dimensional hole in a two-dimensional plane that allows you to see into a three-dimensional world. So what if we could make three-dimensional holes?

The original idea came from a three.js demo by altered qualia where he was demo’ing fresnel shaders:

I didn’t care much about fresnel shaders, but was intrigued by the bubbles. I realized that rendering the outer sphere was not needed to render the bubbles:

These bubbles are three-dimensional windows that can be taken anywhere. Spherical holograms.

To render the above image, you need 2 cameras, each one looking at a separate texture. Now look at this next image. If we flood Michigan avenue we need 2 cameras as well, one for the surrounding sphere, and one to capture the reflection as well.

We can view the scene of a flooded Michigan Avenue at home, via one of our holo-bubbles from above. The camera count is now 3, and you have to deal with the fact that while you want them all to turn in sync, some will need to be more wider angle than others.

We can make the inner camera have such a wide angle that it captures the zenith and the nadir, and the cursor both zooms and moves in space. It is a very sensitive. (Try it!).

This final image is one of the strangest I’ve made to date. Only one camera, with the sphere in the middle seemingly refracting the surroundings but even though the image is in the sphere is reversed it tracks the outer image as they rotate. How is this possible?

Most of the above images can and should be clicked to see the rendering in WebGL.


Complex Surfaces

I wrote a separate version of formula toy that handles complex functions. So, you can type in a function like: f=sqrt(g). Both f and g are expected to be complex functions:

    g = u + iv


    f = w + ix

where u is the real component of g, v is the imaginary component of g, etc.

To draw this surface we need 4 axes, so formula toy uses a color gradient for the 4th axis. We name these as follows:
– fR – the real component of f.
– fI – the imaginary component of f.
– gR – the real component of g.
– gI – the imaginary component of g.

And you can choose which complex axis maps to which cartesian axis.



This flexible way of doing the mappings allows for simple multi-valued functions/Riemann surfaces:






Lambert W function

Click on the images to open the surface in formula toy. More details here.



Torus Knots

Formula Toy is a simple and free WebGL app I wrote that allows you to enter in 3-d formulas and see the resulting surface. Sort of like Desmos, but for 3D.

When I first wrote it you could express your formulas in 3 different coordinate systems: cartesian, spherical (polar), and cylindrical. I recently add toroidal which is not very useful except for drawing toruses:



AND I added parametric surfaces. If you choose this option, the system is expecting formulas for X, Y, and Z. You are given U and V. For instance a helix could be expressed as:



Parametric equations that are functions of a single variable (t) instead of 2 variables (u,v), don’t display because they have zero thickness. For instance the parametric formula for a trefoil knot is a function of 1 variable. To make this visible in formula toy, you need a tube geometry so that the knot doesn’t have zero thickness/volume. Three.js offers a tube geometry but you can also achieve the same effect using the parametric geometry, but with a little extra math. We can start with a torus, and make that our ‘tube’ that will be bent into a trefoil. Here is the parametric formula for a torus:



So to plot a trefoil:

// Setup
// Parametric formula for a trefoil
pp=2;     // A trefoil is a (2,3) torus ring.
// xx,yy,zz are the formula for the trefoil, a function of one variable (phi)
// Modified Torus formula to bend a torus into a trefoil shape:


So that works, and is succinct, but you could also achieve the same thing in a more mathematically correct but longer way. The correct way is to take 2 normal vectors to the derivative of the trefoil formula with respect to phi. Pseudo-code would look something like this:

    var dv = df(pp, qq, phi); 
    var north = new THREE.Vector3(0,0,1);
    var v1 = cross(dv, north);
    var v2 = cross(dv, v1);
    x = xy + (cos(theta)*v1.x + sin(theta)*v2.x)*.2,
    y = yy + (cos(theta)*v1.y + sin(theta)*v2.y)*.2,
    z = zz + (cos(theta)*v1.z + sin(theta)*v2.z)*.2,

But that code uses three.js objects so is beyond what you can do in formula toy.

A trefoil is just on example of a torus knot. It is a (2,3) torus knot when means it winds 3 times around a circle in the interior of the torus, and 2 times around the torus’ axis of rotational symmetry. There is a whole family of torus knots (p,q). p and q correspond to pp and qq in the parametric formula above.

For instance, here is a (3,7) knot:


Below is another example which shows a (5,6) torus knot winding around a torus. This was not done in Formula Toy since it draws 2 surfaces (the knot and the torus), and Formula Toy only draws one surface. (but it was all done with three.js).



Rotations, Transformations – Geometries and Meshes

I was driving myself batty trying to get all my rotations and transformations to behave correctly in three.js. So in these kind of cases one must always pare down to essentials. As follows:

Lets create a simple mesh and place it on the scene:

// Example 1
var geo = new THREE.BoxGeometry(5,5,20,32);
_mesh = new THREE.Mesh(geo, new THREE.MeshNormalMaterial());

Then in the render loop, we rotate it around the Z axis (the blue axis):

_mesh.rotation.z = -_tick * Math.PI/256;    

The result:
This just a screen grab, an animated gif. Hence the jerk when the animation restarts.

Now what happens if we rotate the mesh in the initial setup:

// Example 2
var geo = new THREE.BoxGeometry(5,5,20,32);
_mesh = new THREE.Mesh(geo, new THREE.MeshNormalMaterial());

Code in the render loop is the same as before:

_mesh.rotation.z = -_tick * Math.PI/256;    

Now the block rotates along the X (red) axis, even though we told it to rotate it along the Z axis.

If we specify rotation order in the initial setup, then it will rotate around the Z axis:

// Example 3
_mesh.rotation.order = 'ZXY';

The result:

Now lets try some translation. Initial setup:

// Example 4
var geo = new THREE.BoxGeometry(5,5,20,32);
_mesh = new THREE.Mesh(geo, new THREE.MeshNormalMaterial());
_mesh.rotation.order = 'ZXY';
_scene.add( _mesh);

Render loop is the same, rotate around Z axis. The result is that the translation is applied and the object rotates around the its new local axis which was also shifted downwards:

Three.js also supports the axis/angle method of specifying rotations:

// Example 5
var geo = new THREE.BoxGeometry(5,5,20,32);
_mesh = new THREE.Mesh(geo, new THREE.MeshNormalMaterial());
// these have no effect because in render() we will directly modify the internal rotation matrix
//_mesh.rotation.order = 'ZXY';

Render loop:

var axis = new THREE.Vector3( 0, 0, 1 );
var angle = _tick * Math.PI / 256;
   // matrix is a THREE.Matrix4()
_matrix.makeRotationAxis( axis.normalize(), angle ); 
_mesh.rotation.setFromRotationMatrix( _matrix );

The result is identical to what we achieved above in Example 1 with mesh.rotation. But often it is easier to conceptualize an axis of rotation rather than a succession of Euler angles.

We can mimic the Example 3 result using makeRotationY and applying it to the geometry.

// Example 6
var geo = new THREE.BoxGeometry(5,5,20,32);
geo.applyMatrix( new THREE.Matrix4().makeRotationY( Math.PI/2 ) );
_mesh = new THREE.Mesh(geo, new THREE.MeshNormalMaterial());
_scene.add( _mesh);

Render loop is same as Example 5, with the desired result.
Now why did that work whereas mesh.rotationY is ignored? Because we rotated the geometry; the vertices were changed. This will be clearer if we translate the geometry:

// Example 7
var geo = new THREE.BoxGeometry(5,5,20,32);
geo.applyMatrix( new THREE.Matrix4().makeRotationY( Math.PI/2 ) );
geo.applyMatrix( new THREE.Matrix4().makeTranslation(0,-6,0) );
_mesh = new THREE.Mesh(geo, new THREE.MeshNormalMaterial());
_scene.add( _mesh);

// put sphere at mesh origin
var sphere = new THREE.Mesh(
    new THREE.SphereGeometry(1,20,20),
    new THREE.MeshNormalMaterial());
sphere.position.set(0, 0, 0,);  // we could put the sphere anywhere
                                // and the box would rotate around it

Render loop code is the same as the previous 2 examples:

var axis = new THREE.Vector3( 0, 0, 1 );
var angle = -_tick * Math.PI / 256;
   // matrix is a THREE.Matrix4()
_matrix.makeRotationAxis( axis.normalize(), angle ); 
_mesh.rotation.setFromRotationMatrix( _matrix );

The result:
The sphere represents the center of our geometry, its origin. The vertices have been rotated and translated from the local origin, where the sphere is.

If we’re rotating geometries, it is helpful to create a set of axes to show the local rotation axes of the geometry.

// Example 8:
// put axes at mesh origin with mesh rotation
// drawAxes is my routine which is based on THREE.AxisUtils(). See animation link below.
_scene.add(drawAxes(10, _mesh.position, _mesh.rotation));

Since we’re just rotating the mesh around the Z (blue) axis, we can use this more compact syntax in the render loop:

_mesh.rotation.z = -_tick * Math.PI/128;

The result:

So to review: we wanted a geometry to rotate around a point that was external to the geometry. We did that by transforming the vertices of the geometry using applyMatrix.

There is another way to accomplish the same result: attach the box mesh to a parent mesh. Set the child’s position (that is to say, the box’s position) to be relative to the parent. And then place the parent where one wants, and rotate the parent if appropriate:

// Example 9:
var geo = new THREE.BoxGeometry(5,5,20,32);
_mesh = new THREE.Mesh(geo, new THREE.MeshNormalMaterial());
_mesh.rotation.y = -Math.PI/2;
_mesh.position.set(0,-6,0);    // _mesh will be the child

_sphere = new THREE.Mesh(      // _sphere will be the parent
    new THREE.SphereGeometry(1,20,20),
    new THREE.MeshNormalMaterial());
_sphere.rotation.x -= Math.PI/8;
_sphere.add(_mesh);      // add child to parent

// put axes at parent origin with parent rotation
_scene.add(drawAxes(10, _sphere.position, _sphere.rotation));

And in the render loop, rotate the _sphere, not the _mesh.

When is this method (building a parent child relationship) preferable to changing the geometry? I couldn’t see much difference until I had to work with physi.js to apply physics to some of my meshes. Physi.js only works with meshes that have certain simple geometries (sphere, cone, box, etc). It will however work with compound meshes and thus with more complicated geometries, but in this case a parent/child relationship between the meshes is required.

Full three.js animation is here.

Using r69 of three.js.


Drawing Pentatope Cross-Sections in three.js

A triangle is the simplest regular figure in 2 dimensions. Its 3 dimensional analogue is a tetrahedron. Its 4 dimensional analogue is the pentatope. Another term for these 3 geometries is: simplex. Many articles online explain these further.

I wanted to view what it would look like if a pentatope passed through our 3-dimensional space. There are many examples of what the projection of a pentatope onto 3-d space would look like (ie its shadow), but I didn’t want to do that because while projections can be pretty, they seem less intuitive than cross-sections.

To summarize, the plan was: take 3-dimensional cross-sections of the pentatope (a 4 dimensional shape). The actual drawing will be done using the 3-dimensional drawing toolkit called three.js.

Our equation for the 3-dimensional cross-section is:

    ax+by+cz+K = w

This is a linear equation; we’re not dealing with curved cross-sections for now, though that would be fun. a,b, and c are constants. x,y,z, and w are the 4 axes. K is a constant that we change to get different cross-sections.

But why do we need 4 dimensions to describe a 3-dimensional space? Because we are locating that 3-d space in 4 dimensions. Just as the equation for a plane in 3-d space requires 3 dimensions (e.g. x+y = z describes a plane in 3-d space).

What about our equation for pentatope? Well we don’t have an equation, but we have a collection of points. Our pentatope has 5 corners. Lines connect each point to every other point, resulting in 10 lines. These 10 lines in turn form 10 faces (2-d planes). These 10 faces in turn from 5 3-d tetrahedrons.

Note that:
– The intersection of a 4-d line and a 3-d space is a point.
– The intersection of a 4-d plane and a 3-d space is a line.
– The intersection of a 4-d volume and a 3-d space is a plane.

Our cross-section is going to look like a wire-frame, in other words a collection of lines. So we will capture the intersection of the pentatope’s faces with our cross-sectional space.

Our pseudo-code would look like this:

foreach (face in faces) {   // 10 of these
  // Each face is a triangle. Lets name the vertices p0, p1, p2. These points have 4-d coords.
  // point1 and 2 will be the points we use to draw a line in 3-d space using three.js.
  // they have 3-d coords of course.
  point1 = calculateIntersectionOfLineWithSpace(p0,p1); 
  point2 = calculateIntersectionOfLineWithSpace(p0,p2);
  drawLineUsingThreeJS(point1, point2);

So the interesting bit is in ‘calculateIntersectionOfLineWithSpace()’:

We must use parametric equations to work with lines in dimensions higher than 2. The parametric form for a line defined by the points p0 and p1 is:

    p = p0 + t*v   (1)

    where v = p1 - p0.

We need to calculate what the value of t is at the intersection with our cross-sectional space. (p0 and p1 are the vertices of one of the faces of our pentatope.) So we need to solve for t.

    t = (Pt - P0)/V

Pt is the point of intersection of the line with the cross-sectional space. Given our formula above for our 3-d cross-sectional space, the equation for t is:

    t = (W0-aX0-bY0-cZ0-K)/(aXv+bYv+cZv-Wv)

    Where P0 = (X0, Y0, Z0, W0) and V is (Xv, Yv, Zv, Wv). 

Plugging t into equation (1) above we calculate the point of intersection of our 4-d line with our 3-d space. We return (x,y,z) from ‘calculateIntersectionOfLineWithSpace()’ above, discarding w.

And we simply change K to see different cross-sections. Here is the animated result:

A still:


Minecraft Menger Sponge – STEAM project.

What has zero volume and an infinite surface area? A Menger Sponge of course. If your child is a Minecraft fan like my 7 year old, then this simple fractal can be used to make a good afternoon STEAM project that teaches math and programming concepts. (Note you should already know how to modify Minecraft code. That would take more than afternoon to get a grip on. And of course you should know Java).

First we built a Level 1 Menger cube with snap cubes. Then we came up with the X,Y, and Z coordinates for each of the 20 blocks that make up the Level 1 cube. This was a major goal of our project: increased fluency with 3-d coordinates.

Screen Shot 2014-11-11 at 11.51.32 PM

Then it was not a difficult leap to see how our Java code used these 20 coordinates to place blocks.

    public static void drawblock(World world, int x, int y, int z, int startx, int starty, int startz) {
        int metadata = world.getBlockMetadata(x, y, z);
        Block block = Block.getBlockById(35);
        boolean res = world.setBlock(startx + x, starty + y, startz +  z+5, block, metadata, 3);
        System.out.println("Placing block at " + x + "," + y + ", res = " + res);
    public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World world,
                             int startx, int starty, int startz, int par7, float par8, float par9, float par10) {

        Menger1Item.drawLevel1Cube(world, startx, starty, startz);
        return true;
    public static void drawLevel1Cube(World world, int startx, int starty, int startz) {
        drawblock(world, 0, 0, 0, startx, starty, startz);
        drawblock(world, 1, 0, 0, startx, starty, startz);
        drawblock(world, 2, 0, 0, startx, starty, startz);
        drawblock(world, 0, 1, 0, startx, starty, startz);
        drawblock(world, 2, 1, 0, startx, starty, startz);
        drawblock(world, 0, 2, 0, startx, starty, startz);
        drawblock(world, 1, 2, 0, startx, starty, startz);
        drawblock(world, 2, 2, 0, startx, starty, startz);

        drawblock(world, 0, 0, 1, startx, starty, startz);
        drawblock(world, 0, 2, 1, startx, starty, startz);
        drawblock(world, 2, 0, 1, startx, starty, startz);
        drawblock(world, 2, 2, 1, startx, starty, startz);

        drawblock(world, 0, 0, 2, startx, starty, startz);
        drawblock(world, 1, 0, 2, startx, starty, startz);
        drawblock(world, 2, 0, 2, startx, starty, startz);
        drawblock(world, 0, 1, 2, startx, starty, startz);
        drawblock(world, 2, 1, 2, startx, starty, startz);
        drawblock(world, 0, 2, 2, startx, starty, startz);
        drawblock(world, 1, 2, 2, startx, starty, startz);
        drawblock(world, 2, 2, 2, startx, starty, startz);

Here is the Level 1 Cube in Minecraft:


At this point we wanted to make higher level cubes. A simple recursive algorithm was called for. This was too much for my son, not surprisingly. It is excerpted below if you want to do something similar. The main concept I tried to convey was that each level was a new power of 20.

Level 1 = 20^1 = 20. Length of side: 3 blocks.
Level 2 = 20^2 = 400. Length of side: 9 blocks.
Level 3 = 20^3 = 8000. Length of side: 27 blocks.
Level 4 = 20^4 = 160,000. Length of side: 81 blocks.
Level 5 = 20^5 = 3,200,000. Length of side 243 blocks.
At this point you could point out how the volume is shrinking with each level. E.g: 400/9^3 < 3200000/243^3. Over time the volume will approach zero! Ah, the mysteries of fractals and limits. Back to the concrete: We started with a level 2 cube. Exploring this next level up was important to understand recursion. My son kindly illuminated the structure with torches as night fell: Level2Night

We skipped right to Level 4 which was beautiful and impressive. When night fell in our Minecraft world, the local wild-life (mobs) colonized our structure and served to give a nice sense of scale and depth.




Take a tour of this level 4 Menger Cube:

Level 4 Menger Cube from Robert Woodley on Vimeo.

Could Minecraft handle a Level 5 cube? That was the question on our minds. 3,200,000 blocks. It took about 5 minutes and the laptop labored mightily. But it worked! There were nice glitch effects as Minecraft struggled to build out the structure. Also the top was truncated as Minecraft prevented us from going into outer space.


This incredible fractal structure is best understood through video:

Level 5 Menger Cube in Minecraft from Robert Woodley on Vimeo.

Complete Java class to build a level 5 Menger Cube:

package com.example.examplemod;

import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;

public class Menger1Item extends Item {

    public Menger1Item() {
    public static void drawblock(World world, int x, int y, int z, int startx, int starty, int startz) {
        int metadata = world.getBlockMetadata(x, y, z);
        Block block = Block.getBlockById(35);
        boolean res = world.setBlock(startx + x, starty + y, startz +  z+5, block, metadata, 3);
        System.out.println("Placing block at " + x + "," + y + ", res = " + res);
    public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World world,
                             int startx, int starty, int startz, int par7, float par8, float par9, float par10) {

        Menger1Item.drawLevel1Cube(world, startx, starty, startz);
        return true;
    public static void drawLevel1Cube(World world, int startx, int starty, int startz) {
        int[][] i5coords = returnCoords(81);
        for (int i5 = 0; i5 < 20; i5++) {
            int[][] i4coords = returnCoords(27);
            for (int i4 = 0; i4 < 20; i4++) {
                int[][] i3coords = returnCoords(9);
                for (int i3 = 0; i3 < 20; i3++) {
                    int[][] i2coords = returnCoords(3);
                    for (int i2 = 0; i2 < 20; i2++) {
                        int[][] coords = returnCoords(1);
                        for (int i1 = 0; i1 < 20; i1++) {
                                    i5coords[i5][0] + i4coords[i4][0] + i3coords[i3][0] + i2coords[i2][0] + coords[i1][0],
                                    i5coords[i5][1] + i4coords[i4][1] + i3coords[i3][1] + i2coords[i2][1] + coords[i1][1],
                                    i5coords[i5][2] + i4coords[i4][2] + i3coords[i3][2] + i2coords[i2][2] + coords[i1][2],
                                    startx, starty, startz);
    public static int[][] returnCoords(int level) {
        int[][] coords = {
                {0, 0, 0},
                {1, 0, 0},
                {2, 0, 0},
                {0, 1, 0},
                {2, 1, 0},
                {0, 2, 0},
                {1, 2, 0},
                {2, 2, 0},

                {0, 0, 1},
                {0, 2, 1},
                {2, 0, 1},
                {2, 2, 1},

                {0, 0, 2},
                {1, 0, 2},
                {2, 0, 2},
                {0, 1, 2},
                {2, 1, 2},
                {0, 2, 2},
                {1, 2, 2},
                {2, 2, 2},
        for (int i = 0; i < 20; i++) {
            for (int j = 0; j < 3; j++)
                coords[i][j] *= level;
        return coords;