Error in geometric options of elements.... PYTHON..?

Good morning.
As you already know, I am new to python and this time I am trying to obtain the GEOMETRIC OPTIONS OF THE ELEMENT, but it gives me an error… that I am doing it wrong and how can I correct it… I would be very grateful if you could explain to me what fragment of text I deo to apply when the revit api shows me code.
Thank you so much.


opciones geo.dyn (3.5 KB)

opciones geo.rvt (2.3 MB)

try to use opciones = Options() instead

Gracias…
Why does it give me as a result these elements that mean … and why in some 2 in others 3???

not sure why. i tried with 2 different type of column and get this.

oh! you also have to use WhereElementIsNotElementType() unless you want those in your list.

1 Like

I followed your steps and I keep getting 3 elements for each column… which one should I work with???
Could you please review the file that I attached at the beginning and see if you get the same amount as me

Hope you’re sitting down for this one as you’re going to have to do a good bit of experimentation to really understand the overall scope.

First up, it’s important to note a two things about geometry in Revit.

  1. Geometry is secondary to elements
  2. Geometry is calculated on demand

The first is important as it means you can’t just ask for geometry, but you have to pull it form something else. This is somewhat unique to Revit - if you look at say an IFC file, you can define a curve, or a solid, or whatever without having an element in the building.
The second is important as it means nothing is there to quarry from the object until you ask for it - it’s not stored in the file directly, but how to build the geometry is.

Now one last important note, we’re dealing with Revit geometry when we use the Python method get_Geometry, not Dynamo geometry. As such things aren’t going to be functional in the Dynamo environment without making more direct calls to the Revit API. To put it bluntly: the standard Dynamo nodes will be of little to no use use untill you convert the data type. Think of it like speaking Swedish, Spanish, or English - we could say sfär, esfera, or sphere and all mean the same thing, but the person listening needs to speak the same language for things to be understood. The ToProtoType(), ToPoint(), and ToVector() methods will do that conversion for you.

Hopefully you’re with me so far, as this is where things get interesting.

In order to simplify the process of deriving geometry, Revit utilizes a variety of methods to calculate the geometry. The first is calculating the family type geometry and transforming it into the location and orientation of the element in the model. Most families with a repeatable type have this in their sequencing. Then next is getting the geometry from the transformed instance and applying it’s modifiers (ie: the openings you added to each column) and pulling that. This requires the extra step of getting the modifiers, pulling their geometry, and applying them to the solids of the original instance geometry. A lot more steps - hence the second method. There are additional methods depending on the object type (think of walls, stairs, railings, direct shapes, adaptive components, and the rest of the Revit object type database). Oh and don’t forget about groups and links, plus the interaction of those on objects… all in it’s a difficult thing to do consistently, and once data is added (the original 'pull the family type geometry and transform that) you can’t remove that reference from the file… so you get a whole bunch of empty lists and null references when you really dig into the geometry.

Confusing as mud? Likely. I’ve had to play with it for quite awhile on several instances before achieving clarity. The code below should hlep you interrogate the forms a bit more clearly. I suggest starting with three column instances - one concrete column unedited, one concrete column with an opening, one steel column, and one steel column with an opening. Toggling the columns to be slanted or vertical can also help if you get into stuff like invisible geometry.

#setting up the Python environment 
import clr
[ clr.AddReference(i) for i in ['RevitAPI', 'RevitNodes', 'RevitServices'] ]
from Autodesk.Revit.DB import *#BuiltInCategory, Element, FilteredElementCollector, GeometryInstance, Options, Solid, ViewDetailLevel
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

#real code starts here 
doc = DocumentManager.Instance.CurrentDBDocument #get the current document 
structuralElements = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_StructuralColumns).WhereElementIsNotElementType().ToElements()  #get the structural elements, excluding the element types

geoOptions = Options() #the options configuration for getting the geometry of elements
geoOptions.DetailLevel = ViewDetailLevel.Fine #ensure we're using fine detail level 
geoOptions.ComputeReferences = False #ensure we're not computing references 

