Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: ann-joker от Май 20, 2012, 07:32



Название: y = cos (x)
Отправлено: ann-joker от Май 20, 2012, 07:32
задание: нарисовать косинусоиду.
пытаюсь сделать таким образом, но ничего не отображается.
x, y - double;
prevX, prevY, curX, curY - int.

Код:
#include "mainwindow.h"
#include <cmath>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{

    widget=new QWidget;
    QVBoxLayout *vb=new QVBoxLayout;
    widget->setLayout(vb);
    widget->setStyleSheet("background-color::white");
    this->setCentralWidget(widget);
    this->setFixedSize(500,500);
    x = (- (3 * 3.14)) + 100;
    y = cos (x) + 100;

}

MainWindow::~MainWindow()
{

}


void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter *painter = new QPainter(this);
    QPen pen(QColor(Qt::darkGreen));

    painter->drawPixmap(this->width(), this->height(), QPixmap());
    pen.setWidth(2);
    painter->setRenderHint(QPainter::Antialiasing, true);
    painter->setPen(pen);
    painter->setBrush(Qt::darkGreen);

    while (x < 3 * 3.14 + 100){

        prevX = x;
        prevY = y;

        x = x + 1;
        y = cos(x);

        curX = x;
        curY = y;
       
        painter->drawLine(prevX, prevY, curX, curY);
    }
    this->update();
}



Название: Re: y = cos (x)
Отправлено: ann-joker от Май 20, 2012, 07:39
и как еще в MessageBox'е вывести точки соприкосновения с осью абсцисс?
как найти - знаю, а как в бокс записать эти числа?


Название: Re: y = cos (x)
Отправлено: V1KT0P от Май 20, 2012, 11:18
и как еще в MessageBox'е вывести точки соприкосновения с осью абсцисс?
как найти - знаю, а как в бокс записать эти числа?
Незнание программирования, незнание геометрии...
Вот твой адаптированный код:
Код
C++ (Qt)
void MainWindow::on_pushButton_clicked()
{
   QPixmap pix(500, 500);
   QPainter painter(&pix);
   QPen pen(QColor(Qt::darkGreen));
 
   painter.fillRect(QRect(0, 0, 500, 500), Qt::white);
   pen.setWidth(2);
   painter.setRenderHint(QPainter::Antialiasing, true);
   painter.setPen(pen);
   painter.setBrush(Qt::darkGreen);
   double prevX = 0/180.0*M_PI;
   double prevY = cos(prevX)*10+100;
   double curX;
   double curY;
   for (double i=1; i<720; i+=1) {
       curX = i/180.0*M_PI;
       curY = cos(curX);
 
       painter.drawLine(prevX, prevY, i, curY*10+100);
       prevX = i;
       prevY = curY*10+100;
   }
   ui->label->setPixmap(pix);
}
В аттаче картинка.
Это ты что лабу делаешь?


Название: Re: y = cos (x)
Отправлено: ann-joker от Май 20, 2012, 11:24

уоу. спасибо!

да, видимо, геометрия вообще страдает.. а программирование учу, как могу.
можете объяснить, почему так?
только без упреков, если можно..


Название: Re: y = cos (x)
Отправлено: V1KT0P от Май 20, 2012, 11:40
уоу. спасибо!

да, видимо, геометрия вообще страдает.. а программирование учу, как могу.
можете объяснить, почему так?
только без упреков, если можно..
1) Ты через-жопно начал строить график на форме, это плохо. Я для примера привел как в картинку нарисовать и ее отобразить в QLabel.
2) Попробуй посчитать минимальные и максимальные значения получаемых x и y в твоем примере. x: от 90.58 до 109.42, y: от -1 до 1. Вот и получается фигня шириной 20 пикселей и высотой 3 пикселя, при чем видна будет полоска высотой 2 пикселя(Там где положительное y).
3) paintEvent срабатывает каждый раз при необходимости отрисовки, а у тебя после первой отрисовки значение x не сбрасывается к изначальному. Поэтому после второго срабатывания paintEvent уже не отрисовывает твой график и тебе кажется что функция не работает.


Название: Re: y = cos (x)
Отправлено: Igors от Май 20, 2012, 12:22
Вот твой адаптированный код:
Конечно для лабы "более чем достаточно", но вбивание 10, 100, 720 все-таки не есть хорошо  :)
И было бы интересно написать ф-цию которая рисует любой график принимая функтор в качестве одного из аргументов  (такие штучки любит m_ax)


Название: Re: y = cos (x)
Отправлено: V1KT0P от Май 20, 2012, 12:28
Вот твой адаптированный код:
Конечно для лабы "более чем достаточно", но вбивание 10, 100, 720 все-таки не есть хорошо  :)
И было бы интересно написать ф-цию которая рисует любой график принимая функтор в качестве одного из аргументов  (такие штучки любит m_ax)
Я же для примера привел. Да легко можно сделать так что график рисовался по формуле введенной пользователем, но моя цель была только указать на ошибки а не реализовывать полный функционал =).


Название: Re: y = cos (x)
Отправлено: Igors от Май 20, 2012, 12:34
Я же для примера привел. Да легко можно сделать так что график рисовался по формуле введенной пользователем, но моя цель была только указать на ошибки а не реализовывать полный функционал =).
Все мы немного умеем читать между строк, интересно было бы составить "словарь", напр

выражение                значение
----------------------------------
"да легко.."                сразу в кусты
"меня улыбнуло"        человек разярен
"учи матчасть"            да хз как

и.т.д.  :)


