ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 09.06.2020

Просмотров: 132

Скачиваний: 4

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.


4 АЛГОРИТМЫ И ЛИСТИНГИ ПРОГРАММНОГО ПРОДУКТА ДЛЯ

МОДЕЛИРОВАНИЯ РАСПРЕДЕЛЕНИЯ ЭНЕРГЕТИКИ НАГРУЗОК

4.1 Структура программы и содержимое форм


Код, выполняющий основные функции программы, выполнен в виде отдельных модулей:

- u_main – модуль класса главного окна-формы frm_main;

- u_param – модуль класса формы параметров frm_param;

- u_paint – модуль управления основных отображений;

- u_lopatka – основной модуль отображения и расчета напряжений в лопатке;

- u_kamen – модуль отображения и расчета напряжений на камне кулисы;

- u_glcontrol – вспомогательный модуль управления библиотекой OpenGL.

Программа также содержит форму справки, содержащую визуальные компоненты, отображающие справочный текст в наглядном виде.

Рисунок 4.1 – Главная форма программы

Главная форма программы содержит компоненты: управляющее главное меню (MainMenu1) и компонент отображения 3D моделей (OpenGLControl1).

Форма параметров содержит таблицу параметров лопатки и их значений – компонент типа TStringGrid (SG). При дизайне формы задаются значения по умолчанию.

Рисунок 4.2 – Форма параметров лопатки гидротурбины

Н иже приведена блок-схема основного алгоритма программы (рисунок 4.3).

























Рисунок 4.3 – Блок-схема программы

После запуска программы и инициализации графической библиотеки пользователю предоставляется выбор типа модели. Пользователь может ввести параметры, после чего модель рассчитывается и перерисовывается в соответствии с введенными значениями. Во время рассчета модели программа выполняет цикл вычислений и затем передает управление обратно пользователю. Также пользователь может управлять масштабом и углом поворота модели с помощью мыши и клавиатуры.


4.2 Инициализация и управление графической библиотекой


Модуль u_glcontrol использует библиотеки GL и GLU, которые содержат прототипы основных функций OpenGL определённых в opengl32.dll и glu32.dll. Библиотека OpenGLContext управляет связью с компонентом OpenGLControl1 на главной форме. Библиотека Windows предоставляет стандартные WinAPI функции OpenGL.

Ниже приведен листинг данного модуля.

unit u_glcontrol;

{$mode objfpc}{$H+}

interface

uses

Windows, Classes, SysUtils,GL,GLU,OpenGLContext, Controls;

procedure InitGL(OpenGLControl1:TOpenGLControl);

procedure ResizeGL(OpenGLControl1:TOpenGLControl);

procedure BeginSelectGL(OpenGLControl1: TOpenGLControl; x,y:integer);

function EndSelectGL(OpenGLControl1: TOpenGLControl):cardinal;

procedure OutText (txt : PChar);

var

selBuffer:array[0..15] of Cardinal;//количество элементов в массиве 4*максимальное число выбранных объектов

implementation

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

procedure InitGL(OpenGLControl1:TOpenGLControl);

var i: integer;

begin

glClearColor(167/255.0, 203/255.0, 236/255.0, 0);

glEnable(GL_COLOR_MATERIAL);

// glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

glEnable(GL_DEPTH_TEST);

wglUseFontOutlines(TCustomControl(OpenGLControl1.Owner).canvas.handle, 0, 255, 1000, 0, 0.10,WGL_FONT_POLYGONS, nil);

ResizeGL(OpenGLControl1);

end;

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

procedure ResizeGL(OpenGLControl1: TOpenGLControl);

begin

glViewport (0, 0, OpenGLControl1.Width, OpenGLControl1.Height);

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

gluPerspective(45, OpenGLControl1.Width / OpenGLControl1.Height, 0.1, 1000);

glMatrixMode(GL_MODELVIEW);


//OpenGLControl1.Paint;

end;

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

procedure BeginSelectGL(OpenGLControl1: TOpenGLControl; x,y:integer);

const PICK_OBJECTS=10;

