Построение графика функции по заданным точкам

Автор работы: Пользователь скрыл имя, 04 Ноября 2014 в 17:33, курсовая работа

Краткое описание

Цель данной курсовой работы –разработка приложения, позволяющего построить график функции по заданным точкам.
В данном приложение реализуется программное построение графика данной функции. Очень удобным на практике является тот факт, что график строится по заданным точкам. Это актуально в случаях, когда график в силу каких-либо причин невозможно задать уравнением.
При выполнении данной курсовой работы были поставлены следующие задачи:
• Изучение методов построения графиков и их анализ;
• Выбор среды разработки;
• Изучение методов реализации приложения в выбранной среде;
• Разработать приложение, позволяющее строить график по заданным точкам.

Содержание

ВВЕДЕНИЕ 3
1. КРАТКИЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ 4
1.1 ОСНОВНЫЕ ПОНЯТИЯ 4
1.2 СПОСОБЫ ЗАДАНИЯ ФУНКЦИИ 5
1.3 СРЕДСТВА СОЗДАНИЯ ГРАФИЧЕСКОГО ИНТЕРФЕЙСА 6
1.4 СРАВНЕНИЕ OPENGL И DIRECTX 15
2. ОПИСАНИЕ ПРИЛОЖЕНИЯ 18
2.1 ОПИСАНИЕ ИСХОДНОГО КОДА 18
2.2 ИНТЕРФЕЙС ПРИЛОЖЕНИЯ 19
ТЕСТИРОВАНИЕ РАБОТЫ ПРИЛОЖЕНИЯ НА ПРИМЕРЕ 23
ЗАКЛЮЧЕНИЕ 27
СПИСОК ЛИТЕРАТУРЫ 28
ПРИЛОЖЕНИЕ А 29

Вложенные файлы: 1 файл

Kursovaya_Elvira.docx

— 176.35 Кб (Скачать файл)

    {

        if (index.isValid() && role == Qt::EditRole)

        {

            QPointF point = function->points.takeAt(index.row());

            int row, pos;

            qreal x;

            switch (index.column())

            {

            case 0: x = point.x();

                    point.setX(value.toReal());

                    pos = function->addPoint(point);

                    if (pos >= 0)

                    {

                        points[index.row()]->x = value.toString();

                        row = index.row();

                        beginRemoveRows(QModelIndex(), row, row);

                        points.removeAt(row);

                        endRemoveRows();

                        beginInsertRows(QModelIndex(), pos, pos);

                        points.insert(pos, new Item(point.x(), point.y()));

                        endInsertRows();

                    }

                    else

                    {

                        point.setX(x);

                        function->addPoint(point);

                        QMessageBox::warning(0, tr("Недопустимая точка"), tr("Для данного x уже задана другая точка."));

                    }

                    break;

            case 1: points[index.row()]->y = value.toString();

                    point.setY(value.toReal());

                    function->addPoint(point);

                    break;

            }

            emit needUpdate();

            return true;

        }

        return false;

    }

    // Число строк и столбцов.

    int rowCount(const QModelIndex & parent = QModelIndex()) const {return points.size();}

    int columnCount(const QModelIndex & parent) const {return headers.count();}

 

    // Заполнение заголовков строк и столбцов.

    QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const

    {

        if (role != Qt::DisplayRole) return QVariant();

        if (orientation == Qt::Horizontal &&

            role        == Qt::DisplayRole)

            return headers.at(section);

        else

            return QString::number(section + 1);

    }

    // Флаги редактирования, всю таблицу можно редактировать.

    Qt::ItemFlags flags (const QModelIndex & index) const

    {

        if (!index.isValid()) return Qt::ItemIsEnabled;

 

        return QAbstractItemModel::flags(index) |

               Qt::ItemIsEditable;

    }

    // Добавление новой строки в модель.

    bool addRow(QPointF point)

    {

        int row = function->addPoint(point);

        if (row < 0)

        {

            QMessageBox::warning(0, tr("Недопустимая точка"), tr("Для данного x уже задана другая точка."));

            return false;

        }

        beginInsertRows(QModelIndex(), row, row);

        Item * item = new Item(point.x(), point.y());

        points.insert(row, item);

        endInsertRows();

        ++countOfPoints;

        emit needUpdate();

        return true;

    }

    // Удаление строки таблицы.

    bool deleteRow(int row)

    {

        if (!countOfPoints || (row < 0)) return false;

        if (countOfPoints == 2)

        {

            QMessageBox::warning(0, tr("Невозможно удалить точку"), tr("Минимальное количество точек досигнуто"));

            return false;

        }

        beginRemoveRows(QModelIndex(), row, row);

        points.removeAt(row);

        function->points.removeAt(row);

        if (row == 0)

            function->xMin = function->points.first().x();

        if (row == (countOfPoints - 1))

            function->xMax = function->points.last().x();

        --countOfPoints;

        endRemoveRows();

        emit needUpdate();

        return true;

    }

 

