[recovery mode] Расширение (плагин) SketchUp для проектирования мебели программистом

При расчете стоимости новой кухни цена оказалась такой большой, что я решил сделать её сам так как это обойдется в два раза дешевле. Для тренировки решил сделать для себя рабочий стол. Достаточно быстро пришло понимание: чтобы сделать хорошую вещь нужно сделать 3D модель. Это позволит на этапе проектирования посмотреть как будет выглядеть мебель и продумать как в дальнейшем будет происходить сборка. Так как 3D моделированием я не занимаюсь, то начал искать программу попроще. И самая простая что нашел SketchUp. При создании модели постоянно приходилось править модель из-за постоянно изменявшихся размеров. И после третьего изменения появилась идея — сделать параметризированную модель, чтобы она сама генерировалась с нужными размерами. SketchUp поддерживает скрипты на языке Ruby и эта статья о том что у меня получилось.

Решение достаточно простое — создаю некоторый API, который позволяет создавать 3D объекты листов ЛПСД с нужными параметрами. Из этих объектов компонуется готовая модель, а также в отдельный файл выгружаются размеры листов для передачи их в центр распила. В результате эксплуатации добавил ещё возможность указывать кромки для листов. Данный плагин был использован для проектирования более десятка различных изделий из ЛДСП. С каждым новым проектом плагин дорабатывался и модифицировался, улучшалось удобство и совершенствовалось API. В качестве примера последний проект — стол-тумба. На картинке модель + готовое изделие (птица и собака для привлечения внимания :))
main.jpg

Красные — это 2 м кромки, фиолетовый — кромки 0.4 мм. Нижние полки не до конца, так как там батарея отопления у стены. Столешница отстает от стены на 4 см чтобы тепло от батарее отопления поднималось вверх и обогревало стену (вообще делать мебель самому очень удобно — можно сделать под свои размеры).


вот так выглядит код для её генерации
# Толщина фанеры
$weght = 16.0
# Зазор между ящиком и задней стенкой
$zazor = 5.0
# Отступ от краев для ящика
$dWidth = 26.0

#
$width = 770
$offsetStena = 40
$dStoledhnica = 20
$height = 2500 - 150 - 900
$depthLeft = 600
$depthRight = $depthLeft - 175
$jshikHeight = 200
$heightPlanka = 300
$heightJshik = 190
$heightJshikOffset = 10
# Функция точки входа
def object3D_main()
    # Загрузить библиотеки
    Shasoft::Object3D::loadLibrary()
    # Установить толщину ЛДСП
    Shasoft::Object3D::LDSP::setWeght($weght)
    # Создать модель
    stenaLeft = Shasoft::Object3D::LDSP::create($height-$weght,$depthLeft,"2 0 0 1").name("Левая стена").rotateY(-90)
    stenaRight = Shasoft::Object3D::LDSP::create($height-$weght,$depthLeft,"2 0 0 1").name("Правая стена").rotateY(-90).moveX($width-$weght)
    stoleshnica = Shasoft::Object3D::LDSP::create($width,$depthLeft+$dStoledhnica-$offsetStena,"2 2 1 2").name("Столешница").move(-$weght,-$dStoledhnica,$height-$weght)
    polka1 = Shasoft::Object3D::LDSP::create($width-$weght*2,$depthRight,"2 0 0 0").name("Полка 1").moveZ(400)
    polka2 = Shasoft::Object3D::LDSP::create($width-$weght*2,$depthRight-$weght,"2 0 0 0").name("Полка 2").moveZ(600)
    polka3 = Shasoft::Object3D::LDSP::create($width-$weght*2,$depthLeft-$offsetStena,"2 0 0 0").name("Полка 3").moveZ(800+$heightJshik+$heightJshikOffset+10-$weght-5)
    pereborka1 = Shasoft::Object3D::LDSP::create($width-$weght*2,$heightPlanka).name("Переборка").rotateX(90).moveY($depthRight).moveZ(400+$weght)
    # Верхний ящик
    jshik1box = Shasoft::Object3D::LDSP::create_box($width-$weght*2-$dWidth,$depthLeft-$zazor-$offsetStena,$heightJshik,"Верхний ящик",1).moveX($dWidth/2).moveZ($height-$heightJshik-$heightJshikOffset-$weght)
    jshik1Fasad = Shasoft::Object3D::LDSP::create($width,200,"2 2 2 2").rotateX(90).moveX(-$weght).moveZ($height-$heightJshik-$heightJshikOffset-$weght-5).name("Фасад ящика 1")
    jshik1 = Shasoft::Object3D::create(jshik1box,jshik1Fasad)
    # Нижний ящик
    jshik2box = Shasoft::Object3D::LDSP::create_box($width-$weght*2-$dWidth,$depthLeft-$zazor-$offsetStena,$heightJshik-$weght-5,"Нижний ящик",1).moveX($dWidth/2).moveZ($height-$heightJshik-$heightJshikOffset-$weght)
    jshik2Fasad = Shasoft::Object3D::LDSP::create($width,200,"2 2 2 2").rotateX(90).moveX(-$weght).moveZ($height-$heightJshik-$heightJshikOffset-$weght-5).name("Фасад ящика 2")
    jshik2 = Shasoft::Object3D::create(jshik2box,jshik2Fasad).moveZ(-$height+800+$heightJshik+$heightJshikOffset+$weght+10)
    # Двери
    widthDver = $width/2-5
    dver1 = Shasoft::Object3D::LDSP::create(widthDver,800-5-10,"2 2 2 2").rotateX(90).moveZ(5).moveX(-$weght).name("Дверь 1")
    dver2 = dver1.copy.moveX($width-widthDver).name("Дверь 2")
    # 
    for i in 0..5
        Shasoft::Object3D::LDSP::create(467,247,"0 2 0 0").name("Полка в шкаф").moveX(-600).moveZ(i*50)
    end
    for i in 0..2
        Shasoft::Object3D::LDSP::create(467,640,"0 2 0 0").name("Полка в шкаф 2").moveX(-600-600).moveZ(i*50)
    end
    #
    Shasoft::Object3D::LDSP::write_csv( File.dirname(__FILE__)+"/main.csv" )
    #Shasoft::Object3D::LDSP::write_csv_cut( File.dirname(__FILE__)+"/cut.csv" )
    #Shasoft::Object3D::show()
