Hello,
I Have been using 'ConvertFromInternalUnits' for many years using DisplayUnitType, but in Revit 2021 is says:
Warning BC40000
'Public Shared Overloads Function ConvertFromInternalUnits(value As Double, displayUnit As DisplayUnitType) As Double' is obsolete:
'This method is deprecated in Revit 2021 and may be removed in a future version of Revit.
Please use the `ConvertFromInternalUnits(double, ForgeTypeId)` overload instead.'.
Can someone tell me how to use ForgeTypeId for Converting using ConvertFromInternalUnits?
Where do I find the Enumerations? or is it not working like that?
I also seems to need the same ForgeTypeId to get the UnitType of a parameter in Revit 2021 using p.definition.GetSpecTypeId
Is there any documentation about this (for me new) ForgeTypeId ?
Thanks,
Chris Hanschen
LKSVDD architecten
The Netherlands
Solved! Go to Solution.
Solved by jeremytammik. Go to Solution.
I'm also very interested in this new type. And while I haven't used it yet, I see in the API that there are 3 classes, SpecTypeId, SymbolTypeId, and UnitTypeId, that contain many ForgeTypeIds in static properties. This is probably where you'll find what you're looking for.
I've also done a bit of browsing in Revit 2021's data and found some .json files defining Forge schemas for what I guess are the specs, symbols, and units in those classes. What really intrigues me is the possibility of defining custom units (and symbols and specs).
I tried redefining leg hands as having 13 inches and Revit reported every file as corrupt. Restoring the ratio alone did not suffice; I had to restore the name to foot/feet for Revit to open any file (including metric files).
Where did you find these 'static properties'?
By Example, ForgeTypeId() needs an TypeId definded by a string, I can't find any static values to put into this TypeId as a string.
Chris Hanschen
The Netherlands
Please read the What's New section in the Revit API help file RevitAPI.chm provided with the Revit SDK from the Revit developer centre:
https://www.autodesk.com/developer-network/platform-technologies/revit
Thanks @jeremytammik,
I found it, copy - paste for the people who found this topic before reading the CHM:
All i needed was 'Imports Autodesk.Revit.DB.ForgeTypeId' before it al made sense.
----- start copy-paste revit api 2021 chm ------
Units API changes
Revit has converted to use an external reference to unit definitions defined in Forge schemas.
In the Autodesk.Revit.DB namespace, the enumerations DisplayUnitType, UnitSymbolType, and UnitType have been deprecated in favor of a potentially extensible set of units, symbols, and unit types. The new class:
represents an identifier for a unit, symbol, or other object, and is now used throughout the Revit API to identify units of measurement, symbols, and unit types. Unit types are now referred to as "specs" to avoid confusion with units themselves.
A ForgeTypeId instance holds a string, called a "typeid", that uniquely identifies a Forge schema. A Forge schema is a JSON document describing a data structure, supporting data interchange between applications. A typeid string includes a namespace and version number and may look something like "autodesk.spec.aec:length-1.0.0" or "autodesk.unit.unit:meters-1.0.0". By default, comparison of ForgeTypeId values in the Revit API ignores the version number.
The new classes:
contain a default set of named public constant properties of type ForgeTypeId. These values can be used in code replacing values of the deprecated DisplayUnitType, UnitSymbolType, and UnitType enumerations.
For example, where you previously used DisplayUnitType.DUT_WATTS_PER_SQUARE_METER_KELVIN, you would now use UnitTypeId.WattsPerSquareMeterKelvin. Where you previously used UnitType.UT_HVAC_Density, you would now use SpecTypeId.HvacDensity.
The UnitUtils class now offers a set of new methods for mapping between enumeration values and ForgeTypeId values to assist clients in migrating code to ForgeTypeId:
UnitUtils.IsSymbol()
UnitUtils.GetSpecTypeId()
UnitUtils.GetUnitType()
UnitUtils.GetUnitTypeId()
UnitUtils.GetDisplayUnitType()
UnitUtils.GetSymbolTypeId()
UnitUtils.GetUnitSymbolType()
Some of the preceding methods are new but are already deprecated. They have been added to the API only to assist clients in migrating code from the old enumerations to the ForgeTypeId class.
----- end copy-paste revit api 2021 chm ------
Thanks again!
Chris Hanschen
LKSVDD Architecten
The Netherlands
string StaticaPressure = UnitFormatUtils.Format(doc.GetUnits(), SpecTypeId.PipingPressure, pipingSystem.GetStaticPressure(), false);
I would like to start a discussion among those who cannot afford to ignore deploying for "old" Revit versions. Given that there is a lot of add-in developers out there, supporting more than Revit 2021, is there any migration strategy that Autodesk likes to communicate?
In short: How do I ensure that I can still compile Revit 2020 builds when the deprecated DisplayUnitType is removed, possibly next year? It would be nice if Autodesk could delay the actual removal to 2022, so that 2021, 2022 and 2023 can be compiled without introducing hundreds of compile-time switches.
Otherwise: I did not inspect the new API in detail yet, but I hope it is written in such a way that it is possible to create an adapter for ForgeTypeId and port old versions to the new style as long as they are supported. In this way we can do an early migration of code that is supposed to compile with backward-compatibility in mind.
@cwaluga Please be aware that the Revit development team do not systematically read all the discussion forum threads.
To seriously bring your wish to their attention, I suggest you submit it to the the Revit Idea Station and add your comments there:
https://forums.autodesk.com/t5/revit-ideas/idb-p/302
Tag it as an API wish:
https://forums.autodesk.com/t5/revit-ideas/idb-p/302/tab/most-recent/label-name/api
Ensure it gets as many votes as possible to underline its importance to you and the rest of the developer community.
The Revit Idea Station is currently one of the main driving input forces for Revit API enhancements.
The Revit development team look there. Your comment here in the discussion forum might be overlooked.
Thank you!
Best regards,
Jeremy
My plan was hundreds of compile time switches.
A sample code is always welcome:
#if REVIT2019 || REVIT2020
double valueInInternalUnits = UnitUtils.ConvertToInternalUnits(valueInMeters,
DisplayUnitType.DUT_METERS);
#else
// Revit 2021+
double valueInInternalUnits = UnitUtils.ConvertToInternalUnits(valueInMeters, UnitTypeId.Meters);
#endif
I would like, how to show the DisplayUnitType in Revit 2021.
I have
InternalDefinition inter = param.Definition as InternalDefinition;
var displayparam = param.DisplayUnitType;
var unitparam = inter.UnitType;
This is obsolete for Revit 2021,
now is
//Veamos el BuiltinParameter,DisplayUnitType,UnitType
InternalDefinition inter = param.Definition as InternalDefinition;
var displayparam = param.GetUnitTypeId();
var unitparam = inter.GetSpecTypeId();
How do I show it?
How do I show it?
@David_Robison wrote:My plan was hundreds of compile time switches.
Me too!
But I figured I could move most of my conversions to an extension class which I use to convert my values. In my case most of the conversions in my add-ins are from internal unit to metric and back so I'm getting rid of most compiler flags by concentrating them to a couple of extension classes:
public static class DoubleExtensions
{
/// <summary>
/// Translate double from mm to internal Ft
/// </summary>
/// <param name="value"></param>
/// <returns>New value in Ft</returns>
public static double MmToInternal(this double value)
{
#if RVT2021
return UnitUtils.ConvertToInternalUnits(value, UnitTypeId.Millimeters);
#else
return UnitUtils.ConvertToInternalUnits(value, DisplayUnitType.DUT_MILLIMETERS);
#endif
}
/// <summary>
/// Translate double from internal Ft to mm
/// </summary>
/// <param name="value"></param>
/// <returns>New value in mm</returns>
public static double InternalToMm(this double value)
{
#if RVT2021
return UnitUtils.ConvertFromInternalUnits(value, UnitTypeId.Millimeters);
#else
return UnitUtils.ConvertFromInternalUnits(value, DisplayUnitType.DUT_MILLIMETERS);
#endif
}
/// <summary>
/// Translate double from degrees to internal radians
/// </summary>
/// <param name="value"></param>
/// <returns>New value in radians</returns>
public static double DegToInternal(this double value)
{
#if RVT2021
return UnitUtils.ConvertToInternalUnits(value, UnitTypeId.Degrees);
#else
return UnitUtils.ConvertToInternalUnits(value, DisplayUnitType.DUT_DECIMAL_DEGREES);
#endif
}
/// <summary>
/// Translate double from internal radians to degrees
/// </summary>
/// <param name="value"></param>
/// <returns>New value in degrees</returns>
public static double InternalToDeg(this double value)
{
#if RVT2021
return UnitUtils.ConvertFromInternalUnits(value, UnitTypeId.Degrees);
#else
return UnitUtils.ConvertFromInternalUnits(value, DisplayUnitType.DUT_DECIMAL_DEGREES);
#endif
}
}
And with the added bonus that my code gets quite a bit cleaner without all UnitUtils conversions
double distMm = distance.InternalToMm();
so, the way I understand this thread is that:
If you have a plugin that spans Revit 2021 and 2022 and you need to get units of the project,
In revit 2021, you can use
string getUnits = doc.GetUnits().GetFormatOptions(UnitType.UT_Length).DisplayUnits.ToString();
But for the Revit 2022 version, there's no way to get the units unless it's a Forge project and you're running the Revit 2022 API?
For Revit 2022, it doesn't need to be any sort of special Forge project. Link it to the Revit 2022 DLL and the function will exist. The signature changes to use ForgeTypeId, but that's just part of the Revit API now.
I didn't actually test this code at all, but you would need a change something like this and it will work fine in Revit 2022:
#if !REVIT2022
doc.GetUnits().GetFormatOptions(UnitType.UT_Length)
#else
doc.GetUnits().GetFormatOptions(SpecTypeId.Length)
#endif
Thank you for the clarification. That helps.
I gotta figure out how to use preprocessor directives as you have used in your example so I can handle different Revit versions in cases such as this.
I'm using Visual studio 2019 with compile configurations, named R2019, R2020, R2021 and R022
My code to convert units from internal to millimeter, this is an example of redirecting to code for the used API.
Public Function IU2mm(MyValueInternalUnits As Double, Optional AfrondenHeleMm As Boolean = False) As Double '
Dim mm As Double
#If CONFIG = "R2019" Or CONFIG = "R2020" Then
mm = UnitUtils.ConvertFromInternalUnits(MyValueInternalUnits, DisplayUnitType.DUT_MILLIMETERS)
#Else
mm = UnitUtils.ConvertFromInternalUnits(MyValueInternalUnits, unitTypeId:=UnitTypeId.Millimeters)
#End If
If AfrondenHeleMm = True Then mm = Math.Round(mm, 0)
Return mm
End Function
Chris Hanschen
LKSVDD architecten
The Netherlands
Dear Chris,
Thank you for the VB example.
Apparently, the conditional compilation syntax in C# differs slightly from VB:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives
The #if statement in C# is Boolean and only tests whether the symbol has been defined or not. You can use the operators == (equality) and != (inequality) to test for the bool values `true` or `false`. `true` means the symbol is defined.
Here is a nice discussion on concrete usage:
https://stackoverflow.com/questions/2923210/conditional-compilation-and-framework-targets
So, your method could look like this in C#:
public static double InternalUnitToMillimetres(
double a,
bool roundup = false )
{
double mm;
#if (CONFIG_R2019 || CONFIG_R2020)
mm = UnitUtils.ConvertFromInternalUnits(
a, DisplayUnitType.DUT_MILLIMETERS );
#else
mm = UnitUtils.ConvertFromInternalUnits(
a, UnitTypeId.Millimeters );
#endif
return roundup ? Math.Round( mm, 0 ) : mm;
}
Many, many, more nice examples above...
Hi all, I'm having trouble setting up for multiple versions.
I created a separate post here.
It is primarily focused on the .csproj part of the setup.
First time using preprocessor directives.
Feel free to give it a look over.
I'd appreciate it.
Can't find what you're looking for? Ask the community or share your knowledge.