/// <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> /// 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()); }