geom-demo/geom/geom.py

141 lines
4.0 KiB
Python

from .math import *
from .draw import *
import numpy as np
from math import pi, sin, cos
class AxisAlignedBB:
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.height = height
self.width = width
self.update()
def update(self):
self.min_x = self.x
self.min_y = self.y
self.max_x = self.x + self.width
self.max_y = self.y + self.height
self.min = (self.min_x, self.min_y)
self.max = (self.max_x, self.max_y)
self.halfwidth = self.width / 2
self.halfheight = self.height / 2
self.cx = self.x + self.halfwidth
self.cy = self.y + self.halfheight
self.vertices = [
(self.x, self.y),
(self.x + self.width, self.y),
(self.x + self.width, self.y + self.height),
(self.x, self.y + self.height)
]
self.segments = [
(self.vertices[0], self.vertices[1]),
(self.vertices[1], self.vertices[2]),
(self.vertices[2], self.vertices[3]),
(self.vertices[3], self.vertices[0]),
]
def get_center(self):
return (self.cx, self.cy)
def get_center_px(self):
return (int(self.cx), int(self.cy))
def contains(self, x, y):
return (x >= self.min_x and x <= self.max_x
and y >= self.min_y and y <= self.max_y)
def draw(self, surface, colour, width):
pixel(surface, colour, *self.get_center())
rect(surface, colour, self.x, self.y, self.width, self.height, width)
class Polygon:
def __init__(self, x, y, vertices, rotation=0, origin_x=0, origin_y=0):
self.x = x
self.y = y
self.vertices = vertices
self.rotation = rotation
self.length = len(vertices)
self.origin_x = origin_x
self.origin_y = origin_y
self.update_transformation()
self.update()
def update(self):
self.translated_vertices = [
(self.x + x, self.y + y)
for x, y in self.transformed_vertices
]
self.segments = [
(self.translated_vertices[i],
self.translated_vertices[i + 1 if i + 1 < self.length else 0])
for i in range(self.length)
]
self.normals = [
normalize(*lnormal(*sub(*v2, *v1)))
for v1, v2 in self.segments
]
def update_transformation(self):
if self.rotation != 0:
rads = math.radians(self.rotation)
rot_matrix = np.array([[math.cos(rads), -math.sin(rads)],
[math.sin(rads), math.cos(rads)]])
self.transformed_vertices = [
add(*rot_matrix.dot(sub(x, y, self.origin_x, self.origin_y)),
self.origin_x, self.origin_y)
for x, y in self.vertices
]
else:
self.transformed_vertices = [
(self.origin_x + x, self.origin_y + y)
for x, y in self.vertices
]
def set_position(self, x, y):
self.x = x
self.y = y
self.update()
def set_rotation(self, rotation):
self.rotation = rotation
self.update_transformation()
def rotate(self, degrees):
self.set_rotation(self.rotation + degrees)
def get_normals(self):
return self.normals
def get_translated_vertices(self):
return self.translated_vertices
def get_vertices(self):
return self.transformed_vertices
def get_segments(self):
return self.segments
def draw(self, surface, colour, width):
polygon(surface, colour, self.translated_vertices, width)
pixel(surface, colour, self.x, self.y)
def generate_polygon(x, y, rotation=0, sides=3, radius=15):
theta = (2 * pi) / sides
return Polygon(x, y, [
scale(cos((2 * pi) - i * theta),
sin((2 * pi) - i * theta),
radius)
for i in range(sides)
], rotation)