Мои мысли и проекты
Расширение (плагин) SketchUp для проектирования мебели программистом
https://ledtehnology.ru продаем световое табло погодных условий.

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

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

Красные - это 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 После этого плагин запрашивает директорию где будут храниться проекты. Т.е. выводится окно "Укажите директорию с проектами" и требуется указать папку где вы будете хранить ваши проекты.

В результате у нас появляется наше расширение

Использование

Переходим в папку которую мы указали для хранения проектов. Эту папку можно изменить в меню плагина

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

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

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

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

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

API

Файл "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)

результат работы

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

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

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

# Записать в файл команды для CorelCAD (AutoCAD?)
# Для выполнения готового скрипта в Corel CAD (по идее наверное и в вдругих CAD системах тоже можно). Я использовал для генерации 2D проекта для деталей из оргстекла
Shasoft::Object3D::write_cad_commands(filepath)

В результате будет сформирован скрипт SCR для запуска такого вида

LINE 50.0,0.0 65.0,0.0 65.0,70.0 50.0,70.0 50.0,0.0  
LINE 75.0,0.0 90.0,0.0 90.0,70.0 75.0,70.0 75.0,0.0  
LINE 100.0,0.0 115.0,0.0 115.0,20.0 100.0,20.0 100.0,0.0  
LINE 125.0,0.0 140.0,0.0 140.0,20.0 125.0,20.0 125.0,0.0  
# Записать в файл команды для CorelDraw (CorelDraw)
# Для выполнения готового скрипта в CorelDraw. Я использовал для генерации 2D проекта для деталей из оргстекла
Shasoft::Object3D::write_CorelDraw_commands(filepath)

В результате будет сформирован скрипт VBA для запуска в CorelDraw такого вида

Sub generateFigures()
    Dim crv As Curve
    Dim shp As Shape
    '
    Set crv = ActiveDocument.CreateCurve
    With crv.CreateSubPath(0.0,0.0)
        .AppendLineSegment 15.0,0.0
        .AppendLineSegment 15.0,70.0
        .AppendLineSegment 0.0,70.0
        .Closed = True
    End With
    Set shp = ActiveLayer.CreateCurve(crv)
    shp.Fill.ApplyNoFill
    shp.Outline.SetPropertiesEx 0.1, OutlineStyles(0), CreateRGBColor(0, 0, 0), ArrowHeads(0), ArrowHeads(0), cdrFalse, cdrFalse, cdrOutlineButtLineCaps, cdrOutlineMiterLineJoin, 0#, 100, MiterLimit:=1#, Justification:=cdrOutlineJustificationMiddle
    '
    Set crv = ActiveDocument.CreateCurve
    With crv.CreateSubPath(25.0,0.0)
        .AppendLineSegment 40.0,0.0
        .AppendLineSegment 40.0,70.0
        .AppendLineSegment 25.0,70.0
        .Closed = True
    End With
    Set shp = ActiveLayer.CreateCurve(crv)
    shp.Fill.ApplyNoFill
    shp.Outline.SetPropertiesEx 0.1, OutlineStyles(0), CreateRGBColor(0, 0, 0), ArrowHeads(0), ArrowHeads(0), cdrFalse, cdrFalse, cdrOutlineButtLineCaps, cdrOutlineMiterLineJoin, 0#, 100, MiterLimit:=1#, Justification:=cdrOutlineJustificationMiddle
    '
	ActivePage.SetSize 12875.0#, 2100#

В заключении

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

При наличии сверла для конфирматов
(и небольшого навыка) сборка занимает не так много времени.

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

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

0

Комментарии

Чтобы оставлять комментарии войдите на сайт. Вы можете сделать это через социальную сеть