using DevExpress.DataAccess.Native.Json; using Yw.Pump; using Yw.WinFrmUI.Phart; namespace HStation.WinFrmUI { //等效线辅助类 public class EqualParaCurveEListHelper { #region 最大曲线 /// /// 等效线与最大曲线的交点(注意 只适合最大的扬程线,其余流量扬程线要用切割找交点的方法) /// /// /// /// /// public static List GetSectPoints2MaxFeatCurve( List equalCurveListE, Yw.Pump.CurveQH maxCurveQH, double igonre_h)//保证靠的太近可以认为相交) { return GetSectPoints2MaxFeatCurve4QH(equalCurveListE, maxCurveQH, igonre_h); } /// /// 返回QH点 (注意 只适合最大的扬程线) /// /// /// /// /// public static List GetSectPoints2MaxFeatCurve4QH( List equalCurveListE, Yw.Pump.CurveQH maxCurveQH, double igonre_h)//保证靠的太近可以认为相交) { List define_points = null; if (equalCurveListE == null || equalCurveListE.Count < 3 || maxCurveQH == null) { return null; } // define_points = new List(); // foreach (var curve in equalCurveListE) { if (curve.DefinePoints == null || curve.DefinePoints.Count == 0) continue; if (curve.DefinePoints.Count == 1) { //添加单点 define_points.Add(new Yw.Geometry.Point2d(curve.DefinePoints.First().X, curve.DefinePoints.First().Y)); } else { //注意两端都可能有交点 var firstPointY = maxCurveQH.FeatCurve.GetPointY(curve.DefinePoints.First().X); if ((Math.Abs(firstPointY - curve.DefinePoints.First().Y) < igonre_h)) { define_points.Add(new Yw.Geometry.Point2d(curve.DefinePoints.First().X, curve.DefinePoints.First().Y)); } var lastPointY = maxCurveQH.FeatCurve.GetPointY(curve.DefinePoints.Last().X); if ((Math.Abs(lastPointY - curve.DefinePoints.Last().Y) < igonre_h)) { define_points.Add(new Yw.Geometry.Point2d(curve.DefinePoints.Last().X, curve.DefinePoints.Last().Y)); } } } return define_points; } /// /// 返回QE点 (注意 只适合最大的扬程线) /// /// /// /// /// public static List GetSectPoints2MaxFeatCurve4QE( List equalCurveListE, Yw.Pump.CurveQH maxCurveQH, double igonre_h)//保证靠的太近可以认为相交) { List define_points = null; if (equalCurveListE == null || equalCurveListE.Count < 3 || maxCurveQH == null) { return null; } // define_points = new List(); // foreach (CurveEqualEViewModel curve in equalCurveListE) { if (curve.DefinePoints == null || curve.DefinePoints.Count == 0) continue; if (curve.DefinePoints.Count == 1) { //添加单点 define_points.Add(new Yw.Geometry.Point2d(curve.DefinePoints.First().X, curve.Eff)); } else { //注意两端都可能有交点 var firstPointY = maxCurveQH.FeatCurve.GetPointY(curve.DefinePoints.First().X); if ((Math.Abs(firstPointY - curve.DefinePoints.First().Y) < igonre_h)) { define_points.Add(new Yw.Geometry.Point2d(curve.DefinePoints.First().X, curve.Eff)); } var lastPointY = maxCurveQH.FeatCurve.GetPointY(curve.DefinePoints.Last().X); if ((Math.Abs(lastPointY - curve.DefinePoints.Last().Y) < igonre_h)) { define_points.Add(new Yw.Geometry.Point2d(curve.DefinePoints.Last().X, curve.Eff)); } } } return define_points; } ///// ///// 将等效线换算成效率性能曲线:只能针对离心泵 (注意 只适合最大的扬程线,其余流量扬程线要用切割找交点的方法) ///// ///// ///// ///// ///// ///// ///// //public static Yw.Pump.CurveQE CalcCurveQE4Max( // List equalCurveListE, // Yw.Pump.CurveQH maxCurveQH, // Yw.Pump.CurveQE maxCurveQE_Origin,//原来的 // double igonre_h,//保证靠的太近可以认为相交 // out List define_points_qe) //{ // define_points_qe = null; // if (equalCurveListE == null || equalCurveListE.Count < 3) // { // return null; // } // if (igonre_h < 0.01) // { // igonre_h = 0.01; // } // // // define_points_qe = new List(); // // // foreach (CurveEqualEViewModel curve in equalCurveListE) // { // if (curve.DefinePoints == null || curve.DefinePoints.Count == 0) // continue; // if (curve.DefinePoints.Count == 1) // { //添加单点 // define_points_qe.Add(new Yw.Geometry.Point2d(curve.DefinePoints .First().X, curve.Eff)); // } // else // { // //注意两端都可能有交点 // var firstPointY = maxCurveQH.FeatCurve.GetPointY(curve.DefinePoints.First().X); // if ((Math.Abs(firstPointY - curve.DefinePoints.First().Y) < igonre_h)) // { // define_points_qe.Add(new Yw.Geometry.Point2d(curve.DefinePoints.First().X, curve.Eff)); // } // var lastPointY = maxCurveQH.FeatCurve.GetPointY(curve.DefinePoints.Last().X); // if ((Math.Abs(lastPointY - curve.DefinePoints.Last().Y) < igonre_h)) // { // define_points_qe.Add(new Yw.Geometry.Point2d(curve.DefinePoints.Last().X, curve.Eff)); // } // } // } // if (define_points_qe.Count < 3) // return null; // //插入最大流量点 // var maxQ = maxCurveQH.FeatCurve.GetXRange().MaxX; // var maxQ2 = (from x in define_points_qe select x.X).Max(); // if (maxQ2 < maxQ * 0.99) // { // //var maxQ_E = define_points_qe.ge.GetPointY(define_points_qe, maxQ); // //define_points_qe.Add(new Yw.Geometry.Point2d(maxQ, maxQ_E)); // } // //排序 // define_points_qe.Sort(new Yw.Geometry.Point2d.Comparer(Yw.Geometry.Point2d.eSortType.X)); // var fitTypeQE = Eventech.Model.eCurveFitType.CubicCurve; // //跨度有点大, 中间插入原来的曲线值的点 // if (maxCurveQE_Origin != null) // { // fitTypeQE = maxCurveQE_Origin.CurveFitType; // if (define_points_qe[0].X > maxCurveQH.RangeMax / 10) // { // var insert_x = define_points_qe[0].X / 2; // define_points_qe.Insert(0, new Yw.Geometry.Point2d(insert_x, Eventech.Common.FitCurveHelper.GetPointY(maxCurveQE_Origin, insert_x))); // } // } // //插入最小点 // if (maxCurveQH.RangeMin < maxCurveQH.RangeMax / 20) // { // define_points_qe.Insert(0, new Yw.Geometry.Point2d(0, 0)); // } // //处理高效点 // Yw.Geometry.Point2d eta_pt = new Yw.Geometry.Point2d(); // foreach (var pt in define_points_qe) // { // if (pt.Y > eta_pt.Y) // { // eta_pt.X = pt.X; // eta_pt.Y = pt.Y; // } // } // var points2 = Eventech.Common.AmendCurveHelper.ByOnePointY1(define_points_qe, eta_pt, fitTypeQE); // return new Model.CurveExpress(points2, fitTypeQE); //} #endregion #region 中间的线 //根据等效线产生流量效率线(注意 此方法不适合最大的流量扬程线) public static List GetSectPoints2MiddleFeatCurve( List EqualParaCurvesE, Yw.Pump.CurveQH ExpressCurveQH, Yw.Pump.CurveQE ExpressCurveQE_origin, double igonre_h//保证靠的太近可以认为相交 ) { List points_qh_效率 = null; List points_qe = null; CalcCurveQE4Middle(EqualParaCurvesE, ExpressCurveQH, ExpressCurveQE_origin, igonre_h, out points_qh_效率, out points_qe); return points_qh_效率; } public static List GetSectPoints2MiddleFeatCurveQH( List EqualParaCurvesE, Yw.Pump.CurveQH ExpressCurveQH, Yw.Pump.CurveQE ExpressCurveQE_origin, double igonre_h//保证靠的太近可以认为相交 ) { List points_qh_效率 = null; List points_qe = null; CalcCurveQE4Middle(EqualParaCurvesE, ExpressCurveQH, ExpressCurveQE_origin, igonre_h, out points_qh_效率, out points_qe); return points_qh_效率; } //根据等效线产生流量效率线(注意 此方法不适合最大的流量扬程线) public static Yw.Pump.CurveQE CalcCurveQE4Middle( List EqualParaCurvesE, Yw.Pump.CurveQH ExpressCurveQH, Yw.Pump.CurveQE ExpressCurveQE_origin, double igonre_h, out List points_qe) { List points_qh_效率 = null; return CalcCurveQE4Middle(EqualParaCurvesE, ExpressCurveQH, ExpressCurveQE_origin, igonre_h, out points_qh_效率, out points_qe); } //根据等效线产生流量效率线(注意 此方法不适合最大的流量扬程线) public static Yw.Pump.CurveQE CalcCurveQE4Middle( List EqualParaCurvesE, Yw.Pump.CurveQH ExpressCurveQH, Yw.Pump.CurveQE ExpressCurveQE_origin, double igonre_h,//保证靠的太近可以认为相交 out List points_qh_效率,//EqualParaCurvesE 与 ExpressCurveQH 的相交线 out List points_qe)//定义的流量效率线上的点 { return CalcCurveQESimu(EqualParaCurvesE, ExpressCurveQH, ExpressCurveQE_origin, igonre_h, false, out points_qh_效率, out points_qe); } /// /// 不会延长到首尾, 仅仅求交点 /// /// /// /// /// /// /// /// /// public static List GetSectPoints2MiddleFeatCurveQE( List EqualParaCurvesE, Yw.Pump.CurveQH ExpressCurveQH, double igonre_h,//保证靠的太近可以认为相交 bool isCheckEndPt, out List points_head)//定义的流量QH线上的点 { double max_eta_flow = 0; return GetSectPoints2MiddleFeatCurveQE(EqualParaCurvesE, ExpressCurveQH, igonre_h, isCheckEndPt, out points_head, out max_eta_flow); } /// /// 不会延长到首尾, 仅仅求交点 /// /// /// /// /// /// /// /// /// private static List GetSectPoints2MiddleFeatCurveQE( List EqualParaCurvesE, Yw.Pump.CurveQH ExpressCurveQH, double igonre_h,//保证靠的太近可以认为相交 bool isCheckEndPt, out List points_head, out double max_eta_flow)//定义的流量QH线上的点 { max_eta_flow = 0; points_head = null; if (EqualParaCurvesE == null || EqualParaCurvesE.Count < 3) return null; points_head = new List(); var points_eta = new List(); //等效线集合循环 double max_eta = 0; for (int kk = 0; kk < EqualParaCurvesE.Count; kk++) { var curveE = EqualParaCurvesE[kk]; if (curveE.DefinePoints == null || curveE.DefinePoints.Count == 0) continue; if (curveE.Eff > max_eta) { max_eta = curveE.Eff; max_eta_flow = curveE.DefinePoints[0].X; } if (curveE.DefinePoints.Count == 1) {// 点 var pt = curveE.DefinePoints[0]; if (igonre_h < 0.01)//保证靠的太近可以认为相交 igonre_h = pt.Y / 100; var fit_y1 = ExpressCurveQH.FeatCurve.GetPointY(pt.X); // if (Math.Abs(fit_y1 - pt.Y) < igonre_h) { points_head.Add(pt); points_eta.Add(new Yw.Geometry.Point2d(pt.X, curveE.Eff)); } continue; } if (igonre_h < 0.01)//保证靠的太近可以认为相交 { var yyy = from x in curveE.DefinePoints select x.Y; igonre_h = Math.Abs(yyy.Max() - yyy.Min()) / 10; } //判断是否就是等效线的端点 if (isCheckEndPt) { var min_y_pt = curveE.DefinePoints.OrderBy(x => x.Y).FirstOrDefault(); var fit_y_2 = ExpressCurveQH.FeatCurve.GetPointY(min_y_pt.X); // if (Math.Abs(fit_y_2 - min_y_pt.Y) < igonre_h) { points_head.Add(min_y_pt); points_eta.Add(new Yw.Geometry.Point2d(min_y_pt.X, curveE.Eff)); continue; } } if (curveE.DefinePoints.Count == 2) { #region Line var start0_p = curveE.DefinePoints[0]; var end0_p = curveE.DefinePoints[1]; var start0_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(start0_p.X); var end0_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(end0_p.X); //直线于曲线相交 if ((start0_p_y_1 <= start0_p.Y && end0_p_y_1 >= end0_p.Y) || (start0_p_y_1 >= start0_p.Y && end0_p_y_1 <= end0_p.Y)) { var x = (start0_p.X + end0_p.X) / 2; var y = ExpressCurveQH.FeatCurve.GetPointY(x); var p = new Yw.Geometry.Point2d(x, y); points_head.Add(p); points_eta.Add(new Yw.Geometry.Point2d(x, curveE.Eff)); } else { double min_dis_y = double.MaxValue; var min_pt = new Yw.Geometry.Point2d(); var startY_1 = ExpressCurveQH.FeatCurve.GetPointY(curveE.DefinePoints[0].X); if (Math.Abs(startY_1 - curveE.DefinePoints[0].Y) < min_dis_y) { min_dis_y = Math.Abs(startY_1 - curveE.DefinePoints[0].Y); min_pt.X = curveE.DefinePoints[0].X; min_pt.Y = startY_1; } var endY_1 = ExpressCurveQH.FeatCurve.GetPointY(curveE.DefinePoints[1].X); if (Math.Abs(endY_1 - curveE.DefinePoints[1].Y) < min_dis_y) { min_dis_y = Math.Abs(endY_1 - curveE.DefinePoints[1].Y); min_pt.X = curveE.DefinePoints[1].X; min_pt.Y = startY_1; } if (min_dis_y < igonre_h) {//很近就认为相交了 points_head.Add(min_pt); points_eta.Add(new Yw.Geometry.Point2d(min_pt.X, curveE.Eff)); } } continue; #endregion } if (curveE.DefinePoints.Count == 3) {// #region 三个点只能用二次贝塞尔曲线 List current_sect_pts_qh = new List(); List current_sect_pts_qe = new List(); Yw.Geometry.BezierCurve2 bezeir = new Yw.Geometry.BezierCurve2(); bezeir.Point0 = curveE.DefinePoints[0]; bezeir.Point1 = curveE.DefinePoints[1]; bezeir.Point2 = curveE.DefinePoints[2]; if (igonre_h < 0.01)//保证靠的太近可以认为相交 { var yyy = from x in curveE.DefinePoints select x.Y; igonre_h = Math.Abs(yyy.Max() - yyy.Min()) / 15; } #region 贝塞尔曲线集合循环 var startY_1 = ExpressCurveQH.FeatCurve.GetPointY(bezeir.Point0.X); var endY_1 = ExpressCurveQH.FeatCurve.GetPointY(bezeir.Point2.X); //贝塞尔曲线与性能曲线有交点 if ((startY_1 <= bezeir.Point0.Y && endY_1 >= bezeir.Point2.Y) || (startY_1 >= bezeir.Point0.Y && endY_1 <= bezeir.Point2.Y)) { //第一次循环 for (int i = 0; i < 10; i++) { var start0_uu = i * 0.1; var end0_uu = start0_uu + 0.1; var start0_p_x = bezeir.GetX(start0_uu); var start0_p_y = bezeir.GetY(start0_uu); var end0_p_x = bezeir.GetX(end0_uu); var end0_p_y = bezeir.GetY(end0_uu); var start0_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(start0_p_x); var end0_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(end0_p_x); if ((start0_p_y_1 <= start0_p_y && end0_p_y_1 >= end0_p_y) || (start0_p_y_1 >= start0_p_y && end0_p_y_1 <= end0_p_y)) { //第二次循环 for (int j = 0; j < 10; j++) { var start1_uu = start0_uu + j * 0.01; var end1_uu = start1_uu + 0.01; var start1_p_x = bezeir.GetX(start1_uu); var start1_p_y = bezeir.GetY(start1_uu); var end1_p_x = bezeir.GetX(end1_uu); var end1_p_y = bezeir.GetY(end1_uu); var start1_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(start1_p_x); var end1_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(end1_p_x); if ((start1_p_y_1 <= start1_p_y && end1_p_y_1 >= end1_p_y) || (start1_p_y_1 >= start1_p_y && end1_p_y_1 <= end1_p_y)) { //第三次循环 for (int k = 0; k < 10; k++) { var start2_uu = start1_uu + k * 0.001; var end2_uu = start2_uu + 0.001; var start2_p_x = bezeir.GetX(start2_uu); var start2_p_y = bezeir.GetY(start2_uu); var end2_p_x = bezeir.GetX(end2_uu); var end2_p_y = bezeir.GetY(end2_uu); var start2_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(start2_p_x); var end2_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(end2_p_x); if ((start2_p_y_1 <= start2_p_y && end2_p_y_1 >= end2_p_y) || (start2_p_y_1 >= start2_p_y && end2_p_y_1 <= end2_p_y)) { var x = (start2_p_x + end2_p_x) / 2; var y = ExpressCurveQH.FeatCurve.GetPointY(x); var p = new Yw.Geometry.Point2d(x, y); current_sect_pts_qh.Add(p); current_sect_pts_qe.Add(new Yw.Geometry.Point2d(x, curveE.Eff)); break; } } break; } } break; } } } #endregion #region 没有交点,但可能和曲线弯曲有交点, 用离散点求最小距离 double min_dis_y = double.MaxValue; var min_pt = new Yw.Geometry.Point2d(); for (int i = 0; i < 30; i++) { var bsr_uu = i * 1.0 / 29.0; var bsr_pt_x = bezeir.GetX(bsr_uu); var bsr_pt_y = bezeir.GetY(bsr_uu); var fit_pt_y = ExpressCurveQH.FeatCurve.GetPointY(bsr_pt_x); if (Math.Abs(fit_pt_y - bsr_pt_y) < min_dis_y) { min_dis_y = Math.Abs(fit_pt_y - bsr_pt_y); min_pt.X = bsr_pt_x; min_pt.Y = fit_pt_y; } } if (min_dis_y < igonre_h) {//很近就认为相交了 current_sect_pts_qh.Add(min_pt); current_sect_pts_qe.Add(new Yw.Geometry.Point2d(min_pt.X, curveE.Eff)); } #endregion if (current_sect_pts_qe.Count == 1) { points_head.Add(current_sect_pts_qh.First()); points_eta.Add(current_sect_pts_qe.First()); } else if (current_sect_pts_qe.Count > 1) { points_head.Add(current_sect_pts_qh.First()); points_eta.Add(current_sect_pts_qe.First()); if (current_sect_pts_qe.Count > 1) { var xxx = (from x in curveE.DefinePoints select x.X); var min_x = xxx.Min(); var max_x = xxx.Max(); //防制 靠的太近, 重复点 for (int k = 1; k < current_sect_pts_qe.Count; k++) { if (Math.Abs(current_sect_pts_qe[k].X - current_sect_pts_qe[0].X) < (max_x - min_x) / 30) continue; points_head.Add(current_sect_pts_qh[k]); points_eta.Add(current_sect_pts_qe[k]); } } } #endregion } else if (curveE.DefinePoints.Count > 3) { List current_sect_pts_qh = new List(); List current_sect_pts_qe = new List(); List allBeziers = null; //获取所有的贝塞尔曲线 if (curveE.IsClosed) { allBeziers = Yw.Geometry.BezierCurveHelper.CreateCloseCurves(curveE.DefinePoints.ToArray()); } else { allBeziers = Yw.Geometry.BezierCurveHelper.CreateOpenCurves(curveE.DefinePoints.ToArray()); } if (allBeziers == null) continue; if (igonre_h < 0.01)//保证靠的太近可以认为相交 { var yyy = from x in curveE.DefinePoints select x.Y; igonre_h = Math.Abs(yyy.Max() - yyy.Min()) / 5; } foreach (var bezeir in allBeziers) { var startY_1 = ExpressCurveQH.FeatCurve.GetPointY(bezeir.Point0.X); var endY_1 = ExpressCurveQH.FeatCurve.GetPointY(bezeir.Point3.X); //贝塞尔曲线与性能曲线有交点 if ((startY_1 <= bezeir.Point0.Y && endY_1 >= bezeir.Point3.Y) || (startY_1 >= bezeir.Point0.Y && endY_1 <= bezeir.Point3.Y)) { #region 贝塞尔曲线集合循环 //第一次循环 for (int i = 0; i < 10; i++) { var start0_uu = i * 0.1; var end0_uu = start0_uu + 0.1; var start0_p_x = bezeir.GetX(start0_uu); var start0_p_y = bezeir.GetY(start0_uu); var end0_p_x = bezeir.GetX(end0_uu); var end0_p_y = bezeir.GetY(end0_uu); var start0_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(start0_p_x); var end0_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(end0_p_x); if ((start0_p_y_1 <= start0_p_y && end0_p_y_1 >= end0_p_y) || (start0_p_y_1 >= start0_p_y && end0_p_y_1 <= end0_p_y)) { //第二次循环 for (int j = 0; j < 10; j++) { var start1_uu = start0_uu + j * 0.01; var end1_uu = start1_uu + 0.01; var start1_p_x = bezeir.GetX(start1_uu); var start1_p_y = bezeir.GetY(start1_uu); var end1_p_x = bezeir.GetX(end1_uu); var end1_p_y = bezeir.GetY(end1_uu); var start1_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(start1_p_x); var end1_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(end1_p_x); if ((start1_p_y_1 <= start1_p_y && end1_p_y_1 >= end1_p_y) || (start1_p_y_1 >= start1_p_y && end1_p_y_1 <= end1_p_y)) { //第三次循环 for (int k = 0; k < 10; k++) { var start2_uu = start1_uu + k * 0.001; var end2_uu = start2_uu + 0.001; var start2_p_x = bezeir.GetX(start2_uu); var start2_p_y = bezeir.GetY(start2_uu); var end2_p_x = bezeir.GetX(end2_uu); var end2_p_y = bezeir.GetY(end2_uu); var start2_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(start2_p_x); var end2_p_y_1 = ExpressCurveQH.FeatCurve.GetPointY(end2_p_x); if ((start2_p_y_1 <= start2_p_y && end2_p_y_1 >= end2_p_y) || (start2_p_y_1 >= start2_p_y && end2_p_y_1 <= end2_p_y)) { var x = (start2_p_x + end2_p_x) / 2; var y = ExpressCurveQH.FeatCurve.GetPointY(x); var p = new Yw.Geometry.Point2d(x, y); current_sect_pts_qh.Add(p); current_sect_pts_qe.Add(new Yw.Geometry.Point2d(x, curveE.Eff)); break; } } break; } } break; } } #endregion } } #region 没有交点 ,但可能和曲线弯曲有交点, 用离散点求最小距离 double min_dis_y = double.MaxValue; var min_pt = new Yw.Geometry.Point2d(); foreach (var bezeir in allBeziers) { for (int i = 0; i < 30; i++) { var bsr_uu = i * 1.0 / 29.0; var bsr_pt_x = bezeir.GetX(bsr_uu); var bsr_pt_y = bezeir.GetY(bsr_uu); var fit_pt_y = ExpressCurveQH.FeatCurve.GetPointY(bsr_pt_x); if (Math.Abs(fit_pt_y - bsr_pt_y) < min_dis_y) { min_dis_y = Math.Abs(fit_pt_y - bsr_pt_y); min_pt.X = bsr_pt_x; min_pt.Y = fit_pt_y; } } } if (min_dis_y < igonre_h) {//很近就认为相交了 current_sect_pts_qh.Add(min_pt); current_sect_pts_qe.Add(new Yw.Geometry.Point2d(min_pt.X, curveE.Eff)); } #endregion if (current_sect_pts_qe.Count == 0) { } else if (current_sect_pts_qe.Count == 1) { points_head.Add(current_sect_pts_qh.First()); points_eta.Add(current_sect_pts_qe.First()); } else if (current_sect_pts_qe.Count == 2) { var chk_dis = (ExpressCurveQH.FeatCurve.GetXRange().MaxX - ExpressCurveQH.FeatCurve.GetXRange().MinX) / 120; points_head.Add(current_sect_pts_qh.First()); points_eta.Add(current_sect_pts_qe.First()); if (Math.Abs(current_sect_pts_qe[1].X - current_sect_pts_qe[0].X) > chk_dis) { points_head.Add(current_sect_pts_qh[1]); points_eta.Add(current_sect_pts_qe[1]); } } else { points_head.Add(current_sect_pts_qh.First()); points_eta.Add(current_sect_pts_qe.First()); var chk_dis = (ExpressCurveQH.FeatCurve.GetXRange().MaxX - ExpressCurveQH.FeatCurve.GetXRange().MinX) / 120; //防制 靠的太近, 重复点 for (int k = 1; k < current_sect_pts_qe.Count; k++) { bool isOk = true; if (Math.Abs(current_sect_pts_qe[k].X - current_sect_pts_qe[0].X) < chk_dis) { isOk = false; } for (int m = k + 1; m < current_sect_pts_qe.Count; m++) { if (Math.Abs(current_sect_pts_qe[m].X - current_sect_pts_qe[k].X) < chk_dis) { isOk = false; } } if (isOk) { points_head.Add(current_sect_pts_qh[k]); points_eta.Add(current_sect_pts_qe[k]); } } } } } return points_eta = (from x in points_eta orderby x.X select x).ToList(); } #endregion #region 最小曲线 public static List GetSectPoints2MinFeatCurve( List EqualParaCurvesE, Yw.Pump.CurveQH ExpressCurveQH, Yw.Pump.CurveQE ExpressCurveQE_origin, double igonre_h//保证靠的太近可以认为相交 ) { List points_qh_效率 = null; List points_qe = null; CalcCurveQE4Min(EqualParaCurvesE, ExpressCurveQH, ExpressCurveQE_origin, igonre_h, out points_qh_效率, out points_qe); return points_qh_效率; } /// /// 返回QE点 (注意 只适合最小的扬程线) /// /// /// /// /// public static List GetSectPoints2MinFeatCurve4QE( List equalCurveListE, Yw.Pump.CurveQH maxCurveQH, double igonre_h)//保证靠的太近可以认为相交) { List define_points = null; if (equalCurveListE == null || equalCurveListE.Count < 3 || maxCurveQH == null) { return null; } // define_points = new List(); // foreach (CurveEqualEViewModel curve in equalCurveListE) { if (curve.DefinePoints == null || curve.DefinePoints.Count == 0) continue; if (curve.DefinePoints.Count == 1) { //添加单点 continue; } else { //注意两端都可能有交点 var firstPointY = maxCurveQH.FeatCurve.GetPointY(curve.DefinePoints.First().X); if ((Math.Abs(firstPointY - curve.DefinePoints.First().Y) < igonre_h)) { define_points.Add(new Yw.Geometry.Point2d(curve.DefinePoints.First().X, curve.Eff)); } var lastPointY = maxCurveQH.FeatCurve.GetPointY(curve.DefinePoints.Last().X); if ((Math.Abs(lastPointY - curve.DefinePoints.Last().Y) < igonre_h)) { define_points.Add(new Yw.Geometry.Point2d(curve.DefinePoints.Last().X, curve.Eff)); } } } return define_points; } /// /// 只针对离心泵 最后一条切割线, 最后一条可能是等效线的端点, 不用相交判断,所以需要特殊处理 /// /// /// /// /// /// /// /// public static Yw.Pump.CurveQE CalcCurveQE4Min( List EqualParaCurvesE, Yw.Pump.CurveQH ExpressCurveQH, Yw.Pump.CurveQE ExpressCurveQE_origin, double igonre_h,//保证靠的太近可以认为相交 out List points_qh_效率,//EqualParaCurvesE 与 ExpressCurveQH 的相交线 out List points_qe)//定义的流量效率线上的点 { return CalcCurveQESimu(EqualParaCurvesE, ExpressCurveQH, ExpressCurveQE_origin, igonre_h, true, out points_qh_效率, out points_qe); } #endregion /// /// 只针对离心泵 /// /// /// /// /// /// /// /// /// public static Yw.Pump.CurveQE CalcCurveQESimu( List EqualParaCurvesE, Yw.Pump.CurveQH ExpressCurveQH, Yw.Pump.CurveQE ExpressCurveQE_origin, double igonre_h,//保证靠的太近可以认为相交 bool isCheckEndPt, out List points_qh_效率,//EqualParaCurvesE 与 ExpressCurveQH 的相交线 out List points_qe)//定义的流量效率线上的点 { points_qh_效率 = null; points_qe = null; if (EqualParaCurvesE == null || EqualParaCurvesE.Count < 3) return null; points_qh_效率 = new List(); double max_eta_flow = 0; points_qe = GetSectPoints2MiddleFeatCurveQE(EqualParaCurvesE, ExpressCurveQH, igonre_h, isCheckEndPt, out points_qh_效率, out max_eta_flow); if (points_qe == null || points_qe.Count < 4) return null; points_qe = (from x in points_qe orderby x.X select x).ToList(); var min_flow = points_qe.First().X; var fitTypeQE = Yw.Ahart.eFeatType.Cubic; //跨度有点大, 中间插入原来的曲线值的点 if (points_qe.Count < 6) { if (ExpressCurveQE_origin != null) { fitTypeQE = ExpressCurveQE_origin.FeatType; if (points_qe[0].X > ExpressCurveQH.FeatCurve.GetXRange().MaxX / 10) { var insert_x = points_qe[0].X / 2; points_qe.Insert(0, new Yw.Geometry.Point2d(insert_x, ExpressCurveQE_origin.FeatCurve.GetPointY(insert_x))); } } } //插入最小点 if (ExpressCurveQH.FeatCurve.GetXRange().MaxX < ExpressCurveQH.FeatCurve.GetXRange().MaxX / 20) { points_qe.Insert(0, new Yw.Geometry.Point2d(0, 0)); } var last_pt_in_qh = ExpressCurveQH.FeatCurve.GetPointList().LastOrDefault(); if (points_qe.Last().X < last_pt_in_qh.X && ExpressCurveQE_origin != null) {//延长到最后一个点 // 效率线再加一个点 , 最后一个点的效率 var last_pt_eta = ExpressCurveQE_origin.FeatCurve.GetPointY(last_pt_in_qh.X); if (last_pt_eta > points_qe.Last().Y) { var temp = new Yw.Pump.CurveQE(fitTypeQE, points_qe); points_qe.Add(new Yw.Geometry.Point2d(last_pt_in_qh.X, temp.FeatCurve.GetPointY(last_pt_in_qh.X))); } else { points_qe.Add(new Yw.Geometry.Point2d(last_pt_in_qh.X, last_pt_eta)); } } var curve_qe = points_qe.AmendByZeroPointY((min_flow + max_eta_flow) / 2, 0, fitTypeQE); var curve_qe2 = new Yw.Pump.CurveQE(fitTypeQE, points_qe); //高效点 //var curve_para_list = (from x in EqualParaCurvesE orderby x.Eff select x.Eff).ToList(); //var gao_xiao_can_shu = curve_para_list[curve_para_list.Count() - 2]; //foreach (var pt in points_qe) //{ // if (pt.Y < gao_xiao_can_shu) // continue; // var fit_pt_y = Eventech.Common.FitCurveHelper.GetPointY(curve_qh, pt.X); // if (Math.Abs(fit_pt_y - pt.Y) < 0.2) // continue; // Yw.Geometry.Point2d eta_pt = new Yw.Geometry.Point2d(pt.X, fit_pt_y); // var points2 = Eventech.Common.AmendCurveHelper.ByOnePointY1(points_qe, eta_pt, fitTypeQE); // curve_qh = new Model.CurveExpress(points2); //} return curve_qe2; } ////计算效率(现有等效线插值计算):必须用GetBoudaryCurveIndex获取 //public static CurveEqualEViewModel CalcEta( // PumpCurveViewModel curveGroupMax,//最大曲线 // PumpCurveViewModel curveGroupMin,//最小曲线 // List equalCurveListE, // Yw.Geometry.Point2d designPt) //{ // try // { // if (equalCurveListE == null || equalCurveListE.Count < 2) // return null; // var boundary = GetBoundaryPoint(equalCurveListE); // var small_curve_index = GetBoudaryCurveIndex(curveGroupMax, curveGroupMin, equalCurveListE, designPt); // if (small_curve_index < 0) // return null; // var small_paras_curve = equalCurveListE[small_curve_index]; // var large_paras_curve = GetLastLargeCurve(equalCurveListE, small_paras_curve);//上一条 // return CalcEta(boundary, curveGroupMax, curveGroupMin, large_paras_curve, small_paras_curve, designPt); // } // catch // { // return null; // } //} ////计算效率(现有等效线插值计算):必须用GetBoudaryCurveIndex获取 //public static CurveEqualEViewModel CalcEta( // Yw.Geometry.Boundary2d boundary, // PumpCurveViewModel curveGroupMax,//最大曲线 // PumpCurveViewModel curveGroupMin,//最小曲线 // CurveEqualEViewModel equalCurveListE_large, // CurveEqualEViewModel equalCurveListE_small, // Yw.Geometry.Point2d designPt) //{ // var smallCurve = equalCurveListE_small.DefinePoints; // var largeCurve = equalCurveListE_large.DefinePoints; // var small_Eff = equalCurveListE_small.Eff; // var large_Eff = equalCurveListE_large.Eff; // CurveEqualEViewModel result_curve = null; // double result_dis = 0; // for (int i = 0; i <= 10; i++) // { // double currentEta = small_Eff + (large_Eff - small_Eff) * i / 10; // CurveEqualEViewModel curve = null; // if (currentEta == small_Eff) // { // curve = new CurveEqualEViewModel() { IsClosed = equalCurveListE_small.IsClosed, Eff = equalCurveListE_small.Eff, Tension = 0.5f, DefinePoints = equalCurveListE_small.DefinePoints }; // } // else if (currentEta == large_Eff) // { // curve = new CurveEqualEViewModel() { IsClosed = equalCurveListE_large.IsClosed, Eff = equalCurveListE_large.Eff, Tension = 0.5f, DefinePoints = equalCurveListE_large.DefinePoints }; // } // else // { // curve = CalcEqualParaCurveE2(boundary, curveGroupMax, curveGroupMin, largeCurve, equalCurveListE_large.Eff, smallCurve, equalCurveListE_small.Eff, currentEta); // } // if (result_curve == null) // { // result_curve = curve; // result_dis = Yw.Geometry.BezierCurveHelper.GetDistance(boundary, result_curve.DefinePoints, designPt); // } // else // { // var dis2 = Yw.Geometry.BezierCurveHelper.GetDistance(boundary, curve.DefinePoints, designPt); // if (dis2 < result_dis) // {//谁近用谁 // result_dis = dis2; // result_curve = curve; // } // } // } // return result_curve; //} ////获取在哪个等效线里面(注意获取的是designPt外围的CombineCurve序号) //public static int GetBoudaryCurveIndex( // PumpCurveViewModel curveGroupMax,//最大曲线 // PumpCurveViewModel curveGroupMin,//最小曲线 // List equalCurveListE, // Yw.Geometry.Point2d designPt) //{ // if (designPt == null) // return -1; // if (equalCurveListE == null || equalCurveListE.Count < 2) // return -1; // Dictionary dict_sect = new Dictionary();//交点 注意是chart上的点 // Dictionary dict_dictance = new Dictionary(); // for (int i = equalCurveListE.Count - 1; i >= 0; i--)//equalCurveListE是从小到大排序 // { // var current_curve = equalCurveListE[i]; // if (current_curve.DefinePoints == null) // { // continue; // } // if (current_curve.DefinePoints.Count <= 1) // {// 点 // continue; // } // if (current_curve.DefinePoints.Count == 2) // {//直线 // continue; // } // if (current_curve.IsClosed) // {//封闭 // List allBeziers = Yw.Geometry.BezierCurveHelper.CreateCloseCurves(current_curve.DefinePoints.ToArray()); // var apexPoints = Yw.Geometry.BezierCurveHelper.GetApexPoints(allBeziers, 30); // if (Eventech.Common.PolygonHelper.IsInner_Chart(designPt, apexPoints)) // {//在封闭区域内部 // return i; // } // continue; // } // var last_curve = GetLastLargeCurve(equalCurveListE, current_curve);//上一条 // if (last_curve == null) // {//上一条是空 // continue; // } // var boudaryPoints = GetBondaryPoints(last_curve.DefinePoints, current_curve.DefinePoints, 30); // if (Eventech.Common.PolygonHelper.IsInner_Chart(designPt, boudaryPoints)) // {//在封闭区域内部 // return i; // } // } // return -1; //} //得到比current_eta大的最近的等效线,如果上一条有两个,会返回最近的那条 public static CurveEqualEViewModel GetLastLargeCurve( List equalCurveListE, CurveEqualEViewModel current_curve) { var current_eta = current_curve.Eff; CurveEqualEViewModel last_curve = null; for (int i = 0; i < equalCurveListE.Count; i++) { var curve = equalCurveListE[i]; if (curve.Eff <= current_eta + 0.010) continue; if (last_curve == null) { last_curve = curve; continue; } if (curve.Eff < last_curve.Eff) { last_curve = curve; continue; } else if (Math.Abs(curve.Eff - last_curve.Eff) < 0.1) {//相同就看谁靠的近一点 if (Math.Abs(current_curve.DefinePoints.First().X - curve.DefinePoints.First().X) < Math.Abs(current_curve.DefinePoints.First().X - last_curve.DefinePoints.First().X)) last_curve = curve; continue; } } return last_curve; } //两个等效线围城的区域 public static List GetBondaryPoints( List largeCurve, List smallCurve, int insertPointNumber = 8) { if (largeCurve.Count <= 2) { var cur1 = Yw.Geometry.BezierCurveHelper.GetApexPoints(smallCurve, insertPointNumber); List bondaryPoints = new List(); //放一点余量 var yl_y = Math.Max(cur1.First().Y, cur1.Last().Y) * 1.05; bondaryPoints.Add(new Yw.Geometry.Point2d(cur1.First().X, yl_y)); bondaryPoints.AddRange(cur1); bondaryPoints.Add(new Yw.Geometry.Point2d(cur1.Last().X, yl_y)); return bondaryPoints; } var small_monitonicity = IsShapeC(smallCurve); if (small_monitonicity) {//小效率是C型曲线 #region 小效率是C型曲线 var large_monitonicity = IsShapeC(largeCurve); if (large_monitonicity) {//小效率也是C型曲线 var points_large = Yw.Geometry.BezierCurveHelper.GetApexPoints(largeCurve, insertPointNumber); if (points_large.First().X > points_large.Last().X) {//保证从左到右 points_large.Reverse(); } var points_small = Yw.Geometry.BezierCurveHelper.GetApexPoints(smallCurve, insertPointNumber); if (points_small.First().X > points_small.Last().X) {//保证从左到右 points_small.Reverse(); } List bondaryPoints = new List(); //放一点余量 bondaryPoints.Add(new Yw.Geometry.Point2d(points_small.First().X, points_small.First().Y * 1.1)); bondaryPoints.AddRange(points_small); bondaryPoints.Add(new Yw.Geometry.Point2d(points_small.Last().X, points_small.Last().Y * 1.1)); points_large.Reverse();//反过来 bondaryPoints.Add(new Yw.Geometry.Point2d(points_large.First().X, points_large.First().Y * 1.1)); bondaryPoints.AddRange(points_large); bondaryPoints.Add(new Yw.Geometry.Point2d(points_large.Last().X, points_large.Last().Y * 1.1)); return bondaryPoints; } else { return smallCurve; } #endregion } else {//小效率是L型曲线 var large_monitonicity = IsShapeC(largeCurve); if (large_monitonicity) {//小效率是L型曲线, 大效率线是C型 //小效率是L型曲线, 大效率线是C型 #region 大效率线 是 C型 var points_large_all = Yw.Geometry.BezierCurveHelper.GetApexPoints(largeCurve, insertPointNumber); if (points_large_all.First().X > points_large_all.First().X) {//保证从左到右 points_large_all.Reverse(); } int index_end = points_large_all.GetPointIndexOfMinY(); var points_small = Yw.Geometry.BezierCurveHelper.GetApexPoints(smallCurve, insertPointNumber); if (points_small.First().Y < points_small.First().Y) {//保证从上到下 points_small.Reverse(); } // List points_large = new List();//切割后 if (smallCurve.First().X < largeCurve.First().X) {//小效率线在大效率线左边 for (int i = 0; i <= index_end; i++) { points_large.Add(points_large_all[i]); } } else {//小效率线在大效率线右边 for (int i = index_end; i < points_large_all.Count; i++) { points_large.Add(points_large_all[i]); } points_large.Reverse();//要反一下, 保证从上到小 } List bondaryPoints = new List(); //放一点余量 bondaryPoints.Add(new Yw.Geometry.Point2d(points_small.First().X, points_small.First().Y * 1.1)); bondaryPoints.AddRange(points_small); bondaryPoints.Add(new Yw.Geometry.Point2d(points_small.Last().X, points_small.Last().Y * 0.9)); points_large.Reverse();//反过来 bondaryPoints.Add(new Yw.Geometry.Point2d(points_large.First().X, points_large.First().Y * 0.9)); bondaryPoints.AddRange(points_large); bondaryPoints.Add(new Yw.Geometry.Point2d(points_large.Last().X, points_large.Last().Y * 1.1)); return bondaryPoints; #endregion } else { var points_large = Yw.Geometry.BezierCurveHelper.GetApexPoints(largeCurve, insertPointNumber); if (points_large.First().Y < points_large.First().Y) {//保证从上到下 points_large.Reverse(); } var points_small = Yw.Geometry.BezierCurveHelper.GetApexPoints(smallCurve, insertPointNumber); if (points_small.First().Y < points_small.First().Y) {//保证从上到下 points_small.Reverse(); } List bondaryPoints = new List(); //放一点余量 bondaryPoints.Add(new Yw.Geometry.Point2d(points_small.First().X, points_small.First().Y * 1.1)); bondaryPoints.AddRange(points_small); bondaryPoints.Add(new Yw.Geometry.Point2d(points_small.Last().X, points_small.Last().Y * 0.9)); points_large.Reverse();//反过来 bondaryPoints.Add(new Yw.Geometry.Point2d(points_large.First().X, points_large.First().Y * 0.9)); bondaryPoints.AddRange(points_large); bondaryPoints.Add(new Yw.Geometry.Point2d(points_large.Last().X, points_large.Last().Y * 1.1)); return bondaryPoints; } } } //生成等效线(理论相似换算计算) public static List CalcEqualParaCurveE( PumpCurveViewModel curveGroupExpress, double maxValueD2, double minValueD2, double currentEta) { if (maxValueD2 <= minValueD2 || curveGroupExpress == null) return null; List curveSmall = new List(); List curveLarge = new List(); int firstSplitNum = 5; bool isCurveU = false;//是否是U型曲线 bool isMergeCurve = false;//是否把两条曲线合并成一条,注意不是U型曲线的合并,是但在curveGroupExpress上的2个点距离过小时,就只考虑其中一条 double firstSplitSpace = (maxValueD2 - minValueD2) / (firstSplitNum - 1); for (int i = 0; i < firstSplitNum; i++) { double simuValue1 = maxValueD2 - firstSplitSpace * i;//一定要从大到小 Yw.Pump.CurveQH simuCurveQH = null; Yw.Pump.CurveQE simuCurveQE = null; if (i == 0) { simuCurveQH = curveGroupExpress.CurveQH; simuCurveQE = curveGroupExpress.CurveQE; } else { simuCurveQH = (Yw.Pump.CurveQH)curveGroupExpress.CurveQH.ToNewByN(maxValueD2, simuValue1); simuCurveQE = (Yw.Pump.CurveQE)curveGroupExpress.CurveQE.ToNewByN(maxValueD2, simuValue1); } //获取等效率下的流量值:由于点可能在最高点附件所以多打些点 var equalEffPoints1 = simuCurveQE.FeatCurve.GetPointsX(currentEta, 200); if (equalEffPoints1 == null || equalEffPoints1.Count() == 0) {//已没有:说明是U线等效线 //如果最大曲线都没有交点,说明全部没有交点,直接返回 if (i == 0) return null; // isCurveU = true; #region 再次逼近 int secondSplitNum = 6; double secondSplitSpace = firstSplitSpace / (secondSplitNum - 1); double lastSplitValue = simuValue1 + firstSplitSpace; for (int j = 1; j < secondSplitNum; j++)//从1开始,因为0是上次逼近时就保存了 { double simuValue2 = lastSplitValue - secondSplitSpace * j; simuCurveQH = (Yw.Pump.CurveQH)curveGroupExpress.CurveQH.ToNewByN(maxValueD2, simuValue2); simuCurveQE = (Yw.Pump.CurveQE)curveGroupExpress.CurveQE.ToNewByN(maxValueD2, simuValue2); var equalEffPoints2 = simuCurveQE.FeatCurve.GetPointsX(currentEta); if (equalEffPoints2 == null || equalEffPoints2.Count() == 0) {// break; } double smallPtQ2 = equalEffPoints2.First(); var smallPtH2 = simuCurveQH.FeatCurve.GetPointY(smallPtQ2); curveSmall.Add(new Yw.Geometry.Point2d(smallPtQ2, smallPtH2)); if (equalEffPoints2.Count() == 2 && !isMergeCurve) { double largePtQ2 = equalEffPoints2.Last(); var largePtH2 = simuCurveQH.FeatCurve.GetPointY(largePtQ2); curveLarge.Add(new Yw.Geometry.Point2d(largePtQ2, largePtH2)); } } #endregion break; } double smallPtQ1 = equalEffPoints1.First(); var smallPtH1 = simuCurveQH.FeatCurve.GetPointY(smallPtQ1); curveSmall.Add(new Yw.Geometry.Point2d(smallPtQ1, smallPtH1)); if (equalEffPoints1.Count() == 2) { double largePtQ1 = equalEffPoints1.Last(); if (i == 0) {//判断2个点距离是否过小,如过小,就只考虑其中一条 if (Math.Abs(smallPtQ1 - largePtQ1) < 2) { isMergeCurve = true; } } if (!isMergeCurve) { var largePtH1 = simuCurveQH.FeatCurve.GetPointY(largePtQ1); curveLarge.Add(new Yw.Geometry.Point2d(largePtQ1, largePtH1)); } } }//end for(i... List equalCurves = new List(); if (isCurveU) {//U型线,就把曲线连接起来 if (!isMergeCurve) { double smallLastPtX = curveSmall.Last().X; for (int i = 0; i < curveLarge.Count; i++) { var largePt = curveLarge[curveLarge.Count - 1 - i]; if (largePt.X > (smallLastPtX + 1))//由于可能两个点叠加在一起,所以进行一下判断 curveSmall.Add(largePt); } } CurveEqualEViewModel equalCurve = new CurveEqualEViewModel(); equalCurve.IsClosed = false; equalCurve.DefinePoints = curveSmall; equalCurve.Eff = currentEta; equalCurves.Add(equalCurve); } else { if (curveSmall.Count > 0) { CurveEqualEViewModel equalCurve = new CurveEqualEViewModel(); equalCurve.IsClosed = false; equalCurve.DefinePoints = curveSmall; equalCurve.Eff = currentEta; equalCurves.Add(equalCurve); } if (!isMergeCurve) { if (curveLarge.Count > 0) { CurveEqualEViewModel equalCurve = new CurveEqualEViewModel(); equalCurve.IsClosed = false; equalCurve.DefinePoints = curveLarge; equalCurve.Eff = currentEta; equalCurves.Add(equalCurve); } } } return equalCurves; } //知道原始速度和改变后的速度,求原始效率originE对应改变后的效率 public static double GetE(double originE, double originN, double changeN, bool correct) { //变速度公式(P65页) if (correct) { if (changeN >= originN) return originE;//不能处理转速变大的情况,不然效率可能超过100 double ratio = originN / changeN; double bilv = Math.Pow(ratio, 0.17); return originE * 100 / (originE + (100 - originE) * bilv); } else { return originE; } } //生成等效线(现有等效线插值计算) public static CurveEqualEViewModel CalcEqualParaCurveE2( Yw.Geometry.Boundary2d boundary,//为空即可 PumpCurveViewModel curveGroupMax,//最大曲线 PumpCurveViewModel curveGroupMin,//最小曲线 List largeCurve, double largeValue, List smallCurve, double smallValue, double currentEta) { if (largeValue <= smallValue) return null; if (currentEta >= largeValue) { return new CurveEqualEViewModel() { IsClosed = false, Eff = currentEta, Tension = 0.5f, DefinePoints = largeCurve }; } if (currentEta <= smallValue) { return new CurveEqualEViewModel() { IsClosed = false, Eff = currentEta, Tension = 0.5f, DefinePoints = smallCurve }; } //由于流量扬程数量差别特别大, 所以假设他们在一个100*100的方格内 if (boundary == null) { boundary = new Yw.Geometry.Boundary2d(); boundary.MinX = Math.Min((from p in largeCurve select p.X).Min(), (from p in smallCurve select p.X).Min()); boundary.MaxX = Math.Max((from p in largeCurve select p.X).Max(), (from p in smallCurve select p.X).Max()); boundary.MinY = Math.Min((from p in largeCurve select p.Y).Min(), (from p in smallCurve select p.Y).Min()); boundary.MaxY = Math.Max((from p in largeCurve select p.Y).Max(), (from p in smallCurve select p.Y).Max()); } double ratio_x = 0; if (boundary.MinX == boundary.MaxX) { ratio_x = 100 / (boundary.MaxX); } else { ratio_x = 100 / (boundary.MaxX - boundary.MinX); } double ratio_y = 0; if (boundary.MinY == boundary.MaxY) { ratio_y = 100 / (boundary.MaxY); } else { ratio_y = 100 / (boundary.MaxY - boundary.MinY); } if (largeCurve.Count == 1) { #region 大效率线 是 点 Yw.Geometry.Point2d max_eta_pt = largeCurve.OrderBy(x=>x.Y).LastOrDefault(); Yw.Geometry.Point2d max_eta_pt_chart = new Yw.Geometry.Point2d() { X = (max_eta_pt.X - boundary.MinX) * ratio_x, Y = (max_eta_pt.Y - boundary.MinY) * ratio_y }; var points_small = Yw.Geometry.BezierCurveHelper.GetApexPoints(smallCurve, 5); List points_small_chart = new List(); foreach (var pt in points_small) { points_small_chart.Add(new Yw.Geometry.Point2d() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }); } var total_small_large_chart = points_small_chart.TotalLength(); List center_curve = new(); int sectPointNumber = 8; for (int i = 0; i <= sectPointNumber; i++) { var pt_in_small_chart = points_small_chart.GetPosiByLength(i * total_small_large_chart / sectPointNumber); var pt_chart_x = pt_in_small_chart.X + (currentEta - smallValue) * (max_eta_pt_chart.X - pt_in_small_chart.X) / (largeValue - smallValue); var pt_chart_y = pt_in_small_chart.Y + (currentEta - smallValue) * (max_eta_pt_chart.Y - pt_in_small_chart.Y) / (largeValue - smallValue); center_curve.Add(new Yw.Geometry.Point2d() { X = pt_chart_x / ratio_x + boundary.MinX, Y = pt_chart_y / ratio_y + boundary.MinY });//换算成真实坐标 } return new CurveEqualEViewModel() { IsClosed = false, Eff = currentEta, Tension = 0.5f, DefinePoints = center_curve }; #endregion } var small_monitonicity = IsShapeC(smallCurve); if (small_monitonicity) {//小效率是C型曲线 if (smallCurve.First().X > smallCurve.Last().X) { smallCurve.Reverse(); } if (largeCurve.Count == 3 || largeCurve.Count == 2) { #region 大效率线 是 直线 Yw.Geometry.Point2d max_eta_pt_largeCurve = largeCurve.OrderBy(x => x.Y).LastOrDefault(); Yw.Geometry.Point2d min_eta_pt_largeCurve = largeCurve.OrderBy(x => x.Y).FirstOrDefault(); Yw.Geometry.Point2d max_eta_pt_chart_largeCurve = new Yw.Geometry.Point2d() { X = (max_eta_pt_largeCurve.X - boundary.MinX) * ratio_x, Y = (max_eta_pt_largeCurve.Y - boundary.MinY) * ratio_y }; Yw.Geometry.Point2d min_eta_pt_chart_largeCurve = new Yw.Geometry.Point2d() { X = (min_eta_pt_largeCurve.X - boundary.MinX) * ratio_x, Y = (min_eta_pt_largeCurve.Y - boundary.MinY) * ratio_y }; //暂时只能针对开放曲线 var points_small = Yw.Geometry.BezierCurveHelper.GetApexPoints(smallCurve, 5); List points_small_chart = new List(); foreach (var pt in points_small) { points_small_chart.Add(new Yw.Geometry.Point2d() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }); } Yw.Geometry.Point2d max_eta_pt_chart_smallCurve = points_small_chart.OrderBy(x => x.Y).LastOrDefault(); Yw.Geometry.Point2d min_eta_pt_chart_smallCurve = points_small_chart.OrderBy(x => x.Y).FirstOrDefault(); var total_small_large_chart = points_small_chart.TotalLength(); List center_curve = new List(); int sectPointNumber = 8; for (int i = 0; i <= sectPointNumber; i++) { var pt_in_small_chart = points_small_chart.GetPosiByLength(i * total_small_large_chart / sectPointNumber); //计算Y在小效率线上的比率, 根据此比率计算大效率上的点位置 var y_ratio = (pt_in_small_chart.Y - min_eta_pt_chart_smallCurve.Y) / (max_eta_pt_chart_smallCurve.Y - min_eta_pt_chart_smallCurve.Y); var max_eta_pt_chart_x = y_ratio * (max_eta_pt_chart_largeCurve.X - min_eta_pt_chart_largeCurve.X) + min_eta_pt_chart_largeCurve.X; var max_eta_pt_chart_y = y_ratio * (max_eta_pt_chart_largeCurve.Y - min_eta_pt_chart_largeCurve.Y) + min_eta_pt_chart_largeCurve.Y; var pt_chart_x = pt_in_small_chart.X + (currentEta - smallValue) * (max_eta_pt_chart_x - pt_in_small_chart.X) / (largeValue - smallValue); var pt_chart_y = pt_in_small_chart.Y + (currentEta - smallValue) * (max_eta_pt_chart_y - pt_in_small_chart.Y) / (largeValue - smallValue); center_curve.Add(new Yw.Geometry.Point2d() { X = pt_chart_x / ratio_x + boundary.MinX, Y = pt_chart_y / ratio_y + boundary.MinY });//换算成真实坐标 } return new CurveEqualEViewModel() { IsClosed = false, Eff = currentEta, Tension = 0.5f, DefinePoints = center_curve }; #endregion } else { #region 大效率线 是 曲线 //大效率线 点处理, 暂时只能针对开放曲线 var points_large = Yw.Geometry.BezierCurveHelper.GetApexPoints(largeCurve, 5); List points_large_chart = new List(); foreach (var pt in points_large) { points_large_chart.Add(new Yw.Geometry.Point2d() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }); } var total_length_large_chart = points_large_chart.TotalLength();//总长 //小效率线 var points_small = Yw.Geometry.BezierCurveHelper.GetApexPoints(smallCurve, 5); List points_small_chart = new List(); foreach (var pt in points_small) { points_small_chart.Add(new Yw.Geometry.Point2d() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }); } var total_length_small_chart = points_small_chart.TotalLength();//总长 List center_curve = new List(); int sectPointNumber = 8; for (int i = 0; i <= sectPointNumber; i++) { var pt_in_large_chart = points_large_chart.GetPosiByLength(i * total_length_large_chart / sectPointNumber); var pt_in_small_chart = points_small_chart.GetPosiByLength(i * total_length_small_chart / sectPointNumber); var pt_chart_x = pt_in_small_chart.X + (currentEta - smallValue) * (pt_in_large_chart.X - pt_in_small_chart.X) / (largeValue - smallValue); var pt_chart_y = pt_in_small_chart.Y + (currentEta - smallValue) * (pt_in_large_chart.Y - pt_in_small_chart.Y) / (largeValue - smallValue); center_curve.Add(new Yw.Geometry.Point2d() { X = pt_chart_x / ratio_x + boundary.MinX, Y = pt_chart_y / ratio_y + boundary.MinY });//换算成真实坐标 } return new CurveEqualEViewModel() { IsClosed = false, Eff = currentEta, Tension = 0.5f, DefinePoints = center_curve }; #endregion } } else {//小效率是L型曲线 if (smallCurve.First().Y < smallCurve.Last().Y) {//保证Y从大到小, 即从上到下 smallCurve.Reverse(); } if (largeCurve.Count == 3 || largeCurve.Count == 2) {//小效率是L型曲线, 大效率线是直型线 #region 大效率线 是 直线 Yw.Geometry.Point2d max_eta_pt_largeCurve = largeCurve.OrderBy(x => x.Y).LastOrDefault(); Yw.Geometry.Point2d min_eta_pt_largeCurve = largeCurve.OrderBy(x => x.Y).FirstOrDefault(); Yw.Geometry.Point2d max_eta_pt_chart_largeCurve = new Yw.Geometry.Point2d() { X = (max_eta_pt_largeCurve.X - boundary.MinX) * ratio_x, Y = (max_eta_pt_largeCurve.Y - boundary.MinY) * ratio_y }; Yw.Geometry.Point2d min_eta_pt_chart_largeCurve = new Yw.Geometry.Point2d() { X = (min_eta_pt_largeCurve.X - boundary.MinX) * ratio_x, Y = (min_eta_pt_largeCurve.Y - boundary.MinY) * ratio_y }; //暂时只能针对开放曲线 var points_small = Yw.Geometry.BezierCurveHelper.GetApexPoints(smallCurve, 5); List points_small_chart = new List(); foreach (var pt in points_small) { points_small_chart.Add(new Yw.Geometry.Point2d() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }); } Yw.Geometry.Point2d max_eta_pt_chart_smallCurve = points_small_chart.OrderBy(x => x.Y).LastOrDefault(); Yw.Geometry.Point2d min_eta_pt_chart_smallCurve = points_small_chart.OrderBy(x => x.Y).FirstOrDefault(); var total_length_small_chart = points_small_chart.TotalLength();//总长 List center_curve = new List(); int sectPointNumber = 8; for (int i = 0; i <= sectPointNumber; i++) { var pt_in_small_chart = points_small_chart.GetPosiByLength(i * total_length_small_chart / sectPointNumber); //计算Y在小效率线上的比率, 根据此比率计算大效率上的点位置 var y_ratio = (pt_in_small_chart.Y - min_eta_pt_chart_smallCurve.Y) / (max_eta_pt_chart_smallCurve.Y - min_eta_pt_chart_smallCurve.Y); var max_eta_pt_chart_x = y_ratio * (max_eta_pt_chart_largeCurve.X - min_eta_pt_chart_largeCurve.X) + min_eta_pt_chart_largeCurve.X; var max_eta_pt_chart_y = y_ratio * (max_eta_pt_chart_largeCurve.Y - min_eta_pt_chart_largeCurve.Y) + min_eta_pt_chart_largeCurve.Y; var pt_chart_x = pt_in_small_chart.X + (currentEta - smallValue) * (max_eta_pt_chart_x - pt_in_small_chart.X) / (largeValue - smallValue); var pt_chart_y = pt_in_small_chart.Y + (currentEta - smallValue) * (max_eta_pt_chart_y - pt_in_small_chart.Y) / (largeValue - smallValue); center_curve.Add(new Yw.Geometry.Point2d() { X = pt_chart_x / ratio_x + boundary.MinX, Y = pt_chart_y / ratio_y + boundary.MinY });//换算成真实坐标 } return new CurveEqualEViewModel() { IsClosed = false, Eff = currentEta, Tension = 0.5f, DefinePoints = center_curve }; #endregion } else { var large_monitonicity = IsShapeC(largeCurve); if (large_monitonicity) {//小效率是L型曲线, 大效率线是C型 #region 大效率线 是 C型 //大效率线 点处理, 暂时只能针对开放曲线 var points_large = Yw.Geometry.BezierCurveHelper.GetApexPoints(largeCurve, 5); if (points_large.First().X > points_large.Last().X) { points_large.Reverse(); } //小效率线 点处理, 暂时只能针对开放曲线 var points_small = Yw.Geometry.BezierCurveHelper.GetApexPoints(smallCurve, 5); List points_small_chart = new List(); foreach (var pt in points_small) { //换算到图像点 points_small_chart.Add(new Yw.Geometry.Point2d() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }); } var total_length_small_chart = points_small_chart.TotalLength();//总长 // if (smallCurve.First().X < largeCurve.First().X) {//小效率线在大效率线左边 List points_large_chart = new List(); //切断大效率线 if (curveGroupMin != null) { int min_y_index_smallCurve = points_large.GetPointIndexOfMinY(); for (int i = 0; i <= min_y_index_smallCurve; i++) { var pt = points_large[i]; //判断是否超过最小切割线 var pt_in_minFeatCurve_y = curveGroupMin.CurveQH.FeatCurve.GetPointY(pt.X); if (pt_in_minFeatCurve_y <= pt.Y) {//换算到图像点 points_large_chart.Add(new Yw.Geometry.Point2d() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }); } else {//只要一出现小的就马上退出 break; } } } else { int index_end = points_large_chart.GetPointIndexOfMinY(); for (int i = 0; i <= index_end; i++) {//换算到图像点 var pt = points_large[i]; points_large_chart.Add(new Yw.Geometry.Point2d() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }); } } var total_length_large_chart = points_large_chart.TotalLength();//长度 List center_curve = new List(); int sectPointNumber = 8; for (int i = 0; i <= sectPointNumber; i++) { var pt_in_large_chart = points_large_chart.GetPosiByLength(i * total_length_large_chart / sectPointNumber); var pt_in_small_chart = points_small_chart.GetPosiByLength(i * total_length_small_chart / sectPointNumber); var pt_chart_x = pt_in_small_chart.X + (currentEta - smallValue) * (pt_in_large_chart.X - pt_in_small_chart.X) / (largeValue - smallValue); var pt_chart_y = pt_in_small_chart.Y + (currentEta - smallValue) * (pt_in_large_chart.Y - pt_in_small_chart.Y) / (largeValue - smallValue); center_curve.Add(new Yw.Geometry.Point2d() { X = pt_chart_x / ratio_x + boundary.MinX, Y = pt_chart_y / ratio_y + boundary.MinY });//换算成真实坐标 } return new CurveEqualEViewModel() { IsClosed = false, Eff = currentEta, Tension = 0.5f, DefinePoints = center_curve }; } else {//小效率线在大效率线右边 //暂时不考虑 return null; } #endregion } else {//小效率是L型曲线, 大效率线是L直型线 #region 大效率线 是 L型 //大效率线 点处理, 暂时只能针对开放曲线 var points_large = Yw.Geometry.BezierCurveHelper.GetApexPoints(largeCurve, 5); if (points_large.First().Y < points_large.Last().Y) { points_large.Reverse(); } List points_large_chart = new List(); foreach (var pt in points_large) { points_large_chart.Add(new Yw.Geometry.Point2d() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }); } //换算到图像点 //Yw.Geometry.Point2d max_eta_pt_chart_largeCurve = points_large_chart.GetPointOfMaxY(); //int min_eta_pt_chart_largeCurve_index = points_large_chart.GetPointIndexOfMinY(); var total_length_large_chart = points_large_chart.TotalLength();//总长 //小效率线 点处理, 暂时只能针对开放曲线 var points_small = Yw.Geometry.BezierCurveHelper.GetApexPoints(smallCurve, 5); if (points_small.First().Y < points_small.Last().Y) { points_small.Reverse(); } List points_small_chart = new List(); foreach (var pt in points_small) { points_small_chart.Add(new Yw.Geometry.Point2d() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y }); } var total_length_small_chart = points_small_chart.TotalLength();//总长 //小效率线在大效率线左边 List center_curve = new List(); int sectPointNumber = 8; for (int i = 0; i <= sectPointNumber; i++) { var pt_in_large_chart = points_large_chart.GetPosiByLength(i * total_length_large_chart / sectPointNumber); var pt_in_small_chart = points_small_chart.GetPosiByLength(i * total_length_small_chart / sectPointNumber); var pt_chart_x = pt_in_small_chart.X + (currentEta - smallValue) * (pt_in_large_chart.X - pt_in_small_chart.X) / (largeValue - smallValue); var pt_chart_y = pt_in_small_chart.Y + (currentEta - smallValue) * (pt_in_large_chart.Y - pt_in_small_chart.Y) / (largeValue - smallValue); center_curve.Add(new Yw.Geometry.Point2d() { X = pt_chart_x / ratio_x + boundary.MinX, Y = pt_chart_y / ratio_y + boundary.MinY });//换算成真实坐标 } return new CurveEqualEViewModel() { IsClosed = false, Eff = currentEta, Tension = 0.5f, DefinePoints = center_curve }; #endregion } } } } //区分QE曲线 //LargeHcurve为高扬程处的L型曲线,middleHcurve中扬程处的C型曲线,smallHcurve为低扬程处的L型曲线 //而且返回的曲线参数从小到大排列好了 public static bool DevideCurveShape( List curveInfoQE, //Eventech.Model.CurveExpress ZeroCurveQH,//0角度的QH线 out List largeHcurve, out List middleHcurve, out List smallHcurve) { largeHcurve = middleHcurve = smallHcurve = null; if (curveInfoQE == null || curveInfoQE.Count == 0) return false; List caosCurve = new List(); List nonCaosCurve = new List(); var sort_qe = from x in curveInfoQE orderby x.Eff select x;//从小到大排序 for (int i = 0; i < sort_qe.Count(); i++) { var curve = sort_qe.ElementAt(i); if (curve.DefinePoints == null || curve.DefinePoints.Count < 3) continue; //判断是否是C型曲线:注意严格判断X的增减性来判断是否为C型线,有时有问题,因为有时可能有1个点故意偏移一点 //所以忽略一个点 if (IsShapeC(curve.DefinePoints)) {//如果小的都是, 效率更高的也是 for (int j = i; j < sort_qe.Count(); j++) { caosCurve.Add(sort_qe.ElementAt(j)); } break; } else { nonCaosCurve.Add(curve); } } double middleH = 0;//用于比较的中间H值 if (caosCurve.Count > 0) { //有C型曲线 //有C型曲线 caosCurve.Sort(new Comparer());//从小到大排序 middleHcurve = caosCurve; //没有非C型曲线 if (nonCaosCurve.Count == 0) return true; //用效率最高的曲线的Y平均值作为用于比较的中间H值 List curveMaxE = middleHcurve.Last().DefinePoints; for (int i = 0; i < curveMaxE.Count; i++) { middleH += curveMaxE[i].Y; } middleH = middleH / curveMaxE.Count; } else {//没有C型曲线 if (nonCaosCurve.Count == 0) return false;//也没有非C型曲线 // var max_eta = (from x in curveInfoQE select x.Eff).Max(); var max_eta_curve = (from x in curveInfoQE where x.Eff == max_eta select x).ToList(); middleH = 0; foreach (var curve in max_eta_curve) { //求平均值 double averH = 0; for (int i = 0; i < curve.DefinePoints.Count; i++) { averH += curve.DefinePoints[i].Y; } middleH += averH / curve.DefinePoints.Count; } middleH = middleH / max_eta_curve.Count; } // largeHcurve = new List(); smallHcurve = new List(); foreach (CurveEqualEViewModel curve in nonCaosCurve) { //求平均值 double averH = 0; for (int i = 0; i < curve.DefinePoints.Count; i++) { averH += curve.DefinePoints[i].Y; } averH = averH / curve.DefinePoints.Count; //比较平均值 if (averH > middleH) { largeHcurve.Add(curve); } else { smallHcurve.Add(curve); } } if (largeHcurve.Count > 0) largeHcurve.Sort(new Comparer());//从小到大排序 else largeHcurve = null; if (smallHcurve.Count > 0) smallHcurve.Sort(new Comparer());//从小到大排序 else smallHcurve = null; return true; } //规整等效线曲线 //C型圈:保证曲线Y值从大到小 ,开始Y值大,结束Y值小 //一型圈:保证流量值从小到大 public static void StandardCurve(ref CurveEqualEViewModel curve) { Standard4EqualCurveE(ref curve); } public static void StandardCurve(ref List curves) { if (curves == null || curves.Count() == 0) return; //单条线,流量从小到大排序 for (int i = 0; i < curves.Count; i++) { var curve = curves[i]; StandardCurve(ref curve); } //根据参数从小到排序,参数一样 就H从小到大 curves.Sort(new Comparer()); } /// /// 是否是C型的曲线 /// /// /// public static bool IsShapeC(List points) { if (points == null || points.Count() <= 2) return false; if (points.Count() == 3) { if (points[1].X < points[0].X && points[1].X < points[2].X) return true; if (points[1].X > points[0].X && points[1].X > points[2].X) return true; return false; } var b_curve = Yw.Geometry.BezierCurveHelper.CreateOpenCurves(points.ToArray()); var xxx = from x in points select x.X; var x_max = xxx.Max(); var x_min = xxx.Min(); var pt_num = 20; var x_space = (x_max - x_min) / (pt_num - 1); int sect_pt_num = 0; for (int i = 0; i < pt_num; i++) { var x = x_min + x_space * i; var y_list = Yw.Geometry.BezierCurveHelper.GetSectPointsByX(b_curve, x); if (y_list != null && y_list.Count > 1) { sect_pt_num++; } } if (sect_pt_num >= 3) return true; else return false; } //等效线曲线 //C型圈:保证曲线Y值从大到小 ,开始Y值大,结束Y值小 //一型圈:保证流量值从小到大 public static void Standard4EqualCurveE(ref CurveEqualEViewModel curve) { if (curve == null) return; if (curve.FeatCurve.IsInvalid()) return; if (curve.IsClosed) return; //封闭就保证原始状态即可 List pt_list; if (curve.FeatType == Yw.Ahart.eFeatType.Through) { //判断各种情况 var fit_pt_list = curve.FeatCurve.GetPointList(); if (IsShapeC(fit_pt_list)) { //C型圈:保证曲线X值从小到大, 即开始X值小, 结束X值大 if (fit_pt_list.First().X > fit_pt_list.Last().X) { fit_pt_list.Reverse(); } } else { //保证Y值从大到小(即从上到下) if (fit_pt_list.First().Y < fit_pt_list.Last().Y) { fit_pt_list.Reverse(); } } pt_list = fit_pt_list; } else { //拟合的方法不需要排序 只要保证流量从小到大即可 pt_list = curve.FeatCurve.GetPointList(6); } curve.DefinePoints = pt_list; } public static Yw.Geometry.Boundary2d GetBoundaryPoint(List list) { double boudary_min_x = double.MaxValue; double boudary_max_x = double.MinValue; double boudary_min_y = double.MaxValue; double boudary_max_y = double.MinValue; foreach (var curve in list) { boudary_min_x = Math.Min(boudary_min_x, (from x in curve.DefinePoints select x.X).Min()); boudary_max_x = Math.Max(boudary_max_x, (from x in curve.DefinePoints select x.X).Max()); boudary_min_y = Math.Min(boudary_min_y, (from x in curve.DefinePoints select x.Y).Min()); boudary_max_y = Math.Max(boudary_min_y, (from x in curve.DefinePoints select x.Y).Max()); } return new Yw.Geometry.Boundary2d(boudary_min_x, boudary_max_x, boudary_min_y, boudary_max_y); } } public class Comparer : IComparer { public Comparer() { } #region IComparer 成员 private double ignoreDis = 0.001; int IComparer.Compare(CurveEqualEViewModel obj1, CurveEqualEViewModel obj2) { if (Math.Abs(obj1.Eff - obj2.Eff) < ignoreDis) {//参数一样 就比较Y的平均值 double y1_arv = (from x in obj1.DefinePoints select x.Y).Average(); double y2_arv = (from x in obj2.DefinePoints select x.Y).Average(); if (Math.Abs(y1_arv - y2_arv) < 0.01) return 0; else if (y1_arv > y2_arv) return 1; else return -1; } else if (obj1.Eff > obj2.Eff) { return 1; } else { return -1; } } #endregion } //比较相同:主要用与LIST的Contains方法和Distinct public class EqualComparer : IEqualityComparer { private double ignoreDis = 0.001; public EqualComparer() { ignoreDis = 0.001; } public EqualComparer(double dis) { ignoreDis = dis; } public bool Equals(CurveEqualEViewModel lhs, CurveEqualEViewModel rhs) { if (Math.Abs(lhs.Eff - rhs.Eff) < ignoreDis) return true; else return false; } public int GetHashCode(CurveEqualEViewModel obj) { //return obj.X.GetHashCode() + obj.Y.GetHashCode(); return 0; } } }