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 static System.Windows.Forms.VisualStyles.VisualStyleElement; using System.Windows.Forms.DataVisualization.Charting; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Windows.Forms; using MathNet.Numerics.LinearAlgebra.Double; // 引入 Math.NET Numerics 库进行多项式拟合 using MathNet.Numerics; using System.IO; using System.Xml.Serialization; using System.Xml.Linq; using CloudWaterNetwork.建模; using static System.Windows.Forms.LinkLabel; using Series = System.Windows.Forms.DataVisualization.Charting.Series; using System.Drawing.Imaging; namespace CloudWaterNetwork.建模 { public partial class Form_建模 : Form { private double opca = 0.5; //public Form_Curve() //{ // InitializeComponent(); //} FactoryList factoryList = new FactoryList(); private bool isMouseDown = false; // 标记鼠标是否按下 private double lastX, lastY= 0; // 上一次鼠标所在的 x 坐标 double[] lastDataX, lastDataY; private int lastIndex = -1; // 上一次选中的数据点的索引 bool isForPic = false; private void Form_Curve_Load(object sender, EventArgs e) { // 监听 CustomizeLegend 事件 if (chart1.ChartAreas.Count>0) { chart1.ChartAreas[0].AxisY.Enabled = AxisEnabled.True; chart1.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True; chart1.ChartAreas[0].AxisX.Enabled = AxisEnabled.True; chart1.ChartAreas[0].AxisX.LabelStyle.Format = "0.0"; chart1.ChartAreas[0].AxisY2.LabelStyle.Format = "0.0"; } cb_曲线类型.SelectedIndex = 0; this.chart1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.chart1_MouseWheel); //chart1.ChartAreas[0].CursorX.IsUserEnabled = true; //chart1.ChartAreas[0].CursorY.IsUserEnabled = true; } private List dataPoints; // 存储样本数据点 private DenseVector coefficients; // 存储多项式系数 private int degree = 2; // 默认为二次多项式 public Form_建模() { InitializeComponent(); chart1.MouseDown += Chart1_MouseDown; chart1.MouseMove += Chart1_MouseMove; chart1.MouseUp += Chart1_MouseUp; } #region 左下工具栏 private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) { // 将 DataGridView 中的数据点绘制到 Chart 控件中 LoadDataPoint(); } private void button_拟合_Click(object sender, EventArgs e) { // 根据用户选择的拟合多项式系数,计算并绘制出拟合曲线 ShowCurve(); } private void textBox1_TextChanged(object sender, EventArgs e) { // 在 TextBox 中输入 x 值,通过计算得到相应的 y 值,并显示在 TextBox 中 if (_组合曲线) { if (coefficients == null) return; double x = 0; if (!double.TryParse(textBox1.Text, out x)) return; double y = EvaluatePolynomial(coefficients, x); y = Math.Round(y, 2); textBox2.TextChanged -= textBox2_TextChanged; textBox2.Text = y.ToString(); textBox2.TextChanged += textBox2_TextChanged; } else { if (_SelectedPump == null) return; double x = 0; if (double.TryParse(textBox1.Text,out x)) LoadPredict(x); } } private void textBox2_TextChanged(object sender, EventArgs e) { if (_组合曲线) { if (coefficients == null) return; double x = 0,y=0; if (!double.TryParse(textBox2.Text, out y)) return; x = getXbyY(coefficients,y); x = Math.Round(x, 2); textBox1.TextChanged -= textBox1_TextChanged; textBox1.Text = x.ToString(); textBox1.TextChanged += textBox1_TextChanged; } else { if (_SelectedPump == null) return; double x = 0, y = 0; if (!double.TryParse(textBox2.Text, out y)) return; x = _SelectedPump.流量扬程曲线.Evaluate_Solve(y); x = Math.Round(x, 2); textBox1.TextChanged -= textBox1_TextChanged; textBox1.Text = x.ToString(); textBox1.TextChanged += textBox1_TextChanged; if (x!= _SelectedPump.流量扬程曲线.ErrNum) { LoadPredict(x); } } } private void textBox3_TextChanged(object sender, EventArgs e) { if (_组合曲线) { return; } else { if (_SelectedPump == null) return; double x = 0, y = 0; if (!double.TryParse(textBox3.Text, out y)) return; x = _SelectedPump.流量功率曲线.Evaluate_Solve(y); x = Math.Round(x, 2); textBox1.TextChanged -= textBox1_TextChanged; textBox1.Text = x.ToString(); textBox1.TextChanged += textBox1_TextChanged; if (x != _SelectedPump.流量功率曲线.ErrNum) { LoadPredict(x); } } } private void textBox4_TextChanged(object sender, EventArgs e) { if (_组合曲线) { return; } else { if (_SelectedPump == null) return; double x = 0, y = 0; if (!double.TryParse(textBox4.Text, out y)) return; x = _SelectedPump.流量效率曲线.Evaluate_Solve(y); x = Math.Round(x, 2); textBox1.TextChanged -= textBox1_TextChanged; textBox1.Text = x.ToString(); textBox1.TextChanged += textBox1_TextChanged; if (x != _SelectedPump.流量效率曲线.ErrNum) { LoadPredict(x); } } } private void LoadPredict(double x) { double y = 0; if (_SelectedPump.流量扬程曲线.IsFitted) { y = _SelectedPump.流量扬程曲线.Evaluate(x); y = Math.Round(y, 2); textBox2.TextChanged-= textBox2_TextChanged; textBox2.Text=y.ToString(); textBox2.TextChanged += textBox2_TextChanged; } if (_SelectedPump.流量功率曲线.IsFitted) { y = _SelectedPump.流量功率曲线.Evaluate(x); y = Math.Round(y, 2); textBox3.TextChanged -= textBox3_TextChanged; textBox3.Text = y.ToString(); textBox3.TextChanged += textBox3_TextChanged; } if (_SelectedPump.流量效率曲线.IsFitted) { y = _SelectedPump.流量效率曲线.Evaluate(x); y = Math.Round(y, 2); textBox4.TextChanged -= textBox4_TextChanged; textBox4.Text = y.ToString(); textBox4.TextChanged += textBox4_TextChanged; } } private void button_导出_Click(object sender, EventArgs e) { using (SaveFileDialog saveDialog = new SaveFileDialog()) { saveDialog.Filter = "Text file (*.txt)|*.txt"; if (saveDialog.ShowDialog() == DialogResult.OK) { StringBuilder sb = new StringBuilder(); foreach (DataGridViewRow row in dataGridView1.Rows) { sb.AppendLine(string.Format("{0}\t{1}\t{2}\t{3}", row.Cells[0].Value, row.Cells[1].Value, row.Cells[2].Value, row.Cells[3].Value)); } File.WriteAllText(saveDialog.FileName, sb.ToString()); } } } private void button_导入_Click(object sender, EventArgs e) { using (OpenFileDialog openDialog = new OpenFileDialog()) { openDialog.Filter = "Text file (*.txt)|*.txt"; if (openDialog.ShowDialog() == DialogResult.OK) { dataGridView1.Rows.Clear(); string[] lines = File.ReadAllLines(openDialog.FileName); foreach (string line in lines) { string[] fields = line.Split('\t'); if (fields[0].Trim() == "" || fields[1].Trim() == "") continue; if (fields.Length >= 4) { dataGridView1.Rows.Add(fields[0], fields[1], fields[2], fields[3]); } } } } LoadDataPoint(); } private void button_应用_Click(object sender, EventArgs e) { UnLoadCurveData(); } private void button_重置_Click(object sender, EventArgs e) { LoadPump(_SelectedPump); } #endregion #region 鼠标事件 private bool isDragging = false; private Point lastPosition; private ElementPosition lastPositionChart; double x0, x1, y0, y1; private void chart1_MouseWheel(object sender, MouseEventArgs e) { // 实验发现鼠标滚轮滚动一圈时e.Delta = 120,正反转对应正负120 if (chart1.Series.Count < 2 || chart1.Series[1].Points.Count < 3) return; switch (cb_曲线类型.SelectedIndex) { case 0: chart1.ChartAreas[0].AxisY.Maximum -= e.Delta/120; break; case 1: chart1.ChartAreas[0].AxisY2.Maximum -= e.Delta / 24; break; case 2: chart1.ChartAreas[0].AxisY2.Maximum -= e.Delta / 120; break; } updateXY(); } private void Chart1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left && 图片取点 && 取点类型==0) { //var X = chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X); //var Y = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y); //_SelectedPump.流量扬程曲线.Data.Add(new PointF((float)X, (float)Y)); } else // if (e.Button != MouseButtons.Left) return; if (e.Button == MouseButtons.Left) { if (_组合曲线) return; if (chart1.Series.Count < 2 || chart1.Series[1].Points.Count < 3) return; isMouseDown = true; lastX = chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X); lastY = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y); lastDataX = chart1.Series[1].Points.Select(p => p.XValue).ToArray(); lastDataY = chart1.Series[1].Points.Select(p => p.YValues[0]).ToArray(); lastIndex = chart1.Series[1].Points.FindNearest(lastX); moved = false; } if (e.Button == MouseButtons.Right && 图片取点 ) { toolStripSplitButton1_ButtonClick(1, new EventArgs()); } else if (e.Button == MouseButtons.Middle) { // 记录鼠标最后位置 // 记录鼠标最后位置 isDragging = true; lastPosition = new Point(e.X, e.Y); } } void addXY(double a, double b) { chart1.ChartAreas[0].AxisY.LabelStyle.Format = "0.0"; chart1.ChartAreas[0].AxisX.Minimum -=a * 10; chart1.ChartAreas[0].AxisX.Maximum -=a * 10; chart1.ChartAreas[0].AxisY.Minimum +=b/10; chart1.ChartAreas[0].AxisY.Maximum +=b/10; updateXY(); } private void Chart1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left && 图片取点 && 取点类型==0) { double X = 0; double Y = 0; X = chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X); X = Math.Round(X, 1); switch ( cb_曲线类型.SelectedIndex) { case 0: Y = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y); Y = Math.Round(Y, 1); dataGridView1.Rows.Add(X, Y); break; case 1: Y = chart1.ChartAreas[0].AxisY2.PixelPositionToValue(e.Y); Y = Math.Round(Y, 1); dataGridView1.Rows.Add(X, null, Y); break; case 2: Y = chart1.ChartAreas[0].AxisY2.PixelPositionToValue(e.Y); Y = Math.Round(Y, 1); dataGridView1.Rows.Add(X, null,null, Y); break; } LoadDataPoint(); //_SelectedPump.流量扬程曲线.Data.Add(new PointF((float)X,(float)Y)); } else if (e.Button == MouseButtons.Left) { isMouseDown = false; lastIndex = -1; } else if (e.Button == MouseButtons.Middle) { // 重置拖动状态 isDragging = false; } } bool moved = false; private void Chart1_MouseMove(object sender, MouseEventArgs e) { if (isMouseDown && lastIndex != -1) { if (_组合曲线) return; moved = true; double currX = chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.X); double currY = chart1.ChartAreas[0].AxisY.PixelPositionToValue(e.Y); int currIndex = chart1.Series[1].Points.FindNearest(currX); if (currIndex != lastIndex) { // 调整选中的数据点 lastDataX[lastIndex] = currX; lastDataY[lastIndex] = currY; chart1.Series[1].Points.Clear(); for (int i = 0; i < lastDataX.Length; i++) { chart1.Series[1].Points.AddXY(lastDataX[i], lastDataY[i]); } // 更新多项式系数 coefficients = Fit.Polynomial(lastDataX, lastDataY, degree); //textBox2.Text = GeneratePolynomialString(coefficients); Label_Forum.Text = GeneratePolynomialString(coefficients); lastIndex = currIndex; } } else if(isDragging) { // 计算鼠标位置的位移量 int dx = e.X - lastPosition.X; int dy = e.Y - lastPosition.Y; // 调整 ChartArea 的位置 addXY( dx,dy); //chart1.ChartAreas[0].Position.Y += dy; // 更新鼠标最后位置 lastPosition = new Point(e.X, e.Y); // 重绘图表 chart1.Invalidate(); } //chart1.ChartAreas[0].CursorX.SetCursorPixelPosition(new PointF(e.X, e.Y), true); //chart1.ChartAreas[0].CursorY.SetCursorPixelPosition(new PointF(e.X, e.Y), true); //else if (e.Delta != 0) //{ // //// 获取鼠标在 ChartArea 中的位置 // //Point chartLocation = chart1.PointToClient(new Point(e.X, e.Y)); // //// 获取 ChartArea 中心对应的值 // //double centerX = chart1.ChartAreas[0].AxisX.PixelPositionToValue(chartLocation.X); // //double centerY = chart1.ChartAreas[0].AxisY.PixelPositionToValue(chartLocation.Y); // //// 缩放 ChartArea // //double zoomFactor = Math.Max((double)e.Delta / SystemInformation.MouseWheelScrollDelta, 1.0 / 1.1); // //double width = (chart1.ChartAreas[0].AxisX.ScaleView.ViewMaximum - chart1.ChartAreas[0].AxisX.ScaleView.ViewMinimum) * zoomFactor / 2.0; // chart1.ChartAreas[0].AxisX.ScaleView.Zoom(centerX - width, centerX + width); // chart1.ChartAreas[0].AxisY.ScaleView.Zoom(centerY - width, centerY + width); //} } #endregion #region 数学相关 private double EvaluatePolynomial(DenseVector coeffs, double x) { // 计算多项式在点 x 处的取值 double y = 0; for (int i = 0; i < coeffs.Count; i++) { y += coeffs[i] * Math.Pow(x, i); } return y; } private string GeneratePolynomialString(DenseVector coeffs) { // 生成多项式的字符串表示形式 string polyStr = "y="; for (int i = coeffs.Count - 1; i >= 0; i--) { if (coeffs[i] == 0) continue; if (i == coeffs.Count - 1) { polyStr += coeffs[i].ToString() + "x^" + i; } else if (i == 1) { if (coeffs[i] > 0) { if (polyStr != "") polyStr += " + "; polyStr += coeffs[i].ToString() + "x"; } else { polyStr += " - " + (-coeffs[i]).ToString() + "x"; } } else if (i == 0) { if (coeffs[i] > 0) { if (polyStr != "") polyStr += " + "; polyStr += coeffs[i].ToString(); } else { polyStr += " - " + (-coeffs[i]).ToString(); } } else { if (coeffs[i] > 0) { if (polyStr != "") polyStr += " + "; polyStr += coeffs[i].ToString() + "x^" + i; } else { polyStr += " - " + (-coeffs[i]).ToString() + "x^" + i; } } } if (polyStr == "") polyStr = "0"; return polyStr; } #endregion #region 对象树 // 向上移动节点 private void MoveNodeUp(object sender, EventArgs e) { TreeNode node = treeView1.SelectedNode; if (treeView1.SelectedNode != null && treeView1.SelectedNode.Tag is Pump pump) { List parent = ((Factory)node.Parent.Tag).Pumps; int index = parent.IndexOf(pump) - 1; parent.Remove(pump); parent.Insert(index, pump); _EditFlag = true; } else if (treeView1.SelectedNode != null && treeView1.SelectedNode.Tag is Factory factory) { List parent = factoryList.Factories; int index = parent.IndexOf(factory) - 1; parent.Remove(factory); parent.Insert(index, factory); _EditFlag = true; } DisplayFactoryListInTreeView(factoryList); //TreeNode node = treeView1.SelectedNode; //if (node != null && node.PrevNode != null) //{ // dynamic parent = node.Parent; // int index = node.Index - 1; // if (parent == null) parent = treeView1; // parent.Nodes.Remove(node); // parent.Nodes.Insert(index, node); // treeView1.SelectedNode = node; //} } // 向下移动节点 private void MoveNodeDown(object sender, EventArgs e) { TreeNode node = treeView1.SelectedNode; if (treeView1.SelectedNode != null && treeView1.SelectedNode.Tag is Pump pump) { List parent = ((Factory)node.Parent.Tag).Pumps; int index = parent.IndexOf(pump) + 1; parent.Remove(pump); parent.Insert(index,pump); _EditFlag = true; } else if (treeView1.SelectedNode != null && treeView1.SelectedNode.Tag is Factory factory) { List parent = factoryList.Factories; int index = factoryList.Factories.IndexOf(factory) + 1; parent.Remove(factory); parent.Insert(index, factory); _EditFlag = true; } DisplayFactoryListInTreeView(factoryList); //if (node != null && node.NextNode != null) //{ // dynamic parent = node.Parent; // int index = node.Index + 1; // if (parent == null) parent = treeView1; // parent.Nodes.Remove(node); // parent.Nodes.Insert(index, node); // treeView1.SelectedNode = node; //} } private void 删除MenuItem_Click(object sender, EventArgs e) { var result = MessageBox.Show("确认删除?", "即将删除节点", MessageBoxButtons.OKCancel); if (result != DialogResult.OK) return; TreeNode node = treeView1.SelectedNode; if (treeView1.SelectedNode != null && treeView1.SelectedNode.Tag is Pump pump) { List parent = ((Factory)node.Parent.Tag).Pumps; parent.Remove(pump); _EditFlag = true; } else if (treeView1.SelectedNode != null && treeView1.SelectedNode.Tag is Factory factory) { List parent = factoryList.Factories; parent.Remove(factory); _EditFlag = true; } } private void treeView1_AfterCheck(object sender, TreeViewEventArgs e) { //var node = sender as TreeNode; _CheckedPumps.Clear(); foreach (TreeNode n in treeView1.Nodes) { foreach (TreeNode p in n.Nodes) { if (p != null && p.Tag is Pump pump) { if (p.Checked) { if (!_CheckedPumps.Contains(pump)) _CheckedPumps.Add(pump); } } } } } private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) { //chart1.Series.Clear(); //AddSeries("ChartArea1", SeriesChartType.Point, "Legend1", "流量扬程点", false); //AddSeries("ChartArea1", SeriesChartType.Spline, "Legend1", "流量扬程"); Label_Forum.Text = ""; if (treeView1.SelectedNode != null && treeView1.SelectedNode.Tag is Pump pump) { _SelectedPump = pump; Label_SelectedPump.Text = $"{pump.factoryName}_{pump.Name}"; _组合曲线 = false; LoadPump(pump); } else { _SelectedPump = null; Label_SelectedPump.Text = ""; } } private void DisplayFactoryListInTreeView(FactoryList factoryList) { treeView1.Nodes.Clear(); foreach (Factory factory in factoryList.Factories) { TreeNode rootNode = new TreeNode(factory.Name); rootNode.Tag = factory; rootNode.ImageIndex = factory.Type == FactoryType.水厂 ? 0 : 1; rootNode.Checked = false; rootNode.ExpandAll(); foreach (Pump pump in factory.Pumps) { TreeNode pumpNode = new TreeNode(pump.Name); pumpNode.Tag = pump; pumpNode.Checked = false; pumpNode.ImageIndex = pump.Type == PumpType.定速泵 ? 2 : 3; rootNode.Nodes.Add(pumpNode); } treeView1.Nodes.Add(rootNode); } } private void GetSelectedFactoriesAndPumps(TreeNodeCollection nodes, List selectedFactories, List selectedPumps) { foreach (TreeNode node in nodes) { if (node.Checked && node.Tag is Factory factory) { selectedFactories.Add(factory); } else if (node.Checked && node.Tag is Pump pump) { selectedPumps.Add(pump); } GetSelectedFactoriesAndPumps(node.Nodes, selectedFactories, selectedPumps); } } private void 添加水厂button_Click(object sender, EventArgs e) { using (var addFactoryForm = new AddFactoryForm()) { if (addFactoryForm.ShowDialog() == DialogResult.OK) { string name = addFactoryForm.FactoryName; FactoryType type = addFactoryForm.factoryType; factoryList.AddFactory(name, type); DisplayFactoryListInTreeView(factoryList); } } } private void 添加水泵_Click(object sender, EventArgs e) { if (treeView1.SelectedNode != null && treeView1.SelectedNode.Tag is Factory factory) { using (var addPumpForm = new AddPumpForm()) { if (addPumpForm.ShowDialog() == DialogResult.OK) { string name = addPumpForm.PumpName; PumpType type = addPumpForm.pumpType; var pump=factoryList.AddPump(factory, name, type); pump.额定扬程 = addPumpForm.额定扬程; pump.额定流量 = addPumpForm.额定流量; pump.额定转速 = addPumpForm.额定转速; pump.额定功率 = addPumpForm.额定功率; DisplayFactoryListInTreeView(factoryList); } } } } private void 编辑MenuItem_Click(object sender, EventArgs e) { if (treeView1.SelectedNode != null && treeView1.SelectedNode.Tag is Factory factory) { using (var addPumpForm = new AddFactoryForm()) { addPumpForm.FactoryName = factory.Name; addPumpForm.factoryType = factory.Type; if (addPumpForm.ShowDialog() == DialogResult.OK) { string name = addPumpForm.FactoryName; FactoryType type = addPumpForm.factoryType; factory.Name = name; factory.Type = type; DisplayFactoryListInTreeView(factoryList); _EditFlag = true; } } } else if (treeView1.SelectedNode != null && treeView1.SelectedNode.Tag is Pump pump) { using (var addPumpForm = new AddPumpForm()) { addPumpForm.PumpName = pump.Name; addPumpForm.pumpType = pump.Type; addPumpForm.额定扬程 = pump.额定扬程; addPumpForm.额定流量 = pump.额定流量; addPumpForm.额定转速 = pump.额定转速; addPumpForm.额定功率 = pump.额定功率; if (addPumpForm.ShowDialog() == DialogResult.OK) { string name = addPumpForm.PumpName; PumpType type = addPumpForm.pumpType; pump.Name = name; pump.Type = type; pump.额定扬程 = addPumpForm.额定扬程; pump.额定流量 = addPumpForm.额定流量; pump.额定转速 = addPumpForm.额定转速; pump.额定功率 = addPumpForm.额定功率; DisplayFactoryListInTreeView(factoryList); _EditFlag = true; } } } } private void treeView1_BeforeSelect(object sender, TreeViewCancelEventArgs e) { // 取消选中时的图片变化 e.Node.SelectedImageIndex = e.Node.ImageIndex; } Pump _SelectedPump = null; private void treeView1_Click(object sender, EventArgs e) { } #endregion #region 界面加载/卸载;曲线绘制; //鼠标悬停显示曲线点的值 System.Windows.Forms.DataVisualization.Charting.ToolTipEventArgs toolTipEventArgs; private void chart_trace_GetToolTipText(object sender, ToolTipEventArgs e) { toolTipEventArgs = e; if (e.HitTestResult.ChartElementType == System.Windows.Forms.DataVisualization.Charting.ChartElementType.DataPoint) { int i = e.HitTestResult.PointIndex; System.Windows.Forms.DataVisualization.Charting.DataPoint dp = e.HitTestResult.Series.Points[i]; e.Text = string.Format("A:{0},T:{1}", dp.XValue.ToString(), dp.YValues[0]); } } private Series AddSeries(string Area, SeriesChartType type, String Legend, String Name, bool showLegend = true) { Series series = new Series(); series.ChartArea = Area; series.ChartType = type; series.Legend = Legend; series.Name = Name; series.IsVisibleInLegend = showLegend; this.chart1.Series.Add(series); return series; } void LoadDataPoint() { if (chart1.Series.Count == 0) { AddSeries("ChartArea1", SeriesChartType.Point, "Legend1", "扬程点", false); } chart1.Series[0].Points.Clear(); dataPoints = new List(); int index = cb_曲线类型.SelectedIndex + 1; for (int i = 0; i < dataGridView1.Rows.Count - 1; i++) { if (dataGridView1.Rows[i].Cells[index].Value == null) continue; double x = Convert.ToDouble(dataGridView1.Rows[i].Cells[0].Value); double y = Convert.ToDouble(dataGridView1.Rows[i].Cells[index].Value); chart1.Series[0].Points.AddXY(x, y); dataPoints.Add(new double[] { x, y }); } } void UnLoadCurveData() { _SelectedPump.流量扬程曲线.Data = new List(); _SelectedPump.流量功率曲线.Data = new List(); _SelectedPump.流量效率曲线.Data = new List(); foreach (DataGridViewRow row in dataGridView1.Rows) { if (row.Cells[0].Value == null) continue; float temp; float x = float.Parse(row.Cells[0].Value.ToString()); temp = getObj(row.Cells[1].Value); if (temp != -10086f && temp>0) _SelectedPump.流量扬程曲线.Data.Add(new PointF(x, temp)); temp = getObj(row.Cells[2].Value); if (temp != -10086f && temp > 0) _SelectedPump.流量功率曲线.Data.Add(new PointF(x, temp)); temp = getObj(row.Cells[3].Value); if (temp != -10086f && temp > 0) _SelectedPump.流量效率曲线.Data.Add(new PointF(x, temp)); } _SelectedPump.CurveFit(); double min = -1; double max = -1; _EditFlag = true; } private void ShowCurve() { chart1.Series.Clear(); AddSeries("ChartArea1", SeriesChartType.Point, "Legend1", "扬程点", false); AddSeries("ChartArea1", SeriesChartType.Spline, "Legend1", "扬程"); if (_SelectedPump != null && _SelectedPump.流量功率曲线.Data.Count > 0) { var s = AddSeries("ChartArea1", SeriesChartType.Spline, "Legend2", "功率"); s.YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Secondary; } if (_SelectedPump != null && _SelectedPump.流量效率曲线.Data.Count > 0) { var s = AddSeries("ChartArea1", SeriesChartType.Spline, "Legend3", "效率"); s.YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Secondary; } if (dataPoints.Count < 3) return; degree = (int)numericUpDown1.Value; coefficients = Fit.Polynomial(dataPoints.Select(p => p[0]).ToArray(), dataPoints.Select(p => p[1]).ToArray(), degree); chart1.Series[1].Points.Clear(); double step = (dataPoints.Last()[0] - dataPoints.First()[0]) / 50; for (double x = dataPoints.First()[0]; x <= dataPoints.Last()[0]; x += step) { double y = EvaluatePolynomial(coefficients, x); chart1.Series[1].Points.AddXY(x, y); } //textBox2.Text = GeneratePolynomialString(coefficients); // 显示拟合曲线的公式 Label_Forum.Text = GeneratePolynomialString(coefficients); // 设置 X 轴的最大最小值 chart1.ChartAreas[0].AxisX.Minimum = double.NaN; chart1.ChartAreas[0].AxisX.Maximum = double.NaN; // 设置 Y 轴的最大最小值 chart1.ChartAreas[0].AxisY.Minimum = double.NaN; chart1.ChartAreas[0].AxisY.Maximum = double.NaN; updateXY(); } private float getObj(object o) { if (o == null) return -10086f; return float.Parse(o.ToString()); } void LoadPump(Pump pump) { //dataGridView1.Rows.Clear(); //for (int i = 0; i < pump.流量扬程曲线.Data.Count; i++) //{ // PointF p = pump.流量扬程曲线.Data[i]; // double y1=0, y2 = 0; // if (pump.流量功率曲线.IsFitted) y1 = EvaluatePolynomial(pump.流量功率曲线.coefficients, p.X); // if (pump.流量效率曲线.IsFitted) y2 = EvaluatePolynomial(pump.流量效率曲线.coefficients, p.X); // dataGridView1.Rows.Add(p.X, p.Y, y1, y2); //} //LoadDataPoint(); //ShowCurve(); pump.ShowInGrid(dataGridView1); chart1.Series.Clear(); var cb_type= cb_曲线类型.SelectedItem.ToString(); pump.AddCurve(chart1, cb_type); if (pump.Datasets[cb_type].IsFitted) { Label_Forum.Text = pump.Datasets[cb_type].getForum; if (cb_type == "流量功率曲线" && pump.Datasets[cb_type].range_Y == null) { var xMax = chart1.ChartAreas[0].AxisX.Maximum; var yMax = Math.Max(pump.Datasets[cb_type].YdataMax, pump.Datasets[cb_type].Evaluate(xMax)); chart1.ChartAreas[0].AxisY2.Maximum = yMax; } } updateXY(); textBox5.Text = pump.额定功率.ToString(); textBox6.Text = pump.额定转速.ToString(); textBox9.Text = pump.额定流量.ToString(); textBox8.Text = pump.额定扬程.ToString(); } #endregion #region 复合曲线 private void button_曲线对比_Click(object sender, EventArgs e) { if (_CheckedPumps.Count <= 0) return; _组合曲线 = true; double minX = 9999999; double maxX = 0; var 曲线类型=cb_曲线类型.SelectedItem.ToString(); dataGridView1.Rows.Clear(); chart1.Series.Clear(); Range range = new Range(9999,-9999); foreach (var pump in _CheckedPumps) { if (pump.Datasets[曲线类型].IsFitted) range = Range.Union(range, pump.Datasets[曲线类型].range_X); } foreach (var pump in _CheckedPumps) { //pump.ShowInGrid(dataGridView1); pump.AddCurve(chart1, 曲线类型, true, range); } updateXY(); } private void button_组合曲线_Click(object sender, EventArgs e) { if (_CheckedPumps.Count <= 0) return; _组合曲线 = true; dataGridView1.Rows.Clear(); chart1.Series.Clear(); foreach (var pump in _CheckedPumps) { pump.ShowInGrid(dataGridView1); pump.AddCurve(chart1, cb_曲线类型.SelectedItem.ToString(), true); } double minY = 9999999; double maxY = 0; foreach (var pump in _CheckedPumps) { if (pump.流量扬程曲线.Data.Count == 0) { //MessageBox.Show($"{pump.factoryName}_{pump.Name}无曲线数据"); //return; continue; } float firstY = pump.流量扬程曲线.Data.First().Y; float lastY = pump.流量扬程曲线.Data.Last().Y; if (minY > lastY) minY = lastY; if (maxY < firstY) maxY = firstY; var data = pump.流量扬程曲线; data.coefficients = Fit.Polynomial(data.Data.Select(p => (double)p.X).ToArray(), data.Data.Select(p => (double)p.Y).ToArray(), degree); } double step = (maxY - minY) / 100; double xmax = 0; var series = AddSeries("ChartArea1", SeriesChartType.Spline, "Legend1", "组合流量扬程"); for (double y = minY; y <= maxY; y += step) { double x = 0; bool valid_flag = true; foreach (var pump in _CheckedPumps) { //AddSeries("ChartArea1", SeriesChartType.Point, "Legend1", "流量扬程点"+pump.Name, false); if (pump.流量扬程曲线.Data.Count == 0) { //MessageBox.Show($"{pump.factoryName}_{pump.Name}无曲线数据"); //return; continue; } var data = pump.流量扬程曲线; var x0 = getXbyY(data.coefficients, y); if (x0==-1) valid_flag = false; x += x0; //chart1.Series[2*i].Points.AddXY(x, y); } if(valid_flag) { series.Points.AddXY(x, y); if (xmax < x) xmax = x; } } coefficients = Fit.Polynomial(series.Points.Select(p => p.XValue).ToArray(), series.Points.Select(p => p.YValues[0]).ToArray(), degree); chart1.ChartAreas[0].AxisX.Maximum = xmax; updateXY(); } #endregion List _CheckedPumps = new List(); #region 图片/取点相关 double getXbyY(DenseVector coefficients, double y) { int degree = 2; // 多项式次数 double a = coefficients[degree]; // 二次项系数 double b = coefficients[degree - 1]; // 一次项系数 double c = coefficients[0] - y; // 常数项系数减去给定的 y 值 // 求解二次方程 ax^2 + bx + c = 0 double delta = b * b - 4 * a * c; if (delta < 0) return -1; double x1 = (-b + Math.Sqrt(delta)) / (2 * a); double x2 = (-b - Math.Sqrt(delta)) / (2 * a); // 取两个解中符合实际情况的那个(可以根据具体应用场景来确定) double x = (x2 >= x1) ? x2 : x1; return x; } bool __组合曲线 = false; bool _组合曲线 { get { return __组合曲线; } set { __组合曲线 = value; updatePredictTextBox(); } } private void updatePredictTextBox() { textBox3.Enabled = !_组合曲线; textBox4.Enabled = !_组合曲线; } bool 图片取点 = false; int 取点类型 = -1; private bool _editFlag = false; private bool _EditFlag { get { return _editFlag; } set { _editFlag = value; if (_editFlag==true) { this.Text = "曲线拟云(*未保存*)"; } else { this.Text = "曲线拟云"; //if (_editFlag == true) //{ //} } } } private void button_图片取点_Click(object sender, EventArgs e) { if (_SelectedPump == null) { MessageBox.Show("请选择水泵"); return; } if (this.Opacity == 1) { this.Opacity = opca; 图片取点 = true; 取点类型 = 0; } else { 图片取点 = false; //_SelectedPump.流量扬程曲线.Data.Sort((a,b)=>a.Xa.Xa.X=0) { opca = 0.3; } else if (button.Name.IndexOf("50") >= 0) { opca = 0.5; } else { opca = 0.7; } } private void toolStripButton11_Click(object sender, EventArgs e) { if(!string.IsNullOrEmpty( Label_Forum.Text)) Clipboard.SetText(Label_Forum.Text); } private void label9_Click(object sender, EventArgs e) { } private void 查看图片ToolStripMenuItem_Click(object sender, EventArgs e) { if (_SelectedPump == null) { MessageBox.Show("请选择水泵"); return; } showPic(); } #endregion private void button_设置坐标轴_Click(object sender, EventArgs e) { var xmin= double.Parse(tb_Xmin.Text); var xmax= double.Parse(tb_Xmax.Text); var ymin= double.Parse(tb_Ymin.Text); var ymax= double.Parse(tb_Ymax.Text); var y2min= double.Parse(tb_Y2min.Text); var y2max= double.Parse(tb_Y2max.Text); if (xmin selectedFactories = new List(); //List selectedPumps = new List(); //GetSelectedFactoriesAndPumps(treeView1.Nodes, selectedFactories, selectedPumps); //FactoryList factoryList = new FactoryList(); //factoryList.Factories = selectedFactories; //SaveToFile("factory_list.xml", factoryList); factoryList.Save(); _EditFlag = false; } private void openToolStripMenuItem_Click(object sender, EventArgs e) { //FactoryList factoryList = LoadFromFile("factory_list.xml"); factoryList.Load(); DisplayFactoryListInTreeView(factoryList); } } }