We value your input! Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey
2023-09-29 10:58 AM - last edited on 2024-09-16 02:45 PM by Doreena Deng
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
2023-09-29 06:52 PM
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.
2023-10-06 03:52 PM - last edited on 2023-10-08 07:21 AM by Laszlo Nagy
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;
}
}
2023-10-10 08:09 AM - edited 2023-10-10 08:10 AM
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
2024-02-16 12:09 PM - edited 2024-02-16 12:10 PM
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
2024-02-17 01:18 PM
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
2024-02-19 03:27 PM
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);
2024-02-20 04:28 PM
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.