1
$\begingroup$

I need to calculate object's 'length factor', for example:

enter image description here enter image description here

... To achieve this, I need to get object's true length:

TrueLengthGoal

... But the 'dimensions' vector contains dimensions of bounding box, so it's different when we e.g. rotate the object. I have a code that will calculate the 'length factor' value, the only problem is that the 'dimensions' values are from bounding box, not from the object itself. Here's the code:

dimensions = list(ob.dimensions) 
maxDimension1 = max(dimensions)
dimensions.remove(maxDimension1)
maxDimension2 = max(dimensions)
lengthFactor = (maxDimension1/maxDimension2) - 1

I'd be grateful for some help.

$\endgroup$
2
$\begingroup$

The distance between two points can be calculated by extending the Pythagorean theorem to three dimensions. The x,y,z lengths you calculate as the distance between each point on the axis, then square those lengths and get the square root of the sum.

import bpy
from math import sqrt

loc1 = bpy.data.objects['Cube'].location
loc2 = bpy.data.objects['Cube.001'].location

xlen = loc1.x - loc2.x
ylen = loc1.y - loc2.y
zlen = loc1.z - loc2.z

dist = sqrt(xlen**2 + ylen**2 + zlen**2)

Which you can simplify down to -

def distance(p1, p2):
    return sqrt((p1[0]-p2[0])**2+(p1[1]-p2[1])**2+(p1[2]-p2[2])**2)

But that still leaves the dilema of choosing which verts you want to measure between. In your third example of a rotated rectangle, the min/max on y will give you the two outer points and by discarding the min(x) and max(x) you will get the two x locations of the y extremes, this can give you the diagonal length of the rectangle. Similarly if you use min(y) and discard max(y) the next max(y) will give you the longest edge.

$\endgroup$
1
$\begingroup$

An objects bounding box is rotated when the object is rotated, so it is always in local coordinates. You can access them as follows

ob.bound_box[i][j]

Where i is the index of the bounding box corner vertex. Every bounding box is a cuboid and thus has 8 vertices. j is the coordinate of this point, 0 for x, 1 for y and 2 for z. So finding the bounding box length along local axes you could do

bb = ob.bound_box
dx_local = max(bb[i][0] for i in range(8)) - min(bb[i][0] for i in range(8))
dy_local = max(bb[i][1] for i in range(8)) - min(bb[i][1] for i in range(8))
dz_local = max(bb[i][2] for i in range(8)) - min(bb[i][2] for i in range(8))
longest_side = max(dx_local*ob.scale[0], dx_local*ob.scale[1], dx_local*ob.scale[2])

However, I cannot quit figure out how you define the "scalefactor". I guess you can do the rest yourself.

$\endgroup$
  • $\begingroup$ ... The longest_side value changes after applying rotation though. Is there a way to fix it? By the way, I've found a way to get the second longest side, like that: pastebin.com/2XWRNcJD $\endgroup$ – Good Samaritan Apr 13 '17 at 18:37
  • $\begingroup$ After some testing, it looks like it shows the same value as the regular '.dimensions' value... Do I miss something? $\endgroup$ – Good Samaritan Apr 13 '17 at 18:47
  • $\begingroup$ The bounding box does rotate with the object, however it doesn't match the mesh if the mesh is rotated in edit mode. See this example of a single flat triangle. $\endgroup$ – sambler Apr 14 '17 at 9:45
1
$\begingroup$

You can use the below script to get the dimensions of the selected object:

x = bpy.context.object.dimensions[0]
y = bpy.context.object.dimensions[1]
z = bpy.context.object.dimensions[2]

which is controlled from the 3d view as shown below:

enter image description here

$\endgroup$
0
$\begingroup$

A bit simplified and more elegant version of sambler's answer:

    import bpy
    loc1 = bpy.data.objects['Cube'].location
    loc2 = bpy.data.objects['Cube.001'].location
    dist = (loc1 - loc2).length
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.