Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Система рисования. Печать _ Фигуры Лиссажу

Автор: QMainWindow 18.10.2010, 21:54

Добрый день!
Вот подумываю написать по фану программу, генерирующая эти фигуры. Возникли 3 вопроса:
1. Какой класс лучше использовать? Здесь придется очень часто обновлять экран - 0-500ГЦ. Пейнтер, наверное, не подойдет.
2. С помощью чего обновлять экран. Можно отталкиваться от QTimer. Но рационально ли это?
3. Как сделать остаточный след на экране (как в осциллографе, даже если двигать точку медленно, то все равно будет заметна светимость следа)?

Заранее СПС.))

Автор: ufna 18.10.2010, 21:58

1. обновления в Гцах - это уже для монитора вопрос, в мс сколько?

Если не QPainter - советую писать на ассемблере или уж лучше напрямую работать с видеокарточкой :) Ну или забить на Qt и юзать DirectX/OGL, шейдеры и т.п.

Вопрос - что это за фигуры в принципе?

2. обновлять экран - можно по таймеру, это рациоально. Можно - тупо апдейтить и апдейтить в конце каждой перерисовки.

3. двойная буферизация как возможный вариант. Хотя это к вопросу №1 больше, т.к. далее - дело техники

Автор: QMainWindow 18.10.2010, 22:28

Гц - это я вспоминаю значения, стоявшие на осциллографе у нас, когда была практическая работа по данной теме. Т.е. в данном случае - герцы - значения на осциллографе.
Ну я не такой крутой кодер, чтобы уж прям с видеокартой напрямую работать))) Лучше средствами Qt. А OpenGL на Qt может подойти? Или для таких дел QPainter тоже может сгодиться. Я просто почему спрашиваю, потому вот сделаю через Пейнтер, а потом окажется, что можно было делать через другой класс, который подходит лучше.))
Вот ссылка: http://ru.wikipedia.org/wiki/Фигуры_Лиссажу. Тут написано лучше, чем скажу я.

Автор: ufna 18.10.2010, 22:51

я далек от осцилографов, но в графике имеют значения мс, а вот как вы их уже к герцам приложите - вопрос по области применения

OpenGL и Qt дружат отлично, но - здесь те же системы отрисовки, графика то 2Д и динамическая.

Тут как бы - а "другой" - это какой класс? :) QPainter - по сути основа всей отрисовки в Qt. Если не оно, то уже только в видеокарту лезть :)

Вначале переведите герцы нужные Вам в фпс, просчитайте скорость обработки одного кадра чисто математически - а потом уже начинайте реализацию :) логика отрисовки не сильно зависит от выбранного АПИ в данном случае, имхо.

Автор: Алексей1153 19.10.2010, 6:22

никаких жутких ухищрений не нужно, компутер успеет такую фигуру нарисовать и в динамике :)

параметрически кривая задана


единственное, что надо сделать - задать инерцию люминофора. То есть просто точку гонять по кривой недостаточно - глаз не обманется. Надо запоминать шлейф на 1/24 секунды назад и отрисовывать эту линию

тактировать можно таймером этак 40...200 мс

Автор: Litkevich Yuriy 19.10.2010, 8:50

Цитата(QMainWindow @ 19.10.2010, 1:28) *
а потом окажется, что можно было делать через другой класс, который подходит лучше.))
а другого в Qt нету. QPainter - рисовальщик всех примитивов

Цитата(QMainWindow @ 19.10.2010, 0:54) *
2. С помощью чего обновлять экран. Можно отталкиваться от QTimer. Но рационально ли это?
Цитата(QMainWindow @ 19.10.2010, 0:54) *
3. Как сделать остаточный след на экране (как в осциллографе, даже если двигать точку медленно, то все равно будет заметна светимость следа)?
полностью имитировать работу осциллографа на компьютере не стоит.
Для начала просто рисуй, пусть накладываются. Если дальше захочешь развивать программу там и видно будет.

П.С. где-то у меня была программка на дельфи 4, которая именно фигуры Лисажу рисовала

Автор: QMainWindow 19.10.2010, 17:02

А OpenGL? Или пейнтера с головой хватит?

