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+ }
0 commit comments