/***************************************************/ private static List <int> GetInterpolationOrder(TaperedProfile taperedProfile, List <double> newPositions) { List <int> interpolationOrders = new List <int>(); List <double> originalPositions = new List <double>(taperedProfile.Profiles.Keys); for (int i = 0; i < newPositions.Count - 1; i++) { bool containsPosition = taperedProfile.Profiles.ContainsKey(newPositions[i]); bool containsNextPosition = taperedProfile.Profiles.ContainsKey(newPositions[i + 1]); if (containsPosition) { interpolationOrders.Add(taperedProfile.InterpolationOrder[originalPositions.IndexOf(newPositions[i])]); } else if (!containsPosition && !containsNextPosition) { interpolationOrders.Add(taperedProfile.InterpolationOrder[originalPositions.IndexOf(newPositions[i - 1])]); } else if (containsNextPosition) { if (taperedProfile.Profiles.ContainsKey(newPositions[i - 1])) { interpolationOrders.Add(taperedProfile.InterpolationOrder[originalPositions.IndexOf(newPositions[i - 1])]); } else { interpolationOrders.Add(taperedProfile.InterpolationOrder[originalPositions.IndexOf(newPositions[i - 2])]); } } } return(interpolationOrders); }
public static TaperedProfile TaperedProfile(List <double> positions, List <IProfile> profiles, List <int> interpolationOrder = null) { //Checks for positions and profiles if (positions.Count != profiles.Count) { Reflection.Compute.RecordError("Number of positions and profiles provided are not equal"); return(null); } else if (positions.Exists((double d) => { return(d > 1); }) || positions.Exists((double d) => { return(d < 0); })) { Reflection.Compute.RecordError("Positions must exist between 0 and 1 (inclusive)"); return(null); } if (positions.Zip(positions.Skip(1), (a, b) => new { a, b }).Any(p => p.a > p.b)) { Reflection.Compute.RecordError("Positions must be sorted in ascending order."); return(null); } //Checks for interpolationOrder if (interpolationOrder == null || interpolationOrder.Count == 0) { interpolationOrder = Enumerable.Repeat(1, positions.Count - 1).ToList(); } else if (interpolationOrder.Count == 1) { interpolationOrder = Enumerable.Repeat(interpolationOrder.First(), positions.Count - 1).ToList(); } else if (!(interpolationOrder.Count == positions.Count - 1)) { Reflection.Compute.RecordError("InterpolationOrder is between the profiles provided. Therefore, the number of interpolationOrder should be one less (n - 1) than the number of profiles/positions."); return(null); } if (interpolationOrder.Any(x => x < 1)) { Reflection.Compute.RecordError("The interpolationOrder values must be greater than 1."); return(null); } //Create ditionary for TaperedProfile SortedDictionary <double, IProfile> profileDict = new SortedDictionary <double, IProfile>(); for (int i = 0; i < positions.Count; i++) { profileDict[positions[i]] = profiles[i]; } ShapeType shape = GetShapeType(profiles); TaperedProfile taperedProfile = new TaperedProfile(profileDict, interpolationOrder, shape); return(taperedProfile); }
/***************************************************/ private bool CreateProfile(string name, TaperedProfile profile) { profile.MapPositionDomain(); IFGeometricLine lusasGeometricLine = (IFGeometricLine)d_LusasData.getAttribute("Line Geometric", name); lusasGeometricLine.setMultipleVarying(true); lusasGeometricLine.setNumberOfSections(profile.Profiles.Count); lusasGeometricLine.setValue("interpMethod", "Enhanced"); lusasGeometricLine.setSpecifyInterp(true); lusasGeometricLine.setEqualSpacing(false); lusasGeometricLine.setSymmetry(false); lusasGeometricLine.setDistanceType("Parametric"); List <double> keys = new List <double>(profile.Profiles.Keys); IProfile iProfile; for (int i = 0; i < keys.Count; i++) { profile.Profiles.TryGetValue(keys[i], out iProfile); string profileName; if (i == 0) { profileName = $"{name}-0"; } else { profileName = $"{name}-{keys[i]:G3}"; } CreateProfile(profileName, iProfile as dynamic); lusasGeometricLine.setFromLibrary("User Sections", "Local", profileName, 0, 0, i); if (i == 0) { lusasGeometricLine.setInterpolation("Constant", (double)keys[i], i); } else { lusasGeometricLine.setInterpolation("Function", (double)keys[i], i, profile.InterpolationOrder[i - 1]); } } lusasGeometricLine.setVerticalAlignment("CenterToCenter"); lusasGeometricLine.setHorizontalAlignment("CenterToCenter"); lusasGeometricLine.setAlignmentSection(1); return(true); }
public static TaperedProfile MapPositionDomain(this TaperedProfile taperedProfile) { TaperedProfile newTaperedProfile = null; List <double> positions = new List <double>(taperedProfile.Profiles.Keys); if (!positions.Contains(0) && !positions.Contains(1)) { List <double> newPositions = Compute.MapDomain(positions, positions); newTaperedProfile = Create.TaperedProfile(newPositions, new List <IProfile>(taperedProfile.Profiles.Values), taperedProfile.InterpolationOrder); } else { newTaperedProfile = taperedProfile; } return(newTaperedProfile); }
public static double VoidArea(this IProfile profile) { if (profile is TaperedProfile) { Engine.Reflection.Compute.RecordWarning("The sectional area of TaperedProfiles may vary along their length. The average area of the TaperedProfile has been returned, assuming that the section varies linearly."); TaperedProfile taperedProfile = profile as TaperedProfile; double sum = 0; for (int i = 0; i < taperedProfile.Profiles.Count - 1; i++) { double temArea = (taperedProfile.Profiles.ElementAt(i).Value.VoidArea() + taperedProfile.Profiles.ElementAt(i + 1).Value.VoidArea()) / 2; sum += temArea * System.Convert.ToDouble(taperedProfile.Profiles.ElementAt(i + 1).Key - taperedProfile.Profiles.ElementAt(i).Key); } return(sum); } List <PolyCurve> curvesZ = Engine.Geometry.Compute.IJoin(profile.Edges.ToList()); int[] depth = new int[curvesZ.Count]; if (curvesZ.Count > 1) { // find which is in which for (int i = 0; i < curvesZ.Count; i++) { for (int j = 0; j < curvesZ.Count; j++) { if (i != j) { if (curvesZ[i].IsContaining(new List <Point>() { curvesZ[j].IStartPoint() })) { depth[j]++; } } } } } curvesZ = curvesZ.Where((x, i) => depth[i] != 0).ToList(); depth = depth.Where(x => x != 0).ToArray(); // Using region integration as the Curves are defined on the XY-Plane. depth = depth.Select(x => x % 2 != 0 ? 1 : -1).ToArray(); // positive area as 1 and negative area as -1 return(curvesZ.Select((x, i) => Math.Abs(x.IIntegrateRegion(0)) * depth[i]).Sum()); }
/***************************************************/ private bool SetProfile(TaperedProfile taperProfile, string sectionName, string matName) { //Check and fix taperProfile taperProfile.MapPositionDomain(); //Decompose the taperProfile dictionary IProfile[] profiles = taperProfile.Profiles.Values.ToArray(); double[] positions = taperProfile.Profiles.Keys.ToArray(); //Add the sub-profiles to the model and create a list of names string[] profNames = new string[profiles.Length]; for (int i = 0; i < profiles.Length; i++) { profNames[i] = !string.IsNullOrEmpty(profiles[i].Name)? profiles[i].Name : sectionName + $"_{i}"; SetProfile(profiles[i] as dynamic, profNames[i], matName); } //initialize SAP inputs int nSegments = profiles.Length - 1; string[] startSec = new string[nSegments]; string[] endSec = new string[nSegments]; double[] myLength = new double[nSegments]; int[] myType = new int[nSegments]; int[] EI33 = taperProfile.InterpolationOrder.ToArray(); int[] EI22 = taperProfile.InterpolationOrder.ToArray(); //Convert list of stations to list of segments for (int i = 1; i <= nSegments; i++) { startSec[i - 1] = profNames[i - 1]; endSec[i - 1] = profNames[i]; myLength[i - 1] = positions[i] - positions[i - 1]; myType[i - 1] = 1; } //Send the tapered profile to SAP return(m_model.PropFrame.SetNonPrismatic(sectionName, nSegments, ref startSec, ref endSec, ref myLength, ref myType, ref EI33, ref EI22) == 0); }
/***************************************************/ private bool SetProfile(TaperedProfile profile, string sectionName, IMaterialFragment material) { //Map Position domain to [0,1] profile.MapPositionDomain(); // Create a section for each sub profile IProfile[] profiles = profile.Profiles.Values.ToArray(); for (int i = 0; i < profiles.Length; i++) { ISetProfile(profiles[i], sectionName + "_SubSection" + i.ToString(), material); } // Declare some variables int num = profile.Profiles.Count - 1; string[] segmentStartProfile = new string[num]; string[] segmentEndProfile = new string[num]; double[] length = new double[num]; // Formatt section names and positions to ETABS standard double[] positions = profile.Profiles.Keys.ToArray(); for (int i = 0; i < num; i++) { segmentStartProfile[i] = sectionName + "_SubSection" + (i).ToString(); // Etabs reads this in mm, and multiplying strictly does not matter (since they're relative values), but is easier on the eyes in ETBAS later length[i] = System.Convert.ToDouble(positions[i + 1] - positions[i]) * 1000; segmentEndProfile[i] = sectionName + "_SubSection" + (i + 1).ToString(); } // Some array settings int[] type = length.Select(x => 1).ToArray <int>(); // Relative Length values, (No idea what happens or why someone would mix thease) int[] eI33 = length.Select(x => 1).ToArray <int>(); // Linear variation of EI33 int[] eI22 = length.Select(x => 1).ToArray <int>(); // Linear variation of EI22 Engine.Base.Compute.RecordNote("Tapered Sections Properties are set to vary linearly along the element in ETABS."); return(m_model.PropFrame.SetNonPrismatic(sectionName, num, ref segmentStartProfile, ref segmentEndProfile, ref length, ref type, ref eI33, ref eI22) == 0); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static ISectionProperty ToSection(this IFAttribute lusasAttribute) { string attributeName = GetName(lusasAttribute); string attributeType = lusasAttribute.getAttributeType(); int rows = lusasAttribute.countRows("A"); IProfile profile; GenericSection section = null; List <int> interpolationOrders = new List <int>(); List <double> positions = new List <double>(); List <IProfile> profiles = new List <IProfile>(); for (int i = 0; i < rows; i++) { profile = ToProfile(lusasAttribute, i); double area = lusasAttribute.getValue("A", i); double rgy = lusasAttribute.getValue("ky", i); double rgz = lusasAttribute.getValue("kz", i); double j = lusasAttribute.getValue("J", i); double iy = lusasAttribute.getValue("Iyy", i); double iz = lusasAttribute.getValue("Izz", i); double iw = lusasAttribute.getValue("Cw", i); double wely = Math.Min(Math.Abs(lusasAttribute.getValue("Syt", i)), Math.Abs(lusasAttribute.getValue("Syb", i))); double welz = Math.Min(Math.Abs(lusasAttribute.getValue("Szt", i)), Math.Abs(lusasAttribute.getValue("Szb", i))); double wply = lusasAttribute.getValue("Zpy", i); double wplz = lusasAttribute.getValue("Zpz", i); double centreZ = 0; //Eccentricity is handeled in the Bar not at the section double centreY = 0; //Eccentricity is handeled in the Bar not at the section double zt = lusasAttribute.getValue("zt", i); double zb = Math.Abs(lusasAttribute.getValue("zb", i)); double yt = Math.Abs(lusasAttribute.getValue("yb", i)); //Lusas Y-Axis is opposite to the BHoM Y-axis double yb = lusasAttribute.getValue("yt", i); double asy = lusasAttribute.getValue("Asy", i); double asz = lusasAttribute.getValue("Asz", i); if (profile == null) { return(null); } profile = Engine.Structure.Compute.Integrate(profile, oM.Geometry.Tolerance.MicroDistance).Item1; if (attributeType == "Multiple Varying Geometric") { double position = lusasAttribute.getValue("distanceAlongBeam", i); positions.Add(position); profiles.Add(profile); } else { section = new GenericSection(profile, area, rgy, rgz, j, iy, iz, iw, wely, welz, wply, wplz, centreZ, centreY, zt, zb, yt, yb, asy, asz); } } if (lusasAttribute.getAttributeType() == "Multiple Varying Geometric") { for (int i = 0; i < profiles.Count - 1; i++) { interpolationOrders.Add(1); } TaperedProfile taperedProfile = Engine.Spatial.Create.TaperedProfile(positions, profiles, interpolationOrders); if (taperedProfile == null) { return(null); } section = Engine.Structure.Create.GenericSectionFromProfile(taperedProfile); } section.Name = attributeName; int adapterNameId = lusasAttribute.getID(); section.SetAdapterId(typeof(LusasId), adapterNameId); return(section); }
/***************************************************/ /**** Private Methods ****/ /***************************************************/ private static List <TaperedProfile> MapTaperedProfile(List <Bar> bars, TaperedProfile taperedProfile) { //Check profiles have the same shape if (taperedProfile.Profiles.Values.Any(x => x.Shape != taperedProfile.Profiles.Values.First().Shape)) { Reflection.Compute.RecordError("MapTaperedProfile does not support TaperedProfiles with different ShapeProfiles."); return(null); } //Get geometry of Bars List <Line> lines = bars.Select(x => x.Centreline()).ToList(); //Checks bars form a single line List <Polyline> centrelines = lines.Join(); if (lines.Join().Count > 1) { Reflection.Compute.RecordError("Bars provided do not form a single continuous line."); return(null); } Polyline centreline = centrelines[0]; //Check bars are in order List <Point> midpoints = lines.Select(x => x.PointAtParameter(0.5)).ToList(); List <Point> orderedMidpoints = midpoints.SortAlongCurve(centreline); if (!midpoints.SequenceEqual(orderedMidpoints)) { Reflection.Compute.RecordError("Bars provided are not sorted."); return(null); } List <double> originalPositions = new List <double>(taperedProfile.Profiles.Keys); List <IProfile> originalProfiles = new List <IProfile>(taperedProfile.Profiles.Values); List <TaperedProfile> taperedProfiles = new List <TaperedProfile>(); //For each bar interpolate the profiles as necessary and create a TaperedProfile foreach (Bar bar in bars) { double startPosition = centreline.ParameterAtPoint(bar.StartNode.Position); double endPosition = centreline.ParameterAtPoint(bar.EndNode.Position); double newLength = endPosition - startPosition; List <double> positions = new List <double>(originalPositions); if (!positions.Contains(startPosition)) { positions.Add(startPosition); } if (!positions.Contains(endPosition)) { positions.Add(endPosition); } positions.Sort(); int startIndex = positions.IndexOf(startPosition); int endIndex = positions.IndexOf(endPosition); //These are required to create the new TaperedProfile mapped to the Bar List <IProfile> newProfiles = new List <IProfile>(); List <double> newPositions = new List <double>(); List <int> newInterpolationOrders = GetInterpolationOrder(taperedProfile, positions); //Cycle through the positions in the extents of the Bar to get the newProfile and newPosition for (int i = startIndex; i < endIndex + 1; i++) { double position = positions[i]; IProfile newProfile; double newPosition = 0; if (position == 0) { //If the position is the same as the start of the TaperedProfile taperedProfile.Profiles.TryGetValue(0, out newProfile); newPosition = 0; } else if (position == 1) { //If the position is the same as the end of the TaperedProfile taperedProfile.Profiles.TryGetValue(1, out newProfile); newPosition = (1 - startPosition) / newLength; } else if (taperedProfile.Profiles.ContainsKey(position)) { //If the position is equal to an existing position in the TaperedProfile taperedProfile.Profiles.TryGetValue(position, out newProfile); newPosition = (positions[i] - startPosition) / newLength; } else { //If the position is between existing positions in the TaperedProfile IProfile preProfile; IProfile postProfile; double prePosition = positions[i - 1]; taperedProfile.Profiles.TryGetValue(prePosition, out preProfile); //If the both new positions are between original positions if (preProfile == null) { taperedProfile.Profiles.TryGetValue(positions[i - 2], out preProfile); prePosition = positions[i - 2]; } double postPosition = positions[i + 1]; taperedProfile.Profiles.TryGetValue(postPosition, out postProfile); //If the both new positions are between original positions if (postProfile == null) { taperedProfile.Profiles.TryGetValue(positions[i + 2], out postProfile); postPosition = positions[i + 2]; } double interpolationPosition = (position - prePosition) / (postPosition - prePosition); //One less interpolationOrder than positions/profiles int interpolationIndex = Math.Min(i, newInterpolationOrders.Count - 1); int newInterpolationOrder = newInterpolationOrders[interpolationIndex]; newProfile = Spatial.Compute.IInterpolateProfile(preProfile, postProfile, interpolationPosition, newInterpolationOrder); } newProfiles.Add(newProfile); newPositions.Add(position); } if (endIndex == 1 || endIndex - startIndex == 1) { taperedProfiles.Add(Spatial.Create.TaperedProfile(newPositions, newProfiles, newInterpolationOrders.GetRange(startIndex, 1))); } else { taperedProfiles.Add(Spatial.Create.TaperedProfile(newPositions, newProfiles, newInterpolationOrders.GetRange(startIndex, (endIndex - startIndex)))); } } return(taperedProfiles); }