Навчимося зображати шестигранную призму в різних положеннях.

Вивчіть різні способи побудови правильного шестикутника, зробіть малюнки шестикутників, перевірте правильність їх побудови. На основі шестикутників побудуйте шестигранні призми.

Розгляньте шестигранную призму на рис. 3.52 і її ортогональні проекції на рис. 3.53. У підставі шестигранної призми (шестикутника) лежать правильні шестикутники, бічні грані - однакові прямокутники. Для того, щоб правильно зобразити шестигранник в перспективі, необхідно спочатку навчитися грамотно зображати в перспективі його підставу (рис. 3.54). У шестикутнику на рис. 3.55 вершини позначені цифрами від одного до шести. Якщо з'єднати точки 1 і 3, 4 і 6 вертикальними прямими, можна помітити, що ці прямі разом з точкою центру кола ділять діаметр 5 - 2 на чотири рівних відрізка (ці відрізки позначені дугами). Протилежні сторони шестикутника паралельні один одному і прямої, що проходить через його центр і з'єднує дві вершини (наприклад, сторони 6 - 1 і 4 - 3 паралельні прямій 5 - 2). Ці спостереження допоможуть вам побудувати шестикутник в перспективі, а також перевірити правильність цього побудови. Побудувати правильний шестикутник за поданням можна двома способами: на основі описаного кола і на основі квадрата.

На основі описаного кола. Розгляньте рис. 3.56. Всі вершини правильного шестикутника належать описаного кола, радіус якої дорівнює стороні шестикутника.


Горизонтальний шестикутник. Зобразіть горизонтальний еліпс довільного розкриття, т. Е. Описану окружність в перспективі. Тепер необхідно знайти на ній шість точок, які є вершинами шестикутника. Проведіть будь діаметр даної окружності через її центр (рис. 3.57). Крайні точки діаметра - 5 і 2, що лежать на еліпсі, є вершинами шестикутника. Для знаходження інших вершин необхідно розділити цей діаметр на чотири однакових відрізка. Діаметр вже розділений точкою центру кола на два радіуса, залишається розділити кожен радіус навпіл. На перспективному малюнку всі чотири відрізка рівномірно скорочуються при видаленні від глядача (рис. 3.58). Тепер проведіть через середини радіусів - точки А і В - прямі, перпендикулярні прямий 5 - 2. Знайти їх напрямок можна за допомогою дотичних до еліпса в точках 5 і 2 (рис. 3.59). Ці дотичні будуть перпендикулярні діаметру 5 - 2, а прямі, проведені через точки А і В паралельно цим дотичним, будуть також перпендикулярні прямий 5 - 2. Позначте точки, отримані на перетині цих прямих з еліпсом, як 1, 3, 4, 6 ( рис. 3.60). З'єднайте всі шість вершин прямими лініями (рис. 3.61).

Перевірте правильність вашого побудови різними способами. Якщо побудова вірно, то лінії, що з'єднують протилежні вершини шестикутника, перетинаються в центрі кола (рис. 3.62), а протилежні сторони шестикутника паралельні відповідним діаметрам (рис. 3.63). Ще один спосіб перевірки показаний на рис. 3.64.

Вертикальний шестикутник. В такому шестикутнику прямі, що з'єднують точки 7 і 3, б і 4, а також дотичні до описаного кола в точках 5 і 2, мають вертикальний напрямок і зберігають його на перспективному малюнку. Таким чином, провівши дві вертикальні дотичні до еліпса, знайдемо точки 5 і 2 (точки дотику). З'єднайте їх прямою лінією, а потім розділіть отриманий діаметр 5 - 2 на 4 рівних відрізка, враховуючи їх перспективні скорочення (рис. 3.65). Проведіть вертикальні прямі через точки А і Б, а на їх перетині з еліпсом знайдіть точки 1,3,6л4. Потім послідовно з'єднайте точки 1 - 6 прямими (рис. 3.66). Правильність побудови шестикутника перевірте аналогічно до попереднього прикладу.

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

На основі квадрата. Розгляньте рис. 3.67. Вписаний в квадрат шестикутник по горизонтальному напрямку 5 - 2 дорівнює стороні квадрата, а по вертикалі - менше її довжини.

Вертикальний шестикутник. Намалюйте вертикальний квадрат в перспективі. Проведіть через перетин діагоналей пряму, паралельну його горизонтальних сторін. Розділіть отриманий відрізок 5 - 2 на чотири рівні частини і проведіть через точки А і В вертикальні прямі (рис. 3.68). Лінії, що обмежують шестикутник зверху і знизу, не збігаються зі сторонами квадрата. Зобразіть їх на деякій відстані (1114 а) від горизонтальних сторін квадрата і паралельно їм. Поєднавши знайдені таким чином точки 1 і 3 з точкою 2, а точки 6 і 4 - з точкою 5, отримаємо шестикутник (рис. 3.69).

Горизонтальний шестикутник будується в тій же послідовності (рис. 3.70 і 3.71).

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

Крім того існує ще один - описати навколо отриманого шестикутника окружність (на вашому малюнку - еліпс). Всі вершини шестикутника повинні належати цьому еліпсу.

Оволодівши навичками зображення шестикутника, ви вільно перейдете до зображення шестигранної призми. Уважно розгляньте схему на рис. 3.72, а також схеми побудови шестигранних призм на основі описаного кола (рис. 3.73; 3.74 і 3.75) і на основі квадрата (рис. 3.76; 3.77 і 3.78). Зобразіть вертикальні і горизонтальні шестигранники різними способами. На малюнку вертикального шестикутника довгі сторони бічних граней будуть паралельними один одному вертикальними прямими, а шестикутник підстави буде тим більше розкритий, чим далі він знаходиться від лінії горизонту. На малюнку горизонтального шестикутника довгі сторони бічних граней будуть сходитися в точці сходу на горизонті, а розкриття шестикутника підстави буде тим більше, чим далі від глядача він знаходиться. Зображуючи шестигранник, стежте також за тим, щоб паралельні грані обох підстав сходилися в перспективі (рис. 3.79; 3.80).

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


Побудова вписаного в коло рівностороннього трикутника. Вершини такого трикутника можна побудувати за допомогою циркуля і косинця з кутами в 30 і 60 ° або тільки одного циркуля. Щоб побудувати сторону 2-3, встановлюємо рейсшини в положення, показане штриховими лініями, і через точку 2 проводимо пряму, яка визначить третю вершину трикутника.

Метод 1 з 3: Малюємо ідеальний шестикутник за допомогою циркуля

Намічаємо на колі точку 1 і приймаємо її за одну з вершин п'ятикутника. Нехай дана окружність діаметра D; потрібно вписати в неї правильний семикутник (фіг. 65). Ділимо вертикальний діаметр окружності на сім рівних частин. З точки 7 радіусом, рівним діаметру окружності D, описуємо дугу до перетину з продовженням горизонтального діаметра в точці F. Точку F назвемо полюсом багатокутника.

Саме на вмінні будувати бісектриси кутів і серединні перпендикуляри відрізків і грунтується методика побудови правильних багатокутників

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

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

4. Отримали шуканий правильний трикутник АВС. Завдання вирішена. 3. Помістивши одну ніжку циркуля в довільну точки А1 на окружності, за допомогою другої ніжки відзначимо на тій же окружності точку А2 і з'єднаємо її з точкою А1. Отримаємо першу сторону шестикутника. 3. За допомогою серединних перпендикулярів до сторін багатокутника, опущеним з точки О, розділимо всі його сторони і всі дуги окружності, укладені між його сусідніми вершинами, навпіл.

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

Для отримання вершин /// - /// з точок IV, V і VI проводимо до перетину з колом горизонтальні прямі

Знайдені вершини з'єднуємо послідовно між собою. Семикутник може бути побудований шляхом проведення променів з полюса F і через непарні поділу вертикального діаметра. Центри обох кіл збігаються (точка О на Рис. 1). Також на малюнку наведені радіуси описаної (R) і вписаною (r) кіл.

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

Сітки з шестикутників (гексагональних сітки) використовуються в деяких іграх, але вони не такі прості і поширені, як сітки прямокутників. Я колекціоную ресурси про сітках шестикутників вже майже 20 років, і написав це керівництво по самим елегантним підходам, що реалізовуються в найпростішому коді. У статті часто використовуються керівництва Чарльза Фу (Charles Fu) і Кларка Вербрюгген (Clark Verbrugge). Я опишу різні способи створення сіток шестикутників, їх взаємозв'язок, а також найзагальніші алгоритми. Багато частин цієї статті інтерактивні: вибір типу сітки змінює відповідні схеми, код і тексти. (Прим. Пер .: це відноситься тільки до оригіналу, раджу його вивчити. У перекладі вся інформація оригіналу збережена, але без інтерактивності.).

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

геометрія

Шестикутники - це шестигранні багатокутники. У правильних шестикутників всі сторони (грані) мають однакову довжину. Ми будемо працювати тільки з правильними шестикутниками. Зазвичай в сітках шестикутників використовуються горизонтальна (з гострим верхом) і вертикальна (з плоским верхом) орієнтації.


Шестикутники з плоским (зліва) і гострим (праворуч) верхом

У шестикутників по 6 граней. Кожна грань загальна для двох шестикутників. У шестикутників по 6 кутових точок. Кожна кутова точка загальна для трьох шестикутників. Детальніше про центрах, гранях і кутових точках можна прочитати в моїй статті про частинах сіток (квадратах, шестикутник і трикутниках).

кути

У правильному шестикутнику внутрішні кути рівні 120 °. Є шість «клинів», кожен з яких є рівностороннім трикутником з внутрішніми кутами 60 °. кутова точка iзнаходиться на відстані (60 ° * i) + 30 °, на size одиниць від центру center. У коді:

Function hex_corner (center, size, i): var angle_deg = 60 * i + 30 var angle_rad = PI / 180 * angle_deg return Point (center.x + size * cos (angle_rad), center.y + size * sin (angle_rad) )
Для заповнення шестикутника потрібно отримати вершини багатокутника з hex_corner (..., 0) по hex_corner (..., 5). Для відтворення контуру шестикутника потрібно використовувати ці вершини, а потім намалювати лінію знову в hex_corner (..., 0).

