Dear all,
Lately i been enhancing the workflow that i shared before.
Last time i faced an issue to do the clash detection within Revit using dynamo due to running time, but thanks to BimorohNodes that they enhanced the process of intersection method between elements. below i will share with you the process of clash detecting scriPt. The script is enable you to detect the clashes between host model and linked models or host model elements.
What you need:
1- Dynamo. 1.3.
Packages:
MEPover.
Data-Shapes.
BimorphNodes.
RevitPythonWrapper.
Visual Style Select.
2- Revit 2016 – 2018.
Dynamo Script.
Part-1: Read the linked models and make selection form, so the user pick which model to run versus the host model. We will add ability also to run the clash detection for the elements in the host model only. Check the figure below.
Tip. Make sure to keep the Run model of the dynamo as manual.
Part-2: Collect host model elements. Check figure below.
Python code for the needed Nodes:
Library importing:
import clr
import sys
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib')
import os
appdata_path = os.getenv('appdata')
dynamo_path = os.path.join(appdata_path, 'Dynamo')
module_path = None
for root, subfolders, files in os.walk(dynamo_path):
if 'RevitPythonWrapper' in subfolders:
extra_path = os.path.join(root, 'RevitPythonWrapper', 'extra')
module_path = os.path.join(extra_path, 'rpw.zip')
OUT = module_path or 'Could Not Find Module. Make sure it\'s installed properly'
Collect elements in model:
x = IN[1]
import sys
sys.path.append(IN[0])
import rpw
l = []
for i in x:
try:
col = rpw.db.Collector(of_category= i, is_not_type=True)
s = col.elements
l.append(s)
except:
pass
OUT = l
Part-3: Collect the elements from the picked model. Check figure below.
Python code for the needed Nodes:
Collect Elements:
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import System
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
#The inputs to this node will be stored as a list in the IN variable.
dataEnteringNode = IN
_linkDoc = IN[0]
_category = IN[1]
result = []
for i in _category:
try:
errorReport = None
filter = ElementCategoryFilter(System.Enum.ToObject(BuiltInCategory, i.Id))
result.append(FilteredElementCollector(_linkDoc).WherePasses(filter).WhereElementIsNotElementType().ToElements())
except:
pass
# if error accurs anywhere in the process catch it
#import traceback
#errorReport = traceback.format_exc()
#Assign your output to the OUT variable
if errorReport == None:
OUT = result
else:
OUT = errorReport
Part-4: Get previous parts together . Notice I added if statement to check which model you will pick (Linked models or host model). Check figures below.
Python code for the needed Nodes:
If Statement:
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
cond = IN[0]
x = IN[1]
y = IN[2]
#Assign your output to the OUT variable.
o = []
if cond:
OUT = y
else:
OUT = x
Part-5: Check the intersection between the elements to detect the clashes. Check figure below.
Part-6: Create 3D view for each element. Check figures below.
Python code for the needed Nodes:
Create Views:
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from System.Collections.Generic import *
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
#The inputs to this node will be stored as a list in the IN variable.
dataEnteringNode = IN
d = []
v = IN[1]
s = 0
for k in IN[0]:
elements = []
for i in k:
elements.append(UnwrapElement(i))
elements.append(UnwrapElement(k))
viewName = v[s]
offset = float(IN[2])
s = 1+s
#get ViewFamilyType for a 3D View
collector = FilteredElementCollector(doc)
viewTypeColl = collector.OfClass(ViewFamilyType)
for i in viewTypeColl:
if i.ViewFamily == ViewFamily.ThreeDimensional:
viewType = i
else:
continue
# "Start" the transaction
TransactionManager.Instance.EnsureInTransaction(doc)
#define bounding box enclosing all elements
bboxMin, bboxMax = [], []
i = elements[0]
bboxMin.append(i.get_BoundingBox(doc.ActiveView).Min)
bboxMax.append(i.get_BoundingBox(doc.ActiveView).Max)
minX, minY, minZ, maxX, maxY, maxZ = [], [], [], [], [], []
for i, j in zip(bboxMin, bboxMax):
minX.append(i.X)
minY.append(i.Y)
minZ.append(i.Z)
maxX.append(j.X)
maxY.append(j.Y)
maxZ.append(j.Z)
bboxMinX = min(minX)
bboxMinY = min(minY)
bboxMinZ = min(minZ)
bboxMaxX = max(maxX)
bboxMaxY = max(maxY)
bboxMaxZ = max(maxZ)
#create a bounding box
bbox = BoundingBoxXYZ()
bbox.Min = XYZ((bboxMinX - offset), (bboxMinY - offset), (bboxMinZ - offset))
bbox.Max = XYZ((bboxMaxX + offset), (bboxMaxY + offset), (bboxMaxZ + offset))
#create 3d View
view = View3D.CreateIsometric(doc, viewType.Id)
d.append(view)
view.Name = viewName
view.SetSectionBox(bbox)
# "End" the transaction
TransactionManager.Instance.TransactionTaskDone()
#Assign your output to the OUT variable
OUT = d
Part-7 Make the 3D-View in Revit as shaded. Check figures below.
Part-8: Color the element in the 3D-view. Check figures below.
Python code for the needed Nodes:
Override:
import clr
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from System.Collections.Generic import *
doc = DocumentManager.Instance.CurrentDBDocument
def overridecolor(element, color, fillpatternid, view):
gSettings = OverrideGraphicSettings()
gSettings.SetProjectionFillColor(color)
gSettings.SetProjectionFillPatternId(fillpatternid)
gSettings.SetCutFillColor(color)
gSettings.SetCutFillPatternId(fillpatternid)
view.SetElementOverrides(element.Id, gSettings)
return element
fillpatterns = FilteredElementCollector(doc).OfClass(FillPatternElement).ToElements()
solidfillid = [f.Id for f in fillpatterns if f.Name == 'Solid fill'][0]
for j in IN[1]:
for i in IN[2]:
if isinstance(IN[0],list):
color = UnwrapElement(IN[0])
else:
color = [UnwrapElement(IN[0])]
adskcolor = [Autodesk.Revit.DB.Color(c.Red, c.Green, c.Blue) for c in color]
view = UnwrapElement(j)
elements = UnwrapElement(i)
TransactionManager.Instance.EnsureInTransaction(doc)
for e,c in zip(elements,adskcolor):
overridecolor(e,c,solidfillid,view)
TransactionManager.Instance.TransactionTaskDone()
OUT = elements
Last thing every time you run the script you need to make sure to delete the previous created views or choose different name for the new views, otherwise Revit will give an error that views already created with the same names. The deleting for the views can be automated as well. Since the script made with input form you can run it from dynamo player without opening dynamo.
Each view includes the clashed elements and if you still can’t detect the clash visually you can run the interference check as the colored element versus the linked element. With this way you will make sure to detect the clash and understand it. Check figures below.
Future consideration:
1- Automate solving the clashes that need to be joined.
2- Show clash details within the view.
3- Categories the views to avoid naming issue.
Dynamo Script:
Clash Detection.dyn (50.5 KB)
Regards,
Mohammad Nawar