2025-07-01
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
import math
|
||||
from mathutils import Vector
|
||||
|
||||
|
||||
class BBox:
|
||||
@classmethod
|
||||
def calc_bbox(cls, coords):
|
||||
xmin = math.inf
|
||||
xmax = -math.inf
|
||||
ymin = math.inf
|
||||
ymax = -math.inf
|
||||
|
||||
for x, y in coords:
|
||||
if xmin > x:
|
||||
xmin = x
|
||||
if xmax < x:
|
||||
xmax = x
|
||||
if ymin > y:
|
||||
ymin = y
|
||||
if ymax < y:
|
||||
ymax = y
|
||||
return cls(xmin, xmax, ymin, ymax)
|
||||
|
||||
@classmethod
|
||||
def calc_bbox_uv(cls, group, uv_layers, are_loops=False):
|
||||
xmin = math.inf
|
||||
xmax = -math.inf
|
||||
ymin = math.inf
|
||||
ymax = -math.inf
|
||||
|
||||
if not are_loops:
|
||||
for face in group:
|
||||
for loop in face.loops:
|
||||
x, y = loop[uv_layers].uv
|
||||
if xmin > x:
|
||||
xmin = x
|
||||
if xmax < x:
|
||||
xmax = x
|
||||
if ymin > y:
|
||||
ymin = y
|
||||
if ymax < y:
|
||||
ymax = y
|
||||
else:
|
||||
for loop in group:
|
||||
x, y = loop[uv_layers].uv
|
||||
if xmin > x:
|
||||
xmin = x
|
||||
if xmax < x:
|
||||
xmax = x
|
||||
if ymin > y:
|
||||
ymin = y
|
||||
if ymax < y:
|
||||
ymax = y
|
||||
return cls(xmin, xmax, ymin, ymax)
|
||||
|
||||
@classmethod
|
||||
def init_from_minmax(cls, min, max):
|
||||
bbox = cls(min[0], max[0], min[1], max[1])
|
||||
bbox.sanitize()
|
||||
return bbox
|
||||
|
||||
def __init__(self, xmin=math.inf, xmax=-math.inf, ymin=math.inf, ymax=-math.inf):
|
||||
self.xmin = xmin
|
||||
self.xmax = xmax
|
||||
self.ymin = ymin
|
||||
self.ymax = ymax
|
||||
|
||||
def __str__(self):
|
||||
return f"xmin={self.xmin:.6}, xmax={self.xmax:.6}, ymin={self.ymin:.6}, ymax={self.ymax:.6}, width={self.width:.6}, height={self.height:.6}"
|
||||
|
||||
@property
|
||||
def is_valid(self) -> bool:
|
||||
return (self.xmin < self.xmax) and (self.ymin < self.ymax)
|
||||
|
||||
@property
|
||||
def max(self):
|
||||
return Vector((self.xmax, self.ymax))
|
||||
|
||||
@property
|
||||
def min(self):
|
||||
return Vector((self.xmin, self.ymin))
|
||||
|
||||
@property
|
||||
def left_upper(self):
|
||||
return Vector((self.xmin, self.ymax))
|
||||
|
||||
@property
|
||||
def left_bottom(self):
|
||||
return Vector((self.xmin, self.ymin))
|
||||
|
||||
@property
|
||||
def right_bottom(self):
|
||||
return Vector((self.xmax, self.ymin))
|
||||
|
||||
@property
|
||||
def right_upper(self):
|
||||
return Vector((self.xmax, self.ymax))
|
||||
|
||||
@property
|
||||
def upper(self):
|
||||
return Vector(((self.xmin + self.xmax) * 0.5, self.ymax))
|
||||
|
||||
@property
|
||||
def bottom(self):
|
||||
return Vector(((self.xmin + self.xmax) * 0.5, self.ymin))
|
||||
|
||||
@property
|
||||
def left(self):
|
||||
return Vector((self.xmin, (self.ymin + self.ymax) * 0.5))
|
||||
|
||||
@property
|
||||
def right(self):
|
||||
return Vector((self.xmax, (self.ymin + self.ymax) * 0.5))
|
||||
|
||||
@property
|
||||
def center(self):
|
||||
return Vector(((self.xmin + self.xmax) * 0.5, (self.ymin + self.ymax) * 0.5))
|
||||
|
||||
@property
|
||||
def width(self) -> float:
|
||||
return self.xmax - self.xmin
|
||||
|
||||
@property
|
||||
def height(self) -> float:
|
||||
return self.ymax - self.ymin
|
||||
|
||||
@property
|
||||
def max_lenght(self):
|
||||
return max(self.width, self.height)
|
||||
|
||||
@property
|
||||
def min_lenght(self):
|
||||
return min(self.width, self.height)
|
||||
|
||||
@property
|
||||
def half_width(self) -> float:
|
||||
return (self.xmax - self.xmin) * 0.5
|
||||
|
||||
@property
|
||||
def half_height(self) -> float:
|
||||
return (self.ymax - self.ymin) * 0.5
|
||||
|
||||
@property
|
||||
def area(self):
|
||||
return self.width * self.height
|
||||
|
||||
@property
|
||||
def is_empty(self) -> bool:
|
||||
return (self.xmax <= self.xmin) or (self.ymax <= self.ymin)
|
||||
|
||||
def union(self, other):
|
||||
if self.xmin > other.xmin:
|
||||
self.xmin = other.xmin
|
||||
if self.xmax < other.xmax:
|
||||
self.xmax = other.xmax
|
||||
if self.ymin > other.ymin:
|
||||
self.ymin = other.ymin
|
||||
if self.ymax < other.ymax:
|
||||
self.ymax = other.ymax
|
||||
return self
|
||||
|
||||
def sanitize(self):
|
||||
if self.xmin > self.xmax:
|
||||
self.xmin, self.xmax = self.xmax, self.xmin
|
||||
if self.ymin > self.ymax:
|
||||
self.ymin, self.ymax = self.ymax, self.ymin
|
||||
# assert self.is_valid
|
||||
return self
|
||||
|
||||
def do_minmax_v(self, xy):
|
||||
if xy[0] < self.xmin:
|
||||
self.xmin = xy[0]
|
||||
if xy[0] > self.xmax:
|
||||
self.xmax = xy[0]
|
||||
if xy[1] < self.ymin:
|
||||
self.ymin = xy[1]
|
||||
if xy[1] > self.ymax:
|
||||
self.ymax = xy[1]
|
||||
|
||||
def update(self, coords):
|
||||
for x, y in coords:
|
||||
if x < self.xmin:
|
||||
self.xmin = x
|
||||
if x > self.xmax:
|
||||
self.xmax = x
|
||||
if y < self.ymin:
|
||||
self.ymin = y
|
||||
if y > self.ymax:
|
||||
self.ymax = y
|
||||
Reference in New Issue
Block a user