Topology constructions
These animations go with my solutions to the problem sheets of Topological Spaces (IGCE-UNESP, 2026.2), where I am the teaching assistant. Each one follows the construction used in the written solution, with the same notation and the same exercise numbers; the solutions themselves are in Portuguese.
Exercise 2.8: an interval and the line
Show that the subset \((a,b)\) of \(\mathbb{R}\) with the induced topology is homeomorphic to \(\mathbb{R}\).
An affine map \(\varphi\) takes \((a,b)\) onto \(\left(-\frac{\pi}{2},\frac{\pi}{2}\right)\), and the tangent stretches that interval over the whole line. The video also shows where the induced topology enters the argument.
| Time | Section |
|---|---|
| 0:07 | The plan: two homeomorphisms in a row |
| 0:22 | Step 1: the affine map \(\varphi\) and its inverse \(\psi\) |
| 0:48 | Continuity, with the induced topology |
| 1:13 | Step 2: the tangent |
| 1:37 | Step 3: the composition \(\tan\circ\varphi\) |
Exercise 2.11: stereographic projection
Prove that \(S^{n}\setminus\{(0,0,\dots,1)\}\) is homeomorphic to \(\mathbb{R}^{n}\) with the usual topology.
Every line through the north pole \(N\) that is not tangent to the sphere meets the sphere at one more point and the hyperplane \(H=\{x_{n+1}=0\}\) at exactly one point. Reading this in one direction gives \(\varphi\), in the other direction \(\psi\). The video derives both formulas from the lines through \(N\), then shows the cases \(n=1\) and \(n=2\).
| Time | Section |
|---|---|
| 0:07 | The setting |
| 0:20 | The construction: lines through \(N\) |
| 1:01 | The map \(\varphi\colon S^n\setminus\{N\}\to H\) |
| 1:24 | The map \(\psi\colon H\to S^n\setminus\{N\}\) |
| 1:47 | \(\varphi\) is a homeomorphism, with inverse \(\psi\) |
| 2:10 | The case \(n=1\): the circle and the line |
| 2:47 | The case \(n=2\): the sphere and the plane |
Exercise 2.17: the real projective line
Prove that \(\mathbb{R}P^{1}\) and \(S^{1}\) are homeomorphic.
The map \(h(u,v)=(u^2-v^2,\,2uv)\) doubles angles, so it sends \(x\) and \(-x\) to the same point and induces \(\bar h\colon\mathbb{R}P^1\to S^1\). The video checks that \(\bar h\) is a continuous and open bijection. The short “intuition” at the start (half a circle with its ends glued) is not part of the written solution.
| Time | Section |
|---|---|
| 0:07 | The space \(\mathbb{R}P^1\): pairs of antipodal points |
| 0:34 | The map \(h(u,v)=(u^2-v^2,\ 2uv)\) |
| 0:56 | \(h(x)=h(y)\) exactly when \(y=\pm x\) |
| 1:19 | \(h\) is an open map |
| 1:41 | The induced map \(\bar h\colon\mathbb{R}P^1\to S^1\) |
Exercise 2.19: gluing the ends of a segment
Let \(I=[0,1]\subset\mathbb{R}\) and \(\sim\) the equivalence relation on \(I\): \(x\sim x'\) if and only if \(\{x,x'\}=\{0,1\}\) or \(x=x'\). Show that \(I/\!\sim\) is homeomorphic to \(S^{1}\).
The map \(g(t)=e(2\pi t)\) induces a continuous bijection \(\bar g\colon I/\!\sim\ \to S^1\). The delicate point is openness: \(g\) itself is not open, but \(\bar g\) is, because an open set of \(I/\!\sim\) containing the class of \(0\) comes from a set containing both ends of the segment.
| Time | Section |
|---|---|
| 0:07 | The intuition: bend the segment and glue its ends |
| 0:24 | The map \(g\) and the induced map \(\bar g\) |
| 0:45 | \(g\) is not an open map |
| 1:00 | \(\bar g\) is an open map |
Exercise 2.23: the punctured plane
Prove that \(\mathbb{R}^{2}\setminus\{0\}\) is homeomorphic to \(\mathbb{R}\times S^{1}\).
With \(A=(0,+\infty)\), the maps \(\varphi(r,z)=rz\) and \(\psi(v)=\bigl(\|v\|,\,v/\|v\|\bigr)\) are inverse homeomorphisms between \(A\times S^1\) and the punctured plane; in the picture, circles around the origin become horizontal circles of a cylinder and rays become its vertical lines. Then \(\exp\colon\mathbb{R}\to A\) replaces \(A\) by \(\mathbb{R}\).
| Time | Section |
|---|---|
| 0:07 | Polar coordinates, without angles |
| 0:29 | Circles and rays: the plane becomes the cylinder \(A\times S^1\) |
| 1:04 | Why \(\varphi\) and \(\psi\) are continuous |
| 1:34 | From \(A=(0,+\infty)\) to \(\mathbb{R}\): the exponential |
Made with Manim Community v0.22. The excerpts below are the key parts of the code, each followed by a short explanation.
How the code works
1. Stereographic projection: one line through \(N\)
def ray_from_N(ang, color=C_MAP, width=3, length=20, box=BOX):
1 v = P(math.cos(ang), math.sin(ang))
2 seg = clip_seg(NN, NN + length * v, box)
return Line(seg[0], seg[1], color=color, stroke_width=width)
def phi1(u, w):
"""phi for n = 1, in sphere units."""
3 return u / (1 - w)
def psi1(y):
d = y * y + 1
4 return 2 * y / d, (y * y - 1) / d- 1
- The direction \(v\) of a line through \(N\), here a unit vector.
- 2
-
clip_segkeeps only the part of the line inside the box of the figure, so that no line ever runs over the text on the right. - 3
- For \(n=1\), \(\varphi(x)=\bar x/(1-x_{n+1})\) with \(x=(u,w)\).
- 4
- For \(n=1\), \(\psi(y)=\bigl(2y,\ y^2-1\bigr)/(y^2+1)\).
2. Bending a segment into a circle (Exercise 2.19)
- 1
- An arc of length \(L\) that turns through the angle \(k\) has radius \(L/k\); its centre is above the midpoint of the segment.
- 2
- The parameter \(s\in[0,1]\) becomes an angle in \([-k/2,\,k/2]\), measured from the lowest point of the arc.
- 3
- When \(k\) is close to \(0\) this is (almost) the straight segment; animating \(k\) from \(0\) to \(2\pi\) bends it until \(s=0\) and \(s=1\) meet.
- 4
- A last rotation moves the glued point to \((1,0)\), where \(g(0)=g(1)=e(0)\) lies.
3. From the plane to the cylinder in two moves (Exercise 2.23)
- 1
-
One number,
lam, goes from \(0\) to \(2\) and drives both moves:k1runs the first andk2the second. Every circle and ray of the picture is redrawn from it at each frame. - 2
-
The radius: \(r=\|v\|\) while
k2is \(0\), the radiusRCof the cylinder whenk2is \(1\). This is the second move, replacing \(v\) by \(v/\|v\|\). - 3
-
The height: \(0\) while
k1is \(0\), an increasing affine function of \(r=\|v\|\) whenk1is \(1\). This is the first move, which turns the plane into a cone.
4. Labels that never touch a line
Every label that moves with a point (\(x\), \(\varphi(x)\), \(\psi(y)\), …) is placed again at each frame by a small function:
def place(m, anchor, obstacles=(), prefs=(UR, UL, DR, DL, RIGHT, LEFT, UP, DOWN),
buffs=(0.1, 0.17, 0.25, 0.35, 0.47, 0.6), pad=0.05, labels=(), frame=None):
"""Put label m next to the point `anchor`, at the first spot (preferred directions first, closest
first) where its box touches no sampled point of `obstacles` and no box of `labels`."""
pts = obstacles if isinstance(obstacles, np.ndarray) else sample_points(*obstacles)
lbl_boxes = [bbox(l, 0.02) for l in labels]
anchor = np.array(anchor, dtype=float)
1 for b in buffs:
for d in prefs:
m.next_to(anchor, d, buff=b)
l, r, bt, t = bbox(m, pad)
if frame is not None and (l < frame[0] or r > frame[1] or bt < frame[2] or t > frame[3]):
continue
2 if len(pts) and ((pts[:, 0] > l) & (pts[:, 0] < r) & (pts[:, 1] > bt) & (pts[:, 1] < t)).any():
continue
3 if any(boxes_meet((l, r, bt, t), q) for q in lbl_boxes):
continue
4 return m
m.next_to(anchor, prefs[0], buff=buffs[0])
return m- 1
- Positions close to the point are tried first, in the preferred directions.
- 2
- The label’s box must contain none of the points sampled densely along the curves and lines of the figure…
- 3
- …and must not meet the labels already placed.
- 4
- The first free position wins.
Rendering with TC_CHECK=1 runs a similar test after every animation and lists any label that touches a line, a dot or another label, or that leaves the screen.