Examples Gallery¶
A collection of examples demonstrating Geolet's capabilities.
Basic Shapes¶
Triangle¶
"""Simple triangle example using the Triangle class."""
from geolet import Midpoint, Point, Triangle, autofigure
@autofigure
def triangle():
A = Point("A", 0, 0)
B = Point("B", 4, 0)
C = Point("C", 1.5, 3)
# Triangle automatically draws all three sides
T = Triangle(A, B, C)
# Midpoint of AB (using side accessor)
M = Midpoint(T.side12.p1, T.side12.p2, label="M", label_dir="S")
Line¶
"""Line example - infinite line through two points."""
from geolet import Line, Point, figure
@figure
def line():
A = Point("A", 0, 0, label_dir="SW")
B = Point("B", 2, 1, label_dir="NE")
return [
A,
B,
Line(A, B, color="blue"),
]
Circle with Radius¶
"""Circle with radius example."""
from geolet import CircleWithRadius, Point, figure
@figure
def circle_radius():
O = Point("O", 0, 0, label_dir="S")
return [
O,
CircleWithRadius(O, 2.0, color="red"),
]
Triangle Centers¶
Centroid¶
The centroid is the intersection of the medians.
"""Centroid example - intersection of medians."""
from geolet import Centroid, Point, Segment, figure
@figure
def centroid():
A = Point("A", 0, 4, label_dir="N")
B = Point("B", 0, 0, label_dir="SW")
C = Point("C", 5, 0, label_dir="SE")
return [
A,
B,
C,
Segment(A, B),
Segment(B, C),
Segment(C, A),
# Centroid (intersection of medians)
Centroid(A, B, C, label="G", color="red"),
]
Orthocenter¶
The orthocenter is the intersection of the altitudes.
"""Orthocenter example - intersection of altitudes."""
from geolet import Orthocenter, Point, Segment, figure
@figure
def orthocenter():
A = Point("A", 1, 4, label_dir="N")
B = Point("B", 0, 0, label_dir="SW")
C = Point("C", 5, 0, label_dir="SE")
return [
A,
B,
C,
Segment(A, B),
Segment(B, C),
Segment(C, A),
# Orthocenter (intersection of altitudes)
Orthocenter(A, B, C, label="H", color="red"),
]
Incenter & Incircle¶
The incenter is the intersection of angle bisectors. The incircle is tangent to all sides.
"""Incenter and Incircle example - intersection of angle bisectors."""
from geolet import Incenter, Incircle, Point, Segment, figure
@figure
def incenter():
A = Point("A", 1, 4, label_dir="N")
B = Point("B", 0, 0, label_dir="SW")
C = Point("C", 5, 0, label_dir="SE")
return [
A,
B,
C,
Segment(A, B),
Segment(B, C),
Segment(C, A),
# Incenter (intersection of angle bisectors)
Incenter(A, B, C, label="I", color="red"),
# Incircle (inscribed circle)
Incircle(A, B, C, color="blue"),
]
Circumcircle¶
The circumcircle passes through all three vertices.
"""Circumcircle example - circle through 3 points."""
from geolet import Circle, Point, Segment, figure
@figure
def circumcircle():
A = Point("A", 0, 0, label_dir="SW")
B = Point("B", 4, 0, label_dir="SE")
C = Point("C", 1.5, 3, label_dir="N")
return [
A,
B,
C,
Segment(A, B),
Segment(B, C),
Segment(C, A),
Circle(A, B, C, color="blue"),
]
Euler Line¶
The orthocenter (H), centroid (G), and circumcenter (O) are collinear.
"""Euler line example - line through orthocenter, centroid, and circumcenter."""
from geolet import Line, Point, Triangle, autofigure
@autofigure
def euler_line():
A = Point("A", 0, 0, label_dir="SW")
B = Point("B", 6, 0, label_dir="SE")
C = Point("C", 2, 5, label_dir="N")
T = Triangle(A, B, C)
# Orthocenter (intersection of altitudes)
H = T.orthocenter(label="H", label_dir="S", color="red")
# Centroid (intersection of medians)
G = T.centroid(label="G", label_dir="S", color="blue")
# Circumcenter (intersection of perpendicular bisectors)
O = T.circumcenter(label="O", label_dir="S", color="green")
# Euler line through H and O (also passes through G)
euler = Line(H, O, color="purple", style="dashed")
Intersections¶
Segment Intersection¶
"""Segment intersection example - intersection of two segments."""
from geolet import Intersection, Point, Segment, figure
@figure
def segment_intersection():
A = Point("A", 0, 0, label_dir="SW")
B = Point("B", 3, 2, label_dir="NE")
C = Point("C", 0, 2, label_dir="NW")
D = Point("D", 3, 0, label_dir="SE")
seg1 = Segment(A, B)
seg2 = Segment(C, D)
return [
A,
B,
C,
D,
seg1,
seg2,
Intersection(seg1, seg2, label="P", label_dir="N", color="red"),
]
Circle-Circle Intersection¶
"""Circle-circle intersection example - where two circles intersect."""
from geolet import CircleWithRadius, Intersection, Point, figure
@figure
def circle_circle_intersection():
O1 = Point("O_1", 0, 0, label_dir="S")
O2 = Point("O_2", 2.5, 0, label_dir="S")
circle1 = CircleWithRadius(O1, 2.0, color="blue")
circle2 = CircleWithRadius(O2, 2.0, color="green")
return [
O1,
O2,
circle1,
circle2,
Intersection(circle1, circle2, label="P", index=0, label_dir="N", color="red"),
Intersection(circle1, circle2, label="Q", index=1, label_dir="S", color="red"),
]
Circle-Segment Intersection¶
"""Circle-segment intersection example - where a segment crosses a circle."""
from geolet import CircleWithRadius, Intersection, Point, Segment, figure
@figure
def circle_segment_intersection():
O = Point("O", 0, 0, label_dir="S")
A = Point("A", -3, -1, label_dir="SW")
B = Point("B", 3, 1, label_dir="NE")
circle = CircleWithRadius(O, 2.0, color="blue")
segment = Segment(A, B, style="dashed")
return [
O,
A,
B,
circle,
segment,
Intersection(circle, segment, label="P", index=0, label_dir="NW", color="red"),
Intersection(circle, segment, label="Q", index=1, label_dir="SE", color="red"),
]
Tangent Lines¶
"""Tangent example - drawing tangent lines from external point to circle."""
from geolet import CircleWithRadius, Point, Segment, Tangent, TangentPoint, autofigure
@autofigure
def tangent():
# Circle with center O and radius 2
O = Point("O", 0, 0)
c = CircleWithRadius(O, 2, color="gray")
# External point P
P = Point("P", 5, 0)
# Two tangent lines from P to circle c
t1 = Tangent(P, c, index=0, label="t_1", label_dir="S", color="blue")
t2 = Tangent(P, c, index=1, label="t_2", label_dir="N", color="red")
# Tangent points - where each tangent line touches the circle
T1 = TangentPoint(P, c, index=0, label="T_1", label_dir="SW", color="blue")
T2 = TangentPoint(P, c, index=1, label="T_2", label_dir="NW", color="red")
# Segments from P to tangent points (these have equal length)
Segment(P, T1, style="dashed", color="blue")
Segment(P, T2, style="dashed", color="red")
Tangent Point¶
"""TangentPoint example - finding where tangent lines touch a circle."""
from geolet import CircleWithRadius, Point, Segment, TangentPoint, autofigure
@autofigure
def tangent_point():
# Circle with center O and radius 2
O = Point("O", 0, 0)
c = CircleWithRadius(O, 2, color="gray")
# External point P
P = Point("P", 5, 0)
# Tangent points - where tangent lines from P touch the circle
T1 = TangentPoint(P, c, index=0, label="T_1", label_dir="SW", color="blue")
T2 = TangentPoint(P, c, index=1, label="T_2", label_dir="NW", color="red")
# Segments from external point to tangent points
# These segments have equal length (property of tangent lines)
s1 = Segment(P, T1, color="blue")
s2 = Segment(P, T2, color="red")
# Segments from center to tangent points (radii, perpendicular to tangents)
r1 = Segment(O, T1, style="dashed", color="gray")
r2 = Segment(O, T2, style="dashed", color="gray")
Altitude & Foot¶
"""Altitude example - foot of perpendicular from vertex to opposite side."""
from geolet import Foot, Point, Segment, figure
@figure
def altitude():
A = Point("A", 1, 3, label_dir="N")
B = Point("B", 0, 0, label_dir="SW")
C = Point("C", 4, 0, label_dir="SE")
# Triangle sides
bc = Segment(B, C)
return [
A,
B,
C,
Segment(A, B),
bc,
Segment(C, A),
Foot(A, bc, label="H", label_dir="S"),
]
Perpendicular Line¶
"""Perpendicular line example - line perpendicular to a segment through a point."""
from geolet import PerpendicularLine, Point, Segment, figure
@figure
def perpendicular():
A = Point("A", 0, 0, label_dir="SW")
B = Point("B", 4, 0, label_dir="SE")
P = Point("P", 2, 2, label_dir="N")
seg = Segment(A, B)
return [
A,
B,
P,
seg,
PerpendicularLine(P, seg, color="red", style="dashed"),
]
Median¶
"""Median example - segment from vertex to midpoint of opposite side."""
from geolet import Median, Point, Segment, figure
@figure
def median():
A = Point("A", 0, 4, label_dir="N")
B = Point("B", 0, 0, label_dir="SW")
C = Point("C", 5, 0, label_dir="SE")
return [
A,
B,
C,
Segment(A, B),
Segment(B, C),
Segment(C, A),
# Median from A to midpoint of BC
Median(A, B, C, color="blue"),
]
Angle Marking¶
"""Example showing angle marking in a triangle."""
from geolet import Angle, Foot, Point, Segment, Triangle, autofigure
@autofigure
def angle():
A = Point("A", 0, 0, label_dir="SW")
B = Point("B", 5, 0, label_dir="SE")
C = Point("C", 2, 3, label_dir="N")
tri = Triangle(A, B, C)
# Mark angle CAB (at vertex A) with label
angle_a = Angle(C, A, B, label="\\alpha", color="blue")
# Mark angle ABC (at vertex B) with double arc (congruent angle notation)
angle_b = Angle(A, B, C, n=2, color="red")
# Mark angle BCA (at vertex C) with fill
angle_c = Angle(B, C, A, fill=True, color="green")
# Altitude from C to AB
H = Foot(C, Segment(A, B), label="H", label_dir="S")
altitude = Segment(C, H, style="dashed", color="gray")
# Right angle marker at foot of altitude (angle AHC)
right_angle = Angle(A, H, C, right_angle=True, color="gray")
Reflections¶
"""Reflect example - point, segment, and line reflections."""
from geolet import Line, Point, Reflect, Segment, autofigure
@autofigure
def reflect():
# Original point
A = Point("A", 1, 1, label_dir="SW")
# 1. Reflect over a point (central reflection)
O = Point("O", 2.5, 1.5, label_dir="S", color="red")
A1 = Reflect(A, O, label="A_1", label_dir="NE", color="red")
AO = Segment(A, A1, color="red", style="dashed") # Connect to show symmetry
# 2. Reflect over a segment
P = Point("P", 5, 0, label_dir="S")
Q = Point("Q", 5, 3, label_dir="N")
seg = Segment(P, Q, color="blue")
A2 = Reflect(A, seg, label="A_2", label_dir="E", color="blue")
# 3. Reflect over a line (infinite)
R = Point("R", 0, 4, label_dir="W")
S = Point("S", 6, 4, label_dir="E")
line = Line(R, S, color="green", style="dashed")
A3 = Reflect(A, line, label="A_3", label_dir="N", color="green")
Inversions¶
Invert Point¶
"""InvertPoint example - inverting points with respect to a circle."""
from math import sqrt
from geolet import CircleWithRadius, InvertPoint, Line, Point, autofigure
@autofigure
def invert_point():
# Circle of inversion centered at O with radius 2
O = Point("O", 0, 0, label_dir="SW")
inv_circle = CircleWithRadius(O, 2, color="gray", style="dashed")
# Points to invert
# P is inside the circle (distance 1 from center), on horizontal axis
P = Point("P", 1, 0, label_dir="S")
# Q is outside the circle, to the right
Q = Point("Q", 3, 1, label_dir="N")
# R is on the circle (distance 2 from center) on the diagonal - maps to itself
R = Point("R", sqrt(2), sqrt(2), label_dir="NE")
# Invert the points
# P at distance 1 maps to P' at distance 4 (1 * 4 = 2^2 = 4)
P_inv = InvertPoint(
P, respect_to=inv_circle, label="P'", label_dir="S", color="blue"
)
# Q at distance sqrt(10) maps to Q' at distance 4/sqrt(10)
Q_inv = InvertPoint(
Q, respect_to=inv_circle, label="Q'", label_dir="N", color="red"
)
# R on the circle maps to itself
R_inv = InvertPoint(
R, respect_to=inv_circle, label="R'", label_dir="SW", color="green"
)
# Draw lines through O connecting original points to their inversions
line1 = Line(P, P_inv, color="blue", style="dashed")
line2 = Line(Q, Q_inv, color="red", style="dashed")
Invert Line¶
"""InvertLine example - inverting lines with respect to a circle."""
from geolet import (
CircleWithRadius,
InvertLine,
InvertLineThroughCenter,
Line,
Point,
autofigure,
)
@autofigure
def invert_line():
# Circle of inversion centered at O with radius 2
O = Point("O", 0, 0, label_dir="E")
inv_circle = CircleWithRadius(O, 2)
# Case 1: A line that doesn't pass through the center (x = 0.8)
C = Point("C", 0.8, -2.5, label_dir="SE")
D = Point("D", 0.8, 2.5, label_dir="NE")
line_cd = Line(C, D)
# Invert the line - produces a circle passing through O
inverted_circle_1 = InvertLine(
line_cd, respect_to=inv_circle, color="red", style="dashed"
)
O_CD = inverted_circle_1.center_point(label="O_{CD}", label_dir="E", color="red")
# Case 2: A line closer to the edge (x = -1.5) - produces a larger circle
E = Point("E", -1.5, -2.5, label_dir="W")
F = Point("F", -1.5, 2.5, label_dir="W")
line_ef = Line(E, F)
inverted_circle_2 = InvertLine(
line_ef, respect_to=inv_circle, color="green", style="dashed"
)
O_EF = inverted_circle_2.center_point(label="O_{EF}", label_dir="E", color="green")
# Case 3: A line through the center (x = 0) maps to itself
A = Point("A", 0, -2.5, label_dir="SW")
B = Point("B", 0, 2.5, label_dir="NW")
line_through_center = Line(A, B)
# Invert the line through center - stays the same line (dashed to show inversion)
inverted_same = InvertLineThroughCenter(
line_through_center, respect_to=inv_circle, color="blue", style="dashed"
)
Invert Circle¶
"""InvertCircle example - inverting circles with respect to another circle."""
from geolet import (
CircleWithRadius,
InvertCircle,
InvertCircleThroughCenter,
Point,
autofigure,
)
@autofigure
def invert_circle():
# Circle of inversion centered at O with radius 3
O = Point("O", 0, 0, label_dir="E")
inv_circle = CircleWithRadius(O, 3)
# Case 1: A circle that doesn't pass through the center of inversion
# This circle centered at (2, 0) with radius 0.5 will invert to another circle
C1 = Point("C_1", 2, 0, label_dir="E")
circle1 = CircleWithRadius(C1, 0.7, color="blue")
circle1_inv = InvertCircle(
circle1, respect_to=inv_circle, color="blue", style="dashed"
)
C1_prime = circle1_inv.center_point(label="C'_1", label_dir="E", color="blue")
# Case 2: Another circle further from center
C2 = Point("C_2", 0, -4, label_dir="S")
circle2 = CircleWithRadius(C2, 0.8, color="green")
circle2_inv = InvertCircle(
circle2, respect_to=inv_circle, color="green", style="dashed"
)
C2_prime = circle2_inv.center_point(label="C'_2", label_dir="S", color="green")
# Case 3: A circle passing through the center of inversion maps to a line
C3 = Point("C_3", 0, 2, label_dir="S")
circle3 = CircleWithRadius(C3, 2, color="purple") # passes through O
circle3_inv = InvertCircleThroughCenter(
circle3, respect_to=inv_circle, color="purple", style="dashed"
)
Advanced Examples¶
Nine-Point Circle¶
"""Nine-point circle (Euler circle / Feuerbach circle).
Given triangle ABC with altitudes AD, BE, and CF. Let H be the orthocenter of
triangle ABC. Let MA, MB, and MC be the midpoints of sides BC, CA, and AB
respectively. Let HA, HB, and HC be the midpoints of segments AH, BH, and CH.
Prove that these nine points lie on a single circle:
D, E, F, MA, MB, MC, HA, HB, HC.
The nine points are:
- D, E, F: feet of the altitudes
- MA, MB, MC: midpoints of the sides
- HA, HB, HC: midpoints from vertices to orthocenter
"""
from geolet import (
Circle,
Circumcenter,
Foot,
Midpoint,
Orthocenter,
Point,
Segment,
figure,
)
@figure
def nine_point_circle():
# Triangle vertices
A = Point("A", 0, 4, label_dir="N")
B = Point("B", -1, 0, label_dir="SW")
C = Point("C", 5, 0, label_dir="SE")
# Triangle sides
seg_ab = Segment(A, B)
seg_bc = Segment(B, C)
seg_ca = Segment(C, A)
# Orthocenter H
H = Orthocenter(A, B, C, label="H", label_dir="S")
# Feet of altitudes (D, E, F)
D = Foot(A, seg_bc, label="D", label_dir="S") # Foot from A to BC
E = Foot(B, seg_ca, label="E", label_dir="NE") # Foot from B to CA
F = Foot(C, seg_ab, label="F", label_dir="NW") # Foot from C to AB
# Midpoints of sides (MA, MB, MC)
MA = Midpoint(B, C, label="M_A", label_dir="S") # Midpoint of BC
MB = Midpoint(C, A, label="M_B", label_dir="NE") # Midpoint of CA
MC = Midpoint(A, B, label="M_C", label_dir="NW") # Midpoint of AB
# Midpoints from vertices to orthocenter (HA, HB, HC)
HA = Midpoint(A, H, label="H_A", label_dir="E") # Midpoint of AH
HB = Midpoint(B, H, label="H_B", label_dir="W") # Midpoint of BH
HC = Midpoint(C, H, label="H_C", label_dir="E") # Midpoint of CH
# Circumcenter O of triangle ABC
O = Circumcenter(A, B, C, label="O", label_dir="N", color="red")
# Center of nine-point circle O_9 is the midpoint of O and H
O_9 = Midpoint(O, H, label="O_9", label_dir="N", color="blue")
# The nine-point circle passes through all nine points
# We can define it using any three of them
nine_pt_circle = Circle(D, E, F, color="blue", style="dashed")
# Show O_9 is midpoint of O and H with equal length segments
seg_o_o9 = Segment(O, O_9, color="purple", marks=1) # O to O_9
seg_o9_h = Segment(O_9, H, color="purple", marks=1) # O_9 to H
return [
# Triangle
seg_ab,
seg_bc,
seg_ca,
# Euler line segments O--O_9--H with equal marks
seg_o_o9,
seg_o9_h,
# Nine-point circle
nine_pt_circle,
# Triangle vertices
A,
B,
C,
# Orthocenter
H,
# Circumcenter of ABC
O,
# Center of nine-point circle (midpoint of O and H)
O_9,
# Feet of altitudes
D,
E,
F,
# Midpoints of sides
MA,
MB,
MC,
# Midpoints to orthocenter
HA,
HB,
HC,
]
IMO 2025 Problem 2¶
A complex geometry problem showcasing multiple features.
"""IMO 2025 Problem 2 - Circles, circumcenters, and tangent lines.
Let Ω and Γ be circles with centres M and N, respectively, such that the
radius of Ω is less than the radius of Γ. Suppose Ω and Γ intersect at two
distinct points A and B. Line MN intersects Ω at C and Γ at D, so that
C, M, N, D lie on MN in that order. Let P be the circumcentre of triangle ACD.
Line AP meets Ω again at E ≠ A and meets Γ again at F ≠ A. Let H be the
orthocentre of triangle PMN.
Prove that the line through H parallel to AP is tangent to the circumcircle
of triangle BEF.
Proposed by Trần Quang Hùng, Vietnam
"""
from geolet import (
Circle,
CircleWithRadius,
Circumcenter,
Intersection,
Line,
Orthocenter,
ParallelLine,
Point,
Segment,
figure,
)
@figure
def imo_2025_p2():
# Circle centers
M = Point("M", 0, 0, label_dir="SW")
N = Point("N", 3, 0, label_dir="SE")
# Circles Ω (blue, radius 2) and Γ (green, radius 2.5)
omega = CircleWithRadius(M, 2.0, color="blue")
gamma = CircleWithRadius(N, 2.5, color="green")
# A, B: intersection points of Ω and Γ
A = Intersection(omega, gamma, label="A", index=0, label_dir="N")
B = Intersection(omega, gamma, label="B", index=1, label_dir="S")
# Line MN for intersections
line_mn_path = Line(M, N)
# C: line MN intersects Ω (left of M)
# D: line MN intersects Γ (right of N)
C = Intersection(omega, line_mn_path, label="C", index=1, label_dir="W")
D = Intersection(gamma, line_mn_path, label="D", index=0, label_dir="E")
# P: circumcenter of triangle ACD
P = Circumcenter(A, C, D, label="P", label_dir="W")
# Circumcircle of triangle ACD (center P)
circle_acd = Circle(A, C, D, color="purple", style="dashed")
# Line AP (extended) - needed for E, F intersections
line_ap = Line(A, P, color="purple", style="dashed")
# E: line AP meets Ω again at E ≠ A (index 1 to get second intersection)
E = Intersection(omega, line_ap, label="E", index=1, label_dir="NW")
# F: line AP meets Γ again at F ≠ A (index 1 to get second intersection)
F = Intersection(gamma, line_ap, label="F", index=1, label_dir="S")
# H: orthocenter of triangle PMN
H = Orthocenter(P, M, N, label="H", label_dir="E")
# Triangle PMN
seg_pm = Segment(P, M)
seg_mn = Segment(M, N)
seg_np = Segment(N, P)
# Line MN (shown as segment C--D)
line_mn = Segment(C, D, style="dashed")
# Triangle ACD
seg_ac = Segment(A, C)
seg_cd = Segment(C, D)
seg_da = Segment(D, A)
# Circumcircle of BEF (the key circle for the theorem)
circle_bef = Circle(B, E, F, color="red")
# Tangent line: through H parallel to AP
tangent_line = ParallelLine(H, line_ap, color="orange", style="dashed")
return [
# Circles
omega,
gamma,
circle_acd,
circle_bef,
# Triangle PMN
seg_pm,
seg_mn,
seg_np,
# Triangle ACD
seg_ac,
seg_cd,
seg_da,
# Construction lines
line_mn,
line_ap,
tangent_line,
# Points
M,
N,
A,
B,
C,
D,
P,
E,
F,
H,
]
Running Examples¶
Generate output from any example file:
# Generate Asymptote source
geolet generate examples/euler_line.py
# Generate PDF
geolet generate examples/euler_line.py -f pdf
# Generate SVG
geolet generate examples/euler_line.py -f svg
List all available examples:
Generate all examples: