Creating a list by selecting coordinates

rhino
rhinopython
python

(Zoey) #1

HI,

I am trying to select specific curves by using their area centroid, which is basically three coordinates.

Ive managed to obtain these coordinates using bounding boxes, given these curves are not sitting on cplanes.

However i cant seem to select specific curves by using just the z coordinates. Basically i can put them into lists based on length etc, but not sure how to work with coordinates. Here are my current notes

from Rhino.Commands import Result
from Rhino.DocObjects import ObjectType
import rhinoscriptsyntax as rs
from scriptcontext import doc

layer_objs = rs.ObjectsByType(4,True)
if layer_objs:
#create an empty list
mylist=[]
for obj in layer_objs:
#find curves among the objects
if rs.IsCurve(obj):
if abs(rs.CurveLength(obj)<100):
#curve meets selection criteria, append to “good” list
mylist.append(obj)

rs.UnselectAllObjects()

#bBox = rs.BoundingBox(mylist[0])

#CURVE1
#rs.UnselectAllObjects()
for i in mylist:
bBox = rs.BoundingBox(i)
cent = [(bBox[0][0] + bBox[6][0])/2,(bBox[0][1] + bBox[6][1])/2,(bBox[0][2] + bBox[6][2])/2]
print cent
rs.AddPoint(cent[0],cent[1],cent[2])

newlines = rs.SelectObjects(mylist)

if newlines:
s=[]
for line in newlines:
if rs.IsCurve(line):
if abs(cent[2]< -11):
s.append(line)

rs.UnselectAllObjects()

rs.SelectedObjects(s)

I keep getting the error: expected an indented block.

Help would be appreciated, thank you.


#2

@ZKislost, based on the other example using the length to filter curve objects, you can use a custom function definition to perform the filtering using multiple variables. The example below filters out the curves which have a bounding box centroid.Z coordinate within min_z and max_z.

import Rhino
import scriptcontext
import rhinoscriptsyntax as rs

def MyFilterFunction(crv_id, min_z, max_z):
        bbox = rs.BoundingBox(crv_id)
        cent = (bbox[0] + bbox[6]) * 0.5
        if cent.Z > min_z and cent.Z < max_z:
            return True
        else:
            return False

def DoSomething():
    curve_ids = rs.ObjectsByType(rs.filter.curve, select=False, state=1)
    if not curve_ids: return
    
    min_z, max_z = -10.0, 100.0
    
    mylist = filter(lambda crv_id: MyFilterFunction(crv_id, min_z, max_z), curve_ids)
    if mylist: 
        rs.UnselectAllObjects()
        rs.SelectObjects(mylist)
    
DoSomething()

_
c.


(Zoey) #3

HI thank you so much for your response. When i tried using your code on my model however, it gave me no response. But no error either so im assuming its running. thought maybe the min and max z’s were off so i tried readjusting but nothing seems to be working. Also cent.Z doesnt work outside of this code… cent[2] wont accept < Z for some reason.

can you offer any advice
?


#4

@ZKislost, can you upload your model ? Which Rhino version do you use ?

_
c.


(Zoey) #5

ahh never mind, i just got schooled by my boss for haveing such crap coding knowledge… I last coded 5 years ago :") and only in basic C now im trying to work with python.

Anyway he said i was doing it all wrong to begin with and i need to store cent values in a list. the way im doing it it is reproducing the same cent value again and again, over riding my previous cent value. he said to store sent in a list then work with that. I so regret asking him for help but here is how he fixed it

from Rhino.Commands import Result
from Rhino.DocObjects import ObjectType
import rhinoscriptsyntax as rs
from scriptcontext import doc

layer_objs = rs.ObjectsByType(4,True)
if layer_objs:
#create an empty list
mylist=[]
for obj in layer_objs:
#find curves among the objects
if rs.IsCurve(obj):
if abs(rs.CurveLength(obj)<100):
#curve meets selection criteria, append to “good” list
mylist.append(obj)

rs.UnselectAllObjects()

centroid = []
for i in mylist:
bBox = rs.BoundingBox(i)
cent = [(bBox[0][0] + bBox[6][0])/2,(bBox[0][1] + bBox[6][1])/2,(bBox[0][2] + bBox[6][2])/2]
centroid.append(cent)

print centList

this should give me the list of all the cent values with which can work the max thing out? but as long as it uses cent [2] instead of z. so yeah
anyway, if that makes any sense ill leave that here. thanks for the help :slight_smile:


#6

Well, some parts make really no sense, eg:

layer_objs = rs.ObjectsByType(4,True)

you’re getting objects by type and not objects by layer, so the variable name was kind of confusing to me.

if rs.IsCurve(obj):

that should not be required, your list can only include curves since you where collecting it by type=4 which is curve.

abs(rs.CurveLength(obj)

a curve length is a positive value, there is no need to get the absolute value from it.

cent = [(bBox[0][0] + bBox[6][0])/2,(bBox[0][1] + bBox[6][1])/2,(bBox[0][2] + bBox[6][2])/2]

i’ve shown this in my other example, you could make the calculation on the points directly, eg.:

cent = (bbox[0] + bbox[6]) * 0.5

you can do that all in one function as my example above. If you want to access the Z coordinate of a Point3d type object it must be uppercase not lowercase.

_
c.


(Zoey) #7

… that’s all my code man. And like i said im not super selective or neat, hence the lack of experience. I liked the shorter version of cent ( longer one not my idea ) though will put that in my code so thank you :slight_smile: i ll try and see if i made that mistake with the z. Thanks :slight_smile: and i will post it here if it works just in case you wanna take a look back and see if it went anywhere :slight_smile: