This element type can store arbitrary geometry obtained from import operations or calculations in either a project or family document.
The DirectShape element and related classes support the ability to store externally created geometric shapes in a Revit document. The geometry can include closed solids or meshes. DirectShape is primarily intended for importing shapes from other data formats such as IFC or STEP where not enough information is available to create a "real" Revit element.
A DirectShape object may be assigned a top-level Model category, such as the Wall category. Sub-categories cannot be assigned to DirectShape elements. The IsValidCategoryId() method can test a category id to make sure it is a top-level built-in category approved for use with DirectShape and the Category.CategoryType enumerated value will indicated if the category type is Model. Assigning a category will affect how that object is displayed in Revit and will grant the object a collection of available parameters and some limited behaviors. creation
The static CreateElement() method will create a new instance-level DirectShape. It requires the document in which the DirectShape will be added and the id of an appropriate built-in category. DirectShape provides the ApplicationId and ApplicationDataId string parameters that provide context for the source of the created shape.
Once the DirectShape is created, the shape can be set using one of the overloaded SetShape() method. The shape can be set either directly from a ShapeBuilder object or from a list of GeometryObjects. If you are using a ShapeBuilder object to construct geometry for the DirectShape anyway, there may be a slight performance advantage to using the ShapeBuilder input, as Revit will bypass repetitive validation of the input geometry. It is also possible to append additional geometry objects to the DirectShape using versions of the AppendShape() method. Note that AppendShape() will not merge or join the incoming geometry with any geometry already present, the geometry will be stored independently.
DirectShapes accept the following geometry types as input:
In addition, you can specify geometry to be used in a view-specific representation of a DirectShape. This geometry is input along with the input of a DirectShapeTargetViewType. When setting a view-specific shape representation, it will only be used in views of that type. Currently the only view-specific representation supported is for Plan views.
The following example demonstrates how to create a simple DirectShape from a sphere created using the GeometryCreationUtilities class. Note the use of a reference Frame in creating the geometry. Prior to using it to create geometry, it is good practice to call the static method Frame.CanDefineRevitGeometry() which tests whether the supplied Frame object may be used to define a Revit curve or surface. In order to satisfy the requirements the Frame must be orthonormal and its origin is expected to lie within the Revit design limits. (When creating geometry, it also can be useful to use the static XYZ. IsWithinLengthLimits() to ensure the point is within Revit design limits.)
Code Region: Create a DirectShape |
// Create a DirectShape Sphere public void CreateSphereDirectShape(Document doc) { List |
Code Region: Create a DirectShape using TessellatedShapeBuilder |
// Create a pyramid-shaped DirectShape using given material for the faces public void CreateTessellatedShape(Document doc, ElementId materialId) { List |
Code Region: Create a DirectShape using BRepBuilder |
private void CreateDirectShapeFromCylinder(Document doc) { // Naming convention for faces and edges: we assume that x is to the left and pointing down, y is horizontal and pointing to the right, z is up BRepBuilder brepBuilder = new BRepBuilder(BRepType.Solid); // The surfaces of the four faces. Frame basis = new Frame(new XYZ(50, -100, 0), new XYZ(0, 1, 0), new XYZ(-1, 0, 0), new XYZ(0, 0, 1)); CylindricalSurface cylSurf = CylindricalSurface.Create(basis, 50); Plane top = Plane.CreateByNormalAndOrigin(new XYZ(0, 0, 1), new XYZ(0, 0, 100)); // normal points outside the cylinder Plane bottom = Plane.CreateByNormalAndOrigin(new XYZ(0, 0, 1), new XYZ(0, 0, 0)); // normal points inside the cylinder // Add the four faces BRepBuilderGeometryId frontCylFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(cylSurf, null), false); BRepBuilderGeometryId backCylFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(cylSurf, null), false); BRepBuilderGeometryId topFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(top, null), false); BRepBuilderGeometryId bottomFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(bottom, null), true); // Geometry for the four semi-circular edges and two vertical linear edges BRepBuilderEdgeGeometry frontEdgeBottom = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 0), new XYZ(100, -100, 0), new XYZ(50, -50, 0))); BRepBuilderEdgeGeometry backEdgeBottom = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(100, -100, 0), new XYZ(0, -100, 0), new XYZ(50, -150, 0))); BRepBuilderEdgeGeometry frontEdgeTop = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 100), new XYZ(100, -100, 100), new XYZ(50, -50, 100))); BRepBuilderEdgeGeometry backEdgeTop = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 100), new XYZ(100, -100, 100), new XYZ(50, -150, 100))); BRepBuilderEdgeGeometry linearEdgeFront = BRepBuilderEdgeGeometry.Create(new XYZ(100, -100, 0), new XYZ(100, -100, 100)); BRepBuilderEdgeGeometry linearEdgeBack = BRepBuilderEdgeGeometry.Create(new XYZ(0, -100, 0), new XYZ(0, -100, 100)); // Add the six edges BRepBuilderGeometryId frontEdgeBottomId = brepBuilder.AddEdge(frontEdgeBottom); BRepBuilderGeometryId frontEdgeTopId = brepBuilder.AddEdge(frontEdgeTop); BRepBuilderGeometryId linearEdgeFrontId = brepBuilder.AddEdge(linearEdgeFront); BRepBuilderGeometryId linearEdgeBackId = brepBuilder.AddEdge(linearEdgeBack); BRepBuilderGeometryId backEdgeBottomId = brepBuilder.AddEdge(backEdgeBottom); BRepBuilderGeometryId backEdgeTopId = brepBuilder.AddEdge(backEdgeTop); // Loops of the four faces BRepBuilderGeometryId loopId_Top = brepBuilder.AddLoop(topFaceId); BRepBuilderGeometryId loopId_Bottom = brepBuilder.AddLoop(bottomFaceId); BRepBuilderGeometryId loopId_Front = brepBuilder.AddLoop(frontCylFaceId); BRepBuilderGeometryId loopId_Back = brepBuilder.AddLoop(backCylFaceId); // Add coedges for the loop of the front face brepBuilder.AddCoEdge(loopId_Front, linearEdgeBackId, false); brepBuilder.AddCoEdge(loopId_Front, frontEdgeTopId, false); brepBuilder.AddCoEdge(loopId_Front, linearEdgeFrontId, true); brepBuilder.AddCoEdge(loopId_Front, frontEdgeBottomId, true); brepBuilder.FinishLoop(loopId_Front); brepBuilder.FinishFace(frontCylFaceId); // Add coedges for the loop of the back face brepBuilder.AddCoEdge(loopId_Back, linearEdgeBackId, true); brepBuilder.AddCoEdge(loopId_Back, backEdgeBottomId, true); brepBuilder.AddCoEdge(loopId_Back, linearEdgeFrontId, false); brepBuilder.AddCoEdge(loopId_Back, backEdgeTopId, true); brepBuilder.FinishLoop(loopId_Back); brepBuilder.FinishFace(backCylFaceId); // Add coedges for the loop of the top face brepBuilder.AddCoEdge(loopId_Top, backEdgeTopId, false); brepBuilder.AddCoEdge(loopId_Top, frontEdgeTopId, true); brepBuilder.FinishLoop(loopId_Top); brepBuilder.FinishFace(topFaceId); // Add coedges for the loop of the bottom face brepBuilder.AddCoEdge(loopId_Bottom, frontEdgeBottomId, false); brepBuilder.AddCoEdge(loopId_Bottom, backEdgeBottomId, false); brepBuilder.FinishLoop(loopId_Bottom); brepBuilder.FinishFace(bottomFaceId); brepBuilder.Finish(); using (Transaction tr = new Transaction(doc, "Create a DirectShape")) { tr.Start(); DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel)); ds.SetShape(brepBuilder); tr.Commit(); } } |
The ShapeImporter utility class supports conversion of geometry stored in external formats (such as SAT and Rhino) into a collection of GeometryObjects which can be used to set the shape for a DirectShape. Use ShapeImporter.Convert() to generate the geometry objects (and where possible, corresponding materials and graphics styles in the associated document).
Code Region: Create a DirectShape from SAT file |
public void ReadSATFile(Document revitDoc) { // Allow the user to select a SAT file. OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "SAT Files (.sat)|.sat"; if (DialogResult.OK == ofd.ShowDialog()) { ShapeImporter shapeImporter = new ShapeImporter(); shapeImporter.InputFormat = ShapeImporterSourceFormat.SAT; IList |
The DirectShapeOptions class is used to control behavior of a DirectShape object. Use DirectShape.SetOptions() to set the options used by a DirectShape object. The GetOptions() method will return the DirectShapeOptions currently used by the DirectShape object.
DirectShape elements, by default, support element references, including dimensions, alignments, and face hosting, as well as snapping. This default behavior can be changed using the DirectShapeOptions.ReferencingOption property. If it is set to NotReferenceable, the geometry may not be used for dimensioning, snapping, alignment, or face-hosting. The element may still be selected by the user for operations which do not reference individual geometry objects.
DirectShape elements also support the ability to participate in room boundary calculations, if they are of an appropriate category for room boundary calculations, and if the associated "Room Bounding" parameter is set to true. The property DirectShapeOptions.RoomBoundingOption identifies whether the DirectShape supports an option for the "Room Bounding" parameter to permit participation in room boundary calculations. The default value is NotApplicable, but this will be changed automatically to SetByParameter for applicable DirectShapes.