modules

geometor.etc

Tools for processing and modeling the Encyclopedia of Triangle Centers (ETC).

Key Components

Submodules

Attributes

CANONICAL_CENTER_CONCORDANCE

CANONICAL_TRIANGLES

Classes

CenterConcordance

Concordance entry linking canonical function names, Kimberling IDs, and classical citations.

CenterSymbolicRegistry

Exact symbolic evaluator and persistent cache for ETC triangle centers.

SymbolicCenterRecord

Exact symbolic coordinates and invariants for center X_num on a triangle.

SymbolicTriangle

Exact symbolic reference triangle with side lengths, vertices, and invariants.

Functions

extract_glossary_terms(html_content) → dict[str, Any]

Extract all glossary terms, their rich RST bodies, and plain-text summaries from GLOSSARY HTML.

generate_glossary_rst(terms[, intro_rst, valid_centers]) → str

Generate rich docsrc/glossary.rst with deterministic #term-<slug> anchors.

ingest_folder(input_folder, output_folder) → dict[str, Any]

Ingest all ETC volume HTML files in input_folder and write split files to output_folder.

bevan_point(model, A, B, C[, ID, classes]) → sympy.geometry.Point

Construct the Bevan point X_40 (reflection of X_1 across X_3).

centroid(model, A, B, C[, ID, classes, draw_medians]) → sympy.geometry.Point

Construct the centroid X_2 of triangle ABC.

circumcenter(model, A, B, C[, ID, classes, ...]) → sympy.geometry.Point

Construct the circumcenter X_3 of triangle ABC (Euclid IV.5).

circumcircle_inverse_of_incenter(model, A, B, C[, ID, ...]) → sympy.geometry.Point

Construct X_36, the circumcircle inverse of X_1.

clawson_point(model, A, B, C[, ID, classes]) → sympy.geometry.Point

Construct the Clawson point X_19.

construct_baseline_triangle(model[, a, b, c, ...]) → tuple[sympy.geometry.Point, sympy.geometry.Point, sympy.geometry.Point]

Construct an exact symbolic triangle with side ratios (a, b, c).

construct_reference_triangle(model[, preset, ...]) → tuple[sympy.geometry.Point, sympy.geometry.Point, sympy.geometry.Point]

Construct one of the 4 canonical exact symbolic reference triangles in model.

create_model([name]) → geometor.model.Model

Create a silent exact geometor.model.Model with auto_intersect=False.

de_longchamps_point(model, A, B, C[, ID, classes]) → sympy.geometry.Point

Construct the de Longchamps point X_20 (reflection of X_4 in X_3).

fermat_point(model, A, B, C[, ID, classes, ...]) → sympy.geometry.Point

Construct the 1st isogonic center (Fermat point) X_13.

feuerbach_point(model, A, B, C[, ID, classes, ...]) → sympy.geometry.Point

Construct the Feuerbach point X_11 of triangle ABC.

first_isodynamic_point(model, A, B, C[, ID, classes]) → sympy.geometry.Point

Construct the 1st isodynamic point X_15.

first_napoleon_point(model, A, B, C[, ID, classes]) → sympy.geometry.Point

Construct the 1st Napoleon point X_17.

gergonne_point(model, A, B, C[, ID, classes, ...]) → sympy.geometry.Point

Construct the Gergonne point X_7 of triangle ABC.

get_center_concordance(num) → CenterConcordance | None

Return the CenterConcordance for center X_num, if registered.

harmonic_feuerbach_point(model, A, B, C[, ID, classes]) → sympy.geometry.Point

Construct X_12 (the {X_1, X_5}-harmonic conjugate of X_11).

incenter(model, A, B, C[, ID, classes, ...]) → sympy.geometry.Point

Construct the incenter X_1 of triangle ABC (Euclid IV.4).

isotomic_conjugate_of_incenter(model, A, B, C[, ID, ...]) → sympy.geometry.Point

Construct X_75, the isotomic conjugate of X_1.

mittenpunkt(model, A, B, C[, ID, classes]) → sympy.geometry.Point

Construct the Mittenpunkt X_9 of triangle ABC.

nagel_point(model, A, B, C[, ID, classes, ...]) → sympy.geometry.Point

Construct the Nagel point X_8 of triangle ABC.

nine_point_center(model, A, B, C[, ID, classes, ...]) → sympy.geometry.Point

Construct the nine-point center X_5 of triangle ABC.

orthocenter(model, A, B, C[, ID, classes, draw_altitudes]) → sympy.geometry.Point

