mirror of
https://github.com/ksherlock/prez.git
synced 2024-09-27 05:54:33 +00:00
395 lines
8.8 KiB
Python
395 lines
8.8 KiB
Python
# point(h,v) or point(x=.., y=..)
|
|
|
|
import struct
|
|
|
|
__all__ = ['point', 'rect', 'size']
|
|
|
|
|
|
# struct Point {
|
|
# short v;
|
|
# short h;
|
|
# };
|
|
|
|
# struct Rect {
|
|
# short v1;
|
|
# short h1;
|
|
# short v2;
|
|
# short h2;
|
|
# };
|
|
|
|
def all_defined(*args): return args.count(None)==0
|
|
def all_none(*args): return args.count(None)==len(args)
|
|
def is_listy(x): return type(x) in (tuple, list)
|
|
|
|
|
|
def old_point(*args, x=None, y=None, h=None, v=None):
|
|
|
|
if len(args) == 2: return args
|
|
|
|
if len(args) == 1:
|
|
a, = args
|
|
if is_listy(a) and len(a) == 2:
|
|
return a
|
|
|
|
if not args:
|
|
if all_defined(x,y): return (y, x)
|
|
if all_defined(h,v): return (v, h)
|
|
raise ValueError("bad point parameter")
|
|
|
|
|
|
class point_class:
|
|
"""docstring for point_class"""
|
|
__slots__ = ('x', 'y')
|
|
def __init__(self, *args, x=None, y=None, h=None, v=None):
|
|
self.x = 0
|
|
self.y = 0
|
|
|
|
if len(args) == 2:
|
|
self._assign(*args)
|
|
return
|
|
|
|
if len(args) == 1:
|
|
other = args[0]
|
|
if (type(other) == point_class):
|
|
self.x = other.x;
|
|
self.y = other.y
|
|
return
|
|
|
|
if is_listy(other) and len(other) == 2:
|
|
self._assign(*other)
|
|
return
|
|
|
|
if not args:
|
|
if all_defined(x,y):
|
|
self.x = x
|
|
self.y = y
|
|
return
|
|
if all_defined(h,v):
|
|
self.x = h
|
|
self.y = v
|
|
return
|
|
|
|
raise ValueError("bad point parameter")
|
|
|
|
def _assign(self, v, h):
|
|
self.x = h
|
|
self.y = v
|
|
|
|
def __str__(self):
|
|
return "{{ {:d}, {:d} }}".format(self.y, self.x)
|
|
|
|
def __bytes__(self):
|
|
return struct.pack("2H", self.y, self.x)
|
|
|
|
def __iter__(self):
|
|
return (self.y, self.x).__iter__()
|
|
|
|
def __eq__(self, other):
|
|
return type(other) == point_class and self.x == other.x and self.y == other.y
|
|
|
|
def __add__(self, other):
|
|
if type(other) != point_class: ValueError("bad point parameter")
|
|
return point_class(x = self.x + other.x, y = self.y + other.y)
|
|
|
|
def __sub__(self, other):
|
|
if type(other) != point_class: ValueError("bad point parameter")
|
|
return point_class(x = self.x - other.x, y = self.y - other.y)
|
|
|
|
|
|
class size_class:
|
|
__slots__ = ('height', 'width')
|
|
def __init__(self, *args, height=None, width=None):
|
|
|
|
self.height = 0
|
|
self.width = 0
|
|
|
|
if len(args) == 2:
|
|
self._assign(*args)
|
|
return
|
|
|
|
if len(args) == 1:
|
|
other = args[0]
|
|
if type(other) == size_class:
|
|
self.height = other.height
|
|
self.width = other.width
|
|
return
|
|
|
|
if is_listy(other) and len(other) == 2:
|
|
self._assign(*other)
|
|
return
|
|
|
|
if not args:
|
|
if all_defined(height,width):
|
|
self.height = height
|
|
self.width = width
|
|
return
|
|
|
|
raise ValueError("bad size parameter")
|
|
|
|
def _assign(self, height, width):
|
|
self.height = height
|
|
self.width = width
|
|
|
|
def __eq__(self, other):
|
|
return type(other) == size_class and self.height == other.height and self.width == other.width
|
|
|
|
def __str__(self):
|
|
return "{{ {:d}, {:d} }}".format(self.height, self.width)
|
|
|
|
def __bytes__(self):
|
|
return struct.pack("2H", self.height, self.width)
|
|
|
|
def __iter__(self):
|
|
return (self.height, self.width).__iter__()
|
|
|
|
|
|
def old_size(*args, height=None, width=None):
|
|
|
|
if len(args) == 2: return args
|
|
|
|
if len(args) == 1:
|
|
a, = args
|
|
if is_listy(a) and len(a) == 2:
|
|
return a
|
|
|
|
if not args:
|
|
if all_defined(height,width): return (height, width)
|
|
raise ValueError("bad size parameter")
|
|
|
|
|
|
def old_rect(*args,
|
|
x=None,y=None,height=None,width=None,
|
|
h1=None,h2=None,v1=None,v2=None,
|
|
top=None,left=None,right=None,bottom=None):
|
|
|
|
if len(args) == 4: return args
|
|
|
|
if len(args) == 2:
|
|
a, b = args
|
|
if is_listy(a) and is_listy(b):
|
|
if len(a) == 2 and len(b) == 2:
|
|
return ( *a, *b )
|
|
|
|
if len(args) == 1:
|
|
a, = args
|
|
if is_listy(a) and len(a) == 4: return a
|
|
|
|
if not args:
|
|
if all_defined(x,y,height,width):
|
|
return (y, x, y + height, x + width)
|
|
if all_defined(h1,h2,v1,v2):
|
|
return (v1, h1, v2, h2)
|
|
if all_defined(top,left,bottom,right):
|
|
return (top, left, bottom, right)
|
|
|
|
raise ValueError("bad rect parameter")
|
|
|
|
|
|
class rect_class:
|
|
__slots__ = ('x', 'y', 'height', 'width')
|
|
def __init__(self, *args,
|
|
x=None,y=None,height=None,width=None,
|
|
h1=None,h2=None,v1=None,v2=None,
|
|
top=None,left=None,right=None,bottom=None):
|
|
|
|
self.x = 0
|
|
self.y = 0
|
|
self.height = 0
|
|
self.width = 0
|
|
|
|
if len(args) == 4:
|
|
self._assign(*args)
|
|
return
|
|
|
|
if len(args) == 2:
|
|
a, b = args
|
|
if type(a) == point_class and type(b) == point_class:
|
|
self.x = a.x
|
|
self.y = a.y
|
|
self.width = b.x - a.x
|
|
self.height = b.y - a.y
|
|
return
|
|
|
|
if type(a) == point_class and type(b) == size_class:
|
|
self.x = a.x
|
|
self.y = a.y
|
|
self.height = b.height
|
|
self.width = b.width
|
|
return
|
|
|
|
if is_listy(a) and is_listy(b):
|
|
if len(a) == 2 and len(b) == 2:
|
|
self._assign(*a, *b)
|
|
return
|
|
|
|
if len(args) == 1:
|
|
args = args[0]
|
|
if type(args) == rect_class:
|
|
self.x = args.x
|
|
self.y = args.y
|
|
self.height = args.height
|
|
self.width = args.width
|
|
return
|
|
|
|
if is_listy(args) and len(args) == 4:
|
|
self._assign(*args)
|
|
return
|
|
|
|
if not args:
|
|
if all_defined(x,y,height,width):
|
|
self.x = x
|
|
self.y = y
|
|
self.height = height
|
|
self.width = width
|
|
return
|
|
|
|
if all_defined(h1,h2,v1,v2):
|
|
self._assign(v1, h1, v2, h2)
|
|
return
|
|
|
|
if all_defined(top,left,bottom,right):
|
|
self._assign(top, left, bottom, right)
|
|
return
|
|
|
|
raise ValueError("bad rect parameter")
|
|
|
|
|
|
def _assign(self, v1, h1, v2, h2):
|
|
self.x = h1
|
|
self.y = v1
|
|
self.width = h2 - h1
|
|
self.height = v2 - v1
|
|
|
|
def center(self, width = 640, height = 200):
|
|
x = (width - self.width) // 2
|
|
y = (height - self.height) // 2
|
|
return self.offset_to(x, y)
|
|
|
|
|
|
def center_640(self):
|
|
x = (640 - self.width) // 2
|
|
y = (200 - self.height) // 2
|
|
return self.offset_to(x, y)
|
|
|
|
def center_320(self):
|
|
x = (320 - self.width) // 2
|
|
y = (200 - self.height) // 2
|
|
return self.offset_to(x, y)
|
|
|
|
def inset_by(self, horizontal, vertical):
|
|
return rect_class(
|
|
x = self.x + horizontal,
|
|
y = self.y + vertical,
|
|
width = self.width - horizontal * 2,
|
|
height = self.height - vertical * 2
|
|
)
|
|
|
|
def offset_to(self, x, y):
|
|
return rect_class(
|
|
x = x,
|
|
y = y,
|
|
width = self.width,
|
|
height = self.height
|
|
)
|
|
|
|
def offset_by(self, horizontal, vertical):
|
|
return rect_class(
|
|
x = self.x + horizontal,
|
|
y = self.y + vertical,
|
|
width = self.width,
|
|
height = self.height
|
|
)
|
|
|
|
def top_left(self):
|
|
return point_class(x = self.x, y = self.y)
|
|
|
|
def top_right(self):
|
|
return point_class(x = self.x + self.width, y = self.y)
|
|
|
|
def bottom_left(self):
|
|
return point_class(x = self.x, y = self.y + self.height)
|
|
|
|
|
|
def bottom_right(self):
|
|
return point_class(x = self.x + self.width, y = self.y + self.height)
|
|
|
|
def split_horizontal(self, where):
|
|
|
|
if where < 0: where = self.width + where
|
|
where = max(0, min(self.width, where))
|
|
|
|
l = rect_class(x = self.x, y = self.y, height = self.height, width = where)
|
|
r = rect_class(x = where, y = self.y, height = self.height, width = self.width - where)
|
|
|
|
return l, r
|
|
|
|
def split_vertical(self, where):
|
|
|
|
if where < 0: where = self.height + where
|
|
where = max(0, min(self.height, where))
|
|
|
|
l = rect_class(x = self.x, y = self.y, height = where, width = self.width)
|
|
r = rect_class(x = self.x, y = where, height = self.height - where, width = self.width)
|
|
|
|
return l, r
|
|
|
|
|
|
|
|
def __str__(self):
|
|
return "{{ {:d}, {:d}, {:d}, {:d} }}".format(self.y, self.x, self.y + self.height, self.x + self.width)
|
|
|
|
def __bytes__(self):
|
|
return struct.pack("4H", self.y, self.x, self.y + self.height, self.x + self.width)
|
|
|
|
def __iter__(self):
|
|
return (self.y, self.x, self.y + self.height, self.x + self.width).__iter__()
|
|
|
|
def __eq__(self, other):
|
|
return type(other) == rect_class and \
|
|
self.x == other.x and self.y == other.y and \
|
|
self.width == other.width and self.height == other.height
|
|
|
|
def __bool__(self):
|
|
# check if valid
|
|
return self.width >= 0 and self.height >= 0
|
|
|
|
def __and__(self, other):
|
|
# intersection
|
|
if type(other) != rect_class: ValueError("bad rect parameter")
|
|
|
|
x1 = max(self.x, other.x)
|
|
y1 = max(self.y, other.y)
|
|
x2 = min(self.x + self.width, other.x + other.width)
|
|
y2 = min(self.y + self.height, other.y + other.height)
|
|
|
|
return rect_class(v1 = y1, h1 = x1, v2 = y2, h2 = x2)
|
|
|
|
def __or__(self, other):
|
|
# union
|
|
if type(other) != rect_class: ValueError("bad rect parameter")
|
|
|
|
x1 = min(self.x, other.x)
|
|
y1 = min(self.y, other.y)
|
|
x2 = max(self.x + self.width, other.x + other.width)
|
|
y2 = max(self.y + self.height, other.y + other.height)
|
|
|
|
return rect_class(v1 = y1, h1 = x1, v2 = y2, h2 = x2)
|
|
|
|
def __add__(self, other):
|
|
if type(other) == size_class:
|
|
return rect_class(x = self.x, y = self.y, height = self.height + other.height, width = self.width + other.width)
|
|
|
|
raise ValueError("bad parameter")
|
|
|
|
def __sub__(self, other):
|
|
if type(other) == size_class:
|
|
return rect_class(x = self.x, y = self.y, height = self.height - other.height, width = self.width - other.width)
|
|
|
|
raise ValueError("bad parameter")
|
|
|
|
|
|
|
|
point = point_class
|
|
rect = rect_class
|
|
size = size_class
|