signals:

    void needUpdate();

};

 

// Класс таблицы для отображения точек.

class PointsWidget : public QTableView

{

    Q_OBJECT

 

public:

    explicit PointsWidget(QWidget *parent = 0) :

        QTableView(parent)

    {

        setItemDelegate(new Delegate());    // Использует разработанный делегат.

        setSelectionMode(QAbstractItemView::SingleSelection);

        setContextMenuPolicy(Qt::CustomContextMenu);

    }

    // Позволяет получить индекс выбранной строки.

    int selectedRow()

    {

        if (selectedIndexes().isEmpty()) return -1;

            return selectedIndexes().takeFirst().row();

    }

};

 

#endif // WIDGETS_H

 

dialogaddfunction.h

#ifndef DIALOGADDFUNCTION_H

#define DIALOGADDFUNCTION_H

 

#include <QDialog>

#include <QColor>

#include <QTime>

#include <QColorDialog>

#include <QMessageBox>

 

namespace Ui

{

class DialogAddFunction;

}

 

// Диалог добавления новой функции.

// Позволяет задавать имя функции, цвет и две крайние точки.

class DialogAddFunction : public QDialog

{

    Q_OBJECT

 

public:

    QString name;               // Параметры функции.

    QColor color;

    qreal x1, y1, x2, y2;

    explicit DialogAddFunction(QWidget *parent = 0);

    ~DialogAddFunction();

   

private:

    Ui::DialogAddFunction *ui;

    void changeColor();         // Изменения цвета метки диалога.

 

private slots:

    void setColor();            // Задание цвета диалогом.

    void check();               // Подтверждение.

};

 

#endif // DIALOGADDFUNCTION_H

 

dialogsettings.h

#ifndef DIALOGSETTINGS_H

#define DIALOGSETTINGS_H

 

#include <QDialog>

#include <QLabel>

#include <QColorDialog>

#include <QColor>

#include <QPalette>

#include <QMessageBox>

 

namespace Ui {

class DialogSettings;

}

 

// Диалог настроек графика.

// Позволяет задавать границы графика и его оформление.

class DialogSettings : public QDialog

{

    Q_OBJECT

 

public:

    qreal   xMin, xMax, yMin, yMax;                 // Границы.

    int     outline, gridStep;                      // Отступ графика и шаг сетки.

    QColor  gridColor, background, textColor;       // Цветовое оформление.

 

    explicit DialogSettings(qreal xMin, qreal xMax, qreal yMin, qreal yMax,

                            int outline, int gridStep,

                            QColor gridColor, QColor background, QColor textColor,

                            QWidget *parent);

    ~DialogSettings();

   

private:

    Ui::DialogSettings *ui;

    void setColor(QLabel * label, QColor color);    // Изменение цвета метки.

 

private slots:

    void check();                                   // Подтверждение.

    void on_btnBackgroundColor_clicked();           // Определение цветов диалогом.

    void on_btnGridColor_clicked();

    void on_btnTextColor_clicked();

};

 

#endif // DIALOGSETTINGS_H

 

dialogaddpoint.h

#ifndef DIALOGADDPOINT_H

#define DIALOGADDPOINT_H

 

#include <QDialog>

 

namespace Ui {

class DialogAddPoint;

}

 

// Диалог добавления новой точки.

// Позволяет задавать координаты точки.

class DialogAddPoint : public QDialog

{

    Q_OBJECT

 

public:

    qreal x, y;     // Координаты точки.

    explicit DialogAddPoint(QWidget *parent = 0);

    ~DialogAddPoint();

   

private:

    Ui::DialogAddPoint *ui;

 

private slots:

    void check();   // Подтверждение.

};

 

#endif // DIALOGADDPOINT_H

 

Файлы исходники:

main.cpp

#include <QtGui>

 

#include <QApplication>

#include "mainwindow.h"

 

#include <QTextCodec>

#include <QStyleFactory>

 

int main(int argc, char *argv[])

{

    QTextCodec::setCodecForLocale(QTextCodec::codecForName("Windows-1251"));

 

    QApplication a(argc, argv);

 

    MainWindow w;

    w.show();

 

    return a.exec();

}

 

graph.cpp

#include "graph.h"

#include <qmath.h>

 

Graph::Graph(   Functions *functions,

                QWidget *parent) :

    QGLWidget(parent)

{

    left    = -5;   // Границы графика.

    right   = 5;

    top     = 5;

    bottom  = -5;

 

    outline  = 30;  // Граничный отступ графика.

    gridStep = 25;  // Шаг Автосетки.

    scale    = 100; // Масштаб графика.

 

    // Внешний вид графика.

    gridPen         = QPen(Qt::lightGray);          // Линии сетки.

    backgroundBrush = QBrush(Qt::gray);             // Задний фон.

    textColor       = Qt::black;                    // Цвет текста.

    labelFont       = QFont("Arial", 8, 1, true);   // Шрифт подписей.

 

    setMouseTracking(true); // Отслеживание мыши.

    mouseX = mouseY = 0;    // Координаты мыши.

 

    this->functions = functions;    // Список отображаемых функций.

 

    tracing = &(functions->first());    // Трассировать первую функцию из списка.

 

    setContextMenuPolicy(Qt::CustomContextMenu);    // Поддерживает контестное меню.

}

 

// Перерисовка графика, при изменении размера виджета.

void Graph::resizeGL(int w, int h)

{

    ///////////////////////////////////////////////////////

    // Пересчёт размеров графика к новому размеру виджета.

    ///////////////////////////////////////////////////////

 

    graphSize.setHeight (scale * (bottom - top));   // Размеры графика.

    graphSize.setWidth  (scale * (right  - left));

 

    graph = QRect(QPoint(scale * left, scale * top), graphSize);    // Прямоугольная область графика.

 

    setMinimumSize(outline * 3, outline * 3);   // Ограничение на минимальный размер виджета.

 

    viewportSize = size();  // Прямоугольная область виджета.

 

    // График будет сжат с обеих сторон на толщину отступа границы.

    qreal   adjustWidth  (viewportSize.width()   - 2 * outline),

            adjustHeight (viewportSize.height()  - 2 * outline);

    // Сжатие области рисования на виджете.

    viewportSize.scale(adjustWidth, adjustHeight, Qt::IgnoreAspectRatio);

    // Сдвигание области рисования на толщину границы.

    viewport = QRect(QPoint(outline, outline), viewportSize);

 

    ///////////////////////////////////////

    // Пересчёт подписей и разметки сетки.

    ///////////////////////////////////////

 

    // Количество подписей сетки.

    qreal xLabelCount(1), yLabelCount(1);

    // Шаг сетки определяется цикличным делением пополам.

    xViewportStep = viewportSize.width();

    yViewportStep = viewportSize.height();

 

    for (;;)

    {

        qreal value(xViewportStep / 2.0);

 

        if (value >= gridStep) xViewportStep = value;

        else break;

 

        ++xLabelCount;

    }

 

    for (;;)

    {

        qreal value(yViewportStep / 2.0);

 

        if (value >= gridStep) yViewportStep = value;

        else break;

 

        ++yLabelCount;

    }

 

    // Обратная операция для получения количества подписей.

    xLabelCount = qPow(2, xLabelCount);

    yLabelCount = qPow(2, yLabelCount);

 

    // Шаг графика для виртуальных координат.

    xGraphStep = 2 * graph.width()  / qreal(xLabelCount);

    yGraphStep = 2 * graph.height() / qreal(yLabelCount);

 

    xStepCount = graph.width()  / xGraphStep;

    yStepCount = graph.height() / yGraphStep;

 

    // Рисование.

    paintGL();

}

 

// Перерисовка графика.

void Graph::paintGL()

