1// Copyright 2021 The Cirq Developers 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {Group, Vector3} from 'three'; 16import { 17 BoxGate3DSymbol, 18 ConnectionLine, 19 Control3DSymbol, 20 Swap3DSymbol, 21 X3DSymbol, 22} from './meshes'; 23 24export interface SymbolInformation { 25 readonly wire_symbols: string[]; 26 readonly location_info: Coord[]; 27 readonly color_info: string[]; 28 readonly moment: number; 29} 30 31export interface Coord { 32 readonly row: number; 33 readonly col: number; 34} 35 36/** 37 * Builds a 3D symbol representing a Cirq `Operation`. 38 */ 39export class Symbol3D extends Group { 40 readonly moment: number; 41 private padding_factor: number; 42 43 /** 44 * Class constructor. 45 * @param symbol_info A typed object with information instructing 46 * the class on how to build the mesh. 47 * @param padding_factor A number scaling the distance between meshes. 48 */ 49 constructor(symbol_info: SymbolInformation, padding_factor = 1) { 50 super(); 51 this.padding_factor = padding_factor; 52 this.moment = symbol_info.moment; 53 this.buildAndAddMeshesToGroup(symbol_info); 54 55 // If this is a multi-qubit operation, we automatically 56 // add lines connecting the symbols. 57 this.addConnectionLines(symbol_info); 58 } 59 60 private buildAndAddMeshesToGroup(symbol_info: SymbolInformation) { 61 const locationInfo = symbol_info.location_info; 62 63 symbol_info.wire_symbols.forEach((symbol, index) => { 64 let mesh; 65 switch (symbol) { 66 case 'X': 67 mesh = new X3DSymbol(symbol_info.color_info[index]); 68 break; 69 case '@': 70 mesh = new Control3DSymbol(); 71 break; 72 case '×': 73 mesh = new Swap3DSymbol(); 74 break; 75 default: 76 mesh = new BoxGate3DSymbol(symbol, symbol_info.color_info[index]); 77 } 78 79 mesh.position.set( 80 locationInfo[index].row * this.padding_factor, 81 symbol_info.moment * this.padding_factor, 82 locationInfo[index].col * this.padding_factor 83 ); 84 this.add(mesh); 85 }); 86 } 87 88 private addConnectionLines(symbol_info: SymbolInformation) { 89 const locationInfo = symbol_info.location_info; 90 91 if (locationInfo.length > 1) { 92 let i = 0; 93 while (i < locationInfo.length - 1) { 94 const coords = [ 95 new Vector3( 96 locationInfo[i].row * this.padding_factor, 97 symbol_info.moment * this.padding_factor, 98 locationInfo[i].col * this.padding_factor 99 ), 100 new Vector3( 101 locationInfo[i + 1].row * this.padding_factor, 102 symbol_info.moment * this.padding_factor, 103 locationInfo[i + 1].col * this.padding_factor 104 ), 105 ]; 106 this.add(new ConnectionLine(coords[0], coords[1])); 107 i++; 108 } 109 } 110 } 111} 112