Example #1
0
    protected override void OnDeviceUpdate(object s, GDIDeviceUpdateArgs e)
    {
        Angle += 0.0360 * e.Delta;

        var SecondPoint = FirstPoint + Length * new DVector2(
            Math.Cos(Angle * Math.PI / 180),
            Math.Sin(Angle * Math.PI / 180)
            );

        e.Surface.DrawLine(Color.Red.ToArgb(), FirstPoint, SecondPoint);
    }
Example #2
0
    protected override void OnDeviceUpdate(object s, GDIDeviceUpdateArgs e)
    {
        Width  = (int)e.Width;
        Height = (int)e.Heigh;

        double WindowScale;

        if (Height < Width)
        {
            WindowScale = (double)Height / InitialHeight;
        }
        else
        {
            WindowScale = (double)Width / InitialWidth;
        }

        DVector2 pivot = new DVector2(Width / 2, Height / 2);

        Pen graphPen = new Pen(Brushes.DarkBlue, 2.0f);
        Pen xAxisPen = new Pen(Brushes.Red, 2.0f);
        Pen yAxisPen = new Pen(Brushes.Green, 2.0f);

        if (points == null || PrevApproxLevel != ApproxLevel || PrevAmplitude != Amplitude)
        {
            points          = ComputePoints();
            PrevApproxLevel = ApproxLevel;
            PrevAmplitude   = Amplitude;
            Console.WriteLine("Recomputed!");
        }

        // -----
        double RotationAngleRad = RotationAngle / 180.0 * Math.PI;

        DVector2 center = new DVector2(pivot.X + Offset.X + ShiftX, pivot.Y - Offset.Y - ShiftY);

        DrawAxis(e.Graphics, xAxisPen, RotationAngleRad, center, Math.Abs(Scale.X), WindowScale, false, 180.0);
        DrawAxis(e.Graphics, yAxisPen, RotationAngleRad + Math.PI / 2.0, center, Math.Abs(Scale.Y), WindowScale, true, 90.0);

        e.Graphics.FillEllipse(Brushes.Black, new Rectangle((int)(center.X - centerCircleSize), (int)(center.Y - centerCircleSize), centerCircleSize * 2, centerCircleSize * 2));

        DVector2 prevP = new DVector2(pivot);
        bool     firstPointComputed = false;

        foreach (var p in points)
        {
            DVector2 scaledP = (new DVector2(p.X, -p.Y)).Multiply(Scale * WindowScale);

            double sin = Math.Sin(RotationAngleRad);
            double cos = Math.Cos(RotationAngleRad);

            DVector2 rotatedP = VecRotate(scaledP, RotationAngleRad);

            DVector2 transformedP = new DVector2(rotatedP.X + Offset.X + ShiftX + pivot.X,
                                                 rotatedP.Y + -Offset.Y - ShiftY + pivot.Y);

            if (firstPointComputed)
            {
                e.Graphics.DrawLine(graphPen, prevP.X, prevP.Y, transformedP.X, transformedP.Y);
            }

            prevP = transformedP;

            firstPointComputed = true;
        }

        e.Graphics.DrawString(LabelTxt, new Font("Arial", 15f), Brushes.Black, 10f, 10f);
    }
Example #3
0
    // Перегружаем главный метод. По назначению он анологичен методу OnPaint() и предназначен
    // для формирования изображения. Однако в отличии от оного он выполняется паралелльно в
    // другом потоке и вызывается непрерывно. О текущей частоте вызовов можно судить по
    // счетчику числа кадров в заголовке окна (конечно в режиме отладки скорость падает).
    // Помимо прочего он обеспечивает более высокую скорость рисования и не мерцает.
    protected override void OnDeviceUpdate(object s, GDIDeviceUpdateArgs e)
    {
        double sx = ShiftX; // С точки зрения производительности часто используемые свойства лучше
        double sy = ShiftY; // сохранить в локальные переменные или обращаться к связаным с ними полям
        double lx1 = sx + e.Width / 2, ly1 = sy + e.Heigh / 2, lx2 = e.Width / 4, ly2 = e.Heigh / 4;

        double[] txy = new double[] { 0, -60, -40, +20, +50, +40 };

        if (EnableRot)
        {
            angle += 0.1 * e.Delta;
        }
        var sinf = Math.Sin(angle * Math.PI / 180);
        var cosf = Math.Cos(angle * Math.PI / 180);

        for (int i = 0; i < 3; ++i)
        {
            var x = txy[2 * i];
            var y = txy[2 * i + 1];
            txy[2 * i]     = x * cosf - y * sinf + e.Width / 2 + sx;
            txy[2 * i + 1] = x * sinf + y * cosf + e.Heigh / 2 - sy;
        }

        if (DrawMode == DrawingMode.GFX)
        {
            // Стандартный способ отображения при помощи штатных средств
            // + Больше гибкость, например можно задать толщину линий
            // + Для треугольников есть сглаживание
            for (double fi = 0; fi < 2 * Math.PI; fi += Math.PI / 32)
            {
                e.Graphics.DrawLine(Pens.GhostWhite, lx1, ly1,
                                    +sx + lx1 + lx2 * Math.Cos(fi) - ly2 * Math.Sin(fi),
                                    -sy + ly1 + lx2 * Math.Sin(fi) + ly2 * Math.Cos(fi));
            }
            e.Graphics.FillPolygon(Brushes.Chocolate, new PointF[] {
                new PointF((float)txy[0], (float)txy[1]),
                new PointF((float)txy[2], (float)txy[3]),
                new PointF((float)txy[4], (float)txy[5])
            });

            e.Graphics.FillRectangle(Brushes.DodgerBlue, 9, 35, 200, 12);
        }
        else
        {
            // Собственная реализация отображения (CGLabPlatform.Drawing)
            // + Выше скорость работы (у меня разница более чем в 5 раз)
            // + Лучшее качество сглаженных прямых
            // + Градиентная закраска треугольника (т.е. задание различных
            //   цветов для каждой из верши), что будет востребаванно
            for (double fi = 0; fi < 2 * Math.PI; fi += Math.PI / 32)
            {
                e.Surface.DrawLine(Color.GhostWhite.ToArgb(), lx1, ly1,
                                   +sx + lx1 + lx2 * Math.Cos(fi) - ly2 * Math.Sin(fi),
                                   -sy + ly1 + lx2 * Math.Sin(fi) + ly2 * Math.Cos(fi));
            }
            e.Surface.DrawTriangle(Color.Chocolate.ToArgb(), txy[0], txy[1], txy[2], txy[3], txy[4], txy[5]);

            e.Surface.FillRectangle(Color.DodgerBlue.ToArgb(), 10, 35, 200, 12);
        }

        // Вторая реализация отображения осуществляется путем прямого доступа
        // к поверхности связанной с объектом Graphics. Поэтому возможно
        // одновременное использование обоих методов работы с изображением.
        // Так вне зависимости от выбранного метода, используется объект
        // Graphics для вывода текста.
        e.Graphics.DrawString(LabelTxt, new Font("Arial", 15f), Brushes.Chartreuse, 10f, 10f);
    }
