Dimensions of all selected objects

Welcome. A few days ago I started to learn python basics, and wonder how to write operator which will return the size of all selected objects and not only the active one. I have now a lot of work on visualization designs based on aluminum profiles as an example in the attached. To create a description I need the exact size of whole structure, so I have to connect all the elements to read exact sizes and reconnect but it takes a little extra time…

If I could write a script that display the size of all selected objects my job would be much easier and faster.
Thank you for any suggestions.

Attachments


got something is a big script like that
but you have to analyse the box size of all selected ob and determine min max ect. do some math and get the final max min values

I can try to extract the part to calculate that but will take time to do it!
it can be done but a little complicated

might be easier and faster to use the ruler / protractor tool may be!

happy bl

I was afraid it would be complicated :(. I hope that in the api there is a function line “Bounding box” or something like that…

I was afraid it would be complicated :(. I hope that in the api there is a function line “Bounding box” for the entire selection or something like that…

sorry “replay …” instead of “edit post”

there is one function for box on one ob
but when you combine several ob you have to analyse box of each ob find min max ect and calculate the overall min max

it begins like this


    
  for o1 in bpy.context.scene.objects[:]: # Calculate Scene Size
 
   if o1.name=="Camera" or o1.name=="Empty":
    pass
   else:
 
#   print ('ob=',ob.name)
 
    bounds = functions.getobjectBounds(o1)
 
 
    oxmin = bounds[0][0]
    oxmax = bounds[1][0]
 
    oymin = bounds[0][1]
    oymax = bounds[1][1]
 
    ozmin = bounds[0][2]
    ozmax = bounds[1][2]
 
    if oxmin <= minx:
     minx = oxmin
    if oymin <= miny:
     miny = oymin
    if ozmin <= minz:
     minz = ozmin
 
    if oxmax >= maxx:
     maxx = oxmax
    if oymax >= maxy:
     maxy = oymax
    if ozmax >= maxz:
     maxz = ozmax
 
  widhtx=maxx+minx
  widhty=maxy+miny
  widhtz=maxz+minz
 
 
 
  col2.label('Scene X Bounds: {' + str(round(minx,3)) + ',' + str(round(maxx,3)) + '}')
  col2.label('Scene Y Bounds: {' + str(round(miny,3)) + ',' + str(round(maxy,3)) + '}')
  col2.label('Scene Z Bounds: {' + str(round(minz,3)) + ',' + str(round(maxz,3)) + '}')
 
  minx = minx - s_padding
  miny = miny - s_padding
  minz = minz - s_padding
 
  maxx = maxx + s_padding
  maxy = maxy + s_padding
  maxz = maxz + s_padding
 
  midx = (minx + maxx) /2
  midy = (miny + maxy) /2
  midz = (minz + maxz) /2
 
    
    


let me get back with the function missing!

happy bl

I will be grateful :slight_smile:

Thx

here is missing function

can u try to rework it a little to make it work alome



###
 
class functions():
 
 def getobjectBounds(ob):
 
  obminx = ob.location.x
  obminy = ob.location.y
  obminz = ob.location.z
 
  obmaxx = ob.location.x
  obmaxy = ob.location.y
  obmaxz = ob.location.z
 
  for vertex in ob.bound_box[:]:
   x = ob.location.x + (ob.scale.x * vertex[0])
   y = ob.location.y + (ob.scale.y * vertex[1])
   z = ob.location.z + (ob.scale.z * vertex[2])
 
   if x <= obminx:
    obminx = x
   if y <= obminy:
    obminy = y
   if z <= obminz:
    obminz = z
 
   if x >= obmaxx:
    obmaxx = x
   if y >= obmaxy:
    obmaxy = y
   if z >= obmaxz:
    obmaxz = z
  
  boundsmin = [obminx,obminy,obminz]
  boundsmax = [obmaxx,obmaxy,obmaxz] 
  bounds = [boundsmin,boundsmax]
 
  return bounds
 
 


this will take whatever ob selected joined or not
and determine the min max size for all selected obs!

happy bl

ok here is working script



	
import bpy,bmesh
	
minx = 0
miny = 0
minz = 0
	
maxx = 0
maxy = 0
maxz = 0
	
midx=0
midy=0
midz=0
	
widhtx=0
widhty=0
widhtz=0
	
####
	
class functions():
	
	def getobjectBounds(ob):
	
		obminx = ob.location.x
		obminy = ob.location.y
		obminz = ob.location.z
	
		obmaxx = ob.location.x
		obmaxy = ob.location.y
		obmaxz = ob.location.z
	
		for vertex in ob.bound_box[:]:
			x = ob.location.x + (ob.scale.x * vertex[0])
			y = ob.location.y + (ob.scale.y * vertex[1])
			z = ob.location.z + (ob.scale.z * vertex[2])
	
			if x <= obminx:
				obminx = x
			if y <= obminy:
				obminy = y
			if z <= obminz:
				obminz = z
	
			if x >= obmaxx:
				obmaxx = x
			if y >= obmaxy:
				obmaxy = y
			if z >= obmaxz:
				obmaxz = z
		
		boundsmin = [obminx,obminy,obminz]
		boundsmax = [obmaxx,obmaxy,obmaxz] 

		bounds = [boundsmin,boundsmax]
	
		return bounds
	
###
	
	
#global minx,miny,minz,maxx,maxy,maxz,energymult,s_padding
	
	
	
	
minx = 0
miny = 0
minz = 0
	
maxx = 0
maxy = 0
maxz = 0
	
	
	
#for o1 in bpy.context.scene.objects[:]:					# Calculate Scene Size
for o1 in bpy.context.selected_objects:	

	if o1.name=="Camera" or o1.name=="Empty":
		pass
	
	else:
	
		print ('ob=',o1.name)
		print ()
	
		bounds = functions.getobjectBounds(o1)
 
 
		oxmin = bounds[0][0]
		oxmax = bounds[1][0]
 
		oymin = bounds[0][1]
		oymax = bounds[1][1]
 
		ozmin = bounds[0][2]
		ozmax = bounds[1][2]
 
		if oxmin <= minx:
			minx = oxmin
		if oymin <= miny:
			miny = oymin
		if ozmin <= minz:
			minz = ozmin
 
		if oxmax >= maxx:
			maxx = oxmax
		if oymax >= maxy:
			maxy = oymax
		if ozmax >= maxz:
			maxz = ozmax
 
widhtx=maxx-minx
widhty=maxy-miny
widhtz=maxz+minz


 
print ('Scene X Y Z Bounds : { ',widhtx, ' + ' ,widhty , ' + ', widhtz )
 

 




happy bl

Almost perfect, but calculations for the z-axis appear to be incorrect:

it seems that the script takes into account the distance of objects from the grid (ground), and adds it to the calculation.

just re did a test with 3 obs and works fine !
check the overall dimensions of all ob

can u upload file

I did a test with 3 ob and look like it was working but there might be an error

thanks

It seems that the script works correctly only if the objects are at the center of the coordinate system and the lowest vertex must be in the position z = 0, otherwise, the script added the distance value for each axis. I attach the file:
Cube, Cube.001, Cube.002 are calculated correctly, but Cube.003, Cube.004 and Cube.005 incorrectly

Attachments

Cubes.blend (1.03 MB)

try this one

Cubesa1.blend (998 KB)
happy bl

Bingo :slight_smile: Now script works great every time. You are a MASTER. I have one more question. Is this type of script can be run automatically after each selection change ? in the same way as the default “Dimensions”…

it could be added in a panel script with auto update
but if you have a lot of ob it might get sluggish!

let me see if I can find a simple panel script to add this
but may take a day sorry!

happy bl

I do not know how to repay for YOUR help :), also believe that you should release this script as an official addon because it can be very useful in the work of architectural…

try this one with panel in ob properties on the right
seen only when one selected ob !

scebedim2.blend (161 KB)

tell me what you think
works also as addon

just added the date and link to this thread here

happy bl

Here’s a script that visualizes the bounding boxes and axis-aligned bounding box of these boxes (this can be larger than the actual min/max extends of vertices in the meshes):

import bpy
import bgl
from mathutils import Vector


def draw_callback_px(self, context):

    ob = context.object
    if ob is None or ob.type not in ('MESH', 'CURVE', 'SURFACE', 'META', 'FONT'):
        # Type that doesn't support .bound_box
        return
    mat = ob.matrix_world
    
    # 50% alpha, 2 pixel width line
    bgl.glEnable(bgl.GL_BLEND)
    bgl.glColor4f(1.0, 0.0, 0.0, 0.5)
    bgl.glLineWidth(2)
    
    bboxes = []
    
    for ob in context.selected_objects:
        if ob.type == 'MESH':
            bbox = [ob.matrix_world * Vector(b) for b in ob.bound_box]
            bboxes.extend(bbox)
            
            bgl.glBegin(bgl.GL_LINE_STRIP)
            bgl.glVertex3f(*bbox[0])
            bgl.glVertex3f(*bbox[1])
            bgl.glVertex3f(*bbox[2])
            bgl.glVertex3f(*bbox[3])
            bgl.glVertex3f(*bbox[0])
            bgl.glVertex3f(*bbox[4])
            bgl.glVertex3f(*bbox[5])
            bgl.glVertex3f(*bbox[6])
            bgl.glVertex3f(*bbox[7])
            bgl.glVertex3f(*bbox[4])
            bgl.glEnd()
            
            bgl.glBegin(bgl.GL_LINES)
            bgl.glVertex3f(*bbox[1])
            bgl.glVertex3f(*bbox[5])
            bgl.glVertex3f(*bbox[2])
            bgl.glVertex3f(*bbox[6])
            bgl.glVertex3f(*bbox[3])
            bgl.glVertex3f(*bbox[7])
            bgl.glEnd()
            
    min_x = min(b.x for b in bboxes)
    max_x = max(b.x for b in bboxes)
    min_y = min(b.y for b in bboxes)
    max_y = max(b.y for b in bboxes)
    min_z = min(b.z for b in bboxes)
    max_z = max(b.z for b in bboxes)
    
    bgl.glColor4f(0.0, 1.0, 0.0, 0.5)
    bgl.glBegin(bgl.GL_LINE_STRIP)
    bgl.glVertex3f(min_x, min_y, min_z)
    bgl.glVertex3f(min_x, max_y, min_z)
    bgl.glVertex3f(max_x, max_y, min_z)
    bgl.glVertex3f(max_x, min_y, min_z)
    bgl.glVertex3f(min_x, min_y, min_z)
    bgl.glVertex3f(min_x, min_y, max_z)
    bgl.glVertex3f(min_x, max_y, max_z)
    bgl.glVertex3f(max_x, max_y, max_z)
    bgl.glVertex3f(max_x, min_y, max_z)
    bgl.glVertex3f(min_x, min_y, max_z)
    bgl.glEnd()
    
    bgl.glBegin(bgl.GL_LINES)
    bgl.glVertex3f(max_x, min_y, min_z)
    bgl.glVertex3f(max_x, min_y, max_z)
    bgl.glVertex3f(min_x, max_y, min_z)
    bgl.glVertex3f(min_x, max_y, max_z)
    bgl.glVertex3f(max_x, max_y, min_z)
    bgl.glVertex3f(max_x, max_y, max_z)
    bgl.glEnd()
    
    # restore opengl defaults
    bgl.glLineWidth(1)
    bgl.glDisable(bgl.GL_BLEND)
    bgl.glColor4f(0.0, 0.0, 0.0, 1.0)


class ModalDrawOperator(bpy.types.Operator):
    """Draw a line with the mouse"""
    bl_idname = "view3d.modal_operator"
    bl_label = "Simple Modal View3D Operator"

    def modal(self, context, event):
        context.area.tag_redraw()

        if event.type in {'ESC'}:
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'CANCELLED'}

        return {'PASS_THROUGH'}

    def invoke(self, context, event):
        if context.area.type == 'VIEW_3D':
            # the arguments we pass the the callback
            args = (self, context)
            # Add the region OpenGL drawing callback
            # draw in view space with 'POST_VIEW' and 'PRE_VIEW'
            self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_VIEW')

            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "View3D not found, cannot run operator")
            return {'CANCELLED'}


def register():
    bpy.utils.register_class(ModalDrawOperator)


def unregister():
    bpy.utils.unregister_class(ModalDrawOperator)

if __name__ == "__main__":
    register()
    
    for area in bpy.context.screen.areas:
        if area.type == 'VIEW_3D':
            context = bpy.context.copy()
            context['area'] = area
            bpy.ops.view3d.modal_operator(context, 'INVOKE_DEFAULT')
            break


nice to see it shown in viewport

but I think he also needs to have the max min of all selected ob in a sub panel

happy bl

That’s what I was missing from the beginning you did in 2 days :), functionality now looks great.
Very helpful would be also a possibility to choose units between mm, cm, m, when the scene is in the metric mode.
Number of decimal places - 2 should be sufficient

I think the units are always as meter or feet or bu only

I can try to add it after values
but have to find how you get these unit !

I can change the numbers shown
be back in 10 minutes

thanks