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.
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…
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. )