Название: Re: y = cos (x)
Отправлено: V1KT0P от Май 20, 2012, 12:44
"да легко.."                сразу в кусты
Хочешь поспорить что я легко смогу реализовать такой функционал? Например в случае выигрыша ты должен будешь написать кукую-нибудь программу на Qt без сторонних библиотек. Какую я выберу сам =). Хочешь поспорить?
Там реально просто:
1) Парсинг функции в древовидный вид.
2) Преобразовывание древовидного вида что-нибудь попроще, например в QScript. Либо же написать функцию которая сама будет по дереву вычислять(тут скорость побольше будет).
3) Ну и отрисовка графика на плоскости.

У меня алгоритм как это сделать уже полтора года в голове крутится. Все никак времени не найду реализовать.
Я просто хочу себе сделать продвинутый калькулятор(именно как я это вижу, ибо те что видел меня бесят просто) на Android телефон =).


Название: Re: y = cos (x)
Отправлено: iroln от Май 20, 2012, 13:28
У меня алгоритм как это сделать уже полтора года в голове крутится. Все никак времени не найду реализовать.
Я просто хочу себе сделать продвинутый калькулятор(именно как я это вижу, ибо те что видел меня бесят просто) на Android телефон =).
Алгоритм "как это сделать" можно в каком-нибудь open-source проекте посмотреть, наверняка кто-нибудь уже сделал хорошую реализацию. Те же gnuplot, matplotlib.mathtext.Parser.

Я python + IPython использую в качестве продвинутого калькулятора. Правда не знаю, портированы ли всякие matplotlib и numpy на андройд, но интерпретатор питона там точно есть. :)


Название: Re: y = cos (x)
Отправлено: Igors от Май 20, 2012, 13:32
Хочешь поспорить что я легко смогу =).
..
Хочешь поспорить?
Да не хочу я с Вами спорить :) Просто это интересно. Ну вот допустим понадобился тангенс вместо косинуса, или синус или др. Что изменится в Вашем коде? Почти ничего кроме вызова самой расчетной ф-ции. Нехорошо делать N копий кода если оно явно обобщается

Там реально просто:
1) Парсинг функции в древовидный вид.
Наверное все-таки "парсинг строки" (введенной пользователем). И задача звучит как "мини-интерпретатор". Неск раз у меня подобные потребности возникали, и ничего путного я не нашел, реализовывал сам. По существу дело сводится к разбору строки "токен за токеном". Обсуждать это здесь я пытался, но без успеха, свелось к тому что я не знаю RegExp, должен/обязан его учить и.т.п.  :)


Название: Re: y = cos (x)
Отправлено: iroln от Май 20, 2012, 13:35
Вот статья в тему: http://habrahabr.ru/post/50158/

На счёт "реально просто", я стараюсь избегать таких выражений, потому что везде есть свои подводные камни и обычное "реально просто" может оказаться совсем не просто.


Название: Re: y = cos (x)
Отправлено: V1KT0P от Май 20, 2012, 13:57
Да не хочу я с Вами спорить :) Просто это интересно. Ну вот допустим понадобился тангенс вместо косинуса, или синус или др. Что изменится в Вашем коде? Почти ничего кроме вызова самой расчетной ф-ции. Нехорошо делать N копий кода если оно явно обобщается
Где я говорил про копии кода?

Наверное все-таки "парсинг строки" (введенной пользователем). И задача звучит как "мини-интерпретатор". Неск раз у меня подобные потребности возникали, и ничего путного я не нашел, реализовывал сам. По существу дело сводится к разбору строки "токен за токеном". Обсуждать это здесь я пытался, но без успеха, свелось к тому что я не знаю RegExp, должен/обязан его учить и.т.п.  :)
Правильно, я решил что мини-интерпрератор будит рулить по скорости. Вообще он там банальный:
1) Парсинг реализуется просто в древовидную структуру.
2) Вычисление структуры начинается он низа дерева к верху, то-есть на каждом этапе имеем два числа и одну операцию. Сразу скажу что если например интеграл не интегрируется, то он преобразовывается во вложенное дерево. Это позволит не усложняя алгоритма численно интегрировать интегралы.
3) Собственно построение графика, тоже ничего сложного. Можно даже сделать так, чтоб алгоритм просчитывал точки без разрывов(скорее все такой алгоритм уже создан).

На счёт "реально просто", я стараюсь избегать таких выражений, потому что везде есть свои подводные камни и обычное "реально просто" может оказаться совсем не просто.
Там где я не уверен в простоте реализации я такого и не говорю. Тут же все довольно просто, да времени на реализацию уйдет много. Но то что для реализации требуется много времени не делает ее сложной, просто кода многовато надо будет написать.


Название: Re: y = cos (x)
Отправлено: Igors от Май 20, 2012, 14:16
1) Парсинг реализуется просто в древовидную структуру.
2) Вычисление структуры начинается он низа дерева к верху, то-есть на каждом этапе имеем два числа и одну операцию.
Так часто пишут, но у меня почему-то получалось все наоборот :) Примерно так

5 + sin(0.5 + cos(1.0)) * 4  // исходная строка, преобразуем ее в контейнер выражений


+
sin(0.5 + cos(1.0))  // это вложенный контейнер выражений { sin,  "0.5 + cos(1.0)" }
*


В контейнере находим операцию с наивысшим приоритетом, здесь это *. Разматываем операнды и.т.д до победного конца


Название: Re: y = cos (x)
Отправлено: daimon от Май 21, 2012, 09:26
вот парсер хороший
http://svn.code.sf.net/p/phyxcalc/code/trunk (http://svn.code.sf.net/p/phyxcalc/code/trunk)
но он требует boost 1.47, qwt6.0