Dynamo bug 001.rvt (6.6 MB)
Revit file attached ,
we need perimeter values for multilevel floors ,there are multiple edges and multiple faces within the Floor, Any information is highly appreciated.
2 standard methods for getting values of Perimeter of Floor/Parts in Revit 2024
Get Perimeter Value of Floor in Dynamo
Method 1: By Selecting Edges
This method involves manually selecting the edges of a floor element. The workflow includes:
- Using the ‘Select Edges’ node to choose edges.
- Calculating the length of each edge with ‘Curve.Length’.
- Summing the lengths with ‘Math.Sum’ to get the total perimeter.
Method 2: By Selecting Model Elements
This method involves selecting the entire model element and calculating the perimeter of its surfaces. The workflow includes:
- Using the ‘Select Multiple Model Elements’ node to select one or more elements.
- Extracting faces of the selected element(s) with ‘Element.Faces’.
- Calculating the perimeter of each face using ‘Surface.Perimeter’.
- Using ‘List.MaximumItem’ to identify the largest perimeter.
Hi,
try this track
Code Block
Autodesk.Surface.NormalAtParameter(s,0.5,0.5).Z>0.001;
Sincerely
christian.stan
2 Likes
An implementation of this would simplify things and speed them along: GetTopFaces Method
From there converting to a polysurface, pulling the perimeter curves, creating a polycurve using the grouped curves method, and then pulling the perimeter of the larger area polycurve if you just want the exterior perimeter, or all curve lengths if you want all edge perimeter.
1 Like
@christian.stan ,
works perfectly ,I Cross checked the result with Revit perimeter values .its accurate. Thank you very much for quick reply .I hope anyone looking for perimeter values will find all results in this single blog.
I have marked your reply as SOLVED.
2 Likes
Hi Jocob,
Thank you for your response,
Is there any Dynamo node, Code block or python code to implement GetTopfacesMethod.
I would love to explore this idea further.
@jacob.small ,
python script below for further working,
import clr
clr.AddReference(“RevitAPI”)
clr.AddReference(“RevitServices”)
from RevitServices.Persistence import DocumentManager
from Autodesk.Revit.DB import *
Get the active document
doc = DocumentManager.Instance.CurrentDBDocument
Input: HostObject from Dynamo
host_object = UnwrapElement(IN[0]) # Input from Dynamo (e.g., Roof or Floor)
Output list of top face references
def get_top_faces(host_object):
if host_object is None:
return
# Initialize the list to store top face references
top_faces = []
# Get the geometry of the host object
options = Options()
options.ComputeReferences = True
geometry_element = host_object.get_Geometry(options)
if geometry_element is None:
return top_faces
for geom_obj in geometry_element:
if isinstance(geom_obj, Solid) and geom_obj.Faces.Size > 0:
for face in geom_obj.Faces:
planar_face = face if isinstance(face, PlanarFace) else None
if planar_face:
normal = planar_face.FaceNormal
# Check if the face is upward-facing
if abs(normal.X) < 1e-6 and abs(normal.Y) < 1e-6 and normal.Z > 0:
top_faces.append(planar_face.Reference)
return top_faces
Call the function
OUT = get_top_faces(host_object)
1 Like
Hi, here is Mr. Jacob’s recommendation using the GetTopFace Method of the Revit API
Script Python
import sys
#sys is a fundamental Python library
import clr
#This is .NET's Common Language Runtime. It's an execution environment
#that is able to execute code from several different languages.
clr.AddReference("RevitNodes")
#Dynamo's nodes for Revit
import Revit
#Loads in the Revit namespace in RevitNodes
clr.ImportExtensions(Revit.GeometryConversion)
#More loading of Dynamo's
#Revit libraries. You'll only need this if you're interacting with geometry
clr.AddReference("RevitAPI")
#Adding reference to Revit's API DLLs
import Autodesk
#Loads the Autodesk namespace
from Autodesk.Revit.DB import HostObjectUtils,Element
#To charge the class you want
def uw(lst):
if isinstance(lst,list):
return UnwrapElement(lst)
return UnwrapElement([lst])
#Fuction to unwrap
elt=uw(IN[0])
#Collect the items
doc = elt[0].Document
#Retrieve the current document
FR=[]
#Container for face revit
FD=[]
#Container for Surface Dynamo
for e in elt:
Faces_Top_Dynamo=[]
Faces_Top_Revit=[]
fref=HostObjectUtils.GetTopFaces(e)
for f in fref:
faceR = doc.GetElement(f).GetGeometryObjectFromReference(f)
faceD = faceR.ToProtoType()
Faces_Top_Revit.append(faceR)
Faces_Top_Dynamo.extend(faceD)
FD.append(Faces_Top_Dynamo)
FR.append(Faces_Top_Revit)
OUT = FD
if it is only the raw data of the perimeter that interests you you can also obtain it with the GetParameter node
Sincerely
christian.stan
3 Likes
@christian.stan ,
Thank you again for you valuable inputs,
Actually we took this task through dynamo because we were not accessible to add Perimeter parameter to the part element which is again a bug in Revit, you can check the same in the revit model.
Below images for your referance.
1 Like
Absolutely not a bug. Floors have a perimeter. Parts (once made) aren’t floors anymore, and can be edited in such a way as to invalidate the ‘perimeter’ function.
If you want to keep the capabilities of floors, why not skip going to parts and write a Dynamo graph to subdivide the floors instead?