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

API get the Concrete formwork area question?

leilei
Enthusiast
Hi !!
Can someone help me? I am writing a plugin to calculate the surface area of ​​the concrete formwork.There are a few problems here. I don't know how to solve them.For example, the beam and the column intersect only core.I want to calculate the side area of the column minus the area that intersects the beam.
I can't get the wanted area when I use the ACAPI_Element_GetSurfaceQuantities
and ACAPI_Element_GetQuantities function.I would like to ask if there is any way to get this area.

Regards,
Leilei
11 REPLIES 11
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
Hi Leilei,

ACAPI_Element_GetSurfaceQuantities should return the wanted area if you input the beam as a cover.
GS::Array<API_Guid>	elemGuids = { <guid_of_the_column> };
GS::Array<API_Guid>	coverElemGuids = { <guid_of_the_beam> };
GS::Array<API_ElemPartSurfaceQuantity>	elemPartSurfaces;

GSErrCode err = ACAPI_Element_GetSurfaceQuantities (&elemGuids, &coverElemGuids, &elemPartSurfaces);
if (err == NoError) {
	for (const auto& q : elemPartSurfaces) {
		ACAPI_WriteReport ("Visible area without the covered parts is %.2lf", true, q.exposedSurface);
	}
}
In your case the returned elemPartSurfaces array should contain only one API_ElemPartSurfaceQuantity.

Regards,
Tibor
leilei
Enthusiast
Tibor wrote:
Hi Leilei,

ACAPI_Element_GetSurfaceQuantities should return the wanted area if you input the beam as a cover.
GS::Array<API_Guid>	elemGuids = { <guid_of_the_column> };
GS::Array<API_Guid>	coverElemGuids = { <guid_of_the_beam> };
GS::Array<API_ElemPartSurfaceQuantity>	elemPartSurfaces;

GSErrCode err = ACAPI_Element_GetSurfaceQuantities (&elemGuids, &coverElemGuids, &elemPartSurfaces);
if (err == NoError) {
	for (const auto& q : elemPartSurfaces) {
		ACAPI_WriteReport ("Visible area without the covered parts is %.2lf", true, q.exposedSurface);
	}
}
In your case the returned elemPartSurfaces array should contain only one API_ElemPartSurfaceQuantity.

Regards,
Tibor
Hi Tibor,
I used the Do_CalcQuantities function in element_test to test this area. elemGuids is the guid of the column, and coverElemGuids is the guid of the beam, but what I get through this ACAPI_Element_GetSurfaceQuantities function is that the surface area of ​​the entire column does not reduce the intersection area with the beam, I don't Know where I am wrong?
Regards,
Leilei
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
Hi Lei,

I checked it with AC21 and AC22 using the Do_CalcQuantities function, see my video:
https://lorantfyt.tinytake.com/sf/MjgzNzY2Nl84NTIwMjQ4

Using the Do_CalcQuantities function the selected elements will be the coverElemGuids. So after I selected the beam, the returned surface was 6.41, which means it was sucessfully reduced with the intersection.

Regards,
Tibor
leilei
Enthusiast
Hi Tibor,
Thank you for your answer!
I got the same result according to the operation of your video 6.5, I called another developer to test the element_test demo, and the result is also 6.5. I don't know where there is any difference.
This is the video link I tested in AC21, and I also have the same result in AC22.
https://cl94083851-gmail.tinytake.com/sf/MjgzOTE5NF84NTI0NTIy
This is the Do_CalcQuantities fuction code

// -----------------------------------------------------------------------------
// Get quantities of the clicked element
// -----------------------------------------------------------------------------

