2024-05-06 12:49 AM - last edited on 2024-09-16 02:51 PM by Doreena Deng
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(¶ms, 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, ¶ms, &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);
}
2024-05-06 03:28 AM
Dear @BerndSchwarzenbacher ,
Please do you have any counsel relating to Composite Wall Quantities?
2024-05-06 06:00 PM
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.
2024-05-06 06:42 PM - edited 2024-05-06 07:41 PM
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, ¶ms, &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()));
}
}
2024-05-08 01:05 PM
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.
2024-05-14 09:44 PM
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, ¶ms, &quants, &mask);
if (error != NoError)
continue;
for (auto& comp : comps) {
//Process composite quants here
}
}
2024-05-15 10:43 AM
Thank you @Ralph Wessel . I will try you advice. I will get back to give you an update. Once again thank you.