Select objects inside solid


#1

Does anyone know if there is a way to select all the object inside a solid?

I have a relatively simple solid that is L shaped, and so I can’t use SelBox. I also can’t use SelBoundary of the planar face, because I don’t want to select object above and below it.

Gav


#2

depending on the situation/perspective, you might be able to do a SelVisible then Invert.
there are some other ways but that’s possibly the easiest/fastest way to try first.


#3

Gavin, post this over in the scripting category. I’ll bet someone over there has a handy dandy one for you. At least I hope they do, 'cus I want it too. :smile: A ‘select all objects inside a selected solid volume’ script.


#4

This is kinda complicated if you want to do it right…

Attached is a draft version done with Python, not tested much, not guaranteed…

If it works, will find points, curves, surfaces, polysurfaces and meshes that are completely enclosed by a volume - either a single surface or a polysurface. If you have meshes with a lot of points, that will be slow (I may be able to fix that later).

Let me know how/when it fails… :smile:

–Mitch

edit: Removed version previously attached, use the one below…


#5

Nice one Mitch.

It is interesting that rhinoscript function rs.IsObjectSolid() does not treat closed extrusions as closed solids (cube, cylinder), which would technically be correct. Still those geometries are sort of closed bodies too:

def IsObjectSolid(object_id):
    """Verifies that an object is a closed, solid object
    Parameters:
      object_id: String or Guid. The identifier of an object
    Returns:
      True if the object is solid
      False if the object is not solid
    """
    rhobj = rhutil.coercerhinoobject(object_id, True, True)
    if( isinstance(rhobj, Rhino.DocObjects.BrepObject) or isinstance(rhobj, Rhino.DocObjects.SurfaceObject) ):
        return rhobj.Geometry.IsSolid
    if( isinstance(rhobj, Rhino.DocObjects.MeshObject) ):
        return rhobj.MeshGeometry.IsClosed
    return False

So in order to use this function, one needs to either explode the extrusion and then join its parts (which will create a polysurface), or convert it to a brep.


#6

Sigh, I thought I checked for extrusions… Actually I did, but I added the “is solid” check for the outer envelope at the last minute and didn’t check again.

I was just about to post another message about how painful dealing with extrusion objects still is, this will add to the list.

Attached is a revised version that should work with extrusions and has a couple of other bugfixes, let me know where it fails…

Edit: Please use the revised version further below.

–Mitch

SelObjsInsideSolid.py (2.9 KB)


Mesh faces inside frustum + visibility of mesh faces
#7

Thanks Mitch,

It partially works. Here’s the error I get:

and I’ve attached the file I’m testing it on.

I don’t know if it makes any difference, but I’m running the script from a button using -runpythonscript ()

test-selectobjinsidesolid.3dm (129.9 KB)


#8

I changed line 18 to:

except: s_brep=sObj

and that fixed the error.

Its selecting the 3 points, but not the two triangles or the text object. I know its asking a lot to find a planar curve that is right on the boundary of the solid, and likewise for the textobject. I may need to create another script to moveface each face 0.5mm in the direction of the normal first.

I manually enlarged the solid and then it found the triangles, but not the textobject.


#9

I added a bit to check text objects. I basically just find the mesh of the text, and then modified your mesh test.

SelObjsInsideSolid.py (3.4 KB)


#10

OK, thanks for checking, the error was due to a false assumption on my part that if it was already a Brep, that sObj.ToBrep() would be transparent and just return the original Brep, instead, it errors out.

I hadn’t imagined you wanted to find text objects, I can add those - instead of meshing the text, which could be long if you have a lot of objects, I will try using the text object’s aligned bounding box and test for the 4 corners being in. There might be a few marginal cases where it will fail if it’s very close to the edge…

I will do some more tweaking today.

–Mitch


#11

OK, here is a cleaned up and rationalized version with some more bells and whistles… I used it as a learning experience for some more RhinoCommon stuff.

  • Objects that can be found now include text objects and hatches in addition to points, curves, surfaces, polysurfaces and meshes.
  • Will only allow you to select a closed volume as input (custom object filter)
  • Hopefully should be “transparent” as concerns extrusion objects (treated like polysurfaces)

One limitation, volumes or surfaces that are coincident with (but not outside of) the outer selection envelope will not be selected. Since I am using the intersection of the objects to detect collisions, and an intersection is found if surfaces coincide, these objects get thrown out. There may be workarounds, but I think they will be a bit painful and I don’t have much time anymore…

Please download and try this one.

–Mitch

SelObjsInsideSolid.py (5.0 KB)


#12

Thanks Mitch, I really appreciate your help. That script is going to help me a ton.

I realized I don’t actually need to select the objects that are on the envelope because they are already part of the grouping that I’m using - its only extra objects for hinges, drawer runners etc that I need to capture, so it will work perfectly

-Gav


#13

Agree. Works like a charm. Added to a button immediately.

By the way: mesh has the same IsPointInside() method for checking on point inclusion, brep has. So with a little bit of work of copying parts of the current code and replacing brep.IsPointInside with its mesh counterpart, and adding an initial condition for separating the mesh instance from the rest of the code, one can get a nice additional option of checking for solid meshes too.


#14

You’re talking about using a mesh as an outer envelope object? I had considered that, but for time reasons I gave up on the idea…

Since I use intersections to determine if the objects cross the envelope boundary, I would need to use mesh intersections. As there is no Brep-Mesh intersector, I would have to mesh all the breps. And, there is no Mesh-Curve intersector either, so NURBS curves would need to be converted to polylines. That’s when I decided to abandon the idea… :smile:

–Mitch


#15

Exactly. That’s the way grasshopper’s Mesh Curve intersection works too
Do you think that would be inaccurate (converting to a polyline curve)? I think Rhino handles this conversion pretty nice.


#16

Depends on the parameters used… I was more worried about Breps which, depending on the complexity, could take a long time to mesh. If they have a render mesh that can be extracted and used, but that’s not guaranteed.

–Mitch


#17

Hi there,
thank you for the script. Could the script be altered to have multiple solids intersecting with the content to be selected?

in line 43, I changed it to the following
solid=rs.GetObjects(msg,8+16+1073741824,minimum_count=1,maximum_count=1000,custom_filter=closedObj)

I keep getting Message: expected UInt32, got list as a message.
How could this be changed?

Thanks in advance!


#18

@Helvetosaur Thanks again for this. Is it easy to add blocks to the type of objects to be selected? This script is not selecting blocks for me.


#19

Well, block instances are kind of a special case… They can contain (references to) any number of different types of objects; its also not possible to sub-select individual objects inside a block instance - it’s one entity…

So, it should be possible to check to see if ALL the objects inside the block are entirely inside the selection volume and select the block instance if that’s the case… Might be slow if there are a lot of objects. Is that what you are looking for?

–Mitch


#20

The blocks i’m using are very condensed. Composed only of a couple objects at most. All are close together and close to insert pt.