Skip to content

Commit aa46202

Browse files
committed
New CreateSlabs command
1 parent c4c55f4 commit aa46202

File tree

4 files changed

+281
-1
lines changed

4 files changed

+281
-1
lines changed

README.md

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Download the Add-On or build it for your own platform and Archicad version.
2020
- [ReloadLibraries](#reloadlibraries)
2121
- [MoveElements](#moveelements)
2222
- [CreateColumns](#createcolumns)
23+
- [CreateSlabs](#createcolumns)
2324
- [GetHotlinks](#gethotlinks)
2425
- [GetGDLParametersOfElements](#getgdlparametersofelements)
2526
- [ChangeGDLParametersOfElements](#changegdlparametersofelements)
@@ -212,11 +213,66 @@ conn = ACConnection.connect ()
212213
acc = conn.commands
213214
act = conn.types
214215

215-
origosOfNewColumns = [{'x': 1.0, 'y': 1.0, 'z': 0.0}, {'x': 5.0, 'y': 5.0, 'z': 3.0}]
216+
storyHeight = 3.0
217+
origosOfNewColumns = [{'x': x*2, 'y': y*2, 'z': z*storyHeight} for x in range(10) for y in range(10) for z in range(2)]
216218

217219
acc.ExecuteAddOnCommand (act.AddOnCommandId ('AdditionalJSONCommands', 'CreateColumns'), {'coordinates': origosOfNewColumns})
218220
```
219221

222+
## CreateSlabs
223+
Creates polygonal slabs. The given coordinates will define the polygon of the edges.
224+
### Parameters
225+
* slabs (required)
226+
* Type: object
227+
* Fields:
228+
* level (required)
229+
* Type: number
230+
* The elevation of the slab, the Z coordinate of the reference line.
231+
* polygonCoordinates (required)
232+
* Type: array of 2D coordinates with x,y values.
233+
* holes (optional)
234+
* polygonCoordinates (optional)
235+
* Type: array of 2D coordinates with x,y values.
236+
### Response
237+
* errorMessage
238+
* Type: string
239+
* The error message upon error. If the command executed successfully, then there is no response.
240+
### Python Example
241+
```python
242+
from archicad import ACConnection
243+
244+
conn = ACConnection.connect ()
245+
246+
acc = conn.commands
247+
act = conn.types
248+
249+
origo = {'x': 0, 'y': 0, 'z': 0}
250+
slabWidth = 6.0
251+
slabHoleWidth = 2.0
252+
storyHeight = 3.0
253+
254+
slabPolygonCoordinates = [
255+
{'x': +3.0, 'y': -3.0},
256+
{'x': +3.0, 'y': +3.0},
257+
{'x': -3.0, 'y': +3.0},
258+
{'x': -3.0, 'y': -3.0}
259+
]
260+
slabHolePolygonCoordinates = [
261+
{'x': +1.0, 'y': -1.0},
262+
{'x': +1.0, 'y': +1.0},
263+
{'x': -1.0, 'y': +1.0},
264+
{'x': -1.0, 'y': -1.0}
265+
]
266+
267+
slabs = [{
268+
'level': i * storyHeight,
269+
'polygonCoordinates': slabPolygonCoordinates,
270+
'holes': [{'polygonCoordinates': slabHolePolygonCoordinates}]
271+
} for i in range(3)]
272+
273+
acc.ExecuteAddOnCommand (act.AddOnCommandId ('AdditionalJSONCommands', 'CreateSlabs'), {'slabs': slabs})
274+
```
275+
220276
## GetHotlinks
221277
Get the file system locations (path) of the hotlink modules. The hotlinks can have tree hierarchy in the project.
222278
### Response

Src/CreateSlabsCommand.cpp

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#include "CreateSlabsCommand.hpp"
2+
#include "ObjectState.hpp"
3+
#include "OnExit.hpp"
4+
5+
6+
GS::String CreateSlabsCommand::GetName () const
7+
{
8+
return "CreateSlabs";
9+
}
10+
11+
12+
constexpr const char* SlabsParameterField = "slabs";
13+
constexpr const char* LevelParameterField = "level";
14+
constexpr const char* PolygonCoordinatesParameterField = "polygonCoordinates";
15+
constexpr const char* HolesParameterField = "holes";
16+
17+
18+
GS::Optional<GS::UniString> CreateSlabsCommand::GetInputParametersSchema () const
19+
{
20+
return GS::UniString::Printf (R"({
21+
"type": "object",
22+
"properties": {
23+
"%s": {
24+
"type": "array",
25+
"description": "The parameters of the new Slabs.",
26+
"items": {
27+
"type": "object",
28+
"description" : "The parameters of the new Slab.",
29+
"properties" : {
30+
"%s": {
31+
"type": "number",
32+
"description" : "The Z coordinate value of the reference line of the slab."
33+
},
34+
"%s": {
35+
"type": "array",
36+
"description": "The 2D coordinates of the edge of the slab.",
37+
"items": {
38+
"type": "object",
39+
"description" : "Position of a 2D point.",
40+
"properties" : {
41+
"x": {
42+
"type": "number",
43+
"description" : "X value of the point."
44+
},
45+
"y" : {
46+
"type": "number",
47+
"description" : "Y value of the point."
48+
}
49+
},
50+
"additionalProperties": false,
51+
"required" : [
52+
"x",
53+
"y"
54+
]
55+
}
56+
}
57+
},
58+
"additionalProperties": true,
59+
"required" : [
60+
"%s",
61+
"%s"
62+
]
63+
}
64+
}
65+
},
66+
"additionalProperties": false,
67+
"required": [
68+
"%s"
69+
]
70+
})",
71+
SlabsParameterField,
72+
LevelParameterField,
73+
PolygonCoordinatesParameterField,
74+
LevelParameterField,
75+
PolygonCoordinatesParameterField,
76+
SlabsParameterField);
77+
}
78+
79+
80+
static API_Coord GetCoordinateFromObjectState (const GS::ObjectState& objectState)
81+
{
82+
API_Coord coordinate = {};
83+
objectState.Get ("x", coordinate.x);
84+
objectState.Get ("y", coordinate.y);
85+
return coordinate;
86+
}
87+
88+
89+
static void AddPolyToMemo (const GS::Array<GS::ObjectState>& polygonCoordinates,
90+
const API_OverriddenAttribute& sideMat,
91+
Int32& iCoord,
92+
Int32& iPends,
93+
API_ElementMemo& memo)
94+
{
95+
Int32 iStart = iCoord;
96+
for (const GS::ObjectState& polygonCoordinate : polygonCoordinates) {
97+
(*memo.coords)[iCoord] = GetCoordinateFromObjectState (polygonCoordinate);
98+
(*memo.edgeTrims)[iCoord].sideType = APIEdgeTrim_Vertical; // Only vertical trim is supported yet by my code
99+
memo.sideMaterials[iCoord] = sideMat;
100+
++iCoord;
101+
}
102+
(*memo.coords)[iCoord] = (*memo.coords)[iStart];
103+
(*memo.pends)[iPends++] = iCoord;
104+
(*memo.edgeTrims)[iCoord].sideType = (*memo.edgeTrims)[iStart].sideType;
105+
(*memo.edgeTrims)[iCoord].sideAngle = (*memo.edgeTrims)[iStart].sideAngle;
106+
memo.sideMaterials[iCoord] = memo.sideMaterials[iStart];
107+
++iCoord;
108+
}
109+
110+
111+
GS::ObjectState CreateSlabsCommand::Execute (const GS::ObjectState& parameters, GS::ProcessControl& /*processControl*/) const
112+
{
113+
GS::Array<GS::ObjectState> slabs;
114+
parameters.Get (SlabsParameterField, slabs);
115+
116+
GSIndex iSlab = 0;
117+
const APIErrCodes err = (APIErrCodes) ACAPI_CallUndoableCommand ("Create Slabs", [&] () -> GSErrCode {
118+
APIErrCodes err = (APIErrCodes) NoError;
119+
const GS::Array<GS::Pair<short, double>> storyLevels = Utilities::GetStoryLevels ();
120+
for (const GS::ObjectState& slab : slabs) {
121+
if (!slab.Contains (LevelParameterField) ||
122+
!slab.Contains (PolygonCoordinatesParameterField)) {
123+
continue;
124+
}
125+
126+
API_Element element = {};
127+
API_ElementMemo memo = {};
128+
const GS::OnExit guard ([&memo] () { ACAPI_DisposeElemMemoHdls (&memo); });
129+
130+
#ifdef ServerMainVers_2600
131+
element.header.type = API_SlabID;
132+
#else
133+
element.header.typeID = API_SlabID;
134+
#endif
135+
err = (APIErrCodes) ACAPI_Element_GetDefaults (&element, &memo);
136+
137+
slab.Get(LevelParameterField, element.slab.level);
138+
element.header.floorInd = Utilities::GetFloorIndexAndOffset (element.slab.level, storyLevels, element.slab.level);
139+
140+
GS::Array<GS::ObjectState> polygonCoordinates;
141+
GS::Array<GS::ObjectState> holes;
142+
slab.Get (PolygonCoordinatesParameterField, polygonCoordinates);
143+
if (slab.Contains (HolesParameterField)) {
144+
slab.Get (HolesParameterField, holes);
145+
}
146+
element.slab.poly.nCoords = polygonCoordinates.GetSize() + 1;
147+
element.slab.poly.nSubPolys = 1;
148+
element.slab.poly.nArcs = 0; // Curved edges are not supported yet by my code
149+
150+
for (const GS::ObjectState& hole : holes) {
151+
if (!hole.Contains (PolygonCoordinatesParameterField)) {
152+
continue;
153+
}
154+
GS::Array<GS::ObjectState> holePolygonCoordinates;
155+
hole.Get (PolygonCoordinatesParameterField, holePolygonCoordinates);
156+
element.slab.poly.nCoords += holePolygonCoordinates.GetSize() + 1;
157+
++element.slab.poly.nSubPolys;
158+
}
159+
160+
memo.coords = reinterpret_cast<API_Coord**> (BMAllocateHandle ((element.slab.poly.nCoords + 1) * sizeof (API_Coord), ALLOCATE_CLEAR, 0));
161+
memo.edgeTrims = reinterpret_cast<API_EdgeTrim**> (BMAllocateHandle ((element.slab.poly.nCoords + 1) * sizeof (API_EdgeTrim), ALLOCATE_CLEAR, 0));
162+
memo.sideMaterials = reinterpret_cast<API_OverriddenAttribute*> (BMAllocatePtr ((element.slab.poly.nCoords + 1) * sizeof (API_OverriddenAttribute), ALLOCATE_CLEAR, 0));
163+
memo.pends = reinterpret_cast<Int32**> (BMAllocateHandle ((element.slab.poly.nSubPolys + 1) * sizeof (Int32), ALLOCATE_CLEAR, 0));
164+
165+
Int32 iCoord = 1;
166+
Int32 iPends = 1;
167+
AddPolyToMemo(polygonCoordinates,
168+
element.slab.sideMat,
169+
iCoord,
170+
iPends,
171+
memo);
172+
173+
for (const GS::ObjectState& hole : holes) {
174+
if (!hole.Contains (PolygonCoordinatesParameterField)) {
175+
continue;
176+
}
177+
GS::Array<GS::ObjectState> holePolygonCoordinates;
178+
hole.Get (PolygonCoordinatesParameterField, holePolygonCoordinates);
179+
180+
AddPolyToMemo(holePolygonCoordinates,
181+
element.slab.sideMat,
182+
iCoord,
183+
iPends,
184+
memo);
185+
}
186+
187+
err = (APIErrCodes) ACAPI_Element_Create (&element, &memo);
188+
189+
if (err != NoError) {
190+
break;
191+
}
192+
193+
++iSlab;
194+
}
195+
196+
return err;
197+
});
198+
199+
if (err != NoError) {
200+
const GS::UniString errorMsg = GS::UniString::Printf ("Failed to create slab #%d!", iSlab);
201+
return CreateErrorResponse (err, errorMsg);
202+
}
203+
204+
return {};
205+
}

Src/CreateSlabsCommand.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#if !defined (CREATESLABCOMMAND_HPP)
2+
#define CREATESLABCOMMAND_HPP
3+
4+
#pragma once
5+
6+
#include "AdditionalJSONCommand.hpp"
7+
8+
9+
class CreateSlabsCommand : public AdditionalJSONCommand {
10+
public:
11+
virtual GS::String GetName () const override;
12+
virtual GS::Optional<GS::UniString> GetInputParametersSchema () const override;
13+
virtual GS::ObjectState Execute (const GS::ObjectState& parameters, GS::ProcessControl& processControl) const override;
14+
};
15+
16+
17+
#endif

Src/Main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "ReloadLibrariesCommand.hpp"
1515
#include "MoveElementsCommand.hpp"
1616
#include "CreateColumnsCommand.hpp"
17+
#include "CreateSlabsCommand.hpp"
1718
#include "GetHotlinksCommand.hpp"
1819
#include "GetGDLParametersOfElementsCommand.hpp"
1920
#include "ChangeGDLParametersOfElementsCommand.hpp"
@@ -65,6 +66,7 @@ GSErrCode __ACENV_CALL Initialize (void)
6566
err |= ACAPI_Install_AddOnCommandHandler (GS::NewOwned<ReloadLibrariesCommand> ());
6667
err |= ACAPI_Install_AddOnCommandHandler (GS::NewOwned<MoveElementsCommand> ());
6768
err |= ACAPI_Install_AddOnCommandHandler (GS::NewOwned<CreateColumnsCommand> ());
69+
err |= ACAPI_Install_AddOnCommandHandler (GS::NewOwned<CreateSlabsCommand> ());
6870
err |= ACAPI_Install_AddOnCommandHandler (GS::NewOwned<GetHotlinksCommand> ());
6971
err |= ACAPI_Install_AddOnCommandHandler (GS::NewOwned<GetGDLParametersOfElementsCommand> ());
7072
err |= ACAPI_Install_AddOnCommandHandler (GS::NewOwned<ChangeGDLParametersOfElementsCommand> ());

0 commit comments

Comments
 (0)