I am looking how to resolve this in ironpython2.7 script, the best efficient way to get the bottom closed loop edges of a revit mass element, its solid geometry made by vertical extrusion.
I was thinking a process of getting things like this: element mass ==> solid geometry ==> solid surfaces ==> get bottom surface ==> get surface perimeter curves, but maybe it is too expensive high time consuming, I wonder if there is a intelligent wat to do it, I was thinking element mass ==> solid ==> vertexes ==> rebuild bottom curves byjoining clockwise vertex points. I was just hinking intersect a plane through the geometry and get edges directly but not sure what is best faster to compute, i have no idea. the mass element can be a loadable family or a family in-place, I just say will be always like a vertical extrusion of a bottom boundary, but let say other day can be a more complex geometry not extrusion vertical, so I am thinking in projection of edges into a plane
let say the mass elements are made of vertical extrusion of a close loop boundary, I have not done anything like Dispose(), I do not have an example yet, I am trying to figure out which is fastest way for computer to achieve results before i even try
Get the faces which have a normal with a Z component less than 0.5 or get the faces who have a point at parameter 0.5,0.5 which have a Z component equal to the Z component of the solidâs min point (the later is slower but more robust into the future.
For each face, extract the curve loops
For each curve loop, extract the curves and union to a polycurve.
I would not recommend using the vertex method you proposed as curved edges are a thing you lose entirely and you wonât want to find out they had to be accounted for well after the fact.
The perimeter curves of the surface will also work well but curve loops and faces will be faster and more readily account for donut faces.
what function does this âproject the solid onto a planeâ using Revit API or python libraries?, I know in AutoCAD there is just a function to do that, in spanish is called GEOPLANA, in english maybe is something like 2D shot
So you have more than one element⌠why would you want taht to run even slower?
Topology.Faces > Filter to base face > Faces.Loops > Loops.CoEdges > CoEdge.Edges > Edge.CurveGeometry
The work is multiple orders of magnitude faster than what youâll get with any geometry modification which is what youâre describing, and the larger the dataset the slower the modifications will be.
import clr #add the common language runtime (CLR) to the Python environment
clr.AddReference('ProtoGeometry') #add the Dynamo geometry namespace to the CLR
from Autodesk.DesignScript.Geometry import * #import the entirety of the Dynamo geometry namespace to the Python environment
slds = IN[0] #the solids from the Dynamo environment
if not slds.__class__ == list: slds = [slds] #if a list wasn't provided as the input convert it to one
results = [] #set results
outlineOnly = false #boolean variable to control if you want to extract only exterior edges
for sld in slds: #for each solid
result = [] #empty list for the result of the processed solid
faces = [i for i in sld.Faces if i.SurfaceGeometry().NormalAtParameter(0.5,0.5).Z == -1] #as you indicated you have extruded sketches there can only be one downward pointing face, but this will get it and others to account for separated curve loops in the sketch
for face in faces: #for each face
loops = face.Loops #get the loops
if outlineOnly: loops = [i for i in loops if i.IsExternal] #removes any interior loops if outlineOnly is set to true
for loop in loops: #for each loop
coEdges = loop.CoEdges #get the coeges
crvs = [coEdge.Edge.CurveGeometry for coEdge in coEdges] #convert the coedges to curves
loop = PolyCurve.ByJoinedCurves(crvs,0,0,0) #build a polycurve from the curv es
result.append(loop) #append the curve to the result list
results.append(result) #append the result to the results
OUT = results #return the results
I am thinking the way to take the boundary sketch that originates the solid geometry, like for example room/space of revit is made from closed loop curves sketch in a horizontal plane level, then it extrudes vertically or fills the forms of the elements that create boundaries, so i suppose in revit api there is a function to take directly those curve loops without having to get the element geometry, the solid, the faces, the edges or points and rebuild a close loop from points unnecessarily. maybe is something like this? SpatialElementBoundaryLocation Property;
so I am thinking how to go to a mass family made in place in the same way that room/space is created with a sketch in a horizontal plane and extruded vertically so I could take the original sketch directly which originates that solid, let say the mass is made of one solid made of extrusion
It has been awhile since I have looked at it so I may be wrong, but the minute you said âin place familyâ the ability to access the sketch data programmatically is lost as there is no access to the in place family editor in the API. If you had loadable families you can:
Open the document
Get the form(s)
Extract the sketch from the forms
Pull the curve loops from the sketch
If my memory is correct, with in place all you can do is start to interrogate the element. So that workflow would look something like this:
Query the geometry of the instance
Convert to solids
Extract the faces
Extract the loops
All 4 of those steps are doable but in a much more difficult way then I showed with the Python above.
someone told me this, which matches somehow with your answer:
Mass (in-place âMassâ family, vertical extrusion case)
Thereâs no single universal API that returns the âoriginal sketch profileâ for every kind of mass form.
What you can do depends on how the mass was built:
A) Traditional sketch-based solids (Extrusion/Blend/Revolve/Sweep/SweptBlend) inside a family
If your mass were one of those (common in many non-mass family templates), you can open the family doc and read the Sketch:
famDoc = doc.EditFamily(fi.Symbol.Family) # fi = FamilyInstance in project
exts = FilteredElementCollector(famDoc).OfClass(Extrusion)
for ex in exts:
sk = ex.Sketch # Autodesk.Revit.DB.Sketch
for loop in sk.Profile: # CurveArrayArray
for c in loop: # CurveArray
# c is a Curve from the original profile
pass
Then transform those curves into project coordinates using the family instanceâs transform.
B) Conceptual Mass Form (what âIn-Place Massâ usually creates)
Most in-place mass geometry is stored as Form / GenericForm (lofts, extrusions, voids). These do not expose their generating profiles via a Sketch property. The original ModelCurves may still exist, but the API doesnât give a reliable 1:1 mapping from those curves back to a particular Form.
Practical workaround (fast and robust):
Read the mass Solid once.
Grab a horizontal planar face (bottom/top) and read its edge loops (these are the profile rings as built).
You can use face.EdgeLoops (EdgeArrayArray) and edge.AsCurve() to recover loops directly.
Cache those loops; you now have the âsketchâ rings you wanted, without recomputing from scattered vertices.
Right - and as noted above each step including âget geometryâ of type B will be more difficult in Revit. If you donât have a good reason for staying in Revit youâre likely best suited to take the Python above, run it, and move on with the day as the project would be done by now.