/// <summary>
        /// Нахождение шага разбиения стороны
        /// </summary>
        /// <param name="fSide">длина стороны</param>
        /// <param name="step">первоначальный шаг разбиения</param>
        /// <returns>новый шаг разбиения</returns>
        public static double FindNewStep(double fSide, double step)
        {
            double newStep = 0;
            double n, step1, step2;

            n = fSide / step;
            if (n <= 1.4f)
            {
                newStep = fSide;
            }
            else if (fSide % step <= 0.3f * step)
            {
                newStep = step;
            }
            else
            {
                newStep = fSide / Mathematics.floor(fSide / step, 1.0);
                //step1 = step;
                //step2 = step;
                //while ((fSide % step) > (0.3f * step))
                //{
                //    step1 = step1 + 0.1f;
                //    if ((fSide % step1) <= (0.3f * step1))
                //        return step1;
                //    step2 = step2 - 0.1f;
                //    if ((fSide % step2) <= (0.3f * step2))
                //        return step2;
                //}
            }
            return(newStep);
        }
        public float ScaleToFit(double _width, double _height)
        {
            float width = (float)_width, height = (float)_height;

            if (width == 0 && height == 0)
            {
                return(1.0f);
            }
            float prevScale = 1;
            float k         = (float)Mathematics.floor((scale >= 1.0f) ? scale : 1.0 / scale, 0.1);

            // максимизируем
            while (borders.Width < width || borders.Height < height)
            {
                prevScale = scale;
                IncreaseScale(ref k);
                RefreshBorders();
            }
            // минимизируем
            while (borders.Width > width && borders.Height > height)
            {
                prevScale = scale;
                DecreaseScale(ref k);
                RefreshBorders();
            }
            scale = prevScale;
            IncreaseScale(ref k);
            RefreshBorders();
            return(scale);
        }
 private void DecreaseScale(ref float k)
 {
     k = (float)Mathematics.floor(k, 0.1);
     if (scale > 1.0f)
     {
         k -= 0.1f;
     }
     else
     {
         k += 0.1f;
     }
     if (scale > 1.0f)
     {
         scale = k;
     }
     else
     {
         scale = 1.0f / k;
     }
 }
        public void DrawForces(MyFiniteElementModel model, double scale, Color color, bool showValues = true)
        {
            MyNode[] forcedNodes = model.Nodes.FindAll(n => n.ForceX != 0.0 || n.ForceY != 0.0).ToArray();
            int      nodesCount  = forcedNodes.Length;

            if (nodesCount == 0)
            {
                return;
            }
            int count = 6 * nodesCount;

            float[] pts = new float[count * 2];
            Gl.glColor3dv(colorArray(color));

            for (int i = 0; i < nodesCount; i++)
            {
                MyNode node = forcedNodes[i];
                // силу будем рисовать, как линию со стрелочкой на конце. Если сила > 0, то она идет вверх или вправо ( зависит от нагрузки - по X или по Y)
                // плюс, надо еще масштабировать длину стрелки
                // координаты начальной и конечной точки в пикселях

                float forceLengthX = (float)node.ForceX;
                float forceLengthY = (float)node.ForceY;
                float x1           = (float)node.X;
                float y1           = (float)node.Y;
                float x2           = x1 + forceLengthX * (float)scale; // масштабируем длину стрелки
                float y2           = y1 + forceLengthY * (float)scale; // масштабируем длину стрелки

                pts[(i * 12)]     = x1;
                pts[(i * 12) + 1] = y1;
                pts[(i * 12) + 2] = x2;
                pts[(i * 12) + 3] = y2;

                // вычисляем угол нагрузки
                float alfa = (float)Math.Atan2(y2 - y1, x2 - x1);
                // длина стрелочки
                float aSize = (float)Math.Pow(((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)), 0.5) / 10.0f;

                float px1 = x2;
                float py1 = y2;
                float px2 = (float)(x2 - aSize * Math.Cos(alfa + 15.0 * (Math.PI / 180.0)));
                float py2 = (float)(y2 - aSize * Math.Sin(alfa + 15.0 * (Math.PI / 180.0)));
                float px3 = (float)(x2 - aSize * Math.Cos(alfa - 15.0 * (Math.PI / 180.0)));
                float py3 = (float)(y2 - aSize * Math.Sin(alfa - 15.0 * (Math.PI / 180.0)));

                pts[(i * 12) + 4] = px1;
                pts[(i * 12) + 5] = py1;
                pts[(i * 12) + 6] = px2;
                pts[(i * 12) + 7] = py2;

                pts[(i * 12) + 8]  = px1;
                pts[(i * 12) + 9]  = py1;
                pts[(i * 12) + 10] = px3;
                pts[(i * 12) + 11] = py3;

                if (showValues)
                {
                    float  f      = (float)Math.Pow((Math.Pow(node.ForceX, 2) + Math.Pow(node.ForceY, 2)), 0.5);
                    double fRound = Mathematics.floor(f, Mathematics.accuracy_medium);
                    DrawString(fRound.ToString(), x2, y2, true);
                }
            }
            int list;

            list = Gl.glGenLists(1);
            Gl.glNewList(list, Gl.GL_COMPILE);
            Gl.glColor3dv(colorArray(color));
            Gl.glLineWidth(1.0f);
            Gl.glEndList();
            drawBuffer.Add(new DrawingOperation(Gl.GL_LINES, pts, list));
            if (showValues)
            {
                FlushText(color);
            }
        }