├── web-ifc.wasm ├── web-ifc-mt.wasm ├── HandoutImages ├── 1.png ├── 2.PNG ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png ├── 9.png ├── 10.png ├── 11.png └── 12.png ├── package.json ├── styles.css ├── index.html └── README.md /web-ifc.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/web-ifc.wasm -------------------------------------------------------------------------------- /web-ifc-mt.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/web-ifc-mt.wasm -------------------------------------------------------------------------------- /HandoutImages/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/1.png -------------------------------------------------------------------------------- /HandoutImages/2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/2.PNG -------------------------------------------------------------------------------- /HandoutImages/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/3.png -------------------------------------------------------------------------------- /HandoutImages/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/4.png -------------------------------------------------------------------------------- /HandoutImages/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/5.png -------------------------------------------------------------------------------- /HandoutImages/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/6.png -------------------------------------------------------------------------------- /HandoutImages/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/7.png -------------------------------------------------------------------------------- /HandoutImages/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/8.png -------------------------------------------------------------------------------- /HandoutImages/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/9.png -------------------------------------------------------------------------------- /HandoutImages/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/10.png -------------------------------------------------------------------------------- /HandoutImages/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/11.png -------------------------------------------------------------------------------- /HandoutImages/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDonkers/Frontends-and-LBD/HEAD/HandoutImages/12.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lbd_and_frontends", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@comunica/query-sparql": "^2.7.1", 14 | "node-polyfill-webpack-plugin": "^2.0.1", 15 | "three": "^0.135.0", 16 | "web-ifc-viewer": "^1.0.218", 17 | "webpack": "^5.86.0", 18 | "webpack-cli": "^5.1.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | html, body { 8 | overflow: hidden; 9 | font-family: Verdana, sans-serif; 10 | } 11 | 12 | #viewer-container { 13 | position: fixed; 14 | top: 0; 15 | left: 0; 16 | outline: none; 17 | width: 100%; 18 | height: 100%; 19 | } 20 | 21 | #load-ifc-button { 22 | position: absolute; 23 | background-color: #ff0072; 24 | float: left; 25 | border: none; 26 | width: 500px; 27 | outline: none; 28 | cursor: pointer; 29 | padding: 6px 10px; 30 | font-size: 12px; 31 | color: white; 32 | z-index: 1; 33 | } 34 | 35 | #query-box { 36 | background-color: green; 37 | border: none; 38 | width: 500px; 39 | outline: none; 40 | padding: 6px 10px; 41 | font-size: 12px; 42 | color: white; 43 | position: relative; 44 | z-index: 1; 45 | margin-top: 40px; 46 | } 47 | 48 | #results-box { 49 | background-color: green; 50 | border: none; 51 | width: 500px; 52 | outline: none; 53 | padding: 6px 10px; 54 | font-size: 12px; 55 | color: white; 56 | position: relative; 57 | z-index: 1; 58 | margin-top: 10px; 59 | } 60 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | MyNewFrontendTool 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
32 |

Selected guid:

33 |

34 |
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 | Creative Commons License
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 | ![Image1](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/1.png) 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 | ![Image2](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/2.PNG) 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 | ![Image3](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/3.png) 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 | ![Image4](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/4.png) 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 | ![Image5](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/5.png) 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 | ![Image6](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/6.png) 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 | ![Image7](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/7.png) 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 | ![Image8](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/8.png) 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 | ![Image9](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/9.png) 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 | ![Image10](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/10.png) 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 |
400 | 408 | 409 | 410 |
411 | 412 | 413 |
414 |