dynGeo = [] #a list to hold our resulting Dynamo geometry objects 
rvtGeo = [] #a list ot hold our revit geometry object 
rvtVol = [] #a list to hold our revit volumes - as a sanity check
for elem in structuralElements: #start a loop over the list of elements 
	rvtGeometryObjects = elem.get_Geometry(geoOptions) #get the revit geometry objects from each element - a list in all cases
	rvtGeo.append(rvtGeometryObjects) #append the raw Revit geometry to the revit geometry variable
	rvtVolumes = [] #an empty list fo rthe Revit geometry volumes
	dynamoGeoSet = [] #an empty list for our element's geometry as Dynamo geometry 
	
	for rvtGeoObj in rvtGeometryObjects: #start a loop for every revit geometry object 
	
		if rvtGeoObj.GetType() == Solid: #if the object is a solid 
			rvtVolumes.append(rvtGeoObj.Volume) #get the volume and append it to the rvtVolumes list
		else: #otherwise 
			rvtVolumes.append(0) #append a zero
			
		if not rvtGeoObj.GetType() == GeometryInstance: #if the geometry is not a GeometryInstance 
			dynamoGeo = rvtGeoObj.ToProtoType() #convert it to a Dynamo geometry object
			dynamoGeoSet.append(dynamoGeo) #append the Dynamo geo to the dynamo geometry set 
			
		else: #if it was a Geometry instance 
			instanceGeo = rvtGeoObj.GetInstanceGeometry() #get the revit geometry calcualted by the geometry instance
			if len([i for i in instanceGeo]) == 0: #if there isn't anything in the instance geomtery 
				dynamoGeoSet.append([]) #append an empty list to the Dynamo geometry 
			for ig in instanceGeo: #for every revit instance geometry in the list of instance geometry 
				dynInstGeo = ig.ToProtoType() #convert it to a Dynamo geometry object 
				dynamoGeoSet.append(dynInstGeo) #append the Dyanmo geo to the Dyanmo geometry set
				
	dynGeo.append(dynamoGeoSet) #append the Dynamo geometry set to the 
	rvtVol.append(rvtVolumes) #append the volume list to the rvtVol list
	
OUT = zip(rvtGeo, dynGeo, rvtVol) #return the revit geometry, Dynamo geometry, and revit volume as sequenced lists

Hope this helps you sort it all out.

4 Likes

My goodness… I was thinking that this could be a question of a parenthesis () it becomes a whole mess… no wonder not everyone wants to learn to program…

Thank you very much for your explanation.
Truthfully, my final goal was to be able to obtain outputs where I can have separately the upper surfaces, lower surfaces, lateral surfaces, vectors and lines that simulate the central axis of the columns.
I had managed to do it through dynamo nodes but it was heavy for my computer to process hundreds of columns, so I thought I could apply some method through the REVIT API and it returns these surfaces specifically so that it does not consume resources My PC
Any code that allows me to obtain these surfaces…??

1 Like

i like your extensive explanation.
i dont understand myself why @AM3D.BIM.STUDIO is getting more stuff with the same code. i used default structural column.

anyway, @AM3D.BIM.STUDIO you wanted the center of column, you meant center of mass? or center of the family type?

@AM3D.BIM.STUDIO ,

Revit is from 90`s and you are from the future :wink: you have to learn programming

check out also this topic regarding geometry…

KR
Andreas

Host an opening to your structural column. :slight_smile:

1 Like

Knowing that, it would help your fellow forum members to help you if you posted that graph. It may be that there is a simple repair of sorts which could be run on the tool.

That said what you’re after is certainly doable, and my code above is one possible start. Another option would be to call the Dynamo node for Element.Faces via the Python loop, and to utilize the Dynamo geometry library to build the rest of your loop - because the Python node will do some garbage collection as you go things may be quicker. Sticking with the Revit API will require learning quite a few new tricks, like getting surface normals and points, identifying the upper and lower limit of surface UV parameters (Revit doesn’t use a 0-1 range for surface parameterization) and a whole lot more.

You may also want to look into the Dynamo’s topology nodes for your filtering. I did a fairly robust demo of these last week for the Dynamo Office Hour. I utilized topology and a bunch of filtering to locate and generate some detailed geometry in a complex stair form. Not exactly what you’re after but it’s fairly close and as such you can likely utilize it as a template of sorts.

1 Like

Hello, with your comments and many others from you and other people + more acquisition


(I feel that I will progress, thank you)
English - Spanish - French (I dare not speak Swedish :wink:)
cordially
christian.stan

5 Likes

Jag pratar inte heller svenska än, men jag lär mig. :wink:

We all learn from each other - that’s what makes this community so great!

4 Likes

det går da riktigt bra :wink: