The two main classes in the Revit API for working with units are Units and FormatOptions. The Units class represents a document's default settings for formatting numbers with units as strings. It contains a FormatOptions object for each unit type as well as settings related to decimal symbol and digit grouping.
The Units class stores a FormatOptions object for every valid unit type, but not all of them can be directly modified. Some, like UT_Number and UT_SiteAngle, have fixed definitions. Others have definitions which are automatically derived from other unit types. For example, UT_SheetLength is derived from UT_Length and UT_ForceScale is derived from UT_Force.
The FormatOptions class contains settings that control how to format numbers with units as strings. It contains those settings that are typically chosen by an end-user in the Format dialog and stored in the document, such as rounding, accuracy, display units, and whether to suppress spaces or leading or trailing zeros.
The FormatOptions class is used in two different ways. A FormatOptions object in the Units class represents the default settings for the document. A FormatOptions object used elsewhere represents settings that may optionally override the default settings.
The UseDefault property controls whether a FormatOptions object represents default or custom formatting. If UseDefault is true, formatting will be according to the default settings in the Units class, and none of the other settings in the object are meaningful. If UseDefault is false, the object contains custom settings that override the default settings in the Units class. UseDefault is always false for FormatOptions objects in the Units class.
Important unit-related enumerations in the Revit API include:
The Revit API provides utility classes to facilitate working with quantities in Revit. The UnitUtils class makes it easy to convert unit data to and from Revit's internal units.
Revit has seven base quantities, each with its own internal unit. These internal units are identified in the following table.
Table 9: 7 Base Units in Revit Unit System
Base Unit |
Unit In Revit |
Unit System |
Length |
Feet (ft) |
Imperial |
Angle |
Radian |
Metric |
Mass |
Kilogram (kg) |
Metric |
Time |
Seconds (s) |
Metric |
Electric Current |
Ampere (A) |
Metric |
Temperature |
Kelvin (K) |
Metric |
Luminous Intensity |
Candela (cd) |
Metric |
Code Region: Converting from Revit's internal units |
double GetYieldStressInKsi(Material material) { double dMinYieldStress = 0; // Get the structural asset for the material ElementId strucAssetId = material.StructuralAssetId; if (strucAssetId != ElementId.InvalidElementId) { PropertySetElement pse = material.Document.GetElement(strucAssetId) as PropertySetElement; if (pse != null) { StructuralAsset asset = pse.GetStructuralAsset(); // Get the min yield stress and convert to ksi dMinYieldStress = asset.MinimumYieldStress; dMinYieldStress = UnitUtils.ConvertFromInternalUnits(dMinYieldStress, DisplayUnitType.DUT_KIPS_PER_SQUARE_INCH); } } return dMinYieldStress; } |
The UnitUtils can also be used to convert a value from one unit type to another, such as square feet to square meters. In the following example, a wall's top offset value that was entered in inches is converted to feet, the expected unit for setting that value.
Code Region: Converting between units |
void SetTopOffset(Wall wall, double dOffsetInches) { // convert user-defined offset value to feet from inches prior to setting double dOffsetFeet = UnitUtils.Convert(dOffsetInches, DisplayUnitType.DUT_DECIMAL_INCHES, DisplayUnitType.DUT_DECIMAL_FEET); Parameter paramTopOffset = wall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET); paramTopOffset.Set(dOffsetFeet); } |
Another utility class, UnitFormatUtils, can format data or parse formatted unit data.
The overloaded method Format() can be used to format a value into a string based on formatting options as the following example demonstrates. The material density is retrieved and then the value is then converted to a user-friendly value with unit using the Format() method.
Code Region: Format value to string |
void DisplayDensityOfMaterial(Material material) { double density = 0; // get structural asset of material in order to get the density ElementId strucAssetId = material.StructuralAssetId; if (strucAssetId != ElementId.InvalidElementId) { PropertySetElement pse = material.Document.GetElement(strucAssetId) as PropertySetElement; if (pse != null) { StructuralAsset asset = pse.GetStructuralAsset(); density = asset.Density; // convert the density value to a user readable string that includes the units Units units = material.Document.GetUnits(); // false for maxAccuracy means accuracy specified by the FormatOptions should be used // false for forEditing since this will be for display only and no formatting modifications are necessary string strDensity = UnitFormatUtils.Format(units, UnitType.UT_UnitWeight, density, false, false); string msg = string.Format("Raw Value: {0}\r\nFormatted Value: {1}", density, strDensity); TaskDialog.Show("Material Density", msg); } } } |
The overloaded UnitFormatUtils.TryParse() method parses a formatted string, including units, into a value if possible, using the Revit internal units of the specified unit type. The following example takes a user entered length value, assumed to be a number and length unit, and attempts to parse it into a length value. The result is compared with the input string in a TaskDialog for demonstration purposes.
Code Region: Parse string |
double GetLengthInput(Document document, String userInputLength) { double dParsedLength = 0; Units units = document.GetUnits(); // try to parse a user entered string (i.e. 100 mm, 1'6") bool parsed = UnitFormatUtils.TryParse(units, UnitType.UT_Length, userInputLength, out dParsedLength); if (parsed == true) { string msg = string.Format("User Input: {0}\r\nParsed value: {1}", userInputLength, dParsedLength); TaskDialog.Show("Parsed Data", msg); } return dParsedLength; } |