0 / 0 / 0
Регистрация: 19.12.2018
Сообщений: 2
1

Оптимизация работы приложения для отрисовки фрактала

04.01.2020, 15:35. Показов 1157. Ответов 2

Здравствуйте, всех с 2020 годом
Требуется ваша помощь, форумчане) Надеюсь, на ваши идеи. Буду признателен за помощь

Есть простое приложение для отрисовки фрактала

Нужно его оптимизировать, есть 2 проблемы:
1. Шумы на изображении при параллельной отрисовке
2. Сама параллельная отрисовка дольше, чем в одном потоке. Вероятно, что проблема в отрисовке пикселей на форме. Как это можно исправить? Скорее всего можно загрузить итоговое изображение в массив данных, а потом отрисовать. Но как это можно реализовать?

Проект приложен
В C# я новичок, так что не судите строго.
Заранее благодарю за какую либо помощь

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace ArtFractals
{
    public partial class Form1 : Form
    {
 
        // Элементы
        private List<Rectangle> Items = new List<Rectangle>();
        /// <summary>
        /// Будем хранить время
        /// </summary>
        private Point TimeOut = new Point();
        /// <summary>
        /// Обьект блокировки
        /// </summary>
        private object ObjLock = new object();
        public Graphics g; //Графика
        public Bitmap map; //Битмап
        public Color Clr; //Переменная цвета
        SolidBrush br; //Кисть
 
        public Form1()
        {
            InitializeComponent();
            // Настройка стиле (ускоряет отрисовку)
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
 
        }
 
       struct Complex
        {
            public double x;
            public double y;
  
         };
       
       const int iter = 50;
       const double min = 1e-6;
       const double max = 1e+6;
 
 
        public void Draw(int mx1, int my1, Graphics g, Pen pen)
        {
            // Очистим элемнты
            g.Clear(Color.Black);
            // Засекаем время
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
 
            int n, mx, my;
            double p;
            Complex z, t, d = new Complex();
 
            mx = mx1 / 2;
            my = my1 / 2;
 
            for (int y = -my; y < my; y++)
                for (int x = -mx; x < mx; x++)
                {
                    n = 0;
                    z.x = x * 0.005;
                    z.y = y * 0.005;
                    d = z;
 
                    while ((Math.Pow(z.x, 2) + Math.Pow(z.y, 2) < max) && (Math.Pow(d.x, 2) + Math.Pow(d.y, 2) > min) && (n < iter))
                    {
                        t = z;
                        p = Math.Pow(Math.Pow(t.x, 2) + Math.Pow(t.y, 2), 2);
                        z.x = 2 / 3 * t.x + (Math.Pow(t.x, 2) - Math.Pow(t.y, 2)) / (3 * p);
                        z.y = 2 / 3 * t.y * (1 - t.x / p);
                        d.x = Math.Abs(t.x - z.x);
                        d.y = Math.Abs(t.y - z.y);
                        n++;
                    }
                    pen.Color = Color.FromArgb(255, (n * 9) % 255, 0, (n * 9) % 255);
                    g.DrawRectangle(pen, mx + x, my + y, 1, 1);
                }
            Console.WriteLine(stopWatch.Elapsed);
        }
 
        public void Draw2(int mx1, int my1, Graphics g)
       {
            lock (ObjLock)
            {
                // Ускорит отрисовку (оптимизация)
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
                // Очистим элемнты
                g.Clear(Color.Black);
                // Засекаем время
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Start();
 
                int n, mx, my;
                double p;
                Complex z, t, d = new Complex();
 
                mx = mx1 / 2;
                my = my1 / 2;
 
                
                for (int y = -my; y < my; y++)
                {
                    for (int x = -mx; x < mx; x++)
                    {
                        n = 0;
                        z.x = x * 0.005;
                        z.y = y * 0.005;
                        d = z;
 
                        while ((Math.Pow(z.x, 2) + Math.Pow(z.y, 2) < max) && (Math.Pow(d.x, 2) + Math.Pow(d.y, 2) > min) && (n < iter))
                        {
                            t = z;
                            p = Math.Pow(Math.Pow(t.x, 2) + Math.Pow(t.y, 2), 2);
                            z.x = 2 / 3 * t.x + (Math.Pow(t.x, 2) - Math.Pow(t.y, 2)) / (3 * p);
                            z.y = 2 / 3 * t.y * (1 - t.x / p);
                            d.x = Math.Abs(t.x - z.x);
                            d.y = Math.Abs(t.y - z.y);
                            n++;
                        }
                        Clr = Color.FromArgb(255, (n * 9) % 255, 0, (n * 9) % 255);
                        br = new SolidBrush(Clr);
                        g.FillRectangle(br, mx + x, my + y, 1, 1);
                    }
                };
                Console.WriteLine(stopWatch.Elapsed);
            }
       }
 
        public void Draw3(int mx1, int my1, Graphics g)
        {
            // Ускорит отрисовку (оптимизация)
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
            // Очистим элемнты
            g.Clear(Color.Black);
            // Засекаем время
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
 
            int n, mx, my;
            double p;
            Complex z, t, d = new Complex();
 
            mx = mx1 / 2;
            my = my1 / 2;
 
            Parallel.For(-my, my, y =>
            //for (int y = -my; y < my; y++)
            {
                for (int x = -mx; x < mx; x++)
                {
                    n = 0;
                    z.x = x * 0.005;
                    z.y = y * 0.005;
                    d = z;
 
                    while ((Math.Pow(z.x, 2) + Math.Pow(z.y, 2) < max) && (Math.Pow(d.x, 2) + Math.Pow(d.y, 2) > min) && (n < iter))
                    {
                        t = z;
                        p = Math.Pow(Math.Pow(t.x, 2) + Math.Pow(t.y, 2), 2);
                        z.x = 2 / 3 * t.x + (Math.Pow(t.x, 2) - Math.Pow(t.y, 2)) / (3 * p);
                        z.y = 2 / 3 * t.y * (1 - t.x / p);
                        d.x = Math.Abs(t.x - z.x);
                        d.y = Math.Abs(t.y - z.y);
                        n++;
                    }
                    Clr = Color.FromArgb(255, (n * 9) % 255, 0, (n * 9) % 255);
                    br = new SolidBrush(Clr);
                    lock (ObjLock)
                    {
                        g.FillRectangle(br, mx + x, my + y, 1, 1);
                    }
 
                }
            });
            Console.WriteLine(stopWatch.Elapsed);
        }
 
        private void Draw_Newton_fractal(object sender, EventArgs e)
        {
            //Создаем перо цвета - Черный(Black)
            //Толщина - 1 пиксель:
            Pen myPen = new Pen(Color.Black, 1);
            //Объявляем объект "g" класса Graphics и предоставляем
            //ему возможность рисования на pictureBox1:
            Graphics g = Graphics.FromHwnd(pictureBox1.Handle);
            //Вызов функции отрисовки фрактала
            int mx = pictureBox1.Width, my = pictureBox1.Height; 
            Draw(mx, my, g, myPen);
        }
 
        private void Picturebox(object sender, EventArgs e)
        {
            
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            //Объявляем объект "g" класса Graphics и предоставляем
            //ему возможность рисования на pictureBox1:
            Graphics g = Graphics.FromHwnd(pictureBox1.Handle);
            //Вызов функции отрисовки фрактала
            int mx = pictureBox1.Width, my = pictureBox1.Height;
           
            ThreadPool.QueueUserWorkItem(f => { Draw2(mx, my, g); });
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            //Объявляем объект "g" класса Graphics и предоставляем
            //ему возможность рисования на pictureBox1:
            Graphics g = Graphics.FromHwnd(pictureBox1.Handle);
            //Вызов функции отрисовки фрактала
            int mx = pictureBox1.Width, my = pictureBox1.Height;
            ThreadPool.QueueUserWorkItem(f => { Draw3(mx, my, g); });
        }
    }
}
Вложения
Тип файла: rar Архив WinRAR.rar (250.0 Кб, 1 просмотров)
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.01.2020, 15:35
Ответы с готовыми решениями:

