Skip to content

Commit 0efe807

Browse files
Add Adapter Support for Structure Openings (#479)
2 parents 306a48b + f4d88d0 commit 0efe807

File tree

6 files changed

+273
-27
lines changed

6 files changed

+273
-27
lines changed

Etabs_Adapter/CRUD/Create/Opening.cs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* This file is part of the Buildings and Habitats object Model (BHoM)
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
4+
*
5+
* Each contributor holds copyright over their respective contributions.
6+
* The project versioning (Git) records all such contribution source information.
7+
*
8+
*
9+
* The BHoM is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3.0 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* The BHoM is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public License
20+
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
21+
*/
22+
23+
using System.Collections.Generic;
24+
using System.Linq;
25+
using BH.Engine.Adapter;
26+
using BH.oM.Adapters.ETABS;
27+
using BH.oM.Structure.Elements;
28+
using BH.Engine.Structure;
29+
using BH.Engine.Geometry;
30+
using BH.Engine.Spatial;
31+
using BH.Engine.Adapters.ETABS;
32+
using BH.oM.Adapters.ETABS.Elements;
33+
using BH.oM.Geometry;
34+
using BH.oM.Analytical.Elements;
35+
36+
37+
namespace BH.Adapter.ETABS
38+
{
39+
#if Debug16 || Release16
40+
public partial class ETABS2016Adapter : BHoMAdapter
41+
#elif Debug17 || Release17
42+
public partial class ETABS17Adapter : BHoMAdapter
43+
#else
44+
public partial class ETABSAdapter : BHoMAdapter
45+
#endif
46+
{
47+
/***************************************************/
48+
/*** Create Methods ***/
49+
/***************************************************/
50+
51+
private bool CreateObject(Opening bhOpening)
52+
{
53+
bool success = true;
54+
int retA = 0;
55+
56+
double mergeTol = 1e-3; //Merging panel points to the mm, same behaviour as the default node comparer
57+
58+
if (!CheckPropertyError(bhOpening, bhO => bhO.Edges, true))
59+
return false;
60+
61+
for (int i = 0; i < bhOpening.Edges.Count; i++)
62+
{
63+
if (!CheckPropertyError(bhOpening, bhO => bhO.Edges[i], true))
64+
return false;
65+
66+
if (!CheckPropertyError(bhOpening, bhO => bhO.Edges[i].Curve, true))
67+
return false;
68+
}
69+
70+
NonLinearEdgesCheck(bhOpening.Edges);
71+
72+
List<BH.oM.Geometry.Point> boundaryPoints = bhOpening.ControlPoints(true).CullDuplicates(mergeTol);
73+
74+
int segmentCount = boundaryPoints.Count();
75+
double[] x = new double[segmentCount];
76+
double[] y = new double[segmentCount];
77+
double[] z = new double[segmentCount];
78+
for (int i = 0; i < segmentCount; i++)
79+
{
80+
x[i] = boundaryPoints[i].X;
81+
y[i] = boundaryPoints[i].Y;
82+
z[i] = boundaryPoints[i].Z;
83+
}
84+
85+
string openingName = GetAdapterId<string>(bhOpening);
86+
retA = m_model.AreaObj.AddByCoord(segmentCount, ref x, ref y, ref z, ref openingName, "Default");
87+
ETABSId etabsid = new ETABSId();
88+
etabsid.Id = openingName;
89+
90+
//Label and story
91+
string label = "";
92+
string story = "";
93+
string guid = null;
94+
95+
if (m_model.AreaObj.GetLabelFromName(openingName, ref label, ref story) == 0)
96+
{
97+
etabsid.Label = label;
98+
etabsid.Story = story;
99+
}
100+
101+
if (m_model.AreaObj.GetGUID(openingName, ref guid) == 0)
102+
etabsid.PersistentId = guid;
103+
104+
bhOpening.SetAdapterId(etabsid);
105+
106+
m_model.AreaObj.SetOpening(openingName, true);
107+
108+
return success;
109+
}
110+
111+
/***************************************************/
112+
113+
}
114+
}

Etabs_Adapter/CRUD/Read/Opening.cs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* This file is part of the Buildings and Habitats object Model (BHoM)
3+
* Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
4+
*
5+
* Each contributor holds copyright over their respective contributions.
6+
* The project versioning (Git) records all such contribution source information.
7+
*
8+
*
9+
* The BHoM is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3.0 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* The BHoM is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public License
20+
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
21+
*/
22+
23+
using System;
24+
using BH.Engine.Adapter;
25+
using BH.oM.Adapters.ETABS;
26+
using System.Collections;
27+
using System.Collections.Generic;
28+
using System.Linq;
29+
using System.Text;
30+
using System.Threading.Tasks;
31+
using BH.oM.Structure.Elements;
32+
using BH.oM.Structure.SurfaceProperties;
33+
using BH.Engine.Adapters.ETABS;
34+
using BH.oM.Geometry;
35+
using BH.Engine.Geometry;
36+
using BH.oM.Adapters.ETABS.Elements;
37+
using BH.Engine.Structure;
38+
using BH.Engine.Spatial;
39+
40+
41+
namespace BH.Adapter.ETABS
42+
{
43+
#if Debug16 || Release16
44+
public partial class ETABS2016Adapter : BHoMAdapter
45+
#elif Debug17 || Release17
46+
public partial class ETABS17Adapter : BHoMAdapter
47+
#else
48+
public partial class ETABSAdapter : BHoMAdapter
49+
#endif
50+
{
51+
/***************************************************/
52+
/*** Read Methods ***/
53+
/***************************************************/
54+
55+
private List<Opening> ReadOpening(List<string> ids = null)
56+
{
57+
58+
List<string> openingNames = new List<string>();
59+
List<Opening> openingList = new List<Opening>();
60+
61+
int nameCount = 0;
62+
string[] nameArr = { };
63+
m_model.AreaObj.GetNameList(ref nameCount, ref nameArr);
64+
65+
66+
bool isOpening = false;
67+
openingNames = nameArr.Where(panelName => {
68+
m_model.AreaObj.GetOpening(panelName, ref isOpening);
69+
return isOpening;
70+
}).ToList();
71+
72+
ids = FilterIds(ids, openingNames);
73+
74+
foreach (string id in ids)
75+
{
76+
ETABSId etabsId = new ETABSId();
77+
etabsId.Id = id;
78+
79+
Opening opening = new Opening();
80+
Polyline pl = GetOpeningOutline(id);
81+
82+
opening.Edges = pl.SubParts().Select(x => new Edge { Curve = x }).ToList();
83+
84+
//Label and story
85+
string label = "";
86+
string story = "";
87+
string guid = null;
88+
if (m_model.AreaObj.GetLabelFromName(id, ref label, ref story) == 0)
89+
{
90+
etabsId.Label = label;
91+
etabsId.Story = story;
92+
}
93+
94+
if (m_model.AreaObj.GetGUID(id, ref guid) == 0)
95+
etabsId.PersistentId = guid;
96+
97+
opening.SetAdapterId(etabsId);
98+
openingList.Add(opening);
99+
}
100+
101+
return openingList;
102+
}
103+
104+
/***************************************************/
105+
106+
private Polyline GetOpeningOutline(string id)
107+
{
108+
string[] pName = null;
109+
int pointCount = 0;
110+
double pX1 = 0;
111+
double pY1 = 0;
112+
double pZ1 = 0;
113+
m_model.AreaObj.GetPoints(id, ref pointCount, ref pName);
114+
List<Point> pts = new List<Point>();
115+
for (int j = 0; j < pointCount; j++)
116+
{
117+
m_model.PointObj.GetCoordCartesian(pName[j], ref pX1, ref pY1, ref pZ1);
118+
pts.Add(new Point() { X = pX1, Y = pY1, Z = pZ1 });
119+
}
120+
pts.Add(pts[0]);
121+
122+
Polyline pl = new Polyline() { ControlPoints = pts };
123+
124+
return pl;
125+
}
126+
127+
/***************************************************/
128+
129+
}
130+
}
131+

Etabs_Adapter/CRUD/Read/Panel.cs

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -61,29 +61,21 @@ private List<Panel> ReadPanel(List<string> ids = null)
6161
string[] nameArr = { };
6262
m_model.AreaObj.GetNameList(ref nameCount, ref nameArr);
6363

64-
ids = FilterIds(ids, nameArr);
65-
66-
//get openings, if any
67-
m_model.AreaObj.GetNameList(ref nameCount, ref nameArr);
64+
//Remove the Opening Objects from the Panels List
6865
bool isOpening = false;
69-
Dictionary<string, Polyline> openingDict = new Dictionary<string, Polyline>();
70-
foreach (string name in nameArr)
71-
{
72-
m_model.AreaObj.GetOpening(name, ref isOpening);
73-
if (isOpening)
74-
{
75-
openingDict.Add(name, GetPanelPerimeter(name));
76-
}
77-
}
66+
List<string> nameList=nameArr.Where(panelName => {
67+
m_model.AreaObj.GetOpening(panelName, ref isOpening);
68+
return !isOpening;}).ToList();
69+
//Update number of Panels removing Opening Objects from it
70+
nameCount = nameList.Count;
71+
72+
ids = FilterIds(ids, nameList);
7873

7974
foreach (string id in ids)
8075
{
8176
ETABSId etabsId = new ETABSId();
8277
etabsId.Id = id;
8378

84-
if (openingDict.ContainsKey(id))
85-
continue;
86-
8779
string propertyName = "";
8880

8981
m_model.AreaObj.GetProperty(id, ref propertyName);
@@ -99,16 +91,6 @@ private List<Panel> ReadPanel(List<string> ids = null)
9991

10092
panel.ExternalEdges = pl.SubParts().Select(x => new Edge { Curve = x }).ToList();
10193

102-
foreach (KeyValuePair<string, Polyline> kvp in openingDict)
103-
{
104-
if (pl.IsContaining(kvp.Value.ControlPoints))
105-
{
106-
Opening opening = new Opening();
107-
opening.Edges = kvp.Value.SubParts().Select(x => new Edge { Curve = x }).ToList();
108-
panel.Openings.Add(opening);
109-
}
110-
}
111-
11294
panel.Property = panelProperty;
11395
string PierName = "";
11496
string SpandrelName = "";

Etabs_Adapter/CRUD/Read/_Read.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ protected override IEnumerable<IBHoMObject> IRead(Type type, IList ids, ActionCo
7070
return ReadMaterial(listIds);
7171
else if (type == typeof(Panel))
7272
return ReadPanel(listIds);
73+
else if (type == typeof(Opening))
74+
return ReadOpening(listIds);
7375
else if (type == typeof(ISurfaceProperty) || type.GetInterfaces().Contains(typeof(ISurfaceProperty)))
7476
return ReadSurfaceProperty(listIds);
7577
else if (type == typeof(LoadCombination))
@@ -121,6 +123,18 @@ public Dictionary<Type, List<string>> SelectedElements()
121123

122124
m_model.SelectObj.GetSelected(ref numItems, ref objectTypes, ref objectIds);
123125

126+
// Replace Panels' type numbers with Openings' type numbers
127+
128+
for (int i=0; i<numItems; i++)
129+
{
130+
if (objectTypes[i]==5)
131+
{
132+
bool isOpening=false;
133+
m_model.AreaObj.GetOpening(objectIds[i], ref isOpening);
134+
if (isOpening) objectTypes[i] = 8;
135+
}
136+
}
137+
124138
Dictionary<int, List<string>> dict = objectTypes.Distinct().ToDictionary(x => x, x => new List<string>());
125139

126140
for (int i = 0; i < numItems; i++)
@@ -144,6 +158,8 @@ public Dictionary<Type, List<string>> SelectedElements()
144158
return null;
145159
case 7: // Link Object
146160
return typeof(RigidLink);
161+
case 8: // Opening Object (not api-native)
162+
return typeof(Opening);
147163
default:
148164
return null;
149165
}

Etabs_Adapter/Etabs_Adapter.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@
351351
<Compile Include="Convert\ToCSI\Vector.cs" />
352352
<Compile Include="CRUD\Create\Loadcase.cs" />
353353
<Compile Include="CRUD\Create\Diaphragm.cs" />
354+
<Compile Include="CRUD\Create\Opening.cs" />
354355
<Compile Include="CRUD\Create\SurfaceProperty.cs" />
355356
<Compile Include="CRUD\Create\SectionProperty.cs" />
356357
<Compile Include="CRUD\Create\Panel.cs" />
@@ -365,6 +366,7 @@
365366
<Compile Include="CRUD\Delete\_Delete.cs" />
366367
<Compile Include="CRUD\Read\Grid.cs" />
367368
<Compile Include="CRUD\Read\Loadcase.cs" />
369+
<Compile Include="CRUD\Read\Opening.cs" />
368370
<Compile Include="CRUD\Read\Results\PierAndSpandrelResults.cs" />
369371
<Compile Include="CRUD\Read\SectionProperty.cs" />
370372
<Compile Include="CRUD\Read\Results\BarResults.cs" />

Etabs_Adapter/Types/DependencyTypes.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ protected void SetupDependencies()
5252
{
5353
{typeof(Bar), new List<Type> { typeof(ISectionProperty), typeof(Node)} },
5454
{typeof(ISectionProperty), new List<Type> { typeof(IMaterialFragment) } },
55-
{typeof(Panel), new List<Type> { typeof(ISurfaceProperty)} },
55+
{typeof(Panel), new List<Type> { typeof(ISurfaceProperty) } },
56+
{typeof(Opening), new List<Type> {typeof(Edge) } },
5657
{typeof(ISurfaceProperty), new List<Type> { typeof(IMaterialFragment) } },
5758
{typeof(RigidLink), new List<Type> { typeof(Node), typeof(LinkConstraint)} },
5859
{typeof(ILoad), new List<Type> {typeof(Loadcase) } },

0 commit comments

Comments
 (0)