From 497757c1763db5377f7422f94e57afd87834b509 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Tue, 28 Oct 2025 11:08:03 +0000
Subject: [PATCH 01/23] Create ETABSGroup.cs class in ETABS_oM
---
ETABS_oM/ETABS_oM.csproj | 1 +
ETABS_oM/Elements/ETABSGroup.cs | 49 +++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+)
create mode 100644 ETABS_oM/Elements/ETABSGroup.cs
diff --git a/ETABS_oM/ETABS_oM.csproj b/ETABS_oM/ETABS_oM.csproj
index 665755e4..601601bc 100644
--- a/ETABS_oM/ETABS_oM.csproj
+++ b/ETABS_oM/ETABS_oM.csproj
@@ -67,6 +67,7 @@
+
diff --git a/ETABS_oM/Elements/ETABSGroup.cs b/ETABS_oM/Elements/ETABSGroup.cs
new file mode 100644
index 00000000..4596fcce
--- /dev/null
+++ b/ETABS_oM/Elements/ETABSGroup.cs
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the Buildings and Habitats object Model (BHoM)
+ * Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
+ *
+ * Each contributor holds copyright over their respective contributions.
+ * The project versioning (Git) records all such contribution source information.
+ *
+ *
+ * The BHoM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3.0 of the License, or
+ * (at your option) any later version.
+ *
+ * The BHoM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this code. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using BH.oM.Base;
+using BH.oM.Structure.Elements;
+
+namespace BH.oM.Adapters.ETABS.Elements
+{
+ public class ETABSGroup : BHoMObject, IFragment
+ {
+ /***************************************************/
+ /**** Public Properties ****/
+ /***************************************************/
+
+ public virtual List elements { get; set; }
+
+ /***************************************************/
+ }
+}
+
+
+
+
+
+
From 4dd775ace38e06e0d5d3a5276c962242a55b10ff Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 16:40:46 +0000
Subject: [PATCH 02/23] Delete ETABSGroup.cs
Unnecessary since groupname information is going to be stored in tags.
---
ETABS_oM/ETABS_oM.csproj | 1 -
ETABS_oM/Elements/ETABSGroup.cs | 49 ---------------------------------
2 files changed, 50 deletions(-)
delete mode 100644 ETABS_oM/Elements/ETABSGroup.cs
diff --git a/ETABS_oM/ETABS_oM.csproj b/ETABS_oM/ETABS_oM.csproj
index 601601bc..665755e4 100644
--- a/ETABS_oM/ETABS_oM.csproj
+++ b/ETABS_oM/ETABS_oM.csproj
@@ -67,7 +67,6 @@
-
diff --git a/ETABS_oM/Elements/ETABSGroup.cs b/ETABS_oM/Elements/ETABSGroup.cs
deleted file mode 100644
index 4596fcce..00000000
--- a/ETABS_oM/Elements/ETABSGroup.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * This file is part of the Buildings and Habitats object Model (BHoM)
- * Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
- *
- * Each contributor holds copyright over their respective contributions.
- * The project versioning (Git) records all such contribution source information.
- *
- *
- * The BHoM is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3.0 of the License, or
- * (at your option) any later version.
- *
- * The BHoM is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this code. If not, see .
- */
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BH.oM.Base;
-using BH.oM.Structure.Elements;
-
-namespace BH.oM.Adapters.ETABS.Elements
-{
- public class ETABSGroup : BHoMObject, IFragment
- {
- /***************************************************/
- /**** Public Properties ****/
- /***************************************************/
-
- public virtual List elements { get; set; }
-
- /***************************************************/
- }
-}
-
-
-
-
-
-
From 915b00ffd9baf5f2257e04f3fb3634cdfee4a418 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 16:46:35 +0000
Subject: [PATCH 03/23] Add SetGroup Method to Create/Bar.cs
Add feature allowing to assign pushed bars to corresponding groups.
---
Etabs_Adapter/CRUD/Create/Bar.cs | 44 +++++++++++++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/Etabs_Adapter/CRUD/Create/Bar.cs b/Etabs_Adapter/CRUD/Create/Bar.cs
index b85ce405..1411f3a8 100644
--- a/Etabs_Adapter/CRUD/Create/Bar.cs
+++ b/Etabs_Adapter/CRUD/Create/Bar.cs
@@ -108,7 +108,7 @@ private bool CreateObject(Bar bhBar)
bhBar.SetAdapterId(etabsIdFragment);
- return SetObject(bhBar);
+ return SetObject(bhBar) && SetGroup(bhBar);
}
/***************************************************/
@@ -215,6 +215,48 @@ private bool SetObject(Bar bhBar)
/***************************************************/
+ private bool SetGroup(Bar bhBar)
+ {
+ int ret = 0;
+ /* Get the ETABS name of the Bar */
+ string name = GetAdapterId(bhBar);
+
+ try {
+ /* Get the list of unique groupNames assigned to the BHoM Bar */
+ List groupNames = bhBar.Tags.Distinct().ToList();
+ /* Get the list of existing group names in the ETABS model */
+ int modelNumGroups = 0;
+ string[] modelGroupNames = null;
+ m_model.GroupDef.GetNameList(ref modelNumGroups, ref modelGroupNames);
+
+ /* Create any groups that do not already exist in the ETABS model */
+ foreach (string groupName in groupNames)
+ {
+ if (!modelGroupNames.Contains(groupName))
+ {
+ ret = m_model.GroupDef.SetGroup_1(groupName);
+ if (ret != 0)
+ {
+ Engine.Base.Compute.RecordError("Could not create the Group <" + groupName + "> assigned to the Bar. Group not created.");
+ return false;
+ }
+ }
+ }
+
+ /* Assign the Bar to each group in the list */
+ groupNames.ToList().ForEach(groupName => m_model.FrameObj.SetGroupAssign(name, groupName));
+ }
+ catch (Exception e)
+ {
+ Engine.Base.Compute.RecordError("Could not assign input groups to the bar. Bar not created.");
+ return false;
+ }
+
+ return true;
+ }
+
+ /***************************************************/
+
#if Debug16 || Release16
[Description("Returns a bar where the endpoints have been flipped without cloning the object")]
From c63a3ab9792f7fbe9a6dfb4adb6d497e7ad35418 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 18:47:41 +0000
Subject: [PATCH 04/23] Add Support for Group Feature for Push/Pull of Nodes
---
Etabs_Adapter/CRUD/Create/Node.cs | 55 ++++++++++++++++++++++++++++---
Etabs_Adapter/CRUD/Read/Node.cs | 13 +++++++-
2 files changed, 62 insertions(+), 6 deletions(-)
diff --git a/Etabs_Adapter/CRUD/Create/Node.cs b/Etabs_Adapter/CRUD/Create/Node.cs
index 3bd54f38..6fdb953d 100644
--- a/Etabs_Adapter/CRUD/Create/Node.cs
+++ b/Etabs_Adapter/CRUD/Create/Node.cs
@@ -20,15 +20,16 @@
* along with this code. If not, see .
*/
-using System.Collections.Generic;
-using System.Linq;
using BH.Engine.Adapter;
-using BH.oM.Adapters.ETABS;
-using BH.oM.Structure.Elements;
-using BH.Engine.Structure;
using BH.Engine.Adapters.ETABS;
using BH.Engine.Geometry;
+using BH.Engine.Structure;
+using BH.oM.Adapters.ETABS;
using BH.oM.Geometry;
+using BH.oM.Structure.Elements;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace BH.Adapter.ETABS
{
@@ -69,6 +70,7 @@ private bool CreateObject(Node bhNode)
bhNode.SetAdapterId(etabsid);
SetObject(bhNode, name);
+ SetGroup(bhNode);
}
return true;
@@ -106,6 +108,49 @@ private bool SetObject(Node bhNode, string name)
}
/***************************************************/
+
+ private bool SetGroup(Node bhNode)
+ {
+ int ret = 0;
+ /* Get the ETABS name of the Node */
+ string name = GetAdapterId(bhNode);
+
+ try
+ {
+ /* Get the list of unique groupNames assigned to the BHoM Node */
+ List groupNames = bhNode.Tags.Distinct().ToList();
+ /* Get the list of existing group names in the ETABS model */
+ int modelNumGroups = 0;
+ string[] modelGroupNames = null;
+ m_model.GroupDef.GetNameList(ref modelNumGroups, ref modelGroupNames);
+
+ /* Create any groups that do not already exist in the ETABS model */
+ foreach (string groupName in groupNames)
+ {
+ if (!modelGroupNames.Contains(groupName))
+ {
+ ret = m_model.GroupDef.SetGroup_1(groupName);
+ if (ret != 0)
+ {
+ Engine.Base.Compute.RecordError("Could not create the Group <" + groupName + "> assigned to the Node. Group not created.");
+ return false;
+ }
+ }
+ }
+
+ /* Assign the Node to each group in the list */
+ groupNames.ToList().ForEach(groupName => m_model.PointObj.SetGroupAssign(name, groupName));
+ }
+ catch (Exception e)
+ {
+ Engine.Base.Compute.RecordError("Could not assign input groups to the node. Groups not assigned.");
+ return false;
+ }
+
+ return true;
+ }
+
+ /***************************************************/
}
}
diff --git a/Etabs_Adapter/CRUD/Read/Node.cs b/Etabs_Adapter/CRUD/Read/Node.cs
index 7e31c9c4..5ff5ae85 100644
--- a/Etabs_Adapter/CRUD/Read/Node.cs
+++ b/Etabs_Adapter/CRUD/Read/Node.cs
@@ -84,7 +84,18 @@ private List ReadNode(List ids = null)
etabsIdFragment.Story = story;
}
- if(m_model.PointObj.GetGUID(id, ref guid) == 0)
+
+ // Get the groups the bar is assigned to
+ int numGroups = 0;
+ string[] groupNames = new string[0];
+ if (m_model.PointObj.GetGroupAssign(id, ref numGroups, ref groupNames) == 0)
+ {
+ foreach (string grpName in groupNames)
+ bhNode.Tags.Add(grpName);
+ }
+
+
+ if (m_model.PointObj.GetGUID(id, ref guid) == 0)
etabsIdFragment.PersistentId = guid;
bhNode.SetAdapterId(etabsIdFragment);
From 49a09c9ef39b2cff29f1ce91f2fce43d335aea45 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 18:48:00 +0000
Subject: [PATCH 05/23] Add Support for Group Feature for Push of Bars
---
Etabs_Adapter/CRUD/Create/Bar.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Etabs_Adapter/CRUD/Create/Bar.cs b/Etabs_Adapter/CRUD/Create/Bar.cs
index 1411f3a8..0297759b 100644
--- a/Etabs_Adapter/CRUD/Create/Bar.cs
+++ b/Etabs_Adapter/CRUD/Create/Bar.cs
@@ -248,7 +248,7 @@ private bool SetGroup(Bar bhBar)
}
catch (Exception e)
{
- Engine.Base.Compute.RecordError("Could not assign input groups to the bar. Bar not created.");
+ Engine.Base.Compute.RecordError("Could not assign input groups to the bar. Groups not assigned.");
return false;
}
From bed45c9ec8f42e0b035e21b26234f60ac6a78367 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 18:48:13 +0000
Subject: [PATCH 06/23] Add Support for Group Feature for Push/Pull of Links
---
Etabs_Adapter/CRUD/Create/Link.cs | 56 ++++++++++++++++++++++++++++---
Etabs_Adapter/CRUD/Read/Link.cs | 12 +++++++
2 files changed, 63 insertions(+), 5 deletions(-)
diff --git a/Etabs_Adapter/CRUD/Create/Link.cs b/Etabs_Adapter/CRUD/Create/Link.cs
index 50a790d1..492f67cb 100644
--- a/Etabs_Adapter/CRUD/Create/Link.cs
+++ b/Etabs_Adapter/CRUD/Create/Link.cs
@@ -20,14 +20,15 @@
* along with this code. If not, see .
*/
-using System.Collections.Generic;
-using System.Linq;
using BH.Engine.Adapter;
+using BH.Engine.Adapters.ETABS;
+using BH.Engine.Structure;
using BH.oM.Adapters.ETABS;
-using BH.oM.Structure.Elements;
using BH.oM.Structure.Constraints;
-using BH.Engine.Structure;
-using BH.Engine.Adapters.ETABS;
+using BH.oM.Structure.Elements;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace BH.Adapter.ETABS
@@ -70,6 +71,8 @@ private bool CreateObject(RigidLink bhLink)
multiId.Id = linkIds;
bhLink.SetAdapterId(multiId);
+ SetGroup(bhLink);
+
return success;
}
@@ -106,6 +109,49 @@ private bool CreateObject(LinkConstraint bhLinkConstraint)
}
/***************************************************/
+
+ private bool SetGroup(RigidLink bhLink)
+ {
+ int ret = 0;
+ /* Get the ETABS name of the Link */
+ string name = GetAdapterId(bhLink);
+
+ try
+ {
+ /* Get the list of unique groupNames assigned to the BHoM Link */
+ List groupNames = bhLink.Tags.Distinct().ToList();
+ /* Get the list of existing group names in the ETABS model */
+ int modelNumGroups = 0;
+ string[] modelGroupNames = null;
+ m_model.GroupDef.GetNameList(ref modelNumGroups, ref modelGroupNames);
+
+ /* Create any groups that do not already exist in the ETABS model */
+ foreach (string groupName in groupNames)
+ {
+ if (!modelGroupNames.Contains(groupName))
+ {
+ ret = m_model.GroupDef.SetGroup_1(groupName);
+ if (ret != 0)
+ {
+ Engine.Base.Compute.RecordError("Could not create the Group <" + groupName + "> assigned to the Link. Group not created.");
+ return false;
+ }
+ }
+ }
+
+ /* Assign the Link to each group in the list */
+ groupNames.ToList().ForEach(groupName => m_model.LinkObj.SetGroupAssign(name, groupName));
+ }
+ catch (Exception e)
+ {
+ Engine.Base.Compute.RecordError("Could not assign input groups to the link. Groups not assigned.");
+ return false;
+ }
+
+ return true;
+ }
+
+ /***************************************************/
}
}
diff --git a/Etabs_Adapter/CRUD/Read/Link.cs b/Etabs_Adapter/CRUD/Read/Link.cs
index 7b69c087..fc8548fa 100644
--- a/Etabs_Adapter/CRUD/Read/Link.cs
+++ b/Etabs_Adapter/CRUD/Read/Link.cs
@@ -125,6 +125,18 @@ private List ReadRigidLink(List ids = null)
bhLink.Constraint = new LinkConstraint { Name = propName }; //Dummy constraint to be populated in later loop
+ /* Get the ETABS name of the Rigid Link */
+ string name = GetAdapterId(bhLink);
+
+ // Get the groups the link is assigned to
+ int numGroups = 0;
+ string[] groupNames = new string[0];
+ if (m_model.LinkObj.GetGroupAssign(name, ref numGroups, ref groupNames) == 0)
+ {
+ foreach (string grpName in groupNames)
+ bhLink.Tags.Add(grpName);
+ }
+
linkList.Add(bhLink);
}
From e7a1d78ba60c161718739c1bd2bdb5565c9e0501 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 18:48:24 +0000
Subject: [PATCH 07/23] Add Support for Group Feature for Push/Pull of Panels
---
Etabs_Adapter/CRUD/Create/Panel.cs | 56 ++++++++++++++++++++++++++----
Etabs_Adapter/CRUD/Read/Panel.cs | 9 +++++
2 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/Etabs_Adapter/CRUD/Create/Panel.cs b/Etabs_Adapter/CRUD/Create/Panel.cs
index 3868fefb..64a437f2 100644
--- a/Etabs_Adapter/CRUD/Create/Panel.cs
+++ b/Etabs_Adapter/CRUD/Create/Panel.cs
@@ -20,17 +20,18 @@
* along with this code. If not, see .
*/
-using System.Collections.Generic;
-using System.Linq;
using BH.Engine.Adapter;
-using BH.oM.Adapters.ETABS;
-using BH.oM.Structure.Elements;
-using BH.Engine.Structure;
+using BH.Engine.Adapters.ETABS;
using BH.Engine.Geometry;
using BH.Engine.Spatial;
-using BH.Engine.Adapters.ETABS;
+using BH.Engine.Structure;
+using BH.oM.Adapters.ETABS;
using BH.oM.Adapters.ETABS.Elements;
using BH.oM.Geometry;
+using BH.oM.Structure.Elements;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace BH.Adapter.ETABS
@@ -200,6 +201,49 @@ private static void NonLinearEdgesCheck(List edges)
/***************************************************/
+ private bool SetGroup(Panel bhPanel)
+ {
+ int ret = 0;
+ /* Get the ETABS name of the Panel */
+ string name = GetAdapterId(bhPanel);
+
+ try
+ {
+ /* Get the list of unique groupNames assigned to the BHoM Panel */
+ List groupNames = bhPanel.Tags.Distinct().ToList();
+ /* Get the list of existing group names in the ETABS model */
+ int modelNumGroups = 0;
+ string[] modelGroupNames = null;
+ m_model.GroupDef.GetNameList(ref modelNumGroups, ref modelGroupNames);
+
+ /* Create any groups that do not already exist in the ETABS model */
+ foreach (string groupName in groupNames)
+ {
+ if (!modelGroupNames.Contains(groupName))
+ {
+ ret = m_model.GroupDef.SetGroup_1(groupName);
+ if (ret != 0)
+ {
+ Engine.Base.Compute.RecordError("Could not create the Group <" + groupName + "> assigned to the Panel. Group not created.");
+ return false;
+ }
+ }
+ }
+
+ /* Assign the Panel to each group in the list */
+ groupNames.ToList().ForEach(groupName => m_model.AreaObj.SetGroupAssign(name, groupName));
+ }
+ catch (Exception e)
+ {
+ Engine.Base.Compute.RecordError("Could not assign input groups to the panel. Groups not assigned.");
+ return false;
+ }
+
+ return true;
+ }
+
+ /***************************************************/
+
}
}
diff --git a/Etabs_Adapter/CRUD/Read/Panel.cs b/Etabs_Adapter/CRUD/Read/Panel.cs
index ba0dc67f..404a2596 100644
--- a/Etabs_Adapter/CRUD/Read/Panel.cs
+++ b/Etabs_Adapter/CRUD/Read/Panel.cs
@@ -115,6 +115,15 @@ private List ReadPanel(List ids = null)
etabsId.Story = story;
}
+ // Get the groups the panel is assigned to
+ int numGroups = 0;
+ string[] groupNames = new string[0];
+ if (m_model.AreaObj.GetGroupAssign(id, ref numGroups, ref groupNames) == 0)
+ {
+ foreach (string grpName in groupNames)
+ panel.Tags.Add(grpName);
+ }
+
if (m_model.AreaObj.GetGUID(id, ref guid) == 0)
etabsId.PersistentId = guid;
From c12c00fc2d2554eaa6bfd4afc040561c2d68c8d0 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 18:48:36 +0000
Subject: [PATCH 08/23] Add Support for Group Feature for Push/Pull of Openings
---
Etabs_Adapter/CRUD/Create/Opening.cs | 58 ++++++++++++++++++++++++----
Etabs_Adapter/CRUD/Read/Opening.cs | 28 +++++++++-----
2 files changed, 70 insertions(+), 16 deletions(-)
diff --git a/Etabs_Adapter/CRUD/Create/Opening.cs b/Etabs_Adapter/CRUD/Create/Opening.cs
index 245aa63e..a9ad3a30 100644
--- a/Etabs_Adapter/CRUD/Create/Opening.cs
+++ b/Etabs_Adapter/CRUD/Create/Opening.cs
@@ -20,18 +20,19 @@
* along with this code. If not, see .
*/
-using System.Collections.Generic;
-using System.Linq;
using BH.Engine.Adapter;
-using BH.oM.Adapters.ETABS;
-using BH.oM.Structure.Elements;
-using BH.Engine.Structure;
+using BH.Engine.Adapters.ETABS;
using BH.Engine.Geometry;
using BH.Engine.Spatial;
-using BH.Engine.Adapters.ETABS;
+using BH.Engine.Structure;
+using BH.oM.Adapters.ETABS;
using BH.oM.Adapters.ETABS.Elements;
-using BH.oM.Geometry;
using BH.oM.Analytical.Elements;
+using BH.oM.Geometry;
+using BH.oM.Structure.Elements;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace BH.Adapter.ETABS
@@ -110,5 +111,48 @@ private bool CreateObject(Opening bhOpening)
/***************************************************/
+ private bool SetGroup(Opening bhOpening)
+ {
+ int ret = 0;
+ /* Get the ETABS name of the Opening */
+ string name = GetAdapterId(bhOpening);
+
+ try
+ {
+ /* Get the list of unique groupNames assigned to the BHoM Opening */
+ List groupNames = bhOpening.Tags.Distinct().ToList();
+ /* Get the list of existing group names in the ETABS model */
+ int modelNumGroups = 0;
+ string[] modelGroupNames = null;
+ m_model.GroupDef.GetNameList(ref modelNumGroups, ref modelGroupNames);
+
+ /* Create any groups that do not already exist in the ETABS model */
+ foreach (string groupName in groupNames)
+ {
+ if (!modelGroupNames.Contains(groupName))
+ {
+ ret = m_model.GroupDef.SetGroup_1(groupName);
+ if (ret != 0)
+ {
+ Engine.Base.Compute.RecordError("Could not create the Group <" + groupName + "> assigned to the Opening. Group not created.");
+ return false;
+ }
+ }
+ }
+
+ /* Assign the Opening to each group in the list */
+ groupNames.ToList().ForEach(groupName => m_model.AreaObj.SetGroupAssign(name, groupName));
+ }
+ catch (Exception e)
+ {
+ Engine.Base.Compute.RecordError("Could not assign input groups to the openings. Groups not assigned.");
+ return false;
+ }
+
+ return true;
+ }
+
+ /***************************************************/
+
}
}
diff --git a/Etabs_Adapter/CRUD/Read/Opening.cs b/Etabs_Adapter/CRUD/Read/Opening.cs
index 2cb44820..4fdeedbc 100644
--- a/Etabs_Adapter/CRUD/Read/Opening.cs
+++ b/Etabs_Adapter/CRUD/Read/Opening.cs
@@ -20,22 +20,23 @@
* along with this code. If not, see .
*/
-using System;
using BH.Engine.Adapter;
+using BH.Engine.Adapters.ETABS;
+using BH.Engine.Geometry;
+using BH.Engine.Spatial;
+using BH.Engine.Structure;
using BH.oM.Adapters.ETABS;
+using BH.oM.Adapters.ETABS.Elements;
+using BH.oM.Analytical.Elements;
+using BH.oM.Geometry;
+using BH.oM.Structure.Elements;
+using BH.oM.Structure.SurfaceProperties;
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using BH.oM.Structure.Elements;
-using BH.oM.Structure.SurfaceProperties;
-using BH.Engine.Adapters.ETABS;
-using BH.oM.Geometry;
-using BH.Engine.Geometry;
-using BH.oM.Adapters.ETABS.Elements;
-using BH.Engine.Structure;
-using BH.Engine.Spatial;
namespace BH.Adapter.ETABS
@@ -91,6 +92,15 @@ private List ReadOpening(List ids = null)
etabsId.Story = story;
}
+ // Get the groups the opening is assigned to
+ int numGroups = 0;
+ string[] groupNames = new string[0];
+ if (m_model.AreaObj.GetGroupAssign(id, ref numGroups, ref groupNames) == 0)
+ {
+ foreach (string grpName in groupNames)
+ opening.Tags.Add(grpName);
+ }
+
if (m_model.AreaObj.GetGUID(id, ref guid) == 0)
etabsId.PersistentId = guid;
From fc85629159c15a0bc03fc39d2f07ad0e7b535a9c Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 21:27:49 +0000
Subject: [PATCH 09/23] Fix Support of Group feature in Push for Links,
Openings and Panels
---
Etabs_Adapter/CRUD/Create/Link.cs | 10 ++++++----
Etabs_Adapter/CRUD/Create/Opening.cs | 3 +++
Etabs_Adapter/CRUD/Create/Panel.cs | 4 ++++
3 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/Etabs_Adapter/CRUD/Create/Link.cs b/Etabs_Adapter/CRUD/Create/Link.cs
index 492f67cb..89026232 100644
--- a/Etabs_Adapter/CRUD/Create/Link.cs
+++ b/Etabs_Adapter/CRUD/Create/Link.cs
@@ -113,8 +113,8 @@ private bool CreateObject(LinkConstraint bhLinkConstraint)
private bool SetGroup(RigidLink bhLink)
{
int ret = 0;
- /* Get the ETABS name of the Link */
- string name = GetAdapterId(bhLink);
+ /* Get the ETABS names of all the Links */
+ List names = ((ETABSId)bhLink.Fragments[0]).Id as List;
try
{
@@ -139,8 +139,10 @@ private bool SetGroup(RigidLink bhLink)
}
}
- /* Assign the Link to each group in the list */
- groupNames.ToList().ForEach(groupName => m_model.LinkObj.SetGroupAssign(name, groupName));
+ /* Assign the Links to each group in the list */
+ foreach (string name in names) {
+ groupNames.ToList().ForEach(groupName => m_model.LinkObj.SetGroupAssign(name, groupName));
+ }
}
catch (Exception e)
{
diff --git a/Etabs_Adapter/CRUD/Create/Opening.cs b/Etabs_Adapter/CRUD/Create/Opening.cs
index a9ad3a30..dbd78293 100644
--- a/Etabs_Adapter/CRUD/Create/Opening.cs
+++ b/Etabs_Adapter/CRUD/Create/Opening.cs
@@ -106,6 +106,9 @@ private bool CreateObject(Opening bhOpening)
m_model.AreaObj.SetOpening(openingName, true);
+ //Set Groups Assignment
+ SetGroup(bhOpening);
+
return success;
}
diff --git a/Etabs_Adapter/CRUD/Create/Panel.cs b/Etabs_Adapter/CRUD/Create/Panel.cs
index 64a437f2..ee55231a 100644
--- a/Etabs_Adapter/CRUD/Create/Panel.cs
+++ b/Etabs_Adapter/CRUD/Create/Panel.cs
@@ -176,6 +176,10 @@ private bool CreateObject(Panel bhPanel)
{
m_model.AreaObj.SetDiaphragm(name, diaphragm.Name);
}
+
+ //Set Groups Assignment
+ SetGroup(bhPanel);
+
return success;
}
From 16139fbc95a91a24197f384b9183a95b7622b8c7 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 21:42:50 +0000
Subject: [PATCH 10/23] Add UpdateGroup Feature for Bars
---
Etabs_Adapter/CRUD/Update/Bar.cs | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/Etabs_Adapter/CRUD/Update/Bar.cs b/Etabs_Adapter/CRUD/Update/Bar.cs
index 04df5ec6..56f5f9b3 100644
--- a/Etabs_Adapter/CRUD/Update/Bar.cs
+++ b/Etabs_Adapter/CRUD/Update/Bar.cs
@@ -77,7 +77,7 @@ private bool UpdateObjects(IEnumerable bhBars)
}
#endif
- if (SetObject(bhBar))
+ if (SetObject(bhBar) && UpdateGroup(bhBar))
ret++;
}
@@ -97,6 +97,31 @@ private bool UpdateObjects(IEnumerable bhBars)
/***************************************************/
+ private bool UpdateGroup(Bar bhBar)
+ {
+ return ResetGroup(bhBar) && SetGroup(bhBar);
+ }
+
+ /***************************************************/
+
+ private bool ResetGroup(Bar bhBar)
+ {
+ /* Get the ETABS name of the Bar */
+ string name = GetAdapterId(bhBar);
+
+ /* Get the names of all groups currently assigned to the bar */
+ int numGroups = 0;
+ string[] groupNames = null;
+ m_model.FrameObj.GetGroupAssign(name, ref numGroups, ref groupNames);
+
+ /* Remove the Bar from each group in the list */
+ groupNames.ToList().ForEach(groupName => m_model.FrameObj.SetGroupAssign(name, groupName, true));
+
+ return true;
+ }
+
+ /***************************************************/
+
}
}
From 4c1647764eba4977b3d9e5bdf47687d8ac019f96 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 21:43:10 +0000
Subject: [PATCH 11/23] Add UpdateGroup feature for Nodes
---
Etabs_Adapter/CRUD/Update/Node.cs | 48 +++++++++++++++++++++++++------
1 file changed, 39 insertions(+), 9 deletions(-)
diff --git a/Etabs_Adapter/CRUD/Update/Node.cs b/Etabs_Adapter/CRUD/Update/Node.cs
index 5ade95c4..2d9c4ae0 100644
--- a/Etabs_Adapter/CRUD/Update/Node.cs
+++ b/Etabs_Adapter/CRUD/Update/Node.cs
@@ -20,14 +20,15 @@
* along with this code. If not, see .
*/
-using System.Collections.Generic;
-using System.Linq;
using BH.Engine.Adapter;
-using BH.oM.Adapters.ETABS;
-using BH.oM.Structure.Elements;
-using BH.oM.Structure.Constraints;
using BH.Engine.Adapters.ETABS;
+using BH.oM.Adapters.ETABS;
using BH.oM.Physical.Elements;
+using BH.oM.Structure.Constraints;
+using BH.oM.Structure.Elements;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace BH.Adapter.ETABS
{
@@ -48,6 +49,12 @@ private bool UpdateObjects(IEnumerable nodes)
bool success = true; // θ(1)
m_model.SelectObj.ClearSelection(); // θ(1)
+ // 1. UPDATE GROUP ASSIGNMENT
+ nodes.ToList().ForEach(node => UpdateGroup(node)); // n*θ(1) + θ(1)
+
+
+ // 2. UDPATE LOCATION
+
double factor = DatabaseLengthUnitFactor(); // θ(1)
Engine.Structure.NodeDistanceComparer comparer = AdapterComparers[typeof(Node)] // θ(1)
@@ -58,7 +65,7 @@ private bool UpdateObjects(IEnumerable nodes)
Dictionary> dz = new Dictionary>(); // θ(1)
- // 1. GROUP NODES BY RELATIVE MOVEMENT IN X/Y/Z DIRECTION - ** HASH TABLES **
+ // 2.1 Group Nodes by Relative Movement in X/Y/Z Direction - ** HASH TABLES **
foreach (Node bhNode in nodes) // n*θ(1) + θ(1)
{
@@ -94,9 +101,7 @@ private bool UpdateObjects(IEnumerable nodes)
}
}
-
-
- // 2. MOVE NODES GROUP-BY-GROUP - ** STREAMS **
+ // 2.2 Move Nodes Group-By-Group - ** STREAMS **
// dX Movement
dx.ToList().ForEach(kvp => // θ(n)
@@ -135,6 +140,31 @@ private bool UpdateObjects(IEnumerable nodes)
}
/***************************************************/
+
+ private bool UpdateGroup(Node bhNode)
+ {
+ return ResetGroup(bhNode) && SetGroup(bhNode);
+ }
+
+ /***************************************************/
+
+ private bool ResetGroup(Node bhNode)
+ {
+ /* Get the ETABS name of the Node */
+ string name = GetAdapterId(bhNode);
+
+ /* Get the names of all groups currently assigned to the node */
+ int numGroups = 0;
+ string[] groupNames = null;
+ m_model.PointObj.GetGroupAssign(name, ref numGroups, ref groupNames);
+
+ /* Remove the Node from each group in the list */
+ groupNames.ToList().ForEach(groupName => m_model.PointObj.SetGroupAssign(name, groupName,true));
+
+ return true;
+ }
+
+ /***************************************************/
}
}
From 781c2d95e486b4e3572cf2e54c66c08e32c52408 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 21:43:26 +0000
Subject: [PATCH 12/23] Add UpdateGroup feature for Panels
---
Etabs_Adapter/CRUD/Update/Panel.cs | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/Etabs_Adapter/CRUD/Update/Panel.cs b/Etabs_Adapter/CRUD/Update/Panel.cs
index 2b7158a2..8cf12c2c 100644
--- a/Etabs_Adapter/CRUD/Update/Panel.cs
+++ b/Etabs_Adapter/CRUD/Update/Panel.cs
@@ -85,6 +85,10 @@ private bool UpdateObjects(IEnumerable bhPanels)
{
m_model.AreaObj.SetDiaphragm(name, diaphragm.Name);
}
+
+ //Update Groups Assignment
+ UpdateGroup(bhPanel);
+
}
//Force refresh to make sure panel local orientation are set correctly
@@ -95,6 +99,31 @@ private bool UpdateObjects(IEnumerable bhPanels)
/***************************************************/
+ private bool UpdateGroup(Panel bhPanel)
+ {
+ return ResetGroup(bhPanel) && SetGroup(bhPanel);
+ }
+
+ /***************************************************/
+
+ private bool ResetGroup(Panel bhPanel)
+ {
+ /* Get the ETABS name of the Panel */
+ string name = GetAdapterId(bhPanel);
+
+ /* Get the names of all groups currently assigned to the panel */
+ int numGroups = 0;
+ string[] groupNames = null;
+ m_model.AreaObj.GetGroupAssign(name, ref numGroups, ref groupNames);
+
+ /* Remove the Panel from each group in the list */
+ groupNames.ToList().ForEach(groupName => m_model.AreaObj.SetGroupAssign(name, groupName, true));
+
+ return true;
+ }
+
+ /***************************************************/
+
}
}
From 6118b7601be563bd072d1123a14af10280271c32 Mon Sep 17 00:00:00 2001
From: GCRA101 <126593217+GCRA101@users.noreply.github.com>
Date: Wed, 29 Oct 2025 22:14:27 +0000
Subject: [PATCH 13/23] Add UpdateGroup Feature for Links
---
Etabs_Adapter/CRUD/Update/Link.cs | 145 ++++++++++++++++++++++++++++++
1 file changed, 145 insertions(+)
create mode 100644 Etabs_Adapter/CRUD/Update/Link.cs
diff --git a/Etabs_Adapter/CRUD/Update/Link.cs b/Etabs_Adapter/CRUD/Update/Link.cs
new file mode 100644
index 00000000..112898cb
--- /dev/null
+++ b/Etabs_Adapter/CRUD/Update/Link.cs
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the Buildings and Habitats object Model (BHoM)
+ * Copyright (c) 2015 - 2025, the respective contributors. All rights reserved.
+ *
+ * Each contributor holds copyright over their respective contributions.
+ * The project versioning (Git) records all such contribution source information.
+ *
+ *
+ * The BHoM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3.0 of the License, or
+ * (at your option) any later version.
+ *
+ * The BHoM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this code. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using BH.Engine.Adapter;
+using BH.oM.Adapters.ETABS;
+using BH.oM.Structure.Elements;
+
+namespace BH.Adapter.ETABS
+{
+#if Debug16 || Release16
+ public partial class ETABS2016Adapter : BHoMAdapter
+#elif Debug17 || Release17
+ public partial class ETABS17Adapter : BHoMAdapter
+#else
+ public partial class ETABSAdapter : BHoMAdapter
+#endif
+ {
+ /***************************************************/
+ /**** Update Rigid Links ****/
+ /***************************************************/
+
+ private bool UpdateObjects(IEnumerable bhLinks)
+ {
+ bool success = true;
+
+ int nameCount = 0;
+ string[] names = { };
+ m_model.LinkObj.GetNameList(ref nameCount, ref names);
+
+ foreach (RigidLink bhLink in bhLinks)
+ {
+ // Get underlying ETABS names for this BHoM Link
+ List etabsNames = GetEtabsNamesForLink(bhLink);
+
+ if (etabsNames == null || !etabsNames.Any())
+ {
+ Engine.Base.Compute.RecordWarning("The Link must have an ETABS adapter id to be updated.");
+ continue;
+ }
+
+ // Ensure at least one of the underlying link names exists in the model
+ if (!etabsNames.Any(n => names.Contains(n)))
+ {
+ Engine.Base.Compute.RecordWarning("The Link must be present in ETABS to be updated.");
+ continue;
+ }
+
+ // ETABS does not support updating of link connectivity or constraints here - only group assignment
+ Engine.Base.Compute.RecordWarning("The Etabs API does not allow for updating of the geometry or constraint details of links. To change these, delete and recreate the link.");
+
+ if (!UpdateGroup(bhLink))
+ success = false;
+ }
+
+ return success;
+ }
+
+ /***************************************************/
+
+ private List GetEtabsNamesForLink(RigidLink bhLink)
+ {
+ if (bhLink == null)
+ return new List();
+
+ // Prefer explicit ETABS fragment id if present
+ var frag = bhLink.Fragments?.FirstOrDefault() as ETABSId;
+ if (frag != null && frag.Id != null)
+ {
+ switch (frag.Id)
+ {
+ case List list:
+ return list;
+ case string[] arr:
+ return arr.ToList();
+ case IEnumerable ies:
+ return ies.ToList();
+ case IEnumerable