Filtered element collector to get elements of category on view in docs


What I tried: I am trying to reteive all the walls that appear in a list of floorplans views, but I also want to get the walls from linked documents.

What I expeted: A list of list of walls in this format Docs>View>WallElement

What I got: An Emty lists and no errors! in the right format.

Comment: I am not all too familiar with the filter element collectors and mostly “Frankensteining” things toghether. Something must be happening during the collector because I get as many sublists as I have views. I guess nothing passes the filter and I don’t know why.

import System
import clr
from Autodesk.Revit.DB import *

import RevitServices
from RevitServices.Persistence import DocumentManager

doc = DocumentManager.Instance.CurrentDBDocument

cats = IN[0]
views = UnwrapElement(IN[1])
Doclist = IN[2]

doc_elementlist = list()
for Docs in Doclist:
	elementlist = []
	for cat in cats:
		catlist = list()
		for view in views:
			collector = FilteredElementCollector(Docs)
			filter = ElementOwnerViewFilter(view.Id)
			bic = System.Enum.ToObject(BuiltInCategory, cat.Id)
OUT = doc_elementlist

I can assure you all of my documents have walls, the views are in the current doc.

I don’t believe you can get elements from a linked model by using a view in the current document. The views need to come from the document used in the collector.

You might be able to modify the Data-Shapes node GetLinkedElement.InHostViewAndCategory to work with your process though. I believe the node filters out elements within the bounding region of the view. Just use that node alongside the filtered elements from your current document.

You will have to get the linked elements. Try to use the “RevitLinkType”.

Here is a C# sample that I have used. The code should be very similar because this is mostly all Revit API.

   IList<Element> elems = collector

Check the linked model if you have many models linked by

foreach(Element e in elems)
// cast element to RevitLinkType
RevitLinkType linkType = e as RevitLinkType;
            //loop over linked documents 
            foreach (Document linkedDoc in uiApp.Application.Documents)
                //Check the linked model by name. 
                if (linkedDoc.Title.Equals(linkType.Name))

@Nick_Boyts You are right, the filtered element collector need to use a a view that is within it’s document.

@Mostafa_El_Ayoubi I also found the thread where GetLinkedElement.InHostViewAndCategory was born from:How to collect elements from links visible on a view in the host model? And modified it like so to get it to use lists documents. And changed the VERY SUBTLE “Elev” parameter call to “Elév.” because french. I just combine it with a Select.ByCategoryAndView to get the current document, then AddItemToFront with funny lacing.

As a side note, ElementOwnerViewFilter only considers 2d elements, wish explains my empty lists.

#Copyright (c) mostafa el ayoubi ,  2017
#Data-Shapes ,

import clr
from Autodesk.Revit.DB import*
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
import System
from System.Collections.Generic import *

from Autodesk.DesignScript.Geometry import*
doc = DocumentManager.Instance.CurrentDBDocument

if isinstance(IN[2],list):
	categories = IN[2]
	categories = [UnwrapElement(IN[2])]
linkdocs = IN[1]
if isinstance(IN[0],list):
	views = UnwrapElement(IN[0])
	views = [UnwrapElement(IN[0])]

collector = []

#getting project base point elevation
basepointfilter = ElementCategoryFilter(BuiltInCategory.OST_ProjectBasePoint)
basepoint = FilteredElementCollector(doc).WherePasses(basepointfilter).ToElements()
bpelevation = [b.ParametersMap.get_Item('Elév.').AsDouble() for b in basepoint]

#Category filter
catfilter = []
for i in categories:
	catfilter.append(ElementCategoryFilter(System.Enum.ToObject(BuiltInCategory, int(str(i.Id)))))

catfilterlist = List[ElementFilter](catfilter)
filter = LogicalOrFilter(catfilterlist)

UIunit = Document.GetUnits(doc).GetFormatOptions(UnitType.UT_Length).DisplayUnits
level = []
for v in views:

	#creating a boundingbox for each view from it's crop box and view range
	bb = v.CropBox
	vr = v.GetViewRange()
	topclip = PlanViewPlane.TopClipPlane
	bottomclip = PlanViewPlane.BottomClipPlane
	cutclip = PlanViewPlane.CutPlane
	toplevel = (doc.GetElement(vr.GetLevelId(topclip)))
	topoffset = vr.GetOffset(topclip)
	cutlevel = (doc.GetElement(vr.GetLevelId(cutclip)))
	cutoffset = vr.GetOffset(cutclip)
		topZ = toplevel.Elevation + topoffset - bpelevation[0]
		topZ = cutlevel.Elevation + cutoffset - bpelevation[0]
	bottomlevel = (doc.GetElement(vr.GetLevelId(bottomclip)))
	bottomoffset = vr.GetOffset(bottomclip)
		bottomZ = bottomlevel.Elevation + bottomoffset - bpelevation[0]
	except :
		bottomZ = cutlevel.Elevation - bpelevation[0]
	min = bb.Min
	max = bb.Max
	newmin = XYZ(min.X,min.Y,bottomZ)
	newmax = XYZ(max.X,max.Y,topZ)
	ol = Outline(newmin,newmax)

	#combining boundingbox and category filters
	bbfilter = BoundingBoxIntersectsFilter(ol)
	andfilter = LogicalAndFilter(filter,bbfilter)

	#collecting elements
	collectordoc = []
	for linkdoc in linkdocs:

OUT = collector

I am trying to do something very similar, but with Rooms and only the current document. However, I too am getting an empty list when feeding it multiple views. I have tried to change the lacing, but that doesn’t help.

The last post by @slepagetrudeau allowed me to work it out along with using @2 Levels for the Create Annotation Tag Node.

1 Like