Rhino Python

rhino
python
rhino5

(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 :slight_smile:
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. )