Exact Symbolic Demonstrations (demos/)¶
All executable Python constructions for Albrecht Dürer’s Underweysung der Messung live
cleanly outside the historical codex in demos/ and src/geometor/durer/. Every
Model instance runs with auto_intersect=False and 100% exact
SymPy coordinates over $\mathbb{Q}$, $\mathbb{Q}(\sqrt{2})$, $\mathbb{Q}(\sqrt{3})$,
$\mathbb{Q}(\phi)$, and $\mathbb{Q}(\sqrt{5}, \sin 36^\circ)$.
1. Book I — Spirals & Two-View Conic Sections¶
Constructs Dürer’s 12-sector Archimedean spiral (Schneckenlini) over $\mathbb{Q}(\sqrt{3})$ and verifies his 12-station descriptive-geometry transfer law $w_k = \frac{\sqrt{2k(12 - k)}}{3}$ for the right circular cone, proving exact bilateral symmetry $w_{12-k} = w_k$ (Elipsis vs. Eierlini).
1"""Runnable demonstration of Book I Archimedean spirals & two-view orthographic conic sections."""
2
3from __future__ import annotations
4
5import sys
6from pathlib import Path
7
8ROOT = Path(__file__).resolve().parents[1]
9for p in (ROOT / "src", ROOT.parent / "model" / "src"):
10 if str(p) not in sys.path:
11 sys.path.insert(0, str(p))
12
13from rich.console import Console
14from rich.table import Table
15
16from geometor.durer import construct_durer_conic_sections, construct_durer_spiral_volute
17
18
19def main() -> None:
20 console = Console()
21 spiral = construct_durer_spiral_volute(turns=2)
22 conics = construct_durer_conic_sections()
23
24 console.print("[bold cyan]Book I — 12-Sector Archimedean Spiral & Two-View Conic Projection[/bold cyan]")
25 console.print(
26 f"Spiral sectors: {spiral.sector_count}, outer radius: {spiral.outer_radius}, "
27 f"constructed exact points in Q(sqrt(3)): {len(spiral.spiral_points)}"
28 )
29
30 tbl = Table(title="Book I, Fig. 34 — Orthographic Cone-Section Stations (Elipsis / Eierlini)")
31 tbl.add_column("Station k", justify="right")
32 tbl.add_column("Elevation x_k")
33 tbl.add_column("Height z_k")
34 tbl.add_column("Plan Radius r_k")
35 tbl.add_column("Exact Half-Width w_k", style="green")
36
37 for k, xk, zk, rk, wk in conics.ellipse_stations:
38 tbl.add_row(str(k), str(xk), str(zk), str(rk), str(wk))
39
40 console.print(tbl)
41 console.print(
42 f"Bilateral symmetry w_k == w_{{12-k}} verified: [bold green]{conics.ellipse_bilateral_symmetry_verified}[/bold green] | "
43 f"a = {conics.ellipse_semi_major}, b = {conics.ellipse_semi_minor}, "
44 f"c = {conics.ellipse_focal_distance}, e = {conics.ellipse_eccentricity}"
45 )
46 console.print(
47 f"Parabola focal length f = {conics.parabola_focal_length} | "
48 f"Hyperbola (a_h, b_h) = ({conics.hyperbola_semi_transverse}, {conics.hyperbola_semi_conjugate})"
49 )
50
51
52if __name__ == "__main__":
53 main()
2. Book II — Pentagon, Heptagon & Quadrature Audit¶
Constructs both Dürer’s single-aperture (“rusty compass”) pentagon and Euclid’s $\mathbb{Q}(\phi)$ regular pentagon on shared base $AB$, proving exact unit side quadrances $Q = 1$ and quantifying the $+21.97'$ base-angle discrepancy, alongside the Eisenstein cubic residual $P_7\left(\frac{3}{4}\right) = -\frac{1}{64}$ for the workshop heptagon and $\pi_{\text{Dürer}} = \frac{25}{8}$.
1"""Runnable demonstration auditing Book II regular polygons (Dürer vs. Euclid) & circle quadrature."""
2
3from __future__ import annotations
4
5import sys
6from pathlib import Path
7
8ROOT = Path(__file__).resolve().parents[1]
9for p in (ROOT / "src", ROOT.parent / "model" / "src"):
10 if str(p) not in sys.path:
11 sys.path.insert(0, str(p))
12
13from rich.console import Console
14from rich.table import Table
15
16from geometor.durer import (
17 construct_durer_heptagon_workshop,
18 construct_durer_vs_euclid_pentagon,
19)
20
21
22def main() -> None:
23 console = Console()
24 pent = construct_durer_vs_euclid_pentagon()
25 hep = construct_durer_heptagon_workshop()
26
27 console.print("[bold cyan]Book II — Demonstrative vs. Mechanice Regular Polygons[/bold cyan]")
28 console.print(f"Euclid regular pentagon over Q(phi) verified: [green]{pent.euclid_regular}[/green]")
29 console.print(
30 f"Dürer single-aperture pentagon: equilateral=[green]{pent.durer_equilateral}[/green], "
31 f"equiangular=[yellow]{pent.durer_equiangular}[/yellow]"
32 )
33 console.print(
34 f"Dürer base interior angle = {pent.durer_base_interior_deg:.5f}° vs. 108.00000° "
35 f"(error = {pent.base_angle_error_deg:+.5f}° = {pent.base_angle_error_arcmin:+.2f}')"
36 )
37 console.print(
38 f"Heptagon minimal polynomial P_7(q) = {hep.minimal_polynomial_expr}; "
39 f"P_7(3/4) = [bold yellow]{hep.minimal_polynomial_at_durer}[/bold yellow] (Eisenstein p={hep.eisenstein_prime})"
40 )
41
42 tbl = Table(title="Book II Polygon & Quadrature Accuracy Audit")
43 tbl.add_column("n", justify="right")
44 tbl.add_column("Construction")
45 tbl.add_column("Type", style="magenta")
46 tbl.add_column("Exact s/R")
47 tbl.add_column("Rel. Chord Error", justify="right")
48 tbl.add_column("Step Angle", justify="right")
49
50 for row in hep.workshop_catalog:
51 tbl.add_row(
52 str(row.n_sides),
53 row.durer_label,
54 row.classification,
55 str(row.exact_chord_over_r),
56 f"{row.relative_chord_error * 100:+.4f}%",
57 f"{row.central_angle_durer_deg:.4f}° (true {row.central_angle_true_deg:.4f}°)",
58 )
59 console.print(tbl)
60 console.print(
61 f"Circle Quadrature (Fig. 34): d/a = {hep.quadrature_circle_diameter_over_side} "
62 f"=> pi_Durer = {hep.quadrature_implied_pi} = {float(hep.quadrature_implied_pi):.4f}"
63 )
64
65
66if __name__ == "__main__":
67 main()
3. Book III — Roman Antiqua Capitals & Modular Textura¶
Constructs Roman capitals A, O, and Q inside the $10 \times 10$ square (rechte
Fierung) with $1 : \frac{1}{3}$ stroke contrast, circular serif fillets ($r = \frac{10}{7}, \frac{1}{2}$),
and shifted-diagonal bowls ($r = 5 - \frac{\sqrt{2}}{4}$), paired with modular Gothic Textura
minuscules i, n, m.
1"""Runnable demonstration of Book III Roman Antiqua capitals (A, O, Q) & Gothic Textura minuscules."""
2
3from __future__ import annotations
4
5import sys
6from pathlib import Path
7
8ROOT = Path(__file__).resolve().parents[1]
9for p in (ROOT / "src", ROOT.parent / "model" / "src"):
10 if str(p) not in sys.path:
11 sys.path.insert(0, str(p))
12
13from rich.console import Console
14from rich.table import Table
15
16from geometor.durer import (
17 construct_durer_roman_letter_A,
18 construct_durer_roman_letter_O,
19 construct_durer_roman_letter_Q,
20 construct_durer_textura_minuscules,
21)
22
23
24def main() -> None:
25 console = Console()
26 let_a = construct_durer_roman_letter_A()
27 let_o = construct_durer_roman_letter_O()
28 let_q = construct_durer_roman_letter_Q()
29 tex = construct_durer_textura_minuscules()
30
31 tbl = Table(title="Book III — Geometric Typography (Antiqua & Textura)")
32 tbl.add_column("Glyph", style="cyan")
33 tbl.add_column("Framing Grid")
34 tbl.add_column("Exact Algebraic Parameters", style="green")
35
36 tbl.add_row(
37 "Roman A",
38 "10 x 10 Square",
39 f"thick={let_a.thick_stroke}, thin={let_a.thin_stroke}, "
40 f"outer serif r={let_a.outer_serif_radius}, inner serif r={let_a.inner_serif_radius}, "
41 f"counter apex=({let_a.counter_triangle[2].x}, {let_a.counter_triangle[2].y})",
42 )
43 tbl.add_row(
44 "Roman O",
45 "10 x 10 Square (cb diagonal)",
46 f"centers f=({let_o.shifted_center_f.x}, {let_o.shifted_center_f.y}), "
47 f"g=({let_o.shifted_center_g.x}, {let_o.shifted_center_g.y}), r={let_o.bowl_radius}",
48 )
49 tbl.add_row(
50 "Roman Q",
51 "10 x 10 Square + ad tail",
52 f"bowl r={let_q.bowl_radius}, tail tip=({let_q.tail_points[-1].x}, {let_q.tail_points[-1].y})",
53 )
54 tbl.add_row(
55 "Textura i, n, m",
56 "3 Unit Squares + 45° Diamonds",
57 f"stem width={tex.stem_width}, modules: i={len(tex.glyph_polygons['i'])}, "
58 f"n={len(tex.glyph_polygons['n'])}, m={len(tex.glyph_polygons['m'])}",
59 )
60 console.print(tbl)
61
62
63if __name__ == "__main__":
64 main()
4. Book IV — Planar Polyhedral Nets & Perspective Apparatus¶
Unfolds exact non-overlapping planar nets for the Tetrahedron, Cube, Octahedron, Dodecahedron
(double 6-pentagon rosette), Icosahedron, and Archimedean Cuboctahedron, projects a 3D cube in
$\mathbb{Q}^3$ onto Dürer’s glass picture plane verifying harmonic cross-ratio invariance
$\operatorname{CR}(A', E'; M', V_x) = -1$, and generates all 11 .euclid-graphic SVG plates.
1"""Runnable demonstration of Book IV planar polyhedral nets, perspective glass frame & cube doubling."""
2
3from __future__ import annotations
4
5import sys
6from pathlib import Path
7
8ROOT = Path(__file__).resolve().parents[1]
9for p in (ROOT / "src", ROOT.parent / "model" / "src"):
10 if str(p) not in sys.path:
11 sys.path.insert(0, str(p))
12
13from rich.console import Console
14from rich.table import Table
15
16from geometor.durer import (
17 construct_durer_perspective_apparatus,
18 construct_durer_polyhedral_nets,
19 generate_all_codex_figures,
20)
21
22
23def main() -> None:
24 console = Console()
25 nets = construct_durer_polyhedral_nets()
26 persp = construct_durer_perspective_apparatus()
27
28 tbl = Table(title="Book IV — Exact Planar Polyhedral Fold-Out Nets")
29 tbl.add_column("Net", style="cyan")
30 tbl.add_column("Field", style="magenta")
31 tbl.add_column("V, E, F (chi)")
32 tbl.add_column("Folds / Cuts")
33 tbl.add_column("Unit Q=1", style="green")
34 tbl.add_column("Disjoint", style="green")
35
36 for net in nets.values():
37 tbl.add_row(
38 net.title,
39 net.algebraic_field,
40 f"({net.vertices_3d}, {net.edges_3d}, {net.faces_3d}) -> {net.euler_characteristic}",
41 f"{len(net.fold_edges)} / {len(net.cut_edges)}",
42 str(net.unit_edge_verified),
43 str(net.non_overlapping_verified),
44 )
45 console.print(tbl)
46
47 console.print(
48 f"Perspective Apparatus: Eye={persp.eye_3d} -> Vanishing Point V_x="
49 f"({persp.vanishing_point.x}, {persp.vanishing_point.y}), "
50 f"Harmonic Cross-Ratio CR={persp.harmonic_cross_ratio_2d} "
51 f"(verified={persp.cross_ratio_invariant_verified})"
52 )
53 console.print(
54 f"Delian Doubling of the Cube (Fig. 50): g={persp.delian_cube.given_g}, "
55 f"c={persp.delian_cube.first_mean_c}, d={persp.delian_cube.second_mean_d}, "
56 f"e={persp.delian_cube.given_e} => c^3/g^3 = {persp.delian_cube.volume_ratio}"
57 )
58
59 figs_dir = ROOT / "docsrc" / "_static" / "figures"
60 paths = generate_all_codex_figures(figs_dir)
61 console.print(f"[bold green]Generated {len(paths)} .euclid-graphic SVG figures in {figs_dir}[/bold green]")
62
63
64if __name__ == "__main__":
65 main()