using Hydro.CommonBase; using Hydro.CommonBase; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; using static Hydro.Core.ObjectEnum; namespace Hydro.MapView { [Serializable] public class PumpViewModel : LinkViewModel { public static List CurveStrings=new List { "流量扬程曲线", "流量功率曲线", "流量效率曲线" }; [Browsable(false)] public new string Name { get { return base.Name; } set { base.Name = value; } } [Category("基本信息")] [DisplayName("水泵类型")] public new PumpType Type { get; set; } [Browsable(false)] public dict Datasets { get; set; } = new dict(); [Category("计算参数")] public double 额定转速 { get; set; } = 1500; [Category("计算参数")] public double 额定流量 { get; set; } = 200; [Category("计算参数")] public double 额定扬程 { get; set; } = 50; [Category("计算参数")] public double 额定功率 { get; set; } = 75; public double 转速比 { get; set; } = 1; [DisplayName("当前转速")] [Category("计算参数")] public double 当前转速 { get; set; } = 1500; [Browsable(false)] public Dataset 流量扬程曲线 { get { if (!Datasets.ContainsKey("流量扬程曲线")) Datasets.Add("流量扬程曲线", new Dataset("流量扬程曲线", null)); return Datasets["流量扬程曲线"]; } } [Browsable(false)] public Dataset 流量功率曲线 { get { if (!Datasets.ContainsKey("流量功率曲线")) Datasets.Add("流量功率曲线", new Dataset("流量功率曲线", null)); return Datasets["流量功率曲线"]; } } [Browsable(false)] public Dataset 流量效率曲线 { get { if (!Datasets.ContainsKey("流量效率曲线")) Datasets.Add("流量效率曲线", new Dataset("流量效率曲线", null)); return Datasets["流量效率曲线"]; } } [Browsable(false)] public string factoryName { set; get; //get //{ // if (factory != null) // return factory.Name; // else // return null; //} } [Browsable(false)] [JsonIgnore] public Factory factory { get; set; } = null; public PumpViewModel Copy() { PumpViewModel p = new PumpViewModel(); p.Name = Name; p.额定流量 = 额定流量; p.额定扬程 = 额定扬程; p.额定功率 = 额定功率; p.额定转速 = 额定转速; p.当前转速 = 当前转速; p.Type = Type; p.factory = factory; //为Datasets添加CurveStrings数据 foreach (var str in CurveStrings) { if (!p.Datasets.ContainsKey(str)) { p.Datasets.Add(str, new Dataset(str,p)); } } foreach (var pair in Datasets) { List list = new List(); pair.Value._data.ForEach(m => list.Add(m)); p.Datasets[pair.Key].Data = list; DRange rangeDefault = new DRange(double.MaxValue, double.MinValue); p.Datasets[pair.Key].range_X = DRange.Union(rangeDefault, pair.Value.range_X); p.Datasets[pair.Key].range_Y = DRange.Union(rangeDefault, pair.Value.range_Y); } p.CurveFit(); return p; //factory.Pumps.Add(p); //_EditFlag = true; //DisplayFactoryListInTreeView(factoryList); } public void CurveFit() { foreach (var data in Datasets) { data.Value.Data.Sort((a, b) => a.X > b.X ? 1 : (a.X == b.X ? 0 : -1)); if (data.Value.HasData) data.Value.CurveFit(); } string basetype = "流量扬程曲线"; string type = ""; type = "流量效率曲线"; var type1 = "流量功率曲线"; if (!Datasets.ContainsKey(type)) Datasets.Add(type, new Dataset(type, null)); if (!Datasets.ContainsKey(type1)) Datasets.Add(type1, new Dataset(type1, null)); if (Datasets[type].IsFitted && !Datasets[type1].IsFitted) { List points = new List(); List points1 = new List(); foreach (var yc in Datasets[basetype].Data) { float x = yc.X; float y_扬程 = yc.Y; float y_效率 = (float)Datasets[type].Evaluate(x); float y_功率 = (float)x * y_扬程 / y_效率 / 3.6f; points.Add(new PointF(x, y_效率)); points1.Add(new PointF(x, y_功率)); } Datasets[type].Data = points; Datasets[type1].Data = points1; Datasets[type].CurveFit(); Datasets[type1].CurveFit(); } if (!Datasets[type].IsFitted && Datasets[type1].IsFitted) { List points = new List(); List points1 = new List(); foreach (var yc in Datasets[basetype].Data) { float x = yc.X; float y_扬程 = yc.Y; float y_功率 = (float)Datasets[type1].Evaluate(x); float y_效率 = (float)x * y_扬程 / y_功率 / 3.6f; points.Add(new PointF(x, y_效率)); points1.Add(new PointF(x, y_功率)); } Datasets[type].Data = points; Datasets[type1].Data = points1; Datasets[type].CurveFit(); Datasets[type1].CurveFit(); } } public void ShowInGrid(DataGridView dataGridView) { dataGridView.Rows.Clear(); // if () for (int i = 0; i < 流量扬程曲线.Data.Count; i++) { PointF p = 流量扬程曲线.Data[i]; PointF p_temp; double y1 = 0, y2 = 0; if (流量功率曲线.IsFitted) { if ((p_temp = 流量功率曲线.Data.Find(p0 => p0.X == p.X)) == default(PointF)) y1 = 流量功率曲线.Evaluate(p.X); else y1 = p_temp.Y; } if (流量效率曲线.IsFitted) //y2 = i< 流量效率曲线.Data.Count ? 流量效率曲线.Data[i].Y:0; { if ((p_temp = 流量效率曲线.Data.Find(p0 => p0.X == p.X)) == default(PointF)) y2 = 流量效率曲线.Evaluate(p.X); else y2 = p_temp.Y; } dataGridView.Rows.Add(Math.Round(p.X, 1), Math.Round(p.Y, 2), Math.Round(y1, 2), Math.Round(y2, 2)); } } /// /// /// /// /// /// 是否使用第三轴 public void AddSeries(Chart chart, Series series, bool mode, Color color) { series.Color = color; if (mode) CreateYAxis(chart, chart.ChartAreas[0], series, -8, 1, color); else chart.Series.Add(series); } public void AddCurve(Chart chart, string type = "流量扬程曲线", bool onlyOne = false, DRange Force_range_X = null) { Series series; List Points; List FittedCurve; string baseType = "流量扬程曲线"; string baseType2 = "流量功率曲线"; string baseType3 = "流量效率曲线"; if (onlyOne) { if (Datasets[type].IsFitted) { FittedCurve = Datasets[type].FittedCurvebyRange(Force_range_X); series = AddSeries("ChartArea1", SeriesChartType.Spline, Datasets[type].Legend, Datasets[type].axisType, $"{factoryName}_{Name}_{type}", FittedCurve, true); chart.Series.Add(series); } } else { //while (chart.ChartAreas.Count > 1) //{ // chart.ChartAreas.RemoveAt(1); //} chart.ChartAreas[1].Visible = false; chart.ChartAreas[2].Visible = false; Points = Datasets[type].Data; series = AddSeries("ChartArea1", SeriesChartType.Point, Datasets[type].Legend, Datasets[type].axisType, $"{type}点", Points, false); //if (chart.ChartAreas.Count > 1) chart.ChartAreas.RemoveAt(1); //series.ToolTip = "Value: #VALY{N2}"; AddSeries(chart, series, type == "流量效率曲线", Datasets[type].Color); var series0 = series; foreach (var data in Datasets) { var type0 = data.Key; if (!Datasets[type0].IsFitted) continue; FittedCurve = Datasets[type0].FittedCurve; series = AddSeries("ChartArea1", SeriesChartType.Spline, Datasets[type0].Legend, Datasets[type0].axisType, $"{factoryName}_{Name}_{type0}", FittedCurve, true); //CreateYAxis(chart, chart.ChartAreas[0], series, 0.5f, 1); //chart.Series.Add(series); AddSeries(chart, series, type0 == "流量效率曲线", Datasets[type0].Color); } if (chart.Series.Count == 1 && series0.Points.Count == 0) { series0.Points.Add(-2, -2); series0.Points.Add(-1, -1); series0.IsVisibleInLegend = true; series0.YAxisType = AxisType.Primary; chart.ChartAreas[0].AxisX.Minimum = 0; chart.ChartAreas[0].AxisX.Maximum = 3000; chart.ChartAreas[0].AxisY.Minimum = 0; chart.ChartAreas[0].AxisY.Maximum = 50; chart.ChartAreas[0].AxisY2.Minimum = 0; chart.ChartAreas[0].AxisY2.Maximum = 500; return; } } DRange range_X = null; //if (chart.ChartAreas[0].AxisY.Interval>5) //chart.ChartAreas[0].AxisY.Interval = 2; chart.ChartAreas[0].AxisY2.Interval = 25; // 设置Y轴主刻度线的颜色为红色,透明度为50% chart.ChartAreas[0].AxisX.Name = "流量"; chart.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.FromArgb(40, Color.Black); chart.ChartAreas[0].AxisX.MajorTickMark.LineColor = Color.FromArgb(40, Color.Black); chart.ChartAreas[0].AxisY.MajorTickMark.LineColor = Color.FromArgb(128, Color.Black); chart.ChartAreas[0].AxisY.MajorTickMark.LineColor = Color.FromArgb(60, Color.Black); chart.ChartAreas[0].AxisY2.MajorTickMark.LineColor = Color.FromArgb(128, Color.Red); chart.ChartAreas[0].AxisY2.MajorTickMark.LineColor = Color.FromArgb(60, Color.Red); chart.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.FromArgb(60, Color.Black); chart.ChartAreas[0].AxisY2.MajorGrid.LineColor = Color.FromArgb(10, Color.Red); chart.ChartAreas[0].AxisY.LabelStyle.ForeColor = Color.Blue; chart.ChartAreas[0].AxisY2.LabelStyle.ForeColor = Color.Orange; if (Force_range_X != null && Force_range_X.isValid) { range_X = Force_range_X; } else if (Datasets[type].range_X != null && Datasets[type].range_X.isValid) { range_X = Datasets[type].range_X; } else if (Datasets[baseType].range_X != null && Datasets[baseType].range_X.isValid) { range_X = Datasets[baseType].range_X; } else { range_X = new DRange(double.NaN, double.NaN); } if (range_X.isValid) { chart.ChartAreas[0].AxisX.Minimum = range_X.Min; chart.ChartAreas[0].AxisX.Maximum = range_X.Max; if (chart.ChartAreas.Count > 1) { chart.ChartAreas[2].AxisX.Minimum = range_X.Min; chart.ChartAreas[2].AxisX.Maximum = range_X.Max; chart.ChartAreas[2].AxisX.Crossing = range_X.Min + (range_X.Max - range_X.Min) * 0.96; } } if (Datasets[baseType].range_Y != null && Datasets[baseType].range_Y.isValid) { // 设置 Y 轴的最大最小值 chart.ChartAreas[0].AxisY.Minimum = Datasets[baseType].range_Y.Min; chart.ChartAreas[0].AxisY.Maximum = Datasets[baseType].range_Y.Max; } else { chart.ChartAreas[0].AxisY.Minimum = double.NaN; chart.ChartAreas[0].AxisY.Maximum = double.NaN; } //if (type!=baseType && Datasets[type].range_Y != null) //{ // // 设置 X 轴的最大最小值 // chart.ChartAreas[0].AxisY2.Minimum = Datasets[type].range_Y.Min; // chart.ChartAreas[0].AxisY2.Maximum = Datasets[type].range_Y.Max; //} //else if (Datasets[baseType2].range_Y != null && Datasets[baseType2].range_Y.isValid) { DRange range_Y2 = Datasets[baseType2].range_Y; // 设置 Y 轴的最大最小值 chart.ChartAreas[0].AxisY2.Minimum = range_Y2.Min; chart.ChartAreas[0].AxisY2.Maximum = range_Y2.Max; } else { chart.ChartAreas[0].AxisY2.Minimum = 0; chart.ChartAreas[0].AxisY2.Maximum = 500; } if (chart.ChartAreas.Count > 1) { chart.ChartAreas[2].AxisY2.Interval = 10; chart.ChartAreas[2].AxisY2.MajorTickMark.LineColor = Color.FromArgb(60, Color.Blue); chart.ChartAreas[2].AxisY2.MinorTickMark.LineColor = Color.FromArgb(20, Color.Blue); chart.ChartAreas[2].AxisY2.MajorGrid.LineColor = Color.FromArgb(60, Color.Blue); if (Datasets[baseType3].range_Y != null && Datasets[baseType3].range_Y.isValid) { chart.ChartAreas[2].AxisY2.Minimum = Datasets[baseType3].range_Y.Min; chart.ChartAreas[2].AxisY2.Maximum = Datasets[baseType3].range_Y.Max; } else { chart.ChartAreas[2].AxisY2.Minimum = 0; chart.ChartAreas[2].AxisY2.Maximum = 100; } //chart.ChartAreas[2].AxisY.MajorTickMark.LineColor = Color.FromArgb(60, Color.Blue); //chart.ChartAreas[2].AxisY.MinorTickMark.LineColor = Color.FromArgb(20, Color.Blue); //chart.ChartAreas[1].AxisY2.MajorTickMark.LineColor = Color.FromArgb(60, Color.Blue); //chart.ChartAreas[1].AxisY2.MinorTickMark.LineColor = Color.FromArgb(20, Color.Red); //chart.ChartAreas[1].AxisY.MajorTickMark.LineColor = Color.FromArgb(60, Color.Blue); //chart.ChartAreas[1].AxisY.MinorTickMark.LineColor = Color.FromArgb(20, Color.Red); //chart.ChartAreas[1].AxisY.MajorTickMark.LineColor = Color.FromArgb(20, Color.Red); //chart.ChartAreas[1].AxisY2.MajorTickMark.LineColor = Color.FromArgb(20, Color.Red); } } public void CreateYAxis(Chart chart, ChartArea area, Series series, float axisOffset, float labelsSize, Color color) { // Create new chart area for original series ChartArea areaSeries; ChartArea areaAxis; if (chart.ChartAreas.Count == 1) { areaSeries = chart.ChartAreas.Add("ChartArea_" + series.Name); areaAxis = chart.ChartAreas.Add("AxisY_" + series.ChartArea); } else { areaSeries = chart.ChartAreas[1]; areaAxis = chart.ChartAreas[2]; } areaSeries.Visible = false; areaSeries.BackColor = Color.Transparent; areaSeries.BorderColor = Color.Transparent; areaSeries.Position.FromRectangleF(area.Position.ToRectangleF()); areaSeries.InnerPlotPosition.FromRectangleF(area.InnerPlotPosition.ToRectangleF()); areaSeries.AxisX.MajorGrid.Enabled = false; areaSeries.AxisX.MajorTickMark.Enabled = false; areaSeries.AxisX.LabelStyle.Enabled = false; areaSeries.AxisY.Enabled = AxisEnabled.False; areaSeries.AxisY2.Enabled = AxisEnabled.False; areaSeries.AxisY2.MajorGrid.Enabled = false; areaSeries.AxisY2.MajorTickMark.Enabled = false; areaSeries.AxisY2.LabelStyle.Enabled = false; areaSeries.AxisY2.IsStartedFromZero = area.AxisY.IsStartedFromZero; series.ChartArea = areaSeries.Name; // Create new chart area for axis areaAxis.Visible = true; areaAxis.BackColor = Color.Transparent; areaAxis.BorderColor = Color.Transparent; areaAxis.Position.FromRectangleF(chart.ChartAreas[0].Position.ToRectangleF()); areaAxis.InnerPlotPosition.FromRectangleF(chart.ChartAreas[0].InnerPlotPosition.ToRectangleF()); // Create a copy of specified series Series seriesCopy = chart.Series.Add(series.Name); seriesCopy.YAxisType = AxisType.Secondary; seriesCopy.ChartType = series.ChartType; foreach (DataPoint point in series.Points) { seriesCopy.Points.AddXY(point.XValue, point.YValues[0]); } // Hide copied series seriesCopy.IsVisibleInLegend = true; seriesCopy.Color = color; seriesCopy.BorderColor = Color.Transparent; seriesCopy.ChartArea = areaAxis.Name; // Disable drid lines & tickmarks areaAxis.AxisX.LineWidth = 0; areaAxis.AxisX.MajorGrid.Enabled = false; areaAxis.AxisX.MajorTickMark.Enabled = false; areaAxis.AxisX.LabelStyle.Enabled = false; areaAxis.AxisY.Enabled = AxisEnabled.False; areaAxis.AxisY2.Enabled = AxisEnabled.True; areaAxis.AxisY2.MajorGrid.Enabled = false; areaAxis.AxisY2.IsStartedFromZero = area.AxisY.IsStartedFromZero; areaAxis.AxisY2.LabelStyle.Font = area.AxisY.LabelStyle.Font; areaAxis.AxisY2.LabelStyle.ForeColor = color; float f = areaAxis.InnerPlotPosition.Width - axisOffset; // Adjust area position //if (f < 0 || f>100) f = 0; //areaAxis.Position.Width = f; //f = areaAxis.InnerPlotPosition.Width + labelsSize; //if (f < 0 || f > 100) f = 100; //areaAxis.InnerPlotPosition.Width = f; // 设置Y2轴偏移量为5% //areaAxis.AxisY2.Crossing = 50; } private Series AddSeries(string Area, SeriesChartType type, String Legend, AxisType axisType, String Name, List Points, bool showLegend = true) { Series series = new Series(); series.ChartArea = Area; series.ChartType = type; series.Legend = Legend; series.Name = Name; series.IsVisibleInLegend = showLegend; series.YAxisType = axisType; if (Points != null) Points.ForEach(p => series.Points.AddXY(p.X, p.Y)); return series; } [Category("计算参数")] [DisplayName("流量扬程曲线")] public List HeadCurvePoints { get { this.Datasets.TryGetValue("流量扬程曲线", out Dataset dataset); if (dataset != null) { return dataset._data; } return null; } set { this.Datasets.TryGetValue("流量扬程曲线", out Dataset dataset); if (dataset == null) { dataset = new Dataset("流量扬程曲线", this); } dataset._data = value; } } [Category("计算参数")] [DisplayName("流量效率曲线")] public List EfficCurvePoints { get { this.Datasets.TryGetValue("流量效率曲线", out Dataset dataset); if (dataset != null) { return dataset._data; } return null; } set { this.Datasets.TryGetValue("流量效率曲线", out Dataset dataset); if (dataset == null) { dataset = new Dataset("流量效率曲线", this); } dataset._data = value; } } [Browsable(false)] public string HeadCurve { get; set; } = "PumpDefault"; [Browsable(false)] public List Parameters { get; set; } //实际需水量 [Category("计算结果")] [DisplayName("扬程")] [Browsable(true)] public new float EN_HEADLOSS { get { return -base.EN_HEADLOSS; } } [Browsable(false)] public new float EN_VELOCITY { get { return base.EN_VELOCITY; } } public override string ToString() { string para = Parameters == null ? null : string.Join("\t", Parameters); return $"{ID}\t{Node1}\t{Node2}\tHead\t{HeadCurve}\tSPEED\t{转速比}\t{para}\t;\t"; } } }