GetInstanceGeometry() returns instance based geometry, but has references to symbol

GetInstanceGeometry() returns instance based geometry, but has references to symbol

a.schacht
Contributor Contributor
2,404 Views
10 Replies
Message 1 of 11

GetInstanceGeometry() returns instance based geometry, but has references to symbol

a.schacht
Contributor
Contributor

Hi there!

 

I have for a long time now had a problem, where sometimes the geometry retrieved from a FamilyInstance refers to the FamilySymbol. This seems to happen at random in different projects, and is easily identifiable in that the geometry retrieved from: 

 

familyInstance.get_Geometry(options)

 

is not a list of solids and other misc. GeometryObjects, but instead a singular GeometryInstance object. Then we can run GetInstanceGeometry() and GetSymbolGeometry() on this object and get the usual GeometryObject(s) like solids. As you would expect, GetInstanceGeometry() returns the geometry of the instance and not the symbol, but every single GeometryObject in the returned solid(s) (faces, curves etc.) exclusively have references to the FamilySymbol. Likewise, GetSymbolGeometry() returns geometry for the symbol, but now all the references of GeometryObject(s) refer to the FamilyInstance???

 

This behaviour can co-exist along with the normal expected behaviour in the same projects across different FamilyInstances.

 

Has anyone got any kind of clue as to why this happens on occasion in some projects, and not in others?

Accepted solutions (1)
2,405 Views
10 Replies
Replies (10)
Message 2 of 11

jeremy_tammik
Alumni
Alumni

Oh dear. That sounds pretty tricky indeed.

 

Does this related discussion throw any additional light?

 

https://thebuildingcoder.typepad.com/blog/2020/04/references-in-symbol-versus-instance-geometry.html

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 11

a.schacht
Contributor
Contributor

Hi Jeremy

 

I did have a look at that post first, but to my understanding that post is a bit more about understanding the difference between using symbol and instance references to create new instances. I have a fair understanding of the difference between the two (although, I'm sure it could be better), but my problem is not related I think. For this particular problem it is affecting my new automatic rebar constraints program, where I need references to instance based faces, and not the symbol. However, the instance geometry refers to the symbol face and vice versa.

0 Likes
Message 4 of 11

a.schacht
Contributor
Contributor

Some more details here after I found out a bit more about it: The family is a concrete beam with some nested hosted families in it. It seems that for any newly inserted instance of the families we use at my company, this problem occours. However, if we then insert another geometry cutting family which is hosted by some face of the main element, the geometry is recalculated and now it's correct. If we then remove this hosted family, the recalculation is still correct. So it's only the initial insertion which is the problem and any subsequent action which causes geometry recalculation, still maintains correctness. This seems a lot like a bug to me, but I don't know.

Message 5 of 11

RPTHOMAS108
Mentor
Mentor

That sounds a bit confusing you'll probably need a minimum reproducible case with family to demonstrate it so it can be progressed.

 

I don't think the GetInstanceGeometry and GetSymbolGeometry methods are that well named with respect to FamilySymbol and FamilyInstance confusion. I have no understanding how Revit rationalises geometry but my previous observations are as follows:

 

(A) Geometry from GeometryInstance.GetSymbolGeometry on the FamilyInstance is a unique version of physical geometry as driven by both instance and type parameters (each a unique version of geometry for a family).
(B) Geometry from GeometryInstance.GetInstanceGeometry on the FamilyInstance is a copy of (A) but relocated to the family instance position (not family position).
(C) FamilySymbol doesn't contain GeometryInstance just top level geometry
(D) When a family instance is modified by cuts it also doesn't contain a GeometryInstance just top level geometry (the same as a system family).

 

I think GetSymbolGeometry and GetInstanceGeometry happens at two separate stages. First Revit decides what unique geometry versions it has for a family (symbol geometry) then it copies them into position (instance geometry). Unfortunately we don't get the true rationalisation of symbol geometry in the API i.e. each symbol geometry doesn't contain a key. We just get the final result i.e. this family instance has this symbol geometry (driven by a combination of instance and type parameters).

 

So it is possible that a cut makes the instance unique (no longer sharing geometry with other instances and becomes D). If a cut is removed does Revit:

1) Create a new symbol geometry set and add to a GeometryInstance

2) Look to match against an existing symbol geometry to use in a new GeometryInstance

3) Keep top level geometry and don't revert to having GeometryInstance in family instance geometry.

