Hi, guys! I am writing a script, meant to place walls by the contours of a room and join them after. My test files and the script itself can be downloaded from the following link: https://we.tl/t-jP0dfH5HQL
Here is the logic behind it:
- create walls for every curve from a room boundary, change its core location, height, etc.
- check for room bounding elements, belonging to a linked file. If found, their indices are removed from both lists - boundary and finishing walls (for the purpose of this example, the script is oversimplified - there are many other checks - columns in the interior of the room, columns and walls from linked files in the interior, filter out curtain walls, etc. )
- finally, join the newly created walls with the existing ones - this is when the script fails
I found that “Element.JoinGeometry” node wouldn’t work in my case, which is why I have created a simple python script for the purpose. However, it seems like it would still not join the walls:
I have checked multiple times the Ids of the walls, just to make sure they are given in the proper order and they are.
Here is the code:
import clr
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
#The inputs to this node will be stored as a list in the IN variables.
list_a = UnwrapElement(IN[0])
list_b = UnwrapElement(IN[1])
doc = DocumentManager.Instance.CurrentDBDocument
TransactionManager.Instance.EnsureInTransaction(doc)
output = []
for a,b in zip(list_a,list_b):
try:
JoinGeometryUtils.JoinGeometry(doc,a,b)
output.append("OK")
except Exception,e:
output.append(str(e))
TransactionManager.Instance.TransactionTaskDone()
#Assign your output to the OUT variable.
OUT = output
Thanks in advance for any support on the issue, cheers!
Have you tried using the Element.JoinGeometry node from Dynamo for Revit 2021 and beyond?
Info here: https://github.com/DynamoDS/DynamoRevit/pull/2456
Hello @danail.momchilov
try this
Home2.dyn (65.1 KB)
I modified the last Python node and the node “Room.Boundaries” (a little bit) from @Konrad_K_Sobon
# Copyright(c) 2015, Konrad K Sobon
# @arch_laboratory, http://archi-lab.net
# This node was an update to Wall.Boundaries node
# that can be found in Clockwork package. Thanks
# to Andreas Dieckmann for making the original one.
# modify by Cyril POUPIN
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
def Unwrap(item):
return UnwrapElement(item)
def ProcessList(_func, _list):
return map( lambda x: ProcessList(_func, x) if type(x)==list else _func(x), _list )
def GetRoomBoundary(doc, item, options):
global calculator
eList = []
cList = []
results = calculator.CalculateSpatialElementGeometry(item)
for face in results.GetGeometry().Faces:
for bface in results.GetBoundaryFaceInfo(face):
if bface.SubfaceType == SubfaceType.Side:
# get Wall Element
wallElem = doc.GetElement(bface.SpatialBoundaryElement.HostElementId)
eList.append(wallElem)
# get Curve from EdgeLoop
arrArrayLoop = face.EdgeLoops
lstCurve = [edge.AsCurve() for edge in arrArrayLoop[0]]
# get horizontal curves
lstCurveH = [[c, c.GetEndPoint(0).Z] for c in lstCurve if c.GetEndPoint(0).Z == c.GetEndPoint(1).Z]
lstCurveH.sort(key = lambda x : x[1])
cList.append(lstCurveH[0][0].ToProtoType())
return [eList, cList]
if isinstance(IN[0], list):
items = ProcessList(Unwrap, IN[0])
else:
items = [Unwrap(IN[0])]
options = SpatialElementBoundaryOptions()
boundloc = AreaVolumeSettings.GetAreaVolumeSettings(doc).GetSpatialElementBoundaryLocation(SpatialElementType.Room)
options.SpatialElementBoundaryLocation = boundloc
calculator = SpatialElementGeometryCalculator(doc)
elementList = []
curveList = []
try:
errorReport = None
if isinstance(items, list):
for item in items:
elementList.append(GetRoomBoundary(doc, item, options)[0])
curveList.append(GetRoomBoundary(doc, item, options)[1])
else:
elementList = GetRoomBoundary(doc, items, options)[0]
curveList = GetRoomBoundary(doc, items, options)[1]
except:
# if error accurs anywhere in the process catch it
import traceback
errorReport = traceback.format_exc()
# Release calculator to avoid get the new finish walls in result after this node
calculator.Dispose()
#Assign your output to the OUT variable
if errorReport == None:
OUT = [elementList, curveList]
else:
OUT = errorReport
Hi, Jacob. Yes, I have. It didn’t work
This partially works, thanks a lot! However, I noticed now the lists of walls (Existing and new ones) are not in the correct order, as a result some of them are joined, while others are not. This also generates multiple warnings in the model. For a large - scale project, there would be thousands of them:
An update from me - I only used the Room.CoreBoundary node to get the boundary curves and that already narowed the warnings down to 1 (and it’s about two adjacent walls anyway, so needs investigating). The rest is the same as in your script:
I will easily take over from here, thx once again
1 Like