Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Creating a list of element IDs and IFC GUIDs

8 REPLIES 8
SOLVED
Reply
Message 1 of 9
itinerati
4111 Views, 8 Replies

Creating a list of element IDs and IFC GUIDs

I need a list of element IDs matched to their IFC GUIDs, but I'm not having much luck. I've tried piecing together a bit of what I know and what I've found, but I keep getting errors connected to the IDs : I can't get the element ID from an element, and I can't create the GUID to feed into an ifc converter. I imagine I'm making a total rookie mistake, as this is my first attempt to code in C#, but here you have it. Suggestions?

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;

using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB.IFC.ExporterIFCUtils;

[TransactionAttribute(TransactionMode.Manual)]
[RegenerationAttribute(RegenerationOption.Manual)]

public class copyEverything : IExternalCommand
{

    //Set the path for the new text file
    string myPath = @"c:\temp\MyTest.txt";

    public Result Execute(
      ExternalCommandData commandData,
      ref string message,
      ElementSet elements)
    {

        
        //Get application and document objects
        UIApplication uiApp = commandData.Application;
        Document doc = uiApp.ActiveUIDocument.Document;



        var collector = new FilteredElementCollector(doc).WhereElementIsNotElementType()
            ;

        //Create a new text file and fill it with lines of elementIDs and IFC GUIDs, with a space in between
        using (StreamWriter myText = File.CreateText(myPath))
        {

            foreach (Element x in collector)
            {

                //THIS IS WHERE I'M HAVING PROBLEMS
                var elemId = GetElementId(x);
                var tempNum = CreateGUID(x);


                //Convert the GUID to IFC format, and add a new line to the text file
                var tempIfcId = IfcGuid.cv_to_64( tempNum );
                myText.WriteLine(elemId + " " + tempIfcId);
            }
        }
        return Result.Succeeded;
    }

    //Found function to convert GUID's into IFC's 64-bit scheme
    public static class IfcGuid
    {

        private static readonly char[] base64Chars = new char[]
        { '0','1','2','3','4','5','6','7','8','9'
        , 'A','B','C','D','E','F','G','H','I','J'
        , 'K','L','M','N','O','P','Q','R','S','T'
        , 'U','V','W','X','Y','Z','a','b','c','d'
        , 'e','f','g','h','i','j','k','l','m','n'
        , 'o','p','q','r','s','t','u','v','w','x'
        , 'y','z','_','$' };

        public static void cv_to_64(uint number, ref char[] result, int start, int len)
        {
            uint act;
            int iDigit, nDigits;

            Debug.Assert(len <= 4);
            act = number;
            nDigits = len;

            for (iDigit = 0; iDigit < nDigits; iDigit++)
            {
                result[start + len - iDigit - 1] = base64Chars[(int)(act % 64)];
                act /= 64;
            }
            Debug.Assert(act == 0, "Logic failed, act was not null: " + act.ToString());
            return;
        }
    }
}

 

8 REPLIES 8
Message 2 of 9
ollikat
in reply to: itinerati

Hi

 

What is this "GetElementId()"?

 

You should get an element id directly from element like this:

 

Element foo;
int bar = foo->Id->IntegerValue;

 

Message 3 of 9
itinerati
in reply to: ollikat

Mostly a stab in the dark from searching through functions 🙂 Really new to this API and C# in general, so I really appreciate the help.

 

When I use that snippet of code, setting foo = to the element I'm looking at, I get an error saying "The * or -> operator must be applied to a pointer." I only have a vague idea of what a pointer is (researching more now), but is there something else I should be doing with this?

Message 4 of 9
ollikat
in reply to: itinerati

Aa...sorry, my bad. I accidentally mixed C++ syntax to the code. Just use '.' instead

Message 5 of 9
itinerati
in reply to: ollikat

Awesome, that did it. Using that as a base, I think I have the right way to get the Unique ID for the cv_to_64 function too, so thanks!

 

Now I'm seeing that I'm not using that function right, though. Do you have any experience with it? I got it from here: http://thebuildingcoder.typepad.com/blog/2010/06/ifc-guid-algorithm-in-c.html

 

If I'm reading it right, it takes four arguments...trouble is, I don't really know what those four are supposed to be. I'd assume it only would have been the UniqueID, but that seems not to be the case. Any ideas?

Message 6 of 9
ollikat
in reply to: itinerati

I think you should be using ToIfcGuid() function instead. Here's one way to use it:

 

Guid elemGuid = Autodesk.Revit.DB.ExportUtils.GetExportId(element.Document, element.Id);

String ifcGuid = IfcGuid.toIfcGuid(elemGuid);

 Hope that is something you are looking for

Message 7 of 9
itinerati
in reply to: itinerati

That did it, I now have a text file that contains exactly what I was looking for!

 