Example #4
0
    protected override void OnDeviceUpdate(object s, GDIDeviceUpdateArgs e)
    {
        if (PrevApproxLevel != ApproxLevel)
        {
            ComputeObject();
            PrevApproxLevel = ApproxLevel;
        }

        if (e.Heigh < e.Width)
        {
            WindowScale = (double)e.Heigh / InitialHeight;
        }
        else
        {
            WindowScale = (double)e.Width / InitialWidth;
        }

        switch (ProjMode)
        {
        case ProjectionMode.FR:
            rotX = Rotation.X;
            rotY = Rotation.Y;
            rotZ = Rotation.Z;
            break;

        case ProjectionMode.ISO:
            rotX = -35.0;
            rotY = -45.0;
            rotZ = 0.0;
            break;

        case ProjectionMode.ORT_F:
            rotX = 0.0;
            rotY = 0.0;
            rotZ = 0.0;
            break;

        case ProjectionMode.ORT_L:
            rotX = 0.0;
            rotY = 90.0;
            rotZ = 0.0;
            break;

        case ProjectionMode.ORT_T:
            rotX = -90.0;
            rotY = 0.0;
            rotZ = 0.0;
            break;
        }

        // compute transformation ( scale and rotation ) matrix
        DMatrix4 mat = DMatrix4.Identity;

        double scale = 100.0;

        RotateMatrix(ref mat, rotX, rotY, rotZ);
        ScaleMatrix(ref mat, scale * Scale.X * WindowScale, scale * Scale.Y * WindowScale, scale * Scale.Z * WindowScale);

        // transform verticis of object
        foreach (Vertex v in Vertecis)
        {
            v.Point = mat * v._Point;
        }

        Polygons.QuickSort(p => p.Vertex.Average(v => v.Point.Z));

        // draw main object
        foreach (Polygon p in Polygons)
        {
            p.Normal  = CrossProduct(p.Vertex[0].Point - p.Vertex[1].Point, p.Vertex[1].Point - p.Vertex[2].Point);
            p.Normal /= p.Normal.GetLength();

            if (p.Normal.Z > 0)
            {
                DrawPolygonFixGaps2(p, e.Graphics, e.Width, e.Heigh);
            }
        }

        // some optional features
        foreach (Polygon p in Polygons)
        {
            if (p.Normal.Z > 0)
            {
                if (EnableNormals)
                {
                    DrawNormal(p, e.Graphics, e.Width, e.Heigh);
                }
                if (EnableVertexNumbers)
                {
                    DrawVertexNumbers(p, e.Graphics, e.Width, e.Heigh);
                }
            }
        }

        // Drawing axis (in the right lower corner)
        DVector4 ox = mat * (new DVector4(1.0, 0.0, 0.0, 0.0));
        DVector4 oy = mat * (new DVector4(0.0, 1.0, 0.0, 0.0));
        DVector4 oz = mat * (new DVector4(0.0, 0.0, 1.0, 0.0));

        ox = ox / ox.GetLength() * 50.0 * WindowScale;
        oy = oy / oy.GetLength() * 50.0 * WindowScale;
        oz = oz / oz.GetLength() * 50.0 * WindowScale;

        DVector4 pos = new DVector4(e.Width - 70.0 * WindowScale, e.Heigh - 70.0 * WindowScale, 0.0, 0.0);

        DrawAxis(e.Graphics, ox, oy, oz, pos);
    }