Лучший отвечающий
List, for и события

Вопрос
-
В событии постоянно приходят новые данные:
private void SmartServer_AddTick(string symbol, System.DateTime datetime, double price, double volume, string tradeno, StClientLib.StOrder_Action action) { AllTicks.Add(new Tick(datetime, price, volume, tradeno, action)); }
Я их добавляю в список AllTicks. Каждое значение Price из этих данных рисую на экране в виде точки:
if (AllTicks.Count > 0) { Gl.glBegin(Gl.GL_POINTS); for (int x = 1518, i = AllTicks.Count - 1; (i > AllTicks.Count - 1519) && (i >= 0); x--, i--) { Gl.glVertex2i(x, (int)AllTicks[i].Price - ScaleCor); } Gl.glEnd(); }
В итоге график рисуется не точный. Т.е. по идее, каждому значению координаты X должно соответствовать только одно значение Price. На графике же видно, что в некоторых местах координате X не соответствует ни одного значения Price, а в соседней координате X рисуется сразу 2 значения Price. Визуально график двигается с права налево частями, а должен двигаться не меняя расстояние между точками.
Будьте любезны, подскажите как это можно побороть.
17 мая 2011 г. 18:30
Ответы
-
После долгих мытарств найдена логика. Нужно делать так, в любом другом случае будут искажения масштаба на экране:
Gl.glViewport(0, 0, TaoWin.Width + 1, TaoWin.Height + 1); // устанавливаем проекционную матрицу Gl.glMatrixMode(Gl.GL_PROJECTION); // очищаем ее Gl.glLoadIdentity(); // Вычисляем новые геометрические размеры сцены; Glu.gluOrtho2D(0.0, TaoWin.Width, 0.0, TaoWin.Height); // переходим к объектно-видовой матрице Gl.glMatrixMode(Gl.GL_MODELVIEW); Gl.glLoadIdentity();
- Помечено в качестве ответа 4dimuser 29 мая 2011 г. 9:56
29 мая 2011 г. 9:56
Все ответы
-
Это нужно просто пощагово щупать, что входит, где и как проходит, и что получается.
Если ошибки возникают синхронно, т.е. на одних и тех же данных,
то в тексте программы нужно попытаться сформулировать условие ошибки
и пометить это место точкой останова.for сложен - отслеживаются одновременно две переменные, лучше пользоваться простыми структурами.
При каждом добавлении тика перерисовывается весь список, причем в обратном порядке?
Это нелогично.Событий здесь я не вижу - Вы поймали тик по какому-то событию,
а здесь пытаетесь этот тик нарисовать.18 мая 2011 г. 3:41 -
После AllTicks.Add данные добавляются корректно. Пробовал выводить на экран в виде текста последний тик AllTicks[AllTicks.Count - 1].Price, все выводится точно, никаких ошибок. OpenGL тоже корректно работает. Ошибка именно в for.
1. Вы говорили про простые структуры, это что такое?
2. Почему не логично перерисовывать список в обратном порядке? Начало координат (0;0) - левый нижний угол. Правый верхний угол (1919;1079). Я вывожу только последние 1518 тиков от i = AllTicks.Count - 1 до i > AllTicks.Count - 1519. X при этом от 1518 до 0. Есть другие варианты?
18 мая 2011 г. 7:09 -
"Ошибка именно в for"- возможно.
В операторе for используется обычно только счетчик циклов,
т.е. вы должны сформулировать, сколько итераций вам нужно произвести.
Формирование номера точки я бы привязал к счетчику и расположил бы в теле цикла,
в фигурных скобках.
"Почему не логично перерисовывать список в обратном порядке?"
Да. Можно и так, это я привык обходиться без перерисовок,
поэтому глаз и цепляется.В общем, нужно определить какие точки выпадают,
тогда и решение придет само собой18 мая 2011 г. 7:42 -
Когда Вы говорили про простые структуры, Вы что имели в виду, Do while? Какие простые структуры существуют для отслеживания двух переменных?18 мая 2011 г. 7:53
-
Нет, я имел в виду, более простой for - это ведь только цикл со своим счетчиком, не более.
Все остальное отвлекает.18 мая 2011 г. 8:25 -
Переделал так
int x = 1518, i = AllTicks.Count - 1; do { Gl.glVertex2i(x, (int)AllTicks[i].Price - ScaleCor); x--; i--; } while ((i > AllTicks.Count - 1519) && (i >= 0));
Все равно тоже самое. Если перестать записывать новые тики в список, то ошибка остается. Как же мне сделать более простой for, если необходимо отслеживать две переменные.18 мая 2011 г. 10:11 -
Сейчас попробовал перейти в полноэкранный режим и проблема исчезла, а в оконном режиме проблема остается. Значит это не for.
Прям полтергейст какой-то. Может кто может сказать в чем причина сего действа?
public FormFS() { InitializeComponent(); // Инициализируем работу TaoWin; TaoWin.InitializeContexts(); // Инициализация OpenGL // !!!Последовательность строк имеет значение!!! InitGL(); ResizeGlScene(); } public FormFS(bool fullscreen) { InitializeComponent(); // Инициализируем работу TaoWin; TaoWin.InitializeContexts(); // Инициализация OpenGL // !!!Последовательность строк имеет значение!!! InitGL(); ResizeGlScene(); } // Инициализация OpenGL private void InitGL() { Glut.glutInit(); Glut.glutInitDisplayMode(Glut.GLUT_RGB | Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH); } // Изменение размеров окна OpenGL void ResizeGlScene() { // очитка окна черным цветом Gl.glClearColor(0, 0, 0, 1); // Сбрасываем текущую область просмотра; Gl.glViewport(0, 0, TaoWin.Width, TaoWin.Height); // Выбираем матрицу проекций; Gl.glMatrixMode(Gl.GL_PROJECTION); // Сбрасываем выбранную матрицу; Gl.glLoadIdentity(); // Вычисляем новые геометрические размеры сцены; Glu.gluOrtho2D(0.0, TaoWin.Width, 0.0, TaoWin.Height); // Выбираем матрицу вида модели; Gl.glMatrixMode(Gl.GL_MODELVIEW); // Сбрасываем ее; Gl.glLoadIdentity(); } //РИСОВАНИЕ СЦЕНЫ private void DrawGlScene() { // Очищаем экран выбранным цветом; Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT); // Сбрасываем текущую матрицу проекций; Gl.glLoadIdentity(); // утснаовка зеленого цвета Gl.glColor3f(0, 255, 0); // Текст цены и объема первого бида стакана PrintText2D(1560, (int)Glassful[0].Bid - ScaleCor - 3, Glassful[0].Bid.ToString()); PrintText2D(1540, (int)Glassful[0].Bid - ScaleCor - 3, Glassful[0].Bidsize.ToString()); //Линия объема первого бида стакана Gl.glBegin(Gl.GL_LINES); Gl.glVertex2i(1520, (int)Glassful[0].Bid - ScaleCor); Gl.glVertex2i(1520 + (int)Glassful[0].Bidsize, (int)Glassful[0].Bid - ScaleCor); Gl.glEnd(); // утснаовка красного цвета Gl.glColor3f(255, 0, 0); // Текст цены и объема первого аска стакана PrintText2D(1560, (int)Glassful[0].Ask - ScaleCor - 3, Glassful[0].Ask.ToString()); PrintText2D(1540, (int)Glassful[0].Ask - ScaleCor - 3, Glassful[0].Asksize.ToString()); //Линия объема первого аска стакана Gl.glBegin(Gl.GL_LINES); Gl.glVertex2i(1520, (int)Glassful[0].Ask - ScaleCor); Gl.glVertex2i(1520 + (int)Glassful[0].Asksize, (int)Glassful[0].Ask - ScaleCor); Gl.glEnd(); // утснаовка белого цвета Gl.glColor3f(255, 255, 255); // Линии от курсора Gl.glBegin(Gl.GL_LINES); Gl.glVertex2i(2, 30); Gl.glVertex2i(1918, 30); // 1917+1 Gl.glVertex2i(30, 2); Gl.glVertex2i(30, 1078); // 1077+1 Gl.glVertex2i(0, 120); // 119+1 Gl.glVertex2i(0, 20); Gl.glVertex2i(1919, 120); // 119+1 Gl.glVertex2i(1919, 20); Gl.glVertex2i(20, 0); Gl.glVertex2i(120, 0); // 119+1 Gl.glVertex2i(20, 1079); Gl.glVertex2i(120, 1079); // 119+1 Gl.glVertex2i(Mcoord_X, 1080); // 1079+1 Gl.glVertex2i(Mcoord_X, 0); Gl.glVertex2i(0, Mcoord_Y); Gl.glVertex2i(1920, Mcoord_Y); Gl.glEnd(); Gl.glBegin(Gl.GL_POINTS); Gl.glVertex2i(0, 0); Gl.glVertex2i(1, 1); Gl.glVertex2i(2, 2); Gl.glVertex2i(1919, 1079); Gl.glVertex2i(1918, 1078); Gl.glVertex2i(1917, 1077); Gl.glEnd(); if (AllTicks.Count > 0) { Gl.glBegin(Gl.GL_POINTS); int x = 1518, i = AllTicks.Count - 1; do { Gl.glVertex2i(x, (int)AllTicks[i].Price - ScaleCor); x--; i--; } while ((i > AllTicks.Count - 1519) && (i >= 0)); Gl.glEnd(); // утснаовка белого цвета Gl.glColor3f(255, 255, 255); PrintText2D(1400, 550, AllTicks[AllTicks.Count - 1].Price.ToString()); } // выводим текст со значением координаты Y if (Mcoord_Y < 1060) PrintText2D(1679, Mcoord_Y + 6, Mcoord_X.ToString() + ";" + Mcoord_Y.ToString()); else if (Mcoord_Y >= 1060) PrintText2D(1679, Mcoord_Y - 17, Mcoord_X.ToString() + ";" + Mcoord_Y.ToString()); Gl.glFlush(); TaoWin.Invalidate(); } // Обработчик события изменения размеров формы; private void FormFS_Resize(object sender, EventArgs e) { // Вначале изменим размеры сцены; ResizeGlScene(); // А потом перерисуем; DrawGlScene(); } // Смена режима (Fullscreen/Window) private void ScreenMode(bool fullscreen) { // Присваиваем значение "глобальной" переменной; FS = fullscreen; if (FS) { // *** ПОЛНОЭКРАННЫЙ РЕЖИМ *** // Скрываем рамку окна; this.FormBorderStyle = FormBorderStyle.None; // Разворачиваем окно; this.WindowState = FormWindowState.Maximized; } else { // *** ОКОННЫЙ РЕЖИМ *** // Возвращаем состояние окна; this.WindowState = FormWindowState.Normal; // Показываем масштабируемую рамку окна; this.FormBorderStyle = FormBorderStyle.None; } ResizeGlScene(); } private void FormFS_KeyDown(object sender, KeyEventArgs e) { // Нажата клавиша ЕSCAPE; if (e.KeyCode == Keys.Escape) { // Отключаемся Disconnect(); // Завершим приложение; this.Close(); } // Нажата клавиша F2; if (!FS && e.KeyCode == Keys.F2) { // Изменяем режим на ПОЛНОЭКРАННЫЙ; ScreenMode(true); // Прячем курсор; Cursor.Hide(); } // Нажата клавиша F1; if (FS && e.KeyCode == Keys.F1) { // Изменяем режим на оконный; ScreenMode(false); // Показываем курсор; Cursor.Hide(); } } private void RefreshTimer_Tick(object sender, EventArgs e) { DrawGlScene(); } private void TaoWin_MouseMove(object sender, MouseEventArgs e) { // вычисляем параметры для будующей дорисовке линий от указателя мыши к координатным осям. Mcoord_X = e.X; Mcoord_Y = (int)(TaoWin.Height - e.Y - 1); } private void PrintText2D(int x, int y, string text) { // устанавливаем позицию вывода растровых символов // в переданных координатах x и y. Gl.glRasterPos2i(x, y); // в цикле foreach перебираем значения из массива text, // который содержит значение строки для визуализации foreach (char char_for_draw in text) { // визуализируем символ c, с помощью функции glutBitmapCharacter, используя шрифт GLUT_BITMAP_HELVETICA_10. Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_10, char_for_draw); } }
Извините за длинный текст
18 мая 2011 г. 10:28 -
Может быть, как я уже говорил, Ваш график ограничен снизу и сверху, и пропуски - это значения выше или ниже ограничений.
Полтергейст - это нормальное явление в программировании.18 мая 2011 г. 11:19 -
Это исключено. Каждое следующее значение отличается от предыдущего на очень маленькую величину. К тому же у меня на экран в виде цифры выдается это значение, поэтому я бы заметил.
Еще я заметил, что если навести курсор мыши на место пропусков, то таким же образом не отображается линия, идущая от верхней границы монитора к нижней через курсор мыши. Хотя, во всех других точках экрана линия, проходящая через курсор мыши отображается корректно.
18 мая 2011 г. 12:30 -
Тогда нужно ловить эти точки и смотреть, что происходит.
Еще может быть ситуация, когда дискрет графика по x не вполне соответствует сумме пикселей,
например, 1 минута - это не строго 10, а 10.05 или 9.95 пикселей, тогда ошибка будет накапливаться и
в какой-то момент будет перескок.18 мая 2011 г. 13:27 -
С точками, как оказалось, все в порядке. В полноэкранном режиме все отображается корректно, а в оконном не корректно. Здесь что-то с OpenGL, код рисующий все ведь один и для полноэкранного режима и для оконного.18 мая 2011 г. 13:52
-
OpenGL - это для меня темный лес18 мая 2011 г. 13:59
-
Можно еще попробовать следующий прием.
Привязать график к форме, чтобы график увеличивался или уменьшался с изменением размера формы.
и посмотреть, будет ли что-либо меняться.- Помечено в качестве ответа Abolmasov Dmitry 27 мая 2011 г. 5:47
- Снята пометка об ответе 4dimuser 29 мая 2011 г. 9:57
18 мая 2011 г. 15:43 -
Уважаемый пользователь, пожалуйста, не забудьте отметить ответ/ответы, которые решили вашу проблему. Для этого под каждым сообщением есть кнопка 'Пометить как ответ'. Спасибо.
Для связи [mail]18 мая 2011 г. 18:25 -
Я бы с радостью, но проблема не решена. Данный код абсолютно корректно выводит график в полноэкранном режиме, А в оконном режиме некоторые точки графика не прорисовываются. Видимо проблема в OpenGL, но где именно понять не могу. Очень надеюсь на ваш совет.19 мая 2011 г. 10:28
-
Если без деталей - я думаю, проблема решиться если отделить цепочку событий (поток), в который данные накапливаются от другого потока (посмотрите к примеру в сторону BackgroundWorker класса и прочей организации многопоточности), в котором имеет смысл организовать отрисовку.
Вариантов как это сделать - масса. Общую мысль я изложил. Дерзайте!
Don't forget to vote for useful replies and/or mark answers for your questions - that helps other guys to find the answer faster.- Помечено в качестве ответа Abolmasov Dmitry 27 мая 2011 г. 5:43
- Снята пометка об ответе 4dimuser 29 мая 2011 г. 9:57
24 мая 2011 г. 20:17 -
Проблему решил. Может кому пригодится. Просто слов нет от тупости OpenGL.
Если размер окна 1575; 1078, то плоскость почему-то надо задавать именно так:
Gl.glViewport(0, 0, TaoWin.Width, TaoWin.Height); Glu.gluOrtho2D(0.0, 1574, 0.0, TaoWin.Height);
Искажения возникали из-за того, что вместо цифры 1574 стояла TaoWin.Width, равная 1575.
Почему таким же образом не надо вместо TaoWin.Height не надо ставить 1077 одному богу известно.
27 мая 2011 г. 15:19 -
После долгих мытарств найдена логика. Нужно делать так, в любом другом случае будут искажения масштаба на экране:
Gl.glViewport(0, 0, TaoWin.Width + 1, TaoWin.Height + 1); // устанавливаем проекционную матрицу Gl.glMatrixMode(Gl.GL_PROJECTION); // очищаем ее Gl.glLoadIdentity(); // Вычисляем новые геометрические размеры сцены; Glu.gluOrtho2D(0.0, TaoWin.Width, 0.0, TaoWin.Height); // переходим к объектно-видовой матрице Gl.glMatrixMode(Gl.GL_MODELVIEW); Gl.glLoadIdentity();
- Помечено в качестве ответа 4dimuser 29 мая 2011 г. 9:56
29 мая 2011 г. 9:56 -
Какая фигня, я и слова-то эти уже позабыл...
А все потому, что Вы решили вместо графиков рисовать мультики29 мая 2011 г. 14:09