Моделювання експериментів у дзеркальній кімнаті

Теоретичні відомості для моделювання оптичних експериментів в дзеркальній кімнаті. Закони відбивання променів від дзеркал. Особливості об’єктно-орієнтованого програмування. Програмна реалізація моделі оптичних експериментів в дзеркальній кімнаті.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык украинский
Дата добавления 13.11.2016
Размер файла 193,2 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru/

ЗМІСТ

РОЗДІЛ 1. ПОСТАНОВКА ЗАДАЧІ ДЛЯ РОЗРОБКИ ПОГРАМИ

1.1 ВИБІР МЕТОДУ ВИРІШЕННЯ ЗАДАЧІ

1.2 ТЕОРЕТИЧНІ ВДІОМОСТІ ДЛЯ МОДЕЛЮВАННЯ ОПТИЧНИХ ЕКСПЕРИМЕНТІВ В ДЗЕРКАЛЬНІЙ КІМНАТІ

1.3 ЗАКОНИ ВІДБИВАННЯ ПРОМЕНІВ

1.4 ВІДБИВАННЯ ПРОМЕНІВ ВІД ПЛОСКОГО ДЗЕРКАЛА

1.5 ВІДБИВАННЯ ПРОМЕНІВ ВІД СФЕРИЧНИХ ДЗЕРКАЛ (ОПУКЛОГО ТА ВВІГНУТОГО)

РОЗДІЛ 2. ОСОБЛИВОСТІ ОБ'ЄКТНО - ОРІЄНТОВАНОГО ПРОГРАМУВАННЯ

2.1 ОСНОВНІ ХАРАКТЕРИСТИКИ СЕРДОВИЩА ПРОГРАМУВАННЯ BORLAND C++ BUILDER

2.2 ОСНОВНІ ХАРАКТЕРИСТИКИ ОБ'ЄКТНО - ОРІЄНТОВАНОГО ПРОГРАМУВАННЯ

2.3 ВЕКТОРИ

2.4 ОПЕРАЦІЇ ВВЕДЕННЯ ТА ВИВЕДЕННЯ З ПОТОКУ

РОЗДІЛ ІІІ. ПРОГРАМНА РЕАЛІЗАЦІЯ МОДЕЛІ ОПТИЧНИХ ЕКСПЕРИМЕНТІВ В ДЗЕРКАЛЬНІЙ КІМНАТІ

3.1 ДЕКОМПОЗИЦІЯ ВИХІДНОЇ ЗАДАЧІ НА ФУНКЦІОНАЛЬНІ МОДУЛІ

3.2 ПРОГРАМА ЗАДАЧІ ТА ЇЇ ОПИС

3.3 ІНСТРУКЦІЯ КОРИСТУВАЧА ДЛЯ РОБОТИ З ПРОГРАМОЮ

ДОДАТОК

РОЗДІЛ 1. ПОСТАНОВКА ЗАДАЧІ ДЛЯ РОЗРОБКИ ПОГРАМИ

1.1 ВИБІР МЕТОДУ ВИРІШЕННЯ ЗАДАЧІ

Дзеркальна кімната представляє в плані довільний замкнутий М-кутник (4 ? М ? 9), кожна стіна - плоске або сферичне дзеркало. Для проведення експериментів необхідно визначити для кожної стіни кімнати вид дзеркала (плоске або сферичне), а для кожного сферичного дзеркала - його тип (увігнуте або опукле) і радіус кривизни.

Основна функція програмної системи - проведення оптичного експерименту, при якому з деякої точки на одній зі стін кімнати, під певним кутом до цієї стіни (кут може варіюватися від 0 до 180 градусів) випускається промінь світла, і потім показується його шлях всередині кімнати з урахуванням відображень від дзеркал. Траєкторія променя визначається фізичними законами відбиття від дзеркальних поверхонь.

Мета моделювання - підбір користувачем системи параметрів дзеркал і вихідного кута випущеного променя, при яких промінь, відбиваючись від дзеркальних стін, потрапляє в потрібну точку (зону) кімнати.

При візуалізації оптичного експерименту показаний план кімнати і зображений шлях променя в кімнаті.

Користувач системи має можливість:

• визначати число М стін кімнати і малювати її план (наприклад, вказуючи мишею на екрані комп'ютера кутові точки кімнати);

• задавати і змінювати параметри дзеркал (вид, тип, радіус кривизни), точку випускання променя і його вихідний кут;

• запам'ятовувати у файлі копію оптичного експерименту, зберігаючи всі його параметри, і зчитувати збережену копію з файлу в робоче вікно.

Зазначені дії користувач може виробляти в довільному, зручному для нього порядку, і зміна одного параметра експерименту не зачіпає інші встановлені параметри.

1.2 ТЕОРЕТИЧНІ ВДІОМОСТІ ДЛЯ МОДЕЛЮВАННЯ ОПТИЧНИХ ЕКСПЕРИМЕНТІВ В ДЗЕРКАЛЬНІЙ КІМНАТІ

Для початку обираємо типи дзеркал та радіус кривизни для опуклих дзеркал, будуємо многокутник, та перевіряємо чи він є правильним(сторони не перетинаються). Будуємо точку, з якої проектуватиметься промінь, та точку яка вказував напрям руху променя. Знаходимо всі точки відбивань та малюємо рух світлового променя між цими точками. Для побудови цих точок перевіряється умова чи точка знаходиться на стороні многокутника.

Для побудови світлового променя будується пряма між точками з якої проектується промінь та точкою, який вказує напрям променя і перевіряється умова, з якою з сторін многокутника перетинається ця пряма. Знаходиться точку перетину цих двох прямих та точка відбивання. На основі точки перетину та точки відбивання будується нова пряма, і знову перевіряється умова, з якою з сторін многокутника вона перетинається. Ця процедура проводитиметься стільки раз скільки відбивань ми вказали.

1.3 ЗАКОНИ ВІДБИВАННЯ ПРОМЕНІВ

Дзеркало - поверхня, яка паралельні пучки відбиває паралельними пучками.

Світловий промінь -- умовна лінія, вздовж якої світлове випромінювання переносить енергію.

Закони відбивання

Перший закон відбивання світла: падаючий і відбитий пучки лежать в одній площині з перпендикуляром до відбиваючої поверхні, поставленим у точці падіння світлового пучка.

Щоб установити, як пов'язані напрями променів світла -- того, що падає, та відбитого, - визначимо кути падіння та відбивання.

Кутом падіння променя називають кут між променем, що падає, і перпендикуляром до дзеркала, поставленим у точці падіння (Рис. 3.1) Кут падіння позначають часто грецькою літерою б (альфа). А кут між відбитим променем і перпендикуляром до дзеркала називають кутом відбивання та позначають часто в(бета).

Хід променів при відбиванні світла має властивість оборотності:

Якщо точковий об'єкт і його зображення поміняти місцями, то хід променів при цьому не зміниться, зміниться лише їхній напрям.

Рис.1.3.1 Перший закон відбивання світла

Другий закон відбивання світла: кут відбивання завжди буде дорівнювати куту падіння світла. Розглянуте відбиття світла називають дзеркальним (Рис.3.1.1). Воно відбувається в разі відбиття світла від дуже гладкої поверхні. У такому разі паралельний пучок променів після відбиття залишається паралельним. (Пригадайте сонячних зайчиків. Відбиті від дзеркальця промені не розсіюються, а відбиваються одним пучком, тому і засліплюють. І саме ця властивість променів - не розсіюватись, допомогла Архімеду спалити ворожі кораблі).

1.4 ВІДБИВАННЯ ПРОМЕНІВ ВІД ПЛОСКОГО ДЗЕРКАЛА

Якщо побудувати хід відбитих від дзеркала променів, що вийшли із точкового джерела світла S (Рис. 3.2.1), ми помітимо, що продовження відбитих променів перетинаються в одній точці S?. Людині, в око якої потраплять відбиті промені, здаватиметься, що всі вони вийшли з точки S?.

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

Рис. 3.2.1 Відбивання променів від плоского дзеркала

Зображення у плоскому дзеркалі уявне, пряме, дзеркальне, дорівнює за розмірами предметові і знаходиться за дзеркалом на такій же відстані від нього, як і предмет перед дзеркалом.

1.5 ВІДБИВАННЯ ПРОМЕНІВ ВІД СФЕРИЧНИХ ДЗЕРКАЛ (ОПУКЛОГО ТА ВВІГНУТОГО)

Сферичне дзеркало може бути опуклим або увігнутим -- в залежності від того, який бік сегмента сфери -- опуклий або увігнутий -- є відбиваючий. Центр відповідної сферичному дзеркалу сфери називається його центром або оптичним центром, середина сегмента -- полюсом дзеркала, пряма, що проходить через центр та полюс -- головною оптичною віссю дзеркала. Інші прямі, що проходять через центр дзеркала та точку, відмінну від полюса, називаються його бічними оптичними осями, параксіальні промені, паралельні головній оптичній осі опуклого сферичного дзеркала, так само як і продовження параксіальних променів,

паралельних головній оптичній осі увігнутого сферичного дзеркала, перетинаються в одній точці, що зветься його фокусом. Він розташований посередині між центром та полюсом дзеркала, тобто відстань (f) його до дзеркала дорівнює половині радіуса (R)[1] :

Увігнуте дзеркало -- збирає пучок світла після відбивання, опукле -- розсіює.

Рівняння спряжених точок і зображення предмета у сферичних дзеркалах за умови параксіальності променів такі самі, як для сферичних лінз.

Промінь, який падає в оптичний центр сферичного дзеркала, відбивається від дзеркала під кутом, рівним куту падіння. Хід променів для випадку ввігнутого дзеркала (паралельний оптичній осі пучок променів -- параксіальні промені) зображений на Рис. 3.3.1, а; для опуклого дзеркала -- на Рис. 3.3.1, б.

Рис. 3.3.1 Промінь, що падає в оптичний центр сферичного дзеркала

О - полюс сферичного дзеркала

С - оптичний центр сферичного дзеркала

F - головний фокус

R - радіус дзеркала

Для моделювання оптичних експериментів ми визначили основні закони відбивання променів від дзеркала. Описали як саме відбиваються промені від таких дзеркал як плоске та сферичне. Визначили, що сферичне дзеркало поділяється на опукле та увігнуте.

РОЗДІЛ 2. ОСОБЛИВОСТІ ОБ'ЄКТНО - ОРІЄНТОВАНОГО ПРОГРАМУВАННЯ

2.1 ОСНОВНІ ХАРАКТЕРИСТИКИ СЕРДОВИЩА ПРОГРАМУВАННЯ BORLAND C++ BUILDER

Borland C++ Builder - це одна з найпотужніших систем, що дозволяє на найсучаснішому рівні створювати як окремі прикладні програми Windows, так і розгалужені комплекси, призначені для роботи в кооперативних мережах і в Інтернет.

Компанія Borland пропонує потужний набір власних розширень мови C++, що забезпечує підтримку VCL бібліотеки (Visual Component Library). У C++ Builder поряд із звичайними об`єктними класами мови C++, з`явилися нові компонентні класи (компоненти).

Для візуалізації інтерфейсів програмного забезпечення існує цілий ряд спеціально розроблених елементів інтерфейсу - візуальних компонентів, що дозволяють відображати різну інформацію й здійснювати керування програмою в цілому.

Саме наявність візуальних засобів побудови інтерфейсів для Windows в C++ Builder, а також створюване ним візуальне програмне забезпечення закріпили за ним термін «візуальне програмування»[5].

Конструювання методом «перетягування» дозволяє створювати додаток простим перетаскуванням захоплених мишею візуальних компонентів з палітри на форму додатка[7].

Компоненти - це будівельні блоки для додатків. Тобто, використовуються об`єкти-компоненти зі своїми можливостями і об`єднаються в один додаток. C++ Builder сам побудований на компонентах і робота з компонентами в C++ Builder надійна та проста.[6]

Отже, C++ Builder настільки багатогранний, що для того, щоб розповісти про всі його аспекти однієї книги не вистачить. Він простий у використанні та за допомогою нього можна створити будь яку програму.

Для створення своєї програми я використала наступні компоненти С++ Builder. Form - це вікно програми, на якому розміщуються візуальні елементи. Щоб додати компонент Form потрібно натиснути кнопку “New Form” на панелі інструментів.

Panel - це компонент, що є сукупністю властивостей, які використовуються для відображення надписів і групування кнопок. Такі властивості цього компоненту, як BevelInner, BevelOuter, BevelWidth, BorderStyle, BorderWidth показують різні можливості зміни зовнішнього вигляду панелі. Наприклад, можна зробити її або втиснутою, або більш опуклою.

Canvas -- це поверхня (форми або компоненту image), на якій відповідні методи можуть викреслювати графічні примітиви. Вид графічних елементів визначають властивості поверхні, на якій ці елементи викреслюються.

UpDown - компонент для завдання потрібного цілого числа за допомогою двох кнопок. Головною властивістю є Associate. Вона служить для вибору компонента, до якого буде «причіплений» даний компонент та його властивості.

Button - це звичайна кнопка, при натисненні на яку відбувається та чи інша дія. Тобто, можна сказати, що цей компонент слугує для здійснення команд в програмі.

LabeledEdit - компонент, що поєднує в собі компоненти Label та Edit. Містить текстове поле Edit та мітку Label.

Отже, ми розглянули всі компоненти, які я використовувала для реалізації даної програми. І як можна помітити, вони є прості та надійні у використанні.

2.2 ОСНОВНІ ХАРАКТЕРИСТИКИ ОБ'ЄКТНО - ОРІЄНТОВАНОГО ПРОГРАМУВАННЯ

Об'єктно - орієнтоване програмування (ООП) - одна з парадигм програмування, яка розглядає програму як множину «об'єктів», що взаємодіють між собою. В ній використано декілька технологій від попередніх парадигм, зокрема успадкування, модульність, поліморфізм та інкапсуляцію. Незважаючи на те, що ця парадигма з'явилась ще в 1960-тих роках, вона не мала широкого застосування до 1990-тих. Сьогодні багато мов програмування (зокрема, Java, C#, C++, Objective-C, ActionScript 3) підтримують ООП. Об'єктно - орієнтований хід до розроблення програмних продуктів побудований на такому понятті як класи [2].

Клас визначає новий тип даних, який задає формат об'єкта. Клас містить як дані, так і коди програм, призначені для виконання дій над ними. Загалом, клас пов'язує дані з кодами програми, представляє собою набір об'єктів, що мають спільні характеристики. Клас також визначає інтерфейс із навколишнім світом, за допомогою якого здійснюється взаємодія з окремими об'єктами. Важливо розуміти, що клас - це логічна абстракція, яка реально не існує доти, доки не буде створено об'єкт цього класу, тобто це те, що стане фізичним представленням цього класу в пам'яті комп'ютера. Тому об'єкти - це примірники класового типу. Кожен об'єкт в цій моделі є незалежним, і він здатний отримувати, обробляти дані та відправляти ці дані іншим об'єктам. В ООП використано моделі успадкування, модульності, поліморфізму та інкапсуляції. Основним поняттям ООП є об'єкт. Об'єкт можна визначити як певну сукупність даних (характеристик об'єкта) та методів роботи з ними [2]. Кожен об'єкт має процедури і функції, які служать для роботи з даними об'єкта. Ці процедури і функції називаються методами. Визначаючи клас, оголошують ті глобальні дані, які міститимуть об'єкти, і програмні коди, які виконуватимуться над цими даними. Хоча інколи прості класи можуть містити тільки програмні коди або тільки дані, проте більшість

реальних класів містять обидва компоненти. У класі дані оголошуються у вигляді змінних, а програмні коди оформляють у вигляді функцій. Змінні та функції називаються членами класу. Змінну, оголошену в класі, називають членом даних, а оголошену в класі функцію - функцією-членом класу. Іноді замість терміна член даних класу використовують термін змінна класу, а замість терміна функція-член класу використовують термін метод класу. Тому загальний формат оголошення класу має такий вигляд [3]:

class ім'я_класу

{

private:

закриті дані та функції класу

public:

відкриті дані та функції класу

}

перелік_об'єктів_класy;

У цих оголошеннях елемент ім'я класу означає ім'я «класового» типу. Воно стає іменем нового типу, яке можна використовувати для побудови об'єктів цього класу. Визначивши клас, можна створити об'єкт цього «класового» типу, якщо використати ім'я класу. Отож, ім'я класу стає специфікатором нового типу. Наприклад, у процесі виконання наведеної нижче настанови створюється два об'єкти :

ObjA і ObjB типу myClass:

myClass ObjA, ObjB;

Після створення об'єктів класу кожен з них набуває власні копії членів-даних, які утворює клас. Це означає, що кожний з об'єктів ObjA і ObjB

матиме власні копії змінної a. Отже, дані, пов'язані з об'єктом ObjA, відокремлені (ізольовані) від даних, які пов'язані з об'єктом ObjB. Щоб

отримати доступ до відкритого члена класу через об'єкт цього класу, використовують оператор "крапка" (саме так це робиться і під час роботи із структурами). Наприклад, щоб вивести на екран значення змінної a, яка належить об'єкту ObjA, використовують таку настанову:

cout << " ObjA.a= " << ObjA.a;

У оголошенні класу myClass містяться прототипи функцій-членів класу. Щоб реалізувати код функції, яка є членом класу, необхідно повідомити компілятор, до якого класу вона належить, кваліфікувавши ім'я цієї функції з іменем відповідного класу. Наприклад, ось як можна записати код функції

Get():

void myClass::Get(double x, double y)

{

double a1 = pow(x,1.3);

double a2 = pow(fabs(3.2*x - y),0.4);

double a3 = pow(pow(cos(a2),2),1./3);

a = a1+a3;

}

За своєю сутністю такий запис повідомляє компілятор про те, що дана версія функції Get() належить класу myClass [3]. Іншими словами, оператор дозволу "::" заявляє компілятору, що функція Get() знаходиться у області видимості класу myClass.

Існування ООП можливе завдяки трьом основним парадигмам на яких базується саме ООП:

Інкапсуляція - це механізм в програмуванні, який пов'язує в одне ціле функції і дані, якими вони маніпулюють, а також захищає їх від зовнішнього доступу і неправильного застосування. В об'єктно-орієнтованій мові функції

і всі необхідні дані можуть пов'язуватись таким способом, що створюється автономна структура - об'єкт. Іншими словами, об'єктом є структура, яка підтримує інкапсуляцію. В межах об'єкта функції, дані або і функції і дані можуть бути або закритими для інших об'єктів -private, або відкритими -public.

Успадкування - це властивість, з допомогою якої один об'єкт може набувати властивостей іншого. При цьому підтримується концепція ієрархічної класифікації. Без використання успадкування кожний об'єкт повинен явно визначати всі свої характеристики; використовуючи наслідування, об'єкт повинен визначати тільки ті якості, які роблять його унікальним в межах свого класу. Визначення нового класу може базуватись на визначенні вже існуючого. В такому випадку, новий клас отримає властивості та поведінку базового класу, та доповнить їх своїми власними. У випадку одиничного успадкування, у кожного класу може бути лише один безпосередній базовий клас. У випадку множинного успадкування, дозволяється існування декількох безпосередніх надкласів. Застосування методів успадкування дозволяє покращити повторне використання коду шляхом використання властивостей та методів базових класів.

Разом з інкапсуляцією і успадкуванням поліморфізм також являє собою одну із важливих концепцій ООП. Застосування цієї концепції дозволяє значно полегшити розробку складних програм.[5]

Термін поліморфізм має грецьке походження і означає “наявність багатьох форм”. З поліморфізмом тісно пов'язані такі поняття,як абстрактні класи, віртуальні методи, перевантаження методів і властивостей.

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

Клас, який містить хоча б один такий метод називається абстрактним. Об'єкт такого класу створювати не можна. Нащадки абстрактного класу повинні обов'язково представити реалізацію для всіх його абстрактних методів, інакше, вони в свою чергу будуть абстрактними. Можливість присвоювати різну функціональність одному методу називається перевантаженням методу.[3]

Конструктор та деструктор

При створенні об'єктів однією з найбільш широко використовуваних операцій є ініціалізація елементів даних об'єкту.

Проте, щоб спростити процес ініціалізації елементів даних класу, в C++ є можливість використовувати так званий конструктор, який автоматично запускається для кожного створюваного об'єкту, ініціалізуючи його.

· Конструктор є методом класу, який полегшує вашим програмам ініціалізацію елементів даних класу.

· Конструктор має таке ж ім'я, як і клас.

· Конструктор не має значення, що повертається.

· Кожного разу, коли ваша програма створює змінну класу, C++ викликає конструктор класу, якщо конструктор існує.

Конструктор можна уявити як функцію, яка допомагає будувати (конструювати) об'єкт. Деструктор автоматично запускається кожного разу, коли програма знищує об'єкт. Щоб створити такі динамічні списки, ваша програма для зберігання об'єктів розподіляє пам'ять динамічно. Ви можете створювати і знищувати об'єкти в процесі виконання програми. В таких випадках має сенс застосування деструктора.[4]

При завершенні програм C++ знищував об'єкти. Якщо ви визначаєте деструктор усередині своєї програми, C++ буде автоматично викликати деструктор для кожного об'єкту, коли програма завершується (тобто коли об'єкти знищуються). Подібно конструктору, деструктор має таке ж ім'я, як і клас об'єкту. Проте у разі деструктора перед його ім'ям ставиться символ тильди (~), як показано: ~person(void).

Параметризовані конструктори.

Конструктор може мати параметри, за допомогою яких при створенні об'єкта членам-даних (змінним класу) можна надати деякі початкові значення, які визначаються у основній функції main(). Це реалізується шляхом передачі аргументів конструктору об'єкта. У наведеному нижче коді програми спробуємо удосконалити клас myClass так, щоб він приймав аргументи, які слугуватимуть ідентифікаційними номерами (n) черги. Передусім необхідно внести зміни у визначення класу myClass:

class myClass { // Оголошення класового типу

double a;

int nom; // Містить ідентифікаційний номер об'єкта

public:

myClass(int n); // Оголошення параметризованого конструктора

myClass(); // Оголошення деструктора

void Get(double, double); // Введення в об'єкт значення

double Put(); // Виведення з об'єкта значення

};

Член-даних nom використовують для зберігання ідентифікаційного номера об'єкта, який створюється основною функцією. Його реальне значення визначається значенням, яке передається конструктору як формальний параметр n при створенні змінної типу myClass. Параметризований конструктор myClass() буде мати такий вигляд:

// Визначення параметризованого конструктора

myClass::myClass(int n)

{

a = 0; nom = n;

cout << "Об'єкт " << nom << " ініціалізовано" << endl;

}

Загальний формат передачі аргументів конструктору: тип_класу ім'я_об'єкта(перелік_аргументів);

Конструктор копії

Конструктор копії є спеціальним типом перевизначеного конструктора.

Основна причина використання конструктора копії полягає у тому, що при передачі об'єкта функції створюється побітова (тобто точна) його копія, яка передається параметру цієї функції.

Найпоширеніший формат конструктора копії об'єкта має такий вигляд:

ім'я_класу (const ім'я_класу &obj)

{

//Тіло конструктора копії

}

2.3 ВЕКТОРИ

Вектор - один з найпоширеніших контейнерів загального призначення, динамічний масив, проте для доступу до його елементів можна використовувати стандартне позначення індексації елементів масивів.

Шаблонна специфікація для класу vector:

template <class myType, class Allocator = allocator<myType>> class vector

У цьому записі myType - тип даних, який зберігається, а елемент Allocator означає розподільник пам'яті, який за замовчуванням використовує стандартний розподільник.

Приклади:

vector<int> iv; // Створення вектора нульової довжини для зберігання int-значень.

vector<char> cv(5); // Створення 5-елементного вектора для зберігання char-значень.

vector<char> cv(5, 'x'); // Ініціалізація 5-елементного char-вектора.

vector<int> iv2(iv); // Створення int-вектора на основі int-вектора iv.

Методи класу vector:

size() - повертає кількість елементів в векторі;

begin()- повертає ітератор на перший елемент вектора;

end()- повертає ітератор на останній елемент вектора;

insert( ) - вставляє елемент в вектор;

erase( ) - видаляє вказані елементи вектора (один або декілька);

push_back( ) - вставляє елемент в кінець вектора;

pop_back( ) - видаляє останній елемент вектора.

2.4 ОПЕРАЦІЇ ВВЕДЕННЯ ТА ВИВЕДЕННЯ З ПОТОКУ

C++ підтримує всі функції введення-виведення і визначає свою власну об'єктно-орієнтовану систему введення-виведення. Щоб забезпечити доступ програмі до бібліотеки потоків, необхідно підключити заголовний файл <iostream>, у якому визначені складні набори ієрархії класів, що підтримують операції введення-виведення. Клас ios забезпечує підтримку форматованого введення-виведення, контроль помилок і інформацію про стан потоку введення-виведення. Від нього породжені класи istream, ostream, iostream, які використовуються відповідно для створення потоків введення, виведення і введення-виведення.

Операція лівого зсуву використовується в С++ як операція помістити в потік, а операція правого зсуву використовується як операція взяти з потоку. Кожна з цих операцій перевантажена в бібліотеці класів С++. Таке перевантаження дозволяє використати одноманітний синтаксис для введення і виведення, символів рядків, цілого і дійсних чисел. У загальному випадку для виведення на екран монітора використовується така форма операції <<: «cout << вираз» або «file1<< вираз».

Для роботи з файлами потрібно підключити бібліотеку <fstream>, вона включає набір класів, методів і функцій, які надають інтерфейс для читання та запису даних файлу або в файл. [1]

#include <iostream>

#include <fstream>

using namespace std;

int main(){

string a;

ofstream file1("FileOut.txt);//відкриття файлу для запису

file1<<”запис”//запис інформації

file1.close();//закриття файлу

ifstream file2("FileOut");//відкриття файлу для зчитування інформації

file2>>a;// зчитування інформації

file2.close();//закриття файлу}

РОЗДІЛ 3. ПРОГРАМНА РЕАЛІЗАЦІЯ МОДЕЛІ ОПТИЧНИХ ЕКСПЕРИМЕНТІВ В ДЗЕРКАЛЬНІЙ КІМНАТІ

3.1 ДЕКОМПОЗИЦІЯ ВИХІДНОЇ ЗАДАЧІ НА ФУНКЦІОНАЛЬНІ МОДУЛІ

Для реалізації даного програмного продукту я створив абстрактний клас під назвою Mirror, що відповідає за дзеркало. Він містить параметризований конструктор, дві точки між якими буде малюватись дзеркало та віртуальний метод Draw, який малює дзеркало на об'єкті класу TCanvas. В цього класу є два похідні класи FlatMirror,описує плоске дзеркало та абстрактний клас RMirror, що описує сферичне дзеркало. Він містить змінні, що відповідають за радіус кривизни дзеркала і точку центра кола. Клас RMirror має два похідні класи ConvexMirror - описує опукле дзеркало та ConcaveMirror - описує увігнуте дзеркало.

Клас Polygon описує многокутник з дзеркал різних типів. Він містить вектор вказівників на об'єкти-нащадки класу Mirror та змінну size, яка відповідає за кількість сторін многокутника. Описана функція isNormal, яка перевіряє чи перетинаються сторони многокутника. Перевантаженні оператори введення-виведення. Клас Experiment відповідає за проведення експерименту. Він складається з прямої, яка відповідає за початковий напрям променя, многокутник дзеркал, змінні, які відповідають за кількість сторін та кількість відбивань, та вектор, що містить точки відбивань. Описаний метод Do, що приймає кількість відбивань та дві точки, які відповідають за початкове положення, з якого буде випускатись промінь, та кінцеве положення, що відповідає за напрям променя. Метод Draw відповідає за побудову многокутника та відбивання променя від сторін многокутника.

програмування промінь дзеркало оптичний

3.2 ПРОГРАМА ЗАДАЧІ ТА ЇЇ ОПИС

У класі Experiment описаний метод Do який розраховує точки відбивання, код якого наведений нижче.

void Do(TPoint s1, TPoint s2, int _reflections)

{

reflections = _reflections;

start = Line(s1,s2);

ps.clear();

ps.push_back(s1);

int q = reflections;

Line last = start;

int j=-1;

bool found = false,logic;

TPoint p,newP;

int i;

for(i=0;i<count && !found;i++)

{

logic=false;

if(i==j) continue;

p = cross(sides[i],&last);

found = pointOnSegment(sides[i],p) && (Direction(s1,s2)==Direction(s1,p));

if(found && typeid(*sides[i])!=typeid(FlatMirror))

{RMirror* apriori = (RMirror*)sides[i];

p = ArcPoint(last,apriori,p);

logic=true;}}

if(logic == false)

newP = TVector::Reflect(ps[ps.size()-1],p,*sides[i-1]);

else

{

RMirror* apriori = (RMirror*)sides[i-1];

TVector nn = TVector::normal(apriori->center,p);

newP = TVector::Reflect(ps[ps.size() - 1], p,FlatMirror(Point(p.x+nn.x,p.y+nn.y),Point(p.x-nn.x,p.y-nn.y)));

}

ps.push_back(p);

last = Line(p,newP);

j=i-1;

while(q>0){

found = false;

for(i=0;i<count && !found;i++)

{

logic = false;

if(i==j) continue;

p = cross(sides[i],&last);

found = pointOnSegment(sides[i],p);

if(found && typeid(*sides[i])!=typeid(FlatMirror))

{

RMirror* apriori = (RMirror*)sides[i];

p = ArcPoint(last,apriori,p);

logic=true;

}

}

if(logic == 0)

newP = TVector::Reflect(ps[ps.size()-1],p,*sides[i-1]);

else

{

RMirror* apriori = (RMirror*)sides[i-1];

TVector nn = TVector::normal(apriori->center,p);

newP = TVector::Reflect(ps[ps.size()-1], p,FlatMirror(Point(p.x+nn.x,p.y+nn.y),Point(p.x-nn.x,p.y-nn.y)));

}

ps.push_back(p);

last = Line(p,newP);

j=i-1;

q--;

}

}

Також в класі Experiment описаний метод draw, код якого наведений нижче.

void draw(TForm1* Form)

{

Form->PaintBox1->Canvas->Pen->Width=1;

Form->PaintBox1->Canvas->Pen->Color=clBlack;

Form->PaintBox1->Canvas->Brush->Color=clWhite;

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

{

sides[i]->draw(Form->PaintBox1->Canvas);

}

if(reflections==0) return;

Form->PaintBox1->Canvas->Pen->Width=2;

Form->PaintBox1->Canvas->Pen->Color=clYellow;

Form->PaintBox1->Canvas->Brush->Color=clYellow;

Form->Lock();

for(int i = 0;i<reflections+1;i++)

{

AnimateLine(ps[i],ps[i+1],Form->PaintBox1->Canvas);

Application->ProcessMessages();}

Form->Unlock();}

Даний програмний продукт створений для моделювання моделювання оптичних експериментів в дзеркальній кімнаті. Дана програма реалізована на мові C++, в компіляторі Borland C++ Builder 6.

Інтерфейс програми складається з двох вікон. Перше вікно відповідає за параметри дзеркал (Рис. 7.1.1), друге за візуалізацію експермента (Рис. 7.1.2).

Рис. 3.2.1 Параметри дзеркал

Рис. 3.2.2 Проведення експермента

Меню програми включає в себе наступні пункти:

· Файл

· Експермент

Файл

Даний пункт дозволяє користувачу відкрити раніше збережений файл чи зберегти експеримент в новий файл.

Експермент

Даний пункт меню складається з декількох підпунктів, які допоможуть користувачу в:

· побудові нового многокутника(кімнати), за це відповідає пункт - Побудувати заново многокутник;

· проведенні нового експерименту, пункт - Повторити експеримент;

· змінах розмірів сторін, пункт - Змінити розміри сторін;

· завершенні змін розмірів сторін - Завершити зміни ;

· змінах параметрів сторін (кількість дзеркал, тип дзеркала, радіус кривизни) - Змінити параметри дзеркал.

На вікні Відбивання променів від дзеркал також знаходиться текстове поле, в якому користувач вказує кількість відбивань. Справа в інформаційному полі можете спостерігати за ходом експерименту де вказана початкова точка та точки відбивань.

3.3 ІНСТРУКЦІЯ КОРИСТУВАЧА ДЛЯ РОБОТИ З ПРОГРАМОЮ

Після запуску програми користувач побачить перед собою два вікна, одне буде активним, а інше неактивним до того часу, поки користувач не вибере кількість дзеркал( від 4 до 9) та тип для кожного дзеркала(для сферичних дзеркал ще радіус кривизни). Потім після натиснення клавіші «Ok» справа внизу форми, вікно з параметрами дзеркал закриється, виведеться інформація в вікні з інформацією «Побудуйте n-кутник» і вікно з проведенням експерименту стане активним. Після цього наведенням на форму та натисненням лівої клавіші миші обирайте точки, між якими будуватимуться сторони многокутника. Многокутник повинен бути правильним, їхні сторони не повинні перетинатись. Після побудови многокутника справа вкажіть кількість відбивань променя, оберіть початкове положення точки в многокутнику(дзеркальній кімнаті), з якої буде проектуватись світловий промінь та напрям променя, до якої з сторін, під яким кутом він будуватиметься. Після цього спостерігайте за відбиванням світлового променя від сторін многокутника. Для повторення експерименту оберіть пункт головного меню «Експермент», підпункт «Повторення експерименту». Для змін розмірів дзеркал виберіть підпункт «Змінити розміри сторін», після змін оберіть пункт «Завершити зміни». Для зміни початкового положення сторін многокутника(дзеркал) оберіть підпункт «Побудувати заново многокутник». Для збереження експерименту у файл натисніть пункт головного меню «Файл» та оберіть підпункт «Зберегти файл». Для відкриття файлу оберіть підпункт «Відкрити файл».

ДОДАТОК

Unit1.cpp

#include <vcl.h>

#include <fstream>

#include <iostream>

#pragma hdrstop

#include "Unit1.h"

#include "Unit2.h"

#include "Experiment.h"

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

#pragma package(smart_init)

#pragma resource "*.dfm"

TForm1 *Form1;

int state;

TPoint *points,p,s;

int sideCount = 0;

Experiment *ex;

polygon *pol;

TShape** shapes;

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

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)

{count = 0; state = -1;}

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

void __fastcall TForm1::Button1Click(TObject *Sender)

{ state = 0; ShowMessage("Побудуйте "+IntToStr(count)+"-кутник");}

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

void TForm1::DrawPoint(TPoint p,int r)

{ PaintBox1->Canvas->Ellipse(p.x-r,p.y-r,p.x+r,p.y+r); }

void __fastcall TForm1::Button2Click(TObject *Sender)

{state = 0; sideCount = 0; Canvas->Pen->Width=1; Canvas->Pen->Color=clBlack;

PaintBox1->Repaint(); ShowMessage("Побудуйте правильний"+IntToStr(count) +"-кутник"); }

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

void __fastcall TForm1::Button3Click(TObject *Sender)

{state = 2; Canvas->Pen->Width=1; Canvas->Pen->Color=clBlack;

PaintBox1->Repaint();

ShowMessage("Вкажіть початковий напрям променя та кількість відбивань");}

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

void TForm1::Lock()

{LabeledEdit2->Enabled=false;}

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

void TForm1::Unlock()

{LabeledEdit2->Enabled=1;}

void __fastcall TForm1::N6Click(TObject *Sender)

{state = 0; sideCount = 0; PaintBox1->Canvas->Pen->Width=1;

PaintBox1->Canvas->Pen->Color=clBlack; PaintBox1->Repaint();

ShowMessage("Побудуйте правильний "+IntToStr(count)+"-кутник");}

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

void __fastcall TForm1::N7Click(TObject *Sender)

{if(state<2)

{ ShowMessage("Спочатку побудуйте многокутник "); return;}

state = 2; ex->Reset(); PaintBox1->Repaint();

ShowMessage("Вкажіть початковий напрям променя та кількість відбивань"); }

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

void __fastcall TForm1::PaintBox1MouseDown(TObject *Sender,

TMouseButton Button, TShiftState Shift, int X, int Y)

{ switch(state)

{case 0:

points[sideCount]=p; sideCount++; state = 1; PaintBox1->Repaint();

break;

case 1:

if(sideCount>=count-1)

{state = 2; points[sideCount]=p; sideCount++;

pol = new polygon(points,count,Form2->mirrors,Form2->radiuses);

if(!pol->isNormal())

{ShowMessage("Многокутник повинен бути правильний");

N6->Click();break; }

ex = new Experiment(*pol);

PaintBox1->Repaint();

ShowMessage("Вкажіть початковий напрям променя та кількість відбивань ");break; }

points[sideCount]=p;

sideCount++;

PaintBox1->Repaint();

break;

case 2:

s=p; state=3; PaintBox1->Repaint();break;

case 3:

ex->Do(s,p,UpDown2->Position); state = 4; PaintBox1->Repaint();

break;

}

}

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

void __fastcall TForm1::PaintBox1MouseMove(TObject *Sender,

TShiftState Shift, int X, int Y)

{ p.x=X; p.y=Y; if(state==1 || state==3) Repaint();

}

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

void __fastcall TForm1::PaintBox1Paint(TObject *Sender)

{

switch(state)

{

case 1:

PaintBox1->Canvas->Brush->Color=clBlack;

DrawPoint(points[0],2);

for(int i=1;i<sideCount;i++)

{

PaintBox1->Canvas->MoveTo(points[i-1].x,points[i-1].y);

PaintBox1->Canvas->LineTo(points[i].x,points[i].y);

DrawPoint(points[i],2);

}

PaintBox1->Canvas->MoveTo(points[sideCount-1].x, points[sideCount-1].y);

PaintBox1->Canvas->LineTo(p.x,p.y);

break;

case 2:

ex->draw(this);

break;

case 3:

ex->draw(this); DrawPoint(s,2);

PaintBox1->Canvas->Brush->Color=clWhite;

PaintBox1->Canvas->MoveTo(s.x,s.y);

PaintBox1->Canvas->LineTo(p.x,p.y); break;

case 4:

ex->draw(this); break;

case 5:

PaintBox1->Canvas->Brush->Color=clBlack;

PaintBox1->Canvas->Pen->Color=clBlack;

PaintBox1->Canvas->Pen->Width=1;

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

{DrawPoint(points[i],2);}

PaintBox1->Canvas->Brush->Color=clWhite;

PaintBox1->Canvas->Polygon(points,sideCount-1); break; }

}

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

void __fastcall TForm1::P1Click(TObject *Sender)

{state = 5;

PaintBox1->Repaint();

shapes = new TShape*[count];

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

{shapes[i]=new TShape(Form1);

shapes[i]->Parent=Form1;

shapes[i]->Shape=stCircle;

shapes[i]->Brush->Color=clBlack;

shapes[i]->Height=10;

shapes[i]->Width=10;

shapes[i]->Top=points[i].y;

shapes[i]->Left=points[i].x;

shapes[i]->Tag=i;

shapes[i]->OnMouseMove=Shape1MouseMove;

shapes[i]->OnMouseDown=Shape1MouseDown;

shapes[i]->OnMouseUp=Shape1MouseUp; }

}

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

TPoint shapePoint,sh;

void __fastcall TForm1::Shape1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y)

{if(!Shift.Contains(ssLeft)) return;

TShape* Shape = (TShape*)Sender;

int dx = X-shapePoint.x;

int dy = Y-shapePoint.y;

Shape->Top+=dy; Shape->Left+=dx;

points[Shape->Tag]=Point(Shape->Left,Shape->Top);

PaintBox1->Repaint();}

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

void __fastcall TForm1::Shape1MouseDown(TObject *Sender,

TMouseButton Button, TShiftState Shift, int X, int Y)

{

shapePoint = Point(X,Y); TShape* Shape = (TShape*)Sender;

sh = Point(Shape->Left,Shape->Top);

}

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

void __fastcall TForm1::Shape1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)

{TShape* Shape = (TShape*)Sender; if(pol) delete pol;

pol = new polygon(points,count,Form2->mirrors,Form2->radiuses);

if(!pol->isNormal())

{ShowMessage("Многокутник повинен бути правильним");

points[Shape->Tag]=sh;

Repaint();Shape->Top=sh.y; Shape->Left=sh.x; delete pol;

pol = new polygon(points,count,Form2->mirrors,Form2->radiuses); }

}

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

void __fastcall TForm1::N8Click(TObject *Sender)

{for(int i=0;i<count;i++)

{delete shapes[i];}

delete [] shapes;

ex = new Experiment(*pol); state=2; PaintBox1->Repaint();

ShowMessage("Вкажіть початковий напрям променя та кількість відбивань ");

}

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

void __fastcall TForm1::N2Click(TObject *Sender)

{if(SaveDialog1->Execute())

{if(!ifstream(SaveDialog1->FileName.c_str()))

{ShowMessage("Не вдалось відкрити файл");return; }

ex->SaveToFile(SaveDialog1->FileName.c_str());}

}

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

void __fastcall TForm1::N3Click(TObject *Sender)

{

if(OpenDialog1->Execute())

{if(ex) delete ex;

ex = Experiment::LoadFromFile(OpenDialog1->FileName.c_str());

state = 4;

ex->draw(Form1); }

}

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

void __fastcall TForm1::N4Click(TObject *Sender)

{

Form2->ShowModal();

}

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

void TForm1::Init()

{

if(count!=Form2->UpDown10->Position || state<2)

{

state = 0;

count = Form2->UpDown10->Position;

PaintBox1->Canvas->Pen->Color=clBlack;

PaintBox1->Canvas->Pen->Width=1;

PaintBox1->Repaint();

if(points) delete [] points;

points = new TPoint[count];

ShowMessage("Побудуйте "+IntToStr(count)+"-кутник");

}

else

{

if(pol) delete pol;

pol = new polygon(points,count,Form2->mirrors,Form2->radiuses);

ex = new Experiment(*pol);

state = 2;

PaintBox1->Repaint();

ShowMessage("Вкажіть початковий напрям променя та кількість відбивань ");}

}

void __fastcall TForm1::FormShow(TObject *Sender)

{

Form2->ShowModal();

}

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

void __fastcall TForm1::FormActivate(TObject *Sender)

{

Form2->ShowModal();

}

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

Experiment.h

#include <math.h>

#include <vector>

#include <typeinfo>

using namespace std;

class Line;

class Mirror;

class Experiment;

TPoint Orient(TPoint*,int,int);

TPoint Middle(const TPoint& p1,const TPoint& p2);

class FlatMirror;

bool SegmentsCross(Mirror* ,Mirror*);

double len(const TPoint& p1,const TPoint& p2);

double angle(Line l1, Line l2);

int Direction(const TPoint & s1,const TPoint &s2);

//структура, що відповідає за математичний вектор

struct TVector

{

double x,y;

TVector(TPoint p1,TPoint p2)

{

x = p2.x-p1.x;

y = p2.y-p1.y;

}

TVector(){x=y=0;}

TVector(double _x, double _y) : x(_x), y(_y) {}

TVector(POINT& pt) {x = pt.x; y=pt.y;}

double length()

{

return sqrt(x*x+y*y);

}

//метод, що повертає вектор нормалі

static TVector normal(TPoint p1, TPoint p2) {

TVector v;

v.x = p1.y-p2.y;

v.y = p2.x-p1.x;

return v;

}

//перевизначення оператора +

TVector operator+ (TVector obj)

{

obj.x+=x;

obj.y+=y;

return obj;

}

//перевизначення оператора -

TVector operator- (const TVector &obj)

{

TVector v = *this;

v.x-=obj.x;

v.y-=obj.y;

return v;

}

//перевизначення оператора *

TVector operator* (double a)

{

TVector obj = *this;

obj.x*=a;

obj.y*=a;

return obj;

}

//дружня функція для перевизначення множення числа на вектор

friend TVector operator* (double a,TVector v);

double operator* (TVector obj)

{

double a;

a = x*obj.x+y*obj.y;

return a;

}

//метод, що відповідає за нормування вектора

void norm(){

double l = length();

x/=l;

y/=l;

}

//метод, що відповідає за відбивання

static TPoint Reflect(TPoint a, TPoint c, const Mirror& line);

};

//клас, що описує пряму у вигляді рівняння прямої

class Line

{

public:

double A,B,C;

Line(){A=B=C=1;}

Line(TPoint p1, TPoint p2)

{

A = p2.y-p1.y;

B = p1.x-p2.x;

C = p2.x*p1.y - p2.y*p1.x;

}

Line(Line line, TPoint point, double angle)

{

A = (line.A/line.B-tan(angle))/(line.A/line.B*tan(angle)+1);

B = -1;

C = point.y+(point.x*(-tan(angle)+line.A/line.B))/(1+line.A/ line.B*tan(angle));

}

//віртуальні методи, що повертають х та у

virtual double fX(double x) const

{

double y = ((-C)-A*x)/B;

return y;

}

virtual double fY(double y) const

{

double x = ((-C)-B*y)/A;

return x;

}

};

//абстрактний клас, що описує дзеркало

class Mirror: public Line

{

public:

TPoint p1,p2;

Mirror() {}

Mirror(TPoint _p1, TPoint _p2): Line(_p1,_p2)

{

p1 = _p1;

p2 = _p2;

}

//віртуальний метод, який перевизначається в похідних класах

virtual void draw(TCanvas* Canvas)=0;

};

//клас, що описує плоске дзеркало

class FlatMirror: public Mirror

{

public:

FlatMirror() {}

FlatMirror(TPoint _p1, TPoint _p2): Mirror(_p1,_p2) {}

//метод, що малює дзеркало

void draw(TCanvas* Canvas)

{Canvas->MoveTo(p1.x,p1.y);

Canvas->LineTo(p2.x,p2.y); }

};

//абстрактний клас, що описує сферичне дзеркало

class RMirror: public Mirror

{public:

TPoint center;

int radius;

RMirror() {}

RMirror(TPoint _p1, TPoint _p2): Mirror(_p1,_p2) {}

};

//клас, що описує опукле дзеркало

class ConvexMirror: public RMirror

{public:

ConvexMirror() {}

ConvexMirror(TPoint _p1, TPoint _p2,int r,TPoint o): RMirror(_p1,_p2)

{

radius = r;

TPoint m = Middle(_p1,_p2);

TVector n = TVector::normal(_p1,_p2);

n.norm();

double ll = sqrt(pow(radius,2) - pow(len(_p1,m),2));

n = n*ll;

TPoint r1(m.x+n.x,m.y+n.y);

TPoint r2(m.x-n.x,m.y-n.y);

if(len(r1,o)>len(r2,o))

{

center = r1;

TPoint t = p1;

p1 = p2;

p2 = t;

}

else

center = r2;

}

void draw(TCanvas* Canvas)

{

Canvas->Arc(center.x-radius, center.y-radius, center.x+radius, center.y+radius, p1.x,p1.y ,p2.x,p2.y );

}

};

//клас, що описує увігнуте дзеркало

class ConcaveMirror: public RMirror

{public:

ConcaveMirror() {}

ConcaveMirror(TPoint _p1, TPoint _p2,int r,TPoint o): RMirror(_p1,_p2)

{

radius = r;

TPoint m = Middle(_p1,_p2);

AnsiString ss = "p1: "+AnsiString(p1.x)+" "+AnsiString(p1.y)+"; p2: "+AnsiString(p2.x)+" "+AnsiString(p2.y)+"; m: "+AnsiString(m.x)+" "+AnsiString(m.y);

TVector n = TVector::normal(_p1,_p2);

n.norm();

double ll = sqrt(pow(radius,2) - pow(len(_p1,m),2));

n = n*ll;

TPoint r1(m.x+n.x,m.y+n.y);

TPoint r2(m.x-n.x,m.y-n.y);

if(len(r1,o)<len(r2,o))

{

center = r1;

TPoint t = p1;

p1 = p2;

p2 = t;

}

else

center = r2;

}

void draw(TCanvas* Canvas)

{

Canvas->Arc(center.x-radius, center.y-radius, center.x+radius, center.y+radius, p1.x,p1.y ,p2.x,p2.y );

}

};

//клас, що описує многокутник дзеркал різних типів

class polygon

{

vector<Mirror *> v; //вектор, що містить вказівники на дзеркала

public:

int size;

polygon(int s = 4): v(s), size(s) {}

polygon(TPoint* points, int count, int* mirrors,int* radiuses) : size(count)

{

for(int i=1;i<count;i++)

{

if(mirrors[i-1]==0)

v.push_back(new FlatMirror(points[i-1],points[i]));

else if(mirrors[i-1]==1)

{

v.push_back(new ConcaveMirror(points[i-1],points[i],radiuses[i-1],Orient(points,count,i-1)));

}

else

{

v.push_back(new ConvexMirror(points[i-1],points[i],radiuses[i-1],Orient(points,count,i-1)));

}

}

if(mirrors[count-1]==0)

v.push_back(new FlatMirror(points[count-1],points[0]));

else if(mirrors[count-1]==1)

v.push_back(new ConcaveMirror(points[count-1],points[0],radiuses[count-1],Orient(points,count,count-1)));

else

v.push_back(new ConvexMirror(points[count-1],points[0], radiuses[count-1],Orient(points,count,count-1)));

}

//перевизнчення оператора індексації

Mirror* operator[] (int idx)

{

return v[idx];

}

//перевизначення оператора присвоєння

polygon& operator= (polygon& right)

{

size = right.size;

v = right.v;

return *this;

}

//метод, що перевіряє чи перетинаються сторони многокутника

bool isNormal()

{

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

for(int j=i+2;j<size;j++)

if(i==0 && j==size-1) continue;

else if( SegmentsCross(v[i],v[j]) )

{

return false;

}

return true;

}

friend ostream& operator<<(ostream &stream, polygon& p);

friend istream& operator>>(istream &stream, polygon& p);

};

//перевизначення оператора виведення

ostream& operator<<(ostream& stream, polygon& p)

{

stream<<(p.size)<<endl;

for(int i=0;i<p.size;i++)

{

stream<<(p.v[i]->p1.x)<<" "<<(p.v[i]->p1.y)<<" "

<<(p.v[i]->p2.x)<<" "<<(p.v[i]->p2.y)<<endl;

}

return stream;

}

//перевизначення оператора введення

istream& operator>>(istream& stream, polygon& p)

{

vector<Mirror* > v;

stream>>(p.size);

TPoint p1,p2;

for(int i=0;i<p.size;i++)

{

stream>>p1.x>>p1.y

>>p2.x>>p2.y;

v.push_back(new FlatMirror(p1,p2));

}

p.v=v;

return stream;

}

TVector operator* (double a,TVector v)

{

v.x*=a;

v.y*=a;

return v;

}

//клас, що відповідає за проведення експерменту

class Experiment

{

Line start; // початкова прямма

polygon sides; //сторони многокутника

int count, //кількість сторін

reflections; //кількість відбивань

vector<TPoint> ps; //точки відбивань

public:

Experiment(){}

Experiment(polygon poly)

{

reflections = 0;

count = poly.size;

sides = poly;

}

Experiment(polygon poly, TPoint s1, TPoint s2, int _reflections)

{

count = poly.size;

sides = poly;

Do(s1,s2,_reflections);

}

//метод, що відповідає за розрахунок точок відбивань

void Do(TPoint s1, TPoint s2, int _reflections)

{

reflections = _reflections;

start = Line(s1,s2);

ps.clear();

ps.push_back(s1);

int q = reflections;

Line last = start;

int j=-1;

bool found = false,logic;

TPoint p,newP;

int i;

for(i=0;i<count && !found;i++)

{

logic=false;

if(i==j) continue;

p = cross(sides[i],&last);

found = pointOnSegment(sides[i],p) && (Direction(s1,s2)==Direction(s1,p));

if(found && typeid(*sides[i])!=typeid(FlatMirror))

{

RMirror* apriori = (RMirror*)sides[i];

p = ArcPoint(last,apriori,p);

logic=true;

}

}

if(logic == false)

newP = TVector::Reflect(ps[ps.size()-1],p,*sides[i-1]);

else

{

RMirror* apriori = (RMirror*)sides[i-1];

TVector nn = TVector::normal(apriori->center,p);

newP = TVector::Reflect(ps[ps.size()-1], p,FlatMirror(Point(p.x+nn.x,p.y+nn.y),Point(p.x-nn.x,p.y-nn.y)));

}

ps.push_back(p);

last = Line(p,newP);

j=i-1;

while(q>0){

found = false;

for(i=0;i<count && !found;i++)

{

logic = false;

if(i==j) continue;

p = cross(sides[i],&last);

found = pointOnSegment(sides[i],p);

if(found && typeid(*sides[i])!=typeid(FlatMirror))

{

RMirror* apriori = (RMirror*)sides[i];

p = ArcPoint(last,apriori,p);

logic=true;

}

}

if(logic == 0)

newP = TVector::Reflect(ps[ps.size()-1],p,*sides[i-1]);

else

{

RMirror* apriori = (RMirror*)sides[i-1];

TVector nn = TVector::normal(apriori->center,p);

newP = TVector::Reflect(ps[ps.size()-1], p,FlatMirror(Point(p.x+nn.x,p.y+nn.y),Point(p.x-nn.x,p.y-nn.y)));

}

ps.push_back(p);

last = Line(p,newP);

j=i-1;

q--;

}

}

//метод, що відповідає за оновлення експерменту

void Reset()

{

reflections = 0;

ps.clear();

}

//метод, що повертає точку перетину двох прямих

static TPoint cross(Line* l1,Line* l2)

{

double d,dA,dB,x,y;

d = l1->A*l2->B - l2->A*l1->B;

dA = l2->C*l1->B - l1->C*l2->B;

dB = l2->A*l1->C - l1->A*l2->C;

x = dA/d;

y = dB/d;

return Point(x,y);

}

//метод, що перевіряє чи точка знаходиться на поверхні дзеркала

static bool pointOnSegment(Mirror* s, TPoint p)

{

int minX = s->p1.x > s->p2.x ? s->p2.x : s->p1.x;

int maxX = s->p1.x < s->p2.x ? s->p2.x : s->p1.x;

int minY = s->p1.y > s->p2.y ? s->p2.y : s->p1.y;

int maxY = s->p1.y < s->p2.y ? s->p2.y : s->p1.y;

return (p.x>=minX && p.x<=maxX && p.y>=minY && p.y<=maxY);

}

//метод, що відповідає за малювання експерменту

void draw(TForm1* Form)

{

Form->PaintBox1->Canvas->Pen->Width=1;

Form->PaintBox1->Canvas->Pen->Color=clBlack;

Form->PaintBox1->Canvas->Brush->Color=clWhite;

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

{

sides[i]->draw(Form->PaintBox1->Canvas);

}

if(reflections==0) return;

Form->PaintBox1->Canvas->Pen->Width=2;

Form->PaintBox1->Canvas->Pen->Color=clYellow;

Form->PaintBox1->Canvas->Brush->Color=clYellow;

Form->Lock();

for(int i = 0;i<reflections+1;i++)

{

AnimateLine(ps[i],ps[i+1],Form->PaintBox1->Canvas);

Application->ProcessMessages();

}

Form->Unlock();

}

void AnimateLine(TPoint startPoint, TPoint finalPoint, TCanvas* Canvas)

{

const Line line(startPoint,finalPoint);

TPoint p;

if(abs(startPoint.x-finalPoint.x) > abs(startPoint.y-finalPoint.y))

{

if(startPoint.x<finalPoint.x)

{

for(int i=startPoint.x; i<=finalPoint.x; i++)

{

p = Point(i,line.fX(i));

Canvas->MoveTo(startPoint.x,startPoint.y);

Canvas->LineTo(p.x,p.y);

Sleep(10);

Application->ProcessMessages();

}

}

else if(startPoint.x>finalPoint.x)

{

for(int i=startPoint.x; i>=finalPoint.x; i--)

{

Canvas->MoveTo(startPoint.x,startPoint.y);

Canvas->LineTo(i,line.fX(i));

Sleep(10);

Application->ProcessMessages();

}

}

}

else

{

if(startPoint.y<finalPoint.y)

{

for(int i=startPoint.y; i<=finalPoint.y; i++)

{

p = Point(line.fY(i),i);

Canvas->MoveTo(startPoint.x,startPoint.y);

Canvas->LineTo(p.x,p.y);

Sleep(10);

Application->ProcessMessages();

}

}

else if(startPoint.y>finalPoint.y)

{

for(int i=startPoint.y; i>=finalPoint.y; i--)

{

Canvas->MoveTo(startPoint.x,startPoint.y);

Canvas->LineTo(line.fY(i),i);

Sleep(10);

Application->ProcessMessages();

}

}

}

}

//метод, що повертає точку, в якій відіб'ється промінь від сферичного дзеркала

static TPoint ArcPoint(const Line& l, RMirror* mirror,const TPoint& p)

{

double k = (-l.A)/l.B;

...

Подобные документы

  • Редагування за допомогою текстового редактора NotePad вхідного файлу даних. Програмна реалізація основного алгоритму з використанням засобів об'єктно-орієнтованого програмування. Об’ява та опис класів і об'єктів. Розробка допоміжних програмних засобів.

    курсовая работа [69,4 K], добавлен 14.03.2013

  • Описано вказану систему, побудована її концептуальна модель, зроблено формальний опис системи та імітаційної моделі, виконано програмування моделі системи та наведено результати моделювання.

    курсовая работа [73,1 K], добавлен 16.06.2007

  • Unified modeling language як мова об'єктно-орієнтованого моделювання. Дослідження сучасних сase-засобів моделювання бізнес процесів. Кодогенератор для забезпечення зв'язку між Delphi і Rose. Перелік основних інструментів для створення моделі в ERwin.

    дипломная работа [3,2 M], добавлен 22.10.2012

  • Модель в об’єктно-орієнтованих мовах програмування. Програмна модель створена на мові програмування С++, в середовищі програмування Borland С++ Builder 6.0. Вибір засобів реалізації програми. Види інструментів для об'єктно-орієнтованої розробки.

    курсовая работа [116,9 K], добавлен 06.06.2010

  • Загальні відомості, методи та постановка задачі динамічного програмування. Практичне застосування методу динамічного програмування на прикладі розподілення вантажів між 4-ма торговими суднами. Рекурентна природа обчислень в динамічному програмуванні.

    курсовая работа [1,1 M], добавлен 22.05.2015

  • Особливості редагування за допомогою текстового редактора NotePad вхідного файлу. C++ як універсальна мова програмування, знайомство с функціями. Характеристика графічних засобів мови С. Аналіз основних понять об’єктно-орієнтованого програмування.

    курсовая работа [123,3 K], добавлен 14.03.2013

  • Принципи об'єктно-орієнтованого підходу. Розробка програмного комплексу з використанням цього алгоритму і користувальницьких класів на мові програмування С++. Реалізація простого відкритого успадкування. Тестування працездатності системи класів.

    курсовая работа [98,0 K], добавлен 06.05.2014

  • Огляд суті гри "Доміно", характеристика її існуючих програмних реалізацій. Розробка евристичного алгоритму для розв’язання ігрової ситуації "Доміно". Програмна реалізація алгоритму мовою програмування високого рівня C#. Отладка оціночної функції.

    курсовая работа [1,4 M], добавлен 14.05.2012

  • Технології об'єктно-орієнтованого аналізу та проектування інформаційних систем. Історія та структура мови UML. Опис функціональної моделі засобами UML. Використання UML в проектуванні програмного забезпечення. Характеристика CASE-засобів Visual Paradigm.

    дипломная работа [7,9 M], добавлен 26.05.2012

  • Засоби візуального моделювання об'єктно-орієнтованих інформаційних систем. Принципи прикладного системного аналізу. Принцип ієрархічної побудови моделей складних систем. Основні вимоги до системи. Розробка моделі програмної системи засобами UML.

    курсовая работа [546,6 K], добавлен 28.02.2012

  • Розробка програми для моделювання роботи алгоритму Дейкстри мовою C# з використанням об’єктно-орієнтованих принципів програмування. Алгоритм побудови робочого поля. Програмування графічного інтерфейсу користувача. Тестування програмного забезпечення.

    курсовая работа [991,4 K], добавлен 06.08.2013

  • Класифікація інформаційних систем. Дослідження особливостей мови UML як засобу моделювання інформаційних систем. Розробка концептуальної моделі інформаційної системи поліклініки з використанням середи редактора програмування IBM Rational Rose 2003.

    дипломная работа [930,4 K], добавлен 26.10.2012

  • Сутність та особливості параметричного, воксельного, полігонального моделювання, моделювання сплайнами та скульптингу. Застосування 3D моделювання в науці, техніці, рекламі, маркетингу, дизайні інтер'єру, архітектурі, анімаці, кіно та медицині.

    доклад [873,9 K], добавлен 04.05.2022

  • Концепції об'єктно-орієнтованого програмування. Конструктори та деструктори. Успадкування класів. Побудова об’єктної моделі. Визначення об'єктів та класів і зв’язків між ними. Реалізація програми в середовищі Visual Studio C++. Інтерфейс програми.

    курсовая работа [743,7 K], добавлен 25.01.2016

  • Програмування математичної моделі довільної ланки хіміко-технологічної системи та дослідження її динамічних характеристик. Система Mat Lab – середовище програмування. Побудова програмними засобами кривих перехідних процесів, логарифмічних характеристик.

    курсовая работа [551,3 K], добавлен 12.01.2011

  • Визначення найкращого режиму роботи системи обробки повідомлень. Представлення моделі у вигляді системи масового обслуговування. Визначення структури моделі. Обмеження на зміну величин. Програмна реалізація імітаційної моделі. Оцінка адекватності.

    курсовая работа [153,9 K], добавлен 29.01.2013

  • Концепції об'єктно-орієнтованого програмування. Методи створення класів. Доступ до методів базового класу. Структура даних, функції. Розробка додатку на основі діалогових вікон, програми меню. Засоби розробки програмного забезпечення мовами Java та С++.

    курсовая работа [502,5 K], добавлен 01.04.2016

  • Основні принципи об’єктно-орієнтованого програмування. Типові середовища програмування та особливості мови С++. Етапи проектування БД. Розробка програмного забезпечення для реалізації створення бази відеофільмів. Основні положення та моделі БД.

    курсовая работа [2,7 M], добавлен 24.03.2011

  • Прототип об'єктно-орієнтованого програмування. Управління процесом реалізації програми. Розвиток апаратних засобів. Об'єктно-орієнтовані мови програмування. Надійність і експлуатаційні якості програм. Візуальне об’єктна-орієнтовне проектування Delphi.

    контрольная работа [28,9 K], добавлен 18.05.2009

  • Особливості об'єктно-орієнтованого програмування. Розробка програми для елементарних математичних розрахунків, виведення результату на екран та запису у файлі. Сортування слів у рядку. Програма, яка реалізовує ходи шахових фігур. Програма-калькулятор.

    отчет по практике [2,0 M], добавлен 19.03.2015

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.