end

Скачиваем файл Object3D.rbz
Запускаем SketchUp
Открываем Диспечер расширений (Окно/Диспечер расширений)
Жмем кнопку «Установить расширение» и выбираем скаченный файл Object3D.rbz
После этого плагин запрашивает директорию где будут храниться проекты. Т.е. выводится окно «Укажите директорию с проектами» и требуется указать папку где вы будете хранить ваши проекты.

В результате у нас появляется наше расширение
2019-01-25-10_02_19.png

Переходим в папку которую мы указали для хранения проектов. Эту папку можно изменить в меню плагина
2019-01-25-10_06_10.png

Создаем в папке директорию с названием нашего проекта. В моем случае это «Шкафчик в зал». Затем заходим в созданную директорию и создаем файл main.rb в котором создаем функцию точки входа

# Функция точки входа
def object3D_main()
 ... # код для генерации модели
end

Перезапускаем SketchUp и в меню плагина у вас появится пункт с названием созданной вами папки. Теперь вы выборе этого пункта будет происходить следующее:


  • очистка консоли Ruby
  • удаление всех элементов в текущем проекте
  • загрузка файла main.rb из указанной директории
  • вызов функции object3D_main

В функции object3D_main нужно сделать генерацию вашей модели. Можно скопировать в файл main.rb код который я приводил выше и тогда у вас сгенерируется мой шкафчик.


Файл «core.rb»