Різниця між двома орієнтаціями в тому, що x і y міняються місцями, що призводить до зміни кутів: кути шестикутників з плоским верхом рівні 0 °, 60 °, 120 °, 180 °, 240 °, 300 °, а з гострим верхом - 30 °, 90 °, 150 °, 210 °, 270 °, 330 °.


Кути шестикутників з плоским і гострим верхом

Розмір і розташування

Тепер ми хочемо розташувати кілька шестикутників разом. У горизонтальній орієнтації висота шестикутника height = size * 2. Вертикальна відстань між сусідніми шестикутниками vert = height * 3/4.

Ширина шестикутника width = sqrt (3) / 2 * height. Горизонтальна відстань між сусідніми шестикутниками horiz = width.

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



системи координат

Давайте приступимо до складання шестикутників в сітку. У разі сіток квадратів існує тільки один очевидний спосіб збирання. Для шестикутників ж є безліч підходів. Я рекомендую використовувати в якості первинного уявлення кубічні координати. Осьові координати або координати зсувів слід використовувати для зберігання карт і відображення координат для користувача.

координати зсувів

Найбільш частий підхід - зміщення кожного наступного стовпця або рядка. Стовпці позначаються col або q. Рядки позначаються row або r. Можна зміщувати непарні або парні стовпці / рядки, тому у горизонтальних і вертикальних шестикутників є по два варіанти.


Горизонтальне розташування «непарне-r»


Горизонтальне розташування «чет-r»


Вертикальне розташування «непарне-q»


Вертикальне розташування «чет-q»

кубічні координати

Ще один спосіб розгляду сіток шестикутників - бачити в них триосновні осі, а не дві, Як в сітках квадратів. У них проявляється елегантна симетрія.

Візьмемо сітку кубів і виріжемодіагональну площину в x + y + z = 0. Це дивна думка, але вона допоможе нам спростити алгоритми сіток шестикутників. Зокрема, ми зможемо скористатися стандартними операціями з декартових координат: підсумовуванням і відніманням координат, множенням і діленням на скалярну величину, а також відстанями.

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


шестикутники


Куби

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

Вивчіть, як кубічні координати працюють для сітки шестикутників. При виборі шестикутників виділяються кубічні координати, відповідні трьох осях.

  1. Кожен напрямок сітки кубів відповідає лініїна сітці шестикутників. Спробуйте виділити шестикутник з z, рівним 0, 1, 2, 3, щоб побачити зв'язок. Рядок відзначена синім. Спробуйте те ж саме для x (зелений) і y (бузковий).
  2. Кожен напрямок сітки шестикутника - це поєднання двох напрямків сітки кубів. Наприклад, «північ» сітки шестикутників лежить між + y і -z, тому кожен крок на «північ» збільшує y на 1 і зменшує z на 1.
Кубічні координати - розумний вибір для системи координат сітки шестикутників. Умовою є x + y + z = 0, тому в алгоритмах воно повинно зберігатися. Умова також гарантує, що для кожного шестикутника завжди буде канонічна координата.

Існує безліч різних систем координат для кубів і шестикутників. У деяких з них умова відрізняється від x + y + z = 0. Я показав лише одну з безлічі систем. Можна також створити кубічні координати з x-y, y-z, z-x, у яких буде свій набір цікавих властивостей, але я не буду їх тут розглядати.

Але ви можете заперечити, що не хочете зберігати 3 числа для координат, бо не знаєте, як зберігати карту в такому вигляді.

осьові координати

Осьова система координат, іноді звана «трапецеидальной», будується на основі двох або трьох координат з кубічної системи координат. Оскільки у нас є умова x + y + z = 0, третя координата не потрібна. Осьові координати корисні для зберігання карт і відображення координат користувачеві. Як і у випадку з кубічними координатами, з ними можна використовувати стандартні операції підсумовування, віднімання, множення і ділення декартових координат.

Існує безліч кубічних систем координат і безліч осьових. У цьому керівництві я не буду розглядати всі поєднання. Я виберу дві змінні, q (стовпець) і r (рядок). У схемах цієї статті q відповідає x, а r відповідає z, але таке відповідність довільно, тому що можна обертати і повертати схеми, отримуючи різні відповідності.

Перевага цієї системи перед сітками зсувів в більшій зрозумілості алгоритмів. Недоліком системи є те, що зберігання прямокутної карти виконується трохи дивно; см. розділ про збереження карт. Деякі алгоритми ще зрозуміліше в кубічних координатах, але оскільки у нас є умова x + y + z = 0, ми можемо обчислити третю обіцяну координату і використовувати її в цих алгоритмах. У своїх проектах я називаю осі q, r, s, тому умова виглядає як q + r + s = 0, і я, коли потрібно, можу обчислити s = -q - r.

осі

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


Координати зміщення, кубічні і осьові

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

перетворення координат

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

Осьові координати близько пов'язані з кубічними, тому перетворення робиться просто:

# Перетворення кубічних в осьові координати q = x r = z # перетворення осьових в кубічні координати x = q z = r y = -x-z
У коді ці дві функції можуть бути записані таким чином:

Function cube_to_hex (h): # осьова var q = hx var r = hz return Hex (q, r) function hex_to_cube (h): # кубічна var x = hq var z = hr var y = -xz return Cube (x, y , z)
Координати зміщення зовсім трохи складніше:

сусідні шестикутники

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

кубічні координати

Переміщення на один простір в координатах шестикутників призводить до зміни однієї з трьох кубічних координат на +1 і інший на -1 (сума повинна залишатися рівною 0). На +1 можуть змінюватися три можливих координати, а на -1 - залишилися дві. Це дає нам шість можливих змін. Кожне відповідає одному з напрямків шестикутника. Найпростіший і найшвидший спосіб - попередньо обчислити зміни і помістити їх в таблицю кубічних координат Cube (dx, dy, dz) під час компіляції:

Var directions = [Cube (+1, -1, 0), Cube (+1, 0, -1), Cube (0, +1, -1), Cube (-1, +1, 0), Cube ( -1, 0, +1), Cube (0, -1, +1)] function cube_direction (direction): return directions function cube_neighbor (hex, direction): return cube_add (hex, cube_direction (direction))

осьові координати

Як і раніше, ми використовуємо для початку кубічну систему. Візьмемо таблицю Cube (dx, dy, dz) і перетворимо в таблицю Hex (dq, dr):

Var directions = [Hex (+1, 0), Hex (+1, -1), Hex (0, -1), Hex (-1, 0), Hex (-1, +1), Hex (0, +1)] function hex_direction (direction): return directions function hex_neighbor (hex, direction): var dir = hex_direction (direction) return Hex (hex.q + dir.q, hex.r + dir.r)

координати зміщення

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

Як і раніше, ми створюємо таблицю чисел, які потрібно додати до col and row. Однак на цей раз у нас буде два масиви, один для непарних стовпців / рядків, а інший - для парних. Подивіться на (1,1) на малюнку карти сітки вище і зауважте, як змінюються col і row змінюються при переміщенні в кожному з шести напрямків. Тепер повторимо процес для (2,2). Таблиці і код будуть різними для кожного з чотирьох типів сіток зсувів, наводимо відповідний код для кожного типу сітки.

Непарне-r
var directions = [[Hex (+1, 0), Hex (0, -1), Hex (-1, -1), Hex (-1, 0), Hex (-1, +1), Hex (0 , +1)], [Hex (+1, 0), Hex (+1, -1), Hex (0, -1), Hex (-1, 0), Hex (0, +1), Hex ( +1, +1)]] function offset_neighbor (hex, direction): var parity = hex.row & 1 var dir = directions return Hex (hex.col + dir.col, hex.row + dir.row)


Чет-r
var directions = [[Hex (+1, 0), Hex (+1, -1), Hex (0, -1), Hex (-1, 0), Hex (0, +1), Hex (+1 , +1)], [Hex (+1, 0), Hex (0, -1), Hex (-1, -1), Hex (-1, 0), Hex (-1, +1), Hex (0, +1)]] function offset_neighbor (hex, direction): var parity = hex.row & 1 var dir = directions return Hex (hex.col + dir.col, hex.row + dir.row)


Сітка для парної (EVEN) і непарної (ODD) рядків

Непарне-q
var directions = [[Hex (+1, 0), Hex (+1, -1), Hex (0, -1), Hex (-1, -1), Hex (-1, 0), Hex (0 , +1)], [Hex (+1, +1), Hex (+1, 0), Hex (0, -1), Hex (-1, 0), Hex (-1, +1), Hex (0, +1)]] function offset_neighbor (hex, direction): var parity = hex.col & 1 var dir = directions return Hex (hex.col + dir.col, hex.row + dir.row)


Чет-q
var directions = [[Hex (+1, +1), Hex (+1, 0), Hex (0, -1), Hex (-1, 0), Hex (-1, +1), Hex (0 , +1)], [Hex (+1, 0), Hex (+1, -1), Hex (0, -1), Hex (-1, -1), Hex (-1, 0), Hex (0, +1)]] function offset_neighbor (hex, direction): var parity = hex.col & 1 var dir = directions return Hex (hex.col + dir.col, hex.row + dir.row)


Сітка для парного (EVEN) і непарного (ODD) стовпців

діагоналі

Переміщення в «диагональном» просторі в координатах шестикутників змінює одну з трьох кубічних координат на ± 2 і дві інші на ∓1 (сума повинна залишатися рівною 0).

Var diagonals = [Cube (+2, -1, -1), Cube (+1, +1, -2), Cube (-1, +2, -1), Cube (-2, +1, +1 ), Cube (-1, -1, +2), Cube (+1, -2, +1)] function cube_diagonal_neighbor (hex, direction): return cube_add (hex, diagonals)
Як і раніше, ми можемо перетворити ці координати в осьові, відкинувши одну з трьох координат, або перетворити в координати зсуву, попередньо обчисливши результати.


відстані

кубічні координати

У кубічної системі координат кожен шестикутник є кубом в тривимірному просторі. Сусідні шестикутники знаходяться в сітці шестикутників на відстані 1 один від одного, але на відстані 2 в сітці кубів. Це робить розрахунок відстаней простим. У сітці квадратів манхеттенські відстані рівні abs (dx) + abs (dy). У сітці кубів манхеттенські відстані рівні abs (dx) + abs (dy) + abs (dz). Відстань в сітці шестикутників одно їх половині:

Function cube_distance (a, b): return (abs (a.x - b.x) + abs (a.y - b.y) + abs (a.z - b.z)) / 2
Еквівалентом цього запису буде вираз того, що одна з трьох координат повинна бути сумою двох інших, а потім отримання її в якості відстані. Можна вибрати форму поділу навпіл або форму максимального значення, наведену нижче, але вони дають однаковий результат:

Function cube_distance (a, b): return max (abs (a.x - b.x), abs (a.y - b.y), abs (a.z - b.z))
На малюнку максимальні значення виділені кольором. Зауважте також, що кожен колір позначає одне з шести «діагональних» напрямків.

GIF


осьові координати

У осьової системі третя координата виражена неявно. Давайте перетворимо з осьової в кубічну систему для розрахунку відстані:

Function hex_distance (a, b): var ac = hex_to_cube (a) var bc = hex_to_cube (b) return cube_distance (ac, bc)
Якщо компілятор в вашому випадку вбудовує (inline) hex_to_cube і cube_distance, то він згенерує такий код:

Function hex_distance (a, b): return (abs (a.q - b.q) + abs (a.q + a.r - b.q - b.r) + abs (a.r - b.r)) / 2
Існує безліч різних способів запису відстаней між шестикутниками в осьових координатах, але незалежно від способу запису відстань між шестикутниками в осьової системі витягується з манхеттенського відстані в кубічної системі. Наприклад, описана «різниця різниць» виходить із запису a.q + a.r - b.q - b.r як a.q - b.q + a.r - b.r і з використанням форми максимального значення замість форми поділу навпіл cube_distance. Всі вони аналогічні, якщо побачити зв'язок з кубічними координатами.

координати зміщення

Як і у випадку з осьовими координатами, ми перетворимо координати зсуву в кубічні координати, а потім використовуємо відстань кубічної системи.

Function offset_distance (a, b): var ac = offset_to_cube (a) var bc = offset_to_cube (b) return cube_distance (ac, bc)
Ми будемо використовувати той же шаблон для багатьох алгоритмів: перетворимо з шестикутників в куби, виконуємо кубічну версію алгоритму і перетворимо кубічні результати в координати шестикутників (осьові або координати зсуву).

отрісовка ліній

Як намалювати лінію від одного шестикутника до іншого? Я використовую лінійну інтерполяцію для малювання ліній. Лінія рівномірно семпліруется в N + 1 точках і обчислюється, в яких шестикутника знаходяться ці семпли.

GIF


  1. Спочатку ми обчислюємо N, яке буде відстанню в шестикутник між кінцевими точками.
  2. Потім рівномірно семпліруем N + 1 точок між точками A і B. За допомогою лінійної інтерполяції визначаємо, що для значень i від 0 до N, включаючи їх, кожна точка буде A + (B - A) * 1.0 / N * i. На малюнку ці контрольні точки показані синім. В результаті виходять координати з плаваючою комою.
  3. Перетворимо кожну контрольну точку (float) назад в шестикутники (int). Алгоритм називається cube_round (див. Нижче).
З'єднуємо все разом для відтворення лінії від A до B:

Function lerp (a, b, t): // для float return a + (b - a) * t function cube_lerp (a, b, t): // для шестикутників return Cube (lerp (ax, bx, t), lerp (ay, by, t), lerp (az, bz, t)) function cube_linedraw (a, b): var N = cube_distance (a, b) var results = for each 0 ≤ i ≤ N: results.append ( cube_round (cube_lerp (a, b, 1.0 / N * i))) return results
Примітки:

  • Бувають випадки, коли cube_lerp повертає точку, що знаходиться точно на межі між двома шестикутниками. Потім cube_round зрушує її в ту чи іншу сторону. Лінії виглядають краще, якщо їх зрушують в одному напрямку. Це можна зробити, додавши «Епсілон» -шестіугольний Cube (1e-6, 1e-6, -2e-6) до однієї або обох кінцевих точок перед початком циклу. Це «підштовхне» лінію в одному напрямку, щоб вона не потрапляла на межі граней.
  • Алгоритм DDA-лінії в сітках квадратів прирівнює N до максимуму відстані по кожній з осей. Ми робимо те ж саме в кубічному просторі, що аналогічно відстані в сітці шестикутників.
  • Функція cube_lerp повинна повертати куб з координатами в float. Якщо ви програмуєте на мові зі статичної типізацією, то не зможете використовувати тип Cube. Замість нього можна визначити тип FloatCube або вбудувати (inline) функцію в код відтворення ліній, якщо ви не хочете визначати ще один тип.
  • Можна оптимізувати код, вмонтувавши (inline) cube_lerp, а потім розрахувавши B.x-A.x, B.x-A.y і 1.0 / N за межами циклу. Множення можна перетворити в повторюване підсумовування. В результаті вийде щось на зразок алгоритму DDA-лінії.
  • Для відтворення ліній я використовую осьові або кубічні координати, але якщо ви хочете працювати з координатами зміщення, то вивчіть.
  • Існує багато варіантів відтворення ліній. Іноді потрібно «сверхпокритіе». Мені прислали код відтворення ліній з сверхпокритіем в шестикутник, але я поки не вивчав його.

діапазон переміщення

діапазон координат

Для заданого центру шестикутника і діапазону N які шестикутники знаходяться в межах N кроків від нього?

Ми можемо зробити зворотну роботу з формули відстані між шестикутниками distance = max (abs (dx), abs (dy), abs (dz)). Щоб знайти всі шестикутники в межах N, нам потрібні max (abs (dx), abs (dy), abs (dz)) ≤ N. Це означає, що потрібні всі три значення: abs (dx) ≤ N і abs (dy) ≤ N і abs (dz) ≤ N. Прибравши абсолютне значення, ми одержимо -N ≤ dx ≤ N і -N ≤ dy ≤ N і -N ≤ dz ≤ N. У коді це буде вкладений цикл:

Var results = for each -N ≤ dx ≤ N: for each -N ≤ dy ≤ N: for each -N ≤ dz ≤ N: if dx + dy + dz = 0: results.append (cube_add (center, Cube (dx , dy, dz)))
Цей цикл спрацює, але буде досить неефективним. З усіх значень dz, які ми перебираємо в циклі, тільки одне дійсно задовольняє умові кубів dx + dy + dz = 0. Замість цього ми безпосередньо обчислимо значення dz, що задовольняє умові:

Var results = for each -N ≤ dx ≤ N: for each max (-N, -dx-N) ≤ dy ≤ min (N, -dx + N): var dz = -dx-dy results.append (cube_add ( center, Cube (dx, dy, dz)))
Цей цикл проходить тільки по потрібним координатами. На малюнку кожен діапазон є парою ліній. Кожна лінія - це нерівність. Ми беремо всі шестикутники, що задовольняють шести неравенствам.

GIF


пересічні діапазони

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

Можна підійти до цієї проблеми з точки зору алгебри або геометрії. Алгебраїчно кожна область виражається як умови нерівностей в формі -N ≤ dx ≤ N, і нам потрібно знайти перетин цих умов. Геометрично кожна область є кубом в тривимірному просторі, і ми перетнемо два куба в тривимірному просторі для отримання прямокутного паралелепіпеда в тривимірному просторі. Потім ми проектуємо його назад на площину x + y + z = 0, щоб отримати шестикутники. Я буду вирішувати цю задачу алгебраїчних.

По-перше, ми перепишемо умова -N ≤ dx ≤ N в більш загальній формі x min ≤ x ≤ x max, і приймемо x min = center.x - N і x max = center.x + N. Зробимо те ж саме для y і z, в результаті отримавши загальний вигляд коду з попереднього розділу:

Var results = for each xmin ≤ x ≤ xmax: for each max (ymin, -x-zmax) ≤ y ≤ min (ymax, -x-zmin): var z = -xy results.append (Cube (x, y, z))
Перетином двох діапазонів a ≤ x ≤ b і c ≤ x ≤ d є max (a, c) ≤ x ≤ min (b, d). Оскільки область шестикутників виражена як діапазони над x, y, z, ми можемо окремо перетнути кожен з діапазонів x, y, z, а потім використовувати вкладений цикл для генерування списку шестикутників в перетині. Для однієї області шестикутників ми приймаємо x min = H.x - N and x max = H.x + N, аналогічно для y і z. Для перетину двох областей шестикутників ми приймаємо x min = max (H1.x - N, H2.x - N) і x max = min (H1.x + N, H2.x + N), аналогічно для y і z. Той же шаблон працює для перетину трьох або більше областей.

GIF


перешкоди

При наявності перешкод найпростіше виконати заливку з обмеженням по відстані (пошук в ширину). На малюнку нижче ми обмежуємося чотирма ходами. У коді fringes [k] - це масив всіх шестикутників, яких можна досягти за k кроків. При кожному проході по основному циклу ми розширюємо рівень k-1 на рівень k.

Function cube_reachable (start, movement): var visited = set () add start to visited var fringes = fringes.append () for each 1< k ≤ movement: fringes.append() for each cube in fringes: for each 0 ≤ dir < 6: var neighbor = cube_neighbor(cube, dir) if neighbor not in visited, not blocked: add neighbor to visited fringes[k].append(neighbor) return visited

повороти

Для заданого вектора шестикутника (різницю між двома шестикутниками) нам може знадобитися повернути його, щоб він вказував на інший шестикутник. Це просто зробити, маючи кубічні координати, якщо дотримуватися повороту на 1/6 окружності.

Поворот на 60 ° вправо зрушує кожну координату на одну позицію вправо:

[X, y, z] to [-z, -x, -y]
Поворот на 60 ° вліво зрушує кожну координату на одну позицію вліво:

[X, y, z] to [-y, -z, -x]



«Погравши» [в оригіналі статті] зі схемою, можна помітити, що кожен поворот на 60 ° змінюєзнаки і фізично «повертає» координати. Після повороту на 120 ° знаки знову стають тими ж. Поворот на 180 ° змінює знаки, але координати повертаються в своє початкове положення.

Ось повна послідовність повороту положення P навколо центрального положення C, що приводить до нового положення R:

  1. Перетворення положень P і C в кубічні координати.
  2. Обчислення вектора вирахуванням центру: P_from_C = P - C = Cube (P.x - C.x, P.y - C.y, P.z - C.z).
  3. Поворот вектора P_from_C як описано вище і присвоювання підсумкового вектору позначення R_from_C.
  4. Перетворення вектора назад в положення додатком центру: R = R_from_C + C = Cube (R_from_C.x + C.x, R_from_C.y + C.y, R_from_C.z + C.z).
  5. Перетворення кубічного положення R назад в потрібну систему координат.
Тут кілька етапів перетворень, але кожен з них досить простий. Можна скоротити деякі з цих етапів, визначивши поворот безпосередньо в осьових координатах, але вектори шестикутників не працюють з координатами зміщення, і я не знаю, як скоротити етапи для координат зміщення. Див. Також обговорення інших способів обчислення повороту на stackexchange.

кільця

просте кільце

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

Function cube_ring (center, radius): var results = # цей код не працює для radius == 0; ви розумієте, чому? var cube = cube_add (center, cube_scale (cube_direction (4), radius)) for each 0 ≤ i< 6: for each 0 ≤ j < radius: results.append(cube) cube = cube_neighbor(cube, i) return results
У цьому коді cube починається на кільці, показаному великий стрілкою від центру до кута схеми. Я вибрав для початку кут 4, тому що він відповідає шляху, в якому рухаються мої числа напрямків. Вам може знадобитися інший початковий кут. На кожному етапі внутрішнього циклу cube рухається на один шестикутник по кільцю. Через 6 * radius кроків він завершує там, де почав.


спіральні кільця

Проходячи по кільцях по спіральному паттерну, ми можемо заповнити внутрішні частини кілець:

Function cube_spiral (center, radius): var results = for each 1 ≤ k ≤ radius: results = results + cube_ring (center, k) return results



Площа великого шестикутника дорівнює сумі всіх кіл плюс 1 для центру. Для обчислення площі використовуйте цю формулу.

Обхід шестикутників таким способом можна також використовувати для обчислення діапазону переміщення (див. Вище).

Область видимості

Що мабуть із заданого положення з заданим відстанню, і не перекривається перешкодами? Найпростіший спосіб визначити це - намалювати лінію до кожного шестикутник в заданому діапазоні. Якщо лінія не зустрічається зі стінами, то ви бачите шестикутник. Переміщайте курсор по шестикутника [на схемі в оригіналі статті], щоб побачити отрисовку ліній до цих шестикутник і стіни, з якими лінії зустрічаються.

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

GIF



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

Я хочу в подальшому розширювати це керівництво. У мене є

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

Правильний шестикутник є багатокутник з шістьма однаковими сторонами і рівними кутами. Зі шкільного курсу нам відомо, що він має такі властивості:

  • Довжина його сторін відповідає радіусу описаного кола. З усіх це властивість має лише правильний шестикутник.
  • Кути рівні між собою, і величина кожного становить 120 °.
  • Периметр гексагона можна знайти за формулою Р = 6 * R, якщо відомий радіус описаної навколо нього кола, або Р = 4 * √ (3) * r, якщо окружність в нього вписана. R і r - радіуси описаної і вписаного кола.
  • Площа, яку займає правильний шестикутник, визначається наступним чином: S = (3 * √ (3) * R 2) / 2. Якщо радіус невідомий, замість нього підставляємо довжину однієї зі сторін - як відомо, вона відповідає довжині радіуса описаного кола.

У правильного шестикутника є одна цікава особливість, завдяки якій він отримав в природі таке широке поширення, - він здатний заповнити будь-яку поверхню площині без накладень і прогалин. Існує навіть так звана лема Пала, згідно з якою правильний шестикутник, сторона якого дорівнює 1 / √ (3), являє собою універсальну покришку, тобто може покрити будь-яка множина з діаметром в одну одиницю.

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

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

вміст:

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

кроки

