"""Clearance of the kit's moving parts through their whole travel (memory: moving-parts-checked-through-their-travel). Each moving part is turned about its axis in steps; at every step its triangles (world space) are tested against its own part's static mesh. TRAVEL: degrees, sign = the opening direction worked out from where the part lies.""" import math import bpy from mathutils import Matrix from mathutils.bvhtree import BVHTree TRAVEL = {"Hatch": (0, -110), "Lid": (0, 110), "Leaf": (0, 120), "FanRotor": (0, 360)} def _tree(ob, M): me = ob.data vs = [M @ v.co for v in me.vertices] return BVHTree.FromPolygons(vs, [tuple(p.vertices) for p in me.polygons]) def check(steps=24): out = {} for ch in bpy.data.collections["MPK | Parts"].objects: suf = ch.name.rsplit("_", 1)[-1] if ch.parent is None or suf not in TRAVEL: continue base = ch.parent tb = _tree(base, base.matrix_world) a0, a1 = TRAVEL[suf] hits = [] for i in range(steps + 1): a = math.radians(a0 + (a1 - a0) * i / steps) R = Matrix.Rotation(a, 4, ch["mpk_axis"]) M = base.matrix_world @ Matrix.Translation(ch.location) @ R n = len(_tree(ch, M).overlap(tb)) if n: hits.append((round(math.degrees(a)), n)) out[ch.name] = hits or "clear" return out