예제 #1
0
        public void TestValueOutOfRange()
        {
            LinearInterpolation interpolation = new LinearInterpolation(new[] { 1.0, 2.0, 3.0 }, new[] { 1.0, 2.0, 3.0 });
            double value = interpolation.Interpolate(3.5);

            Assert.AreEqual(3.5, value);
        }
예제 #2
0
        /// <summary>
        /// A percentile is the value of a variable below which a certain
        /// percentage of observations reside.
        /// If percentile*(data size - 1) is not an integer, then linear
        /// interpolation around the relevant index is applied to compute
        /// the percentile.
        /// </summary>
        /// <param name="data">Data from which to compute the
        /// percentile. There is no requirement for the array to be sorted
        /// into ascending/descending order.</param>
        /// <param name="percentile">The requested percentile as an integer
        /// in the range [0,100].
        /// Example: To request the 99'th percentile use the value 99.</param>
        /// <returns></returns>
        public double Percentile(ref double[] data, int percentile)
        {
            // Check for valid inputs.
            if (data.Length < 1)
            {
                const string errorMessage = "Data array used to calculate a percentile cannot be empty.";
                throw new ArgumentException(errorMessage);
            }
            if (percentile < 0 || percentile > 100)
            {
                const string errorMessage = "Percentile is restricted to the range [0,100].";
                throw new ArgumentException(errorMessage);
            }
            // Copy the array into a temporary array and then sort into
            // ascending order.
            long numElements = data.Length;
            var  yArray      = new double[numElements];

            Array.Copy(data, yArray, numElements);
            Array.Sort(yArray);
            // Compute the index at which the percentile is to be located.
            var percentileIndex = (numElements - 1) * percentile / 100.0;
            // Compute the percentile by linear interpolation at the
            // target percentile index.
            var xArray = new double[numElements]; // array index

            for (long i = 0; i < numElements; ++i)
            {
                xArray[i] = i;
            }
            var interpObj       = LinearInterpolation.Interpolate(xArray, yArray);
            var percentileValue = interpObj.ValueAt(percentileIndex, true);

            return(percentileValue);
        }
예제 #3
0
        public void TestUnsortedValues()
        {
            LinearInterpolation interpolation = new LinearInterpolation(new[] { 2.0, 1.0, 3.0, 1.5 }, new[] { 2.0, 1.0, 3.0, 1.5 });
            double value = interpolation.Interpolate(2.5);

            Assert.AreEqual(2.5, value);
        }
예제 #4
0
        public void TestGeneral()
        {
            LinearInterpolation interpolation = new LinearInterpolation(new [] { 1.0, 2.0, 3.0 }, new [] { 1.0, 2.0, 3.0 });
            double value = interpolation.Interpolate(1.5);

            Assert.AreEqual(1.5, value);
        }
        public void InterpolateTest()
        {
            var keyPoints = new AbsoluteKeyPointCollection <int, int>(new ValueTypeInterpolationProvider <int>(), 0)
            {
                0, 10
            };
            var interpolate = new LinearInterpolation <int, int>(keyPoints);

            Assert.Equal(5, interpolate.Interpolate(0.5));
        }
예제 #6
0
        public void ValueTest()
        {
            double[] xValues = { 0.00273972602739726,
                                 0.0191780821917808,
                                 0.0383561643835616,
                                 0.0821917808219178,
                                 0.16986301369863,
                                 0.252054794520547,
                                 0.265753424657534,
                                 0.506849315068493,
                                 0.753424657534246,
                                 1.01369863013698,
                                 1.26301369863013,
                                 1.50410958904109,
                                 1.75068493150684,
                                 2.01369863 };

            double[] yValues = { 0.000198610398037118,
                                 0.00144115280642265,
                                 0.00292486360387681,
                                 0.00631290829444216,
                                 0.0129485443009048,
                                 0.0191542839259883,
                                 0.0203498757471952,
                                 0.0391594113610678,
                                 0.0585407323615074,
                                 0.0789041494478555,
                                 0.0982464310004563,
                                 0.116728055717234,
                                 0.135405191240189,
                                 0.154521506325593 };


            var plc = LinearInterpolation.Interpolate(xValues, yValues);

            // Test the actual nodes
            var actual   = plc.ValueAt(0.00273972602739726);
            var expected = 0.000198610398037118;

            Assert.AreEqual(expected, actual);

            actual   = plc.ValueAt(2.01369863);
            expected = 0.154521506325593;
            Assert.AreEqual(expected, actual);

            actual   = plc.ValueAt(1.75068493150684);
            expected = 0.135405191240189;
            Assert.AreEqual(expected, actual);

            // Test mid point
            actual   = plc.ValueAt(1.882191780822);
            expected = 0.14496334878289;
            LessOrEqual(Math.Abs(actual - expected), 10E-12);
        }
