Revit native project identifier

Revit native project identifier

ollikat
Collaborator Collaborator
1,366 Views
10 Replies
Message 1 of 11

Revit native project identifier

ollikat
Collaborator
Collaborator

Hi,

 

I have been studying how to get an unique (Guid) identifier for the project. I know there has been few posts already here and in the Building Coder blog about the subject.

But the bottom line is that I REALLY would like to have a Revit native method, mainly to avoid challenges in the work sharing environment. Below some highlights from my study:

 

- I have managed to confirm that using a project information element unique id is NOT an option, as several different projects can have identical id (perhaps it comes from the template...?).
- Utilizing the ExportUtils.GetExportId() with project information seems to result exactly the same. So probably this method uses the unique id too. Not usable.
- ExportUtils.GetGBXMLDocumentId() works somewhat better, and seems pretty good
- ExporterIFCUtils.CreateProjectLevelGUID() seems to be best though. Difference to previous is that this method results different id for project that has been detached from the central and saved with Save as (which sound reasonable).

So...I was pretty much already made my decision to use CreateProjectLevelGUID()...until I saw compilation warning from R2022 build. It has been deprecated :-(. "Ok, no problem" I though, as there has always been new alternative mentioned in the warning text. In this case it says:

"This function is deprecated in Revit 2022. Please see the IFC open source function CreateProjectLevelGUID for examples of how to do this starting in Revit 2022."

So eventually I decided to download the source codes from the "https://github.com/Autodesk/revit-ifc", as that's what it means right!?

More over I did found the method called CreateProjectLevelGUID() at took a look of the implementation (I'll paste the code at the bottom as it is public anyway). To me there's no native Revit mechanism I could utilize:

 

- Seems that the project information element dos NOT have following parameters by default (even in the R2022 level project): "IfcProjectGuid", BuiltInParameter.IFC_PROJECT_GUID
- The implementation in the comments (refering also to R2022) seems incorrect to me, as a) it is utilizing the IFCProjectLevelGUIDType enumeration which is also deprecated. b) moreover creating a ElementId from the enumeration value seems quite odd as according to IL reflection tool, enumeration values are using default enum values (0,1,2...)

 

So my questions basically is:

Is there a native method/technique replacing the deprecated CreateProjectLevelGUID(), or what's the best alternative (not necessarily specific to IFC)

 

/// <summary>
/// Creates a Project, Site, or Building GUID.  If a shared parameter is set with a valid IFC GUID value,
/// that value will override the default one.
/// </summary>
/// <param name="document">The document.</param>
/// <param name="guidType">The GUID being created.</param>
/// <returns>The IFC GUID value.</returns>
/// <remarks>For Sites, the user should only use this routine if there is no Site element in the file.  Otherwise, they
/// should use CreateSiteGUID below, which takes an Element pointer.</remarks>
static public string CreateProjectLevelGUID(Document document, IFCProjectLevelGUIDType guidType)
{
   string parameterName = "Ifc" + guidType.ToString() + " GUID";
   ProjectInfo projectInfo = document.ProjectInformation;

   BuiltInParameter parameterId = BuiltInParameter.INVALID;
   switch (guidType)
   {
      case IFCProjectLevelGUIDType.Building:
         parameterId = BuiltInParameter.IFC_BUILDING_GUID;
         break;
      case IFCProjectLevelGUIDType.Project:
         parameterId = BuiltInParameter.IFC_PROJECT_GUID;
         break;
      case IFCProjectLevelGUIDType.Site:
         parameterId = BuiltInParameter.IFC_SITE_GUID;
         break;
      default:
         // This should eventually log an error.
         return null;
   }

   if (projectInfo != null)
   {
      string paramValue = null;
      ParameterUtil.GetStringValueFromElement(projectInfo, parameterName, out paramValue);
      if (!IsValidIFCGUID(paramValue) && parameterId != BuiltInParameter.INVALID)
         ParameterUtil.GetStringValueFromElement(projectInfo, parameterId, out paramValue);

      if (IsValidIFCGUID(paramValue))
         return paramValue;
   }

   // Only for 2022
   //ElementId projectLevelElementId = new ElementId((int)guidType);
   //System.Guid guid = ExportUtils.GetExportId(document, projectLevelElementId);
   //string ifcGUID = ConvertToIFCGuid(guid);
   string ifcGUID = ExporterIFCUtils.CreateProjectLevelGUID(document, guidType);

   if ((projectInfo != null) && ExporterCacheManager.ExportOptionsCache.GUIDOptions.StoreIFCGUID)
   {

      if (parameterId != BuiltInParameter.INVALID)
         ExporterCacheManager.GUIDsToStoreCache[new KeyValuePair<ElementId, BuiltInParameter>(projectInfo.Id, parameterId)] = ifcGUID;
   }
   return ifcGUID;
}
0 Likes
1,367 Views
10 Replies
Replies (10)
Message 2 of 11

