Getting data from imported window geometry

I have imported windows from a CAD-tool (Revit) including framing that are almost planar rectangular meshes and I need to write some key metrics to a textfile for each window. The data I need is midpoint, width, height and normal direction for each window. Normal direction could be inverted and height is determined by Z-axes (the lower part of the window is allways is the X-Y plane). I am thinking of creating a bounding box to get midpoint and width but that does not take me all the way.

A file with a few examples of windows from Revit can be found at https://github.com/maxtillberg/BlenderICE/blob/main/windows.blend Note that this includes a non rectangular window that should (if possible) be treated like a rectangular and one wndow have separate window panes and are actually two meshes (sigh).

This is what I got

import bpy from mathutils import Vector

selected = bpy.context.selected_objects

for obj in selected:
#ensure origin is centered on bounding box center
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS')
#create a cube for the bounding box
#our new cube is now the active object, so we can keep track of it in a variable:
bound_box = bpy.context.active_object

#copy transforms
bound_box.dimensions = obj.dimensions
bound_box.location = obj.location
bound_box.rotation_euler = obj.rotation_euler
print (obj.location)
print (obj.dimensions)
centre = sum((Vector(b) for b in bound_box.bound_box), Vector())
centre /= 8
print(centre)

• So what precisely doesn't work? First you set origin to be in the center of bounds, and then you average the corner of the bounds to get the... Center, which is simply the ob.location or locally 0? Also, why create the cube and not just operate directly on an object? Commented Jun 20, 2022 at 17:22

Hard to suggest something without seeing the actual data, but I would try something like this:

import bpy
from bpy import context as C

for ob in C.selected_objects:
#ensure origin is centered on bounding box center
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS')
centre = 0  # doesn't it achieve what you do?
faces_up = (p for p in ob.data.polygons if p.normal.z > 0)
normal = max(faces_up, key=lambda f: f.area).normal
verts = ob.data.vertices
width = max(v.co.x for v in verts) - min(v.co.x for v in verts)
height = max(v.co.z for v in verts) - min(v.co.z for v in verts)
print(f"\n--\n{ob.name}:\n{centre=}\n{normal=}\n{width=}\n{height=}")

• Thanks a lot Markus, that was a great start! You are right is was much better to operate directly on the object. As far as I can tell the height and width works great for vertical windows but if they slope (like a roof window) I get the height and width of the bounding box and not the actual window. The other problem is that the windows sometimes includes a window sill that is thicker then the rest of the window and then the normal direction is affected. Commented Jun 20, 2022 at 18:06
• I uploaded an example file to github.com/maxtillberg/BlenderICE/blob/main/windows.blend Commented Jun 20, 2022 at 18:38
• @user2404987 in the file the objects have their location, rotation, scale applied, so they no longer contain the information about e.g. window direction. Therefore you need some logic to detect the front/top/side of a window. Apparently looking by face surface fails... In some cases it could be hard even for a human to figure where's the front, e.g. a cube (glass block). Also I imagine you have quite a lot more objects, therefore you don't do it manually, in the file all objects are either facing Y or X axes. Maybe you could analyze on which axis the object is symmetrical... Commented Jun 20, 2022 at 19:58
• This is one of the tricky part but I need to assume that the width and height is always larger the the thickness of the window and I think that is the case for most of the windows. I guess I gould postprocess so all windows needs to contain one or more planar window surfces and/or a frame in the same mesh. Commented Jun 20, 2022 at 20:27
• One more thing, depth and width was mixed up for a number of windows so I calculated both and used the largest one but know I would like to find the corosponding vector. I guess I just could rotade the vector 90° Commented Jun 21, 2022 at 16:08