cancel
Showing results for 
Search instead for 
Did you mean: 
EN
cancel
Showing results for 
Search instead for 
Did you mean: 
Apollos
Booster

Wall Quantities Extraction

Dear fellow Archicad C++ Users,

I am trying to extract the Quantities of walls (particularly composite walls). I followed the example folder Element_Snippets. But I am stuck, please I need help. I have tried several code setups some crashed but only this one gave me a WriteReport Dialog page but with Wall GUIDs but no Composite as output. 

Please here is my code, any useful help and guidance is appreciated.

 

 

void ExtractCompositeWallQuantities1() {
    GS::Array<API_Guid> wallGuids;
    ACAPI_Element_GetElemList(API_WallID, &wallGuids, APIFilt_OnActFloor);

    char reportBuffer[4096];
    BNZeroMemory(reportBuffer, sizeof(reportBuffer)); // Initialize reportBuffer with zeros

    char wallBuffer[512];
    BNZeroMemory(wallBuffer, sizeof(wallBuffer)); // Initialize wallBuffer with zeros

    strcat(reportBuffer, "Composite Wall Quantities:\n");

    for (const auto& wallGuid : wallGuids) {
        API_Quantities quantities;
        

        API_QuantitiesMask mask;
        BNZeroMemory(&mask, sizeof(mask)); // Initialize mask with zeros
        API_QuantityPar params;
        BNZeroMemory(&params, sizeof(params)); // Initialize params with zeros

        ACAPI_ELEMENT_COMPOSITES_QUANTITY_MASK_CLEAR(mask); // Clear the composites part of the mask
        ACAPI_ELEMENT_COMPOSITES_QUANTITY_MASK_SETFULL(mask); // Set the composites part of the mask to full


    	params.minOpeningSize = EPS;
        GSErrCode err = ACAPI_Element_GetQuantities(wallGuid, &params, &quantities, &mask);
        if (err == NoError) {
            const GS::Array<API_CompositeQuantity>* compositeQuantities = quantities.composites; // Dereference the pointer
            if (compositeQuantities) {
                for (UInt32 i = 0; i < compositeQuantities->GetSize(); ++i) {
                    const API_CompositeQuantity& compositeQuantity = (*compositeQuantities)[i];
                    double const wallVolume = compositeQuantity.volumes;
                    double const wallProjectedArea = compositeQuantity.projectedArea;
                    sprintf(wallBuffer, "Wall GUID: %s, Composite Index: %d, Volume: %.3lf, Projected Area: %.3lf\n",
                        APIGuidToString(wallGuid).ToCStr().Get(), i, wallVolume, wallProjectedArea);
                    strcat(reportBuffer, wallBuffer);
                }
            }
            else {
                strcat(reportBuffer, "No composite quantities available for wall GUID: ");
                strcat(reportBuffer, APIGuidToString(wallGuid).ToCStr().Get());
                strcat(reportBuffer, "\n");
            }
        }
        else {
            strcat(reportBuffer, "Failed to get quantities for wall GUID: ");
            strcat(reportBuffer, APIGuidToString(wallGuid).ToCStr().Get());
            strcat(reportBuffer, "\n");
        }
    }

    ACAPI_WriteReport(reportBuffer, true);
}

 

 

6 Replies 6
Apollos
Booster

Dear @BerndSchwarzenbacher ,

Please do you have any counsel relating to Composite Wall Quantities?

After this line:

API_Quantities quantities;

…add:

CompositeQuantityList composites;
quantities.composites = &composites;

ACAPI_Element_GetQuantities won't populate this variable for you - leaving it as nullptr indicates you aren't interested in those quantities.

 

Then instead of this:

const GS::Array<API_CompositeQuantity>* compositeQuantities = quantities.composites;

…just use the existing composites variable.

Ralph Wessel BArch
Central Innovation
Apollos
Booster

Thank you @Ralph Wessel . I will try out what you advised. Even though I also tried ACAPI_Element_GetMoreQuantities() as described in the Documentation but still not successful. I try out your suggestion I hope all goes. Please, here is the extra code I tried but no result. Please, where do you think I made a mistake?  Please I use Archicad 27 C++ API.

 

