Skip to main content

Graphics

What goes into the app's canvas besides the geometry: StageLook, the model as a drawing, and the pieces the plugins draw with.

Components​

StageLook​

const StageLook: React.FC<StageLookProps>;

The model on the stage: a solid body, drawn by its lines as a drawing shows it (BRANDING.md, "The stage").

  • Body. A body the model gives a colour of its own keeps it; the engine's stock grey takes the theme's body tone: a neutral grey that stands clearly off the ground, in either theme.
  • Edges. The engine's edges are hairlines (a GL line is one device pixel wide, half a pixel on a dense screen). Each is drawn instead as a line of real width, which takes its colour and its opacity from the hairline, so whatever recolours or fades the model's edges still does. The hairline stays where it is, unseen, as what is pointed at and picked. Seams, where a curved face meets itself, are not drawn: a drawing has none.
  • Silhouettes. Where a curved face turns away from the eye there is no edge, and a drawing has a line. It is found for the view as it stands, and found again when the view turns.
  • Thin bodies. A body only a few lines thick on screen (a rod, a wire, a sheet from far off) is drawn by its faces: it has no silhouette, and the edges of a body that narrow, or edges that lie that close together, take on its colour. A dense model reads as its parts, not as ink.

Mount it inside the canvas, beside the geometry. (That the edges are ink is the theme's doing: Drawing tells the engine's geometry so.) Without it the model is the engine's own grey with hairline edges. Its props: StageLookProps.

Example​

import { Canvas } from '@react-three/fiber'
import type { DrawingID } from '@buerli.io/core'
import { BuerliGeometry } from '@buerli.io/react'
import { StageLook } from '@buerli.io/react-cad'

// the model drawn as a drawing: heavier lines, and no silhouettes on its curved faces
const Stage = ({ drawingId }: { drawingId: DrawingID }) => (
<Canvas orthographic>
<StageLook weight={1.8} silhouettes={false} />
<BuerliGeometry drawingId={drawingId} />
</Canvas>
)

GeometryOverridesManager​

const GeometryOverridesManager: React.FC<GeometryOverridesManagerProps>;

Applies the colour overrides that useOverrideGeometryColor registers to the model's meshes and edges in the scene.

It swaps the material of each mesh and edge of the geometry for a recoloured copy, and puts the material back when the override goes. It applies them anew when the geometry, the active feature or the rollback bar changes. Without it, the overrides do nothing: mount it once inside the canvas. Its props: GeometryOverridesManagerProps.

Example​

import { Canvas } from '@react-three/fiber'
import type { DrawingID } from '@buerli.io/core'
import { BuerliGeometry } from '@buerli.io/react'
import { GeometryOverridesManager, HoveredConstraintDisplay, PluginGeometryBounds, StageLook } from '@buerli.io/react-cad'

// the pieces an app's own canvas carries for react-cad's plugins and panels
const Stage = ({ drawingId }: { drawingId: DrawingID }) => (
<Canvas orthographic>
<StageLook />
<GeometryOverridesManager drawingId={drawingId} />
<HoveredConstraintDisplay drawingId={drawingId} />
<BuerliGeometry drawingId={drawingId} />
<PluginGeometryBounds drawingId={drawingId} />
</Canvas>
)

Types​

GeometryOverridesManagerProps​

type GeometryOverridesManagerProps = {
drawingId: DrawingID;
};

Props of GeometryOverridesManager.

Properties​

PropertyTypeDescription
drawingIdDrawingIDThe drawing whose geometry is recoloured.

StageLookProps​

type StageLookProps = {
silhouettes?: boolean;
weight?: number;
};

Props of StageLook.

Properties​

PropertyTypeDescription
silhouettes?booleanfalse leaves curved faces without their silhouettes. Default true.
weight?numberHow wide a line is inked, in px. Default 1.4.

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.

Badge​

const Badge: React.FC<BadgeProps>;

A badge on the stage: a constraint's sign where it holds. At rest a neutral disc, its ring and its glyph in the theme's grey. A badge that has something to say (it is under the pointer, in hand, redundant, in conflict) is lit in that colour, its glyph in white, or in ink on a light one.

