Monthly Archives: Грудень 2019

Як збудувати геодезичний купол?

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

Картон в меблевій майстерні

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

3d модель

Перший етап – змоделювати все на комп’ютері.

  1. Запускаємо Blender, вибираємо куб який там за замовчуванням, натискаємо Delete.
  2. Shift+A (додати об’єкт) -> Icosphere, Subdivision: 2, Size: 1.0 location: (0.0, 0.0, 0.0).
  3. Переключаємось на вид з переду, тиснемо Tab і переходимо в Edit mode.
  4. Тиснемо правою кнопкою на якусь вершину аби вибрати лише її. Тиснемо b, аби вибрати вершини рамкою, і вибираємо ті що нижче 0 по осі Z.
  5. Натискаємо Delete і видалаємо половину вершин знизу.

Має вийти щось таке:

Купол в Blender

Це можна експортувати в розгортку для паперової моделі, якщо зробити наступне:

  1. Зайти в меню File -> User preferences, вкладка Add-ons, категорія Import-Export.
  2. Поставити галочку біля Export Paper Model, і натиснути “Save User Settings”.
  3. File -> Export -> Paper Model експортує модель в файл pdf (хоча пише що svg).

Отримаємо таке:

Розгортка

Для деяких розрахунків більшої моделі ще корисно експортувати в .obj файл.

Паперова модель

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

Склеєна паперова модель

Паперова модель дає краще уявлення про те скільки трикутників доведеться вирізати, але як різати картон все ще не ясно. Якщо я хочу купол радіусом 1 метр, то якого розміру мають бути трикутники?

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

Розміри

Наступний скрипт якщо йому згодувати наш obj файл зробить дві речі:

import sys
import math
from collections import Counter

# Distance between two vectors (iterables) rounded to 3 digits after comma
def distance(A, B):
    return round(math.sqrt(sum((a - b)**2 for a, b in zip(A,B))), 3)

def obj_fline_to_edges(line, vertices):
    # get indexes of vertices
    face = [int(e.split('/')[0]) - 1 for e in line[2:].split(' ')]

    # compute edge length's
    edges = sorted([
        distance(vertices[face[0]], vertices[face[1]]),
        distance(vertices[face[2]], vertices[face[1]]),
        distance(vertices[face[2]], vertices[face[0]]),
    ])
    return tuple(edges)

def main(filename):
    vertices = []
    faces = []
    face_lines = []
    with open(filename) as f:
        for line in f:
            if line.startswith('v '): # add line to list of vertices
                coords = [float(e) for e in line[2:].split(' ')]
                vertices.append(coords)

            if line.startswith('f '): # it's a face
                face_lines.append(line.strip())
                edges = obj_fline_to_edges(line, vertices)
                faces.append(edges)

    stats = Counter(faces).most_common()
    for i, (edges, count) in enumerate(stats, 1):
        print(f'{i}) {edges} - {count}')

    materials = [
        'redMtl',
        'blueMtl',
    ]
    for i, (edges_type, count) in enumerate(stats):
        print("usemtl", materials[i])
        for line in face_lines:
            edges = obj_fline_to_edges(line, vertices)
            if edges == edges_type:
                print(line)

if __name__ == "__main__":
    main(sys.argv[1])

Напише статистику по трикутнихах, і скаже що в нас їх є два види, 30 рівнобедрених і 10 рівносторонніх. Розміри в міліметрах, якщо купол метровий:
1) (0.547, 0.547, 0.618) – 30
2) (0.618, 0.618, 0.618) – 10

А крім того, додасть матеріали, які в позначать в моделі трикутники різного типу різними кольорами. Кожен рядок що починається на f, в об’єктному файлі треба замінити на той який виводиться нашим скриптом. (Разом з usemtl, вони позначають кольори). В файл *.mtl який Blender експортує поряд з об’єктним, треба додати наприклад такі матеріали:

newmtl redMtl
Ns 18
Ka 0.000000 0.000000 0.000000
Kd 1.0 0.5 0.5
Ks 0.8 0.8 0.8
d 1
illum 2

newmtl blueMtl
Ns 1
Ka 0.000000 0.000000 0.000000
Kd 0.5 0.5 1.0
Ks 0.8 0.8 0.8
d 1
illum 2

Kd означає колір дифузного відбиття за Фонгом.

Тепер, якщо ми експортуємо те що відредагували в текстовому редакторі назад в Blender – отримаємо таке:

Бачимо що рівнобедрені трикутники треба з’єднати по 5 штук коротшими сторонами в п’ятикутні піраміди, тоді до країв піраміди причепити ще 5 рівносторонніх трикутників, тоді поміж кожні два трикутники вліпити ще по 5 п’ятикутних пірамід і між ними вліпити решту рівносторонніх трикутників. Або іншим способом. Якщо тепер експортувати розгортку, і при експорті вибрати в налаштуваннях документа “Textures: From materials”, то розгортка теж буде кольоровою:

Кольорова розгортка геокупола

Картонна модель

Тепер, головне аби картону вистачило. Виявилось що вирізати трикутник зі стороною майже 62 см я не можу, бо той картон що я маю вужчий. (Насправді головне висота, але я хотів вмістити більше трикутників, тому вирішив що довша сторона буде 38 см, помножив всі розміри на 380/618, і загалом вийшло таке:

1) (0.336, 0.336, 0.380) – 30
2) (0.380, 0.380, 0.380) – 10

І добре, бо діаметр оригінального купола – 2 метри, того що в мене 1.23м, і він набагато краще вміщується в кімнаті. Для того щоб під купол було легше заходити, я зробив лише 9 рівносторонніх трикутників, таким чином що один в основі відсутній, і поставив купол на стіну висотою 50 см з 9 прямокутних секцій шириною по 38 см. Загалом зі стіною висота в центрі складає 1.11м.

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

Краї для склеювання клеєм я вирішив не креслити аби зекономити картон і поклався на скотч.

Картонний циркуль і креслення зроблені ним

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

Натисніть, щоби переглянути слайдшоу.

Враховуючи те що трикутники я вирізав криво, вони прилягають не щільно і в хатинку потрапляє світло через те що скотч прозорий.

Чи сподобалась дитині хатинка? Ніби так, вона туди пару раз лазила грати “ку-ку”, але здається не настільки як мені. 🙂

Тому що нові іграшки – то тимчасове задоволення, а вміння робити 3d штуки без 3d принтера – то назавжди. 😉