Newer
Older
// jshint esversion: 6
let gui = new lil.GUI();
let hideTimeout = false;
let svg;
let zoom = 1;
let oldZoom = 1;
let panZoomPanther;
let foundAnimate = 1;
let foundScale = 1.05;
let myPanZoomTimer = null;
let historytime = + new Date();
let fel1 = false;
let fel2 = false;
const panZoomTime = 500;
const facilities = [''];
const names = [];
const serviceareanames = [];
const alias = [];
let maxZoom = 230;
const status = [];
const point = {x: 0, y: 0};
const pa = document.location.search.replace('?','').split('&');
const parameters = {};
const state = document.location.search.indexOf('ps')>-1;
const vlv = document.location.search.indexOf('vlv')>-1;
const vlvs = [];
const speechToken = Math.floor(Math.random() * 1000000000000);
for (let i=0; i<pa.length; i++) {const p = pa[i].split('='); parameters[p[0]] = p[1];}
const machineCaseSensitive = document.location.search.indexOf('machine=')>-1? document.location.search.split('machine=')[1].split('&')[0]: 'elettra';
const machine = machineCaseSensitive.toLowerCase();
let measurementType = document.location.search.indexOf('measurement=')>-1? document.location.search.split('measurement=')[1].split('&')[0].split(','): document.location.search.indexOf('measurement')>-1;
let measurementEvent = 'contextmenu';
if (typeof measurementType == "object") {
const index = measurementType.indexOf('left');
measurementEvent = 'mousedown';
measurementType.splice(index, 1);
let measurement = typeof measurementType == "object" || measurementType;
function setTick(x, y, cx, cy, dist, distPixel, n, pow10=1000) {
const tx1 = cx + (x - cx) / dist * pow10 * n;
const ty1 = cy + (y - cy) / dist * pow10 * n;
const tx2 = tx1 - (y - cy) / distPixel * 10;
const ty2 = ty1 + (x - cx) / distPixel * 10;
$('#tick'+n).attr('x1', tx1);
$('#tick'+n).attr('y1', ty1);
$('#tick'+n).attr('x2', tx2);
$('#tick'+n).attr('y2', ty2);
$('#tickLabel'+n).attr('x', 2*tx2-tx1);
$('#tickLabel'+n).attr('y', 2*ty2-ty1);
$('#tickLabel'+n).html(x==cx || distPixel<220? '': pow10 * n / 1000);
}
// https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
function pDistance(x, y, x1, y1, x2, y2) {
var A = x - x1;
var B = y - y1;
var C = x2 - x1;
var D = y2 - y1;
var dot = A * C + B * D;
var len_sq = C * C + D * D;
var param = -1;
if (len_sq != 0) param = dot / len_sq; //in case of 0 length line
var xx, yy;
if (param < 0) {
xx = x1;
yy = y1;
}
else if (param > 1) {
xx = x2;
yy = y2;
}
else {
xx = x1 + param * C;
yy = y1 + param * D;
}
var dx = x - xx;
var dy = y - yy;
return {dist: Math.sqrt(dx * dx + dy * dy), x: xx, y: yy};
}
function getCursorPosition(main, event) {
const rect = main.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const distPixel = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(y - cy, 2));
const dist = distPixel / panZoomPanther.getSizes().realZoom;
if (measurementStart) $('#stright').val(Math.round(dist)/1000);
// const alpha = (Math.atan2(y-cy, x-cx) * 180) / Math.PI;
$('#pos').val(Math.round((x - panZoomPanther.getPan().x)/panZoomPanther.getSizes().realZoom)/1000+' '+(-Math.round((y - panZoomPanther.getPan().y)/panZoomPanther.getSizes().realZoom)/1000));
const pow10 = Math.pow(10, Math.round(Math.log10(dist))-1);
$('#measurementLine').attr('x2', x);
$('#measurementLine').attr('y2', y);
$('#measurementLineStroke').attr('x2', x);
$('#measurementLineStroke').attr('y2', y);
for (let i=1; i<32; i++) {
if (i<dist/pow10 && distPixel>50) setTick(x, y, cx, cy, dist, distPixel, i, pow10); else setTick(x, y, x, y, dist, distPixel, i, pow10);
const vertex = [];
let minDistance = Infinity;
let dindex = -1;
let mincDistance = Infinity;
let dcindex = -1;
// beam pattern measurement
if (typeof measurementType == "object" && typeof lattice[measurementType[0]] == "object") {
let d = 0;
const x1 = (x - panZoomPanther.getPan().x) / panZoomPanther.getSizes().realZoom;
const y1 = (y - panZoomPanther.getPan().y) / panZoomPanther.getSizes().realZoom;
const xc1 = (cx - panZoomPanther.getPan().x) / panZoomPanther.getSizes().realZoom;
const yc1 = (cy - panZoomPanther.getPan().y) / panZoomPanther.getSizes().realZoom;
for (let i=0; i < lattice[measurementType[0]].sections.length; i++) {
j = (i+1) % lattice[measurementType[0]].sections.length;
vertex[i] = lattice[measurementType[0]].sections[i].start;
// d = Math.sqrt(Math.pow(vertex[i].x - x, 2) + Math.pow(vertex[i].z - y, 2));
d = pDistance(x1, y1, vertex[i].x, vertex[i].z, lattice[measurementType[0]].sections[j].start.x, lattice[measurementType[0]].sections[j].start.z);
if (minDistance > d.dist) { minDistance = d.dist; dindex = i; p = d;}
d = pDistance(xc1, yc1, vertex[i].x, vertex[i].z, lattice[measurementType[0]].sections[j].start.x, lattice[measurementType[0]].sections[j].start.z);
if (mincDistance > d.dist) { mincDistance = d.dist; dcindex = i; pc = d;}
}
let pathd = 'M '+(pc.x*panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().x)+' '+(pc.y * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().y)+' ';
k = dcindex;
j = (k+1) % lattice[measurementType[0]].sections.length;
let dd = Math.sqrt(Math.pow(pc.x-lattice[measurementType[0]].sections[j].start.x, 2) + Math.pow(pc.y-lattice[measurementType[0]].sections[j].start.z, 2));
if (dcindex == dindex) dd = Math.sqrt(Math.pow(pc.x-p.x, 2) + Math.pow(pc.y-p.y, 2));
else {
while (k != dindex) {
j = (k+1) % lattice[measurementType[0]].sections.length;
if (k != dcindex) dd = dd + Math.sqrt(Math.pow(lattice[measurementType[0]].sections[k].start.x-lattice[measurementType[0]].sections[j].start.x, 2) + Math.pow(lattice[measurementType[0]].sections[k].start.z-lattice[measurementType[0]].sections[j].start.z, 2));
pathd = pathd + 'L '+(lattice[measurementType[0]].sections[j].start.x * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().x)+' '+(lattice[measurementType[0]].sections[j].start.z * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().y)+' ';
dd = dd + Math.sqrt(Math.pow(p.x-lattice[measurementType[0]].sections[dindex].start.x, 2) + Math.pow(p.y-lattice[measurementType[0]].sections[dindex].start.z, 2));
}
$('#bm').val(Math.round(dd)/1000);
pathd = pathd + 'L '+(p.x * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().x)+' '+(p.y * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().y);
//<path d="M 10 10 H 90 V 90 H 10 L 10 10"/>
console.log('minDistance', mincDistance, dcindex, pc, minDistance, dindex, p, dd, 'pathd', pathd);
$('#beam').attr('d', pathd);
$('#measurementSide1').attr('x2', pc.x * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().x);
$('#measurementSide1').attr('y2', pc.y * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().y);
$('#measurementSide2').attr('x1', x);
$('#measurementSide2').attr('y1', y);
$('#measurementSide2').attr('x2', p.x * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().x);
$('#measurementSide2').attr('y2', p.y * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().y);
function clearmeasurement() {
$('#measurementLine').attr('x1', cx);
$('#measurementLine').attr('y1', cy);
$('#measurementLine').attr('x2', cx);
$('#measurementLine').attr('y2', cy);
$('#measurementLineStroke').attr('x1', cx);
$('#measurementLineStroke').attr('y1', cy);
$('#measurementLineStroke').attr('x2', cx);
$('#measurementLineStroke').attr('y2', cy);
$('#measurementSide1').attr('x1', cx);
$('#measurementSide1').attr('y1', cy);
$('#measurementSide1').attr('x2', cx);
$('#measurementSide1').attr('y2', cy);
$('#measurementSide2').attr('x1', cx);
$('#measurementSide2').attr('y1', cy);
$('#measurementSide2').attr('x2', cx);
$('#measurementSide2').attr('y2', cy);
for (let i=1; i<32; i++) {setTick(cx, cy, cx, cy, 1, 1, i);}
if (measurementStart) { measurementStart = false; return;}
const rect = main.getBoundingClientRect();
cx = event.clientX - rect.left;
cy = event.clientY - rect.top;
console.log(Math.round(cx) + "," + Math.round(cy) + ",");
if (!measurementStart) {
// appendSvg("circle", {id: 'measurementStart', cx: cx, cy: cy, r:8, style:"display: block", fill:"none", stroke:"red","stroke-width":2});
if ($('#measurementLine').length==0) {
appendSvg("line", {id: 'measurementLineStroke', x1: cx, y1: cy, x2: cx, y2: cy, style:"display: block", fill:"yellow", stroke:"black","stroke-width":4});
appendSvg("line", {id: 'measurementLine', x1: cx, y1: cy, x2: cx, y2: cy, style:"display: block", fill:"yellow", stroke:"yellow","stroke-width":2});
appendSvg("path", {d: '', fill: "none", stroke: "limegreen", "stroke-width": 3, id:"beam"});
appendSvg("line", {id: 'measurementSide1', x1: cx, y1: cy, x2: cx, y2: cy, style:"display: block", fill:"none", stroke:"pink","stroke-width":2});
appendSvg("line", {id: 'measurementSide2', x1: cx, y1: cy, x2: cx, y2: cy, style:"display: block", fill:"none", stroke:"pink","stroke-width":2});
appendSvg("line", {id: 'tick'+i, x1: cx, y1: cy, x2: cx, y2: cy, style:"display: block", fill:"yellow", stroke:"black","stroke-width":1});
appendSvg("text", {id: 'tickLabel'+i, x: cx, y: cy, fill:"white", stroke:"black","stroke-width":1, "font-family":"Arial", "font-size":20, "font-weight":"bold", "text-anchor": "start"});
// $('#measurementStart').attr('cx', cx); $('#measurementStart').attr('cy', cy);
$('#measurementLine').attr('x1', cx);
$('#measurementLine').attr('y1', cy);
$('#measurementLineStroke').attr('x1', cx);
$('#measurementLineStroke').attr('y1', cy);
}
main.addEventListener('mousemove', function(e) {
getCursorPosition(main, e);
});
}
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
if (document.location.search.indexOf('measurement')>-1) {
measurementEnable();
}
function measurementToggle(enable) {
for (let i=1; i<100; i++) {
if ($('#lil-gui-name-'+i).html()=='measurement') {
if (enable) {
$('#lil-gui-name-'+(i+1)).parent().show();
$('#lil-gui-name-'+(i+2)).parent().show();
}
else {
$('#lil-gui-name-'+(i+1)).parent().hide();
$('#lil-gui-name-'+(i+2)).parent().hide();
}
break;
}
}
}
function measurementDisable() {
clearmeasurement();
main.removeEventListener(measurementEvent, measurementListener, false);
main.style.cursor = 'default';
measurementToggle(false);
}
function measurementListener(e) {
e.preventDefault();
initCursorPosition(main, e);
return false;
}
function measurementEnable() {
$('#measurement').show();
main.addEventListener(measurementEvent, measurementListener, false);
measurementToggle(true);
}
function measurementFacility(msg) {
console.log('measurementFacility()', msg);
if (msg=='left') {
if (measurementEvent != 'mousedown') {
measurementDisable();
measurementEvent = 'mousedown';
measurementEnable();
}
}
else if (msg=='right') {
if (measurementEvent == 'mousedown') {
measurementDisable();
measurementEvent = 'contextmenu';
measurementEnable();
}
}
else if (msg=='') {
measurementDisable();
measurementType = true;
measurementEnable();
}
else {
measurementDisable();
measurementType = [msg];
measurementEnable();
//https://puma-01.elettra.eu/rchan.php?json&valueOnly&src=srv-tango-srf-01.fcs.elettra.trieste.it:20000/f/access_control/safety/Undulator_access_state -> 5 FEL1, 6 FEL2
if (machine.indexOf('fermi')>-1) {
fetch(conf.rchan+'srv-tango-srf-01:20000/f/access_control/safety/Undulator_access_state').then((response) => {return response.json();}).then((fel) => {
fel1 = fel[5] == 1;
fel2 = fel[6] == 1;
});
}
function resizeIframe(obj) {
obj.style.height = obj.contentWindow.document.documentElement.scrollHeight + 'px';
}
let latticeFile = document.location.href.split('?')[0].split('/').slice(0,-1).join('/')+'/'+machine+'_lattice.json';
if (machine.indexOf('simulator_')>-1) {latticeFile = document.location.href.split('?')[0].split('/').slice(0,-1).join('/')+'/'+'simulator.php?lattice&machine='+machine.split('simulator_')[1];}
const menuParams = {machine: machineCaseSensitive.toLowerCase(), search: '', backgroundColor: '#333333'};
gui.title('PAnTHer - controls');
// if (navigator.userAgent.indexOf('Firefox/63')>-1) {$( "body" ).append('<button id="starter" style="align: center;height: 500px; width: 95%;background-color: #449944; font-size: 100px;" onClick="mystart()">START</button>');}
function mystart() {
panZoomPanther = svgPanZoom('#panther', {beforeZoom: myZoom, fit: false, contain: false});
$("#sname").on("keydown", searchText);
$('#starter').hide();
}
// Polyfill replaceAll()
if (typeof String.prototype.replaceAll !== 'function') {
String.prototype.replaceAll = function(search, replacement) {
var target = this;
return target.split(search).join(replacement);
};
// Polyfill for parentNode.replaceChildren()
if (typeof Element.prototype.replaceChildren !== 'function') {
Object.defineProperty(Element.prototype, 'replaceChildren', {
configurable: true,
writable: true,
value: function replaceChildren(...nodes) {
// Remove all existing child nodes
while (this.firstChild) {
this.removeChild(this.firstChild);
}
// Append new DOM objects
this.append(...nodes);
}
});
}
function toggleMachine(machine) {
document.location = document.location.href.split('?')[0] + '?machine='+machine;
/*if (document.location.search.indexOf('machine=')==-1) document.location = document.location.href + (document.location.href.indexOf('?')==-1? '?': '&') + 'machine='+machine;
let search = document.location.search.split('machine=')[1].split('&')[0];
document.location = document.location.href.replace('machine='+search, 'machine='+machine);*/
}
function compLink(id) {
console.log('compLink()', id, document.getElementById("compdb").href);
// window.open(document.getElementById("compdb").href, '_blank').focus();
window.open(id, 'components').focus();
// event.stopPropagation();
return false;
}
function searchText(e) {
console.log('searchText()', e, e.keyCode || e.which, $("#sname").val().toUpperCase().replace('.','_'));
if (e.keyCode == 13) findComponent($("#sname").val().toUpperCase());
function shrinkName(name) {
return name.replaceAll('FEL0', 'FEL').replaceAll('PS_', 'PS').replaceAll('SIP_', 'SIP').replaceAll('KG0', 'KG').replaceAll('BC0', 'BC').replaceAll('_L0', 'L').replaceAll('_F0', 'F').replaceAll('_0', '').replaceAll('_', '');
}
// if (navigator.userAgent.indexOf('Firefox/63')==-1) {gui.add(menuParams, 'machine', conf.machineList).onChange(function() {toggleMachine(menuParams.machine);});}
gui.add(menuParams, 'machine', conf.machineList).onChange(function() {toggleMachine(menuParams.machine);});
gui.add(menuParams, 'search');
$('.controller.string:last').parent().append('<iframe id="talk" style="height: 30px;" src="./speech/talk.php?background=black&token='+speechToken+'" frameborder="0" scrolling="no" onload="resizeIframe(this)"></iframe>');
gui.addColor(menuParams, 'backgroundColor').onChange(function() {toggleParam('backgroundColor');});
menuParams.vlv = document.location.search.indexOf('vlv')>-1;
gui.add(menuParams, 'vlv').name('vlv & bst').onChange(function() {toggleParam('vlv');});
menuParams.ps = document.location.search.indexOf('ps')>-1;
gui.add(menuParams, 'ps').onChange(function() {toggleParam('ps');});
menuParams.measurement = document.location.search.indexOf('measurement')>-1;
gui.add(menuParams, 'measurement').onChange(function() {toggleParam('measurement');});
const sstring = $('.controller.string').children().eq(1).children().eq(0);
sstring.attr('id', 'sname');
sstring.attr('name', 'sname');
sstring.addClass("form-control sname");
function findComponent(name) {
// https://stackoverflow.com/questions/5497318/replace-last-occurrence-of-character-in-string
if (name.indexOf('.')==-1 && name.indexOf('_')>-1) name = name.replace(/_([^_]*)$/, '.' + '$1');
if (document.location.search.indexOf('debugfind')>-1) {console.log('findComponent('+name+')'); return 'OK';}
let servicearea = false;
console.log('lattice', lattice);
if (lattice.servicearea) for (let i in lattice.servicearea.sections) {
for (let j in lattice.servicearea.sections[i].components) {
if (name.replace('.', '_')==lattice.servicearea.sections[i].components[j].name.replace('.', '_')) {servicearea = true;}
for (let k in lattice.servicearea.sections[i].components[j].embedded) {
if (name==lattice.servicearea.sections[i].components[j].embedded[k]) {servicearea = true;}
}
}
}
console.trace(name, servicearea, document.location.search.indexOf('servicearea'), document.location.search.indexOf('search='+name)); // return;
if ((servicearea != document.location.search.indexOf('servicearea')>-1) && document.location.search.indexOf('search='+name)==-1) {
document.location = './panther2d.php?machine='+machine+'&search='+name+(servicearea? '&servicearea': '');
}
if (name==null) name = document.getElementById('sname').value;
for (let i=0; i<alias.length; i++) if (alias[i][1]==name) name = alias[i][0];
console.log(name, typeof $('#'+name)[0], shrinkName(name), shrinkedNames.indexOf(shrinkName(name)));
if (typeof $('#'+id)[0] == 'undefined') {
const sindex = shrinkedNames.indexOf(shrinkName(id));
if (sindex>-1) id = names[sindex]; else return name+' Not found';
console.log(name, window.innerWidth/2, $('#'+id)[0].getCTM().e, $('#'+id)[0].getCTM().f);
// panZoomPanther.zoomAtPoint(10, {x: window.innerWidth/2 - $('#'+name)[0].getCTM().e, y: window.innerHeight/2 - $('#'+name)[0].getCTM().f})
panZoomPanther.zoom(10);
// leave a delay between zoom and pan
}
function mypan(name) {
$('.label').show();
const x = window.innerWidth/2 - $('#'+name)[0].getCTM().e + panZoomPanther.getPan().x;
const y = window.innerHeight/2 - $('#'+name)[0].getCTM().f + panZoomPanther.getPan().y;
const m = $("svg")[0].getTransformToElement($('#'+name)[0]);
panZoomPanther.pan({x: x, y: y});
setTimeout(pinhide, 100, name, $('#'+name).eq(0).attr('transform'));
}
function pinhide(name, transform) {
foundAnimate *= foundScale;
if (foundAnimate>1.5) foundScale = 0.95;
if (foundAnimate<1) {foundScale = 1.05; foundAnimate = 1;} else setTimeout(pinhide, 100, name, transform);
$('#'+name).eq(0).attr('transform',transform+',scale('+foundAnimate+')');
}
// $(function() {$(".sname").autocomplete({source: names, close: function(event, ui) {findComponent($('#sname').val()); }, select: function(event, ui) {findComponent(ui.item.value); return false;}});});
$(function() {$(".sname").autocomplete({source: names, select: function(event, ui) {findComponent(ui.item.value); return false;}});});
function toggleParam(name) {
if (name=='measurement') { measurement = !measurement; measurementType = measurement; if (measurement) measurementEnable(); else measurementDisable(); return;}
if (name=='backgroundColor') {$('body').css('backgroundColor', menuParams.backgroundColor); return;}
const urlparam = {};
let search = document.location.search.replace('?', '').split('&');
if (search[0]=='') search.splice(0,1);
const i=search.indexOf(name);
if (i==-1) search.push(name); else search.splice(i,1);
const res = search.join('&');
document.location = document.location.href.split('?')[0]+(res.length? '?'+res: '');
}
async function subscribeSpeech() {
mylog('subscribeSpeech()', 1, 2);
let response = await fetch("./speech/talk.php?read&token="+speechToken);
} else if (response.status != 200) {
// An error - let's show it
mylog('subscribeSpeech() ERROR ', response.statusText);
// Reconnect in one second
await new Promise(resolve => setTimeout(resolve, 1000));
} else {
// Get and show the message
let message = await response.text();
window.open('../ujive.php?token='+speechToken, 'ujive').focus();
/*if (!ujiveStarted) ujiveWindow = window.open('../ujive.php?token='+speechToken, '_blank').focus();
setTimeout(ujiveReset, 15000);
ujiveStarted = true;*/
}
else {
const msg = findComponent(message);
// return feedback
fetch("./speech/talk.php?readresult="+msg+"&token="+speechToken);
}
// Call subscribeSpeech() again to get the next message
await subscribeSpeech();
if (document.location.search.indexOf('debug')>-1) $('#debug').val($('#debug').val()+JSON.stringify(args)+'\n');
console.trace.apply(null);
console.log(args, JSON.stringify(args), $('#debug').val());
}
function initIndex(lattice) {
const index = [];
for (let l in lattice.conf.index) {
if (l=='start') continue;
const cmd = "findComponent('"+lattice.conf.index[l].replace('.','_')+"')";
index.push('<button onclick="'+cmd+'">'+l+'</button>');
}
$('body').append('<div style="position: absolute; left: 5px; bottom: 5px;">'+index.join(' ')+'</div>');
}
function toggleFacility(value) {
console.log('toggleFacility', value, this);
if (value) $('.'+this.property).show(); else $('.'+this.property).hide();
}
function init() {
fetch(latticeFile).then((response) => {return response.json();}).then((flattice) => {
lattice = flattice;
if (Object.keys(lattice).length>0) {
gui.add(menuParams, 'measurement button', {Left: 'left', Right: 'right'}).onChange(measurementFacility);
const machineFolder = gui.addFolder('toggle facility');
for (let i in lattice) {if (i!='conf') facilities.push(i);}
menuParams[' '] = false; machineFolder.add(menuParams, ' ').onChange(toggleFacility);
// for (let i=0; i<facilities.length; i++) if (facilities[i]!='') {menuParams[facilities[i]] = true;}
menuParams[i] = document.location.search.indexOf(i+'=hide')==-1;
if (i != 'servicearea' && i != 'bl') measurementDevice[i] = i;
// logic XOR https://stackoverflow.com/questions/2335979/is-there-anyway-to-implement-xor-in-javascript
if ((document.location.search.indexOf('servicearea')==-1) != (i=='servicearea')) {
initLattice(lattice[i].sections, i);
// menuParams[i] = true;
}
else {
initLattice(lattice[i].sections, i);
console.log('.', i, menuParams[i]);
if (document.location.search.indexOf('+servicearea')>-1) {
// menuParams[i] = true;
}
else {
menuParams[i] = false;
}
for (let i=0; i<facilities.length; i++) if (facilities[i]!='') {machineFolder.add(menuParams, facilities[i]).onChange(toggleFacility);}
gui.add(menuParams, 'measurement device', measurementDevice).onChange(measurementFacility);
if (document.location.search.indexOf('measurement')==-1) measurementToggle(false);
if (document.location.search.indexOf('servicearea')>-1) initSearch(lattice.servicearea.sections, 'servicearea');
if (typeof blm != 'undefined') blmMenu(lattice, facilities, menuParams);
if (typeof bpmData != 'undefined') bpmMenu(lattice, facilities, menuParams);
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
if (lattice.conf && lattice.conf.index) initIndex(lattice);
}
$('.scale').attr('transform', "scale(2)");
// {$('<div><iframe style="width: 100%;height:250px;" src="../misc/gauge.html?dark&r1only=1&r=100&max=360&throttlingPeriod=50&apply=rotate&val='+0+'"></iframe></div>').insertBefore('.function');}
// panZoomPanther = svgPanZoom('#panther', {beforeZoom: myZoom, fit: false, contain: false}); // https://github.com/bastienmoulia/svg-pan-zoom-rotate
// if( /Android|webOS|iPhone|iPad|Mac|Macintosh|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
panZoomPanther = svgPanZoom('#panther', {
zoomEnabled: true,
controlIconsEnabled: false,
fit: 0,
center: 1,
maxZoom: maxZoom*2,
customEventsHandler: eventsHandler,
//beforeZoom: myZoom,
});
}
else {
panZoomPanther = svgPanZoom('#panther', {
zoomEnabled: true,
zoomScaleSensitivity: 0.3,
controlIconsEnabled: false,
fit: false,
center: false,
minZoom: 0.2,
maxZoom: maxZoom,
beforePan: myPan,
beforeZoom: myZoom,
});
}
if (document.location.search.indexOf('debug')>-1) {
$('#tooltip').show();
$('#tooltip').css('width', '100%');
$('#tooltip').html('<textarea id="debug" style="height: 100px; width:100%;"></textarea>');
}
let pan = [window.innerWidth/2, window.innerHeight/2];
if (document.location.search.indexOf('pan=')>-1) pan = document.location.search.split('pan=')[1].split('&')[0].split(',');
if (document.location.search.indexOf('search=')>-1) findComponent(document.location.search.split('search=')[1].split('&')[0]);
else {
const default_zoom = typeof conf.default_zoom[machine.split('_')[0]]=='undefined'? conf.default_zoom.default: conf.default_zoom[machine.split('_')[0]];
const zoom = document.location.search.indexOf('zoom=')>-1? document.location.search.split('zoom=')[1].split('&')[0]-0: default_zoom;
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
panZoomPanther.zoom(zoom);
setTimeout(panZoomPanther.pan, 600, {x: pan[0], y: pan[1]});
}
if (state) {
fetch(conf.stateSrcUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
const statSrc = data.toUpperCase().split('.').join('_').split(',');
for (let j=0; j<statSrc.length; j++) {
// if (statSrc[j].split('/')[2]=='POWER_SUPPLY' || statSrc[j].split('/')[2]=='INJECTION' || statSrc[j].split('/')[2]=='EXTRACTION')
statSrc[j] = statSrc[j].split('/')[3].replace('PS', '');
}
for (let i=0; i<status.length; i++) {
if (status[i].name.indexOf('KICK')>-1) console.log('KICK state', i, status[i].name, statSrc);
for (let j=0; j<statSrc.length; j++) {
if (status[i].name.indexOf(statSrc[j])>-1) {status[i].statsrc = state; status[i].statindex = j;}
}
}
// console.log('statSrc', data, statSrc, status);
});
setInterval(updateStatus, 1000);
}
if (vlv) {
for (let i in conf.bstmap) { if (i.indexOf('.')>-1) conf.bstmap[i.replace('.','_')] = conf.bstmap[i];}
fetch(conf.vlvSrcUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
const vlvSrc = data.toUpperCase().substring(14).split(',');
for (let i=0; i<vlvs.length; i++) {
for (let j=0; j<vlvSrc.length; j++) {
const vlva = vlvSrc[j].split('/');
if (vlva.length < 4) continue;
const name = vlva[3].replace('.','_');
if (vlvs[i].name.replace('.','_').indexOf(name)>-1) {vlvs[i].vlvsrc = state; vlvs[i].vlvindex = j; vlvs[i].type = 'vlv';}
if (vlvSrc[j].split('/')[2].indexOf(conf.bstmap.base)>-1) {
if (conf.bstmap[vlvs[i].name] && conf.bstmap[vlvs[i].name].indexOf(vlvSrc[j].split('/')[4])>-1) {
vlvs[i].vlvsrc = 'bst'; vlvs[i].vlvindex = j; vlvs[i].type = 'bst';
}
}
}
}
//console.log('vlvSrc', data, vlvSrc, vlvs);
});
setInterval(updateVlv, 1000);
}
$("#sname").on("keydown", searchText);
window[lattice.conf.modules[i]+'2d'](lattice, menuParams, compData);
menuParams.gotoAdmin = function() {document.location = './admin.php';};
gui.add(menuParams, 'gotoAdmin').name('Admin');
menuParams.goto3D = function() {document.location = './panther.php?machine='+menuParams.machine;};
gui.add(menuParams, 'goto3D').name('3D');
});
}
function showStatus(i, stat) {
if (stat == 0 || stat == 'null' || stat == '' || stat == 'ON' || stat == 'RUNNING' || (!fel1 && $('#'+status[i].name)[0].classList[0]=='fel1') || (!fel2 && $('#'+status[i].name)[0].classList[0]=='fel2')) {$('#'+status[i].name).hide();}
else if (stat == 'ON' || stat == 'RUNNING') {$('#'+status[i].name).show();document.getElementById(status[i].name).style.fill = conf.stateLabelColor[stat];$('#'+status[i].name).addClass('noblink');}
else {$('#'+status[i].name).show(); document.getElementById(status[i].name).style.fill = conf.stateLabelColor[stat];$('#'+status[i].name).removeClass('noblink');}
// console.log(i, status[i], stat);
}
function clearStatus() {
}
function updateStatus() {
fetch(conf.stateUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
const statVal = data.split(';');
// console.log(conf.stateUrl, statVal, status);
for (let i=0; i<status.length; i++) {
if (status[i].statsrc==state) {
if (status[i].statindex) showStatus(i, statVal[status[i].statindex]);
// console.log(statVal, status, status[i].name, i, status[i].statindex, statVal[status[i].statindex]);
}
}
setTimeout(clearStatus, 600);
});
}
function updateVlv() {
fetch(conf.vlvUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
const vlvVal = data.split(':')[1].split(';');
// console.log('updateVlv()', conf.vlvUrl, vlvVal, vlvs);
for (let i=0; i<vlvs.length; i++) {
if (vlvs[i].type=='vlv') $('#'+vlvs[i].name).css('fill', vlvVal[vlvs[i].vlvindex]=='CLOSED'? 'red': (vlvVal[vlvs[i].vlvindex]=='OPENED'? 'limegreen': 'grey'));
if (vlvs[i].type=='bst') {
if (typeof vlvVal[vlvs[i].vlvindex] != 'string') continue;
const val = vlvVal[vlvs[i].vlvindex].split(',');
$('#'+vlvs[i].name).css('fill', val[0]=='true'? 'limegreen': (val[1]=='true'? 'red': 'grey'));
}
}
});
}
function rescale(x) {return x;}
String.prototype.replaceAt = function(index, replacement) {
return this.substring(0, index) + replacement + this.substring(index + replacement.length);
};
function evalId(base) {
if (base.indexOf('.')>-1) return base;
return base.replaceAt(base.lastIndexOf('_'), '.').replace('RTBPM','BPM');
}
function openTooltip(event) {
if (document.location.search.indexOf('debug')==-1) {
const type = this.href? this.href.baseVal.replace('#',''): (this.id.indexOf('BLM')>-1 || this.id.indexOf('BERGOZ')>-1? 'blm': '???');
console.log('openTooltip()',type, this.id, this, event, event.clientY);
$('#tooltip').css('left', event.clientX+30);
$('#tooltip').css('top', event.clientY+30);
const embedded = (typeof this.dataset.embedded == 'undefined' || this.id[0]=='R')? '': ','+this.dataset.embedded;
document.getElementById('tooltipFrame').src = conf.tooltipApp+'?s='+type.replace('fast', '')+'¶m='+this.id + embedded;
console.log('openTooltip(event)', type.toLowerCase(), type.toLowerCase().indexOf('beamline'));
document.getElementById('tooltip').style.display = 'block';
if (hideTimeout!==false) clearTimeout(hideTimeout);
hideTimeout = setTimeout(hideTooltip, 120000);
const id = evalId(this.id);
let buttons = '<button onClick="compLink(\''+conf.compdb + id+'\')">'+id+'</button> ';
if (typeof this.dataset.embedded != 'undefined') {
const emb = this.dataset.embedded.split(',');
for (let e=0; e<emb.length; e++) {
buttons = buttons + '<button onClick="compLink(\''+evalId(emb[e])+'\')">'+evalId(emb[e])+'</button> ';
}
}
else {
for (let i=0; i<lattice.servicearea.sections.length; i++) {
if (lattice.servicearea.sections[i].components) for (let j=0; j<lattice.servicearea.sections[i].components.length; j++) {
if (lattice.servicearea.sections[i].components[j].embedded && lattice.servicearea.sections[i].components[j].embedded.indexOf('PS'+id)>-1) rack = 'rack <button onClick="compLink(\'https://puma-01.elettra.eu/spa/index.html?s='+lattice.servicearea.sections[i].components[j].name.split('_')[0].toLowerCase()+'¶m='+lattice.servicearea.sections[i].components[j].name+'\')">'+lattice.servicearea.sections[i].components[j].name+'</button> ';
}
}
}
buttons = buttons + rack;
document.getElementById('compdb').innerHTML = buttons;
document.getElementById('compdb').style.display = (type.indexOf('rv')==0 || type.indexOf('rc')==0 || type.indexOf('rid')==0 || type.indexOf('rd')==0 || type.indexOf('rps')==0 || type.indexOf('plc')==0)? 'none': 'block';
if (document.getElementById('compname')) document.getElementById('compname').innerHTML = id;
// document.getElementById('compdb').href = conf.compdb + id;
// document.getElementById("compdb").addEventListener("click", compLink);
if (type.toLowerCase().indexOf('beamline')>-1) {
document.getElementById('compdb').href = 'http://adam.elettra.trieste.it/projects/blcs/beamwatch/';
document.getElementById('compdb').innerHTML = 'search '+this.id+' in ADAM Beamwatch <span id="compname"/>';
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
}
else if (machine=='elettra') document.getElementById('compdb').setAttribute("disabled", true);
event.stopPropagation();
}
else {
for (let l in lattice) {
if (l=='confg') continue;
let servicearea = false;
for (let i in lattice[l].sections) {
for (let j in lattice[l].sections[i].components) {
if (this.id==lattice[l].sections[i].components[j].name.replace('.', '_')) {mylog('openTooltip()', lattice[l].sections[i].components[j], lattice[l].sections[i].components[j].position-document.location.search.split('offset=')[1].split('&')[0]);}
}
}
}
}
}
function hideTooltip() {
if (hideTimeout!==false) clearTimeout(hideTimeout);
hideTimeout = false;
// mylog('hideTooltip');
if (document.location.search.indexOf('debug')==-1) {
document.getElementById('tooltipFrame').src = '';
document.getElementById('tooltip').style.display = 'none';
}
}
function transformLabel(x, y, beta, labelReverse) {
if (typeof labelReverse == 'object') return "translate("+rescale(x)+" "+rescale(y)+") rotate("+(beta+labelReverse[0])+") translate("+labelReverse[1]+" "+labelReverse[2]+")";
return labelReverse==180? "translate("+rescale(x)+" "+rescale(y)+") rotate("+(beta-90)+") translate(1800 100)":
"translate("+rescale(x)+" "+rescale(y)+") rotate("+(beta+90)+") translate("+(labelReverse? -350: 350)+" "+(labelReverse? 100: 200)+")";
function appendSvg(tagName, attrib, onClickCall=false, text=false, myclass=false, appendTo="svg") {
const elem = document.createElementNS("http://www.w3.org/2000/svg", tagName);
if (onClickCall) elem.addEventListener("click", onClickCall, false);
const titelem = document.createElementNS("http://www.w3.org/2000/svg", 'title');
const embedded = typeof attrib['data-embedded']=='object'? '\n'+attrib['data-embedded'].join(', '): '';
const aka = typeof attrib['data-aka']=='object' && attrib['data-aka'].length>0? '\naka: '+attrib['data-aka'].join(', '): '';
const title = document.createTextNode(attrib.id + aka + embedded);
titelem.appendChild(title);
elem.appendChild(titelem);
// const textNode = document.createTextNode(text); elem.appendChild(textNode);
elem.innerHTML = text;
}
const jelem = $(elem);
if (myclass) {/*mylog(elem, jelem, myclass);*/ elem.classList.add(myclass);}
for (let i in attrib) {
jelem.attr(i, attrib[i]);
}
const hook = appendTo.indexOf('.')==0? appendTo.replace(' ','_'): appendTo.replace('.','_').replace(' ','_');
$(hook).append(jelem);
}
function appendSearch(component, facility) {
// mylog('appendSearch()',component, facility);
if (component) {
const comp = component.type.replace('booster', '');
if (comp && comp!=' ' && $('#'+comp)[0]) {
const id = extractId(component.name);
names.push(id[0]);
if (facility=='servicearea') serviceareanames.push(id[0]);
for (let j=0; j<component.embedded.length; j++) {
names.push(component.embedded[j]);
shrinkedNames.push(shrinkName(component.embedded[j]));
alias.push([id[0],component.embedded[j]]);
}
if (component.alias) {
for (let j=0; j<component.alias.length; j++) {
names.push(component.alias[j]);
shrinkedNames.push(shrinkName(component.alias[j]));
alias.push([id[0],component.alias[j]]);
}
}
function appendLabel(id, labelclass, display, x, y, beta, labelReverse, suffix='label', fontSize=1, appendTo="svg") {
if ((beta+3600)%360 <180 && typeof labelReverse != 'object') labelReverse = [-90, -250, -100];
appendSvg("text", {
id: (id+suffix).replace(' ','_'),
x:0, y:0, style:"display: "+display, fill:"white", stroke:"#101020","stroke-width":0, "font-family":"Arial", "font-size":100*fontSize, "font-weight":"700",
"text-anchor": (labelReverse? "end": "start"),
transform: transformLabel(x, y, beta, labelReverse)
}, false, appendTo=="svg"? id: '', false, appendTo);
// }, false, id, false, appendTo);
}
function appendLabel2(param, labelclass, display, x, y, beta, labelReverse, suffix='label') {
const id = param.name;
const fontsize = labelclass.indexOf('bl')>-1? 800: 500;
// console.log("appendLabel2()",param, labelclass, display, x, y, beta, labelReverse);
if (labelclass.indexOf('bl')>-1 && typeof labelReverse != 'object') {
labelReverse = [180, 17000, param.type=='beamlineUp'? -500: +800];
if ((beta+3690)%360 < 180) labelReverse = [0, -14000, param.type=='beamlineUp'? 1000: -300];
}
else if ((beta+3600)%360 < 180 && typeof labelReverse != 'object') labelReverse = [-90, -250, -100];
appendSvg("text", {
x:0, y:0, style:"display: block", fill:"red", stroke:"pink","stroke-width":5, "font-family":"Arial", "font-size":fontsize, "font-weight":"700",
"text-anchor": (labelReverse? "end": "start"),
transform: transformLabel(x, y, beta, labelReverse)
}, false, id);
}
function appendComponent(components, x0, y0, x1, y1, facility) {
const dx = x1 - x0;
const dy = y1 - y0;
const d = Math.sqrt(dx*dx + dy*dy);
const beta = 180*Math.atan2(y0-y1, x0-x1)/Math.PI;
if (components) for (let i=0; i<components.length; i++) {
const comp = components[i].type; // .replace('booster', '');
let x = x0+components[i].position/d*dx;
let y = y0+components[i].position/d*dy;
if (components[i].offset2d) {x += components[i].offset2d[0]; y += components[i].offset2d[1];}
if (typeof blm != 'undefined' && comp=='blm') {
const name = components[i].name.replace('BPM','BLM');
// mylog('appendComponent(), ', name, blm.obj);
blm.obj.push(name);
blm.dir.push(beta);
appendSvg("rect", {id:name, name:name, x:0, y:0, width:40, height:40, rx:20, ry:20, transform:"translate("+rescale(x)+" "+rescale(y)+") rotate("+(name.indexOf('_L')>-1? beta + 180: beta)+")"}, openTooltip, false, "blm");
}
if (typeof bpmData != 'undefined' && comp=='bpm') {
// mylog('appendComponent()',components[i], x0, y0, x1, y1, beta, facility, 180*Math.atan2(y0-y1, x0-x1)/Math.PI);
bpmData[facility].obj.push(components[i].name);
bpmData[facility].dir.push(beta);
bpmData[facility].pos.push([rescale(x), rescale(y)]);
}
if (typeof bpmData != 'undefined' && comp=='corrector') {
corr[facility].obj.push(components[i].name);
corr[facility].dir.push(beta);
corr[facility].pos.push([x, y]);
}
compData[facility].obj.push(components[i].name);
compData[facility].dir.push(beta);
compData[facility].pos.push([rescale(x), rescale(y)]);
if ($('#'+comp)[0]) {
// mylog('components['+i+']',components[i]);
const id = extractId(components[i].name);
const section = components[i].name.indexOf('_')>-1? components[i].name.split('_')[1].split('.')[0]+' ': '';
const offset = components[i].type == 'beamlineUp'? "-2100 -3500": "0 -200";
const transform = "translate("+rescale(x)+" "+rescale(y)+") rotate("+(beta+180)+") translate("+offset+")";
const compid = comp + (components[i].length > 0 && $('#'+comp+'_'+components[i].length)[0]? '_'+components[i].length: '');
const aka = components[i].alias && components[i].alias.length? components[i].alias: [];
const compClass = typeof components[i].class == 'undefined'? '': ' '+components[i].class;
appendSvg("use", {href:"#"+compid, id: id[0], name:components[i].name, "data-embedded":components[i].embedded, "data-aka": aka, class: comp+' '+section+facility+compClass, style:"cursor: pointer", transform:transform}, openTooltip);
if (components[i].type == 'label' || components[i].type == 'beamlineDown' || components[i].type == 'beamlineUp')
appendLabel2(components[i], section+facility, 'none', x, y, beta, components[i].labelReverse);
else
appendLabel(components[i].name, comp+' label '+section+facility+compClass, 'none', x, y, beta, components[i].labelReverse);
if (id[0].indexOf('<')==-1) {
appendSvg("g", {"id": id[0]+'_g'});
appendLabel(components[i].name, comp+' value '+section+facility, 'none', x+600, y+400, 90, true, 'value', 0.7, '#'+id[0]+'_g');
for (let j=0; j<components[i].embedded.length; j++) {names.push(components[i].embedded[j]); alias.push([id[0],components[i].embedded[j]]);}
if (typeof components[i].alias == 'object') {
for (let j=0; j<components[i].alias.length; j++) {names.push(components[i].alias[j]); alias.push([id[0],components[i].alias[j]]);}
}
if (id[1]) {names.push(id[1]); shrinkedNames.push(shrinkName(id[1])); alias.push(id);}
if (state) {
if (components[i].ps) {
for (let pi=0; pi<components[i].ps.length; pi++) {
const name = components[i].ps[pi].replace('PS','').replace('.','_') + '_status';
status.push({name: name});
appendSvg('circle', {id: name, class: facility+' ps', style:"display: none", cx: 150+pi*100, cy: 200, transform:transform, r: 80, stroke: 10, strokeColor: 'blue', fill: 'gray'}, false, false, 'status');
}
}
else {
status.push({name: id[0]+'_status'});
appendSvg('circle', {id: id[0]+'_status', class: facility+' ps', style:"display: none", cx: 200, cy: 200, transform:transform, r: 80, stroke: 10, strokeColor: 'blue', fill: 'gray'}, false, false, 'status');
}
if (components[i].name.toUpperCase().indexOf('KICK')>-1) console.log('PS: ', components[i].name, components[i].name.toUpperCase().indexOf('KICK'), status);
}
if (vlv && (components[i].type == 'vlv' || components[i].type == 'bst')) {
// appendSvg('rect', {id: id[0]+'_disable', style:"display: none", x: x+75, y: y-90, width: 50, height: 200, stroke: 10, fill: 'black'}, false, false, 'vlvs');
vlvs.push({name: id[0], type: components[i].type});
}
}
}
}
String.prototype.replaceAll = function(search, replace) {
return this.split(search).join(replace);
};
function extractId(name) {
if (name.indexOf('(')>-1) {
let tok = name.split('(');
return [tok[0].replaceAll('.','_').replaceAll(' ','_').replace(/_+$/, ''), tok[1].replaceAll('.','_').replaceAll(' ','_').replaceAll(')','').replace(/_+$/, '')];
}
// .replace(/_+$/, '') => https://stackoverflow.com/questions/8141718/how-to-trim-specific-characters-from-the-end-of-the-javascript-string
return [name.replaceAll('.','_').replaceAll(' ','_').replace(/_+$/, ''), false];
}
function highlightobjects(objclass) {
$("use").css('opacity',0.3);
$("text").css('opacity',0.3);
$("."+objclass).css('opacity',1);
}
function magnifyobjects(objclass) {
$("text").css('opacity',0.15);
$("text."+objclass).css('opacity',1);
$('.scale').attr('transform', "scale(1) translate(90,100)");
let x = -40;
let y = -40;
let s = 3;
if (objclass=="vlv") {x = -50; y = -50; s = 5;}
$('.'+objclass+'scale').attr('transform', "scale("+s+") translate("+x+","+y+")");
}
function initSearch(sections, facility) {
if (sections[i].bending && sections[i].bending.type) {
// console.log('names.push()', sections[i].bending.name);
names.push(sections[i].bending.name.replace('.','_'));
shrinkedNames.push(shrinkName(sections[i].bending.name.replace('.','_')));
if (typeof sections[i].components == 'object') for (let j=0; j<sections[i].components.length; j++) appendSearch(sections[i].components[j], facility);
}
}
function initLattice(sections, facility) {
if (document.location.search.indexOf('facility=')>-1 && document.location.search.split('facility=')[1].split('&')[0].split(',').indexOf(facility)==-1) return;
compData[facility] = {obj: [], dir: [], pos: [], index: []};
bpmData[facility] = {obj: [], dir: [], pos: []};
corr[facility] = {obj: [], dir: [], pos: []};
}
// vacuum chamber
let d = '';
let m = true;
let wall = false;
for (let i=0; i<sections.length; i++) {
d = d + (m? 'M ': ' L ')+rescale(sections[i].start.x)+' '+rescale(sections[i].start.z);
if (i<sections.length-1 && typeof sections[i+1].chamber == 'undefined') {m = true;} else if (i<sections.length-1 && (sections[i+1].chamber.type=="chamber" || sections[i+1].chamber.type.indexOf("wall")>-1)) {m = false;}
if (i<sections.length-1 && typeof sections[i+1].chamber != 'undefined' && sections[i+1].chamber.type.indexOf("wall")>-1) {
if (sections[i+1].chamber.type.indexOf('_')>-1) w = sections[i+1].chamber.type.split('_')[1]-0;
wall = true;
}
}
if (sections[0].chamber && sections[0].chamber.type=='chamber') d = d + ' Z';
if (facility=='sr') console.log('sections', sections, 'd', d);
if (wall) {
console.log('w', w, sections, d);
//appendSvg("path", {d: d, fill: "none", stroke: "#990000", "stroke-dasharray": "200 200", "stroke-width": 50, id:"wall"+facility});
appendSvg("path", {d: d, fill: "none", stroke: "#f0fff0", "stroke-width": w+20, id:"chamber"+facility, class: facility});
appendSvg("path", {d: d, fill: "none", stroke: "#ff0000", "stroke-width": w, id:"chamber"+facility, class: facility});
else appendSvg("path", {d: d, fill: "none", stroke: "#999999", "stroke-width": 20, id:"chamber"+facility, class: facility});
let j = 0;
let i = sections.length - 1;
let k = sections.length - 2;
let alpha = 180/Math.PI*Math.atan2(sections[j].start.z-sections[i].start.z, sections[j].start.x-sections[i].start.x);
for (i=0; i<sections.length; i++) { // if(i>1) break;
j = (i + 1) % sections.length;
k = (i + sections.length - 1) % sections.length;
let beta = 180/Math.PI*Math.atan2(sections[j].start.z-sections[i].start.z, sections[j].start.x-sections[i].start.x);
let gamma = (beta+alpha)/2;
if (sections[k] && sections[j].start.z<sections[i].start.z && sections[i].start.z>sections[k].start.z) gamma = gamma + 180;
if (alpha>beta && gamma<0) gamma = gamma + 180;
if (sections[i].bending && sections[i].bending.type) {
const section = sections[i].bending.name.indexOf('_')>-1? sections[i].bending.name.split('_')[1].split('.')[0]+' ': '';
const comp = sections[i].bending.type.replace('dipolefermi','bending');
const compid = comp + (sections[i].bending.length > 0 && $('#'+comp+'_'+sections[i].bending.length)[0]? '_'+sections[i].bending.length: '');
appendSvg("use", {href:"#"+compid, id:sections[i].bending.name.replace('.','_'), class: 'bending '+section+facility, style:"cursor: pointer", transform:"translate("+rescale(sections[i].start.x)+" "+rescale(sections[i].start.z)+") rotate("+gamma+") translate(-600 -200)"}, openTooltip);
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
appendLabel(sections[i].bending.name, 'bending '+section+facility, 'block', sections[i].start.x, sections[i].start.z, gamma+180, sections[i].bending.labelReverse);
}
alpha = beta;
appendComponent(sections[i].components, sections[i].start.x, sections[i].start.z, sections[j].start.x, sections[j].start.z, facility);
}
}
$(document).ready(function() {
$("svg").attr('height', window.innerHeight+'px');
init();
});
var eventsHandler;
let myhammer;
eventsHandler = {
haltEventListeners: ['touchstart', 'touchend', 'touchmove', 'touchleave', 'touchcancel','tap', 'pinch','pinchstart','pinchmove'],
init: function(options) {
var instance = options.instance, initialScale = 1, pannedX = 0, pannedY = 0;
// mylog('init', options, panZoomPanther);
myhammer = Hammer(options.svgElement, {
inputClass: Hammer.SUPPORT_POINTER_EVENTS ? Hammer.PointerEventInput : Hammer.TouchInput
});
myhammer.get('pinch').set({enable: true});
myhammer.on('panstart panmove', function(ev){
if (ev.type === 'panstart') {
pannedX = 0;
pannedY = 0;
}
panZoomPanther.panBy({x: ev.deltaX - pannedX, y: ev.deltaY - pannedY});
pannedX = ev.deltaX;
pannedY = ev.deltaY;
});
myhammer.on('pinchstart pinchmove', function(ev){
if (ev.type === 'pinchstart') {
initialScale = panZoomPanther.getZoom();
panZoomPanther.zoomAtPoint(initialScale * ev.scale, {x: ev.center.x, y: ev.center.y}, zoom, ev.scale);
// mylog(''); mylog('panZoomPanther.zoomAtPoint('+(initialScale * ev.scale)+', {x: '+ev.center.x+', y: '+ev.center.y+'})');
}
if (ev.type === 'pinchmove') {
oldZoom = zoom;
zoom = initialScale * ev.scale;
// mylog('zoom', zoom, ev.center.x);