/// <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;
                        }
                    }
                }
            }
        }