crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Подкорректируйте отрисовку графика
ROMANtic
  опции профиля:
сообщение 22.8.2011, 13:39
Сообщение #1


Новичок


Группа: Новичок
Сообщений: 7
Регистрация: 3.8.2011
Пользователь №: 2788

Спасибо сказали: 0 раз(а)




Репутация:   0  


Есть функция, график которой - ломаная, точки (0; 0) (0,25; 2) (0,75; -2) (1,0). Я приближаю эту функцию ступенчатой.

haar.h

#ifndef HAAR_H
#define HAAR_H

#include <QWidget>
#include <QtGui>

#include <math.h>

class Haar : public QWidget
{
    Q_OBJECT

public:
    Haar(QWidget *parent = 0);


protected:
     void paintEvent(QPaintEvent *event);

};

#endif



haar.cpp

#include <QWidget>
#include <QPainter>
#include <QPoint>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGraphicsScene>

#include "haar.h"

QPen funcpen = QPen(Qt::red);

Haar::Haar(QWidget *parent) :
    QWidget(parent)
{

}

//Степень двойки с натуральным показателем

int int_pow_2(int b)
{
    int i = 1, power = 1;
    while (i <= b)
{
        power *=2;
        ++i;
}
    return power;
}

//Функция hi[n] = hi[k][j]

double hi(int k, int j, double t)
{
    int P = int_pow_2(k);
    double R = pow(2.0, k/2);
    if ((t >= j / P) && (t < (j + 0.5) / P))
            {return R;}
    if ((t >= (j + 0.5) / P) && (t < (j + 1) / P))
            {return -R;}
    else //((t < j / P) || (t >= (j + 1) / P))
            return 0;

}

