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:
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:
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: