Реалізація класу тривимірний вектор
Дата створення: 2009-08-09 18:24:44 Востаннє редаговано: 2012-02-08 09:52:33
Сьогодні ми розглянемо реалізацію класу векторів. У цьому класі є майже все, що нам знадобиться під час роботи з векторами.
Крім того, цей клас згодом увійде до бібліотеки, на основі якої ми створимо ігровий двигун.
Реалізація класу тривимірних векторів.
За допомогою даного класу ми представлятимемо не тільки вектори, а й точки у просторі, оскільки з математичної точки зору ці поняття еквіваленти.
Перед класом визначено константу:
Вона використовується для порівняння двох векторів. Деталі нижче.
Усі змінні (а це компоненти вектора) визначені у сфері public. Я неодноразово писав, що всі дані класу потрібно розташовувати у сфері private. Але це не той випадок.
Кожен вектор складається з трьох компонентів: x, y, z. У цьому прикладі я використовував безіменне об'єднання для отримання доступу до компонентів вектора як поіменно, так і за допомогою індексів масиву. Для того, щоб компоненти вектора не розглядалися як те саме значення, ми їх поміщаємо в безіменну структуру. Може здатися, що ця конструкція складна. Звичайно, це не так. Давайте розглянемо приклад використання векторів:
Докладніші пояснення принципу роботи об'єднань можна знайти у статті "Структури, перерахування та об'єднання".
Для зберігання компонентів векторів використовуються змінні типу float. Чому не double? Тип double потрібно використовувати коли необхідна підвищена точність або при моделюванні величезних просторів, наприклад, в ArmA 2. У наших навчальних прикладах така точність не знадобиться.
Конструктори класу векторів
В класіvector3 використовується три конструктори:
Перший конструктор ініціалізує компоненти вектора нулями. Другий конструктор приймає як аргумент посилання на інший вектор. Завдяки цьому значення створюваного вектора можна ініціалізувати значеннями іншого вектора. І останній конструктор приймає три аргументи.
Привласнення векторів
У цьому коді відбувається присвоєння компонент одного вектора - іншого. Робиться це за допомогою перевантаженої операції =:
Порівняння двох векторів
Це, мабуть, найскладніша функція у класі. Ми не можемо просто порівнювати відповідні компоненти двох векторів, оскільки вони мають тип float, а значить може виникнути помилка через округлення чисел. Ми порівнюватимемо вектора з точністю до трьох знаків після десяткової коми.
Розглянемо два вектори v1 = [3.001, 2.3267, 1.182] та v2 = [3.001, 2.2368, 1.182]. Чи рівні ці вектори. Ми можемо впевнено заявити: ні, не рівні. Але комп'ютер не може дати однозначну відповідь (особливо якщо мова йтиме не про три знаки після коми, а більшу кількість). Щоб комп'ютеру було легше порівнювати вектора ми вводимо константу EPSILON = 0.001. Тепер ми знаходимо модуль (абсолютне значення) різниці відповідних компонентів і порівнюємо значення, що вийшло, з EPSILON. Якщо модуль різниці менший за EPSILON, то вважаємо, що компоненти векторів рівні.
Сума/різниця двох векторів
Розглянемо код методу суми двох векторів:
Для суми використовується перевантажена операція +. Різниця векторів реалізується аналогічно.
Розмноження/розподіл вектора на скаляр
Розглянемо лише поділ вектора на скаляр:
Перший оператор - розподіл одиниці на параметр методу. Справа в тому, що розподіл виконується набагатоповільніше, ніж множення. Тому замість виконання трьох операцій розподілу: x/a,y/a,z/a - ми вводимо додаткову змінну b і виконуємо один розподіл і три операції множення.
Зверніть увагу, що ми не перевіряємо можливість розподілу на нуль.
Операції поділу/множення вектора на скаляр дозволяють зменшити/збільшити довжину вектора.
Перевантажені операції із присвоєнням
У класі перевизначено чотири операції з присвоєнням: сума/різниця векторів та множення/розподіл вектора на скаляр. Ці операції майже повністю повторюють ті, що ми розглянули вище.
Скалярний та векторний твір векторів
Наступні операції використовуватимуться дуже часто (особливо скалярний твір). Код методів дуже простий. Ми розглядали формули цих операцій, коли вивчали вектори.
Для скалярного добутку використовується перевантажена операція *:
Для векторного твору складно підібрати перевантажену операцію, тому ми будемо використовувати ім'я методу cross:
Розмір вектора
Досить простий метод, який знаходить величину (довжину) вектора:
Нормалізація вектора
Відстань між двома точками
Останній метод використовується знаходження відстані між двома точками. Формулу ми вже розглядали.