diff --git a/.gitignore b/.gitignore index aae0387c..f22eccde 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ *.exe *.o *.so -*.dll # Packages # ############ diff --git a/README.md b/README.md index e3512746..2705027d 100644 --- a/README.md +++ b/README.md @@ -9,14 +9,6 @@ This toolkit allows interoperability between the BHoM and SAP2000. Enables creat ### Known Versions of Software Supported The adapter is intended to support SAP2000 version 21 and all future versions. It is currently tested on version 23 exclusively. -### Net runtime issues - -There are currently some internal failures in the SAP2000 API when called in a NET Core environment. For this reason, running the ETABSAdapter in runtimes above NET4 is disabled. - -If you are using the SAP2000 Adapter with Grasshopper in Rhino 8 you can change the runtime used by Rhino to framework. To do this, please see this link: https://www.rhino3d.com/en/docs/guides/netcore/#to-change-rhino-to-always-use-net-framework - -A fix to allow for higher net runtimes is being worked on. - ### Documentation For more information about functionality see [Object Relation Table](https://github.com/BHoM/SAP2000_Toolkit/wiki/BHoM-SAP2000-Object-Relations) diff --git a/SAP2000_Adapter/CRUD/Create/Bar.cs b/SAP2000_Adapter/CRUD/Create/Bar.cs index e8c9271d..956470f1 100644 --- a/SAP2000_Adapter/CRUD/Create/Bar.cs +++ b/SAP2000_Adapter/CRUD/Create/Bar.cs @@ -70,20 +70,20 @@ private bool CreateObject(Bar bhBar) return false; } - // Set AdapterID - if (name != bhBar.Name & bhBar.Name != "") - Engine.Base.Compute.RecordNote($"Bar {bhBar.Name} was assigned SAP2000_id of {name}"); + // Assign the Unique Name to the SAP2000 Element + string newName = SetUniqueName(bhBar, name); + + if (newName == null) return false; string guid = null; - m_model.FrameObj.GetGUID(name, ref guid); + m_model.FrameObj.GetGUID(newName, ref guid); - SAP2000Id sap2000IdFragment = new SAP2000Id { Id = name, PersistentId = guid }; + SAP2000Id sap2000IdFragment = new SAP2000Id { Id = newName, PersistentId = guid }; bhBar.SetAdapterId(sap2000IdFragment); // Set Properties - SetObject(bhBar); + return SetObject(bhBar); - return true; } /***************************************************/ diff --git a/SAP2000_Adapter/CRUD/Create/Node.cs b/SAP2000_Adapter/CRUD/Create/Node.cs index 898fd5ba..ac56ca9b 100644 --- a/SAP2000_Adapter/CRUD/Create/Node.cs +++ b/SAP2000_Adapter/CRUD/Create/Node.cs @@ -55,20 +55,20 @@ private bool CreateObject(Node bhNode) return false; } - // Set Adapter ID - if (name != bhNode.Name & bhNode.Name != "") - Engine.Base.Compute.RecordNote($"Node {bhNode.Name} was assigned SAP2000_id of {name}"); + // Assign the Unique Name to the SAP2000 Element + string newName = SetUniqueName(bhNode, name); + + if (newName == null) return false; + // Set Adapter ID string guid = null; - m_model.PointObj.GetGUID(name, ref guid); + m_model.PointObj.GetGUID(newName, ref guid); - SAP2000Id sap2000IdFragment = new SAP2000Id { Id = name, PersistentId = guid }; + SAP2000Id sap2000IdFragment = new SAP2000Id { Id = newName, PersistentId = guid }; bhNode.SetAdapterId(sap2000IdFragment); // Set Properties - SetObject(bhNode); - - return true; + return SetObject(bhNode); } /***************************************************/ diff --git a/SAP2000_Adapter/CRUD/Create/Panel.cs b/SAP2000_Adapter/CRUD/Create/Panel.cs index 25f27f4e..0e0b47c9 100644 --- a/SAP2000_Adapter/CRUD/Create/Panel.cs +++ b/SAP2000_Adapter/CRUD/Create/Panel.cs @@ -67,17 +67,18 @@ private bool CreateObject(Panel bhPanel) return false; } - // Set AdapterID - if (name != bhPanel.Name & bhPanel.Name != "") - Engine.Base.Compute.RecordNote($"Panel {bhPanel.Name} was assigned SAP2000_id of {name}."); + // Assign the Unique Name to the SAP2000 Element + string newName = SetUniqueName(bhPanel, name); + + if (newName == null) return false; + // Set AdapterID string guid = null; - m_model.AreaObj.GetGUID(name, ref guid); - SAP2000Id sap2000IdFragment = new SAP2000Id{Id = name, PersistentId = guid}; + m_model.AreaObj.GetGUID(newName, ref guid); + SAP2000Id sap2000IdFragment = new SAP2000Id{Id = newName, PersistentId = guid}; bhPanel.SetAdapterId(sap2000IdFragment); // Set Properties - SetObject(bhPanel); - return true; + return SetObject(bhPanel); } /***************************************************/ diff --git a/SAP2000_Adapter/CRUD/Create/RigidLink.cs b/SAP2000_Adapter/CRUD/Create/RigidLink.cs index 081eeb6c..ed6031c4 100644 --- a/SAP2000_Adapter/CRUD/Create/RigidLink.cs +++ b/SAP2000_Adapter/CRUD/Create/RigidLink.cs @@ -24,6 +24,7 @@ using BH.oM.Adapters.SAP2000; using BH.oM.Structure.Elements; using System.Collections.Generic; +using System.ComponentModel; namespace BH.Adapter.SAP2000 { @@ -86,13 +87,59 @@ private bool CreateObject(RigidLink bhLink) } } - sap2000id.Id = linkIds; + // Assign the Unique Name to the SAP2000 Element + List newLinkNames = SetUniqueName(bhLink, linkIds); + + if (newLinkNames == null) return false; + + sap2000id.Id = newLinkNames; bhLink.SetAdapterId(sap2000id); return true; } /***************************************************/ + + [Description("Concatenates the last 7 characters of the SAP2000 Element GUID and the Link Name to get the Unique Name to assign to the SAP2000 Element.")] + private List SetUniqueName(RigidLink bhLink, List names) + { + + int ret01, ret02; + string guid = null; + string tempLinkName = ""; + List newLinkNames = new List(); + + foreach (string name in names) + { + + /* 1. GET THE SAP2000 ELEMENT GUID */ + tempLinkName = ""; + ret01 = m_model.LinkObj.GetGUID(name, ref guid); + + /* 2. CREATE THE NEW UNIQUE NAME */ + if (bhLink.Name == "") + { + tempLinkName = guid.Substring(guid.Length - 7); + } + else + { + tempLinkName = bhLink.Name + "::" + guid.Substring(guid.Length - 7); + } + + /* 3. ASSIGN THE NEW UNIQUE NAME TO THE SAP2000 ELEMENT */ + ret02 = m_model.LinkObj.ChangeName(name, tempLinkName); + + /* 4. ADD THE NEW NAME TO THE LIST */ + newLinkNames.Add(tempLinkName); + + if (!(ret01 == 0 && ret02 == 0)) return null; + + } + + return newLinkNames; + } + + /***************************************************/ } } diff --git a/SAP2000_Adapter/CRUD/Create/_ICreate.cs b/SAP2000_Adapter/CRUD/Create/_ICreate.cs index 0fca87f7..c1953d7c 100644 --- a/SAP2000_Adapter/CRUD/Create/_ICreate.cs +++ b/SAP2000_Adapter/CRUD/Create/_ICreate.cs @@ -20,21 +20,22 @@ * along with this code. If not, see . */ +using BH.oM.Adapter; +using BH.oM.Adapters.SAP2000; +using BH.oM.Analytical; using BH.oM.Base; using BH.oM.Dimensional; +using BH.oM.Structure.Constraints; using BH.oM.Structure.Elements; using BH.oM.Structure.Loads; -using BH.oM.Structure.Constraints; +using BH.oM.Structure.MaterialFragments; using BH.oM.Structure.SectionProperties; using BH.oM.Structure.SurfaceProperties; -using BH.oM.Structure.MaterialFragments; using System; using System.Collections; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; -using BH.oM.Analytical; -using BH.oM.Adapter; -using BH.oM.Adapters.SAP2000; namespace BH.Adapter.SAP2000 { @@ -46,16 +47,26 @@ public partial class SAP2000Adapter protected override bool ICreate(IEnumerable objects, ActionConfig actionConfig) { + bool success = true; + this.SAPPushConfig = actionConfig as SAP2000PushConfig; + if (!objects.Any()) //Return if no objects + return true; + if (typeof(BH.oM.Base.IBHoMObject).IsAssignableFrom(typeof(T))) { - return (CreateCollection(objects)); + success = CreateCollection(objects); } else { - return false; + success = false; } + + // Refresh the view to ensure that the newly created objects are displayed correctly + m_model.View.RefreshView(0, false); + + return success; } /***************************************************/ @@ -82,6 +93,41 @@ private bool CreateObject(IBHoMObject obj) } /***************************************************/ + + [Description("Concatenates the the BHoM Object Name and the last 7 characters of the SAP2000 Element GUID to get the Unique Name to assign to the SAP2000 Element.")] + private string SetUniqueName(BHoMObject obj, string name) + { + /* 1. CHECK OBJECT TYPE IS ACCEPTABLE */ + if (!(obj.GetType() == typeof(Node) || + obj.GetType() == typeof(Bar) || + obj.GetType() == typeof(Panel) || + obj.GetType() == typeof(Opening))) + { + return null; + } + + /* 2. GET THE SAP2000 ELEMENT GUID */ + int ret01 = 1; + int ret02 = 1; + string guid = null; + + if (obj.GetType() == typeof(Node)) ret01 = m_model.PointObj.GetGUID(name, ref guid); + if (obj.GetType() == typeof(Bar)) ret01 = m_model.FrameObj.GetGUID(name, ref guid); + if (obj.GetType() == typeof(Panel) || obj.GetType() == typeof(Opening)) ret01 = m_model.AreaObj.GetGUID(name, ref guid); + + string tempObjName = obj.Name == "" ? guid.Substring(guid.Length - 7) : obj.Name + "::" + guid.Substring(guid.Length - 7); + + /* 4. ASSIGN THE NEW UNIQUE NAME TO THE SAP2000 ELEMENT */ + if (obj.GetType() == typeof(Node)) ret02 = m_model.PointObj.ChangeName(name, tempObjName); + if (obj.GetType() == typeof(Bar)) ret02 = m_model.FrameObj.ChangeName(name, tempObjName); + if (obj.GetType() == typeof(Panel) || obj.GetType() == typeof(Opening)) ret02 = m_model.AreaObj.ChangeName(name, tempObjName); + + if (!(ret01 == 0 && ret02 == 0)) return ""; + + return tempObjName; + + /***************************************************/ + } } } diff --git a/SAP2000_Adapter/CRUD/Read/Bar.cs b/SAP2000_Adapter/CRUD/Read/Bar.cs index 89e2265d..a07a6273 100644 --- a/SAP2000_Adapter/CRUD/Read/Bar.cs +++ b/SAP2000_Adapter/CRUD/Read/Bar.cs @@ -60,7 +60,11 @@ private List ReadBars(List ids = null) try { - Bar bhomBar = new Bar(); + + string bhomName = GetBhomNameFromSAP2000Id(id); + + Bar bhomBar = new Bar() { Name = bhomName }; + string startId = ""; string endId = ""; m_model.FrameObj.GetPoints(id, ref startId, ref endId); diff --git a/SAP2000_Adapter/CRUD/Read/Mesh.cs b/SAP2000_Adapter/CRUD/Read/Mesh.cs new file mode 100644 index 00000000..4d3f43b8 --- /dev/null +++ b/SAP2000_Adapter/CRUD/Read/Mesh.cs @@ -0,0 +1,147 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2026, 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 BH.oM.Structure.Elements; +using BH.oM.Adapters.SAP2000; +using BH.oM.Geometry; +using BH.oM.Structure.Elements; +using BH.oM.Structure.SurfaceProperties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BH.Engine.Structure; + +namespace BH.Adapter.SAP2000 +{ + public partial class SAP2000Adapter + { + /***************************************************/ + + private List ReadMesh(List ids = null) + { + int nameCount = 0; + string[] nameArr = { }; + m_model.AreaObj.GetNameList(ref nameCount, ref nameArr); + + ids = FilterIds(ids, nameArr); + + List meshes = new List(); + Dictionary nodes = GetCachedOrReadAsDictionary(); + Dictionary surfaceProps = GetCachedOrReadAsDictionary(); + + foreach (string id in ids) + { + FEMesh mesh = new FEMesh(); + + SAP2000Id sap2000id = new SAP2000Id(); + sap2000id.Id = id; + + List meshNodeIds = new List(); + + //Get out the "Element" ids, i.e. the mesh faces + int nbELem = 0; + string[] elemNames = new string[0]; + m_model.AreaObj.GetElm(id, ref nbELem, ref elemNames); + + for (int j = 0; j < nbELem; j++) + { + //Get out the name of the points for each face + int nbPts = 0; + string[] ptsNames = new string[0]; + m_model.AreaElm.GetPoints(elemNames[j], ref nbPts, ref ptsNames); + + FEMeshFace face = new FEMeshFace(); + + for (int k = 0; k < nbPts; k++) + { + string nodeId = ptsNames[k]; + Node node; + + //Check if node already has been pulled + if (!nodes.TryGetValue(nodeId, out node)) + { + double x = 0, y = 0, z = 0; + m_model.PointElm.GetCoordCartesian(nodeId, ref x, ref y, ref z); + node = new Node() { Position = new Point { X = x, Y = y, Z = z } }; + SetAdapterId(node, nodeId); + nodes[ptsNames[k]] = node; + } + + //Check if node already has been added to the mesh + if (!meshNodeIds.Contains(nodeId)) + meshNodeIds.Add(nodeId); + + //Get corresponding node index + face.NodeListIndices.Add(meshNodeIds.IndexOf(nodeId)); + } + + //Add face to list + SetAdapterId(face, elemNames[j]); + mesh.Faces.Add(face); + + } + + //Set mesh nodes - if there are no nodes, don't create the mesh. + if (nodes.Count != 0 && mesh.Faces.Count != 0) + { + mesh.Nodes = meshNodeIds.Select(x => nodes[x]).ToList(); + + string propertyName = ""; + + m_model.AreaObj.GetProperty(id, ref propertyName); + + if (propertyName != "None") + { + mesh.Property = surfaceProps[propertyName]; + } + + //Get local x-axis + double orientation = 0; + bool advanced = false; + m_model.AreaObj.GetLocalAxes(id, ref orientation, ref advanced); + + Vector normal = mesh.Faces.First().Normal(mesh); //Assuming flat mesh, all normals equal + Vector localX = Convert.ToPanelLocalXAxis(normal, orientation); + mesh = mesh.SetLocalOrientations(localX); + + // Get guid + string guid = null; + m_model.AreaObj.GetGUID(id, ref guid); + sap2000id.PersistentId = guid; + + SetAdapterId(mesh, sap2000id); + meshes.Add(mesh); + } + else + { + BH.Engine.Base.Compute.RecordWarning("Mesh " + id.ToString() + " could not be pulled, because it contains no nodes"); + } + } + BH.Engine.Base.Compute.RecordWarning("Meshes - Only one face normal vector is pulled from every mesh and it is applied to all the faces of the mesh."); + return meshes; + } + + /***************************************************/ + } +} diff --git a/SAP2000_Adapter/CRUD/Read/Node.cs b/SAP2000_Adapter/CRUD/Read/Node.cs index 39e8b01f..345404f7 100644 --- a/SAP2000_Adapter/CRUD/Read/Node.cs +++ b/SAP2000_Adapter/CRUD/Read/Node.cs @@ -52,7 +52,10 @@ private List ReadNodes(List ids = null) foreach (string id in ids) { - Node bhNode = new Node(); + string bhomName = GetBhomNameFromSAP2000Id(id); + + Node bhNode = new Node { Name = bhomName}; + string guid = null; SAP2000Id sap2000id = new SAP2000Id(); sap2000id.Id = id; diff --git a/SAP2000_Adapter/CRUD/Read/Panel.cs b/SAP2000_Adapter/CRUD/Read/Panel.cs index 160c113c..19ee63ac 100644 --- a/SAP2000_Adapter/CRUD/Read/Panel.cs +++ b/SAP2000_Adapter/CRUD/Read/Panel.cs @@ -52,7 +52,9 @@ private List ReadPanel(List ids = null) ids = FilterIds(ids, nameArr); foreach (string id in ids) { - Panel bhomPanel = new Panel(); + string bhomName = GetBhomNameFromSAP2000Id(id); + Panel bhomPanel = new Panel() { Name = bhomName }; + SAP2000Id sap2000id = new SAP2000Id(); string guid = null; //Set the Adapter ID diff --git a/SAP2000_Adapter/CRUD/Read/Results/BarResults.cs b/SAP2000_Adapter/CRUD/Read/Results/BarResults.cs index e93a19aa..d5147c2c 100644 --- a/SAP2000_Adapter/CRUD/Read/Results/BarResults.cs +++ b/SAP2000_Adapter/CRUD/Read/Results/BarResults.cs @@ -46,7 +46,7 @@ public IEnumerable ReadResults(BarResultRequest request, { CheckAndSetUpCases(request); - List barIds = CheckGetBarIds(request); + List barIds = CheckAndGetIds(request); switch (request.ResultType) { @@ -73,7 +73,7 @@ public IEnumerable ReadResults(BarResultRequest request, private List ReadBarDisplacements(List barIds = null, int divisions = 0) { - List displacements = new List(); + List displacements = new List(); if (divisions != 0) { Engine.Base.Compute.RecordWarning("Displacements will only be extracted at SAP2000 calculation nodes." + diff --git a/SAP2000_Adapter/CRUD/Read/Results/GlobalResults.cs b/SAP2000_Adapter/CRUD/Read/Results/GlobalResults.cs deleted file mode 100644 index a3d45dab..00000000 --- a/SAP2000_Adapter/CRUD/Read/Results/GlobalResults.cs +++ /dev/null @@ -1,202 +0,0 @@ -/* - * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2026, 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; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using BH.oM.Structure.Results; -using BH.oM.Common; -using BH.oM.Structure.Elements; -using BH.Engine.SAP2000; -using BH.oM.Structure.Loads; -using BH.oM.Structure.Requests; -using BH.oM.Adapters.SAP2000; -using BH.oM.Geometry; -using BH.Engine.Geometry; -/*using SAP2000v19;*/ -using BH.oM.Adapter; -using SAP2000v1; - -namespace BH.Adapter.SAP2000 -{ - /***************************************************/ - /**** Public method - Read override ****/ - /***************************************************/ - - public IEnumerable ReadResults(GlobalResultRequest request, - ActionConfig actionConfig = null) - { - CheckAndSetUpCases(request); - - switch (request.ResultType) - { - case GlobalResultType.Reactions: - return GetGlobalReactions(); - case GlobalResultType.ModalDynamics: - return GetModalParticipationMassRatios(); - default: - Engine.Reflection.Compute.RecordError("Result extraction of type " + request.ResultType + " is not yet supported"); - return new List(); - } - } - - /***************************************************/ - /**** Private method - Extraction methods ****/ - /***************************************************/ - - private List GetGlobalReactions() - { - List globalReactions = new List(); - - int resultCount = 0; - string[] loadcaseNames = null; - string[] stepType = null; - int[] stepNum = 0; - - double[] fx = null; - double[] fy = null; - double[] fz = null; - double[] mx = null; - double[] my = null; - double[] mz = null; - double gx = 0; - double gy = 0; - double gz = 0; - - int ret = m_model.Results.BaseReact(ref resultCount, - ref loadcaseNames, - ref stepType, - ref stepNum, - ref fx, - ref fy, - ref fz, - ref mx, - ref my, - ref mz, - ref gx, - ref gy, - ref gz); - - for (int i; i < resultCount; i++) - { - GlobalReactions g = new GlobalReactions() - { - ResultCase = loadcaseNames[i], - FX = fx[i], - FY = fy[i], - FZ = fz[i], - MX = mx[i], - MY = my[i], - MZ = mz[i], - TimeStep = stepNum[i] - }; - - globalReactions.Add(g); - } - - return globalReactions; - } - - /***************************************************/ - - private List GetModalParticipationMassRatios() - { - List partRatios = new List(); - - int resultCount = 0; - string[] loadcaseNames = null; - string[] stepType = null; - int[] stepNum = null; - double[] period = null; - double[] ux = null; - double[] uy = null; - double[] uz = null; - double[] sumUx = null; - double[] sumUy = null; - double[] sumUz = null; - double[] rx = null; - double[] ry = null; - double[] rz = null; - double[] sumRx = null; - double[] sumRy = null; - double[] sumRz = null; - - int ret = m_model.Results.ModalParticipatingMassRatios(ref resultCount, - ref loadcaseNames, - ref stepType, - ref stepNum, - ref period, - ref ux, - ref uy, - ref uz, - ref sumUx, - ref sumUy, - ref sumUz, - ref rx, - ref ry, - ref rz, - ref sumRx, - ref sumRy, - ref sumRz); - - if (ret != 0) Engine.Reflection.Compute.RecordError("Could not extract Modal information."); - - string previousModalCase = ""; - int modeNumber = 1; //makes up for stepnumber always = 0 - for (int i = 0; i < resultCount; i++) - { - if (loadcaseNames[i] != previousModalCase) - modeNumber = 1; - - ModalDynamics mod = new ModalDynamics() - { - ResultCase = loadcaseNames[i], - ModeNumber = modeNumber, - Frequency = 1 / period[i], - MassRatioX = ux[i], - MassRatioY = uy[i], - MassRatioZ = uz[i], - InertiaRatioX = rx[i], - InertiaRatioY = ry[i], - InertiaRatioZ = rz[i] - }; - - modeNumber += 1; - previousModalCase = loadcaseNames[i]; - - partRatios.Add(mod); - } - - return partRatios; - } - - /***************************************************/ -} - - - - - - diff --git a/SAP2000_Adapter/CRUD/Read/Results/MeshResults.cs b/SAP2000_Adapter/CRUD/Read/Results/MeshResults.cs index 4dee5add..abf9295e 100644 --- a/SAP2000_Adapter/CRUD/Read/Results/MeshResults.cs +++ b/SAP2000_Adapter/CRUD/Read/Results/MeshResults.cs @@ -20,24 +20,22 @@ * along with this code. If not, see . */ +using BH.Engine.Geometry; +using BH.oM.Adapter; +using BH.oM.Adapters.SAP2000; +using BH.oM.Analytical.Results; +using BH.oM.Geometry; +using BH.oM.Structure.Elements; +using BH.oM.Structure.Loads; +using BH.oM.Structure.Requests; +using BH.oM.Structure.Results; +using SAP2000v1; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using BH.oM.Structure.Results; -using BH.oM.Common; -using BH.oM.Structure.Elements; -using BH.Engine.SAP2000; -using BH.oM.Structure.Loads; -using BH.oM.Structure.Requests; -using BH.oM.Adapters.SAP2000; -using BH.oM.Geometry; -using BH.Engine.Geometry; -/*using SAP2000v19;*/ -using BH.oM.Adapter; -using SAP2000v1; namespace BH.Adapter.SAP2000 @@ -48,44 +46,43 @@ public partial class SAP2000Adapter : BHoMAdapter /**** Public method - Read override ****/ /***************************************************/ - public IEnumerable ReadResults(MeshResultRequest request, - ActionConfig actionConfig = null) + public IEnumerable ReadResults(MeshResultRequest request, ActionConfig actionConfig = null) { List cases = GetAllCases(request.Cases); CheckAndSetUpCases(request); - List panelIds = CheckGetPanelIds(request); + List panelIds = CheckAndGetIds (request); switch (request.ResultType) { case MeshResultType.Forces: - /* return ReadMeshForce(panelIds, request.smoothing);*/ + return ReadMeshForce(panelIds, request.Smoothing); case MeshResultType.Displacements: + return ReadMeshDisplacement(panelIds, request.Smoothing); case MeshResultType.Stresses: + return ReadMeshStress(panelIds, cases, request.Smoothing, request.Layer); case MeshResultType.VonMises: + return ReadMeshVonMises(panelIds, cases, request.Smoothing, request.Layer); default: - Engine.Reflection.Compute.RecordError("Result extraction of type " + request.ResultType + " is not yet supported"); + Engine.Base.Compute.RecordError("Result extraction of type " + request.ResultType + " is not yet supported."); return new List(); } + } /***************************************************/ - /**** Private methods - Extraction methods ****/ + /**** Private method - Extraction methods ****/ /***************************************************/ - private List ReadMeshForce(List panelIds, - MeshResultSmoothingType smoothing) + + private List ReadMeshForce(List panelIds, MeshResultSmoothingType smoothing) { - switch (smoothing) + if (smoothing != MeshResultSmoothingType.None && smoothing != MeshResultSmoothingType.ByPanel) { - case MeshResultSmoothingType.BySelection: - case MeshResultSmoothingType.Global: - case MeshResultSmoothingType.ByFiniteElementCentres: - Engine.Reflection.Compute.RecordWarning("Smoothing type not supported for MeshForce. No results extracted"); - default: - return new List(); + Engine.Base.Compute.RecordWarning("Smoothing type not supported for MeshStress. No results extracted."); + return new List(); } - List results = new List(); + eItemTypeElm itemTypeElm = eItemTypeElm.ObjectElm; int resultCount = 0; string[] obj = null; string[] elm = null; @@ -111,62 +108,35 @@ private List ReadMeshForce(List panelIds, double[] vMax = null; double[] vAngle = null; + List results = new List(); + if (smoothing == MeshResultSmoothingType.ByPanel) - Engine.Reflection.Compute.RecordWarning("Force values have been smoothed outside the API by averaging all force values in each node"); + Engine.Base.Compute.RecordWarning("Force values have been smoothed outside the API by averaging all force values in each node."); for (int i = 0; i < panelIds.Count; i++) { List forces = new List(); - int ret = m_model.Results.AreaForceShell(panelIds[i], - eItemTypeElm.ObjectElm, - ref resultCount, - ref obj, - ref elm, - ref pointElm, - ref loadCase, - ref stepType, - ref stepNum, - ref f11, - ref f22, - ref f12, - ref fMax, - ref fMin, - ref fAngle, - ref fvm, - ref m11, - ref m22, - ref m12, - ref mMax, - ref mMin, - ref mAngle, - ref v13, - ref v23, - ref vMax, - ref vAngle); + int ret = m_model.Results.AreaForceShell(panelIds[i], itemTypeElm, ref resultCount, ref obj, ref elm, + ref pointElm, ref loadCase, ref stepType, ref stepNum, ref f11, ref f22, ref f12, ref fMax, ref fMin, ref fAngle, ref fvm, + ref m11, ref m22, ref m12, ref mMax, ref mMin, ref mAngle, ref v13, ref v23, ref vMax, ref vAngle); for (int j = 0; j < resultCount; j++) { - double step = 0; + int mode; + double timeStep; + if (stepType[j] == "Single Value" || stepNum.Length < j) - step = 0; - else: - step = stepNum[j]; - - MeshForce pf = new MeshForce(panelIds[i], - pointElm[j], - elm[j], - loadCase[j], - step, 0, 0, 0, - oM.Geometry.Basis.XY, - f11[j], - f22[j], - f12[j], - m11[j], - m22[j], - m12[j], - v13[j], - v23[j]); + { + mode = 0; + timeStep = 0; + } + else + GetStepAndMode(stepType[j], stepNum[j], out timeStep, out mode); + + MeshForce pf = new MeshForce(panelIds[i], pointElm[j], elm[j], loadCase[j], mode, timeStep, 0, 0, 0, + oM.Geometry.Basis.XY, f11[j], f22[j], f12[j], m11[j], m22[j], m12[j], v13[j], v23[j]); + forces.Add(pf); } @@ -179,20 +149,289 @@ private List ReadMeshForce(List panelIds, return results; } + /***************************************************/ + + private List ReadMeshStress(List panelIds, List cases, MeshResultSmoothingType smoothing, MeshResultLayer layer) + { + if (smoothing!= MeshResultSmoothingType.None && smoothing != MeshResultSmoothingType.ByPanel) { + Engine.Base.Compute.RecordWarning("Smoothing type not supported for MeshStress. No results extracted."); + return new List(); + } + + if (layer == MeshResultLayer.Upper || layer == MeshResultLayer.Lower) + { + Engine.Base.Compute.RecordWarning("Results for both bottom and top layers will be extracted at the same time."); + } + else + { + Engine.Base.Compute.RecordWarning("Stress extraction is currently only possible at bottom and top layers. Please update the MeshResultLayer parameter."); + return new List(); + } + + eItemTypeElm itemTypeElm = eItemTypeElm.ObjectElm; + int resultCount = 0; + string[] obj = null; + string[] elm = null; + string[] pointElm = null; + string[] loadCase = null; + string[] stepType = null; + double[] stepNum = null; + double[] s11Top = null; + double[] s22Top = null; + double[] s12Top = null; + double[] sMaxTop = null; + double[] sMinTop = null; + double[] sAngTop = null; + double[] svmTop = null; + double[] s11Bot = null; + double[] s22Bot = null; + double[] s12Bot = null; + double[] sMaxBot = null; + double[] sMinBot = null; + double[] sAngBot = null; + double[] svmBot = null; + double[] s13Avg = null; + double[] s23Avg = null; + double[] sMaxAvg = null; + double[] sAngAvg = null; + + List results = new List(); + + if (smoothing == MeshResultSmoothingType.ByPanel) + Engine.Base.Compute.RecordWarning("Stress values have been smoothed outside the API by averaging all force values in each node."); + + foreach (string caseName in cases) + { + m_model.Results.Setup.DeselectAllCasesAndCombosForOutput(); + if (!SetUpCaseOrCombo(caseName)) + continue; + + for (int i = 0; i < panelIds.Count; i++) + { + List stressTop = new List(); + List stressBot = new List(); + int ret = m_model.Results.AreaStressShell(panelIds[i], itemTypeElm, ref resultCount, ref obj, ref elm, ref pointElm, ref loadCase, ref stepType, ref stepNum, ref s11Top, ref s22Top, ref s12Top, ref sMaxTop, ref sMinTop, ref sAngTop, ref svmTop, ref s11Bot, ref s22Bot, ref s12Bot, ref sMaxBot, ref sMinBot, ref sAngBot, ref svmBot, ref s13Avg, ref s23Avg, ref sMaxAvg, ref sAngAvg); + + if (ret == 0) + { + for (int j = 0; j < resultCount; j++) + { + int mode; + double timeStep; + GetStepAndMode(stepType[j], stepNum[j], out timeStep, out mode); + MeshStress mStressTop = new MeshStress(panelIds[i], pointElm[j], elm[j], loadCase[j], mode, timeStep, MeshResultLayer.Upper, 1, MeshResultSmoothingType.None, oM.Geometry.Basis.XY, s11Top[j], s22Top[j], s12Top[j], s13Avg[j], s23Avg[j], sMaxTop[j], sMinTop[j], double.NaN); + MeshStress mStressBot = new MeshStress(panelIds[i], pointElm[j], elm[j], loadCase[j], mode, timeStep, MeshResultLayer.Lower, 0, MeshResultSmoothingType.None, oM.Geometry.Basis.XY, s11Bot[j], s22Bot[j], s12Bot[j], s13Avg[j], s23Avg[j], sMaxBot[j], sMinBot[j], double.NaN); + + stressBot.Add(mStressBot); + stressTop.Add(mStressTop); + } + + if (smoothing == MeshResultSmoothingType.ByPanel) + { + stressTop = SmoothenStresses(stressTop); + stressBot = SmoothenStresses(stressBot); + } + + results.AddRange(GroupMeshResults(stressBot)); + results.AddRange(GroupMeshResults(stressTop)); + + } + else + { + Engine.Base.Compute.RecordWarning("Failed to extract results for element " + panelIds[i] + " for case " + caseName + "."); + } + } + } + return results; + } + + /***************************************************/ + + private List ReadMeshVonMises(List panelIds, List cases, MeshResultSmoothingType smoothing, MeshResultLayer layer) + { + if (smoothing != MeshResultSmoothingType.None && smoothing != MeshResultSmoothingType.ByPanel) + { + Engine.Base.Compute.RecordWarning("Smoothing type not supported for MeshStress. No results extracted."); + return new List(); + } + + if (layer == MeshResultLayer.Upper || layer == MeshResultLayer.Lower) + { + Engine.Base.Compute.RecordWarning("Results for both bot and top layers will be extracted at the same time."); + } + else + { + Engine.Base.Compute.RecordWarning("Stress extraction is currently only possible at bottom and top layers. Please update the MeshResultLayer parameter."); + return new List(); + } + + eItemTypeElm itemTypeElm = eItemTypeElm.ObjectElm; + int resultCount = 0; + string[] obj = null, elm = null; + string[] pointElm = null, loadCase = null, stepType = null; + double[] stepNum = null; + double[] s11Top = null, s22Top = null, s12Top = null, sMaxTop = null, sMinTop = null, sAngTop = null, svmTop = null; + double[] s11Bot = null, s22Bot = null, s12Bot = null, sMaxBot = null, sMinBot = null, sAngBot = null, svmBot = null; + double[] s13Avg = null, s23Avg = null, sMaxAvg = null, sAngAvg = null; + double[] f11 = null, f22 = null, f12 = null, fMax = null, fMin = null, fAngle = null, fvm = null; + double[] m11 = null, m22 = null, m12 = null, mMax = null, mMin = null, mAngle = null; + double[] v13 = null, v23 = null, vMax = null, vAngle = null; + + List results = new List(); + + if (smoothing == MeshResultSmoothingType.ByPanel) + Engine.Base.Compute.RecordWarning("Stress values have been smoothed outside the API by averaging all force values in each node."); + + foreach (string caseName in cases) + { + m_model.Results.Setup.DeselectAllCasesAndCombosForOutput(); + + if (!SetUpCaseOrCombo(caseName)) + continue; + + for (int i = 0; i < panelIds.Count; i++) + { + List stressVMTop = new List(); + List stressVMBot = new List(); + int ret1, ret2; + + // Extract Von Mises Stresses + ret1 = m_model.Results.AreaStressShell(panelIds[i], itemTypeElm, ref resultCount, ref obj, ref elm, ref pointElm, + ref loadCase, ref stepType, ref stepNum, ref s11Top, ref s22Top, ref s12Top, ref sMaxTop, ref sMinTop, ref sAngTop, ref svmTop, + ref s11Bot, ref s22Bot, ref s12Bot, ref sMaxBot, ref sMinBot, ref sAngBot, ref svmBot, ref s13Avg, ref s23Avg, ref sMaxAvg, ref sAngAvg); + + // Extract Von Mises Resultant Axial Forces + ret2 = m_model.Results.AreaForceShell(panelIds[i], itemTypeElm, ref resultCount, + ref obj, ref elm, ref pointElm, ref loadCase, ref stepType, ref stepNum, + ref f11, ref f22, ref f12, ref fMax, ref fMin, ref fAngle, ref fvm, + ref m11, ref m22, ref m12, ref mMax, ref mMin, ref mAngle, + ref v13, ref v23, ref vMax, ref vAngle); + + if ((ret1 == 0) && (ret2 == 0)) + { + for (int j = 0; j < resultCount; j++) + { + int mode; + double timeStep; + + GetStepAndMode(stepType[j], stepNum[j], out timeStep, out mode); + MeshVonMises mStressVMTop = new MeshVonMises(panelIds[i], pointElm[j], elm[j], loadCase[j], mode, timeStep, + MeshResultLayer.Upper, 1, MeshResultSmoothingType.None, oM.Geometry.Basis.XY, svmTop[j], fvm[j], double.NaN); + MeshVonMises mStressVMBot = new MeshVonMises(panelIds[i], pointElm[j], elm[j], loadCase[j], mode, timeStep, + MeshResultLayer.Lower, 0, MeshResultSmoothingType.None, oM.Geometry.Basis.XY, svmBot[j], fvm[j], double.NaN); + + stressVMBot.Add(mStressVMBot); + stressVMTop.Add(mStressVMTop); + } + + if (smoothing == MeshResultSmoothingType.ByPanel) + { + stressVMTop = SmoothenVonMisesStresses(stressVMTop); + stressVMBot = SmoothenVonMisesStresses(stressVMBot); + } + + results.AddRange(GroupMeshResults(stressVMTop)); + results.AddRange(GroupMeshResults(stressVMBot)); + + } + else + { + Engine.Base.Compute.RecordWarning("Failed to extract results for element " + panelIds[i] + " for case " + caseName + "."); + } + } + } + return results; + + } /***************************************************/ - - private List ReadMeshDisplacement(List panelIds, - MeshResultSmoothingType smoothing) + //Method atempting to extract results using AreaStressLayered method. API call is currently never returning any results for this. + //Keeping for further reference. Method is not called from anywhere + private List ReadMeshStressLayered(List panelIds, MeshResultSmoothingType smoothing, List cases) { + if (smoothing != MeshResultSmoothingType.None && smoothing != MeshResultSmoothingType.ByPanel) + { + Engine.Base.Compute.RecordWarning("Smoothing type not supported for MeshStress. No results extracted."); + return new List(); + } + + eItemTypeElm itemTypeElm = eItemTypeElm.ObjectElm; int resultCount = 0; string[] obj = null; string[] elm = null; + string[] layer = null; + int[] intPtNb = null; + double[] layerPos = null; + string[] pointElm = null; string[] loadCase = null; string[] stepType = null; double[] stepNum = null; + double[] s11 = null; + double[] s22 = null; + double[] s12 = null; + double[] sMax = null; + double[] sMin = null; + double[] sAng = null; + double[] svm = null; + double[] s13 = null; + double[] s23 = null; + double[] sMaxAvg = null; + double[] sAngAvg = null; + + List results = new List(); + + if (smoothing == MeshResultSmoothingType.ByPanel) + Engine.Base.Compute.RecordWarning("Stress values have been smoothened outside the API by averaging all force values in each node."); + + foreach (string caseName in cases) + { + m_model.Results.Setup.DeselectAllCasesAndCombosForOutput(); + if (!SetUpCaseOrCombo(caseName)) + continue; + for (int i = 0; i < panelIds.Count; i++) + { + List stresses = new List(); + int ret = m_model.Results.AreaStressShellLayered(panelIds[i], itemTypeElm, ref resultCount, ref obj, ref elm, ref layer, ref intPtNb, ref layerPos, ref pointElm, ref loadCase, ref stepType, ref stepNum, ref s11, ref s22, ref s12, ref sMax, ref sMin, ref sAng, ref svm, ref s13, ref s23, ref sMaxAvg, ref sAngAvg); + + if (ret == 0) + { + for (int j = 0; j < resultCount - 1; j++) + { + int mode; + double timeStep; + GetStepAndMode(stepType[j], stepNum[j], out timeStep, out mode); + MeshStress mStress = new MeshStress(panelIds[i], pointElm[j], elm[j], loadCase[j], mode, timeStep, MeshResultLayer.Arbitrary, layerPos[j], MeshResultSmoothingType.None, oM.Geometry.Basis.XY, s11[j], s22[j], s12[j], s13[j], s23[j], sMax[j], sMin[j], sMaxAvg[j]); + stresses.Add(mStress); + } + + if (smoothing == MeshResultSmoothingType.ByPanel) stresses = SmoothenStresses(stresses); + + results.AddRange(GroupMeshResults(stresses)); + } + else + { + Engine.Base.Compute.RecordWarning("Failed to extract results for element " + panelIds[i] + " for case " + caseName + "."); + } + + } + } + + return results; + } + + /***************************************************/ + + private List ReadMeshDisplacement(List panelIds, MeshResultSmoothingType smoothing) + { + + int resultCount = 0; + string[] obj = null; + string[] elm = null; + string[] loadCase = null; + string[] stepType = null; + double[] stepNum = null; double[] ux = null; double[] uy = null; double[] uz = null; @@ -205,20 +444,19 @@ private List ReadMeshDisplacement(List panelIds, for (int i = 0; i < panelIds.Count; i++) { List displacements = new List(); - HashSet ptNbs = new HashSet(); - - int nbElem = 0; + int nbELem = 0; string[] elemNames = new string[0]; - m_model.AreaObj.GetElm(panelIds[i], ref nbElem, ref elemNames); + m_model.AreaObj.GetElm(panelIds[i], ref nbELem, ref elemNames); - for (int j = 0; j < nbElem; j++) + for (int j = 0; j < nbELem; j++) { + //Get out the name of the points for each face int nbPts = 0; string[] ptsNames = new string[0]; m_model.AreaElm.GetPoints(elemNames[j], ref nbPts, ref ptsNames); - foreach (string ptId in ptsNames); + foreach (string ptId in ptsNames) { ptNbs.Add(ptId); } @@ -226,64 +464,46 @@ private List ReadMeshDisplacement(List panelIds, foreach (string ptId in ptNbs) { - int ret = m_model.Results.JointDispl(ptId, - eItemTypeElm.Element, - ref resultCount, - ref obj, - ref elm, - ref loadCase, - ref stepType, - ref stepNum, - ref ux, - ref uy, - ref uz, - ref rx, - ref ry, - ref fz); + int ret = m_model.Results.JointDispl(ptId, eItemTypeElm.Element, ref resultCount, ref obj, ref elm, ref loadCase, ref stepType, ref stepNum, ref ux, ref uy, ref uz, ref rx, ref ry, ref rz); for (int j = 0; j < resultCount; j++) { - MeshDisplacement disp = new MeshDisplacement(panelIds[i], - ptId, - "", - loadCase[j], - stepNum[j], - MeshResultLayer.Middle, - 0, - MeshResultSmoothingType.Global, - Basis.Xy, - ux[j], - uy[j], - uz[j], - rx[j], - ry[j], - rz[j]); + int mode; + double timeStep; + GetStepAndMode(stepType[j], stepNum[j], out timeStep, out mode); + MeshDisplacement disp = new MeshDisplacement(panelIds[i], ptId, "", loadCase[j], mode, timeStep, MeshResultLayer.Middle, 0, MeshResultSmoothingType.Global, Basis.XY, ux[j], uy[j], uz[j], rx[j], ry[j], rz[j]); + displacements.Add(disp); } } results.AddRange(GroupMeshResults(displacements)); } - return results + + return results; } /***************************************************/ - /* - private List ReadMeshStress(List panelIds, List cases, - MeshResultSmoothingType smoothing, MeshResultLayer layer) + /**** Private method - Support methods ****/ + /***************************************************/ + + private List GroupMeshResults(IEnumerable meshElementResults) { - return results + List results = new List(); + foreach (IEnumerable group in meshElementResults.GroupBy(x => new { x.ResultCase, x.TimeStep, x.ModeNumber })) + { + MeshElementResult first = group.First(); + results.Add(new MeshResult(first.ObjectId, first.ResultCase, first.ModeNumber, first.TimeStep, first.MeshResultLayer, first.LayerPosition, first.Smoothing, new System.Collections.ObjectModel.ReadOnlyCollection(group.ToList()))); + } + + return results; } - - /***************************************************/ - /**** Private methods - Support methods ****/ /***************************************************/ private List SmoothenForces(List forces) { List smoothenedForces = new List(); - foreach (IEnumerable gorup in forces.GroupBy(x => new { x.ResultCase, - x.TimeStep, x.NodeID})) + foreach (IEnumerable group in forces.GroupBy(x => new { x.ResultCase, x.TimeStep, x.NodeId })) { MeshForce first = group.First(); @@ -298,31 +518,63 @@ private List SmoothenForces(List forces) double vx = group.Average(x => x.VX); double vy = group.Average(x => x.VY); - smoothenedForces.Add(new MeshForce(first.ObjectId, - first.NodeID, - "", - first.ResultCase, - first.TimeStep, - first.MeshResultLayer, - first.LayerPosition, - MeshResultSmoothingType.ByPanel, - first.Orientation, - nxx, - nyy, - nxy, - mxx, - myy, - mxy, - vx, - vy)); + smoothenedForces.Add(new MeshForce(first.ObjectId, first.NodeId, "", first.ResultCase, first.ModeNumber, first.TimeStep, first.MeshResultLayer, first.LayerPosition, MeshResultSmoothingType.ByPanel, first.Orientation, nxx, nyy, nxy, mxx, myy, mxy, vx, vy)); } + return smoothenedForces; } - } -} + /***************************************************/ + + private List SmoothenStresses(List forces) + { + List smoothenedForces = new List(); + + foreach (IEnumerable group in forces.GroupBy(x => new { x.ResultCase, x.TimeStep, x.NodeId })) + { + MeshStress first = group.First(); + + double sxx = group.Average(x => x.SXX); + double syy = group.Average(x => x.SYY); + double sxy = group.Average(x => x.SXY); + double txx = group.Average(x => x.TXX); + double tyy = group.Average(x => x.TYY); + double pr1 = group.Average(x => x.Principal_1); + double pr2 = group.Average(x => x.Principal_2); + double pr1_2 = group.Average(x => x.Principal_1_2); + + smoothenedForces.Add(new MeshStress(first.ObjectId, first.NodeId, "", first.ResultCase, first.ModeNumber, first.TimeStep, first.MeshResultLayer, first.LayerPosition, MeshResultSmoothingType.ByPanel, first.Orientation, sxx, syy, sxy, txx, tyy, pr1, pr2, pr1_2)); + } + + return smoothenedForces; + } + + /***************************************************/ + + private List SmoothenVonMisesStresses(List forces) + { + List smoothenedVMStresses = new List(); + + foreach (IEnumerable group in forces.GroupBy(x => new { x.ResultCase, x.TimeStep, x.NodeId })) + { + MeshVonMises first = group.First(); + + double s = group.Average(x => x.S); + double n = group.Average(x => x.N); + + smoothenedVMStresses.Add(new MeshVonMises(first.ObjectId, first.NodeId, "", first.ResultCase, first.ModeNumber, first.TimeStep, + first.MeshResultLayer, first.LayerPosition, MeshResultSmoothingType.ByPanel, first.Orientation, s, n, double.NaN)); + } + + return smoothenedVMStresses; + } + + /***************************************************/ + + } +} diff --git a/SAP2000_Adapter/CRUD/Read/Results/NodeResults.cs b/SAP2000_Adapter/CRUD/Read/Results/NodeResults.cs index 112332e8..807b1056 100644 --- a/SAP2000_Adapter/CRUD/Read/Results/NodeResults.cs +++ b/SAP2000_Adapter/CRUD/Read/Results/NodeResults.cs @@ -29,6 +29,7 @@ using BH.oM.Structure.Requests; using BH.oM.Adapter; using SAP2000v1; +using BH.oM.Structure.Elements; namespace BH.Adapter.SAP2000 @@ -43,7 +44,7 @@ public IEnumerable ReadResults(NodeResultRequest request, ActionConfig actionConfig = null) { CheckAndSetUpCases(request); - List nodeIds = CheckGetNodeIds(request); + List nodeIds = CheckAndGetIds(request); switch (request.ResultType) { @@ -52,7 +53,9 @@ public IEnumerable ReadResults(NodeResultRequest request, case NodeResultType.NodeDisplacement: return ReadNodeDisplacement(nodeIds); case NodeResultType.NodeAcceleration: + return ReadNodeAcceleration(nodeIds); case NodeResultType.NodeVelocity: + return ReadNodeVelocity(nodeIds); default: Engine.Base.Compute.RecordError("Result extraction of type " + request.ResultType + " is not yet supported"); return new List(); @@ -63,14 +66,46 @@ public IEnumerable ReadResults(NodeResultRequest request, /**** Private method - Extraction methods ****/ /***************************************************/ - private List ReadNodeAcceleration(IList ids = null, - IList cases = null) + private List ReadNodeAcceleration(List nodeIds) { - throw new NotImplementedException("Node Acceleration results is not supported yet!"); + List nodeAccelerations = new List(); + + int resultCount = 0; + string[] loadcaseNames = null; + string[] objects = null; + string[] elm = null; + string[] stepType = null; + double[] stepNum = null; + double[] ux = null; + double[] uy = null; + double[] uz = null; + double[] rx = null; + double[] ry = null; + double[] rz = null; + + for (int i = 0; i < nodeIds.Count; i++) + { + int ret = m_model.Results.JointAccAbs(nodeIds[i].ToString(), eItemTypeElm.ObjectElm, ref resultCount, ref objects, ref elm, ref loadcaseNames, + ref stepType, ref stepNum, ref ux, ref uy, ref uz, ref rx, ref ry, ref rz); + if (ret == 0) + { + for (int j = 0; j < resultCount; j++) + { + int mode; + double timeStep; + GetStepAndMode(stepType[j], stepNum[j], out timeStep, out mode); + NodeAcceleration na = new NodeAcceleration(nodeIds[i], loadcaseNames[j], mode, timeStep, oM.Geometry.Basis.XY, ux[j], uy[j], uz[j], rx[j], ry[j], rz[j]); + nodeAccelerations.Add(na); + } + } + } + + return nodeAccelerations; } /***************************************************/ + private List ReadNodeDisplacement(List nodeIds) { @@ -169,18 +204,47 @@ private List ReadNodeReaction(List nodeIds) /***************************************************/ - - private List ReadNodeVelocity(IList ids = null, - IList cases = null) + private List ReadNodeVelocity(List nodeIds) { - throw new NotImplementedException("Node velocity results are not supported yet!"); + List nodeVelocities = new List(); + int resultCount = 0; + string[] loadcaseNames = null; + string[] objects = null; + string[] elm = null; + string[] stepType = null; + double[] stepNum = null; + double[] ux = null; + double[] uy = null; + double[] uz = null; + double[] rx = null; + double[] ry = null; + double[] rz = null; + + for (int i = 0; i < nodeIds.Count; i++) + { + int ret = m_model.Results.JointVelAbs(nodeIds[i], eItemTypeElm.ObjectElm, ref resultCount, ref objects, ref elm, + ref loadcaseNames, ref stepType, ref stepNum, ref ux, ref uy, ref uz, ref rx, ref ry, ref rz); + if (ret == 0) + { + for (int j = 0; j < resultCount; j++) + { + int mode; + double timeStep; + GetStepAndMode(stepType[j], stepNum[j], out timeStep, out mode); + NodeVelocity nv = new NodeVelocity(nodeIds[i], loadcaseNames[j], mode, timeStep, oM.Geometry.Basis.XY, ux[j], uy[j], uz[j], rx[j], ry[j], rz[j]); + nodeVelocities.Add(nv); + } + } + } + + return nodeVelocities; } + /***************************************************/ /**** Private method - Support methods ****/ /***************************************************/ - } } diff --git a/SAP2000_Adapter/CRUD/Read/Results/Result.cs b/SAP2000_Adapter/CRUD/Read/Results/Result.cs index 9d101f1e..29b058b1 100644 --- a/SAP2000_Adapter/CRUD/Read/Results/Result.cs +++ b/SAP2000_Adapter/CRUD/Read/Results/Result.cs @@ -20,15 +20,18 @@ * along with this code. If not, see . */ +using BH.oM.Adapter; +using BH.oM.Analytical.Results; +using BH.oM.Base; +using BH.oM.Data.Requests; +using BH.oM.Structure.Elements; +using BH.oM.Structure.Loads; +using BH.oM.Structure.Requests; using System; +using System.CodeDom; using System.Collections; using System.Collections.Generic; using System.Linq; -using BH.oM.Analytical.Results; -using BH.oM.Structure.Loads; -using BH.oM.Data.Requests; -using BH.oM.Structure.Requests; -using BH.oM.Adapter; namespace BH.Adapter.SAP2000 { @@ -109,25 +112,106 @@ private bool SetUpCaseOrCombo(string caseName) } /***************************************************/ - private List CheckGetBarIds(IStructuralResultRequest request) + + private void GetStepAndMode(string stepType, double stepNum, out double timeStep, out int mode) { - int sapBarCount = 0; - string[] sapBarIds = null; - m_model.FrameObj.GetNameList(ref sapBarCount, ref sapBarIds); + if (stepType == "Mode") + { + mode = (int)stepNum; + timeStep = 0; + } + else + { + timeStep = stepNum; + mode = 0; + } + } + + /***************************************************/ - //Get the bar ids which are valid - return FilterIds(request.ObjectIds.Select(x => x.ToString()), sapBarIds); + private List CheckAndGetIds(IEnumerable ids) where T : IBHoMObject + { + if (ids == null) + { + return null; + } + else + { + List idsOut = new List(); + foreach (object o in ids) + { + if (o is string) + idsOut.Add((string)o); + else if (o is int || o is double) + idsOut.Add(o.ToString()); + else if (o is T) + { + string id = GetAdapterId((T)o); + if (id != null) + idsOut.Add(id); + } + } + return idsOut; + } } /***************************************************/ - private List CheckGetNodeIds(NodeResultRequest request) + private List CheckAndGetIds(IResultRequest request) where T : IBHoMObject { - int sapNodeCount = 0; - string[] sapNodeIds = null; - m_model.PointObj.GetNameList(ref sapNodeCount, ref sapNodeIds); + List ids = new List(); + + if (request.ObjectIds == null) + { + return null; + } + else + { + foreach (object o in request.ObjectIds) + { + if (o is string) + ids.Add((string)o); + else if (o is int || o is double) + ids.Add(o.ToString()); + else if (o is T) + { + string id = GetAdapterId((T)o); + if (id != null) + ids.Add(id); + } + } + } + + if (ids != null && ids.Count != 0) { + return ids; + } + + string[] names = null; + + switch (typeof(T)) + { + case Type t when t == typeof(Node): + int nodes = 0; + m_model.PointObj.GetNameList(ref nodes, ref names); + break; + case Type t when t == typeof(Bar): + int bars = 0; + m_model.FrameObj.GetNameList(ref bars, ref names); + break; + case Type t when t == typeof(Panel): + int panels = 0; + m_model.AreaObj.GetNameList(ref panels, ref names); + break; + case Type t when t == typeof(FEMesh): + int feMeshes = 0; + m_model.AreaObj.GetNameList(ref feMeshes, ref names); + break; + default: + names = new string[] { }; + break; + } - return FilterIds(request.ObjectIds.Select(x => x.ToString()), sapNodeIds); + return names.ToList(); } } } diff --git a/SAP2000_Adapter/CRUD/Read/Results/SteelUtilisationResults.cs b/SAP2000_Adapter/CRUD/Read/Results/SteelUtilisationResults.cs index a6bfe919..1b3a5d38 100644 --- a/SAP2000_Adapter/CRUD/Read/Results/SteelUtilisationResults.cs +++ b/SAP2000_Adapter/CRUD/Read/Results/SteelUtilisationResults.cs @@ -35,6 +35,7 @@ using BH.oM.Adapters.SAP2000.Results; using BH.oM.Adapters.SAP2000.Requests; using SAP2000v1; +using BH.oM.Structure.Elements; namespace BH.Adapter.SAP2000 @@ -49,7 +50,7 @@ public IEnumerable ReadResults(SteelUtilisationRequest request, ActionConfig actionConfig = null) { CheckAndSetUpCases(request); - List barIds = CheckGetBarIds(request); + List barIds = CheckAndGetIds(request); switch (request.Code) { diff --git a/SAP2000_Adapter/CRUD/Read/RigidLink.cs b/SAP2000_Adapter/CRUD/Read/RigidLink.cs index a48ccc48..98bab654 100644 --- a/SAP2000_Adapter/CRUD/Read/RigidLink.cs +++ b/SAP2000_Adapter/CRUD/Read/RigidLink.cs @@ -39,81 +39,126 @@ public partial class SAP2000Adapter private List ReadRigidLink(List ids = null) { List linkList = new List(); - Dictionary bhomNodes = ReadNodes().ToDictionary(x => GetAdapterId(x)); - Dictionary bhomLinkConstraints = ReadLinkConstraints().ToDictionary(x => GetAdapterId(x)); - - //Read all links, filter by id at end, so that we can join multi-links. int nameCount = 0; - string[] nameArr = { }; - m_model.LinkObj.GetNameList(ref nameCount, ref nameArr); + string[] names = { }; + m_model.LinkObj.GetNameList(ref nameCount, ref names); + + ids = FilterIds(ids, names); + + //read primary-multiSecondary nodes if these were initially created from (non-etabs)BHoM side + Dictionary> idDict = new Dictionary>(); + string[] primarySecondaryId; + foreach (string id in ids) + { + primarySecondaryId = id.Split(new[] { ":::" }, StringSplitOptions.None); + if (primarySecondaryId.Count() > 1) + { + //has plural secondaries + if (idDict.ContainsKey(primarySecondaryId[0])) + idDict[primarySecondaryId[0]].Add(primarySecondaryId[1]); + else + idDict.Add(primarySecondaryId[0], new List() { primarySecondaryId[1] }); + } + else + { + //normal single link + idDict.Add(id, null); + } + } - foreach (string id in nameArr) + foreach (KeyValuePair> kvp in idDict) { - RigidLink newLink = new RigidLink(); - SAP2000Id sap2000id = new SAP2000Id(); - string guid = null; + string bhomName = GetBhomNameFromSAP2000Id(kvp.Key); + + RigidLink bhLink = new RigidLink() { Name = bhomName }; - sap2000id.Id = id; + SetAdapterId(bhLink, kvp.Key); - try + if (kvp.Value == null) { - string primaryId = ""; - string secondaryId = ""; - string propName = ""; - m_model.LinkObj.GetPoints(id, ref primaryId, ref secondaryId); - newLink.PrimaryNode = bhomNodes[primaryId]; - newLink.SecondaryNodes = new List { bhomNodes[secondaryId] }; - - if (m_model.LinkObj.GetProperty(id, ref propName) == 0) - { - LinkConstraint bhProp = new LinkConstraint(); - bhomLinkConstraints.TryGetValue(propName, out bhProp); - newLink.Constraint = bhProp; m_model.LinkObj.GetProperty(id, ref propName); - } - else - { - Engine.Base.Compute.RecordWarning("Could not get link property for RigidLink " + id + "."); - } - - // Get the groups the link is assigned to - int numGroups = 0; - string[] groupNames = new string[0]; - if (m_model.LinkObj.GetGroupAssign(id, ref numGroups, ref groupNames) == 0) + string startId = ""; + string endId = ""; + m_model.LinkObj.GetPoints(kvp.Key, ref startId, ref endId); + + //Dummy nodes with correct Id + bhLink.PrimaryNode = new Node { Name = startId }; + bhLink.SecondaryNodes = new List() { new Node { Name = endId } }; + } + else + { + string startId = ""; + string endId = ""; + string multiLinkId = kvp.Key + ":::0"; + + + m_model.LinkObj.GetPoints(multiLinkId, ref startId, ref endId); + bhLink.PrimaryNode = new Node { Name = startId }; //Dummy startnode with correct Id + + List endIds = new List(); + for (int i = 1; i < kvp.Value.Count(); i++) { - foreach (string grpName in groupNames) - newLink.Tags.Add(grpName); + multiLinkId = kvp.Key + ":::" + i; + m_model.LinkObj.GetPoints(multiLinkId, ref startId, ref endId); + endIds.Add(endId); } - if (m_model.LinkObj.GetGUID(id, ref guid) == 0) - sap2000id.PersistentId = guid; - - newLink.SetAdapterId(sap2000id); - linkList.Add(newLink); + bhLink.SecondaryNodes = endIds.Select(x => new Node { Name = x }).ToList(); //Dummy endnodes with correct Id } + string propName = ""; + m_model.LinkObj.GetProperty(kvp.Key, ref propName); - catch + 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) { - ReadElementError("RigidLink", id.ToString()); + foreach (string grpName in groupNames) + bhLink.Tags.Add(grpName); } + + linkList.Add(bhLink); } - Dictionary joinedLinks = BH.Engine.Adapters.SAP2000.Query.JoinRigidLink(linkList).ToDictionary(x => x.Name); + if (linkList.Count == 0) + return linkList; - ids = FilterIds(ids, joinedLinks.Keys); + //Get ids of primary and secondary nodes + List nodeIds = linkList.SelectMany(x => x.SecondaryNodes.Select(s => s.Name).Concat(new List { x.PrimaryNode.Name })).Distinct().ToList(); + Dictionary nodes = GetCachedOrReadAsDictionary(nodeIds); - if (ids != null) - { - return joinedLinks - .Where(x => ids.Contains(x.Key)) - .Select(x => x.Value).ToList(); - } - else + List contstrainIds = linkList.Select(x => x.Constraint.Name).Distinct().ToList(); + //Get cached or read out all constraints used by Links + Dictionary constraints = contstrainIds.Any() ? new Dictionary() : GetCachedOrReadAsDictionary(contstrainIds); + + foreach (RigidLink link in linkList) { - return joinedLinks.Values.ToList(); + LinkConstraint constraint; //Reasign cached/read contraint + if (constraints.TryGetValue(link.Constraint.Name, out constraint)) + link.Constraint = constraint; + + Node stNode; + if (nodes.TryGetValue(link.PrimaryNode.Name, out stNode)) + link.PrimaryNode = stNode; + + for (int i = 0; i < link.SecondaryNodes.Count; i++) + { + Node secNode; + if (nodes.TryGetValue(link.SecondaryNodes[i].Name, out secNode)) + link.SecondaryNodes[i] = secNode; + } } + + + return linkList; } /***************************************************/ diff --git a/SAP2000_Adapter/CRUD/Read/_IRead.cs b/SAP2000_Adapter/CRUD/Read/_IRead.cs index edb073c4..fbb39b48 100644 --- a/SAP2000_Adapter/CRUD/Read/_IRead.cs +++ b/SAP2000_Adapter/CRUD/Read/_IRead.cs @@ -63,6 +63,8 @@ protected override IEnumerable IRead(Type type, IList ids, ActionCo return ReadMaterial(listIds); else if (type == typeof(Panel)) return ReadPanel(listIds); + else if (type == typeof(FEMesh)) + return ReadMesh(listIds); else if (type == typeof(ISurfaceProperty) || type.GetInterfaces().Contains(typeof(ISurfaceProperty))) return ReadSurfaceProperty(listIds); else if (type == typeof(LoadCombination)) @@ -166,6 +168,19 @@ private static List FilterIds(IEnumerable ids, IEnumerable bhBars) // Set Properties SetObject(bhBar); + UpdateUniqueName(bhBar); } return success; diff --git a/SAP2000_Adapter/CRUD/Update/Node.cs b/SAP2000_Adapter/CRUD/Update/Node.cs index 3f3dcb11..7c519485 100644 --- a/SAP2000_Adapter/CRUD/Update/Node.cs +++ b/SAP2000_Adapter/CRUD/Update/Node.cs @@ -40,9 +40,13 @@ private bool UpdateObjects(IEnumerable nodes) foreach (Node bhNode in nodes) { + // Update the node object and its unique name + SetObject(bhNode); + UpdateUniqueName(bhNode); + + // Retrieve node's updated unique name string name = GetAdapterId(bhNode); - SetObject(bhNode); double x = 0; double y = 0; diff --git a/SAP2000_Adapter/CRUD/Update/Panel.cs b/SAP2000_Adapter/CRUD/Update/Panel.cs new file mode 100644 index 00000000..94687882 --- /dev/null +++ b/SAP2000_Adapter/CRUD/Update/Panel.cs @@ -0,0 +1,91 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2026, 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 BH.Engine.Adapter; +using BH.Engine.Structure; +using BH.oM.Adapter; +using BH.oM.Adapters.SAP2000; +using BH.oM.Architecture.Theatron; +using BH.oM.Geometry; +using BH.oM.Structure.Elements; +using CSiAPIv1; +using System.Collections.Generic; +using System.Linq; + +namespace BH.Adapter.SAP2000 +{ + public partial class SAP2000Adapter : BHoMAdapter + { + /***************************************************/ + /**** Update Panel ****/ + /***************************************************/ + + private bool UpdateObjects(IEnumerable bhPanels) + { + //Make sure Diaphragms are pushed + //List diaphragms = bhPanels.Select(x => x.Diaphragm()).Where(x => x != null).ToList(); + //this.FullCRUD(diaphragms, PushType.FullPush); + + bool success = true; + m_model.SelectObj.ClearSelection(); + + foreach (Panel bhPanel in bhPanels) + { + string name = GetAdapterId(bhPanel); + string propertyName = GetAdapterId(bhPanel.Property); + + Engine.Base.Compute.RecordWarning("The SAP2000 API does not allow for updating of the geometry of panels. This includes the external edges as well as the openings. To update the panel geometry, delete the existing panel you want to update and create a new one."); + + m_model.AreaObj.SetProperty(name, propertyName); + + //Set local orientations: + Basis orientation = bhPanel.LocalOrientation(); + //m_model.AreaObj.SetLocalAxes(name, Convert.ToEtabsPanelOrientation(orientation.Z, orientation.Y)); + + //Diaphragm diaphragm = bhPanel.Diaphragm(); + + //if (diaphragm != null) + //{ + // m_model.AreaObj.SetDiaphragm(name, diaphragm.Name); + //} + + //Update Unique Name + UpdateUniqueName(bhPanel); + + //Update Groups Assignment + //if (!UpdateGroup(bhPanel)) success = false; + + } + + //Force refresh to make sure panel local orientation are set correctly + ForceRefresh(); + + return success; + } + + /***************************************************/ + } +} + + + + diff --git a/SAP2000_Adapter/CRUD/Update/_IUpdate.cs b/SAP2000_Adapter/CRUD/Update/_IUpdate.cs index 03b48b1f..f2389606 100644 --- a/SAP2000_Adapter/CRUD/Update/_IUpdate.cs +++ b/SAP2000_Adapter/CRUD/Update/_IUpdate.cs @@ -20,12 +20,14 @@ * along with this code. If not, see . */ +using BH.Engine.Adapter; using BH.oM.Adapter; -using BH.oM.Base; -using System.Collections.Generic; using BH.oM.Adapters.SAP2000; +using BH.oM.Base; using BH.oM.Structure.Elements; using BH.oM.Structure.SectionProperties; +using System.Collections.Generic; +using System.ComponentModel; using System.Linq; namespace BH.Adapter.SAP2000 @@ -58,6 +60,47 @@ private bool UpdateObjects(IEnumerable objects) } /***************************************************/ + + [Description("Concatenates the last 7 characters of the SAP2000 Element GUID and the Node Name to get the Unique Name to assign to the SAP2000 Element.")] + private bool UpdateUniqueName(BHoMObject obj) + { + int ret01 = 1; + int ret02 = 1; + string guid = null; + string tempObjName = ""; + + /* 1. GET THE SAP2000 ELEMENT GUID */ + string uniqueName = GetAdapterId(obj); + + if (obj.GetType() == typeof(Node)) ret01 = m_model.PointObj.GetGUID(uniqueName, ref guid); + if (obj.GetType() == typeof(Bar)) ret01 = m_model.FrameObj.GetGUID(uniqueName, ref guid); + if (obj.GetType() == typeof(Panel) || obj.GetType() == typeof(Opening)) ret01 = m_model.AreaObj.GetGUID(uniqueName, ref guid); + + /* 2. CREATE THE NEW UNIQUE NAME */ + if (obj.Name == "" || obj.Name == guid.Substring(guid.Length - 7)) + { + tempObjName = guid.Substring(guid.Length - 7); + } + else + { + tempObjName = obj.Name + "::" + guid.Substring(guid.Length - 7); + } + + /* 3. ASSIGN THE NEW UNIQUE NAME TO THE SAP2000 ELEMENT */ + if (obj.GetType() == typeof(Node)) ret02 = m_model.PointObj.ChangeName(uniqueName, tempObjName); + if (obj.GetType() == typeof(Bar)) ret02 = m_model.FrameObj.ChangeName(uniqueName, tempObjName); + if (obj.GetType() == typeof(Panel) || obj.GetType() == typeof(Opening)) ret02 = m_model.AreaObj.ChangeName(uniqueName, tempObjName); + + if (!(ret01 == 0 && ret02 == 0)) return false; + + SAP2000Id SAP2000IdFragment = new SAP2000Id { Id = tempObjName }; + + obj.SetAdapterId(SAP2000IdFragment); + + return true; + } + + /***************************************************/ } } diff --git a/SAP2000_oM/Properties/AssemblyInfo.cs b/SAP2000_Adapter/Convert/ToBHoM/Panel.cs similarity index 51% rename from SAP2000_oM/Properties/AssemblyInfo.cs rename to SAP2000_Adapter/Convert/ToBHoM/Panel.cs index 9cdd1114..609a473c 100644 --- a/SAP2000_oM/Properties/AssemblyInfo.cs +++ b/SAP2000_Adapter/Convert/ToBHoM/Panel.cs @@ -1,61 +1,70 @@ -/* - * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2026, 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.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("SAP2000_oM")] -[assembly: AssemblyDescription("https://github.com/BHoM/SAP2000_Toolkit")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Buro Happold")] -[assembly: AssemblyProduct("SAP2000_oM")] -[assembly: AssemblyCopyright("Copyright © https://github.com/BHoM")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("bc975b64-e35e-4155-a067-7a88505e61c2")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("9.0.0.0")] -[assembly: AssemblyFileVersion("9.2.0.0")] - - - - - - +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2026, 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 BH.Engine; +using BH.Engine.Geometry; +using BH.Engine.Units; +using BH.oM.Geometry; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BH.Adapter.SAP2000 +{ + public static partial class Convert + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + public static Vector ToPanelLocalXAxis(Vector normal, double orientationAngle) + { + Vector locYref; + + if (BH.Engine.Geometry.Query.IsParallel(normal, Vector.ZAxis)!=0) + { + //Vector is paralell to z-axis + locYref = Vector.YAxis; + } + else + { + //Vector is not paralell to z-axis + locYref = Vector.ZAxis.Project(new Plane { Normal = normal }); + } + + Vector localXref = locYref.CrossProduct(normal); + + return localXref.Rotate(Engine.Units.Convert.FromDegree(orientationAngle), normal); + } + + /***************************************************/ + + } +} + + + + + + diff --git a/SAP2000_Adapter/Properties/AssemblyInfo.cs b/SAP2000_Adapter/Properties/AssemblyInfo.cs deleted file mode 100644 index 2b0d4c88..00000000 --- a/SAP2000_Adapter/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2026, 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.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SAP2000_Adapter")] -[assembly: AssemblyDescription("https://github.com/BHoM/SAP2000_Toolkit")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Buro Happold")] -[assembly: AssemblyProduct("SAP2000_Adapter")] -[assembly: AssemblyCopyright("Copyright © https://github.com/BHoM")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("04e7e3bc-bd2f-47a4-b4f0-a9675f702ced")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("9.0.0.0")] -[assembly: AssemblyFileVersion("9.2.0.0")] - - - - - - diff --git a/SAP2000_Adapter/SAP2000Adapter.cs b/SAP2000_Adapter/SAP2000Adapter.cs index 5ab97c11..6899c18a 100644 --- a/SAP2000_Adapter/SAP2000Adapter.cs +++ b/SAP2000_Adapter/SAP2000Adapter.cs @@ -57,12 +57,6 @@ public SAP2000Adapter(string filePath = "", bool active = false) if (active) { - if(Environment.Version.Major > 4) - { - Engine.Base.Compute.RecordError($"The SAP2000Adapter is currently not support in NET runtimes above .NETFramework due to internal errors in the SAP2000 API. A fix for this is being worked on. \n" + - $"If you are running this adapter from Grasshopper in Rhino 8, you can change the runtime being used by Rhino to .NETFramework. To do this please follow the instructions here: https://www.rhino3d.com/en/docs/guides/netcore/"); - } - string progId = "CSI.SAP2000.API.SapObject"; cHelper helper = new Helper(); @@ -167,6 +161,16 @@ public SAP2000Adapter(string filePath = "", bool active = false) private cSapModel m_model; /***************************************************/ + /**** Private Methods ****/ + /***************************************************/ + + private bool ForceRefresh() + { + int ret0, ret1; + ret0 = m_model.View.RefreshView(0,false); + ret1 = m_model.View.RefreshWindow(0); + return (ret0==1 && ret1==1); + } } } diff --git a/SAP2000_Adapter/SAP2000_Adapter.csproj b/SAP2000_Adapter/SAP2000_Adapter.csproj index 84c83f84..f414aef0 100644 --- a/SAP2000_Adapter/SAP2000_Adapter.csproj +++ b/SAP2000_Adapter/SAP2000_Adapter.csproj @@ -1,269 +1,174 @@ - - - + - Debug - AnyCPU - {04E7E3BC-BD2F-47A4-B4F0-A9675F702CED} +net472 Library - Properties BH.Adapter.SAP2000 - SAP2000_Adapter - v4.7.2 - 512 - - - - true - full - false - ..\Build\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true ..\Build\ - TRACE - prompt - 4 + SAP2000_Adapter + https://github.com/BHoM/SAP2000_Toolkit + Buro Happold + SAP2000_Adapter + Copyright � https://github.com/BHoM + 9.0.0.0 + 9.3.0.0 + + + - C:\ProgramData\BHoM\Assemblies\Acoustic_oM.dll + $(ProgramData)\BHoM\Assemblies\Acoustic_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Adapter_Engine.dll + $(ProgramData)\BHoM\Assemblies\Adapter_Engine.dll False False - C:\ProgramData\BHoM\Assemblies\Adapter_oM.dll + $(ProgramData)\BHoM\Assemblies\Adapter_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Analytical_oM.dll + $(ProgramData)\BHoM\Assemblies\Analytical_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Architecture_oM.dll + $(ProgramData)\BHoM\Assemblies\Architecture_oM.dll False False - C:\ProgramData\BHoM\Assemblies\BHoM.dll + $(ProgramData)\BHoM\Assemblies\BHoM.dll False False - C:\ProgramData\BHoM\Assemblies\BHoM_Adapter.dll + $(ProgramData)\BHoM\Assemblies\BHoM_Adapter.dll False False - C:\ProgramData\BHoM\Assemblies\BHoM_Engine.dll + $(ProgramData)\BHoM\Assemblies\BHoM_Engine.dll False False + + ..\libs\v26\CSiAPIv1.dll + False + - C:\ProgramData\BHoM\Assemblies\Data_oM.dll + $(ProgramData)\BHoM\Assemblies\Data_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Dimensional_oM.dll + $(ProgramData)\BHoM\Assemblies\Dimensional_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Environment_oM.dll + $(ProgramData)\BHoM\Assemblies\Environment_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Geometry_Engine.dll + $(ProgramData)\BHoM\Assemblies\Geometry_Engine.dll False False - C:\ProgramData\BHoM\Assemblies\Geometry_oM.dll + $(ProgramData)\BHoM\Assemblies\Geometry_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Graphics_oM.dll + $(ProgramData)\BHoM\Assemblies\Graphics_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Humans_oM.dll + $(ProgramData)\BHoM\Assemblies\Humans_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Library_Engine.dll + $(ProgramData)\BHoM\Assemblies\Library_Engine.dll False False - C:\ProgramData\BHoM\Assemblies\Physical_Engine.dll + $(ProgramData)\BHoM\Assemblies\Physical_Engine.dll False False - C:\ProgramData\BHoM\Assemblies\Physical_oM.dll + $(ProgramData)\BHoM\Assemblies\Physical_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Planning_oM.dll + $(ProgramData)\BHoM\Assemblies\Planning_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Quantities_oM.dll + $(ProgramData)\BHoM\Assemblies\Quantities_oM.dll False - False + False - C:\ProgramData\BHoM\Assemblies\Results_Engine.dll + $(ProgramData)\BHoM\Assemblies\Results_Engine.dll False False - - ..\packages\BHoM.Interop.SAP2000v21.1.0.0\lib\net47\SAP2000v1.dll + + ..\libs\v26\SAP2000v1.dll + False - C:\ProgramData\BHoM\Assemblies\Serialiser_Engine.dll + $(ProgramData)\BHoM\Assemblies\Serialiser_Engine.dll False False - C:\ProgramData\BHoM\Assemblies\Spatial_Engine.dll + $(ProgramData)\BHoM\Assemblies\Spatial_Engine.dll False False - C:\ProgramData\BHoM\Assemblies\Spatial_oM.dll + $(ProgramData)\BHoM\Assemblies\Spatial_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Structure_AdapterModules.dll + $(ProgramData)\BHoM\Assemblies\Structure_AdapterModules.dll False False - C:\ProgramData\BHoM\Assemblies\Structure_Engine.dll + $(ProgramData)\BHoM\Assemblies\Structure_Engine.dll False False - C:\ProgramData\BHoM\Assemblies\Structure_oM.dll + $(ProgramData)\BHoM\Assemblies\Structure_oM.dll False False - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + $(ProgramData)\BHoM\Assemblies\Units_Engine.dll + False + False + + + - - {4bb31ae9-b7ce-42c8-80a4-484389d23de2} - SAP2000_Engine - False - - - {bc975b64-e35e-4155-a067-7a88505e61c2} - SAP2000_oM - False - + + - - - - xcopy "$(TargetDir)$(TargetFileName)" "C:\ProgramData\BHoM\Assemblies" /Y - xcopy "$(TargetDir)SAP2000v1.dll" "C:\ProgramData\BHoM\Assemblies" /Y - - - - \ No newline at end of file + diff --git a/SAP2000_Adapter/packages.config b/SAP2000_Adapter/packages.config deleted file mode 100644 index d337e302..00000000 --- a/SAP2000_Adapter/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/SAP2000_Engine/Properties/AssemblyInfo.cs b/SAP2000_Engine/Properties/AssemblyInfo.cs deleted file mode 100644 index 4a137dae..00000000 --- a/SAP2000_Engine/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of the Buildings and Habitats object Model (BHoM) - * Copyright (c) 2015 - 2026, 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.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("SAP2000_Engine")] -[assembly: AssemblyDescription("https://github.com/BHoM/SAP2000_Toolkit")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Buro Happold")] -[assembly: AssemblyProduct("SAP2000_Engine")] -[assembly: AssemblyCopyright("Copyright © https://github.com/BHoM")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("4bb31ae9-b7ce-42c8-80a4-484389d23de2")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("9.0.0.0")] -[assembly: AssemblyFileVersion("9.2.0.0")] - - - - - - diff --git a/SAP2000_Engine/SAP2000_Engine.csproj b/SAP2000_Engine/SAP2000_Engine.csproj index cdf2bb73..cff2306d 100644 --- a/SAP2000_Engine/SAP2000_Engine.csproj +++ b/SAP2000_Engine/SAP2000_Engine.csproj @@ -1,35 +1,20 @@ - - - + - Debug - AnyCPU - {4BB31AE9-B7CE-42C8-80A4-484389D23DE2} +net472 Library - Properties BH.Engine.Adapters.SAP2000 - SAP2000_Engine - v4.7.2 - 512 - - - - true - full - false - ..\Build\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true ..\Build\ - TRACE - prompt - 4 + SAP2000_Engine + https://github.com/BHoM/SAP2000_Toolkit + Buro Happold + SAP2000_Engine + Copyright © https://github.com/BHoM + 9.0.0.0 + 9.3.0.0 + + + $(ProgramData)\BHoM\Assemblies\Acoustic_oM.dll @@ -131,48 +116,13 @@ False False - - - - - - - - - - - - - - - - - + + - + - - - {bc975b64-e35e-4155-a067-7a88505e61c2} - SAP2000_oM - False - - - - - -xcopy "$(TargetDir)$(TargetFileName)" "C:\ProgramData\BHoM\Assemblies" /Y - - - diff --git a/SAP2000_Engine/packages.config b/SAP2000_Engine/packages.config deleted file mode 100644 index c1639134..00000000 --- a/SAP2000_Engine/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/SAP2000_Toolkit.sln b/SAP2000_Toolkit.sln index d0a596c5..0af8353e 100644 --- a/SAP2000_Toolkit.sln +++ b/SAP2000_Toolkit.sln @@ -1,16 +1,16 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30225.117 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SAP2000_Adapter", "SAP2000_Adapter\SAP2000_Adapter.csproj", "{04E7E3BC-BD2F-47A4-B4F0-A9675F702CED}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SAP2000_Adapter", "SAP2000_Adapter\SAP2000_Adapter.csproj", "{04E7E3BC-BD2F-47A4-B4F0-A9675F702CED}" ProjectSection(ProjectDependencies) = postProject {4BB31AE9-B7CE-42C8-80A4-484389D23DE2} = {4BB31AE9-B7CE-42C8-80A4-484389D23DE2} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SAP2000_Engine", "SAP2000_Engine\SAP2000_Engine.csproj", "{4BB31AE9-B7CE-42C8-80A4-484389D23DE2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SAP2000_Engine", "SAP2000_Engine\SAP2000_Engine.csproj", "{4BB31AE9-B7CE-42C8-80A4-484389D23DE2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SAP2000_oM", "SAP2000_oM\SAP2000_oM.csproj", "{BC975B64-E35E-4155-A067-7A88505E61C2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SAP2000_oM", "SAP2000_oM\SAP2000_oM.csproj", "{BC975B64-E35E-4155-A067-7A88505E61C2}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/SAP2000_oM/SAP2000_oM.csproj b/SAP2000_oM/SAP2000_oM.csproj index ad5b784f..44b68243 100644 --- a/SAP2000_oM/SAP2000_oM.csproj +++ b/SAP2000_oM/SAP2000_oM.csproj @@ -1,100 +1,51 @@ - - - + - Debug - AnyCPU - {BC975B64-E35E-4155-A067-7A88505E61C2} +net472 Library - Properties BH.oM.Adapters.SAP2000 - SAP2000_oM - v4.7.2 - 512 - - - - true - full - false - ..\Build\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true ..\Build\ - TRACE - prompt - 4 + SAP2000_oM + https://github.com/BHoM/SAP2000_Toolkit + Buro Happold + SAP2000_oM + Copyright © https://github.com/BHoM + 9.0.0.0 + 9.3.0.0 + + + - C:\ProgramData\BHoM\Assemblies\Adapter_oM.dll + $(ProgramData)\BHoM\Assemblies\Adapter_oM.dll False False - C:\ProgramData\BHoM\Assemblies\BHoM.dll + $(ProgramData)\BHoM\Assemblies\BHoM.dll False False - C:\ProgramData\BHoM\Assemblies\Data_oM.dll + $(ProgramData)\BHoM\Assemblies\Data_oM.dll False False - C:\ProgramData\BHoM\Assemblies\Quantities_oM.dll + $(ProgramData)\BHoM\Assemblies\Quantities_oM.dll False False + + ..\libs\v26\SAP2000v1.dll + True + - C:\ProgramData\BHoM\Assemblies\Structure_oM.dll + $(ProgramData)\BHoM\Assemblies\Structure_oM.dll False False - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -xcopy "$(TargetDir)$(TargetFileName)" "C:\ProgramData\BHoM\Assemblies" /Y - - - \ No newline at end of file + diff --git a/dependencies.txt b/dependencies.txt index c859174b..f9af9c0d 100644 --- a/dependencies.txt +++ b/dependencies.txt @@ -1,3 +1,4 @@ BHoM/BHoM BHoM/BHoM_Engine -BHoM/BHoM_Adapter \ No newline at end of file +BHoM/BHoM_Adapter +BHoM/Localisation_Toolkit \ No newline at end of file diff --git a/libs/v26/CSiAPIv1.dll b/libs/v26/CSiAPIv1.dll new file mode 100644 index 00000000..70657150 Binary files /dev/null and b/libs/v26/CSiAPIv1.dll differ diff --git a/libs/v26/SAP2000v1.dll b/libs/v26/SAP2000v1.dll new file mode 100644 index 00000000..28252ab3 Binary files /dev/null and b/libs/v26/SAP2000v1.dll differ