void CompositeWallQuantitiesExtraction()
{
    
    API_Element element;
	GS::Array<API_CompositeQuantity> composites;
    GS::Array<API_Quantities> quantities;
    GS::Array<API_Guid>       elemGuids;
	API_QuantitiesMask        mask;
    API_QuantityPar           params;

    ACAPI_Element_GetElemList(API_WallID, &elemGuids, APIFilt_OnActFloor);

    ACAPI_ELEMENT_COMPOSITES_QUANTITY_MASK_CLEAR(mask);
    ACAPI_ELEMENT_COMPOSITES_QUANTITY_MASK_SETFULL(mask);

    quantities.Push(API_Quantities());
    quantities[0].composites = &composites;
    elemGuids.Push(element.header.guid);
    params.minOpeningSize = EPS;

	GSErrCode err = ACAPI_Element_GetMoreQuantities(&elemGuids, &params, &quantities, &mask);
    if (err != NoError) {
        ErrorBeep("ACAPI_Element_GetQuantities", err);
        return;
    }
    WriteReport("%s GUID:%s", ElemID_To_Name(API_WallID).ToCStr(CC_UTF8).Get(),
        APIGuidToString(element.header.guid).ToCStr().Get());

    for (UInt32 i = 0; i < composites.GetSize(); i++) {
        API_Attribute	attr;
        GS::UniString	cFlags;
        GSErrCode		err;

        attr = {};
        attr.header.typeID = API_BuildingMaterialID;
        attr.header.index = composites[i].buildMatIndices;

        err = ACAPI_Attribute_Get(&attr);
        if (err == NoError) {
            if ((composites[i].flags & APISkin_Core) != 0) {
                cFlags.Assign("Core");
            } if ((composites[i].flags & APISkin_Finish) != 0) {
                if (!cFlags.IsEmpty())
                    cFlags.Append("+");
                cFlags.Append("Finish");
            }
        }

        WriteReport("  	composite:   %s[%d]		- volume: %lf		- projected area: %lf	- flag: %s", attr.header.name, composites[i].buildMatIndices, composites[i].volumes, composites[i].projectedArea, static_cast<const char*> (cFlags.ToCStr()));
    }
}

 

Apollos
Booster

Dear @Ralph Wessel , please your recommendations did not achieve the expected task. May be I did not understand and therefore still omitting something. Thank you for being there to help.

Try processing the quantities element by element like this:

void CompositeWallQuantitiesExtraction() {
	GS::Array<API_Guid> elemGuids;
	if ((ACAPI_Element_GetElemList(API_WallID, &elemGuids, APIFilt_OnActFloor) != NoError) || elemGuids.IsEmpty())
		return;
	for (auto& guid : elemGuids ) {
		API_QuantityPar params{};
		params.minOpeningSize = eps;
		GS::Array<API_CompositeQuantity> comps;
		API_Quantities quants;
		API_ElementQuantity elemQuants{};
		GS::Array <API_ElemPartQuantity> elemPartQuantities;
		GS::Array <API_ElemPartCompositeQuantity> elemPartComposites;
		quants.elements = &elemQuants;
		quants.composites = &comps;
		quants.elemPartQuantities = &elemPartQuantities;
		quants.elemPartComposites = &elemPartComposites;
		API_QuantitiesMask mask;
		ACAPI_ELEMENT_QUANTITIES_MASK_SETFULL(mask);
		auto error = ACAPI_Element_GetQuantities(guid, &params, &quants, &mask);
		if (error != NoError)
			continue;
		for (auto& comp : comps) {
			//Process composite quants here
		}
	}
Ralph Wessel BArch
Central Innovation
Apollos
Booster

Thank you @Ralph Wessel . I will try you advice. I will get back to give you an update. Once again thank you.

Didn't find the answer?

Check other topics in this Forum

Back to Forum

Read the latest accepted solutions!

Accepted Solutions

Start a new conversation!