var viewport:TViewPortArray;

begin

glSelectBuffer ( PICK_OBJECTS, selBuffer );

glGetIntegerv ( GL_VIEWPORT, viewport );

glMatrixMode ( GL_PROJECTION );

glRenderMode ( GL_SELECT );

glLoadIdentity();

gluPickMatrix ( x, viewport[3] - y, 2, 2, viewport );

gluPerspective(45, OpenGLControl1.Width / OpenGLControl1.Height, 0.1, 1000);

glMatrixMode ( GL_MODELVIEW );

end;

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

function EndSelectGL(OpenGLControl1: TOpenGLControl): cardinal;

begin

if glRenderMode ( GL_RENDER )>0 then

Result:=selBuffer[3] else Result:=0;

ResizeGL(OpenGLControl1);

end;

procedure OutText (txt : PChar);

begin

glPushAttrib(GL_ALL_ATTRIB_BITS);

glListBase(1000);

glCallLists(Length (txt), GL_UNSIGNED_BYTE, txt);

glPopAttrib;

end;

end.

Процедура InitGL инициализирует графическую библиотеку. glClearColor устанавливает цвет (в нашем случае чёрный), которым будет заполняться экран при очищении. У этой процедуры - 4 параметра, что соответствует RGBA. glEnable(GL_DEPTH_TEST) – выполняет тест глубины модели. wglUseFontOutlineswindows-функция создания списков для объемного отображения шрифта. В данном случае за образец берется шрифт главной формы, как предка компонента OpenGLControl1.

Процедура ResizeGL устанавливает размер и режим окна отображения модели. glViewport устанавливает область вывода - область, в которую OpenGL будет выводить изображение. В нашем случае – весь компонент. glLoadIdentity заменяет текущую матрицу видового преобразования на единичную (матрицу идентичности), т.е. просто сбрасывает изменения. gluPerspective устанавливает, что модель будет отображаться в перспективе под углом 450. glMatrixMode устанавливает режим матрицы видового преобразования. Если изменяется тип проецирования, положение или направление камеры, то параметр должен быть GL_PROJECTION. После того, как изменения завершены, вызывается процедура с параметром GL_MODELVIEW.

Процедуры BeginSelectGL и EndSelectGL позволяют выбрать конкретный примитив (объект) модели с помощью буфера выбора. Смысл выбора объектов заключается в том, что имея двумерные координаты мышки, необходимо выбрать объект в трехмерном мире. Для этого выполняются переводы из 2D в 3D или обратно.

Для того чтобы буфер выбора имел силу, нужно чтобы все объекты имели свои идентификаторы. Без них OpenGL не будет знать, что чему должно соответствовать в программе. Идентификация (далее имя) объекта - это процесс, при котором OpenGL получает уникальное имя объекта.

Все поименованные объекты находятся в стеке имен. Для того чтобы начать работу с буфером выбора нужно очистить стек имен. Делает это функция glInitNames(). Способ задачи имен заключается в том, что мы устанавливаем нулевой объект, а затем загружаем все имена через glLoadName(ID), где ID - идентификатор объекта.

Массив selBuffer содержит информацию о выбранных объектах. Каждый объект занимает четыре поля, четвертое из них содержит идентификатор выбранного объекта.

Процедура BeginSelectGL переходит в 2D режим, запомнив текущую матрицу и установить режим glRenderMode() в GL_SELECT. Этот режим позволяет рисовать нам плоские объекты при этом не портить FrameBuffer, при этом вся система буфера выбора начинает работать в "активном режиме", то есть вести запись в буфер выбора. Принцип работы функции gluPickMatrix заключается в том, что она создает матрицу проекции вокруг курсора. Это позволяет рисовать объекты в этом регионе (регион будет задан параметрами функции gluPickMatrix()). Следовательно, если объект в этом регионе рисуется, то буфер выбора запоминает его и записывает в массив, который мы передали в glSelectBuffer(). Первые два параметра функции gluPickMatrix() - это координаты мышки. Вторые два параметра ширина и высота области, начиная от начальной точки (первых двух параметров). Обычно их задают двойкой.


