UNPKG

@qbead/bloch-sphere

Version:

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

109 lines (97 loc) 2.92 kB
import * as THREE from 'three' import { BaseComponent } from './component' import { BlochVector } from '../math/bloch-vector' import { defaultColors } from '../colors' // import { getArcBetween } from '../math/geometry' // import { Operator } from '../math/operator' class BlochSpherePath extends THREE.Curve<THREE.Vector3> { from: BlochVector to: BlochVector constructor(from: BlochVector, to: BlochVector) { super() this.from = from this.to = to } getPoint( t: number, optionalTarget: THREE.Vector3 = new THREE.Vector3() ): THREE.Vector3 { // we interpolate using their angles so they interpolate spherically optionalTarget.copy(this.from.slerpTo(this.to, t)) return optionalTarget } } function* pairs<T>(arr: T[]): Generator<[T, T]> { for (let i = 0; i < arr.length - 1; i++) { yield [arr[i], arr[i + 1]] } } function tubePath(vertices: BlochVector[], material: THREE.Material) { const curves = Array.from(pairs(vertices)) .map(([v1, v2]) => new BlochSpherePath(v1, v2)) .reduce((curvePath, curve) => { curvePath.add(curve) return curvePath }, new THREE.CurvePath<THREE.Vector3>()) const tube = new THREE.TubeGeometry(curves, 256, 0.005, 6, false) return new THREE.Mesh(tube, material) } // function makeMeshes(path: BlochVector[], material: THREE.Material) { // return pairs(path).map(([v1, v2]) => { // const { arcOffset, arcAngle, norm } = getArcBetween( // v1, // v2 // ) // // const geo = new THREE.RingGeometry(1, 1 + 0.01, 64, 1, arcOffset, arcAngle) // // TODO: potentially use tube geometry // const geo = new THREE.TorusGeometry(1, 0.005, 12, 64, arcAngle) // const mesh = new THREE.Mesh(geo, material) // const rot = new THREE.Quaternion().setFromUnitVectors( // new THREE.Vector3(0, 0, 1), // norm // ) // mesh.applyQuaternion(rot) // const zrot = new THREE.Quaternion().setFromAxisAngle(norm, arcOffset) // mesh.applyQuaternion(zrot) // return mesh // }) // } /** * A display for a path on the Bloch sphere * * The path is defined by a series of Bloch vectors. * * @example * ```ts * const path = new PathDisplay([ * BlochVector.fromAngles(0, 0), * BlochVector.fromAngles(1, 0.1), * BlochVector.fromAngles(1, 1), * ]) * path.color = 0xc33175 * blochSphere.add(path) * ``` */ export class PathDisplay extends BaseComponent { constructor(path?: BlochVector[]) { super('path-display') if (path) { this.set(path) } } /// Set the path set(vertices: BlochVector[]) { this.clear() const material = new THREE.MeshBasicMaterial({ color: defaultColors.path, side: THREE.DoubleSide, transparent: true, opacity: 0.8, }) // @ts-ignore material.depthTest = false const mesh = tubePath(vertices, material) mesh.renderOrder = 10 this.add(mesh) } }