Задать вопрос
@Mister_krid

Как правильно построить функцию?

ТО ЧТО У МЕНЯ
60757b008165e522558083.png
ТО ЧТО ДОЛЖНО ПОЛУЧИТЬСЯ
60757b3a6e883047668175.png
Рисую фигуры на форме НЕ с помощью встроенных методов(изучение комп. графики). Построил функцию(вроде правильно), но она рисуется зеркально, не понимаю где проблема все перерыл уже. И ограничения функции не особо работают.
Главный класс с функцией.
public partial class DrawWindow : Form
    {
        
        public DrawWindow()
        {
            InitializeComponent();
            pictureBox1.Paint += PictureBox1_Paint;           
            //pictureBox1.Paint += DrawWindow_Paint;
            //Paint += new PaintEventHandler(DrawWindow_Paint);
        }


        private void PictureBox1_Paint(object sender, PaintEventArgs e)
        {
            int w = pictureBox1.ClientSize.Width / 2;
            int h = pictureBox1.ClientSize.Height / 2;
            //Смещение начала координат в центр PictureBox
            e.Graphics.TranslateTransform(w, h);
            // Оси x y
            DrawGrid.DrawXAxis(new Point(-w, 0), new Point(w, 0), e.Graphics);
            DrawGrid.DrawYAxis(new Point(0, h), new Point(0, -h), e.Graphics);
            //Центр координат
            e.Graphics.FillEllipse(Brushes.Red, -2, -2, 4, 4);

            DrPlot(e.Graphics);           

            Circle.BresenhamCircle(e.Graphics,Color.Black, 1, 1, 5);
            Line.Bresenham4Line(e.Graphics, Color.Black, -5, 5, 6, 10);
        }
       

      
        private void DrPlot(Graphics Grf)
        {
            Plot MyPlot = new Plot();
            double x;
            double y;
            MyPlot.ClientArea = this.ClientSize;
            MyPlot.SetPlotPort(-5, 5, -5, 5);
            for (x = -5.0; x < 5; x += 0.005)
            {
                //MyPlot.PlotPixel(x, y, Color.Black, Grf);
                if (x + 5 != 0)
                {
                    y = (Math.Pow(x, 3) - 1) / (x + 5);
                    MyPlot.PlotPixel(x, y, Color.Black, Grf);
                    //Circle.PutPixel(Grf, Color.Black, (int)x, (int)y, 255);
                }
                else
                    continue;
            }

        }
    }


Класс рисующий все PIX_IN_ONE взято 20
class Plot
    {
        struct PlotPort
        {
            public int minX;
            public int maxX;
            public int minY;
            public int maxY;
        };

        private PlotPort _PlotW;    //"window" of carthesian coordinates
        private Size _ClientArea;   //keeps the pixels info
        private double _Xspan;
        private double _Yspan;

        public Plot() { }

        public Plot(Size Plotarea)
        {
            _ClientArea = Plotarea;
        }

        public Size ClientArea { set { _ClientArea = value; } }

        public void SetPlotPort(int minx, int maxx, int miny, int maxy)
        {
            //set the bounderies of the form(screen) to real coordinates.
            _PlotW.minX = minx;
            _PlotW.maxX = maxx;
            _PlotW.minY = miny;
            _PlotW.maxY = maxy;
            _Xspan = _PlotW.maxX - _PlotW.minX;
            _Yspan = _PlotW.maxY - _PlotW.minY;
        }

        public void PlotPixel(double X, double Y, Color C, Graphics G)
        {
            //workhorse of this class
            Bitmap bm = new Bitmap(1, 1);
            bm.SetPixel(0, 0, C);
            G.DrawImageUnscaled(bm, ToX(X), ToY(Y));
        }

        private int ToX(double X) //transform real coordinates to pixels for the X-axis
        {
            double w;
            w = _ClientArea.Width / _Xspan * X + _ClientArea.Width / DrawGrid.PIX_IN_ONE;
            return Convert.ToInt32(w);
        }

        private int ToY(double Y) //transform real coordinates to pixels for the Y-axis
        {
            double w;
            w = _ClientArea.Height / _Yspan * Y + _ClientArea.Height / DrawGrid.PIX_IN_ONE;
            return Convert.ToInt32(w);
        }
    }
  • Вопрос задан
  • 194 просмотра