jeremy_tammik
Alumni
Alumni

Dear Ollikat,

 

Thank you for your careful in-depth research and very relevant observations.

 

I passed them on to the development team and hope that they can suggest a way forward (my internal link).

 

Cheers,

 

Jeremy

  

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

ollikat
Collaborator
Collaborator

Ok, thanks. Looking forward hearing something from the factory :-).

0 Likes
Message 4 of 11

ollikat
Collaborator
Collaborator

According to my email, there was a reply to this topic, but for some reason it seems not to exists anymore.

@dan.siroky, did you intentionally delete your post? There were some interesting points made, although still something that I don't fully understand.

0 Likes
Message 5 of 11

jeremy_tammik
Alumni
Alumni

I re-prompted the development team but heard nothing back from them on this yet. 

 

I received an email about Dan's reply as well. He initially communicated on the topic in a comment on The Building Coder:

 

https://thebuildingcoder.typepad.com/blog/2021/04/pdf-export-forgetypeid-and-multi-target-add-in.htm...

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 6 of 11

dan.siroky
Explorer
Explorer

I did reply, but it was flagged as spam for some reason. I tried to submit a report to the moderators to reinstate it, but I'm not sure the status of that. It appears it might be completely deleted, which is really unfortunate for a first contribution 🙄

 

The main point of my post was that there is a method available withing Revit-IFC to replace Revit's native CreateProjectLevelGUID(), you just have to change which Git branch you're on before building the Revit.IFC.Export library / referencing it in your code. After that you can pass it your document and ProjectLevelGUIDType.Project instead of IFCProjectLevelGUIDType.Project to get an IFC GUID.

 

Message 7 of 11

ollikat
Collaborator
Collaborator

Thanks for your reply.


I did took a look of the code inside the CreateProjectLevelGUID():
- first it tries to get identifier from a specific parameters (mentioned also in my orginal post). But as I stated, it seems that from those the project doesn't provide the identifier by default.

- After that it tries to use given type identifier directly, as we can see in the code section below:

 

ElementId projectLevelElementId = new ElementId((int)guidType);
System.Guid guid = ExportUtils.GetExportId(document, projectLevelElementId);
string ifcGUID = ConvertToIFCGuid(guid);

 

So in other words it tries to find an element with integer id, which is same as the integer value of corresponding enumeration. From the definition of the ProjectLevelGUIDType we see that the project value is "-16".
This is the part I don't really understand. Does the code really assume, that there would be such element? At least I couldn't spot an element with that id (Using Revit Manage->Select by ID). The resulting message actually indicates an invalid id (because it's negative?).

So...fact of the matter is that I still don't know whether this helps me to get Revit (native) project identifier in reliable manner. I would really love to hear API developer insigths.

 

0 Likes
Message 8 of 11

ollikat
Collaborator
Collaborator

Any news from the API devs yet?

@jeremy_tammik 

 

Thanks.

0 Likes
Message 9 of 11

jeremy_tammik
Alumni
Alumni

Nope, sorry, nothing yet from them at all. I re-prompted for you...

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 10 of 11

ollikat
Collaborator
Collaborator

By the way, I actually did some further research on this.

To my surprise, the following code does really work, although only in R2022 (and onward hopefully)

// The used element id works (in R2022 ->), although you cannot get anything from
// the Revit UI (Manage->Select by Id) by using these values.
ElementId projectLevelElementId = new ElementId(-16 /*project*/);
Guid exportGuid = ExportUtils.GetExportId(doc, projectLevelElementId);
Message 11 of 11

ahmadeltobshy
Contributor
Contributor

Hey  ollikat,

I have tried it and it works just fine for me, this is brilliant so thank you. And i hope it will be in next Api updates soon.

 

 

0 Likes