{

    // Создание и настройка рисовальщика.

    QPainter painter(this);

    painter.setRenderHint(QPainter::HighQualityAntialiasing);

 

    // Серый фон.

    painter.setBackground(backgroundBrush);

    painter.eraseRect(rect());

 

    painter.save();

 

    //////////////////////

    // Отображение сетки.

    //////////////////////

 

    // Привязывание виртуальных координат.

    painter.setWindow(graph);

    painter.setViewport(viewport);

 

    // Сетка.

    painter.setPen(gridPen);

 

    // Рисование разметки.

    for (int i(1); i < xStepCount; ++i)

    {

        qreal pos(scale * left + i * xGraphStep);

 

        painter.drawLine(QLineF(pos, scale * top,

                                pos, scale * bottom));

    }

 

    for (int i(1); i < yStepCount; ++i)

    {

        qreal pos(scale * top + i * yGraphStep);

 

        painter.drawLine(QLineF(scale * left,   pos,

                                scale * right,  pos));

    }

 

    painter.drawRect(graph);

 

    //////////////////////

    // Рисование функций.

    //////////////////////

 

    // Проход по функциям.

    QListIterator<Function> i(*functions);

 

    while (i.hasNext())

    {

        const Function * f(&i.next());

 

        // Рисование цветом соответствующим функции.

        if (showTracing && f == tracing)

        {

            painter.setPen(QPen(QBrush(f->color), 5));

            showTracing = false;

        }

        else

            painter.setPen(QPen(f->color));

 

        qreal   xStep(0.01),    // Величина шага по оси x.

                y;              // Значение функции в заданной точке.

 

        int     xStepCount = (right - left) / xStep;    // Количество шагов по оси x.

 

        QPointF prevPoint;  // Предыдущая точка функции.

 

        for(int i(0); i <= xStepCount; ++i)

        {

            // Первая точка графика.

            qreal x = left + i * xStep;

 

            // Входит в область определения.

            if (!f->has(x)) continue;

 

            y = f->value(x);

 

            // График рисуется от предыдущей точки к следующей.

            prevPoint = QPointF(scale * x, scale * y);

 

            bool burst(false);

 

            for(int j(i); j <= xStepCount; ++j)

            {

                qreal x = left + j * xStep;

 

                // Функция на промежутке непрерывна.

                if (!f->has(x)) break;

 

                y = f->value(x);

 

                // Выводятся только значения входящие в границы графика.

                if ((y < top) && (y > bottom))

                {

                    painter.drawLine(QLineF(prevPoint, QPointF(scale * x, scale * y)));

                    burst = false;

                    // Текущая точка становится предыдущей.

                    prevPoint = QPointF(scale * x, scale * y);

                }

                else

                {

                    if (y > top)

                    {

                        if (!burst)

                            painter.drawLine(QLineF(prevPoint, QPointF(scale * x, scale * top)));

                        prevPoint = QPointF(scale * x, scale * top);

                    }

 

                    if (y < bottom)

                    {

                        if (!burst)

                            painter.drawLine(QLineF(prevPoint, QPointF(scale * x, scale * bottom)));

                        prevPoint = QPointF(scale * x, scale * bottom);

                    }

                    burst = true;

                }

            }

 

            break;

        }

    }

 

    ////////////////////////////////

    // Отрисовка линий трассировки.

    ////////////////////////////////

 

    if (tracerOk)

    {

        painter.setPen(QPen(QBrush(Qt::white), 0, Qt::DashLine));

 

        painter.drawLine(QLineF(traceX * scale, top * scale, traceX * scale, bottom * scale));

        painter.drawLine(QLineF(left * scale, traceY * scale, right * scale, traceY * scale));

    }

 

    painter.restore();

 

    painter.eraseRect(QRect(0, 0, width(), outline - 1));

    painter.eraseRect(QRect(0, height() - outline + 1, width(), outline));

 

    /////////////////////////

    // Отображение подписей.

    /////////////////////////

 

    painter.setPen(textColor);

 

    // Задание шрифта подписей.

    painter.setFont(labelFont);

 

    // Специальные размеры.

    qreal   halfSide (outline / 2),                 // Половина оступа границы.

            xMargin  (size().height() - outline),   // Отступ по горизонтали.

            yMargin  (0);                           // Отступ по вертикали.

 

    // Подписи к осям

    for(int i(0); i <= xStepCount; ++i)

    {

        qreal   label    (left + i * xGraphStep / scale),   // Значение метки.

                step     (halfSide + i * xViewportStep);    // Положение метки в реальных координатах.

 

        painter.drawText(QRectF(QPointF(step, xMargin), QSize(outline, outline)),   // Вывод текста метки.

Информация о работе Построение графика функции по заданным точкам