|
Символы кириллицы выводит некорректно. Как сделать чтобы выводился читабельный текст на русском языке? Тип приложения - не Qt, Qt Creator 4.5.0 основан на Qt 5.10.0. Win7.
|
Общие сведения о библиотеке MathGL
При решении различных задач возникает необходимость графического отображения данных (графики, диаграммы, поверхности). Одним из универсальных способов построения различных графиков является кросс-платформенная библиотека MathGL.
Mathgl — свободная кросс-платформенная библиотека для построения двух- и трёх-мерных графиков функций. Её использование позволит построить график с помощью нескольких операторов. Синтаксис функций, используемых в MathGL, подобен синтаксису MathLab, Octave, Scilab, GnuPlot. Официальный сайт — http://mathgl.sourceforge.net/doc_ru/Website.html#Website, на странице загрузки http://mathgl.sourceforge.net/doc_ru/Download.html# Download можно скачать последнюю версию программы для различных операционных систем, англоязычную документацию в формате pdf. Группа в Google — https://groups.google.com/forum/#!forum/mathgl. Русскоязычная страница с описанием — http://mathgl.sourceforge.net/doc_ru/index. html#SEC_Contents , англоязычная — http://mathgl.sourceforge.net/doc_en/ index.html#SEC_Contents. Кроме С(С++) поддерживаются Fortran, Python, Octave, скриптовый язык MGL.
Рассмотрим особенности установки и примеры использования библиотеки для построения графиков.
B.1 Установка MathGL в Linux.
Библиотека входит в репозитории большинства современных дистрибутивов Linux. Её можно установить из репозитория стандартным для вашего дистрибутива способом, однако в репозитории зачастую находится не самая новая версия. Для установки самой новой версии необходимо:
- Скачать исходники последней версии с официального сайта.
- Распаковать.
- Последовательно выполнить команды1Перед выполнением команды cmake, возможно, придётся доставлять необходимые пакеты. При работе в debian (6, 7), ubuntu (12.04, 12.10, 13.04, 13.10) авторам пришлось доставить пакеты cmake, zlib1g-dev, libpng12-dev, libqt4-opengl-dev, libqtwebkit-dev. Кроме того, должен быть устанвлен компилятор g++.
cmake -Denable-qt=ON cmake make sudo make install
- Скопировать файлы libmgl-qt.so.7.1.0 и libmgl.so.7.1.02Версии библиотек libmgl указаны применительно к mathgl 2.2, в вашем конкретном случае могут быть другие библиотеки. из каталога /usr/local/lib в каталог /lib (нужны права администратора(суперпользователя)).
После этого для компиляции программы с использованием библиотеки MathGL необходимо использовать ключи -L/usr/local/lib -L/usr/lib -lmgl -lmgl-qt, например для компиляции файла с именем 1.cpp можно использовать команду
g++ -o 1 1.cpp -L/usr/local/lib -L/usr/lib -lmgl -lmgl-qt
B.2 Использование MathGL при построении двух- и трёхмерных графиков
Рассмотрим возможности библиотеки на конкретных примерах.
Задача B.1. Построить график функции f
.
Следующий программный код позволит построить линию графика (рис. B.1) на интервале [-1;1].
#include <mgl2 / qt .h>
int sample ( mglGraph * gr )
{
gr->Title ( "График функции y = f ( x ) " ); //Заголовок графика
//График заданной функции. Линия графика изображена красным цветом — " r " .
gr->Fplot ( " sin ( x ) + 1 / 3 * sin ( 3 * x ) + 1 / 5 * sin ( 5 * x ) ", " r " );
return 0;
}
int main ( int arg c, char ** argv )
{
set locale (LC_CTYPE, " ru_RU.utf8 " );
mglQT gr ( sample, " Plot " );
return gr.Run ( );
}Далее представлен текст программы, с помощью которого можно усовершенствовать график, показанный на рис. B.1. На рис. B.2 видно, что был увеличен диапазон построения графика, добавлены оси координат, подписи под ними и линии сетки.
#include <mgl2 / qt .h>
int sample ( mglGraph * gr )
{
gr->Title ( "График функции y = f ( x ) " ); //Заголовок графика
gr->setOrigin ( 0, 0 ); //Установка центра координатных осей
//Границы по оси абсцисс от -10 до 10, по оси ординат от -1 до 1.
gr->SetRanges ( -10,10, -1,1);
gr->Axis ( ); //Вывод значений возле осей
gr->Grid ( ); //Линии сетки
//График заданной функции.
gr->Fplot ( " sin ( x ) + 1 / 3 * sin ( 3 * x ) + 1 / 5 * sin ( 5 * x ) ", " r " );
return 0;
}
int main ( int arg c, char ** argv )
{
set locale (LC_CTYPE, " ru_RU.utf8 " ); //Поддержка кириллицы в С++
mglQT gr ( sample, " Plot " ); //Вывод графика на экран в окно с именем Plot
return gr.Run ( );
}Задача B.2. Построить графики функций
и
в одной графической области.
Далее приведён текст программы, реализующий решение поставленной задачи. Результаты работы программы показаны на рис. B.3.
#include <mgl2 / qt .h>
#include <math.h>
int sample ( mglGraph _ gr )
{
gr->Title ( "Графики функции y = f ( x ) " ); //Заголовок графика
gr->SetRanges ( -15,15, -2,2); //Границы по осям
gr->Axis ( ); //Вывод значений возле осей
gr->Grid ( ); //Линии сетки
gr->Fplot ( " sin ( 2 * x ) ", " r " ); //График функции f(x), красная (r) сплошная линия.
gr->AddLegend ( " sin ( 2 * x ) ", " r " ); //Добавление легенды
gr->Fplot ( " 4* cos ( x ) /3 ", " k." ); //График функции y(x), чёрная (k) линия и точки (.).
gr->AddLegend ( " 4* cos ( x ) /3 ", " k." ); //Добавление легенды
gr->Legend ( 3 ); //Вывод легенды на экран в правом верхнем углу
gr->Label ( " x ", " OX ", 0 ); //Вывод подписи по оси абсцисс
gr->Label ( " y ", " OY " ); //Вывод подписи по оси ординат
return 0;
}
int main ( int arg c, char ** argv )
{
set locale (LC_CTYPE, " ru_RU.utf 8 " );
mglQT gr ( sample, " Plot " );
return gr.Run ( );
}Задача B.3. Построить в одном графическом окне графики функций:
-
на интервале [-10;10], -
на интервале [-6;6], -
на интервале [-6;6], -
на интервале [-12;12].
Результаты вывести на экран и в файл.
Далее приведён программный код и результат его работы (рис. B.4).
#include <mgl2/qt .h>
#include <mgl2/mgl .h>
#include <iostream>
using namespace std;
int sample ( mglGraph * gr )
{
//График функции sin(x) на интервале [-10; 10]
gr->Subplot ( 2, 2, 0 );
gr->Title ( "График функции sin ( x ) " );
gr->setOrigin ( 0, 0 );
gr->SetRanges ( -10,10, -1,1);
gr->Axis ( );
gr->Grid ( );
gr->Fplot ( " sin ( x ) ", " k -. " );
//График функции cos(x) на интервале [-6; 6]
gr->Subplot ( 2, 2, 1 );
gr->Title ( "График функции cos ( x ) " );
gr->setOrigin ( 0, 0 );
gr->SetRanges ( -6,6, -1,1);
gr->Axis ( );
gr->Grid ( );
gr->Fplot ( " cos ( x ) ", " k." );
//График функции exp(cos(x)) на интервале [-6; 6]
gr->Subplot ( 2, 2, 2 );
gr->Title ( "График функции e ^{ cos ( x ) } " );
gr->setOrigin ( 0, 0 );
gr->SetRanges ( -6, 6, 0, 3 );
gr->Axis ( );
gr->Grid ( );
gr->Fplot ( " exp ( cos ( x ) ) ", " r o " );
//График функции exp(sin(x)) на интервале [12; 12]
gr->Subplot ( 2, 2, 3 );
gr->Title ( "График функции e ^{ sin ( x ) } " );
gr->setOrigin ( 0, 0 );
gr->SetRanges ( -15, 15, 0, 3 );
gr->Axis ( );
gr->Grid ( );
gr->Fplot ( " exp ( sin ( x ) ) ", " r - o " );
return 0;
}
int main ( int arg c, char __ argv )
{
//Вывод на экран или в файл
int k;
cout<<"Введите 1, если будете выводить на экран, 2 - если в файл\nk = ";
cin>>k;
if ( k==1)
{
//Поддержка кириллицы в С++
set locale (LC_CTYPE, " ru_RU.utf 8 " );
//Вывод на экран
mglQT gr ( sample, " Plot s " );
return gr.Run ( );
}
else
{
mglGraph gr;
gr.Alpha ( true );
gr.Light ( true );
set locale (LC_CTYPE, " ru_RU.utf 8 " );
//Обращение к функции вывода
sample(& gr );
//Запись изображения в файл
gr.WriteEPS ( " test.eps " );
return 0;
}
}Задача B.4. Построить график функций
.
Нетрудно заметить, что функция
не существует в точке ноль. Поэтому построим её график на двух интервалах [-2;-0.1] и [0.1;2], исключив точку разрыва из диапазона построения. Текст программы с подробными комментариями приведён далее. Решение задачи представлено на рис. B.5.
#include <mgl2 / qt .h>
#include <iostream>
using namespace std;
int sample ( mglGraph * gr )
{
mglData x1 ( 191 ), x2 ( 191 ), y1 ( 191 ), y2 ( 191 );
int i; float h, a1, b1, a2, b2;
//График точечной разрывной функции
//Первый интервал
a1=-2;b1=-0.1;
h = 0.01;
for ( i =0; i <191; i++)
{
x1 [ i ]= a1+ i *h;
y1 [ i ]=1 -0.4/ x1 [ i ]+ 0.05 / x1 [ i ] / x1 [ i ];
}
//Второй интервал
a2 = 0.1; b2=2;
h = 0.01;
for ( i =0; i <191; i++)
{
x2 [ i ]= a2+ i *h;
y2 [ i ]=1 -0.4/ x2 [ i ]+ 0.05 / ( x2 [ i ] * x2 [ i ] );
}
gr->SetRanges ( a1, b2, 0, 10 ); //Границы по оси абсцисс и ординат
gr->Axis ( ); //Оси координат
gr->Grid ( ); //Сетка
gr->Plot ( x1, y1, " k " ); //График функции на первом интервале, чёрный (k) цвет.
gr->Plot ( x2, y2, " k " ); //График функции на втором интервале, чёрный (k) цвет.
gr->set font size ( 2 ); //Размер шрифта
gr->Title ( "График разрывной функции" ); //Заголовок
gr->set font size ( 4 ); //Размер шрифта
gr->Label ( " x ", " OX ", 0 ); //Подпись по оси абсцисс
gr->Label ( " y ", " OY " ); //Подпись по оси ординат
return 0;
}
int main ( int arg c, char ** argv )
{
set locale (LC_CTYPE, " ru_RU.utf 8 " );
mglQT gr ( sample, " Plot " );
return gr.Run ( );
}Задача B.5. Построить график функции
на интервале [-5;5].
Функция
имеет разрыв в точках -1 и 3. Построим её график на трёх интервалах [-5; -1.1], [-0.9;2.9] и [3.1;5], исключив точки разрыва из диапазона построения. Текст программы с подробными комментариями приведён далее. Решение задачи представлено на рис. B.6.
#include <mgl2 / qt .h>
#include <iostream>
using namespace std;
int sample ( mglGraph * gr )
{
mglData x1 ( 391 ), x2 ( 381 ), x3 ( 191 ), y1 ( 391 ), y2 ( 381 ), y3 ( 191 );
int i; float h, a1, b1, a2, b2, a3, b3;
//График точечной разрывной функции
a1=-5;b1=-1.1; //Первый интервал
h = 0.01;
for ( i =0; i <391; i++)
{
x1 [ i ]= a1+ i _h;
y1 [ i ]=1/( x1 [ i ] * x1 [ i ]-2*x1 [ i ] -3);
}
a2=-0.9;b2 = 2.9; //Второй интервал
h = 0.01;
for ( i =0; i <381; i++)
{
x2 [ i ]= a2+ i *h;
y2 [ i ]=1/( x2 [ i ] *x2 [ i ]-2*x2 [ i ] -3);
}
a3 = 3.1; b3=5; //Третий интервал
h = 0.01;
for ( i =0; i <191; i++)
{
x3 [ i ]= a3+ i *h;
y3 [ i ]=1/( x3 [ i ] * x3 [ i ]-2*x3 [ i ] -3);
}
gr->SetRanges ( -6,6, -3,3); //Границы по оси абсцисс и ординат
gr->Axis ( ); //Оси координат
gr->Grid ( ); //Сетка
gr->Plot ( x1, y1, " k " ); //График функции на первом интервале, чёрный (k) цвет.
gr->Plot ( x2, y2, " k " ); //График функции на втором интервале, чёрный (k) цвет.
gr->Plot ( x3, y3, " k " ); //График функции на третьем интервале, чёрный (k) цвет.
gr->set font size ( 2 ); //Размер шрифта
gr->Title ( "График функции c двумя разрывами" ); //Заголовок
gr->set font size ( 4 ); //Размер шрифта
gr->Label ( " x ", " OX ", 0 ); //Подпись по оси абсцисс
gr->Label ( " y ", " OY " ); //Подпись по оси ординат
return 0;
}
int main ( int arg c, char ** argv )
{
set locale (LC_CTYPE, " ru_RU.utf 8 " );
mglQT gr ( sample, " Plot " );
return gr.Run ( );
}Задача B.6. Построить график функции
.
График задан в параметрической форме и представляет собой эллипс. Выберем интервал построения графика
, ранжируем переменную
на этом интервале, сформируем массивы
и
и построим точечный график. Текст программы и результаты её работы (рис. B.7) представлены далее.
#include <mgl2/qt .h>
#include <iostream>
#include <math.h>
using namespace std;
int sample ( mglGraph * gr )
{ //График эллипса
int i, n; float h, a, b, t;
a=0;
b=2*M_PI;
n=200;
h=(b-a ) /n;
//Формирование массивов абсцисс и ординат
mglData x ( n ), y ( n );
for ( i =0; i<n; i++)
{
t=a+ i *h;
x [ i ]=3* cos ( t );
y [ i ]=2* sin ( t );
}
gr->SetRanges ( -3,3, -2,2); //Границы по осям координат
gr->Axis ( ); //Оси координат
gr->Grid ( ); //Сетка
gr->Plot ( x, y, " k " ); //График функции
gr->set font size ( 2 );
gr->Title ( "График эллипса" );
gr->SetFontSsize ( 4 );
gr->Label ( " x ", " OX ", 0 );
gr->Label ( " y ", " OY " );
return 0;
}
int main ( int arg c, char ** argv )
{
set locale (LC_CTYPE, " ru_RU.utf 8 " );
mglQT gr ( sample, " Plot " );
return gr.Run ( );
}Задача B.7. Построить график функции:

В данном случае необходимо построить график функции двух аргументов. Для этого нужно сформировать матрицу
при изменении значений аргументов
и
и отобразить полученные результаты.
Далее приведён текст программы и результаты её работы (рис. B.8).
#include <mgl2/qt .h>
#include <iostream>
using namespace std;
int sample ( mglGraph * gr )
{
//Изображение поверхности
gr->SetRanges ( -5,5, -5,5, -1,2); //Диапазон изменения x, y, z.
mglData z ( 500, 400 ); //Размер матрицы z по х и по y
//Формирование матрицы z.
z.Mod ify ( " 0.6 * sin ( 2 * pi * x ) * sin ( 3 * pi * y ) + 0.4 * cos ( 3 * pi *( x * y ) ) " );
gr->Rotate ( 40, 60 ); //Вращение осей
gr->Box ( );
gr->Axis ( );
gr->Grid ( );
gr->Mesh ( z ); //График функции
}
int main ( int arg c, char ** argv )
{
set locale (LC_CTYPE, " ru_RU.utf 8 " );
mglQT gr ( sample, " MathGL Example " );
return gr.Run ( );
}Задача B.8.Построить эллипсоид.
Текст программы и результаты её работы (рис. B.9).
#include <mgl2/qt .h>
#include <mgl2/mgl .h>
#include <iostream>
using namespace std;
int sample ( mglGraph * gr )
{
gr->Title ( "Эллипсоид" );
mglData x ( 50, 40 ), y ( 50, 40 ), z ( 50, 40 );
gr->Fill ( x, " 0.1 + 0.8 * sin ( 2 * pi * x ) * sin ( 2 * pi * y ) " );
gr->Fill ( y, " 0.1 5 + 0.7 * cos ( 2 * pi * x ) * sin ( 2 * pi * y ) " );
gr->Fill ( z, " 0.2 + 0.6 * cos ( 2 * pi * y ) " );
gr->Rotate ( 50, 60 );
gr->Box ( );
gr->Surf ( x, y, z, " BbwrR " );
return 0;
}
int main ( int arg c, char ** argv )
{
set locale (LC_CTYPE, " ru_RU.utf 8 " );
mglQT gr ( sample, " Ellipse " );
return gr.Run ( );
}В завершении приведём решение реальной инженерной задачи с использованием MathGL.
Задача B.9. В "Основах химии" Д. И. Менделеева приводятся данные о растворимости азотнокислого натрия
в зависимости от температуры воды. Число условных частей
, растворяющихся в 100 частях воды при соответствующих температурах, представлено в таблице.
Требуется определить растворимость азотнокислого натрия при температурах 25, 32 и 45 градусов в случае линейной зависимости и найти коэффициент корреляции.
Параметры линейной зависимости (линии регрессии)
подбираются методом наименьших квадратов и рассчитываются по формулам

