a week ago
Archicad 26 C++ API, Windows 11.
We create Interior Elevations with ACAPI_Element_CreateExt. After create we need to set the visible plan distance between the solid marker/view line and the dashed depth line. A user can drag that gap (tracker shows a millimetre). We cannot keep a value written from code.
Live dump of one selected Interior Elevation (id 5, name " - 01", one segment):
ieCreationSegmentHorizontalOffset / ieOffset = 0
ieCreationSegmentDepth / ieDepth = 0
Memo has all three bags, 2 points each:
sectionSegmentMainCoords = view / solid marker line
sectionSegmentDistCoords = marked distant, 500 mm from view
sectionSegmentDepthCoords = depth / dashed, 1000 mm from view
iePolygonEdge coincides with the depth line.
Live horizRange = APIHorRange_Infinite (tool default was Limited).
nMainCoord = nDistCoord = nDepthCoord = 2.
So the millimetre on screen is not the create-only scalars. It is the distance between memo coordinate polylines.
What already failed on similar elements:
1. Writing only ieCreationSegmentDepth at create: finished field 0, live gap unchanged.
2. ACAPI_Element_ChangeExt of dist or main coords: error -2130313112, or 0 with no keep.
3. APIEdit_Drag of the parent: 0, no keep.
4. Replaying the hand APIEdit_Stretch from GetTranParams: 0, no keep.
Hand drag of the isolated segment hotspot does move the line.
Questions:
1. After create, is the supported way to set that gap a ChangeExt of sectionSegmentDepthCoords with memo mask APIMemoMask_SectionDepthCoords? Which subIndex: 0 or ACAPI_ELEMENT_CHANGEEXT_ALLSEGMENTS?
2. Must we also rewrite iePolygonEdge when it currently sits on the depth line?
3. Must horizRange be APIHorRange_Limited for the depth line to be writable?
4. Why do the create-only scalars stay 0 on Get after a successful CreateExt? Are they write-only, and if so what is the post-create write?
5. Markers cannot be changed alone. We already follow that. Does the depth line still require ChangeExt of the parent Interior Elevation together with the marker objects?
We can attach a full segment dump if useful.
Operating system used: Windows 11
yesterday
Hi,
I've analyzed the API code, and found a couple of suggestions:
- Use `APIMemoMask_SectionDepthCoords` with the 0-based index of the segment.
- With `subIndex == ALLSEGMENTS` (-1), any coordinate mask (main, dist or depth) returns `APIERR_BADPARS` immediately. Without a coordinate mask, nothing is written and the call returns 0. That matches your two symptoms.
- With a real `subIndex`, `APIMemoMask_SectionDistCoords` is rejected with `APIERR_BADPARS`. The dist line cannot be written for an Interior Elevation. It is re-synchronised automatically (regenerated between main and depth if needed).
- `memo.intElevSegments` must be non-null and cover `subIndex`.
- `memo.sectionSegmentDepthCoords` must contain only that segment's points. Allocate it with `BMAllocatePtr`. The arrays you get back from `GetMemo` are concatenated across all segments.
- Use `withdel = true`. With `false` the change is applied to a clone with a new GUID and the original stays untouched.
Suggestion from the SDK Sample:
API_Element element = {};
element.header.guid = ieGuid;
ACAPI_Element_Get (&element);
ACAPI_ELEMENT_MASK_SETFULL (mask); // IE-level defaults are not picked up from the live element
API_ElementMemo memo = {};
ACAPI_Element_GetMemo (ieGuid, &memo, APIMemoMask_SectionSegments | APIMemoMask_SectionMainCoords);
const API_Coord m0 = memo.sectionSegmentMainCoords[0], m1 = memo.sectionSegmentMainCoords[1]; // segment 0 only
const API_Coord d0 = memo.sectionSegmentDepthCoords[0];
double nx = d0.x - m0.x, ny = d0.y - m0.y, len = std::hypot (nx, ny);
nx /= len; ny /= len; // main -> depth direction keeps the side
const double gap = 1.5; // metres
BMKillPtr ((GSPtr*) &memo.sectionSegmentDepthCoords);
memo.sectionSegmentDepthCoords = (API_Coord*) BMAllocatePtr (2 * sizeof (API_Coord), ALLOCATE_CLEAR, 0);
memo.sectionSegmentDepthCoords[0] = { m0.x + nx * gap, m0.y + ny * gap };
memo.sectionSegmentDepthCoords[1] = { m1.x + nx * gap, m1.y + ny * gap };
GSErrCode err = ACAPI_Element_ChangeExt (&element, &mask, &memo, APIMemoMask_SectionDepthCoords,
0, nullptr, /*withdel*/ true, /*subIndex*/ 0);
ACAPI_DisposeElemMemoHdls (&memo);
Best regards,
Tamás
6 hours ago
Thank you Tamas. We tried your sample on Archicad 26 Windows.
Live Interior Elevation, one segment, not grouped. GetMemo with SectionSegments, SectionMainCoords and SectionDepthCoords. Then ChangeExt with memoMask SectionDepthCoords only, subIndex 0, withdel true, two depth points, nSubElems 0. SETFULL was on after CreateExt. We did not send ALLSEGMENTS (in this DevKit that value is minus one).
Result is APIERR_BADPARS. Live Get after the call is the same. A hand drag of the isolated hotspot still moves the dashed line.
Is another memoMask bit required on AC26 together with SectionDepthCoords?
Must marker objects be passed even when only depth coords change?
Does SETFULL after CreateExt cause BADPARS?
Must iePolygonEdge move with the depth line? Ours sits 100 mm from the view, not on the depth line.
We can send the full segment numbers if useful.
5 hours ago
Hi,
I'm looking into your other question about associative dimensions, if you can send a code snippet here, I can debug both.
Best regards,
Tamás
4 hours ago
Thank you Tamas. This thread is the Interior Elevation depth write. Happy to send the associative-dimension snippet in that other thread if you want both.
Here is the ChangeExt we ran on Archicad 26 Windows, one segment, not grouped. Same argument order as your sample. Difference: GetMemo also asks for SectionDepthCoords, because we read the live depth point for the side.
Result is APIERR_BADPARS, minus 2130313112. Live Get is unchanged.
API_Element element = {};
element.header.guid = ieGuid;
ACAPI_Element_Get (&element);
API_ElementMemo memo = {};
ACAPI_Element_GetMemo (
ieGuid,
&memo,
APIMemoMask_SectionSegments |
APIMemoMask_SectionMainCoords |
APIMemoMask_SectionDepthCoords);
const API_Coord m0 = memo.sectionSegmentMainCoords[0];
const API_Coord m1 = memo.sectionSegmentMainCoords[1];
const API_Coord d0 = memo.sectionSegmentDepthCoords[0];
double nx = d0.x - m0.x, ny = d0.y - m0.y, len = hypot (nx, ny);
nx /= len; ny /= len;
const double gap = 0.405;
BMKillPtr ((GSPtr*) &memo.sectionSegmentDepthCoords);
memo.sectionSegmentDepthCoords = (API_Coord*) BMAllocatePtr (2 * sizeof (API_Coord), ALLOCATE_CLEAR, 0);
memo.sectionSegmentDepthCoords[0].x = m0.x + nx * gap;
memo.sectionSegmentDepthCoords[0].y = m0.y + ny * gap;
memo.sectionSegmentDepthCoords[1].x = m1.x + nx * gap;
memo.sectionSegmentDepthCoords[1].y = m1.y + ny * gap;
API_Element mask = {};
ACAPI_ELEMENT_MASK_SETFULL (mask);
GSErrCode err = ACAPI_Element_ChangeExt (
&element,
&mask,
&memo,
APIMemoMask_SectionDepthCoords,
0,
NULL,
true,
0);
ACAPI_DisposeElemMemoHdls (&memo);
Live numbers for this element: nSegments 1, nMainCoord 2, nDepthCoord 2, horizRange Infinite, ieOffset and ieDepth 0. View-to-depth was 505 mm. Planned gap 405 mm on the same side. intElevSegments non-null. nSubElems 0. withdel true. subIndex 0. iePolygonEdge sits 100 mm from the view, not on the depth line. We did not rewrite it.