Revit API Developer's Guide MD 변환본 추가 (368 페이지)

Revit 2026 공식 Developer's Guide HTML → MD 변환.
Output/revit-api-guide/에 8개 카테고리 폴더로 정리.
CLAUDE.md에 참조 규칙 추가, .gitignore에 .scratch/ 제외.

소스: help.autodesk.com/view/RVT/2026/ENU (CC BY-NC-SA 3.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
minsung
2026-04-14 17:33:42 +09:00
parent 3bd01e31c9
commit b4a8714793
370 changed files with 28908 additions and 0 deletions

View File

@@ -0,0 +1,386 @@
# Rooms
# Rooms
The following sections cover information about the room class, its parameters, and how to use the room class in the API.
### Room, Area, and Tags
The Room class is used to represent rooms and elements such as room schedule and area plans. The properties and create function for different rooms, areas, and their corresponding tags in the API are listed in the following table:
**Table 55: Room, Area, and Tags relationship**
**Element** | **Class** | **Category** | **Boundary** | **Location** | **Can Create**
---|---|---|---|---|---
Room in Plan View | Room | OST_Rooms | Has if in an enclosed region | LocationPoint | NewRoom() except for NewRoom(Phase)
Room in Schedule View | Room | OST_Rooms | Null | Null | NewRoom(Phase)
Area | Room | OST_Areas | Always has | LocationPoint | No
Room Tag | RoomTag | OST_RoomTags | | LocationPoint | Creation.Document.NewRoomTag()
Area Tag | FamilySymbol | OST_AreaTags | | LocationPoint | No
Note: Room.Name is the combination of the room name and room number. For example, for a room whose number is 2 and whose name is "Upstairs Bedroom", Room.Name returns "Upstairs Bedroom 2". Use the ROOM_NAME BuiltInParameter to get the room name.
Note: As an Annotation Element, the specific view is available using RoomTag.View. Never try to set the RoomTag.Name property because the name is automatically assigned; otherwise an exception is thrown.
### Creating a room
The following code illustrates the simplest way to create a room at a certain point in a specific level:
**Code Region 28-1: Creating a room**
---
Room CreateRoom(Autodesk.Revit.DB.Document document, Level level)
{
// Create a UV structure which determines the room location
UV roomLocation = new UV(0, 0);
// Create a new room
Room room = document.Create.NewRoom(level, roomLocation);
if (null == room)
{
throw new Exception("Create a new room failed.");
}
return room;
}
Rooms can be created in a room schedule then inserted into a plan circuit.
* The Document.NewRoom(Phase) method is used to create a new room, not associated with any specific location, and insert it into an existing schedule. Make sure the room schedule exists or create a room schedule in the specified phase before you make the call.
* The Document.NewRoom(Room room, PlanCircuit circuit) method is used to create a room from a room in a schedule and a PlanCircuit.
* The input room must exist only in the room schedule, meaning that it does not display in any plan view.
* After invoking the method, a model room with the same name and number is created in the view where the PlanCircuit is located.
For more details about PlanCircuit, see Plan Topology below.
The following code illustrates the entire process:
**Code Region 28-2: Creating and inserting a room into a plan circuit**
---
Room InsertNewRoomInPlanCircuit(Autodesk.Revit.DB.Document document, Level level, Phase newConstructionPhase)
{
// create room using Phase
Room newScheduleRoom = document.Create.NewRoom(newConstructionPhase);
// set the Room Number and Name
string newRoomNumber = "101";
string newRoomName = "Class Room 1";
newScheduleRoom.Name = newRoomName;
newScheduleRoom.Number = newRoomNumber;
// Get a PlanCircuit
PlanCircuit planCircuit = null;
// first get the plan topology for given level
PlanTopology planTopology = document.get_PlanTopology(level);
// Iterate circuits in this plan topology
foreach (PlanCircuit circuit in planTopology.Circuits)
{
// get the first circuit we find
if (null != circuit)
{
planCircuit = circuit;
break;
}
}
Room newRoom2 = null;
if (null != planCircuit)
{
using (Transaction transaction = new Transaction(document, "Create Room"))
{
if (transaction.Start() == TransactionStatus.Started)
{
// The input room must exist only in the room schedule,
// meaning that it does not display in any plan view.
newRoom2 = document.Create.NewRoom(newScheduleRoom, planCircuit);
// a model room with the same name and number is created in the
// view where the PlanCircuit is located
if (null != newRoom2)
{
// Give the user some information
TaskDialog.Show("Revit", "Room placed in Plan Circuit successfully.");
}
transaction.Commit();
}
}
}
return newRoom2;
}
Once a room has been created and added to a location, it can be removed from the location (but still remains in available in the project) by using the Room.Unplace() method. It can then be placed in a new location.
### Room Boundary
Rooms have boundaries that create an enclosed region where the room is located.
* Boundaries include the following elements:
* Walls
* Model lines
* Columns
* Roofs
#### Retrieving Room Boundaries
The boundary around a room is obtained from the base class method SpatialElement.GetBoundarySegments(). The method returns null when the room is not in an enclosed region or only exists in the schedule. Each room may have several regions, each of which have several segments hence the data is returned in the form of a list of BoundarySegment lists.
The following figure shows a room boundary selected in the Revit UI:
**Figure 138: Room boundary**
The size of the segment list depends on the enclosed region topology. Each BoundarySegment list makes a circuit or a continuous line in which one segment joins the next. The following pictures provide several examples. In the following pictures, all walls are Room-Bounding and the model lines category is OST_AreaSeparationLines. If an element is not Room-Bounding, it is excluded from the elements to make the boundary.
**Figure 139: Rooms 1, 2, 3, 4**
**Figure 140: Room 5, 6**
The following table provides the Room.GetBoundarySegments().Size results for the previous rooms:
**Table 56: Room.GetBoundarySegments().Size**
**Room** | **Room.GetBoundarySegments().Size**
---|---
Room 1 Room 2 Room 3 | 1
Room 4 | 2
Room 5 Room 6 | 3
Note: Walls joined by model lines are considered continuous line segments. Single model lines are ignored.
After getting `IList<IList<BoundarySegment>>` , get the BoundarySegment by iterating the list.
#### BoundarySegment
The segments that make the region are represented by the BoundarySegment class; its ElementId property returns the id of the corresponding element with the following conditions:
* For a ModelCurve element, the category must be BuiltInCategory.OST_AreaSeparationLines meaning that it represents a Room Separator.
* For other elements such as wall, column, and roof, if the element is a room boundary, the Room Bounding parameter (BuiltInParameter.WALL_ATTR_ROOM_BOUNDING) must be true as in the following picture.
**Figure 141: Room Bounding property**
**Code Region 28-3: Setting room bounding**
---
public void SetRoomBounding(Wall wall)
{
Parameter parameter = wall.GetParameter(ParameterTypeId.WallAttrRoomBounding);
parameter.Set(1); //set "Room Bounding" to true
parameter.Set(0); //set "Room Bounding" to false
}
Notice how the roof forms the BoundarySegment for a room in the following pictures. The first picture shows Level 3 in the elevation view. The room is created in the Level 3 floor view. The latter two pictures show the boundary of the room and the house in 3D view.
**Figure 142: Room created in level 3 view**
**Figure 143: Room boundary formed by** roof
The area boundary can only be a ModelCurve with the category Area Boundary (BuiltInCategory.OST_AreaSchemeLines) while the boundary of the displayed room can be walls and other elements.
**Figure 144: Wall end edge**
If the BoundarySegment corresponds to the curve between the room separation and wall as the previous picture shows:
* The Element property returns null.
* The Curve is not null.
#### Boundary and Transaction
When you call Room.GetBoundarySegments() after creating an Element using the API such as a wall, the wall can change the room boundary. You must make sure the data is updated.
The following illustrations show how the room changes after a wall is created using the Revit Platform API.
**Figure 145: Added wall changes the room boundary**
To update the room boundary data, use the transaction mechanism in the following code:
**Code Region 28-4: Using a transaction to update room boundary**
---
public void UpdateRoomBoundary(UIApplication application, Room room, Level level)
{
Document document = application.ActiveUIDocument.Document;
//Get the size before creating a wall
int size = room.GetBoundarySegments(new SpatialElementBoundaryOptions()).First().Count;
string message = "Room boundary size before wall: " + size;
//Prepare a line
XYZ startPos = new XYZ(-10, 0, 0);
XYZ endPos = new XYZ(10, 0, 0);
Line line = Line.CreateBound(startPos, endPos);
//Create a new wall and enclose the creating into a single transaction
using (Transaction transaction = new Transaction(document, "Create Wall"))
{
if (transaction.Start() == TransactionStatus.Started)
{
Wall wall = Wall.Create(document, line, level.Id, false);
if (null != wall)
{
if (TransactionStatus.Committed == transaction.Commit())
{
//Get the new size
size = room.GetBoundarySegments(new SpatialElementBoundaryOptions()).First().Count;
message += "\nRoom boundary size after wall: " + size;
TaskDialog.Show("Revit", message);
}
}
else
{
transaction.RollBack();
}
}
}
}
For more details, see [Transactions](../../Basic_Interaction_with_Revit_Elements/Revit_API_Revit_API_Developers_Guide_Basic_Interaction_with_Revit_Elements_Transactions_html.html).
### Plan Topology
The level plan that rooms lie in have a topology made by elements such as walls and room separators. The PlanTopology and PlanCircuit classes are used to present the level topology.
* Get the PlanTopology object from the Document object using the Level. In each plan view, there is one PlanTopology corresponding to every phase.
* The same condition applies to BoundarySegment, except room separators and Elements whose Room Bounding parameter is true can be a side (boundary) in the PlanCircuit.
**Figure 146: Room and Plan Topology diagram**
The PlanCircuit.SideNum property returns the circuit side number, while SpatialElement.GetBoundarySegments() returns an `IList<IList<Autodesk.Revit.DB.BoundarySegment>>` , whose Count is different from the circuit side number.
* SpatialElement.GetBoundarySegments() recognizes the bottom wall as two walls if there is a branch on the wall.
* PlanCircuit.SideNum always sees the bottom wall in the picture as one regardless of the number of branches.
**Figure 147: Compare room boundary with PlanCircuit**
**Table 57: Compare Room Boundary with PlanCircuit**
| |
---|---|---
Circuit | Circuit.SideNum | `IList<IList<Autodesk.Revit.DB.BoundarySegment>>.Count` for Room
Circuit 1 | 3 | 3 (Room1)
Circuit 2 | 4 +2 = 6 | 4 +3 = 7 (Room2)
Circuit 3 | 3 +2 = 5 | 3 +3 = 6 (Room3)
Circuit 4 | 3 | 3 (Room4)
Circuit 5 | 3 | 3 (Room5)
### Room and FamilyInstance
Doors and Windows are special family instances related to Room. Only doors are discussed here since the only difference is that windows have no handle to flip.
The following characteristics apply to doors:
* Door elements can exist without a room.
* In the API (and only in the API), a Door element has two additional properties that refer to the regions on the two opposite sides of a door: ToRoom and FromRoom.
* If the region is a room, the property's value would be a Room element.
* If the region is not a room, the property will return null. Both properties may be null at the same time.
* The region on the side into which a door opens, will be ToRoom. The room on the other side will be FromRoom.
* Both properties get dynamically updated whenever the corresponding regions change.
In the following pictures, five doors are inserted into walls without flipping the facing. The table lists the FromRoom, ToRoom, and Room properties for each door. The Room property belongs to all Family Instances.
**Figure 148: Door 1**
**Figure 149: Door 2**
**Figure 150: Door 3**
**Figure 151: Door 4**
**Figure 152: Door 5**
**Table 58: Door Properties**
**Door** | **FromRoom** | **ToRoom** | **Room**
---|---|---|---
Door 1 | null | null | null
Door 2 | Room 1 | null | null
Door 3 | Room 3 | Room 2 | Room 2
Door 4 | Room 4 | null | null
Door 5 | null | Room 6 | Room 6
All family instances have the Room property, which is the room where an instance is located in the last project phase. Windows and doors face into a room. Change the room by flipping the door or window facing, or by calling FamilyInstance.FlipFromToRoom(). For other kinds of instances, such as beams and columns, the Room is the room that has the same boundary as the instance.
The following code illustrates how to get the Room from the family instance. It is necessary to check if the result is null or not.
**Code Region 28-5: Getting a room from the family instance**
---
public void GetRoomInfo(FamilyInstance familyInstance)
{
Room room = familyInstance.Room;
room = familyInstance.FromRoom; //for door and window family only
room = familyInstance.ToRoom; //for door and window family only
if (null != room)
{
//use the room...
}
}
### Other Room Properties
The Room class has several other properties you can use to get information about the object. Rooms have these read-only dimension properties:
* Area
* Perimeter
* UnboundedHeight
* Volume
* ClosedShell
This example displays the dimension information for a selected room. Note that the volume calculations setting must be enabled, or the room volume is returned as 0.
**Code Region 28-6: Getting a room's dimensions**
---
public void GetRoomDimensions(Document doc, Room room)
{
String roominfo = "Room dimensions:\n";
// turn on volume calculations:
using (Transaction t = new Transaction(doc, "Turn on volume calculation"))
{
t.Start();
AreaVolumeSettings settings = AreaVolumeSettings.GetAreaVolumeSettings(doc);
settings.ComputeVolumes = true;
t.Commit();
}
roominfo += "Vol: " + room.Volume + "\n";
roominfo += "Area: " + room.Area + "\n";
roominfo += "Perimeter: " + room.Perimeter + "\n";
roominfo += "Unbounded height: " + room.UnboundedHeight + "\n";
TaskDialog.Show("Revit",roominfo);
}
The ClosedShell property for a Room (or Space) is the geometry formed by the boundaries of the open space of the room (walls, floors, ceilings, roofs, and boundary lines). This property is useful if you need to check for intersection with other physical element in the model with the room, for example, to see if part or all of the element is located in the room. For an example, see the RoofsRooms sample application, included with the Revit SDK, where ClosedShell is used to check whether a room is vertically unbounded.
In addition, you can get or set the base offset and limit offset for rooms with these properties:
* BaseOffset
* LimitOffset
You can get or set the level that defines the upper limit of the room with the UpperLimit property.
**Parent page:** [Architecture](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Architecture_html.html)

View File

@@ -0,0 +1,17 @@
# Architecture
# Architecture
This chapter covers API functionality that is specific to the architectural features of Revit:
* Functionality related to rooms (Element.Room, RoomTag, etc.)
**Pages in this section**
* [Rooms](Architecture/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Architecture_Rooms_html.html)
**Parent page:** [Discipline-Specific Functionality](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_html.html)

View File

@@ -0,0 +1,18 @@
# Civil Alignments API
# Civil Alignments API
Revit provides support for Civil Alignments and their associated annotations. Alignments are imported from InfraWorks as a part of the workflow to transfer Civil Structures. The API supports read of alignment properties and geometric information, along with read/write and create of associated annotations. All new classes for the Alignments API are exposed through a different assembly in the Revit installation, located at Addins\CivilAlignments \Autodesk.CivilAlignments.DBApplication.dll.
`Autodesk.Revit.DB.Infrastructure.Alignment` represents an alignment and can be used to find alignments in a document, and to query a particular alignment's properties and to analyze alignment geometry. This object is not an Element, but the underlying Element can be obtained from this object if needed.
`Autodesk.Revit.DB.Infrastructure.AlignmentStationLabel` represents an alignment station label annotation and can be used to find such labels in a document as well as to create and modify such labels. This object is not an Element, but the underlying Element (which is a SpotDimension instance) can be obtained from this object if needed.
* Autodesk.Revit.DB.Infrastructure.AlignmentStationLabelOptions
* Autodesk.Revit.DB.Infrastructure.AlignmentStationLabelSetOptions
provide options for creating a single alignment label or for creating a set of alignment labels.
**Parent page:** [Discipline-Specific Functionality](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_html.html)

View File

@@ -0,0 +1,77 @@
# Connectors
# Connectors
Connectors are associated with a domain - ducts, piping or electrical - which is obtained from the Domain property of a Connector. Connectors are present on mechanical equipment as well as on ducts and pipes.
To traverse a system, you can examine connectors on the base equipment of the system and determine what is attached to the connector by checking the IsConnected property and then the AllRefs property. When looking for a physical connection, it is important to check the ConnectionType of the connector. There are both physical and logical connectors in Revit, but only the physical connectors are visible in the application. The following imagine shows the two types of physical connectors - end connections and curve connectors.
## Connector Creation
Several static methods exist to create connectors. They require a reference to a planar face that will host the connector and, optionally, an edge of that planar face that defines the connector location.
These connectors are created in the family document, and their data is exposed on elements in a project via FamilyInstance.MEPModel.ConnectorManager.
* CreateCableTrayConnector
* CreateConduitConnector
* CreateDuctConnector
* CreateElectricalConnector
* CreatePipeConnector
Connectors on MEPCurve and FabricationPart are created by default when a new MEPCurve element is created and cannot be rehosted. Their data are accessed via MEPCurve.ConnectorManager or FabricationPart.ConnectorManager.
## Connector Modification
The `ConnectorElement.ChangeHostReference` method changes the connector host reference by allowing you to specify a reference to a different plane reference, and optionally to an edge. If only a plane reference is specified, the connector position will be able to subsequently move along the plane. If an edge is also specified, then the connector location is fixed in place.
**Figure 167: Physical connectors**
The following sample shows how to determine the owner of a connector, and what, if anything it attaches to, along with the connection type.
**Code Region 30-5: Determine what is attached to a connector**
---
public void GetElementAtConnector(Autodesk.Revit.DB.Connector connector)
{
MEPSystem mepSystem = connector.MEPSystem;
if (null != mepSystem)
{
string message = "Connector is owned by: " + connector.Owner.Name;
if (connector.IsConnected == true)
{
ConnectorSet connectorSet = connector.AllRefs;
ConnectorSetIterator csi = connectorSet.ForwardIterator();
while (csi.MoveNext())
{
Connector connected = csi.Current as Connector;
if (null != connected)
{
// look for physical connections
if (connected.ConnectorType == ConnectorType.End ||
connected.ConnectorType == ConnectorType.Curve ||
connected.ConnectorType == ConnectorType.Physical)
{
message += "\nConnector is connected to: " + connected.Owner.Name;
message += "\nConnection type is: " + connected.ConnectorType;
}
}
}
}
else
{
message += "\nConnector is not connected to anything.";
}
TaskDialog.Show("Revit", message);
}
}
The following dialog box is the result of running this code example on the connector from a piece of plumbing equipment.
**Figure 168: Connector Information**
**Parent page:** [MEP Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_html.html)

View File

@@ -0,0 +1,111 @@
# Electrical Analysis for Preliminary Design
# Electrical Analysis for Preliminary Design
Electrical engineers can estimate the building load throughout the distribution system without placing physical electrical families in the model, enabling conceptual analysis and planning.
## Overview
* Create area-based load boundary lines based on one or more lines and a specified level using `CurveElement.CreateAreaBasedLoadBoundaryLine` or `CurveElement.CreateAreaBasedLoadBoundaryLines`.
* For a given level and phase, check if there are any empty plan circuits that do not have electrical load areas with `ElectricalLoadAreaData.HasCircuitsWithoutElectricalLoadAreas`.
* If this returns true, create electrical load areas on all the empty plan circuits of the given level using `ElectricalLoadAreaData.CreateElectricalLoadAreas`.
* Because electrical load areas are special kind of `SpatialElement`, you can find all existing and any newly created ones using a `FilteredElementCollector`.
* Finally, create Area Based Loads by creating a Zone with `Zone.CreateAreaBasedLoad` and a `AreaBasedLoadData` then add the Electrical Load Area to the AreaBasedLoadData. Note that one Load Area can be included by more than one Area Based Loads - for example Area Based Load 1 can include Load Area X and Area Based Load 2 can also include Load Area X.
Connections between an `AreaBasedLoadData` object and other nodes can be managed with the methods:
* `ConnectToUpstreamNode(ElementId upstreamNodeId)`
* `DisconnectFromUpstreamNode()`
* `CanDisconnectFromUpstreamNode()`
* `CanConnectToUpstreamNode(ElementId upstreamNodeId)`
* `GetUpstreamNodeId()`
public void CreateAreaBasedElectricalLoads(Document doc, List<Curve> lines, Level level, Phase phase)
{
IEnumerable<SpatialElement> electricalLoadAreas;
using (Transaction transaction = new Transaction(doc, "Create Electrical Load Areas"))
{
transaction.Start();
//Create Area Based Load Boundary Lines.
CurveElement.CreateAreaBasedLoadBoundaryLines(doc, lines, level.Id);
if (ElectricalLoadAreaData.HasCircuitsWithoutElectricalLoadAreas(doc, level.Id, phase.Id))
{
//Create Electrical Load Areas.
ISet<ElementId> createdElectricalLoadAreaIds = ElectricalLoadAreaData.CreateElectricalLoadAreas(doc, level.Id, phase.Id);
}
electricalLoadAreas = new FilteredElementCollector(doc)
.OfClass(typeof(SpatialElement))
.WherePasses(new ElementLevelFilter(level.Id))
.WherePasses(new ElementPhaseStatusFilter(phase.Id, ElementOnPhaseStatus.None))
.Cast<SpatialElement>()
.Where(x => x.SpatialElementType == SpatialElementType.ElectricalLoadArea);
transaction.Commit();
}
using (Transaction transaction = new Transaction(doc, "Create Area Based Loads"))
{
transaction.Start();
//Create Area Based Load on each Load Area.
foreach (SpatialElement electricalLoadArea in electricalLoadAreas)
{
Zone areaBasedLoad = Zone.CreateAreaBasedLoad(doc, "AreaBasedLoad1", level.Id, phase.Id);
AreaBasedLoadData areaBasedLoadData = areaBasedLoad.GetDomainData() as AreaBasedLoadData;
areaBasedLoadData.AddElectricalLoadArea(electricalLoadArea.Id);
areaBasedLoadData.Voltage = UnitUtils.ConvertToInternalUnits(100, UnitTypeId.Volts);
}
transaction.Commit();
}
}
## Defining Electrical Analytical Loads
When defining loads, you can define area-based loads and point-based equipment loads.
### Area-based loads
Area-based loads let you define a closed region and indicate power requirements based on power/area density. For example, lighting in 2nd floor office spaces is 2w/ft2, while lighting in conference rooms is 3w/ft2, and general power across the entire floor is 3.5 w/ft2.
An Area Based Load is composed by one or more Electrical Load Areas. One Electrical Load Area can be included by more than one Area Based Loads. Geometrically, an Electrical Load Area is a minimized enclosed region surrounded by area-based load boundary lines. In the Revit API, Electrical Load Area elements are represented as SpatialElement objects with their property SpatialElementType = ElectricalLoadArea. The SpatialElement.GetSpatialElementDomainData() method gets the SpatialElementDomainData for a given spatial element, and then down-casts it as ElectricalLoadAreaData to GetAreaBasedLoadIds() of it.
The Electrical Load Area elements can be created by `CreateElectricalLoadAreas()`. This function creates electrical load areas on all the empty plan circuits of the given level.
### Point-based equipment loads
Equipment loads allow you to capture load requirements associated with major equipment components, such as elevators, chillers, or any other component beyond the general power density-based loads.
Equipment load elements can be created by ElectricalAnalyticalNode.Create() with the parameter ElectricalAnalyticalNodeType as EquipmentLoad. The `AnalyticalEquipmentLoadData` class provides access to this data.
When defining the distribution system, you can create Electrical Analytical Equipment (busses, transformers, transfer switches, and power sources), and interconnect these components. You can then associate area and equipment loads with the distribution system components to sum load throughout the distribution system.
The `AnalyticalEquipmentLoadData.LoadSet` property returns the element id of the electrical analytical load set of the analytical equipment load. This `ElectricalAnalyticalLoadSet` has members:
* GetLoadIds() to get the equipment load ids in the LoadSet
* QuantityOnStandBy to get or set the number of Equipment Loads that are not operational at any time
* TotalQuantity to get the total count of the equipment loads in the LoadSet
## Electrical Analytical Nodes
The ElectricalAnalyticalNode class represents an electrical analytical node under the Analytical Power Distribution in the System Browser. The type of this node can be any of the value of the ElectricalAnalyticalNodeType enum:
* Power Source
* Bus
* Transformer
* Transfer Switch
* Equipment Load
The static method ElectricalAnalyticalNode.Create is used to create these nodes. `GetAllDownstreamLoadIds()` gets all the descendant Electrical Analytical Load ids of the node.
**Parent page:** [MEP Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_html.html)

View File

@@ -0,0 +1,65 @@
# Electrical Settings
# Electrical Settings
Some of the settings available on the Manage tab under MEP Settings - Electrical Settings are also available through the Revit API.
## Electrical Settings
The ElectricalSetting class provides access to different electrical settings, such as fitting angles, wire types, and voltage types. There is one ElectricalSetting object per document and it is accessible through the static method ElectricalSetting.GetElectricalSettings().
### General Settings
The following general settings are available as properties of the ElectricalSetting class:
* CircuitSequence - Accesses the circuit sequence numbering schema
* CircuitNamePhaseA - Accesses the circuit naming by phase (Phase A Label).
* CircuitNamePhaseB - Accesses the circuit naming by phase (Phase B Label).
* CircuitNamePhaseC - Accesses the circuit naming by phase (Phase C Label).
### Fitting Angles
Fitting angle settings for cable trays and conduits are available from the following methods of the ElectricalSetting class:
* GetSpecificFittingAngles()
* GetSpecificFittingAngleStatus()
* SetSpecificFittingAngleStatus()
**Fitting Angles**
### Other Electrical Settings
Properties of the ElectricalSetting class provide access to:
* Distribution System Types
* Voltage Types
* Wire Conduit Types
* Wire Material Types
* Wire Types
Methods also are available to add or remove from the project distribution system types, voltate types, wire material types and wire types.
# Circuit Naming
`Autodesk.Revit.DB.Electrical.CircuitNamingScheme` represents a scheme used for electrical circuit naming. Significant methods on this class allow schemes to be created and allowing access to the list of combined parameters associated with the scheme:
* CircuitNamingScheme.Create()
* CircuitNamingScheme.GetCombinedParameters()
* CircuitNamingScheme.SetCombinedParameters()
`Autodesk.Revit.DB.Electrical.CircuitNamingSchemeSettings` represents the circuit naming scheme settings object in a project document. Members on this class include:
* CircuitNamingSchemeSettings.GetCircuitNamingSchemeSettings()
* CircuitNamingSchemeSettings.CircuitNamingSchemeId
**Parent page:** [MEP Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_html.html)

View File

@@ -0,0 +1,73 @@
# Family Creation
# Family Creation
When creating mechanical equipment in a Revit family document, you will need to add connectors to allow the equipment to connect to a system. Duct, electrical and pipe connectors can all be added similarly, using a reference plane where the connector will be placed and a system type for the connector.
The overloaded static methods provided by the ConnectorElement class are:
* CreateCableTrayConnector
* CreateConduitConnector
* CreateDuctConnector
* CreateElectricalConnector
* CreatePipeConnector
Each of the methods above has a second overload that takes an additional Edge parameter that allows creation of connector elements centered on internal loops of a given face. The following code demonstrates how to add two pipe connectors to faces on an extrusion and set some properties on them.
**Code Region 30-6: Adding a pipe connector**
---
public void CreatePipeConnectors(UIDocument uiDocument, Extrusion extrusion)
{
// get the faces of the extrusion
Options geoOptions = uiDocument.Document.Application.Create.NewGeometryOptions();
geoOptions.View = uiDocument.Document.ActiveView;
geoOptions.ComputeReferences = true;
List<PlanarFace> planarFaces = new List<PlanarFace>();
Autodesk.Revit.DB.GeometryElement geoElement = extrusion.get_Geometry(geoOptions);
foreach (GeometryObject geoObject in geoElement)
{
Solid geoSolid = geoObject as Solid;
if (null != geoSolid)
{
foreach (Face geoFace in geoSolid.Faces)
{
if (geoFace is PlanarFace)
{
planarFaces.Add(geoFace as PlanarFace);
}
}
}
}
if (planarFaces.Count > 1)
{
// Create the Supply Hydronic pipe connector
ConnectorElement connSupply = ConnectorElement.CreatePipeConnector(uiDocument.Document,
PipeSystemType.SupplyHydronic,
planarFaces[0].Reference);
Parameter param = connSupply.GetParameter(ParameterTypeId.ConnectorRadius);
param.Set(1.0); // 1' radius
param = connSupply.GetParameter(ParameterTypeId.RbsPipeFlowDirectionParam);
param.Set(2);
// Create the Return Hydronic pipe connector
ConnectorElement connReturn = ConnectorElement.CreatePipeConnector(uiDocument.Document,
PipeSystemType.ReturnHydronic,
planarFaces[1].Reference);
param = connReturn.GetParameter(ParameterTypeId.ConnectorRadius);
param.Set(0.5); // 6" radius
param = connReturn.GetParameter(ParameterTypeId.RbsPipeFlowDirectionParam);
param.Set(1);
}
}
The following illustrates the result of running this example using in a new family document created using a Mechanical Equipment template and passing in an extrusion 2'×2'×1'. Note that the connectors are placed at the centroid of the planar faces.
**Figure 169: Two connectors created on an extrusion**
**Parent page:** [MEP Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_html.html)

View File

@@ -0,0 +1,17 @@
# MEP Analytical Model
# MEP Analytical Model
The MEP analytical model facilitates network-based flow calculation for piping, fabrication piping, and duct work.
## MEPAnalyticalModelCell
By attaching the MEPAnalyticalModelCell to the applicable elements such as Pipe, Duct, FamilyInstance, and FabricationPart, these elements provide a generic data structure for MEP flow and pressure drop analysis, as shown in the diagram below.
## Iterating the flow network
While each element is assigned to one MEPAnalyticalModel data cell, multiple elements are connected together to form a network. The MEPNetworkIterator is used to visit each segment on the network.
For more information, see the SDK sample NetworkPressureLossReport.
**Parent page:** [MEP Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_html.html)

View File

@@ -0,0 +1,189 @@
# Create Pipes and Ducts
# Create Pipes and Ducts
There are 3 ways to create new ducts, flex ducts, pipes and flex pipes. They can be created between two points, between two connectors, or between a point and a connector.
The following code creates a new pipe between two points using the Pipe.Create() method. New flex pipes, ducts and flex ducts can all be created similarly.
**Code Region: Creating a new Pipe using static Create() method**
---
public Pipe CreateNewPipe(Document document, ElementId systemTypeId, ElementId levelId)
{
// find a pipe type
FilteredElementCollector collector = new FilteredElementCollector(document);
collector.OfClass(typeof(PipeType));
PipeType pipeType = collector.FirstElement() as PipeType;
Pipe pipe = null;
if (null != pipeType)
{
// create pipe between 2 points
XYZ p1 = new XYZ(0, 0, 0);
XYZ p2 = new XYZ(10, 0, 0);
pipe = Pipe.Create(document, systemTypeId, pipeType.Id, levelId, p1, p2);
}
return pipe;
}
The code region below demonstrates how to create a FlexPipe using the static FlexPipe.Create() method. Pipes, ducts and flex ducts can all be created between two points similarly.
**Code Region: Creating a new FlexPipe using static Create() method**
---
public FlexPipe CreateFlexPipe(Document document, Level level)
{
// find a pipe type
FilteredElementCollector collector = new FilteredElementCollector(document);
collector.OfClass(typeof(FlexPipeType));
ElementId pipeTypeId = collector.FirstElementId();
// find a pipe system type
FilteredElementCollector sysCollector = new FilteredElementCollector(document);
sysCollector.OfClass(typeof(PipingSystemType));
ElementId pipeSysTypeId = sysCollector.FirstElementId();
FlexPipe pipe = null;
if (pipeTypeId != ElementId.InvalidElementId && pipeSysTypeId != ElementId.InvalidElementId)
{
// create flex pipe with 3 points
List<XYZ> points = new List<XYZ>();
points.Add(new XYZ(0, 0, 0));
points.Add(new XYZ(10, 10, 0));
points.Add(new XYZ(10, 0, 0));
pipe = FlexPipe.Create(document, pipeSysTypeId, pipeTypeId, level.Id, points);
}
return pipe;
}
After creating a pipe, you might want to change the diameter. The Diameter property of Pipe is read-only. To change the diameter, get the RBS_PIPE_DIAMETER_PARAM built-in parameter.
**Code Region: Changing pipe diameter**
---
public void ChangePipeSize(Pipe pipe)
{
Parameter parameter = pipe.GetParameter(ParameterTypeId.RbsPipeDiameterParam);
string message = "Pipe diameter: " + parameter.AsValueString();
parameter.Set(0.5); // set to 6"
// Regenerate the docucment before trying to read a parameter that has been edited
pipe.Document.Regenerate();
message += "\nPipe diameter after set: " + parameter.AsValueString();
TaskDialog.Show("Revit", message);
}
Another common way to create a new duct or pipe is between two existing connectors, as the following example demonstrates. In this example, it is assumed that 2 elements with connectors have been selected in Revit, one being a piece of mechanical equipment and the other a duct fitting with a connector that lines up with the SupplyAir connector on the equipment.
**Code Region: Adding a duct between two connectors**
---
public Duct CreateDuctBetweenConnectors(UIDocument uiDocument)
{
// prior to running this example
// select some mechanical equipment with a supply air connector
// and an elbow duct fitting with a connector in line with that connector
ElementId levelId = ElementId.InvalidElementId;
Connector connector1 = null, connector2 = null;
ConnectorSetIterator csi = null;
ICollection<ElementId> selectedIds = uiDocument.Selection.GetElementIds();
Document document = uiDocument.Document;
// First find the selected equipment and get the correct connector
foreach (ElementId id in selectedIds)
{
Element e = document.GetElement(id);
if (e is FamilyInstance)
{
FamilyInstance fi = e as FamilyInstance;
Family family = fi.Symbol.Family;
if (family.FamilyCategory.Name == "Mechanical Equipment")
{
csi = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator();
while (csi.MoveNext())
{
Connector conn = csi.Current as Connector;
if (conn.Direction == FlowDirectionType.Out &&
conn.DuctSystemType == DuctSystemType.SupplyAir)
{
connector1 = conn;
levelId = family.LevelId;
break;
}
}
}
}
}
// next find the second selected item to connect to
foreach (ElementId id in selectedIds)
{
Element e = document.GetElement(id);
if (e is FamilyInstance)
{
FamilyInstance fi = e as FamilyInstance;
Family family = fi.Symbol.Family;
if (family.FamilyCategory.Name != "Mechanical Equipment")
{
csi = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator();
while (csi.MoveNext())
{
if (null == connector2)
{
Connector conn = csi.Current as Connector;
// make sure to choose the connector in line with the first connector
if (Math.Abs(conn.Origin.Y - connector1.Origin.Y) < 0.001)
{
connector2 = conn;
break;
}
}
}
}
}
}
Duct duct = null;
if (null != connector1 && null != connector2 && levelId != ElementId.InvalidElementId)
{
// find a duct type
FilteredElementCollector collector = new FilteredElementCollector(uiDocument.Document);
collector.OfClass(typeof(DuctType));
// Use Linq query to make sure it is one of the rectangular duct types
var query = from element in collector
where element.Name.Contains("Mitered Elbows") == true
select element;
// use extension methods to get first duct type
DuctType ductType = collector.Cast<DuctType>().First<DuctType>();
if (null != ductType)
{
duct = Duct.Create(document, ductType.Id, levelId, connector1, connector2);
}
}
return duct;
}
## Lining and Insulation
Pipe and duct insulation and lining can be added as separate objects associated with ducts and pipes. The ids of insulation elements associated with a duct or pipe can be retrieved using the static method InsulationLiningBase.GetInsulationIds() while the ids of lining elements can be retreived using the static method InsulationLiningBase.GetLiningIds().
To create new insulations associated with a given duct, pipe, fitting, accessory, or content use the corresponding static method: DuctInsulation.Create() or PipeInsulation.Create(). DuctLining.Create() can be used to create a new instance of a lining applied to the inside of a given duct, fitting or accessory.
**Parent page:** [MEP Element Creation](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Element_Creation_html.html)

View File

@@ -0,0 +1,74 @@
# Creating Systems
# Creating Systems
Create electrical, mechanical and piping systems.
MechanicalSystem and PipingSystem have static overloaded Create() methods to create new mechanical or piping systems. This is the preferred method for creating new MEP Systems. The simplest Create() overload for both classes creates a new system in a given document with a given type Id (which should be the Id for a DuctSystemType for a MechanicalSystem or the Id of a PipeSystemType for a PipingSystem. Both classes have a second Create() overload that also takes a name for the system. Once created, elements can be added to the system using the MEPSystem.Add() method.
MechanicalSystem and PipingSystem can also be created from the Creation.Document class using NewMechanicalSystem() and NewPipingSystem(). NewPipingSystem() and NewMechanicalSystem() both take a Connector that is the base equipment connector, such as a hot water heater for a piping system, or a fan for a mechanical system. They also take a ConnectorSet of connectors that will be added to the system, such as faucets on sinks in a piping system. The last piece of information required to create a new system is either a PipeSystemType for NewPipingSystem() or a DuctSystemType for NewMechanicalSystem().
Electrical systems can be created using the ElectricalSystem.Create method, which has two overloads. One creates a new ElectricalSystem element from an unused Connector. The other creates a new ElectricalSystem element from a set of electrical components. Both overloads require an ElectricalSystemType.
In the following sample, a new SupplyAir duct system is created from a selected piece of mechanical equipment (such as a fan) and all selected Air Terminals.
**Code Region: Creating a new mechanical system**
---
public void CreateSystem(UIDocument uiDocument)
{
// create a connector set for new mechanical system
ConnectorSet connectorSet = new ConnectorSet();
// Base equipment connector
Connector baseConnector = null;
// Select a Parallel Fan Powered VAV and some Supply Diffusers
// prior to running this example
ConnectorSetIterator csi = null;
ICollection<ElementId> selectedIds = uiDocument.Selection.GetElementIds();
Document document = uiDocument.Document;
foreach (ElementId id in selectedIds)
{
Element e = document.GetElement(id);
if (e is FamilyInstance)
{
FamilyInstance fi = e as FamilyInstance;
Family family = fi.Symbol.Family;
// Assume the selected Mechanical Equipment is the base equipment for new system
if (family.FamilyCategory.Name == "Mechanical Equipment")
{
//Find the "Out" and "SupplyAir" connector on the base equipment
if (null != fi.MEPModel)
{
csi = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator();
while (csi.MoveNext())
{
Connector conn = csi.Current as Connector;
if (conn.Direction == FlowDirectionType.Out && conn.DuctSystemType == DuctSystemType.SupplyAir)
{
baseConnector = conn;
break;
}
}
}
}
else if (family.FamilyCategory.Name == "Air Terminals")
{
// add selected Air Terminals to connector set for new mechanical system
csi = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator();
csi.MoveNext();
connectorSet.Insert(csi.Current as Connector);
}
}
}
MechanicalSystem mechanicalSys = null;
if (null != baseConnector && connectorSet.Size > 0)
{
// create a new SupplyAir mechanical system
mechanicalSys = uiDocument.Document.Create.NewMechanicalSystem(baseConnector, connectorSet, DuctSystemType.SupplyAir);
}
}
**Parent page:** [MEP Element Creation](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Element_Creation_html.html)

View File

@@ -0,0 +1,59 @@
# Creating Wires
# Creating Wires
New electrical wires can be created using the Revit API.
The static Wire.Create() allows for new wires to be created in the document. The Create() method requires the id of the view in which the newly created wire will be visible. It must be the id of a floor plan or reflected ceiling plan view. The WiringType for the wire can be either Arc, for wiring that is concealed within walls, ceilings, or floors, or Chamfer, for wiring that is exposed.
The location of the wire is specified by a list of XYZ points defining the vertices of the wire, and optionally a start and/or end connector. The endpoint connectors can be null, however, if the start connector is specified, the connector's origin will be added to the wire's vertices as the start point. Likewise, if the end connector is specified, the connector's origin will be added to the wire's vertices as the end point. The static method Wire.AreVertexPointsValid() will check a list of XYZ points and start and end connectors to ensure they are suitable for a wire.
The shape of the wire is determined by it's wiring type and the total number of points supplied via the vertex points and endpoint connectors. If the wiring type is WiringType.Arc:
* If there are 2 total points supplied, the wire is a straight-line wire.
* If there are 3 total points supplied, the wire is a circular arc wire.
* If there are 4 or more points, the wire is a spline wire.
If the wiring type is WiringType.Chamfer, a polyline wire will be created connecting all the points.
The following example creates a new straight-line wire in the active view with no connectors specified.
**Code Region: Creating a new wire**
---
public Wire CreateWire(Document document)
{
Wire wire = null;
FilteredElementCollector collector = new FilteredElementCollector(document);
IList<Element> wireTypes = collector.OfCategory(BuiltInCategory.OST_Wire).WhereElementIsElementType().ToElements();
WireType wireType = wireTypes.First() as WireType;
if (wireType != null)
{
IList<XYZ> wireVertices = new List<XYZ>();
wireVertices.Add(new XYZ(0, 0, 0));
wireVertices.Add(new XYZ(2, 0, 0));
wire = Wire.Create(document, wireType.Id, document.ActiveView.Id, WiringType.Arc, wireVertices, null, null);
}
return wire;
}
### Connectors
To connect a wire to elements after creation, call Wire.ConnectTo(), passing in a start and end connector. If the wire is already connected when this method is used, the old connection will be disconnected and the wire will be connected to the new target.
### Vertices
Once a wire is created, vertices can be retrieved using the Wire.GetVertex() method. This method takes an index of the requested vertex which should be between 0 and Wire.NumberOfVertices (which includes the start and end points of the wire).
Use Wire.AppendVertex() to add a vertex to the end of the list, or Wire.InsertVertex() to add a vertex at a specific point in the list. The Wire.IsVertexPointValid() method checks if the given vertex point can be added to this wire. IsVertexPointValid() will return false if the point cannot be added because there is already a vertex at this position on the view plane (within tolerance). Note that a vertex cannot be inserted before the start vertex if the start vertex already connects to an element. Similarly, a vertex cannot be appended to the end of the list if the end point is already connected to an element.
Wire.RemoveVertex() will remove a vertex from the list. If the wire vertex is already connected to an element, this method will fail to remove the vertex. In order to remove this vertex, it should be disconnected first, then removed, and then reconnected (if required).
**Parent page:** [MEP Element Creation](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Element_Creation_html.html)

View File

@@ -0,0 +1,13 @@
# Placeholders
# Placeholders
### Placeholder ducts and pipes
The Revit API provides the ability to put placeholder elements into a system when the exact design of the layout is not yet know. Using placeholder ducts and pipes can allow for a well-connected system while the design is still unknown, and then which can then be elaborated in the final design at a later stage.
The two static methods Duct.CreatePlaceholder() and Pipe.CreatePlaceholder() create placeholder elements. The IsPlaceholder property of Duct and Pipe indicates whether they are a placeholder element or not.
When ready to create actual ducts and pipes from the placeholders, use the MechanicalUtils.ConvertDuctPlaceholders() and PlumbingUtils.ConvertPipePlaceholders() methods to convert a set of placeholder elements to ducts and pipes. Once conversion succeeds, the placeholder elements are deleted. The new duct, pipe and fitting elements are created and connections are established.
**Parent page:** [MEP Element Creation](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Element_Creation_html.html)

View File

@@ -0,0 +1,42 @@
# MEP Element Creation
# MEP Element Creation
MEP Elements can be created using the Revit API.
Many elements related to duct, pipe and electrical systems can be created using the following methods available in the Autodesk.Revit.Creation.Document class:
* NewFlexDuct
* NewFlexPipe
* NewMechanicalSystem
* NewPipingSystem
* NewCrossFitting
* NewElbowFitting
* NewTakeoffFitting
* NewTeeFitting
* NewTransitionFitting
* NewUnionFitting
Other MEP elements, such as pipes, can only be created using the static Create() method of its corresponding class. Some MEP elements, such as ducts, can be created by a static method of the corresponding class (i.e. Duct) or by a method of the Autodesk.Revit.Creation.Document class. For these elements, the static Create() method is preferred.
* Duct
* FlexDuct
* Pipe
* FlexPipe
* PipingSystem
* Wire
**Pages in this section**
* [Create Pipes and Ducts](MEP_Element_Creation/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Element_Creation_Create_Pipes_and_Ducts_html.html)
* [Creating Wires](MEP_Element_Creation/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Element_Creation_Creating_Wires_html.html)
* [Placeholders](MEP_Element_Creation/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Element_Creation_Placeholders_html.html)
* [Creating Systems](MEP_Element_Creation/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Element_Creation_Creating_Systems_html.html)
**Parent page:** [MEP Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_html.html)

View File

@@ -0,0 +1,131 @@
# MEP Fabrication Detailing
# MEP Fabrication Detailing
Several Revit API classes work together to provide the ability to add fabrication components to a Revit document.
## Fabrication detailing classes
Before you can place fabrication parts in an MEP model, you must specify a fabrication configuration and load fabrication services into the model. There are a number of classes in the Revit API to facilitate this process including:
* **FabricationConfiguration** \- Contains information about the fabrication configuration settings used by the project.
* **FabricationConfigurationInfo** \- Contains information about the properties of a FabricationConfiguration.
* **ConfigurationReloadInfo** \- Contains results from reloading a FabricationConfiguration.
* **ConnectionValidationInfo** \- Contains connection-related warnings generated by reloading a FabricationConfiguration.
* **FabricationService** \- Part of the fabrication configuration and defines what FabricationServiceButtons can be used.
* **FabricationServiceButton** \- Defines what items to use for different size-based conditions.
* **FabricationPart** \- Represents a fabrication component in Revit.
* **FabricationPartType** \- Defines the type of a FabricationPart.
* **FabricationRodInfo** \- Gives support rod information for a FabricationPart.
* **FabricationHostedInfo** \- Contains hosting information for a FabricationPart and provides the ability to disconnect from the host.
* **FabricationConnectorInfo** \- Contains information about the connectors of a FabricationPart.
* **FabricationUtils** \- General utility methods in the Autodesk Revit product for fabrication.
* **FabricationDimensionDefinition** \- Contains information about a fabrication dimension.
The primary classes involved in MEP Fabrication are covered in more detail below. Sample code can be found in the Revit SDK in the FabricationPartLayout sample.
## Fabrication configuration
Using the FabricationConfiguration class, users can get and set the fabrication configuration settings for the document. They can also load and unload services, reload the fabrication configuration, get loaded services, get fabrication specifications, get material and insulation information from the configuration, and get connector information.
There is only one fabrication configuration for the document and you can get it using the static FabricationConfiguration.GetFabricationConfiguration() method. To change the configuration, call the overloaded SetConfiguration() method, passing in a FabricationConfigurationInfo object which contains the information about the FabricationConfiguration. One overload of the SetConfiguration() method will set the configuration with the global profile, and one takes a profile name and sets the configuration with that specific profile. (The FabricationConfiguration.GetProfile() method returns the name of the current profile in use and the FabricationConfigurationInfo.GetProfiles() method returns all profile names associated with the configuration.)
The ReloadConfiguration() method reloads the fabrication configuration from its source fabrication configuration. This must be done prior to loading fabrication services.
Use the GetAllLoadedServices() method to get all loaded services or GetAllUsedServices() to get only used fabrication services. A service is in use if any fabrication part in the service is created by the user. Both methods return a list of FabricationService objects.
LoadServices() and UnloadServices() can be used to load and unload a list of fabrication services, respectively.
The FabricationConfiguration class also has methods to get configuration data abbreviations. The GetMaterialAbbreviation() returns the abbreviation of the material or the insulation or the double wall material. GetSpecificationAbbreviation() returns the specification abbreviation for the given specification and GetInsulationSpecificationAbbreviation() will return the abbreviation for the given insulation specification.
## Fabrication services
Fabrication services are part of the fabrication configuration and define what fabrication service buttons can be used. The PaletteCount property returns the number of palettes in the service. Using the index of the palettes, you can call GetPaletteName() to get the name of the palette. The method GetButtonCount() will return the number of buttons in a specified palette and the actual buttons can be retrieved by calling GetButton() with a specified palette index and button index.
### Fabrication service button
The FabricationServiceButton class contains information about a fabrication button. A fabrication service button defines an item that can be used to define a FabricationPart, possibly subject to a list of size-based specific conditions. Fabrication service buttons are part of a fabrication service.
## Fabrication parts
Using the FabricationPart class, users can create, place, move and align fabrication parts in a Revit model. Users can also get or set the dimensions of the fabrication part, and get the fabrication hosted information and support rod information.
The overloaded static FabricationPart.Create() method creates a new fabrication part based on a fabrication service button. The overloaded static CreateHanger() method creates a hanger on another fabrication part. The static AlignPartByConnectors() method will move and align a fabrication part by one of its connectors to align with another connector.
FabricationParts can also be created from design elements using the DesignToFabricationConverter class. The Convert() method will convert a set of MEP design elements into fabrication parts. Successfully created FabricationParts can be obtained using the GetConvertedFabricationParts() methods. If the Convert() method indicates a partial failure, the GetPartialConvertFailureResults() method will return a list of possible failures. For partial failure types (e.g., InvalidConnections) there is a corresponding method of the DesignToFabricationConverter class to retrieve a list of the ElementIds of the FabricationParts with that error type (e.g., GetConvertedFabricationPartsWithInvalidConnections()).
Methods also exist to get and set the value of the fabrication dimension, to get the host element information and to get the fabrication rod information. `FabricationPart.GetInsulationLiningGeometry()` returns any insulation or liner geometry for a fabrication part. If there is no insulation or liner applied the return value will be null.
### Connections and position
FabricationPart has a number of methods to attach to connectors or to change the position of the FabricationPart. The static StretchAndFit() method supports the operation to stretch the fabrication part from the specified connector and fit to the target routing end. The routing end is indicated as a FabricationPartRouteEnd object, which can be obtained from the static FabricationPartRouteEnd.CreateFromConnector() or FabricationPartRouteEnd.CreateFromCenterline() methods. If the StretchAndFit() method fails, it will return a FabricationPartFitResult enumeration that provides more details on the failure.
Other methods to modify the FabricationPart include Reposition(), RotateConnectedPartByConnector() and PlaceAsTap().
The methods:
* FabricationPart.GetAllFabricationBodyConnectorDefinitions()
* FabricationPart.GetAllFabricationDoubleWallConnectorDefinitions()
return all identifiers for fabrication connector definitions that are compatible with and valid to be assigned to the input connector, for the body and double wall connections respectively.
### Product lists
Some FabricationPart elements, such as purchased duct and pipe fittings, have a "product list". The product list entries represent a catalog of available sizes for the selected part. The ProductListEntry property specifies the product list entry of the FabricationPart. If the IsProductList() method returns false, the ProductListEntry will be -1.
To get the list of product entries for the FabricationPart, use the GetProductListEntryCount() and GetProductListEntryName() methods. Prior to changing the ProductListEntry for the FabricationPart, call IsProductListEntryCompatibleSize() to check to see if this part can be changed to the specified product list entry without altering any connected dimensions.
### Exporting fabrication job files
FabricationPart.SaveAsFabricationJob() writes a fabrication job to disk in the MAJ file format. The exported file will contain the fabrication parts included in the input. It takes an options class, FabricationSaveJobOptions, allowing for the possibility of including holes in fabrication parts where branches meet the main straight.
### Load and unload of one-off fabrication parts from loose item files
Autodesk.Revit.DB.FabricationItemFile contains information about one-off items that can be loaded into a fabrication configuration.
Autodesk.Revit.DB.FabricationItemFolder may contain nested FabricationItemFolders and a list of FabricationItemFiles.
The members:
* FabricationConfiguration.LoadItemFiles()
* FabricationConfiguration.UnloadItemFiles()
* FabricationConfiguration.GetAllLoadedItemFiles()
* FabricationConfiguration.GetAllUsedItemFiles()
* FabricationConfiguration.CanUnloadItemFiles()
* FabricationConfiguration.AreItemFilesLoaded()
* FabricationConfiguration.GetItemFolders()
allow control over the loading and unloading of item files into the configuration.
FabricationPart.Create(Document, FabricationItemFile, ElementId) creates a FabricationPart from an item file.
### Version history of parts
Autodesk.Revit.DB.FabricationVersionInfo gives the information about differerent versions of fabrication data, including the reason why the data was changed.
FabricationPart.GetVersionHistory() returns a list of FabricationVersionInfo classes that describe the history of the changes made to the part. The most recent changes are first in the list.
### Part swap out information
Autodesk.Revit.DB.ReloadSwapOutInfo gives information about a part that was swapped out during reload.
The members:
* ConfigurationReloadInfo.OutOfDatePartCount
* ConfigurationReloadInfo.GetOutOfDatePartStatus()
identify the parts that had newer versions found during a reload and which Revit attempted to swap out.
### Centerline length
FabricationPart.CenterlineLength returns the length of the fabrication part's centerline.
**Parent page:** [MEP Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_html.html)

View File

@@ -0,0 +1,51 @@
# MEP Systems
# MEP Systems
MEPSystem is the base class for electrical, mechanical and piping systems in Revit MEP.
ElectricalSystem, MechanicalSystem and PipingSystem all derive from the MEPSystem class. The base class has some common functionality across system types, such as adding elements to the system or finding the base panel or equipment of the system. A few methods in the base class only apply to HVAC and plumbing systems, such as the DivideSystem() method which divides the physical networks in the system and creates a new system for each network.
The derived classes have additional methods and properties specific to the system type.
## MEPSection
The MEPSystem class has a SectionsCount property which returns the number of sections for the system. An MEPSection object can be obtained using either the GetSectionByIndex() method or the GetSectionByNumber() method. Although these methods are in the base MEPSystem class, the MEPSection class represents duct and pipe sections and is mainly for pressure loss calculation. It is a series of connected elements (segments - ducts or pipes, fittings, terminals and accessories) which can be obtained from the GetElementIds() method. All section members should have same flow analysis properties: Flow, Size, Velocity, Friction and Roughness.
The segment length, pressure drop and loss coefficient for each element in the section can vary, so methods are available in MEPSection to get these values given a specific element id for an element in the section. The coefficient for ducts is the loss coefficient. For pipes this is the same as the friction factor.
### MEP Duct/Pipe Pressure Loss Calculations
The members:
* MEPAnalyticalSegment.OverrideType
* MEPAnalyticalSegment.SetOverrideType()
* MEPAnalyticalSegment.GetLossCoefficientOverride()
* MEPAnalyticalSegment.SetLossCoefficientOverride()
* MEPAnalyticalSegmentGetPressureDropOverride()
* MEPAnalyticalSegment.SetPressureDropOverride() support override of the analytical segment coefficient and pressure drop. These allow application of specified loss coefficients or pressure drop values in the network-based flow calculation.
The methods:
* MEPAnalyticalSegment.GetFlowConvergenceCharacteristic()
* MEPAnalyticalSegment.GetFlowTransititionCharacteristic()
provide information about the flow characteristics for a given segment.
## Calculations
Some properties of MEP systems are calculated by Revit. Both MechanicalSystem and PipingSystem have an IsWellConnected property which indicates if the system is well connected or not. If the system is not well connected, parameters which need to be calculated are invalid.
For mechanical and piping systems, some values are calculated based on properties of the sections of the system. The MEPSystem.GetCriticalPathSectionNumbers() method returns a list of the critical path section numbers in order of the direction of flow and PressureLossOfCriticalPath() gets the total pressure loss of the sections in the critical path.
The GetFlow() and GetStaticPressure() methods available from MechanicalSystem and PipingSystem get the flow and static pressure for the system.
PipingSystem has additional calculated properties: GetFixtureUnits() and GetVolume().
Note: Due to the way these calculated properties are handled internally by Revit, they do not support dynamic model update. However, other system properties that are not calculated do support dynamic model update.
**Parent page:** [MEP Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_html.html)

View File

@@ -0,0 +1,105 @@
# Mechanical Settings
# Mechanical Settings
Many of the settings available on the Manage tab under MEP Settings - Mechanical Settings are also available through the Revit API.
### Pipe Settings
**Pipe Settings**
The PipeSettings class provides access to the settings shown above, such as Pipe Size Suffix and Pipe Connector Tolerance. There is one PipeSettings object per document and it is accessible through the static method PipeSettings.GetPipeSettings().
#### Fitting Angles
Fitting angle usage settings for pipes are available from the following property and methods of the PipeSettings class:
* PipeSettings.FittingAngleUsage
* PipeSettings.GetSpecificFittingAngles()
* PipeSettings.GetSpecificFittingAngleStatus()
* PipeSettings.SetSpecificFittingAngleStatus()
**Pipe Fitting Angles**
#### Segments and Sizes
The settings available in the UI under Pipe Settings - Segments and Sizes are available as well.
**Segments and Sizes**
This information is available through the Segment and MEPSize classes. A Segment represents a length of MEPCurve that contains a material and set of available sizes. The pipe sizes are represented by the MEPSize class. The Segments available can be found using a filter. The following example demonstrates how to get some of the information in the dialog above.
**Code Region: Traversing Pipe Sizes in Pipe Settings**
---
public void PipeSizes(Document document)
{
FilteredElementCollector collectorPipeType = new FilteredElementCollector(document);
collectorPipeType.OfClass(typeof(Segment));
IEnumerable<Segment> segments = collectorPipeType.ToElements().Cast<Segment>();
foreach (Segment segment in segments)
{
StringBuilder strPipeInfo = new StringBuilder();
strPipeInfo.AppendLine("Segment: " + segment.Name);
strPipeInfo.AppendLine("Roughness: " + segment.Roughness);
strPipeInfo.AppendLine("Pipe Sizes:");
double dLengthFac = 304.8; // used to convert stored units from ft to mm for display
foreach (MEPSize size in segment.GetSizes())
{
strPipeInfo.AppendLine(string.Format("Nominal: {0:F3}, ID: {1:F3}, OD: {2:F3}",
size.NominalDiameter * dLengthFac, size.InnerDiameter * dLengthFac, size.OuterDiameter * dLengthFac));
}
TaskDialog.Show("PipeSetting Data", strPipeInfo.ToString());
break;
}
}
**Output of previous example**
To add new sizes to the list, use the Segment.AddSize() method. Use Segment.RemoveSize() to remove a size by nominal diameter.
#### Slopes
The PipeSettings class also provides access to the slope values available in the UI under Pipe Settings - Slopes. Use GetPipeSlopes() to retreive a list of slope values. PipeSettings.SetPipeSlopes() provides the ability to set all the slope values at once, while PipeSettings.AddPipeSlope() adds a single pipe slope. Revit stores the slope value as a percentage (0-100).
**Pipe Slope Values**
### Duct Settings
**Duct Settings**
The DuctSettings class provides access to the settings shown above, such as Duct Fitting Annotation Size and Air Density. There is one DuctSettings object per document and it is accessible through the static method DuctSettings.GetDuctSettings().
#### Duct Fitting Angles
Fitting angle usage settings for ducts are available from the following property and methods of the DuctSettings class:
* DuctSettings.FittingAngleUsage
* DuctSettings.GetSpecificFittingAngles()
* DuctSettings.GetSpecificFittingAngleStatus()
* DuctSettings.SetSpecificFittingAngleStatus()
**Duct Fitting Angles**
### MEP Hidden Line Settings
The `MEPHiddenLineSettings` class represents the settings of the mechanical hidden line display (e.g., ducts and pipes). It can be obtained from the static method: `MEPHiddenLineSettings.GetMEPHiddenLineSettings(Document)` It offers the following properties:
* MEPHiddenLineSettings.DrawHiddenLine
* MEPHiddenLineSettings.LineStyle
* MEPHiddenLineSettings.InsideGap
* MEPHiddenLineSettings.OutsideGap
* MEPHiddenLineSettings.SingleLineGap
**Parent page:** [MEP Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_html.html)

View File

@@ -0,0 +1,62 @@
# Routing Preferences
# Routing Preferences
Routing prefences are accessible through the RoutingPreferenceManager class. An instance of this class is available from a property of the MEPCurveType class. Currently, only PipeType and DuctType support routing preferences.
The RoutingPreferenceManager manages all rules for selecting segment types and sizes as well as fitting types based on user selection criteria. The RoutingPreferenceRule class manages one segment or fitting preference and instances of this class can be added to the RoutingPreferenceManager. Each routing preference rule is grouped according to what type of routing item in manages. The type is represented by the RoutingPreferenceRuleGroupType and includes these options:
**Member name** | **Description**
---|---
Undefined | Undefined group type (default initial value)
Segments | Segment types (e.g., pipe stocks)
Elbows | Elbow types
Junctions | Junction types (e.g., takeoff, tee, wye, tap)
Crosses | Cross types
Transitions | Transition types (Note that the multi-shape transitions may have their own groups)
Unions | Union types that connect two segments together
MechanicalJoints | Mechanical joint types that connect fitting to fitting, segment to fitting, or segment to segment
TransitionsRectangularToRound | Multi-shape transition from the rectangular profile to the round profile
TransitionsRectangularToOval | Multi-shape transition from the rectangular profile to the oval profile
TransitionsOvalToRound | Multi-shape transition from the oval profile to the round profile
Each routing preference rule can have one or more selection criteria, represented by the RoutingCriterionBase class, and the derived type PrimarySizeCriterion. PrimarySizeCriterion selects fittings and segments based on minimum and maximum size constraints.
The RoutingConditions class holds a collection of RoutingCondition instances. The RoutingCondition class represents routing information that is used as input when determining if a routing criterion, such as minimum or maximum diameter, is met. The RoutingPreferencesManager.GetMEPPartId() method gets a fitting or segment id based on a RoutingPreferenceRuleGroupType and RoutingConditions.
The following example gets all the pipe types in the document, gets the routing preference manager for each one, then gets the sizes for each segment based on the rules in the routing preference manager.
**Code Region: Using Routing Preferences**
---
private List<double> GetAvailablePipeSegmentSizesFromDocument(Document document)
{
System.Collections.Generic.HashSet<double> sizes = new HashSet<double>();
FilteredElementCollector collectorPipeType = new FilteredElementCollector(document);
collectorPipeType.OfClass(typeof(PipeType));
IEnumerable<PipeType> pipeTypes = collectorPipeType.ToElements().Cast<PipeType>();
foreach (PipeType pipeType in pipeTypes)
{
RoutingPreferenceManager rpm = pipeType.RoutingPreferenceManager;
int segmentCount = rpm.GetNumberOfRules(RoutingPreferenceRuleGroupType.Segments);
for (int index = 0; index != segmentCount; ++index)
{
RoutingPreferenceRule segmentRule = rpm.GetRule(RoutingPreferenceRuleGroupType.Segments, index);
Segment segment = document.GetElement(segmentRule.MEPPartId) as Segment;
foreach (MEPSize size in segment.GetSizes())
{
sizes.Add(size.NominalDiameter); //Use a hash-set to remove duplicate sizes among Segments and PipeTypes.
}
}
}
List<double> sizesSorted = sizes.ToList();
sizesSorted.Sort();
return sizesSorted;
}
**Parent page:** [MEP Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_html.html)

View File

@@ -0,0 +1,31 @@
# MEP Engineering
# MEP Engineering
To support MEP engineering features of the Revit software, the API provides read and write access to HVAC and Piping data in a Revit model including:
* Traversing ducts, pipes, fittings, and connectors in a system
* Adding, removing, and changing ducts, pipes, and other equipment
* Getting and setting system properties
* Determining if the system is well-connected
* Access to Mechanical Settings
* Managing Routing Preferences
**Pages in this section**
* [MEP Element Creation](MEP_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Element_Creation_html.html)
* [MEP Analytical Model](MEP_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Analytical_Model_html.html)
* [MEP Systems](MEP_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Systems_html.html)
* [Connectors](MEP_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_Connectors_html.html)
* [MEP Fabrication Detailing](MEP_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_MEP_Fabrication_Detailing_html.html)
* [Family Creation](MEP_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_Family_Creation_html.html)
* [Mechanical Settings](MEP_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_Mechanical_Settings_html.html)
* [Electrical Analysis for Preliminary Design](MEP_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_Electrical_Analysis_for_Preliminary_Design_html.html)
* [Electrical Settings](MEP_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_Electrical_Settings_html.html)
* [Routing Preferences](MEP_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_MEP_Engineering_Routing_Preferences_html.html)
**Parent page:** [Discipline-Specific Functionality](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_html.html)

View File

@@ -0,0 +1,44 @@
# Toposolid
# Toposolid
The `Autodesk.Revit.DB.Toposolid` class is a solid element that has an assigned type and basic parameters and is eligible for Boolean operations such as cutting with Mass and In-place components. This class is closely related to floors and its points are editable using the same SlabShapeEditor interfaces. In addition, if the Toposolid has a Sketch boundary it can be accessed via the standard SketchEditScope capabilities.
## ToposolidType
`Autodesk.Revit.DB.ToposolidType` represents the type of a Toposolid in Autodesk Revit. This class inherits from HostObjAttributes and provides read/write access to the CompoundStructure of the ToposolidType. The `GetCountourSetting()` method provides access to the object that defines the elevations where contours will be drawn.
## Creation
`Toposolid.Create` can be used with one of three overloads that allow you to specify either or both:
* An array of planar curve loops that represent the profiles of the toposolid
* An array of points that used to construct the top face of the toposolid
`Toposolid.CreateFromTopographySurface` creates a toposolid element from a host TopographySurface and toposolid sub-divisions from its subregions.
## Linked Topography
* TopographyLinkType represents a site file brought into the current Revit model as a link.
* TopographyLinkType.Reload() reloads the TopographyLinkType from its current location.
## Subdivision creation
The method Toposolid.CreateSubDivision(Document, ElementId, IList) creates a Toposolid subdivision element with the input toposolid as its host, and a specified type to be used for the new subdivision.
## Stability for cutting and void operations
The static routines:
* Toposolid.IsCutVoidStabilityEnabled(Document)
* Toposolid.SetCutVoidStability(Document, bool)
access the option to use random shifting to find a successful Boolean operation for cutting and joining Toposolid objects.
**Parent page:** [Discipline-Specific Functionality](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_html.html)

View File

@@ -0,0 +1,41 @@
# Analysis Link
# Analysis Link
With Revit, a structural analytical model is automatically generated as you create the physical model. The analytical model is linked to structural analysis applications, and the physical model is automatically updated from the results through the Revit API. Some third-party software developers already provide bi-directional links to their structural analysis applications. These include the following:
* RFEM from Dlubal ([www.dlubal.com/en/download/rfem_revit_en.pdf](https://www.dlubal.com/en/download/rfem_revit_en.pdf))
* Advance Design, VisualDesign, Arche, Effel and SuperSTRESS from GRAITEC ([www.graitec.com/En/revit.asp](http://www.graitec.com/En/revit.asp))
* Scia Engineer from Nemetschek ([www.scia.net/en/software/product-selection/scia-engineer](https://www.scia.net/en/software/product-selection/scia-engineer))
* GSA from Oasys Software (Arup) ([www.oasys-software.com/products](http://www.oasys-software.com/products))
* ProDESK from Prokon Software Consultants ([www.prokon.com/](http://www.prokon.com/))
* RAM Structural System from Bentley ([www.bentley.com/en/products/product-line/structural-analysis-software/ram-structural-system](https://www.bentley.com/en/products/product-line/structural-analysis-software/ram-structural-system))
* SOFiSTiK Structural Desktop Suite from SOFiSTiK ([www.sofistik.com](http://www.sofistik.com))
* Robot Structural Analysis Professional from Autodesk ([www.autodesk.com/products/robot-structural-analysis](http://www.autodesk.com/products/robot-structural-analysis))
The key to linking Revit to other analysis applications is to set up the mapping relationship between the objects in different object models. That means the difficulty and level of the integration depends on the similarity between the two object models.
For example, during the product design process, design a table with at least the first two columns in the object mapping in the following table: one for the Revit API and the other for the structural analysis application, shown as follows:
**Table 62: Revit and Analysis Application Object Mapping**
**Revit API** | **Analysis Application** | **Import to Revit**
---|---|---
StructuralColumn | Column | NewStructuralColumn
Property: | |
… | |
Location | | Read-only;
Parameter: | |
… | |
Analyze as | | Editable;
AnalyticalModel: | |
… | |
Profile | | Read-only;
RigidLink | | Read-only;
… | |
Material: | |
… | |
**Parent page:** [Structural Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_html.html)

View File

@@ -0,0 +1,87 @@
# Analytical Links
# Analytical Links
An analytical link is an element connecting 2 separate analytical nodes, which has properties such as fixity state. Analytical links can be created automatically by Revit from analytical beams to analytical columns during modeling based on certain rules. And they can also be created manually, both in the Revit UI and using the Revit API.
In the Revit API, an analytical link is represented by the AnalyticalLink class. Fixity values are available from its associated AnalyticalLinkType.
The example below demonstrates how to read all of the AnalyticalLinks in the document and displays a TaskDialog summarizing the number of automatically generated and manually created AnalyticalLinks.
**Code Region: Reading AnalyticalLinks**
---
public void ReadAnalyticalLinks(Document document)
{
FilteredElementCollector collectorAnalyticalLinks = new FilteredElementCollector(document);
collectorAnalyticalLinks.OfClass(typeof(AnalyticalLink));
IEnumerable<AnalyticalLink> alinks = collectorAnalyticalLinks.ToElements().Cast<AnalyticalLink>();
int nAutoGeneratedLinks = 0;
int nManualLinks = 0;
foreach (AnalyticalLink alink in alinks)
{
if (alink.IsAutoGenerated() == true)
nAutoGeneratedLinks++;
else
nManualLinks++;
}
string msg = "Auto-generated AnalyticalLinks: " + nAutoGeneratedLinks;
msg += "\nManually created AnalyticalLinks: " + nManualLinks;
TaskDialog.Show("AnalyticalLinks", msg);
}
The static method AnalyticalLink.Create() creates a new analytical link. Rather than connecting the two elements directly, the connection is created between two Hubs. The Hub class represents a connection between two or more Autodesk Revit Elements.
The following example creates a new analytical link between two selected FamilyInstance objects. It uses a filter to find all Hubs in the model and then the GetHub() method searches the hubs to find one which references the Id of the AnalyticalElement of each FamilyInstance.
**Code Region: Creating a new AnalyticalLink**
---
public void CreateLink(Document doc, FamilyInstance fi1, FamilyInstance fi2)
{
FilteredElementCollector hubCollector = new FilteredElementCollector(doc);
hubCollector.OfClass(typeof(Hub)); //Get all hubs
ICollection<Element> allHubs = hubCollector.ToElements();
FilteredElementCollector linktypeCollector = new FilteredElementCollector(doc);
linktypeCollector.OfClass(typeof(AnalyticalLinkType));
ElementId firstLinkType = linktypeCollector.ToElementIds().First(); //Get the first analytical link type.
// Get hub Ids from two selected family instance items
ElementId startHubId = GetHub(AnalyticalToPhysicalAssociationManager.GetAnalyticalToPhysicalAssociationManager(doc)
.GetAssociatedElementId(fi1.Id), allHubs);
ElementId endHubId = GetHub(AnalyticalToPhysicalAssociationManager.GetAnalyticalToPhysicalAssociationManager(doc)
.GetAssociatedElementId(fi2.Id), allHubs);
Transaction tran = new Transaction(doc, "Create Link");
tran.Start();
//Create a link between these two hubs.
AnalyticalLink createdLink = AnalyticalLink.Create(doc, firstLinkType, startHubId, endHubId);
tran.Commit();
}
//Get the first Hub on a given AnalyticalElement element
private ElementId GetHub(ElementId hostId, ICollection<Element> allHubs)
{
foreach (Element ehub in allHubs)
{
Hub hub = ehub as Hub;
ConnectorManager manager = hub.GetHubConnectorManager();
ConnectorSet connectors = manager.Connectors;
foreach (Connector connector in connectors)
{
ConnectorSet refConnectors = connector.AllRefs;
foreach (Connector refConnector in refConnectors)
{
if (refConnector.Owner.Id == hostId)
{
return hub.Id;
}
}
}
}
return ElementId.InvalidElementId;
}
**Parent page:** [Structural Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_html.html)

View File

@@ -0,0 +1,146 @@
# Analytical Model
# Analytical Model
In structural engineering, an analytical model is the engineering description of a structural physical model. The Analytical Model is an essential part of BIM data and is subject to collaborative workflows within engineering teams and across project teams. The Analytical Model implementation in Revit enables engineers to:
* Have freedom of analytical modeling to reflect their individual design decisions with respect to structural elements and buildings/structures seen as whole systems.
* Analytically represent any types of structure.
* Create consistent Analytical Models enabling structural analysis jobs from Revit models.
* Perform full bi-directional workflow with analysis software and capture model modifications made there.
* Preserve Analytical Model from unexpected changes if needed.
* Create multiple analytical models reflecting diverse analysis types and configurations.
* Replicate the ease of analytical modeling like in dedicated structural analysis software, combined with the power of parametric and collaboration enabling BIM platform.
## AnalyticalElement
AnalyticalElement represents the base class for all analytical objects.
* Transform GetTransform() - Returns the transform which reflects Analytical Element orientation.
* AnalyzeAs AnalyzeAs - This represents the Analyze As parameter assigned to Analytical Element.
* Reference GetReference(AnalyticalModelSelector selector) - Returns a reference to a given curve within the Analytical Element.
* ElementId MaterialId - Defines the Material Id for the Analytical Element.
## AnalyticalMember
AnalyticalMember represents a linear element in the structural analytical model.
* AnalyticalMember Create(Document document, Curve curve) - Method which creates a new instance of an Analytical Member within the project.
* AnalyticalStructuralRole StructuralRole - The structural role assigned to the Analytical Member.
* Curve GetCurve() - Returns the curve of the Analytical Member.
* void SetCurve(Curve curve) - Sets the curve for the Analytical Member. This method disconnects elements from other analytical elements (if the end nodes are in the same position). If the user wants to move the corner, and keep the connection, there are other ways for achieving that like ElementTransformUtils.moveElements.
* bool IsValidCurve(Curve curve) - Verifies if the curve is valid for an Analytical Member.
* void FlipCurve() - Flips the ends of the Analytical Member.
* StructuralSectionShape StructuralSectionShape - The structural section shape of the Analytical Member (read only).
* ElementId SectionType - The id of the type from the structural Family assigned to the Analytical Member.
* double CrossSectionRotation - Cross section rotation of the Analytical Member.
## AnalyticalPanel
AnalyticalPanel represents a surface in the structural analytical model.
* AnalyticalPanel Create(Document document, CurveLoop curveLoop) - Method which creates a new instance of an Analytical Panel within the project.
* CurveLoop GetOuterContour() - Returns the Curve Loop that defines the geometry of the Analytical Surface element.
* bool IsCurveLoopValid(CurveLoop profile) - Checks if curve loop is valid for Analytical Panel.
* To modify Analytical Panel geometry, users should use SketchEditScope framework.
* void StartWithNewSketch(ElementId elementId) - Starts a sketch edit mode for an element which, at this moment, doesn't have a sketch. Another way of editing geometry is SetOuterContour(CurveLoop outerContour) - Sets the Curve Loop that defines the geometry of the Analytical Surface element. Like for AnalyticalMember, setting the contour for analytical panel will break the connection with other analytical elements. If the user wants to move the corner, and keep the connection, there are other ways for achieving that like ElementTransformUtils.MoveElements.
* `ISet<ElementId> GetAnalyticalOpeningsIds()` \- Returns the Analytical Openings Ids of the Analytical Panel.
* ElementId SketchId - Sketch associated to this Revit element.
* AnalyticalStructuralRole StructuralRole - Structural role assigned to the Analytical Panel.
## AnalyticalOpening
AnalyticalOpening is an element which represents an opening in an Analytical Panel.
* AnalyticalOpening Create(Document doc, CurveLoop curveLoop, ElementId panelId) - Method which creates a new instance of an Analytical Opening within the project.
* CurveLoop GetOuterContour() - Returns the Curve Loop that defines the geometry of the Analytical Surface element.
* bool IsCurveLoopValidForAnalyticalOpening(CurveLoop loop, Document document, ElementId panelId) - Checks if curve loop is valid for Analytical Opening To modify Analytical Opening geometry, you should use SketchEditScope framework. Another way to modify Analytical Opening geometry is: void SetOuterContour(CurveLoop outerContour). - Sets the Curve Loop that defines the geometry of the Analytical Surface element.
* ElementId PanelId - ElementId of the host Analytical Panel.
* ElementId SketchId - Sketch associated to this Revit element.
## AnalyticalToPhysicalAssociationManager
AnalyticalToPhysicalAssociationManager manages the associations between analytical and physical elements. In the past solution, the elements itself knew about each other and the user had no control over it (the association could not be modified). With this new approach, the association can be edited. Revit supports 1-1 association and elements cannot be part of multiple associations at the same time.
* AnalyticalToPhysicalAssociationManager GetAnalyticalToPhysicalAssociationManager(Document doc) Returns the AnalyticalToPhysicalAssociationManager for this document.
* void AddAssociation(ElementId analyticalElementId, ElementId physicalElementId) - Adds a new association between an analytical element and a physical element.
* void RemoveAssociation(ElementId elementId) - This method will remove the association for the element with the given ElementId.
* ElementId GetAssociatedElementId(ElementId elementId) - Returns id of the element which is associated with the given ElementId.
* bool HasAssociation(ElementId id) - Verifies if the element has already defined an association.
## AnalyticalNodeData
The AnalyticalNodeData class holds information about connection status of analytical nodes.
* AnalyticalNodeData GetAnalyticalNodeData(Element element) - Returns AnalyticalNodeData associated with this element, if it exists.
* AnalyticalNodeConnectionStatus GetConnectionStatus() - Returns the Connections Status for an Analytical Node.
## Loads
All loads in the analytical model have a host. For each type of load - point, line, area - there are two options:
* "Constrained on host"
* The load is created for the entire shape of the host analytical element.
* The load is always hosted on the analytical element.
* The load follows the host analytical element shape and adjust its shape accordingly.
* "Custom"
* The load can be placed anywhere on the host analytical element.
* The load is always hosted on the analytical element.
* The load moves with the host but keeps its shape.
Methods to create loads and validate their hosts are:
Load Base:
* LoadBase.IsConstrainedOnHost - checks if the load is constrained on host (is created on the entire shape of the host).
Line Load:
* LineLoad.Create(Document document, ElementId hostElemId, XYZ forceVector1, XYZ momentVector1, LineLoadType symbol) - Creates a new hosted line load within the project.
* LineLoad.Create(Document document, ElementId hostElemId, int curveIndex, XYZ forceVector1, XYZ momentVector1, Structure.LineLoadType symbol) - Creates a new hosted line load within the project.
* LineLoad.Create(Document document, ElementId hostElemId, Curve curve, XYZ forceVector1, XYZ momentVector1, LineLoadType symbol) - Creates a new custom line load within the project.
* LineLoad.IsValidHostId(Document doc, ElementId hostElemId) - Indicates if the provided element id can host line loads.
Area Load:
* AreaLoad.Create(Document doc, ElementId hostElemId, XYZ forceVector1, AreaLoadType symbol) - Creates a new hosted area load within the project.
* AreaLoad.Create(Document document, ElementId hostElemId, IList<CurveLoop> loops, XYZ forceVector, AreaLoadType symbol) - Creates a new custom area load within the project.
* AreaLoad.Create(Document document, ElementId hostElemId, IList<CurveLoop> loops, IList<XYZ> forceVectors, IList<int> refPointCurveIndexes, IList<int> refPointCurveEnds, AreaLoadType symbol) - Creates a new custom area load within the project.
* AreaLoad.IsValidHostId(Document doc, ElementId hostElemId) - Indicates if the provided element id can host area loads.
* AreaLoad.AreCurveLoopsValid(IList<CurveLoop> loops) - Checks if curve loops are valid for creating an area load.
* AreaLoad.AreCurveLoopsInsideHostBoundaries(Document doc, ElementId hostId, IList<CurveLoop> loops) - Checks if contour loops are inside host boundaries.
Point Loads:
* PointLoad.Create(Document doc, ElementId hostElemId, AnalyticalElementSelector selector, XYZ forceVector, XYZ momentVector, PointLoadType symbol) - Creates a new hosted point load within the project.
* PointLoad.Create(Document document, ElementId hostElemId, XYZ point, XYZ forceVector, XYZ momentVector, PointLoadType symbol) - Creates a new custom hosted point load within the project using data at point.
* PointLoad.IsPointInsideHostBoundaries(Document pDoc, ElementId hostId, XYZ point) - Indicates if the point is inside panel boundaries or is on the member's curve.
* PointLoad.IsValidHostId(Document doc, ElementId hostElemId).
**Parent page:** [Structural Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_html.html)

View File

@@ -0,0 +1,250 @@
# Loads
# Loads
The following sections identify load settings and discuss load limitation guidelines.
### Load Settings
All functionality on the Setting dialog box Load Cases and Load Combinations tabs can be accessed by the API.
The following properties are available from the corresponding LoadCase BuiltInParameter:
**Table 60 Load Case Properties and Parameters**
**Property** | **BuiltInParameter**
---|---
Case Number | LOAD_CASE _NUMBER
Nature | LOAD_CASE_NATURE
Category | LOAD_CASE_CATEGORY
The LOAD_CASE_CATEGORY parameter returns an ElementId. The following table identifies the mapping between Category and ElementId Value.
**Table 61: Load Case Category**
**Load Case Category** | **BuiltInCategory**
---|---
Dead Loads | OST_LoadCasesDead
Live Loads | OST_LoadCasesLive
Wind Loads | OST_LoadCasesWind
Snow Loads | OST_LoadCasesSnow
Roof Live Loads | OST_LoadCasesRoofLive
Accidental Loads | OST_LoadCasesAccidental
Temperature Loads | OST_LoadCasesTemperature
Seismic Loads | OST_LoadCasesSeismic
#### Creating loads and load combinations
The following classes have one or more static Create() methods to create corresponding classes:
* LoadUsage
* LoadNature
* LoadCase
* LoadCombination
* PointLoad
* LineLoad
* AreaLoad
Point, area, and line loads can be created with or without a host element. Each of these classes has a `isValidHostId` method that indicates if a specific element can host that type of load.
Because they are all Element subclasses, they can be deleted using Document.Delete().
Load Combinations are created via the static method LoadCombination.Create() which has two overloads. The first takes only a reference to the document in which you want to create the load combination and the string for the name of the new combination. The second takes these arguments plus the LoadCombinationType and LoadCombinationState. The LoadCombinationType can be either Combination, for a straight load combination, or Envelope, for an envelope of the effects of several load cases or combinations.
These values are available for the Autodesk.Revit.DB.Structure.LoadCombinationState enum:
* Serviceability
* Ultimate
* ServiceabilityQuasiPermanent
* ServiceabilityFrequent
* ServiceabilityRare
* Accidental
* Special
Use a Serviceability type if the load combination represents a service load level on the structure. This is typically used in design or checking of member deflections or other serviceability criteria such as Allowable Stress Design methodologies. Use Ultimate if the load combination represents an ultimate load state or a factored load state on the structure typically used in Load Resistance Factor Design methodologies.
After a LoadCombination is created, you will need to fill it with LoadComponents which comprise the load combination and their factors. LoadComponents are added to the LoadCombination by calling LoadCombination.SetComponents() with a list of the components as shown in this code snippet below.
Note: Make sure that the list of components does not refer to itself.
The following example demonstrates how to create a Load Combination and how to find or create Load Cases and Load Natures to use to set the components of the Load Combination.
**Code Region: Creating a new LoadCombination**
---
LoadCombination CreateLoadCombinationLoadCaseLoadUsageLoadNatureAndLoadComponent(Document document)
{
// Create a new load combination
LoadCombination loadCombination = LoadCombination.Create(document, "DL1 + RAIN1", LoadCombinationType.Combination, LoadCombinationState.Ultimate);
if (loadCombination == null)
throw new Exception("Create new load combination failed.");
// Get all existing LoadCase
FilteredElementCollector collector = new FilteredElementCollector(document);
ICollection<Element> collection = collector.OfClass(typeof(LoadCase)).ToElements();
// Find LoadCase "DL1"
LoadCase case1 = null;
foreach (Element e in collection)
{
LoadCase loadCase = e as LoadCase;
if (loadCase.Name == "DL1")
{
case1 = loadCase;
break;
}
}
// Get all existing LoadNature
collector = new FilteredElementCollector(document);
collection = collector.OfClass(typeof(LoadNature)).ToElements();
// Find LoadNature "Dead"
LoadNature nature1 = null;
foreach (Element e in collection)
{
LoadNature loadNature = e as LoadNature;
if (loadNature.Name == "Dead")
{
nature1 = loadNature;
break;
}
}
// Create LoadNature "Dead" if not exist
if (nature1 == null)
nature1 = LoadNature.Create(document, "Dead");
// Create LoadCase "DL1" if not exist
if (case1 == null)
case1 = LoadCase.Create(document, "DL1", nature1.Id, LoadCaseCategory.Dead);
// Create LoadNature "Rain"
LoadNature nature2 = LoadNature.Create(document, "Rain");
if (nature2 == null)
throw new Exception("Create new load nature failed.");
// Create LoadCase "RAIN1"
LoadCase case2 = LoadCase.Create(document, "RAIN1", nature2.Id, LoadCaseCategory.Snow);
if (case1 == null || case2 == null)
throw new Exception("Create new load case failed.");
// Create LoadComponents - they consist of LoadCases or nested LoadCombination and Factors
List<LoadComponent> components = new List<LoadComponent>();
components.Add(new LoadComponent(case1.Id, 2.0));
components.Add(new LoadComponent(case2.Id, 1.5));
// Add components to combination
loadCombination.SetComponents(components);
// Create LoadUsages
LoadUsage usage1 = LoadUsage.Create(document, "Frequent");
LoadUsage usage2 = LoadUsage.Create(document, "Rare");
if (usage1 == null || usage2 == null)
throw new Exception("Create new load usage failed.");
// Add load usages to combination
loadCombination.SetUsageIds(new List<ElementId>() {usage1.Id, usage2.Id});
// Give the user some information
TaskDialog.Show("Revit", string.Format("Load Combination ID='{0}' created successfully.", loadCombination.Id.Value));
return loadCombination;
}
You may also modify the cases, components, natures, etc by using LoadCombination.GetComponents(), making modifications and then calling LoadCombination.SetComponents() again. LoadUsages for the LoadCombination can be modified by calling LoadCombination.GetUsageIds() to get the list of LoadUsage Ids, modifying the list, and calling SetUsageIds() again. The following code sample demonstrates how to modify an existing LoadCombination.
**Code Region: Modify a load combination**
---
void ModifyLoadCombinationLoadCaseLoadUsageLoadNatureAndLoadComponent(Document document, LoadCombination loadCombination)
{
// Change name of LoadCombination
loadCombination.Name = "DL2 + RAIN1";
// Get any LoadCase from combination
// Combination can have assigned LoadCase or other (nested) LoadCombination so we need to filter out any LoadCombination
LoadCase case1 = null;
IList<ElementId> caseAndCombinationIds = loadCombination.GetCaseAndCombinationIds();
foreach (ElementId id in caseAndCombinationIds)
{
Element element = document.GetElement(id);
if (element is LoadCase)
{
case1 = (LoadCase)element;
break;
}
else if (element is LoadCombination)
{
continue;
}
}
if (case1 == null)
throw new Exception("Can't get LoadCase.");
// Change case name and number
case1.Name = "DL2";
if (LoadCase.IsNumberUnique(document, 3))
{
case1.Number = 3;
}
// Create load nature
LoadNature liveNature = LoadNature.Create(document, "Dead nature");
if (liveNature == null)
throw new Exception("Create new load nature failed.");
// Change nature category and ID for case
case1.SubcategoryId = new ElementId(BuiltInCategory.OST_LoadCasesDead);
case1.NatureId = liveNature.Id;
//Change factor for case1
IList<LoadComponent> components = loadCombination.GetComponents();
foreach (LoadComponent loadComponent in components)
{
if (loadComponent.LoadCaseOrCombinationId == case1.Id)
{
loadComponent.Factor = 3.0;
}
}
loadCombination.SetComponents(components);
// Remove one usage from combination
IList<ElementId> usages = loadCombination.GetUsageIds();
usages.RemoveAt(0);
loadCombination.SetUsageIds(usages);
// Give the user some information
TaskDialog.Show("Revit", string.Format("Load Combination ID='{0}' modified successfully.", loadCombination.Id.Value));
}
There is no Duplicate() method in the LoadCase and LoadNature classes. To implement this functionality, you must first create a new LoadCase (or LoadNature) object, and then copy the corresponding properties and parameters from an existing LoadCase (or LoadNature).
The following is a minimum sample code to demonstrate the creation of a point load:
**Code Region: New PointLoad**
---
public void CreatePointLoad(Document document, ElementId hostId)
{
// Define the location at which the PointLoad is applied.
XYZ point = new XYZ(0, 0, 4);
// Define the 3d force.
XYZ force = new XYZ(0, 0, -1);
// Define the 3d moment.
XYZ moment = new XYZ(0, 0, 0);
PointLoad pointLoad = PointLoad.Create(document, hostId, point, force, moment, null);
}
**Parent page:** [Structural Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_html.html)

View File

@@ -0,0 +1,53 @@
# Steel Fabrication
# Steel Fabrication
## Linking between Revit elements and steel fabrication elements
Autodesk.Revit.DB.Steel.SteelElementProperties attaches steel fabrication information to Revit elements. Elements which can have fabrication information include:
* FamilyInstance elements (structural beams and columns)
* StructuralConnectionHandler elements
* Specific steel connection elements (bolts, anchors, plates, etc). These connection elements will be of type Element but with categories related to structural connections, for example:
* OST_StructConnectionWelds
* OST_StructConnectionHoles
* OST_StructConnectionShearStuds
* OST_StructConnectionBolts
* OST_StructConnectionAnchors
* OST_StructConnectionPlates
* Some concrete elements (walls, floors, concrete beams) when they are used as input elements to creation of steel connections.
Use SteelElementProperties.GetSteelElementProperties() to obtain the properties if they exist.
The properties contain SteelElementProperties.UniqueID which is the id of the object in fabrication terms, and can be used to determine the Steel Core element corresponding to this Revit element, for use with the Advance Steel API.
You can also look up the id for a Revit element using the static method SteelElementProperties.GetFabricationUniqueID().
For Revit elements which do not currently have a fabrication link, it can be added using: SteelElementProperties.AddFabricationInformationForRevitElements().
If you have a fabrication id, you can lookup the corresponding Revit element using: SteelElementProperties.GetReference(). This may return a reference to an element or a subelement.
## Custom steel connections
StructuralConnectionHandler.CreateGenericConnection() creates a custom StructuralConnectionHandler along with its associated StructuralConnectionHandlerType. Input elements should include structural members and steel connection members, and at least one StructuralConnectionHandler representing the generic connection to replace with the new detailed custom connection.
The method StructuralConnectionHandlerType.UpdateCustomConnectionType() provides support for updating steel connection elements in a custom connection.
The properties:
* StructuralConnectionHandler.IsCustom
* StructuralConnectionHandler.IsDetailed
* StructuralConnectionHandlerType.IsCustom
* StructuralConnectionHandlerType.IsDetailed
provide read access to information about the structural connection handler elements.
**Parent page:** [Structural Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_html.html)

View File

@@ -0,0 +1,67 @@
# Boundary Conditions
# Boundary Conditions
## BoundaryConditions
There are three types of BoundaryConditions:
* Point
* Curve
* Area
The type and pertinent geometry information is retrieved using the following code:
**Code Region 29-9: Getting boundary condition type and geometry**
---
public void GetInfo_BoundaryConditions(BoundaryConditions boundaryConditions)
{
string message = "BoundaryConditions : ";
boundaryConditions.GetBoundaryConditionsType();
switch (boundaryConditions.GetBoundaryConditionsType())
{
case BoundaryConditionsType.Point:
XYZ point = boundaryConditions.Point;
message += "\nThis BoundaryConditions is a Point Boundary Conditions.";
message += "\nLocation point: (" + point.X + ", "
+ point.Y + ", " + point.Z + ")";
break;
case BoundaryConditionsType.Line:
message += "\nThis BoundaryConditions is a Line Boundary Conditions.";
Curve curve = boundaryConditions.GetCurve();
// Get curve start point
message += "\nLocation Line: start point: (" + curve.GetEndPoint(0).X + ", "
+ curve.GetEndPoint(0).Y + ", " + curve.GetEndPoint(0).Z + ")";
// Get curve end point
message += "; end point:(" + curve.GetEndPoint(1).X + ", "
+ curve.GetEndPoint(1).Y + ", " + curve.GetEndPoint(1).Z + ")";
break;
case BoundaryConditionsType.Area:
message += "\nThis BoundaryConditions is an Area Boundary Conditions.";
IList<CurveLoop> loops = boundaryConditions.GetLoops();
foreach (CurveLoop curveLoop in loops)
{
foreach (Curve areaCurve in curveLoop)
{
// Get curve start point
message += "\nCurve start point:(" + areaCurve.GetEndPoint(0).X + ", "
+ areaCurve.GetEndPoint(0).Y + ", " + areaCurve.GetEndPoint(0).Z + ")";
// Get curve end point
message += "; Curve end point:(" + areaCurve.GetEndPoint(1).X + ", "
+ areaCurve.GetEndPoint(1).Y + ", " + areaCurve.GetEndPoint(1).Z + ")";
}
}
break;
default:
break;
}
TaskDialog.Show("Revit",message);
}
**Parent page:** [Structural Model Elements](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_html.html)

View File

@@ -0,0 +1,47 @@
# Annotation
# Annotation
The `MultiReferenceAnnotation` can be used to label and dimension Rebar elements, and are labeled in the user interface as "Multi-rebar annotations". The members of this class include:
* Create - creates a new MultiReferenceAnnotation based on a document, view, and an instance of the MultiReferenceAnnotationOptions class.
* AreElementsValidForMultiReferenceAnnotation - validates if the input elements match the element category id for the MultiReferenceAnnotationType.
* is3DViewValidForDimension - Returns True if the view is suitable for placing the MultiReferenceAnnotation.
* If the DimensionStyle is LinearFixed, it cannot be created in a 3D View.
* If the DimensionStyle is Linear, it cannot be created in a 3D View if the view direction is perpendicular to the current work plane normal.
* Returns true if the ownerViewId is not a 3D view.
The references of the annoation and placement options are specified in the `MultiReferenceAnnotationOptions` class. Its members include:
* DimensionLineDirection - The direction vector of the dimension line.
* SetElementsToDimension - The elements referenced by the dimension.
* SetAdditionalReferencesToDimension - Sets the additional references which the dimension will witness. The additional references to dimension cannot come from the same category as the MultiReferenceAnnotationType's reference category.
* ReferencesDontMatchReferenceCategory - Verifies that all of the references belongs to elements which don't match the reference category required by the MultiReferenceAnnotationType.
* GetAdditionalReferencesToDimension - Gets the additional references which the dimension will witness.
Code Region: Create MultiReferenceAnnotation
---
public void CreateAnnotation(Document doc)
{
MultiReferenceAnnotationOptions opt = new MultiReferenceAnnotationOptions(
new FilteredElementCollector(doc)
.OfClass(typeof(MultiReferenceAnnotationType))
.Cast<MultiReferenceAnnotationType>()
.FirstOrDefault());
opt.DimensionLineDirection = XYZ.BasisX;
opt.DimensionPlaneNormal = XYZ.BasisZ;
opt.DimensionStyleType = DimensionStyleType.Linear;
opt.SetElementsToDimension(new FilteredElementCollector(doc, doc.ActiveView.Id).OfClass(typeof(Rebar)).ToElementIds());
using (Transaction t = new Transaction(doc, "MultiReferenceAnnotation"))
{
t.Start();
MultiReferenceAnnotation mra = MultiReferenceAnnotation.Create(doc, doc.ActiveView.Id, opt);
t.Commit();
}
}
**Parent page:** [Reinforcement](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_html.html)

View File

@@ -0,0 +1,99 @@
# Area and Path Reinforcement
# Area and Path Reinforcement
The Revit API provides classes representing area and path reinforcement in the structural features of Revit.
Find the AreaReinforcementCurves for AreaReinforcement by calling the GetBoundaryCurveIds() method which returns an IList of ElementIds that represent AreaReinforcementCurves.
While the AreaReinforcement.GetBoundaryCurveIds() method returns a set of ElementIds representing AreaReinforcementCurves, which have a property that returns a Curve, the PathReinforcement.GetCurveElementIds() method returns a collection of ElementIds that represent ModelCurves. There is no way to flip the PathReinforcement except by on creation using the PathReinforcement.Create() method. PathReinforcment can only be created using an array of curves.
For more details about retrieving an Element's Geometry, refer to [Geometry](../../../../Revit_Geometric_Elements/Revit_API_Revit_API_Developers_Guide_Revit_Geometric_Elements_Geometry_html.html).
Note: Project-wide settings related to area and path reinforcement are accessible from the [ReinforcementSettings](Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_Reinforcement_Settings_html.html "Several settings regarding reinforcement in the model are controlled at the document level and are accessed through the ReinfocementSettings class for the document.") class.
The API provides access to the layers of Area Reinforcement elements and allows the individual lines exposed through those layers to be moved and removed.
The overloaded AreaReinforcement.Create() method provides two ways to create new AreaReinforcement: based on a host boundary or from an array of curves. The Major Direction of the area reinforcement can be set when creating a new AreaReinforcement using either of the overloaded Create() methods, but the AreaReinforcment.Direction property is read-only.
**Creating area reinforcement**
---
AreaReinforcement CreateAreaReinforcementInWall(Wall wall, Autodesk.Revit.DB.Document document)
{
// Get the wall analytical profile whose curves will define the boundary of the the area reinforcement
AnalyticalPanel analytical = (AnalyticalPanel)document.GetElement(AnalyticalToPhysicalAssociationManager.GetAnalyticalToPhysicalAssociationManager(document)
.GetAssociatedElementId(wall.Id));
if (null == analytical)
{
throw new Exception("Can't get AnalyticalModel from the selected wall");
}
IList<Curve> curves = analytical.GetOuterContour().Cast<Curve>().ToList();
//define the Major Direction of AreaReinforcement,
//we get direction of first Line on the Wall as the Major Direction
Line firstLine = (Line)(curves[0]);
XYZ majorDirection = new XYZ(
firstLine.GetEndPoint(1).X - firstLine.GetEndPoint(0).X,
firstLine.GetEndPoint(1).Y - firstLine.GetEndPoint(0).Y,
firstLine.GetEndPoint(1).Z - firstLine.GetEndPoint(0).Z);
// Obtain the default types
ElementId defaultRebarBarTypeId = document.GetDefaultElementTypeId(ElementTypeGroup.RebarBarType);
ElementId defaultAreaReinforcementTypeId = document.GetDefaultElementTypeId(ElementTypeGroup.AreaReinforcementType);
ElementId defaultHookTypeId = ElementId.InvalidElementId;
// Create the area reinforcement
AreaReinforcement rein = AreaReinforcement.Create(document, wall, curves, majorDirection, defaultAreaReinforcementTypeId, defaultRebarBarTypeId, defaultHookTypeId);
return rein;
}
## Creating path reinforcement
The overloaded static method PathReinforcement.Create() method provides two ways to create path reinforcement. Both create path reinforcement in a host object from an array of curves, but one will use the default rebar shape while the other takes a Rebar Shape id as a parameter. The example below uses the default rebar shape.
**Creating path reinforcement**
---
PathReinforcement CreatePathReinforcement(Autodesk.Revit.DB.Document document, Wall wall)
{
// Create a geometry line in the selected wall as the path
List<Curve> curves = new List<Curve>();
LocationCurve location = wall.Location as LocationCurve;
XYZ start = location.Curve.GetEndPoint(0);
XYZ end = location.Curve.GetEndPoint(1);
curves.Add(Line.CreateBound(start, end));
// Obtain the default types
ElementId defaultRebarBarTypeId = document.GetDefaultElementTypeId(ElementTypeGroup.RebarBarType);
ElementId defaultPathReinforcementTypeId = document.GetDefaultElementTypeId(ElementTypeGroup.PathReinforcementType);
ElementId defaultHookTypeId = ElementId.InvalidElementId;
// Begin to create the path reinforcement
PathReinforcement rein = PathReinforcement.Create(document, wall, curves, true, defaultPathReinforcementTypeId, defaultRebarBarTypeId, defaultHookTypeId, defaultHookTypeId);
if (null == rein)
{
throw new Exception("Create path reinforcement failed.");
}
// Give the user some information
TaskDialog.Show("Revit","Create path reinforcement succeed.");
return rein;
}
When specifying the rebar shape id for a new PathReinforcement, if there are no rebar shapes in the project or you are not initially concerned with the rebar shape, you can use the static PathReinforcement method GetOrCreateDefaultRebarShape() to obtain a valid rebar shape for use with PathReinforcement. If you would like to check whether an existing rebar shape is valid for use with path reinforcement, you can call the static method PathReinforcement.IsValidRebarShapeId().
New shape types may be queried, or assigned to the path reinforcement by using the PathReinforcement properties PrimaryBarShapeId and AlternatingBarShapeId. The static method IsValidRebarShapeId() can be used to determine if you have a valid shape before attempting to set the shape id on a path reinforcement object. Note that before attempting to set alternating bars, the alternating bars parameter must be enabled in the Path Reinforcement by setting PATH_REIN_ALTERNATING BuiltInParameter to true.
The orientation of the primary and alternating bars may also be queried, or set through the properties PrimaryBarOrientation and AlternatingBarOrientation which take a value from the ReinforcementBarOrientation enumeration. You may check whether an orientation is valid for a particular path reinforcement object by calling the class method IsValidPrimaryBarOrientation() or IsValidAlternatingBarOrientation().
You may query the state of the alternating layer by calling the IsAlternatingLayerEnabled() method. The alternating layer is controlled via the built in parameter PATH_REIN_ALTERNATING on the path reinforcing element.
The API provides access to move, include, or remove individual bars for RebarInSystem elements that are owned by PathReinforcement.
**Parent page:** [Reinforcement](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_html.html)

View File

@@ -0,0 +1,208 @@
# Fabric Reinforcement
# Fabric Reinforcement
Fabric reinforcement is a layer of fabric sheets made of welded fabric wire and hosted in concrete slabs or walls.
Fabric sheets are typically created in a pattern which results in welded wire sheets overlapping each other to provide continuity of load transfer from one sheet to the next. Sheets may be in one or more layers within a concrete element.
Fabric Sheets are typically specified by a grid spacing and a wire size for each direction. For example: 6x6 - W2.9/W2.9 in US Imperial units (or 152x152-MW18.7/MW18.7 in SI units) would be interpreted as a grid of wires at 6" on center with a wire area of 2.9 hundredths of an inch squared (0.029 sq-in).
In the Revit API, these sheets are represented by the FabricSheet class and they are defined by a FabricSheetType class which controls the number and spacing of wires in each direction, either by a pattern or custom definition. FabricSheetType reference wires as FabricWireItems that are associated with a FabricWireType.
## Fabric Area
The FabricArea class is a container for fabric sheets. When created, fabric sheets are automatically generated for the FabricArea based on the FabricSheetType referenced on creation. The FabricArea class has an overloaded Create() method to create a FabricArea based either on the host boundary or from an array of curves. FabricArea must be hosted by a structural floor, wall, foundation slab or a part created from a structural layer of one of these types.
### Fabric Sheet and Area
The members:
* FabricArea.DistributionOfWiresAtCover
* FabricSheet.DistributionOfWiresAtCover provide information about which distribution is set closest to the cover.
The example below demonstrates how to create a new FabricArea and get a list of the resulting FabricSheets.
Code Region: Create a fabric area
---
private FabricArea CreateNewFabricArea(Document document, Element wall)
{
FabricArea system = null;
// create default types if they aren't already in the model
ElementId fabricAreaTypeId = FabricAreaType.CreateDefaultFabricAreaType(document);
ElementId fabricSheetTypeId = FabricSheetType.CreateDefaultFabricSheetType(document);
system = FabricArea.Create(document, wall, new XYZ(1, 0, 0), fabricAreaTypeId, fabricSheetTypeId);
// call regenerate to generate fabric sheets in fabric area
document.Regenerate();
// get the list of elementIds for the sheets automatically generated in the fabric area
IList<ElementId> sheetIds = system.GetFabricSheetElementIds();
TaskDialog.Show("Revit", string.Format("{0} fabric sheets created", sheetIds.Count));
return system;
}
## Creating fabric sheets
Fabric sheets can be hosted by a container (represented by the FabricArea class), or can exist as single fabric sheets. Single fabric sheets are hosted elements and must be hosted by a structural floor, structural wall, structural foundation slab, or a part created from a structural layer of one of these types. Bent fabric sheets can also be hosted in structural beams, columns and braces.
The FabricSheet class provides an overloaded static Create() method for creating new single fabric sheets in the model. One overload of FabricSheet.Create() creates a flat fabric sheet and requires a reference to the document in which the fabric sheet will be created, a reference to the host element which will host the fabric sheet and the ElementId of the fabric sheet type to create.
Another overload of FabricSheet.Create() can be used to create bent fabric sheets, which is not possible in the Revit user interface. It requires the same input as above, plus a CurveLoop that defines the bending path. This bending path is a profile that defines the bending shape of the fabric sheet. Fabric wires have an allowable bend radiuses so you may provide this CurveLoop profile with or without fillets. In other words, if a U shaped profile is desired, only 3 lines must be specified and the fabric sheet created will be created with the appropriate bend radii at the corners. If the provided profile has no hard corners, (I.e., the curve has a tangent at each point, except the end) no fillets will be created in the final fabric sheet.
The provided CurveLoop is intended to define the centerline of the bent wire. You may specify whether the bend is in the major wires or the minor wires with the BentFabricBendDirection property of the FabricSheet. You may also specify the location of straight wires with respect to bent wires with the BentFabricStraightWiresLocation property.
## Fabric sheet type
A FabricSheet is associated with a FabricSheetType, which is used in the generation of wires for the sheet in the major and minor directions. The FabricSheetLayoutPattern for the wires in a FabricSheetType can be defined as:
* ActualSpacing - spacing of rebars is fixed
* FixedNumber - spacing of rebars is adjustable, but the number of bars is constant
* MaximumSpacing - number of rebars depends on length of rebar set with a maximum spacing constraint specified
* NumberWithSpacing - spacing and number of rebars are fixed
* QuantitativeSpacing - multiple groups of wires with a specific spacing and diameter For the first 4 options, FabricSheetType has methods to set the layout pattern with given information for either the minor or major direction, such as SetMajorLayoutAsFixedNumber() or SetMinorAsActualSpacing(). The layout pattern can be retrieved with the properties MajorLayoutPattern and MinorLayoutPattern.
QuantitativeSpacing is for custom patterns. Use SetLayoutAsCustomPattern() to set the major and minor layout patterns to QuantitativeSpacing. If the layout pattern for the FabricSheetType is custom, the MajorDirectionWireType, MinorDirectionWireType, MajorSpacing and MinorSpacing properties do not apply. The SetLayoutAsCustomPattern() method has parameters for the start overlaps for the major and minor directions (both end overhangs are read only and computed internally), as well as a list of FabricWireItems for each direction.
Code Region: Fabric sheet with custom wire pattern
---
private FabricSheet CreateCustomFabricSheet(Document document, Element wall)
{
if (FabricSheet.IsValidHost(wall) == false)
return null;
// Create a new type for custom FabricSheet
ElementId fabricSheetTypeId = FabricSheetType.CreateDefaultFabricSheetType(document);
FabricSheetType fst = document.GetElement(fabricSheetTypeId) as FabricSheetType;
// Create some fabric wire types
ElementId idWireType1 = FabricWireType.CreateDefaultFabricWireType(document);
FabricWireType wireType1 = document.GetElement(idWireType1) as FabricWireType;
wireType1.WireDiameter = 3.5 / 12.0;
ElementId idWireType2 = FabricWireType.CreateDefaultFabricWireType(document);
FabricWireType wireType2 = document.GetElement(idWireType1) as FabricWireType;
wireType2.WireDiameter = 2.0 / 12.0;
// Create the wires for the custom pattern
IList<FabricWireItem> majorWires = new List<FabricWireItem>();
IList<FabricWireItem> minorWires = new List<FabricWireItem>();
FabricWireItem item = FabricWireItem.Create(2.0 / 12.0, 1, idWireType1, 0);
majorWires.Add(item);
majorWires.Add(item);
item = FabricWireItem.Create(1.5 / 12.0, 10.0 / 12.0, idWireType2, 0);
majorWires.Add(item);
item = FabricWireItem.Create(3.0 / 12.0, 1, idWireType2, 0);
minorWires.Add(item);
item = FabricWireItem.Create(3.0 / 12.0, 10.0 / 12.0, idWireType2, 0);
minorWires.Add(item);
fst.SetLayoutAsCustomPattern(6.0 / 12.0, 4.0 / 12.0, minorWires, majorWires);
FabricSheet sheet = FabricSheet.Create(document, wall, fabricSheetTypeId);
// Regeneration is required before setting any property to object that was created in the same transaction.
document.Regenerate();
AnalyticalMember member = (AnalyticalMember)document.GetElement(AnalyticalToPhysicalAssociationManager.GetAnalyticalToPhysicalAssociationManager(document)
.GetAssociatedElementId(wall.Id));
sheet.PlaceInHost(wall, member.GetTransform());
// Give the user some information
TaskDialog.Show("Revit", string.Format("Flat Fabric Sheet ID='{0}' created successfully.", sheet.Id.IntegerValue));
return sheet;
}
## Single fabric sheets
When fabric sheets are created, they are not yet placed in their host. You must call the method FabricSheet.PlaceInHost() and pass in the host element as well as a transform which describes the final position of the fabric sheet. The element passed for the host must support hosting fabric sheets. Note that only bent fabric sheets can be hosted in beams, columns or braces, while both bent and flat fabric sheets can be hosted in structural floors, walls and foundation slabs, or parts created from a structural layer of one of these types.
Code Region: Creating a bent fabric sheet
---
private FabricSheet CreateBentFabricSheet(Document document, Element column)
{
if (FabricSheet.IsValidHost(column) == false)
return null;
CurveLoop bendingProfile = new CurveLoop();
Line line1 = Line.CreateBound(new XYZ(2, 0.8, 0), new XYZ(6, 0.8, 0));
Line line2 = Line.CreateBound(new XYZ(6, -0.8, 0), new XYZ(4, -2, 0));
Arc arc = Arc.Create(line1.GetEndPoint(1), line2.GetEndPoint(0), new XYZ(7, 0, 0));
bendingProfile.Append(line1);
bendingProfile.Append(arc);
bendingProfile.Append(line2);
ElementId fabricSheetTypeId = document.GetDefaultElementTypeId(ElementTypeGroup.FabricSheetType);
FabricSheetType fst = document.GetElement(fabricSheetTypeId) as FabricSheetType;
fst.SetMajorLayoutAsFixedNumber(12.0, 1.0, 0.8, 4);
fst.SetMinorLayoutAsMaximumSpacing(10.0, .75, .90, 3.0);
FabricSheet bentFabricSheet = FabricSheet.Create(document, column.Id, fabricSheetTypeId, bendingProfile);
// Regeneration is required before setting any property to object that was created in the same transaction.
document.Regenerate();
bentFabricSheet.BentFabricBendDirection = BentFabricBendDirection.Major;
AnalyticalMember amc = (AnalyticalMember)document.GetElement(AnalyticalToPhysicalAssociationManager.GetAnalyticalToPhysicalAssociationManager(document)
.GetAssociatedElementId(column.Id));
bentFabricSheet.PlaceInHost(column, amc.GetTransform());
// Give the user some information
TaskDialog.Show("Revit", string.Format("Bent Fabric Sheet ID='{0}' created successfully.", bentFabricSheet.Id.IntegerValue));
return bentFabricSheet;
}
## Bent fabric sheets
The IsBent property indicates if the fabric sheet is a bent fabric sheet or not. It is not possible to convert a Fabric Sheet between flat and bent.
You may obtain the curves for a bent sheet or set new curves by calling GetBendProfile() or SetBendProfile() respectively. Code Region: Change the bend profile of a fabric sheet
---
private void ModifyBentFabricSheet(Document document, FabricSheet bentFabricSheet)
{
CurveLoop newBendingProfile = CurveLoop.CreateViaOffset(bentFabricSheet.GetBendProfile(), 0.5, new XYZ(0, 0, -1));
bentFabricSheet.SetBendProfile(newBendingProfile);
// Give the user some information
TaskDialog.Show("Revit", string.Format("Bent Fabric Sheet ID='{0}' modified successfully.", bentFabricSheet.Id.IntegerValue));
}
The GetSegmentParameterIdsAndLengths() method will return a dictionary with segment parameter ids as the keys and length as the values. These correspond to segments of a bent fabric sheet (like A, B, C, D etc.), but are not in alphabetical or any other order. (An empty dictionary is returned for flat fabric sheets.) To set the length of a bent fabric sheet segment, use SetSegmentLength(). Code Region: Get segment ids and lengths
---
private void GetBentFabricSheetData(FabricSheet fabricSheet)
{
string fabricNumber = fabricSheet.FabricNumber;
IDictionary<ElementId, double> idsAndLengths = fabricSheet.GetSegmentParameterIdsAndLengths(true);
StringBuilder displayInfo = new StringBuilder();
displayInfo.AppendLine(string.Format("Parameter Ids and segment lengths for FabricSheet {0}:", fabricNumber));
foreach (ElementId key in idsAndLengths.Keys)
{
displayInfo.AppendLine(string.Format("Parameter Id: {0}, Length: {1}", key, idsAndLengths[key]));
}
TaskDialog.Show("Revit", displayInfo.ToString());
}
The FabricNumber property used in the example above, specifies the numerical parameter assigned to the fabric sheet and any sheet of the same type, dimension, material, shape, and partition.
**Parent page:** [Reinforcement](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_html.html)

View File

@@ -0,0 +1,138 @@
# Rebar Containers
# Rebar Containers
Rebar Containers are elements which represent an aggregation of rebars in one host. This element can only be created via the API.
The advantages of using the RebarContainer element are:
* Defining new types of rebar distributions not possible with the Revit user interface
* Improve rebar performance by combining multiple rebar sets into the definition of a single element
* The bars dont react to the hosts geometry modifications
Each RebarContainer contains a collection (empty when first created) of RebarContainerItem objects. RebarContainerItem provides properties and methods similar to that of a Rebar element.
## Creating a new RebarContainer
You may use the static method RebarContainer.Create() which requires the Document in which you want to create a new RebarContainer, the host Element which will host the new RebarContainer and the ElementId of the RebarContainerType which will be assigned to the new RebarContainer.
The following example creates a new rebar container and specifies that any items in the container will be presented as subelements in schedules and tags.
**Code Region: Creating a rebar container**
---
RebarContainer CreateRebarContainer(Autodesk.Revit.DB.Document document, FamilyInstance beam)
{
// Create a new rebar container
ElementId defaultRebarContainerTypeId = RebarContainerType.CreateDefaultRebarContainerType(document);
RebarContainer container = RebarContainer.Create(document, beam, defaultRebarContainerTypeId);
// Any items for this container should be presented in schedules and tags as separate subelements
container.PresentItemsAsSubelements = true;
return container;
}
## Filling a RebarContainer
Once you have a new RebarContainer object, you can fill it up with RebarContainerItems by calling one of the following methods on the RebarContainer object:
* AppendItemFromRebar() - Appends a RebarContainerItem to the collection using properties of the Rebar element used to create it.
* AppendItemFromCurves() - Appends a RebarContainerItem to the collection from a list of curves using properties from the specified RebarBarType.
* AppendItemFromRebarShape() - Appends a RebarContainerItem to the collection using properties from the specified RebarBarType and RebarShapeType.
* AppendItemFromCurvesAndShape() - Appends a RebarContainerItem to the collection from a list of curves using properties from the specified RebarBarType and RebarShapeType. Note that in creating the container items, you will often be required to specify the normal of the plane in which the curves exist. This normal also defines the direction of multiple rebar creation if you set the layout rules to anything other than single. If you set the RebarContainerItem to a FixedNumber layout rule, for instance, those additional bars will be distributed along a line perpendicular to the plane you specify when creating the RebarContainerItem. In this sense the Normal also serves as the direction of distribution for RebarContainerItems with layout rules applied.
## Accessing RebarContainerItems
Use the method RebarContainer.Contains() to query whether the particular RebarContainerItem exists in the RebarContainer.
RebarContainer provides methods to remove individual items, clear all items, get specific items and return the count of RebarContainerItems in the container. The SetItemHiddenStatus() method controls whether specific items in the container are hidden in a specific view or not, and IsItemHidden() identifies if an items is hidden in a view.
**Code Region: Adding items to a rebar container**
---
void AddItemsToRebarContainer(RebarContainer container, FamilyInstance beam, RebarBarType barType, RebarHookType hookType)
{
// Define the rebar geometry information - Line rebar
LocationCurve location = beam.Location as LocationCurve;
XYZ origin = location.Curve.GetEndPoint(0);
// create rebar along the length of the beam
XYZ rebarLineEnd = location.Curve.GetEndPoint(1);
Line line = Line.CreateBound(origin, rebarLineEnd);
XYZ normal = new XYZ(1, 0, 0);
Curve rebarLine = line.CreateOffset(0.5, normal);
// Create the line rebar
IList<Curve> curves = new List<Curve>();
curves.Add(rebarLine);
RebarContainerItem item = container.AppendItemFromCurves(RebarStyle.Standard, barType, hookType, hookType, normal, curves, RebarTerminationOrientation.Right, RebarTerminationOrientation.Left, true, true);
if (null != item)
{
// set specific layout for new rebar as fixed number, with 10 bars, distribution path length of 1.5'
// with bars of the bar set on the same side of the rebar plane as indicated by normal
// and both first and last bar in the set are shown
item.SetLayoutAsFixedNumber(10, 1.5, true, true, true);
}
// Hide the new item in the active view
container.SetItemHiddenStatus(container.Document.ActiveView, item.ItemIndex, true);
}
## RebarContainerType
Rebar Containers will have types. These types are agnostic to the individual RebarContainerItems contained in them but will afford access to the Container's parameters at the type level. It is a required argument for creation of a new RebarContainer. Obtain a default by calling the static method RebarContainerType.CreateDefaultRebarContainerType() to obtain the ElementId of a RebarContainerType if the desired one does not exist in the database.
## RebarContainer parameters management
Because the RebarContainer may contain several different configurations of individual RebarContainerItems, the overall RebarContainer parameters will be derived from the contained RebarContainerItem members if possible. If the parameter exists on all RebarContainerItems and it is the same across all RebarContainerItems in the RebarContainer then the RebarContainer parameter will show this value. If they are different, or do not exist on all RebarContainerItems in the Container, the parameter will display without value.
To allow you to manage this and specify necessary parameters for the RebarContainer as a whole, you may request the RebarContainerParameterManager from the RebarContainer calling the method GetParametersManager() which will return an object you can use to override the parameters of the RebarContainer. As an example, TotalLength in a RebarContainer with multiple RebarContainerItems with differing lengths, will show an empty parameter for TotalLength. You can call the RebarContainerParametersManager method AddOverride() which has 4 overloads so that you can override the value of any of four value types of parameters (ElementId, Double, Integer, String). Use the method IsRebarContainerParameter() to determine if the parameter is a RebarContainer parameter before attempting to add an override for the parameter.
You can also add a shared parameter as an override to a RebarContainer by calling the method AddSharedParameterAsOverride() and passing in the id of the shared parameter. Check to see that the parameter has not already been added to the RebarContainer before calling this method.
You may remove overrides by calling the method RemoveOverride() or remove all overrides by calling ClearOverrides().
Individual overridden parameters may be set to be modifiable or read only by calling the methods SetOverriddenParameterModifiable() or SetOverriddenParameterReadonly() and query the same with the IsOverriddenParameterModifiable() method.
Lastly, to check if a RebarContainer parameter is overridden, call the method IsParameterOverridden() passing in the ElementId of the parameter in question.
**Code Region: RebarContainer parameters management**
---
void ManageParameters(RebarContainer container)
{
RebarContainerParameterManager paramManager = container.GetParametersManager();
Parameter aParam = container.LookupParameter("A");
if (aParam != null)
{
paramManager.AddOverride(aParam.Id, 0.4);
paramManager.SetOverriddenParameterModifiable(aParam.Id);
}
}
## RebarContainerItems
Rebar container items offer many of the same properties as do Rebar elements. They are a much lighter representation of a modeled rebar and unlike the Rebar class which is derived from Element, RebarContainerItem is derived from the IDisposable Interface.
You may redefine the RebarContainerItem represented by any RebarContainerItem by calling the class methods available on RebarContainerItem objects:
* SetFromRebar()
* SetFromCurves()
* SetFromRebarShape()
* SetFromCurvesAndShape() These methods mimic the methods which were used on RebarContainer to create the RebarContainerItem in the first place and have identical or nearly identical arguments which can be used to modify any RebarContainerItem in the RebarContainer.
You may query the RebarBarType ID with the class property BarTypeId. In order to apply a different RebarBarType to the RebarContainerItem you must use the SetFrom methods on the RebarContainerItem (i.e. SetFromCurves() or SetFromRebar()).
**Parent page:** [Reinforcement](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_html.html)

View File

@@ -0,0 +1,153 @@
# Rebar Couplers
# Rebar Couplers
Rebar couplers are used to connect adjacent rebar.
## Creating couplers
Couplers can connect two adjacent rebar or cap the end of a single rebar. Couplers are represented by the RebarCoupler class. The static Create() method can be used to create new couplers.
The following example creates a coupler to connect two adjacent single rebar bars. The Create() method needs the ElementId of a coupler type and the RebarReinforcementData for the two rebars to connect. **Code Region: Creating a rebar coupler**
---
private RebarCoupler CreateCoupler(Document doc, List<Rebar> bars)
{
RebarCoupler coupler = null;
// if we have at least 2 bars, create a coupler between them
if (bars.Count > 1)
{
// get a type id for the Coupler
ElementId defaultTypeId = doc.GetDefaultFamilyTypeId(new ElementId(BuiltInCategory.OST_Coupler));
if (defaultTypeId != ElementId.InvalidElementId)
{
// Specify the rebar and ends to couple
RebarReinforcementData rebarData1 = RebarReinforcementData.Create(bars[0].Id, 0);
RebarReinforcementData rebarData2 = RebarReinforcementData.Create(bars[1].Id, 1);
RebarCouplerError error;
coupler = RebarCoupler.Create(doc, defaultTypeId, rebarData1, rebarData2, out error);
if (error != RebarCouplerError.ValidationSuccessfuly)
{
TaskDialog.Show("Revit", "Create Coupler failed: " + error.ToString());
}
// Use a coupler to cap the other end of the first bar
RebarReinforcementData rebarData = RebarReinforcementData.Create(bars[0].Id, 1);
RebarCoupler.Create(doc, defaultTypeId, rebarData, null, out error);
if (error != RebarCouplerError.ValidationSuccessfuly)
{
TaskDialog.Show("Revit", "Create Coupler failed: " + error.ToString());
}
}
}
return coupler;
}
If the coupler cannot be created, a RebarCouplerError enum will be returned. Some reasons the creation may fail include bars not touching, different layouts between the rebar sets, or the bars may be the wrong diameter for the coupler.
The CouplerLinkTwoBars() method will return true if the coupler connects two rebars, or false it if only caps one rebar.
The Rebar class has a GetCouplerId() method to get the id of the a coupler attached to either end of the rebar.
## Coupler location and Angle
To get the location point or points (in the case of a rebar set), call the GetPointsForPlacement() method, which returns a list of XYZ points indicating where the coupler (or couplers) are placed. The GetCouplerPositionTransform() method will return a transform representing the relative position of the coupler at a specified index in the set. The index should be between 0 and the coupler quantity - 1. GetCouplerQuantity() will return the quantity of couplers in the set.
`RebarCoupler.RotationAngle` identifies the rotation angle of the coupler around its axis.
## Numbering
RebarCoupler is one of the categories of elements whose numbering can be controlled via the Revit API. The NumberingSchema and NumberingSchemaType classes can be used to define how coupler elements are to be organized for the purpose of numbering/tagging them. Each NumberingSchema controls numbering of elements of one particular kind. Instances of NumberingSchema are also elements and there is always only one of each type in every Revit document. Available types of all built-in numbering schemas are enumerated in NumberingSchemaTypes class.
Elements (e.g., RebarCoupler) belonging to a particular schema (e.g., NumberingSchemaTypes.StructuralNumberingSchemas.RebarCoupler) are organized and numbered in sequences. A sequence is a collection of elements that share the same numbering partition as defined by their respective values of the Partition parameter (NUMBER_PARTITION_PARAM). A numbering sequence must contain at least one element. In other words, a sequence is established once there is at least one element of which the partition parameter has a value that differs from other elements (in the same numbering schema). If the last element is removed (deleted or moved to a different sequence) then the empty sequence ceases to exist.
## End Treatments
The end treatment for a rebar bar comes from the coupler attached to it. The end treatment type for both ends of the coupler is specified by the coupler family type.
The overloaded EndTreatmentType.Create() method can be used to create a new EndTreatmentType with or without a string to specify the end treatment name. The CreateDefaultEndTreatmentType() method creates a new EndTreatmentType with a default name.
To access the end treatment type for a RebarCoupler, use the BuiltInParameters COUPLER_MAIN_ENDTREATMENT to set End Treatment 1 and COUPLER_COUPLED_ENDTREATMENT to set End Treatment 2 for the FamilySymbol representing the rebar coupler type. The example below creates a new EndTreatmentType and assigns it to End Treatment 1 for the coupler type. An existing EndTreatmentType can also be used.
**Code Region: Change EndTreatmentType for RebarCoupler**
---
private void NewEndTreatmentForCouplerType(Document doc, ElementId couplerTypeId)
{
EndTreatmentType treatmentType = EndTreatmentType.Create(doc, "Custom");
FamilySymbol couplerType = doc.GetElement(couplerTypeId) as FamilySymbol;
Parameter param = couplerType.GetParameter(ParameterTypeId.CouplerMainEndtreatment);
param.Set(treatmentType.Id);
}
An end treatment can be defined in a RebarShape to define the shapes that have specific treatments at the ends. The end treatment in the RebarShape is used for shape recognition. The user defines the shapes according to their specifications and when a coupler is placed on a bar, it automatically searches for the right RebarShape, if the ReinforcementSettings.RebarShapeDefinesEndTreatments property is set to true. Note that this property can only be set before any rebar or reinforcement are added to the document.
**Code Region: Set and EndTreatmentType for a RebarShape**
---
private bool SetEndTreatmentType(Document doc, RebarShape rebarShape)
{
bool set = false;
// check if end treatments are defined by rebar shape
ReinforcementSettings settings = ReinforcementSettings.GetReinforcementSettings(doc);
if (settings.RebarShapeDefinesEndTreatments)
{
EndTreatmentType treatmentType = EndTreatmentType.Create(doc, "Flame Cut");
rebarShape.SetEndTreatmentTypeId(treatmentType.Id, 0);
ElementId treatmentTypeId = EndTreatmentType.CreateDefaultEndTreatmentType(doc);
rebarShape.SetEndTreatmentTypeId(treatmentTypeId, 1);
set = true;
}
else
{
try
{
// can only be changed if document contains no rebars, area reinforcement or path reinforcement
settings.RebarShapeDefinesEndTreatments = true;
}
catch (Exception e)
{
// cannot change the settings value
TaskDialog.Show("Revit", e.Message);
}
}
return set;
}
The RebarShape class has methods to determine if it has end treatments, and methods to get and set the EndTreatmentType for both ends of the RebarShape.
Note that Rebar Couplers cant be placed on Area, Path, or Rebar Container.
**Code Region: Get end treatments for Rebar**
---
private void ListEndTreatments(Document doc, List<Rebar> bars)
{
StringBuilder info = new StringBuilder();
for (int n = 0; n < bars.Count; n++)
{
// get end treatment for both ends of bar
for (int i = 0; i < 2; i++)
{
ElementId treatmentTypeId = bars[n].GetEndTreatmentTypeId(i);
if (treatmentTypeId != ElementId.InvalidElementId)
{
EndTreatmentType treatmentType = doc.GetElement(treatmentTypeId) as EndTreatmentType;
info.AppendLine(string.Format("End treatment for bar {0} end {1}: {2}", n, i, treatmentType.EndTreatment));
}
}
}
TaskDialog.Show("Revit", info.ToString());
}
**Parent page:** [Reinforcement](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_html.html)

View File

@@ -0,0 +1,387 @@
# Rebar
# Rebar
The Rebar class represents rebar used to reinforce suitable elements, such as concrete beams, columns, slabs or foundations.
## Shape Driven and Free Form Rebar
There are two kind of rebar Shape Driven and Free Form. Shape Driven Rebar is Rebar that is driven by a shape. Free Form rebar is driven by curves. Free Form Rebar can be constructed in two ways: from curves (which will not have constraints) and the second option with a server that will allow the rebar to have constraints. The server will also allow the API user the possibility to implement how the rebar curves are calculated based on the constraints. This allows API developers to create their own kind of Rebar.
### Distribution Path
RebarHandlePositionData.GetDistributionPath() gets the distribution path currently stored in the rebar.
For a free form rebar set, the distance between two consecutive bars may be different if it is calculated between different points on bars. The distribution path is an array of curves with the property that based on these curves the set was calculated to respect the layout rule and number of bars or spacing.
## Creating rebar
Free Form Rebar can be created with the Rebar.CreateFreeForm() methods. Shape Driven Rebar can be created using Rebar.CreateFromCurves(), Rebar. CreateFromRebarShape() or Rebar. CreateFromCurvesAndShape().
### Creating shape driven rebar with a specific layout
The following code illustrates how to create Rebar with a specific layout. Rebar CreateRebar(Autodesk.Revit.DB.Document document, FamilyInstance column, RebarBarType barType, RebarHookType hookType)
{
// Define the rebar geometry information - Line rebar
LocationPoint location = column.Location as LocationPoint;
XYZ origin = location.Point;
XYZ normal = new XYZ(1, 0, 0);
// create rebar 9' long
XYZ rebarLineEnd = new XYZ(origin.X, origin.Y, origin.Z + 9);
Line rebarLine = Line.CreateBound(origin, rebarLineEnd);
// Create the line rebar
IList<Curve> curves = new List<Curve>();
curves.Add(rebarLine);
// Bar Terminations
BarTerminationsData barTerminationsData = new BarTerminationsData(document);
Rebar rebar = Rebar.CreateFromCurves(document, RebarStyle.Standard, barType, hookType, hookType, column, normal, curves, barTerminationsData, true, true);
if (null != rebar)
{
// set specific layout for new rebar as fixed number, with 10 bars, distribution path length of 1.5'
// with bars of the bar set on the same side of the rebar plane as indicated by normal
// and both first and last bar in the set are shown
rebar.GetShapeDrivenAccessor().SetLayoutAsFixedNumber(10, 1.5, true, true, true);
}
return rebar;
}
### Free Form Rebar creation
Free Form Rebar can be created using server GUIDS.
The static properties:
* Rebar.FreeFormAlignedServerGuid
* Rebar.FreeFormSurfaceServerGuid
return the GUID of the to-be-used external IRebarUpdateServer for computing Aligned or Surface Free Form Rebar.
The enums:
* SurfaceDistributionRebarHandles
* AlignedDistributionRebarHandles
correspond to the values that might be returned by RebarConstrainedHandle.GetCustomHandleTag() for Aligned or Surface Free Form Rebar.
Shape Driven rebar objects can be created using static Rebar methods. The method `RebarHostData.IsReferenceContainedByAValidHost()` identifies if an element that contains the given reference can host reinforcement.
**Name** | **Description**
---|---
public static Rebar Rebar.CreateFromCurves(
public static Rebar.CreateFromCurves(
Document doc,
RebarStyle style,
RebarBarType barType,
Element host, XYZ norm,
IList<Curve> curves,
BarTerminationsData barTerminationsData,
bool useExistingShapeIfPossible,
bool createNewShape)
);
| Creates a new instance of a Rebar element within the project. All curves must belong to the plane defined by the normal and origin.
public static Rebar Rebar.CreateFromRebarShape(
Document doc,
RebarShape rebarShape,
RebarBarType rebarType,
Element host,
XYZ origin,
XYZ xVec,
XYZ yVec
);
| Creates a new Rebar, as an instance of a RebarShape. The instance will have the default shape parameters from the RebarShape, and its location is based on the bounding box of the shape in the shape definition. Hooks are removed from the shape before computing its bounding box. If appropriate hooks can be found in the document, they will be assigned arbitrarily.
public static Rebar Rebar.CreateFromCurvesAndShape(
public static Rebar.CreateFromCurvesAndShape(
Document doc,
RebarShape rebarShape,
RebarBarType barType,
Element host,
XYZ norm,
IList<Curve> curves,
BarTerminationsData barTerminationsData)
);
| Creates a new instance of a Rebar element within the project. The instance will have the default shape parameters from the RebarShape. All curves must belong to the plane defined by the normal and origin.
The first version creates rebar from an array of curves describing the rebar, while the second creates a Rebar object based on a RebarShape and position. The third version creates rebar from an array of curves and based on a RebarShape.
When using the CreateFromCurves() or CreateFromCurvesAndShape() method, the parameters RebarBarType and RebarHookType are available in the RebarBarTypes and RebarHookTypes properties of the Document.
The following code illustrates how to create Rebar with a specific layout.
**Creating rebar with a specific layout**
---
Rebar CreateRebar(Autodesk.Revit.DB.Document document, FamilyInstance column, RebarBarType barType, RebarHookType hookType)
{
// Define the rebar geometry information - Line rebar
LocationPoint location = column.Location as LocationPoint;
XYZ origin = location.Point;
XYZ normal = new XYZ(1, 0, 0);
// create rebar 9' long
XYZ rebarLineEnd = new XYZ(origin.X, origin.Y, origin.Z + 9);
Line rebarLine = Line.CreateBound(origin, rebarLineEnd);
// Create the line rebar
IList<Curve> curves = new List<Curve>();
curves.Add(rebarLine);
Rebar rebar = Rebar.CreateFromCurves(document, Autodesk.Revit.DB.Structure.RebarStyle.Standard, barType, hookType, hookType, column, origin, curves, RebarTerminationOrientation.Right, RebarTerminationOrientation.Left, true, true);
if (null != rebar)
{
// set specific layout for new rebar as fixed number, with 10 bars, distribution path length of 1.5'
// with bars of the bar set on the same side of the rebar plane as indicated by normal
// and both first and last bar in the set are shown
rebar.GetShapeDrivenAccessor().SetLayoutAsFixedNumber(10, 1.5, true, true, true);
}
return rebar;
}
Note: For more examples of creating rebar elements, see the Reinforcement and NewRebar sample applications included with the Revit SDK.
The following table lists the integer value for the Parameter REBAR_ELEM_LAYOUT_RULE:
**Rebar Layout Rule**
**Value** | **0** | **1** | **2** | **3** | **4**
---|---|---|---|---|---
Description | Single | Fixed Number | Maximum Spacing | Number with Spacing | Minimum Clear Spacing
Rebar.GetShapeDrivenAccessor().ScaleToBox() takes the shape and scales it to fit the box defined by an origin and two vectors that define the edges of a rectangle.
Clear cover is associated with individual faces of valid rebar hosts. You can access the cover settings of a host through the Autodesk.Revit.Elements.RebarHostData object. A simpler, less powerful mechanism for accessing the same settings is provided through parameters.
Cover is defined by a named offset distance, modeled as an element Autodesk.Revit.DB.Structure.RebarCoverType.
### Free Form Rebar Space Event
The API allows you to control the behavior of free form rebar when the user pushes the <space> key by using these methods:
* `RebarFreeFormAccessor.CycleCounter()` \- This property Identifies the cycle counter. It can be zero or a positive number. Its value is changed when the free form Rebar element is selected and the user press Space key, or-through the setter of this property or- by the server if it considers that the counter reaches the maximum value and reset it (set it to 0). property can be accessed just for Rebars that are controlled by a server.
* `RebarUpdateCurvesData.CycleCounterChanged()` \- True if the cycle counter was changed, false otherwise. The cycle counter value is changed when the free form Rebar element is selected and the user press Space key -or- by through RebarRebarFreeFormAccessor.CycleCounter property or- by the server if it considers that the counter reaches the maximum value and reset it (set it to 0).
* `RebarUpdateCurvesData.GetCycleCounter()` \- Gets the cycle counter that is stored in the rebar.
* `RebarUpdateCurvesData.SetCycleCounter()` \- Sets the cycle counter to a specific value during the execution of the server. The actual value will be set into the Rebar element after the free form server curve computation is completed.
## Aligned Free form Rebar
Aligned Free form rebar can be aligned to the distribution path, to keep the bars vertical, parallel, or perpendicular to a face.
* RebarFreeFormAccessor.hasValidAlignedServer() - Returns true if the current rebar is created with the Aligned Free Form rebar server, false otherwise.
* RebarFreeFormAccessor.AlignedFreeFormSetOrientationOptions() - Orientation options for an Aligned Free Form Rebar set.
* RebarFreeFormAccessor.AlignedFreeFormSetOrientationOptions - The enum has the following values.
* AlignedToDistributionPath - Cutting planes are perpendicular to the distribution path.
* Vertical - Cutting planes are oriented vertically, X or Y vector being Z axis.
* ParallelToFace - Cutting planes are parallel to a selected planar face.
* PerpendicularToFace - Cutting planes are oriented perpendicular to a selected planar face, X or Y vector being the face normal.
## Copying / Propagating Rebar to a new host
Methods in the `RebarPropagation` class allow rebar to be copied from one host element to a different host element with similar geometry. It copies the source rebars, aligns them to the destination face based on their alignment with the source face, and adapts them to destination host. The propagation is done based on a destination host element where the new rebar will be hosted or a destination face.
## Moving individual rebar in a Rebar Set
The methods `Rebar.MoveBarInSet()`, `Rebar.GetBarIndexFromReference()`, `Rebar.GetMovedBarTransform()`, and `Rebar.ResetMovedBarTransform()` allow an application to move an individual bar and to read and reset the transform of the individual bar in a Rebar Set.
## Removing individual bars from a Rebar Set
`Rebar.SetBarIncluded(bool, int)` allows you to designate that the bar at a given index will be included or excluded. Setting `Rebar.IncludeFirstBar(bool)` and `Rebar.IncludeLastBar(bool)` are equivalent to removing the bar at the first or last position index.
`Rebar.DoesBarExistAtPosition(int)` can be used to find if the bar at any position index is included or excluded.
## Geometry
The methods `Rebar.GetTransformedCenterlineCurves()` and `RebarInSystem.GetTransformedCenterlineCurves()` return the centerline curves for a given bar, where the geometry of the curves are in the actual transformed position. The `BarPositionTransform` (representing the relative position of any individual bar in the set - a translation along the distribution path)and `MovedBarTransform` (representing the movement of the bar relative to its default position along the distribution path) will be applied to the returned curves.
## Numbering
Rebar is one of the categories of elements whose numbering can be controlled via the Revit API. The NumberingSchema and NumberingSchemaType classes can be used to define how rebar elements are to be organized for the purpose of numbering/tagging them. Each NumberingSchema controls numbering of elements of one particular kind. Instances of NumberingSchema are also elements and there is always only one of each type in every Revit document. Available types of all built-in numbering schemas are enumerated in NumberingSchemaTypes class.
Elements (e.g., Rebar) belonging to a particular schema (e.g., NumberingSchemaTypes.StructuralNumberingSchemas.Rebar) are organized and numbered in sequences. A sequence is a collection of elements that share the same numbering partition as defined by their respective values of the Partition parameter (NUMBER_PARTITION_PARAM). A numbering sequence must contain at least one element. In other words, a sequence is established once there is at least one element of which the partition parameter has a value that differs from other elements (in the same numbering schema). If the last element is removed (deleted or moved to a different sequence) then the empty sequence ceases to exist.
Elements get assigned to sequences either upon their creation (based on the then current numbering partition value), by explicitly modifying the Partition parameter of an element, or by using the AssignElementsToSequence() method. The AssignElementsToSequence() method is preferred over explicitly changing the Partition parameter, because the method applies changes to sequences and element numbers immediately, while changed parameters only go into effect after the current transaction is closed.
In addition to directly or indirectly changing the Partition parameter of elements, numbering sequences can be reorganized by using methods of the NumberingSchema class. The MoveSequence() method moves all elements of an existing sequence to a new sequence that does not exist yet in the schema, thus effectively renaming the Partition parameter on all the affected elements. The AppendSequence() method removes all elements from one sequence and appends them to elements of another existing sequence while applying the matching policy. The method MergeSequences() takes elements of all specified sequences and moves them all into a newly created sequence. All the merged elements will be renumbered and matched as needed based on the matching algorithm.
The property:
* ReinforcementSettings.NumberingMethod provides access to the setting for how varying length bars are numbered.
The sample below uses the MoveSequence() method to swap numbers for Rebar in two numbering sequences.
Code Region: Swap numbers
---
/// <summary>
/// This method uses multiple moving operations to swap numbers
/// for Rebars in two numbering sequences. The sequences are
/// identified by the names of two numbering partitions.
/// </summary>
/// <param name="document">Document to modify</param>
/// <param name="part1">Name of the partition of one numbering sequence</param>
/// <param name="part2">Name of the partition of another numbering sequence</param>
private void SwapNumberingSequences(Document document, string part1, string part2)
{
// Obtain a schema object for a particular kind of elements
NumberingSchema schema = NumberingSchema.GetNumberingSchema(document,NumberingSchemaTypes.StructuralNumberingSchemas.Rebar);
using (Transaction transaction = new Transaction(document))
{
// Changes to numbering sequences must be made inside a transaction
transaction.Start("Swap Numbering Sequences");
// We will use a temporary partition for the swap operation,
// for the move operation only works if the target partition
// does not exist yet in the same numbering schema.
// (We assume this TEMPORARY partition does not exist.)
string tempPartition = "TEMPORARY";
// Step 1
// First we move all elements from one sequence into
// a partition we know does not exist. This action will
// create the temporary partition and remove the original
// one (part1).
schema.MoveSequence(part1, tempPartition);
// Step 2
// With the sequence in partition 'part1' removed
// we can now move elements from the second sequence to it.
// This action will re-create a sequence in partition 'part1'
// and remove the sequence in partition 'part2'
schema.MoveSequence(part2, part1);
// Step 3
// Finally, we can move elements 'parked' in the temporary
// sequence to partition 'part2', for that partition was
// removed in the previous step and thus can now be created
// again. The temporary partition will be automatically
// removed upon completing this step.
schema.MoveSequence(tempPartition, part2);
transaction.Commit();
}
}
Elements in different sequences are numbered independently, meaning that there may be elements with the same number in two sequences even though the elements are different. Likewise, there may be perfectly identical elements in two or more sequences bearing different numbers. However, within each one numbering sequence any two identical elements will always have the same number, while different elements will never have the same number within a numbering sequence.
Enumerable elements are always numbered automatically upon their creation. Each new element will get an incrementally higher number. However, new elements that match existing elements within the same sequence will get the same number assigned. Elements will keep their assigned numbers as long as it is possible. This means, for example, that if some previously created rebar elements get deleted, all remaining elements (within the same numbering sequence) will keep their numbers, which may result in gaps in the respective numbering sequence. Gaps can be removed by invoking RemoveGaps() for sequences in which gaps are not desired.
The following example consolidates the numbers on Rebar elements by removing any remaining gaps in numbering sequences and setting the start number of each sequence so numbers in sequences do not overlap.
Code Region: Consolidate Rebar numbers
---
private void ConsolidateRebarNumbers(Document document)
{
// Obtain a schema object for a particular kind of elements
NumberingSchema schema = NumberingSchema.GetNumberingSchema(document,NumberingSchemaTypes.StructuralNumberingSchemas.Rebar);
// Collect the names of partitions of all the numbering sequences currently contained in the schema
IList<string> sequences = schema.GetNumberingSequences();
using (Transaction transaction = new Transaction(document))
{
// Changes to numbers must be made inside a transaction
transaction.Start("Consolidate Rebar Numbers");
// First we make sure numbers in all sequences are consecutive
// by removing possible gaps in numbers. Note: RemoveGaps does
// nothing for a sequence where there are no gaps present.
// We also want to find what the maximum range of numbers is
// of all the sequences (the one the widest span of used numbers)
int maxRange = 0;
foreach (string name in sequences)
{
schema.RemoveGaps(name);
// Here we use First() from the Linq extension.
// There is always at least one range in every sequence,
// and after gaps are closed there is exactly one range.
IntegerRange range = schema.GetNumbers(name).First();
int rangeSpan = 1 + (range.High - range.Low);
if (rangeSpan > maxRange)
{
maxRange = rangeSpan;
}
}
// Next we give sequences different start numbers
// starting with 100 and then stepping by at least
// the maximum range we found in the previous step
int startNumber = 100;
// We round the range up to the closest 100
int step = 100 * (int)((maxRange + 99) / 100.0);
foreach (string name in sequences)
{
schema.ShiftNumbers(name, startNumber);
startNumber += step;
}
transaction.Commit();
}
}
Numbers are stored as values of a numbering parameter on each numbered element. The Id of the parameter is obtained by querying the NumberingSchema.NumberingParameterId property. The value of the number can be obtained by querying the parameter for the respective numbered element. The value is read-only and thus cannot be set; it is always computed based on relations of elements across numbering partitions and the matching policy within the numbering sequence of each element.
Even though numbers are always assigned automatically to all elements of a schema, the method ChangeNumber() gives the programmer a way to explicitly overwrite a specific number as long as the new number is unique in the numbering sequence. The caller specifies a number to be changed and a new value that is to be applied, providing the value does not exist yet in the same numbering sequence.
## Distribution type
Shape Driven Rebar can be uniform or have varying lengths. The property RebarShapeDrivenAccessor.UseRebarConstraintsToProduceVaryingBars identifies if the rebar constraints should be used to compute each bar in set (which can produce varying length bars). The property Rebar.HasVariableLengthBars identifies if a set has varying length bars or not.
## Bar Type Diameter
The options classBarTypeDiameterOptions allows creation of a new set of diameter values for a RebarBarType. It can be used when copying the diameter information as a bulk of data from one RebarBarType to another.
The diameter options can be set for a RebarBarType with RebarBarType.SetBarTypeDiameters() which sets all input diameters from the input BarTypeDiameterOptions in the current RebarBarType.
## Constraints
The RebarConstraint class represents a constraint on a handle of a rebar element.
For Shape Driven Rebar Constraints, Each handle on a rebar is defined by a plane, and can be constrained along the direction perpendicular to the plane. Rebar constraints work by locking the handle planes to planar references, or 'targets.'
For Free Form Rebar Constraints, each handle of the Rebar can be constrained to multiple host faces or to the face cover.
The RebarConstraintsManager provides information about the constraints (RebarConstraints) acting on the shape handles (RebarConstrainedHandles) of a Rebar element. It can also be used to modify the constraints.
To identify the direction for a positive offset value for a Rebar-to-Rebar constraint RebarConstraint, use `GetPositiveOffsetDirectionForToOtherRebarConstraint()` which returns the positive offset direction vector. This is available only for constraints of type RebarConstraintType.ToOtherRebar. This is the same vector shown in the UI as an arrow representing the direction of a positive offset value.
### Rebar Constraint Relationship
The method RebarConstraint.GetTargetRebarHandleBehavior() gets the RebarHandleBehavior of the handle of the other Rebar Element to which this RebarConstraint is attached. (The RebarConstraintType of the RebarConstraint must be 'ToOtherRebar').
## Rebar conversion
The methods `AreaReinforcement.ConvertRebarInSystemToRebars()` and `PathReinforcement.ConvertRebarInSystemToRebars()` convert all of the RebarInSystem elements owned by the input element into equivalent Rebar elements.
**Parent page:** [Reinforcement](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_html.html)

View File

@@ -0,0 +1,37 @@
# Reinforcement Rounding
# Reinforcement Rounding
Reinforcement rounding is important for preparation of construction documents. You can use numerical rounding of rebar lengths to simplify organization and annotation when tagging, filtering, or scheduling rebar.
Revit enables overriding of three different reinforcement parameters: Fabric Sheet lengths, Rebar total lengths, and Rebar segment lengths. Rebar segment lengths are the individual segments which make up a rebar shape.
The application of Rebar and/or Fabric Sheet rounding is controlled initially at the Document level. If rounding is not enabled at the document level, the rounding for Reinforcement Length (structural unit settings) will be applied to rebar lengths in schedules and tags. If the Document level reinforcement settings are overridden then the rebar settings control rounding for rebars and fabric sheets and may be overridden further at the type and element level.
## Overriding reinforcement rounding settings
The ReinforcementSettings class provides methods to obtain either the fabric or rebar rounding managers by calling GetFabricRoundingManager() or GetRebarRoundingManager() respectively. These rounding managers represent the document level rounding overrides and will control rounding for any types or elements which are not otherwise overridden by accessing the corresponding rounding manager for the type or element in question.
Reinforcement rounding override is enabled by setting the ReinforcementRoundingManager.IsActiveOnElement property to true at the document level. This property must be set to true before attempting to override the reinforcement rounding settings for the document, a type, or an element.
The ReinforcementRoundingManager has two derived classes, FabricRoundingManager and RebarRoundingManager, to handle overrides for these different types of elements. FabricRoundingManager is used for managing reinforcement rounding override settings used by FabricSheetType and FabricSheet elements while RebarRoundingManager is used for managing reinforcement rounding override settings used by RebarBarTypes, Rebar and RebarInSystem elements.
To override reinforcement rounding settings for a rebar type, call Rebar.GetReinforcementRoundingManager() to get a reference to a RebarRoundingManager. Once you have access to the RebarRoundingManager, to override the rounding settings, first set RebarRoundingManager.IsActiveOnElement to true before attempting to set any of the rounding properties.
RebarRoundingManager.TotalLengthRounding is the rounding increment that will be used in rounding (e.g., 1" means that the actual length will be rounded to an increment of 1"). RebarRoundingManager.TotalLengthRoundingMethod takes a RoundingMethod enum which has the following possible values:
* Nearest - Standard rounding: round to nearest
* Up - Round up
* Down - round down
RebarRoundingManager also provides access to the Segment length rounding with properties RebarRoundingManager.SegmentLengthRounding and RebarRoundingManager.SegmentLengthRoundingMethod.
To override reinforcement settings on a fabric sheet type or a fabric sheet element, calling GetReinforcementRoundingManager() on the corresponding class will return a FabricRoundingManager. The FabricRoundingManager class has similar functionality to the RebarRoundingManager for controlling rounding for fabric sheets.
## Querying an element's current reinforcement rounding settings
You may access information about what is currently controlling the reinforcement rounding for any element by querying the following properties: RebarRoundingManager.ApplicableReinforcementRoundingSource (for rebar) or FabricRoundingManager.ApplicableReinforcementRoundingSource (for fabric sheets). You may also query current rounding settings by using the ApplicableTotalLengthRoundingMethod and ApplicableTotalLengthRounding properties, available from both types of rounding managers.
**Parent page:** [Reinforcement](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_html.html)

View File

@@ -0,0 +1,41 @@
# Reinforcement Settings
# Reinforcement Settings
Several settings regarding reinforcement in the model are controlled at the document level and are accessed through the ReinfocementSettings class for the document.
These settings include reinforcement rounding document level overrides, hosting of rebar elements on path and area reinforcement, as well as tag abbreviations for reinforcement tagging.
Access the document reinforcement settings object by calling the static ReinforcementSettings.GetReinforcementSettings() which takes a reference to the document and returns the corresponding reinforcement settings object.
## Reinforcement rounding overrides
You may access settings for document level reinforcement rounding overrides by using the methods GetRebarRoundingManager() or GetFabricRoundingManager().
## Hosting rebar on area and path reinforcing
The property HostStructuralRebar controls whether Revit will automatically host real rebar on path and area reinforcement. Before setting this property to true, you must verify that there are no path or area reinforcing objects currently in the document by using a FilteredElementCollector.
## Include hooks in rebar shape definition
The RebarShapeDefinesHooks property controls whether rebar shape definitions include hooks in the definition. This maps to the UI property "Include hooks in Rebar Shape definition" setting in Reinforcement Settings. Note that this property may not be changed if the model contains: rebar elements, area or path reinforcing, or rebar containers. Use a FilteredElementCollector to query the model for the existence of any of these elements before attempting to set this property.
## Include end treatments in rebar shape definition
The RebarShapeDefinesEndTreatments property indicates if end treatments are defined by the RebarShape. This property can only be set if there are no rebars, area reinforcements or path reinforcements.
## Reinforcement abbreviation tags
You may access as well as apply new rebar tag abbreviations. Engineers typically specify rebar with certain abbreviations (E.g., NF = near face, E.W. = each way). There are 16 different abbreviation tags stored by the ReinforcementSettings object and are indexed by the enumeration ReinforcementAbbreviationTagType.
Query current abbreviation tags by calling the method GetReinforcementAbbreviationTag() which will return a string value of the current abbreviation corresponding to the tag type passed to the method. You may also retrieve all of the abbreviation tags associated with either path or area reinforcement by calling the method GetReinforcementAbbreviationTags().
Set new abbreviations by calling the method SetReinforcementAbbreviationTag() passing a ReinforcementAbbreviationTagType to specify for which tag type you wish to set the new abbreviation.
## Varying Rebar Set
The NumberVaryingLengthRebarsIndividually property of ReinforcementSettings modifies the way varying length bars are numbered (individually or as a whole). If true, then each bar in a varying rebar set will be assigned a rebar number. Otherwise, the whole rebar set will be assigned a unique rebar number and each bar within the set will be assigned a suffix that is unique within the set.
The ReinforcementSettings.RebarVaryingLengthNumberSuffix property is a unique string identifier used for a bar within a variable length rebar set.
**Parent page:** [Reinforcement](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_html.html)

View File

@@ -0,0 +1,20 @@
# Reinforcement
# Reinforcement
The Revit API provides classes to manage reinforcement, such as rebar or fabric sheets, in valid hosts such as concrete columns, beams, walls, foundations, and structural floors.
**Pages in this section**
* [Rebar](Reinforcement/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_Rebar_html.html)
* [Rebar Couplers](Reinforcement/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_Rebar_Couplers_html.html)
* [Area and Path Reinforcement](Reinforcement/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_Area_and_Path_Reinforcement_html.html)
* [Fabric Reinforcement](Reinforcement/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_Fabric_Reinforcement_html.html)
* [Reinforcement Settings](Reinforcement/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_Reinforcement_Settings_html.html)
* [Reinforcement Rounding](Reinforcement/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_Reinforcement_Rounding_html.html)
* [Annotation](Reinforcement/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_Annotation_html.html)
* [Rebar Containers](Reinforcement/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_Rebar_Containers_obsolete_html.html)
**Parent page:** [Structural Model Elements](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_html.html)

View File

@@ -0,0 +1,26 @@
# Slabs
# Slabs
## Slab
Both Slab (Structural Floor) and Slab Foundation are represented by the Floor class and are distinguished by the IsFoundationSlab property.
The Slab Span Directions are represented by the IndependentTag class in the API and are available as follows:
**Figure 157: Slab span directions**
When using Floor.Create() to create a Slab, Span Directions are not automatically created. There is also no way to create them directly.
The Slab compound structure layer Structural Deck properties are exposed by the following properties:
* CompoundStructuralLayer.DeckUsage
* DeckProfile
The properties are outlined in the following dialog box:
**Figure 158: Floor CompoundStructuralLayer properties**
**Parent page:** [Structural Model Elements](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_html.html)

View File

@@ -0,0 +1,94 @@
# Structural Columns, Beams and Braces
# Structural Columns, Beams and Braces
Structural column, beam, and brace elements are all represented by the FamilyInstance class. They are distinguished by the StructuralType property.
**Code Region 29-1: Distinguishing between column, beam and brace**
---
public void GetStructuralType(FamilyInstance familyInstance)
{
string message = "";
switch (familyInstance.StructuralType)
{
case StructuralType.Beam:
message = "FamilyInstance is a beam.";
break;
case StructuralType.Brace:
message = "FamilyInstance is a brace.";
break;
case StructuralType.Column:
message = "FamilyInstance is a column.";
break;
case StructuralType.Footing:
message = "FamilyInstance is a footing.";
break;
default:
message = "FamilyInstance is non-structural or unknown framing.";
break;
}
TaskDialog.Show("Revit",message);
}
You can filter out FamilySymbol objects corresponding to structural columns, beams, and braces by using categories. The category for structural beams and braces is BuiltInCategory.OST_StructuralFraming. The category for structural columns is BuiltInCategory.OST_StructuralColumns.
**Code Region 29-2: Using BuiltInCategory.OST_StructuralFraming**
---
public void GetBeamAndColumnSymbols(Document document)
{
List<FamilySymbol> columnTypes = new List<FamilySymbol>();
List<FamilySymbol> framingTypes = new List<FamilySymbol>();
FilteredElementCollector collector = new FilteredElementCollector(document);
ICollection<Element> elements = collector.OfClass(typeof(Family)).ToElements();
foreach(Element element in elements)
{
Family family = element as Family;
Category category = family.FamilyCategory;
if (null != category)
{
ISet<ElementId> familySymbolIds = family.GetFamilySymbolIds();
if ((int)BuiltInCategory.OST_StructuralColumns == category.Id.Value)
{
foreach (ElementId id in familySymbolIds)
{
FamilySymbol symbol = family.Document.GetElement(id) as FamilySymbol;
columnTypes.Add(symbol);
}
}
else if ((int)BuiltInCategory.OST_StructuralFraming == category.Id.Value)
{
foreach (ElementId id in familySymbolIds)
{
FamilySymbol symbol = family.Document.GetElement(id) as FamilySymbol;
framingTypes.Add(symbol);
}
}
}
}
string message = "Column Types: ";
foreach (FamilySymbol familySymbol in columnTypes)
{
message += "\n" + familySymbol.Name;
}
TaskDialog.Show("Revit",message);
}
You can get and set beam setback properties with the FamilyInstance.ExtensionUtility property. If this property returns null, the beam setback can't be modified.
## BeamSystem
BeamSystem provides full access and edit ability to beam systems. You can get and set all of its properties, such as BeamSystemType, BeamType, Direction, and Level. BeamSystem.Direction is not limited to one line of edges. It can be set to any XYZ coordinate on the same plane with the BeamSystem.
Note: You cannot change the StructuralBeam AnalyticalModel after the Elevation property is changed in the UI or by the API. In the following picture the analytical model lines stay in the original location after BeamSystem Elevation is changed to 10 feet.
**Figure 156: Change BeamSystem elevation**
**Parent page:** [Structural Model Elements](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_html.html)

View File

@@ -0,0 +1,75 @@
# Trusses
# Trusses
## Truss
The Truss class represents all types of trusses in Revit. The TrussType property indicates the type of truss.
**Code Region 29-7: Creating a truss over two columns**
---
Truss CreateTruss(Autodesk.Revit.DB.Document document, FamilyInstance column1, FamilyInstance column2)
{
Truss truss = null;
using (Transaction transaction = new Transaction(document, "Add Truss"))
{
if (transaction.Start() == TransactionStatus.Started)
{
//sketchPlane
XYZ origin = new XYZ(0, 0, 0);
XYZ xDirection = new XYZ(1, 0, 0);
XYZ yDirection = new XYZ(0, 1, 0);
XYZ zDirection = new XYZ(0, 0, 1);
Plane plane = Plane.Create(new Frame(origin, xDirection, yDirection, zDirection));
SketchPlane sketchPlane = SketchPlane.Create (document, plane);
//new base Line - use line that spans two selected columns
AnalyticalMember frame1 = (AnalyticalMember)document.GetElement(AnalyticalToPhysicalAssociationManager.GetAnalyticalToPhysicalAssociationManager(document).GetAssociatedElementId(column1.Id));
XYZ centerPoint1 = (frame1.GetCurve() as Line).GetEndPoint(0);
AnalyticalMember frame2 = (AnalyticalMember)document.GetElement(AnalyticalToPhysicalAssociationManager.GetAnalyticalToPhysicalAssociationManager(document).GetAssociatedElementId(column2.Id));
XYZ centerPoint2 = (frame2.GetCurve() as Line).GetEndPoint(0);
XYZ startPoint = new XYZ(centerPoint1.X, centerPoint1.Y, 0);
XYZ endPoint = new XYZ(centerPoint2.X, centerPoint2.Y, 0);
Autodesk.Revit.DB.Line baseLine = null;
try
{
baseLine = Line.CreateBound(startPoint, endPoint);
}
catch (System.ArgumentException)
{
throw new Exception("Selected columns are too close to create truss.");
}
// use the active view for where the truss's tag will be placed; View used in
// NewTruss should be plan or elevation view parallel to the truss's base line
Autodesk.Revit.DB.View view = document.ActiveView;
// Get a truss type for the truss
FilteredElementCollector collector = new FilteredElementCollector(document);
collector.OfClass(typeof(FamilySymbol));
collector.OfCategory(BuiltInCategory.OST_Truss);
TrussType trussType = collector.FirstElement() as TrussType;
if (null != trussType)
{
truss = Truss.Create(document, trussType.Id, sketchPlane.Id, baseLine);
transaction.Commit();
}
else
{
transaction.RollBack();
throw new Exception("No truss types found in document.");
}
}
}
return truss;
}
**Parent page:** [Structural Model Elements](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_html.html)

View File

@@ -0,0 +1,19 @@
# Structural Model Elements
# Structural Model Elements
Structural Model Elements are, literally, elements that support a structure such as columns, rebar, trusses, and so on. The following section describe how to manipulate these elements.
The model elements included in this section are specific to the structural engineering features of Revit. For more information about other structural element classes, see the corresponding parts in [Walls, Floors, Ceilings, Roofs and Openings](../../Revit_Geometric_Elements/Revit_API_Revit_API_Developers_Guide_Revit_Geometric_Elements_Walls_Floors_Ceilings_Roofs_and_Openings_html.html) and [Family](../../Revit_Geometric_Elements/Family_Instances/Revit_API_Revit_API_Developers_Guide_Revit_Geometric_Elements_Family_Instances_Family_html.html) Instances.
**Pages in this section**
* [Structural Columns, Beams and Braces](Structural_Model_Elements/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Structural_Columns_Beams_and_Braces_html.html)
* [Trusses](Structural_Model_Elements/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Trusses_html.html)
* [Reinforcement](Structural_Model_Elements/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Reinforcement_html.html)
* [Boundary Conditions](Structural_Model_Elements/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Boundary_Conditions_html.html)
* [Slabs](Structural_Model_Elements/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_Slabs_html.html)
**Parent page:** [Structural Engineering](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_html.html)

View File

@@ -0,0 +1,28 @@
# Structural Engineering
# Structural Engineering
The following sections describe API features that only pertain to the structural engineering features of Revit:
* Structural Model Elements - Discusses specific Elements and their properties that only relate to the structural engineering features of Revit.
* AnalyticalModel - Discusses analytical model-related classes such as AnalyticalModel, RigidLink, and AnalyticalModelSupport.
* AnalyticalLink - Discusses creating new analytical links between analytical beams and columns.
* Loads - Discusses Load Settings and three kinds of Loads.
* Your Analysis Link - Provides suggestions for API users who want to link Revit to certain Structural Analysis applications.
This chapter contains some advanced topics. If you are not familiar with the Revit Platform API, read the basic sections first, such as [Getting Started](../Introduction/Revit_API_Revit_API_Developers_Guide_Introduction_Getting_Started_html.html), [Elements Essentials](../Introduction/Revit_API_Revit_API_Developers_Guide_Introduction_Elements_Essentials_html.html), [Parameters](../Basic_Interaction_with_Revit_Elements/Revit_API_Revit_API_Developers_Guide_Basic_Interaction_with_Revit_Elements_Parameters_html.html), and so on.
**Pages in this section**
* [Structural Model Elements](Structural_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Structural_Model_Elements_html.html)
* [Analytical Model](Structural_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Analytical_Model_html.html)
* [Loads](Structural_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Loads_html.html)
* [Analysis Link](Structural_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Analysis_Link_html.html)
* [Analytical Links](Structural_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Analytical_Links_html.html)
* [Steel Fabrication](Structural_Engineering/Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_Structural_Engineering_Steel_Fabrication_html.html)
**Parent page:** [Discipline-Specific Functionality](../Revit_API_Revit_API_Developers_Guide_Discipline_Specific_Functionality_html.html)