Get Filter Rule or Color from Tagged Element

We are a Mechanical Contractor and we use MEP Fabrication Parts for all the different pipe and duct services, such as domestic cold water, domestic hot water, natural gas, RO water, etc. We use view template filters to add color to the services as seen in a testing environment I created below:

The filters are simple and just use the Fabrication Service Name to override the graphics of the filter. However, within Dynamo and the Revit API the override settings seen above are properties of the view, whereas the filter rule information seen below are properties of the element that is being filtered. And I have been having a heck of a time trying to make a bridge between these two classes to accomplish my ultimate goal, which is: to have the Tags be able to inherit the color properties from the element that is tagged. For example: DHWR tag to be orange, DHW to be Red, DCW to be Blue, etc. Right now my department is manually overriding each tag, and can be cumbersome, I have some coding experience (back in college) and have been given this task.

I have Dynamo nodes and python scripts shown below. The main nodes and scripts get all the tags, then get the fabrication part elements that are tagged (in the order in which they were tagged for what it’s worth). those are fed into two scripts, one returns the service name of all the tagged elements. My thought with that was, If I can associate the color values with the filter rules, which includes the service name as a “value” then I could compare arrays/lists and pull the right color for the right filter. Because right now, the script returning the color values of the filters is returning all 40 of them, not just the 13 that are tagged. and they are returned, presumably, in the order they were created.

Python script returning service name:

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

# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument
view = doc.ActiveView

# Input: Element
element = UnwrapElement(IN[0])
partService = []

# Get the service name of each element
for item in element:
    partService.append(item.ServiceName)


            
OUT = partService;

Python script returning filter colors:

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

# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument
view = doc.ActiveView

# Input: Element and Services of tagged elements
element = UnwrapElement(IN[0])
taggedServices = UnwrapElement(IN[1])

# Get the element's ID
for item in element:
    element_id = item.Id
    element_service = item.ServiceName

# Get the view's filter overrides
filter_overrides = view.GetFilters()


# Initialize output
color = None
colorList = []


# Loop through filters to find the override color
for filter_id in filter_overrides:
    if view.IsFilterApplied(filter_id):
        override_settings = view.GetFilterOverrides(filter_id)
        if override_settings.ProjectionLineColor.IsValid:
            color = override_settings.ProjectionLineColor
            RGB = (color.Red, color.Green, color.Blue)
            colorList.append(RGB)
           

OUT = colorList;

I have the service names returned from the tagged elements feeding into the second script as a secondary input in the hopes that it can be used to parse the list down to just the colors of the filters being used by service name. But the trouble is, as stated above, the filter color overrides are referring to the view class, and the filter rules are referring to the element properties and I can not figure out how to build the bridge between them. Any ideas to try are appreciated!

1 Like

Hi,

try to use DB.ElementFilter.PassesFilter(element)

here an example

def get_color_element(elem, view):
    """
    get color element by filter
    """
    fels = view.GetFilters()
    for fel in fels:
        if isinstance(doc.GetElement(fel), DB.ParameterFilterElement):
            filtercats = [x for x in doc.GetElement(fel).GetCategories()]
            # Check if element category corresponds to filter category
            if elem.Category.Id in filtercats:
                #
                elemfilter = doc.GetElement(fel).GetElementFilter()
                if elemfilter is not None and elemfilter.PassesFilter(elem):
                    override = view.GetFilterOverrides(fel)
                    if override.ProjectionLineColor.IsValid:
                        colorvalue = ','.join([str(override.ProjectionLineColor.Red), str(override.ProjectionLineColor.Blue), str(override.ProjectionLineColor.Green)])
                        return override.ProjectionLineColor, colorvalue
                    else:
                        pass
                else:
                    pass
            # Otherwise the element category does not correspond to the filter category
            else:
                pass

    return None, None
2 Likes

Thank you so much!

I was able to use this method with some minor adjustments to fit it into my script, and it is working flawlessly!

1 Like