Construct the orthocenter X_4 of triangle ABC.

second_isodynamic_point(model, A, B, C[, ID, classes]) → sympy.geometry.Point

Construct the 2nd isodynamic point X_16.

second_isogonic_center(model, A, B, C[, ID, classes]) → sympy.geometry.Point

Construct the 2nd isogonic center X_14.

second_napoleon_point(model, A, B, C[, ID, classes]) → sympy.geometry.Point

Construct the 2nd Napoleon point X_18.

spieker_center(model, A, B, C[, ID, classes, ...]) → sympy.geometry.Point

Construct the Spieker center X_10 of triangle ABC.

symmedian_point(model, A, B, C[, ID, classes, ...]) → sympy.geometry.Point

Construct the symmedian (Lemoine) point X_6 of triangle ABC.

parse_center(html_content) → dict[str, Any] | None

Parse a center's HTML content into a rich structured dictionary.

generate_rst_files(centers, output_dir[, ...]) → None

Generate thematic collection folders (c-XXXXX-YYYYY/) and per-center folders (x-NNNNN/).

get_canonical_triangle([preset, unit_baseline]) → SymbolicTriangle

Return a canonical SymbolicTriangle by preset key.

Package Contents

geometor.etc.extract_glossary_terms(html_content: str) → dict[str, Any]

Extract all glossary terms, their rich RST bodies, and plain-text summaries from GLOSSARY HTML.

geometor.etc.generate_glossary_rst(terms: dict[str, Any], intro_rst: str = '', valid_centers: set[int] | None = None) → str

Generate rich docsrc/glossary.rst with deterministic #term-<slug> anchors.

geometor.etc.ingest_folder(input_folder: str | pathlib.Path, output_folder: str | pathlib.Path) → dict[str, Any]

Ingest all ETC volume HTML files in input_folder and write split files to output_folder.

Returns a summary dictionary with counts of centers, preambles, and intro sections.

geometor.etc.CANONICAL_CENTER_CONCORDANCE: dict[int, CenterConcordance]
class geometor.etc.CenterConcordance

Concordance entry linking canonical function names, Kimberling IDs, and classical citations.

num: int
function_name: str
etc_id: str
title: str
classical_ref: str
property signature: str

Return canonical functional signature string.

geometor.etc.bevan_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X40', classes: list[str] | None = None) → sympy.geometry.Point

Construct the Bevan point X_40 (reflection of X_1 across X_3).