Этапы решения задачи:
- Ввод исходных данных из текстового файла.
- Вычисление параметров
и
. - Расчёт значений линейной зависимости
в точках 25, 32, 45. - Изображение графиков: экспериментальных точек, линии регрессии и рассчитанных значений.
Исходные данные задачи хранятся в текстовом файле input.txt (см. рис. B.10).
В первой строке файла хранится количество экспериментальных точек, в следующих двух строках — массивы абсцисс и ординат экспериментальных точек. В четвёртой строке хранится количество (3) и точки (25, 32, 45), в которых необходимо вычислить ожидаемое значение.
Текст программы решения задачи с комментариями приведён ниже.
#include <mgl2/qt .h>
#include <iostream>
#include <fstream>
using namespace std;
int sample ( mglGraph * gr )
{
mglData x2 ( 70 ), y2 ( 70 );
int i, n, k;
float h, a, b, sx =0, sy =0, syx =0, sx2 =0;
ifstream f; //Поток для чтения файла исходных данных
f.open ( " input.txt " );
F>>n; //Чтение исходных данных, n — количество экспериментальных точек.
mglData x ( n ), y ( n ); //x(n),y(n) — координаты экспериментальных точек
cout<<" X \n ";
for ( i =0; i<n; i++)
{
F>>x [ i ];
cout<<x [ i ]<<" ";
}
cout<<endl;
cout<<" Y \n ";
for ( i =0; i<n; i++)
{
F>>y [ i ];
cout<<y [ i ]<<" ";
}
cout<<endl;
F>>k;
cout<<" k = "<<k<<endl;
mglData xr ( k ), yr ( k );
//xr, yr — ожидаемые значения,
for ( i =0; i<k; i++)
F>>xr [ i ];
cout<<endl;
for ( i =0; i<n; i++)
{
sx+=x [ i ];
sy+=y [ i ];
syx+=y [ i ] * x [ i ];
sx2+=x [ i ] * x [ i ];
}
//Расчёт коэффициентов линии регрессиии.
b=(n*syx-sy * sx ) / ( n*sx2-sx * sx );
a=(sy-b* sx ) /n;
cout<<" a = "<<a<<" b = "<<b<<endl;
//Формирование массивов для изображения линии регрессии на графике.
for ( i =0; i <70; i++)
{
x2 [ i ]=x [ i ]+ 1;
y2 [ i ]=a+b*x2 [ i ];
}
//Вычисление ожидаемых значений — растворимость азотнокислого натрия
//при температурах 25, 32 и 45 градусов.
cout<<" Xr Yr \n ";
for ( i =0; i<k; i++)
{
yr [ i ]=a+b* xr [ i ];
cout<<xr [ i ]<<" "<<yr [ i ]<< endl;
}
gr->SetRanges ( x [ 0 ], 80, 70, 140 );
gr->set font size ( 3 );
gr->Axis ( ); //Оси координат
gr->Grid ( ); //Сетка
//Первая легенда
gr->AddLegend ( "Эксперимент", " b o " );
gr->Plot ( x, y, " b o " ); //График экспериментальных точек, голубой (b) цвет.
//Вторая легенда
gr->AddLegend ( "Расчёт", " r * " );
gr->Plot ( xr, yr, " r * " ); //График ожидаемых значений.
//Третья легенда
gr->AddLegend ( "Линия регрессии", " k - " );
gr->Plot ( x2, y2, " k - " ); //Изображение линиии регрессии.
gr->Title ( "Задача Менделеева" ); //Заголовок
gr->Label ( " x ", " t ", 0 ); //Подпись по оси абсцисс
gr->Label ( " y ", " NaNO_3 " ); //Подпись по оси ординат
gr->Legend ( 2 ); //Вывод легенды
return 0;
}
int main ( int arg c, char ** argv )
{
set locale (LC_CTYPE, " ru_RU.utf 8 " );
mglQT gr ( sample, " Plot " );
return gr.Run ( );
}После запуска программы на экране пользователь увидит следующие значения
X 0 4 10 15 21 29 36 51 68 Y 66.7 71 76.3 80.6 85.7 92.9 99.4 113.6 125.1 k=3 a=67.5078 b=0.87064 Xr Yr 25 89.2738 32 95.3683 45 106.687
Графическое решение задачи, полученное с помощью средств библиотеки MathGL, представлено на рис. B.11.
Для изучения всех возможностей MathGL, авторы советуют обратиться к документации по MathGL. При освоении библиотеки MathGL следует помнить, что логика и синтаксис библиотеки напоминает синтаксис Scilab и Octave.










