.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/topology/curves/plot_02_hopf_umlaufsatz.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_topology_curves_plot_02_hopf_umlaufsatz.py: Hopf's Umlaufsatz: the turning number of a closed curve (1935) ============================================================== As you walk once around a closed plane curve, your heading turns by a whole number of full turns. Hopf proved that for every *simple* closed curve that number is :math:`\pm 1`. Curves that cross themselves can have any turning number: 0 for a figure eight, 2 for a limaçon with an inner loop, 4 for a circle carrying three small inner loops. .. GENERATED FROM PYTHON SOURCE LINES 13-42 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from mathematicskit.topology import turning_number t = np.linspace(0, 2 * np.pi, 800, endpoint=False) rng = np.random.default_rng(3) radius = 1 + sum(rng.normal(0, 0.12) * np.cos(k * t + rng.uniform(0, 6)) for k in range(2, 7)) curves = { "ellipse": np.column_stack([2 * np.cos(t), np.sin(t)]), "random blob": radius[:, None] * np.column_stack([np.cos(t), np.sin(t)]), "blob, clockwise": (radius[:, None] * np.column_stack([np.cos(t), np.sin(t)]))[::-1], "figure eight": np.column_stack([np.sin(t), np.sin(2 * t)]), "limaçon": (0.5 + np.cos(t))[:, None] * np.column_stack([np.cos(t), np.sin(t)]), "three inner loops": np.column_stack([np.cos(t) + 0.6 * np.cos(4 * t), np.sin(t) + 0.6 * np.sin(4 * t)]), } fig, axes = plt.subplots(2, 3, figsize=(11, 7)) for ax, (name, c) in zip(axes.ravel(), curves.items(), strict=True): ax.plot(*np.vstack([c, c[:1]]).T, lw=1.5) # arrows show the direction of travel for i in range(0, len(c), len(c) // 6): d = c[(i + 3) % len(c)] - c[i] ax.annotate("", c[i] + d, c[i], arrowprops={"arrowstyle": "->", "color": "tab:red"}) ax.set_title(f"{name}\nturning number {turning_number(c)}") ax.set_aspect("equal") ax.axis("off") fig.suptitle("Hopf (1935): a simple closed curve turns exactly once") .. image-sg:: /api/gallery/topology/curves/images/sphx_glr_plot_02_hopf_umlaufsatz_001.png :alt: Hopf (1935): a simple closed curve turns exactly once, ellipse turning number 1, random blob turning number 1, blob, clockwise turning number -1, figure eight turning number 0, limaçon turning number 2, three inner loops turning number 4 :srcset: /api/gallery/topology/curves/images/sphx_glr_plot_02_hopf_umlaufsatz_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(0.5, 0.98, 'Hopf (1935): a simple closed curve turns exactly once') .. GENERATED FROM PYTHON SOURCE LINES 43-47 The tangent angle along the curve --------------------------------- The unwrapped heading rises by :math:`2\pi` per turn. .. GENERATED FROM PYTHON SOURCE LINES 47-56 .. code-block:: Python fig, ax = plt.subplots(figsize=(8, 4)) for name in ("random blob", "figure eight", "limaçon", "three inner loops"): c = curves[name] d = np.roll(c, -1, axis=0) - c ax.plot(t, np.unwrap(np.arctan2(d[:, 1], d[:, 0])) / (2 * np.pi), label=name) ax.set_xlabel("parameter") ax.set_ylabel("heading / $2\\pi$") ax.legend() .. image-sg:: /api/gallery/topology/curves/images/sphx_glr_plot_02_hopf_umlaufsatz_002.png :alt: plot 02 hopf umlaufsatz :srcset: /api/gallery/topology/curves/images/sphx_glr_plot_02_hopf_umlaufsatz_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.091 seconds) .. _sphx_glr_download_api_gallery_topology_curves_plot_02_hopf_umlaufsatz.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../../../lite/lab/index.html?path=api/gallery/topology/curves/plot_02_hopf_umlaufsatz.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_02_hopf_umlaufsatz.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_02_hopf_umlaufsatz.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_02_hopf_umlaufsatz.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_