We value your input!
Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey

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

Move several elements to mesh

tolltech
Participant

I have a task to move elements down to mesh. I try to write a plugin, but i can't get all mesh polygons or vertices using API. I need it because I want to change the Z coordinate of other objects to move it closer to mesh. What else can I do? Or maybe is it a way to do what i want? I have tried to build structures API_Element;API_ElementMemo;  using API_MeshID, but there is no information about polygons or vertices

7 REPLIES 7

Hi tolltech!

Maybe the ModelAccess API would help in your case.

In the API there's also a related example called ModelAccess_Test.

 

For simple objects like walls and doors, I think it would be possible to derive the coordinates for a mesh from the information given in API_Element and API_ElementMemo.


Hope that helps!
Feel free to ask further if you get stuck.

tolltech
Participant

Sad, but i still cant solve my problem, i try to get several models, but i cant see usefull data inside. Maybe i should try use ACAPI_ModelAccess_GetTextureCoord to determine z coordinate, but i cant understand what paramateres i should pass to this function. Please help i have no idea(

 

My bad tries here:

 

GS::Array<API_Guid> elemList;
ACAPI_Element_GetElemList(API_MeshID, &elemList, APIFilt_OnActFloor);

if (elemList.GetSize() > 0)
{
API_Element mesh = {};
API_ElementMemo  memo;
mesh.header.guid = elemList[0];
GSErrCode err = ACAPI_Element_Get(&mesh);

if (err != NoError)
return;

//https://archicadapi.graphisoft.com/documentation/api_gridmesh
if (mesh.header.hasMemo) {
err = ACAPI_Element_GetMemo(mesh.header.guid, &memo);
if (err != NoError) {
return;
}

//here deeper

ACAPI_DisposeElemMemoHdls(&memo);

API_ElemInfo3D mesh3D = {};

err = ACAPI_Element_Get3DInfo(mesh.header, &mesh3D);

if (err != NoError)
return;

API_Component3D          comp3D;
BNZeroMemory(&comp3D, sizeof(API_Component3D));
comp3D.header.index = 0;
comp3D.header.typeID = API_BodyID;
//err = ACAPI_ModelAccess_GetComponent(&comp3D); //compilation error

if (err != NoError)
return;
}
}

Sorry I've completely misunderstood your question before. I thought with "move down to mesh" you mean something like "convert to mesh".

You actually want to get the z-coordinates from a mesh! You can use memo.meshPolyZ for that. Here's a code example:

 

 

GS::Array<API_Guid> elemList;
ACAPI_Element_GetElemList (API_MeshID, &elemList, APIFilt_OnActFloor);

if (elemList.GetSize () > 0)
{
  API_Element mesh{};
  API_ElementMemo memo{};
  mesh.header.guid = elemList[0];
  GSErrCode err = ACAPI_Element_Get (&mesh);
  if (err != NoError) { return err; }

  //https://archicadapi.graphisoft.com/documentation/api_gridmesh
  if (mesh.header.hasMemo) {
    err = ACAPI_Element_GetMemo (mesh.header.guid, &memo);
    if (err != NoError) { return err; }

    ACAPI_WriteReport ("i: (x, y, z)", false);
    ACAPI_WriteReport ("------------", false);
    for (GS::Int32 i = 1; i <= mesh.mesh.poly.nCoords; ++i) {
      ACAPI_WriteReport ("%d: (%f, %f, %f): ", false, i, (*memo.coords)[i].x, (*memo.coords)[i].y, (*memo.meshPolyZ)[i]);
    }
  }
  ACAPI_DisposeElemMemoHdls (&memo);
}

 

 


Be aware that the meshPolyZ coordinates are relative to the mesh reference plane! So if you want the global z coordinate you also have to take element.header.level and element.header.floor into account.

Hope that helps!
Bernd

Hello again!

Your code works, thanks a lot!

 

Now I want to change the Z coordiante of objects, i tried like this, but nothng happened

 

 

 

GSErrCode            err;
API_SelectionInfo    selectionInfo;
GS::Array<API_Neig>  selNeigs;

err = ACAPI_Selection_Get(&selectionInfo, &selNeigs, true);
BMKillHandle((GSHandle*)&selectionInfo.marquee.coords);

GS::Array<API_Guid> inds = GS::Array<API_Guid>();

if (selectionInfo.typeID != API_SelEmpty) 
{		
	for (const API_Neig& selNeig : selNeigs) {
		if (!ACAPI_Element_Filter(selNeig.guid, APIFilt_IsEditable))
			continue;

		API_Element element = {};
		element.header.guid = selNeig.guid;
		GSErrCode err = ACAPI_Element_Get(&element);
		if (err != NoError)
			continue;

		element.object.level = 0;

		ACAPI_Element_Change(&element, NULL, NULL, 0, true);
	}
}

 

 

 Sorry I am newbie, but it is all I found in google.

 

Also it is very strange that i see in selected objects. I select two objects, try to see element.object.level and see that the upper object has smaller value in this field

 

You need to specify a mask for ACAPI_Element_Change for the fields you want to change.

So something like this should work (untested):

// .......

element.object.level = 0;

API_Element mask{};
ACAPI_ELEMENT_MASK_CLEAR (mask);
ACAPI_ELEMENT_MASK_SET (mask, API_ObjectType, level);

ACAPI_Element_Change(&element, &mask, NULL, 0, true);

// ......

 

 


@tolltech wrote:

Also it is very strange that i see in selected objects. I select two objects, try to see element.object.level and see that the upper object has smaller value in this field


This is likely due to the second object being placed on a different story. The field element.object.level is relative to the story base line.


Hope that helps,
Bernd

tolltech
Participant

I have tried this ones, but got the error -2130312307 (or 7003)

 

			API_Element mask{};
			ACAPI_ELEMENT_MASK_CLEAR(mask);
			ACAPI_ELEMENT_MASK_SET(mask, API_ObjectType, level);

			err = ACAPI_Element_Change(&element, &mask, NULL, 0, true);

 

			API_Element mask{};
			ACAPI_ELEMENT_MASK_CLEAR(mask);
			ACAPI_ELEMENT_MASK_SET(mask, API_Element, object.level);

			err = ACAPI_Element_Change(&element, &mask, NULL, 0, true);

 

 

You can check error codes here: https://graphisoft.github.io/archicad-api-devkit/md__common_doxygen_files_2_articles_2_error___codes...

The error you get is APIERR_NEEDSUNDOSCOPE. So you need to wrap the above code into a ACAPI_CallUndoableCommand scope.