public void DrawLinesArray(MyStraightLine[] lines, Color color, bool drawId = true, bool isAreaLine = false, double width = 2.0)
        {
            int count = lines.Length * 2;

            if (count == 0)
            {
                return;
            }
            float[]  pts     = new float[count * 2];
            double[] vColors = colorArray(color);
            int      list    = Gl.glGenLists(1);

            Gl.glNewList(list, Gl.GL_COMPILE);
            Gl.glColor3dv(vColors);
            Gl.glLineWidth((float)(width));
            Gl.glEndList();
            for (int i = 0; i < lines.Length; i++)
            {
                MyStraightLine line = lines[i];
                pts[i * 4]     = (float)line.StartPoint.X;
                pts[i * 4 + 1] = (float)line.StartPoint.Y;
                pts[i * 4 + 2] = (float)line.EndPoint.X;
                pts[i * 4 + 3] = (float)line.EndPoint.Y;
                if (drawId)
                {
                    DrawString("L" + line.Id.ToString(), (float)(line.EndPoint.X + line.StartPoint.X) / 2.0f, (float)(line.EndPoint.Y + line.StartPoint.Y) / 2.0f);
                }
            }
            if (drawId)
            {
                FlushText(color);
            }
            drawBuffer.Add(new DrawingOperation(Gl.GL_LINES, pts, list));
        }
        public static MyPoint crossPoint(MyPoint point, MyStraightLine sline)
        {
            double commonX, commonY;

            if (Math.Abs(sline.EndPoint.X - sline.StartPoint.X) < 0.01)
            {
                commonX = sline.StartPoint.X;
                commonY = point.Y;
            }
            else if (Math.Abs(sline.EndPoint.Y - sline.StartPoint.Y) < 0.01)
            {
                commonX = point.X;
                commonY = sline.StartPoint.Y;
            }
            else
            {
                double k1, b1;
                double k2, b2;

                // Находим точку пересечения прямой и перпендикуляра, опущенного на эту прямую из точки point
                k2 = (double)(sline.EndPoint.Y - sline.StartPoint.Y) / (sline.EndPoint.X - sline.StartPoint.X);
                k1 = Math.Tan(Math.Atan(k2) + Math.PI / 2.0);
                b2 = (double)sline.EndPoint.Y - k2 * sline.EndPoint.X;
                b1 = point.Y - k1 * point.X;

                commonX = (b2 - b1) / (k1 - k2);
                commonY = commonX * k2 + b2;
            }
            return(new MyPoint(commonX, commonY, MyPoint.PointType.IsGeometryPoint));
        }
 private void findNodesAtStraightLine(List <MyNode> notMoveableNodes, MyStraightLine sline)
 {
     foreach (MyNode node in currentModel.Nodes)
     {
         // уравнение прямой, проходящей через две точки
         if (Mathematics.pointOnLine(node.X, node.Y, sline))
         {
             if (notMoveableNodes.IndexOf(node) == -1)
             {
                 notMoveableNodes.Add(node);
             }
         }
     }
 }
        public bool pointNearLine(MyPoint point, MyStraightLine sline)
        {
            MyPoint comPoint = crossPoint(point, sline);

            if (Mathematics.FindDist(point, comPoint) < visualizer.pointLocality)
            {
                if (comPoint.X <= Math.Max(sline.StartPoint.X, sline.EndPoint.X) && comPoint.X >= Math.Min(sline.StartPoint.X, sline.EndPoint.X) &&
                    comPoint.Y <= Math.Max(sline.StartPoint.Y, sline.EndPoint.Y) && comPoint.Y >= Math.Min(sline.StartPoint.Y, sline.EndPoint.Y)) // условие, гарантирующее, что точка от клика мышки лежит на отрезке, а не на прямой
                {
                    return(true);
                }
            }

            return(false);
        }
        private bool LineCrossingArc(MyStraightLine line, MyArc arc)
        {
            double r, a, b, c;

            if (Math.Abs(line.StartPoint.X - line.EndPoint.X) < 0.01)
            {
                b = 0; a = 1; c = -arc.CenterPoint.X;
            }
            else if (Math.Abs(line.StartPoint.Y - line.EndPoint.Y) < 0.01)
            {
                b = 1; a = 0; c = -arc.CenterPoint.Y;
            }
            else
            {
                double k, bx;
                k  = (line.EndPoint.Y - line.StartPoint.Y) / (line.EndPoint.X - line.StartPoint.X);
                bx = line.EndPoint.Y - k * line.EndPoint.X;
                a  = -k;
                c  = -(bx + k * arc.CenterPoint.X - arc.CenterPoint.Y);
                b  = 1;
            }
            r = Mathematics.FindDist(arc.StartPoint, arc.CenterPoint);
            double x0 = -a * c / (a * a + b * b), y0 = -b * c / (a * a + b * b);

            if (c * c > r * r * (a * a + b * b) + 0.01)
            {
                return(false);
            }
            else if (Math.Abs(c * c - r * r * (a * a + b * b)) < 0.01)
            {
                MyPoint xPoint = new MyPoint(x0, y0, MyPoint.PointType.IsGeometryPoint);
                return(pointFitsArc(xPoint, arc, checkType.doublePrecision) && Mathematics.FindDist(xPoint, line.EndPoint) > 0.01 && Mathematics.pointOnLine(xPoint, line));
            }
            else
            {
                double d = r * r - c * c / (a * a + b * b);
                double mult = Math.Sqrt(d / (a * a + b * b));
                double ax, ay, bx, by;
                ax = arc.CenterPoint.X + x0 + b * mult;
                bx = arc.CenterPoint.X + x0 - b * mult;
                ay = arc.CenterPoint.Y + y0 - a * mult;
                by = arc.CenterPoint.Y + y0 + a * mult;
                MyPoint xPoint1 = new MyPoint(ax, ay, MyPoint.PointType.IsGeometryPoint);
                MyPoint xPoint2 = new MyPoint(bx, by, MyPoint.PointType.IsGeometryPoint);
                return((pointFitsArc(xPoint1, arc, checkType.doublePrecision) && Mathematics.FindDist(xPoint1, line.EndPoint) > 0.01 && Mathematics.pointOnLine(xPoint1, line)) ||
                       (pointFitsArc(xPoint2, arc, checkType.doublePrecision) && Mathematics.FindDist(xPoint2, line.EndPoint) > 0.01 && Mathematics.pointOnLine(xPoint2, line)));
            }
        }
