modules

geometor.petersen

GEOMETOR • petersen: Digital Scriptorium Codex & Exact Constructive Pattern Library.

Scholarly 3-track edition (English 1879 · Summary · Notes) and 100% exact symbolic geometor.model constructions for Julius Petersen’s Methods and Theories for the Solution of Problems of Geometrical Constructions, Applied to 410 Problems (Copenhagen, 1866; Authorized English Edition translated by Sophus Haagensen, 1879).

Submodules

Attributes

__version__

ALL_CONSTRUCTIONS

export_euclid_svg

render_euclid_svg

UNIT_SPECS

Classes

ConcordanceEntry

Single cross-repository concordance entry linking Petersen to the GEOMETOR canon.

PetersenApparatus

Loaded scholarly apparatus and concordance tables for Methods and Theories.

UnitSpec

Metadata specification for one 3-track Book Codex unit.

Functions

build_codex([repo_root, export_figures]) → list[pathlib.Path]

Compile all 3-track Book Codex RST files, root apparatus mirrors, and SVG figures.

export_all_figures([repo_root]) → list[pathlib.Path]

Build all 8 exact symbolic models and export calibrated .euclid-graphic SVGs.

apparatus_slug(key) → str

Convert an apparatus key (e.g. 'euclid:elements') to a safe RST anchor slug.

load_apparatus([repo_root]) → PetersenApparatus

Load and validate all JSON apparatus files from resources/methods_and_theories/.

apollonius_two_loci([model, A, B, ratio, altitude]) → tuple[geometor.model.Model, dict[str, Any]]

Find points P with PA : PB = m : n at given distance h from line AB.

discussion_mean_proportional([model, hypotenuse, altitude]) → tuple[geometor.model.Model, dict[str, Any]]

Construct right triangles on hypotenuse BC = a with given altitude h_a (Loci e & b).

equal_chords_line_locus([model, O, outer_radius, ...]) → tuple[geometor.model.Model, dict[str, Any]]

Through external point P draw lines intercepting a chord of length L in circle (O, R).

equilateral_on_three_parallels([model, y1, y2, y3, x0]) → tuple[geometor.model.Model, dict[str, Any]]

Place an equilateral triangle PQR with vertices on three parallel lines L1, L2, L3.

hero_reflection_shortest_path([model, A, B, axis_pts]) → tuple[geometor.model.Model, dict[str, Any]]

Find X on a given line so AX and BX make equal angles with the line (Prob. 338).

inscribe_square_by_homothety([model, A, B, C]) → tuple[geometor.model.Model, dict[str, Any]]

Inscribe a square DEFG resting on base AB of ABC via homothety from A.

tangent_circle_by_inversion([model, O, M1, M2, M3, ...]) → tuple[geometor.model.Model, dict[str, Any]]

Construct a circle touching three circles K1, K2, K3 concurrent at O via inversion.

trapezoid_from_four_sides([model, a, b, c, d]) → tuple[geometor.model.Model, dict[str, Any]]

Construct trapezoid ABCD (AB || DC, AB=a, CD=b, BC=c, DA=d) via translation.

export_svg(model, output_path, *[, graphic_id, title, ...]) → pathlib.Path

Write a .euclid-graphic SVG rendering of model to output_path.

render_svg_string(model, *[, graphic_id, title, ...]) → str

Render model as a theme-adaptive .euclid-graphic SVG string.

Package Contents

geometor.petersen.__version__ = '0.1.0'
geometor.petersen.build_codex(repo_root: pathlib.Path | None = None, *, export_figures: bool = True) → list[pathlib.Path]

Compile all 3-track Book Codex RST files, root apparatus mirrors, and SVG figures.

geometor.petersen.export_all_figures(repo_root: pathlib.Path | None = None) → list[pathlib.Path]

Build all 8 exact symbolic models and export calibrated .euclid-graphic SVGs.

class geometor.petersen.ConcordanceEntry

Single cross-repository concordance entry linking Petersen to the GEOMETOR canon.

id: str
unit: str
petersen_locus: str
problems: tuple[str, ...]
title: str
summary: str
constructor: str | None
cross_refs: tuple[dict[str, str], ...]
class geometor.petersen.PetersenApparatus

Loaded scholarly apparatus and concordance tables for Methods and Theories.

sources_manifest: dict[str, Any]
entries: tuple[ConcordanceEntry, ...]
persons: dict[str, dict[str, Any]]
citations: dict[str, dict[str, Any]]
glossary: dict[str, dict[str, Any]]
property concordance: tuple[ConcordanceEntry, ...]

Alias returning all ConcordanceEntry records.

by_unit(unit_slug: str) → list[ConcordanceEntry]

Return concordance entries belonging to unit_slug.

geometor.petersen.apparatus_slug(key: str) → str

Convert an apparatus key (e.g. 'euclid:elements') to a safe RST anchor slug.

geometor.petersen.load_apparatus(repo_root: pathlib.Path | None = None) → PetersenApparatus

Load and validate all JSON apparatus files from resources/methods_and_theories/.

