ForgeTypeId how to use?

ForgeTypeId how to use?

c_hanschen
Advocate Advocate
31,219 Views
33 Replies
Message 1 of 34

ForgeTypeId how to use?

c_hanschen
Advocate
Advocate

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

 

0 Likes
Accepted solutions (1)
31,220 Views
33 Replies
Replies (33)
Message 2 of 34

mhannonQ65N2
Collaborator
Collaborator

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).

Message 3 of 34

mhannonQ65N2
Collaborator
Collaborator

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).

0 Likes
Message 4 of 34

c_hanschen
Advocate
Advocate

@mhannonQ65N2 ,

 

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

0 Likes
Message 5 of 34

jeremytammik
Autodesk
Autodesk
Accepted solution

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

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 6 of 34

c_hanschen
Advocate
Advocate

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:

  • Autodesk.Revit.DB.ForgeTypeId

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:

  • Autodesk.Revit.DB.UnitTypeId
  • Autodesk.Revit.DB.SymbolTypeId
  • Autodesk.Revit.DB.SpecTypeId

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

 

Message 7 of 34

reylorente1
Collaborator
Collaborator

string StaticaPressure = UnitFormatUtils.Format(doc.GetUnits(), SpecTypeId.PipingPressure, pipingSystem.GetStaticPressure(), false);

Message 8 of 34

cwaluga
Advocate
Advocate

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.

Message 9 of 34

jeremytammik
Autodesk
Autodesk

@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

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 10 of 34

David_Robison
Advocate
Advocate

My plan was hundreds of compile time switches.

Message 11 of 34

FRFR1426
Collaborator
Collaborator

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
Maxence DELANNOY
Manager
Add-ins development for Autodesk software products
http://wiip.fr
Message 12 of 34

reylorente1
Collaborator
Collaborator

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?2020-08-24.png

 

How do I show it?

 

Message 13 of 34

ottosson_mathias
Advocate
Advocate

@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();

 

 

Message 14 of 34

Maltezc
Advocate
Advocate

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?

0 Likes
Message 15 of 34

David_Robison
Advocate
Advocate

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
Message 16 of 34

Maltezc
Advocate
Advocate

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. 

0 Likes
Message 17 of 34

c_hanschen
Advocate
Advocate

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

0 Likes
Message 18 of 34

jeremy_tammik
Alumni
Alumni

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

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 19 of 34

jeremy_tammik
Alumni
Alumni

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...

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 20 of 34

Maltezc
Advocate
Advocate

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. 

 

0 Likes