Select Contents of Closed Curve

Hello,

I am working on a lot of 2D closed shapes. To select the contents(there are textboxes inside) of these closed polylines/curves I have been using:

rs.UnselectAllObjects()
rs.Command("_SelBoundary _SelectionMode=_Crossing selid " + str(Id) + " _Enter", False)

return rs.SelectedObjects()

This works; however, it is slow when I have a lot of shapes because it highlights each shape, one at a time. Is there a way to obtain the same results from SelBoundary without actually highlighting anything, or could someone point me to where this function is so that I could modify it to my use?

By the way, I used to use a bounding box, but this proved erroneous because of shapes that were rotated 45 degrees and close together.

If the curves are closed and planar and the text items are on the same plane, I might try using PointInPlanarClosedCurve and loop through the text object insertion points… I might have a script that uses something like that procedure in my library.

1 Like

This is interesting. I didn’t know about that particular function. Let me see if that works better for me. Thanks!

Unfortunately, it looks like in my case they don’t share a plane. In fact, every shape has it’s own plane. The files that I am working with are sometimes preexisting, so I don’t have control on what I am given, but I find it hard to believe this was intentional, unless it could happen from layers.

Actually, what would have caused a difference in planes? Could different layers?

Annotation%202019-07-03%20143539

Lastly, is it possible to move the curve onto the text object’s plane because actually I want the curve to follow any rotations that its text object has anyways.

Well, in the example above, the two planes are essentially the same - that is to say the the text and the curve are flat on the World Z0 plane. You can see that from the fact that the Z axis vector is 0,0,1 for both and that the Z coordinate of the origin points of both is also 0. Their inherent planes are rotated differently and have different origin in X and Y (totally normal) but the PointInPlanarClosedCurve should work still work for this case.

If they are all supposed to be on the world Z0 plane, one could also take the precaution of projecting everything to that plane (script or manual) before starting. However, if you were to have a set of curves and texts that are not all in a common plane, the search for containment becomes a bit more difficult, but not impossible - you would first have to look for coplanarity (within tolerance) and then containment.

You have There are two threads on the same problem (two different op’s), maybe we can concentrate in just one…

Following is a sample that finds the text insertion point inside a closed planar curve and groups the text object with the curve. You can modify it to suit. Note that as it is set up now, if there is more than one text inside a curve, it will only grab the first one - this can also be changed. Note also that the text insertion point is projected to the curve plane for comparison, so it does not actually need to be in the same plane as the curve - just within the projection of it.

import rhinoscriptsyntax as rs

#planar closed curves
def cp_crv_filt(rhino_object, geometry, component_index):
    return rs.IsCurvePlanar(geometry) and rs.IsCurveClosed(geometry)
    
#text objects
def to_filt(rhino_object, geometry, component_index):
    return rs.IsText(geometry)

def GroupTextWContainingCrv():
    msg="Select closed planar curves to process"
    crvs=rs.GetObjects(msg,4,preselect=True,custom_filter=cp_crv_filt)
    if not crvs: return
    
    msg="Select texts to check"
    txts=rs.GetObjects(msg,512,custom_filter=to_filt)
    if not txts: return
    
    txt_data=[(rs.TextObjectPoint(txt),txt) for txt in txts]
    tol=rs.UnitAbsoluteTolerance()
    
    for crv in crvs:
        plane=rs.CurvePlane(crv)
        for txt_item in txt_data:
            #point is automatically projected to the curve plane for testing !!
            if rs.PointInPlanarClosedCurve(txt_item[0],crv,plane,tol)==1:
                #match found
                group=rs.AddGroup()
                rs.AddObjectsToGroup([crv,txt_item[1]],group)
                #items grouped, remove text item from search to go faster
                txt_data.remove(txt_item)
                #go to next curve in list
                break
GroupTextWContainingCrv()
1 Like

Thank you so much for the help.