duheng
2024-10-15 69f942b58a5924e34e6c2bfdadefdcb8e6313edb
WinFrmUI/Yw.WinFrmUI.Phart.Core/00-core/01-calculate/PumpCalcHelper.cs
@@ -1,11 +1,12 @@
using NPOI.Util;
using Yw.Geometry;
namespace Yw.WinFrmUI.Phart
{
    /// <summary>
    /// 性能计算辅助类
    /// </summary>
    public class PumpCalcHelper
    public static class PumpCalcHelper
    {
        #region 常规计算 
@@ -699,6 +700,8 @@
            return similar_point;
        }
        #endregion
        #region 计算推荐参数
@@ -1500,7 +1503,200 @@
        #endregion
        #endregion
    }
        #region 曲线与H=K*Q^i的交点
        /// <summary>
        /// 根据相似点设置相似曲线,相似点(选择点)的x:流量y:杨程
        /// </summary>
        public static double GetSimuValue(Yw.Geometry.CubicSpline2d cubic_spline, Yw.Geometry.Point2d simular_pt, double origin_value, double extend_ratio = 1)
        {
            if (cubic_spline == null)
                return -3;
            if (simular_pt.X < 0.1 || simular_pt.Y < 0.1)
                return -2;
            if (simular_pt.X > cubic_spline.MaxX * extend_ratio * 1.5)
                return -4;
            Yw.Geometry.Point2d sect_pt = GetSectPoint(cubic_spline, simular_pt, extend_ratio);
            if (sect_pt == null || sect_pt.IsZeroPoint())
                return -5;
            //计算相似点的转速/直径
            return CalculateSimuByH(origin_value, sect_pt.Y, simular_pt.Y);
        }
        //ratioIgnore:作用 当simularPoint超出曲线范围时,曲线扩大的倍数
        public static Yw.Geometry.Point2d GetSectPoint(Yw.Geometry.CubicSpline2d cubic_spline, Yw.Geometry.Point2d simular_pt, double ratioIgnore)
        {
            return GetSectPointGeneral(cubic_spline, simular_pt, 2, ratioIgnore);
        }
        public static Yw.Geometry.Point2d GetSectPointParabola(Yw.Geometry.CubicSpline2d cubic_spline, Yw.Geometry.Point2d simular_pt)
        {
            var sect_pt = new Yw.Geometry.Point2d(0, 0);
            if (cubic_spline == null)
                return sect_pt;
            var pt_list = cubic_spline.GetPointListByXRatioRange(1,1.2, 50);
            return GetSectPointParabola(pt_list, simular_pt);
        }
        //通过点simular_pt和点(0,0)的直线,与曲线Curve的交点(没有,返回Point(0,0))
        public static Yw.Geometry.Point2d GetSectPointLine(List<Yw.Geometry.Point2d> CurvePoints, Yw.Geometry.Point2d simular_pt)
        {
            Yw.Geometry.Point2d sect_pt = new Yw.Geometry.Point2d(0, 0);
            if (CurvePoints == null || CurvePoints.Count < 2)
                return sect_pt;
            //计算直线的K
            if (simular_pt.X < 1)
                return sect_pt;
            double a = simular_pt.Y / simular_pt.X;
            if (a < 0.0001)
                return sect_pt;
            //与2点连成直线的交点,判断交点是否在2点之间,即可是曲线的交点
            double b, c;
            double x;
            for (int i = 0; i < CurvePoints.Count - 1; i++)
            {
                 LineHelper.GetKandB(CurvePoints[i], CurvePoints[i + 1], out b, out c);
                /*解方程
                 * y=ax
                 * y=bx+c
                 */
                if (Math.Abs(a - b) < 0.001)
                    continue;
                x = c / (a - b);
                if (UtilsHelper.IsMiddle(CurvePoints[i].X, CurvePoints[i + 1].X, x))
                {
                    sect_pt.X = x;
                    sect_pt.Y = a * x;
                    return sect_pt;
                }
            }
            return sect_pt;
        }
        //通过点simular_pt和点(0,0)的抛物线,与曲线Curve的交点(没有,返回Point(0,0))
        //曲线公式:H=K*Q^2
        public static Yw.Geometry.Point2d GetSectPointParabola(List<Yw.Geometry.Point2d> pt_list, Yw.Geometry.Point2d simular_pt)
        {
            return ParabolaCurveHelper.GetSectPoint(pt_list, simular_pt, 0);
        }
        public static Yw.Geometry.Point2d GetSectPointLine(this Yw.Geometry.CubicSpline2d cubic_spline, Yw.Geometry.Point2d simular_pt)
        {
            Yw.Geometry.Point2d sect_pt = new Yw.Geometry.Point2d(0, 0);
            if (cubic_spline == null)
                return sect_pt;
            //计算直线的K
            if (simular_pt.X < 1)
                return sect_pt;
            double a = simular_pt.Y / simular_pt.X;
            if (a < 0.0001)
                return sect_pt;
            //点越多越精确
            return GetSectPointLine(cubic_spline.GetPointList(100), simular_pt);
        }
        //曲线H=K*Q^i 与曲线Curve的交点(没有,返回Point(0,0))
        public static Yw.Geometry.Point2d GetSectPointGeneral(List<Yw.Geometry.Point2d> pt_list, Yw.Geometry.Point2d simular_pt, double index)
        {
            Yw.Geometry.Point2d sect_pt = new Yw.Geometry.Point2d(0, 0);
            if (pt_list == null || pt_list.Count < 2)
                return sect_pt;
            if (simular_pt.X < 0.1)
                return sect_pt;
            if (Math.Abs(index - 1) < 0.01)
                return GetSectPointLine(pt_list, simular_pt);
            if (Math.Abs(index - 2) < 0.01)
                return GetSectPointParabola(pt_list, simular_pt);
            //计算系数K
            double fixK = simular_pt.Y / Math.Pow(simular_pt.X, index);
            if (fixK < 0.000001)
                return sect_pt;
            //思路是从simular_pt开始逐个增加0.1,直到k值最接近fixK
            double space = (pt_list.Last().X - simular_pt.X) / 1200;
            double x = simular_pt.X;
            double y, k;
            do
            {
                x = x + space;
                y = 0;
                var y_pt_list = pt_list.GetInterPointsY(x);
                if (y_pt_list==null|| !y_pt_list.Any())
                {
                    break;
                }
                y = y_pt_list.Last();
                k = y / Math.Pow(x, index);
            } while (k > fixK);
            sect_pt.X = x;
            sect_pt.Y = y;
            return sect_pt;
        }
        //ratioIgnore:作用 当simular_pt超出范围时,扩大的倍数
        public static Yw.Geometry.Point2d GetSectPointGeneral(this Yw.Geometry.CubicSpline2d cubic_spline, Yw.Geometry.Point2d simular_pt, double index, double ratioIgnore)
        {
            Yw.Geometry.Point2d sect_pt = new Yw.Geometry.Point2d(0, 0);
            if (cubic_spline == null)
                return sect_pt;
            if (simular_pt.X < 1)
                return sect_pt;
            var cubic_spline_ex = cubic_spline.Copy();
            //检查是否在曲线的区域范围内
            double maxQ = cubic_spline_ex.MaxX;
            double maxH = cubic_spline_ex.GetPointY(maxQ);
            double k1 = maxH / Math.Pow(maxQ, index);
            double k2 = simular_pt.Y / Math.Pow(simular_pt.X, index);
            if (k1 > k2)
            {
                cubic_spline_ex.MaxX = cubic_spline_ex.MaxX * ratioIgnore;//放大1.2倍
            }
            if (Math.Abs(index - 1) < 0.01)
                return GetSectPointLine(cubic_spline_ex, simular_pt);
            if (Math.Abs(index - 2) < 0.01)
                return GetSectPointParabola(cubic_spline_ex, simular_pt);
            //计算系数K
            double fixK = simular_pt.Y / Math.Pow(simular_pt.X, index);
            if (fixK < 0.000001)
                return sect_pt;
            //思路是从simular_pt开始逐个增加0.1,直到k值最接近fixK
            double space = (cubic_spline_ex.MaxX - simular_pt.X) / 1000;
            double x = simular_pt.X;
            double y, k;
            do
            {
                x = x + space;
                y = cubic_spline_ex.GetPointY(x);
                k = y / Math.Pow(x, index);
            } while (k > fixK);
            sect_pt.X = x;
            sect_pt.Y = y;
            return sect_pt;
        }
        #endregion 曲线与H=K*Q^i的交点 protect类型,给子类调用,怎么覆盖GetSectPoint
    }
}