"""Mako: read-only probe of models/docking-arm/DockArm_Carousel.blend (never saved). The clamp head's envelope in the Tender's frame (clamp axis at the origin of this table, z over the Tender origin), claws shut and open, at BOARD: for each 5 cm band of height, the largest horizontal distance of any part of the head, claws, links and hose from the clamp axis, and the largest distance along the Tender's length (both headings). Used to place the dorsal fin before the clamp check proper. Writes checks/arm_envelope.json.""" import bpy, os, json, math from mathutils import Vector HERE = os.path.dirname(os.path.abspath(__file__)) arm = bpy.data.objects["Arm1"] parts = [o for o in bpy.data.objects if o.type == 'MESH' and (o.name.startswith("Arm1_") or o.name == "SM_DockArm_Turret")] dg = bpy.context.evaluated_depsgraph_get() out = {} for claw in (0.0, 1.0): arm["lower_m"] = 5.3 arm["claw_open"] = claw for ob in bpy.data.objects: if ob.name.startswith("Arm1"): ob.update_tag() bpy.context.view_layer.update() dg.update() head = bpy.data.objects["Arm1_Head"].matrix_world ax = head.translation.copy() # the clamp axis: under the wrist zt = ax.z - 1.94 # Tender origin height bands = {} for o in parts: ev = o.evaluated_get(dg) me = ev.to_mesh() M = ev.matrix_world for v in me.vertices: p = M @ v.co z = p.z - zt if z > 3.2: continue r = math.hypot(p.x - ax.x, p.y - ax.y) b = round(math.floor(z / 0.05) * 0.05, 2) e = bands.setdefault(b, {"r": 0.0, "part": ""}) if r > e["r"] and r < 2.5: e["r"] = round(r, 3); e["part"] = o.name ev.to_mesh_clear() out["claws_open" if claw else "claws_shut"] = {"%.2f" % k: bands[k] for k in sorted(bands)} json.dump(out, open(os.path.join(HERE, "checks", "arm_envelope.json"), "w"), indent=0) for k, v in out.items(): print("ENV", k, " ".join("%s:%.2f" % (z, e["r"]) for z, e in v.items() if float(z) <= 3.0))