Skip to main content

Creating Storey Plan Views

· 5 min read

The xeokit SDK gives you flexible tools to create a variety of custom browser-based experiences for navigating the building storeys in your IFC building models. Using these tools, you can create a 2D plan view "mini-map" to help you navigate the 3D view, or just use certain functions to isolate storey objects in the 3D view, highlight them, fit them in view, and so on.

Run this example

Introduction

The StoreyViewsPlugin provides a set of simple but flexible methods that lets us visualize building storeys in a variety of ways.

Two methods are for setting up 3D views of storeys:

The other two methods are for creating 2D mini-map images of storeys:

  • createStoreyMap - generates a plan view mini-map image of a givenn storey, and
  • pickStoreyMap - picks the 3D Entity at the given 2D pixel coordinates within a plan view image.

Usage

Let's start by creating a Viewer with a StoreyViewsPlugin and an XKTLoaderPlugin. Then we'll load a BIM building model from an .xkt file.

import {Viewer,XKTLoaderPlugin,StoreyViewsPlugin} from "https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/xeokit-sdk.es.min.js";

// Create a Viewer, arrange the camera

const viewer = new Viewer({
canvasId: "myCanvas",
transparent: true
});

viewer.camera.eye = [-2.56, 8.38, 8.27];
viewer.camera.look = [13.44, 3.31, -14.83];
viewer.camera.up = [0.10, 0.98, -0.14];

// Add an XKTLoaderPlugin

const xktLoader = new XKTLoaderPlugin(viewer);

// Add a StoreyViewsPlugin

const storeyViewsPlugin = new StoreyViewsPlugin(viewer);

// Load a BIM model from .xkt format

const model = xktLoader.load({
id: "myModel",
src: "./models/xkt/schependomlaan/schependomlaan.xkt",
edges: true
});

Finding Storeys

Having loaded our model, we can now get information on a given storey:

const storey = storeyViewsPlugin.storeys["2SWZMQPyD9pfT9q87pgXa1"]; // ID of the IfcBuildingStorey

const modelId = storey.modelId; // "myModel"
const storeyId = storey.storeyId; // "2SWZMQPyD9pfT9q87pgXa1"
const aabb = storey.aabb; // Axis-aligned 3D World-space boundary of the IfcBuildingStorey

We can also get a "storeys" event every time the set of storeys changes, ie. every time a storey is created or destroyed. This happens whenever we load or unload a model that has IfcBuildingStorey elements.

storeyViewsPlugin.on("storeys", ()=> {
const storey = storeyViewsPlugin.storeys["2SWZMQPyD9pfT9q87pgXa1"];
//...
});

Isolating a Storey

Let's show the Entitys within our storey:

storeyViewsPlugin.showStoreyObjects("2SWZMQPyD9pfT9q87pgXa1");

Showing only the Entitys in a storey, hiding all others:

storeyViewsPlugin.showStoreyObjects("2SWZMQPyD9pfT9q87pgXa1", {
hideOthers: true
});

Showing only the storey Entitys, applying custom appearances configured on StoreyViewsPlugin#objectStates:

storeyViewsPlugin.showStoreyObjects("2SWZMQPyD9pfT9q87pgXa1", {
hideOthers: true,
useObjectStates: true
});

Run this example

When using this option, at some point later you'll probably want to restore all Entitys to their original visibilities and appearances. To do that, save their visibility and appearance states in an ObjectsMemento beforehand, from which you can restore them later:

const objectsMemento = new ObjectsMemento();

// Save all Entity visibility and appearance states

objectsMemento.saveObjects(viewer.scene);

// Show storey view Entitys, with custom appearances as configured for IFC types

storeyViewsPlugin.showStoreyObjects("2SWZMQPyD9pfT9q87pgXa1", {
useObjectStates: true // <<--------- Apply custom appearances
});

//...

// Later, restore all Entitys to their saved visibility and appearance states
objectsMemento.restoreObjects(viewer.scene);

Arranging the Camera for a Storey Plan View

The StoreyViewsPlugin#gotoStoreyCamera method positions the Camera for a plan view of the Entitys within the given storey.

Run this example

Let's fly the Camera to a downward-looking orthographic view of the Entitys within our storey.

storeyViewsPlugin.gotoStoreyCamera("2SWZMQPyD9pfT9q87pgXa1", {
projection: "ortho", // Orthographic projection
duration: 2.5, // 2.5 second transition
done: () => {
viewer.cameraControl.planView = true; // Disable rotation
}
});

Note that we also set CameraControl#planView true, which prevents the CameraControl from rotating or orbiting. In orthographic mode, this effectively makes the Viewer behave as if it were a 2D viewer, with picking, panning and zooming still enabled. If you need to be able to restore the Camera to its previous state, you can save it to a CameraMemento beforehand, from which you can restore it later:

const cameraMemento = new CameraMemento();

// Save camera state

cameraMemento.saveCamera(viewer.scene);

// Position camera for a downward-looking orthographic view of our storey

storeyViewsPlugin.gotoStoreyCamera("2SWZMQPyD9pfT9q87pgXa1", {
projection: "ortho",
duration: 2.5,
done: () => {
viewer.cameraControl.planView = true; // Disable rotation
}
});

//...

// Later, restore the Camera to its saved state
cameraMemento.restoreCamera(viewer.scene);

Creating a 2D StoreyMap

The StoreyViewsPlugin#createStoreyMap method creates a 2D orthographic plan image of the given storey, which we can use as a mini-map to help us navigate within the 3D view.

Run this example

This method creates a StoreyMap, which provides the plan image as a Base64-encoded string.

Let's create a 2D plan image of our building storey:

const storeyMap = storeyViewsPlugin.createStoreyMap("2SWZMQPyD9pfT9q87pgXa1", {
width: 300,
format: "png"
});

const imageData = storeyMap.imageData; // Base64-encoded image data string
const width = storeyMap.width; // 300
const height = storeyMap.height; // Automatically derived from width
const format = storeyMap.format; // "png"

As with showStoreyEntitys, We also have the option to customize the appearance of the Entitys in our plan images according to their IFC types, using the lookup table configured on StoreyViewsPlugin#objectStates. For example, we usually want to show only element types like IfcWallIfcDoor and IfcFloor in our plan images. Let's create another StoreyMap, this time applying the custom appearances:

const storeyMap = storeyViewsPlugin.createStoreyMap("2SWZMQPyD9pfT9q87pgXa1", {
width: 300,
format: "png",
useObjectStates: true // <<--------- Apply custom appearances
});

We can also specify a height for the plan image, as an alternative to width:

 const storeyMap = storeyViewsPlugin.createStoreyMap("2SWZMQPyD9pfT9q87pgXa1", {
height: 200,
format: "png",
useObjectStates: true
});

Navigating with a 2D StoreyMap

We can use StoreyViewsPlugin#pickStoreyMap to pick Entities in our building storey, using 2D coordinates from mouse or touch events on our StoreyMap's 2D plan image.

Run this example

Let's programmatically pick the Entity at the given 2D pixel coordinates within our image:

const mouseCoords = [65, 120]; // Mouse coords within the image extents

const pickResult = storeyViewsPlugin.pickStoreyMap(storeyMap, mouseCoords);

if (pickResult && pickResult.entity) {
pickResult.entity.highlighted = true;
}