BIM Coordinator Program (INT) April 22, 2024

Find the next step in your career as a Graphisoft Certified BIM Coordinator!

Archicad C++ API
About Archicad add-on development using the C++ API.
SOLVED!

Retrieving Names and Bounding Boxes of Building Elements in ArchiCAD Add-On

sercet65
Booster

Hello ArchiCAD Developer Community,

I'm currently developing an add-on for ArchiCAD and have encountered a challenge that I need some assistance with. My add-on aims to process various building elements like walls, slabs, and doors, and I need to retrieve not only their GUIDs but also their names (or local names) and bounding boxes.

So far, I have successfully obtained the GUIDs of the elements, but I'm struggling with how to fetch their names and bounding boxes. I'm looking for a way to access these additional details for each building element.

Here's a summary of my current approach:

  • The add-on iterates through building elements and retrieves their GUIDs.
  • I'm using functions like ACAPI_Element_Get and ACAPI_Element_GetMemo to fetch element data.

My question is:

  • How can I retrieve the name or local name of each building element (e.g., "Wall 1", "Slab A", etc.)?
  • Additionally, how can I obtain the bounding box of each element?

I suspect there are specific API functions or properties that I need to use, but I haven't been able to find the right approach.

Here is a snippet of the code where I process the elements:

 

void ReportElementProperties(const API_Guid& elementGuid, API_ElemTypeID elemType, std::ofstream& outFile)
{
    char reportStr[1024];
    API_Element element;
    BNZeroMemory(&element, sizeof(API_Element));
    element.header.guid = elementGuid;

    // Retrieve the element
    if (ACAPI_Element_Get(&element) == NoError) {
        GS::UniString elemName;
        // Handle Zone type specifically
        if (elemType == API_ZoneID) {
            // Assuming API_ZoneID correctly identifies a Zone
            API_ZoneType& zone = element.zone;
            GS::Guid gsGuid = APIGuid2GSGuid(zone.stampGuid);
            std::string guidStr = (const char*)gsGuid.ToUniString().ToCStr().Get();
            sprintf(reportStr, "Zone Stamp GUID: %s, Position: (%.2f, %.2f)", guidStr.c_str(), zone.pos.x, zone.pos.y);

            // Include the room or zone name if it exists
            if (!zone.roomName[0]) {
                strcat(reportStr, ", Room/Zone Name: ");
                strcat(reportStr, (const char*)zone.roomName);
            }
        }
        else if (elemType == API_DoorID) {
            // Handle Door elements

            API_DoorType& door = element.door;
            // Access markGuid from openingBase
            GS::Guid markGuid = APIGuid2GSGuid(door.openingBase.markGuid);
            std::string markGuidStr = (const char*)markGuid.ToUniString().ToCStr().Get();
            sprintf(reportStr, "Door Element, GUID: %s, Marker GUID: %s", APIGuidToString(elementGuid).ToCStr().Get(), markGuidStr.c_str());
        }

        else {
            // Handle other types (walls, slabs, etc.)
            if (ACAPI_Element_GetElemTypeName(elemType, elemName) == NoError) {
                sprintf(reportStr, "Element Type: %s, GUID: %s", (const char*)elemName.ToCStr(), APIGuidToString(elementGuid).ToCStr().Get());
            }
            else {
                sprintf(reportStr, "Element Type: %d, GUID: %s", elemType, APIGuidToString(elementGuid).ToCStr().Get());
            }
        }

 

 

Any guidance on how to retrieve both the name and bounding box for each building element within the add-on would be greatly appreciated. Are there specific API calls or structs that I should be looking into?

 

Thank you in advance for your time and assistance!

Best regards,

1 ACCEPTED SOLUTION

Accepted Solutions
Solution
Viktor Kovacs
Graphisoft
Graphisoft

For the bounding box you can use the ACAPI_Element_CalcBounds function.

 

For the name it depends on what you are trying to do. It may be different for some element types, but these are functions that work with all types:

  • ACAPI_Element_GetElemTypeName will return the localized name of the element type (like Wall, Slab, Zone, etc.)
  • ACAPI_Element_GetElementInfoString will return the user defined ID field of the element, and almost all elements have this field.

View solution in original post

4 REPLIES 4
Solution
Viktor Kovacs
Graphisoft
Graphisoft

For the bounding box you can use the ACAPI_Element_CalcBounds function.

 

For the name it depends on what you are trying to do. It may be different for some element types, but these are functions that work with all types:

  • ACAPI_Element_GetElemTypeName will return the localized name of the element type (like Wall, Slab, Zone, etc.)
  • ACAPI_Element_GetElementInfoString will return the user defined ID field of the element, and almost all elements have this field.

@Viktor Kovacs Thank you very much for the feedback.

// Retrieve the element
    if (ACAPI_Element_Get(&element) == NoError) {
        GS::UniString elemName;
        // Handle Zone type specifically
        if (elemType == API_ZoneID) {
            // Assuming API_ZoneID correctly identifies a Zone
            API_ZoneType& zone = element.zone;
            GS::Guid gsGuid = APIGuid2GSGuid(zone.stampGuid);
            std::string guidStr = (const char*)gsGuid.ToUniString().ToCStr().Get();
            sprintf(reportStr, "Zone Stamp GUID: %s, Position: (%.2f, %.2f)", guidStr.c_str(), zone.pos.x, zone.pos.y);

            // Include the room or zone name if it exists
            if (!zone.roomName[0]) {
                strcat(reportStr, ", Room/Zone Name: ");
                strcat(reportStr, (const char*)zone.roomName);
            }
        }

I have a small follow-up question to that.

 

I tried to handle the zone part separately. I got zone details but not room details such as room name etc. Is there a way to get this one also?

 

Thanks.

 

 

There are two problems with your code:

  • "if (!zone.roomName[0])" checks the opposite you probably wanted to check. Replace it with "if (zone.roomName[0])".
  • You are copying a GS::uchar_t (2-bytes) array to a char (1-byte) array. To have the correct value, convert it to GS::UniString, and then convert it to a C string.

Something like this:

if (zone.roomName[0]) {
    strcat_s (reportStr, ", Room/Zone Name: ");
    strcat_s (reportStr, GS::UniString (zone.roomName).ToCStr ());
}

 

poco2013
Mentor

FYI: Everything your  asking for can be returned with a short Python script including the 2D and 3D bounding box coordinates - Just saying , it's a lot simpler??

Gerry

Windows 11 - Visual Studio 2022; ArchiCAD 27
Learn and get certified!