A GeometryInstance represents a set of geometry stored by Revit in a default configuration, and then transformed into the proper location as a result of the properties of the element. The most common situation where GeometryInstances are encountered is in Family instances. Revit uses GeometryInstances to allow it to store a single copy of the geometry for a given family and reuse it in multiple instances.
Note that not all Family instances will include GeometryInstances. When Revit needs to make a unique copy of the family geometry for a given instance (because of the effect of local joins, intersections, and other factors related to the instance placement) no GeometryInstance will be encountered; instead the Solid geometry will be found at the top level of the hierarchy.
A GeometryInstance offers the ability to read its geometry through the GetSymbolGeometry() and GetInstanceGeometry() methods. These methods return another Autodesk.Revit.DB.GeometryElement which can be parsed just like the first level return.
GetSymbolGeometry() returns the geometry represented in the coordinate system of the family. Use this, for example, when you want a picture of the “generic” table without regards to the orientation and placement location within the project. This is also the only overload which returns the actual Revit geometry objects to you, and not copies. This is important because operations which use this geometry as input to creating other elements (for example, dimensioning or placement of face-based families) require the reference to the original geometry.
GetInstanceGeometry() returns the geometry represented in the coordinate system of the project where the instance is placed. Use this, for example, when you want a picture of the specific geometry of the instance in the project (for example, ensuring that tables are placed parallel to the walls of the room). This always returns a copy of the element geometry, so while it would be suitable for implementation of an exporter or a geometric analysis tool, it would not be appropriate to use this for the creation of other Revit elements referencing this geometry.
There are also overloads for both GetInstanceGeometry() and GetSymbolGeometry() that transform the geometry by any arbitrary coordinate system. These methods always return copies similar to GetInstanceGeometry().
The GeometryInstance also stored a transformation from the symbol coordinate space to the instance coordinates. This transform is accessible as the Transform property. It is also the transformation used when extracting a the copy of the geometry via GetInstanceGeometry(). For more details, refer to Geometry.Transform.
2 family instances placed with different transforms - the same geometry will be acquired from both
Instances may be nested several levels deep for some families. If you encounter nested instances they may be parsed in a similar manner as the first level instance.
Two samples are presented to explain how geometry of instances can be parsed.
In this sample, curves are extracted from the GeometryInstance method GetInstanceGeometry().
Code Region: Getting curves from an instance |
public void GetAndTransformCurve(Autodesk.Revit.ApplicationServices.Application app, Autodesk.Revit.DB.Element element, Options geoOptions) { // Get geometry element of the selected element Autodesk.Revit.DB.GeometryElement geoElement = element.get_Geometry(geoOptions); // Get geometry object foreach (GeometryObject geoObject in geoElement) { // Get the geometry instance which contains the geometry information Autodesk.Revit.DB.GeometryInstance instance = geoObject as Autodesk.Revit.DB.GeometryInstance; if (null != instance) { GeometryElement instanceGeometryElement = instance.GetInstanceGeometry(); foreach (GeometryObject o in instanceGeometryElement) { // Try to find curves Curve curve = o as Curve; if (curve != null) { // The curve is already transformed into the project coordinate system } } } } } |
In this sample, the solids are obtained from an instance using GetSymbolGeometry(). The constituent points are then transformed into the project coordinate system using the GeometryInstance.Transform.
Code Region: Getting solid information from an instance |
private void GetAndTransformSolidInfo(Application application, Element element, Options geoOptions) { // Get geometry element of the selected element Autodesk.Revit.DB.GeometryElement geoElement = element.get_Geometry(geoOptions); // Get geometry object foreach (GeometryObject geoObject in geoElement) { // Get the geometry instance which contains the geometry information Autodesk.Revit.DB.GeometryInstance instance = geoObject as Autodesk.Revit.DB.GeometryInstance; if (null != instance) { GeometryElement instanceGeometryElement = instance.GetSymbolGeometry(); foreach (GeometryObject instObj in instanceGeometryElement) { Solid solid = instObj as Solid; if (null == solid || 0 == solid.Faces.Size || 0 == solid.Edges.Size) { continue; } Transform instTransform = instance.Transform; // Get the faces and edges from solid, and transform the formed points foreach (Face face in solid.Faces) { Mesh mesh = face.Triangulate(); foreach (XYZ ii in mesh.Vertices) { XYZ point = ii; XYZ transformedPoint = instTransform.OfPoint(point); } } foreach (Edge edge in solid.Edges) { foreach (XYZ ii in edge.Tessellate()) { XYZ point = ii; XYZ transformedPoint = instTransform.OfPoint(point); } } } } } } |