Далее вызывается стандартную для приложения перспективу. Это нужно для того чтобы создать проекционную матрицу для региона, который мы указали в функции gluPickMatrix(). Затем переходим в матрицу модели glMatrixMode(GL_MODELVIEW) и рисуем объекты в режиме выбора. Затем вызывается функция glRenderMode() с параметром GL_RENDER. Функция вернет количество объектов находящихся под тем регионом, который мы указали в функции gluPickMatrix().

Следует заметить, что между BeginSelectGL и EndSelectGL необходимо «прорисовать» модель и задать идентификаторы. Функция EndSelectGL выдает идентификатор выбранного объекта.

Процедура OutText выводит объемный текст в текущем положении.


4.3 Отображение модели


4.3.1 Основные функции отображения 3D фигур. Отображение 3D модели с помощью графической библиотеки OpenGL происходит с использованием буферов изображений. После того, как 3D модель прорисуется на невидимом буфере, с помощью команды SwapBuffers он заменяет видимый, благодаря чему мы не видим процесс построения, и прорисовка на экране происходит мгновенно. В модуле u_paint содержится код отображения начала координат и вызов вызов функции прорисовки самой модели. Команды glClear и glLoadIdentity стирают предыдущее изображение. glTranslatef позволяет отобразить систему координат смещенной от пользователя на значение (xdist,ydist,zdist). glRotated позволяет вращать систему координат на определенный угол.

Примитивы в OpenGL отображаются через список вершин, заключенных в операторы glBegin(), glEnd. Значение GL_LINES показывает способ отображения – в виде линий. glPopMatrix и glPushMatrix позволяют запоминать и возвращать в модель уже отображенное изображение. Эти директивы используются для того, чтобы прорисовывать отдельные смещенные (повернутые) элементы, не трансформируя уже имеющееся изображение.

unit u_paint;

{$mode objfpc}{$H+}

interface

uses

Classes, SysUtils, GL,OpenGLContext, u_volna_example, u_lopatka,u_glcontrol;

procedure Draw(OpenGLControl:TOpenGLControl;alpha,beta:integer;xdist,ydist:single;
zdist:integer);

procedure Draw(OpenGLControl:TOpenGLControl;alpha,beta:integer;xdist,ydist:single;
zdist:integer;SelectedObject:cardinal);

procedure DrawInternal(alpha,beta:integer;xdist,ydist:single;zdist:integer;

SelectedObject:cardinal);

implementation

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

procedure Draw(OpenGLControl: TOpenGLControl; alpha, beta: integer; xdist,

ydist: single; zdist: integer);

begin

Draw(OpenGLControl,alpha,beta,xdist,ydist,zdist,0);

end;

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

procedure Draw(OpenGLControl:TOpenGLControl;alpha,beta:integer;xdist,ydist:single;zdist:integer;SelectedObject:cardinal);

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

begin

DrawInternal(alpha,beta,xdist,ydist,zdist,SelectedObject);

OpenGLControl.SwapBuffers;

end;

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

procedure DrawInternal(alpha,beta:integer;xdist,ydist:single;zdist:integer;

SelectedObject:cardinal);

begin

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glLoadIdentity;

glTranslatef(xdist,ydist,-zdist);

glPushMatrix;

glRotated(alpha, 0,1,0);

glRotated(beta, -1,0,0);

glLineWidth(3);

glBegin(GL_LINES);

glColor3d(1,0,0);

glVertex3d(0,0,0);

glVertex3d(1,0,0);

glColor3d(0,1,0);

glVertex3d(0,0,0);

glVertex3d(0,1,0);

glColor3d(0,0,1);

glVertex3d(0,0,0);

glVertex3d(0,0,-1);

glEnd();

Draw_(SelectedObject);

//текст

glPushMatrix; glColor3d(1,0,0);

glTranslatef(1, 0,0);

outText ('X');

glPopMatrix;

glPushMatrix;

glTranslatef(0, 1,0); glColor3d(0,1,0);


outText ('Y');

glPopMatrix;

