144 lines
3.6 KiB
Python
144 lines
3.6 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)
|
|
|
|
points = []
|
|
lines = []
|
|
|
|
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
|
|
sqr = x_0*x_0 - x_1*x_1 - x_2*x_2
|
|
if sqr < 0:
|
|
return
|
|
norm = math.sqrt(sqr)
|
|
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.
|
|
theta = math.atan2(line.e1, line.e2)
|
|
start_x = int(CENTER_X-DISK_RADIUS*math.cos(theta))
|
|
start_y = int(CENTER_Y-DISK_RADIUS*math.sin(theta))
|
|
end_x = int(CENTER_X+DISK_RADIUS*math.cos(theta))
|
|
end_y = int(CENTER_Y+DISK_RADIUS*math.sin(theta))
|
|
pygame.draw.line(screen, BLUE, (start_x, start_y), (end_x, end_y), 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)
|
|
|
|
def simulation(t):
|
|
lines.clear()
|
|
points.clear()
|
|
lines.append(y_axis)
|
|
lines.append(x_axis)
|
|
points.append(origin)
|
|
|
|
x_motor = tx_generator.exp()
|
|
y_motor = ty_generator.exp()
|
|
|
|
generator = math.sin(t)*tx_generator + math.sin(math.sqrt(2)*t)*ty_generator + math.sin(math.sqrt(3)*t)*origin
|
|
m = generator.exp()
|
|
y_tick = m*y_axis*m.reverse()
|
|
x_tick = m*x_axis*m.reverse()
|
|
lines.append(y_tick)
|
|
lines.append(x_tick)
|
|
points.append(y_tick^x_tick)
|
|
|
|
for i in range(13):
|
|
for j in range(13):
|
|
motor_x = ((i-6)*tx_generator/10).exp()
|
|
motor_y = ((j-6)*ty_generator/10).exp()
|
|
y_tick = m * motor_x * y_axis * motor_x.reverse() * m.reverse()
|
|
x_tick = m * motor_y * x_axis * motor_y.reverse() * m.reverse()
|
|
lines.append(y_tick)
|
|
lines.append(x_tick)
|
|
points.append(y_tick^x_tick)
|
|
|
|
|
|
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
|
|
|
|
lines.append(x_axis)
|
|
lines.append(y_axis)
|
|
while running:
|
|
t += 0.0002
|
|
# Clear the screen
|
|
screen.fill(WHITE)
|
|
|
|
#Poincare Disk Boundary
|
|
pygame.draw.circle(screen, BLACK, (CENTER_X, CENTER_Y), DISK_RADIUS, 1)
|
|
|
|
simulation(t)
|
|
for line in lines:
|
|
draw_line(line)
|
|
for point in points:
|
|
draw_point(point)
|
|
|
|
for event in pygame.event.get():
|
|
if event.type == pygame.QUIT:
|
|
running = False
|
|
|
|
# Update the display
|
|
pygame.display.flip()
|
|
|
|
# Quit Pygame
|
|
pygame.quit()
|