//================= Canvas elements let staticLayer = document.getElementById('static'); let beamLineLayer = document.getElementById('beamLine'); function rotate(xy, center, rad){ let haha = [xy[0]-center[0], xy[1]-center[1]]; let kaka = [ haha[0]*Math.cos(rad) - haha[1]*Math.sin(rad), haha[0]*Math.sin(rad) + haha[1]*Math.cos(rad)]; return [ kaka[0] + center[0], kaka[1] + center[1]]; } function translate(xy, t){ return [xy[0] + t[0], xy[1] + t[1]]; } function distance(xy1, xy2){ return Math.sqrt( Math.pow(xy1[0]-xy2[0],2) + Math.pow(xy1[1]-xy2[1],2)); } class basicShape{ constructor(layer){ this.layer = layer; this.shape = new Path2D(); this.entracePos = [0,0]; this.exitPos = [0,0]; this.rad = 0; } GetExitPos(d){ let l = [ - d * Math.sin(this.rad), - d * Math.cos(this.rad)]; return translate(this.exitPos, l); } clear(){ let ctx = this.layer.getContext('2d'); ctx.save(); ctx.globalCompositeOperation = 'destination-out'; ctx.fill(this.shape); ctx.stroke(this.shape); ctx.restore(); } draw(color){ let ctx = this.layer.getContext('2d'); ctx.fillStyle = color; ctx.fill(this.shape); } } class tandemClass extends basicShape{ constructor(xy, l, w){ super(staticLayer); this.exitPos = [ xy[0], xy[1] - w - l]; this.shape.rect(xy[0] - w/2, xy[1] - l - w/2, w, l); this.shape.arc(xy[0], xy[1]-w/2, w/2, 0, Math.PI); this.shape.arc(xy[0], xy[1]-w/2 - l, w/2, Math.PI, 2* Math.PI); } } class beamLine extends basicShape{ constructor(xy, rad, l){ super(beamLineLayer); this.offset = 0; this.lineWidth = 10; this.exitPos = [xy[0], xy[1] - l]; this.exitPos = rotate(this.exitPos, xy, rad); this.shape.moveTo(xy[0], xy[1]); this.shape.lineTo(this.exitPos[0], this.exitPos[1]); } draw(color){ this.clear(); let ctx = this.layer.getContext('2d'); ctx.setLineDash([10,6]); ctx.lineDashOffset = -this.offset; ctx.lineWidth = 10; ctx.strokeStyle = color; ctx.stroke(this.shape); } march(color){ this.offset++; if( this.offset > 16) this.offset = 0; this.draw(color); //setTimeout(this.march.bind(this), 20); } } class beamRectElement extends basicShape{ constructor(xy, rad, l, w){ super(staticLayer); let A = [xy[0]-w/2, xy[1]]; let B = [xy[0]+w/2, xy[1]]; let C = [xy[0]+w/2, xy[1] - l]; let D = [xy[0]-w/2, xy[1] - l]; A = rotate(A, xy, rad); B = rotate(B, xy, rad); C = rotate(C, xy, rad); D = rotate(D, xy, rad); this.shape.moveTo(A[0], A[1]); this.shape.lineTo(B[0], B[1]); this.shape.lineTo(C[0], C[1]); this.shape.lineTo(D[0], D[1]); this.shape.closePath(); this.exitPos = [xy[0], xy[1] - l] } } class beamCircleElement extends basicShape{ constructor(xy, r, rad0, rad1){ super(staticLayer); this.shape.moveTo(xy[0], xy[1]); this.shape.arc(xy[0], xy[1], r, rad0, rad1); let rad = (rad0 + rad1)/2; let l = [r*Math.cos(rad), r*Math.sin(rad)]; this.exitPos = [xy[0] + l[0], xy[1] + l[1]]; // the middle of the arc } GetExitPos(frac){ let rad = rad0 + Math.abs(rad0 - rad1) * frac; let l = [r*Math.cos(rad), r*Math.sin(rad)]; return [xy[0] + l[0], xy[1] + l[1]]; } } class BeamSpilter extends basicShape{ constructor(xy, r, rad){ super(staticLayer); this.entracePos = xy; this.r = r; let w = r; let l = r/2; let A = [xy[0]+w/2, xy[1] - l]; let B = [xy[0]+w/2, xy[1]]; let C = [xy[0]-w/2, xy[1]]; let D = [xy[0]-w/2, xy[1] - l]; A = rotate(A, xy, rad); B = rotate(B, xy, rad); C = rotate(C, xy, rad); D = rotate(D, xy, rad); this.shape.moveTo(A[0], A[1]); this.shape.lineTo(B[0], B[1]); this.shape.lineTo(C[0], C[1]); this.shape.lineTo(D[0], D[1]); this.rad0 = rad - Math.PI*3/4; this.rad1 = rad - Math.PI/4; this.shape.arc(xy[0], xy[1], r, this.rad0 , this.rad1); } GetExitPos(frac){ let rad = this.rad0 + Math.abs(this.rad0 - this.rad1) * frac; let l = [this.r*Math.cos(rad), this.r*Math.sin(rad)]; return translate(this.entracePos, l); } } class dipole extends basicShape{ constructor(xy, r, rad){ super(staticLayer); this.entracePos = xy; let A = [xy[0] + r/2, xy[1]]; let B = [A[0] , A[1] - r*3/2*Math.tan(rad/2)]; let C = [xy[0] - r - r*3/2 * Math.cos(rad), xy[1] - r*3/2 * Math.sin(rad)]; let D = [xy[0] - r - r/2 * Math.cos(rad), xy[1] - r/2 * Math.sin(rad)]; let F = [xy[0] - r/2, xy[1]]; let E = [xy[0] - r/2, xy[1] - r/2*Math.tan(rad/2)]; this.shape.moveTo(A[0], A[1]); this.shape.arcTo(B[0], B[1], C[0], C[1], r*3/2); this.shape.lineTo(D[0],D[1]); this.shape.arcTo(E[0], E[1], F[0], F[1], r/2); this.shape.lineTo(A[0], A[1]); this.exitPos = [(C[0] + D[0])/2, (C[1] + D[1])/2]; } } let colors = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]; let colorIndex = 0; let color = { BeamPipe : ['White', 'grey30'], Dipole : ['gold', 'gold4'], Deflector : ['Orange', 'Orange4'], Qpole : ['Blue', 'Blue4'], Detector : ['Yellow', 'Yellow4'], LINAC : ['Cyan', 'Cyan4'], Tandem : [ '#782F40', '#CEB888'], Buncher : ['Ivory', 'Ivory4'], SNICS : ['tan', 'tan4'], RFsourcce : ['Olivedrab', 'Olivedrab4'], Other : ['Black', 'Red'] } ///========================= Sand Box; const deg = Math.PI/180; let windowSize = [3840, 2160]; // 4K let RFSource1 = new beamRectElement([windowSize[0]*0.9, windowSize[1]*0.8], 0, 40, 100); let RFSource2 = new beamRectElement(RFSource1.exitPos, 0, 40, 20); let s1 = new BeamSpilter(RFSource2.GetExitPos(120), 50, Math.PI); let b1S = new beamLine(RFSource2.exitPos, 0, 200); let tandem = new tandemClass(b1S.exitPos, 100, 100); let bl0 = new beamLine(tandem.exitPos, 0, 300); bl0.offset = 8; let bl0a = new beamLine(bl0.exitPos, 0, 400); bl0a.offset = 11; let q1 = new beamRectElement(tandem.GetExitPos(50), 0, 60, 60); let df1 = new beamRectElement(q1.GetExitPos(50), 0, 30, 40); let df2 = new beamRectElement(df1.GetExitPos(20), 0, 30, 40); //============ beam line for target room 1 let d1 = new dipole(bl0.exitPos, 80, Math.PI/2); let bl1 = new beamLine(d1.exitPos, -Math.PI/2, 100); let bfan1 = new BeamSpilter(bl1.exitPos, 50, -100 * deg); RFSource1.draw(color.RFsourcce[0]); RFSource2.draw(color.RFsourcce[0]); b1S.draw(color.BeamPipe[0]); s1.draw(color.Dipole[0]); tandem.draw(color.Tandem[0]); bl0.draw(color.BeamPipe[0]); bl0a.draw(color.BeamPipe[1]); q1.draw(color.Qpole[0]); df1.draw(color.Deflector[0]); df2.draw(color.Deflector[0]); d1.draw(color.Dipole[0]); bl1.draw(color.BeamPipe[0]); bfan1.draw(color.Dipole[0]); function lineMotion(){ b1S.march('red'); bl0.march('red'); //bl0a.march('red'); bl1.march('red'); setTimeout(lineMotion, 20); } lineMotion();