Last updated: 2026-09-27
Sweeping Shapes: Discs, Cones, and Tori from a Rotor
12.1 A Shape Times a Circle FoundationalKnowledge that endures for decades — core principles
Chapter 9 gave us blades to describe shapes and rotors to move them. A rotor moves a shape through an angle. Let that angle run through a full turn and the shape leaves a trail, which is a new shape one dimension higher. Sweep a line segment about an axis and the trail is a disc. Sweep a circle about an axis, keeping it clear of the axis, and the trail is a torus.
This chapter turns that observation into a recipe. One rotor and a handful of generating shapes produce the disc, the cylinder, the cone, the hyperboloid, the sphere and the torus. We write the result as shape × circle. The × means sweep, and the geometric product does its work inside the rotor. The name is ours. The surfaces are the classical surfaces of revolution, and the rotor form of the sweep is the outer-morphism rule of §10.6 applied across a range of angles[1][2]. cf. planar rotors for arcs
12.2 The Sweep Recipe FoundationalKnowledge that endures for decades — core principles
Three choices define a sweep.
-
1
Pick a generator \(X\): a point, a segment, a line or a circle. Anything a rotor can act on will do, and by §10.6 that includes every grade.
-
2
Pick a plane of rotation, a unit bivector \(B\). Its dual is the axis. For a turn about \(z\) we use \(B=\mathbf{e}_{12}\).
-
3
Sweep. Build the rotor \(R(\theta)=\cos\tfrac{\theta}{2}-\sin\tfrac{\theta}{2}\,B\) and let the angle run: \(S(\theta)=R(\theta)\,X\,\widetilde{R}(\theta)\) for \(0\le\theta<2\pi\). The union of all the copies is the swept shape.
Each point of the generator that is off the axis traces a circle, so a generator of dimension \(k\) sweeps out a shape of dimension \(k+1\). Points on the axis stay where they are.
What the sandwich leaves alone. A turn about \(z\) changes a point's angle around the axis and nothing else. Its height \(z\) and its distance from the axis \(\rho=\sqrt{x^2+y^2}\) both survive. So whatever relation between \(\rho\) and \(z\) holds along the generator holds over the whole swept surface. Writing that relation down gives the implicit equation of the surface almost for free, and it gives us a test for every construction below.cylindrical coords: rho and z define the surface profile
| Generator | Swept about \(z\) | Result |
|---|---|---|
| A point off the axis | full turn | a circle |
| A segment from the axis, perpendicular to it | full turn | a disc (an annulus if it starts away from the axis) |
| A line through the axis, perpendicular to it | half turn | a plane |
| A segment parallel to the axis | full turn | a cylinder |
| A segment through the axis, tilted | full turn | a cone |
| A line that neither meets nor is parallel to the axis | full turn | a hyperboloid of one sheet |
| A circle centred on the axis, in a plane that contains it | half turn | a sphere |
| A circle in a plane that contains the axis, clear of it | full turn | a torus |
12.3 A Disc: Line × Circle FoundationalKnowledge that endures for decades — core principles
Start with the simplest sweep. The generator is the segment \(u\,\mathbf{e}_1\) for \(0\le u\le\rho\), and the plane of rotation is \(\mathbf{e}_{12}\).
-
1
A single point of the segment: \(u\,\mathbf{e}_1\). Section 10.6 already computed the sandwich on \(\mathbf{e}_1\): \(R(\theta)\,\mathbf{e}_1\,\widetilde{R}(\theta)=\cos\theta\,\mathbf{e}_1+\sin\theta\,\mathbf{e}_2\).
-
2
Scale by \(u\). The swept point is \(S(u,\theta)=u\,(\cos\theta\,\mathbf{e}_1+\sin\theta\,\mathbf{e}_2)\).
-
3
Read off the shape. Every point has \(z=0\) and \(\rho=u\le\rho_{\max}\), so the sweep fills the disc \(x^2+y^2\le\rho_{\max}^2\) in the plane \(z=0\).
-
4
Check the area. The ring at radius \(u\) has circumference \(2\pi u\), so the area is \(\int_0^{\rho}2\pi u\,du=\pi\rho^2\). The factor \(u\) is why the copies in Fig. 12.1 crowd toward the centre.
Start the segment at \(u_0>0\) and the same sweep gives an annulus of area \(\pi(\rho^2-u_0^2)\). Let \(u\) range over the whole line through the axis and a half turn is enough to cover the plane. half a turn is enough: the line runs both ways
12.4 One Rotor, Three Lines FoundationalKnowledge that endures for decades — core principles
Keep the rotor and change the generator. Three straight lines give three different surfaces, and the tip in 12.2 turns each into a one-line derivation.
| Surface | Generator | \(\rho\) against \(z\) on the generator | Implicit equation |
|---|---|---|---|
| Cylinder | \(a\,\mathbf{e}_1+t\,\mathbf{e}_3\) | \(\rho=a\) | \(x^2+y^2=a^2\) |
| Cone | \(t\,(\sin\alpha\,\mathbf{e}_1+\cos\alpha\,\mathbf{e}_3)\) | \(\rho=z\tan\alpha\) | \(x^2+y^2=z^2\tan^2\alpha\) |
| Hyperboloid | \(a\,\mathbf{e}_1+t\,(\sin\gamma\,\mathbf{e}_2+\cos\gamma\,\mathbf{e}_3)\) | \(\rho^2=a^2+z^2\tan^2\gamma\) | \(x^2+y^2=a^2+z^2\tan^2\gamma\) |
The hyperboloid row is the least obvious, so we work it through. The generator point at parameter \(t\) is \((a,\ t\sin\gamma,\ t\cos\gamma)\). Its height is \(z=t\cos\gamma\) and its squared distance from the axis is \(\rho^2=a^2+t^2\sin^2\gamma\). Substituting \(t=z/\cos\gamma\) gives \(\rho^2=a^2+z^2\tan^2\gamma\). The waist, where \(z=0\), has radius \(a\).
The hyperboloid curves, and it is built entirely from straight lines: every copy of the generator lies on the surface. A skew line gives a doubly curved surface with no bending in it.
12.5 A Torus: Circle × Circle FoundationalKnowledge that endures for decades — core principles
Now sweep a circle. The torus needs two rotors, one for each circle, and the order in which they act matters. The small circle is built first, and the sweep then acts on it.
-
1
The small circle. Take the point \(r\,\mathbf{e}_1\) and turn it by an angle \(\varphi\) in the \(\mathbf{e}_{13}\) plane, with \(R_\varphi=\cos\tfrac{\varphi}{2}-\sin\tfrac{\varphi}{2}\,\mathbf{e}_{13}\). By the same calculation as 12.3 with the index 2 replaced by 3, this sends \(\mathbf{e}_1\) to \(\cos\varphi\,\mathbf{e}_1+\sin\varphi\,\mathbf{e}_3\). The circle's centre sits at distance \(R\) from the \(z\) axis, so we shift by \(R\,\mathbf{e}_1\): \[ q(\varphi)=R\,\mathbf{e}_1+R_\varphi\,(r\,\mathbf{e}_1)\,\widetilde{R}_\varphi=(R+r\cos\varphi)\,\mathbf{e}_1+r\sin\varphi\,\mathbf{e}_3. \] The shift is plain vector addition in this algebra. It is the offset-axis rotation of §11.7, where PGA writes the same thing as a translator sandwich around the rotor.
-
2
The sweep. Turn the whole small circle about \(z\) with \(R_\theta=\cos\tfrac{\theta}{2}-\sin\tfrac{\theta}{2}\,\mathbf{e}_{12}\): \[ T(\theta,\varphi)=R_\theta\,q(\varphi)\,\widetilde{R}_\theta=\big((R+r\cos\varphi)\cos\theta,\ (R+r\cos\varphi)\sin\theta,\ r\sin\varphi\big). \] Rotors act from the inside out, so \(R_\varphi\) acts first and \(R_\theta\) second.
-
3
Check it. On the surface, \(\rho=R+r\cos\varphi\) and \(z=r\sin\varphi\), so \((\rho-R)^2+z^2=r^2\). That is a circle of radius \(r\) in the \((\rho,z)\) half-plane, which is the tip of 12.2 at work. The implicit equation is \[ \big(\sqrt{x^2+y^2}-R\big)^2+z^2=r^2. \]
-
4
Measure it. The area element is \(r\,(R+r\cos\varphi)\,d\varphi\,d\theta\). Integrating over both full turns gives the surface area \(4\pi^2Rr\). The enclosed volume is \(2\pi^2Rr^2\): the small disc's area \(\pi r^2\) times the length \(2\pi R\) of the path its centre travels (Pappus's centroid theorem).
The same formula covers three shapes. With \(r<R\) we get the familiar ring torus. At \(r=R\) the hole closes to a point on the axis (a horn torus), and for \(r>R\) the surface crosses itself (a spindle torus). Each point of the surface has two angles, \(\theta\) and \(\varphi\), and the two circles are independent of each other, which is why the torus is the product of two circles in the topologist's sense as well.
12.6 A Sphere from a Half Turn FoundationalKnowledge that endures for decades — core principles
Sweep the circle of radius \(\rho\) centred at the origin in the \(\mathbf{e}_{13}\) plane, \((\rho\sin\varphi,\ 0,\ \rho\cos\varphi)\), about \(z\). The sweep gives \((\rho\sin\varphi\cos\theta,\ \rho\sin\varphi\sin\theta,\ \rho\cos\varphi)\), which satisfies \(x^2+y^2+z^2=\rho^2\).
A full turn covers the sphere twice, because the circle is symmetric about the axis: the point at \((\varphi,\theta)\) and the point at \((2\pi-\varphi,\ \theta+\pi)\) coincide. A half turn, \(0\le\theta<\pi\), covers it exactly once. Sweeping a semicircle through a full turn gives the same sphere and the same area, \(4\pi\rho^2\).
Where the recipe stops. A sweep about one axis makes surfaces with rotational symmetry about it. A general three-axis ellipsoid needs a scaling, which no rotor provides. A helicoid needs a screw motor that adds a translation to the rotation (§11.8). The recipe itself carries over: pick a generator, pick a one-parameter family of motions, and take the union.projective motors add translation to rotation
12.7 Try It: The Sweeps in ganja.js
The constructions above run as they stand in ganja.js[3] in its plain 3D Euclidean algebra. Press Run and the page fetches the library from the jsDelivr CDN and executes the code below in your browser. The source is editable in place: change \(R\), \(r\), or an angle and run it again.
ganja.js uses the same rotor as this chapter, \(\cos\tfrac{\theta}{2}-\sin\tfrac{\theta}{2}\,\mathbf{e}_{12}\), so no sign adjustments are needed. Literals such as 1e12 are algebraic blades, not numbers, because ganja.js rewrites the code inside the function you pass to Algebra.
// Sweeping shapes with rotors, in ganja.js (Euclidean 3D algebra).
Algebra(3, () => {
const v = (x, y, z) => x*1e1 + y*1e2 + z*1e3;
const xyz = P => [P.e1, P.e2, P.e3].map(c => +c.toFixed(4));
const deg = d => d * Math.PI / 180;
// exp(-theta B / 2) for a unit bivector B: the rotor of Chapter 9.
const rotor = (th, B) => Math.cos(th/2) - Math.sin(th/2)*B;
const apply = (R, X) => R * X * ~R; // the sandwich product
const spin = th => rotor(th, 1e12); // turn about the z axis
// 1. Disc: sweep the segment u e1 (0 <= u <= 2) about z.
console.log("rim, 90 deg:", xyz(apply(spin(deg(90)), v(2, 0, 0)))); // expect [0, 2, 0]
console.log("u = 1, 210 deg:", xyz(apply(spin(deg(210)), v(1, 0, 0)))); // expect [-0.866, -0.5, 0]
// Largest deviation from an implicit equation over a grid of (t, theta) samples.
const worst = (gen, implicit, ts) => {
let m = 0;
for (const t of ts) for (let k = 0; k < 12; k++) {
const P = apply(spin(deg(30 * k)), gen(t));
m = Math.max(m, Math.abs(implicit(P.e1, P.e2, P.e3)));
}
return +m.toExponential(2);
};
// 2. Cylinder, cone and hyperboloid: sweep three different lines about z.
const a = 1.5, alpha = 0.6, gamma = 0.7, ts = [-2, -1, 0, 1, 2];
console.log("cylinder:", worst(t => v(a, 0, t), (x, y, z) => Math.hypot(x, y) - a, ts));
console.log("cone:", worst(t => v(t*Math.sin(alpha), 0, t*Math.cos(alpha)), (x, y, z) => Math.hypot(x, y) - Math.abs(z)*Math.tan(alpha), ts));
console.log("hyperboloid:", worst(t => v(a, t*Math.sin(gamma), t*Math.cos(gamma)), (x, y, z) => x*x + y*y - a*a - z*z*Math.tan(gamma)**2, ts));
// 3. Torus: circle x circle. The small circle is a rotor orbit about the axis through (3,0,0) parallel to y;
// the big circle is the sweep about z.
const R = 3, r = 1;
const tube = ph => v(R, 0, 0) + apply(rotor(ph, 1e13), v(r, 0, 0));
const torus = (th, ph) => apply(spin(th), tube(ph));
console.log("theta 90, phi 0:", xyz(torus(deg(90), 0))); // expect [0, 4, 0]
console.log("theta 90, phi 90:", xyz(torus(deg(90), deg(90)))); // expect [0, 3, 1]
let m = 0;
for (let i = 0; i < 12; i++) for (let j = 0; j < 12; j++) {
const P = torus(deg(30*i), deg(30*j));
m = Math.max(m, Math.abs((Math.hypot(P.e1, P.e2) - R)**2 + P.e3**2 - r*r));
}
console.log("torus:", +m.toExponential(2)); // ~1e-6 (32-bit floats)
});
The output should show the rim point at 90° landing on \((0,2,0)\) and the halfway point at 210° on \((-0.866,-0.5,0)\). The torus points at \(\theta=90^\circ\) should be \((0,4,0)\) for \(\varphi=0\) and \((0,3,1)\) for \(\varphi=90^\circ\). The four residuals report the largest deviation from each implicit equation over a grid of sample points. They come out near \(10^{-7}\) and not exactly zero, because ganja.js stores coefficients in 32-bit floats.
12.8 Testing a Sweep Applied / MethodologicalKnowledge with a 5–10 year half-life — stable practice
A sweep gives us three checks that need no reference implementation. They suit the habits of the testing chapter.
- Invariants. Every swept point keeps its generator point's height and distance from the axis. Assert both for a grid of angles.
- Implicit residual. Substitute swept points into the surface's equation. Any residual larger than the arithmetic's rounding error points to a wrong rotor, a wrong plane, or a wrong order of rotors.
- Area and volume. Sum the area element over a grid and compare with the closed form.
The Python below runs the residual and area checks for the torus, using rotation matrices for the same rotations the rotors perform. With \(R=3\), \(r=1\) and an 800 by 800 midpoint grid, the numerical area agrees with \(4\pi^2Rr=118.4353\) to about nine digits.
import numpy as np
R, r, n = 3.0, 1.0, 800
mid = lambda k: (np.arange(k) + 0.5) * 2 * np.pi / k
ph, th = np.meshgrid(mid(n), mid(n), indexing="ij")
def torus(ph, th):
rho = R + r * np.cos(ph) # small circle: (R + r cos phi, r sin phi)
return np.array([rho * np.cos(th), # sweep about z by theta
rho * np.sin(th),
r * np.sin(ph) + 0 * th])
P = torus(ph, th)
residual = (np.hypot(P[0], P[1]) - R) ** 2 + P[2] ** 2 - r ** 2
print("max residual:", np.abs(residual).max()) # ~1e-15
h = 1e-6 # tangent vectors by central differences
d_ph = (torus(ph + h, th) - torus(ph - h, th)) / (2 * h)
d_th = (torus(ph, th + h) - torus(ph, th - h)) / (2 * h)
area = np.linalg.norm(np.cross(d_ph, d_th, axis=0), axis=0).sum() * (2 * np.pi / n) ** 2
print("area:", area, " expected:", 4 * np.pi ** 2 * R * r)
12.9 Key Terms
- Generator. The shape that is swept: a point, segment, line or circle.
- Sweep. The union of the copies \(R(\theta)\,X\,\widetilde{R}(\theta)\) as \(\theta\) runs through a range of angles. The number of dimensions goes up by one.
- Surface of revolution. A surface swept by rotating a curve about an axis. Height and distance from the axis are preserved by the rotation.
- Ruled surface. A surface made of straight lines. The cylinder, the cone and the hyperboloid of one sheet are all ruled.
- Ring, horn and spindle torus. The three cases \(r<R\), \(r=R\) and \(r>R\) of one formula.
- Pappus's centroid theorem. The volume of a solid of revolution is the area of the generating region times the distance its centroid travels, for a region that does not cross the axis.
Related Topics
- Vectors, Quaternions, and Blades: Why Geometric Algebra Subsumes Both — the rotor \(\cos\tfrac{\theta}{2}-\sin\tfrac{\theta}{2}B\) that every sweep here is built on.
- Building Shapes from Blades — the flat primitives (points, lines, planes) and the rule that a rotor acts on every grade, which lets us sweep any generator.
- Projective Geometric Algebra: Points, Planes, and Motors for Graphics — offset-axis rotations and screw motors, which change the generator's motion and so the family of surfaces.
- CGA Worked Examples: Interval Arithmetic in Conformal Space — where circles and spheres are blades in their own right and the sweeps of this chapter can be written without coordinates.
- Testing and Validation — the habits behind the checks in 12.8.
References
- (2007). Geometric Algebra for Computer Science. Morgan Kaufmann.
- (1999). New Foundations for Classical Mechanics (2nd ed.). Kluwer Academic.
- ganja.js: Geometric algebra generator for JavaScript, C++, C#, Rust and Python. https://github.com/enkimute/ganja.js