@@ -100,6 +100,19 @@ const VdMInfoText = wire()`
100100 </p>
101101 </div>
102102` ;
103+ const VdMTiltInfoText = wire ( ) `
104+ <div style='width: 300px'>
105+ <p>
106+ The generated sequence will be inserted at the current position of the cursor in the editor.
107+ </p>
108+ <p>
109+ To generate a TILTED Van der Meer type scan, choose which beam(s) that will be moving, and fill numbers.
110+ </p>
111+ <p>
112+ The tilt angle is defined as the <strong>angle between the scan direction and the separation plane</strong>, in degrees.
113+ </p>
114+ </div>
115+ ` ;
103116const arrayInfoText = wire ( ) `
104117 <div style='width: 300px'>
105118 <p>
@@ -229,6 +242,52 @@ export class GenerateSequenceWindow extends HTMLElement {
229242 return this . generator . generateFromFunction ( funcArr , waitTime , stepNum ) ;
230243 }
231244
245+ genFromVdMTiltedInput ( ) {
246+ const tiltDeg = Number ( this . allInputs . VdMtilt [ 0 ] . value ) || 0 ;
247+ const waitTime = Number ( this . allInputs . VdMtilt [ 1 ] . value ) ;
248+ const stepNum = Number ( this . allInputs . VdMtilt [ 2 ] . value ) ;
249+ const startSep = Number ( this . allInputs . VdMtilt [ 3 ] . value ) || 0 ;
250+ const endSep = Number ( this . allInputs . VdMtilt [ 4 ] . value ) || 0 ;
251+
252+ const beam = this . root . querySelector ( "#VdMtilt" ) . querySelector ( "#beam-select" ) . value ;
253+
254+ // Convert tilt angle to radians
255+ const tiltRad = ( tiltDeg * Math . PI ) / 180 ;
256+
257+ // Calculate the components for separation and crossing planes
258+ const startSepX = startSep * Math . cos ( tiltRad ) ;
259+ const startSepY = startSep * Math . sin ( tiltRad ) ;
260+ const endSepX = endSep * Math . cos ( tiltRad ) ;
261+ const endSepY = endSep * Math . sin ( tiltRad ) ;
262+
263+ let handleArr = Array ( 4 ) ;
264+ if ( beam == "Beam 1" ) {
265+ handleArr [ 0 ] = `linear(${ startSepX } ,${ endSepX } )` ; // Separation plane
266+ handleArr [ 2 ] = `linear(${ startSepY } ,${ endSepY } )` ; // Crossing plane
267+ }
268+ if ( beam == "Beam 2" ) {
269+ handleArr [ 1 ] = `linear(${ startSepX } ,${ endSepX } )` ; // Separation plane
270+ handleArr [ 3 ] = `linear(${ startSepY } ,${ endSepY } )` ; // Crossing plane
271+ }
272+ if ( beam == "Both beams" ) {
273+ handleArr [ 0 ] = `linear(${ startSepX / 2 } ,${ endSepX / 2 } )` ;
274+ handleArr [ 1 ] = `linear(${ - startSepX / 2 } ,${ - endSepX / 2 } )` ;
275+ handleArr [ 2 ] = `linear(${ startSepY / 2 } ,${ endSepY / 2 } )` ;
276+ handleArr [ 3 ] = `linear(${ - startSepY / 2 } ,${ - endSepY / 2 } )` ;
277+ }
278+
279+ const funcArr = handleArr . map ( ( handle , index ) => {
280+ try {
281+ return this . generator . getFunctionFromString ( handle , waitTime , stepNum ) ;
282+ } catch ( error ) {
283+ if ( error instanceof ArgError ) throw new ArgError ( error . message , index ) ;
284+ else throw error ;
285+ }
286+ } ) ;
287+
288+ return this . generator . generateFromFunction ( funcArr , waitTime , stepNum ) ;
289+ }
290+
232291 onFunctionGenerateClick ( ) {
233292 if ( ! this . allInputs . functions [ 0 ] . value ) {
234293 this . allInputs . functions [ 0 ] . classList . add ( "error" ) ;
@@ -300,6 +359,36 @@ export class GenerateSequenceWindow extends HTMLElement {
300359 else throw error ;
301360 }
302361 }
362+
363+ onVdMTiltGenerateClick ( ) {
364+ if ( ! this . allInputs . VdMtilt [ 0 ] . value ) {
365+ this . allInputs . VdMtilt [ 0 ] . classList . add ( "error" ) ;
366+ alert ( '"Tilt" is a required field' ) ;
367+ return ;
368+ }
369+ if ( ! this . allInputs . VdMtilt [ 1 ] . value ) {
370+ this . allInputs . VdMtilt [ 1 ] . classList . add ( "error" ) ;
371+ alert ( '"Time between trims" is a required field' ) ;
372+ return ;
373+ }
374+ const stepNum = Number ( this . allInputs . VdMtilt [ 2 ] . value ) ;
375+ if ( ! stepNum || ! Number . isInteger ( stepNum ) || stepNum > 100 || stepNum < 2 ) {
376+ this . allInputs . VdMtilt [ 2 ] . classList . add ( "error" ) ;
377+ alert ( '"Number of steps" must be an integer strictly greater than 1 and less than 100' ) ;
378+ return ;
379+ }
380+ try {
381+ let newLines = this . genFromVdMTiltedInput ( ) ;
382+ this . onSuccess ( newLines ) ;
383+ }
384+ catch ( error ) {
385+ if ( error instanceof ArgError ) {
386+ this . allInputs . VdMtilt [ error . where + 3 ] . classList . add ( "error" ) ;
387+ alert ( "Invalid input function: " + error . message ) ;
388+ }
389+ else throw error ;
390+ }
391+ }
303392
304393 set ip ( ip ) {
305394 this . _ip = ip ;
@@ -316,6 +405,7 @@ export class GenerateSequenceWindow extends HTMLElement {
316405 arrays : this . root . querySelector ( "#arrays" ) . querySelectorAll ( "input" ) ,
317406 functions : this . root . querySelector ( "#functions" ) . querySelectorAll ( "input" ) ,
318407 VdM : this . root . querySelector ( "#VdM" ) . querySelectorAll ( "input" ) ,
408+ VdMtilt : this . root . querySelector ( "#VdMtilt" ) . querySelectorAll ( "input" ) ,
319409 } ;
320410 this . tabButtons = this . root . querySelector ( ".tabs" ) . querySelectorAll ( "button" ) ;
321411 this . allTabs = this . root . querySelectorAll ( ".tab" ) ;
@@ -336,6 +426,7 @@ export class GenerateSequenceWindow extends HTMLElement {
336426 } ) ;
337427
338428 this . root . querySelector ( "#VdM-generate" ) . addEventListener ( "click" , ( ) => this . onVdMGenerateClick ( ) ) ;
429+ this . root . querySelector ( "#VdM-tilt-generate" ) . addEventListener ( "click" , ( ) => this . onVdMTiltGenerateClick ( ) ) ;
339430 this . root . querySelector ( "#function-generate" ) . addEventListener ( "click" , ( ) => this . onFunctionGenerateClick ( ) ) ;
340431 this . root . querySelector ( "#array-generate" ) . addEventListener ( "click" , ( ) => this . onArrayGenerateClick ( ) ) ;
341432
@@ -351,7 +442,8 @@ export class GenerateSequenceWindow extends HTMLElement {
351442 </style>
352443 <model-window>
353444 <div class='tabs'>
354- <button id='VdM-tab'>Van Der Meer</button>
445+ <button id='VdM-tab'>Van der Meer</button>
446+ <button id='VdMtilt-tab'>Van der Meer (Tilted)</button>
355447 <button id='arrays-tab'>From array</button>
356448 <button id='functions-tab'>From function</button>
357449 </div>
@@ -384,6 +476,31 @@ export class GenerateSequenceWindow extends HTMLElement {
384476 <button id='VdM-generate'>Generate at cursor</button>
385477 </div>
386478
479+ <div class='tab' id='VdMtilt'>
480+ Generate Van der Meer scan
481+ <info-box>
482+ ${ VdMTiltInfoText }
483+ </info-box>
484+ <hr>
485+ <div>
486+ <select id='beam-select'>
487+ <option>Both beams</option>
488+ <option>Beam 1</option>
489+ <option>Beam 2</option>
490+ </select>
491+ <input id="tilt-angle" type="number" placeholder="Tilt (°)" title="Tilt angle (°) - 0 = SEPARATION">
492+ </div>
493+ <div>
494+ <input id="wait-time" type="number" placeholder="Time between steps (s)" title="Time between steps (s)">
495+ <input id="step-number" type="number" placeholder="Number of steps" title="Number of steps">
496+ </div>
497+ <div>
498+ <input type="number" placeholder="Initial Separation (σ)" title="Initial Separation (σ)">
499+ <input type="number" placeholder="Final Separation (σ)" title="Final Separation (σ)">
500+ </div>
501+ <button id='VdM-tilt-generate'>Generate at cursor</button>
502+ </div>
503+
387504 <div class='tab' id='arrays'>
388505 Generate scan from position arrays
389506 <info-box>
0 commit comments