예제 #7
0
        public void TestWriteReadXml()
        {
            string path = Path.GetTempFileName();
            LinearInterpolation interpolation = new LinearInterpolation(new[] { 2.0, 1.0, 3.0, 1.5 }, new[] { 2.0, 1.0, 3.0, 1.5 });

            Xml.WriteXml(path, interpolation);
            LinearInterpolation interpolation2 = Xml.ReadXml <LinearInterpolation>(path);
            double value = interpolation2.Interpolate(2.5);

            Assert.AreEqual(2.5, value);
        }
        // (Linearly) interpolates the feature, generating n (=numberOfValues) values
        // for the feature.
        public void Interpolate(int numberOfValues)
        {
            List <List <double> > timeValueList = new List <List <double> >()
            {
                timeList, valueList
            };
            List <List <double> > interpolatedTimeValueList = LinearInterpolation.Interpolate(timeValueList, numberOfValues);
            List <List <double> > timeVarianceList          = new List <List <double> >()
            {
                timeList, varianceList
            };
            List <List <double> > interpolatedTimeVarianceList = LinearInterpolation.Interpolate(timeVarianceList, numberOfValues);

            timeList     = interpolatedTimeValueList[0];
            valueList    = interpolatedTimeValueList[1];
            varianceList = interpolatedTimeVarianceList[1];
        }
예제 #9
0
        private double ForwardRate(double time1, double time2)
        {
            int n = _ratedays.Length;

            double[] rtYrfrac = new double[n];
            for (int idx = 0; idx < n; idx++)
            {
                rtYrfrac[idx] = Convert.ToDouble(_ratedays[idx]) / daybasis;
            }
            var interpObj = LinearInterpolation.Interpolate(rtYrfrac, _rateamts);
            var fd1       = interpObj.ValueAt(time1, true);
            var fd2       = interpObj.ValueAt(time2, true);

            if (time1 == time2)
            {
                return(0);
            }
            return((fd2 * time2 - fd1 * time1) / (time2 - time1));
        }
예제 #10
0
        private double ForwardRate(int days1, int days2)
        {
            int n = _ratedays.Length;

            double[] rtYrfrac = new double[n];
            for (int idx = 0; idx < n; idx++)
            {
                rtYrfrac[idx] = Convert.ToDouble(_ratedays[idx]) / daybasis;
            }
            double yearFrac1 = Convert.ToDouble(days1) / daybasis;
            double yearFrac2 = Convert.ToDouble(days2) / daybasis;
            var    interpObj = LinearInterpolation.Interpolate(rtYrfrac, _rateamts);
            var    fd1       = interpObj.ValueAt(yearFrac1, true);
            var    fd2       = interpObj.ValueAt(yearFrac2, true);

            if (yearFrac2 == yearFrac1)
            {
                return(0);
            }
            return((fd2 * yearFrac2 - fd1 * yearFrac1) / (yearFrac2 - yearFrac1));
        }
