/// <summary> /// функция, реализующая расчет приложенной нагрузки в узлах, лежащих на прямой /// </summary> /// <param name="nodes">Список узлов, лежащих на линии</param> /// <param name="type">Тип линии</param> private void calculateForceAtNodes(List <MyNode> nodes, LineType type, MyArc arc, int currentModel) { // количество итераций для алгоритма симпсона int splitCount = 500; // мы имеем список узлов, лежащих на стороне, к которой приложенна нагрузка. надо их отсортировать по возрастанию координат switch (type) { case LineType.ParallelOX: if (this.ascSort.Checked) { nodes.Sort(delegate(MyNode node1, MyNode node2) { return(node1.X.CompareTo(node2.X)); }); } else { nodes.Sort(delegate(MyNode node1, MyNode node2) { return(-node1.X.CompareTo(node2.X)); }); } break; case LineType.ParallelOY: if (this.ascSort.Checked) { nodes.Sort(delegate(MyNode node1, MyNode node2) { return(node1.Y.CompareTo(node2.Y)); }); } else { nodes.Sort(delegate(MyNode node1, MyNode node2) { return(-node1.Y.CompareTo(node2.Y)); }); } break; case LineType.NotParallel: if (this.ascSort.Checked) { if (this.sortByX.Checked == true) { nodes.Sort(delegate(MyNode node1, MyNode node2) { return(node1.X.CompareTo(node2.X)); }); } else { nodes.Sort(delegate(MyNode node1, MyNode node2) { return(node1.Y.CompareTo(node2.Y)); }); } } else { if (this.sortByX.Checked == true) { nodes.Sort(delegate(MyNode node1, MyNode node2) { return(-node1.X.CompareTo(node2.X)); }); } else { nodes.Sort(delegate(MyNode node1, MyNode node2) { return(-node1.Y.CompareTo(node2.Y)); }); } } break; case LineType.IsArc: // упорядочиваем точки дуги по часовой if (ascSort.Checked) { nodes.Sort(delegate(MyNode point1, MyNode point2) { double phi1 = Math.Atan2(point1.Y - arc.CenterPoint.Y, point1.X - arc.CenterPoint.X); double phi2 = Math.Atan2(point2.Y - arc.CenterPoint.Y, point2.X - arc.CenterPoint.X); if (Math.Abs(phi2 - phi1) < Math.PI) { return(-phi1.CompareTo(phi2)); } else { return(phi1.CompareTo(phi2)); } }); } else { nodes.Sort(delegate(MyNode point1, MyNode point2) { double phi1 = Math.Atan2(point1.Y - arc.CenterPoint.Y, point1.X - arc.CenterPoint.X); double phi2 = Math.Atan2(point2.Y - arc.CenterPoint.Y, point2.X - arc.CenterPoint.X); if (Math.Abs(phi2 - phi1) < Math.PI) { return(phi1.CompareTo(phi2)); } else { return(-phi1.CompareTo(phi2)); } }); } break; } List <MyNode> excludedNodes = new List <MyNode>(); if (cbxExcludeNodes.Checked) { string[] strNumbers = txtExcludedNodes.Text.Split(','); for (int i = 0; i < strNumbers.Length; i++) { int num; MyNode node; bool error = false; if (!int.TryParse(strNumbers[i], out num)) { error = true; } else { node = nodes.Find(n => n.Id == num); if (node == null) { error = true; } else { excludedNodes.Add(node); } } if (error) { MessageBox.Show("Неверно заданы узлы!", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } } bool excludeFirstNode = false, excludeLastNode = false; foreach (MyNode node in excludedNodes) { if (nodes.IndexOf(node) == 0) { excludeFirstNode = true; } else if (nodes.IndexOf(node) == nodes.Count - 1) { excludeLastNode = true; } else { nodes.Remove(node); } } if (type != LineType.IsArc) { // далее расчитываем значение нагрузки в узле по методу трапеции double x1 = 0; double y1 = 0; double x2 = 0; double y2 = 0; double x3 = 0; double y3 = 0; double d21 = 0; double d13 = 0; double S = 0; double d0 = 0.0; double Sum, A, B; double CH = (this.parent.currentFullModel.geometryModel.Points.Max(point => point.Y) - this.parent.currentFullModel.geometryModel.Points.Min(point => point.Y)) / 2.0; CH = CH + this.parent.currentFullModel.geometryModel.Points.Min(point => point.Y); double CW = (this.parent.currentFullModel.geometryModel.Points.Max(point => point.X) - this.parent.currentFullModel.geometryModel.Points.Min(point => point.X)) / 2.0; CW = CW + this.parent.currentFullModel.geometryModel.Points.Min(point => point.X); double k = (nodes[1].Y - nodes[0].Y) / (nodes[1].X - nodes[0].X); //double test = 2 * 3.14 - k; //test = test + 1; for (int i = 0; i < nodes.Count; i++) { if ((i == 0 && excludeFirstNode) || (i == nodes.Count - 1 && excludeLastNode)) { continue; } //Координата текущей точки x1 = nodes[i].X; y1 = nodes[i].Y; //Координата предыдущей точки if (i != 0) { x3 = nodes[i - 1].X; y3 = nodes[i - 1].Y; if (i == 1 && excludeFirstNode) { x3 -= (x1 - x3); y3 -= (y1 - y3); } } else { x3 = x1; y3 = y1; } //Координата следующей точки if (i != nodes.Count - 1) { x2 = nodes[i + 1].X; y2 = nodes[i + 1].Y; if (i == nodes.Count - 2 && excludeLastNode) { x2 += (x2 - x1); y2 += (y2 - y1); } } else { x2 = x1; y2 = y1; } // Сила приложенная к текущему узлу (вычисляется через площадь трапеции) // S-размер участка поверхности между силами d21 = Mathematics.FindDist(x1, y1, x2, y2); d13 = Mathematics.FindDist(x1, y1, x3, y3); S = (d21 + d13) / 2.0; Sum = CalculateIntegral(d0, d0 + S, splitCount); d0 += S; if (type == LineType.ParallelOX) { if (radioButton1.Checked == true && nodes[0].Y < CH) { nodes[i].ForceY -= Sum; } else if (radioButton1.Checked == true) { nodes[i].ForceY += Sum; } if (radioButton2.Checked == true && nodes[0].Y < CH) { nodes[i].ForceY += Sum; } else if (radioButton2.Checked == true) { nodes[i].ForceY -= Sum; } } if (type == LineType.ParallelOY) { if (radioButton1.Checked == true && nodes[0].X < CW) { nodes[i].ForceX -= Sum; } else if (radioButton1.Checked == true) { nodes[i].ForceX += Sum; } if (radioButton2.Checked == true && nodes[0].X < CW) { nodes[i].ForceX += Sum; } else if (radioButton2.Checked == true) { nodes[i].ForceX -= Sum; } } if (type == LineType.NotParallel) { if (radioButton1.Checked == true) { if ((nodes[0].Y < nodes[1].Y && nodes[0].X < nodes[1].X) || (nodes[0].Y > nodes[1].Y && nodes[0].X > nodes[1].X)) { if (getFEnumber(nodes, LineAngleType.right_up, FESearchSpace.up, currentModel) > getFEnumber(nodes, LineAngleType.right_up, FESearchSpace.down, currentModel)) { nodes[i].ForceX += Sum * Math.Sin(Math.Atan(Math.Abs(k))); nodes[i].ForceY -= Sum * Math.Cos(Math.Atan(Math.Abs(k))); } else { nodes[i].ForceX -= Sum * Math.Sin(Math.Atan(Math.Abs(k))); nodes[i].ForceY += Sum * Math.Cos(Math.Atan(Math.Abs(k))); } } else if ((nodes[0].Y <nodes[1].Y && nodes[0].X> nodes[1].X) || (nodes[0].Y > nodes[1].Y && nodes[0].X < nodes[1].X)) { if (getFEnumber(nodes, LineAngleType.left_up, FESearchSpace.up, currentModel) > getFEnumber(nodes, LineAngleType.left_up, FESearchSpace.down, currentModel)) { nodes[i].ForceX -= Sum * Math.Sin(Math.Atan(Math.Abs(k))); nodes[i].ForceY -= Sum * Math.Cos(Math.Atan(Math.Abs(k))); } else { nodes[i].ForceX += Sum * Math.Sin(Math.Atan(Math.Abs(k))); nodes[i].ForceY += Sum * Math.Cos(Math.Atan(Math.Abs(k))); } } } else if (radioButton2.Checked == true) { if ((nodes[0].Y < nodes[1].Y && nodes[0].X < nodes[1].X) || (nodes[0].Y > nodes[1].Y && nodes[0].X > nodes[1].X)) { if (getFEnumber(nodes, LineAngleType.right_up, FESearchSpace.up, currentModel) > getFEnumber(nodes, LineAngleType.right_up, FESearchSpace.down, currentModel)) { nodes[i].ForceX -= Sum * Math.Sin(Math.Atan(Math.Abs(k))); nodes[i].ForceY += Sum * Math.Cos(Math.Atan(Math.Abs(k))); } else { nodes[i].ForceX += Sum * Math.Sin(Math.Atan(Math.Abs(k))); nodes[i].ForceY -= Sum * Math.Cos(Math.Atan(Math.Abs(k))); } } else if ((nodes[0].Y <nodes[1].Y && nodes[0].X> nodes[1].X) || (nodes[0].Y > nodes[1].Y && nodes[0].X < nodes[1].X)) { if (getFEnumber(nodes, LineAngleType.left_up, FESearchSpace.up, currentModel) > getFEnumber(nodes, LineAngleType.left_up, FESearchSpace.down, currentModel)) { nodes[i].ForceX += Sum * Math.Sin(Math.Atan(Math.Abs(k))); nodes[i].ForceY += Sum * Math.Cos(Math.Atan(Math.Abs(k))); } else { nodes[i].ForceX -= Sum * Math.Sin(Math.Atan(Math.Abs(k))); nodes[i].ForceY -= Sum * Math.Cos(Math.Atan(Math.Abs(k))); } } } } } } else { //расчет нагрузки на дуге double x1 = 0; double y1 = 0; double x2 = 0; double y2 = 0; double x3 = 0; double y3 = 0; double L31 = 0; double L12 = 0; double S; double d0 = 0; for (int i = 0; i < nodes.Count; i++) { if ((i == 0 && excludeFirstNode) || (i == nodes.Count - 1 && excludeLastNode)) { continue; } //Координата текущей точк x1 = nodes[i].X; y1 = nodes[i].Y; //Координата предыдущей точки if (i != 0) { x3 = nodes[i - 1].X; y3 = nodes[i - 1].Y; if (i == 1 && excludeFirstNode) { x3 -= (x1 - x3); y3 -= (y1 - y3); } } else { x3 = x1; y3 = y1; } //Координата следующей точки if (i != nodes.Count - 1) { x2 = nodes[i + 1].X; y2 = nodes[i + 1].Y; if (i == nodes.Count - 2 && excludeLastNode) { x2 += (x2 - x1); y2 += (y2 - y1); } } else { x2 = x1; y2 = y1; } // R1 - сила приложенная к текущему узлу double r = Mathematics.FindDist(arc.CenterPoint, arc.StartPoint); L31 = Mathematics.ArcLength(x1, y1, x3, y3, arc.CenterPoint.X, arc.CenterPoint.Y); L12 = Mathematics.ArcLength(x1, y1, x2, y2, arc.CenterPoint.X, arc.CenterPoint.Y); double R1; S = (L12 + L31) / 2.0; R1 = CalculateIntegral(d0, d0 + S, splitCount); d0 += S; if (radioButton1.Checked == true) { if (getFEnumber(nodes, arc.CenterPoint, FESearchSpace.inside, currentModel) > getFEnumber(nodes, arc.CenterPoint, FESearchSpace.outside, currentModel)) { nodes[i].ForceX += R1 * (x1 - arc.CenterPoint.X) / r; nodes[i].ForceY += R1 * (y1 - arc.CenterPoint.Y) / r; } else { nodes[i].ForceX -= R1 * (x1 - arc.CenterPoint.X) / r; nodes[i].ForceY -= R1 * (y1 - arc.CenterPoint.Y) / r; } } if (radioButton2.Checked == true) { if (getFEnumber(nodes, arc.CenterPoint, FESearchSpace.inside, currentModel) > getFEnumber(nodes, arc.CenterPoint, FESearchSpace.outside, currentModel)) { nodes[i].ForceX -= R1 * (x1 - arc.CenterPoint.X) / r; nodes[i].ForceY -= R1 * (y1 - arc.CenterPoint.Y) / r; } else { nodes[i].ForceX += R1 * (x1 - arc.CenterPoint.X) / r; nodes[i].ForceY += R1 * (y1 - arc.CenterPoint.Y) / r; } } } } }