Увеличить скорость отрисовки фрактала
Здраствуйте, написал такой вот код отрисовки фрактала #include &quot;stdafx.h&quot; #include...

Оптимизация работы приложения
Добрый день, уважаемые форумчане! Столкнулся со следующей проблемой. Написал программу для склада...

Оптимизация работы приложения с Диспетчером печати
Постановка задачи: Есть сеть, в ней 100 ПК. К 15 ПК физически подключены принтера. Все принтера...

Какие существуют приложения для отрисовки блок-схем?
Можно ли сделать алгоритм в c++ как делали на бумаги(фигурами)

2
0 / 0 / 0
Регистрация: 19.12.2018
Сообщений: 2
04.01.2020, 16:36  [ТС] 2
Вот функция и ее вызов, в котором нужно изменить метод отрисовки

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public void Draw3(int mx1, int my1, Graphics g)
        {
            // Ускорит отрисовку (оптимизация)
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
            // Очистим элемнты
            g.Clear(Color.Black);
            // Засекаем время
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
 
            int n, mx, my;
            double p;
            Complex z, t, d = new Complex();
 
            mx = mx1 / 2;
            my = my1 / 2;
 
            Parallel.For(-my, my, y =>
            //for (int y = -my; y < my; y++)
            {
                for (int x = -mx; x < mx; x++)
                {
                    n = 0;
                    z.x = x * 0.005;
                    z.y = y * 0.005;
                    d = z;
 
                    while ((Math.Pow(z.x, 2) + Math.Pow(z.y, 2) < max) && (Math.Pow(d.x, 2) + Math.Pow(d.y, 2) > min) && (n < iter))
                    {
                        t = z;
                        p = Math.Pow(Math.Pow(t.x, 2) + Math.Pow(t.y, 2), 2);
                        z.x = 2 / 3 * t.x + (Math.Pow(t.x, 2) - Math.Pow(t.y, 2)) / (3 * p);
                        z.y = 2 / 3 * t.y * (1 - t.x / p);
                        d.x = Math.Abs(t.x - z.x);
                        d.y = Math.Abs(t.y - z.y);
                        n++;
                    }
                    Clr = Color.FromArgb(255, (n * 9) % 255, 0, (n * 9) % 255);
                    br = new SolidBrush(Clr);
                    lock (ObjLock)
                    {
                        g.FillRectangle(br, mx + x, my + y, 1, 1);
                    }
 
                }
            });
            Console.WriteLine(stopWatch.Elapsed);
        }