1 Малюємо ідеальний шестикутник за допомогою циркуля

  1. 1 За допомогою циркуля малюємо коло.Вставте олівець в циркуль. Розширте циркуль на бажану ширину радіусу вашого кола. Радіус може бути від пари до десятка сантиметрів шириною. Далі поставте циркуль з олівцем на папір і намалюйте коло.
    • Іноді легше спочатку намалювати підлогу кола, а потім другу половину.
  2. 2 Наведіть голку циркуля до краю кола.Поставте його на вершину кола. Не міняйте кут і розташування циркуля.
  3. 3 Зробіть невелику позначку олівцем на краю кола.Зробіть її виразною, але не дуже темною, так як пізніше ви її зітрете. Не забудьте зберігати кут, який ви встановили для циркуля.
  4. 4 Наведіть голку циркуля на ту позначку, яку ви тільки що зробили.Поставте голку прямо на позначку.
  5. 5 Зробіть ще одну позначку олівцем на краю кола.Таким чином, ви зробите другу позначку на певній дистанції від першої позначки. Продовжуйте рухатися в одному напрямку.
  6. 6 Тим же способом зробіть ще чотири позначки.Ви повинні повернутися назад на початкову позначку. Якщо немає, тоді, швидше за все, кут, під яким ви тримали циркуль і робили позначки, змінився. Можливо, це сталося через те, що ви стиснули його занадто сильно або навпаки, трохи послабили.
  7. 7 З'єднайте позначки за допомогою лінійки.Шість місць, де ваші позначки перетинаються з краєм круга, - це шість вершин шестикутника. За допомогою лінійки і олівця намалюйте прямі лінії, з'єднуючи сусідні позначки.
  8. 8 Зітріть і коло, і позначки на краях кола, і інші мітки, які ви зробили. Після того, як ви стерли всі свої допоміжні лінії, ваш ідеальний шестикутник повинен бути готовий.

2 Малюємо грубий шестикутник за допомогою круглого предмета і лінійки

  1. 1 Обведіть ободок склянки олівцем.Таким чином, ви намалюєте коло. Дуже важливо малювати саме олівцем, так як пізніше вам потрібно буде стерти всі допоміжні лінії. Ви також можете обвести перевернутий стакан, банку або щось ще, що має круглу основу.
  2. 2 Намалюйте горизонтальні лінії через центр вашого кола.Можете скористатися лінійкою, книгою - чим завгодно з прямим краєм. Якщо у вас все ж є лінійка, ви можете відзначити середину, розрахувавши вертикальну довжину кола і розділивши його навпіл.
  3. 3 Намалюйте "Х" над половиною кола, розділяючи його на шість рівних секцій.Так як ви вже провели лінію через середину кола, Х повинен бути більше в ширину, ніж у висоту, щоб частини були рівні. Уявіть, що ви ділите піцу на шість частин.
  4. 4 Зробіть з кожної секції трикутники.Щоб це зробити, за допомогою лінійки намалюйте пряму лінію під вигнутою частиною кожної секції, поєднуючи її з іншими двома лініями, утворюючи трикутник. Зробіть це з рештою п'ятьма секціями. Думайте про це, як про виготовлення скоринки навколо ваших шматків піци.
  5. 5 Зітріть всі допоміжні лінії.До допоміжних лініях відносяться ваш коло, три лінії, які розділили ваш коло на секції і інші позначки, які ви робили в процесі.

3 Малюємо грубий шестикутник за допомогою одного олівця

  1. 1 Намалюйте горизонтальну лінію.Щоб намалювати пряму лінію без лінійки, просто намалюйте початкову і кінцеву точку вашої горизонтальної лінії. Потім помістіть олівець в початкову точку і протягуйте лінію до кінця. Довжина цієї лінії може бути всього пара сантиметрів.
  2. 2 Намалюйте дві діагональні лінії з кінців горизонтальної.Діагональна лінія з лівого боку має бути спрямована назовні так само, як і діагональна лінія праворуч. Ви можете уявити, що ці лінії формують кут в 120 градусів по відношенню до горизонтальної лінії.
  3. 3 Намалюйте ще дві горизонтальні лінії, які виходять із перших горизонтальних прямих, намальованих всередину.Таким чином, буде створено дзеркальне відображення перших двох діагональних ліній. Нижня ліва лінія повинна бути відображенням верхній лівій лінії, а нижня права - відображенням верхній правій лінії. У той час як верхні горизонтальні лінії повинні дивитися назовні, нижні повинні дивитися всередину підстави.
  4. 4 Намалюйте ще одну горизонтальну лінію, з'єднуючи нижні дві діагональні лінії.Таким чином, ви намалюєте основу для свого шестикутника. В ідеалі ця лінія повинна бути паралельною до верхньої горизонтальної лінії. Ось ви і завершили свій шестикутник.
  • Олівець і циркуль повинні бути гострими, щоб мінімізувати помилки від занадто широких відміток.
  • Якщо при використанні методу з циркулем ви з'єднали кожну позначку замість всіх шести, то отримаєте рівносторонній трикутник.

попередження

  • Циркуль - досить гострий предмет, будьте з ним дуже акуратні.

Принцип роботи

  • Кожен метод допоможе намалювати шестикутник, утворений шістьма рівносторонніми трикутниками з радіусом, рівним довжині всіх сторін. Шість намальованих радіусів однакової довжини і всі лінії для створення шестикутника теж однієї довжини, так як ширина циркуля не змінювалася. Завдяки тому, що шість трикутників равносторонние, кути між їх вершинами рівні 60 градусів.

Що вам знадобиться

  • папір
  • олівець
  • лінійка
  • пара циркулей
  • Щось, що можна підкласти під папір, щоб голка циркуля не зісковзували.
  • ластик

Close