Mapping IFC GUIDs Between Revit and Exported Files

Moustafa KhalilMoustafa Khalil
4 min read

Understanding the IFC GUID Mapping Between Revit and Exported IFC Files

Working with BIM projects in Revit often involves exporting models to the Industry Foundation Classes (IFC) format, a crucial step for interoperability in construction projects. A recurring question when dealing with this export process is how to correlate the IFC GUIDs assigned to elements in the exported IFC file with those in the original Revit model. Since the Revit IFC exporter is open-source, it offers a unique opportunity to explore the internals of this transformation. Here, I’ll walk you through my journey in understanding the process and reveal some intriguing details about generating and mapping IFC GUIDs.

The Basics: Extracting IFC GUIDs for Standalone Elements

Extracting the IFC GUID of a standalone element from a Revit project is fairly straightforward. Each element in Revit has an IfcGUID parameter, which is directly mapped to its corresponding GUID in the exported IFC file. This makes the initial step quite simple: all we need is the IfcGUID property of the element, which remains consistent across Revit and the IFC file.

Here’s an example code snippet illustrating how to retrieve the IFC GUID from a standalone element:

public string GetIfcGuid(Element element)
{
    if (element == null)
        throw new ArgumentException("Element is null");

    return element.get_Parameter(BuiltInParameter.IFC_GUID).AsString();
}

This straightforward retrieval works well for individual elements, but linked instances present a more complex challenge.

The Challenge: Generating IFC GUIDs for Linked Instances

When dealing with linked elements, the process is less direct. The IFC GUID of a linked element must uniquely identify not only the element itself but also the context of its link to the main Revit project. To achieve this, we combine the GUIDs of both the linked Revit instance and the element within it.

Here’s a step-by-step breakdown of the process:

  1. Retrieve IFC GUIDs: Get the IfcGUID of both the Revit link instance and the linked element.

  2. Combine the GUIDs: Concatenate the GUIDs with a separator by : (As it is done by IFC Exporter).

  3. Compute Hash: Convert the combined string to a byte array (using UTF-8 encoding) and apply an MD5 hash to create a unique identifier.

  4. Repeat the Hash: Interestingly, the Revit exporter repeats this process. The hash generated from the first combination is further combined with the Revit instance’s GUID and hashed again. This extra step reinforces uniqueness, though it remains unclear whether this repetition is intentional or a potential bug.

Here’s how the code looks in action:

public string GenerateIFCGuidFrom(Element e, RevitLinkInstance rvtInstance)
{
    if (e == null)
        throw new ArgumentException("Missing element");

    var eIfc = e.get_Parameter(BuiltInParameter.IFC_GUID).AsString();
    if (rvtInstance == null)
        return eIfc;

    var rvtInsIfc = rvtInstance.get_Parameter(BuiltInParameter.IFC_GUID).AsString();
    string expectedIFc = GenerateIFCGuidFrom(eIfc, rvtInsIfc);
    expectedIFc = GenerateIFCGuidFrom(expectedIFc, rvtInsIfc);

    return expectedIFc;
}

public string GenerateIFCGuidFrom(string eIfc, string rvtDocIfcGuid)
{
    string key = rvtDocIfcGuid + ":" + eIfc;

    byte[] hash = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(key));
    var expectedGuid = ConvertToIFCGuid(new Guid(hash));
    return expectedGuid;
}

private string ConvertToIFCGuid(Guid guid)
{
    byte[] byteArray = guid.ToByteArray();
    ulong[] num = new ulong[6];
    num[0] = byteArray[3];
    num[1] = byteArray[2] * (ulong)65536 + byteArray[1] * (ulong)256 + byteArray[0];
    num[2] = byteArray[5] * (ulong)65536 + byteArray[4] * (ulong)256 + byteArray[7];
    num[3] = byteArray[6] * (ulong)65536 + byteArray[8] * (ulong)256 + byteArray[9];
    num[4] = byteArray[10] * (ulong)65536 + byteArray[11] * (ulong)256 + byteArray[12];
    num[5] = byteArray[13] * (ulong)65536 + byteArray[14] * (ulong)256 + byteArray[15];

    char[] buf = new char[22];
    int offset = 0;

    for (int ii = 0; ii < 6; ii++)
    {
        int len = (ii == 0) ? 2 : 4;
        for (int jj = 0; jj < len; jj++)
        {
            buf[offset + len - jj - 1] = s_ConversionTable_2X[(int)(num[ii] % 64)];
            num[ii] /= 64;
        }
        offset += len;
    }

    return new string(buf);
}

Breaking Down the Code

In this code:

  • GenerateIFCGuidFrom(Element e, RevitLinkInstance rvtInstance) generates the IFC GUID by initially combining the linked element’s IfcGUID with that of the Revit link instance.

  • The GenerateIFCGuidFrom(string eIfc, string rvtDocIfcGuid) method then applies MD5 hashing to create a GUID that is unique for this specific context.

The code also repeats the hashing process by combining the hashed GUID with the Revit link instance’s GUID, adding a second layer of uniqueness.

The Result: A Unique IFC GUID

This approach ensures that each linked instance has a unique identifier in the IFC file, even when similar elements appear in different linked files or instances. The additional hashing step reinforces the uniqueness of the IFC GUID across different project contexts, minimizing clashes in the IFC model.

Insights and Open Questions

While this method works well for ensuring uniqueness, the reason behind the repeated hashing in the Revit exporter remains a bit of a mystery. Whether intentional or a quirk, it seems to provide a unique and repeatable result that can reliably correlate the GUIDs between Revit and IFC.

This exploration highlights how open-source tools allow us to understand and fine-tune processes within BIM workflows, especially when dealing with cross-platform compatibility in the construction industry. Hopefully, this article has shed light on the complex relationship between Revit elements and their representation in IFC files, making it easier to handle IFC exports in your own projects!

0
Subscribe to my newsletter

Read articles from Moustafa Khalil directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Moustafa Khalil
Moustafa Khalil

I'm Moustafa Khalil El-Sayed, an Egyptian native with a passion for architecture and technology. After completing high school in 1999, I embarked on my journey into architecture, earning my Bachelor's degree in Architecture in 2004. My academic pursuits continued, and I later acquired my Master's degree in Architecture from Wings University. However, my thirst for knowledge extended beyond architectural design, leading me to pursue a degree in Computer Science as well. Driven by a desire to innovate, I began self-teaching computer science, which later empowered me to achieve my Associate degree in Computer Science from the University of the People more easily. Armed with dual expertise in architecture and computer science, I've cultivated a unique skill set that blends creativity with technical acumen. My career has taken me across borders, from Egypt to Oman and the UAE, where I've honed my skills as an architect. As a graduate architect and a proficient .NET BIM Solution Developer, I specialize in translating unique visions into tangible realities. My role extends beyond conventional architectural practices; I leverage technology to streamline processes and enhance project outcomes. My journey into programming began with developing script-based Excel tools to augment project management efforts, notably during the Sharm El Sheikh development. Over time, I expanded my programming prowess to address practical challenges encountered in bridging Revit and AutoCAD within my professional sphere. Several of my applications, born from this evolution, have gained recognition, with some even being featured on the Autodesk website. I am committed to pushing boundaries and continually enriching the intersection of architecture and technology, ensuring that my clients benefit from cutting-edge solutions tailored to their needs.