Perimeter value of floor- ALL 3 methods



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:

  1. Using the ‘Select Edges’ node to choose edges.
  2. Calculating the length of each edge with ‘Curve.Length’.
  3. 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:

  1. Using the ‘Select Multiple Model Elements’ node to select one or more elements.
  2. Extracting faces of the selected element(s) with ‘Element.Faces’.
  3. Calculating the perimeter of each face using ‘Surface.Perimeter’.
  4. 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?