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

Auto-generation add-on for column CAD compatibility

Anonymous
Not applicable
I'm still an API beginner. I've been dealing with C ++ 10 years ago.
Area(or Zone) and text were created by inserting the precast columns and column name layers drawn in CAD drawings using merge to worksheet function.
I want to create an add-on that uses this and calculates the outline size of the area to create a column object and select the column Text nearest to each area as this object and input it as the id of the column object. Would it be easy to develop based on an example
24 REPLIES 24
Ralph Wessel
Mentor
The ID is set in API_ElementMemo.elemInfoString
Ralph Wessel BArch
Anonymous
Not applicable
ACAPI_Element_Create (& columnElem, & columnMemo); An error has occurred during debugging.
What's wrong?
---------------------------------------------------------------------------------------------------------------------------------------------
GSErrCode err;
GS::Array<API_Guid> polylineList, textList;

err = ACAPI_Element_GetElemList(API_PolyLineID, &polylineList);
WriteReport("Number of total polyline: %u", (GS::UIntForStdio) polylineList.GetSize());
err = ACAPI_Element_GetElemList(API_TextID, &textList);
WriteReport("Number of total Text: %u", (GS::UIntForStdio) textList.GetSize());

Int32 i,j;
API_Element polyElem, textElem, columnElem;
API_ElementMemo polyMemo, textMemo, columnMemo;
API_Coord cenCoord;
API_Guid guid;
char text[20];
double a, b,x,y,minDist,Dist;
for (i = 0 ; i < 1; i++) //polylineList.GetSize(); i++)
{
BNZeroMemory(&polyElem, sizeof(API_Element));
BNZeroMemory(&polyMemo, sizeof(API_ElementMemo));
polyElem.header.guid = polylineList;
err = ACAPI_Element_Get(&polyElem);
err = ACAPI_Element_GetMemo(polyElem.header.guid, &polyMemo);
b = DistCPtr(&(*polyMemo.coords)[1], &(*polyMemo.coords)[2]);
a = DistCPtr(&(*polyMemo.coords)[2], &(*polyMemo.coords)[3]);
cenCoord.x = ((*polyMemo.coords)[1].x + (*polyMemo.coords)[2].x + (*polyMemo.coords)[3].x + (*polyMemo.coords)[4].x) / 4;
cenCoord.y = ((*polyMemo.coords)[1].y + (*polyMemo.coords)[2].y + (*polyMemo.coords)[3].y + (*polyMemo.coords)[4].y) / 4;
minDist = 100000000000000;
for (j=0 ; j<textList.GetSize(); j++)
{
BNZeroMemory(&textElem, sizeof(API_Element));
BNZeroMemory(&textMemo, sizeof(API_ElementMemo));
textElem.header.guid = textList;
err = ACAPI_Element_Get(&textElem);
err = ACAPI_Element_GetMemo(textElem.header.guid, &textMemo);
Dist = DistCPtr(&textElem.text.loc, &cenCoord);

if (Dist < minDist)
{
minDist = Dist;
strcpy(text, *textMemo.textContent);
guid = textElem.header.guid;
}

}
BNZeroMemory(&columnElem, sizeof(API_Element));
BNZeroMemory(&columnMemo, sizeof(API_ElementMemo));

columnElem.header.typeID = API_ColumnID;

GSErrCode err = ACAPI_Element_GetDefaults(&columnElem, nullptr);
columnElem.column.coreWidth = a;
columnElem.column.coreDepth = b;
columnElem.column.origoPos = cenCoord;
columnMemo.coords = (API_Coord**)BMhAllClear((5) * sizeof(API_Coord));
columnMemo.elemInfoString = new GS::UniString(text);
GS::UniString *elemInfoString= columnMemo.elemInfoString;

(*columnMemo.coords)[1].x = (*polyMemo.coords)[1].x;
(*columnMemo.coords)[1].y = (*polyMemo.coords)[1].y;
(*columnMemo.coords)[2].x = (*polyMemo.coords)[2].x;
(*columnMemo.coords)[2].y = (*polyMemo.coords)[2].y;
(*columnMemo.coords)[3].x = (*polyMemo.coords)[3].x;
(*columnMemo.coords)[3].y = (*polyMemo.coords)[3].y;
(*columnMemo.coords)[4].x = (*polyMemo.coords)[4].x;
(*columnMemo.coords)[4].y = (*polyMemo.coords)[4].y;
(*columnMemo.coords)[5].x = (*polyMemo.coords)[5].x;
(*columnMemo.coords)[5].y = (*polyMemo.coords)[5].y;

err = ACAPI_Element_Create(&columnElem, &columnMemo); // nullptr);// ==> Error
}
ACAPI_DisposeElemMemoHdls(&polyMemo);
ACAPI_DisposeElemMemoHdls(&textMemo);
ACAPI_DisposeElemMemoHdls(&columnMemo);
Ralph Wessel
Mentor
Take a look at the documentation for ACAPI_Element_GetMemo. It lists the memos that are relevant to every element type. For API_ColumnID, this includes gables, customOrigProfile and stretchedProfile, but not coords.

