Third and last part of this blog series where I exposed step by step the implementation of a custom "Window Selection" command for the Forge Viewer on top of the public API.
You can find links to the first two parts below if you missed it:
In the second part I was showing how to determine if the bounding box of each component in the model is inside the selection area. Now the last bit of the command is to determine if the boxes that are not inside are completely outside or are being intersected by the selection mesh computed from the rectangular selected area.
In order to do that I went hunting on the web for a geometry-box intersection algorithm and I found it at threejs-geometry-hittest. The logic was implemented specifically for Three.js so luckily I didn't have to change it much. I basically cleaned it up a bit, got rid of some unused variables and rewrote it a bit more ES6 way - see code snippet at the bottom of that article.
This allows to add the "Partial Selection" feature to the command: it lets the user decides if a box that is partially intersected by the selection mesh will end up in the selection set or not. I also added a bit more advanced UI where you can see a treeview of the selected components, you can click each node or the root to select the corresponding component in the viewer or double-click to isolate.
If we would really want to push the selection logic to the maximum, we could iterate the vertices of the intersected box components in order to determine if they are inside or outside the selection volume: there could be cases where the box is being intersected but the vertices are actually all outside of the volume. This would probably add a lot more heaviness to the command for a large model, so I will leave it as a nice to have for the time being.
That's all for now folks, it was quite fun to implement that piece of code and I hope you will find it useful! You can find the current implementation at Viewing.Extension.SelectionWindow, the live demo is still at the same url, and a video of the command in action: