Hi Everyone. Currently I am working on a project where I need to join all elements in one group together. If I do it manually through Revit it works perfectly but It seems It is not working with Dynamo. the script doesn’t give any error but the elements are not joining. I was wondering if there is a problem with only having one list. So there is no List A and B. because I want to join only the elements in that specific list together. can someone help me with that. Thank you
Hi Aween,
Can you paste the python script here so we dont all need to type it out to test it.
Sure, here is the script.
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument
elements_groups = IN[0]
def join_elements(group_elements):
print("Group Elements Count:", len(group_elements))
if len(group_elements) > 1:
try:
if all(revit_elements[0].Category.Id == elem.Category.Id for elem in revit_elements):
# Join all elements with each other in the group
first_element_id = revit_elements[0].Id
joined_element_id = None
for element in revit_elements[1:]:
joined_element_id = ElementTransformUtils.JoinElementGeometry(doc, first_element_id, element.Id)
if joined_element_id == ElementId.InvalidElementId:
print("Error: Elements could not be joined.")
return group_elements
if joined_element_id != ElementId.InvalidElementId:
return doc.GetElement(joined_element_id).ToDSType(False)
else:
print("Error: Elements in the group are not of the same category.")
except Exception as ex:
# Handle any potential errors during the join process
print("Error while joining elements:", str(ex))
return group_elements
else:
return group_elements
joined_elements = [join_elements(group) for group in elements_groups]
# Output the joined elements
OUT = joined_elements
It might be a minor thing but I created the Elements in Revit through Grasshopper/Rhino.Inside. but they are Native Revit Elements.
What type of element? Directshape? Generic Model family instances? Mass? Imports?
In this section
if all(revit_elements[0].Category.Id == elem.Category.Id for elem in revit_elements):
Did you mean to write
if all(group_elements[0].Category.Id == elem.Category.Id for elem in group_elements):
yes. But even if I use group_elements Instead of revit_elements it doesn’t affect the result.
Not sure what it is up here, but i’ve a sneaking suspicion that you voxelized the entire model, and are now trying to union them… why not union them and send the union instead? The rendering complexity (and therefore view display time) goes up exponentially when you build like this as cube 1 doesn’t get displayed until cub n is also calculated, and joined to it.
Does the code work with say 3 adjacent cuboids?
If so, my guess is the order of operations is what’s killing you. that or your have something selected for automation which you don’t have selected manually. Either way we’d need the model to review the root cause.
the script is working in Dynamo environment. But if I plug-in the Revit elements directly to the Python script, It seems not working. Is there a way to bring back those elements from Dynamo to Revit ?
Or it is actually only a visual thing because I didn’t even plug-in the Dynamo List in to the Python script.
Hello, I am not qualified as competent
I don’t see your method used in the ElementTransformUtils class
maybe on this side to dig
Cordially
christian.stan
What is the list input into the List.GroupByKey node?
IO think we need a sample Revit model and your DYN to best help.
Searching a bit and looking at your code, you need UnwrapElement Element
It seems that you send a string in your IN
You have to use the JoinGeometryUtils class
and pass this in a transaction because you are modifying the elements
here is an example with 2 elements if it can help
code + pictures
import clr
import System
from System.Collections.Generic import *
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference("RevitAPI")
clr.AddReference("RevitAPIUI")
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI import *
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = uiapp.ActiveUIDocument
el_A=UnwrapElement(IN[0])
el_B=UnwrapElement(IN[1])
TransactionManager.Instance.EnsureInTransaction(doc)
elJ=JoinGeometryUtils.JoinGeometry(doc,el_A,el_B)
TransactionManager.Instance.TransactionTaskDone()
OUT = elJ
Cordially
christian.stan
thank you Christian for that. In my case there is only one list that I try to join elements in that list together. I tried something similar with having two different lists. it works better. I think the problem is with having only one list. @jacob.small here is also a sample of Revit and my script.
Joining_Boxes.rvt (588 KB)
Joining_Geofoams.dyn (31.7 KB)
the code must be reworked, result not perfect, at the beginning your id 4632 is already joined to another
here is a change to the code previously sent
el_lst=UnwrapElement(IN[0])
TransactionManager.Instance.EnsureInTransaction(doc)
a=JoinGeometryUtils.JoinGeometry(doc,el_lst[0],el_lst[1])
for i in range(1,len(el_lst)-1):
b=JoinGeometryUtils.JoinGeometry(doc,el_lst[i],el_lst[i+1])
doc.Regenerate()
TransactionManager.Instance.TransactionTaskDone()
OUT = el_lst
Cordially.
christian.stan
edit:
I thought of a possibility but I don’t know how to write it at all, I post the idea
I think it must be resource intensive.
There will be much better ideas (in my opinion, there is no shortage of brains here)
1st scan all the cubes, I turn these (if no face of them is in contact) I put them in another receptacle (no longer bother to take care of them)
2nd scan I take one I look at the common faces I join it with its neighboring friends (then I transfer it to the receptacle no longer needed) and so on until exhaustion
it’s clear when I write it but it must be less easy to understand
sorry for not being able to do better
That said taking all the geometries under dynamo and union then creating a monolithic family does not correspond to your expectations maybe but hey it should do the trick
Cordially
christian.stan
hi,
a solution with itertools.product()
import clr
import sys
import System
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
#import net library
from System import Array
from System.Collections.Generic import List, IList, Dictionary
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
import itertools
def join_elements(group_elements):
if all(group_elements[0].Category.Id == elem.Category.Id for elem in group_elements):
for i, j in itertools.product(list(group_elements)[:], list(group_elements)[:]):
if i.Id != j.Id and not DB.JoinGeometryUtils.AreElementsJoined(doc, i, j):
DB.JoinGeometryUtils.JoinGeometry(doc, i, j)
return group_elements
#Preparing input from dynamo to revit
elements_groups = UnwrapElement(IN[0])
#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
joined_elements = [join_elements(group) for group in elements_groups]
TransactionManager.Instance.TransactionTaskDone()
OUT = joined_elements
Thank you guys. It is working now perfectly. Itertools.product() was the solution.
the Problem with that script is I can not add any costume components to Dynamo. because It gives this warning. The script works perfectly without costume packages that I use for totally different purposes.
I can’t reproduce this error, can you detail the context (python egine, etc.) ?
Are all packages on the local disc, or are some on a network or cloud location?
Also, is this a physical desktop or virtual environment?