Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Get Element from GeometryInstance

6 REPLIES 6
Reply
Message 1 of 7
Anonymous
3039 Views, 6 Replies

Get Element from GeometryInstance

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 !

 

 

6 REPLIES 6
Message 2 of 7
jeremytammik
in reply to: Anonymous

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 

ConvertToStableRepresentation method to generate keys for each geometry object:

 

http://www.revitapidocs.com/2017/9d821d63-5b4a-b814-25b2-b92f7d5d1425.htm

 

That would enable you to create a dictionary mapping back the geometry data to the element it comes from.

 

Or maybe redesign your approach?

 

Good luck!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 7
Anonymous
in reply to: jeremytammik

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

Message 4 of 7
jeremytammik
in reply to: Anonymous

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



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 5 of 7
Anonymous
in reply to: jeremytammik

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

Message 6 of 7
jeremytammik
in reply to: Anonymous

  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



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 7 of 7
Anonymous
in reply to: jeremytammik

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.

Post to forums  

Autodesk Customer Advisory Groups


Rail Community