예제 #11
0
        public void AdjustAndInterpolate(SpeechTypeSpecification speechTypeSpecification) // , double deltaTime, Boolean setUnvoicedPitch)
        {
            // Carry out median filtering to remove single errors
            List <double> correctedPitchValues = new List <double>();

            correctedPitchValues.Add(pitchPeriodSpecification.TimePitchPeriodTupleList[0].Item2);
            for (int ii = 1; ii < pitchPeriodSpecification.TimePitchPeriodTupleList.Count - 1; ii++)
            {
                List <double> rawPitchValues = new List <double>()
                {
                    pitchPeriodSpecification.TimePitchPeriodTupleList[ii - 1].Item2,
                    pitchPeriodSpecification.TimePitchPeriodTupleList[ii].Item2,
                    pitchPeriodSpecification.TimePitchPeriodTupleList[ii + 1].Item2
                };
                rawPitchValues.Sort();
                correctedPitchValues.Add(rawPitchValues[1]); // Median
            }
            // Finally adjust the end points (which are not touched by the initial median filtering)
            if (pitchPeriodSpecification.TimePitchPeriodTupleList.Count > 2)
            {
                List <double> rawPitchValues = new List <double>()
                {
                    pitchPeriodSpecification.TimePitchPeriodTupleList[0].Item2,
                    pitchPeriodSpecification.TimePitchPeriodTupleList[1].Item2,
                    pitchPeriodSpecification.TimePitchPeriodTupleList[2].Item2
                };
                rawPitchValues.Sort();
                correctedPitchValues[0] = rawPitchValues[1];
                int lastIndex = pitchPeriodSpecification.TimePitchPeriodTupleList.Count - 1;
                rawPitchValues = new List <double>()
                {
                    pitchPeriodSpecification.TimePitchPeriodTupleList[lastIndex].Item2,
                    pitchPeriodSpecification.TimePitchPeriodTupleList[lastIndex - 1].Item2,
                    pitchPeriodSpecification.TimePitchPeriodTupleList[lastIndex - 2].Item2
                };
                rawPitchValues.Sort();
                correctedPitchValues.Add(rawPitchValues[1]);
            }
            for (int ii = 0; ii < pitchPeriodSpecification.TimePitchPeriodTupleList.Count - 1; ii++)
            {
                pitchPeriodSpecification.TimePitchPeriodTupleList[ii] =
                    new Tuple <double, double>(pitchPeriodSpecification.TimePitchPeriodTupleList[ii].Item1,
                                               correctedPitchValues[ii]);
            }
            // Extend (extrapolate) the pitch period specification so that it runs to the end of the sound:
            double lastTime       = speechTypeSpecification.TimeSpeechTypeTupleList.Last().Item1;
            int    lastPitchIndex = pitchPeriodSpecification.TimePitchPeriodTupleList.Count - 1;
            double lastPitchTime  = pitchPeriodSpecification.TimePitchPeriodTupleList[lastPitchIndex].Item1;

            if (lastTime > lastPitchTime) // Should always be the case, but just to be sure ...
            {
                double lastPitch = pitchPeriodSpecification.TimePitchPeriodTupleList[lastPitchIndex].Item2;
                pitchPeriodSpecification.TimePitchPeriodTupleList.Add(new Tuple <double, double>(lastTime, lastPitch));
            }

            // Next, resample (upsample) the pitch period specification
            List <double> timeList  = new List <double>();
            List <double> pitchList = new List <double>();

            for (int ii = 0; ii < pitchPeriodSpecification.TimePitchPeriodTupleList.Count; ii++)
            {
                double time  = pitchPeriodSpecification.TimePitchPeriodTupleList[ii].Item1;
                double pitch = pitchPeriodSpecification.TimePitchPeriodTupleList[ii].Item2;
                timeList.Add(time);
                pitchList.Add(pitch);
            }
            List <List <double> > timePitchList = new List <List <double> >()
            {
                timeList, pitchList
            };
            int numberOfPoints = (int)Math.Round(lastTime / deltaTime);
            List <List <double> > interpolatedTimePitchList = LinearInterpolation.Interpolate(timePitchList, numberOfPoints);

            pitchPeriodSpecification = new PitchPeriodSpecification();
            for (int ii = 0; ii < interpolatedTimePitchList[0].Count; ii++)
            {
                double time  = interpolatedTimePitchList[0][ii];
                double pitch = interpolatedTimePitchList[1][ii];
                pitchPeriodSpecification.TimePitchPeriodTupleList.Add(new Tuple <double, double>(time, pitch));
            }

            // Optionally (usually true) hard-set the (anyway rather arbitrary) pitch period for
            // unvoiced parts of the sound, by extending the pitch period from surrounding
            // voiced parts. This might cause occasional jumps (in the middle of an unvoiced
            // section), but those jumps are reoved in the subsequent lowpass filtering

            if (setUnvoicedPitch)
            {
                double     previousTime       = pitchPeriodSpecification.TimePitchPeriodTupleList[0].Item1;
                SpeechType previousSpeechType = speechTypeSpecification.GetSpeechType(previousTime);
                int        firstChangeIndex   = 0; // Will be changed later - must initialize here.
                int        lastChangeIndex    = -1;
                double     previousPitch;          // Must define here for use after the loop as well.
                for (int ii = 1; ii < pitchPeriodSpecification.TimePitchPeriodTupleList.Count; ii++)
                {
                    double     time       = pitchPeriodSpecification.TimePitchPeriodTupleList[ii].Item1;
                    SpeechType speechType = speechTypeSpecification.GetSpeechType(time);
                    if ((previousSpeechType == SpeechType.Voiced) && (speechType != SpeechType.Voiced))
                    {
                        firstChangeIndex = ii;
                        lastChangeIndex  = -1; // Not yet assigned. The value -1 is used for handling cases where the
                                               // sound remains not voiced until the end (see below).
                    }
                    else if ((previousSpeechType != SpeechType.Voiced) && (speechType == SpeechType.Voiced))
                    {
                        lastChangeIndex = ii - 1;
                        int middlexIndex = (firstChangeIndex + lastChangeIndex) / 2; // integer division
                                                                                     // assign the preceding pitch to the first half of the interval (unless firstChangeIndex = 0, meaning
                                                                                     // that the sound started with an unvoiced segment), and the  subsequent pitch to the second half of
                                                                                     // the interval:
                        double subsequentPitch = pitchPeriodSpecification.TimePitchPeriodTupleList[lastChangeIndex].Item2;
                        previousPitch = subsequentPitch;
                        if (firstChangeIndex > 0)
                        {
                            previousPitch = pitchPeriodSpecification.TimePitchPeriodTupleList[firstChangeIndex - 1].Item2;
                        }
                        for (int jj = firstChangeIndex; jj < middlexIndex; jj++)
                        {
                            time = pitchPeriodSpecification.TimePitchPeriodTupleList[jj].Item1;
                            pitchPeriodSpecification.TimePitchPeriodTupleList[jj] = new Tuple <double, double>(time, previousPitch);
                        }
                        for (int jj = middlexIndex; jj <= lastChangeIndex; jj++)
                        {
                            time = pitchPeriodSpecification.TimePitchPeriodTupleList[jj].Item1;
                            pitchPeriodSpecification.TimePitchPeriodTupleList[jj] = new Tuple <double, double>(time, subsequentPitch);
                        }
                    }
                    previousTime       = time;
                    previousSpeechType = speechType;
                }
                // At the end, if lastChangeIndex = -1, then the sound remained not voiced from the latest
                // change until the end. Thus:
                if ((lastChangeIndex == -1) && (firstChangeIndex > 0))
                {
                    previousPitch = pitchPeriodSpecification.TimePitchPeriodTupleList[firstChangeIndex - 1].Item2;
                    for (int jj = firstChangeIndex; jj < pitchPeriodSpecification.TimePitchPeriodTupleList.Count; jj++)
                    {
                        double time = pitchPeriodSpecification.TimePitchPeriodTupleList[jj].Item1;
                        pitchPeriodSpecification.TimePitchPeriodTupleList[jj] = new Tuple <double, double>(time, previousPitch);
                    }
                }

                // Then, finally, low-pass filter the interpolated list, and assign the result:
                AveragingFilter averagingFilter = new AveragingFilter();
                List <double>   inputList       = new List <double>();
                for (int ii = 0; ii < pitchPeriodSpecification.TimePitchPeriodTupleList.Count; ii++)
                {
                    double input = pitchPeriodSpecification.TimePitchPeriodTupleList[ii].Item2;
                    inputList.Add(input);
                }
                List <double> outputList = averagingFilter.Run(inputList);
                for (int ii = 0; ii < pitchPeriodSpecification.TimePitchPeriodTupleList.Count; ii++)
                {
                    double filteredPitch = outputList[ii];
                    double time          = pitchPeriodSpecification.TimePitchPeriodTupleList[ii].Item1;
                    pitchPeriodSpecification.TimePitchPeriodTupleList[ii] = new Tuple <double, double>(time, filteredPitch);
                }

                /*     FirstOrderLowPassFilter lowPassFilter = new FirstOrderLowPassFilter();
                 *   lowPassFilter.SetAlpha(0.9); // To do: Parameterize.
                 *   for (int ii = 0; ii < pitchPeriodSpecification.TimePitchPeriodTupleList.Count; ii++)
                 *   {
                 *       double input = pitchPeriodSpecification.TimePitchPeriodTupleList[ii].Item2;
                 *       lowPassFilter.Step(input);
                 *   }
                 *   for (int ii = 0; ii < pitchPeriodSpecification.TimePitchPeriodTupleList.Count; ii++)
                 *   {
                 *       double filteredPitch = lowPassFilter.OutputList[ii];
                 *       double time = pitchPeriodSpecification.TimePitchPeriodTupleList[ii].Item1;
                 *       pitchPeriodSpecification.TimePitchPeriodTupleList[ii] = new Tuple<double, double>(time, filteredPitch);
                 *   }  */
            }
        }