geometor.etc.centroid(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X2', classes: list[str] | None = None, draw_medians: bool = False) → sympy.geometry.Point

Construct the centroid X_2 of triangle ABC.

geometor.etc.circumcenter(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X3', classes: list[str] | None = None, draw_bisectors: bool = False, draw_circumcircle: bool = False) → sympy.geometry.Point

Construct the circumcenter X_3 of triangle ABC (Euclid IV.5).

geometor.etc.circumcircle_inverse_of_incenter(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X36', classes: list[str] | None = None) → sympy.geometry.Point

Construct X_36, the circumcircle inverse of X_1.

geometor.etc.clawson_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X19', classes: list[str] | None = None) → sympy.geometry.Point

Construct the Clawson point X_19.

geometor.etc.construct_baseline_triangle(model: geometor.model.Model, a: sympy.Expr | float = 15, b: sympy.Expr | float = 13, c: sympy.Expr | float = 14, show_guides: bool = False, *, unit_baseline: bool = True) → tuple[sympy.geometry.Point, sympy.geometry.Point, sympy.geometry.Point]

Construct an exact symbolic triangle with side ratios (a, b, c).

Preserves backward compatibility for scripts calling construct_baseline_triangle(model, 5, 6, 7) while computing exact algebraic coordinates without floating-point approximations.

geometor.etc.construct_reference_triangle(model: geometor.model.Model, preset: str | geometor.etc.triangles.SymbolicTriangle = 'heronian', *, unit_baseline: bool = False, show_guides: bool = False) → tuple[sympy.geometry.Point, sympy.geometry.Point, sympy.geometry.Point]

Construct one of the 4 canonical exact symbolic reference triangles in model.

Parameters:
  • model – Target geometor.model.Model.

  • preset – Canonical preset key ("heronian", "right", "kepler", "kimberling") or a SymbolicTriangle.

  • unit_baseline – When True, normalizes side \(AB = 1\). Defaults to False so Heronian \((15, 13, 14)\) and Right \((3, 4, 5)\) preserve exact integer vertex and center coordinates.

  • show_guides – When True, includes Euclid I.22 compass guide circles centered at \(A\) and \(B\).

geometor.etc.create_model(name: str = 'ETC Construction') → geometor.model.Model

Create a silent exact geometor.model.Model with auto_intersect=False.

geometor.etc.de_longchamps_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X20', classes: list[str] | None = None) → sympy.geometry.Point

Construct the de Longchamps point X_20 (reflection of X_4 in X_3).

geometor.etc.fermat_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X13', classes: list[str] | None = None, draw_equilaterals: bool = False) → sympy.geometry.Point

Construct the 1st isogonic center (Fermat point) X_13.

geometor.etc.feuerbach_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X11', classes: list[str] | None = None, draw_circles: bool = False) → sympy.geometry.Point

Construct the Feuerbach point X_11 of triangle ABC.

geometor.etc.first_isodynamic_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X15', classes: list[str] | None = None) → sympy.geometry.Point

Construct the 1st isodynamic point X_15.

geometor.etc.first_napoleon_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X17', classes: list[str] | None = None) → sympy.geometry.Point

Construct the 1st Napoleon point X_17.

geometor.etc.gergonne_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X7', classes: list[str] | None = None, draw_cevians: bool = False, draw_intouch: bool = False) → sympy.geometry.Point

Construct the Gergonne point X_7 of triangle ABC.

geometor.etc.get_center_concordance(num: int) → CenterConcordance | None

Return the CenterConcordance for center X_num, if registered.

geometor.etc.harmonic_feuerbach_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X12', classes: list[str] | None = None) → sympy.geometry.Point

Construct X_12 (the {X_1, X_5}-harmonic conjugate of X_11).

geometor.etc.incenter(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X1', classes: list[str] | None = None, draw_bisectors: bool = False, draw_incircle: bool = False, draw_touchpoints: bool = False) → sympy.geometry.Point

Construct the incenter X_1 of triangle ABC (Euclid IV.4).

Parameters:
  • model – Target geometor.model.Model.

  • A – Vertices of reference triangle ABC.

  • B – Vertices of reference triangle ABC.

  • C – Vertices of reference triangle ABC.

  • ID – Element identifier (defaults to "X_1").

  • classes – Optional CSS/model classes.

  • draw_bisectors – When True, constructs exact internal angle bisector feet I_a, I_b, I_c and concurring bisector lines [ A I_a ], [ B I_b ], [ C I_c ].

  • draw_incircle – When True, constructs the inscribed circle incircle centered at X_1 through exact tangency foot T_c.

  • draw_touchpoints – When True, constructs all three right-spread touchpoints T_a, T_b, T_c.

geometor.etc.isotomic_conjugate_of_incenter(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X75', classes: list[str] | None = None) → sympy.geometry.Point

Construct X_75, the isotomic conjugate of X_1.

geometor.etc.mittenpunkt(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X9', classes: list[str] | None = None) → sympy.geometry.Point

Construct the Mittenpunkt X_9 of triangle ABC.

geometor.etc.nagel_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X8', classes: list[str] | None = None, draw_cevians: bool = False, draw_extouch: bool = False) → sympy.geometry.Point

Construct the Nagel point X_8 of triangle ABC.

geometor.etc.nine_point_center(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X5', classes: list[str] | None = None, draw_circle: bool = False) → sympy.geometry.Point

Construct the nine-point center X_5 of triangle ABC.

geometor.etc.orthocenter(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X4', classes: list[str] | None = None, draw_altitudes: bool = False) → sympy.geometry.Point

Construct the orthocenter X_4 of triangle ABC.

geometor.etc.second_isodynamic_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X16', classes: list[str] | None = None) → sympy.geometry.Point

Construct the 2nd isodynamic point X_16.

geometor.etc.second_isogonic_center(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X14', classes: list[str] | None = None) → sympy.geometry.Point

Construct the 2nd isogonic center X_14.

geometor.etc.second_napoleon_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X18', classes: list[str] | None = None) → sympy.geometry.Point

Construct the 2nd Napoleon point X_18.

geometor.etc.spieker_center(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X10', classes: list[str] | None = None, draw_circle: bool = False, draw_bisectors: bool = False, draw_medial: bool = False) → sympy.geometry.Point

Construct the Spieker center X_10 of triangle ABC.

geometor.etc.symmedian_point(model: geometor.model.Model, A: sympy.geometry.Point, B: sympy.geometry.Point, C: sympy.geometry.Point, ID: str = 'X6', classes: list[str] | None = None, draw_symmedians: bool = False) → sympy.geometry.Point

Construct the symmedian (Lemoine) point X_6 of triangle ABC.

geometor.etc.parse_center(html_content: str) → dict[str, Any] | None

Parse a center’s HTML content into a rich structured dictionary.

class geometor.etc.CenterSymbolicRegistry(triangle: geometor.etc.triangles.SymbolicTriangle | str = 'heronian', *, cache_dir: pathlib.Path | str | None = DEFAULT_SYMBOLIC_CACHE_DIR)

Exact symbolic evaluator and persistent cache for ETC triangle centers.

Parameters:
  • triangle – A SymbolicTriangle instance or canonical preset name ("heronian", "right", "kepler", "kimberling").

  • cache_dir – Directory where per-triangle JSON cache files are stored. Pass None to disable disk persistence (in-memory only).

cache_dir
property cache_file: pathlib.Path | None

Path to this triangle’s JSON cache file.

save_cache() → None

Persist cached symbolic center records to disk if modified.

has_exact_formula(num: int) → bool

Return whether center X_num has a built-in closed-form generator.

evaluate_barycentrics(num: int, raw_bary: tuple[sympy.Expr, sympy.Expr, sympy.Expr] | None = None) → SymbolicCenterRecord

Evaluate and cache a center from either EXACT_CYCLIC_BARYCENTRICS or raw_bary.

get(num: int) → SymbolicCenterRecord

Return the exact SymbolicCenterRecord for X_num.

evaluate_cyclic_sympy(num: int, first_component: sympy.Expr, *, is_trilinear: bool = False, cache: bool = True) → SymbolicCenterRecord

Evaluate an arbitrary cyclic SymPy expression in (a, b, c, A, B, C, S_A, S_B, S_C, S, r, R, s).

warm_collection_1() → dict[int, SymbolicCenterRecord]

Evaluate and cache all Collection 1 centers (X1–X19) plus key companions.

class geometor.etc.SymbolicCenterRecord

Exact symbolic coordinates and invariants for center X_num on a triangle.

num: int
triangle_key: str
bary: tuple[sympy.Expr, sympy.Expr, sympy.Expr]
norm_bary: tuple[sympy.Expr, sympy.Expr, sympy.Expr]
trilinear: tuple[sympy.Expr, sympy.Expr, sympy.Expr]
xy: tuple[sympy.Expr, sympy.Expr]
sub_areas: tuple[sympy.Expr, sympy.Expr, sympy.Expr]
search_value: sympy.Expr
property is_kepler: bool

Return whether this record belongs to the Kepler golden triangle.

xy_latex() → str

Return (x, y) formatted as LaTeX.

xy_pretty() → str

Return (x, y) formatted as compact Unicode.

trilinear_latex() → str

Return homogeneous trilinears formatted as LaTeX.

trilinear_pretty() → str

Return homogeneous trilinears formatted as Unicode.

bary_latex() → str

Return homogeneous barycentrics formatted as LaTeX.

bary_pretty() → str

Return homogeneous barycentrics formatted as Unicode.

search_latex() → str

Return the exact Kimberling search value as LaTeX.

approx_xy() → tuple[float, float]

Return secondary float approximation of (x, y) for SVG layout.

approx_search_value() → float

Return float approximation of search_value.

to_cache_dict() → dict[str, Any]

Serialize exact SymPy expressions via sp.srepr.

classmethod from_cache_dict(data: dict[str, Any]) → SymbolicCenterRecord

Deserialize exact SymPy expressions from sp.srepr strings.

geometor.etc.generate_rst_files(centers: list[dict[str, Any]], output_dir: str | pathlib.Path, glossary_terms: dict[str, Any] | list[str] | None = None, preambles_by_center: dict[str, list[dict[str, Any]]] | None = None, valid_centers: set[int] | None = None, render_graphics: bool = True, constructions_dir: str | pathlib.Path | None = None) → None

Generate thematic collection folders (c-XXXXX-YYYYY/) and per-center folders (x-NNNNN/).

geometor.etc.CANONICAL_TRIANGLES: dict[str, SymbolicTriangle]
class geometor.etc.SymbolicTriangle

Exact symbolic reference triangle with side lengths, vertices, and invariants.

Parameters:
  • key – Preset identifier ("heronian", "right", "kepler", "kimberling", or "acute").

  • label – Short human-readable title (e.g. "Heronian (15, 13, 14)").

  • field_latex – LaTeX string naming the ambient algebraic field (e.g. r"\mathbb{Q}").

  • a – Exact side lengths \(a = |BC|\), \(b = |CA|\), \(c = |AB|\).

  • b – Exact side lengths \(a = |BC|\), \(b = |CA|\), \(c = |AB|\).

  • c – Exact side lengths \(a = |BC|\), \(b = |CA|\), \(c = |AB|\).

  • A_xy – Exact Cartesian coordinates of vertices \(A\), \(B\), \(C\).

  • B_xy – Exact Cartesian coordinates of vertices \(A\), \(B\), \(C\).

  • C_xy – Exact Cartesian coordinates of vertices \(A\), \(B\), \(C\).

  • area – Exact area \(\Delta = \operatorname{Area}(\triangle ABC)\).

  • simplify_fn – Field-aware exact simplification callable.

key: str
label: str
field_latex: str
a: sympy.Expr
b: sympy.Expr
c: sympy.Expr
A_xy: tuple[sympy.Expr, sympy.Expr]
B_xy: tuple[sympy.Expr, sympy.Expr]
C_xy: tuple[sympy.Expr, sympy.Expr]
area: sympy.Expr
simplify_fn: collections.abc.Callable[[sympy.Expr], sympy.Expr]
simplify(expr: sympy.Expr | int) → sympy.Expr

Simplify expr in this triangle’s algebraic field.

property Q_a: sympy.Expr

Exact quadrance \(Q_a = a^2\) of side \(BC\).

property Q_b: sympy.Expr

Exact quadrance \(Q_b = b^2\) of side \(CA\).

property Q_c: sympy.Expr

Exact quadrance \(Q_c = c^2\) of side \(AB\).

property s: sympy.Expr

Exact semiperimeter \(s = (a + b + c)/2\).

property two_area: sympy.Expr

Conway doubled area \(S = 2\Delta\).

property r: sympy.Expr

Exact inradius \(r = \Delta / s\).

property Q_r: sympy.Expr

Exact incircle quadrance \(Q_r = r^2\).

property R: sympy.Expr

Exact circumradius \(R = abc / (4\Delta)\).

property Q_R: sympy.Expr

Exact circumcircle quadrance \(Q_R = R^2\).

property S_A: sympy.Expr

Conway symbol \(S_A = (b^2 + c^2 - a^2)/2\).

property S_B: sympy.Expr

Conway symbol \(S_B = (c^2 + a^2 - b^2)/2\).

property S_C: sympy.Expr

Conway symbol \(S_C = (a^2 + b^2 - c^2)/2\).

unit_baseline() → SymbolicTriangle

Return a homothetic copy scaled by \(1/c\) so \(A=(0,0), B=(1,0)\).

trilinear_to_bary(alpha: sympy.Expr, beta: sympy.Expr, gamma: sympy.Expr) → tuple[sympy.Expr, sympy.Expr, sympy.Expr]

Convert homogeneous trilinears \((\alpha : \beta : \gamma)\) to barycentrics.

bary_to_trilinear(u: sympy.Expr, v: sympy.Expr, w: sympy.Expr) → tuple[sympy.Expr, sympy.Expr, sympy.Expr]

Convert homogeneous barycentrics \((u : v : w)\) to trilinears.

normalize_bary(u: sympy.Expr, v: sympy.Expr, w: sympy.Expr) → tuple[sympy.Expr, sympy.Expr, sympy.Expr]

Normalize homogeneous barycentrics so \(u + v + w = 1\).

bary_to_cartesian(u: sympy.Expr, v: sympy.Expr, w: sympy.Expr) → tuple[sympy.Expr, sympy.Expr]

Map homogeneous barycentrics \((u : v : w)\) to exact Cartesian \((x, y)\).

cartesian_to_sub_areas(x: sympy.Expr, y: sympy.Expr) → tuple[sympy.Expr, sympy.Expr, sympy.Expr]

Return exact signed sub-triangle areas \((\Delta_a, \Delta_b, \Delta_c)\).

kimberling_search_value(u: sympy.Expr, v: sympy.Expr, w: sympy.Expr) → sympy.Expr

Return exact directed distance \(h_a = 2\Delta u / (a(u + v + w))\) to \(BC\).

geometor.etc.get_canonical_triangle(preset: str = 'heronian', *, unit_baseline: bool = False) → SymbolicTriangle

Return a canonical SymbolicTriangle by preset key.

Parameters:
  • preset – One of "heronian", "right", "kepler", "kimberling" (or legacy "acute").

  • unit_baseline – When True, scales the triangle by \(1/c\) so \(AB = 1\).