Каждая функция возвращает объект Shasoft: Object3D: Object3D который содержит методы для перемещения объекта и его поворота


  • Функция name() — установка имени объекта. Не стоит им пренебрегать. При сборке может сильно помочь :)


  • Функции объекта moveX, moveY, moveZ позволяют перемещать объект по соответствующим осям.


  • Функция move(x, y, z) позволяет переместить объект сразу по трем осям


  • Функции объекта rotateX, rotateY, rotateZ позволяют вращать объект вокруг соответствующих осей.


  • Есть функции псевдонимы moveRed, moveGreen, moveBlue, rotateRed, rotateGreen, rotateBlue где оси X (red), Y (green), Z (blue) названы по их цвету в SketchUp. Может кому-то так будет удобнее.
    Каждая функция возвращает указатель на сам обхект. Это позволяет делать цепочку вызовов

    # Повернем объект на 90 градусов вокруг оси X и  переместим по оси Y на 100 мм
    obj.rotateX(90).moveY(100)
    

  • Функция объекта set(dict, key, value) позволяет установить значение атрибута. dict — имя словаря, key — имя атрибута, value — значение


  • Функция объекта get(dict, key, value=nil) позволяет получить значение атрибута. dict — имя словаря, key — имя атрибута, value — значение


  • Метод copy позволяет получить копию объекта (хотя работает не очень стабильно :))


  • Метод group позволяет получить стандартный объект SketchUp: Group


Определен метод для создания объекта. В качестве параметров можно передавать список объектов Shasoft: Object3D: Object3D или SketchUp: Group. Если список параметров пустой, то будет создана новая группа

# Создать объект со списком дочерних объектов
Shasoft::Object3D::create(*args)

Также есть функция которая позволяет получить список объектов (Skechup: Group). Можно задать имя словаря и будут возвращены только объекты, у которых такой словарь присутствует. В частности именно так я отделяю объекты лист ЛПСД от других. При создании я устанавливаю словарь LDSP по которому потом и фильтрую все объекты сцены.

# Получить список объектов
# dict - имя словаря
Shasoft::Object3D::get(dict=nil)


Файл »2D_weght»

# Создать 3D объект выдавливания
# pts - список точек в координатной плоскости x,y
# weght - толщина(высота)
Shasoft::Object3D::create_pushpull(pts,weght)

# Создать плоскую поверхность с заданной толщиной
# lX - размер по X
# lY - размер по Y
# weght - толщина
Shasoft::Object3D::create_plane(lX,lY,weght)


Файл «ldsp.rb»

# Получить текущую толщину
Shasoft::Object3D::LDSP::weght

# Установить толщину
Shasoft::Object3D::LDSP::setWeght(weght)
# Получить текущий материал ЛДСП
Shasoft::Object3D::LDSP::material

# Установить материал ЛДСП
Shasoft::Object3D::LDSP::setMaterial(material)

# Создать лист ЛДСП
# width - ширина (по X)
# depth - глубина (по Y)
# kromka - кромка [X ближний, Y левый, X дальний, Y правый], 0 - нет кромки, 1 - кромка 0.4 мм, 2 - кромка 2 мм
Shasoft::Object3D::LDSP::create(width,depth,kromka="0 0 0 0")

Вспомогательная функция для создания выдвижных ящиков

# Создать ящик
# width - ширина
# depth - глубина
# height - высота
# name - имя
# is_kromka - 1/0 кромить верх 2 мм кромкой
Shasoft::Object3D::LDSP::create_box(width,depth,height,name,is_kromka)

результат работы
box.png

# Записать размеры в файл CSV
Shasoft::Object3D::LDSP::write_csv(filepath)

в результате будет сгенерирован следующий csv файл со следующими колонками


  • A — Ширина
  • B — Глубина
  • C Количество деталей
  • D — кромки в формате Д-длинная сторона, К-короткая сторона. Именно в таком их записывают в той конторе в которой я заказываю распил деталей. Возможно это стандарт.
  • E — кромки в том формате в котором вы их задавили при генерации
  • F — Название всех деталей. Это полезно при сборке

2019-01-25-10_39_50.png


В заключении

Проектирование и сборка мебели самому — это экономия денег где-то в 2 раза. А также возможность втиснуть ваше индивидуальное мебельное изделие в любую нестандартную дырку в квартире. Я обычно собираю мебель на конфирматах 7×50 из ЛДСП 16 мм
1490379431197352996.jpg
При наличии сверла для конфирматов
1490379603123527575.jpg
(и небольшого навыка) сборка занимает не так много времени.

Единственный минус — в это можно втянуться. После рабочего стола я уже собрал: кухню, несколько клеток (для одной и той же птицы она на фото), полки (навесные и напольные), тумбы и столы. В общем «захламил» в квартире все неиспользуемые места.

Ссылка для скачивания расширения

Ссылка на страницу плагина

© Habrahabr.ru