/// <summary> /// Modify cross section /// </summary> /// <param name="csData">Cross section data from the CrossSection example data</param> public static void ModifyCrossSectionProcessed(CrossSectionData csData) { ICrossSection crossSection = csData.FindCrossSection(new Location("river B", 1000), "1"); if (crossSection == null) { throw new Exception("Cross section not found at location"); } // This is a cross section with raw data XSBase xsBase = crossSection.BaseCrossSection; if (xsBase == null) { throw new Exception("Not a cross section with processed data"); } for (int i = 0; i < xsBase.NumberOfProcessedLevels; i++) { xsBase.ProcessedResistanceFactors[i] *= 1.1; } // Do not call CalculateProcessedData in this case, because that will reset the // processed data. Instead set the protected flag, such that data is not updated // automatically xsBase.ProcessedDataProtected = true; }
public UKSectionLibrary() { UkbSections = new Dictionary<string, ICrossSection>(); string data = Resources.UKB.Trim(); string[] lines = data.Split('\n'); List<ICrossSection> temp = new List<ICrossSection>(); for (int i = 7; i < 103; i++) { string[] parts = lines[i].Split(','); ICrossSection section = new ICrossSection() { Name = parts[0], Area = double.Parse(parts[28].TrimEnd('\r')) / 10000, Height = double.Parse(parts[3]) / 1000, MajorSecondMomentOfArea = double.Parse(parts[16]) / 100000000, WebThickness = double.Parse(parts[5]) / 1000, FlangeThickness = double.Parse(parts[6]) / 1000, }; temp.Add(section); } temp.Reverse(); foreach (ICrossSection section in temp) { UkbSections.Add(section.Name, section); } }
public void ChangeInDefinitionUpdatesGeometry() { //v-shaped cs 100 wide var crossSectionDefinitionYZ = new CrossSectionDefinitionYZ(""); crossSectionDefinitionYZ.YZDataTable.AddCrossSectionYZRow(0, 100, 0); crossSectionDefinitionYZ.YZDataTable.AddCrossSectionYZRow(50, 0, 0); crossSectionDefinitionYZ.YZDataTable.AddCrossSectionYZRow(100, 100, 0); crossSectionDefinitionYZ.Thalweg = 50; //horizontal line var network = HydroNetworkHelper.GetSnakeHydroNetwork(new Point(0, 0), new Point(100, 0)); var branch = network.Channels.First(); ICrossSection crossSection = HydroNetworkHelper.AddCrossSectionDefinitionToBranch(branch, crossSectionDefinitionYZ, 50); var expectedGeometry = new LineString(new[] { new Coordinate(50, 50), new Coordinate(50, -50) }); //use equals exact because rounding errors occur Assert.IsTrue(expectedGeometry.EqualsExact(crossSection.Geometry, 0.0001)); //action : change the profile crossSectionDefinitionYZ.YZDataTable[0].Yq = -20; expectedGeometry = new LineString(new[] { new Coordinate(50, 70), new Coordinate(50, -50) }); Assert.IsTrue(expectedGeometry.EqualsExact(crossSection.Geometry, 0.0001)); //action: change the thalweg crossSectionDefinitionYZ.Thalweg = 40; expectedGeometry = new LineString(new[] { new Coordinate(50, 60), new Coordinate(50, -60) }); Assert.IsTrue(expectedGeometry.EqualsExact(crossSection.Geometry, 0.0001)); }
/// <summary> /// Copy the cross sections detials /// </summary> /// <param name="crossSection">The master cross section</param> public void Copy(ICrossSection crossSection) { RoadWidth = crossSection.RoadWidthValue; WithCurb = crossSection.WithCurbValue; CurbLipHeight = crossSection.CurbLipHeightValue; CurbLipSlope = crossSection.CurbLipSlopeValue; CurbWidth = crossSection.CurbWidthValue; CurbEdgeDrop = crossSection.CurbEdgeDropValue; }
public void SetUp() { nodeFactory = new NodeFactory(ModelType.Frame2D); start = nodeFactory.CreateFor2DTruss(0, 0); end = nodeFactory.CreateFor2DTruss(1, 0); elementFactory = new ElementFactory(ModelType.Frame2D); material = new GenericElasticMaterial(0, 1, 0, 1); section = new GenericCrossSection(1, 1, 1, 1); beam = elementFactory.CreateLinear3DBeam(start, end, material, section); SUT = new Linear3DBernoulliBeamStiffnessMatrixBuilder(beam); }
/// <summary> /// Gets a vaild cross section from the node /// </summary> /// <param name="node">The node</param> /// <returns>The cross section</returns> public static ICrossSection CrossSection(RoadNetworkNode node) { ICrossSection sc = node.gameObject.GetComponent <ICrossSection>(); if (sc == null) { sc = RoadConstructorHelper.CrossSectionDetails; } return(sc); }
/// <summary> /// Lerp between the two sets of values /// </summary> /// <param name="cA">The from section</param> /// <param name="cB">The To section</param> /// <param name="v">The percentage between the first and the seconded</param> /// <returns>The cross section at the percentage</returns> public static ICrossSection Lerp(ICrossSection cA, ICrossSection cB, float v) { CrossSection cs = new CrossSection(); cs.RoadWidth = Mathf.Lerp(cA.RoadWidthValue, cB.RoadWidthValue, v); cs.WithCurb = cA.WithCurbValue; cs.CurbLipHeight = Mathf.Lerp(cA.CurbLipHeightValue, cB.CurbLipHeightValue, v); cs.CurbLipSlope = Mathf.Lerp(cA.CurbLipSlopeValue, cB.CurbLipSlopeValue, v); cs.CurbWidth = Mathf.Lerp(cA.CurbWidthValue, cB.CurbWidthValue, v); cs.CurbEdgeDrop = Mathf.Lerp(cA.CurbEdgeDropValue, cB.CurbEdgeDropValue, v); return(cs); }
/// <summary> /// /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="material"></param> /// <param name="crossSection"></param> /// <returns></returns> public Linear1DBeam CreateLinear1DBeam(IFiniteElementNode start, IFiniteElementNode end, IMaterial material, ICrossSection crossSection) { Guard.AgainstInvalidState(() => { return !Linear1DBeam.IsASupportedModelType(this.ModelType); }, "Linear1DBeams are not available in a model of type {0}", this.ModelType); Linear1DBeam newBeam = new Linear1DBeam(start, end, material, crossSection); if (this.repository != null) { this.repository.Add(newBeam); } return newBeam; }
/// <summary> /// replace an existing node /// </summary> /// <param name="roadSection">The road section</param> /// <param name="crossSection">The cross section details</param> public void ReplaceRoadWith(RoadCrossSection roadSection, ICrossSection crossSection) { if (_startRoadId.ID == roadSection.ID) { _startRoadId = roadSection; _startCrossSection = crossSection; } else if (_endRoadId.ID == roadSection.ID) { _endRoadId = roadSection; _endCrossSection = crossSection; } else { Debug.LogError("StreetData.ReplaceRoadWith: Can't find node to replace"); } }
/// <summary> /// Modify cross section /// </summary> /// <param name="csData">Cross section data from the CrossSection example data</param> public static void ModifyCrossSectionRaw(CrossSectionData csData) { ICrossSection crossSection = csData.FindCrossSection(new Location("river B", 1000), "1"); if (crossSection == null) { throw new Exception("Cross section not found at location"); } // This is a cross section with raw data XSBaseRaw xsBaseRaw = crossSection.BaseCrossSection as XSBaseRaw; if (xsBaseRaw == null) { throw new Exception("Not a cross section with raw data"); } // This cross section has 3 points. // Update the first two points xsBaseRaw.Points[1].X = 0.5; xsBaseRaw.Points[1].Z = 0.5; xsBaseRaw.Points[2] = new CrossSectionPoint(0.5, 0.0); // Add two additional points xsBaseRaw.Points.Add(new CrossSectionPoint(1.0, 0.2)); xsBaseRaw.Points.Add(new CrossSectionPoint(1.0, 1.0)); // Update marker to default xsBaseRaw.UpdateMarkersToDefaults(true, true, true); // Calculates the processed levels, storage areas, radii, etc, ie, fill in all // ProcessedXXX properties. xsBaseRaw.CalculateProcessedData(); // Validates the data. The constraints are that the levels and the areas after sorting // must be monotonically increasing. IDiagnostics diagnostics = xsBaseRaw.Validate(); if (diagnostics.ErrorCountRecursive > 0) { throw new Exception(String.Format("Number of errors: {0}", diagnostics.Errors.Count)); } }
/// <summary> /// Replace the road with the same id /// </summary> /// <param name="nameStart">The first name</param> /// <param name="nameEnd">The second name</param> /// <param name="crossSectionDetails">The cross section details to use</param> /// <param name="roadCrossSection">The replacement cross section</param> public void ReplaceRoadWithId(string nameStart, string nameEnd, ICrossSection crossSectionDetails, RoadCrossSection roadCrossSection) { string[] stringArray = new string[2] { nameStart, nameEnd }; Array.Sort(stringArray); string streetFullName = string.Join("-", stringArray); StreetData street = null; if (_streets.TryGetValue(streetFullName, out street)) { street.ReplaceRoadWith(roadCrossSection, crossSectionDetails); } else { Debug.LogError("SteetData.ReplaceRoadWithId Can't find street to update node on"); } }
/// <summary> /// Add the street end /// </summary> /// <param name="nameStart">The name of the street</param> /// <param name="nameEnd">The second path of the name</param> /// <param name="crossSectionDetails">The cross section details</param> /// <param name="materialFreq">The material frequency details</param> /// <param name="roadCrossSection">The road cross section</param> public void AddStreetEnd(string nameStart, string nameEnd, ICrossSection crossSectionDetails, IMaterialFrequency materialFreq, RoadCrossSection roadCrossSection) { string[] stringArray = new string[2] { nameStart, nameEnd }; Array.Sort(stringArray); string streetFullName = string.Join("-", stringArray); StreetData street = null; if (!_streets.TryGetValue(streetFullName, out street)) { street = new StreetData(roadCrossSection, crossSectionDetails, materialFreq); _streets.Add(streetFullName, street); } else { street.AddSecondRoad(roadCrossSection, crossSectionDetails); } }
/// <summary> /// Extrude the road out, by creating a new node /// </summary> /// <returns>The newly created road section</returns> public GameObject ExtrudeRoad() { Details.CompressRoads(); Details.Modified = true; float roadAngle = GetCurrentAngle() + (float)(Math.PI / 2); if (Details.Union != UNION_TYPE.END) { roadAngle += (float)(Math.PI / 2); } Vector3 pos = MathsHelper.OffSetVector(transform.position, roadAngle, 100); GameObject newNode = RoadNetworkNodeHelper.CreateBasicNode(pos, RoadConstructorHelper.GetUniqueRoadName(gameObject), gameObject); GameObject rnnB = gameObject; RoadNetworkLayout.AddRoadToNode(newNode.GetComponent <RoadNetworkNode>(), rnnB.GetComponent <RoadNetworkNode>()); RoadNetworkLayout.AddRoadToNode(rnnB.GetComponent <RoadNetworkNode>(), newNode.GetComponent <RoadNetworkNode>()); ICrossSection sc = gameObject.GetComponent <ICrossSection>(); if (sc != null) { newNode.AddComponent <OverridableCrossSection>(); OverridableCrossSection ocs = newNode.GetComponent <OverridableCrossSection>(); ocs.Copy(sc); } IMaterialFrequency fm = gameObject.GetComponent <IMaterialFrequency>(); if (fm != null) { newNode.AddComponent <OverridableMaterialFrequency>(); OverridableMaterialFrequency ocs = newNode.GetComponent <OverridableMaterialFrequency>(); ocs.Copy(fm); } return(newNode); }
/// <summary> /// Created the intersections of the roads /// </summary> /// <param name="roadBuilderObject">The road builder object</param> public void CreateLayout(RoadBuilder roadBuilderObject) { float angleRoadStart = RoadUnionHelper.AngleClamp(RoadUnionHelper.GetAngleOfRoad(_roadNetworkNode, 0)); Vector3 pos = _roadNetworkNode.transform.position; ICrossSection sc = _roadNetworkNode.gameObject.GetComponent <ICrossSection>(); if (sc == null) { sc = RoadConstructorHelper.CrossSectionDetails; } IMaterialFrequency mf = _roadNetworkNode.gameObject.GetComponent <IMaterialFrequency>(); if (mf == null) { mf = RoadConstructorHelper.MaterialFrequencySet; } RoadCrossSection rA = new RoadCrossSection(pos, angleRoadStart, sc, mf); StreetManager.Instance.AddStreetEnd(_roadNetworkNode.name, _roadNetworkNode.Details.Roads[0].name, sc, mf, rA); }
/// <summary> /// Standard construsctors /// </summary> /// <param name="startPosition">The middle point on the road</param> /// <param name="angle">The angle of the road</param> /// <param name="crossSections">The cross section for the road</param> /// <param name="mf">The materials frequency</param> public RoadCrossSection(Vector3 startPosition, float angle, ICrossSection crossSections, IMaterialFrequency mf) { _angle = angle; float x = Mathf.Sin(angle); float z = Mathf.Cos(angle); _middle = startPosition; _left = startPosition; _left.x -= (float)(x * crossSections.RoadWidthValue / 2); _left.z += (float)(z * crossSections.RoadWidthValue / 2); _curbUpLeft = Left; if (crossSections.WithCurbValue) { _curbUpLeft.y += crossSections.CurbLipHeightValue; _curbUpLeft.x += (float)(x * -crossSections.CurbLipSlopeValue); _curbUpLeft.z -= (float)(z * -crossSections.CurbLipSlopeValue); } _curbEndLeft = _curbUpLeft; if (crossSections.WithCurbValue) { _curbEndLeft.x -= (float)(x * crossSections.CurbWidthValue); _curbEndLeft.z += (float)(z * crossSections.CurbWidthValue); } _right = startPosition; _right.x += (float)(x * crossSections.RoadWidthValue / 2); _right.z -= (float)(z * crossSections.RoadWidthValue / 2); _curbUpRight = Right; if (crossSections.WithCurbValue) { _curbUpRight.y += crossSections.CurbLipHeightValue; _curbUpRight.x += (float)(x * crossSections.CurbLipSlopeValue); _curbUpRight.z -= (float)(z * crossSections.CurbLipSlopeValue); } _curbEndRight = _curbUpRight; if (crossSections.WithCurbValue) { _curbEndRight.x += (float)(x * crossSections.CurbWidthValue); _curbEndRight.z -= (float)(z * crossSections.CurbWidthValue); } _curbEndLeftDrop = _curbEndLeft; _curbEndRightDrop = _curbEndRight; if (crossSections.WithCurbValue) { _curbEndLeftDrop.y -= crossSections.CurbEdgeDropValue; _curbEndRightDrop.y -= crossSections.CurbEdgeDropValue; } if (crossSections.WithCurbValue) { _curbLipHeight = crossSections.CurbLipHeightValue; _curbEdgeDrop = crossSections.CurbEdgeDropValue; } else { _curbLipHeight = 0; _curbEdgeDrop = 0; } }
internal CrossSection(ICrossSection cs) { _cs = cs; _xsec = (XSOpen)_cs.BaseCrossSection; Line = new XYPolyline(); }
private double GetCurrentIy(int crossSectionNumber) { ICrossSection currentCrossSection = model.scheme.CrossSections.Where(cs => cs.Number == crossSectionNumber).FirstOrDefault(); return(currentCrossSection.Iy); }
/// <summary> /// Standard Constructor /// </summary> /// <param name="id">The id of the first road</param> /// <param name="crossSection">The cross section details</param> /// <param name="mf">The materials frequency</param> public StreetData(RoadCrossSection id, ICrossSection crossSection, IMaterialFrequency mf) { _startRoadId = id; _startCrossSection = crossSection; _materialFrequency = mf; }
/// <summary> /// /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="mat"></param> /// <param name="section"></param> protected LinearBeam(IFiniteElementNode start, IFiniteElementNode end, IMaterial mat, ICrossSection section) : base(start, end) { Guard.AgainstNullArgument(mat, "mat"); Guard.AgainstNullArgument(section, "section"); this.Material = mat; this.CrossSection = section; }
/// <summary> /// Add a second road /// </summary> /// <param name="roadSection">The road section</param> /// <param name="crossSection">The cross section details</param> public void AddSecondRoad(RoadCrossSection roadSection, ICrossSection crossSection) { _endRoadId = roadSection; _endCrossSection = crossSection; }
/*** Public methods ****************************************************************************************************/ /// <summary> /// Public method that calculates beam results using beam input values, supports, and loads, entered by User. /// Method saves results to public string CommonItems.stringBeamResultsthat can be retrieved elsewhere. /// </summary> public static void CalculateBeamResults() { //Debug.WriteLine("CalculateResults.CalculateBeamResults(): Method entered."); // Initialize output string with beam properties. Output results will be added to this string as they are calculated. CommonItems.stringOutputResults = CreateBeamPropertiesString(); // Create a new instance of Scheme class with static scheme information. IScheme iScheme = new Scheme(); // Create a new instance of Material class. IMaterial iMaterial = iScheme.IMaterialNew(); iMaterial.IntNumber = 1; // Potentially can use multiple materials across beam length. iMaterial.StringName = CommonItems.stringNameMaterial; iMaterial.DoubleYoungsModulus = CommonItems.doubleYoungsModulus; iMaterial.DoublePoissonsRatio = CommonItems.doublePoissonsRatio; iScheme.ListIMaterial.Add(iMaterial); // Add an instance of Material class to the list of materials // Create a new instance of CrossSection class. ICrossSection iCrossSection = iScheme.ICrossSectionNew(); iCrossSection.IntNumber = 1; // Potentially can use multiple cross sections across beam length. iCrossSection.StringName = CommonItems.stringNameCrossSection; iCrossSection.DoubleAreaMomentOfInertia = CommonItems.doubleInertia; iScheme.ListICrossSection.Add(iCrossSection); // Add an instance of CrossSection class to the list of cross sections // Create sorted list of INodes that contains all supports and all concentrated loads. List <INode> listINodesSorted = BuildNodeList(); // Following is dubug code that shows listINodesSorted by position to verify if nodes sorted properly. //int intNodeIndex = 0; //foreach (INode iNodeItem in listINodesSorted) //{ // Debug.WriteLine($"iNodeItem[{intNodeIndex}]: DoubleNodePosition={iNodeItem.DoubleNodePosition}, BoolNodeSupport={iNodeItem.BoolNodeSupport}"); // intNodeIndex++; //} // // Create multiple new instances of INode from listINodesSorted. int intINodeCounter = 1; // First node number alway is 1. INode iNode; foreach (INode iNodeItem in listINodesSorted) { iNode = iScheme.INodeNew(); iNode.DoubleNodePosition = iNodeItem.DoubleNodePosition; iNode.IntNumber = intINodeCounter++; iNode.BoolNodeSupport = iNodeItem.BoolNodeSupport; iNode.IntNodeDofDisplacement = iNodeItem.IntNodeDofDisplacement; iNode.IntNodeDofRotation = iNodeItem.IntNodeDofRotation; iNode.DoubleNodeForce = iNodeItem.DoubleNodeForce; iNode.DoubleNodeMoment = iNodeItem.DoubleNodeMoment; iScheme.ListINode.Add(iNode); } listINodesSorted.Clear(); // Clean up some by clearing original list values since not needed after copy to iScheme.ListINode. // Send node output values to Debug! //Debug.WriteLine($"\nCalculateResults.cs.CalculateResults(): List iScheme.ListINode should be sorted by DoubleNodePosition. scheme.ListINode.Count={iScheme.ListINode.Count}"); //foreach (INode iNodeItem in iScheme.ListINode) //{ // Debug.WriteLine($" DoubleNodePosition={iNodeItem.DoubleNodePosition}, IntNumber={iNodeItem.IntNumber}, BoolNodeSupport={iNodeItem.BoolNodeSupport}, IntNodeDofDisplacement={iNodeItem.IntNodeDofDisplacement}, IntNodeDofRotation={iNodeItem.IntNodeDofRotation}, DoubleNodeForce={iNodeItem.DoubleNodeForce}, DoubleNodeMoment={iNodeItem.DoubleNodeMoment}"); //} //Debug.WriteLine(""); // // Create multiple new instances of IElement. Create a new element between each INode in iScheme.ListINode. for (int i = 1; i < iScheme.ListINode.Count; i++) { IElement iElement = iScheme.IElementNew(); iElement.IntNumber = i; iElement.IntNodeLeft = i; iElement.IntNodeRight = i + 1; iElement.IntMaterial = 1; // Note: Underlying FEM methods allow use of different material per element. iElement.IntCrossSection = 1; // Note: Underlying FEM methods allow use of different CrossSection per element. iScheme.ListIElement.Add(iElement); } //Debug.WriteLine($"\n\nCalculateResults.cs.CalculateResults(): iScheme.ListINode.Count={iScheme.ListINode.Count}, scheme.ListIElement.Count={iScheme.ListIElement.Count}"); //foreach (IElement iElement in iScheme.ListIElement) //{ // Debug.WriteLine($" iElement Values: IntNumber={iElement.IntNumber}, IntNodeLeft={iElement.IntNodeLeft}, IntNodeRight={iElement.IntNodeRight}"); //} // // Create multiple new instances of ILoad. int intLoadCounter = 1; foreach (INode iNodeItem in iScheme.ListINode) { if (!iNodeItem.BoolNodeSupport) // Skip following if not a load node. { ILoad iLoad = iScheme.ILoadNew(); iLoad.IntNumber = intLoadCounter++; iLoad.IntNode = iNodeItem.IntNumber; // Assigned load to corresponding INode. iLoad.DoubleForce = iNodeItem.DoubleNodeForce; // Downward forces are negative. iLoad.DoubleMoment = iNodeItem.DoubleNodeMoment; // Clockwise moments are negative. iScheme.ListILoad.Add(iLoad); } } //Debug.WriteLine($"\n\nCalculateResults.cs.CalculateResults(): scheme.ListILoad.Count={iScheme.ListILoad.Count}"); //foreach (ILoad iLoad in iScheme.ListILoad) //{ // Debug.WriteLine($" iLoad Values: IntNumber={iLoad.IntNumber}, IntNode={iLoad.IntNode}, DoubleForce={iLoad.DoubleForce}, DoubleMoment={iLoad.DoubleMoment}"); // Debug.WriteLine($" iLoad Values: IntNumber={iLoad.IntNumber}, StringName={iLoad.StringName}, IntNode={iLoad.IntNode}, DoubleForce={iLoad.DoubleForce}, DoubleMoment={iLoad.DoubleMoment}"); //} // // Create new instance of IModel. IModel iModel = new Model(iScheme); iModel.AssemblyModel(); if (CommonItems.boolMatricesShow) { // Display calculated matrix data for iMmodel. CommonItems.stringOutputResults += DisplayMatrices.DisplayResultsIModel(iModel); } // Create new instance of ISolver. ISolver iSolver = new Solver(iModel); iSolver.AssembleFiniteElementModel(); iSolver.Run(); if (CommonItems.boolMatricesShow) { // Display calculated matrix data for iSolver. CommonItems.stringOutputResults += DisplayMatrices.DisplayResultsISolver(iSolver); } // Create a new instance of PostProcessor to initialize values. Discard result since not used. _ = new PostProcessor(iScheme, iModel, iSolver); PostProcessor.CalculateNodalResults(); if (CommonItems.boolMatricesShow) { // Display calculated data for iPostProcessor. CommonItems.stringOutputResults += DisplayMatrices.DisplayResultsPostProcessor(); } // // Next 3 foreach loops output shear, moment, and deflection results. // int intIntervals = Convert.ToInt32(CommonItems.doubleBeamLength / CommonItems.doubleOutputSegmentLength); //Debug.WriteLine($"\nCalculateResults(): intIntervals={intIntervals}"); // Save absolute maximum shear, moment, and deflection values found for output below. Values always have positive sign since absolute values. double doubleMaxValueShear = 0d; double doubleMaxValueMoment = 0d; double doubleMaxValueDeflection = 0d; Dictionary <double, double> dictionary; // CommonItems.stringOutputResults += "\n\n****** Shear results ******\n"; dictionary = PostProcessor.GetDictionaryShear(intIntervals); // Output shear plot results and save maximum shear value found. foreach (KeyValuePair <double, double> keyValuePair in dictionary) { if (Math.Abs(keyValuePair.Value) > doubleMaxValueShear) { doubleMaxValueShear = Math.Abs(keyValuePair.Value); } CommonItems.stringOutputResults += $"\n{keyValuePair.Key,CommonItems.intPadOutput:0.0000} {keyValuePair.Value,CommonItems.intPadOutput:0.0}"; } // CommonItems.stringOutputResults += "\n\n****** Moment results ******\n"; dictionary = PostProcessor.GetDictionaryMoment(intIntervals); // Output moment plot results and save maximum moment value found. foreach (KeyValuePair <double, double> keyValuePair in dictionary) { if (Math.Abs(keyValuePair.Value) > doubleMaxValueMoment) { doubleMaxValueMoment = Math.Abs(keyValuePair.Value); } CommonItems.stringOutputResults += $"\n{keyValuePair.Key,CommonItems.intPadOutput:0.0000} {keyValuePair.Value,CommonItems.intPadOutput:0.0}"; } // CommonItems.stringOutputResults += "\n\n****** Deflection results ******\n"; dictionary = PostProcessor.GetDictionaryDeflection(intIntervals); // Output deflection plot results and save maximum deflection value found. foreach (KeyValuePair <double, double> keyValuePair in dictionary) { if (Math.Abs(keyValuePair.Value) > doubleMaxValueDeflection) { doubleMaxValueDeflection = Math.Abs(keyValuePair.Value); } // Note: 'keyValuePair.Value,CommonItems.intPadOutput:0.00000' in next line should have same number of trailing zeros as value of PostProcessor.intRoundDigits CommonItems.stringOutputResults += $"\n{keyValuePair.Key,CommonItems.intPadOutput:0.0000} {keyValuePair.Value,CommonItems.intPadOutput:0.00000}"; } // dictionary.Clear(); // Done with dictionary so clear content. CommonItems.stringOutputResults += $"\n\n****** Beam results: ******\n"; CommonItems.stringOutputResults += $"\n{CommonItems.stringConstLoadForce} {CommonItems.stringConstLoadMoment}"; double doubleSupportPosition; double doubleSupportForce; double doubleSupportMoment; int intIndex = 0; foreach (INode iNodeScheme in iScheme.ListINode) { //Debug.WriteLine($"intIndex={intIndex}"); if (iNodeScheme.BoolNodeSupport) { // Node is a support so retrieve an display support position, force, and moment. doubleSupportPosition = iNodeScheme.DoubleNodePosition; doubleSupportForce = iSolver.DoubleMatrixReactions[intIndex, 0]; doubleSupportMoment = iSolver.DoubleMatrixReactions[++intIndex, 0]; CommonItems.stringOutputResults += $"\n\nSupport location: {doubleSupportPosition,0:0.0000} {CommonItems.stringConstUnitsLength}"; // Round following values before display to eliminate roundoff error that can occur at a support when value should really be zero. CommonItems.stringOutputResults += $"\n Reaction force: {Math.Round(doubleSupportForce, CommonItems.intRoundDigits, MidpointRounding.AwayFromZero).ToString(LibNum.fpNumericFormatSeparator)} {CommonItems.stringConstUnitsForce}"; CommonItems.stringOutputResults += $"\n Reaction moment: {Math.Round(doubleSupportMoment, CommonItems.intRoundDigits, MidpointRounding.AwayFromZero).ToString(LibNum.fpNumericFormatSeparator)} {CommonItems.stringConstUnitsMoment}"; } else { // This node is not a support so skip it. intIndex++; } intIndex++; } CommonItems.stringOutputResults += $"\n\nAbsolute maximum values of shear, moment, and deflection found."; // Round following values before display to eliminate roundoff error. CommonItems.stringOutputResults += $"\n Shear: {Math.Round(doubleMaxValueShear, CommonItems.intRoundDigits, MidpointRounding.AwayFromZero).ToString(LibNum.fpNumericFormatSeparator)} {CommonItems.stringConstUnitsForce}"; CommonItems.stringOutputResults += $"\n Moment: {Math.Round(doubleMaxValueMoment, CommonItems.intRoundDigits, MidpointRounding.AwayFromZero).ToString(LibNum.fpNumericFormatSeparator)} {CommonItems.stringConstUnitsMoment}"; CommonItems.stringOutputResults += $"\n Deflection: {Math.Round(doubleMaxValueDeflection, CommonItems.intRoundDigits, MidpointRounding.AwayFromZero).ToString(LibNum.fpNumericFormatNone)} {CommonItems.stringConstUnitsLength}"; // // // NOTE: This is a beam analysis application versus a beam design application. // Following link shows many deflection limits that could be checked in a beam design application. Save link for future reference. // AISC Steel Construction Manual, 14th Edition, Deflection Limits: http://www.bgstructuralengineering.com/BGSCM14/BGSCM008/Deflection/BGSCM0080402.htm // // Comment out following Debug lines after confirming specific FEM case matches AISC Steel Construction formula results. // To test, uncomment one sample case below and then enter matching beam and load configuration. Can only test one case at a time! // Conclusion: Application returns results that closely match AISC Steel Construction formula results. // //if (CommonItems.listLoadConcentratedValues.Count == 1) // DebugSamples.CheckResultsSampleBeam01(CommonItems.listLoadConcentratedValues[0]); // //if (CommonItems.listLoadConcentratedValues.Count == 2) // DebugSamples.CheckResultsSampleBeam02(CommonItems.listLoadConcentratedValues[0], CommonItems.listLoadConcentratedValues[1]); // //if (CommonItems.listLoadConcentratedValues.Count == 1) // DebugSamples.CheckResultsSampleBeam03(CommonItems.listLoadConcentratedValues[0]); // //if (CommonItems.listLoadConcentratedValues.Count == 1) // DebugSamples.CheckResultsSampleBeam04(CommonItems.listLoadConcentratedValues[0]); // //if (CommonItems.listLoadUniformValues.Count == 1) // DebugSamples.CheckResultsSampleBeam05(CommonItems.listLoadUniformValues[0]); // //if (CommonItems.listLoadUniformValues.Count == 1) // DebugSamples.CheckResultsSampleBeam06(CommonItems.listLoadUniformValues[0]); // //if (CommonItems.listLoadUniformValues.Count == 2) // DebugSamples.CheckResultsSampleBeam07(CommonItems.listLoadUniformValues[0]); // //DebugSamples.CheckResultsDoubleFormatting(); }
/// <summary> /// /// </summary> /// <param name="node1"></param> /// <param name="node2"></param> /// <param name="material"></param> /// <param name="crossSection"></param> /// <returns></returns> public LinearTruss CreateLinearTruss(IFiniteElementNode node1, IFiniteElementNode node2, IMaterial material, ICrossSection crossSection) { Guard.AgainstInvalidState(() => { return(!LinearTruss.IsASupportedModelType(this.ModelType)); }, "LinearTruss are not available in a model of type {0}", this.ModelType); LinearTruss newTruss = new LinearTruss(node1, node2, material, crossSection); if (this.repository != null) { this.repository.Add(newTruss); } return(newTruss); }
/// <summary> /// /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="material"></param> /// <param name="crossSection"></param> /// <returns></returns> public Linear3DBeam CreateLinear3DBeam(IFiniteElementNode start, IFiniteElementNode end, IMaterial material, ICrossSection crossSection) { Guard.AgainstInvalidState(() => { return(!Linear3DBeam.IsASupportedModelType(this.ModelType)); }, "Linear3DBeams are not available in a model of type {0}", this.ModelType); Linear3DBeam newBeam = new Linear3DBeam(start, end, material, crossSection); if (this.repository != null) { this.repository.Add(newBeam); } return(newBeam); }
/// <summary> /// /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="material"></param> /// <param name="crossSection"></param> public LinearTruss(IFiniteElementNode start, IFiniteElementNode end, IMaterial material, ICrossSection crossSection) : base(start, end) { this.CrossSection = crossSection; this.Material = material; }
/// <summary> /// /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="mat"></param> /// <param name="section"></param> public Linear3DBeam(IFiniteElementNode start, IFiniteElementNode end, IMaterial mat, ICrossSection section) : base(start, end, mat, section) { // empty }
/// <summary> /// Modify the terrain for the corner /// </summary> /// <param name="sections">The number of sections</param> /// <param name="tm">The terrain modifier</param> private void CreateCornerTerrain(int sections, TerrainModifier tm) { // this is not the best way - but it's a start // maybe have a function that returns a list of cross sections // find the point where the two roads meet Vector3 pos = _roadNetworkNode.gameObject.transform.position; // create a corne at this postion Vector3 newpos = pos; float roadAngleA = RoadUnionHelper.AngleClamp(RoadUnionHelper.GetAngleOfRoadClampped(_roadNetworkNode, 0) - Mathf.PI / 2); float roadAngleB = RoadUnionHelper.AngleClamp(RoadUnionHelper.GetAngleOfRoadClampped(_roadNetworkNode, 1) + Mathf.PI / 2); float roadAngleDifference = roadAngleB - roadAngleA; float couveSize = 1.85f; float x, z; float road_A_length = GetLengthOfRoad(0); float road_B_length = GetLengthOfRoad(1); float minLength = Mathf.Min(road_A_length, road_B_length); float offSetDownRoad = RoadConstructorHelper.CrossSectionDetails.RoadWidthValue * couveSize; if (offSetDownRoad > minLength / 2) { offSetDownRoad = minLength / 2; } RoadNetworkNode oppositeEnd = _roadNetworkNode.Details.Roads[1].GetComponent <RoadNetworkNode>(); Vector3 roadPointA = oppositeEnd.GetOffSetDownRoad(pos, (offSetDownRoad)); Vector3 outA; bool offSetPos = _roadNetworkNode.GetInnerCorner(0, 1, (offSetDownRoad), out outA); Vector3 CornerPoint = outA; newpos = CornerPoint; // get the gap form point to point Vector3 gap = CornerPoint - roadPointA; couveSize = offSetPos ? gap.magnitude : 0; couveSize = offSetPos ? gap.magnitude : 0; Radian currentAngle = new Radian(roadAngleA - (float)(Math.PI / 2)); roadAngleDifference = MathsHelper.ClampAngle(roadAngleDifference); if (roadAngleDifference > Mathf.PI) { roadAngleDifference = (Mathf.PI * 2) - roadAngleDifference; currentAngle = new Radian(roadAngleB + (float)(Math.PI / 2)); } float diff = roadAngleDifference; x = Mathf.Sin(currentAngle.Value) * (couveSize); z = Mathf.Cos(currentAngle.Value) * (couveSize); newpos.x -= x; newpos.z += z; ICrossSection crossSectionMiddle = RoadConstructorHelper.CrossSection(_roadNetworkNode); IMaterialFrequency materialFrequency = _roadNetworkNode.gameObject.GetComponent <IMaterialFrequency>(); if (materialFrequency == null) { materialFrequency = RoadConstructorHelper.MaterialFrequencySet; } RoadCrossSection rA = new RoadCrossSection(newpos, currentAngle.Value, crossSectionMiddle, materialFrequency); float angleStep = Mathf.Abs(diff / sections); for (int i = 0; i < sections; i++) { newpos = CornerPoint; currentAngle.Value += angleStep; x = Mathf.Sin(currentAngle.Value) * (couveSize); z = Mathf.Cos(currentAngle.Value) * (couveSize); newpos.x -= x; newpos.z += z; RoadCrossSection rB = new RoadCrossSection(newpos, currentAngle.Value, crossSectionMiddle, materialFrequency); tm.ApplyToTerrain(rA, rB); rA = rB; } RoadConstructorHelper.ApplyLeadingStrights(_roadNetworkNode, tm, 0); RoadConstructorHelper.ApplyLeadingStrights(_roadNetworkNode, tm, 1); }
/// <summary> /// Import from text file to xns11 file /// </summary> /// <param name="txtFileName">Path and name of text file to import</param> /// <param name="xns11FileName">Path and name of xns11 file to create or update</param> /// <param name="xns11NewFileName">Path and name of xns11 file to write to</param> public static void Import(string txtFileName, string xns11FileName, string xns11NewFileName = null) { StreamReader reader = new StreamReader(txtFileName); CrossSectionDataFactory crossSectionDataFactory = new CrossSectionDataFactory(); CrossSectionData csData; if (File.Exists(xns11FileName)) { csData = crossSectionDataFactory.Open(Connection.Create(xns11FileName), null); } else { csData = new CrossSectionData(); } if (string.IsNullOrEmpty(xns11NewFileName)) { xns11NewFileName = xns11FileName; } string line; // Read cross section info-line while ((line = reader.ReadLine()) != null) { // Split cross section info-line string[] split = line.SplitQuoted(',', '"'); // extract info from info-line Location location = new Location(split[1], double.Parse(split[2], CultureInfo.InvariantCulture)); string topoId = split[3]; double datum = double.Parse(split[4], CultureInfo.InvariantCulture); int numRawPoints = int.Parse(split[5]); // Check if this cross section is to be processed if (split[0] == "1") { ICrossSection cs = csData.FindCrossSection(location, topoId); CrossSectionPointList points = new CrossSectionPointList(); // Read raw points for (int i = 0; i < numRawPoints; i++) { line = reader.ReadLine(); if (line == null) // end-of-file { throw new EndOfStreamException("File ended prematurely"); } string[] coords = line.Split(','); double x = double.Parse(coords[0], CultureInfo.InvariantCulture); double z = double.Parse(coords[1], CultureInfo.InvariantCulture); points.Add(new CrossSectionPoint(x, z)); } // Check if cross section already exists if (cs != null) { // Check if it is a cross section with raw points XSBaseRaw xsBaseRaw = cs.BaseCrossSection as XSBaseRaw; if (xsBaseRaw == null) { throw new Exception("Cannot modify raw points of a cross section without raw points: " + location.ToString() + ", " + topoId); } // replace datum (in case datum changes) cs.Location.Z = datum; // Replace points xsBaseRaw.Points = points; // Set default markers xsBaseRaw.UpdateMarkersToDefaults(true, true, true); // Recalculate processed data xsBaseRaw.ProcessingLevelsSpecs.NoOfLevels = 50; xsBaseRaw.CalculateProcessedData(); } else { // Create a new cross section CrossSectionFactory builder = new CrossSectionFactory(); builder.BuildOpen(""); // Defines the location of the current cross section. The Z-coordinate // for an open cross section with raw data is a Z-offset, and usually zero. builder.SetLocation(new ZLocation(location.ID, location.Chainage) { Z = datum }); // Set raw points and default markers builder.SetRawPoints(points); builder.SetDefaultMarkers(); // Define resistance properties as relative FlowResistance flowResistance = new FlowResistance(); flowResistance.Formulation = ResistanceFormulation.Relative; flowResistance.ResistanceDistribution = ResistanceDistribution.Uniform; flowResistance.ResistanceValue = 1; builder.SetFlowResistance(flowResistance); builder.SetRadiusType(RadiusType.ResistanceRadius); // Get the cross section CrossSectionLocated csLocated = builder.GetCrossSection(); // Set topo-id csLocated.TopoID = topoId; // now, calculate processed data csLocated.BaseCrossSection.ProcessingLevelsSpecs.Option = ProcessingOption.AutomaticLevels; csLocated.BaseCrossSection.ProcessingLevelsSpecs.NoOfLevels = 0; csLocated.BaseCrossSection.CalculateProcessedData(); // Store cross section in database csData.Add(csLocated); } } else // this cross section should not be processed { // Skip line containing raw points for (int i = 0; i < numRawPoints; i++) { line = reader.ReadLine(); if (line == null) // end-of-file { throw new EndOfStreamException("File ended prematurely"); } } } } csData.Connection = Connection.Create(xns11NewFileName); CrossSectionDataFactory.Save(csData); }
/// <summary> /// Create the road object /// </summary> /// <param name="roadObject">The base object to add the road to</param> /// <param name="sections">The number of sections to use for this road</param> private void CreateCorner(RoadBuilder roadObject, int sections) { // find the point where the two roads meet Vector3 pos = _roadNetworkNode.gameObject.transform.position; // create a corne at this postion Vector3 newpos = pos; float roadAngleA = RoadUnionHelper.AngleClamp(RoadUnionHelper.GetAngleOfRoadClampped(_roadNetworkNode, 0) - (Mathf.PI / 2)); float roadAngleB = RoadUnionHelper.AngleClamp(RoadUnionHelper.GetAngleOfRoadClampped(_roadNetworkNode, 1) + (Mathf.PI / 2)); float roadAngleDifference = roadAngleB - roadAngleA; float couveSize = 1.85f; float x, z; float road_A_length = GetLengthOfRoad(0); float road_B_length = GetLengthOfRoad(1); float minLength = Mathf.Min(road_A_length, road_B_length); float offSetDownRoad = RoadConstructorHelper.CrossSectionDetails.RoadWidthValue * couveSize; if (offSetDownRoad > minLength / 2) { offSetDownRoad = minLength / 2; } RoadNetworkNode oppositeEnd = _roadNetworkNode.Details.Roads[1].GetComponent <RoadNetworkNode>(); Vector3 roadPointA = oppositeEnd.GetOffSetDownRoad(pos, (offSetDownRoad)); Vector3 outA; bool offSetPos = _roadNetworkNode.GetInnerCorner(0, 1, (offSetDownRoad), out outA); Vector3 CornerPoint = outA; newpos = CornerPoint; // get the gap form point to point Vector3 gap = CornerPoint - roadPointA; couveSize = offSetPos ? gap.magnitude : 0; couveSize = offSetPos ? gap.magnitude : 0; bool backward = false; Radian currentAngle = new Radian(roadAngleA - (float)(Math.PI / 2)); roadAngleDifference = MathsHelper.ClampAngle(roadAngleDifference); if (roadAngleDifference > Mathf.PI) { roadAngleDifference = (Mathf.PI * 2) - roadAngleDifference; currentAngle = new Radian(roadAngleB + (float)(Math.PI / 2)); backward = true; } float diff = roadAngleDifference; x = Mathf.Sin(currentAngle.Value) * (couveSize); z = Mathf.Cos(currentAngle.Value) * (couveSize); newpos.x -= x; newpos.z += z; ICrossSection crossSectionMiddle = RoadConstructorHelper.CrossSection(_roadNetworkNode); IMaterialFrequency materialFrequency = _roadNetworkNode.gameObject.GetComponent <IMaterialFrequency>(); if (materialFrequency == null) { materialFrequency = RoadConstructorHelper.MaterialFrequencySet; } RoadCrossSection rA = new RoadCrossSection(newpos, currentAngle.Value, crossSectionMiddle, materialFrequency); RoadCrossSection Start = rA; float angleStep = Mathf.Abs(diff / sections); for (int i = 0; i < sections; i++) { newpos = CornerPoint; currentAngle.Value += angleStep; x = Mathf.Sin(currentAngle.Value) * (couveSize); z = Mathf.Cos(currentAngle.Value) * (couveSize); newpos.x -= x; newpos.z += z; RoadCrossSection rB = new RoadCrossSection(newpos, currentAngle.Value, crossSectionMiddle, materialFrequency); // TODO Sub divide corners - need to update before the add basic road! _meshSection.AddBasicRoad(IntersectionManager.Instance.AddLinkedIntersecions(rA, rB), RoadConstructorHelper.GetMainMaterial(materialFrequency), 0); rA = rB; } RoadCrossSection End = rA; if (backward) { StreetManager.Instance.AddStreetEnd(_roadNetworkNode.name, _roadNetworkNode.Details.Roads[0].name, crossSectionMiddle, materialFrequency, End); StreetManager.Instance.AddStreetEnd(_roadNetworkNode.name, _roadNetworkNode.Details.Roads[1].name, crossSectionMiddle, materialFrequency, Start); } else { StreetManager.Instance.AddStreetEnd(_roadNetworkNode.name, _roadNetworkNode.Details.Roads[1].name, crossSectionMiddle, materialFrequency, End); StreetManager.Instance.AddStreetEnd(_roadNetworkNode.name, _roadNetworkNode.Details.Roads[0].name, crossSectionMiddle, materialFrequency, Start); } }
static void Main(string[] args) { /* Static scheme * * * |F=15kN * HEA400 |F=10kN | * *====================*==========*==========* * /\ /\ * * | | | | * /--------5.0m--------/---2.5m---/---2.5m---/ * * */ // Proposed consistent units applied in this example are: [Pa], [N], [Nm], [m], [m^4] // Create a new instance of Scheme class with static scheme information IScheme scheme = new Scheme(); // Create a new instance of Material class IMaterial material = scheme.NewMaterial(); material.Number = 1; material.Name = "Steel"; material.E = 2.1e11; material.v = 0.3; // Add an instance of Material class to the list of materials scheme.Materials.Add(material); // Create a new instance of CrossSection class ICrossSection crossSection = scheme.NewCrossSection(); crossSection.Number = 1; crossSection.Name = "HEA400"; crossSection.Iy = 0.00045070; // Add an instance of CrossSection class to the list of cross sections scheme.CrossSections.Add(crossSection); // Create new instances of Node class INode node_1 = scheme.NewNode(); node_1.Number = 1; node_1.Name = "Start node"; node_1.X = 0; INode node_2 = scheme.NewNode(); node_2.Number = 2; node_2.Name = "Load node"; node_2.X = 5; INode node_3 = scheme.NewNode(); node_3.Number = 3; node_3.Name = "Middle node"; node_3.X = 7.5; INode node_4 = scheme.NewNode(); node_4.Number = 4; node_4.Name = "End node"; node_4.X = 10.00; // Add instances of Node class to the list of nodes scheme.Nodes.Add(node_1); scheme.Nodes.Add(node_2); scheme.Nodes.Add(node_3); scheme.Nodes.Add(node_4); // Create new instances of Element class IElement element_1 = scheme.NewElement(); element_1.Number = 1; element_1.Name = "Left element"; element_1.MaterialNumber = 1; element_1.CrossSectionNumber = 1; element_1.StartNodeNumber = 1; element_1.EndNodeNumber = 2; IElement element_2 = scheme.NewElement(); element_2.Number = 2; element_2.Name = "Middle element"; element_2.MaterialNumber = 1; element_2.CrossSectionNumber = 1; element_2.StartNodeNumber = 2; element_2.EndNodeNumber = 3; IElement element_3 = scheme.NewElement(); element_3.Number = 3; element_3.Name = "Right element"; element_3.MaterialNumber = 1; element_3.CrossSectionNumber = 1; element_3.StartNodeNumber = 3; element_3.EndNodeNumber = 4; // Add instances of Element class to the list of elements scheme.Elements.Add(element_1); scheme.Elements.Add(element_2); scheme.Elements.Add(element_3); // Create a new instance of Load class ILoad load_1 = scheme.NewLoad(); load_1.Number = 1; load_1.Name = "Force 1"; load_1.NodeNumber = 2; load_1.Pz = -10000; load_1.My = 0; // Create a new instance of Load class ILoad load_2 = scheme.NewLoad(); load_2.Number = 2; load_2.Name = "Force 2"; load_2.NodeNumber = 3; load_2.Pz = -15000; load_2.My = 0; // Add an instance of Material class to the list of materials scheme.Loads.Add(load_1); scheme.Loads.Add(load_2); // Create a new instance of Model class with Finite Element Method model IModel model = new Model(scheme); model.AssembyModel(); // ### Display calculated data for model ### DisplayResults(model); // Create a new instance of Solver class with Finite Element Method solver module ISolver solver = new Solver(model); solver.AssemblyFiniteElementModel(); solver.Run(); // ### Display calculated data for solver ### DisplayResults(solver); // Create a new instance of PostProcessor class with results of the finite element method calculations IPostProcessor postProcessor = new PostProcessor(scheme, model, solver); postProcessor.CalculateResults(); // ### Display calculated data from post processor ### DisplayResults(postProcessor); Console.ReadKey(); }
/// <summary> /// /// </summary> /// <param name="node1"></param> /// <param name="node2"></param> /// <param name="material"></param> /// <param name="crossSection"></param> /// <returns></returns> public LinearTruss CreateLinearTruss(IFiniteElementNode node1, IFiniteElementNode node2, IMaterial material, ICrossSection crossSection) { Guard.AgainstInvalidState(() => { return !LinearTruss.IsASupportedModelType(this.ModelType); }, "LinearTruss are not available in a model of type {0}", this.ModelType); LinearTruss newTruss = new LinearTruss(node1, node2, material, crossSection); if (this.repository != null) { this.repository.Add(newTruss); } return newTruss; }
/// <summary> /// Create the steet layout /// </summary> public void CreateStreetLayout(int subDivide) { if (_startRoadId == null) { return; } if (_endRoadId == null) { return; } RoadCrossSection rA = _startRoadId; ICrossSection crossSectionStart = _startCrossSection; if (crossSectionStart == null) { crossSectionStart = RoadConstructorHelper.CrossSectionDetails; } RoadCrossSection rB = _endRoadId; ICrossSection crossSectionEnd = _endCrossSection; if (crossSectionEnd == null) { crossSectionEnd = RoadConstructorHelper.CrossSectionDetails; } IMaterialFrequency materialFrequency = _materialFrequency; if (materialFrequency == null) { materialFrequency = RoadConstructorHelper.MaterialFrequencySet; } Vector3 len = rA.Middle - rB.Middle; float mag = len.magnitude; int sections = (int)(mag / crossSectionStart.RoadWidthValue); RoadCrossSection[] array = new RoadCrossSection[sections + 1]; string[] materialNames = new string[sections + 1]; float an = rB.Angle; Vector3 start = rB.Middle; if (sections < 2) { Vector3 another = rB.Middle; another = rA.Middle; RoadCrossSection rn = new RoadCrossSection(another, an, crossSectionStart, materialFrequency); _meshSection.AddBasicRoad(IntersectionManager.Instance.AddLinkedIntersecions(rB, rn), RoadConstructorHelper.GetMainMaterial(materialFrequency), 0); // TODO SubDivide return; } Vector3 gap = len / sections; float mag2 = gap.magnitude; for (int i = 0; i < sections + 1; i++) { ICrossSection crossSection = CrossSection.Lerp(crossSectionEnd, crossSectionStart, (mag2 * i) / mag); RoadCrossSection rn = new RoadCrossSection(start, an, crossSection, materialFrequency); array[i] = rn; start += gap; } RoadConstructorHelper.SetMaterialsArray(materialNames, materialFrequency); for (int i = 0; i < sections; i++) { _meshSection.AddBasicRoad(IntersectionManager.Instance.AddLinkedIntersecions(array[i], array[i + 1]), materialNames[i], subDivide); } }
private double GetCurrentIy(int crossSectionNumber) { ICrossSection currentCrossSection = BeamModel.AbstractIScheme.ListICrossSection.Where(cs => cs.IntNumber == crossSectionNumber).FirstOrDefault(); return(currentCrossSection.DoubleAreaMomentOfInertia); }