From 2db92e91308ff6fb35b32ae3247abe5c2695de4b Mon Sep 17 00:00:00 2001 From: Toste Skanberg Dahlstedt Date: Thu, 6 Jul 2023 09:31:47 +0100 Subject: [PATCH] Redefined how GSA_RigidConstraints are treated, now a part of Structures_RigidLinks. Rigid Constraints are now treated by BHoM as a Rigid Link object but with a fragment that if true tells GSA it is a Rigid Constraints. Removed previously added RigidConstraint Type and ENUM from this PR and instead adjusted the RigidLink methods. Also added more possible LinkConstraint options to the FromGsa - LinkConstraint method. --- GSA_Adapter/CRUD/Create.cs | 48 +++--- GSA_Adapter/CRUD/Read.cs | 19 +-- .../Convert/FromGsa/Elements/RigidLink.cs | 148 +++++++++++++++++- .../Convert/FromGsa/Loads/BarPrestressLoad.cs | 121 ++++++++++++++ .../FromGsa/Properties/LinkConstraint.cs | 36 ++--- .../Convert/ToGsa/Elements/RigidLink.cs | 108 +++++++++++-- GSA_Adapter/GSAAdapter.cs | 1 - GSA_Adapter/GSA_Adapter.csproj | 2 - GSA_oM/Fragments/GSARigidConstraint.cs | 37 +++++ GSA_oM/GSA_oM.csproj | 3 +- 10 files changed, 452 insertions(+), 71 deletions(-) create mode 100644 GSA_Adapter/Convert/FromGsa/Loads/BarPrestressLoad.cs create mode 100644 GSA_oM/Fragments/GSARigidConstraint.cs diff --git a/GSA_Adapter/CRUD/Create.cs b/GSA_Adapter/CRUD/Create.cs index 5ed01f96..f5061654 100644 --- a/GSA_Adapter/CRUD/Create.cs +++ b/GSA_Adapter/CRUD/Create.cs @@ -160,32 +160,46 @@ private bool CreateObject(ISectionProperty prop) // private bool CreateLinks(IEnumerable links) { - bool success = true; - foreach (RigidLink link in links) - { - success &= ComCall(Convert.ToGsaString(link, GetAdapterId(link).ToString(), 0)); - } foreach (RigidLink link in links) { - List allIds = new List(); - for (int i = 1; i < link.SecondaryNodes.Count; i++) + if (Convert.CheckRigCon(link) == false) { - int id = (int)NextFreeId(link.GetType(), i == 1); - success &= ComCall(Convert.ToGsaString(link, id.ToString(), i)); - allIds.Add(id); + if (link.SecondaryNodes.Count > 1) + { + List secondaryIds = new List(); + foreach (Node secondaryNode in link.SecondaryNodes) + { + int id = (int)NextFreeId(link.GetType(), false); + success &= ComCall(Convert.ToGsaString(link, id.ToString())); + secondaryIds.Add(id); + } + + var allIds = new List { GetAdapterId(link) }; + allIds.AddRange(secondaryIds); + link.Fragments.Remove(typeof(GSAId)); + link.SetAdapterId(typeof(GSAId), allIds); + } + else + { + int id = (int)NextFreeId(link.GetType(), false); + success &= ComCall(Convert.ToGsaString(link, id.ToString())); + link.Fragments.Remove(typeof(GSAId)); + link.SetAdapterId(typeof(GSAId), id); + } } - if (link.SecondaryNodes.Count > 1) + else { - allIds.Insert(0, GetAdapterId(link)); - link.Fragments.Remove(typeof(GSAId)); // to remove the existing single id on the link - link.SetAdapterId(typeof(GSAId), allIds); + success &= ComCall(Convert.ToGsaString(link, GetAdapterId(link).ToString())); } } + return success; } + + /***************************************************/ private bool CreateFEMesh(FEMesh mesh) @@ -280,12 +294,6 @@ private bool CreateObject(FabricPanelProperty fabricProperty) /***************************************************/ - private bool CreateObject(RigidConstraint rigidConstraint) - { - return ComCall(rigidConstraint.ToGsaString()); - } - - /***************************************************/ } } diff --git a/GSA_Adapter/CRUD/Read.cs b/GSA_Adapter/CRUD/Read.cs index a9f2963a..5675dc52 100644 --- a/GSA_Adapter/CRUD/Read.cs +++ b/GSA_Adapter/CRUD/Read.cs @@ -79,8 +79,6 @@ protected override IEnumerable IRead(Type type, IList indices, Acti return ReadRigidLink(indices as dynamic); if (type == typeof(LinkConstraint)) return ReadLinkConstraint(indices as dynamic); - if (type == typeof(RigidConstraint)) - return ReadRigidConstraint(indices as dynamic); if (type == typeof(FEMesh)) return ReadFEMesh(indices as dynamic); if (type == typeof(ISurfaceProperty)) @@ -374,11 +372,14 @@ public List ReadRigidLink(List ids = null) Dictionary constraints = GetCachedOrReadAsDictionary(); Dictionary nodes = GetCachedOrReadAsDictionary(); + string allConstr = m_gsaCom.GwaCommand("GET_ALL, RIGID").ToString(); + string[] constrArr = string.IsNullOrWhiteSpace(allConstr) ? new string[0] : allConstr.Split('\n'); + int[] potentialBeamRefs = GenerateIndices(ids, typeof(RigidLink)); GsaElement[] gsaElements = new GsaElement[potentialBeamRefs.Length]; m_gsaCom.Elements(potentialBeamRefs, out gsaElements); - return Convert.FromGsaRigidLinks(gsaElements, constraints, nodes); + return Convert.FromGsaRigidLinks(gsaElements, constrArr, constraints, nodes); //if (ids == null) // return proArr.Select(x => Convert.FromGsaSectionProperty(x, materials)).ToList(); @@ -388,18 +389,6 @@ public List ReadRigidLink(List ids = null) /***************************************/ - public List ReadRigidConstraint(List ids = null) - { - string allProps = m_gsaCom.GwaCommand("GET_ALL, RIGID").ToString(); - string[] proArr = string.IsNullOrWhiteSpace(allProps) ? new string[0] : allProps.Split('\n'); - - Dictionary nodes = GetCachedOrReadAsDictionary(); - - return Convert.FromGsaRigidConstraint(proArr, nodes); - } - - /***************************************/ - public List ReadSpacers(List ids = null) { Dictionary nodes = GetCachedOrReadAsDictionary(); diff --git a/GSA_Adapter/Convert/FromGsa/Elements/RigidLink.cs b/GSA_Adapter/Convert/FromGsa/Elements/RigidLink.cs index 473afd01..fe8e2327 100644 --- a/GSA_Adapter/Convert/FromGsa/Elements/RigidLink.cs +++ b/GSA_Adapter/Convert/FromGsa/Elements/RigidLink.cs @@ -31,7 +31,7 @@ using BH.oM.Structure.Elements; using BH.oM.Structure.Constraints; using System.Collections.Generic; - +using System.Linq; namespace BH.Adapter.GSA { @@ -41,10 +41,12 @@ public static partial class Convert /**** Public Methods ****/ /***************************************************/ - public static List FromGsaRigidLinks(IEnumerable gsaElements, Dictionary constraints, Dictionary nodes) + public static List FromGsaRigidLinks(IEnumerable gsaElements, IEnumerable gsaStrings, Dictionary constraints, Dictionary nodes) { + List linkList = new List(); + //Rigid Link foreach (GsaElement gsaLink in gsaElements) { if (gsaLink.eType != 9) @@ -61,8 +63,150 @@ public static List FromGsaRigidLinks(IEnumerable gsaEleme int id = gsaLink.Ref; link.SetAdapterId(typeof(GSAId), id); linkList.Add(link); + } + + //Rigid Constraint + foreach (string gsaString in gsaStrings) + { + string[] tokens = gsaString.Split(','); + + string linkName = tokens[1]; + int primaryNodeName = int.Parse(tokens[2]); + string linkTypeString = tokens[3]; + string[] constrainedNodeNames = tokens[4].Split(','); + + Node primaryNode; + nodes.TryGetValue(primaryNodeName, out primaryNode); + + List constrainedNodes = new List(); + + foreach (string constrainedNodeName in constrainedNodeNames) + { + if (int.TryParse(constrainedNodeName, out int constrainedNodeId)) + { + if (nodes.TryGetValue(constrainedNodeId, out Node constrainedNode)) + constrainedNodes.Add(constrainedNode); + } + } + + LinkConstraint linkType; + + switch (linkTypeString) + { + case "ALL": + linkType = Engine.Structure.Create.LinkConstraintFixed(); + break; + case "PIN": + linkType = Engine.Structure.Create.LinkConstraintPinned(); + break; + case "XY_PLANE": + linkType = Engine.Structure.Create.LinkConstraintXYPlane(); + break; + case "ZX_PLANE": + linkType = Engine.Structure.Create.LinkConstraintZXPlane(); + break; + case "YZ_PLANE": + linkType = Engine.Structure.Create.LinkConstraintYZPlane(); + break; + case "XY_PLANE_PIN": + linkType = Engine.Structure.Create.LinkConstraintXYPlanePin(); + break; + case "ZX_PLANE_PIN": + linkType = Engine.Structure.Create.LinkConstraintZXPlanePin(); + break; + case "YZ_PLANE_PIN": + linkType = Engine.Structure.Create.LinkConstraintYZPlanePin(); + break; + case "XY_PLATE": + linkType = Engine.Structure.Create.LinkConstraintYPlateZPlate(); //Wrong name in engine. Should be just ZPlate. + break; + case "ZX_PLATE": + linkType = Engine.Structure.Create.LinkConstraintYPlate(); + break; + case "YZ_PLATE": + linkType = Engine.Structure.Create.LinkConstraintXPlate(); + break; + case "XY_PLATE_PIN": + linkType = Engine.Structure.Create.LinkConstraintZPlatePin(); + break; + case "ZX_PLATE_PIN": + linkType = Engine.Structure.Create.LinkConstraintYPlatePin(); + break; + case "YZ_PLATE_PIN": + linkType = Engine.Structure.Create.LinkConstraintXPlatePin(); + break; + default: + //String in format example: X:XYY-Y:YZZXX-Z:YY-XX:XX-YY:YY-ZZ:ZZ + linkType = new LinkConstraint(); + string[] constraintProps = linkTypeString.Split('-'); + foreach (string c in constraintProps) + { + string[] fromTo = c.Split(':'); + string from = fromTo[0]; + string to = fromTo[1]; + switch (from) + { + case "X": + if (to.Contains('X')) + linkType.XtoX = true; + if (to.Contains('Y')) + linkType.XtoYY = true; + if (to.Contains('Z')) + linkType.XtoZZ = true; + break; + case "Y": + if (to.Contains('X')) + linkType.YtoXX = true; + if (to.Contains('Y')) + linkType.YtoY = true; + if (to.Contains('Z')) + linkType.YtoZZ = true; + break; + case "Z": + if (to.Contains('X')) + linkType.ZtoXX = true; + if (to.Contains('Y')) + linkType.ZtoYY = true; + if (to.Contains('Z')) + linkType.ZtoZ = true; + break; + case "XX": + if (to.Contains("XX")) + linkType.XXtoXX = true; + break; + case "YY": + if (to.Contains("YY")) + linkType.YYtoYY = true; + break; + case "ZZ": + if (to.Contains("ZZ")) + linkType.ZZtoZZ = true; + break; + } + } + break; + } + + RigidLink link = new RigidLink() + { + PrimaryNode = primaryNode, + SecondaryNodes = constrainedNodes, + Constraint = linkType + }; + + link.ApplyTaggedName(linkName); + + GSARigidConstraint RCtag = new GSARigidConstraint + { + IsRigidConstraint = true + }; + + link.Fragments.Add(RCtag); + + linkList.Add(link); } + return linkList; } diff --git a/GSA_Adapter/Convert/FromGsa/Loads/BarPrestressLoad.cs b/GSA_Adapter/Convert/FromGsa/Loads/BarPrestressLoad.cs new file mode 100644 index 00000000..09cb24d8 --- /dev/null +++ b/GSA_Adapter/Convert/FromGsa/Loads/BarPrestressLoad.cs @@ -0,0 +1,121 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2023, 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.Loads; +using System; +using BH.Engine.Adapter; +using BH.oM.Adapters.GSA; +using System.Collections.Generic; +using BH.oM.Structure.Elements; +using BH.oM.Geometry; +using BH.oM.Base; +using System.Linq; + +namespace BH.Adapter.GSA +{ + public static partial class Convert + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + public static BarPrestressLoad FromGsaBarPrestressLoad(string gsaString, Dictionary lCases, Dictionary bars, double unitFactor) + { + if (string.IsNullOrWhiteSpace(gsaString)) + return null; + + //Example gsaString: "LOAD_BEAM_PRE,,beam list,load case no,force" + + string[] gStr = gsaString.Split(','); + + if (gStr.Length < 4) + return null; + + int lCaseNo = int.Parse(gStr[3]); + + Loadcase loadCase; + if (!lCases.TryGetValue(lCaseNo, out loadCase)) + { + loadCase = new Loadcase { Number = lCaseNo, Nature = LoadNature.Other }; + loadCase.SetAdapterId(typeof(GSAId), lCaseNo); + } + + string[] barNos = gStr[2].Split(' '); + string barNosClean = barNos[0]; + for (int i = 1; i < barNos.Length; i++) + { + string addNo = barNos[i]; + if(barNos[i] == "to") + { + addNo = ""; + int range = int.Parse(barNos[i + 1]) - int.Parse(barNos[i - 1]); + for (int j = 1; j < range; j++) + { + int number = int.Parse(barNos[i - 1]) + j; + addNo = addNo + " " + number.ToString(); + } + } + + barNosClean = barNosClean + " " + addNo; + } + + string[] barNosCleanArray = barNosClean.Split(' '); + + BHoMGroup barGroup = new BHoMGroup(); + + for (int i = 0; i < barNosCleanArray.Length; i++) + { + string cleanStr = barNosCleanArray[i].Replace(" ", ""); + if (!string.IsNullOrEmpty(cleanStr)) + { + Bar bar; + if (!bars.TryGetValue(int.Parse(cleanStr), out bar)) + { + bar = new Bar(); + bar.SetAdapterId(typeof(GSAId), int.Parse(cleanStr)); + } + barGroup.Elements.Add(bar); + } + } + + double prestressForce = double.Parse(gStr[4]) / unitFactor; + + LoadAxis axis = LoadAxis.Global; + if (gStr[4] == "LOCAL") + axis = LoadAxis.Local; + + BarPrestressLoad barPrestressLoad = new BarPrestressLoad + { + Prestress = prestressForce, + Loadcase = loadCase, + Objects = barGroup, + Axis = axis, + Projected = false + }; + + return barPrestressLoad; + } + } +} + + diff --git a/GSA_Adapter/Convert/FromGsa/Properties/LinkConstraint.cs b/GSA_Adapter/Convert/FromGsa/Properties/LinkConstraint.cs index b0fa03fa..70d4bd28 100644 --- a/GSA_Adapter/Convert/FromGsa/Properties/LinkConstraint.cs +++ b/GSA_Adapter/Convert/FromGsa/Properties/LinkConstraint.cs @@ -68,24 +68,24 @@ public static LinkConstraint FromGsaLinkConstraint(string gsaProp) case "YZ_PLANE_PIN": constraint = Engine.Structure.Create.LinkConstraintYZPlanePin(); break; - //case "XY_PLATE": - // constraint = BHP.LinkConstraint.ZPlate; - // break; - //case "ZX_PLATE": - // constraint = BHP.LinkConstraint.YPlate; - // break; - //case "YZ_PLATE": - // constraint = BHP.LinkConstraint.YPlate; - // break; //TODO: CHECK CONSTRUCTOR NAMES IN BHOM_ENGINE - //case "XY_PLATE_PIN": - // constraint = BHP.LinkConstraint.ZPlatePin; - // break; - //case "ZX_PLATE_PIN": - // constraint = BHP.LinkConstraint.YPlatePin; - // break; - //case "YZ_PLATE_PIN": - // constraint = BHP.LinkConstraint.ZPlatePin; - // break; + case "XY_PLATE": + constraint = Engine.Structure.Create.LinkConstraintYPlateZPlate(); //TODO: Wrong name in engine. Should be just ZPlate. + break; + case "ZX_PLATE": + constraint = Engine.Structure.Create.LinkConstraintYPlate(); + break; + case "YZ_PLATE": + constraint = Engine.Structure.Create.LinkConstraintXPlate(); + break; + case "XY_PLATE_PIN": + constraint = Engine.Structure.Create.LinkConstraintZPlatePin(); + break; + case "ZX_PLATE_PIN": + constraint = Engine.Structure.Create.LinkConstraintYPlatePin(); + break; + case "YZ_PLATE_PIN": + constraint = Engine.Structure.Create.LinkConstraintXPlatePin(); + break; default: //String in format example: X:XYY-Y:YZZXX-Z:YY-XX:XX-YY:YY-ZZ:ZZ constraint = new LinkConstraint(); diff --git a/GSA_Adapter/Convert/ToGsa/Elements/RigidLink.cs b/GSA_Adapter/Convert/ToGsa/Elements/RigidLink.cs index c9bc1a2f..a8ba923a 100644 --- a/GSA_Adapter/Convert/ToGsa/Elements/RigidLink.cs +++ b/GSA_Adapter/Convert/ToGsa/Elements/RigidLink.cs @@ -25,6 +25,9 @@ using BH.oM.Adapters.GSA; using BH.oM.Structure.Elements; using BH.Engine.Adapters.GSA; +using BH.oM.Base; +using BH.Engine.Base; +using System.Collections.Generic; namespace BH.Adapter.GSA { @@ -36,27 +39,110 @@ public static partial class Convert public static string ToGsaString(this RigidLink link, string index, int secondaryIndex = 0) { - string command = "EL.2"; - string name = link.TaggedName().ToGSACleanName(); - string type = "LINK"; + if (CheckRigCon(link) == false) + { + string command = "EL.2"; + string name = link.TaggedName().ToGSACleanName(); + string type = "LINK"; - string constraintIndex = link.Constraint.GSAId().ToString(); - string group = "0"; + string constraintIndex = link.Constraint.GSAId().ToString(); + string group = "0"; - string startIndex = link.PrimaryNode.GSAId().ToString(); + string startIndex = link.PrimaryNode.GSAId().ToString(); - string endIndex = link.SecondaryNodes[secondaryIndex].GSAId().ToString(); + string endIndex = link.SecondaryNodes[secondaryIndex].GSAId().ToString(); - string dummy = CheckDummy(link); + string dummy = CheckDummy(link); - //EL 1 gfdgfdg NO_RGB LINK 1 1 1 2 0 0 NO_RLS NO_OFFSET DUMMY - string str = command + ", " + index + "," + name + ", NO_RGB , " + type + " , " + constraintIndex + ", " + group + ", " + startIndex + ", " + endIndex + " , 0" + ",0" + ", NO_RLS" + ", NO_OFFSET," + dummy; - return str; + //EL 1 gfdgfdg NO_RGB LINK 1 1 1 2 0 0 NO_RLS NO_OFFSET DUMMY + string str = command + ", " + index + "," + name + ", NO_RGB , " + type + " , " + constraintIndex + ", " + group + ", " + startIndex + ", " + endIndex + " , 0" + ",0" + ", NO_RLS" + ", NO_OFFSET," + dummy; + return str; + } + else { + string command = "RIGID.2"; + string name = link.TaggedName().ToGSACleanName(); + + string primaryNode = link.PrimaryNode.GSAId().ToString(); + + List constrainedNodes = link.SecondaryNodes; + string constrainedNodesIds = ""; + + foreach (Node constrainedNode in constrainedNodes) + { + string id = constrainedNode.GSAId().ToString(); + constrainedNodesIds = constrainedNodesIds + " " + id; + } + + string typename = link.Name.ToString(); + string type; + + switch (typename) + { + case "Fixed": + type = "ALL"; + break; + case "xy-Plane": + type = "XY_PLANE"; + break; + case "yz-Plane": + type = "YZ_PLANE"; + break; + case "zx-Plane": + type = "ZX_PLANE"; + break; + case "z-Plate": + type = "XY_PLATE"; + break; + case "x-Plate": + type = "YZ_PLATE"; + break; + case "y-Plate": + type = "ZX_PLATE"; + break; + case "Pinned": + type = "PIN"; + break; + case "xy-Plane Pin": + type = "XY_PLANE_PIN"; + break; + case "yz-Plane Pin": + type = "YZ_PLANE_PIN"; + break; + case "zx-Plane Pin": + type = "ZX_PLANE_PIN"; + break; + case "z-Plate Pin": + type = "XY_PLATE_PIN"; + break; + case "x-Plate Pin": + type = "YZ_PLATE_PIN"; + break; + case "y-Plate Pin": + type = "ZX_PLATE_PIN"; + break; + default: + type = "All"; + break; + } + + //RIGID.2 | name | primary_node | type | constrained_nodes | stage + string str = command + ", " + name + ", " + primaryNode + " , " + type + ", " + constrainedNodesIds; + return str; + } } /***************************************************/ + public static bool CheckRigCon(BHoMObject obj) + { + GSARigidConstraint tag = obj.FindFragment(); + + if (tag != null && tag.IsRigidConstraint) + return true; + + return false; + } } } diff --git a/GSA_Adapter/GSAAdapter.cs b/GSA_Adapter/GSAAdapter.cs index c8bd012f..0c28ffbf 100644 --- a/GSA_Adapter/GSAAdapter.cs +++ b/GSA_Adapter/GSAAdapter.cs @@ -94,7 +94,6 @@ public GSA87Adapter(string filePath = "", GSAConfig gsaConfig = null, bool activ {typeof(ISurfaceProperty), new List { typeof(IMaterialFragment) } }, {typeof(Spacer), new List { typeof(SpacerProperty), typeof(Node) } }, {typeof(Panel), new List { typeof(ISurfaceProperty), typeof(Node) } }, - {typeof(RigidConstraint), new List { typeof(Node) } }, #if GSA_10_1 {typeof(Node), new List{typeof(Constraint6DOF) } } #endif diff --git a/GSA_Adapter/GSA_Adapter.csproj b/GSA_Adapter/GSA_Adapter.csproj index bf2c9543..4e57dee0 100644 --- a/GSA_Adapter/GSA_Adapter.csproj +++ b/GSA_Adapter/GSA_Adapter.csproj @@ -184,7 +184,6 @@ - @@ -198,7 +197,6 @@ - diff --git a/GSA_oM/Fragments/GSARigidConstraint.cs b/GSA_oM/Fragments/GSARigidConstraint.cs new file mode 100644 index 00000000..330946bf --- /dev/null +++ b/GSA_oM/Fragments/GSARigidConstraint.cs @@ -0,0 +1,37 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2023, 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.Base; +using System.ComponentModel; + +namespace BH.oM.Adapters.GSA +{ + [Description("Fragment telling whether the element is a Rigid Constraint or Rigid Link")] + public class GSARigidConstraint : IFragment + { + [Description("True means the element will be treated as a rigid constraint in GSA.")] + public virtual bool IsRigidConstraint { get; set; } = false; + } +} + + diff --git a/GSA_oM/GSA_oM.csproj b/GSA_oM/GSA_oM.csproj index 93c80c53..b275e509 100644 --- a/GSA_oM/GSA_oM.csproj +++ b/GSA_oM/GSA_oM.csproj @@ -80,17 +80,16 @@ - - +