Files
blender-portable-repo/scripts/addons/TexTools_1_6_1/utilities_bbox.py
T
2026-03-17 14:30:01 -06:00

190 lines
3.8 KiB
Python

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