glTranslatef(0, 0,-1); glColor3d(0,0,1);

outText ('Z');

// Draw_volna(SelectedObject);

glPopMatrix;

end;

end.

4.3.2 Функции отображения лопатки гидротурбины. Для отображения криволинейной поверхности лопатки используются дискретные элементы-четырехугольники. Их координаты задаются с шагом dx и dy (по умолчанию равны 0,04). Основные элементы лопатки располагаются на передней и задней части лопатки. Отображение одного дискретного элемента производится с помощью процедуры PaintElem, где параметр side указывает сторону лопатки (true – передняя, false – задняя). Значение z координаты по параметрам x, y, side вычисляется функцией GetZ. Данная функция учитывает геометрию и угол поворота лопатки. Пределы изменения координаты x вычисляются функциями Xmin(y) и Xmax(y).

В процедуре Draw_ имеются два цикла по координатам x и y. В начале и в конце цикла по координате x строится элемент правой или левой стенки лопатки процедурой PaintWallx. Переменные xmin1, xmax1 показывают абсциссу предыдущего элемента, это необходимо для того, чтобы в боковых стенках не было «просветов». В крайних положениях координаты y строятся элементы верхней и нижней стенки модели процедурой PaintWally. Внутри цикла строятся элементы задней и передней поверхностей лопатки, которым назначаются последовательно увеличивающиеся идентификаторы IDName. Общее количество идентификаторов сохраняется в переменной KNames. Булевая переменная ColorsReady указывает на то, что значения напряжений в элементах вычислены и при этом цвет элемента задается в соответствии с этим значением.

var R1,R2,x01,Ymax,a12,b12,c12,z0,y0,k,fi:single;

ax,bx,az,bz, mnoj,Qmax,Qmin:double;

Q:Array of double;

KNames:Cardinal;

ColorsReady:boolean;

implementation

uses u_param;

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

function Xmin(const y: single): single;

begin

Xmin:=sqrt(sqr(R1)-sqr(y))-x01;

if Xmin<ax then ax:=Xmin;

end;

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

function Xmax(const y: single): single;

begin

Xmax:=sqrt(sqr(R2)-sqr(y))-x01;

if Xmax>bx then bx:=Xmax;

end;

function GetZ(x,y:single;fs:boolean):single;

var z:single;

begin

if fs then

z:=(c12*((y+y0)/b12)-x/a12)-z0

else z:=-(c12*((y+y0)/b12-x/a12))-z0;

GetZ:=z*cos(fi)-y*sin(fi);

end;

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

procedure Draw_(SelectedObject:cardinal);

procedure PaintElem(x,y:single;side:boolean);

begin

glBegin(GL_QUADS);

glVertex3d(x,y,GetZ(x,y,side));

glVertex3d(x,y+dy,GetZ(x,y+dy,side));

glVertex3d(x+dx,y+dy,GetZ(x+dx,y+dy,side));

glVertex3d(x+dx,y,GetZ(x+dx,y,side));

glEnd();

end;

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

procedure PaintWallx(x,y,xdep:single);

begin

glBegin(GL_QUADS);

glVertex3d(x,y,GetZ(x,y,true));

glVertex3d(x,y,GetZ(x,y,false));

glVertex3d(x,y+dy,GetZ(x,y+dy,false));

glVertex3d(x,y+dy,GetZ(x,y+dy,true));

glEnd(); glBegin(GL_QUADS);

glVertex3d(x,y,GetZ(x,y,true));

glVertex3d(x,y,GetZ(x,y,false));

glVertex3d(x+xdep,y,GetZ(x+xdep,y,false));

glVertex3d(x+xdep,y,GetZ(x+xdep,y,true));

glEnd(); glBegin(GL_QUADS);

glVertex3d(x,y+dy,GetZ(x,y+dy,false));

glVertex3d(x,y+dy,GetZ(x,y+dy,true));

glVertex3d(x+xdep,y+dy,GetZ(x+xdep,y+dy,true));

glVertex3d(x+xdep,y+dy,GetZ(x+xdep,y+dy,false));

