"""Design probe 2 (headless, reads only): the deck's open edges (the well outline) in plan, the lamp housings, the door's inner-face polyline (local y,z) and the lining's inner contour per x. Writes JSON.""" import bpy, json, sys, bmesh from mathutils import Vector OUT = sys.argv[sys.argv.index("--") + 1] scn = bpy.context.scene for o in bpy.data.objects: if not o.users_scene: scn.collection.objects.link(o) scn.frame_set(1) dg = bpy.context.evaluated_depsgraph_get() rep = {} def bm_world(o): ev = o.evaluated_get(dg) bm = bmesh.new(); bm.from_object(o, dg); bm.transform(ev.matrix_world) return bm deck = bpy.data.objects["Moonpool | deck around open well"] bm = bm_world(deck) edges = [] for e in bm.edges: if len(e.link_faces) < 2 or (e.calc_face_angle(0) > 0.6): a, b = e.verts[0].co, e.verts[1].co edges.append([[round(a.x, 3), round(a.y, 3), round(a.z, 3)], [round(b.x, 3), round(b.y, 3), round(b.z, 3)]]) rep["deck_sharp_edges"] = edges bm.free() # door: local vertices grouped by x columns -> inner face (max y per z row) at the x nearest 0 door = bpy.data.objects["Moonpool_Door_Aft"] vs = [v.co.copy() for v in door.data.vertices] xs = sorted(set(round(v.x, 3) for v in vs)) rep["door_x_columns"] = xs[:5] + ["..."] + xs[-5:] + [len(xs)] # normals of faces on the inner face (pointing +y,+z side) inner = [] for p in door.data.polygons: n = p.normal c = p.center if abs(c.x) < 0.06 and n.z > 0.2 and abs(n.x) < 0.2: inner.append([round(c.y, 4), round(c.z, 4), round(n.y, 4), round(n.z, 4), round(c.x, 4)]) inner.sort() rep["door_inner_faces_x0"] = inner outer = [] for p in door.data.polygons: n = p.normal; c = p.center if abs(c.x) < 0.06 and n.z < -0.2 and abs(n.x) < 0.2: outer.append([round(c.y, 4), round(c.z, 4), round(n.y, 4), round(n.z, 4)]) outer.sort() rep["door_outer_faces_x0"] = outer # door end faces (x extremes): their x and shape rep["door_x_extent"] = [min(v.x for v in vs), max(v.x for v in vs)] # lamps and housings world bbox for nm in ("Moonpool | docking lamp", "Moonpool | docking lamp.001", "Moonpool | recessed docking lamp housing", "Moonpool | recessed docking lamp housing.001"): o = bpy.data.objects[nm] cs = [o.matrix_world @ Vector(c) for c in o.bound_box] rep[nm] = [[min(c[i] for c in cs) for i in range(3)], [max(c[i] for c in cs) for i in range(3)]] # end wall: faces facing into the pocket (normal +x for AFT): their y,z extents near the rail height for nm, sgn in (("Pocket AFT | conformal closed end", 1), ("Pocket FORE | conformal closed end", -1)): o = bpy.data.objects[nm] pts = [] for p in o.data.polygons: n = o.matrix_world.to_3x3() @ p.normal if n.x * sgn > 0.9: c = o.matrix_world @ p.center pts.append([round(c.x, 4), round(c.y, 3), round(c.z, 3)]) rep[nm + " | pocket faces"] = {"n": len(pts), "x": sorted(set(p[0] for p in pts)), "y": [min(p[1] for p in pts), max(p[1] for p in pts)], "z": [min(p[2] for p in pts), max(p[2] for p in pts)]} json.dump(rep, open(OUT, "w")) print("PROBE2 DONE")