Python Sorted by X and after by Y

Hello,
I don’t understand the sort method in python, and i need today to sort geometry with the X value and the Y value… for example i select circles, and i need that python sort them like this:


i wrote this:
sorted_circles=sorted([(rs.BoundingBox(circle)[0][0],circle) for circle in circles])

but it’s only on X value…

I don’t find how i have to think about it… :exploding_head:

thank you!

Hi @onlyforpeace,

you can sort by multiple arguments either with a comparison function or using a lambda like below. Note that sort does sort an interable in place while sorted would create a sorted copy:

import Rhino
import scriptcontext
import rhinoscriptsyntax as rs

tolerance = scriptcontext.doc.ModelAbsoluteTolerance

def circle_filter(rhino_object, geometry, component_index):
    rc, circle = geometry.TryGetCircle(tolerance)
    return rc

def DoSomething():
    
    msg = "Select circles to sort"
    obj_ids = rs.GetObjects(msg, 4, True, False, False, None, 2, 0, circle_filter)
    if not obj_ids: return
    
    rh_objs = [rs.coercerhinoobject(obj_id, True, True) for obj_id in obj_ids]
    rh_objs.sort(key=lambda c: (c.Geometry.Arc.Center.Y, c.Geometry.Arc.Center.X))
    
    for i, rh_obj in enumerate(rh_objs):
        rs.AddTextDot(i, rh_obj.Geometry.Arc.Center)
    
DoSomething()

Since the origin is at the lower left in Rhino, you would negate the first item in the sort tuple to get what you want, it has the origin in the upper left:

rh_objs.sort(key=lambda c: (-c.Geometry.Arc.Center.Y, c.Geometry.Arc.Center.X))

Above sorts by the x and y coordinate of the circle center. Does this help ?

_
c.

1 Like

Yes, thank you!! that it’s!

but I took circle for example, in fact it can be square, or rectangle, why not spline… so i need to sort by the less x an y value of boundingbox.

so i wrote this:
rh_objs.sort(key=lambda c: (-c.Geometry.PointAtStart.Y, c.Geometry.PointAtStart.X))
but it isn’t the good value.

Hi @onlyforpeace,

using curves instead of circles, you can provide a custom SortFunction to your sort as the key argument like this:

import Rhino
import scriptcontext
import rhinoscriptsyntax as rs

def DoSomething():
    
    msg = "Select cures to sort"
    obj_ids = rs.GetObjects(msg, 4, True, False, False, None, 2)
    if not obj_ids: return
    
    rh_objs = [rs.coercerhinoobject(obj_id, True, True) for obj_id in obj_ids]
    
    def SortFunction(rh_obj):
        bbox = rh_obj.Geometry.GetBoundingBox(True)
        return (-bbox.Center.Y, bbox.Center.X)
    
    rh_objs.sort(key=SortFunction)
    
    for i, rh_obj in enumerate(rh_objs):
        bbox = rh_obj.Geometry.GetBoundingBox(True)
        rs.AddTextDot(i, bbox.Center)
    
DoSomething()

This will sort by the BoundingBox.Center in the WorldXY plane. Note that the SortFunction also returns a tuple where the first item is the negative Y axis and the second item is the positive X axis, so your origin is at the upper left.

To use the lower left of the bounding box you would just change the SortFunction to look like this:

def SortFunction(rh_obj):
    bbox = rh_obj.Geometry.GetBoundingBox(True)
    return (-bbox.Min.Y, bbox.Min.X)

_
c.

1 Like

merci beaucoup!!
it’s what i need!!!