Join only touching surfaces into polysurfaces

I have a structural column (hollow core). I selected the exterior and interior faces, omitting the caps. I would like to join the surfaces into two polysurfaces, an exterior and interior polysurface. Right now, if I join the surfaces, it creates a single polysurface, with a gap. I am not used to the geometry engine behaving this way, and was expecting it to create two polysurfaces instead since there are two groups which are not touching.

This is similar, in terms of grouping the surfaces by normal direction:
http://dynamobim.com/forums/topic/group-surfaces-by-normal/

mccrone states that he had to write a deep recursive search in python in order to achieve the same result:

How would I sort the two sets of polysurfaces into a group for the interior of the column and another set for the exterior, and join them together into two polysurfaces?

@vk1 This should help …
CorePolySurface.dyn (7.3 KB)

Ar you just trying to get a polysurface of all faces? If so, have you tried ‘element.solid’ or ‘element.geomtry’?

Hello Vikram,

Thank you for your solution. It works flawlessly. I have no idea what the logic is though, could you please enlighten me? How does grouping the surfaces by area work?! This is truly amazing.

What I wrote yesterday to solve this was stupid, I would recursively check if a surfaces intersects other surfaces until all surfaces within a set are joined up. It wasn’t robust, and worked pretty poorly:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('DSCoreNodes')
import DSCore
from DSCore import *

#Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Import geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from System.Collections.Generic import *

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk


#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN

surfacesArray = IN[0]

surfacesNotIntersecting = []
surfaceJoined = "" 

surfacesAlreadyIntersecting = []
surfaceJoinedGroup2 = "" 

for surface1 in surfacesArray:

    if(len(surfacesAlreadyIntersecting) == 0):
        for surface2 in surfacesArray:
            if(surface1 != surface2):
                if(Geometry.DoesIntersect(surface1, surface2)):
                    surfacesAlreadyIntersecting.append(surface1)
                    surfacesAlreadyIntersecting.append(surface2)
                    surfaceJoined = PolySurface.ByJoinedSurfaces(surfacesAlreadyIntersecting)
                    
    else:
        
        if(Geometry.DoesIntersect(surface1, surfaceJoined)):
                    surfacesAlreadyIntersecting.append(surface1)
                    surfaceJoined = PolySurface.ByJoinedSurfaces(surfacesAlreadyIntersecting)
        else:
            surfacesNotIntersecting.append(surface1)
            surfaceJoinedGroup2 = PolySurface.ByJoinedSurfaces(surfacesNotIntersecting)

#sorting is not thorough enough. come back and make it more robust 


#Assign your output to the OUT variable.

if(surfaceJoinedGroup2 == ""):
    OUT = [surfaceJoined]
    
else:
    OUT = [surfaceJoined,surfaceJoinedGroup2]
2 Likes

Hello Paul, I was attempting to join a pipe, caps removed, into two polysurfaces, one for the interior face and one for the exterior face.

Hello Vikram,

I think I understand the logic for your program: You sort the surfaces with identical areas together and you join them.

That makes sense for pipes, which have identical surfaces, but will not work for a W-flange (as there is no hollow core). It also will not work for a rounded-square shape (HSS) steel. I think.

I added more code to my script and now it’s working better:

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('DSCoreNodes')
import DSCore
from DSCore import *

#Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Import geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from System.Collections.Generic import *

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk


#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN

shapesArray = IN[0]
shapesArrayWithPolySurfaces = []



def logText(string1):
    stdsave = sys.stdout
    fout = open(r'C:\Users\user\Desktop\logs\logfile.txt','w')
    sys.stdout = fout
    print string1
    
    sys.stdout = stdsave
    fout.close()



def polySurfacesFromGeometry (surfacesArray): #this function figures out which surfaces touch each other, making polysurfaces from each set of surfaces that touch each other. 

    resultantPolySurfaceArray = ""
    
    surfacesNotIntersecting = []
    surfaceJoined1 = "" 

    surfacesAlreadyIntersecting = []
    surfaceJoined2 = "" 


    for surface1 in surfacesArray:

        if(len(surfacesAlreadyIntersecting) == 0):
            for surface2 in surfacesArray:
                if(surface1 != surface2):
                    if(Geometry.DoesIntersect(surface1, surface2)):
                        surfacesAlreadyIntersecting.append(surface1)
                        surfacesAlreadyIntersecting.append(surface2)
                        surfaceJoined1 = PolySurface.ByJoinedSurfaces(surfacesAlreadyIntersecting)
                        break;
        
        else:
            
            if surface1 in surfacesAlreadyIntersecting:
                continue;
                
            if(Geometry.DoesIntersect(surface1, surfaceJoined1)):
                        surfacesAlreadyIntersecting.append(surface1)
                        surfaceJoined1 = PolySurface.ByJoinedSurfaces(surfacesAlreadyIntersecting)
            else:
                surfacesNotIntersecting.append(surface1)
                surfaceJoined2 = PolySurface.ByJoinedSurfaces(surfacesNotIntersecting)

    #sorting is not thorough enough. come back and make it more robust 


    if(surfaceJoined2 == ""):
        resultantPolySurfaceArray = [surfaceJoined1]
        
    else:

        if(Geometry.DoesIntersect(surfaceJoined1, surfaceJoined2)):
            singlePolySurface = PolySurface.ByJoinedSurfaces([surfaceJoined1,surfaceJoined2])
            resultantPolySurfaceArray = [singlePolySurface]
            
        else: 
            resultantPolySurfaceArray = [surfaceJoined1,surfaceJoined2]
    
    return resultantPolySurfaceArray;
    
    
for shape in shapesArray:
    polysurfacesForShape = polySurfacesFromGeometry(shape)
    shapesArrayWithPolySurfaces.append(polysurfacesForShape)

OUT = shapesArrayWithPolySurfaces

3 Likes

Fireproofing14.dyn (32.4 KB)
dynamo test light project14.rvt (1.4 MB)

Please check out the files!

The question will stay upon until there is a better way to offset surfaces. But this is a working beta.

1 Like