diff --git a/K2Engineering/K2Engineering/Bar.cs b/K2Engineering/K2Engineering/Bar.cs index 7f55cb0..3bb6c37 100644 --- a/K2Engineering/K2Engineering/Bar.cs +++ b/K2Engineering/K2Engineering/Bar.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using KangarooSolver; using Grasshopper.Kernel; using Rhino.Geometry; +using K2Engineering.Goals; namespace K2Engineering { @@ -61,69 +62,6 @@ protected override void SolveInstance(IGH_DataAccess DA) DA.SetData(0, barElement); } - - public class BarGoal : GoalObject - { - double restLenght; - bool isCompressionMember; - double area; - - public BarGoal(Line L, double E, double A) - { - restLenght = L.From.DistanceTo(L.To); - isCompressionMember = true; - area = A; - - PPos = new Point3d[2] { L.From, L.To }; - Move = new Vector3d[2]; - Weighting = new double[2] { (2 * E * A) / restLenght, (2 * E * A) / restLenght }; // Units: [N/m] - } - - public override void Calculate(List p) - { - Point3d ptStart = p[PIndex[0]].Position; - Point3d ptEnd = p[PIndex[1]].Position; - - //Calculate force direction - Vector3d forceDir = new Vector3d(ptEnd - ptStart); //force direction pointing from start of line to end - double currentLength = forceDir.Length; - forceDir.Unitize(); - - //Calculate extension - double extension = currentLength - restLenght; - - if (extension > 0.0) - { - isCompressionMember = false; - } - else if (extension < 0.0) - { - isCompressionMember = true; - } - - //Set vector direction and magnitude - Move[0] = forceDir * (extension / 2); //has to point to exact point according to Hooke's Law. Divide by 2 as the bar is extended in both directions with the same amount - Move[1] = -forceDir * (extension / 2); - } - - //Output geometry and force in bar. Force in [kN] and stress in [MPa] - public override object Output(List p) - { - double factor = 1.0; - if (isCompressionMember) - { - factor = -1.0; - } - - double force = factor * Weighting[0] * Move[0].Length; //Units: [N] - - //Create bar data object to store output information - DataTypes.BarData barData = new DataTypes.BarData(new Line(p[PIndex[0]].Position, p[PIndex[1]].Position), force / 1000.0, force / area); - return barData; - } - - } - /// /// Provides an Icon for the component. /// @@ -131,8 +69,6 @@ protected override System.Drawing.Bitmap Icon { get { - //You can add image files to your project resources and access them like this: - // return Resources.IconForThisComponent; return Properties.Resources.Bar; } } @@ -145,4 +81,68 @@ public override Guid ComponentGuid get { return new Guid("{ccf6dc32-7c3c-4836-94c2-e43e1e3c4f0d}"); } } } +} + +namespace K2Engineering.Goals +{ + public class BarGoal : GoalObject + { + double restLenght; + bool isCompressionMember; + double area; + + public BarGoal(Line L, double E, double A) + { + restLenght = L.From.DistanceTo(L.To); + isCompressionMember = true; + area = A; + + PPos = new Point3d[2] { L.From, L.To }; + Move = new Vector3d[2]; + Weighting = new double[2] { (2 * E * A) / restLenght, (2 * E * A) / restLenght }; // Units: [N/m] + } + + public override void Calculate(List p) + { + Point3d ptStart = p[PIndex[0]].Position; + Point3d ptEnd = p[PIndex[1]].Position; + + //Calculate force direction + Vector3d forceDir = new Vector3d(ptEnd - ptStart); //force direction pointing from start of line to end + double currentLength = forceDir.Length; + forceDir.Unitize(); + + //Calculate extension + double extension = currentLength - restLenght; + + if (extension > 0.0) + { + isCompressionMember = false; + } + else if (extension < 0.0) + { + isCompressionMember = true; + } + + //Set vector direction and magnitude + Move[0] = forceDir * (extension / 2); //has to point to exact point according to Hooke's Law. Divide by 2 as the bar is extended in both directions with the same amount + Move[1] = -forceDir * (extension / 2); + } + + //Output geometry and force in bar. Force in [kN] and stress in [MPa] + public override object Output(List p) + { + double factor = 1.0; + if (isCompressionMember) + { + factor = -1.0; + } + + double force = factor * Weighting[0] * Move[0].Length; //Units: [N] + + //Create bar data object to store output information + DataTypes.BarData barData = new DataTypes.BarData(new Line(p[PIndex[0]].Position, p[PIndex[1]].Position), force / 1000.0, force / area); + return barData; + } + } } \ No newline at end of file diff --git a/K2Engineering/K2Engineering/Beam.cs b/K2Engineering/K2Engineering/Beam.cs index cd5a46c..2bfccea 100644 --- a/K2Engineering/K2Engineering/Beam.cs +++ b/K2Engineering/K2Engineering/Beam.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using Grasshopper.Kernel; using Rhino.Geometry; using KangarooSolver; +using K2Engineering.Goals; namespace K2Engineering { @@ -83,228 +84,222 @@ protected override void SolveInstance(IGH_DataAccess DA) DA.SetData(0, beamElement); } - //Define beam goal - public class BeamGoal : GoalObject + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { - Plane P0; //Start plane (local) - Plane P1; //End plane (local) - Plane P0R; //Updated start plane (local) - Plane P1R; //Updated end plane (local) - - double restLength; - double E, G, A, Iy, Iz, It; - double thetaY0, thetaZ0, thetaY1, thetaZ1, thetaX; - - double N, VY, VZ, MY0, MZ0, MY1, MZ1, MX; - - - public BeamGoal(Plane startPlane, Plane endPlane, double eModulus, double gModulus, double area, double inertiaY, double inertiaZ, double inertiaT) + get { - restLength = startPlane.Origin.DistanceTo(endPlane.Origin); - E = eModulus; - G = gModulus; - A = area; - Iy = inertiaY; - Iz = inertiaZ; - It = inertiaT; + return Properties.Resources.Beam; + } + } + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid + { + get { return new Guid("f76cfabb-06ab-4869-a60d-c6c4865320ea"); } + } + } +} - //stiffness properties used to set the weightings - double axialStiffness = (E * A) / restLength; //Unit: N/m - int axialDigits = axialStiffness.ToString().Split('.')[0].Length; +namespace K2Engineering.Goals +{ + //Define beam goal + public class BeamGoal : GoalObject + { + Plane P0; //Start plane (local) + Plane P1; //End plane (local) + Plane P0R; //Updated start plane (local) + Plane P1R; //Updated end plane (local) - double bendingStiffness = E * Math.Max(Iy, Iz); - bendingStiffness *= 0.001; //Still needs some adjustment to improve convergence speed - int bendingDigits = bendingStiffness.ToString().Split('.')[0].Length; + double restLength; + double E, G, A, Iy, Iz, It; + double thetaY0, thetaZ0, thetaY1, thetaZ1, thetaX; + double N, VY, VZ, MY0, MZ0, MY1, MZ1, MX; - //K2 properties - PPos = new Point3d[2] {startPlane.Origin, endPlane.Origin}; - Move = new Vector3d[2]; - Weighting = new double[2] { Math.Pow(10, axialDigits), Math.Pow(10, axialDigits) }; - Torque = new Vector3d[2]; - TorqueWeighting = new double[2] { Math.Pow(10, bendingDigits), Math.Pow(10, bendingDigits) }; + public BeamGoal(Plane startPlane, Plane endPlane, double eModulus, double gModulus, double area, double inertiaY, double inertiaZ, double inertiaT) + { + restLength = startPlane.Origin.DistanceTo(endPlane.Origin); + E = eModulus; + G = gModulus; + A = area; + Iy = inertiaY; + Iz = inertiaZ; + It = inertiaT; - Plane startGlobal = new Plane(startPlane.Origin, Vector3d.XAxis, Vector3d.YAxis); - Plane endGlobal = new Plane(endPlane.Origin, Vector3d.XAxis, Vector3d.YAxis); - InitialOrientation = new Plane[2] { startGlobal, endGlobal }; + //stiffness properties used to set the weightings + double axialStiffness = (E * A) / restLength; //Unit: N/m + int axialDigits = axialStiffness.ToString().Split('.')[0].Length; - //Local end planes - P0 = startPlane; - P1 = endPlane; - P0R = P0; - P1R = P1; + double bendingStiffness = E * Math.Max(Iy, Iz); + bendingStiffness *= 0.001; //Still needs some adjustment to improve convergence speed + int bendingDigits = bendingStiffness.ToString().Split('.')[0].Length; - //Translate initial local end planes to Origin - P0.Transform(Transform.ChangeBasis(Plane.WorldXY, startGlobal)); - P1.Transform(Transform.ChangeBasis(Plane.WorldXY, endGlobal)); - } + //K2 properties + PPos = new Point3d[2] { startPlane.Origin, endPlane.Origin }; + Move = new Vector3d[2]; + Weighting = new double[2] { Math.Pow(10, axialDigits), Math.Pow(10, axialDigits) }; + Torque = new Vector3d[2]; + TorqueWeighting = new double[2] { Math.Pow(10, bendingDigits), Math.Pow(10, bendingDigits) }; - public override void Calculate(List p) - { - //Get the current positions/orientations of the nodes (global: related to InitialOrientation) - Plane P0Current = p[PIndex[0]].Orientation; - Plane P1Current = p[PIndex[1]].Orientation; + Plane startGlobal = new Plane(startPlane.Origin, Vector3d.XAxis, Vector3d.YAxis); + Plane endGlobal = new Plane(endPlane.Origin, Vector3d.XAxis, Vector3d.YAxis); + InitialOrientation = new Plane[2] { startGlobal, endGlobal }; - Vector3d elementVec = new Vector3d(P1Current.Origin - P0Current.Origin); - double currentLength = elementVec.Length; - Vector3d elementDir = new Vector3d(elementVec); - elementDir.Unitize(); - //Calculate angle changes - //Get the initial orientations of the end planes (local orientation sitting in Origin) - P0R = P0; - P1R = P1; + //Local end planes + P0 = startPlane; + P1 = endPlane; + P0R = P0; + P1R = P1; - //Orient initial local plane sitting in Origin from WorldXY to current global plane in node. This gives the updated local plane - P0R.Transform(Transform.PlaneToPlane(Plane.WorldXY, P0Current)); - P1R.Transform(Transform.PlaneToPlane(Plane.WorldXY, P1Current)); - //Extract vectors of updated local planes - Vector3d Y0 = P0R.XAxis; - Vector3d Z0 = P0R.YAxis; - Vector3d Y1 = P1R.XAxis; - Vector3d Z1 = P1R.YAxis; + //Translate initial local end planes to Origin + P0.Transform(Transform.ChangeBasis(Plane.WorldXY, startGlobal)); + P1.Transform(Transform.ChangeBasis(Plane.WorldXY, endGlobal)); + } - //Bending angle changes around local axes - thetaY0 = Vector3d.Multiply(Z0, elementVec) / elementVec.Length; - thetaZ0 = -1.0 * Vector3d.Multiply(Y0, elementVec) / elementVec.Length; //NB! Negative sign - thetaY1 = Vector3d.Multiply(Z1, elementVec) / elementVec.Length; - thetaZ1 = -1.0 * Vector3d.Multiply(Y1, elementVec) / elementVec.Length; //NB! Negative sign + public override void Calculate(List p) + { + //Get the current positions/orientations of the nodes (global: related to InitialOrientation) + Plane P0Current = p[PIndex[0]].Orientation; + Plane P1Current = p[PIndex[1]].Orientation; - //Twist angle change around element axis - thetaX = (Vector3d.Multiply(Y0, Z1) - Vector3d.Multiply(Y1, Z0)) / 2.0; + Vector3d elementVec = new Vector3d(P1Current.Origin - P0Current.Origin); + double currentLength = elementVec.Length; + Vector3d elementDir = new Vector3d(elementVec); + elementDir.Unitize(); + //Calculate angle changes + //Get the initial orientations of the end planes (local orientation sitting in Origin) + P0R = P0; + P1R = P1; - //Axial + //Orient initial local plane sitting in Origin from WorldXY to current global plane in node. This gives the updated local plane + P0R.Transform(Transform.PlaneToPlane(Plane.WorldXY, P0Current)); + P1R.Transform(Transform.PlaneToPlane(Plane.WorldXY, P1Current)); - //double extA = (Math.Pow(currentLength, 2) - Math.Pow(restLength, 2)) / (2.0 * restLength); - //double extB = (restLength / 60.0) * (4.0 * (Math.Pow(thetaY0, 2) + Math.Pow(thetaZ0, 2)) - 2.0 * ((thetaY0 * thetaY1) + (thetaZ0 * thetaZ1)) + 4.0 * (Math.Pow(thetaY1, 2) + Math.Pow(thetaZ1, 2))); - //double extension = extA + extB; //Unit: [m] + //Extract vectors of updated local planes + Vector3d Y0 = P0R.XAxis; + Vector3d Z0 = P0R.YAxis; + Vector3d Y1 = P1R.XAxis; + Vector3d Z1 = P1R.YAxis; - //For now let's use the most simple expression similar to the Bar Goal (the effect from bowing should be relatively small) - double extension = currentLength - restLength; //Unit: [m] + //Bending angle changes around local axes + thetaY0 = Vector3d.Multiply(Z0, elementVec) / elementVec.Length; + thetaZ0 = -1.0 * Vector3d.Multiply(Y0, elementVec) / elementVec.Length; //NB! Negative sign - //Element internal forces - N = ((E * A) / restLength) * extension; // Unit: [N] - - MY0 = ( ((N * restLength) / 30.0) * ((4.0 * thetaY0) - thetaY1) ) + ( ((E * Iy * 1e-6) / restLength) * ((4.0 * thetaY0) + (2.0 * thetaY1)) ); //Unit: [Nm] - MZ0 = ( ((N * restLength) / 30.0) * ((4.0 * thetaZ0) - thetaZ1) ) + ( ((E * Iz * 1e-6) / restLength) * ((4.0 * thetaZ0) + (2.0 * thetaZ1)) ); //Unit: [Nm] + thetaY1 = Vector3d.Multiply(Z1, elementVec) / elementVec.Length; + thetaZ1 = -1.0 * Vector3d.Multiply(Y1, elementVec) / elementVec.Length; //NB! Negative sign - MY1 = ( ((N * restLength) / 30.0) * ((4.0 * thetaY1) - thetaY0) ) + ( ((E * Iy * 1e-6) / restLength) * ((4.0 * thetaY1) + (2.0 * thetaY0)) ); //Unit: [Nm] - MZ1 = ( ((N * restLength) / 30.0) * ((4.0 * thetaZ1) - thetaZ0) ) + ( ((E * Iz * 1e-6) / restLength) * ((4.0 * thetaZ1) + (2.0 * thetaZ0)) ); //Unit: [Nm] + //Twist angle change around element axis + thetaX = (Vector3d.Multiply(Y0, Z1) - Vector3d.Multiply(Y1, Z0)) / 2.0; - MX = ((G * It * 1e-6) / restLength) * thetaX; //Unit: [Nm] + //Axial - //Calculate shear forces from moments - VY = (MZ1 + MZ0) / restLength; //Unit: [N] - VZ = (MY1 + MY0) / restLength; //Unit: [N] + //For now let's use the most simple expression similar to the Bar Goal (the effect from bowing should be relatively small) + double extension = currentLength - restLength; //Unit: [m] + //Element internal forces + N = ((E * A) / restLength) * extension; // Unit: [N] - //Global forces - //Force start - double F0X = (1.0 / restLength) * ((N * elementVec.X) + (MY0 * Z0.X) - (MZ0 * Y0.X) + (MY1 * Z1.X) - (MZ1 * Y1.X)); - double F0Y = (1.0 / restLength) * ((N * elementVec.Y) + (MY0 * Z0.Y) - (MZ0 * Y0.Y) + (MY1 * Z1.Y) - (MZ1 * Y1.Y)); - double F0Z = (1.0 / restLength) * ((N * elementVec.Z) + (MY0 * Z0.Z) - (MZ0 * Y0.Z) + (MY1 * Z1.Z) - (MZ1 * Y1.Z)); - Vector3d F0 = new Vector3d(F0X, F0Y, F0Z); //Unit: [N] + MY0 = (((N * restLength) / 30.0) * ((4.0 * thetaY0) - thetaY1)) + (((E * Iy * 1e-6) / restLength) * ((4.0 * thetaY0) + (2.0 * thetaY1))); //Unit: [Nm] + MZ0 = (((N * restLength) / 30.0) * ((4.0 * thetaZ0) - thetaZ1)) + (((E * Iz * 1e-6) / restLength) * ((4.0 * thetaZ0) + (2.0 * thetaZ1))); //Unit: [Nm] - //Force end - Vector3d F1 = -1.0 * F0; + MY1 = (((N * restLength) / 30.0) * ((4.0 * thetaY1) - thetaY0)) + (((E * Iy * 1e-6) / restLength) * ((4.0 * thetaY1) + (2.0 * thetaY0))); //Unit: [Nm] + MZ1 = (((N * restLength) / 30.0) * ((4.0 * thetaZ1) - thetaZ0)) + (((E * Iz * 1e-6) / restLength) * ((4.0 * thetaZ1) + (2.0 * thetaZ0))); //Unit: [Nm] + MX = ((G * It * 1e-6) / restLength) * thetaX; //Unit: [Nm] - //Permutation symbol: Includes 6 non-zero components. Is a triple product of vectors (elementVec,y,z) of an orthogonal frame in a right-handed coordinate system - //Moment start - //i=1, j=2, k=3 - double M0X_pos = (-1.0) * (((MY0 * elementVec.Z * Z0.Y) / restLength) - ((MZ0 * elementVec.Z * Y0.Y) / restLength) + ((MX * ((Y0.Y * Z1.Z) - (Z0.Y * Y1.Z))) / 2.0)); + //Calculate shear forces from moments + VY = (MZ1 + MZ0) / restLength; //Unit: [N] + VZ = (MY1 + MY0) / restLength; //Unit: [N] - //i=1, j=3, k=2 - double M0X_neg = (1.0) * (((MY0 * elementVec.Y * Z0.Z) / restLength) - ((MZ0 * elementVec.Y * Y0.Z) / restLength) + ((MX * ((Y0.Z * Z1.Y) - (Z0.Z * Y1.Y))) / 2.0)); - //i=2, j=3, k=1 - double M0Y_pos = (-1.0) * (((MY0 * elementVec.X * Z0.Z) / restLength) - ((MZ0 * elementVec.X * Y0.Z) / restLength) + ((MX * ((Y0.Z * Z1.X) - (Z0.Z * Y1.X))) / 2.0)); + //Global forces + //Force start + double F0X = (1.0 / restLength) * ((N * elementVec.X) + (MY0 * Z0.X) - (MZ0 * Y0.X) + (MY1 * Z1.X) - (MZ1 * Y1.X)); + double F0Y = (1.0 / restLength) * ((N * elementVec.Y) + (MY0 * Z0.Y) - (MZ0 * Y0.Y) + (MY1 * Z1.Y) - (MZ1 * Y1.Y)); + double F0Z = (1.0 / restLength) * ((N * elementVec.Z) + (MY0 * Z0.Z) - (MZ0 * Y0.Z) + (MY1 * Z1.Z) - (MZ1 * Y1.Z)); + Vector3d F0 = new Vector3d(F0X, F0Y, F0Z); //Unit: [N] - //i=2, j=1, k=3 - double M0Y_neg = (1.0) * (((MY0 * elementVec.Z * Z0.X) / restLength) - ((MZ0 * elementVec.Z * Y0.X) / restLength) + ((MX * ((Y0.X * Z1.Z) - (Z0.X * Y1.Z))) / 2.0)); + //Force end + Vector3d F1 = -1.0 * F0; - //i=3, j=1, k=2 - double M0Z_pos = (-1.0) * (((MY0 * elementVec.Y * Z0.X) / restLength) - ((MZ0 * elementVec.Y * Y0.X) / restLength) + ((MX * ((Y0.X * Z1.Y) - (Z0.X * Y1.Y))) / 2.0)); - //i=3, j=2, k=1 - double M0Z_neg = (1.0) * (((MY0 * elementVec.X * Z0.Y) / restLength) - ((MZ0 * elementVec.X * Y0.Y) / restLength) + ((MX * ((Y0.Y * Z1.X) - (Z0.Y * Y1.X))) / 2.0)); + //Permutation symbol: Includes 6 non-zero components. Is a triple product of vectors (elementVec,y,z) of an orthogonal frame in a right-handed coordinate system - //Sum of components - Vector3d M0 = new Vector3d(M0X_pos + M0X_neg, M0Y_pos + M0Y_neg, M0Z_pos + M0Z_neg); //Unit: [Nm] + //Moment start + //i=1, j=2, k=3 + double M0X_pos = (-1.0) * (((MY0 * elementVec.Z * Z0.Y) / restLength) - ((MZ0 * elementVec.Z * Y0.Y) / restLength) + ((MX * ((Y0.Y * Z1.Z) - (Z0.Y * Y1.Z))) / 2.0)); + //i=1, j=3, k=2 + double M0X_neg = (1.0) * (((MY0 * elementVec.Y * Z0.Z) / restLength) - ((MZ0 * elementVec.Y * Y0.Z) / restLength) + ((MX * ((Y0.Z * Z1.Y) - (Z0.Z * Y1.Y))) / 2.0)); - //Moment end - //i=1, j=2, k=3 - double M1X_pos = (-1.0) * (((MY1 * elementVec.Z * Z1.Y) / restLength) - ((MZ1 * elementVec.Z * Y1.Y) / restLength) - ((MX * ((Y0.Y * Z1.Z) - (Z0.Y * Y1.Z))) / 2.0)); + //i=2, j=3, k=1 + double M0Y_pos = (-1.0) * (((MY0 * elementVec.X * Z0.Z) / restLength) - ((MZ0 * elementVec.X * Y0.Z) / restLength) + ((MX * ((Y0.Z * Z1.X) - (Z0.Z * Y1.X))) / 2.0)); - //i=1, j=3, k=2 - double M1X_neg = (1.0) * (((MY1 * elementVec.Y * Z1.Z) / restLength) - ((MZ1 * elementVec.Y * Y1.Z) / restLength) - ((MX * ((Y0.Z * Z1.Y) - (Z0.Z * Y1.Y))) / 2.0)); + //i=2, j=1, k=3 + double M0Y_neg = (1.0) * (((MY0 * elementVec.Z * Z0.X) / restLength) - ((MZ0 * elementVec.Z * Y0.X) / restLength) + ((MX * ((Y0.X * Z1.Z) - (Z0.X * Y1.Z))) / 2.0)); - //i=2, j=3, k=1 - double M1Y_pos = (-1.0) * (((MY1 * elementVec.X * Z1.Z) / restLength) - ((MZ1 * elementVec.X * Y1.Z) / restLength) - ((MX * ((Y0.Z * Z1.X) - (Z0.Z * Y1.X))) / 2.0)); + //i=3, j=1, k=2 + double M0Z_pos = (-1.0) * (((MY0 * elementVec.Y * Z0.X) / restLength) - ((MZ0 * elementVec.Y * Y0.X) / restLength) + ((MX * ((Y0.X * Z1.Y) - (Z0.X * Y1.Y))) / 2.0)); - //i=2, j=1, k=3 - double M1Y_neg = (1.0) * (((MY1 * elementVec.Z * Z1.X) / restLength) - ((MZ1 * elementVec.Z * Y1.X) / restLength) - ((MX * ((Y0.X * Z1.Z) - (Z0.X * Y1.Z))) / 2.0)); + //i=3, j=2, k=1 + double M0Z_neg = (1.0) * (((MY0 * elementVec.X * Z0.Y) / restLength) - ((MZ0 * elementVec.X * Y0.Y) / restLength) + ((MX * ((Y0.Y * Z1.X) - (Z0.Y * Y1.X))) / 2.0)); - //i=3, j=1, k=2 - double M1Z_pos = (-1.0) * (((MY1 * elementVec.Y * Z1.X) / restLength) - ((MZ1 * elementVec.Y * Y1.X) / restLength) - ((MX * ((Y0.X * Z1.Y) - (Z0.X * Y1.Y))) / 2.0)); + //Sum of components + Vector3d M0 = new Vector3d(M0X_pos + M0X_neg, M0Y_pos + M0Y_neg, M0Z_pos + M0Z_neg); //Unit: [Nm] - //i=3, j=2, k=1 - double M1Z_neg = (1.0) * (((MY1 * elementVec.X * Z1.Y) / restLength) - ((MZ1 * elementVec.X * Y1.Y) / restLength) - ((MX * ((Y0.Y * Z1.X) - (Z0.Y * Y1.X))) / 2.0)); - //Sum of components - Vector3d M1 = new Vector3d(M1X_pos + M1X_neg, M1Y_pos + M1Y_neg, M1Z_pos + M1Z_neg); //Unit: [Nm] + //Moment end + //i=1, j=2, k=3 + double M1X_pos = (-1.0) * (((MY1 * elementVec.Z * Z1.Y) / restLength) - ((MZ1 * elementVec.Z * Y1.Y) / restLength) - ((MX * ((Y0.Y * Z1.Z) - (Z0.Y * Y1.Z))) / 2.0)); + //i=1, j=3, k=2 + double M1X_neg = (1.0) * (((MY1 * elementVec.Y * Z1.Z) / restLength) - ((MZ1 * elementVec.Y * Y1.Z) / restLength) - ((MX * ((Y0.Z * Z1.Y) - (Z0.Z * Y1.Y))) / 2.0)); - //Move and torque vectors - Move[0] = F0 / Weighting[0]; - Move[1] = F1 / Weighting[1]; + //i=2, j=3, k=1 + double M1Y_pos = (-1.0) * (((MY1 * elementVec.X * Z1.Z) / restLength) - ((MZ1 * elementVec.X * Y1.Z) / restLength) - ((MX * ((Y0.Z * Z1.X) - (Z0.Z * Y1.X))) / 2.0)); - Torque[0] = M0 / TorqueWeighting[0]; - Torque[1] = M1 / TorqueWeighting[1]; - } + //i=2, j=1, k=3 + double M1Y_neg = (1.0) * (((MY1 * elementVec.Z * Z1.X) / restLength) - ((MZ1 * elementVec.Z * Y1.X) / restLength) - ((MX * ((Y0.X * Z1.Z) - (Z0.X * Y1.Z))) / 2.0)); + //i=3, j=1, k=2 + double M1Z_pos = (-1.0) * (((MY1 * elementVec.Y * Z1.X) / restLength) - ((MZ1 * elementVec.Y * Y1.X) / restLength) - ((MX * ((Y0.X * Z1.Y) - (Z0.X * Y1.Y))) / 2.0)); - //Output moment in [kNm] and normal force/shear in [kN] - public override object Output(List p) - { - DataTypes.BeamData beamData = new DataTypes.BeamData(P0R, P1R, Math.Round(N * 1e-3, 3), Math.Round(VY * 1e-3, 3), Math.Round(VZ * 1e-3, 3), Math.Round(MX * 1e-3, 3), Math.Round(MY0 * 1e-3, 3), Math.Round(MZ0 * 1e-3, 3), Math.Round(MY1 * 1e-3, 3), Math.Round(MZ1 * 1e-3, 3)); - return beamData; - } + //i=3, j=2, k=1 + double M1Z_neg = (1.0) * (((MY1 * elementVec.X * Z1.Y) / restLength) - ((MZ1 * elementVec.X * Y1.Y) / restLength) - ((MX * ((Y0.Y * Z1.X) - (Z0.Y * Y1.X))) / 2.0)); - } + //Sum of components + Vector3d M1 = new Vector3d(M1X_pos + M1X_neg, M1Y_pos + M1Y_neg, M1Z_pos + M1Z_neg); //Unit: [Nm] + //Move and torque vectors + Move[0] = F0 / Weighting[0]; + Move[1] = F1 / Weighting[1]; - /// - /// Provides an Icon for the component. - /// - protected override System.Drawing.Bitmap Icon - { - get - { - //You can add image files to your project resources and access them like this: - // return Resources.IconForThisComponent; - return Properties.Resources.Beam; - } + Torque[0] = M0 / TorqueWeighting[0]; + Torque[1] = M1 / TorqueWeighting[1]; } - /// - /// Gets the unique ID for this component. Do not change this ID after release. - /// - public override Guid ComponentGuid + + //Output moment in [kNm] and normal force/shear in [kN] + public override object Output(List p) { - get { return new Guid("f76cfabb-06ab-4869-a60d-c6c4865320ea"); } + DataTypes.BeamData beamData = new DataTypes.BeamData(P0R, P1R, Math.Round(N * 1e-3, 3), Math.Round(VY * 1e-3, 3), Math.Round(VZ * 1e-3, 3), Math.Round(MX * 1e-3, 3), Math.Round(MY0 * 1e-3, 3), Math.Round(MZ0 * 1e-3, 3), Math.Round(MY1 * 1e-3, 3), Math.Round(MZ1 * 1e-3, 3)); + return beamData; } } } \ No newline at end of file diff --git a/K2Engineering/K2Engineering/Cable.cs b/K2Engineering/K2Engineering/Cable.cs index 9639f54..69fb4f8 100644 --- a/K2Engineering/K2Engineering/Cable.cs +++ b/K2Engineering/K2Engineering/Cable.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using KangarooSolver; using Grasshopper.Kernel; using Rhino.Geometry; +using K2Engineering.Goals; namespace K2Engineering { @@ -69,67 +70,6 @@ protected override void SolveInstance(IGH_DataAccess DA) DA.SetData(0, cableElement); } - - public class CableGoal : GoalObject - { - double startLength; - double restLength; - double area; - - public CableGoal(Line L, double E, double A, double F) - { - startLength = L.From.DistanceTo(L.To); - restLength = (startLength * E * A) / (F + (E * A)); //Units: [m] - area = A; - - PPos = new Point3d[2] { L.From, L.To }; - Move = new Vector3d[2]; - Weighting = new double[2] { (2 * E * A) / restLength, (2 * E * A) / restLength }; //Units: [N/m] - } - - public override void Calculate(List p) - { - Point3d ptStart = p[PIndex[0]].Position; - Point3d ptEnd = p[PIndex[1]].Position; - - //Calculate force direction - Vector3d forceDir = new Vector3d(ptEnd - ptStart); //force direction pointing from start of line to end - double currentLength = forceDir.Length; - forceDir.Unitize(); - - //Calculate extension - double extension = currentLength - restLength; - - //Test if cable is in tension, otherwise not active (zero force) - Vector3d forceStart = new Vector3d(0, 0, 0); - Vector3d forceEnd = new Vector3d(0, 0, 0); - if (extension > 0.0) - { - forceStart = forceDir * (extension / 2); //has to point to exact point according to Hooke's Law. Divide by 2 as the bar is extended in both directions with the same amount - forceEnd = -forceDir * (extension / 2); - } - - //Set move vectors - Move[0] = forceStart; - Move[1] = forceEnd; - } - - //Output geometry and force in cable. Force in [kN] and stress in [MPa] - public override object Output(List p) - { - double force = Weighting[0] * Move[0].Length; - - //Create bar data object to store output information - DataTypes.BarData barData = new DataTypes.BarData(new Line(p[PIndex[0]].Position, p[PIndex[1]].Position), force / 1000.0, force / area); - - return barData; - } - - } - - - - /// /// Provides an Icon for the component. /// @@ -137,8 +77,6 @@ protected override System.Drawing.Bitmap Icon { get { - //You can add image files to your project resources and access them like this: - // return Resources.IconForThisComponent; return Properties.Resources.Cable; } } @@ -151,4 +89,63 @@ public override Guid ComponentGuid get { return new Guid("{efc6c913-9056-4825-b417-01083d2316bc}"); } } } +} + +namespace K2Engineering.Goals +{ + public class CableGoal : GoalObject + { + double startLength; + double restLength; + double area; + + public CableGoal(Line L, double E, double A, double F) + { + startLength = L.From.DistanceTo(L.To); + restLength = (startLength * E * A) / (F + (E * A)); //Units: [m] + area = A; + + PPos = new Point3d[2] { L.From, L.To }; + Move = new Vector3d[2]; + Weighting = new double[2] { (2 * E * A) / restLength, (2 * E * A) / restLength }; //Units: [N/m] + } + + public override void Calculate(List p) + { + Point3d ptStart = p[PIndex[0]].Position; + Point3d ptEnd = p[PIndex[1]].Position; + + //Calculate force direction + Vector3d forceDir = new Vector3d(ptEnd - ptStart); //force direction pointing from start of line to end + double currentLength = forceDir.Length; + forceDir.Unitize(); + + //Calculate extension + double extension = currentLength - restLength; + + //Test if cable is in tension, otherwise not active (zero force) + Vector3d forceStart = new Vector3d(0, 0, 0); + Vector3d forceEnd = new Vector3d(0, 0, 0); + if (extension > 0.0) + { + forceStart = forceDir * (extension / 2); //has to point to exact point according to Hooke's Law. Divide by 2 as the bar is extended in both directions with the same amount + forceEnd = -forceDir * (extension / 2); + } + + //Set move vectors + Move[0] = forceStart; + Move[1] = forceEnd; + } + + //Output geometry and force in cable. Force in [kN] and stress in [MPa] + public override object Output(List p) + { + double force = Weighting[0] * Move[0].Length; + + //Create bar data object to store output information + DataTypes.BarData barData = new DataTypes.BarData(new Line(p[PIndex[0]].Position, p[PIndex[1]].Position), force / 1000.0, force / area); + + return barData; + } + } } \ No newline at end of file diff --git a/K2Engineering/K2Engineering/DataTypes/BarData.cs b/K2Engineering/K2Engineering/DataTypes/BarData.cs index a36215b..710126e 100644 --- a/K2Engineering/K2Engineering/DataTypes/BarData.cs +++ b/K2Engineering/K2Engineering/DataTypes/BarData.cs @@ -1,13 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; +using Grasshopper.Kernel.Types; +using GH_IO.Serialization; using Rhino.Geometry; namespace K2Engineering.DataTypes { - public class BarData + public class BarData : GH_Goo { public Line BarLine; public double Force; @@ -15,6 +13,7 @@ public class BarData public BarData() { + m_value = this; } public BarData(Line barLine, double force, double stress) @@ -22,6 +21,95 @@ public BarData(Line barLine, double force, double stress) BarLine = barLine; Force = force; Stress = stress; + m_value = this; + } + + public BarData(BarData other) + { + if (other != null) + { + BarLine = other.BarLine; + Force = other.Force; + Stress = other.Stress; + } + m_value = this; + } + + public override bool IsValid => true; + + public override string TypeName => "BarData"; + + public override string TypeDescription => "K2Engineering BarData"; + + public override IGH_Goo Duplicate() + { + return new BarData(this); + } + + public override string ToString() + { + return $"BarData [Force: {Force:F2} kN, Stress: {Stress:F2} MPa]"; + } + + public override bool Write(GH_IWriter writer) + { + writer.SetPoint3D("BarLineFrom", new GH_IO.Types.GH_Point3D(BarLine.From.X, BarLine.From.Y, BarLine.From.Z)); + writer.SetPoint3D("BarLineTo", new GH_IO.Types.GH_Point3D(BarLine.To.X, BarLine.To.Y, BarLine.To.Z)); + writer.SetDouble("Force", Force); + writer.SetDouble("Stress", Stress); + return true; + } + + public override bool Read(GH_IReader reader) + { + var pFrom = reader.GetPoint3D("BarLineFrom"); + var pTo = reader.GetPoint3D("BarLineTo"); + BarLine = new Line(new Point3d(pFrom.x, pFrom.y, pFrom.z), new Point3d(pTo.x, pTo.y, pTo.z)); + Force = reader.GetDouble("Force"); + Stress = reader.GetDouble("Stress"); + m_value = this; + return true; + } + + public override bool CastTo(ref Q target) + { + if (typeof(Q).IsAssignableFrom(typeof(BarData))) + { + target = (Q)(object)this; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(Line))) + { + target = (Q)(object)BarLine; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(GH_Line))) + { + target = (Q)(object)new GH_Line(BarLine); + return true; + } + return base.CastTo(ref target); + } + + public override bool CastFrom(object source) + { + if (source is BarData bd) + { + BarLine = bd.BarLine; + Force = bd.Force; + Stress = bd.Stress; + m_value = this; + return true; + } + if (source is GH_ObjectWrapper wrapper && wrapper.Value is BarData bdWrapper) + { + BarLine = bdWrapper.BarLine; + Force = bdWrapper.Force; + Stress = bdWrapper.Stress; + m_value = this; + return true; + } + return base.CastFrom(source); } } } diff --git a/K2Engineering/K2Engineering/DataTypes/BeamData.cs b/K2Engineering/K2Engineering/DataTypes/BeamData.cs index 4fb96f5..3ec477c 100644 --- a/K2Engineering/K2Engineering/DataTypes/BeamData.cs +++ b/K2Engineering/K2Engineering/DataTypes/BeamData.cs @@ -1,13 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; +using Grasshopper.Kernel.Types; +using GH_IO.Serialization; using Rhino.Geometry; namespace K2Engineering.DataTypes { - public class BeamData + public class BeamData : GH_Goo { public Plane P0; public Plane P1; @@ -22,6 +20,7 @@ public class BeamData public BeamData() { + m_value = this; } public BeamData(Plane p0, Plane p1, double n, double vy, double vz, double mx, double my0, double mz0, double my1, double mz1) @@ -36,6 +35,132 @@ public BeamData(Plane p0, Plane p1, double n, double vy, double vz, double mx, d Mz0 = mz0; My1 = my1; Mz1 = mz1; + m_value = this; + } + + public BeamData(BeamData other) + { + if (other != null) + { + P0 = other.P0; + P1 = other.P1; + N = other.N; + Vy = other.Vy; + Vz = other.Vz; + Mx = other.Mx; + My0 = other.My0; + Mz0 = other.Mz0; + My1 = other.My1; + Mz1 = other.Mz1; + } + m_value = this; + } + + public override bool IsValid => true; + + public override string TypeName => "BeamData"; + + public override string TypeDescription => "K2Engineering BeamData"; + + public override IGH_Goo Duplicate() + { + return new BeamData(this); + } + + public override string ToString() + { + return $"BeamData [N: {N:F2} kN, Mx: {Mx:F2} kNm]"; + } + + private void WritePlane(GH_IWriter writer, string prefix, Plane plane) + { + writer.SetPoint3D(prefix + "_Origin", new GH_IO.Types.GH_Point3D(plane.Origin.X, plane.Origin.Y, plane.Origin.Z)); + writer.SetVector3D(prefix + "_XAxis", new GH_IO.Types.GH_Vector3D(plane.XAxis.X, plane.XAxis.Y, plane.XAxis.Z)); + writer.SetVector3D(prefix + "_YAxis", new GH_IO.Types.GH_Vector3D(plane.YAxis.X, plane.YAxis.Y, plane.YAxis.Z)); + } + + private Plane ReadPlane(GH_IReader reader, string prefix) + { + var o = reader.GetPoint3D(prefix + "_Origin"); + var x = reader.GetVector3D(prefix + "_XAxis"); + var y = reader.GetVector3D(prefix + "_YAxis"); + return new Plane(new Point3d(o.x, o.y, o.z), new Vector3d(x.x, x.y, x.z), new Vector3d(y.x, y.y, y.z)); + } + + public override bool Write(GH_IWriter writer) + { + WritePlane(writer, "P0", P0); + WritePlane(writer, "P1", P1); + writer.SetDouble("N", N); + writer.SetDouble("Vy", Vy); + writer.SetDouble("Vz", Vz); + writer.SetDouble("Mx", Mx); + writer.SetDouble("My0", My0); + writer.SetDouble("Mz0", Mz0); + writer.SetDouble("My1", My1); + writer.SetDouble("Mz1", Mz1); + return true; + } + + public override bool Read(GH_IReader reader) + { + P0 = ReadPlane(reader, "P0"); + P1 = ReadPlane(reader, "P1"); + N = reader.GetDouble("N"); + Vy = reader.GetDouble("Vy"); + Vz = reader.GetDouble("Vz"); + Mx = reader.GetDouble("Mx"); + My0 = reader.GetDouble("My0"); + Mz0 = reader.GetDouble("Mz0"); + My1 = reader.GetDouble("My1"); + Mz1 = reader.GetDouble("Mz1"); + m_value = this; + return true; + } + + public override bool CastTo(ref Q target) + { + if (typeof(Q).IsAssignableFrom(typeof(BeamData))) + { + target = (Q)(object)this; + return true; + } + return base.CastTo(ref target); + } + + public override bool CastFrom(object source) + { + if (source is BeamData bd) + { + P0 = bd.P0; + P1 = bd.P1; + N = bd.N; + Vy = bd.Vy; + Vz = bd.Vz; + Mx = bd.Mx; + My0 = bd.My0; + Mz0 = bd.Mz0; + My1 = bd.My1; + Mz1 = bd.Mz1; + m_value = this; + return true; + } + if (source is GH_ObjectWrapper wrapper && wrapper.Value is BeamData bdWrapper) + { + P0 = bdWrapper.P0; + P1 = bdWrapper.P1; + N = bdWrapper.N; + Vy = bdWrapper.Vy; + Vz = bdWrapper.Vz; + Mx = bdWrapper.Mx; + My0 = bdWrapper.My0; + Mz0 = bdWrapper.Mz0; + My1 = bdWrapper.My1; + Mz1 = bdWrapper.Mz1; + m_value = this; + return true; + } + return base.CastFrom(source); } } } diff --git a/K2Engineering/K2Engineering/DataTypes/PointLoadData.cs b/K2Engineering/K2Engineering/DataTypes/PointLoadData.cs index 3e5b69d..18d0e74 100644 --- a/K2Engineering/K2Engineering/DataTypes/PointLoadData.cs +++ b/K2Engineering/K2Engineering/DataTypes/PointLoadData.cs @@ -1,23 +1,117 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; +using Grasshopper.Kernel.Types; +using GH_IO.Serialization; using Rhino.Geometry; namespace K2Engineering.DataTypes { - public class PointLoadData + public class PointLoadData : GH_Goo { public Point3d Location; public Vector3d Load; - public PointLoadData() {} + public PointLoadData() + { + m_value = this; + } public PointLoadData(Point3d location, Vector3d load) { Location = location; Load = load; + m_value = this; + } + + public PointLoadData(PointLoadData other) + { + if (other != null) + { + Location = other.Location; + Load = other.Load; + } + m_value = this; + } + + public override bool IsValid => true; + + public override string TypeName => "PointLoadData"; + + public override string TypeDescription => "K2Engineering PointLoadData"; + + public override IGH_Goo Duplicate() + { + return new PointLoadData(this); + } + + public override string ToString() + { + return $"PointLoadData [Location: {Location}, Load: {Load}]"; + } + + public override bool Write(GH_IWriter writer) + { + writer.SetPoint3D("Location", new GH_IO.Types.GH_Point3D(Location.X, Location.Y, Location.Z)); + writer.SetVector3D("Load", new GH_IO.Types.GH_Vector3D(Load.X, Load.Y, Load.Z)); + return true; + } + + public override bool Read(GH_IReader reader) + { + var loc = reader.GetPoint3D("Location"); + Location = new Point3d(loc.x, loc.y, loc.z); + var ld = reader.GetVector3D("Load"); + Load = new Vector3d(ld.x, ld.y, ld.z); + m_value = this; + return true; + } + + public override bool CastTo(ref Q target) + { + if (typeof(Q).IsAssignableFrom(typeof(PointLoadData))) + { + target = (Q)(object)this; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(Point3d))) + { + target = (Q)(object)Location; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(GH_Point))) + { + target = (Q)(object)new GH_Point(Location); + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(Vector3d))) + { + target = (Q)(object)Load; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(GH_Vector))) + { + target = (Q)(object)new GH_Vector(Load); + return true; + } + return base.CastTo(ref target); + } + + public override bool CastFrom(object source) + { + if (source is PointLoadData pld) + { + Location = pld.Location; + Load = pld.Load; + m_value = this; + return true; + } + if (source is GH_ObjectWrapper wrapper && wrapper.Value is PointLoadData pldWrapper) + { + Location = pldWrapper.Location; + Load = pldWrapper.Load; + m_value = this; + return true; + } + return base.CastFrom(source); } } } diff --git a/K2Engineering/K2Engineering/DataTypes/PressureData.cs b/K2Engineering/K2Engineering/DataTypes/PressureData.cs index 56047d7..08d4b4b 100644 --- a/K2Engineering/K2Engineering/DataTypes/PressureData.cs +++ b/K2Engineering/K2Engineering/DataTypes/PressureData.cs @@ -1,13 +1,11 @@ -using Rhino.Geometry; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Grasshopper.Kernel.Types; +using GH_IO.Serialization; +using Rhino.Geometry; namespace K2Engineering.DataTypes { - public class PressureData + public class PressureData : GH_Goo { public Point3d[] Locations; public Vector3d[] Loads; @@ -18,17 +16,22 @@ public class PressureData public int MolStart; public int MolEnd; - public PressureData() { } + public PressureData() + { + m_value = this; + } public PressureData(Point3d[] locations, Vector3d[] loads, double presStart, double presEnd, double volStart, double volEnd, int molStart, int molEnd) { - Locations = new Point3d[locations.Length]; - Loads = new Vector3d[loads.Length]; - - for(int i=0; i true; + + public override string TypeName => "PressureData"; + + public override string TypeDescription => "K2Engineering PressureData"; + + public override IGH_Goo Duplicate() + { + return new PressureData(this); + } + + public override string ToString() + { + int locCount = Locations != null ? Locations.Length : 0; + return $"PressureData [Locations: {locCount}, PresStart: {PresStart:F2}, PresEnd: {PresEnd:F2}]"; + } + + public override bool Write(GH_IWriter writer) + { + int locCount = Locations != null ? Locations.Length : 0; + writer.SetInt32("LocCount", locCount); + for (int i = 0; i < locCount; i++) + { + writer.SetPoint3D("Loc_" + i, new GH_IO.Types.GH_Point3D(Locations[i].X, Locations[i].Y, Locations[i].Z)); + } + + int loadCount = Loads != null ? Loads.Length : 0; + writer.SetInt32("LoadCount", loadCount); + for (int i = 0; i < loadCount; i++) + { + writer.SetVector3D("Load_" + i, new GH_IO.Types.GH_Vector3D(Loads[i].X, Loads[i].Y, Loads[i].Z)); + } + + writer.SetDouble("PresStart", PresStart); + writer.SetDouble("PresEnd", PresEnd); + writer.SetDouble("VolStart", VolStart); + writer.SetDouble("VolEnd", VolEnd); + writer.SetInt32("MolStart", MolStart); + writer.SetInt32("MolEnd", MolEnd); + return true; + } + + public override bool Read(GH_IReader reader) + { + int locCount = reader.GetInt32("LocCount"); + Locations = new Point3d[locCount]; + for (int i = 0; i < locCount; i++) + { + var p = reader.GetPoint3D("Loc_" + i); + Locations[i] = new Point3d(p.x, p.y, p.z); + } + + int loadCount = reader.GetInt32("LoadCount"); + Loads = new Vector3d[loadCount]; + for (int i = 0; i < loadCount; i++) + { + var v = reader.GetVector3D("Load_" + i); + Loads[i] = new Vector3d(v.x, v.y, v.z); + } + + PresStart = reader.GetDouble("PresStart"); + PresEnd = reader.GetDouble("PresEnd"); + VolStart = reader.GetDouble("VolStart"); + VolEnd = reader.GetDouble("VolEnd"); + MolStart = reader.GetInt32("MolStart"); + MolEnd = reader.GetInt32("MolEnd"); + m_value = this; + return true; + } + + public override bool CastTo(ref Q target) + { + if (typeof(Q).IsAssignableFrom(typeof(PressureData))) + { + target = (Q)(object)this; + return true; + } + return base.CastTo(ref target); + } + + public override bool CastFrom(object source) + { + if (source is PressureData pd) + { + if (pd.Locations != null) + { + Locations = new Point3d[pd.Locations.Length]; + Array.Copy(pd.Locations, Locations, pd.Locations.Length); + } + if (pd.Loads != null) + { + Loads = new Vector3d[pd.Loads.Length]; + Array.Copy(pd.Loads, Loads, pd.Loads.Length); + } + PresStart = pd.PresStart; + PresEnd = pd.PresEnd; + VolStart = pd.VolStart; + VolEnd = pd.VolEnd; + MolStart = pd.MolStart; + MolEnd = pd.MolEnd; + m_value = this; + return true; + } + if (source is GH_ObjectWrapper wrapper && wrapper.Value is PressureData pdWrapper) + { + if (pdWrapper.Locations != null) + { + Locations = new Point3d[pdWrapper.Locations.Length]; + Array.Copy(pdWrapper.Locations, Locations, pdWrapper.Locations.Length); + } + if (pdWrapper.Loads != null) + { + Loads = new Vector3d[pdWrapper.Loads.Length]; + Array.Copy(pdWrapper.Loads, Loads, pdWrapper.Loads.Length); + } + PresStart = pdWrapper.PresStart; + PresEnd = pdWrapper.PresEnd; + VolStart = pdWrapper.VolStart; + VolEnd = pdWrapper.VolEnd; + MolStart = pdWrapper.MolStart; + MolEnd = pdWrapper.MolEnd; + m_value = this; + return true; + } + return base.CastFrom(source); } } } diff --git a/K2Engineering/K2Engineering/DataTypes/RodData.cs b/K2Engineering/K2Engineering/DataTypes/RodData.cs index 55f80b6..f1b5374 100644 --- a/K2Engineering/K2Engineering/DataTypes/RodData.cs +++ b/K2Engineering/K2Engineering/DataTypes/RodData.cs @@ -1,25 +1,127 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; +using Grasshopper.Kernel.Types; +using GH_IO.Serialization; using Rhino.Geometry; namespace K2Engineering.DataTypes { - public class RodData + public class RodData : GH_Goo { public Plane BendingPlane; public double Moment; public double BendingStress; - public RodData() { } + public RodData() + { + m_value = this; + } public RodData(Plane bendingPlane, double moment, double bendingStress) { BendingPlane = bendingPlane; Moment = moment; BendingStress = bendingStress; + m_value = this; + } + + public RodData(RodData other) + { + if (other != null) + { + BendingPlane = other.BendingPlane; + Moment = other.Moment; + BendingStress = other.BendingStress; + } + m_value = this; + } + + public override bool IsValid => true; + + public override string TypeName => "RodData"; + + public override string TypeDescription => "K2Engineering RodData"; + + public override IGH_Goo Duplicate() + { + return new RodData(this); + } + + public override string ToString() + { + return $"RodData [Moment: {Moment:F2} kNm, Stress: {BendingStress:F2} MPa]"; + } + + private void WritePlane(GH_IWriter writer, string prefix, Plane plane) + { + writer.SetPoint3D(prefix + "_Origin", new GH_IO.Types.GH_Point3D(plane.Origin.X, plane.Origin.Y, plane.Origin.Z)); + writer.SetVector3D(prefix + "_XAxis", new GH_IO.Types.GH_Vector3D(plane.XAxis.X, plane.XAxis.Y, plane.XAxis.Z)); + writer.SetVector3D(prefix + "_YAxis", new GH_IO.Types.GH_Vector3D(plane.YAxis.X, plane.YAxis.Y, plane.YAxis.Z)); + } + + private Plane ReadPlane(GH_IReader reader, string prefix) + { + var o = reader.GetPoint3D(prefix + "_Origin"); + var x = reader.GetVector3D(prefix + "_XAxis"); + var y = reader.GetVector3D(prefix + "_YAxis"); + return new Plane(new Point3d(o.x, o.y, o.z), new Vector3d(x.x, x.y, x.z), new Vector3d(y.x, y.y, y.z)); + } + + public override bool Write(GH_IWriter writer) + { + WritePlane(writer, "BendingPlane", BendingPlane); + writer.SetDouble("Moment", Moment); + writer.SetDouble("BendingStress", BendingStress); + return true; + } + + public override bool Read(GH_IReader reader) + { + BendingPlane = ReadPlane(reader, "BendingPlane"); + Moment = reader.GetDouble("Moment"); + BendingStress = reader.GetDouble("BendingStress"); + m_value = this; + return true; + } + + public override bool CastTo(ref Q target) + { + if (typeof(Q).IsAssignableFrom(typeof(RodData))) + { + target = (Q)(object)this; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(Plane))) + { + target = (Q)(object)BendingPlane; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(GH_Plane))) + { + target = (Q)(object)new GH_Plane(BendingPlane); + return true; + } + return base.CastTo(ref target); + } + + public override bool CastFrom(object source) + { + if (source is RodData rd) + { + BendingPlane = rd.BendingPlane; + Moment = rd.Moment; + BendingStress = rd.BendingStress; + m_value = this; + return true; + } + if (source is GH_ObjectWrapper wrapper && wrapper.Value is RodData rdWrapper) + { + BendingPlane = rdWrapper.BendingPlane; + Moment = rdWrapper.Moment; + BendingStress = rdWrapper.BendingStress; + m_value = this; + return true; + } + return base.CastFrom(source); } } } diff --git a/K2Engineering/K2Engineering/DataTypes/Support6DOFData.cs b/K2Engineering/K2Engineering/DataTypes/Support6DOFData.cs index 76665e2..56e6877 100644 --- a/K2Engineering/K2Engineering/DataTypes/Support6DOFData.cs +++ b/K2Engineering/K2Engineering/DataTypes/Support6DOFData.cs @@ -1,24 +1,129 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; +using Grasshopper.Kernel.Types; +using GH_IO.Serialization; using Rhino.Geometry; namespace K2Engineering.DataTypes { - public class Support6DOFData + public class Support6DOFData : GH_Goo { public Plane Pln; public Vector3d ReactionForce; public Vector3d ReactionMoment; - public Support6DOFData() { } + public Support6DOFData() + { + m_value = this; + } + public Support6DOFData(Plane pln, Vector3d rf, Vector3d rm) { Pln = pln; ReactionForce = rf; ReactionMoment = rm; + m_value = this; + } + + public Support6DOFData(Support6DOFData other) + { + if (other != null) + { + Pln = other.Pln; + ReactionForce = other.ReactionForce; + ReactionMoment = other.ReactionMoment; + } + m_value = this; + } + + public override bool IsValid => true; + + public override string TypeName => "Support6DOFData"; + + public override string TypeDescription => "K2Engineering Support6DOFData"; + + public override IGH_Goo Duplicate() + { + return new Support6DOFData(this); + } + + public override string ToString() + { + return $"Support6DOFData [ReactionForce: {ReactionForce}, ReactionMoment: {ReactionMoment}]"; + } + + private void WritePlane(GH_IWriter writer, string prefix, Plane plane) + { + writer.SetPoint3D(prefix + "_Origin", new GH_IO.Types.GH_Point3D(plane.Origin.X, plane.Origin.Y, plane.Origin.Z)); + writer.SetVector3D(prefix + "_XAxis", new GH_IO.Types.GH_Vector3D(plane.XAxis.X, plane.XAxis.Y, plane.XAxis.Z)); + writer.SetVector3D(prefix + "_YAxis", new GH_IO.Types.GH_Vector3D(plane.YAxis.X, plane.YAxis.Y, plane.YAxis.Z)); + } + + private Plane ReadPlane(GH_IReader reader, string prefix) + { + var o = reader.GetPoint3D(prefix + "_Origin"); + var x = reader.GetVector3D(prefix + "_XAxis"); + var y = reader.GetVector3D(prefix + "_YAxis"); + return new Plane(new Point3d(o.x, o.y, o.z), new Vector3d(x.x, x.y, x.z), new Vector3d(y.x, y.y, y.z)); + } + + public override bool Write(GH_IWriter writer) + { + WritePlane(writer, "Pln", Pln); + writer.SetVector3D("ReactionForce", new GH_IO.Types.GH_Vector3D(ReactionForce.X, ReactionForce.Y, ReactionForce.Z)); + writer.SetVector3D("ReactionMoment", new GH_IO.Types.GH_Vector3D(ReactionMoment.X, ReactionMoment.Y, ReactionMoment.Z)); + return true; + } + + public override bool Read(GH_IReader reader) + { + Pln = ReadPlane(reader, "Pln"); + var rf = reader.GetVector3D("ReactionForce"); + ReactionForce = new Vector3d(rf.x, rf.y, rf.z); + var rm = reader.GetVector3D("ReactionMoment"); + ReactionMoment = new Vector3d(rm.x, rm.y, rm.z); + m_value = this; + return true; + } + + public override bool CastTo(ref Q target) + { + if (typeof(Q).IsAssignableFrom(typeof(Support6DOFData))) + { + target = (Q)(object)this; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(Plane))) + { + target = (Q)(object)Pln; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(GH_Plane))) + { + target = (Q)(object)new GH_Plane(Pln); + return true; + } + return base.CastTo(ref target); + } + + public override bool CastFrom(object source) + { + if (source is Support6DOFData sd) + { + Pln = sd.Pln; + ReactionForce = sd.ReactionForce; + ReactionMoment = sd.ReactionMoment; + m_value = this; + return true; + } + if (source is GH_ObjectWrapper wrapper && wrapper.Value is Support6DOFData sdWrapper) + { + Pln = sdWrapper.Pln; + ReactionForce = sdWrapper.ReactionForce; + ReactionMoment = sdWrapper.ReactionMoment; + m_value = this; + return true; + } + return base.CastFrom(source); } } } diff --git a/K2Engineering/K2Engineering/DataTypes/SupportData.cs b/K2Engineering/K2Engineering/DataTypes/SupportData.cs index b4dcb5a..55ee571 100644 --- a/K2Engineering/K2Engineering/DataTypes/SupportData.cs +++ b/K2Engineering/K2Engineering/DataTypes/SupportData.cs @@ -1,22 +1,117 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; +using Grasshopper.Kernel.Types; +using GH_IO.Serialization; using Rhino.Geometry; namespace K2Engineering.DataTypes { - public class SupportData + public class SupportData : GH_Goo { public Point3d Location; public Vector3d Reaction; - public SupportData() { } + public SupportData() + { + m_value = this; + } + public SupportData(Point3d location, Vector3d reaction) { Location = location; Reaction = reaction; + m_value = this; + } + + public SupportData(SupportData other) + { + if (other != null) + { + Location = other.Location; + Reaction = other.Reaction; + } + m_value = this; + } + + public override bool IsValid => true; + + public override string TypeName => "SupportData"; + + public override string TypeDescription => "K2Engineering SupportData"; + + public override IGH_Goo Duplicate() + { + return new SupportData(this); + } + + public override string ToString() + { + return $"SupportData [Location: {Location}, Reaction: {Reaction}]"; + } + + public override bool Write(GH_IWriter writer) + { + writer.SetPoint3D("Location", new GH_IO.Types.GH_Point3D(Location.X, Location.Y, Location.Z)); + writer.SetVector3D("Reaction", new GH_IO.Types.GH_Vector3D(Reaction.X, Reaction.Y, Reaction.Z)); + return true; + } + + public override bool Read(GH_IReader reader) + { + var loc = reader.GetPoint3D("Location"); + Location = new Point3d(loc.x, loc.y, loc.z); + var r = reader.GetVector3D("Reaction"); + Reaction = new Vector3d(r.x, r.y, r.z); + m_value = this; + return true; + } + + public override bool CastTo(ref Q target) + { + if (typeof(Q).IsAssignableFrom(typeof(SupportData))) + { + target = (Q)(object)this; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(Point3d))) + { + target = (Q)(object)Location; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(GH_Point))) + { + target = (Q)(object)new GH_Point(Location); + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(Vector3d))) + { + target = (Q)(object)Reaction; + return true; + } + if (typeof(Q).IsAssignableFrom(typeof(GH_Vector))) + { + target = (Q)(object)new GH_Vector(Reaction); + return true; + } + return base.CastTo(ref target); + } + + public override bool CastFrom(object source) + { + if (source is SupportData sd) + { + Location = sd.Location; + Reaction = sd.Reaction; + m_value = this; + return true; + } + if (source is GH_ObjectWrapper wrapper && wrapper.Value is SupportData sdWrapper) + { + Location = sdWrapper.Location; + Reaction = sdWrapper.Reaction; + m_value = this; + return true; + } + return base.CastFrom(source); } } } diff --git a/K2Engineering/K2Engineering/Load.cs b/K2Engineering/K2Engineering/Load.cs index 997c57a..315d9f0 100644 --- a/K2Engineering/K2Engineering/Load.cs +++ b/K2Engineering/K2Engineering/Load.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using KangarooSolver; using Grasshopper.Kernel; using Rhino.Geometry; +using K2Engineering.Goals; namespace K2Engineering { @@ -56,39 +57,6 @@ protected override void SolveInstance(IGH_DataAccess DA) DA.SetData(0, load); } - - public class LoadGoal : GoalObject - { - Vector3d load; - - public LoadGoal(Point3d pt, Vector3d force) - { - load = force; - - PPos = new Point3d[1] {pt}; - Move = new Vector3d[1] {load}; - Weighting = new double[1] {1.0}; - } - - - public override void Calculate(List p) - { - Move[0] = load; - } - - - //Output updated position of node where the load acts. Load in [kN] - public override object Output(List p) - { - //Create load data object to store output information - DataTypes.PointLoadData loadData = new DataTypes.PointLoadData(p[PIndex[0]].Position, Move[0] * Weighting[0] * 1e-3); - return loadData; - } - - } - - - /// /// Provides an Icon for the component. /// @@ -96,8 +64,6 @@ protected override System.Drawing.Bitmap Icon { get { - //You can add image files to your project resources and access them like this: - // return Resources.IconForThisComponent; return Properties.Resources.Load; } } @@ -110,4 +76,34 @@ public override Guid ComponentGuid get { return new Guid("{64e19caa-a444-4ac4-bbc1-5bf4d62dd406}"); } } } +} + +namespace K2Engineering.Goals +{ + public class LoadGoal : GoalObject + { + Vector3d load; + + public LoadGoal(Point3d pt, Vector3d force) + { + load = force; + + PPos = new Point3d[1] { pt }; + Move = new Vector3d[1] { load }; + Weighting = new double[1] { 1.0 }; + } + + public override void Calculate(List p) + { + Move[0] = load; + } + + //Output updated position of node where the load acts. Load in [kN] + public override object Output(List p) + { + //Create load data object to store output information + DataTypes.PointLoadData loadData = new DataTypes.PointLoadData(p[PIndex[0]].Position, Move[0] * Weighting[0] * 1e-3); + return loadData; + } + } } \ No newline at end of file diff --git a/K2Engineering/K2Engineering/Pressure.cs b/K2Engineering/K2Engineering/Pressure.cs index fd0e3ea..6144572 100644 --- a/K2Engineering/K2Engineering/Pressure.cs +++ b/K2Engineering/K2Engineering/Pressure.cs @@ -1,9 +1,10 @@ -using System; +using System; using System.Collections.Generic; using Grasshopper.Kernel; using Rhino.Geometry; using Plankton; using KangarooSolver; +using K2Engineering.Goals; namespace K2Engineering { @@ -64,217 +65,218 @@ protected override void SolveInstance(IGH_DataAccess DA) } + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon + { + get + { + return Properties.Resources.Pressure; + } + } - public class PressureGoal : GoalObject + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid { - //Global properties - PlanktonMesh pMesh; + get { return new Guid("dfe7573e-5d67-481b-8226-15fe9b07d3fd"); } + } + } +} - double pres0; - double pres1; +namespace K2Engineering.Goals +{ + public class PressureGoal : GoalObject + { + //Global properties + PlanktonMesh pMesh; - double vol0; - double vol1; + double pres0; + double pres1; - double mol0; - double mol1; + double vol0; + double vol1; - double gasConst; - double temp; + double mol0; + double mol1; - bool opt; - bool negativePres; + double gasConst; + double temp; - public PressureGoal(PlanktonMesh mesh, double p, bool option) - { - pMesh = (PlanktonMesh) mesh; + bool opt; + bool negativePres; - //Pressure - pres0 = Math.Abs(p); // Unit: [N/m2] / [Pa] - pres1 = pres0; - if (p < 0.0) - { - negativePres = true; - } - else - { - negativePres = false; - } - - //Calculate starting volume - vol0 = 0.0; // Unit: [m3] - - for (int j = 0; j < pMesh.Faces.Count; j++) - { - int[] faceVertices = pMesh.Faces.GetFaceVertices(j); + public PressureGoal(PlanktonMesh mesh, double p, bool option) + { + pMesh = (PlanktonMesh)mesh; - Point3d pA = new Point3d(pMesh.Vertices[faceVertices[0]].X, pMesh.Vertices[faceVertices[0]].Y, pMesh.Vertices[faceVertices[0]].Z); - Point3d pB = new Point3d(pMesh.Vertices[faceVertices[1]].X, pMesh.Vertices[faceVertices[1]].Y, pMesh.Vertices[faceVertices[1]].Z); - Point3d pC = new Point3d(pMesh.Vertices[faceVertices[2]].X, pMesh.Vertices[faceVertices[2]].Y, pMesh.Vertices[faceVertices[2]].Z); + //Pressure + pres0 = Math.Abs(p); // Unit: [N/m2] / [Pa] + pres1 = pres0; + if (p < 0.0) + { + negativePres = true; + } + else + { + negativePres = false; + } - Point3d pD = new Point3d(0, 0, 0); + //Calculate starting volume + vol0 = 0.0; // Unit: [m3] - Vector3d AB = pB - pA; - Vector3d AC = pC - pA; - Vector3d AD = pD - pA; + for (int j = 0; j < pMesh.Faces.Count; j++) + { + int[] faceVertices = pMesh.Faces.GetFaceVertices(j); - Vector3d cross = Vector3d.CrossProduct(AB, -AC); - double dot = Vector3d.Multiply(cross, AD); + Point3d pA = new Point3d(pMesh.Vertices[faceVertices[0]].X, pMesh.Vertices[faceVertices[0]].Y, pMesh.Vertices[faceVertices[0]].Z); + Point3d pB = new Point3d(pMesh.Vertices[faceVertices[1]].X, pMesh.Vertices[faceVertices[1]].Y, pMesh.Vertices[faceVertices[1]].Z); + Point3d pC = new Point3d(pMesh.Vertices[faceVertices[2]].X, pMesh.Vertices[faceVertices[2]].Y, pMesh.Vertices[faceVertices[2]].Z); - double v = (1.0 / 6.0) * dot; + Point3d pD = new Point3d(0, 0, 0); - vol0 += v; - } + Vector3d AB = pB - pA; + Vector3d AC = pC - pA; + Vector3d AD = pD - pA; - vol1 = vol0; + Vector3d cross = Vector3d.CrossProduct(AB, -AC); + double dot = Vector3d.Multiply(cross, AD); - //Gas constant and temperature - gasConst = 8.314472; // Unit: [J/(K*mol)] - temp = 273 + 20; // Unit: [Kelvins] Set to 20 degrees by default + double v = (1.0 / 6.0) * dot; - //Molecules - mol0 = (pres0 * vol0) / (gasConst * temp); // Unit: [moles] - mol1 = mol0; + vol0 += v; + } - opt = option; + vol1 = vol0; + //Gas constant and temperature + gasConst = 8.314472; // Unit: [J/(K*mol)] + temp = 273 + 20; // Unit: [Kelvins] Set to 20 degrees by default - PPos = new Point3d[pMesh.Vertices.Count]; - Move = new Vector3d[pMesh.Vertices.Count]; - Weighting = new double[pMesh.Vertices.Count]; + //Molecules + mol0 = (pres0 * vol0) / (gasConst * temp); // Unit: [moles] + mol1 = mol0; - for (int i = 0; i < pMesh.Vertices.Count; i++) - { - PPos[i] = new Point3d(pMesh.Vertices[i].X, pMesh.Vertices[i].Y, pMesh.Vertices[i].Z); - Move[i] = new Vector3d(0, 0, 0); - Weighting[i] = 1.0; - } + opt = option; - } + PPos = new Point3d[pMesh.Vertices.Count]; + Move = new Vector3d[pMesh.Vertices.Count]; + Weighting = new double[pMesh.Vertices.Count]; - public override void Calculate(List p) + for (int i = 0; i < pMesh.Vertices.Count; i++) { - //Lists of vertex normals and areas - Vector3d[] normals = new Vector3d[pMesh.Vertices.Count]; - double[] vertexAreas = new double[pMesh.Vertices.Count]; - - for (int j = 0; j < pMesh.Vertices.Count; j++) - { - normals[j] = new Vector3d(0, 0, 0); - vertexAreas[j] = 0.0; - } + PPos[i] = new Point3d(pMesh.Vertices[i].X, pMesh.Vertices[i].Y, pMesh.Vertices[i].Z); + Move[i] = new Vector3d(0, 0, 0); + Weighting[i] = 1.0; + } - vol1 = 0.0; + } - //Run through all mesh faces to calculate vertex normals, areas and current volume - for (int i = 0; i < pMesh.Faces.Count; i++) - { + public override void Calculate(List p) + { + //Lists of vertex normals and areas + Vector3d[] normals = new Vector3d[pMesh.Vertices.Count]; + double[] vertexAreas = new double[pMesh.Vertices.Count]; - //Get face vertices - int[] faceVertices = pMesh.Faces.GetFaceVertices(i); + for (int j = 0; j < pMesh.Vertices.Count; j++) + { + normals[j] = new Vector3d(0, 0, 0); + vertexAreas[j] = 0.0; + } - Point3d PA = p[PIndex[faceVertices[0]]].Position; - Point3d PB = p[PIndex[faceVertices[1]]].Position; - Point3d PC = p[PIndex[faceVertices[2]]].Position; + vol1 = 0.0; - Vector3d AB = PB - PA; - Vector3d BC = PC - PB; - Vector3d CA = PA - PC; - Vector3d normal = Vector3d.CrossProduct(AB, BC); - double nodalArea = normal.Length / 6.0; - normal.Unitize(); + //Run through all mesh faces to calculate vertex normals, areas and current volume + for (int i = 0; i < pMesh.Faces.Count; i++) + { - normals[faceVertices[0]] += normal; - normals[faceVertices[1]] += normal; - normals[faceVertices[2]] += normal; + //Get face vertices + int[] faceVertices = pMesh.Faces.GetFaceVertices(i); - vertexAreas[faceVertices[0]] += nodalArea; - vertexAreas[faceVertices[1]] += nodalArea; - vertexAreas[faceVertices[2]] += nodalArea; + Point3d PA = p[PIndex[faceVertices[0]]].Position; + Point3d PB = p[PIndex[faceVertices[1]]].Position; + Point3d PC = p[PIndex[faceVertices[2]]].Position; + Vector3d AB = PB - PA; + Vector3d BC = PC - PB; + Vector3d CA = PA - PC; - //Current volume - Point3d PD = new Point3d(0, 0, 0); - Vector3d AD = PD - PA; - Vector3d cross = Vector3d.CrossProduct(AB, CA); - double dot = Vector3d.Multiply(cross, AD); - vol1 += (1.0 / 6.0) * dot; - } + Vector3d normal = Vector3d.CrossProduct(AB, BC); + double nodalArea = normal.Length / 6.0; + normal.Unitize(); - //constant molecules -> pressure adjusts - if (opt == false) - { - pres1 = (mol0 * gasConst * temp) / vol1; - } - //constant pressure -> molecules adjust - else - { - mol1 = (pres0 * vol1) / (gasConst * temp); - } + normals[faceVertices[0]] += normal; + normals[faceVertices[1]] += normal; + normals[faceVertices[2]] += normal; + vertexAreas[faceVertices[0]] += nodalArea; + vertexAreas[faceVertices[1]] += nodalArea; + vertexAreas[faceVertices[2]] += nodalArea; - //Calculate pressure vector acting in each vertex in [N] - for (int k = 0; k < pMesh.Vertices.Count; k++) - { - Vector3d n = new Vector3d(normals[k]); - n.Unitize(); - if (negativePres) - { - n.Reverse(); - } - Move[k] = pres1 * vertexAreas[k] * n; - } + //Current volume + Point3d PD = new Point3d(0, 0, 0); + Vector3d AD = PD - PA; + Vector3d cross = Vector3d.CrossProduct(AB, CA); + double dot = Vector3d.Multiply(cross, AD); + vol1 += (1.0 / 6.0) * dot; } - - public override object Output(List p) + //constant molecules -> pressure adjusts + if (opt == false) { - Point3d[] vertices = new Point3d[pMesh.Vertices.Count]; - Vector3d[] pForces = new Vector3d[pMesh.Vertices.Count]; + pres1 = (mol0 * gasConst * temp) / vol1; + } + //constant pressure -> molecules adjust + else + { + mol1 = (pres0 * vol1) / (gasConst * temp); + } - for (int i = 0; i < pMesh.Vertices.Count; i++) - { - vertices[i] = p[PIndex[i]].Position; - pForces[i] = Move[i] * Weighting[i] * 1e-3; // Unit: [kN] - } - //Create pressure data object to store output information - double p0 = pres0 * 1e-3; //Unit: [kN/m2] - double p1 = pres1 * 1e-3; //Unit: [kN/m2] + //Calculate pressure vector acting in each vertex in [N] + for (int k = 0; k < pMesh.Vertices.Count; k++) + { + Vector3d n = new Vector3d(normals[k]); + n.Unitize(); if (negativePres) { - p0 *= -1.0; - p1 *= -1.0; + n.Reverse(); } - - DataTypes.PressureData presData = new DataTypes.PressureData(vertices, pForces, Math.Round(p0,3), Math.Round(p1,3), Math.Round(vol0,3), Math.Round(vol1,3), Convert.ToInt32(mol0), Convert.ToInt32(mol1)); - return presData; + Move[k] = pres1 * vertexAreas[k] * n; } } - /// - /// Provides an Icon for the component. - /// - protected override System.Drawing.Bitmap Icon + public override object Output(List p) { - get + Point3d[] vertices = new Point3d[pMesh.Vertices.Count]; + Vector3d[] pForces = new Vector3d[pMesh.Vertices.Count]; + + for (int i = 0; i < pMesh.Vertices.Count; i++) { - return Properties.Resources.Pressure; + vertices[i] = p[PIndex[i]].Position; + pForces[i] = Move[i] * Weighting[i] * 1e-3; // Unit: [kN] } - } - /// - /// Gets the unique ID for this component. Do not change this ID after release. - /// - public override Guid ComponentGuid - { - get { return new Guid("dfe7573e-5d67-481b-8226-15fe9b07d3fd"); } + //Create pressure data object to store output information + double p0 = pres0 * 1e-3; //Unit: [kN/m2] + double p1 = pres1 * 1e-3; //Unit: [kN/m2] + if (negativePres) + { + p0 *= -1.0; + p1 *= -1.0; + } + + DataTypes.PressureData presData = new DataTypes.PressureData(vertices, pForces, Math.Round(p0, 3), Math.Round(p1, 3), Math.Round(vol0, 3), Math.Round(vol1, 3), Convert.ToInt32(mol0), Convert.ToInt32(mol1)); + return presData; } + } } \ No newline at end of file diff --git a/K2Engineering/K2Engineering/Rod.cs b/K2Engineering/K2Engineering/Rod.cs index 1ab8731..df03916 100644 --- a/K2Engineering/K2Engineering/Rod.cs +++ b/K2Engineering/K2Engineering/Rod.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using KangarooSolver; using Grasshopper.Kernel; using Rhino.Geometry; +using K2Engineering.Goals; namespace K2Engineering { @@ -81,122 +82,119 @@ protected override void SolveInstance(IGH_DataAccess DA) DA.SetData(0, rodElement); } - - public class RodGoal : GoalObject + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { - Line lineA; - Line lineB; - double eModulus; - double inertia; - double zDist; - double restAngle; - - public RodGoal(Line LA, Line LB, double E, double I, double z, int opt) + get { - PPos = new Point3d[4] { LA.From, LA.To, LB.From, LB.To }; - Move = new Vector3d[4]; - Weighting = new double[4] {E*I*1e-6, E*I*1e-6, E*I*1e-6, E*I*1e-6 }; //Units: [N*m2] - - //Other - lineA = LA; - lineB = LB; - eModulus = E; - inertia = I; - zDist = z; - - if (opt == 0) - { - restAngle = Math.PI; - } - else if (opt == 1) - { - restAngle = Vector3d.VectorAngle(new Vector3d(PPos[0] - PPos[1]), new Vector3d(PPos[3] - PPos[2])); - } + return Properties.Resources.Rod; } + } + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid + { + get { return new Guid("{824f9e75-7bda-4760-bb73-ae2b40c1754b}"); } + } + } +} - public override void Calculate(List p) +namespace K2Engineering.Goals +{ + public class RodGoal : GoalObject + { + Line lineA; + Line lineB; + double eModulus; + double inertia; + double zDist; + double restAngle; + + public RodGoal(Line LA, Line LB, double E, double I, double z, int opt) + { + PPos = new Point3d[4] { LA.From, LA.To, LB.From, LB.To }; + Move = new Vector3d[4]; + Weighting = new double[4] { E * I * 1e-6, E * I * 1e-6, E * I * 1e-6, E * I * 1e-6 }; //Units: [N*m2] + + //Other + lineA = LA; + lineB = LB; + eModulus = E; + inertia = I; + zDist = z; + + if (opt == 0) { - Point3d P0 = p[PIndex[0]].Position; - Point3d P1 = p[PIndex[1]].Position; - Point3d P2 = p[PIndex[2]].Position; - Point3d P3 = p[PIndex[3]].Position; - - Vector3d V01 = P1 - P0; - Vector3d V23 = P3 - P2; - Vector3d V03 = P3 - P0; - double currentAngle = restAngle - Vector3d.VectorAngle(-V01, V23); + restAngle = Math.PI; + } + else if (opt == 1) + { + restAngle = Vector3d.VectorAngle(new Vector3d(PPos[0] - PPos[1]), new Vector3d(PPos[3] - PPos[2])); + } + } - Vector3d n = Vector3d.CrossProduct(-V01, V23); - Vector3d shearA = Vector3d.CrossProduct(-V01, n); - Vector3d shearB = Vector3d.CrossProduct(V23, n); - shearA.Unitize(); - shearB.Unitize(); + public override void Calculate(List p) + { + Point3d P0 = p[PIndex[0]].Position; + Point3d P1 = p[PIndex[1]].Position; + Point3d P2 = p[PIndex[2]].Position; + Point3d P3 = p[PIndex[3]].Position; - double shearAVal = (2.0 * Math.Sin(currentAngle)) / (V01.Length * V03.Length); //Units: [1/m2] - double shearBVal = (2.0 * Math.Sin(currentAngle)) / (V23.Length * V03.Length); + Vector3d V01 = P1 - P0; + Vector3d V23 = P3 - P2; + Vector3d V03 = P3 - P0; + double currentAngle = restAngle - Vector3d.VectorAngle(-V01, V23); - shearA *= shearAVal; - shearB *= shearBVal; + Vector3d n = Vector3d.CrossProduct(-V01, V23); + Vector3d shearA = Vector3d.CrossProduct(-V01, n); + Vector3d shearB = Vector3d.CrossProduct(V23, n); - Move[0] = shearA; - Move[1] = -shearA; - Move[2] = shearB; - Move[3] = -shearB; - } + shearA.Unitize(); + shearB.Unitize(); + double shearAVal = (2.0 * Math.Sin(currentAngle)) / (V01.Length * V03.Length); //Units: [1/m2] + double shearBVal = (2.0 * Math.Sin(currentAngle)) / (V23.Length * V03.Length); - //Output bending plane and moment between two consecutive line segments. Moment in [kNm] and stress in [MPa] - public override object Output(List p) - { - Point3d P0 = p[PIndex[0]].Position; - Point3d P1 = p[PIndex[1]].Position; - Point3d P2 = p[PIndex[2]].Position; - Point3d P3 = p[PIndex[3]].Position; - Vector3d V01 = P1 - P0; - Vector3d V23 = P3 - P2; - Vector3d n = Vector3d.CrossProduct(-V01, V23); - - //Calculate moment and bending stress - double moment = Move[0].Length * Weighting[0] * V01.Length * 1e3; //Units: [Nmm] - double bendingStress = (moment * zDist) / inertia; - - //Calculate bending plane - Vector3d planeYAxis = -(Move[1] + Move[2]) / 2.0; - Vector3d planeXAxis = Vector3d.CrossProduct(planeYAxis, n); - planeYAxis.Unitize(); - planeXAxis.Unitize(); - Plane pl = new Plane(P1, planeXAxis, planeYAxis); - - //Create rod data object to store output information - DataTypes.RodData rodData = new DataTypes.RodData(pl, moment * 1e-6, bendingStress); - return rodData; - } + shearA *= shearAVal; + shearB *= shearBVal; + Move[0] = shearA; + Move[1] = -shearA; + Move[2] = shearB; + Move[3] = -shearB; } - - /// - /// Provides an Icon for the component. - /// - protected override System.Drawing.Bitmap Icon - { - get - { - //You can add image files to your project resources and access them like this: - // return Resources.IconForThisComponent; - return Properties.Resources.Rod; - } - } - - /// - /// Gets the unique ID for this component. Do not change this ID after release. - /// - public override Guid ComponentGuid + //Output bending plane and moment between two consecutive line segments. Moment in [kNm] and stress in [MPa] + public override object Output(List p) { - get { return new Guid("{824f9e75-7bda-4760-bb73-ae2b40c1754b}"); } + Point3d P0 = p[PIndex[0]].Position; + Point3d P1 = p[PIndex[1]].Position; + Point3d P2 = p[PIndex[2]].Position; + Point3d P3 = p[PIndex[3]].Position; + Vector3d V01 = P1 - P0; + Vector3d V23 = P3 - P2; + Vector3d n = Vector3d.CrossProduct(-V01, V23); + + //Calculate moment and bending stress + double moment = Move[0].Length * Weighting[0] * V01.Length * 1e3; //Units: [Nmm] + double bendingStress = (moment * zDist) / inertia; + + //Calculate bending plane + Vector3d planeYAxis = -(Move[1] + Move[2]) / 2.0; + Vector3d planeXAxis = Vector3d.CrossProduct(planeYAxis, n); + planeYAxis.Unitize(); + planeXAxis.Unitize(); + Plane pl = new Plane(P1, planeXAxis, planeYAxis); + + //Create rod data object to store output information + DataTypes.RodData rodData = new DataTypes.RodData(pl, moment * 1e-6, bendingStress); + return rodData; } } } \ No newline at end of file diff --git a/K2Engineering/K2Engineering/Support.cs b/K2Engineering/K2Engineering/Support.cs index 9c747ad..fd09f44 100644 --- a/K2Engineering/K2Engineering/Support.cs +++ b/K2Engineering/K2Engineering/Support.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using KangarooSolver; using Grasshopper.Kernel; using Rhino.Geometry; +using K2Engineering.Goals; namespace K2Engineering { @@ -75,81 +76,79 @@ protected override void SolveInstance(IGH_DataAccess DA) DA.SetData(0, support); } - - //Define goal - public class SupportGoal : GoalObject + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { - Point3d Target = new Point3d(); - bool xFixed; - bool yFixed; - bool zFixed; - - public SupportGoal(Point3d Pt, bool x, bool y, bool z, double k) + get { - PPos = new Point3d[1] { Pt }; - Move = new Vector3d[1]; - Weighting = new double[1] { k }; - - Target = Pt; - xFixed = x; - yFixed = y; - zFixed = z; + return Properties.Resources.Support; } + } - public override void Calculate(List p) - { - Point3d currentPt = p[PIndex[0]].Position; - Vector3d moveTotal = Target - currentPt; + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid + { + get { return new Guid("{2672a780-8cb4-4da5-bd5f-67ddcbeed60b}"); } + } + } +} - if (!xFixed) - { - moveTotal.X = 0.0; - } +namespace K2Engineering.Goals +{ + //Define goal + public class SupportGoal : GoalObject + { + Point3d Target = new Point3d(); + bool xFixed; + bool yFixed; + bool zFixed; - if (!yFixed) - { - moveTotal.Y = 0.0; - } + public SupportGoal(Point3d Pt, bool x, bool y, bool z, double k) + { + PPos = new Point3d[1] { Pt }; + Move = new Vector3d[1]; + Weighting = new double[1] { k }; + + Target = Pt; + xFixed = x; + yFixed = y; + zFixed = z; + } - if (!zFixed) - { - moveTotal.Z = 0.0; - } + public override void Calculate(List p) + { + Point3d currentPt = p[PIndex[0]].Position; + Vector3d moveTotal = Target - currentPt; - Move[0] = moveTotal; + if (!xFixed) + { + moveTotal.X = 0.0; } - //Output position of support and reaction force. Force in [kN] - public override object Output(List p) + if (!yFixed) { - //Create support data object to store output information - DataTypes.SupportData supportData = new DataTypes.SupportData(p[PIndex[0]].Position, Move[0] * Weighting[0] * 1e-3); - return supportData; + moveTotal.Y = 0.0; } - } - - - - /// - /// Provides an Icon for the component. - /// - protected override System.Drawing.Bitmap Icon - { - get + if (!zFixed) { - //You can add image files to your project resources and access them like this: - // return Resources.IconForThisComponent; - return Properties.Resources.Support; + moveTotal.Z = 0.0; } + + Move[0] = moveTotal; } - /// - /// Gets the unique ID for this component. Do not change this ID after release. - /// - public override Guid ComponentGuid + //Output position of support and reaction force. Force in [kN] + public override object Output(List p) { - get { return new Guid("{2672a780-8cb4-4da5-bd5f-67ddcbeed60b}"); } + //Create support data object to store output information + DataTypes.SupportData supportData = new DataTypes.SupportData(p[PIndex[0]].Position, Move[0] * Weighting[0] * 1e-3); + return supportData; } + } } \ No newline at end of file diff --git a/K2Engineering/K2Engineering/Support6DOF.cs b/K2Engineering/K2Engineering/Support6DOF.cs index 6b3f905..1b70c8c 100644 --- a/K2Engineering/K2Engineering/Support6DOF.cs +++ b/K2Engineering/K2Engineering/Support6DOF.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using KangarooSolver; using Grasshopper.Kernel; using Rhino.Geometry; +using K2Engineering.Goals; namespace K2Engineering { @@ -83,125 +84,126 @@ protected override void SolveInstance(IGH_DataAccess DA) DA.SetData(0, support); } - //Define goal - public class Support6DOFGoal : GoalObject + /// + /// Provides an Icon for the component. + /// + protected override System.Drawing.Bitmap Icon { - public Plane plnOrig; - bool xFixed; - bool yFixed; - bool zFixed; - bool rxFixed; - bool ryFixed; - bool rzFixed; - - public Support6DOFGoal(Point3d pt, bool x, bool y, bool z, bool rx, bool ry, bool rz, double k) + get { - plnOrig = Plane.WorldXY; - plnOrig.Origin = pt; - - xFixed = x; - yFixed = y; - zFixed = z; - rxFixed = rx; - ryFixed = ry; - rzFixed = rz; - - PPos = new Point3d[1] {pt}; - Move = new Vector3d[1]; - Weighting = new double[1] {k}; - - InitialOrientation = new Plane[1] { plnOrig }; - Torque = new Vector3d[1]; - TorqueWeighting = new double[1] {k}; + return Properties.Resources.Support6DOF; } + } - public override void Calculate(List p) - { - Plane plnCurrent = p[PIndex[0]].Orientation; - - //Translation - Vector3d translation = new Vector3d(plnOrig.Origin - plnCurrent.Origin); - if (!xFixed) - { - translation.X = 0.0; - } + /// + /// Gets the unique ID for this component. Do not change this ID after release. + /// + public override Guid ComponentGuid + { + get { return new Guid("3e9e7e8a-5f44-4409-93d6-4750f4bb954a"); } + } + } +} - if (!yFixed) - { - translation.Y = 0.0; - } +namespace K2Engineering.Goals +{ + //Define goal + public class Support6DOFGoal : GoalObject + { + public Plane plnOrig; + bool xFixed; + bool yFixed; + bool zFixed; + bool rxFixed; + bool ryFixed; + bool rzFixed; + + public Support6DOFGoal(Point3d pt, bool x, bool y, bool z, bool rx, bool ry, bool rz, double k) + { + plnOrig = Plane.WorldXY; + plnOrig.Origin = pt; + + xFixed = x; + yFixed = y; + zFixed = z; + rxFixed = rx; + ryFixed = ry; + rzFixed = rz; + + PPos = new Point3d[1] { pt }; + Move = new Vector3d[1]; + Weighting = new double[1] { k }; + + InitialOrientation = new Plane[1] { plnOrig }; + Torque = new Vector3d[1]; + TorqueWeighting = new double[1] { k }; + } - if (!zFixed) - { - translation.Z = 0.0; - } + public override void Calculate(List p) + { + Plane plnCurrent = p[PIndex[0]].Orientation; - Move[0] = translation; + //Translation + Vector3d translation = new Vector3d(plnOrig.Origin - plnCurrent.Origin); + if (!xFixed) + { + translation.X = 0.0; + } + if (!yFixed) + { + translation.Y = 0.0; + } - //Rotation - Quaternion q = Quaternion.Rotation(plnCurrent, plnOrig); + if (!zFixed) + { + translation.Z = 0.0; + } - double angle = new double(); - Vector3d axis = new Vector3d(); - q.GetRotation(out angle, out axis); + Move[0] = translation; - if (angle > Math.PI) - { - angle = angle - 2.0 * Math.PI; - } - Vector3d rotation = Vector3d.Multiply(axis, angle); + //Rotation + Quaternion q = Quaternion.Rotation(plnCurrent, plnOrig); - if (!rxFixed) - { - rotation.X = 0.0; - } + double angle = new double(); + Vector3d axis = new Vector3d(); + q.GetRotation(out angle, out axis); - if (!ryFixed) - { - rotation.Y = 0.0; - } + if (angle > Math.PI) + { + angle = angle - 2.0 * Math.PI; + } - if (!rzFixed) - { - rotation.Z = 0.0; - } + Vector3d rotation = Vector3d.Multiply(axis, angle); - Torque[0] = rotation; + if (!rxFixed) + { + rotation.X = 0.0; } - //Output position of support and reaction force. Force in [kN] - public override object Output(List p) + if (!ryFixed) { - Plane pln = p[PIndex[0]].Orientation; - Vector3d rf = Vector3d.Multiply(Move[0], Weighting[0]) * 1e-3; //Units [kN] - Vector3d rm = Vector3d.Multiply(Torque[0], TorqueWeighting[0]) * 1e-3; //Units [kNm] - - DataTypes.Support6DOFData supportData = new DataTypes.Support6DOFData(pln, rf, rm); - return supportData; + rotation.Y = 0.0; } - } - /// - /// Provides an Icon for the component. - /// - protected override System.Drawing.Bitmap Icon - { - get + if (!rzFixed) { - //You can add image files to your project resources and access them like this: - // return Resources.IconForThisComponent; - return Properties.Resources.Support6DOF; + rotation.Z = 0.0; } + + Torque[0] = rotation; } - /// - /// Gets the unique ID for this component. Do not change this ID after release. - /// - public override Guid ComponentGuid + //Output position of support and reaction force. Force in [kN] + public override object Output(List p) { - get { return new Guid("3e9e7e8a-5f44-4409-93d6-4750f4bb954a"); } + Plane pln = p[PIndex[0]].Orientation; + Vector3d rf = Vector3d.Multiply(Move[0], Weighting[0]) * 1e-3; //Units [kN] + Vector3d rm = Vector3d.Multiply(Torque[0], TorqueWeighting[0]) * 1e-3; //Units [kNm] + + DataTypes.Support6DOFData supportData = new DataTypes.Support6DOFData(pln, rf, rm); + return supportData; } } } \ No newline at end of file