415 |
416 | 417 | 418 |
419 | 420 | 421 | 422 | ``` 423 | 424 | ### Step 18 425 | We’re finally adding Query capabilities. First, install comunica: 426 | 427 | `PS C:\Users\...\MyNewProjectFolder> npm i @comunica/query-sparql` 428 | 429 | Add the following code to the end of app.js. 430 | ```javascript 431 | /////////////////////////////////////////////////////////////////////// 432 | // COMUNICA 433 | 434 | import { QueryEngine } from '@comunica/query-sparql' 435 | 436 | export async function queryComunica() { 437 | const myEngine = new QueryEngine(); 438 | const query = document.getElementById("SPARQL-input").value 439 | const graphs = document.getElementById("GRAPH-input").value.split(',') 440 | const bindingsStream = await myEngine.queryBindings(query, { 441 | sources: graphs, 442 | }); 443 | const bindings = await bindingsStream.toArray(); 444 | console.log("Results"+bindings) 445 | 446 | // Plot in results box 447 | 448 | } 449 | window.queryComunica = queryComunica; 450 | ``` 451 | 452 | Now run `npm run build` again in the terminal. You can now run SPARQL queries in your frontend tool. First, paste a link to an RDF file in the GRAPH-input box. Here’s an example link: 453 | https://raw.githubusercontent.com/AlexDonkers/ofo/main/SWJ_Resources/OpenFlat/OpenFlat_Donkers.ttl 454 | 455 | Then, click on **Run query!** You should now see results of the query in the console. 456 | 457 | ![Image11](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/11.png) 458 | 459 | ### Step 19 460 | Add code to plot these results in the results box. We do this in app.js, right after the //Plot in results box line. 461 | ```javascript 462 | // Plot in results box 463 | //clear result box 464 | document.getElementById("results-box-content").innerHTML = ""; 465 | //start table component 466 | let tableContent = "" 467 | 468 | tableContent +="" 469 | const headers = bindings[0].entries._root.entries 470 | for (var y = 0; y" 472 | } 473 | tableContent +="" 474 | 475 | for (var i = 0; i" 486 | } 487 | if (results[x][1].termType !== "Literal") { 488 | console.log(results[x][0] +": "+ results[x][1].value.split("#", 2)[1]) 489 | tableContent += "" 490 | } 491 | } 492 | tableContent += "" 493 | } 494 | //end 495 | tableContent += "
"+results[x][1].value.split("#", 2)[1]+"
" 496 | 497 | //add table to results box 498 | document.getElementById("results-box-content").innerHTML = tableContent 499 | ``` 500 | After running `npm run build` again, you can now find query results in the results box. 501 | 502 | 503 | 504 | ### Step 20 505 | Finally, we’ll create some interaction between SPARQL and the IFC model. 506 | First, in **index.html**, replace the results box section by the following code: 507 | ```html 508 | 509 |
510 |

Selected guid:

511 |

512 |
513 | ``` 514 | Then, in app.js, replace the window.onclick function in line 33 by the following code. This will fill in the GlobalId of the selected IFC element in the results box. 515 | 516 | ```javascript 517 | window.onclick = async () => { 518 | const result = await viewer.IFC.selector.pickIfcItem(true); 519 | if(!result) return; 520 | const {modelID, id} = result; 521 | const props = await viewer.IFC.getProperties(modelID, id, true, false); 522 | console.log(props.GlobalId.value); 523 | document.getElementById("selected-guid").innerHTML = props.GlobalId.value; 524 | return props.GlobalId 525 | }; 526 | ``` 527 |   528 | Then finally, change the queryComunica function in app.js to the following: 529 | 530 | ```javascript 531 | /////////////////////////////////////////////////////////////////////// 532 | // COMUNICA 533 | 534 | import { QueryEngine } from '@comunica/query-sparql' 535 | 536 | export async function queryComunica() { 537 | const myEngine = new QueryEngine(); 538 | console.log(document.getElementById("selected-guid").innerHTML); 539 | const graphs = document.getElementById("GRAPH-input").value.split(',') 540 | const bindingsStream = await myEngine.queryBindings(`PREFIX bpt: 541 | select * where { 542 | ?element bpt:hasGlobalIdIfcRoot `+JSON.stringify(document.getElementById("selected-guid").innerHTML)+` . 543 | ?element ?p ?o . 544 | } limit 100 `, { 545 | sources: graphs, 546 | }); 547 | ``` 548 | Now run **npm run build**. Use the OpenFlat resources, indicated in the beginning of the file. Insert the [IFC](https://github.com/AlexDonkers/ofo/blob/main/SWJ_Resources/OpenFlat/OpenFlat_Donkers.ifc) file, then insert the link to the [TTL](https://raw.githubusercontent.com/AlexDonkers/ofo/main/SWJ_Resources/OpenFlat/OpenFlat_Donkers.ttl) file in the GRAPH-input box. Click at one of the elements in the viewer and click on **Run query!** (you might need to wait a second or so). Instead of using the SPARQL-input box, Comunica now queries nodes around the node of the clicked element, by inserting the guid of the element into the query! 549 | 550 | ![Image12](https://github.com/AlexDonkers/Frontends-and-LBD/blob/main/HandoutImages/12.png) 551 | 552 | ## Well done! 🥳 553 | I hope you enjoyed this tutorial. For questions, please use the [Issues](https://github.com/AlexDonkers/Frontends-and-LBD/issues) section or reach out: a.j.a.donkers@tue.nl. 554 | Follow me on [LinkedIn](https://www.linkedin.com/in/alexdonkers/) for regular research updates. 555 | 556 | The code is shared under a CC BY-SA 4.0, meaning that I expect you to share your results - because Open Science is the way to go! 557 | 558 | If you used this work, please cite it as: 559 | 560 | [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) 561 | --------------------------------------------------------------------------------