예제 #12
0
        private void CalculatePipeCharacteristic(object sender, EventArgs e)
        {
            if (txtOutDiameter.Text == string.Empty)
            {
                return;
            }

            double outDiameter, insulationThickness, pipeThickness, insulationDensity, materialDensity, designTemperature, corrosionAllowance;

            double.TryParse(txtInsulationThickness.Text, out insulationThickness);
            double.TryParse(txtPipeThickness.Text, out pipeThickness);
            double.TryParse(txtOutDiameter.Text, out outDiameter);
            double.TryParse(txtInsulationDensity.Text, out insulationDensity);
            double.TryParse(txtMaterialDensity.Text, out materialDensity);
            double.TryParse(txtDesignTemperature.Text, out designTemperature);
            double.TryParse(txtCorrosionAllowance.Text, out corrosionAllowance);
            // 统一以米为单位
            outDiameter         /= 1000;
            pipeThickness       /= 1000;
            corrosionAllowance  /= 1000; // 腐蚀裕量
            insulationThickness /= 1000;

            // 保护层面积
            var jackerArea = 3.14 * (outDiameter + insulationThickness * 2);
            // 涂漆面积
            var paintArea = 3.14 * outDiameter;
            // 防烫体积
            var insulationVolume = 3.14 / 4 * (Math.Pow(outDiameter + insulationThickness * 2, 2) - Math.Pow(outDiameter, 2));
            // 管道单重
            var pipeWeight = 0.02466 * 1000000 * pipeThickness * (outDiameter - pipeThickness);

            // 奥氏体不锈钢考虑1.015系数
            if (cbxPipeMaterial.Text.Contains("304") || cbxPipeMaterial.Text.Contains("316"))
            {
                pipeWeight *= 1.015;
            }
            // 物料单重
            var materialWeight = materialDensity * 3.14 / 4 * Math.Pow(outDiameter - pipeThickness * 2, 2);
            // 充水单重
            var waterWeight = 1000 * 3.14 / 4 * Math.Pow(outDiameter - pipeThickness * 2, 2);
            // 保温单重
            var insulationWeight = insulationVolume * insulationDensity;
            // 水压试验工况荷重
            var testingLoad = pipeWeight + waterWeight + insulationWeight;
            // 操作工况荷重
            var operatingLoad = pipeWeight + materialWeight + insulationWeight;
            // 管道截面惯性矩,单位mm4
            var innerDiameter = outDiameter - 2 * (pipeThickness + corrosionAllowance);
            var moment        = 3.14 / 64 * (Math.Pow(outDiameter * 1000, 4) - Math.Pow(innerDiameter * 1000, 4));
            // 弹性模量,单位为MPa
            double modulus = 0;

            if (cbxPipeMaterial.Text.Contains("20"))
            {
                modulus = LinearInterpolation.Interpolate(ElasticModulus.CS20, designTemperature) * 1000;
            }
            else if (cbxPipeMaterial.Text.Contains("12Cr"))
            {
                modulus = LinearInterpolation.Interpolate(ElasticModulus.AS12Cr1MoVG, designTemperature) * 1000;
            }
            else if (cbxPipeMaterial.Text.Contains("15Cr"))
            {
                modulus = LinearInterpolation.Interpolate(ElasticModulus.AS15CrMoG, designTemperature) * 1000;
            }
            else if (cbxPipeMaterial.Text.Contains("235"))
            {
                modulus = LinearInterpolation.Interpolate(ElasticModulus.CSQ235, designTemperature) * 1000;
            }
            else if (cbxPipeMaterial.Text.Contains("06Cr"))
            {
                modulus = LinearInterpolation.Interpolate(ElasticModulus.SS06Cr19Ni10, designTemperature) * 1000;
            }
            // 管道单位荷载,区分是否水压试验
            var calculatedLoad = testingLoad * 9.8;

            if (!chkWaterTest.Checked)
            {
                calculatedLoad = operatingLoad * 9.8;
            }
            // 荷载系数,区别装置内、装置外、动力管道
            var factor = 0.039;

            if (rioChemicalOnSiteOutSite.Checked)
            {
                factor = 0.048;
            }
            else if (rioPowerPipeline.Checked)
            {
                factor = 0.02093;
            }
            // 计算跨距
            var span = factor * Math.Pow(moment * modulus / calculatedLoad, 0.25);

            txtHorizontalSpan.Text   = Math.Round(span, 1) + string.Empty;
            txtJacketArea.Text       = Math.Round(jackerArea, 3) + string.Empty;
            txtPaintArea.Text        = Math.Round(paintArea, 3) + string.Empty;
            txtInsulationVolume.Text = Math.Round(insulationVolume, 3) + string.Empty;
            txtTestingLoad.Text      = Math.Round(testingLoad, 3) + string.Empty;
            txtOperatingLoad.Text    = Math.Round(operatingLoad, 3) + string.Empty;

            if (txtDesignTemperature.Text == string.Empty || modulus < 0)
            {
                txtHorizontalSpan.Clear();
                txtHorizontalSpan.Clear();
            }

            if (materialDensity <= 1)
            {
                txtOperatingLoad.Clear();
            }
        }
