Determine if element is on wall

I’m trying to create a tool to check if our MEPT elements are on walls. They are not hosted. I’m new to python, the API, and coding in general. I’ve made a few python nodes in Dynamo but that is it.

From the code below you can probably see that I’m poking around in the dark, trying to find something that would be useful. At first I assumed that I could get the solids of both the walls and elements and see if they intersect but have had issues trying to even get the solid. I also can’t seem to find anything I could use to check if they intersect.

I’ve also started looking into the Location class and HostObjectUtils for the walls. It seems like I’m able to get to a certain point with obtaining information like the curve or point or face, but then stumble on trying to find some method on how to determine how they related to each other.

I’m not asking for the code but if anyone has done something similar and would be willing to point to the best classes and methods I could try creating it myself. Thanks for any help.

# Check if on wall

# Import libraries
from pyrevit import DB, revit, script, forms
from Autodesk.Revit.DB import *
#FilteredElementCollector,
#RevitLinkInstance,
#GeometryInstance)
from System.Collections.Generic import List

# Current document
doc = __revit__.ActiveUIDocument.Document
################################################################################
# Linked documents
link_instances = FilteredElementCollector(doc) \
                    .OfClass(RevitLinkInstance)\
                    .ToElements()

link_docs = []
for l in link_instances:
    if l.GetLinkDocument() != None:
        l_doc = l.GetLinkDocument()
        if l_doc:
            link_docs.append(l_doc)
        else:
            pass
    else:
        pass

################################################################################
# Get items for comparing
getFixtures = FilteredElementCollector(doc).\
            OfCategory(DB.BuiltInCategory.OST_ElectricalFixtures).\
            WhereElementIsNotElementType().\
            ToElements()

getWalls = []
for l in link_docs:
    lWalls = FilteredElementCollector(l).\
            OfCategory(DB.BuiltInCategory.OST_Walls).\
            WhereElementIsNotElementType().\
            ToElements()
    for w in lWalls:
        getWalls.append(w)
        


################################################################################
# Get Element location info
fLocation = []
for f in getFixtures:
    fLocation.append(f.Location.Point)

print(fLocation)
print("____________________________________________________________________")

wLocation = []
for w in getWalls:
    wLocation.append(w.Location.Curve)

print(wLocation)

gWalls = []
for w in getWalls:
    extSide = HostObjectUtils.GetSideFaces(w,ShellLayerType.Exterior)
    for e in extSide:
        extface = w.GetGeometryObjectFromReference(e)
        if extface == None:
            continue
        else:
            gWalls.append(extface)
            print(extface)



#print(getFixtures)
#print(getWalls)
################################################################################
# Get geometry
# fGeometry = []
# for f in getFixtures:
    # fGeometry.append(f.get_Geometry(Options()))

# wGeometry = []
# for w in getWalls:
    # wGeometry.append(w.get_Geometry(Options()))

# fTest = []
# for f in getFixtures:
    # fGeo = f.get_Geometry(Options())
    # fgEnum = fGeo.GetEnumerator()
    # next  = fgEnum.MoveNext()
    # geoInst = fgEnum.Current
    # instGeo = geoInst.GetInstanceGeometry()
    # fTest.append(instGeo)

# fBox = []
# for f in fGeometry:
    # fBox.append(f.GetBoundingBox)
#print(fBox)
#print(geoInst.__getattribute__)
#print(dir(geoInst))
#print(fTest)



# print("____________________________________________________________________")
# print(fGeometry)
# print("____________________________________________________________________")
# print(wGeometry)
# test = fGeometry[0].GetEnumerator()
# print("____________________________________________________________________")
# print(test)
# test2 = test.Current
# print("____________________________________________________________________")
# print(test2)
################################################################################
# Compare lists

Hello @Crapai

Have fun with this great method :grinning:

And here’s a thread that might be a good read for you

Thanks, I should have mentioned. I have seen that method but was scared away because it is a slow filter. I’m going to have to run this for maybe hundreds of elements and walls. I read somewhere that it should only be used for a handful. Have you ran it with many elements?

Also not entirely sure how to get a solid from a wall.

I was thinking today that i might want to try to stick to location for the element because i want to make sure the insertion point is on the wall face. Its probably not good enough to make sure the element intersects the solid because i want to catch cases when those pesky architects move walls by a few inches or our designers misclick and forget to move the element to the wall face.

And I’d recommend using functions in your code to make it better understandable for others and yourself. Use proper functon names and there is no need for additional coments.
Something like this.

from pyrevit import DB, revit, script, forms
from Autodesk.Revit.DB import FilteredElementCollector, RevitLinkInstance, HostObjectUtils, ShellLayerType
from System.Collections.Generic import List

doc = __revit__.ActiveUIDocument.Document

def get_linked_docs(doc):
    link_instances = FilteredElementCollector(doc) \
                        .OfClass(RevitLinkInstance)\
                        .ToElements()
    
    link_docs = [l.GetLinkDocument() for l in link_instances if l.GetLinkDocument()]
    return link_docs

def get_fixtures(doc):
    return FilteredElementCollector(doc)\
            .OfCategory(DB.BuiltInCategory.OST_ElectricalFixtures)\
            .WhereElementIsNotElementType()\
            .ToElements()

def get_linked_walls(link_docs):
    walls = []
    for l in link_docs:
        lWalls = FilteredElementCollector(l)\
                .OfCategory(DB.BuiltInCategory.OST_Walls)\
                .WhereElementIsNotElementType()\
                .ToElements()
        walls.extend(lWalls)
    return walls

def get_fixture_locations(fixtures):
    return [f.Location.Point for f in fixtures]

def get_wall_locations(walls):
    return [w.Location.Curve for w in walls]

def get_external_walls_faces(walls):
    gWalls = []
    for w in walls:
        extSide = HostObjectUtils.GetSideFaces(w, ShellLayerType.Exterior)
        for e in extSide:
            extface = w.GetGeometryObjectFromReference(e)
            if extface:
                gWalls.append(extface)
    return gWalls

link_docs = get_linked_docs(doc)
fixtures = get_fixtures(doc)
linked_walls = get_linked_walls(link_docs)
f_locations = get_fixture_locations(fixtures)
w_locations = get_wall_locations(linked_walls)
external_wall_faces = get_external_walls_faces(linked_walls)
1 Like

Look at the dynamo post

  • Get wall solid with w.get_Geometry(opt)
1 Like

Then just scale the solids.

In my beginnings I tested every element with every wall in the project for intersections, that took really long. Compared to that ElementIntersectsSolidFilter is a super fast method.

I’ve tried get_Geometry before but it doesn’t give me a solid. It provides GeometryElement and I can see anyway to get solid from that.