Files
Python-Geometric-Algebra/main.py

132 lines
3.3 KiB
Python

import pygame
from kingdon import Algebra
import math
ERROR = 0.00001
DISK_RADIUS = 250
WIDTH, HEIGHT = 800, 600
CENTER_X, CENTER_Y = 400, 300
alg = Algebra(2,1,0)
locals().update(alg.blades)
def point(x,y):
#Construct a point.
#Hyperbolic space is modeled as a hyperboloid embedded in 3D Minkowski space.
#Find w such that x,y,w is a point on the hyperboloid.
w_sqr = x*x + y*y + 1
w = math.sqrt(w_sqr)
return x*e23 -y*e13 + w*e12
def draw_point(point):
#Normalize the point
x_0 = point.e12
x_1 = -point.e23
x_2 = point.e13
norm = math.sqrt(x_0*x_0 - x_1*x_1 - x_2*x_2)
x_0 = x_0/norm
x_1 = x_1/norm
x_2 = x_2/norm
#Transform it into the Poincare Space
u = x_1/(1+x_0)
v = x_2/(1+x_0)
pygame.draw.circle(screen, RED, (int(u*DISK_RADIUS+CENTER_X), int(v*DISK_RADIUS+CENTER_Y)), 5)
def draw_line(line):
delta = line.e3
if abs(delta) < ERROR:
# The geodesic is a line through the origin.
if abs(line.e2) < ERROR:
pygame.draw.line(screen, BLUE, (CENTER_X, CENTER_Y+DISK_RADIUS), (CENTER_X, CENTER_Y-DISK_RADIUS), 1)
else:
slope = line.e1/line.e2
pygame.draw.line(screen, BLUE, (CENTER_X-DISK_RADIUS, int(CENTER_Y-slope*DISK_RADIUS)), (CENTER_X+DISK_RADIUS, int(CENTER_Y+slope*DISK_RADIUS)), 1)
else:
#The geodesic is a circle
a = line.e1
b = line.e2
sqr = a*a + b*b
norm = math.sqrt(sqr)
x_c = a/delta
y_c = b/delta
r = math.sqrt(x_c*x_c+y_c*y_c - 1)
c_x = int(CENTER_X + x_c*DISK_RADIUS)
c_y = int(CENTER_Y + y_c*DISK_RADIUS)
pygame.draw.circle(screen, BLUE, (c_x, c_y), int(r*DISK_RADIUS), 1)
y_axis = e1 #x = 0 line
x_axis = e2 #y = 0 line
tx_generator = e13 #A translation in the x direction
ty_generator = e23 #A translation in the y direction
origin = e12 #The origin, and a rotation about the origin
# Initialize Pygame
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Pygame Example")
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
# Game loop
running = True
t = 0
while running:
t += 0.0002
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Clear the screen
screen.fill(WHITE)
#Poincare Disk Boundary
pygame.draw.circle(screen, BLACK, (CENTER_X, CENTER_Y), DISK_RADIUS, 1)
#Generate a transformation for demonstration
transform = math.sin(t)*tx_generator + math.sin(math.sqrt(2)*t)*ty_generator + math.sin(math.sqrt(3)*t)*origin
transform = transform
motor = transform.exp()
#Apply the transformation
y_tick = motor*y_axis*motor.reverse()
x_tick = motor*x_axis*motor.reverse()
#Construct a point as the intersection of the two lines
point = y_tick^x_tick
#Draw everything
draw_line(y_tick)
draw_line(x_tick)
draw_point(point)
tx = tx_generator.exp()
ty = ty_generator.exp()
point_a = tx*ty*origin*ty.reverse()*tx.reverse()
point_b = ty*tx*origin*tx.reverse()*ty.reverse()
draw_line(x_axis)
draw_line(y_axis)
draw_point(origin)
draw_point(point_a)
draw_point(point_b)
# Update the display
pygame.display.flip()
# Quit Pygame
pygame.quit()