Подписаться 1 Простой 10 комментариев
Решения вопроса 2
@cicatrix
было бы большой ошибкой думать
Короче, вот готовый пример, как работать с матрицами трансформации. Это действительно проще показать, чем объяснить
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace DrawPlot
{
    public partial class MainForm : Form
    {
        // Добавил сюда, чтобы в InitializeComponent не лезть
        PictureBox picDisplay;

        // Макс размер сетки по наибольшему измерению окна 
        // для сохранения пропорции (либо по ширине, либо по высоте)
        const float MaxGrid = 10.0f;

        // Это задаёт логический размер окна
        SizeF viewPort;

        // Шаги сетки 
        const float GridStep = 0.1f;
        // Каждые 10 линий сетки делаем линию поярче
        const int BoldLineStep = 10;

        // Цвета        
        Pen pen_LargeGrid = new Pen(Color.FromArgb(0,64,0));
        Pen pen_SmallGrid = new Pen(Color.FromArgb(0,32,0));        
        Pen pen_Axii = new Pen(Color.FromArgb(0,128,0));
        SolidBrush plotBrush = new SolidBrush(Color.Red);

        // Ширина 1 пиксела в логических размерах
        float Pixel_Width;

        public MainForm()
        {
            InitializeComponent();
            picDisplay = new PictureBox() { Parent = this, Dock = DockStyle.Fill, BackColor = Color.Black };
            picDisplay.Paint += this.PicDisplay_Paint;
            picDisplay.Resize += this.PicDisplay_Resize;
            // Стрелочка 10х4
            AdjustableArrowCap cap = new AdjustableArrowCap(4.0f,10.0f);
            pen_Axii.CustomEndCap = cap;
            CalculateDimensions();
        } // MainForm Ctor       

        private void PicDisplay_Resize(object sender, EventArgs e)
        {
            CalculateDimensions();
            picDisplay.Invalidate();
        } // PicDisplay_Resize

        private void CalculateDimensions()
        {
            var rect = picDisplay.ClientRectangle;
            // Устанавливаем размеры в зависимости от того, что больше, длина или ширина
            // для сохранения квадратной сетки
            if (rect.Width > rect.Height)
                viewPort = new SizeF(MaxGrid, MaxGrid * (rect.Height / (float)rect.Width));
            else
                viewPort = new SizeF(MaxGrid * (rect.Width / (float)rect.Height), MaxGrid);
            // Считаем ширину 1 пикселя 
            Pixel_Width = viewPort.Width / rect.Width;
            // Назначаем эту ширину используемым перьям
            foreach (var pen in new Pen[] { pen_Axii, pen_LargeGrid, pen_SmallGrid, pen_LargeGrid })
                pen.Width = Pixel_Width;
        } // CalculateDimensions

        private void PicDisplay_Paint(object sender, PaintEventArgs e)
        {            
            Graphics g = e.Graphics;
            
            // Масштабируем
            g.ScaleTransform(picDisplay.Width / viewPort.Width, (picDisplay.Height / viewPort.Height));

            // Двигаем начало координат в середину
            float halfWidth = viewPort.Width / 2;
            float halfHeight = viewPort.Height / 2;
            g.TranslateTransform(halfWidth, halfHeight);

            // Переворачиваем Y
            g.ScaleTransform(1.0f, -1.0f);

            // Рисуем сетку
            int step = 0;
            for(var f = 0f; f < MaxGrid / 2 ; f += GridStep)
            {
                var currentPen = pen_SmallGrid;                
                if (0 == step % BoldLineStep) currentPen = pen_LargeGrid;
                // Горизонтальные
                g.DrawLine(currentPen, -halfWidth, f, halfWidth, f);
                g.DrawLine(currentPen, -halfWidth, -f, halfWidth, -f);
                // Вертикальные
                g.DrawLine(currentPen, f, -halfHeight, f, halfHeight);
                g.DrawLine(currentPen, -f, -halfHeight, -f, halfHeight);
                step++;
            } // for
            // Оси координат
            g.DrawLine(pen_Axii, -halfWidth, 0, halfWidth, 0);
            g.DrawLine(pen_Axii, 0, -halfHeight, 0, halfHeight);

            // график
            float y;
            for (var x = -halfWidth ; x < halfWidth ; x+= Pixel_Width)
            {
                y = ((float)Math.Pow(x, 3) - 1) / (x + 5);
                // Обязательно проверка на NaN и Infinity
                if (!float.IsNaN(y) && !float.IsInfinity(y)) 
                      g.FillRectangle(plotBrush, new RectangleF(x, y, Pixel_Width, Pixel_Width));
            } // for
        } // PicDisplay_Paint
    } // class MainForm`    1+m  
} // DrawPlot namespace


6076227c0d1d2664851754.png
Ответ написан
zagayevskiy
@zagayevskiy
Android developer at Yandex
Наверняка у формы начало координат находится в левом верхнем углу, и ось ординат направлена вниз, как это обычно и бывает в оконных системах. Отсюда и отражение. Код не читал.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы