При расчете стоимости новой кухни цена оказалась такой большой, что я решил сделать её сам так как это обойдется в два раза дешевле. Для тренировки решил сделать для себя рабочий стол. Достаточно быстро пришло понимание: чтобы сделать хорошую вещь нужно сделать 3D модель. Это позволит на этапе проектирования посмотреть как будет выглядеть мебель и продумать как в дальнейшем будет происходить сборка. Так как 3D моделированием я не занимаюсь, то начал искать программу попроще. И самая простая что нашел SketchUp. При создании модели постоянно приходилось править модель из-за постоянно изменявшихся размеров. И после третьего изменения появилась идея - сделать параметризированную модель, чтобы она сама генерировалась с нужными размерами. SketchUp поддерживает скрипты на языке Ruby и эта статья о том что у меня получилось.
Решение достаточно простое - создаю некоторый API, который позволяет создавать 3D объекты листов ЛДСП с нужными параметрами. Из этих объектов компонуется готовая модель а также в отдельный файл выгружаются размеры листов для передачи их в центр распила. В результате эксплуатации добавил ещё возможность указывать кромки для листов. Данный плагин был использован для проектирования более десятка различных изделий из ЛДСП. С каждым новым проектом плагин дорабатывался и модифицировался, улучшалось удобство и совершенствовалось API. В качестве примера последний проект - стол-тумба. На картинке модель + готовое изделие (птица и собака для привлечения внимания :))
# Толщина фанеры
$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 и в меню плагина у вас появится пункт с названием созданной вами папки. Теперь вы выборе этого пункта будет происходить следующее:
В функции object3D_main нужно сделать генерацию вашей модели. Можно скопировать в файл main.rb код который я приводил выше и тогда у вас сгенерируется мой шкафчик.
Каждая функция возвращает объект Shasoft::Object3D::Object3D который содержит методы для перемещения объекта и его поворота
# Повернем объект на 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)
# Создать 3D объект выдавливания
# pts - список точек в координатной плоскости x,y
# weght - толщина(высота)
Shasoft::Object3D::create_pushpull(pts,weght)
# Создать плоскую поверхность с заданной толщиной
# lX - размер по X
# lY - размер по Y
# weght - толщина
Shasoft::Object3D::create_plane(lX,lY,weght)
# Получить текущую толщину
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 файл со следующими колонками
# Записать в файл команды для 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 мм
Единственный минус - в это можно втянуться. После рабочего стола я уже собрал: кухню, несколько клеток (для одной и той же птицы она на фото), полки (навесные и напольные), тумбы и столы. В общем "захламил" в квартире все неиспользуемые места.