Its three layers lie in one plane, at the badge's offset, and are drawn in their order: the disc and the ring are a ground that leaves the depth alone, so the glyph is never measured against them. (They were set apart by fractions of a polygon offset, which WebGPU takes in whole units only: there the disc came out in front, and the badges were empty.) A badge onTop, in a HUD, is not measured against anything: it lies in the sketch's plane with its lines and regions, which in a slanted view and on WebGPU won it by a hair or lost it as the view was zoomed.

It lies in the XY plane of where it is put, and takes no pointer. Its props: BadgeProps.

Example​

import { useMemo } from 'react'
import * as THREE from 'three'
import { Badge, iconDataUrl, useStage } from '@buerli.io/react-cad'

// a badge of the app's own on the stage: a pin's sign, lit while it is under the pointer
function PinBadge({ position, hovered }: { position: [number, number, number]; hovered: boolean }) {
const stage = useStage()
const glyph = useMemo(() => new THREE.TextureLoader().load(iconDataUrl('pin', { ink: '#ffffff' }, 96, 15)), [])
return (
<group position={position}>
<Badge size={6} texture={glyph} tone={hovered ? stage.sketchHover : undefined} renderOrder={10} />
</group>
)
}

BadgeProps​

type BadgeProps = {
onTop?: boolean;
polygonOffsetUnits?: number;
renderOrder?: number;
size: number;
texture?: THREE.Texture | null;
tone?: THREE.ColorRepresentation;
};

Props of Badge.

Properties​

PropertyTypeDescription
onTop?booleanDrawn over what it lies on, in its render order (a HUD's badge): no depth test. Default false.
polygonOffsetUnits?numberThe polygon offset of its layers, in whole units. Default 0.
renderOrder?numberThe render order of the glyph; the disc and the ring are drawn just before it. Default 0.
sizenumberThe disc's diameter, in the scene's units.
texture?THREE.Texture | nullThe glyph: a texture of a drawing in white, which the badge colours (see iconDataUrl).
tone?THREE.ColorRepresentationThe colour the badge is lit in, when it has something to say. Without it, it is at rest.

CompositeCurveObj​

const CompositeCurveObj: React.FC<CompositeCurveObjProps>;

Draws a composite curve of the drawing's structure on the stage: its curves as lines of a width in px.

It draws what the engine tessellated of the curve (its lines, edges and arcs), over the model. Its props: CompositeCurveObjProps. See WorkPointObj.


CompositeCurveObjProps​

type CompositeCurveObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
lineWidth?: number;
objectId: ObjectID;
userData?: any;
};

Props of CompositeCurveObj.

Properties​

