MaterialElementId from GetRegion from Face from GetBoundingElementFace

I can get the material id from a face of an object (in this case a room) but I can’t seem to get the material id’s of any split regions on the face.

Ultimately, I want to pull materials off the boundary elements of a room (using SpatialElementGeometryCalculator) and have their marks reported in a line-based detail. I’ve got most of it working so long as the surface doesn’t have a region as defined by a Split Face. I think the answer lies in needing an IList but I don’t know how that would work.


This is what is working:

import clr

clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager

from itertools import compress

doc = DocumentManager.Instance.CurrentDBDocument

rooms = UnwrapElement(IN[0])

calculator = SpatialElementGeometryCalculator(doc)

elementMaterial = list()
elementMaterialID = list()
elementEdgeS = list()
elementEdgeE = list()
elementRoom = list()
rSolid = list()
for room in rooms:
	results = calculator.CalculateSpatialElementGeometry(room)
	roomSolid = results.GetGeometry()
	rSolid.append(roomSolid)
   	roomMaterial = list()
	roomMaterialID = list()
	roomEdgeS = list()
	roomEdgeE = list()
	normals = list()
	faceEdge = list()
	for face in roomSolid.Faces:
		for subface in results.GetBoundaryFaceInfo(face):
 			boundingElement = subface.GetBoundingElementFace()
			normalFace = boundingElement.ComputeNormal(UV())
			normalZ = normalFace.Z
		#if normalZ == 1:
		#	floorFace = boundingElement
		if normalZ == 0:
			#floorInt = floorFace.Intersect(boundingElement)
			materialID = boundingElement.MaterialElementId
			materialName = doc.GetElement(materialID).Name
			roomMaterialID.append(materialID)
			roomMaterial.append(materialName)
			faceEdge=face.EdgeLoops
			for loop in faceEdge:
				for fE in loop:
					curve = fE.AsCurve()
					p = curve.GetEndPoint(0)
					q = curve.GetEndPoint(1)
					#r = curve.GetEndPoint(2)
					roomEdgeS.append(p)
					roomEdgeE.append(q)
	
elementRoom.append(rSolid)
elementEdgeS.append(roomEdgeS)
elementEdgeE.append(roomEdgeE)	
elementMaterial.append(roomMaterial)
elementMaterialID.append(roomMaterialID)

OUT = elementEdgeS,elementEdgeE,elementMaterialID

And this is what I started to do for the regions:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)

faces = UnwrapElement(IN[0])

elemmat = []
mat = []
sublist=[]


for face in faces:
for f in face:
	if f.HasRegions:
		region=f.GetRegions()
		for r in region:
			mat=r.MaterialElementId
			elemmat.append(mat)
	else:
		mat=f.MaterialElementId
		elemmat.append(mat)
sublist.append(elemmat)

#Assign your output to the OUT variable.
OUT = sublist

Maybe it helps to see the graph?

For some reason the GetBoundingElementFace method does not return the face regions. I’m trying with the wall geometry. It works, but when a wall share two or more rooms takes all the face regions of the wall.

import clr

clr.AddReference("RevitAPI")
clr.AddReference("RevitServices")

import Autodesk
import RevitServices

from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager

doc =  DocumentManager.Instance.CurrentDBDocument

rooms = UnwrapElement(IN[0])

options = SpatialElementBoundaryOptions()
calculator = SpatialElementGeometryCalculator(doc, options)

roomRegionMaterial = []
for room in rooms:    
    results = calculator.CalculateSpatialElementGeometry(room)    
    roomSolid = results.GetGeometry()
    
    regionFaceMaterial = []
    for face in roomSolid.Faces:  
        for subface in results.GetBoundaryFaceInfo(face):
            roomFace = subface.GetSpatialElementFace()

            wallFace = subface.GetBoundingElementFace()                    
            wallId = subface.SpatialBoundaryElement.HostElementId
            wall = doc.GetElement(wallId)            
            geomElements = wall.get_Geometry(Options())            
            
            regionMaterial = []
            for geomElement in geomElements:
                if geomElement != Solid:
                    solid = geomElement                    
                    
                    for solidFace in solid.Faces:
                        if solidFace.HasRegions:
                            regions = solidFace.GetRegions()
                            for reg in range(1, len(regions)):
                                materialElementId = regions[reg].MaterialElementId
                                materialName = doc.GetElement(materialElementId).Name                                                               
                                regionMaterial.append(materialName)                                                                
                        else:
                            materialElementId = wallFace.MaterialElementId
                            materialName = doc.GetElement(materialElementId).Name
                            regionMaterial.append(materialName)
                            break                            
                        
            regionFaceMaterial.append(regionMaterial)                                       
    roomRegionMaterial.append(regionFaceMaterial)       
        
OUT = roomRegionMaterial

I also tried intersecting the face regions with the faces of the room, but nothing…

for reg in range(1, len(regions)):
    if regions[reg].Intersect(roomFace) == FaceIntersectionFaceResult.Intersecting:
        materialElementId = regions[reg].MaterialElementId
        materialName = doc.GetElement(materialElementId).Name                                                               
        regionMaterial.append(materialName)
    else:
        regionMaterial.append(False) 

Saludos.

2 Likes

Thanks for the effort.