void		Do_CalcQuantities (void)
{
	API_ElemTypeID		typeID;
	API_Guid			guid;
	API_ElementQuantity	quantity;
	API_QuantityPar		params;
	GSErrCode			err;

	if (!ClickAnElem ("Click an element to calculate quantities", API_ZombieElemID, nullptr, &typeID, &guid)) {
		WriteReport_Alert ("No element was clicked");
		return;
	}

	API_Element element;
	BNZeroMemory (&element, sizeof element);
	element.header.typeID = typeID;
	element.header.guid   = guid;

	err = ACAPI_Element_Get (&element);
	if (err != NoError) {
		WriteReport_Alert ("Unknown element");
		return;
	}

	BNZeroMemory (&params, sizeof (API_QuantityPar));
	params.minOpeningSize = EPS;

	GS::Array <API_CompositeQuantity>			composites;
	GS::Array <API_ElemPartQuantity>			elemPartQuantities;
	GS::Array <API_ElemPartCompositeQuantity>	elemPartComposites;

	GS::Array<API_Quantities>	quantities;
	GS::Array<API_Guid>			elemGuids;

	quantities.Push (API_Quantities ());
	quantities[0].elements = &quantity;
	quantities[0].composites = &composites;
	quantities[0].elemPartQuantities = &elemPartQuantities;
	quantities[0].elemPartComposites = &elemPartComposites;
	quantities.Push (quantities[0]);
	quantities.Push (quantities[0]);
	elemGuids.Push (element.header.guid);
	elemGuids.Push (element.header.guid);
	elemGuids.Push (element.header.guid);

	API_QuantitiesMask mask;
	ACAPI_ELEMENT_QUANTITIES_MASK_SETFULL (mask);
	err = ACAPI_Element_GetMoreQuantities (&elemGuids, &params, &quantities, &mask);
	if (err != NoError) {
		ErrorBeep ("ACAPI_Element_GetQuantities", err);
		return;
	}

	WriteReport ("%s GUID:%s", UniStringToConstUTF8String (ElemID_To_Name (typeID)),
	             			   UniStringToConstCString (APIGuidToString (element.header.guid)));

	switch (typeID) {
		case API_WallID:
					WriteReport ("  volume:   %lf", quantity.wall.volume);
					WriteReport ("  surface1: %lf", quantity.wall.surface1);
					WriteReport ("  surface2: %lf", quantity.wall.surface2);
					WriteReport ("  surface3: %lf", quantity.wall.surface3);
					WriteReport ("  length:   %lf", quantity.wall.length);
					WriteReport ("  windowsSurf:    %lf", quantity.wall.windowsSurf);
					WriteReport ("  doorsSurf:      %lf", quantity.wall.doorsSurf);
					WriteReport ("  emptyholesSurf: %lf", quantity.wall.emptyholesSurf);
					WriteReport ("  windowsWidth:   %d",  quantity.wall.windowsWidth);
					WriteReport ("  doorsWidth:     %lf", quantity.wall.doorsWidth);
					for (UInt32 i = 0; i < composites.GetSize (); i++) {
						API_Attribute	attr;
						GS::UniString	cFlags;
						GSErrCode		err;

						BNZeroMemory (&attr, sizeof(API_Attribute));
						attr.header.typeID = API_BuildingMaterialID;
						attr.header.index = composites.buildMatIndices;

						err = ACAPI_Attribute_Get (&attr);
						if (err == NoError) {
							if ((composites.flags & APISkin_Core) != 0) {
								cFlags.Assign ("Core");
							} if ((composites.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.buildMatIndices, composites.volumes, composites.projectedArea, static_cast<const char*> (cFlags.ToCStr ()));
					}
 					break;
		case API_ColumnID:
					WriteReport ("  coreSurface: %lf", quantity.column.coreSurface);
					WriteReport ("  veneSurface: %lf", quantity.column.veneSurface);
					WriteReport ("  coreVolume:  %lf", quantity.column.coreVolume);
					WriteReport ("  veneVolume:  %lf", quantity.column.veneVolume);
					break;
		case API_BeamID:
					WriteReport ("  rightLength:      %lf", quantity.beam.rightLength);
					WriteReport ("  leftLength:       %lf", quantity.beam.leftLength);
					WriteReport ("  bottomSurface:    %lf", quantity.beam.bottomSurface);
					WriteReport ("  topSurface:       %lf", quantity.beam.topSurface);
					WriteReport ("  edgeSurfaceLeft:  %lf", quantity.beam.edgeSurfaceLeft);
					WriteReport ("  edgeSurfaceRight: %lf", quantity.beam.edgeSurfaceRight);
					WriteReport ("  edgeSurface:      %lf", quantity.beam.edgeSurface);
					WriteReport ("  holesSurface:     %lf", quantity.beam.holesSurface);
					WriteReport ("  holesEdgeSurface: %lf", quantity.beam.holesEdgeSurface);
					WriteReport ("  holesNumber:      %d",  quantity.beam.holesNumber);
					WriteReport ("  volume:           %lf", quantity.beam.volume);
					WriteReport ("  holesVolume:      %lf", quantity.beam.holesVolume);
					break;
		case API_DoorID:
		case API_WindowID:
		case API_SkylightID:
					WriteReport ("  surface:  %lf", quantity.window.surface);
					WriteReport ("  volume:   %lf", quantity.window.volume);
					break;
		case API_ObjectID:
		case API_LampID:
					WriteReport ("  surface:  %lf", quantity.symb.surface);
					WriteReport ("  volume:   %lf", quantity.symb.volume);
					break;
		case API_SlabID:
					WriteReport ("  bottomSurface: %lf", quantity.slab.bottomSurface);
					WriteReport ("  topSurface:    %lf", quantity.slab.topSurface);
					WriteReport ("  edgeSurface:   %lf", quantity.slab.edgeSurface);
					WriteReport ("  volume:        %lf", quantity.slab.volume);
					WriteReport ("  perimeter:     %lf", quantity.slab.perimeter);
					WriteReport ("  holesSurf:     %lf", quantity.slab.holesSurf);
					WriteReport ("  holesPrm:      %lf", quantity.slab.holesPrm);
					for (UInt32 i = 0; i < composites.GetSize (); i++) {
						WriteReport ("  	composite:   %d		- volume: %lf		- projected area: %lf", composites.buildMatIndices, composites.volumes, composites.projectedArea);
					}
					break;
		case API_MeshID:
					WriteReport ("  bottomSurface: %lf", quantity.mesh.bottomSurface);
					WriteReport ("  topSurface:    %lf", quantity.mesh.topSurface);
					WriteReport ("  edgeSurface:   %lf", quantity.mesh.edgeSurface);
					WriteReport ("  volume:        %lf", quantity.mesh.volume);
					WriteReport ("  perimeter:     %lf", quantity.mesh.perimeter);
					WriteReport ("  holesSurf:     %lf", quantity.mesh.holesSurf);
					WriteReport ("  holesPrm:      %lf", quantity.mesh.holesPrm);
					break;
		case API_RoofID:
					WriteReport ("  bottomSurface: %lf", quantity.roof.bottomSurface);
					WriteReport ("  topSurface:    %lf", quantity.roof.topSurface);
					WriteReport ("  edgeSurface:   %lf", quantity.roof.edgeSurface);
					WriteReport ("  volume:        %lf", quantity.roof.volume);
					WriteReport ("  perimeter:     %lf", quantity.roof.perimeter);
					WriteReport ("  holesSurf:     %lf", quantity.roof.holesSurf);
					WriteReport ("  holesPrm:      %lf", quantity.roof.holesPrm);
					for (UInt32 i = 0; i < composites.GetSize (); i++) {
						WriteReport ("  	composite:   %d		- volume: %lf		- projected area: %lf", composites.buildMatIndices, composites.volumes, composites.projectedArea);
					}
					WriteReport ("  elemPartQuantities:      %d", elemPartQuantities.GetSize ());
					for (UInt32 i = 0; i < elemPartQuantities.GetSize (); i++) {
						WriteReport ("  	[%d,%d]		- volume: %lf", elemPartQuantities.partId.main, elemPartQuantities.partId.sub, elemPartQuantities.quantity.roof.volume);
					}
					WriteReport ("  elemPartComposites:      %d", elemPartComposites.GetSize ());
					for (UInt32 i = 0; i < elemPartComposites.GetSize (); i++) {
						WriteReport ("  	[%d,%d]", elemPartComposites.partId.main, elemPartComposites.partId.sub);
						for (UInt32 j = 0; j < elemPartComposites.composites.GetSize (); j++) {
							WriteReport ("  		composite:   %d		- volume: %lf		- projected area: %lf", elemPartComposites.composites.buildMatIndices, elemPartComposites.composites.volumes, elemPartComposites.composites.projectedArea);
						}
					}
					break;
		case API_ShellID:
					WriteReport ("  referenceSurface: %lf", quantity.shell.referenceSurface);
					WriteReport ("  oppositeSurface:    %lf", quantity.shell.oppositeSurface);
					WriteReport ("  edgeSurface:   %lf", quantity.shell.edgeSurface);
					WriteReport ("  volume:        %lf", quantity.shell.volume);
					WriteReport ("  perimeter:     %lf", quantity.shell.perimeter);
					WriteReport ("  holesSurf:     %lf", quantity.shell.holesSurf);
					WriteReport ("  holesPrm:      %lf", quantity.shell.holesPrm);
					for (UInt32 i = 0; i < composites.GetSize (); i++) {
						WriteReport ("  	composite:   %d		- volume: %lf		- projected area: %lf", composites.buildMatIndices, composites.volumes, composites.projectedArea);
					}
					break;
		case API_MorphID:
					WriteReport ("  surface:  %lf", quantity.morph.surface);
					WriteReport ("  volume:   %lf", quantity.morph.volume);
					WriteReport ("  elemPartQuantities:      %d", elemPartQuantities.GetSize ());
					for (UInt32 i = 0; i < elemPartQuantities.GetSize (); i++) {
						WriteReport ("  	floor[%d]		- volume: %lf, floorPlanArea: %lf, baseLevel: %lf, baseHeight: %lf, wholeHeight: %lf",
									elemPartQuantities.partId.floor,
									elemPartQuantities.quantity.morph.volume,
									elemPartQuantities.quantity.morph.floorPlanArea,
									elemPartQuantities.quantity.morph.baseLevel,
									elemPartQuantities.quantity.morph.baseHeight,
									elemPartQuantities.quantity.morph.wholeHeight);
					}
					break;
		case API_HatchID:
					WriteReport ("  surface:    %lf", quantity.hatch.surface);
					WriteReport ("  perimeter:  %lf", quantity.hatch.perimeter);
					WriteReport ("  holesPrm:   %lf", quantity.hatch.holesPrm);
					WriteReport ("  holesSurf:  %lf", quantity.hatch.holesSurf);
					break;
		case API_ZoneID:
					WriteReport ("  area:           %lf", quantity.zone.area);
					WriteReport ("  perimeter:      %lf", quantity.zone.perimeter);
					WriteReport ("  holesPrm:       %lf", quantity.zone.holesPrm);
					WriteReport ("  wallsPrm:       %lf", quantity.zone.wallsPrm);
					WriteReport ("  allCorners:     %d",  quantity.zone.allCorners);
					WriteReport ("  concaveCorners: %d",  quantity.zone.concaveCorners);
					WriteReport ("  wallsSurf:      %lf", quantity.zone.wallsSurf);
					WriteReport ("  doorsWidth:     %lf", quantity.zone.doorsWidth);
					WriteReport ("  doorsSurf:      %lf", quantity.zone.doorsSurf);
					WriteReport ("  windowsWidth:   %lf", quantity.zone.windowsWidth);
					WriteReport ("  windowsSurf:    %lf", quantity.zone.windowsSurf);
					WriteReport ("  baseLevel:      %lf", quantity.zone.baseLevel);
					WriteReport ("  floorThick:     %lf", quantity.zone.floorThick);
					WriteReport ("  height:         %lf", quantity.zone.height);
					WriteReport ("  netarea:        %lf", quantity.zone.netarea);
					WriteReport ("  netperimeter:   %lf", quantity.zone.netperimeter);
					break;
		default:
					WriteReport ("  Please click a 3D element", true);
					break;
	}

	API_Neig				**neigs;
	GS::Array<API_Guid>		coverElemGuids;
	API_SelectionInfo		selectionInfo;
	err = ACAPI_Selection_Get (&selectionInfo, &neigs, false);
	UInt32 nSel = BMGetHandleSize ((GSHandle) neigs) / sizeof (API_Neig);
	for (UInt32 i = 0; i < nSel; i++) {
		coverElemGuids.Push ((*neigs).guid);
	}

	BMKillHandle (reinterpret_cast<GSHandle *> (&neigs));

	GS::Array <API_ElemPartSurfaceQuantity>		elemPartSurfaces;
	elemGuids.Pop ();	// We have the same item 3 times. Have no idea why.
	elemGuids.Pop ();
	err = ACAPI_Element_GetSurfaceQuantities (&elemGuids, &coverElemGuids, &elemPartSurfaces);
	if (err != NoError) {
		ErrorBeep ("ACAPI_Element_GetSurfaceQuantities", err);
		return;
	}

	WriteReport ("---------- Exposed Surfaces ----------");
	WriteReport ("%s GUID : %s", UniStringToConstUTF8String (ElemID_To_Name (typeID)),
	             				 UniStringToConstCString (APIGuidToString (element.header.guid)));
	for (UInt32 i = 0; i < elemPartSurfaces.GetSize (); i++) {
		GS::UniString surfaceQuantityString;
		surfaceQuantityString += "Surface " + GS::ValueToUniString (i) + GS::UniString (GS::EOL);
		surfaceQuantityString += "  GUID           : " + APIGuidToString (elemPartSurfaces.elemGUID) + GS::UniString (GS::EOL);
		surfaceQuantityString += "  ComponentIndex : " + GS::ValueToUniString (elemPartSurfaces.componentIndex) + GS::UniString (GS::EOL);
		surfaceQuantityString += "  MaterialIndex  : " + GS::ValueToUniString (elemPartSurfaces.materialIndex) + GS::UniString (GS::EOL);
		surfaceQuantityString += "  BuildMatIndex  : " + GS::ValueToUniString (elemPartSurfaces.buildMatIdx) + GS::UniString (GS::EOL);
		surfaceQuantityString += "  ExposedSurface : " + GS::ValueToUniString (elemPartSurfaces.exposedSurface) + GS::UniString (GS::EOL);
		WriteReport ("%s", surfaceQuantityString.ToCStr ().Get ());
	}
	WriteReport ("---------- Exposed Surfaces ----------");
	return;
}		// Do_CalcQuantities
Regards,
Leilei
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
Hi Lei,

Thank you for the video!
Could you tell me please the following informations about your ARCHICAD?
- version number
- build number
- language version

Thanks,
Tibor
leilei
Enthusiast
Hi Tibor,

I tested the results using the demo versions of AC21 and AC22. Their version information is in the image below.At the same time, I also tested it in the AC21 Chinese version.These informations are:
version number:21.0.0
build number:5021
language version: simple Chinese
version number:21.0.0
build number:3005
language version: English(INT)
version number:22.0.0
build number:3004
language version: English(INT)
Maybe it's a problem with the project environment settings. Can you send me your pln demo test for testing?

Regards,
Leilei
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
Hi Leilei,

Here's my simple project with one column and one beam: I tried using AC21 INT 6551 and AC22 INT 3544. But I will test it using your builds too.

Regards,
Tibor
leilei
Enthusiast
Hi Tibor,

I tested your PLN DEMO, but the same result is 6.5. I don't know why. I called other Chinese developers to test and get the same result.

Regards,
Leilei
leilei
Enthusiast
Hi Tibor,

I tested the AC's own list to calculate the exposed area.This value is correct, but there are some differences.
There is a demo video link here:
https://cl94083851-gmail.tinytake.com/sf/Mjg0MTY0OF84NTMyMjAy

Regards,
Leilei

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!