Thanks a ton for your repeated help, I really appreciate it. This would have taken a lot longer without it 😄

Message 8 of 9
itinerati
in reply to: itinerati

And just in case anyone comes across this post looking to do the same thing, here's the working code. Note that it doesn't give any confirmation, it just exports the file.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;

using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;


[TransactionAttribute(TransactionMode.Manual)]
[RegenerationAttribute(RegenerationOption.Manual)]

public class Lab1PlaceGroup : IExternalCommand
{

    //Set the path for the new text file
    string myPath = @"c:\MyTest.txt";

    public Result Execute(
      ExternalCommandData commandData,
      ref string message,
      ElementSet elements)
    {


        //Get application and document objects
        UIApplication uiApp = commandData.Application;
        Document doc = uiApp.ActiveUIDocument.Document;



        var collector = new FilteredElementCollector(doc).WhereElementIsNotElementType()
            ;

        //If there's an existing file at the path, delete it.
        if (File.Exists(myPath))
        {
            File.Delete(myPath);
        }



        //Create a new text file and fill it with lines of elementIDs and IFC GUIDs, with a space in between
        using (StreamWriter myText = File.CreateText(myPath))
        {

            //Cycle through all elements in the scene, identify their element ID and GUID, then convert GUID into IFC GUID. 
            //Add both numbers to the text file with a space inbetween
            foreach (Element x in collector)
            {

                int elemId = x.Id.IntegerValue;
                Guid elemGuid = Autodesk.Revit.DB.ExportUtils.GetExportId(x.Document, x.Id);
                String tempNum = IfcGuid.ToIfcGuid(elemGuid);

                myText.WriteLine(elemId + " " + tempNum);
            }
        }
        return Result.Succeeded;
    }


    //Found function to convert GUID's into IFC's 64-bit scheme, available at http://thebuildingcoder.typepad.com/blog/2010/06/ifc-guid-algorithm-in-c.html
    public static class IfcGuid
    {


        /// <summary>
        /// The replacement table
        /// </summary>
        private static readonly char[] base64Chars = new char[]
        { '0','1','2','3','4','5','6','7','8','9'
        , 'A','B','C','D','E','F','G','H','I','J'
        , 'K','L','M','N','O','P','Q','R','S','T'
        , 'U','V','W','X','Y','Z','a','b','c','d'
        , 'e','f','g','h','i','j','k','l','m','n'
        , 'o','p','q','r','s','t','u','v','w','x'
        , 'y','z','_','$' };

        /// <summary>
        /// Conversion of an integer into characters 
        /// with base 64 using the table base64Chars
        /// </summary>
        /// <param name="number">The number to convert</param>
        /// <param name="result">The result char array to write to</param>
        /// <param name="start">The position in the char array to start writing</param>
        /// <param name="len">The length to write</param>
        /// <returns></returns>
        static void cv_to_64(uint number, ref char[] result, int start, int len)
        {
            uint act;
            int iDigit, nDigits;

            Debug.Assert(len <= 4);
            act = number;
            nDigits = len;

            for (iDigit = 0; iDigit < nDigits; iDigit++)
            {
                result[start + len - iDigit - 1] = base64Chars[(int)(act % 64)];
                act /= 64;
            }
            Debug.Assert(act == 0, "Logic failed, act was not null: " + act.ToString());
            return;
        }


        public static string ToIfcGuid(Guid guid)
        {
            uint[] num = new uint[6];
            char[] str = new char[22];
            int i, n;
            byte[] b = guid.ToByteArray();

            // Creation of six 32 Bit integers from the components of the GUID structure
            num[0] = (uint)(BitConverter.ToUInt32(b, 0) / 16777216);
            num[1] = (uint)(BitConverter.ToUInt32(b, 0) % 16777216);
            num[2] = (uint)(BitConverter.ToUInt16(b, 4) * 256 + BitConverter.ToInt16(b, 6) / 256);
            num[3] = (uint)((BitConverter.ToUInt16(b, 6) % 256) * 65536 + b[8] * 256 + b[9]);
            num[4] = (uint)(b[10] * 65536 + b[11] * 256 + b[12]);
            num[5] = (uint)(b[13] * 65536 + b[14] * 256 + b[15]);

            // Conversion of the numbers into a system using a base of 64
            n = 2;
            int pos = 0;
            for (i = 0; i < 6; i++)
            {
                cv_to_64(num[i], ref str, pos, n);
                pos += n; n = 4;
            }
            return new String(str);
        }
    }
}

 

 

 

Message 9 of 9
luisgt
in reply to: itinerati

I've a 'reverse' question:

How can I retrieve an Elemento.UniqueId from an Ifc Guid?

(I've observed that Autodesk use an XOR exclusive to obtain the Ifc Guid from the first part of Element.UniqueId and the Element.Id)

Tags (1)

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community