Hi Everyone,
We are trying to extract a list of geometries from a list of random elements and we have some difficulties, specially with railings and stairs.
For now we wrote a recursive function, which is iterating over each geometryObject in a given geometryElement and for each geometryObject over each sub geometryObject, etc, etc.. in pseudo code :
void geometryExtractor(geometryElement)
foreach geometryObject in geometryElement
if geometryObject is Solid
extractFaces(geometryObject as Solid)
else if geometryObject is GeometryInstance
geometryExtractor((geometryObject as GeometryInstance).getInstanceGeometry())
main(elementList)
foreach element in elementList
geometryElement = element.getGeometry()
geometryExtractor(geometryElement)
We are able with this technique to extract 90% of elements, but the last 10% is not correctly working..
A example of the problem we have with this technique :
for a given stairs, when the stairs element pass into our function, we extract the geometry of the landings, supports, railings etc. and when the main loop iterates over the familyInstance of a support or railings associated with the stairs, we extract another time their geometries.
The final extraction contains multiple copies of supports and landings geometries...
Is there a way to get a link between a geometryInstance and a Element ? We think it will be a good strategy to detect which element is a part of another one. We didn't find any solution to reach something like a parent-childs link between elements.
We know that for stairs we can use .GetAssociatedRailings(), GetStairsRuns(), etc but it requires to cast our Element as Stairs and we are looking for a generic method working for all elements.
Thanks for your help !
Dear Pierre,
Sounds as if you created an interesting little problem for yourself.
If you really want to dig deeper (making it harder to get out), you could ask the geometry to be equipped with references and then use the
Or maybe redesign your approach?
Good luck!
Cheers,
Jeremy
Thanks a lot Jeremy,
Stable representation seems to be the way to do it :). I read the Revit API and a really interesting post on your blog related to this question:
http://thebuildingcoder.typepad.com/blog/2016/04/stable-reference-string-magic-voodoo.html
What do you mean by "equipped with references" ? The API doesn't allow to cast GeometryElement or GeometryObject as Reference.
Cheers,
Pierre
Thank you for your appreciation and glad you like the idea.
You can equip the geometry objects with references when you query the element for its geometry by specifying ComputeReferences = true in the options argument:
http://www.revitapidocs.com/2017/d7da6de4-74a9-60e2-826f-698a5730d0a8.htm
Cheers,
Jeremy
Sorry but I don't understand how it works...
Options opts = new Options();
opts.DetailLevel = ViewDetailLevel.Fine;
opts.ComputeReferences = true;
foreach (Element ele in elementList) {
GeometryElement geomEle = ele.get_Geometry(opts);
foreach (GeometryObject geomObj in geomEle) {
if (geomObj is Solid)
// ...
else
// Here we want to access to the instance element Revit ID which geomObj is refering to... it should be very easy but we are completely lost..
}
}
Thanks for your help
if geomobj is solid get all its faces for each face get the face reference using Face.Reference use those to keep track of the solid
I just noticed that the face geometry object has a reference property, whereas the solid itself does not:
http://www.revitapidocs.com/2018/f3d5d2fe-96bf-8528-4628-78d8d5e6705f.htm
That might complicate your algorithm somewhat.
As said in my initial answer, you are entering a really thorny path.
You might need a machete.
Why not plan an easier route, following a road or highway?
Cheers,
Jeremy
We tried this :
Dictionary<string, List<string>> References; public void getReferencesFromGeometryElement(string rvtID, GeometryElement geoElement, Document doc) { if (null != geoElement) { foreach (GeometryObject geoObject in geoElement) { var solid = geoObject as Solid; if (solid != null && solid.Faces.Size > 0) { foreach (Face f in solid.Faces) { if (f.Reference != null && doc.GetElement(f.Reference) != null) { if (!(References.ContainsKey(rvtID))) References.Add(rvtID, new List<string>()); References[rvtID].Add(f.Reference.ConvertToStableRepresentation(doc)); } break; // every faces should belongs to the same reference. } } else { GeometryInstance geoInstance = geoObject as GeometryInstance; if (null != geoInstance && geoInstance.IsElementGeometry && geoInstance.Transform.IsConformal) { getReferencesFromGeometryElement(rvtID, geoInstance.GetSymbolGeometry(), doc); } } } } } public void BuildReferencesFromDocument(Element[] elements, Document doc) { Options opts = new Options(); opts.DetailLevel = ViewDetailLevel.Fine; opts.IncludeNonVisibleObjects = false; opts.ComputeReferences = true; foreach (Element element in elements) { getReferencesFromGeometryElement(element.UniqueId, element.get_Geometry(opts), doc); } }
At this point the References dictionnary contains for each element.UniqueId in elements, a list of stable representations. For example :
For a model containing one Railing we obtain :
1) A Railing Element containing a list of stable representations like this :
...
"53115283-2071-4edc-bb37-faa9ac21c9aa-0001f604:1:INSTANCE:53115283-2071-4edc-bb37-faa9ac21c9aa-0001f605:674:INSTANCE:53115283-2071-4edc-bb37-faa9ac21c9aa-0001f660:26:SURFACE",
"53115283-2071-4edc-bb37-faa9ac21c9aa-0001f604:1:INSTANCE:53115283-2071-4edc-bb37-faa9ac21c9aa-0001f605:673:INSTANCE:53115283-2071-4edc-bb37-faa9ac21c9aa-0001f660:26:SURFACE",
"53115283-2071-4edc-bb37-faa9ac21c9aa-0001f604:1:INSTANCE:53115283-2071-4edc-bb37-faa9ac21c9aa-0001f605:672:INSTANCE:53115283-2071-4edc-bb37-faa9ac21c9aa-0001f660:26:SURFACE",
"53115283-2071-4edc-bb37-faa9ac21c9aa-0001f604:1:INSTANCE:53115283-2071-4edc-bb37-faa9ac21c9aa-0001f605:667:INSTANCE:53115283-2071-4edc-bb37-faa9ac21c9aa-0001f660:26:SURFACE",
...
(the number in bold is the only part of the representation which are not always the same)
2) Multiple FamilyInstance of Supports containing one stable representation like this :
"53115283-2071-4edc-bb37-faa9ac21c9aa-0001f65f:0:INSTANCE:53115283-2071-4edc-bb37-faa9ac21c9aa-0001f660:26:SURFACE"
In 1), the 3 Unique Ids are those of : the Railing Element, then the ElementType of the railing, then the FamilySymbol of the support.
In 2), the 2 Unique Ids are those of : the FamilyInstance of the support, then the FamilySymbol of the support.
The problem is that we can have in 1) 10 references to 1 symbol and in 2) 4 elements referencing 1 symbol. What we want is detecting which references in the Railing Element is pointing to which FamilyInstance, and this information is still missing...
We guess that the 4 FamilyInstance are the 4 differents geometry derivation of the original Symbol (the current support, the one at the end, the one in corner, etc.). Should we have to make a geometric comparison between each solids of the railings and the different candidates FamilyInstance or is it a simple way to access to this information ?
We aim to export all the geometry of a model without any copy of information. Without the link between the Railing and its supports, we can't decide if the FamilyInstance of the support is a part of a railing and should not be drawn, or if it is a FamilyInstance like any other FamilyInstance and should be displayed.
We are open to take the highway, but we probably miss the sign 😉
Thx a lot for your help
Can't find what you're looking for? Ask the community or share your knowledge.