geometor.petersen.ALL_CONSTRUCTIONS: dict[str, collections.abc.Callable[..., tuple[geometor.model.Model, dict[str, Any]]]]
geometor.petersen.apollonius_two_loci(model: geometor.model.Model | None = None, A: tuple[Any, Any] | sympy.geometry.Point2D = (0, 0), B: tuple[Any, Any] | sympy.geometry.Point2D = (15, 0), ratio: tuple[int | sympy.Expr, int | sympy.Expr] = (2, 1), altitude: int | sympy.Expr = 8) → tuple[geometor.model.Model, dict[str, Any]]

Find points P with PA : PB = m : n at given distance h from line AB.

Combines Petersen’s Locus f (the Circle of Apollonius on harmonic diameter CC1 where CA:CB = C1A:C1B = m:n and (A, B; C, C1) = -1, pp. 11–12) with Locus b (parallel line at distance h from AB, p. 8) under the Method of Two Loci (p. 5).

Default A=(0,0), B=(15,0), m:n=2:1, h=8 yields internal/external harmonic points C=(10,0), C1=(30,0), Apollonius circle centered at M=(20,0) of radius 10, and exact integer intersections P1=(14,8) and P2=(26,8).

geometor.petersen.discussion_mean_proportional(model: geometor.model.Model | None = None, hypotenuse: int | sympy.Expr = 10, altitude: int | sympy.Expr = 4) → tuple[geometor.model.Model, dict[str, Any]]

Construct right triangles on hypotenuse BC = a with given altitude h_a (Loci e & b).

Illustrates Petersen’s canonical 4-part anatomy of a problem of construction (Analysis, Mode of Proceeding, Proof, Discussion, pp. 4–5) via Problem 42 (p. 15): Divide a given segment BC into two parts BD, DC having a given segment h as mean proportional. Intersecting the Thales circle on diameter BC (Locus e, 90°) with the parallel line at distance h (Locus b) yields:

  • 2 solutions A1, A2 when 0 < h < a/2 (default a=10, h=4 -> A1=(2,4), A2=(8,4)),

  • 1 tangent solution when h = a/2, and

  • 0 real solutions when h > a/2.

geometor.petersen.equal_chords_line_locus(model: geometor.model.Model | None = None, O: tuple[Any, Any] | sympy.geometry.Point2D = (0, 0), outer_radius: int | sympy.Expr = 17, chord_length: int | sympy.Expr = 16, P: tuple[Any, Any] | sympy.geometry.Point2D = (25, 0)) → tuple[geometor.model.Model, dict[str, Any]]

Through external point P draw lines intercepting a chord of length L in circle (O, R).

Following Petersen’s Loci of Lines (Locus l, p. 40 & Problem 220, p. 42), all straight lines cutting chords of length L from circle (O, R) lie at fixed distance \(r = \sqrt{R^2 - (L/2)^2}\) from O and therefore envelop the concentric circle (O, r). Drawing tangents from P to (O, r) (Problem 16 / Euclid III.17) solves the problem immediately.

Default triple-Pythagorean parameters R=17, L=16, P=(25,0) give concentric envelope radius r=15 (8^2 + 15^2 = 17^2), exact integer contact points T1=(9,12) and T2=(9,-12) (15^2 + 20^2 = 25^2), and exact rational chord endpoints on (O, 17).

geometor.petersen.equilateral_on_three_parallels(model: geometor.model.Model | None = None, y1: int | sympy.Expr = 0, y2: int | sympy.Expr = 1, y3: int | sympy.Expr = 3, x0: int | sympy.Expr = 0) → tuple[geometor.model.Model, dict[str, Any]]

Place an equilateral triangle PQR with vertices on three parallel lines L1, L2, L3.

Following Petersen’s Theory of Revolution (Ch. III, § 1–4 & Problem 349, pp. 65–67), choose P on L1 as the pivot point with angle of revolution v = 60° and ratio of revolution f = 1. Revolving L2 by +60° around P via two Euclidean I.1 equilateral subconstructions produces the rotated line L2', whose intersection with L3 determines R; revolving back (I.1 on PR) yields Q on L2 in \(\mathbb{Q}(\sqrt{3})\).

geometor.petersen.hero_reflection_shortest_path(model: geometor.model.Model | None = None, A: tuple[Any, Any] | sympy.geometry.Point2D = (2, 6), B: tuple[Any, Any] | sympy.geometry.Point2D = (14, 10), axis_pts: tuple[tuple[Any, Any], tuple[Any, Any]] = ((0, 0), (16, 0))) → tuple[geometor.model.Model, dict[str, Any]]

Find X on a given line so AX and BX make equal angles with the line (Prob. 338).

Following Petersen’s Revolution Around an Axis (p. 60–61, Problem 338), revolving A across the mirror axis into A1 straightens the reflected path into the single segment A1 X B. With default A=(2,6), B=(14,10) and axis y=0, A1=(2,-6), X=(13/2, 0), and Q(A1, B) = 12^2 + 16^2 = 400 = 20^2!

