# Rhino Python

(Zoey) #1

If i have four curves in a layer, and i want to select two of them ( i need their object ids). These two have the longer lengths as opposed to the other ones, how should i go about it?

I have already selected them all and i can produce a cumulative length. But i want to detect each length and than select the highest two. any idea?

Sorry bout the amateur post, but i am very new. A good explanation would help me learn as well as a sample.
Thanks.

#2

Sort length with id and select first two from list using id.

#3

Here is a small sample of one way to do thisâ€¦ There are comments in the script.
The principle I used here is a little trick, that in python you can sort nested lists (lists inside of lists), it will sort by the first element inside each nested list or tuple. So I first got all the curve idâ€™s, then created a nested list of tuples of the each curveâ€™s length paired with its id. The lengths are gotten with rs.CurveLength().

I then sort that nested list by biggest first, and retrieve the desired number of longest curves at the end from the sorted list, starting at the beginning of the list.

``````import rhinoscriptsyntax as rs
#user selects a collection of curves
crvs=rs.GetObjects("Select some curves",4,preselect=True)
if crvs:
#ask the user how many of the longest  curves they want to select
msg="How many of the longest curves to select?"
count=rs.GetInteger(msg,minimum=1,maximum=len(crvs))
if count:
#create a nested list of tuples of (curve length,curve id) for all curves
crv_info=[(rs.CurveLength(crv_id),crv_id) for crv_id in crvs]
#sort the nested list by the length, biggest first (reverse=True)
#if you want the shortest, leave out the reverse=True
crv_info.sort(reverse=True)
#get the desired number of longest curves, from beginning of sorted list
for i in range(count):
#select the curve ID's which are in index 1 of each tuple
rs.SelectObject(crv_info[i][1])
#print the curve length for reference
print "Curve {} length: {}".format(i+1,crv_info[i][0])
``````

Let me know if this stuff makes sense and if not, donâ€™t hesitate to ask questionsâ€¦

â€“Mitch

(qythium) #4

Just making a few edits to @Helvetosaur 's answer to make it more Pythonic
The idea of passing functions around as regular objects can be a little weird at first, but itâ€™s really powerful if you get the hang of it! (check out https://wiki.python.org/moin/HowTo/Sorting#Key_Functions for a few such examples.)

``````import rhinoscriptsyntax as rs

# user selects a collection of curves
crvs = rs.GetObjects("Select some curves", 4, preselect=True)

if crvs:
# ask the user how many of the longest  curves they want to select
msg = "How many of the longest curves to select?"
count = rs.GetInteger(msg, minimum=1, maximum=len(crvs))
if count:
# Pass in the function rs.CurveLength as the 'key' argument
# This function is called for every item in the list, and its return value (curve length) is used for sorting
# if you want the shortest, leave out the reverse=True
crvs.sort(reverse=True, key = rs.CurveLength)
longest_curves = crvs[:count] # slices the first 'count' items from the list

for crv_id in longest_curves:
# select the curve ID's
rs.SelectObject(crv_id)
# print the curve length for reference
print "Curve {} length: {}".format(i + 1, rs.CurveLength(crv_id))
``````

(Unfortunately my version involves repeating the rs.CurveLength calculation again for the optional print statement, since the sorting doesnâ€™t store its intermediate results anywhere. )