35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # How to build your own Linked Building Data Frontend tool using IFC.js and Comunica
2 | 🚀 Build a web-based linked building data frontend in only 20 steps!
3 |
4 | :computer: [This is a live demo of what we're going to build!](https://alexdonkers.github.io/Frontends-and-LBD/)
5 |
6 | **Alex Donkers**
7 | a.j.a.donkers@tue.nl
8 |
9 | **Jeroen Werbrouck**
10 | jeroen.werbrouck@ugent.be
11 |
12 | The Frontends-and-LBD Tutorial by Alex Donkers is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
13 |
14 | ## Introduction
15 |
16 | This handout teaches you how to build a simple IFC.js viewer with SPARQL query capabilities. It is created for the Frontends and LBD lecture in [SSoLDAC2023](https://linkedbuildingdata.net/ldac2023/summerschool/). The goal of this document is to increase the knowledge of frontend creation amongst Linked Building Data enthusiasts and to give researchers a toolset to kick-off their frontend development projects. Special thanks to the creators of IFC.js and Comunica for enabling these developments. Please share your results and post your questions in this GitHub repository.
17 |
18 | The **LBDviz** tool was created by following a similar methodology. The methodology and various practical frontend tools are presented in the following work:
19 |
20 | [:page_facing_up: Donkers, A., Yang, D., de Vries, B., Baken, N. (2023). A Visual Support Tool for Decision-Making over Federated Building Information. In: Turrin, M., Andriotis, C., Rafiee, A. (eds) Computer-Aided Architectural Design. INTERCONNECTIONS: Co-computing Beyond Boundaries. CAAD Futures 2023. Communications in Computer and Information Science, vol 1819. Springer, Cham. https://doi.org/10.1007/978-3-031-37189-9_32](https://link.springer.com/chapter/10.1007/978-3-031-37189-9_32)
21 |
22 | More information on interactions with federated AEC models in frontends can be found in a soon to be published paper:
23 |
24 | :page_facing_up: _Werbrouck, J., Verborgh, R., Pauwels, P., Beetz, J. & Mannens E. (unpublished). Facilitating Interactions with AEC Multi Models through Federated Micro Frontend Configurations_
25 |
26 | 
27 |
28 | **Resources you can use for this tutorial: OpenFlat**
29 | [TTL](https://raw.githubusercontent.com/AlexDonkers/ofo/main/SWJ_Resources/OpenFlat/OpenFlat_Donkers.ttl) +
30 | [IFC](https://github.com/AlexDonkers/ofo/blob/main/SWJ_Resources/OpenFlat/OpenFlat_Donkers.ifc)
31 |
32 | ## Tutorial
33 |
34 | ### Step 1
35 | Install Visual Studio Code
36 | In Visual Studio Code, go to Extensions and install **Live Server**.
37 |
38 | 
39 |
40 | ### Step 2
41 | Create a new folder for your project and open it in Visual Studio Code.
42 |
43 | `File > Open Folder`
44 |
45 | ### Step 3
46 | Open a new terminal in Visual Studio Code.
47 |
48 | `Terminal > New Terminal`
49 |
50 | ### Step 4
51 | Run **npm init –yes** in your terminal.
52 |
53 | `PS C:\Users\...\MyNewProjectFolder> npm init --yes`
54 |
55 | A new package.json file will be created.
56 |
57 | ### Step 5
58 | Create a new file named webpack.config.js, in the MyNewFrontendTool folder. You can do this in the left top of Visual Studio Code.
59 |
60 | 
61 |
62 | Paste the code below into this file.
63 | ```javascript
64 | const path = require('path');
65 | const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
66 | module.exports = {
67 | entry: './app.js',
68 | output: {
69 | filename: 'bundle.js',
70 | path: path.resolve(__dirname, './'),
71 | },
72 | plugins: [
73 | new NodePolyfillPlugin()
74 | ],
75 | module: {
76 | rules: [
77 | {
78 | test: /\.css$/i,
79 | use: ['style-loader', 'css-loader'], //always put style-loader before css-loader
80 | },
81 | {
82 | test: /\.m?js/,
83 | resolve: {
84 | fullySpecified: false,
85 | },
86 | },
87 | ],
88 | },
89 | };
90 | ```
91 | Make sure to also install webpack in the terminal:
92 |
93 | `PS C:\Users\...\MyNewProjectFolder> npm i webpack`
94 |
95 | `PS C:\Users\...\MyNewProjectFolder> npm i webpack-cli`
96 |
97 | `PS C:\Users\...\MyNewProjectFolder> npm i node-polyfill-webpack-plugin`
98 |
99 | ### Step 6
100 | Create a new file called **index.html**.
101 |
102 | 
103 |
104 | Paste the following code into the index.html file.
105 |
106 | ```html
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | MyNewFrontendTool
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | ```
124 |
125 | The `` is where the 3D viewer will be.
126 |
127 | ### Step 7
128 | Create a new file called **styles.css**. This is where you’ll define the layout of your app, such as fonts, colors, and sizes.
129 |
130 | 
131 |
132 | Paste the following code in the styles.css file. Everything within #viewer-container will be added to objects with id=”viewer-container”, such as the one in the index.html file. If you find an object starting with a .asdf instead of a #asdf, everything within this object will be added to objects with class=”asdf”.
133 | ```css
134 | *{
135 | margin: 0;
136 | padding: 0;
137 | box-sizing: border-box;
138 | }
139 | html, body {
140 | overflow: hidden;
141 | font-family: Verdana, sans-serif;
142 | }
143 | #viewer-container {
144 | position: fixed;
145 | top: 0;
146 | left: 0;
147 | outline: none;
148 | width: 100%;
149 | height: 100%;
150 | z-index: -1;
151 | }
152 | ```
153 |
154 | ### Step 8
155 | Create a new file called app.js. Your folder should now look like this:
156 |
157 | 
158 |
159 | Paste the following code in app.js:
160 | ```javascript
161 | import { Color } from 'three';
162 | import { IfcViewerAPI } from 'web-ifc-viewer';
163 |
164 | ///////////////////////////////////////////////////////////////////////
165 | // CREATE THE VIEWER
166 |
167 | const container = document.getElementById('viewer-container');
168 | const viewerColor = new Color('#E2F0D9');
169 | const viewer = new IfcViewerAPI({ container, backgroundColor: viewerColor });
170 | viewer.grid.setGrid();
171 | viewer.axes.setAxes();
172 | ```
173 |
174 | Make sure to also install three and the web-ifc-viewer in the terminal:
175 |
176 | `PS C:\Users\...\MyNewProjectFolder> npm i three@0.135`
177 |
178 | `PS C:\Users\...\MyNewProjectFolder> npm i three@0.135 web-ifc-viewer`
179 |
180 | ### Step 9
181 | In the package.json file, change the command in scripts to “build”: “webpack”.
182 |
183 | Old:
184 | ```json
185 | "scripts": {
186 | "test": "echo \"Error: no test specified\" && exit 1"
187 | },
188 | ```
189 | New:
190 | ```json
191 | "scripts": {
192 | "build": "webpack"
193 | },
194 | ```
195 |
196 | ### Step 10
197 | Let’s have a look at our current app. In the Terminal in Visual Studio Code, run the following command. This will create the **bundle.js** file.
198 |
199 | `PS C:\Users\...\MyNewProjectFolder> npm run build`
200 |
201 | In the right bottom of Visual Studio Code, click **Go Live**. You should see something like this:
202 |
203 | 
204 |
205 | :partying_face: Well done, you created your basic viewer component.
206 |
207 | ### Step 11
208 | Let’s add a button to load IFC files in our viewer. First, go to index.html and create a button. The body of your index.html should look like this:
209 | ```html
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 | ```
219 | In styles.css, add the following at the end of the file. This is where you can later design the button, e.g., change its shape and color.
220 | ```css
221 | #load-ifc-button {
222 | position: absolute;
223 | background-color: #ff0072;
224 | float: left;
225 | border: none;
226 | outline: none;
227 | cursor: pointer;
228 | padding: 6px 10px;
229 | font-size: 12px;
230 | color: white;
231 | }
232 | ```
233 | You should now see a pink button in your application.
234 |
235 | ### Step 12
236 | We now add the file input functionality to app.js. Paste this at the end of app.js.
237 | ```javascript
238 | ///////////////////////////////////////////////////////////////////////
239 | // CREATE THE LOAD IFC BUTTON
240 |
241 | const inputButton = document.getElementById("load-ifc-button");
242 | inputButton.addEventListener("change", async () => {
243 | const ifcFile = inputButton.files[0];
244 | const ifcURL = URL.createObjectURL(ifcFile);
245 | const model = await viewer.IFC.loadIfcUrl(ifcURL);
246 | // Create shadows
247 | await viewer.shadowDropper.renderShadow(model.modelID);
248 | viewer.context.renderer.postProduction.active = true;
249 | }
250 | );
251 | ```
252 | The app.js file should look like this:
253 | ```javascript
254 | import { Color } from 'three';
255 | import { IfcViewerAPI } from 'web-ifc-viewer';
256 |
257 | ///////////////////////////////////////////////////////////////////////
258 | // CREATE THE VIEWER
259 |
260 | const container = document.getElementById('viewer-container');
261 | const viewerColor = new Color('#E2F0D9');
262 | const viewer = new IfcViewerAPI({ container, backgroundColor: viewerColor });
263 | viewer.grid.setGrid();
264 | viewer.axes.setAxes();
265 |
266 | ///////////////////////////////////////////////////////////////////////
267 | // CREATE THE LOAD IFC BUTTON
268 |
269 | const inputButton = document.getElementById("load-ifc-button");
270 | inputButton.addEventListener("change", async () => {
271 | const ifcFile = inputButton.files[0];
272 | const ifcURL = URL.createObjectURL(ifcFile);
273 | const model = await viewer.IFC.loadIfcUrl(ifcURL);
274 | // Create shadows
275 | await viewer.shadowDropper.renderShadow(model.modelID);
276 | viewer.context.renderer.postProduction.active = true;
277 | }
278 | );
279 | ```
280 |
281 | ### Step 13
282 | In Visual Studio Code, go to the node_modules folder. Then open the web-ifc folder and copy the web-ifc-mt.wasm and web-ifc.wasm files. Paste them in your main project folder. This folder now looks like this:
283 |
284 | 
285 |
286 | ### Step 14
287 | In the Terminal in Visual Studio Code, run the following command. This will update the bundle.js file.
288 |
289 | `PS C:\Users\...\MyNewProjectFolder> npm run build`
290 |
291 | Go to your browser to check out the app. You can click on the pink button and select an [IFC](https://github.com/AlexDonkers/ofo/blob/main/SWJ_Resources/OpenFlat/OpenFlat_Donkers.ifc) file.
292 |
293 | 🥳 Well done! You have just created your first web-based BIM viewer.
294 |
295 | 
296 |
297 | ### Step 15
298 | Let’s make some interactive elements. Add the following to the end of app.js.
299 | ```javascript
300 | ///////////////////////////////////////////////////////////////////////
301 | // CREATE INTERACTION WITH THE MODEL
302 |
303 | window.onmousemove = async () => await viewer.IFC.selector.prePickIfcItem();
304 |
305 | window.onclick = async () => await viewer.IFC.selector.pickIfcItem();
306 |
307 | viewer.clipper.active=true;
308 |
309 | window.onkeydown = (event) => {
310 | if(event.code === 'KeyP') {
311 | viewer.clipper.createPlane();
312 | }
313 | else if(event.code === 'KeyO') {
314 | viewer.clipper.deletePlane();
315 | }
316 | };
317 | ```
318 | Run `npm run build` again in the Terminal. You can now go to the tool again and import your IFC file. You can now hover over elements and click on them. You can also create planes to crop your model (using P) and delete those planes (using O).
319 |
320 | 
321 |
322 | ### Step 16
323 | We’re now going to bring in linked data!
324 | First, let’s create a text area so that we can create SPARQL queries.
325 | Paste the following at the end of styles.css for basic layout of the query box:
326 | ```css
327 | #query-box {
328 | background-color: green;
329 | border: none;
330 | width: 500px;
331 | outline: none;
332 | padding: 6px 10px;
333 | font-size: 12px;
334 | color: white;
335 | position: relative;
336 | z-index: 1;
337 | margin-top: 40px;
338 | }
339 | ```
340 | In index.html, paste the following code right after the load-ifc-button div:
341 | ```html
342 |
343 |
344 |
352 |
353 |
354 |
355 | ```
356 | As you can see, the text box is pre-filled with a query.
357 |
358 | ### Step 17
359 | Let’s create a results box, so that we can plot the results of our query. First, in styles.css:
360 | ```css
361 | #results-box {
362 | background-color: green;
363 | border: none;
364 | width: 500px;
365 | outline: none;
366 | padding: 6px 10px;
367 | font-size: 12px;
368 | color: white;
369 | position: relative;
370 | z-index: 1;
371 | margin-top: 10px;
372 | }
373 | ```
374 | And the following in index.html, right after the query box:
375 | ```html
376 |
377 |
378 |
379 |
380 | ```
381 |
382 | This should be your current index.html:
383 | ```html
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 | MyNewFrontendTool
393 |
394 |
395 |
396 |
397 |
398 |
399 |