Автор: Алексей1153 19.10.2010, 19:13

QMainWindow, ты сначала с QPainter сделай что-нибудь, а там увидим :)

Автор: QMainWindow 27.10.2010, 20:13

Привет всем!
Короч только что написал прогу. Все хорошо получилось, делал через QPainter. Единственное, что осталось - это след на экране. Как правильно сделать - не знаю. На данный момент, чтобы изображение отображалось, в paintEvent записал цикл с N = 200. Но это все же не след.
Вот тут говорили про буфер. Никогда не работал, не знаю как это работает. Какие классы хоть смотреть? :)

Автор: Алексей1153 27.10.2010, 20:18

QMainWindow, используй вектор

std::vector<QLine>(200) trace_buffer;

организуй кольцо - заведи два итератора- один на начало следа, второй на конец


отрисовав ломаную линию (кстати, по любасу метод есть, чтобы цепь QLine вывести разом) , делай сдвиг, выкидывая из начала несколько звеньев. А новые добавляй в конец. Приоритет делай для конца - если кольцо полностью забито, то выкидывай начальные и добавляй новые в конец

можно ещё поиграться с градиентным цветом очередных линий (QLine), будет совсем как люминофор ))

Автор: QMainWindow 27.10.2010, 22:14

Сделал через вектор на 200 элементов - тормознуто! При одной и той же частоте W цикл бегает по экрану много быстрее чем вектор.((

Автор: kwisp 27.10.2010, 22:20

Цитата(QMainWindow @ 27.10.2010, 23:14) *
Сделал через вектор на 200 элементов - тормознуто!

код покажи?
как сделал?

Автор: QMainWindow 27.10.2010, 22:32

MainWindow::MainWindow()
{...
for(i=0; i<200; i++)
    {
        TraceBufferX.push_front(0);
        TraceBufferY.push_front(0);
    }
...
}

void MainWindow::Start()
{
    connect(timer, SIGNAL(timeout()), this, SLOT(NewFrame()));
    timer->start(10);
}

void MainWindow::NewFrame()
{
    TraceBufferX.pop_back();
    TraceBufferY.pop_back();
    TraceBufferX.push_front(R1*cos(w1*t+f1));
    TraceBufferY.push_front(R2*sin(w2*t+f2));
    t=t+dt;
    update();
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.fillRect(2,2,506,506,QColor("#67b56c"));
    painter.setMatrix(QMatrix(1,0,0,-1,255,255));
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(QPen(QColor(255,0,0), 3, Qt::SolidLine, Qt::RoundCap));
    for(i=0; i<int(exp(w0/4.5)); i++)
    {
        painter.drawPoint(R1*cos(w1*(t-0.1*i)+f1), R2*sin(w2*(t-0.1*i)+f2)); //-- цикл
        //painter.drawLine(TraceBufferX.value(i), TraceBufferY.value(i), TraceBufferX.value(i-1), TraceBufferY.value(i-1)); //--либо линией рисовать
        //painter.drawPoint(TraceBufferX.value(i), TraceBufferY.value(i)); //--либо точками.
    }

}

Автор: kwisp 27.10.2010, 22:41

Цитата(QMainWindow @ 27.10.2010, 23:14) *
При одной и той же частоте W цикл бегает по экрану много быстрее чем вектор

этого в коде не увидел.
где вектор.?
подпиши все переменные.

Цитата(QMainWindow @ 27.10.2010, 23:32) *
for(i=0; i<200; i++)
{
TraceBufferX.push_front(0);
TraceBufferY.push_front(0);
}

вот это вообще странная запись

Автор: QMainWindow 27.10.2010, 22:49

Сделал, чтобы не писать оператора if, когда нужно удалять последний элемент, след же не бесконечный. Буфера - координаты точек следа по x и y. t - время.

могу прогу скинуть, код короткий

Автор: Алексей1153 28.10.2010, 0:17

QMainWindow, я ж предложил кольцо сделать. Размер вектора не меняется при этом. Это будет просто аналог статического массива на время жизни экземпляра вектора

а тормоза вот тут

    for(i=0; i<int(exp(w0/4.5)); i++)
    {
        painter.drawPoint(R1*cos(w1*(t-0.1*i)+f1), R2*sin(w2*(t-0.1*i)+f2)); //-- цикл
    }


вот, чем надо выводить полилинию из вектора-кольца :)

void QPainter::drawLines ( const QLine * lines, int lineCount )

Цитата(kwisp @ 28.10.2010, 1:41) *
могу прогу скинуть, код короткий

скинь. Только в 3 ночи возиться лично я не буду - я скоро спать ))

