Roof Perimeter from slanted roofs, how?

Hello

how can i get the geometry from a slanted roof ? , flatt roof is not issue → i work with the path. BUT how about “complex” forms? can i access the geometry of a layer. My favourite would be the “memprane” so i would have imediatly the Curve… :wink:

KR

Andreas

Something to try:

  1. Make parts
  2. Get the geometry of the new parts
  3. Do stuff with said geometry
  4. Delete the parts if you don’t want them anymore (or keep them if you do)
1 Like

@jacob.small ,

I do not use it regulary can i delete this in the transaction? For Roof it does not work, i tested walls.

Once you have the geometry, yes.

1 Like

@jacob.small ,

than i skip it at all! can i say something like topsurface → union → perimeter ?


KR
Andreas

Thought you were looking for a pure Revit API solution. if so this might not be the most effective, but it seems to work offhand in the context of pure Revit API stuff. Test it before implementing as always.

elems = UnwrapElement(IN[0]) #import the elements from IN[0] of the Dynamo environment and convert to native Revit elements
if not elems.__class__ == [].__class__ : elems = [elems] #ensure that elems is a list, not an individual object, so that we can always prepare for a loop
results = [] # list for the output results
for elem in elems: #for every element
    edges = [] #an empty list for the edges to process
    processed = [] #the list of processed edges which we want to keep
    geos = elem.get_Geometry(Options()) #the geometry
    for geo in geos: #for every geometry found
        if geo.__class__ == Autodesk.Revit.DB.Solid: #if the geomtry is a solid
            faces = geo.Faces #get the facfes
            for face in faces: #for every face
                if face.FaceNormal.Z > 0.00001: [edges.append(i) for loop in face.EdgeLoops for i in loop] #if it is pointing up, add all of it's edges to the edges list 
    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
OUT = results #return the results list to the Dynamo environment

If you want to use Dynamo geometry, pull the ‘up’ faces using a vector filter for Z > 0. Then union those into a PolySurface, and pull the perimeter curves of that.

4 Likes

@jacob.small ,

yes but pure mean, i have no preview… i will check your aproche!

KR

Andreas

yeah - I converted the edges to curves, and then into prototype elements in the 3rd to last line for visualization purposes; I figure you know how to not do so if desired. :slight_smile:

1 Like

@jacob.small,

yes i know it, but i have already a pistol on my chest :wink: it is hard to focus …

i think there is still this CPython issue… i will switch to PyRevit… later

KR

Andreas

Working fine in CPython for me. Verify your boilerplate is complete. I have a shared topic somewhere for that.

1 Like

@jacob.small ,

i check on private desktop! it runs


for one roof, i will test… for more.

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

roofs = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Roofs).WhereElementIsNotElementType().ToElements()



# 🎯 get ... what ever
for elem in roofs:
    if not elem.__class__ == [].__class__ : elem = [elem] #ensure that elem is a list, not an individual object, so that we can always prepare for a loop
    results = [] # list for the output results
    for e in elem: #for every element
        edges = [] #an empty list for the edges to process
        processed = [] #the list of processed edges which we want to keep
        geos = e.get_Geometry(Options()) #the geometry
        for geo in geos: #for every geometry found
            if geo.__class__ == Autodesk.Revit.DB.Solid: #if the geomtry is a solid
                faces = geo.Faces #get the faces
                for face in faces: #for every face
                    if face.FaceNormal.Z > 0.00001: [edges.append(i) for loop in face.EdgeLoops for i in loop] #if it is pointing up, add all of it's edges to the edges list
        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
    OUT = results #return the results list to the Dynamo environment


Thats great! i will develop more!

KR

Andreas

1 Like

@jacob.small ,


it does not work when you have circle … but this is rare :wink:

KR
Andreas

Yeah - add a verification to ensure you only check ‘is planar face’ and that should self resolve.

There are also other ways to pull the ‘top’ surface, but I was too lazy to look them up.

1 Like

If you or others are interested in the ‘get top faces’, I believe it to be this call: GetTopFaces Method