예제 #13
0
파일: frmMain.cs 프로젝트: 3roman/Thermor
        private void CalculatePipeCharacteristic()
        {
            double.TryParse(txtOutDiameter.Text, out double outDiameter);
            double.TryParse(txtPipeThickness.Text, out double pipeThickness);
            double.TryParse(txtInsulationThickness.Text, out double insulationThickness);
            double.TryParse(txtPipeLength.Text, out double pipeLength);
            double.TryParse(txtCorrosionAllowance.Text, out double corrosionAllowance);
            double.TryParse(txtMaterialDensity.Text, out double materialDensity);
            double.TryParse(txtDesignTemperature.Text, out double designTemperature);
            outDiameter         /= 1000; // mm→m
            pipeThickness       /= 1000;
            insulationThickness /= 1000;
            corrosionAllowance  /= 1000;

            // 铁皮面积
            var jackerArea = 3.14 * (outDiameter + insulationThickness * 2) * pipeLength;
            // 涂漆面积
            var paintArea = 3.14 * outDiameter * pipeLength;
            // 保温体积
            var insulationVolume = 0.785 * ((outDiameter + insulationThickness * 2) * (outDiameter + insulationThickness * 2)
                                            - outDiameter * outDiameter) * pipeLength;
            // 管道单重
            var pipeWeight = 0.0246615 * pipeThickness * 1000 * (outDiameter - pipeThickness) * 1000;

            // 奥氏体不锈钢考虑1.015系数
            if (cbxPipeMaterial.Text.Contains("304") || cbxPipeMaterial.Text.Contains("316"))
            {
                pipeWeight *= 1.015;
            }
            // 物料单重
            var materialWeight = materialDensity * 0.785 * (outDiameter - pipeThickness * 2) * (outDiameter - pipeThickness * 2);
            // 充水单重
            var waterWeight = 1000 * 0.785 * (outDiameter - pipeThickness * 2) * (outDiameter - pipeThickness * 2);
            // 保温单重
            var insulationWeight = 200 * 0.785 * ((outDiameter + insulationThickness * 2) * (outDiameter + insulationThickness * 2)
                                                  - outDiameter * outDiameter);
            // 水压试验工况荷
            var hydraulicLoad = (waterWeight + pipeWeight + insulationWeight) * pipeLength;
            // 操作工况荷重
            var operatingLoad = (materialWeight + pipeWeight + insulationWeight) * pipeLength;
            // 管道截面惯性矩,单位mm4
            var innerDiameter = outDiameter - 2 * (pipeThickness + corrosionAllowance);
            var moment        = 3.14 / 64 * (Math.Pow(outDiameter * 1000, 4) - Math.Pow(innerDiameter * 1000, 4));
            // 弹性模量,单位为MPa
            double modulus = 0;

            if (cbxPipeMaterial.Text.Contains("20"))
            {
                modulus = LinearInterpolation.Interpolate(ElasticModulus.CS20, designTemperature) * 1000;
            }
            else if (cbxPipeMaterial.Text.Contains("12Cr"))
            {
                modulus = LinearInterpolation.Interpolate(ElasticModulus.AS12Cr1MoVG, designTemperature) * 1000;
            }
            else if (cbxPipeMaterial.Text.Contains("15Cr"))
            {
                modulus = LinearInterpolation.Interpolate(ElasticModulus.AS15CrMoG, designTemperature) * 1000;
            }
            else if (cbxPipeMaterial.Text.Contains("235"))
            {
                modulus = LinearInterpolation.Interpolate(ElasticModulus.CSQ235, designTemperature) * 1000;
            }
            else if (cbxPipeMaterial.Text.Contains("06Cr"))
            {
                modulus = LinearInterpolation.Interpolate(ElasticModulus.SS06Cr19Ni10, designTemperature) * 1000;
            }
            // 管道满水单重 N/m
            var calculatedLoad = hydraulicLoad / pipeLength * 9.8;
            // 计算跨距
            var span = 0.039 * Math.Pow(moment * modulus / calculatedLoad, 0.25);

            txtSupportSpan.Text      = Math.Round(span, 1) + string.Empty;
            txtJacketArea.Text       = Math.Round(jackerArea, 1) + string.Empty;
            txtPaintArea.Text        = Math.Round(paintArea, 1) + string.Empty;
            txtInsulationVolume.Text = Math.Round(insulationVolume, 1) + string.Empty;
            txtTestingLoad.Text      = Math.Round(hydraulicLoad, 1) + string.Empty;
            txtOperatingLoad.Text    = Math.Round(operatingLoad, 1) + string.Empty;
            if (txtDesignTemperature.Text == string.Empty || modulus <= 0)
            {
                txtSupportSpan.Clear();
            }
            if (materialDensity <= 1)
            {
                txtOperatingLoad.Clear();
            }
        }