PropertyTypeDescription
color?THREE.ColorRepresentationIts colour. Default: the stage's datum colour (StageColors.datum).
drawingIdDrawingIDThe drawing the curve is in.
handlers?anyPointer handlers for its lines (react-three-fiber's onClick, onPointerOver, …).
lineWidth?numberHow wide its line is, in px. Default 3.
objectIdObjectIDThe composite curve (CC_CompositeCurve) in the drawing's structure tree.
userData?anyGiven to its lines' userData, for whoever picks it from the scene.

CSysDisplay​

const CSysDisplay: React.FC<CSysDisplayProps>;

Shows the mates of an assembly on the stage: the work coordinate systems of its instances, in a HUD.

It walks the current instance and the instances in it. A mate that is selected in a field (an assembly constraint's) is drawn flipped and turned as the field has it; the others as their coordinate system lies, as displayMode says. An instance that does not take part shows only its selected mates. It goes inside the canvas. Its props: CSysDisplayProps.

Example​

import type { DrawingID } from '@buerli.io/core'
import { CSysDisplay, CSysDisplayMode, EditMode, useEditMode } from '@buerli.io/react-cad'

// in the canvas: the mates the user switched visible in the tree, while an assembly is worked on
function Mates({ drawingId }: { drawingId: DrawingID }) {
const mode = useEditMode(drawingId)
if (mode !== EditMode.Assembly) return null
return <CSysDisplay drawingId={drawingId} displayMode={CSysDisplayMode.DisplayVisible} />
}

CSysDisplayMode​

Which mates CSysDisplay shows.

Enumeration Members​

Enumeration MemberValueDescription
DisplayAll0Every mate of the instances that take part.
DisplayHovered1The mates of the instance under the pointer (for a while after it leaves), and the selected ones.
DisplayVisible2The mates switched visible in the assembly's tree.

CSysDisplayProps​

type CSysDisplayProps = {
csys?: React.FC<{
drawingId: DrawingID;
matrix: THREE.Matrix4;
userData: {
csysId: ObjectID;
path: ObjectID[];
};
}>;
displayMode?: CSysDisplayMode;
drawingId: DrawingID;
includeSelected?: boolean;
instances?: ObjectID[];
};

Props of CSysDisplay.

Properties​

PropertyTypeDescription
csys?React.FC<{ drawingId: DrawingID; matrix: THREE.Matrix4; userData: { csysId: ObjectID; path: ObjectID[]; }; }>A component that draws a mate that is not selected, instead of the stock axes.
displayMode?CSysDisplayModeWhich mates are shown. Default CSysDisplayMode.DisplayAll.
drawingIdDrawingIDThe drawing whose current assembly's mates are shown.
includeSelected?booleanLets an instance take part that already has a mate selected in another field, which by default does not (a constraint joins two instances); the current product's own mates then do not. Default false.
instances?ObjectID[]The instances whose mates take part, by their product. Default: the current product and every instance in it.

HoveredConstraintDisplay​

const HoveredConstraintDisplay: React.FC<HoveredConstraintDisplayProps>;

Shows what an assembly constraint under the pointer holds: the two mates it joins, or, for a relation such as a gear, the badges of the constraints it relates.

The pointer is on the constraint in the Constraints list or on the stage (the drawing's hovered object). Nothing is shown while a field picks. It goes inside the canvas, and draws in a HUD; the example of GeometryOverridesManager has it in its place. Its props: HoveredConstraintDisplayProps.


HoveredConstraintDisplayProps​

type HoveredConstraintDisplayProps = {
drawingId: DrawingID;
};

Props of HoveredConstraintDisplay.

Properties​

PropertyTypeDescription
drawingIdDrawingIDThe drawing whose assembly constraints are pointed at.

HUD​

const HUD: React.FC<HUDProps>;

Draws its children over the scene, after it and without its depth: what is in a HUD is never hidden by the model.

Every HUD of a canvas shares one scene, which is drawn once a frame with the stage's camera, and only while something in it shows; its children are placed in the scene's coordinates as anywhere else. The work geometry, the mates and the sketch's badges on the stage are drawn in one. It goes inside the canvas. Its props: HUDProps.

Example​

import { Canvas } from '@react-three/fiber'
import type { DrawingID, ObjectID } from '@buerli.io/core'
import { useBuerliCadFacade } from '@buerli.io/react'
import { HUD, StageLook, WorkPointObj } from '@buerli.io/react-cad'

// a work point that stays in sight, even where the body is in front of it
function Stage({ pointId }: { pointId: ObjectID }) {
const { drawingId, Geometry } = useBuerliCadFacade('bracket')
return (
<Canvas orthographic>
<StageLook />
<Geometry />
<HUD>
<WorkPointObj drawingId={drawingId} objectId={pointId} color="#e7000b" />
</HUD>
</Canvas>
)
}

HUDProps​

type HUDProps = {
children?: React.ReactNode;
};

Props of HUD.

Properties​

PropertyTypeDescription
children?React.ReactNodeWhat is drawn over the scene.

Outline​

const Outline: ForwardRefExoticComponent<{
edgeColor1?: [ColorRepresentation, ColorRepresentation];
edgeColor2?: [ColorRepresentation, ColorRepresentation];
edgeColor3?: [ColorRepresentation, ColorRepresentation];
width?: number;
} & Partial<{
selectionLayer: number;
selections1: Object3D<Object3DEventMap>[][];
selections2: Object3D<Object3DEventMap>[][];
selections3: Object3D<Object3DEventMap>[][];
}> & RefAttributes<OutlineEffect>>;

An outline effect for postprocessing's EffectComposer: draws a line around each object of up to three groups, each group in its own colour.

It is an effect, not an object: it goes into an EffectComposer (@react-three/postprocessing), on WebGL. The groups are what is hovered, selected and picked, say. A colour comes as a pair: the outline's colour, and the one that stands in for it on a body of nearly that colour. A ref reaches the effect. Its props: OutlineProps.

Example​

import { EffectComposer } from '@react-three/postprocessing'
import type * as THREE from 'three'
import { Outline, useStage } from '@buerli.io/react-cad'

// in a WebGL canvas: what is hovered outlined in the highlight, held back; what is selected, in the highlight
function Outlines({ hovered, selected }: { hovered: THREE.Object3D[]; selected: THREE.Object3D[] }) {
const stage = useStage()
return (
<EffectComposer autoClear={false} multisampling={8}>
<Outline selections1={[hovered]} selections2={[selected]} width={4}
edgeColor1={[stage.hover, stage.alt]} edgeColor2={[stage.select, stage.alt]} />
</EffectComposer>
)
}

OutlineProps​

type OutlineProps = OutlineProps1;

Props of Outline: the three groups of objects that are outlined, and the outlines' width and colours.


PluginGeometryBounds​

const PluginGeometryBounds: React.FC<PluginGeometryBoundsProps>;

An unseen box around what the plugins of the current part show: its visible work geometry and sketches.

It is a mesh that is not drawn, with the box as its geometry's bounds, so that what fits the view to the scene (drei's <Bounds>) takes the work points, axes, planes, coordinate systems and sketches in, which are not part of the model's geometry. It follows them as they change. It goes inside the canvas, next to the geometry that is fitted. Its props: PluginGeometryBoundsProps.

Example​

import { Bounds } from '@react-three/drei'
import type { DrawingID } from '@buerli.io/core'
import { BuerliGeometry } from '@buerli.io/react'
import { PluginGeometryBounds } from '@buerli.io/react-cad'

// zoom to fit takes the work planes and sketches in, not only the bodies
const Fitted = ({ drawingId }: { drawingId: DrawingID }) => (
<Bounds fit observe margin={1.2}>
<BuerliGeometry drawingId={drawingId} />
<PluginGeometryBounds drawingId={drawingId} />
</Bounds>
)

PluginGeometryBoundsProps​

type PluginGeometryBoundsProps = {
drawingId: DrawingID;
};

Props of PluginGeometryBounds.

Properties​

PropertyTypeDescription
drawingIdDrawingIDThe drawing whose current part's features are measured.

SelectedMateObj​

const SelectedMateObj: React.FC<SelectedMateObjProps>;

Draws a mate of an assembly as it is selected: the coordinate system it is on, flipped and turned as the mate says, where its path places it in the current instance.

Its props: SelectedMateObjProps. CSysDisplay draws all the mates of an assembly.

Example​

import { FlipType, ReorientedType } from '@buerli.io/classcad'
import type { DrawingID, ObjectID } from '@buerli.io/core'
import { HUD, SelectedMateObj, useStage } from '@buerli.io/react-cad'

// in the canvas: a mate the app has in hand, lying along -Z of its coordinate system, over the model
function MateInHand({ drawingId, csysId, path }: { drawingId: DrawingID; csysId: ObjectID; path: ObjectID[] }) {
const stage = useStage()
return (
<HUD>
<SelectedMateObj drawingId={drawingId} csysId={csysId} path={path} flip={FlipType.FLIP_Z_INV}
reorient={ReorientedType.REORIENTED_0} color={stage.pick} />
</HUD>
)
}

SelectedMateObjProps​

type SelectedMateObjProps = {
color?: THREE.ColorRepresentation;
csysId: ObjectID;
drawingId: DrawingID;
flip: FlipType;
opacity?: number;
path: ObjectID[];
reorient: ReorientedType;
};

Props of SelectedMateObj.

Properties​

PropertyTypeDescription
color?THREE.ColorRepresentationIts colour.
csysIdObjectIDThe work coordinate system the mate is on.
drawingIdDrawingIDThe drawing the mate is in.
flipFlipTypeWhich of the coordinate system's axes is the mate's main one, and which way.
opacity?numberIts opacity, from 0 to 1.
pathObjectID[]The mate's path: the instances that lead to the coordinate system, as an assembly constraint's mate gives it.
reorientReorientedTypeHow far the mate is turned about its main axis.

useOverrideGeometryColor()​

function useOverrideGeometryColor(
name,
priority,
values,
solidIds?
): void;

Recolours bodies of the model while the component that calls it is mounted: a geometry override.

The override is registered under name, and removed again when the component unmounts or its arguments change; GeometryOverridesManager applies it in the canvas. Where overrides meet on a body, the one with the lower priority wins. An override without solidIds is for every body that no override of a lower priority has taken, and overrides of a higher priority are then not applied at all. Keep values and solidIds the same objects from render to render (useMemo): a new one registers the override anew.

Parameters​

ParameterTypeDescription
namestringThe override's name: one of the same name replaces it.
prioritynumberIts priority: lower wins.
values{ lineColor?: Color; lineOpacity?: number; meshColor?: Color; meshOpacity?: number; }The colours it gives.
values.lineColor?ColorThe edges' colour.
values.lineOpacity?numberThe edges' opacity, from 0 to 1 (0 leaves it as it is).
values.meshColor?ColorThe faces' colour.
values.meshOpacity?numberThe faces' opacity, from 0 to 1 (0 leaves it as it is).
solidIds?number[]The bodies it is for, as useVisibleSolids gives them; without them, all the others.

Returns​

void

Example​

import { useMemo } from 'react'
import type { ObjectID } from '@buerli.io/core'
import { useOverrideGeometryColor } from '@buerli.io/react-cad'

// while it is mounted, the bodies to keep stay as they are and all the others are see-through
function GhostTheRest({ keep }: { keep: ObjectID[] }) {
const asTheyAre = useMemo(() => ({}), [])
const ghost = useMemo(() => ({ meshOpacity: 0.2, lineOpacity: 0.2 }), [])
useOverrideGeometryColor('keep', 0, asTheyAre, keep)
useOverrideGeometryColor('ghost', 1, ghost)
return null
}

WorkAxisObj​

const WorkAxisObj: React.FC<WorkAxisObjProps>;

Draws a work axis of the drawing's structure on the stage: an arrow from its position along its direction, the same size on the screen at any zoom.

Its props: WorkAxisObjProps. See WorkPointObj.


WorkAxisObjProps​

type WorkAxisObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
objectId: ObjectID;
opacity?: number;
userData?: any;
};

Props of WorkAxisObj.

Properties​

PropertyTypeDescription
color?THREE.ColorRepresentationIts colour. Default: the stage's datum colour (StageColors.datum).
drawingIdDrawingIDThe drawing the object is in.
handlers?anyPointer handlers for its meshes (react-three-fiber's onClick, onPointerOver, …).
objectIdObjectIDThe work axis (CC_WorkAxis) in the drawing's structure tree.
opacity?numberIts opacity, from 0 to 1. Default 1.
userData?anyGiven to its meshes' userData, for whoever picks it from the scene.

WorkCoordSystemObj​

const WorkCoordSystemObj: React.FC<WorkCoordSystemObjProps>;

Draws a work coordinate system (CC_WorkCoordSystem) of the drawing's structure on the stage: its three axes.

Its props: WorkCoordSystemObjProps. See WorkPointObj.


WorkCoordSystemObjProps​

type WorkCoordSystemObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
objectId: ObjectID;
opacity?: number;
userData?: any;
};

Props of WorkCoordSystemObj.

Properties​

PropertyTypeDescription
color?THREE.ColorRepresentationIts colour. Default: its axes' own colours.
drawingIdDrawingIDThe drawing the object is in.
handlers?anyPointer handlers for its meshes (react-three-fiber's onClick, onPointerOver, …).
objectIdObjectIDThe work coordinate system (CC_WorkCoordSystem) in the drawing's structure tree.
opacity?numberIts opacity, from 0 to 1. Default 1.
userData?anyGiven to its meshes' userData, for whoever picks it from the scene.

WorkCSysObj​

const WorkCSysObj: React.FC<WorkCSysObjProps>;

Draws a work coordinate system (CC_WorkCSys) of the drawing's structure on the stage: its three axes, where its coordinate system puts them.

Its props: WorkCSysObjProps. See WorkPointObj.


WorkCSysObjProps​

type WorkCSysObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
objectId: ObjectID;
opacity?: number;
userData?: any;
};

Props of WorkCSysObj.

Properties​

PropertyTypeDescription
color?THREE.ColorRepresentationIts colour. Default: its axes' own colours.
drawingIdDrawingIDThe drawing the object is in.
handlers?anyPointer handlers for its meshes (react-three-fiber's onClick, onPointerOver, …).
objectIdObjectIDThe work coordinate system (CC_WorkCSys) in the drawing's structure tree.
opacity?numberIts opacity, from 0 to 1. Default 1.
userData?anyGiven to its meshes' userData, for whoever picks it from the scene.

WorkPlaneObj​

const WorkPlaneObj: React.FC<WorkPlaneObjProps>;

Draws a work plane of the drawing's structure on the stage: a square of its size at its position, its outline over a thin fill, seen from either side.

Its props: WorkPlaneObjProps. See WorkPointObj.


WorkPlaneObjProps​

type WorkPlaneObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
objectId: ObjectID;
opacity?: number;
userData?: any;
};

Props of WorkPlaneObj.

Properties​

PropertyTypeDescription
color?THREE.ColorRepresentationIts colour. Default: the stage's plane colour (StageColors.plane).
drawingIdDrawingIDThe drawing the object is in.
handlers?anyPointer handlers for its meshes (react-three-fiber's onClick, onPointerOver, …).
objectIdObjectIDThe work plane (CC_WorkPlane) in the drawing's structure tree.
opacity?numberIts opacity, from 0 to 1. Default 1.
userData?anyGiven to its meshes' userData, for whoever picks it from the scene.

WorkPointObj​

const WorkPointObj: React.FC<WorkPointObjProps>;

Draws a work point of the drawing's structure on the stage: a dot at its position, the same size on the screen at any zoom.

Buerligons draws one over the model where the pointer is on a work point, or where one is selected, in a HUD. Its props: WorkPointObjProps.

Example​

import { ScgClassType } from '@buerli.io/classcad'
import { useDrawing } from '@buerli.io/react'
import type { DrawingID } from '@buerli.io/core'
import { HUD, useStage, WorkAxisObj, WorkPlaneObj, WorkPointObj } from '@buerli.io/react-cad'

// in the canvas: the work geometry under the pointer, drawn over the model in the highlight
function HoveredWorkGeometry({ drawingId }: { drawingId: DrawingID }) {
const stage = useStage()
const id = useDrawing(drawingId, (d) => d.interaction.hovered?.objectId)
const clazz = useDrawing(drawingId, (d) => (id ? d.structure.tree[id]?.class : undefined))
if (!id) return null
return (
<HUD>
{clazz === ScgClassType.CCWorkPoint && <WorkPointObj drawingId={drawingId} objectId={id} color={stage.hover} />}
{clazz === ScgClassType.CCWorkAxis && <WorkAxisObj drawingId={drawingId} objectId={id} color={stage.hover} />}
{clazz === ScgClassType.CCWorkPlane && <WorkPlaneObj drawingId={drawingId} objectId={id} color={stage.hover} opacity={0.22} />}
</HUD>
)
}

WorkPointObjProps​

type WorkPointObjProps = {
color?: THREE.ColorRepresentation;
drawingId: DrawingID;
handlers?: any;
objectId: ObjectID;
opacity?: number;
userData?: any;
};

Props of WorkPointObj.

Properties​

PropertyTypeDescription
color?THREE.ColorRepresentationIts colour. Default: the stage's datum colour (StageColors.datum).
drawingIdDrawingIDThe drawing the object is in.
handlers?anyPointer handlers for its meshes (react-three-fiber's onClick, onPointerOver, …).
objectIdObjectIDThe work point (CC_WorkPoint) in the drawing's structure tree.
opacity?numberIts opacity, from 0 to 1. Default 1.
userData?anyGiven to its meshes' userData, for whoever picks it from the scene.