/// <summary> /// Gather all members within the specified chain which connect between two primary members, centred on the specified member /// </summary> /// <param name="Member">The member on which to base the chain</param> /// <param name="ParallelMembers">All the members which provide continuity with the specified member</param> /// <param name="LastNode">The last visited node (leave blank at the start)</param> /// <param name="MoveDownstream">The direction in which to move next (leave blank at start)</param> /// <returns>A list of parallel members spanning between two primary members</returns> private IEnumerable <Member> GatherMembersBetweenPrimaryMembers(Member Member, IEnumerable <Member> ParallelMembers, Node LastNode = null, bool MoveDownstream = false) { bool endHere; Node currentNode; Member nextMember; HashSet <Member> members; members = new HashSet <Member>() { Member }; // Determine the next node depending on the beam orientation with regards to the direction of travel currentNode = MemberHelpers.DetermineNextNode(Member, LastNode, MoveDownstream); // Check if the member is connected to a primary member endHere = currentNode.ConnectedBeams.Any(b => this.PrimaryBeams.Contains(b)); // Get the next member nextMember = null; if (!endHere) { if (!currentNode.ConnectedMembers.Intersect(ParallelMembers).Where(m => m != Member).Any()) { nextMember = null; } else { nextMember = currentNode.ConnectedMembers.Intersect(ParallelMembers).First(m => m != Member); } } endHere = nextMember == null; if (endHere) { if (!MoveDownstream) { members.UnionWith(this.GatherMembersBetweenPrimaryMembers(Member, ParallelMembers, currentNode, true)); } } else { var output = this.GatherMembersBetweenPrimaryMembers(nextMember, ParallelMembers, currentNode, MoveDownstream); if (MoveDownstream) { members.UnionWith(output); } } return(members); }
/// <summary> /// Identify secondary structure: All members spanning directly between primary members /// </summary> /// <param name="members">The list of members to process (all members minus the primary members)</param> /// <returns>The list of members identified as being part of the secondary structure</returns> private IEnumerable <Beam> GetSecondarySupportStructure(IEnumerable <Member> Members) { HashSet <Beam> secondaryStructure; secondaryStructure = new HashSet <Beam>(); foreach (var member in Members.Where(m => this.PrimaryMembers.SelectMany(pm => pm.ConnectedMembers).Contains(m))) { int primaryCount; IEnumerable <Member> parallelMembers; IEnumerable <Member> spanningMembers; parallelMembers = MemberHelpers.GatherParallelMembers(member); spanningMembers = this.GatherMembersBetweenPrimaryMembers(member, parallelMembers).ToList(); primaryCount = spanningMembers.SelectMany(m => m.Nodes).Distinct().Count(n => n.ConnectedBeams.Any(b => this.PrimaryBeams.Contains(b))); if (primaryCount >= 2) { secondaryStructure.UnionWith(spanningMembers.SelectMany(m => m.Beams)); } } return(secondaryStructure.ToList()); }
/// <summary> /// Identify primary structure: All members spanning directly between columns /// </summary> /// <param name="members">The list of members to process (all members)</param> /// <returns>The list of members identified as being part of the primary structure</returns> private IEnumerable <Beam> GetPrimarySupportStructure(IEnumerable <Member> Members) { IEnumerable <Member> columns; HashSet <Beam> primaryStructure; HashSet <Member> processedMembers; primaryStructure = new HashSet <Beam>(); processedMembers = new HashSet <Member>(); // Identify primary structure: All members spanning directly between columns columns = Members.Where(m => m.Type == MemberType.COLUMN); foreach (var column in columns) { primaryStructure.UnionWith(column.Beams); processedMembers.Add(column); foreach (var connectedMember in column.ConnectedMembers.Except(processedMembers)) { int columnCount; IEnumerable <Member> parallelMembers; IEnumerable <Member> spanningMembers; parallelMembers = MemberHelpers.GatherParallelMembers(connectedMember); spanningMembers = GatherMembersBetweenColumns(connectedMember, parallelMembers); columnCount = spanningMembers.SelectMany(m => m.Nodes).Distinct().Count(n => n.ConnectedMembers.Any(m => m.Type == MemberType.COLUMN)); if (columnCount >= 2) { primaryStructure.UnionWith(spanningMembers.SelectMany(m => m.Beams)); } processedMembers.UnionWith(spanningMembers); } } return(primaryStructure); }
/// <summary> /// Gather member which provide continuity with the specified member, i.e. are parallel and unreleased, between columns. /// </summary> /// <param name="Member"></param> /// <returns></returns> private IEnumerable <Member> GatherMembersBetweenColumns(Member Member, IEnumerable <Member> ParallelMembers, Node LastNode = null, bool MoveDownstream = false) { bool endHere; Node currentNode; Beam nextBeam; Member nextMember; List <Member> members; members = new List <Member>() { Member }; // Determine the next node depending on the beam orientation with regards to the direction of travel currentNode = MemberHelpers.DetermineNextNode(Member, LastNode, MoveDownstream); // Check if the member is released endHere = currentNode.ConnectedBeams.Intersect(Member.Beams).Any(b => b.HasReleases); // Get the next member nextMember = null; if (!endHere) { if (!currentNode.ConnectedMembers.Intersect(ParallelMembers).Where(m => m != Member).Any()) { nextMember = null; } else { nextMember = currentNode.ConnectedMembers.Intersect(ParallelMembers).First(m => m != Member); } } endHere = nextMember == null; // Get the next beam nextBeam = nextMember == null ? null : currentNode.ConnectedBeams.Intersect(nextMember.Beams).First(); // Check if the next Beam is released right after the current node if (!endHere) { endHere = currentNode == nextBeam.StartNode ? nextBeam.StartRelease.IsReleased : nextBeam.EndRelease.IsReleased; } // Check if the member connects to a column if (!endHere && currentNode.ConnectedMembers.Any(m => m.Type == MemberType.COLUMN)) { if (nextBeam != null && nextBeam.SectionProperty != currentNode.ConnectedBeams.Intersect(Member.Beams).First().SectionProperty) { endHere = true; } } // Determine what to do depending on whether or not the chain stop here. if moving upstream, reverse and start gathering beams, // if moving upstream, return the chain. if (endHere) { if (!MoveDownstream) { members.AddRange(this.GatherMembersBetweenColumns(Member, ParallelMembers, currentNode, true)); } } else { var output = this.GatherMembersBetweenColumns(nextMember, ParallelMembers, currentNode, MoveDownstream); if (MoveDownstream) { members.AddRange(output); } } return(new HashSet <Member>(members).ToList()); }