Filter Element from Linked Model only if visible in active view

It’s seem related to the Element binding process
2 ways to solve:

  • use Dynamo Player
  • close and re-open the dyn file in Dynamo UI

see here

1 Like

I’ve tried your script on section, but it doesn’t work:

Hi @PiotrB

The code work only for FloorPlan, I’ll look when I have a little more time, but you can get inspiration from this code

Here an updated code for ViewPlans and SectionViews

Python Code (compatible all engines)
Edit 25/04/2024 : code updated → add input list view

import clr
import sys
import System
from System.Collections.Generic import List
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

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

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

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

def gen_PairPts(*args):
    """generator for point pair loop
    """
    for idx, pt in enumerate(args):
        try: yield pt, args[idx + 1]
        except : yield pt, args[0]

def solid_fromBBX(bbox):
    pt0 = XYZ( bbox.Min.X, bbox.Min.Y, bbox.Min.Z )
    pt1 = XYZ( bbox.Max.X, bbox.Min.Y, bbox.Min.Z )
    pt2 = XYZ( bbox.Max.X, bbox.Max.Y, bbox.Min.Z )
    pt3 = XYZ( bbox.Min.X, bbox.Max.Y, bbox.Min.Z )
    #create generator
    pairPts = gen_PairPts(pt0, pt1, pt2, pt3) 
    #Create loop, still in BBox coords
    edges = List[Curve]()
    for pt1, pt2 in pairPts:
        edges.Add(Line.CreateBound( pt1, pt2 ))

    height = bbox.Max.Z - bbox.Min.Z
    baseLoop = CurveLoop.Create( edges )
    loopList = List[CurveLoop]()
    loopList.Add( baseLoop )
    preTransformBox = GeometryCreationUtilities.CreateExtrusionGeometry( loopList, XYZ.BasisZ, height )
    transformBox = SolidUtils.CreateTransformed( preTransformBox, bbox.Transform )
    return transformBox

def toList(x):
    if isinstance(x, (list, dict)) or \
            (hasattr(x, "GetType") and x.GetType().GetInterface("ICollection") is not None):
        return x
    else : return [x]
    
lst_View = toList(UnwrapElement(IN[0]))
catList = toList(UnwrapElement(IN[1]))
catBiplst = [ System.Enum.ToObject(BuiltInCategory, int(x.Id.ToString()) ) for x in catList]
linkInstances = FilteredElementCollector(doc).OfClass(DB.RevitLinkInstance)
out = []

for view_ in lst_View:
    temp = []
    if view_.ViewType  == ViewType.Section:
        for lnkInstance in linkInstances:
            lnk_doc = lnkInstance.GetLinkDocument()
            transf = lnkInstance.GetTotalTransform()
            bbxView = view_.CropBox 
            solidbbx = solid_fromBBX(bbxView)
            # apply link instance transform and create Filters (Solid + Categories)
            solidbbx = DB.SolidUtils.CreateTransformed(solidbbx, transf.Inverse)
            filterSolid = ElementIntersectsSolidFilter(solidbbx)
            cats = List[BuiltInCategory](catBiplst)
            filtercat = ElementMulticategoryFilter(cats)
            elemIntersect = FilteredElementCollector(lnk_doc).WherePasses(filterSolid).WherePasses(filtercat).WhereElementIsNotElementType().ToElements()
            # FOR DEBUG
            #out.append([lnkInstance.Name, elemIntersect, solidbbx.ToProtoType()])
            temp.append([lnkInstance.Name, elemIntersect])
            
        
    elif view_.ViewType in [ViewType.CeilingPlan, ViewType.FloorPlan]:
        #get bootom and top Elevation of active viewrange 
        viewRange = view_.GetViewRange()
        topClipPlaneId = viewRange.GetLevelId(PlanViewPlane.TopClipPlane) 
        topClipPlane = doc.GetElement(topClipPlaneId)
        topOffset = viewRange.GetOffset(PlanViewPlane.TopClipPlane)
        
        bttmClipPlaneId = viewRange.GetLevelId(PlanViewPlane.BottomClipPlane) 
        bttmClipPlane = doc.GetElement(bttmClipPlaneId)
        bttmOffset = viewRange.GetOffset(PlanViewPlane.BottomClipPlane)
        
        for lnkInstance in linkInstances:
            lnk_doc = lnkInstance.GetLinkDocument()
            transf = lnkInstance.GetTotalTransform()
            # get min and max from active ViewRange
            bbxActView = view_.CropBox 
            bbxActView.Min = XYZ(bbxActView.Min.X, bbxActView.Min.Y, bttmClipPlane.ProjectElevation + bttmOffset)
            bbxActView.Max = XYZ(bbxActView.Max.X, bbxActView.Max.Y, topClipPlane.ProjectElevation + topOffset)
            bbxActView.Transform = transf.Inverse
            # create Solid Filter
            solidbbx = solid_fromBBX(bbxActView)
            filterSolid = ElementIntersectsSolidFilter(solidbbx)
            # create categories filter
            cats = List[BuiltInCategory](catBiplst)
            filtercat = ElementMulticategoryFilter(cats)
            elemIntersect = FilteredElementCollector(lnk_doc).WherePasses(filterSolid).WherePasses(filtercat).WhereElementIsNotElementType().ToElements()
            # FOR DEBUG
            #out.append([lnkInstance.Name, elemIntersect, solidbbx.ToProtoType(), bbxActView.Min.ToPoint(), bbxActView.Max.ToPoint()])
            temp.append([lnkInstance.Name, elemIntersect])
    out.append([view_, temp])
OUT = out
3 Likes

Hey, your Python code works for a single view. When it got a list o views there is an error:
image

You’ll need to append a loop into the code. something like for view in views: and then offset the rest of the actions in that section below it.

2 Likes

code upaded in previous post

1 Like