/// <summary> /// Gather beams which provide continuity with the specified beam /// </summary> /// <param name="Beam">The start beam around which to contruct the chain</param> /// <returns></returns> public static IEnumerable<Beam> GatherParallelBeams(Beam Beam, Node LastNode = null, bool MoveDownstream = false) { Node currentNode; Beam nextBeam; IEnumerable<Beam> connectedParallelBeams; HashSet<Beam> parallelBeams; parallelBeams = new HashSet<Beam>(); if (MoveDownstream) parallelBeams.Add(Beam); // Determine which will be the next node depending on the beam orientation and direction of travel currentNode = BeamHelpers.DetermineNextNode(Beam, LastNode, MoveDownstream); // Check if the are any parallel beams among the connected beams and start gathering the beams depending on the direction of travel connectedParallelBeams = currentNode.ConnectedBeams.Where(b => b != null && b != Beam && b.DetermineBeamRelationship(Beam) == BEAMRELATION.PARALLEL); if (connectedParallelBeams.Any()) { nextBeam = connectedParallelBeams.First(); parallelBeams.UnionWith(GatherParallelBeams(nextBeam, currentNode, MoveDownstream)); } else { if (!MoveDownstream) parallelBeams.UnionWith(GatherParallelBeams(Beam, currentNode, true)); } return parallelBeams; }
/// <summary> /// Determine the next node to go to on the specified beam, depending on which the last node was /// </summary> /// <param name="Beam">The beam to inspect</param> /// <param name="LastNode">The previously visited node</param> /// <param name="MoveDownstream">The direction in which to move along the beam</param> /// <returns>The next node</returns> public static Node DetermineNextNode(Beam Beam, Node LastNode = null, bool MoveDownstream = false) { Node currentNode; // Determine which will be the next node depending on the beam orientation and direction of travel if (MoveDownstream) { currentNode = Beam.EndNode; if (LastNode != null && LastNode == Beam.EndNode) currentNode = Beam.StartNode; } else { currentNode = Beam.StartNode; if (LastNode != null && LastNode == Beam.StartNode) currentNode = Beam.EndNode; } return currentNode; }
public bool Equals(Beam m) { if ((object)m == null) return false; return this.ID == m.ID; }
public BEAMRELATIVEDIRECTION DetermineBeamRelativeDirection(Beam Beam2, double AngularTolerance = 0) { double angle = this.GetAngle(Beam2); BEAMRELATIVEDIRECTION output = BEAMRELATIVEDIRECTION.OTHER; if (angle <= AngularTolerance || (angle >= 360 - AngularTolerance && angle <= 360 + AngularTolerance)) output = BEAMRELATIVEDIRECTION.CODIRECTIONAL; else if (angle >= 180 - AngularTolerance && angle <= 180 + AngularTolerance) output = BEAMRELATIVEDIRECTION.CONTRADIRECTIONAL; return output; }
/// <summary> /// Get the relationship between the vectors of two beams /// </summary> /// <param name="Beam1"></param> /// <param name="Beam2"></param> /// <returns></returns> public BEAMRELATION DetermineBeamRelationship(Beam Beam2, double AngularTolerance = 0) { double angle; BEAMRELATION output; ; // Get angle between 0 and 90 degrees angle = Math.Abs((this.GetAngle(Beam2) + 90) % 180 - 90); output = BEAMRELATION.OTHER; if (angle <= AngularTolerance) output = BEAMRELATION.PARALLEL; else if (angle >= 90 - AngularTolerance) output = BEAMRELATION.ORTHOGONAL; return output; }
/// <summary> /// Compare the properties of this beam with those of a second beam. /// </summary> /// <param name="Beam2">The second beam with which to compare this beam's properties</param> /// <returns>True of the beams have the same property, else false</returns> public bool CompareProperties(Beam Beam2) { // Check material if (this.Material != Beam2.Material) return false; // Check section property if (this.SectionProperty != Beam2.SectionProperty) { SectionProperty s1 = this.SectionProperty; SectionProperty s2 = Beam2.SectionProperty; if (!s1.Name.Equals(s2.Name)) return false; else if (s1.Width != s2.Width || s1.Depth != s2.Depth || s1.FlangeThinkness != s2.FlangeThinkness || s1.WebThickness != s2.WebThickness || s1.Ax != s2.Ax || s1.Iy != s1.Iy || s1.Iz != s2.Iz) return false; } // Check beam beta angle if (this.BetaAngle != Beam2.BetaAngle) return false; return true; }
public bool CheckIBeamInAxisPlane(Beam Beam, BEAMAXIS Axis) { double angle; switch (Axis) { case BEAMAXIS.MAJOR: angle = Vector3D.AngleBetween(this.MinorAxis, Vector3D.CrossProduct(this.LongitudinalAxis, Beam.LongitudinalAxis)); break; case BEAMAXIS.MINOR: angle = Vector3D.AngleBetween(this.MajorAxis, Vector3D.CrossProduct(this.LongitudinalAxis, Beam.LongitudinalAxis)); break; default: throw new NotImplementedException(); } var test = Math.Round(angle, 3) % 180; return Math.Round(angle, 3) % 180 == 0; }
public static double GetAngleRelativeToBeamAxis(Beam Beam1, Beam Beam2, BEAMAXIS Axis) { double output = 0; switch (Axis) { case BEAMAXIS.LONGITUDINAL: output = Vector3D.AngleBetween(Beam1.LongitudinalAxis, Beam2.LongitudinalAxis); break; case BEAMAXIS.MAJOR: output = Vector3D.AngleBetween(Beam1.MajorAxis, Beam2.LongitudinalAxis); break; case BEAMAXIS.MINOR: output = Vector3D.AngleBetween(Beam1.MinorAxis, Beam2.LongitudinalAxis); break; } return Math.Round(output, 6); }
private IEnumerable<BeamForces> GetBeamForces(Beam Beam, ILoadCase LoadCase) { List<BeamForces> beamForces = new List<BeamForces>(); dynamic forces = new double[6]; for (int i = 0; i <= 1; i++) { this.Staad.Output.GetMemberEndForces(Beam.ID, i, LoadCase.ID, ref forces, 0); beamForces.Add(new BeamForces() { Fx = forces[0], Fy = forces[1], Fz = forces[2], Mx = forces[3], My = forces[4], Mz = forces[5], Node = i == 0 ? Beam.StartNode : Beam.EndNode, Beam = Beam, LoadCase = LoadCase }); } return beamForces; }
private Member GenerateNewMember(int MemberID, Beam Beam) { return new Member(MemberID, Beam); }
/// <summary> /// Gather the beams which form the member, starting from the specified beam /// </summary> /// <param name="Beam">The beam from which to start forming the member</param> /// <param name="MoveDownStream">The direction in which to collect members</param> /// <returns>The list of beams forming the member</returns> private List<Beam> GatherMemberBeams(Beam Beam, bool MoveDownStream) { bool terminate; List<Beam> beams = new List<Beam>() { Beam }; IEnumerable<Beam> parallelBeams = new List<Beam>(); IEnumerable<Beam> nonParallelBeams = new List<Beam>(); // Split the beams into parallel and non-parallel groups parallelBeams = MoveDownStream ? Beam.OutgoingParallelBeams : Beam.IncomingParallelBeams; nonParallelBeams = (MoveDownStream ? Beam.OutgoingBeams : Beam.IncomingBeams).Except(parallelBeams); // If there are no parallel beams, then the member obviously ends here terminate = !parallelBeams.Any(); // Check non-parallel beams if (!terminate && nonParallelBeams.Any()) if (!(this.Configuration.VerticalMembersTakePrecedence && Beam.IsParallelToY) || this.Configuration.LargerMembersTakePrecedence) foreach (Beam b in nonParallelBeams) if (terminate = this.ResolveBeamIntersection(Beam, b, MoveDownStream)) break; if (!terminate && parallelBeams.Any()) foreach (Beam beam in parallelBeams) { // Check if beam materials are continuous if (this.Configuration.BreakAtMaterialChanges && Beam.Material != beam.Material) break; // Check if beam properties are continuous if (this.Configuration.BreakAtPropertyChanges && !Beam.CompareProperties(beam)) break; // Check if beta angle is continuous if (this.Configuration.BreakAtBetaAngleChanges && Beam.BetaAngle != beam.BetaAngle) break; // Check beam releases // If moving downstream, use the start release, else use the end release. Invert releases if necessary, depending on beam relative direction BEAMRELATIVEDIRECTION beamDirection = Beam.DetermineBeamRelativeDirection(beam); if (this.Configuration.BreakAtReleases && beam.HasReleases) { if (beamDirection == BEAMRELATIVEDIRECTION.CODIRECTIONAL) { if ((MoveDownStream && beam.EndRelease.IsReleased) || (!MoveDownStream && beam.StartRelease.IsReleased)) beams.Add(beam); else break; } else { if ((MoveDownStream && beam.StartRelease.IsReleased) || (!MoveDownStream && beam.EndRelease.IsReleased)) beams.Add(beam); else break; } } else { MoveDownStream = beamDirection == BEAMRELATIVEDIRECTION.CODIRECTIONAL ? MoveDownStream : !MoveDownStream; beams.AddRange(this.GatherMemberBeams(beam, MoveDownStream)); } break; } return beams; }
public Member(int ID, Beam Beam) : this(ID, Beam.StartNode, Beam.EndNode, new List<Beam>() { Beam }) { }
private bool CheckMemberRestraint(Member MemberToCheck, Beam StartBeam, MEMBERCLASS MemberClass) { bool output; HashSet<Node> nodes; // Gather all nodes connected to the beam to check or any beams parallel to it nodes = new HashSet<Node>(BeamHelpers.GatherParallelBeams(StartBeam).SelectMany(b => new List<Node>() { b.StartNode, b.EndNode})); // Check if any of the connected members are class above the current member IEnumerable<Member> connectedMembers = nodes.SelectMany(n => n.ConnectedMembers).Where(m => m != null && m != MemberToCheck); if (MemberClass == MEMBERCLASS.PRIMARY) output = connectedMembers.Any(m => this.PrimaryMembers.Contains(m)); else if (MemberClass == MEMBERCLASS.SECONDARY) output = connectedMembers.Any(m => this.PrimaryMembers.Contains(m) || this.SecondaryMembers.Contains(m)); else if (MemberClass == MEMBERCLASS.TERTIARY) output = connectedMembers.Any(m => this.PrimaryMembers.Contains(m) || this.SecondaryMembers.Contains(m) || this.TertiaryMembers.Contains(m)); else output = false; return output; }
/// <summary> /// Determine whether or not a brace is considered as restrained. A restrained brace is one that connects directly to a column or to a primary member. /// </summary> /// <param name="StartBrace">The brace from which to start the chain</param> /// <param name="CheckedNodes">The chain of nodes that have already been checked (leave null to start)</param> /// <param name="LastNode">The last checked node (leave null to start)</param> /// <param name="MoveDownstream">The direction in which to proceed with the checks (true to move away from end to start node of the first beam, false to move in teh other direction)</param> /// <returns>The chain of restrained braces</returns> public bool CheckBraceRestraint(Beam StartBrace, HashSet<Node> CheckedNodes = null, Node LastNode = null, bool MoveDownstream = false) { bool output; Node currentNode; if (CheckedNodes == null) CheckedNodes = new HashSet<Node>(); // Determine which will be the next node depending on the beam orientation and direction of travel currentNode = BeamHelpers.DetermineNextNode(StartBrace, LastNode, MoveDownstream); output = false; if (!CheckedNodes.Contains(currentNode)) { CheckedNodes.Add(currentNode); if (currentNode.ConnectedBeams.Any(b => this.PrimaryBeams.Contains(b)) || currentNode.ConnectedMembers.SelectMany(m => m.Nodes).Any(n => n.ConnectedMembers.Any(m => m.Type == MEMBERTYPE.COLUMN))) output = true; else { IEnumerable<Beam> nextBraces = currentNode.ConnectedBeams.Where(b => b != StartBrace && b.Spec == BEAMSPEC.MEMBERTRUSS); if (nextBraces.Any()) { foreach (Beam brace in nextBraces) { if (output = this.CheckBraceRestraint(brace, CheckedNodes, currentNode, MoveDownstream)) break; } } else if (!MoveDownstream) output = this.CheckBraceRestraint(StartBrace, CheckedNodes, currentNode, true); } } return output; }
/// <summary> /// Get the angle between this beam and the specified second beam /// </summary> /// <param name="Beam2">The beam to which to determine the angle to</param> /// <returns>The angle between this beam and the second beam</returns> public double GetAngle(Beam Beam2) { return GetAngleRelativeToBeamAxis(this, Beam2, BEAMAXIS.LONGITUDINAL); }
private bool ResolveBeamIntersection(Beam Beam, Beam b, bool MoveDownStream) { bool terminate; //TODO: This needs to be refined to cover all cases, include check for connecting direction terminate = false; // Connecting beam is vertical if (b.IsParallelToY) { // Check if the columns is at least as large as the connecting beam if (b.SectionProperty.Ax >= Beam.SectionProperty.Ax) terminate = true; } // Connecting beam is horizontal else { if (b.SectionProperty.Ax >= this.Configuration.LargerMemberDifferentationFactor * Beam.SectionProperty.Ax) { Node cn = MoveDownStream ? Beam.EndNode : Beam.StartNode; if ((cn == b.StartNode && !b.StartRelease.IsReleased) || (cn == b.EndNode && !b.EndRelease.IsReleased)) terminate = true; } } return terminate; }
public double GetAngleRelativeToBeamAxis(Beam Beam2, BEAMAXIS Axis) { return GetAngleRelativeToBeamAxis(this, Beam2, Axis); }
/// <summary> /// Initialise a new beam with the specified ID /// </summary> /// <param name="BeamID">The ID of the beam to initialise</param> /// <returns></returns> private Beam GetBeam(int BeamID) { Node node1; Node node2; Beam newMember; // Get the member's start and end nodes dynamic node1Number = 0; dynamic node2Number = 0; this.Staad.Geometry.GetMemberIncidence(BeamID, ref node1Number, ref node2Number); node1 = this.Nodes.Single(o => o.ID == node1Number); node2 = this.Nodes.Single(o => o.ID == node2Number); // Generate the member newMember = new Beam(BeamID, node1, node2) { StartRelease = this.GetReleases(BeamID, 0), EndRelease = this.GetReleases(BeamID, 1) }; // Set member specs // Releases dynamic specCode = 0; this.Staad.Property.GetMemberSpecCode(BeamID, ref specCode); switch ((int)specCode) { case 0: newMember.Spec = BEAMSPEC.MEMBERTRUSS; break; case 1: newMember.Spec = BEAMSPEC.TENSIONMEMBER; break; case 2: newMember.Spec = BEAMSPEC.COMPRESSIONMEMBER; break; case 3: newMember.Spec = BEAMSPEC.CABLE; break; case 4: newMember.Spec = BEAMSPEC.JOIST; break; case -1: default: newMember.Spec = BEAMSPEC.UNSPECIFIED; break; } // Beta angle newMember.BetaAngle = Convert.ToDouble(this.Staad.Property.GetBetaAngle(BeamID)); return newMember; }