This I don't know but from a quick test it seems to be (3) then again what happens if the model is compacted etc.

 

I've never analysed if instance geometry references are from symbol geometry (instance geometry is a copy). Sounds odd if symbol geometry references refer to an instance (i.e. which instance out of two or more instances)?

0 Likes
Message 6 of 11

a.schacht
Contributor
Contributor

I've attached a project and the beam family, with two instances of the same family, where I've made a cut in one and then removed the cut again, which indeed keeps top level geometry like you observed yourself in (3) at the bottom of your post. It's a Danish company, and as such the project template, family etc. is all in Danish. If you go to the default 3D view, and use the lookup tool or the API to get information about the families, you can see that the uncut instance has a single GeometryInstance element as its geometry, and the cut version has solids. The uncut instance represents the issue at hand, whereas the cut version represents the behaviour I would expect. 

 

Running GetInstanceGeometry() on the uncut instance's GeometryInstance, still has solids whoose faces refer to the symbol. It's not even possible to get symbol geometry on the cut version.

0 Likes
Message 7 of 11

TripleM-Dev.net
Advisor
Advisor

Hi,

 

I see the different properties, propably due to editing. Always good to make recursive method to keep going until Solid (ed) are found....depending needs.

 

So in this case, if the SymbolGeomerty returns Null, then see if the Symbol itself can return Geometry (should be identical, just has to dig deeper.) and as far as I can determine with Revit lookup, Snoop they have the same geomerty (Type!)

 

- Michel

0 Likes
Message 8 of 11

RPTHOMAS108
Mentor
Mentor

I concur with @TripleM-Dev.net you just need to allow for the two situations. Also true that you can still get the symbol geometry from the cut instance via the Symbol property of the empty GeometryInstance. What you get from GeometryInstance.Symbol isn't the same as what you get from FamilyInstance.Symbol if you compare the ids etc.

 

Below I am comparing the ids of GeometryInstance.Symbol, for this example they are grouped by length regardless of cut.

 

Project1.jpg

 

Bounding box for symbol 427781:

(11.4829396325459, 0.166666666666667, 0.500492125984252)
(-11.4829396325459, -0.166666666666667, -0.500492125984252)

Bounding box for symbol 427801:

(6.56167979002625, 0.166666666666667, 0.500492125984252)
(-6.56167979002625, -0.166666666666667, -0.500492125984252)

 

The conclusion of the above is the symbol geometry bounding box from GeometryInstance.Symbol matches the length of the member when aligned with symbol space.

 

Comparison of top level solids:
Long member: 0.773861742402726 Solid volume with cut
Long member: 0.781251542752411 Solid volume without cut

 

The conclusion from the above is since the cut isn't part of the family it isn't part of the symbol geometry. It is however included in the top level solids.

 

Aside from the above your family also contains some nested items but since these are shared they are not part of the geometry of the host family. They exist in the project in their own right accessed via FamilyInstance.GetSubComponentIds.

0 Likes
Message 9 of 11

a.schacht
Contributor
Contributor

I think we might be getting a bit off track here as to what my problem is - or maybe I am not understanding your responses correctly. I will try to clarify the issue I am trying to figure out the behaviour behind.

 

This is from the cut instance, where the top level geometry is flattened, and this is the behaviour I would expect to see, where the Face from the Solid from the geometry also has a reference to the FamilyInstance that it is part of:

aschacht_0-1633598738822.png

 

This is then from the uncut instance, where the Reference of the Face of the Solid of the GetInstanceGeometry() is not actually a Reference to the FamilyInstance, but to the FamilySymbol:

aschacht_2-1633599003092.png

 

This might be what you guys have been trying to explain, but in that case I still don't quite understand why it is behaving the way it is.

Message 10 of 11

RPTHOMAS108
Mentor
Mentor
Accepted solution

The instance geometry is a copy of the symbol geometry relocated so will point to the symbol. 

 

It sounds backwards but you can get the family instance references:

For cut using top level solids.

For uncut using GeometryInstance.SymbolGeometry

 

GeometryInstance.Symbol in uncut instances has references to the symbol so should not be used for that case it seems.

 

GetInstanceGeometry and GetSymbolGeometry are just helper methods so can likely be avoided.

 

Message 11 of 11

RPTHOMAS108
Mentor
Mentor

One further clarification:

 

GeometryInstance.Symbol gives references to the symbol so should be avoided for your case also.

0 Likes