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…
KR
Andreas
@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.
1 Like
@jacob.small,
yes i know it, but i have already a pistol on my chest 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
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