Selection
Selectors, the lists the user picks faces, edges and other items into in the 3D view, and what the user has selected in the model: for apps that let the user pick.
Types
Selector
type Selector<T> = {
customSelect?: CustomSelect;
customUnSelect?: CustomSelect;
hoveredItem: SelectedItem<T> | null;
isSelectable: SelectionFilter;
items: SelectedItem<T>[];
maxLen: number;
};
A selector: a list that items are picked into, such as the edges of a fillet, with a filter for what it takes.
Plugins and inputs create one with createSelector of a drawing's api.selection, and activate it while the
user picks. The 3D view of @buerli.io/react adds what the user clicks to the active selector, if its filter
takes it.
Example
import { DrawingID, getDrawing, LineGeometry, lineFilter, SelectionFilter } from '@buerli.io/core'
import { useDrawing } from '@buerli.io/react'
import { useEffect } from 'react'
// Lets the user pick two straight edges in the 3D view (BuerliGeometry with `selection`), and shows their lengths
function LinePicker({ drawingId }: { drawingId: DrawingID }) {
useEffect(() => {
const { api } = getDrawing(drawingId)
// An active selector for at most two lines; the cleanup removes it
return api.selection.createSelector('lines', lineFilter as SelectionFilter, true, [], 2)
}, [drawingId])
const items = useDrawing(drawingId, drawing => drawing.selection.refs['lines']?.items) ?? []
const lines = items.map(item => item.data as LineGeometry)
return <p>{lines.map(line => line.start.distanceTo(line.end).toFixed(1)).join(' and ') || 'Pick two edges'}</p>
}
Type Parameters
| Type Parameter | Default type | Description |
|---|---|---|
T extends SeletedItemData<any> | any | The data of the items. |
Properties
| Property | Modifier | Type | Description |
|---|---|---|---|
customSelect? | readonly | CustomSelect | Takes over from select: it is then up to it to set the items, with setItems. |
customUnSelect? | readonly | CustomSelect | Takes over from unselect and unselectAll: it is then up to it to set the items, with setItems. |
hoveredItem | readonly | SelectedItem<T> | null | The item under the pointer, or null. |
isSelectable | readonly | SelectionFilter | Whether the selector takes an item. |
items | readonly | SelectedItem<T>[] | The items picked so far. |
maxLen | readonly | number | How many items the selector holds at most; -1 for any number. |
SelectedItem
type SelectedItem<T> = {
data: T;
id: any;
label?: any;
removeCondition?: (d) => boolean;
scope: SelectionScope;
};
An item in a selector: an element of the geometry, or anything else a selector picks.
Items are told apart by id and scope. createGraphicItem makes the item of a geometry element.
Example
import { getDrawing, SelectedItem } from '@buerli.io/core'
// A feature of the tree as an item of a scope of its own; it leaves the selector when the feature is deleted
const item: SelectedItem<{ objectId: number }> = {
id: `feature|${featureId}`,
scope: 'Features',
data: { objectId: featureId },
label: 'FT',
removeCondition: drawing => drawing.structure.tree[featureId] === undefined,
}
getDrawing(drawingId).api.selection.select(item, 'features')
Type Parameters
| Type Parameter | Default type | Description |
|---|---|---|
T extends SeletedItemData<any> | any | The item's data. |
Properties
| Property | Modifier | Type | Description |
|---|---|---|---|
data | readonly | T | The item's data; for an element of the geometry, the element (ProductElement). |
id | readonly | any | Tells the item apart in its scope; for an element of the geometry, <productId>|<graphicId>|<type>. |
label? | readonly | any | A short text the Selection element of @buerli.io/react shows for the item, such as LI for a line. |
removeCondition? | readonly | (d) => boolean | Called each time the drawing changes; when it returns true, the item is removed from the selector. For example, d => d.structure.tree[id] === undefined when the object is deleted. |
scope | readonly | SelectionScope | What kind of item it is. |
InteractionInfo
type InteractionInfo<T> = {
containerId?: ObjectID;
graphicId?: GraphicID;
objectId: ObjectID;
objectPath?: ObjectID[];
prodRefId?: ObjectID | null;
uniqueIdent: string;
userData?: T;
};
An object of the structure tree or an element of its geometry, as the user selects or hovers it.
It is what interaction of a drawing holds (DrawingState). An object of the tree has objectId and the
product it is in; an element of the geometry also has the solid (containerId) and the element (graphicId).
createInfo makes one, with its uniqueIdent.
Example
import { DrawingID } from '@buerli.io/core'
import { useDrawing } from '@buerli.io/react'
// The names of the objects the user has selected in the model
function Selected({ drawingId }: { drawingId: DrawingID }) {
const names = useDrawing(drawingId, drawing =>
drawing.interaction.selected?.map(info => drawing.structure.tree[info.objectId]?.name).join(', '),
)
return <p>Selected: {names || 'nothing'}</p>
}
Type Parameters
| Type Parameter | Default type |
|---|---|
T | any |
Properties
SelectionFilter
type SelectionFilter<T> = (scope, data) => boolean;
Whether a selector takes an item: called with the item's scope and data.
For elements of the geometry, the 3D view calls it with BuerliScope and the element's GraphicType; the
filters solidFilter, meshFilter, edgeFilter, … check for one kind. Combine them for more.
Type Parameters
| Type Parameter | Default type |
|---|---|
T | any |
Parameters
| Parameter | Type |
|---|---|
scope | SelectionScope |
data | T |
Returns
boolean
Example
import { ScgGraphicType } from '@buerli.io/classcad'
import { BuerliScope, getDrawing, SelectionFilter } from '@buerli.io/core'
// Planar faces and straight edges
const planesAndLines: SelectionFilter = (scope, type) =>
scope === BuerliScope && (type === ScgGraphicType.PLANE || type === ScgGraphicType.LINE)
const remove = getDrawing(drawingId).api.selection.createSelector('references', planesAndLines, true)
SelectorID
type SelectorID = string | number;
A selector's id, chosen by whoever creates the selector.
Selector has an example.
Advanced
Most apps do not need these directly: types they meet through the exports above, and what is there for special cases or for building on buerli itself.
arcCircleFilter()
function arcCircleFilter(scope, data): boolean;
Takes arcs and circles, for example for a center or a radius.
Use it as a selector's filter (SelectionFilter): Selector has an example.
Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | The item's scope; only BuerliScope is taken. |
data | ScgGraphicType | The element's GraphicType. |
Returns
boolean
arcFilter()
function arcFilter(scope, data): boolean;
Takes arcs of solids, not full circles.
Use it as a selector's filter (SelectionFilter): Selector has an example.
Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | The item's scope; only BuerliScope is taken. |
data | ScgGraphicType | The element's GraphicType. |
Returns
boolean
BuerliScope
const BuerliScope: "ClassCAD" = 'ClassCAD';
The scope of selected items that are elements of the geometry: faces, edges, points and solids.
Such an item's data is the element (ProductElement, which has an example); createGraphicItem
makes one. A SelectionFilter gets this scope with the element's GraphicType.
circleFilter()
function circleFilter(scope, data): boolean;
Takes circles of solids.
Use it as a selector's filter (SelectionFilter): Selector has an example.
Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | The item's scope; only BuerliScope is taken. |
data | ScgGraphicType | The element's GraphicType. |
Returns
boolean
createGraphicItem()
function createGraphicItem(productId, el): SelectedItem<ProductElement>;
Makes the selected item of an element of the geometry, in BuerliScope, for a selector.
Parameters
| Parameter | Type | Description |
|---|---|---|
productId | number | The product the element is in; its transformation places the element. |
el | GeometryElement | The element, from a drawing's geometry.cache. |
Returns
The item: its data is the element with productId.
Example
import { ScgGraphicType } from '@buerli.io/classcad'
import { createGraphicItem, getDrawing } from '@buerli.io/core'
// Select all planar faces of a part, in the active selector
const { api, geometry, structure } = getDrawing(drawingId)
const faces = (structure.tree[partId]?.solids ?? []).flatMap(id => geometry.cache[id]?.meshes ?? [])
const items = faces.filter(face => face.type === ScgGraphicType.PLANE).map(face => createGraphicItem(partId, face))
api.selection.select(items)
createInfo()
function createInfo(data): InteractionInfo;
Makes an InteractionInfo: the given fields with the uniqueIdent they make.
Parameters
| Parameter | Type | Description |
|---|---|---|
data | Omit<InteractionInfo, "uniqueIdent"> | The item's fields, without uniqueIdent. |
Returns
The item, for interaction.select or interaction.setSelected of a drawing's API.
Example
import { createInfo, getDrawing } from '@buerli.io/core'
const { api, structure } = getDrawing(drawingId)
const product = structure.currentProduct
// Select a feature of the current part, as a click in the tree does, and hover a sketch
api.interaction.select(createInfo({ objectId: featureId, prodRefId: product }))
api.interaction.setHovered(createInfo({ objectId: sketchId, prodRefId: product }))
CustomSelect
type CustomSelect = (selectorId, newItems, diff, options?) => void;
Takes over from a selector's select (or unselect): it gets the items and sets them itself, with setItems.
Called with the selector, the items it would have (newItems), the ones that change (diff: those added, or
those removed), and the options of the call.
Parameters
| Parameter | Type |
|---|---|
selectorId | SelectorID |
newItems | SelectedItem[] |
diff | SelectedItem[] |
options? | { [key: string]: any; } |
Returns
void
Example
import { CustomSelect, getDrawing, meshFilter, SelectionFilter } from '@buerli.io/core'
// Faces are picked only from one product: what is picked elsewhere is left out
const onlyFrom =
(productId: number): CustomSelect =>
(selectorId, newItems) => {
const items = newItems.filter(item => item.data.productId === productId)
getDrawing(drawingId).api.selection.setItems(selectorId, items)
}
const { api } = getDrawing(drawingId)
api.selection.createSelector('faces', meshFilter as SelectionFilter, true, [], -1, onlyFrom(productId))
edgeFilter()
function edgeFilter(scope, data): boolean;
Takes edges of solids: lines, arcs, circles and other curves.
Use it as a selector's filter (SelectionFilter): Selector has an example.
Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | The item's scope; only BuerliScope is taken. |
data | ScgGraphicType | The element's GraphicType. |
Returns
boolean
lineFilter()
function lineFilter(scope, data): boolean;
Takes straight edges of solids.
Use it as a selector's filter (SelectionFilter): Selector has an example.
Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | The item's scope; only BuerliScope is taken. |
data | ScgGraphicType | The element's GraphicType. |
Returns
boolean
loopFilter()
function loopFilter(scope, data): boolean;
Takes loops, the edges around a face: the 3D view takes the loop of the face that is picked.
Use it as a selector's filter (SelectionFilter): Selector has an example.
Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | The item's scope; only BuerliScope is taken. |
data | ScgGraphicType | The element's GraphicType. |
Returns
boolean
meshFilter()
function meshFilter(scope, data): boolean;
Takes faces of solids: planar, cylindrical, conical, spherical and free-form faces.
Use it as a selector's filter (SelectionFilter): Selector has an example.
Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | The item's scope; only BuerliScope is taken. |
data | ScgGraphicType | The element's GraphicType. |
Returns
boolean
planeFilter()
function planeFilter(scope, data): boolean;
Takes planar faces.
Use it as a selector's filter (SelectionFilter): Selector has an example.
Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | The item's scope; only BuerliScope is taken. |
data | ScgGraphicType | The element's GraphicType. |
Returns
boolean
pointFilter()
function pointFilter(scope, data): boolean;
Takes points of solids: the ends of their edges.
Use it as a selector's filter (SelectionFilter): Selector has an example.
Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | The item's scope; only BuerliScope is taken. |
data | ScgGraphicType | The element's GraphicType. |
Returns
boolean
SelectionScope
type SelectionScope = string | number;
What kind of item a selected item is: BuerliScope for elements of the geometry, or a scope of its own.
Other items have scopes of their own, like the tree objects of react-cad; SelectedItem has an example.
solidFilter()
function solidFilter(scope, data): boolean;
Takes whole solids: picking any face or edge selects its solid.
Use it as a selector's filter (SelectionFilter): Selector has an example.
Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | The item's scope; only BuerliScope is taken. |
data | ScgGraphicType | The element's GraphicType. |
Returns
boolean