Hello,
i stuck, i can access it via node but not via python… so how can i get the lengths of my edges…
how can i integrade this in my code also with the listmanagement! so each list has to remain.
KR
Andreas
Hello,
i stuck, i can access it via node but not via python… so how can i get the lengths of my edges…
KR
Andreas
Full Python? Hard to find where to edit it without the context.
Likely if you have lines you can skip the .Curve
and just return the length - so line 72 becomes dis = i.Length
.
This is effectively what the Dynamo node is doing - pulling the length property from the Curve class object given in the list of inputs. Remember that properties can be called directly via object.Propery rather than Class.Property(object) as you see with the nodes names.
it is this roof perimeter topic…
# demo
# all
import sys
import clr
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import *
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *
clr.AddReference('System')
from System.Collections.Generic import List
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Access the Revit application and document
app = DocumentManager.Instance.CurrentUIApplication
doc = DocumentManager.Instance.CurrentDBDocument
# functions
def tolist(x):
if hasattr(x,'__iter__'): return x
else: return [x]
def isSolid(x):
if x.__class__ == Autodesk.Revit.DB.Solid: return x
def faceNormal(face):
if face.FaceNormal.Z > 0.00001: return [edges.append(i) for loop in face.EdgeLoops for i in loop]
collector = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Roofs).WhereElementIsNotElementType().ToElements()
roofs = tolist(collector)
results = []
for e in roofs:
edges = []
processed = []
geos = e.get_Geometry(Options())
for geo in geos:
faces = isSolid(geo)
faces = geo.Faces
for face in faces:
loop = faceNormal(face)
pnts = [e.AsCurve().Evaluate(0.5,True) for e in edges] #get all the mid points of the edges
for i in range(len(edges)): #for every item in the list of edges
e = edges.pop(0) #remove the edge to process
p = e.AsCurve().Evaluate(0.5,True) #get the midpoint
distSum = sum([1 for i in pnts if i.DistanceTo(p) == 0]) #get the count of midpoints which are equal to the midpoint being evaluated
if distSum == 1: processed.append(e.AsCurve().ToProtoType()) #if the count was 0 the edge isn't shared and is on the perimeter
results.append(processed) #append the processed edges to our results list
"""
lengths = []
for lis in results:
for i in lis:
dis = i.Length
lengths.append(dis)
"""
OUT = results
i struggle with CPython
it runs in Revit2023 but not in 2024
KR
Andreas
Dataset?
Your error message changed so I can’t really identify the issue. The community can’t effectively help if you don’t share more of what you’re building, what you’re after, and datasets to build along with you. Likely best to go back to nodes here if you can’t manage to constrict your environment somewhat.
there should be no error. i just want to have the length of my lines. But the script crashed before. I don`t know how to deal with that. In one Revit it runs and in the other one not. I replicated the error too in Revit2022
I can’t replicate it as I don’t have the model. Try running dir on the object and seeing what you can do with it.
@jacob.small
Dach22.rvt (436 KB)
Dach.rvt (856 KB)
it is just a demo
thanks we have some IT Issue in our company at home the code works…
Thank you
KR
Andreas
so finally i solved it. from getting the lines, lengths and filling the parameter as well.
import clr
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import *
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *
clr.AddReference('System')
from System.Collections.Generic import List
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Access the Revit application and document
app = DocumentManager.Instance.CurrentUIApplication
doc = DocumentManager.Instance.CurrentDBDocument
# Variables LOI
PERIMETER = "Umfang_Massen"
# functions
def tolist(x):
if hasattr(x,'__iter__'): return x
else: return [x]
def isSolid(x):
if x.__class__ == Autodesk.Revit.DB.Solid: return x
def faceNormal(face):
if face.FaceNormal.Z > 0.00001: return [edges.append(i) for loop in face.EdgeLoops for i in loop]
# Get roofs
collector = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Roofs).WhereElementIsNotElementType().ToElements()
roofs = tolist(collector)
# extract lengths from edges of roofs
results = []
for e in roofs:
edges = []
processed = []
geos = e.get_Geometry(Options())
for geo in geos:
faces = isSolid(geo)
faces = geo.Faces
for face in faces:
loop = faceNormal(face)
pnts = [e.AsCurve().Evaluate(0.5,True) for e in edges] #get all the mid points of the edges
for i in range(len(edges)): #for every item in the list of edges
e = edges.pop(0) #remove the edge to process
p = e.AsCurve().Evaluate(0.5,True) #get the midpoint
distSum = sum([1 for i in pnts if i.DistanceTo(p) == 0]) #get the count of midpoints which are equal to the midpoint being evaluated
if distSum == 1: processed.append(e.AsCurve().Length)#ToProtoType()) #if the count was 0 the edge isn't shared and is on the perimeter
results.append(processed) #append the processed edges to our results list
# sum edge.lengths to perimeter total per roof
total = []
for lis in results:
perimeter_per_element = sum(lis)
total.append(perimeter_per_element)
# SetParameter
t = Transaction(doc, "Set Massen_Umfang")
t.Start()
for d,v in zip(roofs,total):
try:
roof_perimeter_param = d.LookupParameter(PERIMETER).Set(v)
except:
pass
t.Commit()
OUT = "Success"
Alternatively,
you can use HostObjectUtils.GetTopFaces
method then remove collinear lines
import clr
import sys
import System
from System.Collections.Generic import List
#
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
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
def remove_collinar(lst_curve):
perimeter_curves = []
for idxA, curvA in enumerate(lst_curve):
if all( curvA.Intersect(curvB) != SetComparisonResult.Equal for idxB, curvB in enumerate(lst_curve) if idxA != idxB):
perimeter_curves.append(curvA)
return perimeter_curves
toList = lambda x : x if isinstance(x, (list, List)) else [x]
#Preparing input from dynamo to revit
lstRoofs = toList(UnwrapElement(IN[0]))
out = []
for roof in lstRoofs:
topRefs = DB.HostObjectUtils.GetTopFaces(roof)
roof_curves = []
for ref in topRefs:
face = roof.GetGeometryObjectFromReference(ref)
#
if face is not None:
curve_loop = face.GetEdgesAsCurveLoops()[0]
for curv in curve_loop:
roof_curves.append(curv)
ds_perimeter_curves = [x.ToProtoType() for x in remove_collinar(roof_curves)]
sum_perimeter = sum(x.Length for x in ds_perimeter_curves)
out.append([ds_perimeter_curves, sum_perimeter])
OUT = out