Автор: QMainWindow 28.10.2010, 8:28

Вот: http://ifolder.ru/19986495
Код простой, подписывать ничего не стал, т.к. особо и нечего.))

Автор: Алексей1153 28.10.2010, 8:37

QMainWindow, не открывается ссылка. Сделай проще - удали папки release и debug, да архивчик тут подвесь

Автор: Алексей1153 28.10.2010, 9:35

QMainWindow, я скачал таки. Ищу драчовый напильник, доводить до ума )))

вообще то, плоттеры обычно делают в новом классе, так ГОРАЗДО УДОБНЕЕ. Но это переделывать я не буду - сам уж сделаешь

Автор: Алексей1153 28.10.2010, 11:28

вот, что у меня вышло. Правда, кольцевой буфер содержит сейчас QPoint, но нпеределать в QLine не сложно - когда кладёшь очередную точку добавляй линию. Это сделай сам, а мне щас работать надо ))


приращение времени я в регулируемое окошко не выводил, тоже сам делай

m_t+=3;//dt;


Автор: QMainWindow 28.10.2010, 20:39

Спасибо, а где собственно прикрепленный архив? :) Не видно что-то...

Автор: Алексей1153 28.10.2010, 20:44

QMainWindow, хм, я , видать, забыл кнопочку нажать. А потом форум был в дауне.

С собой нету проекта, завтра с работы скину

Автор: Алексей1153 29.10.2010, 6:47

ха, я понял, почему не прицепился файл. Дурацкое ограничение - использовать только зип. А у меня в раре был

 DotRotating.zip ( 14.08 килобайт ) : 86
 

Автор: Litkevich Yuriy 29.10.2010, 9:44

Тему разделил: http://www.forum.crossplatform.ru/index.php?showtopic=5856

Автор: QMainWindow 29.10.2010, 20:09

Спасибо за прогу, посмотрел.
Обнаружился интересный феномен (по крайней для меня).
Вот код:

void MainWindow::Start()
{
    connect(timer, SIGNAL(timeout()), this, SLOT(NewFrame()));
    timer->start(10);
}

и слот:
void MainWindow::NewFrame()
{
    Tr.remove(1);
    Tr.append(QLineF(R1*cos(w1*t+f1), R2*sin(w2*t+f2), R1*cos(w1*(t-dt)+f1), R2*sin(w2*(t-dt)+f2)));
    t=t+dt;
    update();
}

Это кнопка Старт. Прикол в том, что если на нее нажимать много раз, не меняя какие-либо параметры на панели, то точка на экране начнет двигаться быстрее и быстрее. Как это можно объяснить?

Автор: Алексей1153 29.10.2010, 20:45

QMainWindow, точно утверждать не могу, но, возможно, ты соединяешь сигнал со слотом ещё раз, следовательно таймер срабатывает с "дребезгом"

Делай контроль количества соединений. Или по кнопке "стоп" рассоединяй сигнал и слот

А ещё лучше - соединить один раз в конструкторе и больше не трогать :)

Автор: Litkevich Yuriy 29.10.2010, 21:37

Цитата(Алексей1153 @ 29.10.2010, 23:45) *
QMainWindow, точно утверждать не могу, но, возможно, ты соединяешь сигнал со слотом ещё раз, следовательно таймер срабатывает с "дребезгом"
Алексей, почти в яблочко. Только вместо дребезга картинка такая:
сколько раз сигнал соединён с одним и тем же слотом, столько раз он и будет доставлен в слот.

QMainWindow, Если MainWindow::Start() - это слот, то фкнцияю соединения вынеси туда, где создаётся объект таймера. А в этом слоте только запускай таймер

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)