2
$\begingroup$

I want to sort 12 different "cubes", they are not really cubes more like objects, according to there size in x.

enter image description here

so from picture nr.1 to picture nr.2. I have started by putting my collection of cubes in a list, but where do I go from there? enter image description here

edit: All I want is to have the objects sorted on the x-axis according to their x- length from smallest to largest. If you look at the images, the first image representing "before" and the second "after", the "skinniest" object will be placed first, and replace the cube that was there from the start. That is all I want, just for them to be sorted according to size, like the second image. I apologise for being unclear, this is all very very new to me and I honestly don't know really how to articulate any better. Thanks.

$\endgroup$
4
  • $\begingroup$ Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. $\endgroup$
    – Community Bot
    Sep 23, 2021 at 20:51
  • $\begingroup$ The answer depends on what you want to do with them when they're sorted. Check out the sorted() function in Python as a starting point and think about what you want to do with the sorted objects. That'll help you figure out what data structures to use to sort them and what to do with the result. (dictionary? list of tuples?) $\endgroup$ Sep 23, 2021 at 21:00
  • $\begingroup$ All I want is to have the objects sorted on the x-axis according to their x- length from smallest to largest. If you look at the images, the first image representing "before" and the second "after", the "skinniest" object will be placed first, and replace the cube that was there from the start. That is all I want, just for them to be sorted according to size, like the second image. I apologise for being unclear, this is all very very new to me and I honestly don't know really how to articulate any better. $\endgroup$ Sep 23, 2021 at 21:26
  • $\begingroup$ Please always post text (eg a script) as text, not an image. $\endgroup$
    – batFINGER
    Sep 24, 2021 at 12:39

2 Answers 2

2
$\begingroup$

This code will solve your problem as stated:

import bpy

d = { (cube.dimensions.x, cube.name) : cube for cube in bpy.data.collections['cubes'].objects }
newx = 0
for k in sorted(d.keys()) :
    d[k].location.x = newx
    newx += 2

It creates a dictionary using the X dimension of each object in the collection cubes as the key and the cube's object data as the value. It uses a tuple that includes the name as the key to account for the case where 2 cubes have the same X dimension. Since object names are unique, this guarantees one entry for each object in the collection.

Once it has created the dictionary, it moves the objects into sorted order, starting at 0 and incrementing by 2 for each new object.

There are three things that could be improved in this code, but how you want to improve them are up to you.

  1. The code could be changed into a function
  2. The function could take two arguments, one being the name of the collection, and the other being the starting point for newx rather than using the hardwired value 0.
  3. newx += 2 could be replaced by code that takes into account the dimension of the object being moved; perhaps by having a third argument that sets a spacing.

Such a function might look like

def sortOnX(collectionName, firstX, spacing):
    d = { (cube.dimensions.x, cube.name) : cube for cube in bpy.data.collections[collectionName].objects}
    nextX = firstX
    for k in sorted(d.keys()) :
        d[k].location.x = nextX
        nextX += d[k].dimensions.x +spacing
    return
$\endgroup$
2
  • $\begingroup$ Thank you! you definitely solved the problem! though if I were to simplify, meaning that I do not want the origin from x=0, and I do not want any added specific spacing, though instead I want the cubes to simply replace the respective cubes spot. How would I do that? If you look at picture nr.2 you'll see irregular spacing. I assume that is because the cube that moves "takes" the replaced cubes x-coordinate without changing anything else so to say. $\endgroup$ Sep 24, 2021 at 0:52
  • $\begingroup$ create a list of just the x locations and sort it. In the for loop, set d[k].location.x to l[nextX] and increment nextX by 1. At this point you should be able to figure those two change out yourself. $\endgroup$ Sep 24, 2021 at 1:15
2
$\begingroup$

Sort by both, zip together.

  • Assumes all objects in collection have dimension (eg are meshes)
  • Locations sorted by x component
  • Cubes sorted by x dimension
  • Assign each to each

Test script, select the cubes collection to give it context, or hard code as in question.

import bpy
context = bpy.context
collection = context.collection
locs = sorted([o.matrix_world.to_translation() for o in collection.objects], key=lambda v: v.x) 
cubes = sorted(collection.objects, key=lambda o: o.dimensions.x)

for o, pos in zip(cubes, locs):
    o.matrix_world.translation = pos
$\endgroup$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .