# -*- 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