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

Creating Hole In Slab

Anonymous
Not applicable
Hello,
i'm trying to use ACAPI_Element_ChangeMemo in order to create a hole in my slab. for some reason, i always get a APIERR_BAPARS error for some reason.

i tried using the hole creation example in the Element_Test, but it showed the same error. here is my code:

void Shtuiot::Do_CreateSlabHole(API_Guid SlabG, API_Guid stairG)
{
	API_Element stair, slab;
	BNZeroMemory(&stair, sizeof(API_Element));
	BNZeroMemory(&slab, sizeof(API_Element));
	slab.header.guid = SlabG;
	stair.header.guid = stairG;
	GSErrCode err = ACAPI_Element_Get(&slab);
	err = ACAPI_Element_Get(&stair);
	API_ElementMemo slabMemo;
	BNZeroMemory(&slabMemo, sizeof(API_ElementMemo));
	err = ACAPI_Element_GetMemo(slab.header.guid, &slabMemo);
	API_Box3D box3D;
	BNZeroMemory(&box3D, sizeof(API_Box3D));
	err = ACAPI_Database(APIDb_CalcBoundsID, &stair.header, &box3D);
	API_Coord A, B, C, D;
	A.x = box3D.xMin;
	A.y = box3D.yMin;
	B.x = box3D.xMax;
	B.y = box3D.yMin;
	C.x = box3D.xMax;
	C.y = box3D.yMax;
	D.x = box3D.xMin;
	D.y = box3D.yMax;

	API_Element poly;
	BNZeroMemory(&poly, sizeof(API_Element));

	poly.header.typeID = API_MeshID;
	API_ElementMemo pmemo;
	BNZeroMemory(&pmemo, sizeof(API_ElementMemo));
	err = ACAPI_Element_GetDefaults(&poly, &pmemo);
	if (err != NoError) {
		ErrorBeep("ACAPI_Element_GetDefaults (Polyline)", err);
		return;
	}

	poly.mesh.poly.nCoords = 5;
	poly.mesh.poly.nSubPolys = 1;
	poly.mesh.poly.nArcs = 0;
	pmemo.coords = (API_Coord**)BMAllocateHandle((poly.mesh.poly.nCoords + 1) * sizeof(API_Coord), ALLOCATE_CLEAR, 0);
	pmemo.pends = (Int32**)BMAllocateHandle((poly.mesh.poly.nSubPolys + 1) * sizeof(Int32), ALLOCATE_CLEAR, 0);

	(*pmemo.pends)[0] = 0;
	(*pmemo.pends)[1] = 5;

	(*pmemo.coords)[0].x = 0.0;
	(*pmemo.coords)[0].y = 0.0;
	(*pmemo.coords)[1] = A;
	(*pmemo.coords)[2] = B;
	(*pmemo.coords)[3] = C;
	(*pmemo.coords)[4] = D;
	(*pmemo.coords)[5] = A;


	err = ACAPI_Goodies(APIAny_InsertSubPolyID, &slabMemo, &pmemo);
	if (err == NoError) {
		API_ElementMemo tmpMemo;
		BNZeroMemory(&tmpMemo, sizeof(API_ElementMemo));
		tmpMemo.coords = slabMemo.coords;
		tmpMemo.pends = slabMemo.pends;
		tmpMemo.parcs = slabMemo.parcs;
		tmpMemo.vertexIDs = slabMemo.vertexIDs;
		tmpMemo.meshPolyZ = slabMemo.meshPolyZ;
		tmpMemo.edgeIDs = slabMemo.edgeIDs;
		tmpMemo.edgeTrims = slabMemo.edgeTrims;
		tmpMemo.contourIDs = slabMemo.contourIDs;
		err = ACAPI_CallUndoableCommand("Delete Poly", [&]() -> GSErrCode {
			return ACAPI_Element_ChangeMemo(slab.header.guid, APIMemoMask_Polygon, &slabMemo); });
		if (err != NoError)
			ErrorBeep("ACAPI_Element_ChangeMemo", err);
	}
	else
		ErrorBeep("APIAny_InsertSubPolyID", err);

	ACAPI_DisposeElemMemoHdls(&pmemo);
	ACAPI_DisposeElemMemoHdls(&slabMemo);


}

Would really appreciate some help!

Thank you
5 REPLIES 5
Ralph Wessel
Mentor
The polygon structure in a memo is quite messy. Note that the vertices of the outer perimeter precede any hole vertices (which I suspect is the problem in this case). For detailed documentation about API_Polygon and the associated memo, look at the documentation here: http://archicadapi.graphisoft.com/documentation/api_polygon
Ralph Wessel BArch
Anonymous
Not applicable
Hi Ralph,
I'm aware of the messiness of the polygon inside the memo. I've read this document carefully a few times
in order to maintain the necessary logic inside the polygon, i used APIAny_​InsertSubPolyID, which doesn't return any error. That's why i thought all the polygon-related issues are not a problem. How can i make sure that the outer vertices precede the inner ones? is there an alternative to this goodies function?
Thanks!
Anonymous
Not applicable
How can i do this correctly?
Ralph Wessel
Mentor
There's some code for this in the Do_Poly_NewHole function of the example project Element_Test. I can't comment specifically on this problem because we've written a C++ polygon class to simplify coding and only convert to/from the API memo structure on an as-need basis.
Ralph Wessel BArch
Hoa Tu
Newcomer
I also need the APIAny_InsertSubPolyID function to be working on the slabs and roofs.

I have tested the example in the Element Test API. I can only make it work on the Fill Element.
When I tried on Slab or Roof Elements, they all returned APIERR_BADPARS.

May be the function is not working properly yet!