From 7cfaddaa3a9eb7b27baec4315b6cb0335a5378b5 Mon Sep 17 00:00:00 2001 From: Tilman Reinhardt Date: Mon, 28 Nov 2022 12:25:37 +0100 Subject: [PATCH 1/7] local axes --- GsaGH/Components/0_Model/GetGeometry.cs | 29 ++++++++++++++----- GsaGH/Components/2_Geometry/ElemFromMem.cs | 11 ++++++- .../2_Geometry/{LocalAxis.cs => LocalAxes.cs} | 12 ++++---- GsaGH/Helpers/Export/_GsaExport.cs | 9 ++++-- GsaGH/Helpers/_Display.cs | 4 +-- GsaGH/Helpers/_GsaImport.cs | 14 +++++++-- GsaGH/Parameters/2_Geometry/GsaElement1d.cs | 14 +++++++-- GsaGH/Parameters/2_Geometry/GsaLocalAxes.cs | 26 +++++++++++++++++ GsaGH/Parameters/2_Geometry/GsaMember1d.cs | 18 +++++++++++- GsaGHTests/Helper/_DisplayTest.cs | 20 ++++++------- 10 files changed, 122 insertions(+), 35 deletions(-) rename GsaGH/Components/2_Geometry/{LocalAxis.cs => LocalAxes.cs} (93%) create mode 100644 GsaGH/Parameters/2_Geometry/GsaLocalAxes.cs diff --git a/GsaGH/Components/0_Model/GetGeometry.cs b/GsaGH/Components/0_Model/GetGeometry.cs index f82ed2fce..f6e041991 100644 --- a/GsaGH/Components/0_Model/GetGeometry.cs +++ b/GsaGH/Components/0_Model/GetGeometry.cs @@ -19,6 +19,7 @@ using OasysUnits.Serialization.JsonNet; using OasysUnits.Units; using Rhino.Geometry; +using System.Collections.ObjectModel; namespace GsaGH.Components { @@ -90,8 +91,9 @@ public class SolveResults internal ConcurrentBag Mem2ds { get; set; } internal ConcurrentBag Mem3ds { get; set; } } + SolveResults Compute( - ConcurrentDictionary allnDict, + ConcurrentDictionary allnDict, ConcurrentDictionary axDict, ConcurrentDictionary nDict, ConcurrentDictionary eDict, @@ -100,7 +102,8 @@ SolveResults Compute( ConcurrentDictionary pDict, ConcurrentDictionary p3Dict, ConcurrentDictionary amDict, - ConcurrentDictionary modDict + ConcurrentDictionary modDict, + ConcurrentDictionary> localAxesDict ) { SolveResults results = new SolveResults(); @@ -121,7 +124,7 @@ ConcurrentDictionary modDict { // create elements Tuple, ConcurrentBag, ConcurrentBag> elementTuple - = Util.Gsa.FromGSA.GetElements(eDict, allnDict, sDict, pDict, p3Dict, amDict, modDict, LengthUnit); + = Util.Gsa.FromGSA.GetElements(eDict, allnDict, sDict, pDict, p3Dict, amDict, modDict, localAxesDict, LengthUnit); results.Elem1ds = elementTuple.Item1; results.Elem2ds = elementTuple.Item2; @@ -132,7 +135,7 @@ Tuple, ConcurrentBag, Concurrent { // create members Tuple, ConcurrentBag, ConcurrentBag> memberTuple - = Util.Gsa.FromGSA.GetMembers(mDict, allnDict, LengthUnit, sDict, pDict, p3Dict, this); + = Util.Gsa.FromGSA.GetMembers(mDict, allnDict, LengthUnit, sDict, pDict, p3Dict, localAxesDict, this); results.Mem1ds = memberTuple.Item1; results.Mem2ds = memberTuple.Item2; @@ -293,8 +296,13 @@ protected override void SolveInstance(IGH_DataAccess data) ConcurrentDictionary amDict = new ConcurrentDictionary(model.AnalysisMaterials()); ConcurrentDictionary modDict = new ConcurrentDictionary(model.SectionModifiers()); + // populate local axes dictionary + ConcurrentDictionary> localAxesDict = new ConcurrentDictionary>(); + foreach(int id in eDict.Keys) + localAxesDict.TryAdd(id, model.ElementDirectionCosine(id)); + tsk = Task.Run(() => Compute(nDict, axDict, out_nDict, - eDict, mDict, sDict, pDict, p3Dict, amDict, modDict), CancelToken); + eDict, mDict, sDict, pDict, p3Dict, amDict, modDict, localAxesDict), CancelToken); } // Add a null task even if data collection fails. This keeps the // list size in sync with the iterations @@ -345,8 +353,13 @@ protected override void SolveInstance(IGH_DataAccess data) ConcurrentDictionary amDict = new ConcurrentDictionary(model.AnalysisMaterials()); ConcurrentDictionary modDict = new ConcurrentDictionary(model.SectionModifiers()); + // populate local axes dictionary + ConcurrentDictionary> localAxesDict = new ConcurrentDictionary>(); + foreach (int id in eDict.Keys) + localAxesDict.TryAdd(id, model.ElementDirectionCosine(id)); + results = Compute(nDict, axDict, out_nDict, - eDict, mDict, sDict, pDict, p3Dict, amDict, modDict); + eDict, mDict, sDict, pDict, p3Dict, amDict, modDict, localAxesDict); } else return; } @@ -603,7 +616,7 @@ public override void DrawViewportWires(IGH_PreviewArgs args) public List SpacerDescriptions; public bool IsInitialised; - + private LengthUnit LengthUnit = DefaultUnits.LengthUnitGeometry; public override void CreateAttributes() @@ -614,7 +627,7 @@ public override void CreateAttributes() m_attributes = new OasysGH.UI.DropDownComponentAttributes(this, SetSelected, DropDownItems, SelectedItems, SpacerDescriptions); } - public void InitialiseDropdowns() + public void InitialiseDropdowns() { this.SpacerDescriptions = new List(new string[] { diff --git a/GsaGH/Components/2_Geometry/ElemFromMem.cs b/GsaGH/Components/2_Geometry/ElemFromMem.cs index 82c870cb9..d72e2e7f2 100644 --- a/GsaGH/Components/2_Geometry/ElemFromMem.cs +++ b/GsaGH/Components/2_Geometry/ElemFromMem.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using Grasshopper.Kernel; using Grasshopper.Kernel.Types; @@ -184,6 +185,13 @@ protected override void SolveInstance(IGH_DataAccess DA) // extract nodes from model ConcurrentBag nodes = Util.Gsa.FromGSA.GetNodes(new ConcurrentDictionary(gsa.Nodes()), LengthUnit); + ConcurrentDictionary elementDict = new ConcurrentDictionary(gsa.Elements()); + + // populate local axes dictionary + ConcurrentDictionary> localAxesDict = new ConcurrentDictionary>(); + foreach (int id in elementDict.Keys) + localAxesDict.TryAdd(id, gsa.ElementDirectionCosine(id)); + // extract elements from model Tuple, ConcurrentBag, ConcurrentBag> elementTuple = Util.Gsa.FromGSA.GetElements( @@ -194,6 +202,7 @@ Tuple, ConcurrentBag, Concurrent new ConcurrentDictionary(gsa.Prop3Ds()), new ConcurrentDictionary(gsa.AnalysisMaterials()), new ConcurrentDictionary(gsa.SectionModifiers()), + localAxesDict, LengthUnit); // post process materials (as they currently have a bug when running parallel!) @@ -363,7 +372,7 @@ public override void UpdateUIFromSelectedItems() this.LengthUnit = (LengthUnit)UnitsHelper.Parse(typeof(LengthUnit), this.SelectedItems[0]); base.UpdateUIFromSelectedItems(); } - + public override void VariableParameterMaintenance() { string unitAbbreviation = Length.GetAbbreviation(this.LengthUnit); diff --git a/GsaGH/Components/2_Geometry/LocalAxis.cs b/GsaGH/Components/2_Geometry/LocalAxes.cs similarity index 93% rename from GsaGH/Components/2_Geometry/LocalAxis.cs rename to GsaGH/Components/2_Geometry/LocalAxes.cs index 0e21fb909..db8e749db 100644 --- a/GsaGH/Components/2_Geometry/LocalAxis.cs +++ b/GsaGH/Components/2_Geometry/LocalAxes.cs @@ -11,7 +11,7 @@ namespace GsaGH.Components /// /// Component to edit a Node /// - public class LocalAxis : GH_OasysComponent, IGH_PreviewObject + public class LocalAxes : GH_OasysComponent, IGH_PreviewObject { #region Name and Ribbon Layout public override Guid ComponentGuid => new Guid("4a322b8e-031a-4c90-b8df-b32d162a3274"); @@ -19,7 +19,7 @@ public class LocalAxis : GH_OasysComponent, IGH_PreviewObject public override OasysPluginInfo PluginInfo => GsaGH.PluginInfo.Instance; protected override System.Drawing.Bitmap Icon => GsaGH.Properties.Resources.LocalAxes; - public LocalAxis() : base("Local Axis", + public LocalAxes() : base("Local Axis", "Axis", "Get Element1D or Member1D local axes", Ribbon.CategoryName.Name(), @@ -50,7 +50,7 @@ protected override void SolveInstance(IGH_DataAccess DA) GsaElement1d elem = null; Point3d midPt = new Point3d(); double size = 0; - Tuple axes; + GsaLocalAxes axes; if (gh_typ.Value is GsaMember1dGoo) { gh_typ.CastTo(ref mem); @@ -81,9 +81,9 @@ protected override void SolveInstance(IGH_DataAccess DA) return; } - Vector3d x = axes.Item1; - Vector3d y = axes.Item2; - Vector3d z = axes.Item3; + Vector3d x = axes.X; + Vector3d y = axes.Y; + Vector3d z = axes.Z; DA.SetData(0, x); DA.SetData(1, y); diff --git a/GsaGH/Helpers/Export/_GsaExport.cs b/GsaGH/Helpers/Export/_GsaExport.cs index 79387fdf3..1ff5d2ab8 100644 --- a/GsaGH/Helpers/Export/_GsaExport.cs +++ b/GsaGH/Helpers/Export/_GsaExport.cs @@ -52,6 +52,11 @@ public static GsaModel MergeModel(GsaModel mainModel, GsaModel appendModel) ConcurrentDictionary amDict = new ConcurrentDictionary(model.AnalysisMaterials()); ConcurrentDictionary modDict = new ConcurrentDictionary(model.SectionModifiers()); + // populate local axes dictionary + ConcurrentDictionary> localAxesDict = new ConcurrentDictionary>(); + foreach (int id in eDict.Keys) + localAxesDict.TryAdd(id, model.ElementDirectionCosine(id)); + // get nodes ConcurrentBag goonodes = Util.Gsa.FromGSA.GetNodes(nDict, LengthUnit.Meter); // convert from Goo-type @@ -61,7 +66,7 @@ public static GsaModel MergeModel(GsaModel mainModel, GsaModel appendModel) // get elements Tuple, ConcurrentBag, ConcurrentBag> elementTuple - = Util.Gsa.FromGSA.GetElements(eDict, nDict, sDict, pDict, p3Dict, amDict, modDict, LengthUnit.Meter); + = Util.Gsa.FromGSA.GetElements(eDict, nDict, sDict, pDict, p3Dict, amDict, modDict, localAxesDict, LengthUnit.Meter); // convert from Goo-type List elem1ds = elementTuple.Item1.Select(n => n.Value).ToList(); // change all members in List's ID to 0; @@ -79,7 +84,7 @@ Tuple, ConcurrentBag, Concurrent // get members Tuple, ConcurrentBag, ConcurrentBag> memberTuple - = Util.Gsa.FromGSA.GetMembers(mDict, nDict, LengthUnit.Meter, sDict, pDict, p3Dict); + = Util.Gsa.FromGSA.GetMembers(mDict, nDict, LengthUnit.Meter, sDict, pDict, p3Dict, localAxesDict); // convert from Goo-type List mem1ds = memberTuple.Item1.Select(n => n.Value).ToList(); // change all members in List's ID to 0; diff --git a/GsaGH/Helpers/_Display.cs b/GsaGH/Helpers/_Display.cs index 202918653..9a749e473 100644 --- a/GsaGH/Helpers/_Display.cs +++ b/GsaGH/Helpers/_Display.cs @@ -13,7 +13,7 @@ namespace GsaGH.UI /// public class Display { - public static Tuple GetLocalPlane(PolyCurve crv, double t, double orientationAngle) + public static GsaLocalAxes GetLocalAxes(PolyCurve crv, double t, double orientationAngle) { crv.PerpendicularFrameAt(t, out Plane pln); pln.Rotate(orientationAngle, pln.Normal); @@ -40,7 +40,7 @@ public static Tuple GetLocalPlane(PolyCurve crv, d outY = pln.YAxis; } Vector3d outZ = Vector3d.CrossProduct(outX, outY); - return new Tuple(outX, outY, outZ); + return new GsaLocalAxes(outX, outY, outZ); } public static void Preview1D(PolyCurve crv, double angle_radian, GsaBool6 start, GsaBool6 end, diff --git a/GsaGH/Helpers/_GsaImport.cs b/GsaGH/Helpers/_GsaImport.cs index d568a2529..e4d771574 100644 --- a/GsaGH/Helpers/_GsaImport.cs +++ b/GsaGH/Helpers/_GsaImport.cs @@ -156,7 +156,7 @@ public static Plane AxisToPlane(Axis axis, LengthUnit unit) public static Tuple, ConcurrentBag, ConcurrentBag> GetElements(ConcurrentDictionary eDict, ConcurrentDictionary nDict, ConcurrentDictionary sDict, ConcurrentDictionary pDict, ConcurrentDictionary p3Dict, - ConcurrentDictionary mDict, ConcurrentDictionary modDict, LengthUnit unit) + ConcurrentDictionary mDict, ConcurrentDictionary modDict, ConcurrentDictionary> localAxesDict, LengthUnit unit) { // Create lists for Rhino lines and meshes ConcurrentBag elem1ds = new ConcurrentBag(); @@ -292,7 +292,12 @@ public static GsaElement1d ConvertToElement1D(Element element, } // create GH GsaElement1d - return new GsaElement1d(element, ln, ID, section, orient); + GsaElement1d element1d = new GsaElement1d(element, ln, ID, section, orient); + + // set local axes + element1d.LocalAxes = new GsaLocalAxes(localAxes[ID]); + + return element1d; } return null; } @@ -799,7 +804,7 @@ public static Member DuplicateMember(Member mem) /// public static Tuple, ConcurrentBag, ConcurrentBag> GetMembers(ConcurrentDictionary mDict, ConcurrentDictionary nDict, LengthUnit unit, - ConcurrentDictionary sDict, ConcurrentDictionary pDict, ConcurrentDictionary p3Dict, GH_Component owner = null) + ConcurrentDictionary sDict, ConcurrentDictionary pDict, ConcurrentDictionary p3Dict, ConcurrentDictionary> localAxesDict, GH_Component owner = null) { // Create lists for Rhino lines and meshes ConcurrentBag mem1ds = new ConcurrentBag(); @@ -1000,6 +1005,9 @@ public static Tuple, ConcurrentBag GsaMember1d mem1d = new GsaMember1d(mem, unit, key, topopts.ToList(), topoType.ToList(), section, orient); mem1d.MeshSize = new Length(mem.MeshSize, LengthUnit.Meter).As(unit); + // set local axes + mem1d.LocalAxes = new GsaLocalAxes(localAxesDict[key]); + // add member to output list mem1ds.Add(new GsaMember1dGoo(mem1d)); } diff --git a/GsaGH/Parameters/2_Geometry/GsaElement1d.cs b/GsaGH/Parameters/2_Geometry/GsaElement1d.cs index e0d3148f7..1d45e6036 100644 --- a/GsaGH/Parameters/2_Geometry/GsaElement1d.cs +++ b/GsaGH/Parameters/2_Geometry/GsaElement1d.cs @@ -29,6 +29,7 @@ public class GsaElement1d private GsaBool6 _rel2; private GsaSection _section = new GsaSection(); private GsaNode _orientationNode; + private GsaLocalAxes _localAxes = null; private Line previewSX1; private Line previewSX2; @@ -250,13 +251,21 @@ public ElementType Type this._element.Type = value; } } - internal Tuple LocalAxes + internal GsaLocalAxes LocalAxes { get { + if (this._localAxes != null) + { + return _localAxes; + } PolyCurve crv = new PolyCurve(); crv.Append(this._line); - return UI.Display.GetLocalPlane(crv, crv.GetLength() / 2, this._element.OrientationAngle * Math.PI / 180.0); + return UI.Display.GetLocalAxes(crv, crv.GetLength() / 2, this._element.OrientationAngle * Math.PI / 180.0); + } + set + { + this._localAxes = value; } } #endregion @@ -298,6 +307,7 @@ public GsaElement1d Duplicate(bool cloneApiElement = false) GsaElement1d dup = new GsaElement1d(); dup._id = this._id; dup._element = this._element; + dup._localAxes = this._localAxes; if (cloneApiElement) dup.CloneApiObject(); dup._line = (LineCurve)this._line.DuplicateShallow(); diff --git a/GsaGH/Parameters/2_Geometry/GsaLocalAxes.cs b/GsaGH/Parameters/2_Geometry/GsaLocalAxes.cs new file mode 100644 index 000000000..78c7f2fa9 --- /dev/null +++ b/GsaGH/Parameters/2_Geometry/GsaLocalAxes.cs @@ -0,0 +1,26 @@ +using Rhino.Geometry; +using System.Collections.ObjectModel; + +namespace GsaGH.Parameters +{ + public class GsaLocalAxes + { + public Vector3d X { get; } + public Vector3d Y { get; } + public Vector3d Z { get; } + + public GsaLocalAxes(Vector3d x, Vector3d y, Vector3d z) + { + this.X = x; + this.Y = y; + this.Z = z; + } + + public GsaLocalAxes(ReadOnlyCollection collection) + { + this.X = new Vector3d(collection[0], collection[1], collection[2]); + this.Y = new Vector3d(collection[3], collection[4], collection[5]); + this.Z = new Vector3d(collection[6], collection[7], collection[8]); + } + } +} diff --git a/GsaGH/Parameters/2_Geometry/GsaMember1d.cs b/GsaGH/Parameters/2_Geometry/GsaMember1d.cs index b0bf29dd1..80794d2fe 100644 --- a/GsaGH/Parameters/2_Geometry/GsaMember1d.cs +++ b/GsaGH/Parameters/2_Geometry/GsaMember1d.cs @@ -25,6 +25,7 @@ public class GsaMember1d private GsaBool6 _rel1; private GsaBool6 _rel2; private GsaNode _orientationNode; + private GsaLocalAxes _localAxes = null; private Line previewSX1; private Line previewSX2; @@ -65,7 +66,21 @@ public class GsaMember1d public GsaSection Section { get; set; } = new GsaSection(); public List Topology => this._topo; public List TopologyType => this._topoType; - internal Tuple LocalAxes => UI.Display.GetLocalPlane(this._crv, this._crv.GetLength() / 2.0, this.OrientationAngle.Radians); + internal GsaLocalAxes LocalAxes + { + get + { + if (this._localAxes != null) + { + return _localAxes; + } + return UI.Display.GetLocalAxes(this._crv, this._crv.GetLength() / 2.0, this.OrientationAngle.Radians); + } + set + { + this._localAxes = value; + } + } public PolyCurve PolyCurve { get @@ -322,6 +337,7 @@ public GsaMember1d Duplicate(bool cloneApiMember = false) dup.Id = this.Id; dup.MeshSize = this.MeshSize; dup.ApiMember = this.ApiMember; + dup._localAxes = this._localAxes; if (cloneApiMember) dup.CloneApiObject(); dup._crv = (PolyCurve)this._crv.DuplicateShallow(); diff --git a/GsaGHTests/Helper/_DisplayTest.cs b/GsaGHTests/Helper/_DisplayTest.cs index c95b38726..6b2a08668 100644 --- a/GsaGHTests/Helper/_DisplayTest.cs +++ b/GsaGHTests/Helper/_DisplayTest.cs @@ -1,5 +1,5 @@ using System; -using GsaGH.UI; +using GsaGH.Parameters; using Rhino.Geometry; using Xunit; @@ -58,15 +58,15 @@ public void GetLocalPlaneTest(double dx, double dy, double dz, double angle, dou int precision = 10; - Assert.Equal(expectedLocalX.X, localAxis.Item1.X, precision); - Assert.Equal(expectedLocalX.Y, localAxis.Item1.Y, precision); - Assert.Equal(expectedLocalX.Z, localAxis.Item1.Z, precision); - Assert.Equal(expectedLocalY.X, localAxis.Item2.X, precision); - Assert.Equal(expectedLocalY.Y, localAxis.Item2.Y, precision); - Assert.Equal(expectedLocalY.Z, localAxis.Item2.Z, precision); - Assert.Equal(expectedLocalZ.X, localAxis.Item3.X, precision); - Assert.Equal(expectedLocalZ.Y, localAxis.Item3.Y, precision); - Assert.Equal(expectedLocalZ.Z, localAxis.Item3.Z, precision); + Assert.Equal(expectedLocalX.X, localAxis.X.X, precision); + Assert.Equal(expectedLocalX.Y, localAxis.X.Y, precision); + Assert.Equal(expectedLocalX.Z, localAxis.X.Z, precision); + Assert.Equal(expectedLocalY.X, localAxis.Y.X, precision); + Assert.Equal(expectedLocalY.Y, localAxis.Y.Y, precision); + Assert.Equal(expectedLocalY.Z, localAxis.Y.Z, precision); + Assert.Equal(expectedLocalZ.X, localAxis.Z.X, precision); + Assert.Equal(expectedLocalZ.Y, localAxis.Z.Y, precision); + Assert.Equal(expectedLocalZ.Z, localAxis.Z.Z, precision); } } } From ab44893dfdcc057825288028e5c64d56ca64843b Mon Sep 17 00:00:00 2001 From: Tilman Reinhardt Date: Mon, 28 Nov 2022 12:51:42 +0100 Subject: [PATCH 2/7] rhino conversions --- GsaGH/Helpers/_RhinoConversions.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/GsaGH/Helpers/_RhinoConversions.cs b/GsaGH/Helpers/_RhinoConversions.cs index c6552f0ea..92a8dcb4c 100644 --- a/GsaGH/Helpers/_RhinoConversions.cs +++ b/GsaGH/Helpers/_RhinoConversions.cs @@ -12,6 +12,7 @@ using OasysUnits.Units; using OasysGH.Units; using OasysGH.Units.Helpers; +using System.Collections.ObjectModel; namespace GsaGH.Util.GH { @@ -816,16 +817,24 @@ public static Mesh ConvertBrepToMesh(Brep brep, List curves, List elementDict = new ConcurrentDictionary(model.Elements()); + + // populate local axes dictionary + ConcurrentDictionary> localAxesDict = new ConcurrentDictionary>(); + foreach (int id in elementDict.Keys) + localAxesDict.TryAdd(id, model.ElementDirectionCosine(id)); + // extract elements from model Tuple, ConcurrentBag, ConcurrentBag> elementTuple = Util.Gsa.FromGSA.GetElements( - new ConcurrentDictionary(model.Elements()), + elementDict, new ConcurrentDictionary(model.Nodes()), new ConcurrentDictionary(model.Sections()), new ConcurrentDictionary(model.Prop2Ds()), new ConcurrentDictionary(model.Prop3Ds()), new ConcurrentDictionary(model.AnalysisMaterials()), new ConcurrentDictionary(model.SectionModifiers()), + localAxesDict, unit); List elem2dgoo = elementTuple.Item2.OrderBy(item => item.Value.Ids).ToList(); From 9ebc3d407ad493cb19104ef3758833039fc11b34 Mon Sep 17 00:00:00 2001 From: Tilman Reinhardt Date: Mon, 28 Nov 2022 12:57:10 +0100 Subject: [PATCH 3/7] local axes --- GsaGH/Helpers/_GsaImport.cs | 4 ++-- GsaGHTests/Helper/_DisplayTest.cs | 22 ++++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/GsaGH/Helpers/_GsaImport.cs b/GsaGH/Helpers/_GsaImport.cs index e4d771574..57b1606d9 100644 --- a/GsaGH/Helpers/_GsaImport.cs +++ b/GsaGH/Helpers/_GsaImport.cs @@ -217,7 +217,7 @@ public static Tuple, ConcurrentBag 0) elem1ds = new ConcurrentBag(elem1dDict.AsParallel(). Select(item => new GsaElement1dGoo( - ConvertToElement1D(item.Value, item.Key, nDict, sDict, mDict, modDict, unit)))); + ConvertToElement1D(item.Value, item.Key, nDict, sDict, mDict, modDict, localAxesDict, unit)))); if (elem2dDict.Count > 0) elem2ds = ConvertToElement2Ds(elem2dDict, nDict, pDict, mDict, unit); @@ -241,7 +241,7 @@ public static Tuple, ConcurrentBag public static GsaElement1d ConvertToElement1D(Element element, int ID, ConcurrentDictionary nodes, ConcurrentDictionary sections, - ConcurrentDictionary materials, ConcurrentDictionary sectionModifiers, LengthUnit unit) + ConcurrentDictionary materials, ConcurrentDictionary sectionModifiers, ConcurrentDictionary> localAxes, LengthUnit unit) { // get element's topology ReadOnlyCollection topo = element.Topology; diff --git a/GsaGHTests/Helper/_DisplayTest.cs b/GsaGHTests/Helper/_DisplayTest.cs index 6b2a08668..f756cb7de 100644 --- a/GsaGHTests/Helper/_DisplayTest.cs +++ b/GsaGHTests/Helper/_DisplayTest.cs @@ -1,5 +1,7 @@ using System; +using GsaGH.Components; using GsaGH.Parameters; +using GsaGH.UI; using Rhino.Geometry; using Xunit; @@ -49,7 +51,7 @@ public void GetLocalPlaneTest(double dx, double dy, double dz, double angle, dou double t = curve.GetLength() / 2.0; // Act - Tuple localAxis = Display.GetLocalPlane(curve, t, angle); + GsaLocalAxes localAxes = Display.GetLocalAxes(curve, t, angle); // Assert Vector3d expectedLocalX = new Vector3d(expextedLocalX1, expextedLocalY1, expextedLocalZ1); @@ -58,15 +60,15 @@ public void GetLocalPlaneTest(double dx, double dy, double dz, double angle, dou int precision = 10; - Assert.Equal(expectedLocalX.X, localAxis.X.X, precision); - Assert.Equal(expectedLocalX.Y, localAxis.X.Y, precision); - Assert.Equal(expectedLocalX.Z, localAxis.X.Z, precision); - Assert.Equal(expectedLocalY.X, localAxis.Y.X, precision); - Assert.Equal(expectedLocalY.Y, localAxis.Y.Y, precision); - Assert.Equal(expectedLocalY.Z, localAxis.Y.Z, precision); - Assert.Equal(expectedLocalZ.X, localAxis.Z.X, precision); - Assert.Equal(expectedLocalZ.Y, localAxis.Z.Y, precision); - Assert.Equal(expectedLocalZ.Z, localAxis.Z.Z, precision); + Assert.Equal(expectedLocalX.X, localAxes.X.X, precision); + Assert.Equal(expectedLocalX.Y, localAxes.X.Y, precision); + Assert.Equal(expectedLocalX.Z, localAxes.X.Z, precision); + Assert.Equal(expectedLocalY.X, localAxes.Y.X, precision); + Assert.Equal(expectedLocalY.Y, localAxes.Y.Y, precision); + Assert.Equal(expectedLocalY.Z, localAxes.Y.Z, precision); + Assert.Equal(expectedLocalZ.X, localAxes.Z.X, precision); + Assert.Equal(expectedLocalZ.Y, localAxes.Z.Y, precision); + Assert.Equal(expectedLocalZ.Z, localAxes.Z.Z, precision); } } } From 2733f7617c9814512237bb9dfd4ddd38ac946ee0 Mon Sep 17 00:00:00 2001 From: Tilman Reinhardt Date: Mon, 28 Nov 2022 14:26:16 +0100 Subject: [PATCH 4/7] local axes preview --- GsaGH/Components/2_Geometry/LocalAxes.cs | 25 ++++++- GsaGH/Helpers/_Display.cs | 31 --------- GsaGH/Parameters/2_Geometry/GsaElement1d.cs | 8 +-- GsaGH/Parameters/2_Geometry/GsaMember1d.cs | 6 +- GsaGHTests/Helper/_DisplayTest.cs | 74 --------------------- 5 files changed, 24 insertions(+), 120 deletions(-) delete mode 100644 GsaGHTests/Helper/_DisplayTest.cs diff --git a/GsaGH/Components/2_Geometry/LocalAxes.cs b/GsaGH/Components/2_Geometry/LocalAxes.cs index db8e749db..2c3f587c1 100644 --- a/GsaGH/Components/2_Geometry/LocalAxes.cs +++ b/GsaGH/Components/2_Geometry/LocalAxes.cs @@ -1,9 +1,15 @@ using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.ObjectModel; using Grasshopper.Kernel; using Grasshopper.Kernel.Types; +using GsaAPI; using GsaGH.Parameters; +using GsaGH.Util.Gsa.ToGSA; using OasysGH; using OasysGH.Components; +using OasysUnits.Units; using Rhino.Geometry; namespace GsaGH.Components @@ -60,6 +66,14 @@ protected override void SolveInstance(IGH_DataAccess DA) return; } axes = mem.LocalAxes; + if (axes == null) + { + GsaModel model = new GsaModel(); + model.Model = Util.Gsa.ToGSA.Assemble.AssembleModel(model, new List(), new List(), new List(), new List(), new List() { mem }, new List(), new List(), new List(), new List(), new List(), new List(), new List(), new List(), new List(), LengthUnit.Meter); + + axes = new GsaLocalAxes(model.Model.ElementDirectionCosine(1)); + AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Members´s local axes might deviate from the local axes in the assembled GSA model."); + } midPt = mem.PolyCurve.PointAtNormalizedLength(0.5); size = mem.PolyCurve.GetLength() * 0.05; } @@ -72,6 +86,14 @@ protected override void SolveInstance(IGH_DataAccess DA) return; } axes = elem.LocalAxes; + if (axes == null) + { + GsaModel model = new GsaModel(); + model.Model = Util.Gsa.ToGSA.Assemble.AssembleModel(model, new List(), new List() { elem }, new List(), new List(), new List(), new List(), new List(), new List(), new List(), new List(), new List(), new List(), new List(), new List(), LengthUnit.Meter); + + axes = new GsaLocalAxes(model.Model.ElementDirectionCosine(1)); + AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Element´s local axes might deviate from the local axes in the assembled GSA model."); + } midPt = elem.Line.PointAtNormalizedLength(0.5); size = elem.Line.GetLength() * 0.05; } @@ -80,15 +102,12 @@ protected override void SolveInstance(IGH_DataAccess DA) AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Unable to convert input to Element1D or Member1D"); return; } - Vector3d x = axes.X; Vector3d y = axes.Y; Vector3d z = axes.Z; - DA.SetData(0, x); DA.SetData(1, y); DA.SetData(2, z); - previewXaxis = new Line(midPt, x, size); previewYaxis = new Line(midPt, y, size); previewZaxis = new Line(midPt, z, size); diff --git a/GsaGH/Helpers/_Display.cs b/GsaGH/Helpers/_Display.cs index 9a749e473..e39e821e3 100644 --- a/GsaGH/Helpers/_Display.cs +++ b/GsaGH/Helpers/_Display.cs @@ -9,40 +9,9 @@ namespace GsaGH.UI /// /// Colour class holding the main colours used in colour scheme. /// Make calls to this class to be able to easy update colours. - /// /// public class Display { - public static GsaLocalAxes GetLocalAxes(PolyCurve crv, double t, double orientationAngle) - { - crv.PerpendicularFrameAt(t, out Plane pln); - pln.Rotate(orientationAngle, pln.Normal); - - double absAngleToZ = Vector3d.VectorAngle(pln.Normal, Vector3d.ZAxis); - absAngleToZ %= Math.PI; - - Vector3d outX = pln.ZAxis; - Vector3d outY; - if (absAngleToZ < 0.25 * Math.PI || absAngleToZ > 0.75 * Math.PI) - { - outY = new Vector3d(outX); - double angle; - if (outX.Z > 0) - angle = -0.5 * Math.PI; - else - angle = 0.5 * Math.PI; - - if (!outY.Rotate(angle, pln.XAxis)) - throw new Exception(); - } - else - { - outY = pln.YAxis; - } - Vector3d outZ = Vector3d.CrossProduct(outX, outY); - return new GsaLocalAxes(outX, outY, outZ); - } - public static void Preview1D(PolyCurve crv, double angle_radian, GsaBool6 start, GsaBool6 end, ref List greenLines20, ref List redLines10) { diff --git a/GsaGH/Parameters/2_Geometry/GsaElement1d.cs b/GsaGH/Parameters/2_Geometry/GsaElement1d.cs index 1d45e6036..6a893a765 100644 --- a/GsaGH/Parameters/2_Geometry/GsaElement1d.cs +++ b/GsaGH/Parameters/2_Geometry/GsaElement1d.cs @@ -255,13 +255,7 @@ internal GsaLocalAxes LocalAxes { get { - if (this._localAxes != null) - { - return _localAxes; - } - PolyCurve crv = new PolyCurve(); - crv.Append(this._line); - return UI.Display.GetLocalAxes(crv, crv.GetLength() / 2, this._element.OrientationAngle * Math.PI / 180.0); + return _localAxes; } set { diff --git a/GsaGH/Parameters/2_Geometry/GsaMember1d.cs b/GsaGH/Parameters/2_Geometry/GsaMember1d.cs index 80794d2fe..badee36e6 100644 --- a/GsaGH/Parameters/2_Geometry/GsaMember1d.cs +++ b/GsaGH/Parameters/2_Geometry/GsaMember1d.cs @@ -70,11 +70,7 @@ internal GsaLocalAxes LocalAxes { get { - if (this._localAxes != null) - { - return _localAxes; - } - return UI.Display.GetLocalAxes(this._crv, this._crv.GetLength() / 2.0, this.OrientationAngle.Radians); + return _localAxes; } set { diff --git a/GsaGHTests/Helper/_DisplayTest.cs b/GsaGHTests/Helper/_DisplayTest.cs deleted file mode 100644 index f756cb7de..000000000 --- a/GsaGHTests/Helper/_DisplayTest.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using GsaGH.Components; -using GsaGH.Parameters; -using GsaGH.UI; -using Rhino.Geometry; -using Xunit; - -namespace GsaGHTests.Helpers -{ - [Collection("GrasshopperFixture collection")] - public class _DisplayTest - { - [Theory] - [InlineData(0, 0, 1, 0, 0, 0, 1, 0, 1, 0)] - [InlineData(0, 0, 1, Math.PI / 2.0, 0, 0, 1, -1, 0, 0)] - [InlineData(0, 0, 1, Math.PI, 0, 0, 1, 0, -1, 0)] - [InlineData(0, 0, 1, Math.PI * 3 / 2.0, 0, 0, 1, 1, 0, 0)] - [InlineData(0, 0, 1, 2 * Math.PI, 0, 0, 1, 0, 1, 0)] - [InlineData(0, 0, 1, 5 * Math.PI / 2.0, 0, 0, 1, -1, 0, 0)] - [InlineData(0, 0, -1, 0, 0, 0, -1, 0, 1, 0)] - [InlineData(0, 0, -1, Math.PI / 2.0, 0, 0, -1, 1, 0, 0)] - [InlineData(0, 0, -1, Math.PI, 0, 0, -1, 0, -1, 0)] - [InlineData(0, 1, 0, 0, 0, 1, 0, 0, 0, 1)] - [InlineData(0, 1, 0, Math.PI / 2.0, 0, 1, 0, 1, 0, 0)] - [InlineData(0, 1, 0, Math.PI, 0, 1, 0, 0, 0, -1)] - [InlineData(0, 1, 0, Math.PI * 3 / 2.0, 0, 1, 0, -1, 0, 0)] - [InlineData(0, 1, 0, 2 * Math.PI, 0, 1, 0, 0, 0, 1)] - [InlineData(0, 1, 0, 5 * Math.PI / 2.0, 0, 1, 0, 1, 0, 0)] - [InlineData(0, -1, 0, 0, 0, -1, 0, 0, 0, 1)] - [InlineData(0, -1, 0, Math.PI / 2.0, 0, -1, 0, -1, 0, 0)] - [InlineData(0, -1, 0, Math.PI, 0, -1, 0, 0, 0, -1)] - [InlineData(1, 0, 0, 0, 1, 0, 0, 0, 0, 1)] - [InlineData(1, 0, 0, Math.PI / 2.0, 1, 0, 0, 0, -1, 0)] - [InlineData(1, 0, 0, Math.PI, 1, 0, 0, 0, 0, -1)] - [InlineData(-1, 0, 0, 0, -1, 0, 0, 0, 0, 1)] - [InlineData(-1, 0, 0, Math.PI / 2.0, -1, 0, 0, 0, 1, 0)] - [InlineData(-1, 0, 0, Math.PI, -1, 0, 0, 0, 0, -1)] - public void GetLocalPlaneTest(double dx, double dy, double dz, double angle, double expextedLocalX1, double expextedLocalY1, double expextedLocalZ1, double expextedLocalX2, double expextedLocalY2, double expextedLocalZ2) - { - // Arrange - Random random = new Random(); - double x = random.NextDouble(); - double y = random.NextDouble(); - double z = random.NextDouble(); - Point3d start = new Point3d(x, y, z); - Point3d end = new Point3d(x + dx, y + dy, z + dz); - Line line = new Line(start, end); - PolyCurve curve = new PolyCurve(); - curve.Append(line); - - double t = curve.GetLength() / 2.0; - - // Act - GsaLocalAxes localAxes = Display.GetLocalAxes(curve, t, angle); - - // Assert - Vector3d expectedLocalX = new Vector3d(expextedLocalX1, expextedLocalY1, expextedLocalZ1); - Vector3d expectedLocalY = new Vector3d(expextedLocalX2, expextedLocalY2, expextedLocalZ2); - Vector3d expectedLocalZ = Vector3d.CrossProduct(expectedLocalX, expectedLocalY); - - int precision = 10; - - Assert.Equal(expectedLocalX.X, localAxes.X.X, precision); - Assert.Equal(expectedLocalX.Y, localAxes.X.Y, precision); - Assert.Equal(expectedLocalX.Z, localAxes.X.Z, precision); - Assert.Equal(expectedLocalY.X, localAxes.Y.X, precision); - Assert.Equal(expectedLocalY.Y, localAxes.Y.Y, precision); - Assert.Equal(expectedLocalY.Z, localAxes.Y.Z, precision); - Assert.Equal(expectedLocalZ.X, localAxes.Z.X, precision); - Assert.Equal(expectedLocalZ.Y, localAxes.Z.Y, precision); - Assert.Equal(expectedLocalZ.Z, localAxes.Z.Z, precision); - } - } -} From 94cac40fc4fcac1669a0daf178a4bbb274045b42 Mon Sep 17 00:00:00 2001 From: Tilman Reinhardt Date: Mon, 28 Nov 2022 17:00:15 +0100 Subject: [PATCH 5/7] test --- ExampleFiles/Components/LocalAxes.gh | Bin 0 -> 19046 bytes GsaGH/Components/2_Geometry/EditElement1d.cs | 2 +- GsaGH/Components/2_Geometry/EditMember1d.cs | 2 +- GsaGH/Components/2_Geometry/LocalAxes.cs | 2 +- ...teGridPlane.cs => CreateGridPlaneTests.cs} | 2 - IntegrationTests/Components/LocalAxesTests.cs | 83 ++++++++++++++++++ 6 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 ExampleFiles/Components/LocalAxes.gh rename IntegrationTests/Components/{CreateGridPlane.cs => CreateGridPlaneTests.cs} (91%) create mode 100644 IntegrationTests/Components/LocalAxesTests.cs diff --git a/ExampleFiles/Components/LocalAxes.gh b/ExampleFiles/Components/LocalAxes.gh new file mode 100644 index 0000000000000000000000000000000000000000..85df7bc602e24d083fcaf7bc73905e615320c53c GIT binary patch literal 19046 zcmZVFV{m3o*f#3ewvCBx`;P5oVmq1GHYT=h+qP}ncD{Mu{eD%u_Wrl3`nE@1 z*rC7R%%SlwD?-Y&VL&+$$WOtq*M-7ak~0}@c?Ec_a=&D2aci_JE@Ff=C81d@cpYJb z;F00kR9-|Jwt!*alv1d2wqVt4G=)lF^d{10uFf|Vj-B|iSWK@BTW4)LKat3Sg?*te z3Y8ihH25c!IW>h#=>zdtfboK0Q~d7mdH}Zo24%=N5F5qqR&s)8?nkMJfVoskrp!fkg_WZDraeLy-5@wGiO^asjtJ_v z<-q_<2{QniwOUN2QJmTE}Tu7)#M5~^5W z%_YJY9*lD#_%%=ZPz3V6_L|WaW76MQedLyTAabRaIVd=@4+T`sI^H`gwk@tojpoH6 zn@v6d|05$p5-AWs$gcxtUr8Z-cdmW|&{lH+h zqP-SZRf(1%eF!7w-;B;@ z=GcIhK(*$t`{w{qpJ=Z}0L_~Tl$&51b&n3`RPWLFbzij8-ZXpzn%cLrWAfY_8yg~J z9dc~prHI))tB!^Y0s1>gthDMZGLG^yhRztdQurP%MBt2ys2bT{U^Yre3q^eb#|<~; zHePC$%wqy+Od+EVNndZt9(*6CXL?x2#>`H^cdo^+)4hZu>90MB-5H_OipBtqx=j0Y z)|>=4UIaecpcAXU;b2UhlkXAevti#H46lT=(WE#5&4c0Lj4)1E&^G*+i0~O1C~v%rNT84AOWSD zLD!7zWAc62*RseJ9F=O7*mw2BAsWWeyF7iuTbsjdpp%FQ! zg8N?%WEwe%^i>w}f1ax`l1Pt*wJW!4wV+KiOYxZGo$LO!MIHx{?-&F(H}J2OBta!E z*a_tOD*XRu22)Z|iHYla*XS~6LIJoba{WB4N!Hc|b_X$|*43s=@npIznZ?;9EvPOi zZk>^l1LWhS5$BxtW{Kz$&Bch@na%Zw#4UmJ)BOcl;d8rk=?cfgnj~~@H(VdMI^O#E zPKubWMl$%k*>#3l09D`Rx&09&C*{|fa8;)_x==w+v*r9*Q94V|PZkPQBw~@WM+!z1 zvuT$a8U`p*LXCfMK-Q7nX${>D!oXw8&xK;ca>He?z!&!_Rwgy_p3k98a8>(0^so1E zxE}Gr2`x+{l4>sfYRt9J(&@q0$HKKx1g`>NX9J;vC{fyx_MBmY8SgqGIW2430|T{K z{ip!Bm@qQAqOkdt=F)|8?sKdNg**{@g8?w9v*5g1Xey9<_!C7!DNq$ z2v=9kd+8PO8uvh9HDy4221V2)VyM(zE`HZ^6&rok)53+Ox9j{8jM76jtEOtxQq=NO@(L|>89l#(|Ol9T01J;n3bbUa3P#A=X`29U~i zDjLdwff%K@X3a(-gQ5@P@Fw<*8}{#J*}X1}gN}ju>Xg|~Bu?hv*1YD)_H|pY!nx2a zjK))-rp$jrN6L4Z-Ju4Il1q}LtAH=TC7?J843C5J0mJVe_sm4ZPmacJ9r5i=oIG5@d!FAYgmCT=efZf8ps z(W*Q7dm}t`9sZb@;0~Y~HY-9p8zL%uR=iSHNQQaX%#Df7Ne zYrBCXmw0p?ns;{>z-XHgAeAjX0TzZ11W{_UX;qc71oS>}x;yZ(IlS$xuc!R?H3244uQ-iTxi{saZ^kI*0D zuuNa?N1>Wqk<&m$fQRGUqooVZq8T0ptZ0Q>4k%hyiRt($S&&*vnMtjzM_7`&)JyZ9&w)DKw)#rl4Eu4g0aGzDmH@p3Fh9JJWvF76u6K+Qt#wv=C<&_71T@E3_>>umG>Vv*OVAu2_T=1eZCRS&GcP?gZT z@_9E4eu`i|PXc=yhi5P53RUf7p&57|@tL|HuT&p4uQ@`TV5e#?dzh#r%oO;Ig&@2D ze!vT^4!8%tXPuT;uEtg{EVX8j#s>CYSbmHmqo_9wuT=xnM8X?wj10L%z%V}Odj@+< zNCrfeuwV@`mWB<7=Zl$J4U1sFGR05t-GiwM9Ycb)WB--Ng0mexp4G(TWiLJAC0FjEpx7&dpn zf$@j}&h!u?%?eMH@f0d6WCimo#vFLr1=ZRML60>?sVX`ML|^D63?!1cTToTC_KG5F z3?+;?4bqEq51XehFufe23fUmWR74Db$$LfrLw|}mJuRdm$r`v`c=viZJ6h$?}N0z`5iqhf8c6$ zt6ORx)(v6_B7E-)tVB{4W>X}f%RENKOf%vA#*kFjZ4m?T7A543#QGa%WH_8B1CIkU ziy|JV8gJyIpU0^gUJ?PUv?4qV;L5{ZSJ61AmFwuK+O1Lg`36D6Y_!@D_E^9|2v! zQdXNX7Cc^*2ND~xHG#G8yj`d_9XV#zy+az^6Wm*!F<9jhxdSC;x>$ujM_tNYvU`87 z6QSRRLD%6nP3b*1E@cecgrQeuMl-=${XICAGd{0X?FFmrWE1_a91wiX z0@lYQiTh)X&#MdG453f0qHScGgm|#|E?N^ouV)t%NkuYlW7P=iL&pDGSTm%NvsW90 zHgW)j)%1RdNw#$qI3{|p#&HmUKm)PtT&v0IZ@hd$Uy$6$>fBgeQ{W_Ea?7~SBDQ=W z)p3w#<+u9fn*qioYMlXwlg}#-UE0egb?6POgjn|o7q<5z#2%VdIHmZ56yH$xiyhJp z9Qya){8hZ#N}K$ty%a}JjoG=A=`qR{^0J=0o?jMD`b#thiv??Fg5T0>Xz{~gry#Ue zfIq;=Tx9KnlFQ&45PwfW&^0kj4R!nsu=6CN2}t|};ZCG+^mFa=)?}hkCM{GXnT9MA z_?(SGezqIL?+$*`pT!`-;gGa3lq@FC_K~Fo9(Pxlhc@Ycw=at;mG*?VZ8|0wJ_TUT zG^+JQPy11T{v{YNb#NQ36$lVl2SHZo1>xj2qMkU@5vqIl&}2 zfUzfdbsE`F9cBU1@PD)p99_G7I^wdF3M-%rl0d{&g#ioA4t28+0>#tKt(2p4(O#8o zvWu z@i)`1%g7%%+mI6Wi;J1adqA=;|Afd~t^z%2P`8~C5A}4np2m{e8`dER30lyi$gE=B zOJKHdbK(b)TiWqkD0bep#x<>Vosw~#DL=wDGd)hpk?6M|MV(elzYL<)xt_$}_5e2e zUQi5)t%f^my&Z-8;quSmhFhUrY?eyg8;k{!C$UT<-sAC|`zcTi0X2m?UwE?THu(m| zWIK4?qpw0S`Bmn}wxFqct2n7ij&9Pr%K~?>6UqF@jsSfwftag>DpfF!7zcc4{&yn$s~I_ixtPd_HH&g zIF7TP;j6SuL-$mk{LxAzo|GSJ{Y)g$K?=IYECVM#*tg}I+S2_r6Z2+^)MeDbr83tQ z0)mZ1uxPr!$voRj?>$f$aIZ~(5GAkML-0ckmV%2t8l0OI)7xx~3b}0WsJ8k;!#bmg zIo;=hg0_^7OwBT9MwIfjBH6(h@CGbYf!zxF*}Hl1 z3v#Gq)-C%^EIsO3q;h_Wtj=@++yVrxEZhRL_^n?;^*<%eQ7uVW^WtHOz*)CnH||Fm z(!om$TkCe>G)h$)UbI(bu;Twm!X5hagrG&^?9DIOdRH1 z&nUC(vUTZQ#iB&b$QIG!o6xvZrgEi%pi5!FBG|*HOv&1vN|FEIG%)o9u!j#A3QpJ*9HPiboLiTF5)>6dN;Osu_LES>Wwh05 z250(0P43JV6{}oXp`#G^5YFF5 zB|^s*mT!XG_SR#fW{a=Ef{~Y-2(Wu?nP-)|5ENA>bhp|E5RTfcwSey>wt5yuGnUR0 zpbS5bin>1o^tjkJ&UJE=%$ByUR=6?sw*5Z9l*s(`*tNy{CJt2}?}<2lTalo&^Um7D znE_DQt={R4(%ev7fIL~mJ0bx%tj_4ePz{ic>{F2f;R_$E!0}Al=B9KhW8nu)WB1Xc zao;&j5rY_K$Q=^ckv`1o@Ae2dZR98N9V-+`@#Ia34IOZl+;3FjFWSLT^!O;9x`6)9 zJR-K4yT_8fE4ua664B33p2HD^#Ie~3# z#KU8_t28yWT!IT3?=$Vz!vUR=+U*V9m&*()_`z|yGg6r3I2wN#kD}nCPGJa;;^w;; zXq^#J^wj>no-ynm(0icHY*%XN;9k*mEB{S6^xU{mSq_Nd|cvFpB;- zP+A#o;9-yiMMqcxYA8N=3<#MAq7Jofpfg6&sJ6Q|V2RkbSW}h4t+{D8*Bu1auF#AA$ zhi>cXy@7+reOy?%1g)afp~tyZ7Ds|)%3SN|%d+&D*lgJC zqx1f!!th3dT^jHZPehyOmZ0d6cbs*+r!anLo*!zDc`Z(SE+h7f{4TFwf`Bqk~}ne(7*v??7NgJc;5*^I^rt z7?B2M;)VBNwF9896Su78<#E5=%{-(2aci|dd+xso})p*6HD#HE2EF8JtbwXDJ<#Xj-m0)j(C?MXUm3$(;%5QCH ztEAds4QykDp^Ff)n)FyJbT^IeSVa`gEusqi+isW#zTd3S$L+rBHA_=;Rd`6pZ({N? zk4YNHN7f-YG+yIOk;-?yeiPO!CJjN~4t0g&;iE!p?O`3x#K?D*$zAx~rZix0>_PJi zDK(4RYKkW|=PWa<)epxm#sDGz4uKVBJQi zVybFD^W3K&;+OSQHXt$B8SpGEvt|!OIP>3|Q!z!0j;s?AA~BP1fO|CUL8V30*p;8v zkwmv5Mo=lI@SV*XFI9n2Kb_HOU8!3))7D=bx?04Cr!)F#hGPA4$g2|+CS6z^3V>KxeTwZlEwr~SxG3hJ z8NM-__SqpBwv7Zb3Wkk>N5M*4uI}JnzCLQ*D9q_W=&;^{%P?B9QwZH@bkR0`b!i=F zkwDNZZo8n*Y2&%lTKVpR)cd3DMq8mVQ9hHr!|tjL1|p#Y6+%KBXL92LhBQlx3y(q{ zGnV0abhzF;0NHA?d=f*KUhDhENp>5F3b#&}88XHO^Kry|m==w{LWOfA-b9oL(?zHTz;rXwgnR&sS@el?`2-YTXFePnn zIc)fCL`WMH*7Nk+@wyo(MX%xIA_S0%R=k0m==Tv8nAAE7HgBwRG}Lr62cGh z^THWyW!KSZT{R+YjrP6yJ;!oVMuE~ka(3{%J3_{NmL%E+yqZ&gSFN~SJ^}wgE7a!& z4E`vkg^)emBazKtAfcgF4t8rtcGHlDsR|0D3zhW^%wTpnaSddgq`N8h;rKhd=n6@`m09A_dss{qW;@s_S9IE@|!R1 zQmJ$8Qeq4HLOTA<6QVni>~jUAg|3M$!!r@*mh9nWu{uYf@>Qa3<=Izl1u~%`%bT49k}vNl9CwpX$O0aZ`5v)~VBlXSD!m2`Eb_A>m3(eN`%(8Y`dDhq>r zG^j-@zw)+wQw_L~Ujzui1VcoQkR~eyvx;1YG^!tUH1yJTZAF=Ia(cvV3Xglp@E1(I zcJ6e>+Ppf4GL>9^;+H%%fD6?Wz7GaYInb{jte-S&*&B%d7kY2K~g+6mS2te9nM{x92uQ$`R z>`8mAoHr@r4k`()IBTg2!mgQjg}gNqWI0g?B6%0Tbt)r`L`ZPHYirxY#~y7dugPDt za-P9jKs5?>L2NknGuS;u1{Ls*Qh9p_!W}HQ`6$sa{0oXO5xNHj#S*d~QOl2toejlA ziL@tV>o1dK%LB=V+|13@O|Xp6G6h-+4qXoqih|L;DX*m<+?#+Dyyn{QpJLf0$!NM2 zw(8A}hb=QT+y{3xf&vJlGA5k=@{p+6xJRu{MiW0MZ0V13I+z&Q^-%djw`Dh52}d0# zdDoeZ3zedU{b5wT+SzD${;438ijp=Wl!N`KBDJd)$cz{rEL+(EU#+7n9BtMXh!5d} z6r@|e-Ibi_pENo<$VlXEaQYzW!-8}|{B9($-2#8d^@Sh=RBKxxy~CaGa9(L@h{h}2 z!gl7gt=`K40+Edj7>VN<66i{BVSdgh@qNg3C~jOL<$({&6j%E56oDM*tz4Y&CC5kj z07ZL-i8M@+3!V>PC9Zy%v5H-KC(1xFOm+@nO0a2BAOu{xusJ@0@1+pBsgoMEp?E8<`|T5&0()SZ&lgdzJ0#;o1t2%NY3t%mh-4 z6FIXwz%Yy{hWS7aW%`olBE1?YQgr1KI5{7O^@kt_=NH;Dak#at;JC;l!V=O9aOGGE z&o0QekOwR@^S9v!4XM4lf!)70m)-GfH1ZC$i|iIHj>+nYmlpuIsR~)0?DBA68*)(1 zYo+Xnh~-;>?acbzD&R9i9Nu7{qWIg_(NBwA93LN*N|iU=*SoI=qZ}*5(N#x=gwWWp zYjvZun-(No4ZJp)Z{=1-88o28sqrp`=RUMB26|6F@z*PfM^d77qMB&1oCc_GZYc@c z*NYXNzr~-lg9|l&5ez9rkwQllO}QTqa@TJ5w4egq}lZcR9iMHYvC40b?iGz*Q7gS(u z`d+bFP0<)|_%4c7FSkY=X1baYmTG$3Sm4VP%ieq8e?;+Uv3SXF?IGkV(JfKd!Qf=` z#joB==P?feG$+X$x{6M#fpAp2BOIuKSdUO+DM@bps7ML22eSj=I<3T+TmjOM#4@6B zf1yZwvJaKQ9)2m^qG<6qyC3Q-cHHh%p#-uL|>qo5Z#0A`f4_>C(A z)Zbu0G5c?XsLJuVu^+ek+NAA*^cw!b=O-m4&>T>u4a?Mrg+_tpL7uMUX;pyW zL6pnvFUgYDEBFig5$eZH`1d;Of&b>aGJgdhLD92r@^XPQ%DtK}wJETv@U~^C%NC*B zXvgj|7sn7t{lxz05O9d?OiPoL@HPg2UjtBpgWi9+E5;~a2I87`!KtT(sPBgjg|9H( zxLnoe7nJ*Jl-;0gL3B=-<`>8zE*h`_0q$v*yUAbKkrD*B#`dRs zo^6<5_y!nkjrQubMEV{vaTc5Q{kkLYRExYU_9eb$TFu$cGMgN--M|P4c4&0q-G3kg z5ke*Q__ENrSiLe*_olcA>)V7@aXCGFa*VOcoQPGl!%)Q6Ai$|b`l#BKvil`>f_1xx)RT@#Knk-g8pQqWuHBu~D z-%hdNwQ}bVK8Du*)>W|E`gZ;n%!jcU8ojgN`GF;axnMJ1v_hF3Fb{sx3V0uqu&g%~ zxO>V(*HdgTG{4s}@W#cyY65>c<8YLlFIANJ4cm}*-7FbguBDiUdM9}qdtJpexvC64e95@)^f`H0mg_7r$@TSIyNZOkfCS? zikuL|)UQkX_Y0gK^Tzm)7BA)Y90R^nSPPUhYw>^8dKi)Nj?V|5Qb&G%c=?w@;u z2NqYfY?0zfTf@>yW8N@hEL*1?kwe&k%08+MC8i;88Y+pFNh_(&H>fxdF`ySa@+G83 z^qDe$+g>Cp$VunGi_r_=M9Qv>E^0*VUo=2m0k4p#Iv}*r4-U0(2-Ash8Y5Fx#JwQf z8AO-|Hax8rdWT03hhpRj>{~Yg$Db)a1Ug_*Aq)hh7XdS6h3UCLkbD+3CFwuY3YM<+ zQQfj!7I|816W3b>zkTgsL4o?+i4l-8(IW@_3hfp^L>~QP{2;`9LNr(?bd!Vyh77cH3BSYLAQad&IJFIFd4)W z|4HIP=6fk}o0i7JAY~6JtFnM()@64813`yS*xCrm#$=6wIURy67^6A&C&G5ywVL9ki@_N!$1OWqAl@1+&ObF$B&52`ecw1P$x2jS zhG^GVTa(4@WBqiZI5F!o>P!ro3FU47N55Q=@!R{2^MK*1L&@v2-ZA_!ImrTT&m(SC0BBoq9sVEkwD&ct4#=xRr5>|Zcq^Qia<>Mi?x2{?+In~n@zgn-kuq2 zEL~Xxv}<-g;m8)uhpd68DQWgIce5xSjHZRu<1SM#^e@dghmk$*JVH(tvx42(jt-|O z+M*9s3};4RNBGT=U$dbCn~)Lce7Q%;iTxO|RN3!RtF#EgF>t?LH|mWBC|Ug0CSKT4 z-z461dth6gJD&Gau{pk6EVH7ZalanmLC{wDQJ#lyWM)%Xx&QK44g8umaT`BccXar( zKF(s+tIR>KtcF}#%j>1`VPhas{4p%}MZU6*uNS5>fSU!hD3Cab$?imb`^fWBwGTLD z7xEB%r*(GAoabABR+L>5@LRiP=MV3$*YyNGL#&U-4{~#e?O;)(FGxX_fR= zhA>x|9qxRTq{=Z&(^HZbzb-s9XGO+QCe(}XWfr2(mCUX-5Q$g zoGBI+5`gsA0$*#}jBVPtehDiii`!xe(5HL+S5#73Q|0|{_7d9f!Snuo37ny+I zr-2P_KpxfhXDr!qu%-bMJq@i;F42SmR0*``JM0{0tULP*f9K9kn}N{@U!afk^(=3T zZX}}!0zC_@NH5WZUC9moRkO%Y-`K09fwdgZP4K4U5l0H)jCJ=-rI>~x7rpc$Np0L2 zuT#o|yXkwj2kG)rx$pQrv1+^G<6mDoRi;Te_twc;5MV!_Kb zI7H&Ftp2p)zT~MpZ&lPeP;*br;swb%L^MH(SofKPRYBnyyAN@BL^CVRFk*=t&$?BU?{O zi0>V^7gU0)JBF(maz^$cxfv1N4MiT$nja(o8I3ypr+4Oub0^+FqPI?p1xi{kkG3hg z7rJ*~ugVk>21YlF$lB~m((I6+C5S%zDp(NFa2T&*mG8x?kmh@Lck=tLr_mVIX%d4kk81FCT$0{{xt zKwn)Asd2P7 zA!9TKFRo9+E~oQ|Rof8{uU{#!g9_M0F7K2=iD)qQft+{mF)nS73_fC76Uo?!KWOxr zVFf0Bt8Y6fWi+}A1Q@t&@fbYs+4@Botc{s~r~mIs;1pU}dwDe&2&PCOcT#B^!B{MM zgvx+#B*cUOzrc0=>WZh>7o=VF+h7fyL?C_HU+80mKKe6x8^Yt}6`l>9C6HNtb_jS| z)$%r5d=3dfApH*pd@F*U@bwYi?HYm5&KXJvMa7YM?aNwnbcRSh-%D+`iQ1(slbyeN z94lfVL{{XY4&v4%(tPfP0M#tHSo|l*mcg)Niyl*rw}6FTNech6F!XNj9@P`!ZE0=e_;TybTI=mmLLoh2RmYpccIy3~1FbN|07m|AcShuZ8~y zO%?7mHKG~dqmt@ck(a|ulr>>2Q|GFzho#S_%{MjYuLFKVj%mHt(FM=Ik2n&=!YI$~ z{e(af@%^uuqH-8a4Z!%}$VV02Z~k;FBS;iNfeM#G7C#qaC0K2xwj&_gH!#=Y`?GiA za!QxB;qQi0{&hr>wITFMKuF#K>L_EzYHSNx z>9P0ic?5yGkU2oTot9+qWz=*06hC=IwD$X&beN1#$FRf|6}4tk*&h9x24m_!0p(SS zMRt*jJj-DtI|DEzp-Jx1i^dw*pY{8|oX<)Pm>TKL$sFCO$Adth<5X;fvXOmN)g{Xs zID)RuXL-vuA#i4HCC(5rb2#l3<&;gM1lQf7=2^0H<-ZGDsYJecFN}evPl6gj<7JRK zE+R^-BAepVhOs{;#q_Zxry99iLshtP!VLG`l`WJA2O$b1O8me2De%6MY8P`1j(-gv zZM7Gi^sO)=46ApiYNwT0M_U7ngJ9g7dd=a7>B5gkuiKD)ix9sD#T?KuLoX6 z#sI~WpE7s8f{~T$!)6@j=TbY%OZ@t@9yE=*^6qaT6~s~#!qD#nrOUv`L0hM%Vntds zBsfuA`wtEZb*oQX_-@#O5HUSqHelkn9w4f}Dp7qplma@EIOWf~xhw4r*wlfIvN^=J zOOP`p;$-_+i7Veyv*64ea3;PCJa=RTG!_jVU$I?f-&w~H z`b5)YF12g|=Xf1iA0DQQg$Bye0nOe(z=btGa@D|A1R9=7LL#~AG{>8ae%SvXJb{*g z0Hdz|FL=@o-xJDnw14zDhMC6j0)WkS&!}tJ z!h(Ex+m6)drx)4@0pFgX^8B^;2PYC$@tgI#s6lI3O5HcG%x9GF^j$d>el}X&3bwnzq<~T=eDRz zoENXo+us*jpZQ{@IiFVIwNZSb?S*BT-DuC__U$M8FDY>3e979#d!gsaZ|#*(-{Yg9u?RY& zB0HW~U0v^T(4UrQUHbHG3Uk4ccW&MNe+lbhgRT)&L-QiAWfIPSMXA32(xks#QGA0m zFNow%@{{DdnaMe69^s>PxRYhaypSw3AyA>L84L|loF{^bdj<Afbf@=%|1WX)L~=TG>)YNNUhrM?PW;nt@qP*SMCLs~ zOCM@i=;u^Ga)yg;uvxk-c`5GyvNXc$^SQ?J@Le^fQnO8b8;#~*`{>=i7%hmr9{oFV z$9!Br6f6RDtzf_O9G(0i(CCN{S!gI}mlr9Wq1l{9GB};aAV(xY?f)`|zP^iH+<-{M zG~18-tDBw?FJ~IiU0Eiz2 z{oz&A2GNhmSnkwgu-0ZS}-ai{Q9oFN$UIYQ-_YTlH-ao%v>^1(S`rJO+aS}K{VfCNsZsJ zXqb59MTdO@Ni_B|f3^!>{BVk|mO1p`uJN_6mR+nb=}bl~izhfp4twi73!qnGgI&}C z)!RhxZaw?3o6CI$Y=}g_NFJ7FWvx_g^vu;A{nHiH?0CN4uz?UmxJx=OP3ma$R$u=* zkIPZ)c zV#e-{ihcG@yV2^m>-wGtSBt9V0qmcL|N2NH5eVy6R+)+Z^qO$)Tg<*B$F2PNpY2fo zkN|Xkp+X$tpb%^_7QJryjpAGP=+wrdj0FFZFhm$A6xJP-Q-v4S$ugyf>Yq0cCmk7N z#cMY(P8u8m9}z6=U{UQ>Nj!K7*xA%EM8pE7@)ldP{c2bb?i zm)sLH^~&=H6@f`Zd<(anCcM>X5#_UNL~xfsMuo^CgE4IjGXhZyywV}V9H^QY%Wd5}kWG-8?MHUow@ zjR@9@h%P`XZ>`H7<`@}zVP=!L3E>|=RHI-SNtzV(tRuldm@*kG1bbOA)29Z1^<|1D zp;`6B`m&sTBRMJ#q`%>?@5Leq2#KJDQkbEo1;tQcXD{pEU(pX95Q5k7+K}m4)e;l9 zev@O%M!UW~X@PTa2SUzw4Ek}{4Kn%=pu*b7B4tg)@`kF_X^4YC36}KLob~RRBCMy2 z(&Q(h-`*nDQ#iV_vd`h5tnubs07~KKAgXKe&5NtBp_udi^ngaqaROzd3R!mL!jKyQ zVdBD7IGd3SN2EsBaZ*z-B_Tu1rFc;dsmV9*>o#uXkL`;;4f-oQi3V-)uRGA@hTv`2ROAi2gg?NHT zVv(ti=|^xT@&t6^s}Np|sYv;#t-SV(a-;?9-yyj1Sa9LFw!Fh!!DF2Lk6Dg)F-=8r zt{|1Kmj?(b9UFHOHj}w9Lb5>NSc1(Y5MV->AL~e3bn)9H}x6oN&R^52`(Pg zlb%!5;3ynS1k{u<9qg)p<5}*I0b|iF-{7%CV@6GQiUep9TJ8UrK*iZzY<}MSz;j$) zl21|E)*y!n zl-SWVK5g;JI2zw*Clz;Ql|$jbi-6iXoKJ<*aOTwivD1=@`!-FNjTZN$ z8LXR?pJQPTvdm@XJ?koHJ3m-6$g&2=beIy^i(amJ*Pa;&!lz#kpv*alI7cD8y|q=* zGMw60^{&Ig4X|QHqJOMquo9%~I_VyTk^@q+2-?AfJ^XSynv03u^lju3rHCGXluj9h z@p=0m`VKgNlW0JEYji;gM53o_aBlmCV=;o(psxqYs|V8=cmzUCWOEI~H)z z=?FV<+fDU5GYH@EkH!x_H&Oy& z{yrGs?H-7~%|5p(PWuxc2t;q@<*La9a~7Wa}NHI|&u=@KbRVvDnd* zx~JebGJ4v)wFHHGMT-JM5%4{3iTamsZ|i2?p7mxh-PP69s_$OlXlB{gSRL=9um!Sp zsh$7W*JAaUy`_zWPHk4UPx9coq~J5VjBVL0Nzd?3|5{f0uI@R%G_Vx8Yl^|?0?Bby zy3Qs_^SO!l{xc8)FJSsDv3O-{JZQ-H?A6X!6`5ziH)bw|!GVu+m4wUDxzufT=G=01 zSQpJIm$i3sf$PgtH&bce@!1!uu9IbAWz}Ib+!9+rF*&NpSMc1W`<`bs60~`lZ4~GO2cL6*fxflEV7%SJCof@Did%9{L$tog0;C)|zfDDNZC zH?{My>wQb5dVDt`I+z%uti^VVdgo)IZ`^xF7=A{0d(-OuTLcga6%@rvIWVw@@?n#< z@(Ee}dS{@1Nw@Sdl;Yuv)w%Sib=g1W0QDM!4%gRCEq+dluWH2ZnlReeA*r35OvtR= z=gMjusUvBPztK~fy{2?p`@U9h`m)-GzYBBY1^}gP&eiSWaiVvE+3{x{pU~m5bk27H z*LH<=wS+&Qlju})9cRkwribw#UgTPTlXwh;ckViw6}NTK%YJW&4!;jNv(s_jplfsW z8RBEHoE`vQ8P+Q7e&@eC`Yw70?U*ut((@|YTF3-Nr69-@g6n!I_{5`p%XS#8J%EF? z9jij-2&sM1hS&`2UR|R!u@2pumghvM=>9Ta?duf(oiVwsl-IfUQKfrw%v$M!<6bf8 zW-ZA>IsJ5Xqa$}7oMygyC;$!BIC`UVl&kx2ptx80B`|WsiCx*ow@zk#v6NFo82kSA zJZM}rdXjng;u@<$n>`HA_rZBTsI(Hiu+-H<$jxNA@%mXLih5Pm9;uX)rP$866(gO~ z_88Zduu!^|*pW!6XSZNBsqq}B_}#fT@Rw>0^xg_Bn&zq6hPs8%l2@N$RD0^q7 zS-M%Hn2kmMvi6yh$2D_seYxp#vsZOFbU+WwBZEFd8^ib90JHjM)uw~(QZI?DwMia7 z>8*dg!S&uhmj*Vg^WUe*r#0(Ua1y@3VEgr2+3}Y3d#A4V`lqMG(8WEn>NEp&CP}ia zd!y}m&BoeyihHONH?{0;rd#Jzw&Jf5%bO;vJaTWi&_BOfKJ0VL`oi6XLKJFv2(R9i zUKPI9(*}z59&M(pZZJALN5*k?IOY5I!$XT*c)#O5SYP}Q8LD5XfAWcHGA(m5xZ0VX z3HiNojLllin=U#flC)cF>1d3mGc_}E#kFTuzoNI#MNqfRydqlXPr`z=wL*q{%$~zb zbbYhl+B^WC2hDc{>=w4ZZ*p(l-QTs8DS@u6n{r-?JsVyc8=q;2@~G3N*Qrg$X&&PD z2tLb3^xlEv~95$e!VU=MwZS zZ~{8qp9-s=S!xt^vP#67v$ZE#(~W0#aAx?jYZi{~nt`BBvRB~FD{GK)6sHx@PJhmu zw!AE(>@Z)VVuGb_#W;LAwNS@@UIiPTcmi?FwnL6?Yrx=bP^Uw z+m^WHL>+`Sqf;Kvugi9KT<#f%<^@8OEwOD9W+l(4J+lzgRm!^P&aJSxc*hQOP!_iR zp8%c-VfK7?UE-`|H{ZP1(Dert^Y7lJh85M;u43Qqdw5ngxym@H18IPuxO z+D9*MeEhFs!{E+m)|EN^JXty>TenY-XMaOJI7i*IDxX!|EQp&aIvm)~+xmMa6>Ra`PZ3{paG_#nTwqA7_~kf1k4@J|i|m zPw`CHmQHQvu3FW-^pe-SwWPskuUt85Y@*y=FC*HjkKqBGzRt6`gUwUEjCx%2tJKFX z=Va8@5$o?zZ-pf%Tx0H7d~M0zx`ZLyjE`RKqGhk9rWRV}5x-*15tnr&#SGo#q5J1W z-!vHg_F0FXl!*bidp+V5sdjEZ#lu5kzJ1U7W2F~+Qo5w}(4@1~{bp6z--`Eq>eF|^ zG2NrIaqg_42g>z^_j2%}zb<4M%-gu;# zE#1&=eALzF^A4>^e`|hWkuk-7_*q4hZC8g^M3gAEPY>CD%#7UO_UDd{YY)9HU#RKv zrH7%CSwV3HwAQ}b-B5e(+_}O+<2P*fJeOyi)QqOT&Kz`GH@H*AwhK=W?VS1J>xmOy zZ;lXi=ilgG`^aX7d6e3Z+r=OI+$lP6C25xKs-nR5A9SX8+Oj(=P(PEEoqa)}uVQ5< zZ>2Iy`x(pCv{tX#n{;T%xsX#&JCzPjn0V{@gljQtKW?#dOZQx^JI{aEmx$otoZ_WV z{nd5av>7pC#Ga4WCll9g`!_ zD(tPRtJ|<@>a)fE!;I%Yafwo9e664QRsVFGRE4$*sYCQ<_nW9ar>9!h%G+PhSJ@qW z?OM8WQEop@hh)Yy=bce!x(8S-?VC5Np21+ec=f8c+Uv6kL+)>R;xojyOWTL~Q(gt% ze0zG?O?B^f{TDv_-dQi>^XNObwom==?DFNM#uo~%h3)^4tYv>^T0@O{_r&Cj8?HRp zF#D{rFUq>uYxVy}EO&eoFGmPctW`5XV}?b-!@IcwFkt3r8|fn{S@;Xn0reQ+m@0 z#bsqPpA@DN2*c0!G|sq?(KDEK!N$F=%d@&Cd3j^9Rxvwoo&V_F;1`O82kpM*r*=a%>O zr?vy!j~Q3z9a?oVN~`h<+4$FwTi5TTjY!^qIcrsIZ7p-oo7sgEJma2CSm~vH&2GVn zHv>!8ADel2f63MSe&zEyhbQb(?^&a`f8)W&ncaH+?6CL~JA8s|$%~jnp~fnE&-7XJ zWk*5#?kT?JF&8^J+}iN6+qh@5V^zp&7Ervxl6!4$Q|J<`*p}iSdF-*~>oI}p?7q2a z{emZ(3|XAU4H;56&&AK`M!T|y7v{O9^}BmldEr6QEsvG+RLn_FIMv17H_|H9a#-j3 z{ikYdvDjvc%kIq|ou4~p8ptRkUg?3# z16#Wq?@L(& ztJ2vkS7h0L!B`PFFu%xgHa-2v$<55!RnR zXfLwVu&&Z3Cv<2C-xAWlS2D$fZWpvXpR+vb<9Eip8G9LtUpfxUm}R;x`>SJYhl48l zZxCo7yWmEH^?sU&k+X!|c0Hb=PT(TJ0E7`T1qXInVx!W4m5U4BqdP zXxL%KodtGFCwHFKbM#^nXi}}sP7TsO%B*J#{PYYx<(nVcjbhI#AZzgYYyrYSpzpi8ktY}~ z+er7`Bs{TmEdAa|W$Ei1yJAZ}7uu~;InZ|4=lWS{-9H;9r+pZ(Y{0kwzH{#{(lGYc zx^!n@&pz2*zbv0!SyZ%r$Bt!z-D6{86Klq|kD4AGy>st>NqPST{@CmF*+5%w6MJC( z>EPhtPdB;#6DF)az5aVzZGyt!Ui#z%Dt?zPxlf+tH)7P4s;Vl(HdEuYUau{PI-}c0 z)xlBw`Q^>!#R(NPH5uE|JEbJ`>0PKWd<}Qv#C(), new List(), new List(), new List(), new List() { mem }, new List(), new List(), new List(), new List(), new List(), new List(), new List(), new List(), new List(), LengthUnit.Meter); - axes = new GsaLocalAxes(model.Model.ElementDirectionCosine(1)); + axes = new GsaLocalAxes(model.Model.MemberDirectionCosine(1)); AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Members´s local axes might deviate from the local axes in the assembled GSA model."); } midPt = mem.PolyCurve.PointAtNormalizedLength(0.5); diff --git a/IntegrationTests/Components/CreateGridPlane.cs b/IntegrationTests/Components/CreateGridPlaneTests.cs similarity index 91% rename from IntegrationTests/Components/CreateGridPlane.cs rename to IntegrationTests/Components/CreateGridPlaneTests.cs index 67cc21983..e7c896170 100644 --- a/IntegrationTests/Components/CreateGridPlane.cs +++ b/IntegrationTests/Components/CreateGridPlaneTests.cs @@ -29,8 +29,6 @@ public void GridPlaneSurfaceTest() GH_Document doc = Document(); GH_Component comp = Helper.FindComponent(doc, "gps"); Assert.NotNull(comp); - // Todo fix: referencing GsaGH directly causes tests to fail - // Not only this one but tests that otherwise work GsaGridPlaneSurfaceGoo output = (GsaGridPlaneSurfaceGoo)ComponentTestHelper.GetOutput(comp); GsaGridPlaneSurface gps = output.Value; Assert.Equal(42, gps.GridPlaneId); diff --git a/IntegrationTests/Components/LocalAxesTests.cs b/IntegrationTests/Components/LocalAxesTests.cs new file mode 100644 index 000000000..7625d5b47 --- /dev/null +++ b/IntegrationTests/Components/LocalAxesTests.cs @@ -0,0 +1,83 @@ +using System; +using System.IO; +using System.Reflection; +using Grasshopper.Kernel; +using Grasshopper.Kernel.Types; +using Xunit; + +namespace IntegrationTests.Components +{ + [Collection("GrasshopperFixture collection")] + public class LocalAxesTests + { + public static GH_Document Document() + { + Type thisClass = MethodBase.GetCurrentMethod().DeclaringType; + string fileName = thisClass.Name + ".gh"; + fileName = fileName.Replace(thisClass.Namespace, string.Empty).Replace("Tests", string.Empty); + + string solutiondir = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.Parent.Parent.FullName; + string path = Path.Combine(new string[] { solutiondir, "ExampleFiles", "Components" }); + + return Helper.CreateDocument(Path.Combine(path, fileName)); + } + + [Fact] + public void LocalAxesTest() + { + GH_Document doc = Document(); + + IGH_Param paramX1 = Helper.FindParameter(doc, "X1"); + IGH_Param paramY1 = Helper.FindParameter(doc, "Y1"); + IGH_Param paramZ1 = Helper.FindParameter(doc, "Z1"); + IGH_Param paramX2 = Helper.FindParameter(doc, "X2"); + IGH_Param paramY2 = Helper.FindParameter(doc, "Y2"); + IGH_Param paramZ2 = Helper.FindParameter(doc, "Z2"); + for (int i = 0; i < 20; i++) + { + GH_Vector outputX1 = (GH_Vector)paramX1.VolatileData.get_Branch(0)[i]; + GH_Vector outputY1 = (GH_Vector)paramY1.VolatileData.get_Branch(0)[i]; + GH_Vector outputZ1 = (GH_Vector)paramZ1.VolatileData.get_Branch(0)[i]; + GH_Vector outputX2 = (GH_Vector)paramX2.VolatileData.get_Branch(0)[i]; + GH_Vector outputY2 = (GH_Vector)paramY2.VolatileData.get_Branch(0)[i]; + GH_Vector outputZ2 = (GH_Vector)paramZ2.VolatileData.get_Branch(0)[i]; + + Assert.Equal(outputX1.Value.X, outputX2.Value.X, 6); + Assert.Equal(outputX1.Value.Y, outputX2.Value.Y, 6); + Assert.Equal(outputX1.Value.Z, outputX2.Value.Z, 6); + Assert.Equal(outputY1.Value.X, outputY2.Value.X, 6); + Assert.Equal(outputY1.Value.Y, outputY2.Value.Y, 6); + Assert.Equal(outputY1.Value.Z, outputY2.Value.Z, 6); + Assert.Equal(outputZ1.Value.X, outputZ2.Value.X, 6); + Assert.Equal(outputZ1.Value.Y, outputZ2.Value.Y, 6); + Assert.Equal(outputZ1.Value.Z, outputZ2.Value.Z, 6); + } + + IGH_Param paramX3 = Helper.FindParameter(doc, "X3"); + IGH_Param paramY3 = Helper.FindParameter(doc, "Y3"); + IGH_Param paramZ3 = Helper.FindParameter(doc, "Z3"); + IGH_Param paramX4 = Helper.FindParameter(doc, "X4"); + IGH_Param paramY4 = Helper.FindParameter(doc, "Y4"); + IGH_Param paramZ4 = Helper.FindParameter(doc, "Z4"); + for (int i = 0; i < 20; i++) + { + GH_Vector outputX3 = (GH_Vector)paramX3.VolatileData.get_Branch(0)[i]; + GH_Vector outputY3 = (GH_Vector)paramY3.VolatileData.get_Branch(0)[i]; + GH_Vector outputZ3 = (GH_Vector)paramZ3.VolatileData.get_Branch(0)[i]; + GH_Vector outputX4 = (GH_Vector)paramX4.VolatileData.get_Branch(0)[i]; + GH_Vector outputY4 = (GH_Vector)paramY4.VolatileData.get_Branch(0)[i]; + GH_Vector outputZ4 = (GH_Vector)paramZ4.VolatileData.get_Branch(0)[i]; + + Assert.Equal(outputX3.Value.X, outputX4.Value.X, 6); + Assert.Equal(outputX3.Value.Y, outputX4.Value.Y, 6); + Assert.Equal(outputX3.Value.Z, outputX4.Value.Z, 6); + Assert.Equal(outputY3.Value.X, outputY4.Value.X, 6); + Assert.Equal(outputY3.Value.Y, outputY4.Value.Y, 6); + Assert.Equal(outputY3.Value.Z, outputY4.Value.Z, 6); + Assert.Equal(outputZ3.Value.X, outputZ4.Value.X, 6); + Assert.Equal(outputZ3.Value.Y, outputZ4.Value.Y, 6); + Assert.Equal(outputZ3.Value.Z, outputZ4.Value.Z, 6); + } + } + } +} From 667c08009c2473e32daadc1c56e44788cf19371d Mon Sep 17 00:00:00 2001 From: Tilman Reinhardt Date: Mon, 28 Nov 2022 18:21:59 +0100 Subject: [PATCH 6/7] PublishCodeCoverageResults --- build-test-deploy.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build-test-deploy.yml b/build-test-deploy.yml index 4a50c1cc6..78e003163 100644 --- a/build-test-deploy.yml +++ b/build-test-deploy.yml @@ -66,6 +66,12 @@ steps: summaryFileLocation: '$(System.DefaultWorkingDirectory)/results/gsagh/**/coverage.cobertura.xml' pathToSources: '$(System.DefaultWorkingDirectory)' +- task: PublishCodeCoverageResults@1 + inputs: + codeCoverageTool: 'cobertura' + summaryFileLocation: '$(System.DefaultWorkingDirectory)/results/integration/**/coverage.cobertura.xml' + pathToSources: '$(System.DefaultWorkingDirectory)' + - powershell: | $coverage_file_gsagh = (Resolve-Path $(System.DefaultWorkingDirectory)/results/gsagh/*/coverage.cobertura.xml).Path echo $coverage_file_gsagh From 296bd130798e60455e88833cf0aa00727bfb1f48 Mon Sep 17 00:00:00 2001 From: Tilman Reinhardt Date: Mon, 28 Nov 2022 18:45:12 +0100 Subject: [PATCH 7/7] transformation methods --- GsaGH/Parameters/2_Geometry/GsaElement1d.cs | 28 +++++++++++++ .../Parameters/2_Geometry/GsaElement1dGoo.cs | 42 ++++++------------- GsaGH/Parameters/2_Geometry/GsaElement2d.cs | 1 - GsaGH/Parameters/2_Geometry/GsaMember1d.cs | 2 + GsaGH/Parameters/2_Geometry/GsaMember1dGoo.cs | 1 - 5 files changed, 42 insertions(+), 32 deletions(-) diff --git a/GsaGH/Parameters/2_Geometry/GsaElement1d.cs b/GsaGH/Parameters/2_Geometry/GsaElement1d.cs index 6a893a765..cb79a2c46 100644 --- a/GsaGH/Parameters/2_Geometry/GsaElement1d.cs +++ b/GsaGH/Parameters/2_Geometry/GsaElement1d.cs @@ -405,5 +405,33 @@ internal void UpdatePreview() previewPointEnd = this._line.PointAtEnd; } #endregion + + #region transformation methods + public GsaElement1d Transform(Transform xform) + { + GsaElement1d elem = this.Duplicate(true); + elem.Id = 0; + elem.LocalAxes = null; + + LineCurve xLn = elem.Line; + xLn.Transform(xform); + elem.Line = xLn; + + return elem; + } + + public GsaElement1d Morph(SpaceMorph xmorph) + { + GsaElement1d elem = this.Duplicate(true); + elem.Id = 0; + elem.LocalAxes = null; + + LineCurve xLn = this.Line; + xmorph.Morph(xLn); + elem.Line = xLn; + + return elem; + } + #endregion } } diff --git a/GsaGH/Parameters/2_Geometry/GsaElement1dGoo.cs b/GsaGH/Parameters/2_Geometry/GsaElement1dGoo.cs index 2e1a79a56..8f482ab42 100644 --- a/GsaGH/Parameters/2_Geometry/GsaElement1dGoo.cs +++ b/GsaGH/Parameters/2_Geometry/GsaElement1dGoo.cs @@ -1,6 +1,5 @@ using Grasshopper.Kernel; using Grasshopper.Kernel.Types; -using GsaAPI; using OasysGH; using Rhino.Geometry; using OasysGH.Parameters; @@ -114,35 +113,6 @@ public override bool CastFrom(object source) } #endregion - #region transformation methods - public override IGH_GeometricGoo Transform(Transform xform) - { - if (Value == null) { return null; } - if (Value.Line == null) { return null; } - - GsaElement1d elem = Value.Duplicate(true); - elem.Id = 0; - LineCurve xLn = elem.Line; - xLn.Transform(xform); - elem.Line = xLn; - - return new GsaElement1dGoo(elem); - } - - public override IGH_GeometricGoo Morph(SpaceMorph xmorph) - { - if (Value == null) { return null; } - if (Value.Line == null) { return null; } - - GsaElement1d elem = Value.Duplicate(true); - LineCurve xLn = Value.Line; - xmorph.Morph(xLn); - elem.Line = xLn; - - return new GsaElement1dGoo(elem); - } - #endregion - #region drawing methods public override void DrawViewportMeshes(GH_PreviewMeshArgs args) { @@ -198,5 +168,17 @@ public override void DrawViewportWires(GH_PreviewWireArgs args) } } #endregion + + #region transformation methods + public override IGH_GeometricGoo Transform(Transform xform) + { + return new GsaElement1dGoo(Value.Transform(xform)); + } + + public override IGH_GeometricGoo Morph(SpaceMorph xmorph) + { + return new GsaElement1dGoo(Value.Morph(xmorph)); + } + #endregion } } diff --git a/GsaGH/Parameters/2_Geometry/GsaElement2d.cs b/GsaGH/Parameters/2_Geometry/GsaElement2d.cs index deee16281..0fd51a16b 100644 --- a/GsaGH/Parameters/2_Geometry/GsaElement2d.cs +++ b/GsaGH/Parameters/2_Geometry/GsaElement2d.cs @@ -8,7 +8,6 @@ using OasysUnits; using OasysUnits.Units; using Rhino.Geometry; -using Grasshopper.Kernel.Types; namespace GsaGH.Parameters { diff --git a/GsaGH/Parameters/2_Geometry/GsaMember1d.cs b/GsaGH/Parameters/2_Geometry/GsaMember1d.cs index badee36e6..ccf0be67e 100644 --- a/GsaGH/Parameters/2_Geometry/GsaMember1d.cs +++ b/GsaGH/Parameters/2_Geometry/GsaMember1d.cs @@ -354,6 +354,7 @@ public GsaMember1d Transform(Transform xform) { GsaMember1d dup = this.Duplicate(true); dup.Id = 0; + dup.LocalAxes = null; List pts = this._topo.ToList(); Point3dList xpts = new Point3dList(pts); @@ -374,6 +375,7 @@ public GsaMember1d Morph(SpaceMorph xmorph) { GsaMember1d dup = this.Duplicate(true); dup.Id = 0; + dup.LocalAxes = null; List pts = this._topo.ToList(); for (int i = 0; i < pts.Count; i++) diff --git a/GsaGH/Parameters/2_Geometry/GsaMember1dGoo.cs b/GsaGH/Parameters/2_Geometry/GsaMember1dGoo.cs index 7e32ea9cf..da9c051a7 100644 --- a/GsaGH/Parameters/2_Geometry/GsaMember1dGoo.cs +++ b/GsaGH/Parameters/2_Geometry/GsaMember1dGoo.cs @@ -149,7 +149,6 @@ public override IGH_GeometricGoo Morph(SpaceMorph xmorph) { return new GsaMember1dGoo(Value.Morph(xmorph)); } - #endregion #region drawing methods