# How to set absolute bounding box dimensions of a group of selected elements (vertices, edges or faces)

In Object Mode you can change the absolute Dimensions of the selected object, which are connected to the object's relative Scale.

With some elements (e.g. vertices) selected in Edit Mode you can use the Scale Tool to resize the bounding box of the selection, changing the individual elements' position.

Is it possible to set the dimensions of that bounding box in absolute values? I would have had expected it to be in the Edit Mode transform properties panel, but it only shows the bounding box' origin position.

Example: I want to set the tabletop in the image below to a particular size by setting the selected geometry to, let's say 0.75m x 0.75m.

If there is no built-in way to do this, do you know a suitable Add-On?

Here is a script that I wrote to accomplish this. It simply calculates the bounding box of the selected vertices, then scales in such a way that the new dimensions become what you set the values to be.

https://github.com/ekaj2/MeshTools

To download from GitHub, simply click the green Clone or Download button, then choose "Download ZIP". Once you have the zip downloaded, unzip, then load the .py file with Blender's add-on tool in user preferences.

# Copyright 2016 Jake Dube
#
# ##### BEGIN GPL LICENSE BLOCK ######
# This file is part of MeshTools.
#
# MeshTools is free software: you can redistribute it and/or modify
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# MeshTools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with MeshTools.  If not, see <http://www.gnu.org/licenses/>.
# ##### END GPL LICENSE BLOCK #####

import bpy
from bpy.types import Panel, Operator, PropertyGroup, Scene
from bpy.utils import register_class, unregister_class
from bpy.props import FloatProperty, PointerProperty

bl_info = {
"name": "Mesh Tools",
"author": "Jake Dube",
"version": (1, 0),
"blender": (2, 78, 0),
"location": "View3D > Mesh > Transform > Set Dimensions",
"description": "Sets dimensions for selected vertices.",
"category": "Mesh"}

def calc_bounds():
"""Calculates the bounding box for selected vertices. Requires applied scale to work correctly. """
# for some reason we must change into object mode for the calculations
mode = bpy.context.object.mode
bpy.ops.object.mode_set(mode='OBJECT')

mesh = bpy.context.object.data
verts = [v for v in mesh.vertices if v.select]

# [+x, -x, +y, -y, +z, -z]
v = verts[0].co
bounds = [v.x, v.x, v.y, v.y, v.z, v.z]

for v in verts:
if bounds[0] < v.co.x:
bounds[0] = v.co.x
if bounds[1] > v.co.x:
bounds[1] = v.co.x
if bounds[2] < v.co.y:
bounds[2] = v.co.y
if bounds[3] > v.co.y:
bounds[3] = v.co.y
if bounds[4] < v.co.z:
bounds[4] = v.co.z
if bounds[5] > v.co.z:
bounds[5] = v.co.z

bpy.ops.object.mode_set(mode=mode)

return bounds

def safe_divide(a, b):
if b != 0:
return a / b
return 1

class SetDimensions(Operator):
bl_label = "Set Dimensions"
bl_idname = "view3d.set_dimensions_mt"
bl_description = "Sets dimensions of selected vertices"
bl_options = {'REGISTER', 'UNDO'}
bl_context = "editmode"

new_x = FloatProperty(name="X", min=0, default=1, unit='LENGTH')
new_y = FloatProperty(name="Y", min=0, default=1, unit='LENGTH')
new_z = FloatProperty(name="Z", min=0, default=1, unit='LENGTH')

def invoke(self, context, event):
bounds = calc_bounds()
self.new_x = bounds[0] - bounds[1]
self.new_y = bounds[2] - bounds[3]
self.new_z = bounds[4] - bounds[5]
return {'FINISHED'}

def execute(self, context):
bounds = calc_bounds()
bpy.ops.object.mode_set(mode='EDIT')
x = safe_divide(self.new_x, (bounds[0] - bounds[1]))
y = safe_divide(self.new_y, (bounds[2] - bounds[3]))
z = safe_divide(self.new_z, (bounds[4] - bounds[5]))
bpy.ops.transform.resize(value=(x, y, z))

return {'FINISHED'}

def draw(self, context):
layout = self.layout

box = layout.box()
box.label("New dimensions:")
box.prop(self, "new_x")
box.prop(self, "new_y")
box.prop(self, "new_z")

self.layout.operator(SetDimensions.bl_idname, icon="PLUGIN")

def register():
register_class(SetDimensions)

def unregister():
unregister_class(SetDimensions)

if __name__ == "__main__":
register()

• Good idea, however wouldn't seperating and rejoining break things like assigned textures, UV-data etc.? Regarding a script solution, would calculating the bounding box dimensions, offer text input for each axis, and then repositioning all selected vertices be similarly complex? – Andre Dec 5 '16 at 18:15
• No, it shouldn't be a problem with things like textures and UVs; I believe Blender handles all of that for you. Your mentioned scripting workflow would certainly seem more efficient, but for such a seldom used feature I don't know if it would be worth the development effort. It would be much more difficult to achieve that way, although it technically is the "correct" way to do it. My proposed solution is a way to do it without scripting as well as a sort of hack to easily write an add-on to automate the process in most applications. – JakeD Dec 5 '16 at 18:21
• Of course, rather than manually placing each vertex, you would calculate the difference b/w the desired dimensions and the bounding box, then scale accordingly. – JakeD Dec 5 '16 at 18:24
• Dumb question from a blender dev noob: what's the difference between scripting and writing an addon? – Andre Dec 5 '16 at 18:27
• Scripting, coding, and programming are all synonyms that basically mean the same thing. Writing (or scripting) an add-on is a special type of "program" that "adds on" feature to another program or application. In the case of Blender, add-ons get installed in user preferences and are generally user friendly to install and use. Non-add-ons are sometimes just run with the "run script" button in Blender's text editor, but they could be anything. The differences b/w scripting and programming come from the language it is done in: Python is a scripting language, so we call it scripting. – JakeD Dec 5 '16 at 18:31

The way I found how to do this is to make a basic calculation for each axis with the actual dimension divided by the expected dimension on that axis, then divide the scale of the axis by the result of the previous calculation.

To find your dimensions actual edge length:

Example:

X axis dimension = 2,734 M - X axis expected = 0.75 M - X axis scale = 1 --

2,734 / 0.75 = 3,645633333 - 1/3,645633333 = 0,27432334 -

With this information, scale on the x axis by 0.27432334 and you will have your desired dimension. Then apply the scale and you're done. Repeat on each axis and voilá!

• This would actually be feasible. But how do you know the original X axis dimension of 2,734m in your example? And what do you mean by "apply the scale"? Do you refer to Shift+A in object mode? – Andre Dec 5 '16 at 18:57
• you have to check the transform panel you showed in th question. there you can see the actual dimmension. if you start with a default cube, will be 2 meters. – Joni Mercado Dec 5 '16 at 18:59
• This panel only shows me the total dimensions of the object. I am asking about resizing a selected subset of vertices, which has a different dimension than the whole mesh (this is actually the whole point of the question). With that panel you wouldn't need to calculate, either. Just type in the desired dimensions and hit enter. – Andre Dec 5 '16 at 19:01
• I edited the answer so you can know how to active the edge lenght. so you can know the actual dimension. Hope that helps. – Joni Mercado Dec 5 '16 at 19:04
• Thanks, but this would only help if the edges match the bounding box' edges (as in my example). In the general case however, one cannot assume that this is the case, so just the edge lengths wouldn't suffice to determine the boundix box dimensions. – Andre Dec 5 '16 at 19:07