This seemed to work! Will check it through more thoroughly tomorrow....
Thanks again, I'm sure it's obvious which of the other forum posts have aided me 🙂
Obviously this is (Dynamo) Python code.
All comments welcome.
Cheers,
Mark
#thanks for all the help everyone
import clr
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import System
# Import Element wrapper extension methods
clr.AddReference("RevitNodes")
import Revit
from Autodesk.Revit.DB import *
clr.AddReference("RevitAPIUI")
from Autodesk.Revit.UI.Selection import ObjectType
#for our selection
from Autodesk.Revit.UI.Selection import *
# Import DocumentManager and TransactionManager #
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
uiApp = DocumentManager.Instance.CurrentUIApplication
class selFilt(ISelectionFilter):
#"__init__" is a reseved method in python classes. It is called as a constructor in object oriented terminology. This method is called when an object is created from a class and it allows the class to initialize the attributes of the class.
#it's almost like the self is implied? it has to be there but has no variable, we can't use the allow element function without a separate init, we then must have an equation to keep the code format
def __init__(self, element):
e = element
def AllowElement(self, e):
if e.ToString() == 'Autodesk.Revit.DB.Wall':
return True
else:
return False
def AllowReference(self, ref, point):
return true
#so to compensate for different shared position heights, we need the Internal Project Point, even if it's not current!
#otherwise our cutting line will not have the correct Z value
locName = IN[3]
projectLocs = doc.ProjectLocations
for loc in projectLocs:
if loc.Name == locName:
pos = XYZ(0,0,0)
locPosition = loc.GetProjectPosition(pos).Elevation
solidBaseHtZ = doc.ActiveView.GenLevel.ProjectElevation
solidBaseXYZ = XYZ(0,0,1)
if solidBaseXYZ.Z < 1:
solidBaseXYZ == XYZ(0,0,1)
#get the cut plane offset of the view
solidTopHt= doc.ActiveView.GetViewRange().GetOffset(PlanViewPlane.CutPlane)
cropSh = doc.ActiveView.GetCropRegionShapeManager().GetCropShape()
targetWalls = []
obt = ObjectType.LinkedElement
refElemsLinked = uidoc.Selection.PickObjects(obt, "Please pick elements in the linked model")
refElemLinked = refElemsLinked[0]
for refElemLinked in refElemsLinked:
elem = doc.GetElement(refElemLinked.ElementId)
docLinked = elem.GetLinkDocument()
linkedElement = docLinked.GetElement(refElemLinked.LinkedElementId)
targetWalls.append(linkedElement)
collector = FilteredElementCollector(doc)
elem = doc.GetElement(refElemLinked.ElementId)
docLinked = elem.GetLinkDocument()
#let's go get all walls in the link for use in defining extents of area to interrogate
activeViewId = doc.ActiveView.Id
fec=ElementCategoryFilter(BuiltInCategory.OST_Walls)
#walls in link
targetWalls = FilteredElementCollector(docLinked,doc.ActiveView.Id).WherePasses(fec).WhereElementIsNotElementType().ToElements()
#walls in model
wallsinDoc = FilteredElementCollector(doc, doc.ActiveView.Id).WherePasses(fec).WhereElementIsNotElementType().ToElements()
allWallsInLnkNDoc = []
if docLinked != None and doc.ActiveView.CropBoxVisible:
#Creation of the intersecting solid box for the link (in this case almost in origin)
linkInst = doc.GetElement(refElemLinked.ElementId)
virtualSolid = GeometryCreationUtilities.CreateExtrusionGeometry(cropSh, solidBaseXYZ, solidTopHt)
virtualLinkSolid = SolidUtils.CreateTransformed(virtualSolid, linkInst.GetTotalTransform().Inverse)
solidIntersecFil = Autodesk.Revit.DB.ElementIntersectsSolidFilter(virtualLinkSolid)
instanceElementsInViewRvL = FilteredElementCollector(docLinked).WhereElementIsNotElementType().WherePasses(solidIntersecFil)
else:
#so we want to get all walls in the extent of the view if the view is not cropped.
#we don't want to use the crop region, because that might have been left at some tiny
#part of the screen.
#so we will get all the walls in the model, get the max and min of their bounding box
#and create a new bounding box which spans all of them
#we can then create a solid from it using the level offset and cutplane, and run an intersect on that
#Bounding boxes of walls in link
allWallsInLnkNDocBB = []
for lnkWall in targetWalls:
lnkWallBB = lnkWall.get_BoundingBox(None)
allWallsInLnkNDocBB.append(lnkWallBB)
#Bounding boxes of walls in doc
#seems like it will be handy for when we don't want links
for wallInDoc in wallsinDoc:
wallBB = wallInDoc.get_BoundingBox(None)
allWallsInLnkNDocBB.append(wallBB)
#get bb max and mins
bBMaxX, bBMaxY, bBMinX, bBMinY = [],[],[],[]
for wallBB in allWallsInLnkNDocBB:
bBMinX.append(wallBB.Min.X)
bBMinY.append(wallBB.Min.Y)
bBMaxX.append(wallBB.Max.X)
bBMaxY.append(wallBB.Max.Y)
#now input the max and min values
pt0 = XYZ(min(bBMinX), min(bBMinY), solidBaseHtZ)
pt1 = XYZ(max(bBMaxX), min(bBMinY), solidBaseHtZ)
pt2 = XYZ(max(bBMaxX), max(bBMaxY), solidBaseHtZ)
pt3 = XYZ(min(bBMinX), max(bBMaxY), solidBaseHtZ)
#edges in BBox coords
edge0 = Line.CreateBound(pt0, pt1)
edge1 = Line.CreateBound(pt1, pt2)
edge2 = Line.CreateBound(pt2, pt3)
edge3 = Line.CreateBound(pt3, pt0)
#create loop, still in BBox coords
edges =list()
edges.Add(edge0);
edges.Add(edge1);
edges.Add(edge2);
edges.Add(edge3);
baseLoop = CurveLoop.Create(edges)
loopList = list()
loopList.Add(baseLoop)
linkInst = doc.GetElement(refElemLinked.ElementId)
VirtualSolid = GeometryCreationUtilities.CreateExtrusionGeometry(loopList, solidBaseXYZ, 5)
VirtualLinkSolid = SolidUtils.CreateTransformed(VirtualSolid, linkInst.GetTotalTransform().Inverse)
solidIntersecFil = Autodesk.Revit.DB.ElementIntersectsSolidFilter(VirtualLinkSolid)
#we used all the walls to make our filter, but for this, we are only returning linked walls
instanceElementsInViewRvL = FilteredElementCollector(docLinked).WhereElementIsNotElementType().WherePasses(solidIntersecFil)
OUT = instanceElementsInViewRvL