Введение
Приложение, о котором пойдёт речь, применимо в архитектурно-строительной области. С развитием информационных технологий, технологий строительства и производства, а также экономической составляющей, появилась необходимость в более эффективном и комплексном подходах в управлении инвестиционно-строительными проектами, что поспособствовало появлению и формированию ТИМ BIM-технологии.
BIM (англ. Building Information Model или Информационное моделирование строительных объектов) — это объектно-ориентированная модель строительного объекта, как правило, в трёхмерном представлении, элементы которой содержат данные геометрических, физических и функциональных характеристик будущего здания или сооружения.
BIM-технология — организованный процесс, в результате которого формируется BIM-модель, отвечающая задачам и потребностям конкретной стадии жизненного цикла здания или сооружения.
Основным популяризатором и разработчиком программ в области BIM, принято считать компанию Autodesk с их приложениями для AEC (Architecture, Engineering, and Construction) индустрии — Revit, Navisworks, ACC (Autodesk Construction Cloud, ex-BIM360) и др., но в последнее время, активно набирает обороты недовольство пользователей продуктов Autodesk, аргументируя это стагнацией в части разработки нового полезного функционала и недоработки существующего, при этом явным повышением цен на программное обеспечение. Ещё одной проблемой, является замкнутая экосистема Autodesk и их закрытый формат данных (Closed BIM), работая с которым, ты ограничен в действиях и вынужден оставаться в контуре Autodesk. На примере Revit и Autodesk Platform Services, ex-Forge.
По мере развития BIM-технологии и нежеланием быть зависимым от больших корпораций, свою популярность приобрела концепция OpenBIM и сопутствующий ей IFC формат.
Open BIM — подход к объединению проектов зданий и сооружений в согласованную модель. Методология, позволяющая участникам проектирования коммуницировать, невзирая на используемое программное обеспечение.
IFC (Industry Foundation Classes) — открытый стандарт для формата представления данных BIM. Формат файлов разработан buildingSMART (International Alliance for Interoperability, IAI) для упрощения взаимодействия в строительной сфере и приведению к общему знаменателю.
С тенденцией перехода сервисов в облачные решения, начали появляться open-source библиотеки или бесплатные программы по работе с BIM-моделями в web, такие, как xeokit, IFC++, IfcOpenShell и др., а соответственно и BIM-стартапы, преследующие цели OpenBIM или закрывающие конкретные задачи. Одну из таких библиотек мы и рассмотрим, развернув на её основе простое BIM-решение для просмотра модели IFC формата.
Библиотека IFC.js
IFC.js — это библиотека JavaScript для работы с моделями IFC в браузере. Она полностью бесплатная и распространяется по свободной лицензии MIT.
Идейным создателем и одним из разработчиков библиотеки IFC.js, является Antonio González Viegas — BIM software developer. И в качестве предпосылки для создания этого open-source решения и его описания, приведу вольный перевод с его слов:
Сектор AEC традиционно был рынком нескольких богатых ресурсами игроков. Крупные компании годами создавали свои собственные продукты: миллионы строк кода, решающие проблемы и в конечном итоге составляют приложения для реализации BIM и которые мы знаем из повседневной жизни.
Проблема в этой ситуации заключается в том, что новым разработчикам и компаниям очень трудно предлагать свои идеи и конкурировать на равных условиях на этом рынке. И получается, что доступ к "высшей лиге" имеют те, кто может себе это позволить.
Это не относится к таким секторам, как видеоигры, где существует множество инструментов и технологий (видеоигровых движков), которые позволяют любому создать продукт высокого уровня с минимальными затратами времени и ресурсов. Было бы здорово иметь то же самое в секторе AEC?
Вот почему мы запустили IFC.js. Вместо того чтобы создавать решение для реализации технологии BIM и продавать его как продукт, мы делаем его свободно доступным, чтобы каждый мог создавать свои собственные BIM-продукты высокого уровня. Таким образом, мы все можем конкурировать на рынке программного обеспечения с одним и тем же инструментом, где каждый может предложить свои идеи по улучшению.
IFC.js — молодой проект, который развивается и растет с каждым днем. Наша цель — позволить каждому разрабатывать программное обеспечение BIM с такой же легкостью, с какой разрабатываются видеоигры. IFC.js бесплатен, у него нет владельца, и любой может использовать его или участвовать в проекте.
Как вы уже возможно поняли, преследуется концепция Open BIM, противопоставляя решение тяжеловесным и закрытым проприетарным программам. IFC.js даёт возможность BIM-специалистам или разработчикам из других сфер создавать свои собственные BIM-решения, решающие их бизнес-задачи внутри компаний или же создавать свои коммерческие BIM-стартапы. В этом плане, лицензия IFC.js даёт полную свободу действий. Библиотека предназначена для всех, кто хочет разрабатывать BIM-приложения, будь то разработчики, создающие сервисы для строительной отрасли, так и архитекторы совместно с другими специалистами.
Структура IFC.js
В связи с тем, что IFC.js большая, мульти-язычная библиотека (C++, TypeScript JavaScript и т.д.) и держать её в одном репозитории было бы сложно и громоздко, её разбили на три основные части:
web-ifc — ядро библиотеки: IFC парсер, написанный с нуля на языке C и скомпилирован через Emscripten в WebAssembly. Этот репозиторий инкапсулирует сложность чтения файлов IFC и загрузки их данных в память. Demo
web-ifc-three — эта библиотека адаптирует web-ifc к Three.js, создавая оптимизированную 3D-сцену, в которой пользователи могут напрямую взаимодействовать с IFC. Эта библиотека является официальным IFC загрузчиком в Three.js. Благодаря этому, приложения BIM можно создавать с помощью Three.js всего за пару строк кода. Demo
web-ifc-viewer — это решение для просмотра IFC в браузере со множеством примеров того, что можно сделать с помощью IFC.js. Навигация по сценам, изменение материалов, выбор элементов по нажатию на них, планы разрезов и т. д. В этом репозитории есть пример всех этих функций, поэтому его можно повторно использовать в открытых приложениях BIM из коробки. Demo
Каждая последующая часть зависит от предыдущей, в такой последовательности: web-ifc — web-ifc-three — web-ifc-viewer
Обучение
На данный момент, проводятся два курса IFC.js crash course и Advanced BIM frontend course по работе с их библиотекой в web. Курс IFC.js crach cource, как заявляет создатель, подходит для начального уровня и обучение ведётся с нуля, но под конец, как по мне, без хорошей базы в программировании будет тяжеловато.
Программа поддержки
В целях ускорения разработки проекта, а так же его улучшения — команда IFC.js реализовала программу поддержки, где даёт возможность заработать сообществу, принося свой вклад в проект. Если вкратце, то формируются карточки с разного рода заданиями, например исправление бага или реализации инструментов, таких как проверка на коллизии, формирование планов, разрезов и т.д.
Разработка BIM-сервиса для просмотра IFC формата
Создание BIM-приложения с IFC.js довольно простое, как указано на сайте с документацией. Последующий урок взят оттуда в качестве вольного перевода, с некоторыми сокращениями, отклонениями и комментариями. Развёрнутое демо-приложение находиться тут. Для выполнения следующих шагов необходим Node.js и любая IDE, но в статье я буду использовать VS Code в качестве среды разработки и расширение Live Preview в части локального сервера, не разворачивая Node.js. И если у вас нет файлов IFC, вы можете их скачать отсюда.
Для работы с IFC.js требуются базовые знания веб-разработки (HTML, CSS, JavaScript) и библиотеки Three.js
Установка библиотек
Вначале, создаём пустую папку и запускаем менеджер пакетов npm с помощью команды npm init. Будет создан файл package.json, содержащий некоторые данные, такие как имя проекта, версия, описание, команды и зависимости.
Все вышеперечисленные свойства можно сразу заполнить, либо прожав Enter и использовать значения по умолчанию.
Кроме того, при помощи npm необходимо установить следующие зависимости: модуль web-ifc-three (с ним ставится и Three.js), входящий в IFC.js и rollup.js в качестве сборщика проекта для JavaScript.
//Install IFC.js
npm i web-ifc-three
// Install a bundler: we will use rollup.js for this guide
npm i rollup --save-dev
npm i @rollup/plugin-node-resolve --save-dev
Сразу можно проверить наличие в package.json файле свойство "type": "module" и добавить его, если оно отсутствует.
Следующим шагом, будет создание HTML файла с именемindex.html в качестве основного документа приложения. HTML будет иметь:
- canvas элемент, используемый для рендеринга сцены Three.js;
- input элемент, который будет открывать файлы IFC с нашего компьютера в приложении.
- Тэг script, ссылающийся на файл bundle.js, представляющий собой сборку приложения, которую мы создадим дальше с помощью rollup.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="styles.css"/>
<title>Document</title>
</head>
<body>
<input type="file" name="load" id="file-input"/>
<canvas id="three-canvas"></canvas>
<script src="bundle.js"></script>
</body>
</html>
Для удобства импорта нашей будущей IFC-модели для тэга <input> можно добавить атрибут accept=".ifc" и видеть только файлы с расширением .ifc в директории, откуда загружаем модель.
Добавление стилей
Создаём CSS файл styles.css, где произведём сброс стилей, сделаем наш canvas на весь экран и зададим свойства нашей будущей кнопки для загрузки IFC-модели:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
overflow: hidden;
}
#three-canvas {
position: fixed;
top: 0;
left: 0;
outline: none;
}
#file-input {
z-index: 1;
position: absolute;
}
Сборка проекта
Далее, создадим файл конфигурации с именем rollup.config.js, который будет включать в себя ссылки на ранее установленные дополнения.
Rollup — популярная библиотека пакетов. К примеру, это сборщик, используемый Three.js. Чтобы узнать больше, ознакомьтесь с документацией.
import resolve from "@rollup/plugin-node-resolve";
export default {
input: "app.js",
output: [
{
format: "esm",
file: "bundle.js",
},
],
plugins: [resolve()],
};
Также, в файле package.json изменим команды в области scripts для удобного управления объединением/сборки проекта. В каждой команде необходимо указать относительный путь к файлу конфигурации rollup.
- npm run build объединит проект и создаст файл с именем bundle.js в корневом каталоге проекта.
- npm run watch активирует режим просмотра, автоматически обновляя этот файл каждый раз, когда мы вносим и сохраняем изменения в код.
{
"name": "example",
"version": "1.0.0",
"description": "-",
"main": "app.js",
"scripts": {
"build": "rollup -c ./rollup.config.js",
"watch": "rollup -w -c ./rollup.config.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@rollup/plugin-node-resolve": "^11.2.1",
"rollup": "^2.45.2"
},
"dependencies": {
"three": "^0.128.0",
"web-ifc-three": "0.0.102"
}
}
WebAssembly
Далее, необходимо скопировать файл web-ifc.wasm в директорию проекта. Найти его можно по пути node_modules\web-ifc и скопировать куда угодно, впоследствии указав на него путь, но в примере он будет размещен в корне проекта.
Этот файл необходим, так как содержит скомпилированную C++ логику модуля web-ifc, являющемся ядром парсинга для чтения и записи IFC файлов.
Создание и настройка 3D сцены
Наконец, мы создадим JavaScript файл для нашего приложения. Разместить его можно где-угодно и задать произвольно имя, главное отразить это в файле rollup.config.js. В примере это будет app.js в корне проекта.
Базовая 3D-сцена Three.js
import { AmbientLight, AxesHelper, DirectionalLight, GridHelper, PerspectiveCamera, Scene, WebGLRenderer } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//Creates the Three.js scene
const scene = new Scene();
//Object to store the size of the viewport
const size = {
width: window.innerWidth,
height: window.innerHeight,
};
//Creates the camera (point of view of the user)
const aspect = size.width / size.height;
const camera = new PerspectiveCamera(75, aspect);
camera.position.z = 15;
camera.position.y = 13;
camera.position.x = 8;
//Creates the lights of the scene
const lightColor = 0xffffff;
const ambientLight = new AmbientLight(lightColor, 0.5);
scene.add(ambientLight);
const directionalLight = new DirectionalLight(lightColor, 1);
directionalLight.position.set(0, 10, 0);
directionalLight.target.position.set(-5, 0, 0);
scene.add(directionalLight);
scene.add(directionalLight.target);
//Sets up the renderer, fetching the canvas of the HTML
const threeCanvas = document.getElementById("three-canvas");
const renderer = new WebGLRenderer({
canvas: threeCanvas,
alpha: true,
});
renderer.setSize(size.width, size.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
//Creates grids and axes in the scene
const grid = new GridHelper(50, 30);
scene.add(grid);
const axes = new AxesHelper();
axes.material.depthTest = false;
axes.renderOrder = 1;
scene.add(axes);
//Creates the orbit controls (to navigate the scene)
const controls = new OrbitControls(camera, threeCanvas);
controls.enableDamping = true;
controls.target.set(-2, 0, 0);
//Animation loop
const animate = () => {
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
animate();
//Adjust the viewport to the size of the browser
window.addEventListener("resize", () => {
size.width = window.innerWidth;
size.height = window.innerHeight;
camera.aspect = size.width / size.height;
camera.updateProjectionMatrix();
renderer.setSize(size.width, size.height);
});
Загрузка IFC файлов
В завершении мы будем использовать IFC.js для загрузки IFC файлов. Создадим экземпляр загрузчика и событие, когда пользователь загружает IFC файл с помощью элемента ввода <input>
import { IFCLoader } from "web-ifc-three/IFCLoader";
// Sets up the IFC loading
const ifcLoader = new IFCLoader();
const input = document.getElementById("file-input");
input.addEventListener(
"change",
(changed) => {
const file = changed.target.files[0];
var ifcURL = URL.createObjectURL(file);
ifcLoader.load(ifcURL, (ifcModel) => scene.add(ifcModel));
},
false
);
Готовый app.js файл будет так:
import {
AmbientLight,
AxesHelper,
DirectionalLight,
GridHelper,
PerspectiveCamera,
Scene,
WebGLRenderer,
} from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { IFCLoader } from "web-ifc-three/IFCLoader";
//Creates the Three.js scene
const scene = new Scene();
//Object to store the size of the viewport
const size = {
width: window.innerWidth,
height: window.innerHeight,
};
//Creates the camera (point of view of the user)
const aspect = size.width / size.height;
const camera = new PerspectiveCamera(75, aspect);
camera.position.z = 15;
camera.position.y = 13;
camera.position.x = 8;
//Creates the lights of the scene
const lightColor = 0xffffff;
const ambientLight = new AmbientLight(lightColor, 0.5);
scene.add(ambientLight);
const directionalLight = new DirectionalLight(lightColor, 1);
directionalLight.position.set(0, 10, 0);
directionalLight.target.position.set(-5, 0, 0);
scene.add(directionalLight);
scene.add(directionalLight.target);
//Sets up the renderer, fetching the canvas of the HTML
const threeCanvas = document.getElementById("three-canvas");
const renderer = new WebGLRenderer({
canvas: threeCanvas,
alpha: true,
});
renderer.setSize(size.width, size.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
//Creates grids and axes in the scene
const grid = new GridHelper(50, 30);
scene.add(grid);
const axes = new AxesHelper();
axes.material.depthTest = false;
axes.renderOrder = 1;
scene.add(axes);
//Creates the orbit controls (to navigate the scene)
const controls = new OrbitControls(camera, threeCanvas);
controls.enableDamping = true;
controls.target.set(-2, 0, 0);
//Animation loop
const animate = () => {
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
animate();
//Adjust the viewport to the size of the browser
window.addEventListener("resize", () => {
size.width = window.innerWidth;
size.height = window.innerHeight;
camera.aspect = size.width / size.height;
camera.updateProjectionMatrix();
renderer.setSize(size.width, size.height);
});
// Sets up the IFC loading
const ifcLoader = new IFCLoader();
const input = document.getElementById("file-input");
input.addEventListener(
"change",
(changed) => {
const file = changed.target.files[0];
var ifcURL = URL.createObjectURL(file);
ifcLoader.load(ifcURL, (ifcModel) => scene.add(ifcModel));
},
false
);tURL(file);
ifcLoader.load(ifcURL, (ifcModel) => scene.add(ifcModel));
},
false
);
И если всё настроенное корректно, то после вызова команды npm run build мы можем собрать и запустить наше приложение, запустив расширение Live Preview, которое мы устанавливали ранее, с адресом http://127.0.0.1:3000 в браузере или открыть index.html в папке проекта.
Финальный результат. Можете загрузить свою IFC-модель
В качестве примера — простая модель с пометками и атрибутивной информацией элементов.
Заключение
Библиотека IFC.js действительно молодой проект и развивается довольно быстро, но уже сейчас даёт возможность реализовывать полноценные BIM‑приложения. В связи с последними тенденциями и активным интересом в сторону подхода Open BIM — IFC.js прокладывает отличный путь для развития сервисов в строительной индустрии. Вокруг проекта уже сформировалось значительное комьюнити к которому можно присоединиться в Discord.
P.S.
Я старался максимально сократить и упростить вводную часть, в том числе с определениями и понятиями, на сколько смог. Возможно, некоторые моменты могут быть не до конца понятными или раскрытыми. В свою очередь, я старался сделать акцент больше на технической части, но при этом добавив контекста для читателей не из архитектурно‑строительной сферы.