Skip to main content

SDK Components for Picking Objects with a Marquee Box

· 2 min read

Introduction

In xeokit-sdk v2.4.2, we have added components that enable interactive picking of a Viewer's Entities using a 2D box drawn on the canvas with mouse input.

New Components

  • ObjectsKdTree3 - Automatically indexes a Viewer's Entities in a 3D k-d tree to support fast collision detection with 3D World-space axis-aligned boundaries (AABBs) and frustums.
  • MarqueePicker - Picks a Viewer's Entities with a canvas-space 2D marquee box.
  • MarqueePickerMouseControl - Controls a MarqueePicker with mouse input.

Usage

In the example below, we:

  1. Create a Viewer, arrange the Camera
  2. Use an XKTLoaderPlugin to load BIM model,
  3. Create a ObjectsKdTree3 to automatically index the Viewer's Entities for fast spatial lookup,
  4. Create a MarqueePicker to pick Entities in the Viewer, using the ObjectsKdTree3 to accelerate picking
  5. Create a MarqueePickerMouseControl to perform the marquee-picking with the MarqueePicker, using mouse input to draw the marquee box on the Viewer's canvas.

When the MarqueePickerMouseControl is active:

  • Long-click, drag and release on the canvas to define a marque box that picks Entities.
  • Drag left-to-right to pick Entities that intersect the box.
  • Drag right-to-left to pick Entities that are fully inside the box.
  • On release, the MarqueePicker will fire a "picked" event with IDs of the picked Entities, if any.
  • Handling that event, we mark the Entities as selected.
import { Viewer, XKTLoaderPlugin, ObjectsKdTree3, MarqueePicker, MarqueePickerMouseControl } from "https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/xeokit-sdk.es.min.js";

// 1

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

viewer.scene.camera.eye = [14.9, 14.3, 5.4];
viewer.scene.camera.look = [6.5, 8.3, -4.1];
viewer.scene.camera.up = [-0.28, 0.9, -0.3];

// 2

const xktLoader = new XKTLoaderPlugin(viewer);

const sceneModel = xktLoader.load({
id: "myModel",
src: "HolterTower.ifc.xkt",
});

// 3

const objectsKdTree3 = new ObjectsKdTree3({ viewer });

// 4

const marqueePicker = new MarqueePicker({ viewer, objectsKdTree3 });

// 5

const marqueePickerMouseControl = new MarqueePickerMouseControl({
marqueePicker,
});

marqueePicker.on("clear", () => {
viewer.scene.setObjectsSelected(viewer.scene.selectedObjectIds, false);
});

marqueePicker.on("picked", (objectIds) => {
viewer.scene.setObjectsSelected(objectIds, true);
});

marqueePickerMouseControl.setActive(true);

Design Notes

  • The ObjectsKdTree3 can be shared with any other components that want to use it to spatially search for Entities.
  • The MarqueePickerMouseControl can be replaced with other types of controllers (i.e. touch), or used alongside them.
  • The MarqueePicker has no input handlers of its own, and provides an API through which to programmatically control marquee picking. By firing the "picked" events, MarqueePicker implements the Blackboard Pattern.