kararrr/layer.py

110 lines
3.5 KiB
Python

# -*- coding: utf-8 -*-
# Copyright (C) 2014 Chris Hinsley All Rights Reserved
# Copyright (C) 2022 Jeff Moe
import math, mymath
class Layer():
def __init__(self, dimensions, scale):
self.width, self.height = dimensions
self.scale = scale
self.buckets = [[] for x in range(self.width * self.height)]
self.test = 0
def aabb(self, line):
x1, y1, x2, y2, r, g = line
if x1 > x2:
x1, x2 = x2, x1
if y1 > y2:
y1, y2 = y2, y1
r += g
minx = int(math.floor((x1 - r) * self.scale))
miny = int(math.floor((y1 - r) * self.scale))
maxx = int(math.ceil((x2 + r) * self.scale))
maxy = int(math.ceil((y2 + r) * self.scale))
if minx < 0:
minx = 0
if miny < 0:
miny = 0
if maxx > self.width:
maxx = self.width
if maxy > self.height:
maxy = self.height
return (minx, miny, maxx, maxy)
def all_buckets(self, aabb):
x1, y1, x2, y2 = aabb
for y in range(y1, y2):
for x in range(x1, x2):
yield self.buckets[y * self.width + x]
def all_not_empty_buckets(self, aabb):
x1, y1, x2, y2 = aabb
for y in range(y1, y2):
for x in range(x1, x2):
bucket = self.buckets[y * self.width + x]
if bucket:
yield bucket
def add_line(self, line):
new_record = [0, line]
for bucket in self.all_buckets(self.aabb(line)):
found = False
for record in bucket:
if record[1] == line:
found = True
break
if not found:
bucket.append(new_record)
def sub_line(self, line):
for bucket in self.all_not_empty_buckets(self.aabb(line)):
for i in range(len(bucket) - 1, -1, -1):
if bucket[i][1] == line:
del bucket[i]
def hit_line(self, line):
self.test += 1
for bucket in self.all_not_empty_buckets(self.aabb(line)):
for record in bucket:
if record[0] != self.test:
record[0] = self.test
l1_p1x, l1_p1y, l1_p2x, l1_p2y, l1_r, l1_g = line
l2_p1x, l2_p1y, l2_p2x, l2_p2y, l2_r, l2_g = record[1]
r = l1_r + l2_r + max(l1_g, l2_g)
if mymath.collide_thick_lines_2d((l1_p1x, l1_p1y), (l1_p2x, l1_p2y), (l2_p1x, l2_p1y), (l2_p2x, l2_p2y), r):
return True
return False
class Layers():
def __init__(self, dimensions, scale):
width, height, self.depth = dimensions
self.layers = [Layer((width, height), scale) for z in range(self.depth)]
def all_layers(self, z1, z2):
if z1 != z2:
for z in range(self.depth):
yield self.layers[z]
else:
yield self.layers[int(z1)]
def add_line(self, p1, p2, r, g):
x1, y1, z1 = p1
x2, y2, z2 = p2
for layer in self.all_layers(z1, z2):
layer.add_line((x1, y1, x2, y2, r, g))
def sub_line(self, p1, p2, r, g):
x1, y1, z1 = p1
x2, y2, z2 = p2
for layer in self.all_layers(z1, z2):
layer.sub_line((x1, y1, x2, y2, r, g))
def hit_line(self, p1, p2, r, g):
x1, y1, z1 = p1
x2, y2, z2 = p2
for layer in self.all_layers(z1, z2):
if layer.hit_line((x1, y1, x2, y2, r, g)):
return True
return False