UNPKG

@qbead/bloch-sphere

Version:

A 3D Bloch Sphere visualisation built with Three.js and TypeScript.

140 lines (125 loc) 3.21 kB
import * as THREE from 'three' import { BaseComponent } from './component' import { Operator } from '../math/operator' import { animate } from '../animation' import { Label } from './label' import { defaultColors } from '../colors' /** * A display for a quantum operator * * @example * ```ts * const op = gates.hadamard() * const display = new OperatorDisplay(op) * blochSphere.add(display) * ``` */ export class OperatorDisplay extends BaseComponent { operator: Operator innerGroup: THREE.Group label: Label private anim: any constructor(op?: Operator) { super('operator-display') const innerGroup = new THREE.Group() this.innerGroup = innerGroup // const cone = new THREE.Mesh( // new THREE.ConeGeometry(0.25, 0.05, 32), // new THREE.MeshBasicMaterial({ // color: defaultColors.operator, // transparent: true, // opacity: 0.5, // }) // ) // cone.rotation.x = Math.PI / 2 // cone.position.z = 1.075 // innerGroup.add(cone) const cyl = new THREE.Mesh( new THREE.CylinderGeometry(0.005, 0.005, 1.05, 32), new THREE.MeshBasicMaterial({ color: defaultColors.operator, transparent: true, opacity: 0.5, }) ) cyl.rotation.x = Math.PI / 2 cyl.position.z = 0.525 innerGroup.add(cyl) const ringRadius = 0.7 const rings = new THREE.Group() const ring = new THREE.Mesh( new THREE.RingGeometry( ringRadius - 0.01, ringRadius, 64, 1, 0, Math.PI / 2 ), new THREE.MeshBasicMaterial({ color: defaultColors.operator, side: THREE.DoubleSide, transparent: true, opacity: 0.5, }) ) ring.material.depthTest = false ring.renderOrder = 5 ring.position.z = 0 const ring2 = ring.clone() ring2.rotation.z = Math.PI rings.add(ring) rings.add(ring2) const disc = new THREE.Mesh( new THREE.CircleGeometry(ringRadius - 0.01, 64), new THREE.MeshBasicMaterial({ color: defaultColors.operator, side: THREE.DoubleSide, transparent: true, opacity: 0.1, }) ) disc.material.depthTest = false innerGroup.add(disc) this.anim = animate( (k) => { rings.rotation.z = Math.PI * 2 * k }, 3000, 'linear', true ) innerGroup.add(rings) this.label = new Label('') this.label.position.z = 1.1 innerGroup.add(this.label) this.add(innerGroup) this.renderOrder = 4 this.operator = Operator.identity() if (op) { this.set(op) } } /** * Set the operator to display * @param op The operator to display */ set(op: Operator) { this.operator = op const q = this.operator.quaternion() // the quaternion components are the axis of rotation // so we want to point this group in that direction const n = new THREE.Vector3(q.x, q.y, q.z) const rot = new THREE.Quaternion().setFromUnitVectors( new THREE.Vector3(0, 0, 1), n ) this.setRotationFromQuaternion(rot) } /** * Perform cleanup tasks */ dispose() { this.anim() } }