C#
1
2
3
4
5
6
7
8
9
private void button3_Click(object sender, EventArgs e)
        {
            //Объявляем объект "g" класса Graphics и предоставляем
            //ему возможность рисования на pictureBox1:
            Graphics g = Graphics.FromHwnd(pictureBox1.Handle);
            //Вызов функции отрисовки фрактала
            int mx = pictureBox1.Width, my = pictureBox1.Height;
            ThreadPool.QueueUserWorkItem(f => { Draw3(mx, my, g); });
        }
0
2392 / 1442 / 766
Регистрация: 23.02.2019
Сообщений: 3,540
04.01.2020, 17:47 3
Вы можете воспользоваться ручной буферизацией.

Например изменив самый первый медленный метод Draw, добавив в него 7 строк, вы значительно сократите время рендера (до 4 секунд вместо... пары минут).

Ваш метод Draw может измениться вот так, всё что добавлено - отмечено комментариями
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public void Draw(int mx1, int my1, Graphics g, Pen pen)
{
    //----------------ДОБАВЛЕНО
    BufferedGraphicsContext currentContext;
    BufferedGraphics myBuffer;
    currentContext = BufferedGraphicsManager.Current;
    myBuffer = currentContext.Allocate(g, this.DisplayRectangle);
    //-----------------------------------
 
    // Очистим элемнты
    g.Clear(Color.Black);
    // Засекаем время
    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();
 
    int n, mx, my;
    double p;
    Complex z, t, d = new Complex();
 
    mx = mx1 / 2;
    my = my1 / 2;
 
    for (int y = -my; y < my; y++)
    {
        for (int x = -mx; x < mx; x++)
        {
            n = 0;
            z.x = x * 0.005;
            z.y = y * 0.005;
            d = z;
 
            while ((Math.Pow(z.x, 2) + Math.Pow(z.y, 2) < max) && (Math.Pow(d.x, 2) + Math.Pow(d.y, 2) > min) && (n < iter))
            {
                t = z;
                p = Math.Pow(Math.Pow(t.x, 2) + Math.Pow(t.y, 2), 2);
                z.x = 2 / 3 * t.x + (Math.Pow(t.x, 2) - Math.Pow(t.y, 2)) / (3 * p);
                z.y = 2 / 3 * t.y * (1 - t.x / p);
                d.x = Math.Abs(t.x - z.x);
                d.y = Math.Abs(t.y - z.y);
                n++;
            }
            pen.Color = Color.FromArgb(255, (n * 9) % 255, 0, (n * 9) % 255);
 
            //g.DrawRectangle(pen, mx + x, my + y, 1, 1);
 
            //---------------- ДОБАВЛЕНО
            myBuffer.Graphics.DrawRectangle(pen, mx + x, my + y, 1, 1);
            //-----------------------------------
 
        }
    }
    //----------------ДОБАВЛЕНО
    myBuffer.Render();
    myBuffer.Dispose();
 
    Console.WriteLine(stopWatch.Elapsed);
}
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.01.2020, 17:47
Помогаю со студенческими работами здесь

Оптимизация отрисовки DataGridView
Проблема #1. При первом запуске формы медленно прорисовывется DGV. Столбцы и строки добавляю во...

Оптимизация отрисовки, или как добиться плавности интерфейса
Во время написания проги заметил очень неприятный эффект. При максимизации (развертывании) её на...

Оптимизация приложения для распознавания дорожной разметки
Написала программу на Питоне для распознавания дорожной разметки. За одну секунду обрабатывается...

Оптимизация программы для работы со списками
Здравствуйте! Написал код, который мне скоро сдавать по предмету. Хотелось бы узнать как его...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru