Dynamo Python Node - Changing “AND or OR” on Parameter Filter Element

Dynamo Python Node - Changing “AND or OR” on Parameter Filter Element

anton.shaw
Explorer Explorer
2,458 Views
2 Replies
Message 1 of 3

Dynamo Python Node - Changing “AND or OR” on Parameter Filter Element

anton.shaw
Explorer
Explorer

Hi Everyone

 

First off I understand you are all probably an extremely busy people so if you take the time to read this or help thank you very much!

 

The python node I’m trying to build is to toggle the “AND or OR” options when building a Parameter Filter Elements as by default when created with Dynamo they are set to “AND”.

As far as I’m aware no OTB nodes or current packages for Dynamo have nodes that can do this inside of them?

But through research I have found that these options are available through the API and I have found some bits of python on forums but they are building the filter rules inside the python node not getting them as a input.

 

I’m really quite new to python/coding but I have usually been able to get by with the help of this forum + others and somewhat being able to read and slightly modify bits of python to get the outcome I require, but not this time.

I have tried to 2 methods both without the success I wanted. I think it’s due to me being so ‘green’ and not fully understanding the casting or how to convert one type into another before casting?

 

Method 1

Create the filter then after it is made change the “AND or OR” with input of Parameter Filter Element (In future another input that would be bool for AND or OR)
-This would cause the least disruption to existing graphs as it’s an additional node after the creation of the filter to toggle “AND or OR”.
ERROR - TypeError: Unable to cast object of type ‘Autodesk.Revit.DB.ParameterFilterElement’ to type ‘Autodesk.Revit.DB.ElementParameterFilter’.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

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

# Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
# Import ToProtoType, ToRevitType geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

# Import DSCore nodes in Dynamo
clr.AddReference('DSCoreNodes')
import DSCore
from DSCore import *

# Import python library
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import os
import shutil
import math
# Import math library
from math import *

#Import Data and Time
from datetime import datetime
now = datetime.now()

#Import System Library
import System
from System.Collections.Generic import *
from System.IO import Directory, Path

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
def ToList(x):
	if isinstance(x,list): return UnwrapElement(x)
	else: return [UnwrapElement(x)]
	
#Preparing input from dynamo to revit
iParafilele = ToList(IN[0])
filterele = List[ElementParameterFilter](iParafilele)
	
Parafilele = []
		
fRule = LogicalOrFilter(filterele)

#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
paraele.SetElementFilter(fRule)
Parafilele.append(paraele)
TransactionManager.Instance.TransactionTaskDone()

#Final output
OUT = Parafilele

 

Method 2

Create the filter with python using inputs – Name, Categories, Filter Rules (In future another input that would be bool for AND or OR)
-I like this option as the most robust all in one node solution but will require replacement of nodes in graphs (which isn’t an issue).
ERROR - TypeError: Unable to cast object of type ‘Revit.Filter.FilterRule’ to type ‘Autodesk.Revit.DB.FilterRule’.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

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

# Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
# Import ToProtoType, ToRevitType geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

# Import DSCore nodes in Dynamo
clr.AddReference('DSCoreNodes')
import DSCore
from DSCore import *

# Import python library
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import os
import shutil
import math
# Import math library
from math import *

#Import Data and Time
from datetime import datetime
now = datetime.now()

#Import System Library
import System
from System.Collections.Generic import *
from System.IO import Directory, Path

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
def ToList(x):
	if isinstance(x,list): return UnwrapElement(x)
	else: return [UnwrapElement(x)]
	
#Preparing input from dynamo to revit
names = ToList(IN[0])
cats = ToList(IN[1])
rul = ToList(IN[2])

catids = List[ElementId]()
catids.Clear()
for cc in cats:
	catids.Add(cc.Id)
	

filterrul = List[FilterRule](rul)
	
Parafilele = []
		
fRule = LogicalOrFilter(filterrul)

#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
for name,cat in zip(names,cats):
	paraele = ParameterFilterElement.Create(doc,name,catids)
	paraele.SetElementFilter(fRule)
	Parafilele.append(paraele)
TransactionManager.Instance.TransactionTaskDone()

#Final output
OUT = Parafilele

 

You will see they are both throwing up a similar casting error (shows the error is due to me not understanding casting or how to change types) on each node so its tripping basically at the very start but I’m hoping the rest of it that I have written should be fine?

 

Like I mentioned above in the future I would like to also add a bool input to either of the nodes/methods to toggle whether it was “AND or OR”.

 

If anyone could help me understand how to go forwards with the python code or any provide comments around the casting that would be great!

 

I have attached the dynamo graph I’m using a test trying to write the python nodes. It requires at least one wall in the project for it to get the parameter to feed in.

 

@jeremytammik 

0 Likes
2,459 Views
2 Replies
Replies (2)
Message 2 of 3

jeremytammik
Autodesk
Autodesk

I see no reason why you should have any problem casting.

 

The Revit API provides the two separate classes 

 

 

They are derived from a common parent:

 

 

Normal .NET instantiation and upcasting should enable you to achieve all you need.

 

Downcasting is more tricky, but not required here.

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 3 of 3

RPTHOMAS108
Mentor
Mentor

Object > ElementFilter > ElementSlowFilter > ElementParameterFilter
Object > Element > FilterElement > ParameterFilterElement
They can be used together but have sperate class inheritance so one cannot be cast to another.

 

"ERROR - TypeError: Unable to cast object of type ‘Revit.Filter.FilterRule’ to type ‘Autodesk.Revit.DB.FilterRule’." 

 

This points to a namespace conflict. I assume Revit.Filter.FilterRule is coming from the Dynamo side. You need to consistently use either RevitAPI (DB) objects or Dynamo objects and better define the cross over back to Dynamo output.


You will probably get further help on the Dynamo forum as filtering is a common task.

0 Likes