2DPGA: Distances and AnglesΒΆ

This example shows how to measure distances and angles, using 2DPGA.

Based on https://enkimute.github.io/ganja.js/examples/coffeeshop.html#pga2d_distances_and_angles.

First we create 2DPGA, and add its basis blades to the local namespace.

[1]:
from kingdon import Algebra
import math
import time

alg = Algebra(2, 0, 1)
locals().update(alg.blades)

Next, make formulas to construct points and lines from coefficients, and to pcalculate distances and angles.

[2]:
# Construct points and lines from coefficients
point = lambda x, y: (e0 + x*e1 + y*e2).dual()
line = lambda a, b, c: a*e1 + b*e2 + c*e0

# Distances between elements in 2D PGA (point to point, point to line),
# are always calculated as the length of their join. (assuming normalization)
# The .e selects the scalar coefficient.
# Use alg.rp instead of x & y such that x and y are allowed to be functions.
def dist(x, y):
    return alg.rp(x, y).normsq().e

# Angles between lines in 2D PGA are calculated using the inner product.
# Again normalized elements are assumed.
def angle(x, y):
    return math.acos(alg.ip(x, y).e)

Construct the points \(A\), \(B\), and \(C\). The point \(A\) is a function so it can be animated.

[3]:
A = lambda: point(-1, -0.5*math.sin(0.5 * time.perf_counter()))
B = point(-1, 1)
C = point(1, 1)

Create the three lines connecting these points and normalize them. Be sure to call \(A\) first since it is a function.

[4]:
AB = lambda: (B & A).normalized()
BC = lambda: (C & B).normalized()
CA = lambda: (C & A).normalized()

We then create functions that calculate the distances between the points and return them as labels (strings):

[5]:
AtoB  = lambda: f"{dist(A, B):.3f}"
BtoC  = lambda: f"{dist(B, C):.3f}"
CtoA  = lambda: f"{dist(C, A):.3f}"
BtoCA = lambda: f"{dist(B, CA):.3f}"

Angles between lines as strings (labels for the points)

[6]:
CAtoAB = lambda: f"{angle(CA, AB) * 180 / math.pi:.3f}"
ABtoBC = lambda: f"{angle(BC, AB) * 180 / math.pi:.3f}"
CAtoBC = lambda: f"{angle(CA, BC) * 180 / math.pi:.3f}"
[7]:
alg.graph(
    "Distances and Angles","Drag the points",       # render title
    0xD0FFE1, [A,B,C],                              # render the triangle
    0x00AA88, AB, AtoB, BC, BtoC, CA, CtoA,         # render edges and lengths.
    0x882288, [B, lambda: B @ CA], BtoCA,         # render projection and dist
    0x224488, A, CAtoAB, B, ABtoBC, C, CAtoBC,      # render verts and angles
    lineWidth=3, grid=True, labels=True, animate=True,
)
[7]:
[ ]: