According to my code, some elements return the correct amount of solids and in other cases it returns a different amount of solids, what I am looking for is for it to return the exact amount of solids.
Because some elements that I have in my model intersect with other elements and their geometry is divided, this means that the element should return these pieces of solids, thus having for each element either one solid or several depending on the case of their intersection, but my code does not return what I need. Could anyone please recommend me what to correct or what is wrong in my code… I leave you the code, THANK YOU VERY MUCH.
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
clr.AddReference('RevitAPI')
import Autodesk.Revit.DB.Structure as DBS
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
def get_line_of_framing(framing, opt):
if isinstance(framing.Location, DB.LocationCurve):
return framing.Location.Curve.ToProtoType()
geo_set = framing.get_Geometry(opt)
for geo in geo_set:
if isinstance(geo, DB.Line):
return geo.ToProtoType()
return None
opt = Options()
opt.DetailLevel = ViewDetailLevel.Coarse
opt.IncludeNonVisibleObjects = True
# Obtener todas las vigas en la categoría de "OST_StructuralFraming"
Vigas = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_StructuralFraming).WhereElementIsNotElementType().ToElements()
# Primer filtrado: solo las vigas que tienen un eje válido
VigasConEjes = []
for viga in Vigas:
eje = get_line_of_framing(viga, opt)
if eje is not None:
VigasConEjes.append(viga)
# Segundo filtrado: de las vigas con eje, solo aquellas que pueden albergar refuerzos (Rebars)
VigasRebar = []
for e in VigasConEjes:
# Verificar si la viga es un host válido para barras de refuerzo
if DBS.RebarHostData.IsValidHost(e):
VigasRebar.append(e)
# Obtener sólidos de cada viga
SolidosPorViga = []
for e in VigasRebar:
geoSet = e.get_Geometry(opt)
solids = []
if geoSet:
for g in geoSet:
if isinstance(g, DB.GeometryInstance):
# Extraer sólidos de una instancia de geometría
for gi in g.GetInstanceGeometry():
if isinstance(gi, DB.Solid) and gi.Volume > 0:
solids.append(gi.ToProtoType())
elif isinstance(g, DB.Solid) and g.Volume > 0:
# Agregar sólidos directamente
solids.append(g.ToProtoType())
if solids:
SolidosPorViga.append(solids) # Agregar la lista de sólidos a la lista general
OUT = SolidosPorViga
A single solid can be built from a union of many solids - use the Solid.Separate() Dynamo function - this will recursively separate a solid down to all element solids
Try
Thank you, it has worked for me, and I see that it is due to the level of access to the elements within the list, but now what would be your recommendation based on my general code? I left lines above… I mention it because it’s already confusing me…
Apparently the problem that arises is accessing the method that is in the library “clr.AddReference(‘ProtoGeometry’)
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS” I think something is blocking it and does not allow the “Separate” method.
THX c.poupin
Yes you are right it works but my intention is to have the method in my general code because I try to reduce extra nodes, so I want to keep everything necessary possible within a single Python script nodes
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
clr.AddReference('RevitAPI')
import Autodesk.Revit.DB.Structure as DBS
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
def get_line_of_framing(framing, opt):
if isinstance(framing.Location, DB.LocationCurve):
return framing.Location.Curve.ToProtoType()
geo_set = framing.get_Geometry(opt)
for geo in geo_set:
if isinstance(geo, DB.Line):
return geo.ToProtoType()
return None
opt = Options()
opt.DetailLevel = ViewDetailLevel.Coarse
opt.IncludeNonVisibleObjects = True
# Obtener todas las vigas en la categoría de "OST_StructuralFraming"
Vigas = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_StructuralFraming).WhereElementIsNotElementType().ToElements()
# Primer filtrado: solo las vigas que tienen un eje válido
VigasConEjes = []
for viga in Vigas:
eje = get_line_of_framing(viga, opt)
if eje is not None:
VigasConEjes.append(viga)
# Segundo filtrado: de las vigas con eje, solo aquellas que pueden albergar refuerzos (Rebars)
VigasRebar = []
for e in VigasConEjes:
# Verificar si la viga es un host válido para barras de refuerzo
if DBS.RebarHostData.IsValidHost(e):
VigasRebar.append(e)
# Obtener sólidos de cada viga
SolidosPorViga = []
for e in VigasRebar:
geoSet = e.get_Geometry(opt)
solids = []
if geoSet:
for g in geoSet:
if isinstance(g, DB.GeometryInstance):
# Extraer sólidos de una instancia de geometría
for gi in g.GetInstanceGeometry():
if isinstance(gi, DB.Solid) and gi.Volume > 0:
solids.append(gi.ToProtoType())
elif isinstance(g, DB.Solid) and g.Volume > 0:
# Agregar sólidos directamente
solids.append(g.ToProtoType())
if solids:
SolidosPorViga.append(solids) # Agregar la lista de sólidos a la lista general
OUT = SolidosPorViga
In the code you provided, it implemented the recommendations but it doesn’t work within my Python node.
If you remove the lines of code that give errors you will be able to see what the variable “SolidosPorViga” is returning.
Well I share the dynamo file, .dyn and the revit file where you can try it, .rvt
#LINE CODE ERROR..............
Resultado = []
for e in SolidosPorViga:
if isinstance(e,list):
for s in e:
ss = Solid.Separate(s)
Resultado.append(ss)
else:
sr = Solid.Separate(e)
Resultado.append(sr)
You are working with Revit (Autodesk.Revit.DB) Solids as they come from the filtered element collector before converting to Dynamo. (note to self )
Try converting DB.Solid types with SolidUtils.SplitVolumes(g) before converting to Dynamo
Otherwise you could use solids.append(g.ToProtoType().Separate()) however this is going to introduce lots of lists
Perhaps a helper function
def to_prototype(element):
geom = None
if isinstance(element, Solid) and element.Volume > 0:
geom = element.ToProtoType().Separate()
if isinstance(element, GeometryInstance):
geom = element.GetInstanceGeometry()
geom = list(filter(None, [to_prototype(g) for g in geom]))
if geom:
if len(geom) > 1:
return geom
return geom[0]
Then process something like this
beams = (
FilteredElementCollector(doc)
.OfCategory(BuiltInCategory.OST_StructuralFraming)
.WhereElementIsNotElementType()
.ToElements()
)
opt = Options()
opt.DetailLevel = ViewDetailLevel.Coarse
opt.IncludeNonVisibleObjects = True
output = []
for beam in beams:
geom = beam.get_Geometry(opt)
for g in geom:
solids = to_prototype(g)
if solids:
output.append(solids)
OUT = output