geometor.petersen.inscribe_square_by_homothety(model: geometor.model.Model | None = None, A: tuple[Any, Any] | sympy.geometry.Point2D = (0, 0), B: tuple[Any, Any] | sympy.geometry.Point2D = (14, 0), C: tuple[Any, Any] | sympy.geometry.Point2D = (5, 12)) → tuple[geometor.model.Model, dict[str, Any]]

Inscribe a square DEFG resting on base AB of ABC via homothety from A.

Following Petersen’s Method of Similitude (Case b, p. 28–29, Problem 155), relaxing the condition that the upper-right vertex lie on BC makes all candidate squares resting on AB with upper-left vertex on AC homothetic from centre of similitude A. Constructing the prototype square D0 E0 F0 C of side equal to altitude h_c and intersecting ray A F0 with BC yields F directly.

Default (15, 13, 14) Heronian triangle A=(0,0), B=(14,0), C=(5,12) yields exact rational inscribed square side 84/13 with vertices D=(35/13, 0), E=(119/13, 0), F=(119/13, 84/13), G=(35/13, 84/13).

geometor.petersen.tangent_circle_by_inversion(model: geometor.model.Model | None = None, O: tuple[Any, Any] | sympy.geometry.Point2D = (0, 0), M1: tuple[Any, Any] | sympy.geometry.Point2D = (-12, 0), M2: tuple[Any, Any] | sympy.geometry.Point2D = (0, -9), M3: tuple[Any, Any] | sympy.geometry.Point2D = (12, 9), inversion_radius: int | sympy.Expr = 12) → tuple[geometor.model.Model, dict[str, Any]]

Construct a circle touching three circles K1, K2, K3 concurrent at O via inversion.

Following Petersen’s Inverse Figures (pp. 33–36, Problem 199):

  1. Invert K1, K2, K3 (all passing through O) in circle Omega(O, R0). Because each circle passes through the centre of inversion O, their inverse curves are three straight lines L1, L2, L3 forming triangle V1 V2 V3.

  2. Construct the incircle omega' of V1 V2 V3 (Euclid IV.4) touching L1, L2, L3 at T1', T2', T3'.

  3. Invert T1', T2', T3' back across Omega to obtain the three points of contact T1, T2, T3 and circumscribe the tangent circle omega (center J).

With default integer lattice parameters O=(0,0), M1=(-12,0), M2=(0,-9), M3=(12,9), R0=12 (radii 12, 9, 15), L1, L2, L3 form an (18, 24, 30) right triangle with incenter J'=(0,-2), inradius 6, and inverted tangent circle omega centered at J=(0,9) of exact integer radius 27!

geometor.petersen.trapezoid_from_four_sides(model: geometor.model.Model | None = None, a: int | sympy.Expr = 19, b: int | sympy.Expr = 5, c: int | sympy.Expr = 13, d: int | sympy.Expr = 15) → tuple[geometor.model.Model, dict[str, Any]]

Construct trapezoid ABCD (AB || DC, AB=a, CD=b, BC=c, DA=d) via translation.

Following Petersen’s Parallel Translation (Ch. II.A, Problem 259, p. 49), translating non-parallel leg BC parallel to base CD so B -> E and C -> D gathers the four dispersed lengths into the constructible triangle AED with known sides AE = a - b, AD = d, and ED = c.

With default Heronian lengths (a=19, b=5, c=13, d=15), auxiliary triangle AED has sides (14, 15, 13) and every vertex lies on the exact integer lattice: A=(0,0), E=(14,0), B=(19,0), D=(9,12), C=(14,12).

geometor.petersen.export_euclid_svg
geometor.petersen.export_svg(model: geometor.model.Model, output_path: str | pathlib.Path, *, graphic_id: str = 'petersen-fig', title: str = 'Petersen Constructive Geometry Figure', width: int = 680, height: int = 440, margin: float = 40.0, bbox: tuple[float, float, float, float] | None = None, focus_points: collections.abc.Sequence[sympy.geometry.Point2D] | None = None, include_guides: bool = False, show_labels: bool = True, hide_aux_labels: bool = True, label_overrides: dict[str, tuple[str, str]] | None = None) → pathlib.Path

Write a .euclid-graphic SVG rendering of model to output_path.

geometor.petersen.render_euclid_svg
geometor.petersen.render_svg_string(model: geometor.model.Model, *, graphic_id: str = 'petersen-fig', title: str = 'Petersen Constructive Geometry Figure', width: int = 680, height: int = 440, margin: float = 40.0, bbox: tuple[float, float, float, float] | None = None, focus_points: collections.abc.Sequence[sympy.geometry.Point2D] | None = None, include_guides: bool = False, show_labels: bool = True, hide_aux_labels: bool = True, label_overrides: dict[str, tuple[str, str]] | None = None) → str

Render model as a theme-adaptive .euclid-graphic SVG string.

geometor.petersen.UNIT_SPECS: tuple[UnitSpec, ...]
class geometor.petersen.UnitSpec

Metadata specification for one 3-track Book Codex unit.

slug: str
number: int
title: str
danish_subtitle: str
page_span: str
problem_span: str
figure_svg: str
constructor_name: str