Here comes a quick clarification of the units used for the UnitWeight
built-in parameter PHY_MATERIAL_PARAM_UNIT_WEIGHT
.
One example usage is to calculate the total weight of rebars in a project.
A developer encountered the following issue in that process:
My Revit add-in calculates total weight of rebars in the document using the UnitWeight
parameter from the material.
Displayed in Revit, I write a value of 7850 Kg/m3 (kg/cubicmeters).
When using this parameter in code, I assume that the value I get from the parameter is in internal units, which I assume to be kiloNewton / cubic feet.
So when I use this, I expect to be able to use the UnitUtils.
This snapshot from the values displayed by the Visual Studio debugger immediate window show the original value and the converted ones:
var parameterVaule = Parameter.AsDouble(); 7154.4631104000009 var converted = UnitUtils.ConvertFromInternalUnits(parameterVaule ,Autodesk.Revit.DB.DisplayUnitType.DUT_KILONEWTONS_PER_CUBIC_METER); 77.01 => This is a correct value. var converted2 = UnitUtils.ConvertFromInternalUnits(parameterVaule ,Autodesk.Revit.DB.DisplayUnitType.DUT_KILOGRAMS_PER_CUBIC_METER); 252657.48031496062 => ??? this not correct!
The value string shows 77 kN/cubicmeters, which by manual calculation is 7849.13 Kg/cubicmeters.
Why doesn't the UnitUtils
class return this value?
I assume that the method ConvertFromInternalUnits
should be able to convert from the default internal units to the wanted unit?
Is this a case where I can't trust the UnitUtils
?
Here is a snippet from the calculation of unit weight from a material.
/// <summary> /// Get the unit weight of a material. /// </summary> internal static double GetMaterialEgenvekt( Document doc, ref string material, Element rebarelement ) { var rType = rebarelement.Document.GetElement( rebarelement.GetTypeId() ) as ElementType; var paramMaterial = rType.get_Parameter( BuiltInParameter.MATERIAL_ID_PARAM ); var mat = doc.GetElement( paramMaterial .AsElementId() ) as Material; double egenvekt = 0; if( mat == null ) return egenvekt; var property = doc.GetElement( mat.StructuralAssetId ) as PropertySetElement; if( property != null ) { var unitWeightParam = property.get_Parameter( BuiltInParameter.PHY_MATERIAL_PARAM_UNIT_WEIGHT ); // Not In Use - gives wrong value in metric unit. var unitWeight = UnitUtils.ConvertFromInternalUnits( unitWeightParam.AsDouble(), DisplayUnitType.DUT_KILOGRAMS_PER_CUBIC_METER ); // Manual calculation. In use, and calculates correct. var egenvektFraMaterial = EgenVektFraNewtonPerSquareFootMeter( unitWeightParam.AsDouble() ); if( !( egenvekt > 0 ) ) egenvekt = egenvektFraMaterial; } material = mat.Name; return egenvekt; }
The manual calculation in EgenVektFraNewtonPerSquareFootMeter
is implemented like this:
/// <summary> /// Calculate the unit weight from NewtonPerSquareFootMeter /// </summary> double EgenVektFraNewtonPerSquareFootMeter( double unitweight ) { double egenvekt = unitweight / 9.81F; double meterPerFot = 1000 / GeoHelper.FootMillimeterKonstant; egenvekt = egenvekt * Math.Pow( meterPerFot, 2 ); return egenvekt; }
The constant GeoHelper.FootMillimeterKonstant
is defined thus;
public static double FootMillimeterKonstant = Math.Round( 304.8, 1 );
Hope we can sort out the problem =)
I use the manual way today, after a heads up from a customer who ordered about 900 Kg too little rebars in a project!
The development team took a look at this issue and provided the following explanation:
UnitUtils.ConvertFromInternalUnits
does not convert from UnitWeight (77 kN/cubicmeters) to Density (7849.13 Kg/cubicmeters).
UnitUtils.ConvertFromInternalUnits
displays a value from Revit internal units (kg/(ft²·s²) for UnitWeight and kg/ft³ for Density) to a compatible unit (kN/cubicmeters for UnitWeight and Kg/cubicmeters for Density).
In detail:
UnitWeight and Density are two different units. So it does not make sense to display some UnitWeight values in kg/m3 – there are different units.
Therefore:
// Does not work (different units: value in // UnitWeight units kg/(ft²·s²) displayed as // value in Density units kg/m³) var unitWeight = UnitUtils.ConvertFromInternalUnits( unitWeightParam.AsDouble(), DisplayUnitType.DUT_KILOGRAMS_PER_CUBIC_METER);
and
// Works (same units: value in UnitWeight units // kg/(ft²·s²) displayed as value in UnitWeight // units kN/m3) var converted2 = UnitUtils.ConvertFromInternalUnits( unitWeightParam.AsDouble(), DisplayUnitType.DUT_KILONEWTONS_PER_CUBIC_METER);
If you want to obtain the density in kg/m3 you can use the PHY_MATERIAL_PARAM_STRUCTURAL_DENSITY
built-in parameter:
var densityParam = property.get_Parameter( BuiltInParameter.PHY_MATERIAL_PARAM_STRUCTURAL_DENSITY ); // Works (same units: value in Density units kg/ft³ // displayed as value in Density units kg/m³) var converted = UnitUtils.ConvertFromInternalUnits( densityParam.AsDouble(), DisplayUnitType.DUT_KILOGRAMS_PER_CUBIC_METER ); --> converted = 7849.04687 double
Or use the formula as you did:
UnitWeight = Density * g
I hope this clarifies.
Happily, you already solved this properly yourself.