glEnd();

end;

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

procedure PaintWally(x,y:single);

begin

glBegin(GL_QUADS);

glVertex3d(x,y,GetZ(x,y,true));

glVertex3d(x,y,GetZ(x,y,false));

glVertex3d(x+dx,y,GetZ(x+dx,y,false));

glVertex3d(x+dx,y,GetZ(x+dx,y,true));


glEnd();

end;

var x,y,xmin1,xmax1:single;

IDName:Cardinal;

frontside:boolean;

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

begin

glColor3d(0.5,0.5,1);

glInitNames();

IDName:=1;

glPushName(0);

y:=0;

xmin1:=Xmin(y);

xmax1:=Xmax(y);

while y<Ymax do

begin

x:=Xmin(y);

//левая стенка лопатки

PaintWallx(x,y,xmin1-x);

xmin1:=x;

while x<Xmax(y) do

begin

//цикл по всем элементам поверхности

if SelectedObject=IDName then

glColor3d(1,0,0)

else

begin

if not ColorsReady then glColor3d(x-trunc(x),y-trunc(y),1) else glColor3d((Q[IDName]-Qmin)/(Qmax-Qmin),1-(Q[IDName]-Qmin)/(Qmax-Qmin),0);

end;

//элемент передней части лопатки

glLoadName(IDName);

PaintElem(x,y,true);

inc(IDName);


//элемент передней части лопатки

glLoadName(IDName);

PaintElem(x,y,false);

inc(IDName);

x:=x+dx;

//нижняя и верхняя стенки

if (y=0)or(y+dy>Ymax) then PaintWally(x,y);

end;

//правая стенка лопатки

PaintWallx(x-dx,y,xmax1-x+dx);

xmax1:=x;

y:=y+dy;

end;

KNames:=IDName;

end;


4.4 Алгоритм расчета механической нагрузки лопатки гидротурбины


Окончательной задачей алгоритма является нахождение значений механических нагрузок в каждом элементе модели лопатки. В дальнейшем, в зависимости от значения нагрузки элемент будет окрашиваться в соответствующий нагрузке цвет (зеленый цвет – минимальная нагрузка, красный цвет – максимальная). Очевидно, смыслом данного алгоритма является нахождение статической функции. Пусть в основной формуле для нахождения нагрузки (2.38) зададим время t=1 и вынесем из-под временного интеграла функцию Грина и произведем интегрирование.

(4.1)

(4.2)

где x, y, z – координаты конкретного элемента.

Вычисление интеграла по трехмерной области производится методом последовательных сложений элементарных объемов, умноженных на подынтегральную функцию. Функция вычисляет интеграл вида:

, (4.3)

где V – пространство модели.

Выпишем конечное значение подынтегральной функции с учетом (2.32) и (2.33).

(4.4)


где - скорость течения жидкости на входе, м/с;

- ускорение течения потока жидкости, м/с2.

Каждому именованному элементу модели назначается элемент массива Q механических нагрузок. Вычисление всей модели производится функцией Calc. Функция CalcElem возвращает значение нагрузки для одного элемента с координатами (xp,yp). Функция F возвращает значение подынтегральной функции. Алгоритм нахождения тройного интеграла представляет собой циклы по соответствующим пространственным координатам . Крайние значения координат определяются функциями поверхностей модели. Для того, чтобы процессор не выполнял ненужную работу постоянный множитель mnoj вынесен за знак интеграла. Qmin и Qmax показывают соответственно минимальное и максимальное значение напряженности для элемента (эти переменные необходимы для оценки всей модели и задания цвета).

var Q:Array of double;

procedure Calc;

var IDName:cardinal;

function CalcElem(xp,yp:single;side:boolean):double;

function F(eps,eta,ksi:double):double;

//функция нахождения подынтегрального выражения

begin

Result:=exp(-sqr(xp-eps)/1131798)*exp(-sqr(yp-eta)/1131798)*(exp(-sqr(GetZ(xp,yp,side)-ksi)/1131798)+exp(-sqr(GetZ(xp,yp,side)+ksi)/1131798));