Problem with detecting the inside connection between extrusions

I am a Python developer using Rhino to do a few spatial analyses. My case here is that I have to find the inside connection between the extrusions and I have written a function to detect it. Surprisingly it works for one input in layer (L1) and doesn’t work for other in layer (S1), I have checked infos the object type and whether corners are snapped properly. Likewise, verified everything whether both layers has similar properties. Both couldn’t able to find why it is working for one and not for other one.


I will the add script and sample .3dm file which i am checking below:

def check_cubevscube_connection(layer_name):
def check_cube_position(cube1_guid, cube2_guid):
# Get the bounding boxes of the cubes
cube1_bounding_box = rs.BoundingBox(cube1_guid)
cube2_bounding_box = rs.BoundingBox(cube2_guid)

      if cube1_bounding_box and cube2_bounding_box:
          # Create bounding box objects
          cube1_bbox = rg.BoundingBox(cube1_bounding_box)
          cube2_bbox = rg.BoundingBox(cube2_bounding_box)
  
          # Get the corner points of the bounding boxes
          cube1_corners = cube1_bbox.GetCorners()
          cube2_corners = cube2_bbox.GetCorners()
  
          # Check if all cube1 corners are inside cube2
          cube1_inside_cube2 = all(cube2_bbox.Contains(point) for point in cube1_corners)
  
          if cube1_inside_cube2:
              return "inside"
  
      return "Unable to determine"
  
  layer_id = rs.LayerName(layer_name)
  if layer_id is None:
      return {"Connection": "Layer not found."}
  
  objects = rs.ObjectsByLayer(layer_id)
  polysurface_ids = {}
  
  # Find surface and polysurface IDs based on user attribute text
  for obj in objects:
      # Check if the object has a user attribute text 'ID'
      if rs.GetUserText(obj, 'ID'):
          # Get the ID value
          object_id = rs.GetUserText(obj, 'ID')
  
          # Check if the object is a polysurface using rs.IsObjectSolid()
          if rs.ObjectType(obj) == 1073741824:
              polysurface_ids[object_id] = obj
  
  if len(polysurface_ids) < 2:
      return {"Connection": "Not enough polysurfaces in the layer."}
  
  connection_info = []
  for id1, obj1 in polysurface_ids.items():
      for id2, obj2 in polysurface_ids.items():
          if id1 != id2:
              result = check_cube_position(obj1, obj2)
              if result == "inside":
                  connection = {
                      "Inside ID": id1,
                      "Connection Type": "inside",
                      "Outside ID": id2,
                      "Description": "ID {} is inside ID {}".format(id1, id2)
                  }
                  connection_info.append(connection)
  
  if not connection_info:
      return {"Connection": "No connection found between polysurfaces."}
  
  return {"Connections": connection_info}

check_cube_connection.3dm (36.9 KB)
check_cube_connection.py (2.9 KB)
I have been blocked here and i couldn’t find anything suspicious here. Could I get some assist to find the issue here?

Thanks in advance!

Regards,
Rajasirpi

Hi Rajasirpi - can you please post the py as an attached file?

-Pascal

Hi @pascal - I have attached the .py file now. please have a look at it. Thank You

-Rajasirpi

Hi Rajasirpi - the results for the layer that does work seem incomplete…? I think I would expect more than two

            "Connection Type": "inside", 
            "Outside ID": "6", 
            "Description": "ID 5 is inside ID 6", 
            "Inside ID": "5"

            "Connection Type": "inside", 
            "Outside ID": "6", 
            "Description": "ID 2 is inside ID 6", 
            "Inside ID": "2"

Maybe I am not understanding the goal of the script…

-Pascal

Hi Rajasirpi- It looks to me like all the corners are coincident and not contained by the other boxes - you may need to test using brep versions of the bounding boxes so that you can specify a tolerance and ‘strictness’

https://mcneel-apidocs.herokuapp.com/api/rhinocommon/rhino.geometry.brep/ispointinside

something like this:

import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs
import itertools

def test():
    tol = sc.doc.ModelAbsoluteTolerance
    layers = sc.doc.Layers
    
    for layer in layers:
        objs = sc.doc.Objects.FindByLayer(layer)
        
        if len(objs) > 0:
            objIds = [obj.Id for obj in objs]
            ids = [rs.GetUserText(id, "ID") for id in objIds]
            #geos = [rs.coercegeometry(id) for id in ids]
            
            pairs = list(itertools.combinations(objIds,2))
            
            for pair in pairs:
                
                id1, id2 = pair
                geos = [rs.coercegeometry(id) for id in pair]
                
                bb1 = geos[0].GetBoundingBox(True)
                bb2 = geos[1].GetBoundingBox(True)
                c1 = bb1.GetCorners()
                c2 = bb2.GetCorners()
                
                brep1 = bb1.ToBrep()
                brep2 = bb2.ToBrep()
                
                result = 0

                for c in c1:
                    if not brep2.IsPointInside(c,tol, False):
                        result += 1
                        print(str(id1) + " not inside " + str(id2))
                        break
                if result ==0:
                    print(str(id1) + " is inside " + str(id2))
                for c in c2:
                     if not brep1.IsPointInside(c,tol, False):
                         print(str(id2) + " not inside " + str(id1))
                         result += 2
                         break
                if result == 1:
                    print(str(id1) + " is inside " + str(id2))
                print result

test()

-Pascal

Yeah @pascal, You are right. It works but it gives incomplete results. I will check with the script that you have given. Hopefully, it will give me the required results. Thank you

-Rajasirpi

This solution works. I will adapt this logic into my function. Thank you so much!

-Rajasirpi