Change Wall parameters through ACAPI_Element_Change
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā2014-01-24 04:13 PM - last edited on ā2023-08-01 04:36 PM by Doreena Deng
I would like to change the volume (height,width,length), and the filler material of a wall. How is it possible through ACAPI_Element_Change, currently I have the API_Guid both GSGuid of an element?
Please also attend some example code to start with if possible.
Thank you: Andor
- Labels:
-
Add-On (C++)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā2014-01-25 10:06 AM
void changeWall(const API_Guid* ArchAPIGUID){ API_Element element, mask; API_Coord c1, c2; GSErrCode err = NoError; double height; double width; BNZeroMemory (&element, sizeof (API_Element)); API_Guid currAPIGuid = *ArchAPIGUID; element.header.guid = currAPIGuid; err = ACAPI_Element_Get (&element); if (err != NoError) DBPrintf("hiba"); c1 = element.wall.begC; c2 = element.wall.endC; height = element.wall.height; width = element.wall.thickness; DBPrintf("width XXXXXX %d", width); if (err == NoError) { ACAPI_ELEMENT_MASK_CLEAR (mask); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, begC); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, endC); //ACAPI_ELEMENT_MASK_SET (mask, API_WallType, height); //ACAPI_ELEMENT_MASK_SET (mask, API_WallType, thickness); element.wall.begC = c2; element.wall.endC = c1; //element.wall.height = 100*height; //element.wall.thickness = width; err = ACAPI_Element_Change (&element, &mask, NULL, 0, true); if (err == NoError) { DBPrintf("Fal megvan"); err = ACAPI_Element_Get (&element); width = element.wall.thickness; DBPrintf("width YYYYYY %d", width); } } } //getelements void getElements (void) { API_Quantity quantity, mask; API_Quantities quantities; API_QuantityPar params; GSErrCode err; GS::Array<API_Guid> elemList; ACAPI_Element_GetElemList(API_WallID,&elemList); ACAPI_ELEMENT_QUANTITY_MASK_CLEAR (mask); ACAPI_ELEMENT_QUANTITY_MASK_SET (mask, wall, surface1); ACAPI_ELEMENT_QUANTITY_MASK_SET (mask, wall, surface2); ACAPI_ELEMENT_QUANTITY_MASK_SET (mask, wall, volume); quantities.quantityData = &quantity; params.minOpeningSize = EPS; DBPrintf ("number of walls = %ld,", elemList.GetSize ()); short visible = 0; short onStory = 0; short inView = 0; for (GS::Array<API_Guid>::ConstIterator it = elemList.Enumerate (); it != NULL; ++it) { if (ACAPI_Element_Filter (*it, APIFilt_OnVisLayer)) ++visible; if (ACAPI_Element_Filter (*it, APIFilt_OnActFloor)) ++onStory; if (ACAPI_Element_Filter (*it, APIFilt_InCroppedView)) ++inView; //get quantities err = ACAPI_Element_GetQuantities (*it, ¶ms, &quantities, &mask); if (err == NoError) { DBPrintf ("surface1: %.2lf surface2: %.2lf volume: %.2lf", quantity.wall.surface1, quantity.wall.surface2, quantity.wall.volume); } changeWall(&it.GetCurrent()); } //DBPrintf ("%d visible, %d on the view\'s floor, %d in the cropped view\n", visible, onStory, inView); }
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā2014-01-27 11:21 AM
Your code is absolutely perfect. It works good, it switches the beginning and end coordinates of the walls.
If you check in ArchiCAD on the Wall Settings dialog you can't modify the thickness of the walls in the user interface also. That is because those wall's type is APIWtyp_Normal.
Check API_WallType, there are thickness (at the beginning point) and thickness1 (at the end point) and type (the geometry of the wall) attributes.
If the type is APIWtyp_Normal, it means that the wall has parallel sides, so you can't change thickness because the sides won't be parallel after the modification.
So if you want to change thickness you must change the type too.
void changeWall (const API_Guid* ArchAPIGUID) { API_Element element, mask; API_Coord c1, c2; GSErrCode err = NoError; double height; double width; BNZeroMemory (&element, sizeof (API_Element)); API_Guid currAPIGuid = *ArchAPIGUID; element.header.guid = currAPIGuid; err = ACAPI_Element_Get (&element); if (err != NoError) DBPrintf("hiba"); c1 = element.wall.begC; c2 = element.wall.endC; height = element.wall.height; width = element.wall.thickness; DBPrintf("width XXXXXX %d", width); if (err == NoError) { ACAPI_ELEMENT_MASK_CLEAR (mask); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, begC); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, endC); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, height); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, thickness); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, thickness1); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, type); element.wall.begC = c2; element.wall.endC = c1; element.wall.height = height*2; element.wall.thickness = width*2; element.wall.thickness1 = width*2; element.wall.type = APIWtyp_Trapez; err = ACAPI_Element_Change (&element, &mask, NULL, 0, true); if (err == NoError) { DBPrintf("Fal megvan"); err = ACAPI_Element_Get (&element); width = element.wall.thickness; DBPrintf("width YYYYYY %d", width); } } }
Best Regards,
Tibor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā2014-01-27 08:07 PM
Thank you for the code, but it still does not work. It gives me the error: APIERR_REFUSEDCMD.
If I try to modify the database with the following code gives the error: APIERR_BADDATABASE:
err = ACAPI_Database(APIDb_ChangeCurrentDatabaseID, &element.detail.databaseID); if(err == NoError){ } else { DBPrintf("%d",(Int32)err); }What could be the problem?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā2014-01-28 09:47 AM
Your code worked good for me, so the context of the API function call could be wrong.
Which API function call gives you APIERR_REFUSEDCMD error code?
Can you describe me the situation when you call your AddOn function? (view type, placed elements, maybe a screenshot could help also)
Regards,
Tibor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā2014-01-29 01:24 AM
AndorSzamos wrote:Are you bounding this operation with
It gives me the error: APIERR_REFUSEDCMD.
Active Thread Ltd
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā2014-01-29 08:47 AM
Actually I have a very simple code. I just try to draw a wall in ArchiCAD, and then modify the parameters of it.
#include "APIEnvir.h" // ---------------------------------- Includes --------------------------------- #include <math.h> #include <string.h> #include "ACAPinc.h" // also includes APIdefs.h //#include "Model.hpp" #include "APICommon.h" #include "DGModule.hpp" #include "DG.h" #include "MDIDs_APICD.h" //non-AC #include <iostream> #include <fstream> #include <string> //program includes // ---------------------------------- Types ------------------------------------ #define EvaluateButton 1 #define CancelButton 2 #define UserArea 3 #define Consumption1 5 #define Consumption2 7 using namespace std; // ---------------------------------- Variables -------------------------------- // ---------------------------------- Prototypes ------------------------------- // ============================================================================= // // Dialog control functions // // ============================================================================= void doEvaluation(void){ DBPrintf("bla"); } // ----------------------------------------------------------------------------- // Main dialog callback function // ----------------------------------------------------------------------------- static short DGCALLBACK DialogMessageHandler (short message, short dialId, short itemId, DGUserData userData, DGMessageData msgData) { UNUSED_PARAMETER (msgData); UNUSED_PARAMETER (dialId); UNUSED_PARAMETER (userData); //INNEN FOLYTASD A GOMBOKRA A REAGALAST switch (message) { case DG_MSG_CLOSE: break; case DG_MSG_CLICK: switch (itemId) { //case 2: // Close button case EvaluateButton: doEvaluation(); break; case CancelButton: return(1); break; default: return(1); break; } default: break; } return 0; } // DialogMessageHandler // ============================================================================= // // Main functions // // ============================================================================= #ifdef __APPLE__ #pragma mark - #endif // ----------------------------------------------------------------------------- // Call the list data dialog // ----------------------------------------------------------------------------- //------------------------------------------------------------------------------ // Get Element properties 2 //------------------------------------------------------------------------------ //change properties void changeWall (const API_Guid* ArchAPIGUID) { API_Element element, mask; API_Coord c1, c2; GSErrCode err = NoError; double height; double width; BNZeroMemory (&element, sizeof (API_Element)); API_Guid currAPIGuid = *ArchAPIGUID; element.header.guid = currAPIGuid; err = ACAPI_Element_Get (&element); if (err != NoError) DBPrintf("hiba"); c1 = element.wall.begC; c2 = element.wall.endC; height = element.wall.height; width = element.wall.thickness; DBPrintf("width XXXXXX %d", width); if (err == NoError) { //we need to change the database we are working with to the current database of the current element err = ACAPI_Database(APIDb_ChangeCurrentDatabaseID, &element.detail.databaseID); if(err == NoError){ } else { DBPrintf("%d",(Int32)err); } ACAPI_ELEMENT_MASK_CLEAR (mask); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, begC); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, endC); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, height); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, thickness); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, thickness1); ACAPI_ELEMENT_MASK_SET (mask, API_WallType, type); element.wall.begC = c2; element.wall.endC = c1; element.wall.height = height*2; element.wall.thickness = width*2; element.wall.thickness1 = width*2; element.wall.type = APIWtyp_Trapez; err = ACAPI_Element_Change (&element, &mask, NULL, 0, true); if (err == NoError) { DBPrintf("Fal megvan"); } else{ DBPrintf("%d",(Int32)err); } err = ACAPI_Element_Get (&element); width = element.wall.thickness; DBPrintf("width YYYYYY %d", width); } } void getElements (void) { API_Quantity quantity, mask; API_Quantities quantities; API_QuantityPar params; GSErrCode err; GS::Array<API_Guid> elemList; ACAPI_Element_GetElemList(API_WallID,&elemList); ACAPI_ELEMENT_QUANTITY_MASK_CLEAR (mask); ACAPI_ELEMENT_QUANTITY_MASK_SET (mask, wall, surface1); ACAPI_ELEMENT_QUANTITY_MASK_SET (mask, wall, surface2); ACAPI_ELEMENT_QUANTITY_MASK_SET (mask, wall, volume); quantities.quantityData = &quantity; params.minOpeningSize = EPS; DBPrintf ("number of walls = %ld,", elemList.GetSize ()); short visible = 0; short onStory = 0; short inView = 0; for (GS::Array<API_Guid>::ConstIterator it = elemList.Enumerate (); it != NULL; ++it) { if (ACAPI_Element_Filter (*it, APIFilt_OnVisLayer)) ++visible; if (ACAPI_Element_Filter (*it, APIFilt_OnActFloor)) ++onStory; if (ACAPI_Element_Filter (*it, APIFilt_InCroppedView)) ++inView; //get quantities err = ACAPI_Element_GetQuantities (*it, ¶ms, &quantities, &mask); if (err == NoError) { DBPrintf ("surface1: %.2lf surface2: %.2lf volume: %.2lf", quantity.wall.surface1, quantity.wall.surface2, quantity.wall.volume); } changeWall(&it.GetCurrent()); } //DBPrintf ("%d visible, %d on the view\'s floor, %d in the cropped view\n", visible, onStory, inView); } static void Evaluate (void) { API_ListData param; GSResModule saveResModule; BNZeroMemory (¶m, sizeof (param)); param.header.setIndex = 1; param.header.typeID = API_ComponentID; saveResModule = ACAPI_UseOwnResModule (); DGModalDialog (32510, DialogMessageHandler, (DGUserData) (¶m)); ACAPI_ResetResModule (saveResModule); getElements(); return; } //Evaluate // ----------------------------------------------------------------------------- // MenuCommandHandler // called to perform the user-asked command // ----------------------------------------------------------------------------- GSErrCode __ACENV_CALL MenuCommandHandler (const API_MenuParams *params) { UNUSED_PARAMETER (params); Evaluate (); return NoError; } // DoCommand // ============================================================================= // // Required functions // // ============================================================================= //------------------------------------------------------ // Dependency definitions //------------------------------------------------------ API_AddonType __ACENV_CALL CheckEnvironment (API_EnvirParams* envir) { if (envir->serverInfo.serverApplication != APIAppl_ArchiCADID) return APIAddon_DontRegister; GSResModule saveResModule = ACAPI_UseOwnResModule (); ACAPI_Resource_GetLocStr (envir->addOnInfo.name, 32000, 1); ACAPI_Resource_GetLocStr (envir->addOnInfo.description, 32000, 2); ACAPI_ResetResModule (saveResModule); return APIAddon_Normal; } /* CheckEnvironment */ //------------------------------------------------------ // Interface definitions //------------------------------------------------------ GSErrCode __ACENV_CALL RegisterInterface (void) { ACAPI_Register_Menu (32500, 0, MenuCode_DocExtras, MenuFlag_Default); return NoError; } /* RegisterInterface */ //------------------------------------------------------ // Called when the Add-On has been loaded into memory // to perform an operation //------------------------------------------------------ GSErrCode __ACENV_CALL Initialize (void) { GSErrCode err = ACAPI_Install_MenuHandler (32500, MenuCommandHandler); if (err != NoError) DBPrintf ("Energy-Budget Evaluator:: Initialize() ACAPI_Install_MenuHandler failed\n"); return err; } /* Initialize */ // ----------------------------------------------------------------------------- // FreeData // called when the Add-On is going to be unloaded // ----------------------------------------------------------------------------- GSErrCode __ACENV_CALL FreeData (void) { return NoError; }
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā2014-01-29 10:09 AM
Ralph pointed out your mistake.
If you want to change something through the API, then before the modification you must open an undoable session (ACAPI_OpenUndoableSession) and after you made the changes close the undoable session (ACAPI_CloseUndoableSession). This will guarantee that the user can click to the undo button and revert all the changes the Add-On made.
So put an ACAPI_OpenUndoableSession call in the beginning of the MenuCommandHandler function and an ACAPI_CloseUndoableSession to the end:
GSErrCode __ACENV_CALL MenuCommandHandler (const API_MenuParams *menuParams) { UNUSED_PARAMETER (params); GSErrCode err = ACAPI_OpenUndoableSession ("Undo changes"); if (err != NoError) { DBPrintf ("MenuCommandHandler cannot open undoable session: %d\n", err); return err; } Evaluate (); ACAPI_CloseUndoableSession (); return NoError; } // DoCommand
Regards,
Tibor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ā2014-01-29 10:37 AM
Thanks both of you, it solved the problem.
Regards,
Andor