Exemple #6
0
        private List <MyNode> findNodesAtStraightLine(List <MyNode> nodes, MyStraightLine sline)
        {
            List <MyNode> result = new List <MyNode>();

            foreach (MyNode node in nodes)
            {
                if (Mathematics.pointOnLine(node.X, node.Y, sline))
                {
                    if (result.IndexOf(node) == -1)
                    {
                        result.Add(node);
                    }
                }
            }
            return(result);
        }
        public void CreateStraightLine(int number, MyPoint p1, MyPoint p2)
        {
            if (p1 == p2)
            {
                this.errorSamePoints.Visible = true;
                return;
            }
            MyStraightLine newLine = new MyStraightLine(number, p1, p2);

            this.parent.currentFullModel.geometryModel.StraightLines.Add(newLine);

            this.parent.currentFullModel.geometryModel.NumOfLines++;

            this.number.Text     = (parent.currentFullModel.geometryModel.NumOfLines + 1).ToString();
            this.startPoint.Text = "";
            this.endPoint.Text   = "";
            this.startPoint.Select();
        }
        private bool LinesCrossing(MyStraightLine l1, MyStraightLine l2)
        {
            double k1 = 0, b1 = 0;
            double k2 = 0, b2 = 0;
            double commonX, commonY;

            if (Math.Abs(l1.EndPoint.X - l1.StartPoint.X) < 0.01)
            {
                if (Math.Abs(l2.EndPoint.X - l2.StartPoint.X) < 0.01)
                {
                    // параллельные прямые все ещё не пересекаются
                    return(false);
                }
                else
                {
                    k2      = (double)(l2.EndPoint.Y - l2.StartPoint.Y) / (l2.EndPoint.X - l2.StartPoint.X);
                    b2      = (double)(l2.EndPoint.Y - k2 * l2.EndPoint.X);
                    commonX = l1.StartPoint.X;
                    commonY = commonX * k2 + b2;
                }
            }
            else
            {
                if (Math.Abs(l2.EndPoint.X - l2.StartPoint.X) < 0.01)
                {
                    k1      = (l1.EndPoint.Y - l1.StartPoint.Y) / (l1.EndPoint.X - l1.StartPoint.X);
                    b1      = (l1.EndPoint.Y - k1 * l1.EndPoint.X);
                    commonX = l2.EndPoint.X;
                    commonY = commonX * k1 + b1;
                }
                else
                {
                    k1      = (double)(l1.EndPoint.Y - l1.StartPoint.Y) / (l1.EndPoint.X - l1.StartPoint.X);
                    k2      = (double)(l2.EndPoint.Y - l2.StartPoint.Y) / (l2.EndPoint.X - l2.StartPoint.X);
                    b2      = (double)(l2.EndPoint.Y - k2 * l2.EndPoint.X);
                    b1      = (double)(l1.EndPoint.Y - k1 * l1.EndPoint.X);
                    commonX = (b2 - b1) / (k1 - k2);
                    commonY = commonX * k2 + b2;
                }
            }
            MyPoint commonPoint = new MyPoint(commonX, commonY, MyPoint.PointType.IsGeometryPoint);

            return(Mathematics.pointOnLine(commonX, commonY, l1) && Mathematics.pointOnLine(commonX, commonY, l2) && Mathematics.FindDist(commonPoint, l1.EndPoint) > 0.01);
        }
        public static bool pointOnLine(MyPoint point, MyStraightLine sline)
        {
            double x = point.X, x1 = sline.StartPoint.X, x2 = sline.EndPoint.X;
            double y = point.Y, y1 = sline.StartPoint.Y, y2 = sline.EndPoint.Y;

            if (Math.Abs(y2 - y1) < 0.01 && x.MoreOrEqual(Math.Min(x1, x2)) && x.LessOrEqual(Math.Max(x1, x2)) && Math.Abs(y - y1) < 0.01)
            {
                return(true);
            }
            if (Math.Abs(x2 - x1) < 0.01 && y.MoreOrEqual(Math.Min(y1, y2)) && y.LessOrEqual(Math.Max(y1, y2)) && Math.Abs(x - x1) < 0.01)
            {
                return(true);
            }
            bool onLine = (Math.Abs((x - x1) * (y2 - y1) - (y - y1) * (x2 - x1)) < 0.1);

            onLine = (onLine && x.LessOrEqual(Math.Max(x1, x2)) &&
                      x.MoreOrEqual(Math.Min(x1, x2)) &&
                      y.LessOrEqual(Math.Max(y1, y2)) &&
                      y.MoreOrEqual(Math.Min(y1, y2)));
            return(onLine);
        }
        private void findNodesAtStraightLine(ref List <MyNode> forcedNodes, MyStraightLine sline, int currentModel)
        {
            foreach (MyNode node in this.parent.currentFullModel.FiniteElementModels[currentModel].Nodes)
            {
                // уравнение прямой, проходящей через две точки
                if (Math.Abs((node.X - sline.StartPoint.X) * (sline.StartPoint.Y - sline.EndPoint.Y) - (node.Y - sline.StartPoint.Y) * (sline.StartPoint.X - sline.EndPoint.X)) < 0.001)
                {
                    List <MyPoint> tempPoints = new List <MyPoint>();
                    tempPoints.Add(sline.StartPoint);
                    tempPoints.Add(sline.EndPoint);

                    double minX, maxX, minY, maxY;
                    minX = tempPoints[0].X;
                    maxX = tempPoints[0].X;
                    minY = tempPoints[0].Y;
                    maxY = tempPoints[0].Y;
                    foreach (MyPoint point in tempPoints)  // тут определяем мин и макс координаты точек
                    {
                        if (point.X < minX)
                        {
                            minX = point.X;
                        }
                        if (point.X > maxX)
                        {
                            maxX = point.X;
                        }
                        if (point.Y < minY)
                        {
                            minY = point.Y;
                        }
                        if (point.Y > maxY)
                        {
                            maxY = point.Y;
                        }
                    }

                    /*if (!(node.X < minX || node.Y < minY || node.X > maxX || node.Y > maxY)) // условие, гарантирующее, что точка лежит на отрезке, а не на прямой
                     * {
                     *  if (forcedNodes.IndexOf(node) == -1) forcedNodes.Add(node);
                     * }*/

                    if (Math.Abs(minX - maxX) < 0.001)         // если линия вертикальная
                    {
                        if (!(node.Y < minY || node.Y > maxY)) // условие, гарантирующее, что точка от клика мышки лежит на отрезке, а не на прямой
                        {
                            if (forcedNodes.IndexOf(node) == -1)
                            {
                                forcedNodes.Add(node);
                            }
                        }
                    }
                    if (Math.Abs(minY - maxY) < 0.001)         // если линия горизонтальная
                    {
                        if (!(node.X < minX || node.X > maxX)) // условие, гарантирующее, что точка от клика мышки лежит на отрезке, а не на прямой
                        {
                            if (forcedNodes.IndexOf(node) == -1)
                            {
                                forcedNodes.Add(node);
                            }
                        }
                    }
                    if (!(node.X < minX || node.Y < minY || node.X > maxX || node.Y > maxY)) // условие, гарантирующее, что точка от клика мышки лежит на отрезке, а не на прямой
                    {
                        if (forcedNodes.IndexOf(node) == -1)
                        {
                            forcedNodes.Add(node);
                        }
                    }
                }
            }
        }
        private void OK()
        {
            if (this.number.Text == "")
            {
                MessageBox.Show("Не введены номера линий!");
                return;
            }

            if (this.function.Enabled == true && this.function.Text == "")
            {
                MessageBox.Show("Не введена функция нагрузки!");
                return;
            }
            if (trytocalculateExpression() == false)
            {
                MessageBox.Show("Неверный формат функции нагрузки!");
                return;
            }
            int    x = 0;
            double x1;

            if (this.tb.Text == "")
            {
                x++;
            }
            else
            {
                if (double.TryParse(tb.Text, out x1))
                {
                    ProjectForm.toch = x1;
                }
                else
                {
                    MessageBox.Show("Неверный формат ввода точности нагрузки!");
                    return;
                }
            }
            this.parent.precision = this.parent.DefinePrecision();

            int currentModel = this.parent.GetCurrentModelIndex();

            string[] textlinesnumbers   = this.number.Text.Split(',');
            List <MyStraightLine> lines = new List <MyStraightLine>();
            List <MyArc>          arcs  = new List <MyArc>();

            foreach (string textlinenumber in textlinesnumbers)
            {
                MyStraightLine line = this.parent.currentFullModel.geometryModel.StraightLines.Find(
                    thisline => thisline.Id == Convert.ToInt32(textlinenumber));
                MyArc arc = this.parent.currentFullModel.geometryModel.Arcs.Find(
                    thisline => thisline.Id == Convert.ToInt32(textlinenumber));
                if (line == null && arc == null)
                {
                    //this.number.Clear();
                    this.parent.clearSelection();
                    MessageBox.Show("Неверно заданы линии!");
                    return;
                }
                else if (line != null && arc == null)
                {
                    lines.Add(line);
                }
                else if (line == null && arc != null)
                {
                    arcs.Add(arc);
                }
            }
            if (lines.Count != 0 && arcs.Count != 0)
            {
                //this.number.Clear();
                this.parent.clearSelection();
                MessageBox.Show("Неверно заданы линии!");
                return;
            }
            else if (lines.Count != 0)
            {
                List <MyPoint> points = new List <MyPoint>();
                if (checkLinesConnect(ref lines, ref points, currentModel) == false)
                {
                    //this.number.Clear();
                    this.parent.clearSelection();
                    MessageBox.Show("Неверно заданы линии!");
                    return;
                }
                LineType linesposition = checkLinesPosition(points);
                if (checkLinesOnLine(points, linesposition) == false)
                {
                    //this.number.Clear();
                    this.parent.clearSelection();
                    MessageBox.Show("Неверно заданы линии!");
                    return;
                }
                List <MyNode> nodes = new List <MyNode>();
                getNodesOnLine(lines, ref nodes, currentModel, linesposition);
                this.calculateForceAtNodes(nodes, linesposition, null, currentModel);
            }
            else if (arcs.Count != 0)
            {
                List <MyPoint> points = new List <MyPoint>();
                if (checkArcsConnect(ref arcs, ref points, currentModel) == false)
                {
                    //this.number.Clear();
                    this.parent.clearSelection();
                    MessageBox.Show("Неверно заданы линии!");
                    return;
                }
                LineType      linesposition = LineType.IsArc;
                List <MyNode> nodes         = new List <MyNode>();
                getNodesOnArc(arcs, ref nodes, currentModel, linesposition);
                this.number.Text = Convert.ToString(nodes.Count);
                this.calculateForceAtNodes(nodes, LineType.IsArc, arcs.ElementAt(0), currentModel);
            }
            parent.clearSelection();
            if (this.parent.currentFullModel.FiniteElementModels[currentModel].R.Count == 0)
            {
                for (int i = 0; i <= this.parent.currentFullModel.FiniteElementModels[currentModel].Nodes.Count * 2; i++)
                {
                    this.parent.currentFullModel.FiniteElementModels[currentModel].R.Add(0.0);
                }
            }
            int m = 1;

            foreach (MyNode node in this.parent.currentFullModel.FiniteElementModels[currentModel].Nodes)
            {
                this.parent.currentFullModel.FiniteElementModels[currentModel].R[2 * (m - 1) + 1] = node.ForceX;
                this.parent.currentFullModel.FiniteElementModels[currentModel].R[2 * (m - 1) + 2] = node.ForceY;
                m++;
            }

            this.parent.DrawForces(Color.Purple);
            this.parent.currentFullModel.FiniteElementModels[currentModel].NLD++;
            if (this.parent.showForces.Checked != true)
            {
                this.parent.showForces.Checked = true;
            }

            this.number.TextChanged -= new System.EventHandler(this.number_TextChanged);
            this.number.Text         = "";
            this.number.TextChanged += new System.EventHandler(this.number_TextChanged);
            this.number.Select();

            this.parent.currentFullModel.geometryModel.highlightStraightLines.Clear();
            this.parent.currentFullModel.geometryModel.highlightArcs.Clear();
            this.parent.ReDrawAll();
            this.parent.clearSelection();
        }
 public static bool pointOnLine(double x, double y, MyStraightLine sline)
 {
     return(pointOnLine(new MyPoint(x, y, MyPoint.PointType.IsGeometryPoint), sline));
 }
        private void constructionArea_MouseClick(object sender, MouseEventArgs e)
        {
            MyPoint clickPoint = visualizer.getClickPoint(e.X, e.Y);

            mouseAboveArea = true;
            if (this.mouseMoved)
            {
                this.mouseMoved = false;
                return; // смысл данного действа в том, что если область отображения перемещали мышкой, то ничего рисовать не нужно (перемещение происходит при одновременно нажатой левой клавише мыши и при ее движнии, и комп воспринимает это как событие MouseClick)
            }
            constructionArea.Focus();

            // создаем точку
            if (addPointControl != null && addPointControl.IsHandleCreated)
            {
                MyPoint newPoint = this.addPointControl.CreatePoint(Convert.ToInt32(this.addPointControl.number.Text), clickPoint.X, clickPoint.Y);
                this.TestOnLineCircleAndArc(ref newPoint); // проверяем, не попала ли точка на линию, окружность или дугу
            }

            // запоминаем выбранную точку, и если их две, то рисуем линию между ними
            if (addStraightLineControl != null && addStraightLineControl.IsHandleCreated)
            {
                MyPoint point = currentFullModel.geometryModel.Points.Find(p => Math.Abs(p.X - clickPoint.X) < visualizer.pointLocality && Math.Abs(p.Y - clickPoint.Y) < visualizer.pointLocality);
                if (point != null)
                {
                    if (e.Button == MouseButtons.Left)
                    {
                        this.currentFullModel.geometryModel.pairOfPoints.Add(point);
                        if (this.currentFullModel.geometryModel.pairOfPoints.Count == 1)
                        {
                            this.addStraightLineControl.startPoint.Text = point.Id.ToString();
                        }
                        if (this.currentFullModel.geometryModel.pairOfPoints.Count == 2)
                        {
                            this.addStraightLineControl.endPoint.Text = point.Id.ToString();
                            this.addStraightLineControl.CreateStraightLine(Convert.ToInt32(this.addStraightLineControl.number.Text), this.currentFullModel.geometryModel.pairOfPoints[0], this.currentFullModel.geometryModel.pairOfPoints[1]);
                            clearSelection();
                        }
                    }
                    else if (e.Button == MouseButtons.Right)
                    {
                        if (currentFullModel.geometryModel.pairOfPoints.Count > 0)
                        {
                            addStraightLineControl.startPoint.Text = "";
                            clearSelection();
                        }
                    }
                    ReDrawAll();
                }
            }

            // запоминаем выбранную точку, и если их три то рисуем дугу - режим создания дуги
            if (addArcsControl != null && addArcsControl.IsHandleCreated)
            {
                MyPoint point = currentFullModel.geometryModel.Points.Find(p => Math.Abs(p.X - clickPoint.X) < visualizer.pointLocality && Math.Abs(p.Y - clickPoint.Y) < visualizer.pointLocality);
                if (point != null)
                {
                    if (e.Button == MouseButtons.Left)
                    {
                        this.currentFullModel.geometryModel.tripleOfPoints.Add(point);
                        if (this.currentFullModel.geometryModel.tripleOfPoints.Count == 1)
                        {
                            this.addArcsControl.start2Point.Text = point.Id.ToString();
                        }
                        if (this.currentFullModel.geometryModel.tripleOfPoints.Count == 2)
                        {
                            this.addArcsControl.end2Point.Text = point.Id.ToString();
                        }
                        if (this.currentFullModel.geometryModel.tripleOfPoints.Count == 3)
                        {
                            this.addArcsControl.center2Point.Text = point.Id.ToString();
                        }
                        if (this.currentFullModel.geometryModel.tripleOfPoints.Count == 3)
                        {
                            this.addArcsControl.CreateArc(Convert.ToInt32(this.addArcsControl.number.Text), this.addArcsControl.сlockwise.Checked, currentFullModel.geometryModel.tripleOfPoints[0], currentFullModel.geometryModel.tripleOfPoints[1], currentFullModel.geometryModel.tripleOfPoints[2]);
                            this.currentFullModel.geometryModel.tripleOfPoints.Clear();
                        }
                    }
                    else if (e.Button == MouseButtons.Right)
                    {
                        if (currentFullModel.geometryModel.tripleOfPoints.Count == 1)
                        {
                            currentFullModel.geometryModel.tripleOfPoints.Remove(point);
                            addArcsControl.start2Point.Text = "";
                        }
                        else
                        {
                            currentFullModel.geometryModel.tripleOfPoints.Remove(point);
                            if (addArcsControl.start2Point.Text == point.Id.ToString())
                            {
                                addArcsControl.start2Point.Text = addArcsControl.end2Point.Text;
                                addArcsControl.end2Point.Text   = "";
                            }
                            else
                            {
                                addArcsControl.end2Point.Text = "";
                            }
                        }
                    }
                }
            }

            // выделяем или снимаем выделение с точки
            if (this.editPointsControl != null && this.editPointsControl.IsHandleCreated)
            {
                if (currentFullModel.geometryModel.Points.Find(p => Math.Abs(p.X - clickPoint.X) < visualizer.pointLocality &&
                                                               Math.Abs(p.Y - clickPoint.Y) < visualizer.pointLocality) == null)
                {
                    currentFullModel.geometryModel.editedPoint = null;
                    editPointsControl.number.Text = editPointsControl.x.Text = editPointsControl.y.Text = "";
                    ReDrawAll();
                }

                MyPoint point = currentFullModel.geometryModel.Points.Find(p => Math.Abs(p.X - clickPoint.X) < visualizer.pointLocality &&
                                                                           Math.Abs(p.Y - clickPoint.Y) < visualizer.pointLocality);
                if (point != null)
                {
                    if (e.Button == MouseButtons.Right) // если нажали правую кнопку мыши, то снять выделение с точки
                    {
                        if (this.currentFullModel.geometryModel.editedPoint != null && this.currentFullModel.geometryModel.editedPoint == point)
                        {
                            this.currentFullModel.geometryModel.editedPoint = null;

                            // сбрасываем id, x и y
                            this.editPointsControl.number.Text = "";
                            this.editPointsControl.x.Text      = "";
                            this.editPointsControl.y.Text      = "";
                            ReDrawAll();
                        }
                    }

                    if (e.Button == MouseButtons.Left) // если нажали левую кнопку мыши, то выделить точку
                    {
                        this.currentFullModel.geometryModel.editedPoint = point;

                        // отображаем id, x и y точки
                        this.editPointsControl.number.Text = this.currentFullModel.geometryModel.editedPoint.Id.ToString();
                        this.editPointsControl.x.Text      = Mathematics.floor(this.currentFullModel.geometryModel.editedPoint.X, Mathematics.accuracy_medium).ToString();
                        this.editPointsControl.y.Text      = Mathematics.floor(this.currentFullModel.geometryModel.editedPoint.Y, Mathematics.accuracy_medium).ToString();
                        ReDrawAll();
                    }
                }
            }

            if (this.editNodesControl != null && editNodesControl.IsHandleCreated)
            {
                foreach (MyArea area in this.currentFullModel.geometryModel.Areas)
                {
                    MyPoint node = area.Nodes.Find(p => Math.Abs(p.X - clickPoint.X) < visualizer.pointLocality &&
                                                   Math.Abs(p.Y - clickPoint.Y) < visualizer.pointLocality);
                    if (node != null)
                    {
                        if (e.Button == MouseButtons.Right) // если нажали правую кнопку мыши, то снять выделение с точки
                        {
                            if (this.currentFullModel.geometryModel.editedNode != null && this.currentFullModel.geometryModel.editedNode == node)
                            {
                                this.currentFullModel.geometryModel.editedNode = null;

                                // сбрасываем id, x и y
                                this.editNodesControl.number.Text = "";
                                this.editNodesControl.x.Text      = "";
                                this.editNodesControl.y.Text      = "";
                                ReDrawAll();
                            }
                        }

                        if (e.Button == MouseButtons.Left) // если нажали левую кнопку мыши, то выделить точку
                        {
                            this.currentFullModel.geometryModel.editedNode = node;

                            // отображаем id, x и y точки
                            this.editNodesControl.number.Text = this.currentFullModel.geometryModel.editedNode.Id.ToString();
                            this.editNodesControl.x.Text      = Mathematics.floor(this.currentFullModel.geometryModel.editedNode.X, Mathematics.accuracy_medium).ToString();
                            this.editNodesControl.y.Text      = Mathematics.floor(this.currentFullModel.geometryModel.editedNode.Y, Mathematics.accuracy_medium).ToString();
                            ReDrawAll();
                        }
                        break;
                    }
                }
            }

            //  удаляем точку
            if (this.deletePointsControl != null && this.deletePointsControl.IsHandleCreated)
            {
                MyPoint point = currentFullModel.geometryModel.Points.Find(p => Math.Abs(p.X - clickPoint.X) < visualizer.pointLocality &&
                                                                           Math.Abs(p.Y - clickPoint.Y) < visualizer.pointLocality);
                if (point != null)
                {
                    this.deletePointsControl.DeletePoint(point.Id);
                }
            }

            //  удаляем линию
            if (this.deleteLinesControl != null && this.deleteLinesControl.IsHandleCreated)
            {
                foreach (MyStraightLine sline in this.currentFullModel.geometryModel.StraightLines)
                {
                    if (pointNearLine(clickPoint, sline))
                    {
                        this.currentFullModel.geometryModel.StraightLines.Remove(sline);
                        ReDrawAll();
                        break;
                    }
                }

                foreach (MyArc arc in this.currentFullModel.geometryModel.Arcs)
                {
                    double radius = Mathematics.FindDist(arc.CenterPoint, arc.StartPoint);

                    if (pointFitsArc(clickPoint, arc, checkType.clickPrecision))
                    {
                        this.currentFullModel.geometryModel.Arcs.Remove(arc);
                        this.ReDrawAll();
                        break;
                    }
                }
            }

            //  закрепляем линию
            if (this.addBoundsControl != null && this.addBoundsControl.IsHandleCreated)
            {
                if (!this.addBoundsControl.xBound.Checked && !this.addBoundsControl.yBound.Checked)
                {
                    this.addBoundsControl.errorBoundType.Visible = true; return;
                }
                this.addBoundsControl.errorBoundType.Visible = false;

                foreach (MyStraightLine sline in this.currentFullModel.geometryModel.StraightLines)
                {
                    if (pointNearLine(clickPoint, sline))
                    {
                        this.addBoundsControl.BoundLine(sline);
                        ReDrawAll();
                        break;
                    }
                }

                foreach (MyArc arc in this.currentFullModel.geometryModel.Arcs)
                {
                    double radius = Mathematics.FindDist(arc.CenterPoint, arc.StartPoint);

                    if (pointFitsArc(clickPoint, arc, checkType.clickPrecision))
                    {
                        this.addBoundsControl.BoundLine(arc);
                        ReDrawAll();
                        break;
                    }
                }
            }
            // удаляем закрепление линии
            if (this.deleteBoundsControl != null && this.deleteBoundsControl.IsHandleCreated)
            {
                foreach (MyStraightLine sline in this.currentFullModel.geometryModel.StraightLines)
                {
                    if (pointNearLine(clickPoint, sline))
                    {
                        this.deleteBoundsControl.UnboundLine(sline);
                        ReDrawAll();
                        break;
                    }
                }

                foreach (MyArc arc in this.currentFullModel.geometryModel.Arcs)
                {
                    double radius = Mathematics.FindDist(arc.CenterPoint, arc.StartPoint);

                    if (pointFitsArc(clickPoint, arc, checkType.clickPrecision))
                    {
                        this.deleteBoundsControl.UnboundLine(arc);
                        ReDrawAll();
                        break;
                    }
                }
            }

            // добавляем плотность для Делоне
            if (delauneyTriangulateForm != null && this.delauneyTriangulateForm.IsHandleCreated)
            {
                delauneyTriangulateForm.AddDensity(Mathematics.floor(mouseXcord, 0.01), Mathematics.floor(mouseYcord, 0.01));
            }


            if (activeForm != null)
            {
                MyLine         line  = null;
                bool           add   = false;
                MyStraightLine sline = currentFullModel.geometryModel.StraightLines.Find(l => pointNearLine(clickPoint, l));
                if (sline != null)
                {
                    line = sline;
                    if (currentFullModel.geometryModel.highlightStraightLines.IndexOf(sline) < 0)
                    {
                        add = true;
                        currentFullModel.geometryModel.highlightStraightLines.Add(sline);
                    }
                    else
                    {
                        add = false;
                        currentFullModel.geometryModel.highlightStraightLines.Remove(sline);
                    }
                    ReDrawAll();
                }
                else
                {
                    MyArc arc = currentFullModel.geometryModel.Arcs.Find(a => pointFitsArc(clickPoint, a, checkType.clickPrecision));
                    if (arc != null)
                    {
                        line = arc;
                        if (currentFullModel.geometryModel.highlightArcs.IndexOf(arc) < 0)
                        {
                            add = true;
                            currentFullModel.geometryModel.highlightArcs.Add(arc);
                        }
                        else
                        {
                            add = false;
                            currentFullModel.geometryModel.highlightArcs.Remove(arc);
                        }
                        ReDrawAll();
                    }
                }
                if (line != null)
                {
                    TextBox targetTxt;
                    if (activeForm is StdOptimisation)
                    {
                        targetTxt = StdOptForm.notMoveLines;
                    }
                    else if (activeForm is RuppertForm)
                    {
                        targetTxt = ruppertForm.notMoveLines;
                    }
                    else if (activeForm is Regularization)
                    {
                        targetTxt = RegulizeForm.notMoveLines;
                    }
                    else
                    {
                        targetTxt = forcesForm.number;
                    }
                    if (add)
                    {
                        if (targetTxt.Text == "")
                        {
                            targetTxt.Text = line.Id.ToString();
                        }
                        else
                        {
                            targetTxt.Text += "," + line.Id.ToString();
                        }
                    }
                    else
                    {
                        string[] fixNumbers = targetTxt.Text.Split(',');
                        if (fixNumbers.Length == 1)
                        {
                            targetTxt.Text = "";
                        }
                        else
                        {
                            if (fixNumbers.Last() == line.Id.ToString())
                            {
                                targetTxt.Text = targetTxt.Text.Replace("," + line.Id.ToString(), "");
                            }
                            else
                            {
                                targetTxt.Text = targetTxt.Text.Replace(line.Id.ToString() + ",", "");
                            }
                        }
                    }
                    ReDrawAll();
                }
            }

            // создаем окружность
            if (addCirclesControl != null && addCirclesControl.IsHandleCreated)
            {
                if (this.creatingCircle) // если мы рисовали окружность, а потом кликнули мышкой, то значит надо завершить рисование
                {
                    this.addCirclesControl.CreateCircle(this.currentFullModel.geometryModel.NumOfCircles + 1, this.currentFullModel.geometryModel.tempCircle.CenterPoint, this.currentFullModel.geometryModel.tempCircle.Radius);
                    this.creatingCircle = false;
                    this.currentFullModel.geometryModel.centerOfCircle = null;

                    this.addCirclesControl.number.Text             = "";
                    this.addCirclesControl.centerPoint.Text        = "";
                    this.addCirclesControl.radius.Text             = "";
                    this.currentFullModel.geometryModel.tempCircle = null;
                    if (hoveredPoint != null)
                    {
                        MyCircle addedCircle = currentFullModel.geometryModel.Circles.Find(c => c.Id == currentFullModel.geometryModel.NumOfCircles);
                        splitCircleByPoint(addedCircle, hoveredPoint);
                    }
                }

                else
                {
                    MyPoint point = currentFullModel.geometryModel.Points.Find(p => Math.Abs(p.X - clickPoint.X) < visualizer.pointLocality &&
                                                                               Math.Abs(p.Y - clickPoint.Y) < visualizer.pointLocality);
                    if (point != null)
                    {
                        this.currentFullModel.geometryModel.centerOfCircle = point;
                        if (this.addCirclesControl != null)
                        {
                            this.addCirclesControl.number.Text      = (this.currentFullModel.geometryModel.NumOfCircles + 1).ToString();
                            this.addCirclesControl.centerPoint.Text = point.Id.ToString();
                        }
                        this.creatingCircle = true;
                    }
                }
                ReDrawAll();
            }

            // удаляем окружнсть
            if (this.deleteCirclesControl != null && this.deleteCirclesControl.IsHandleCreated)
            {
                foreach (MyCircle circle in this.currentFullModel.geometryModel.Circles)
                {
                    // уравнение окружности
                    if (Math.Abs(Mathematics.FindDist(clickPoint, circle.CenterPoint) - circle.Radius) < visualizer.pointLocality)
                    {
                        // удаляем окружность
                        this.deleteCirclesControl.DeleteCircle(circle.Id);
                        break;
                    }
                }
            }

            if (this.deleteAreasControl != null && this.deleteAreasControl.IsHandleCreated)
            {
                foreach (MyArea area in currentFullModel.geometryModel.Areas)
                {
                    if (Mathematics.ContainsPoint(area.Nodes.ConvertAll(n => (MyNode)n).ToArray(), clickPoint))
                    {
                        deleteAreasControl.number.Text = area.Id.ToString();
                        deleteAreasControl.OK();
                        ReDrawAll();
                        return;
                    }
                }
            }
            // создаем зону
            if (this.addAreasControl != null && this.addAreasControl.IsHandleCreated)
            {
                if (addAreasControl.autoSearch.Checked == true)
                {
                    List <MyStraightLine> checkLines = new List <MyStraightLine>();
                    foreach (MyPoint point in currentFullModel.geometryModel.Points)
                    {
                        checkLines.Add(new MyStraightLine(0, clickPoint, point));
                    }

                    MyArc          suspiciousArc = null;
                    List <MyPoint> zonePoints    = new List <MyPoint>();
                    foreach (MyStraightLine line in checkLines)
                    {
                        List <MyArc> sarcs;
                        if (currentFullModel.geometryModel.StraightLines.Find(l => LinesCrossing(line, l)) == null)
                        {
                            sarcs = currentFullModel.geometryModel.Arcs.FindAll(a => LineCrossingArc(line, a));
                            if (sarcs.Count == 0)
                            {
                                zonePoints.Add(line.EndPoint);
                            }
                            else
                            {
                                suspiciousArc = sarcs[0];
                            }
                        }
                    }
                    if (zonePoints.Count != 4)
                    {
                        if (suspiciousArc != null)
                        {
                            if (zonePoints.IndexOf(suspiciousArc.EndPoint) == -1)
                            {
                                zonePoints.Add(suspiciousArc.EndPoint);
                            }
                            if (zonePoints.IndexOf(suspiciousArc.StartPoint) == -1)
                            {
                                zonePoints.Add(suspiciousArc.StartPoint);
                            }
                        }
                    }
                    List <MyStraightLine> lines = currentFullModel.geometryModel.StraightLines.FindAll(l => zonePoints.IndexOf(l.StartPoint) != -1 && zonePoints.IndexOf(l.EndPoint) != -1);
                    List <MyArc>          arcs  = currentFullModel.geometryModel.Arcs.FindAll(a => zonePoints.IndexOf(a.StartPoint) != -1 && zonePoints.IndexOf(a.EndPoint) != -1);
                    List <string>         ids   = new List <string>();
                    foreach (MyStraightLine line in lines)
                    {
                        ids.Add(line.Id.ToString());
                    }

                    foreach (MyArc arc in arcs)
                    {
                        ids.Add(arc.Id.ToString());
                    }

                    if (ids.Count < 4)
                    {
                        MessageBox.Show("Ошибка поиска зоны!");
                        return;
                    }
                    addAreasControl.line1.Text = ids[0];
                    addAreasControl.line2.Text = ids[1];
                    addAreasControl.line3.Text = ids[2];
                    addAreasControl.line4.Text = ids[3];
                    if (addAreasControl.OK())
                    {
                        ReDrawAll();
                    }
                }
                else
                {
                    foreach (MyStraightLine sline in this.currentFullModel.geometryModel.StraightLines)
                    {
                        // уравнение прямой, проходящей через две точки
                        if (pointNearLine(clickPoint, sline))
                        {
                            if (this.currentFullModel.geometryModel.numOfSelectedLines == 0)
                            {
                                this.addAreasControl.line1.Text = sline.Id.ToString(); currentFullModel.geometryModel.numOfSelectedLines++; this.currentFullModel.geometryModel.highlightStraightLines.Add(sline); ReDrawAll(); break;
                            }
                            if (this.currentFullModel.geometryModel.numOfSelectedLines == 1)
                            {
                                this.addAreasControl.line2.Text = sline.Id.ToString(); currentFullModel.geometryModel.numOfSelectedLines++; this.currentFullModel.geometryModel.highlightStraightLines.Add(sline); ReDrawAll(); break;
                            }
                            if (this.currentFullModel.geometryModel.numOfSelectedLines == 2)
                            {
                                this.addAreasControl.line3.Text = sline.Id.ToString(); currentFullModel.geometryModel.numOfSelectedLines++; this.currentFullModel.geometryModel.highlightStraightLines.Add(sline); ReDrawAll(); break;
                            }
                            if (this.currentFullModel.geometryModel.numOfSelectedLines == 3)
                            {
                                this.addAreasControl.line4.Text = sline.Id.ToString(); currentFullModel.geometryModel.numOfSelectedLines++; this.currentFullModel.geometryModel.highlightStraightLines.Add(sline); ReDrawAll();
                            }

                            if (this.currentFullModel.geometryModel.numOfSelectedLines == 4)
                            {
                                this.addAreasControl.OK(); // вызываем функцию, как будто была нажата кнопка ОК. эта функция обрабатывает значения линий в текстовых полях контрола.
                                ReDrawAll();
                            }
                            break;
                        }
                    }

                    foreach (MyArc arc in this.currentFullModel.geometryModel.Arcs)
                    {
                        double radius = Mathematics.FindDist(arc.CenterPoint, arc.StartPoint);

                        if (pointFitsArc(clickPoint, arc, checkType.clickPrecision))
                        {
                            if (this.currentFullModel.geometryModel.numOfSelectedLines == 0)
                            {
                                this.addAreasControl.line1.Text = arc.Id.ToString(); currentFullModel.geometryModel.numOfSelectedLines++; this.currentFullModel.geometryModel.highlightArcs.Add(arc); ReDrawAll(); break;
                            }
                            if (this.currentFullModel.geometryModel.numOfSelectedLines == 1)
                            {
                                this.addAreasControl.line2.Text = arc.Id.ToString(); currentFullModel.geometryModel.numOfSelectedLines++; this.currentFullModel.geometryModel.highlightArcs.Add(arc); ReDrawAll(); break;
                            }
                            if (this.currentFullModel.geometryModel.numOfSelectedLines == 2)
                            {
                                this.addAreasControl.line3.Text = arc.Id.ToString(); currentFullModel.geometryModel.numOfSelectedLines++; this.currentFullModel.geometryModel.highlightArcs.Add(arc); ReDrawAll(); break;
                            }
                            if (this.currentFullModel.geometryModel.numOfSelectedLines == 3)
                            {
                                this.addAreasControl.line4.Text = arc.Id.ToString(); currentFullModel.geometryModel.numOfSelectedLines++; this.currentFullModel.geometryModel.highlightArcs.Add(arc); ReDrawAll();
                            }

                            if (this.currentFullModel.geometryModel.numOfSelectedLines == 4)
                            {
                                this.addAreasControl.OK(); // вызываем функцию, как будто была нажата кнопка ОК. эта функция обрабатывает значения линий в текстовых полях контрола.
                                ReDrawAll();
                            }
                            break;
                        }
                    }
                }
            }
        }
        public void ReadSFMFile(string FileName)
        {
            int i;

            // откроем бинарный файл *.sfm
            FileStream F1 = null;

            try
            {
                F1 = new FileStream(FileName, FileMode.Open, FileAccess.Read);
            }
            catch (IOException e)
            {
                MessageBox.Show(e.Message);
                return;
            }
            BinaryReader reader1 = new BinaryReader(F1);

            byte[] array1 = reader1.ReadBytes(10); // читаем префикс
            string prefix = "";

            for (i = 0; i < 10; i++)
            {
                prefix += Convert.ToChar(array1[i]).ToString();
            }
            if (prefix != "Sigma Form")
            {
                MessageBox.Show("Данный файл не является файлом формы!");
                return;
            }

            int version = reader1.ReadInt32();                 // читаем версию

            int bytes = reader1.ReadInt16();                   // читаем количество байт отведенных под хранение числа с плавающей точкой - 2 байта

            byte taskType = reader1.ReadByte();                // тип задачи - 1 байт

            this.variant.Text = reader1.ReadByte().ToString(); // вариант - 1 байт

            int NRC = reader1.ReadInt16();                     // NRC - 2 байта (не имеет никакого значения - параметр все равно задает пользователь при создании сетки)

            // читаем магические 4 байта - не понятно что это... в спецификации нет, в исходниках тоже, откуда взялись - не понятно. если не прочитать, то не заработает...
            int magic = reader1.ReadInt32();

            //24 байта до DB

            double DB = reader1.ReadDouble();        // ширина - 8 байт (не имеет никакого значения - определяется автоматически, если надо)
            double DH = reader1.ReadDouble();        // выстока - 8 байт (не имеет никакого значения - определяется автоматически, если надо)

            double radius = reader1.ReadDouble();    // радиус отверстия - 8 байт (не имеет никакого значения - определяется автоматически, если надо)

            double thickness = reader1.ReadDouble(); // толщина - 8 байт. Такие параметры, как толщина и свойства материала мы не можем применить ко всей пластине из-за устаревшей версии sfm файла, поэтому мы просто сохраним их в библиотеку материалов

            double RsumX = reader1.ReadDouble();
            double RsumY = reader1.ReadDouble();

            Int32 NLD = reader1.ReadInt32();                    // число случаев нагружения - 4 байта

            Int32 NDF = reader1.ReadInt32();                    // число степеней свободы - 4 байта

            Int32 NCN = reader1.ReadInt32();                    // число узлов в элементе - 4 байта

            Int32 NMAT = reader1.ReadInt32();                   // число материалов - 4 байта

            double E = reader1.ReadDouble();                    // свойства материалов - модуль упругости
            double p = reader1.ReadDouble();                    // коэффициент Пуассона
            double T = reader1.ReadDouble();                    // допускаемое напряжение
            double L = reader1.ReadDouble();                    //

            Int32 numOfAreas = reader1.ReadInt32();             // число зон - 4 байта

            Int32 numOfPoints = reader1.ReadInt32();            // число узлов зон - 4 байта

            List <MyPoint> allAreaNodes = new List <MyPoint>(); // список всех узлов, но они тут никак не объединены в зоны

            //reader1.ReadInt32();
            for (i = 0; i < numOfPoints; i++)
            {
                int id = reader1.ReadInt16();
                reader1.ReadBytes(6); // магические 6 байт. таже фигня что и выше.. и теперь я кажется знаю что это за ересь. в делфях тип record занимет больше памяти чем сумма памяти под ее члены. и для этого случая аж на 6 байт больше. и располагаются они между integer и real......

                double x = reader1.ReadDouble();
                double y = reader1.ReadDouble();
                allAreaNodes.Add(new MyPoint(id, x, y, MyPoint.PointType.IsAreaNode));
            }
            allAreaNodes.Sort((n1, n2) => n1.Id.CompareTo(n2.Id));

            AddAreasControl control = new AddAreasControl(this);

            for (i = 0; i < numOfAreas; i++)
            {
                List <MyPoint> areaNodes = new List <MyPoint>();  // список из 8 узлов, составляющих зону.
                for (int j = 0; j < 8; j++)
                {
                    int     nodeId = reader1.ReadInt16(); // номер узла
                    MyPoint node   = allAreaNodes.Find(n => n.Id == nodeId);
                    if (node != null)
                    {
                        areaNodes.Add(node);
                    }
                }

                // после того, как мы знаем из каких узлов состоит зона, то мы можем создать точки, линии и дуги - т.е. создать гемоетрию по зоне.



                // создаем сначала точки
                List <MyPoint> points = new List <MyPoint>(); // угловые точки зоны
                for (int j = 0; j < 8; j += 2)
                {
                    MyPoint existing = currentFullModel.geometryModel.Points.Find(pt => Mathematics.sameNode(pt, areaNodes[j]));
                    if (existing != null)
                    {
                        points.Add(existing);
                    }

                    else
                    {
                        MyPoint newPoint = new MyPoint(this.currentFullModel.geometryModel.NumOfPoints + 1, areaNodes[j].X, areaNodes[j].Y, MyPoint.PointType.IsGeometryPoint);
                        this.currentFullModel.geometryModel.Points.Add(newPoint);
                        points.Add(newPoint);
                        //this.DrawPoint(newPoint, System.Drawing.Color.Blue);
                        this.currentFullModel.geometryModel.NumOfPoints++;
                    }
                }

                List <MyStraightLine> slines = new List <MyStraightLine>();
                List <MyArc>          arcs   = new List <MyArc>();
                List <MyLine>         lines  = new List <MyLine>();

                // цикл по четырем с сторонам зоны - каждый раз берем три точки с одной стороны - 1,2,3; 3,4,5; 5,6,7 и 7,8,1
                for (int j = 0; j <= 6; j = j + 2)
                {
                    MyPoint p1 = areaNodes[j], p2 = areaNodes[j + 1], p3 = areaNodes[j == 6 ? 0 : j + 2];

                    double xc, yc;

                    double k1 = Math.Cos(Math.Atan2(p2.Y - p1.Y, p2.X - p1.X));
                    double k2 = Math.Cos(Math.Atan2(p3.Y - p2.Y, p3.X - p2.X));
                    if (Math.Abs(k1 - k2) < 0.01) // если коэффициенты наклона совпадают, значит точки лежат на прямой (условие непрерывности выполняется, т.к. известно что все точки принадлежат одной стороне зоны)
                    {
                        // создаем прямую линию
                        MyPoint start = null;
                        MyPoint end   = null;

                        foreach (MyPoint point in this.currentFullModel.geometryModel.Points)
                        {
                            if (Mathematics.sameNode(point, p1))
                            {
                                start = point;
                            }
                            else if (Mathematics.sameNode(point, p3))
                            {
                                end = point;
                            }
                        }

                        MyStraightLine line = currentFullModel.geometryModel.StraightLines.Find(
                            sline => (sline.StartPoint == start && sline.EndPoint == end) || (sline.StartPoint == end && sline.EndPoint == start)
                            );

                        if (line != null)
                        {
                            slines.Add(line);
                            lines.Add(line);
                        }

                        else
                        {
                            MyStraightLine newLine = new MyStraightLine(this.currentFullModel.geometryModel.NumOfLines + 1, start, end);
                            this.currentFullModel.geometryModel.StraightLines.Add(newLine);
                            slines.Add(newLine);
                            lines.Add(newLine);
                            this.currentFullModel.geometryModel.NumOfLines++;
                        }
                    }
                    else
                    {
                        double x1 = p1.X, x2 = p2.X, x3 = p3.X;
                        double y1 = p1.Y, y2 = p2.Y, y3 = p3.Y;
                        // затем проверяем каждую сторону зоны - может ли она быть дугой или нет. для этого пытаемся расчитать центр окружности по трем точкам, и если получается, то создаем дугу.
                        if (Math.Abs(x1 * y2 + y1 * x3 - y2 * x3 - x1 * y3 - x2 * y1 + x2 * y3) > 0.1) // если знаменатель не равен нулю
                        {
                            // адские формулы центра окржуности - расчитал Великий Maple
                            // yc = -1.0 / 2.0 * (-x2 * x2 * x1 - y2 * y2 * x1 - x2 * x3 * x3 - x1 * x1 * x3 - y1 * y1 * x3 + x1 * x3 * x3 + x2 * x2 * x3 + y2 * y2 * x3 + x2 * x1 * x1 + x2 * y1 * y1 + x1 * y3 * y3 - x2 * y3 * y3) / (x1 * y2 + y1 * x3 - y2 * x3 - x1 * y3 - x2 * y1 + x2 * y3);
                            // xc = 1.0 / 2.0 * (-x1 * x1 * y3 + x1 * x1 * y2 - x3 * x3 * y2 + y1 * y1 * y2 + y1 * y3 * y3 + y3 * x2 * x2 - y1 * x2 * x2 - y1 * y2 * y2 + y1 * x3 * x3 - y3 * y3 * y2 - y1 * y1 * y3 + y3 * y2 * y2) / (x1 * y2 + y1 * x3 - y2 * x3 - x1 * y3 - x2 * y1 + x2 * y3);

                            // есть формулы попроще:

                            double R1Sqr = x1 * x1 + y1 * y1;
                            double R2Sqr = x2 * x2 + y2 * y2;
                            double R3Sqr = x3 * x3 + y3 * y3;
                            xc = ((R3Sqr - R1Sqr) * (y2 - y1) - (R2Sqr - R1Sqr) * (y3 - y1)) / ((x3 - x1) * (y2 - y1) - (x2 - x1) * (y3 - y1)) / 2.0;
                            yc = ((R2Sqr - R1Sqr) * (x3 - x1) - (R3Sqr - R1Sqr) * (x2 - x1)) / ((x3 - x1) * (y2 - y1) - (x2 - x1) * (y3 - y1)) / 2.0;


                            // ищем в точках точку с такими координатами, если не найдем, то созадим новую
                            MyPoint definedCenter = new MyPoint(xc, yc);

                            MyPoint centerPoint = currentFullModel.geometryModel.Points.Find(pt => Mathematics.sameNode(pt, definedCenter));
                            // если нет, тогда создаем новую точку - центр дуги
                            if (centerPoint == null)
                            {
                                centerPoint = new MyPoint(this.currentFullModel.geometryModel.NumOfPoints + 1, xc, yc, MyPoint.PointType.IsGeometryPoint);
                                this.currentFullModel.geometryModel.Points.Add(centerPoint);
                                //this.DrawPoint(centerPoint, System.Drawing.Color.Blue);
                                this.currentFullModel.geometryModel.NumOfPoints++;
                            }

                            // и проводим дугу...
                            MyPoint start = null;
                            //MyPoint p2 = null;
                            MyPoint end = null;
                            foreach (MyPoint point in this.currentFullModel.geometryModel.Points)
                            {
                                if (Mathematics.sameNode(point, p1))
                                {
                                    start = point;
                                }
                                else if (Mathematics.sameNode(point, p3))
                                {
                                    end = point;
                                }
                            }

                            bool lineExists = false;
                            foreach (MyArc arc in this.currentFullModel.geometryModel.Arcs)
                            {
                                if ((arc.StartPoint == start && arc.EndPoint == end) || (arc.StartPoint == end && arc.EndPoint == start))
                                {
                                    lineExists = true;
                                    arcs.Add(arc);
                                    lines.Add(arc);
                                    break;
                                }
                            }

                            if (!lineExists)
                            {
                                // пробуем создать дугу с поворотом по часовой стрелке. если это невозоможно, то создадим с поворотом против)
                                //MyArc newArc = new MyArc(this.currentFullModel.geometryModel.NumOfLines + 1, true, start, p2, centerPoint);
                                MyArc newArc = new MyArc(this.currentFullModel.geometryModel.NumOfLines + 1, true, start, end, centerPoint);
                                if (this.TestArc(newArc))
                                {
                                    this.currentFullModel.geometryModel.Arcs.Add(newArc);
                                    arcs.Add(newArc);
                                    lines.Add(newArc);
                                    //this.DrawArc(newArc, Color.Blue);
                                    this.currentFullModel.geometryModel.NumOfLines++;
                                }
                                else
                                {
                                    //newArc = new MyArc(this.currentFullModel.geometryModel.NumOfLines + 1, false, start, p2, centerPoint);
                                    newArc = new MyArc(this.currentFullModel.geometryModel.NumOfLines + 1, false, start, end, centerPoint);
                                    if (this.TestArc(newArc))
                                    {
                                        this.currentFullModel.geometryModel.Arcs.Add(newArc);
                                        arcs.Add(newArc);
                                        lines.Add(newArc);
                                        //this.DrawArc(newArc, Color.Blue);
                                        this.currentFullModel.geometryModel.NumOfLines++;
                                    }
                                }
                            }
                        }
                    }
                }

                List <MyStraightLine> Segments = new List <MyStraightLine>();
                for (int l = 0; l < 8; l++) // этим мы создаем отрезки и соединяем ими узлы зоны
                {
                    int k = l + 1;
                    if (k == 8)
                    {
                        k = 0;
                    }
                    Segments.Add(new MyStraightLine(0, areaNodes[l], areaNodes[k]));
                }

                // эмулируем создание зоны так, как если бы мы создавали ее вручную
                control.number.Text = (this.currentFullModel.geometryModel.NumOfAreas + 1).ToString();
                control.line1.Text  = lines[0].Id.ToString();
                control.line2.Text  = lines[1].Id.ToString();
                control.line3.Text  = lines[2].Id.ToString();
                control.line4.Text  = lines[3].Id.ToString();
                control.OK(areaNodes);
            }
        }
        public bool OK(List <MyPoint> formerNodes = null)
        {
            MyPoint point   = null;
            bool    success = false;

            int[]  lineID     = new int[4];
            bool[] lineExists = { false, false, false, false };

            int numOfArcs = 0;

            parent.clearSelection();

            if (number.TextLength == 0 || line1.TextLength == 0 || line2.TextLength == 0 || line3.TextLength == 0 || line4.TextLength == 0)
            {
                errorMessage1.Visible = true;
                return(success);
            }
            if (errorMessage2.Visible)
            {
                return(success);
            }
            lineID[0] = Convert.ToInt32(line1.Text);
            lineID[1] = Convert.ToInt32(line2.Text);
            lineID[2] = Convert.ToInt32(line3.Text);
            lineID[3] = Convert.ToInt32(line4.Text);
            if (lineID.Distinct().ToArray().Length != 4)
            {
                MessageBox.Show("Зона не может содержать повторяющиеся линии!");
                return(success);
            }

            List <MyPoint>        points = new List <MyPoint>();
            List <MyStraightLine> slines = new List <MyStraightLine>();
            List <MyArc>          arcs   = new List <MyArc>();
            List <MyLine>         lines  = new List <MyLine>();

            // ищем линии
            for (int i = 0; i < 4; i++)
            {
                MyLine         currentLine;
                MyStraightLine line = parent.currentFullModel.geometryModel.StraightLines.Find(ln => ln.Id == lineID[i]);
                MyArc          arc  = parent.currentFullModel.geometryModel.Arcs.Find(a => a.Id == lineID[i]);
                if (line == null)
                {
                    currentLine = arc;
                }
                else
                {
                    currentLine = line;
                }
                if (currentLine != null)
                {
                    lineExists[i] = true;
                    bool neighborLineExists = false;
                    // цикл по всем зонам
                    MyArea area;
                    if (line == null)
                    {
                        area = parent.currentFullModel.geometryModel.Areas.Find(a => a.Arcs.IndexOf(arc) != -1);
                    }
                    else
                    {
                        area = parent.currentFullModel.geometryModel.Areas.Find(a => a.StraightLines.IndexOf(line) != -1);
                    }
                    if (area != null)
                    {
                        if (points.IndexOf(currentLine.EndPoint) == -1)
                        {
                            points.Add(currentLine.EndPoint);
                        }
                        if (points.IndexOf(currentLine.StartPoint) == -1)
                        {
                            points.Add(currentLine.StartPoint);
                        }
                        neighborLineExists = true;
                    }

                    if (!neighborLineExists)
                    {
                        if (points.IndexOf(currentLine.StartPoint) == -1)
                        {
                            points.Add(currentLine.StartPoint);
                        }
                        if (points.IndexOf(currentLine.EndPoint) == -1)
                        {
                            points.Add(currentLine.EndPoint);
                        }
                    }
                    lineExists[i] = true;
                    if (line == null)
                    {
                        arcs.Add(arc);
                        numOfArcs++;
                    }
                    else
                    {
                        slines.Add(line);
                    }
                    lines.Add(currentLine);
                }
            }

            // закончили поиск линий

            if (!lineExists.Contains(false))
            {
                // указанные линии существуют, но надо еще проверить, образуют ли они замкнутую зону
                errorMessage4.Visible   = false;
                errorAreaExists.Visible = false;
                if (points.Count == 4) // условие, определяющее то, что линии образуют замкнутую область
                {
                    errorMessage3.Visible = false;
                    // проверяем число зон, в которым принадлежать линии
                    foreach (MyLine l in lines)
                    {
                        if (l.Areas.Count == 2)
                        {
                            clearLines();
                            errorTwoAreas.Visible = true;
                            return(success);
                        }
                    }

                    // проверяем, нет ли такой зоны уже
                    if (lines.Find(l => l.Areas.Count != 1) == null) //lines[0].Areas.Count == 1 && lines[1].Areas.Count == 1 && lines[2].Areas.Count == 1 && lines[3].Areas.Count == 1)
                    {
                        if (lines.ConvertAll(l => parent.currentFullModel.geometryModel.Areas.Find(ar => ar.Id == l.Areas.First()).Id).Distinct().Count() == 1)
                        {
                            errorAreaExists.Visible = true;
                            clearLines();
                            return(success);
                        }
                    }

                    // определяем первую линию в списке линий
                    int firstLine = 0;
                    for (int i = 0; i < 4; i++)
                    {
                        if (lines[i].Areas.Count == 1)
                        {
                            firstLine = i;
                            break;
                        }
                    }
                    if (firstLine != 0)
                    {
                        MyLine tempLine = lines[0];
                        lines[0]         = lines[firstLine];
                        lines[firstLine] = tempLine;
                    }

                    // определяем вторую линию в списке линий
                    int secondLine = 1;
                    point = lines[0].EndPoint;
                    for (int i = 1; i < 4; i++)
                    {
                        if (point == lines[i].EndPoint || point == lines[i].StartPoint)
                        {
                            secondLine = i;
                            break;
                        }
                    }

                    if (secondLine != 1)
                    {
                        MyLine tempLine = lines[1];
                        lines[1]          = lines[secondLine];
                        lines[secondLine] = tempLine;
                    }

                    // определяем четвертую (последниюю) линию в списке линий. определения третий линии нет, и это не ошибка. она определится автоматом
                    int lastLine = 3;
                    point = lines[0].StartPoint;
                    for (int i = 2; i < 4; i++)
                    {
                        if (point == lines[i].EndPoint || point == lines[i].StartPoint)
                        {
                            lastLine = i;
                            break;
                        }
                    }
                    if (lastLine != 3)
                    {
                        MyLine tempLine = lines[3];
                        lines[3]        = lines[lastLine];
                        lines[lastLine] = tempLine;
                    }

                    points.Clear();
                    int newAreaId;
                    if (!int.TryParse(number.Text, out newAreaId))
                    {
                        errorMessage2.Visible = true;
                        number.Focus();
                        return(success);
                    }

                    if (parent.currentFullModel.geometryModel.Areas.Count > 0)
                    {
                        if (lines.All(l => l.Areas.Count == 0))
                        {
                            MessageBox.Show("Невозможно образовать зону: не прилегает ни к одной из существующих зон");
                            return(success);
                        }
                    }

                    points.Add(lines[0].StartPoint);
                    points.Add(lines[0].EndPoint);
                    if (lines[1].StartPoint != points[1])
                    {
                        points.Add(lines[1].StartPoint);
                    }
                    else
                    {
                        points.Add(lines[1].EndPoint);
                    }

                    if (lines[3].StartPoint != points[0])
                    {
                        points.Add(lines[3].StartPoint);
                    }
                    else
                    {
                        points.Add(lines[3].EndPoint);
                    }

                    double S = Square(points[0], points[1]) + Square(points[1], points[2]) + Square(points[2], points[3]) + Square(points[3], points[0]);

                    if (S > 0.0)
                    {
                        MyPoint tempPoint = points[2];
                        points[2] = points[3];
                        points[3] = tempPoint;

                        tempPoint = points[0];
                        points[0] = points[1];
                        points[1] = tempPoint;

                        MyLine tempLine = lines[1];
                        lines[1] = lines[3];
                        lines[3] = tempLine;
                    }

                    MyPoint[] middlePoints = new MyPoint[4];
                    for (int i = 0; i < 4; i++)
                    {
                        middlePoints[i] = new MyPoint(0, 0, 0);
                    }
                    // если импортируем геометрию, возможно узлы уже двигали
                    // считываем инфу оттуда
                    if (formerNodes != null)
                    {
                        for (int j = 0; j < 4; j++)
                        {
                            MyPoint p1 = points[j];
                            MyPoint p2 = points[j == 3 ? 0 : j + 1];
                            for (int i = 1; i < 8; i += 2)
                            {
                                MyPoint f1 = formerNodes[i - 1];
                                MyPoint f2 = formerNodes[i];
                                MyPoint f3 = formerNodes[i == 7 ? 0 : i + 1];
                                if (Mathematics.sameNode(f1, p1) && Mathematics.sameNode(f3, p2) ||
                                    Mathematics.sameNode(f1, p2) && Mathematics.sameNode(f3, p1))
                                {
                                    middlePoints[j].X = f2.X;
                                    middlePoints[j].Y = f2.Y;
                                }
                            }
                        }
                    }
                    // иначе тыкаем узлы на середины линий. Ручками, конечно, ручками :(
                    else
                    {
                        if (numOfArcs == 0)
                        {
                            middlePoints[0].X = points[0].X + (points[1].X - points[0].X) / 2;
                            middlePoints[0].Y = points[0].Y + (points[1].Y - points[0].Y) / 2;

                            middlePoints[1].X = points[1].X + (points[2].X - points[1].X) / 2;
                            middlePoints[1].Y = points[1].Y + (points[2].Y - points[1].Y) / 2;

                            middlePoints[2].X = points[2].X + (points[3].X - points[2].X) / 2;
                            middlePoints[2].Y = points[2].Y + (points[3].Y - points[2].Y) / 2;

                            middlePoints[3].X = points[3].X + (points[0].X - points[3].X) / 2;
                            middlePoints[3].Y = points[3].Y + (points[0].Y - points[3].Y) / 2;
                        }

                        else
                        {
                            for (int i = 0; i < 4; i++)
                            {
                                int m = i + 1;
                                if (m == 4)
                                {
                                    m = 0;
                                }
                                MyArc tempArc = formAnArc(points[i], points[m]);
                                if (tempArc != null)
                                {
                                    double startAngle  = (180.0 / Math.PI) * ProjectForm.ArcAngle(tempArc, tempArc.StartPoint); // вычисляем углы начальной и конечной точек дуги - меряются они от оси Х против часовой стрелки (в градусах)
                                    double endAngle    = (180.0 / Math.PI) * ProjectForm.ArcAngle(tempArc, tempArc.EndPoint);
                                    double centerAngle = 0;                                                                     // угол от оси Х до точки, делящей дугу по полам

                                    double sweepAngle = 0;                                                                      // угол дуги
                                    if (tempArc.Clockwise && startAngle > endAngle)
                                    {
                                        sweepAngle = (startAngle - endAngle);
                                    }
                                    if (tempArc.Clockwise && startAngle < endAngle)
                                    {
                                        sweepAngle = 360.0 - (endAngle - startAngle);
                                    }
                                    if (!tempArc.Clockwise && startAngle > endAngle)
                                    {
                                        sweepAngle = 360.0 - (startAngle - endAngle);
                                    }
                                    if (!tempArc.Clockwise && startAngle < endAngle)
                                    {
                                        sweepAngle = (endAngle - startAngle);
                                    }

                                    if (sweepAngle > 0.0 && sweepAngle <= 180.0)
                                    {
                                        if (tempArc.Clockwise)
                                        {
                                            centerAngle = startAngle - sweepAngle / 2.0;
                                            double X, Y, R;
                                            R  = Mathematics.FindDist(tempArc.CenterPoint, tempArc.StartPoint);
                                            X  = R * Math.Cos(centerAngle * (Math.PI / 180.0));
                                            Y  = R * Math.Sin(centerAngle * (Math.PI / 180.0));
                                            X += tempArc.CenterPoint.X;
                                            Y += tempArc.CenterPoint.Y;
                                            middlePoints[i].X = X;
                                            middlePoints[i].Y = Y;
                                        }
                                        else
                                        {
                                            centerAngle = startAngle + sweepAngle / 2.0;
                                            double X, Y, R;
                                            R  = Mathematics.FindDist(tempArc.CenterPoint, tempArc.StartPoint);
                                            X  = R * Math.Cos(centerAngle * (Math.PI / 180.0));
                                            Y  = R * Math.Sin(centerAngle * (Math.PI / 180.0));
                                            X += tempArc.CenterPoint.X;
                                            Y += tempArc.CenterPoint.Y;
                                            middlePoints[i].X = X;
                                            middlePoints[i].Y = Y;
                                        }
                                    }
                                    if (sweepAngle < 0.0 && sweepAngle >= -180.0)
                                    {
                                        if (tempArc.Clockwise)
                                        {
                                            centerAngle = startAngle + sweepAngle / 2.0;
                                            double X, Y, R;
                                            R  = Mathematics.FindDist(tempArc.CenterPoint, tempArc.StartPoint);
                                            X  = R * Math.Cos(centerAngle * (Math.PI / 180.0));
                                            Y  = R * Math.Sin(centerAngle * (Math.PI / 180.0));
                                            X += tempArc.CenterPoint.X;
                                            Y += tempArc.CenterPoint.Y;
                                            middlePoints[i].X = X;
                                            middlePoints[i].Y = Y;
                                        }
                                        else
                                        {
                                            centerAngle = startAngle - sweepAngle / 2.0;
                                            double X, Y, R;
                                            R  = Mathematics.FindDist(tempArc.CenterPoint, tempArc.StartPoint);
                                            X  = R * Math.Cos(centerAngle * (Math.PI / 180.0));
                                            Y  = R * Math.Sin(centerAngle * (Math.PI / 180.0));
                                            X += tempArc.CenterPoint.X;
                                            Y += tempArc.CenterPoint.Y;
                                            middlePoints[i].X = X;
                                            middlePoints[i].Y = Y;
                                        }
                                    }
                                }
                                else
                                {
                                    middlePoints[i].X = points[i].X + (points[m].X - points[i].X) / 2;
                                    middlePoints[i].Y = points[i].Y + (points[m].Y - points[i].Y) / 2;
                                }
                            }
                        }
                    }

                    List <MyPoint> Nodes = new List <MyPoint>();

                    for (int i = 0; i < 4; i++) // этим мы обеспечиваем чередование угловых узлов зоны с промежуточными узлами, а также следим за сковозной нумерацией узлов для всех зон пластины
                    {
                        bool pointExists      = false;
                        bool middlePointExits = false;
                        // Находим все зоны, содержащие текущую точку
                        List <MyArea> areas = parent.currentFullModel.geometryModel.Areas.FindAll(a => a.Nodes.Any(n => Mathematics.sameNode(n, points[i]) || Mathematics.sameNode(n, middlePoints[i])));
                        areas.Sort((a, b) => a.Id.CompareTo(b.Id));
                        foreach (MyArea area in areas)    // просматриваем все зоны
                        {
                            int     borderSideNumber = 0; // номер стороны существующей зоны, которая соприкасается с другой зоной. номер человеческий и начинается с 1 а не с 0
                            MyPoint node             = area.Nodes.Find(n => Mathematics.sameNode(n, points[i]) && !Nodes.Contains(n));
                            if (node != null)
                            {
                                Nodes.Add(node); // добавляем в список узлов зоны узел, который уже есть в списке узлов другой зоны
                                pointExists = true;
                            }
                            node = area.Nodes.Find(n => Mathematics.sameNode(n, middlePoints[i]) && !Nodes.Contains(n));
                            if (node != null)
                            {
                                Nodes.Add(node); // добавляем в список узлов зоны узел, который уже есть в списке узлов другой зоны
                                middlePointExits = true;
                                borderSideNumber = (area.Nodes.IndexOf(node) + 1) / 2;

                                parent.currentFullModel.geometryModel.joinTable[area.Id - 1, borderSideNumber - 1] = newAreaId; // т.к. area.Id и borderSideNumber - это индексы, а нумерация индексов с 0, то отнимаем 1
                                parent.currentFullModel.geometryModel.joinTable[newAreaId - 1, i] = area.Id;
                            }
                        }

                        if (!pointExists) // если пройдя по всем зонам, мы не нашли там таких узлов, то создаем новый объект и добавляем его в список зоны
                        {
                            parent.currentFullModel.geometryModel.NumOfAreaNodes++;
                            Nodes.Add(new MyPoint(parent.currentFullModel.geometryModel.NumOfAreaNodes, points[i].X, points[i].Y, MyPoint.PointType.IsAreaNode));
                            foreach (MyPoint p in parent.currentFullModel.geometryModel.Points) // задаем узлу зоны в соответствие точку геометрии и наоборот
                            {
                                if (p.X == points[i].X && p.Y == points[i].Y)
                                {
                                    Nodes[Nodes.Count - 1].PointReference = p;
                                    p.NodeReference = Nodes[Nodes.Count - 1];
                                    break;
                                }
                            }
                        }

                        if (!middlePointExits) // если пройдя по всем зонам, мы не нашли там таких узлов, то создаем новый объект и добавляем его в список зоны
                        {
                            parent.currentFullModel.geometryModel.NumOfAreaNodes++;
                            Nodes.Add(new MyPoint(parent.currentFullModel.geometryModel.NumOfAreaNodes, middlePoints[i].X, middlePoints[i].Y, MyPoint.PointType.IsAreaNode));
                            foreach (MyPoint p in parent.currentFullModel.geometryModel.Points) // задаем узлу зоны в соответствие точку геометрии и наоборот
                            {
                                if (p.X == middlePoints[i].X && p.Y == middlePoints[i].Y)
                                {
                                    Nodes[Nodes.Count - 1].PointReference = p;
                                    p.NodeReference = Nodes[Nodes.Count - 1];
                                    break;
                                }
                            }
                        }
                    }

                    List <MyStraightLine> Segments = new List <MyStraightLine>();
                    for (int i = 0; i < 8; i++) // этим мы создаем отрезки и соединяем ими узлы зоны
                    {
                        int k = i + 1;
                        if (k == 8)
                        {
                            k = 0;
                        }
                        Segments.Add(new MyStraightLine(0, Nodes[i], Nodes[k]));
                    }

                    MyArea newArea = new MyArea(newAreaId, lines, slines, Segments, points, arcs, Nodes);

                    parent.currentFullModel.geometryModel.Areas.Add(newArea);
                    success = true;
                    parent.currentFullModel.geometryModel.NumOfAreas++;

                    foreach (MyLine l in lines)
                    {
                        l.Areas.Add(newAreaId);
                    }

                    number.Text = (parent.currentFullModel.geometryModel.NumOfAreas + 1).ToString();


                    parent.showOnlyAreas.Checked = true;
                }
                else
                {
                    errorMessage3.Visible = true;
                }
            }
            else
            {
                errorMessage4.Visible = true;
            }
            return(success);
        }