void Haar::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

    QRegion r1(QRect(0,0,1000,2000),QRegion::Rectangle);
    painter.setClipRegion(r1);
    painter.setWindow(QRect(0, 0, 10000, 2000));
    painter.setPen(Qt::blue);

    const int N = 1023;
    const int AB = 4;

    int K = round(log( N+1 ) / log( 2 ));


    //Считаем коэффициенты ряда Фурье-Хаара
    double x[K][int_pow_2(K-1)-1];

    x[0][0] = 1; x[1][0] = 0; x[1][1] = 0;

    for (int k = 2; k <= (K-1); ++k)

    {   int l = int_pow_2(k-2);

        double A = pow(2.0,-1.5 * k + 1);

            for (int j = 0; j <= (l - 1); ++j)

                x[k][j] = - A;

            for (int j = l; j <= (3 * l - 1); j++)

                x[k][j] = A;

            for (int j= 3 * l; j <= (l * 4 - 1); j++)

                x[k][j]= - A;

     };

    //--------------------------------------------------------------------

    //Считаем значения функции на полуинтервалах

    double t[N+1]; double SUM[N+1];

    for (int n = 0; n <= N; n++)
    {
        SUM[n] = 0;

        for (int k = 0; k <= K-1; k++)
        {
            int P = int_pow_2(k);
            for (int j = 0; j <= P - 1; j++)
            {
                t[n] = n / pow(2.0,K);
                SUM[n] += x[k][j] * hi(k,j,t[n]);
            }

        }
    }

    //Рисуем график

    double fi[N+1];

    for (int n = 0; n <= N; n++)
    {
        fi[n] = 500 - 100 * SUM[n];
        painter.drawLine(n*AB,fi[n],(n+1)*AB,fi[n]);
    }


    //---------------------------------------------------------------------------


    //Считаем элементы последовательности y_n
    /*
    double y[K-1][int_pow_2(K-1)-1];

    y[0][0] = 1; y[1][0] = 0; y[1][1] = 0;

    for (int k = 2; k <= (K-1); ++k)
    {
        int P = int_pow_2(k);
        int alpha[k];


        for (int j = 0; j <= P - 1; j++)
        {
            y[k][j] = - x[k][j];
            int j2 = j;

            for (int i = 0; i <= k - 1; i++)
            {
                alpha[k-i] = j2 % 2;
                j2 = j2 / 2;
            }

            int B = j;

            for (int l = 1; l <= k-1; l++)
            {
                int A = 0;
                B += - alpha[l] * int_pow_2(k-l);

                for (int m = 1; m <= l; m++)
                {
                    A += alpha[m] * int_pow_2(l-m);
                }
                y[k][j] += - x[l][A] * y[k-l][B];
            }
        }
    }


    //Считаем значения функции на полуинтервалах
    double t[N+1]; double S[N+1];

    for (int n = 0; n <= N; n++)
    {
        S[n] = 0;

        for (int k = 0; k <= K-1; k++)
        {
            for (int j = 0; j <= int_pow_2(k)-1; j++)
            {
                t[n] = n / pow(2.0,K);
                S[n] += y[k][j] * hi(k,j,t[n]);
            }

        }
    }
    //Рисуем график

    double psi[N+1];

    for (int n = 0; n <= N; n++)
    {
        psi[n] = 500 - 100 * S[n];
        painter.drawLine(n*AB,psi[n],(n+1)*AB,psi[n]);
    }
};



main.cpp

#include <QApplication>
#include <QPainter>
#include <QGridLayout>

#include "haar.h"

class MyWidget : public QWidget
{
    public:
        MyWidget(QWidget *parent = 0);
};

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    Haar *haar = new Haar;

    QGridLayout *gridLayout = new QGridLayout;
    gridLayout->addWidget(haar,1,1);
    setLayout(gridLayout);
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MyWidget widget;
    widget.setGeometry(100,100,500,355);
    widget.show();


    return app.exec();
}




Получается что-то типа (см. картинку).

Математически тут вроде все правильно подсчитано, я несколько раз проверял. График очень похож на правду, но я не могу понять откуда взялись большие разрывы между ступеньками, и почему в самом конце ветвь уехала в сторону (по идее график должен быть симметричным). Понимаю, что подсчеты такие тут вряд ли кто проверит, но может я что-то не так при отрисовке делаю?
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 22.8.2011, 14:27
Сообщение #2


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


а где на графике отметки значений ?
что значит "Я приближаю эту функцию ступенчатой" ?
что требуется вообще сделать ? Может быть, сплайны спасут ? :) http://ru.wikipedia.org/wiki/%D0%9A%D1%80%...%B7%D1%8C%D0%B5
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
registr
  опции профиля:
сообщение 22.8.2011, 15:38
Сообщение #3


Участник
**

Группа: Участник
Сообщений: 115
Регистрация: 16.11.2009
Пользователь №: 1234

Спасибо сказали: 8 раз(а)




Репутация:   1  


Сначала построй график функции в виде точек, потом последовательно соедини точки в линии. Проверь график на свободном ПО, например Scilab (аналог Matlab)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_Гость_*
сообщение 22.8.2011, 16:56
Сообщение #4





Гости








    


Используй библиотеку Qwt
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ROMANtic
  опции профиля:
сообщение 22.8.2011, 17:47
Сообщение #5


Новичок


Группа: Новичок
Сообщений: 7
Регистрация: 3.8.2011
Пользователь №: 2788

Спасибо сказали: 0 раз(а)




Репутация:   0  


Кривые Безье тут не при чем. Любую непрерывную функцию можно приблизить ступенчатыми функциями. Это как раз и необходимо сделать.

Может тут все-таки есть математики-программисты?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 23.8.2011, 6:32
Сообщение #6


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


ROMANtic, расскажи, что ты понимаешь под ступенчатой функцией ? Может кусочную?

http://ru.wikipedia.org/wiki/%D0%9A%D1%83%...%86%D0%B8%D1%8F

Покажи рисунок с исходными данными (именно рисунок - а то строить то лень) , опиши условия составления описывающей эти точки функции. В конце концов, какой реальный физический закон сгенерировал те точки? Покажи рисунок с совмещёнными исходными данными и результатом.

Почему все отрезки на твоей картинке имеют одинаковую по модулю производную ? Это важно или так получилось случайно ?

Пока на эти минимальные вопросы не ответишь, никто ничего не сможет подсказать. Какой вопрос - такой ответ.

В конце то концов - прикрепи проект, чтобы люди могли поэкспериментировать "с ходу".

Сообщение отредактировал Алексей1153 - 23.8.2011, 6:30
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 14.1.2025, 1:24