Рис.4.1. Схема взаимосвязей процедур и функций
Функции:
ReCalc (n: real; n1: real; alpha: real): real – возвращает угол преломления. n, n1 – показатели преломления, alpha – угол падения.
Menu(number: Integer): Integer – реализует работу с меню, возвращает выбранный пункт. number – предыдущий выбранный пункт меню.
ChangeN(flag: integer): real – возвращает новое значение показателя преломления. Если flag равен 1 – задается для первой среды, если 2 – для второй.
ChangeAl(n: real; n1: real; alpha: real): real – возвращает новое значение угла падения. n, n1 – показатели преломления, alpha – угол падения.
arcsin (x: real): real – возвращает арксинус аргумента x.
Процедуры:
MainCycle() – выполняет основной цикл программы.
GraphMode() – выполняет инициализацию графического режима.
Paint(n: real; n1: real; alpha: real) – отображает график, демонстрирующий преломление луча. n, n1 – показатели преломления, alpha – угол падения.
Recv() – выполняет вывод на экран реквизитов пользователя. Реквизиты хранятся в файле recv. txt.
SaveData(n: real; n1: real; alpha: real) – выполняет запись результатов в файл result. txt. n, n1 – показатели преломления, alpha – угол падения.
Info() – отображает на экран информацию о преломлении лучей.
LoadData(varn: real; varn1: real; varalpha: real) – выполняет загрузку данных из файла. n, n1 – показатели преломления, alpha – угол падения.
OutTextChangeAl() – выводит на экран вспомогательный текст при смене значения угла.
4.3. Описание функционирования
В основной программе выполняется единственная процедура MainCycle.
Перед основным циклом на экран выводятся реквизиты пользователя из файла "recv. txt". Затем выполняется установка входных данных по умолчанию, запись этих данных в файл, прорисовка графика и меню. Вызов меню выполняется в бесконечном цикле до тех пор, пока пользователь не выберет пункт "Выход". При выборе пункта "Информация" на экран будет выведена основная информация о преломлении света (процедура Info). При выборе пункта "Считать данные из файла" программа загрузит данные из файла "data. txt". При выборе пунктов "Изменить показатель преломления в 1-й среде", "Изменить показатель преломления во 2-й среде", "Изменить угол падения" можно менять соответствующие входные данные. При любом изменении данных результаты автоматически отображаются на графике и сохраняются в файл.
Рисунок 4.2. - Схема функционирования программы
4.4. Описание программных модулей
Я использовал в своей работе модули Graph и Crt (для работы с графическим и текстовым режимом соответственно).
Модуль Crtреализует работу в текстовом режиме. С помощью его процедур и функций можно проверять содержимое буфера клавиатуры и проверять код введенного символа.
Graphпозволяет работать с графическим режимом. С его помощью возможно отображение графических объектов. При помощи модуля Graph я выполнил прорисовку меню и графика.
5.1 Комплект поставки
В комплект поставки программного продукта входят следующие файлы:
kursach. exe– файл, запускающий программу.
info. txt - файл, содержащий справочную информацию.
recv. txt – файл, содержащий реквизиты пользователя.
ПЗ. doc - пояснительная записка в формате doc.
bold. chr, euro. chr, goth. chr, lcom. chr, litt. chr, sans. chr, scri. chr, simp. chr, smal. chr, trip. chr, tscr. chr– кириллические шрифты.
egavga. bgi – графический драйвер.
5.2. Порядок инсталляции
Для установки программы необходимо скопировать жесткий диск файлы kursach. exe, info. txt, recv. txt, *. chr и egavga. bgi. При необходимости можно создать файл data. txt, содержащий входные данные.
Во время тестовых испытаний я обнаружил несколько некорректных операций с плавающей точкой, ошибку переполнения стека, извлечение квадратного корня отрицательного аргумента, деление на ноль, некорректный вывод графика и некорректное сохранение результатов в файл. На данный момент все известные мне ошибки исправлены.
В результате выполнения работы я создал программный продукт, имитирующий модель преломления лучей на границе двух сред. Требования, изложенные в техническом задании, выполнены.
Я разработал удобный интерфейс, функцию вывода графика, отображающего преломление лучей на границе двух сред. Также имеется возможность работы с разными преломляющими средами, и смены угла падения.
ТЕХНИЧЕСКОЕ ЗАДАНИЕ
А.1 Общие сведения
Полное название программного продукта: "Преломление света на границе раздела двух сред".
Плановый срок начала работы: 17.02.06
Плановый срок завершения работы: 5.06.06
А.2 Основание для разработки
Основанием для разработки является задание на курсовую работу по дисциплине "Программирование и алгоритмические языки", выданное кафедрой программного обеспечения интеллектуальных систем студенту группы СУА-О5 Паранчуку Станиславу.
А. З Цель работы
Цель разработки - создать программный продукт, который позволит демонстрировать преломление лучей на границе двух сред.
А.4 Требования к программному продукту
А.4.1. Общие требования:
К данному программному продукту предъявляются следующие требования:
а) наличие графического пользовательского интерфейса;
б) возможность работы с файлом;
в) наличие справочного материала;
г) наличие справки о разработчике;
л) наличие контроля вводимых данных.
А.4.2. Функциональные требования:
Программный продукт должен обладать следующими функциями:
- расчет угла отражения на основании угла падения и коэффициентов преломления;
- вывод результатов графически.
А.4.3. Требования к техническому обеспечению
Программный продукт должен нормально функционировать на машине со следующими характеристиками:
- процессор I486 или выше;
- 16 Mb оперативной памяти;
- VGA - монитор с поддержкой разрешения 640x480.
А.4.4. Организационные требования
Программный продукт должен быть снабжен пояснительной запиской объёмом не менее 30 страниц;
документация должна быть оформлена в соответствии с ДСТУ 3008-95 "Документация. Отчеты в сфере науки и техники и правила оформления".
А.5 Этапы разработки и сроки выполнения работы
разработки и плановые сроки выполнения указаны в таблице А.1
Таблица А.1 Этапы и сроки выполнения работы
№ |
Вид работы |
Неделя |
1 |
Получения задания на разработку |
17.02.06 |
2 |
Разработка и согласование технического задания |
1 неделя |
3 |
Подбор и изучение материала по теме "Преломление лучей на границе раздела двух сред". Определение структуры программы |
2-3 недели |
4 |
Разработка алгоритмов, отвечающих за ввод данных |
4-5 неделя |
5 |
Разработка алгоритма расчета угла преломления |
6-7 неделя |
6 |
Разработка и реализация графического и пользовательского интерфейса |
8-9 неделя |
7 |
Тестирование и отладка программы |
10-11 неделя |
8 |
Написание пояснительной записки |
11-12 неделя |
9 |
Защита курсовой работы |
05.06.06 |
Приложение Б
РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ
Б.1 Установка программы
Для установки программы скопировать все файлы на жесткий диск.
Б. З Главное меню
Меню содержит следующие пункты: "Информация", "Считать данные из файла", "Изменить показатель преломления в 1-ой среде", "Изменить показатель преломления во 2-ой среде", "Изменить угол падения", "Выход". Передвижение по меню осуществляется при помощи клавиш "вверх" и "вниз", а также при помощи горячих клавиш.
Б. З.1 "Информация"
При вызове этого пункта меню на экране появится содержимое файла "info. txt" на нескольких страницах. Страницы перелистываются при помощи любой клавиши. После ознакомления с содержимым файла мы возвращаемся в меню.
Б. З.2 "Считать данные из файла"
При вызове этого пункта выполнится загрузка данных из файла "data. txt". Также выполнится пересчет угла преломления, вывод результатов на экран и в файл.
Б.3.3. "Изменить показатель преломления в 1-ой среде", "Изменить показатель преломления во 2-ой среде"
При вызове этих пунктов пользователю будет предложены на выбор некоторые среды преломления. Если необходимой среды нет в списке, пользователь может ввести показатель преломления самостоятельно.
Б.3.4. "Изменить угол падения"
При вызове этого пункта пользователь сможет изменить угол падения клавишами "вверх" и "вниз" а затем подтвердить или отменить ввод (клавиши ENTER и ESC соответственно).
Б.3.5. "Выход"
При нажатии этой клавиши происходит выход из программы
ФАЙЛЫ СПРАВОЧНОЙ ИНФОРМАЦИИ
info. txt – содержит теоретическую информацию о преломлении лучей.
Отражение и преломление света
на границе раздела двух сред
Рассмотрим падение плоской волны на границу, разделяющую две прозрачные однородные диэлектрические среды с показателями преломления n и n1. Будем считать, что граница представляет собой плоскость (так как в пределах бесконечно малой области любую поверхность можно считать плоской). Будем также считать, что сама граница раздела свет не поглощает.
После прохождения границы раздела двух сред падающая плоская волна разделяется на две волны: проходящую во вторую среду и отраженную.
Угол падения - это угол между лучом, падающим на преломляющую или отражающую поверхность и нормалью к поверхности в точке падения.
Угол преломления - это угол между преломленным лучом и нормалью к поверхности в точке преломления.
Угол отражения - это угол между отраженным лучом и нормалью к поверхности в точке отражения.
Закон преломления:
Качественная часть закона:
Падающий луч, преломленный луч и нормаль к поверхности раздела двух сред в точке падения лежат в одной плоскости.
Количественная часть закона:
Произведение показателя преломления на синус угла между лучом и нормалью сохраняет свое значение при переходе в следующую среду:
n*sin(alpha) = n1*sin(alpha)
РЕЗУЛЬТАТЫ РАБОТЫ ПРОГРАММЫ
Файл result. txt содержит результаты работы программы:
Показатель преломления n=1.0003
Угол падения alpha=60
Показатель преломления n1=1.3300
Угол преломления alpha1=41
ЭКРАННЫЕ ФОРМЫ
Рисунок Д.1-Вывод реквизитов
Рисунок Д.2-Главное меню
Рисунок Д.3-Информация о преломлении лучей
Рисунок Д.4-Изменение угла падения
ЛИСТИНГ ПРОГРАММЫ
usesgraph, crt;
function arcsin (x: real): real; {возвращает арксинус угла}
begin
if (x=1) then arcsin: = PI/2 else
if (x=-1) then arcsin: = - 1*PI/2 else
if (x>0) then
arcsin: =arctan(sqrt((x*x) /(1-x*x))) else
arcsin: =-arctan(sqrt((x*x) /(1-x*x)));
end;
function ReCalc(n: real; n1: real; alpha: real): real; {высчитывает угол преломления}
var
radalpha, radalpha1: real; {углы в радианах}
begin
radalpha: =alpha*PI/180;
if ((n*sin(radalpha) /n1) <=1) then
begin
radalpha1: =arcsin(n*sin(radalpha) /n1);
ReCalc: =radalpha1*180/PI;
end
else
begin
ReCalc: =arcsin(1) *180/PI;
end;
end;
procedure Recv; {выводит на экран реквизиты пользователя}
var
f: text; {файл содержащий реквизиты пользователя}
n: integer;
s: string;
begin
n: =0;
{открываем файл для чтения}
assign(f, 'recv. txt');
reset(f);
ClearViewPort;
SetTextStyle(8,0,1);
SetColor (White);
{выводим содержимое файла на экран}
while not eof(f) do
begin
n: =n+15;
readln (f,s);
OutTextXY(0, n, s);
end;
{закрываем файл}
close(f);
repeat until keypressed;
readkey;
ClearViewPort;
end;
function Menu(number: Integer): Integer;
const
Selected = Cyan;
UnSelected = 255;
IV = 20;
var
str1: string;
ch: char;
begin
SetTextStyle(8,0,1);
while (true) do
begin
if (number=1) then
SetColor(Selected)
else SetColor (UnSelected);
OutTextXY(0, 1*IV, 'Информация (F1) ');
if (number=2) then
SetColor(Selected)
else SetColor (UnSelected);
OutTextXY(0, 2*IV, 'Считать данные из файла (L) ');
if (number=3) then
SetColor(Selected)
else SetColor (UnSelected);
OutTextXY(0, 3*IV, 'Изменить показатель преломления в 1-ой среде (1) ');
if (number=4) then
SetColor(Selected)
else SetColor (UnSelected);
OutTextXY(0, 4*IV, 'Изменить показатель преломления во 2-ой среде (2) ');
if (number=5) then
SetColor(Selected)
else SetColor (UnSelected);
OutTextXY(0, 5*IV, 'Изменить угол падения (A) ');
if (number=6) then
SetColor(Selected)
else SetColor (UnSelected);
OutTextXY(0, 6*IV, 'Выход (Esc) ');
SetColor(UnSelected);
ch: =ReadKey;
{если нажали esc - выходим}
if (ch = #27) then
begin
Menu: = 6;
break;
end;
{f1}
if (ch = #59) then
begin
Menu: = 1;
break;
end;
if ((ch = 'L') or (ch = 'l')) then
begin
Menu: = 2;
break;
end;
if ((ch = 'A') or (ch = 'a')) then
begin
Menu: = 5;
break;
end;
if (ch = '1') then
begin
Menu: = 3;
break;
end;
if (ch = '2') then
begin
Menu: = 4;
break;
end;
{"вверх" и "вниз"}
if (ch = #72) then number: =number-1;
if (ch = #80) then number: =number+1;
if (number = 0) then number: = 6;
if (number = 7) then number: = 1;
{ENTER}
if (ch = #13) then
begin
Menu: = number;
break;
end;
end;
end;
procedure GraphMode;
var
gd,gm: Integer;
begin
{драйвер - VGA, режим - VGAHi (640*480) }
gd: = VGA;
gm: = VGAHi;
InitGraph (gd,gm,''); {инициализация графики}
end;
procedure SaveData(n: real; n1: real; alpha: real); {сохраняет данные в файл}
var
f: text;
alpha1: real;
tempstr: string;
begin
alpha1: =ReCalc(n,n1,alpha);
assign(f, 'result. txt');
rewrite(f);
Str(n: 6: 4, tempstr);
writeln(f,concat('Показатель преломления n=', tempstr));
Str(alpha: 2: 0, tempstr);
writeln(f,concat('Угол падения alpha=', tempstr));
Str(n1: 6: 4, tempstr);
writeln(f,concat('Показатель преломления n1=', tempstr));
Str(alpha1: 2: 0, tempstr);
writeln(f,concat('Угол преломления alpha1=', tempstr));
close(f);
end;
procedure Paint(n: real; n1: real; alpha: real);
var
mx,my: Integer; {максимальные значения экранных координат}
delta,delta1: real;
radalpha, radalpha1, alpha1: real;
tempstr: string;
begin
{находим максимальные значения экранных координат}
mx: =GetMaxX;
my: =GetMaxY;
{пересчитываем угол преломления, находим радианные значения углов}
alpha1: =ReCalc(n, n1, alpha);
radalpha: =alpha*PI/180;
radalpha1: =alpha1*PI/180;
if (cos(radalpha) <>0.0) then
delta: = (my/3) *sqrt(1/sqr(cos(radalpha)) - 1)
else
delta: = 100000; {если косинус равен 0 - луч лежит на границе}
if (cos(radalpha1) <>0.0) then
delta1: = (my/3) *sqrt(1/sqr(cos(radalpha1)) - 1)
else
delta1: =-100000; {если косинус равен 0 - луч лежит на границе}
SetColor(White);
SetTextStyle(8, 0, 1);
{выводим n,alpha,n1,alpha1}
Str(n: 6: 4, tempstr);
OutTextXY(3, round(2*my/3-40), concat('n= ', tempstr));
Str(alpha: 2: 0, tempstr);
OutTextXY(3, round(2*my/3-20), concat('alpha= ', tempstr));
Str(n1: 6: 4, tempstr);
OutTextXY(3, round(2*my/3), concat('n1= ', tempstr));
Str(alpha1: 2: 0, tempstr);
OutTextXY(3, round(2*my/3+20), concat('alpha1= ', tempstr));
{выводим рамку}
SetColor(Yellow);
SetLineStyle(SolidLn, 0, NormWidth);
Line(0, round(my/3), mx, round(my/3));
Line(0, my, mx, my);
Line(0, round(my/3), 0, my);
Line(mx, round(my/3), mx, my);
{выводим границу между средами и нормаль}
SetColor(LightGray);
SetLineStyle(DottedLn, 0, NormWidth);
Line(round(mx/2), round(my/3), round(mx/2), my);
Line(0, round(2*my/3), mx, round(2*my/3));
{выводим стрелочки}
SetLineStyle(SolidLn, 0, NormWidth);
Line(round(mx/2) - 3, round(my/3) +10, round(mx/2), round(my/3));
Line(round(mx/2) +3, round(my/3) +10, round(mx/2), round(my/3));
{выводим падающий луч}
SetColor(Blue);
SetLineStyle(SolidLn, 0, NormWidth);
Line(round(mx/2), round(2*my/3), round(mx/2+delta), round(my/3));
{выводим преломленный луч}
SetColor(Red);
SetLineStyle(SolidLn, 0, NormWidth);
Line(round(mx/2), round(2*my/3), round(mx/2-delta1), round(my));
end;
procedure OutTextChangeAl; {выводит вспомогательный текст при смене значения угла}
begin
SetColor(White);
SetTextStyle(8, 0, 1);
OutTextXY(0,0, 'Значение угла падения меняется клавишами ');
OutTextXY(0, 20, '"вверх" и "вниз"');
OutTextXY(0,40, 'подтверждение - ENTER');
OutTextXY(0,60, 'отмена - ESC');
end;
function ChangeAl(n: real; n1: real; alpha: real): real;
var
ch: char;
alpha0: real;
begin
{запоминаем начальное значение угла на случай отмены}
alpha0: =alpha;
while (true) do
begin
ClearViewPort;
Paint(n,n1,alpha);
OutTextChangeAl;
ch: = readkey;
if (ch = #72) then alpha: =alpha-1;
if (ch = #80) then alpha: =alpha+1;
if (alpha = 90) then alpha: = 89;
if (alpha = - 1) then alpha: = 0;
if (ch = #13) then
begin
SaveData(n,n1,alpha); {сохраняем данные}
ChangeAl: = alpha;
break;
end;
if (ch = #27) then
begin
ChangeAl: = alpha0;
break;
end;
end;
end;
function ChangeN(flag: integer): real;
var
tempstr: string;
ch: char;
n: real;
code: integer;
begin
{переход в текстовый режим}
CloseGraph;
{принимаются только символы 1-9}
while ((ch<'1') or (ch>'9')) do
begin
ClrScr;
str(flag, tempstr);
writeln(concat('Выберите ',tempstr,'-ую среду: '));
writeln('1. Вода');
writeln('2. Глицерин');
writeln('3. Алмаз');
writeln('4. Воздух');
writeln('5. Полиэтилен');
writeln('6. Сапфир');
writeln('7. Хлористый натрий');
writeln('8. Сероуглерод');
writeln('9. Другая среда');
ch: =readkey;
end;
if (ch = '1') then ChangeN: =1.33;
if (ch = '2') then ChangeN: =1.47;
if (ch = '3') then ChangeN: =2.42;
if (ch = '4') then ChangeN: =1.0003;
if (ch = '5') then ChangeN: =1.52;
if (ch = '6') then ChangeN: =1.77;
if (ch = '7') then ChangeN: =1.53;
if (ch = '8') then ChangeN: =1.63;
if (ch = '9') then
begin
repeat
ClrScr;
write('Введите показатель преломления среды: ');
readln(tempstr);
val(tempstr, n, code);
until ((code = 0) and (n<=9) and (n>0));
ChangeN: =n;
end;
GraphMode;
end;
procedure LoadData(var n: real; var n1: real; var alpha: real); {загрузка данных из файла}
var
f: text;
begin
{открываем файл для чтения}
assign (f, 'data. txt');
reset (f);
{считываем по порядку значения n,n1,alpha}
readln(f, n);
readln(f, n1);
readln(f, alpha);
close (f);
SaveData(n,n1,alpha); {сохраняем данные}
end;
procedure Info;
var
f: Text;
n, i: Integer;
s, temp: String;
ch: Char;
priznak: Boolean;
const
st_length = 55;
ch_size = 20;
begin
n: = 0;
priznak: = false;
Assign(f, 'info. txt');
ClearViewPort;
SetTextStyle (1, 0, 1);
Reset (f);
while not Eof(f) do
begin
n: = n + 1;
if not priznak then ReadLn (f, s);
if Length(s) > st_length then
begin
priznak: = true;
temp: = s;
Delete (temp, st_length+1, Length(temp));
OutTextXY(0, ch_size * n, temp);
Delete (s, 1, st_length);
end
else
begin
priznak: = false;
OutTextXY (0, ch_size * n, s);
end;
if (n = 22) or Eof(f) then
begin
OutTextXY (200, 460, 'Нажмите любую клавишу... ');
repeat until keypressed;
ch: = readkey;
n: = 0;
ClearViewPort;
end;
end;
end;
procedure MainCycle; {основной цикл программы}
var
action: Integer;
n,n1,alpha,sinalpha1: real;
begin
{установка начальных значений}
n: =1.0003; {показатель воздуха}
n1: =1.33; {показатель воды}
alpha: =60; {начальное значение угла падения}
SaveData(n,n1,alpha);
action: =1; {курсор установлен на первом пункте меню}
GraphMode; {гр режим. }
ClearViewPort; {очищаем экран}
Recv; {выводим реквизиты пользователя}
SetTextStyle(1, 0, 1);
while (action<>6) do {6=выход}
begin
ClearViewPort; {очищаем экран}
Paint(n,n1,alpha); {выводим график}
action: =Menu(action); {считываем пункт меню}
if (action=1) then Info; {информация}
if (action=2) then LoadData(n,n1,alpha); {считываем из файла}
if (action=3) then
begin
n: = ChangeN(1); {изменяем показатель преломления 1}
SaveData(n,n1,alpha);
end;
if (action=4) then
begin
n1: = ChangeN(2); {изменяем показатель преломления 2}
SaveData(n,n1,alpha);
end;
if (action=5) then alpha: = ChangeAl(n,n1,alpha); {изменяем угол падения}
end;
CloseGraph; {закрываем графический режим}
end;
begin
MainCycle;
end.
1. Фаронов В.В. "Турбо Паскаль 7.0. Начальный курс. " Учебное издание - М.: Нолидж, 2000, 575 с.
2. Н. Культин "TurboPascal в задачах и примерах" - С.: БХВ-Петербург, 2004,256 с.
3. Ахманов С. Г "Физическая оптика. Учебник (Ахманов)" - С.: МГУ, 2004, 213 с.