You heard right. Revit is very unforgiving when it comes to working with geometry, sometimes it refuses to accept imports (that AutoCAD can take), and doesnât usually give specific/clear reasoning as to why. Especially challenging when trying to convince designers Revit can be used for design.
A lot of geometry and analysis I take to Rhino these days. Works like a dream vs Revit for mesh and heavier solid analysis.
while that may be true. In this specific example, Revit is successfully outputting the geometry for use in a Revit API context, (Autodesk.Revit.DB.Solid).
Where this workflow is actually falling apart is in the Dynamo side with the ToProtoType converters, (Solid converters are here).
@GavinCrump - I realize it is the âcoolâ thing to do to bash Revit and say, âRHiNo iS bETteRâ, which I can agree with in a lot of instances. But in this case, and I mean this respectfully, youâre assumption re: Revit not handling the geometry is simply incorrect, (because once again, this is happening on the Dynamo conversion portion).
The best thing OP can do is first, supply a sample file here for us to help further (we donât even know the Revit version at this point), then, open a Github Issue, supply the sample Revit file and the team can refine/work on the converters for solids regarding Dynamo geometry. This is how Dynamo becomes better.
Iâm not trying to be cool or edgy, Iâm just trying to encourage people to explore other options. I genuinely feel that Dynamo for data and Rhino(Inside) form a solid combination when both learnt that help plug each others limitations or weaker aspects.
I know weâre on Dynamo forums here, so I get that itâs not the most âhelpfulâ answer but at the same time I think itâs helpful to have some confirmation on what theyâve heard and specifically mentioned. If they hadnât mentioned it then I probably wouldnât have bothered bringing it up.
Sorry if it ruffles anyones feathers/rubs people the wrong way. Not my intent here.
Itâs no problem at all. I think mentioning the other ones is fine and it doesnât matter that this is the âDynamo forumâ. I didnât post my reply to scold for mentioning an alternative product.
I replied because the statement re: Revitâs handling of the geometry is still incorrect regardless. It is most definitely the Dynamo converter itself (separate from the Revit API) that is the issue. If Rhino or whatever else successfully converts that solid, thatâs cool. That just means that the Dynamo converter needs to adopt a similar method.
Either way, there is no sample file to reproduce the issue, so you canât even prove that the alternative methods do work at this time with OPs specific Revit element.
@newshunhk Given that we can get the solid, we are able to at least see the problem, and perhaps use a creative method to approximate a reconstruction of the solid, if that is acceptable�
Apologies to Clockwork for butchering Mr Dieckmannâs code
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB 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
# this function takes care of exploding
# GeometryInstance objects. GI objects typically
# represent family instance geometry.
# in order to also catch possible nested families
# the fucntion calls itself recursively.
def convert_geometry_instance(geo, elementlist):
for g in geo:
if str(g.GetType()) == 'Autodesk.Revit.DB.GeometryInstance':
elementlist = convert_geometry_instance(g.GetInstanceGeometry(), elementlist)
else:
try:
if g.Volume != 0:
elementlist.append(g)
except:
pass
return elementlist
doc = DocumentManager.Instance.CurrentDBDocument
items = UnwrapElement(IN[0])
if IN[1] == "Coarse": detail_lvl = ViewDetailLevel.Coarse
elif IN[1] == "Fine": detail_lvl = ViewDetailLevel.Fine
else: detail_lvl = ViewDetailLevel.Medium
inc_invis = IN[2]
view = UnwrapElement(IN[3])
inserts = UnwrapElement(IN[4])
remove_inserts = IN[5]
revitlist = list()
dynlist = list()
catlist = list()
# we might need a transaction in order to
# temporarily delete all inserts and retrieve gross wall areas
TransactionManager.Instance.EnsureInTransaction(doc)
trans = SubTransaction(doc)
trans.Start()
i = 0
for item in items:
if remove_inserts == True:
for insert in inserts[i]:
doc.Delete(insert.Id)
doc.Regenerate()
geo_options = Options()
if view == None: geo_options.DetailLevel = detail_lvl
geo_options.IncludeNonVisibleObjects = inc_invis
if view != None: geo_options.View = view
revitGeo = item.Geometry[geo_options]
try:
revit_geos = convert_geometry_instance(revitGeo, list())
revitlist.append(revit_geos)
dyn_geos = list()
cats = list()
for geo in revit_geos:
try:
dyn_geos.append(geo.ToProtoType())
except:
dyn_geos.append(None)
try:
graphstyle = doc.GetElement(geo.GraphicsStyleId)
if graphstyle != None:
cats.append(Revit.Elements.Category.ById(graphstyle.GraphicsStyleCategory.Id.IntegerValue))
else:
cats.append(None)
except:
cats.append(None)
dynlist.append(dyn_geos)
catlist.append(cats)
except:
revitlist.append(list())
dynlist.append(list())
catlist.append(list())
i += 1
trans.RollBack()
TransactionManager.Instance.TransactionTaskDone()
facesOut = []
edgesOut = []
for solidList in revitlist:
for solid in solidList:
# for face in solid.Faces:
# facesOut.append(face.ToProtoType())
for edge in solid.Edges:
edgesOut.append(edge.AsCurve().ToProtoType())
OUT = edgesOut#facesOut#(dynlist,revitlist,catlist)
EDIT:
From memory, these kinds of operations can be very systematic, ie. whichever element is interrogated, the geometry is returned in a predictable way. Hopefully this is the case for you⊠(group Curves is Archilab)
import clr
import System
import sys
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB 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
def get_AllSolid(lst_elem, inc = 0):
# sub functon
def populate_lstGeo(g):
if isinstance(g, Solid) and g.Volume > 0:
solids.append(g)
elif isinstance(g, GeometryInstance):
geoInst.append(g)
else:pass
#
# main recursive function
global opt
solids = []
geoInst = []
lst_elem = lst_elem if hasattr(lst_elem, "__iter__") else [lst_elem]
if len(lst_elem) > 0 and inc < 2000:
for elem in lst_elem:
if isinstance(elem, GeometryInstance):
for j in elem.GetInstanceGeometry():
populate_lstGeo(j)
else:
geoSet = elem.get_Geometry(opt)
for i in geoSet:
populate_lstGeo(i)
return solids + get_AllSolid(geoInst, inc + 1)
else:
return []
elem = UnwrapElement(IN[0])
opt = Options()
solids = get_AllSolid(elem)
ds_Solids = []
for s in solids:
try:
ds_Solid = s.ToProtoType()
ds_Solids.append(ds_Solid)
except:
# failed conversion DB.Solid to Solid Prototype -> try get make Solid with ByJoinedSurfaces
ds_face = []
for f in s.Faces:
try:
ds_face.extend(f.ToProtoType())
except:
# failed conversion DB.Face to Prototype -> try get make Surface with PolyCurves.Patch()
ds_edges = [c.ToProtoType() for curveloop in f.GetEdgesAsCurveLoops() for c in curveloop]
ds_poly_edges = PolyCurve.ByJoinedCurves(ds_edges)
ds_face.append(ds_poly_edges.Patch())
ds_Solid = DS.Solid.ByJoinedSurfaces(ds_face)
ds_Solids.append(ds_Solid)
OUT = ds_Solids