You should be able to make this work by setting columnElem.column.coreWidth and columnElem.column.coreDepth. You don't need to set a bounding polygon for a simple rectangle or circle.

Edit: Be careful with your array bounds - I notice you allocate memory for 5 coordinates, but then reference (*polyMemo.coords)[5]. Remember that C/C++ arrays are zero-based, so you can safely reference [0]…[size - 1]
Ralph Wessel BArch
Anonymous
Not applicable
Thanks Ralph Wessel !

Success Ha Ha Ha
!
Anonymous
Not applicable
What parts do I need to modify to make this add-on an API with a name other than Element_Test? What if I change the project name as well?
Ralph Wessel
Mentor
I can't remember all the details off the top of my head, but I think it's primarily named from the project settings Linker > General > Output File

This is generally easier to do by simply editing the files with a text editor, e.g. Find/Replace the expression "Element_Test". You can also rename the project/solution files.
Ralph Wessel BArch
Anonymous
Not applicable
I'm developing a routine to automatically generate beams using CAD data.
The basic development direction is
1) Call up the line list representing the contour of the beam
2) Find a line that is parallel and spaced by a certain width and calculates the width of the beam.
3) After drawing the centerline of the same length
4) Create a rectangular beam with the same information.
So far development has been completed with the test data.
In order to enter the height of the beam,
You want to modify the value of the beam member with the same ID by inputting the beam name and the dimension together, and entering the horizontal and vertical dimensions of the member corresponding to the name, respectively. I have the following questions.
1) How to find a list of elements with a specific layer name (ex: "exp1")?
    How do I find a text element with a layer name "t1"?
2) What is the function formula that calculates the points that meet on the extension line in the algorithm that finds the intersection point of two straight lines in 2D plane?
3) How can I retrieve a list of elements with a specific ID and change the attribute information?
Ralph Wessel
Mentor
park wrote:
I have the following questions.
1) How to find a list of elements with a specific layer name (ex: "exp1")?
    How do I find a text element with a layer name "t1"?
Elements store the index of the layer they are on (not the name), so you need to look up the layer first to retrieve its index. Don't hardcode the index because it can change. Then you will need to iterate through the elements to search for the required layer index. If you're searching for a specific element type, e.g. text, you can use ACAPI_Element_GetElemList to filter for that type.
park wrote:
2) What is the function formula that calculates the points that meet on the extension line in the algorithm that finds the intersection point of two straight lines in 2D plane?
I wrote my own methods for this before the ARCHICAD API existed, so I don't know what it has to offer in this respect.
park wrote:
3) How can I retrieve a list of elements with a specific ID and change the attribute information?
You will have to iterate through all the elements to find those with a specific ID – I'm not aware of a shortcut. If you change any attribute, an element can be written back to the database with ACAPI_Element_Change.
Ralph Wessel BArch
Anonymous
Not applicable
ACAPI_ELEMENT_MASK_CLEAR(mask);
ACAPI_ELEMENT_MASK_SET(mask, API_BeamType, height );

element.beam.height = beamList.height;

err = ACAPI_Element_Change(&element, &mask, &memo, 0, true);
err = ACAPI_Element_Get(&element);
err = ACAPI_Element_GetMemo(element.header.guid, &memo);

Firstly, the beam member generated from the plan view is read by the list data
We want to change the height of the beam member.
I programmed the above to change the height of the beam member

The height of the beam member is not changed.
Why?
Anonymous
Not applicable
When I checked the error, I noticed a NotEditeable error and turned on the layer. But how do you edit attribute information with editability?