threeJsHelper.js 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656
  1. IPE.app = {};
  2. IPE.helper = {};
  3. IPE.interceptors = {};
  4. String.prototype.endsWith = function(suffix) {
  5. return this.indexOf(suffix, this.length - suffix.length) !== -1;
  6. };
  7. Array.prototype.last = function() {
  8. return this[this.length-1];
  9. }
  10. IPE.app = {
  11. init : function(config) {
  12. var headerHeight = $('header').height();
  13. if($(window).height() < 500) {
  14. $("body").animate({ scrollTop: headerHeight }, "slow");
  15. }
  16. $.each(IPE.interceptors, function(index, interceptor) {
  17. interceptor.init();
  18. });
  19. Globals.init();
  20. IPE.app.initializeHelper();
  21. IPE.app.bindEvents();
  22. IPE.app.initData();
  23. // Getting info file
  24. $.ajax({
  25. url: infoUrl + config.defaultSize,
  26. success: function (data) {
  27. textureInfo = data;
  28. originalSizeArray[0] = textureInfo.originalSize.sizex;
  29. originalSizeArray[1] = textureInfo.originalSize.sizey;
  30. originalSizeArray[2] = textureInfo.originalSize.sizez;
  31. imgInfo = data.info;
  32. currentVolumeDimension.xmin = 0;
  33. currentVolumeDimension.xmax = textureInfo.originalSize.sizex;
  34. currentVolumeDimension.ymin = 0;
  35. currentVolumeDimension.ymax = textureInfo.originalSize.sizey;
  36. currentVolumeDimension.zmin = imgInfo.imgMin;
  37. currentVolumeDimension.zmax = imgInfo.imgMax;
  38. // downloading first image and starting
  39. helper.downloadImage(spriteUrl + textureInfo.sprites[0][0].$oid, 0, 0, true);
  40. $(document).trigger('basicsReady');
  41. },
  42. dataType: 'json'
  43. });
  44. container = document.getElementById( 'container' );
  45. $container = $(container);
  46. containerHeader = document.getElementById( 'container-header' );
  47. $containerHeader = $(containerHeader);
  48. containerOverview = document.getElementById('container-overview');
  49. $containerOverview = $(containerOverview);
  50. statsHelper = new StatsHelper($containerHeader.children('#container-stats'));
  51. // until now, it has to be initialized here, needs a new internal structure
  52. zoomHelper = new ZoomHelper();
  53. $(window).on('scroll', function(e) {
  54. if($(this).scrollTop() >= headerHeight) {
  55. $container.css('position', 'relative');
  56. $container.css('top', $(this).scrollTop() - headerHeight);
  57. } else {
  58. $container.css('top', 0);
  59. }
  60. });
  61. },
  62. initializeHelper: function() {
  63. helper = new Helper();
  64. geometryHelper = new GeometryHelper();
  65. stepHelper = new StepHelper();
  66. overviewHelper = new OverviewHelper();
  67. transferHelper = new TransferHelper();
  68. opacityPlotter = new OpacityPlotter();
  69. },
  70. initData: function() {
  71. volumeId = $('#volumeId').val();
  72. $resSpan = $('span#currentRes');
  73. volumeUrl = IPE.util.buildUrl('volumes/' + volumeId + '/');
  74. infoUrl = volumeUrl + 'texture-info/';
  75. spriteUrl = volumeUrl + 'sprite/';
  76. waitDiv = $('div#wait');
  77. helper.initializeShaders(IPE.util.buildUrl('static/shaders/three-shader.vert'), function(script) {
  78. vertexShader = script
  79. });
  80. helper.initializeShaders(IPE.util.buildUrl('static/shaders/three-shader-simple.frag'), function(script) {
  81. fragmentSimleShader = script
  82. });
  83. helper.initializeShaders(IPE.util.buildUrl('static/shaders/three-shader.frag'), function(script) {
  84. fragmentShader = script
  85. });
  86. },
  87. bindEvents : function() {
  88. $(document).on('firstImageOnLoad',function (e, firstImageParams){
  89. initTextures(imgInfo, firstImageParams, true);
  90. initFrameControls();
  91. stepHelper.initStepControls();
  92. initSliders();
  93. });
  94. $(document).on('imageOnLoad', function(e, imageParams) {
  95. initTextures(imgInfo, imageParams, false);
  96. if(useDownloadedTextureImmediately) {
  97. updateTexture();
  98. useDownloadedTextureImmediately = false;
  99. updateFrameControls();
  100. }
  101. });
  102. $(document).on('firstFrameSpritesCompleted', function() {
  103. init();
  104. addResolutionLinks();
  105. overviewHelper.initOverview(containerOverview);
  106. animate();
  107. });
  108. showPopup = false;
  109. $('#save-canvas').click(function(e, params) {
  110. if(params != undefined && params.source != undefined && params.source == 'animate-function') {
  111. window.open(params.imageUrl);
  112. return false;
  113. } else {
  114. saveImage = true;
  115. return false;
  116. }
  117. });
  118. $(window).on('resize', function() {
  119. var rendererSizeHolder = calculateWidthHeight();
  120. width = rendererSizeHolder.width.px;
  121. height = rendererSizeHolder.height.px;
  122. cameraRTT.aspect = width / height;
  123. cameraRTT.updateProjectionMatrix();
  124. camera.aspect = width / height;
  125. camera.updateProjectionMatrix();
  126. renderer.setSize( width, height );
  127. renderer.domElement.style.width = rendererSizeHolder.width.percent + '%';
  128. renderer.domElement.style.height = rendererSizeHolder.height.percent + '%';
  129. });
  130. $resolutionLinks.on('click', 'a', function(e) {
  131. e.preventDefault();
  132. e.stopPropagation();
  133. var $this = $(this);
  134. if($this.attr('href') == undefined) {
  135. return false;
  136. }
  137. requestedSize = $this.attr('data');
  138. $('.res-link').each(function(index, value) {
  139. var $value = $(value);
  140. $value.attr('href', '#');
  141. });
  142. $this.removeAttr('href');
  143. $.ajax({
  144. // todo test after remove of sync flag
  145. url: infoUrl + requestedSize,
  146. success: function (data) {
  147. framesDownloaded = 0;
  148. textures = {};
  149. currentTexture = 0;
  150. textureInfo = data;
  151. imgInfo = data.info;
  152. imgMin = imgInfo.imgMin;
  153. imgMax = imgInfo.imgMax;
  154. useDownloadedTextureImmediately = true;
  155. helper.downloadImage(spriteUrl + textureInfo.sprites[0][0].$oid, 0, 0, false);
  156. $resSpan.text(requestedSize);
  157. if($('input#hide-content-small-devices').is(':visible')) {
  158. $('input#hide-content-small-devices').trigger('click');
  159. }
  160. },
  161. dataType: 'json'
  162. });
  163. return false;
  164. });
  165. $('div.controls').on('click', function() {
  166. var $this = $(this),
  167. bottomControlsContainer = $('div#bottom-controls-container'),
  168. bottomControls = $('div#bottom-controls'),
  169. filledById = '',
  170. thisControlHolder = null;
  171. filledById = hideBottomControlsContainer();
  172. if(filledById === $this.attr('id')) {
  173. return;
  174. }
  175. thisControlHolder = $this.children('.control-holder')[0];
  176. thisControlHolder = $(thisControlHolder);
  177. bottomControls.append(thisControlHolder.children());
  178. bottomControls.attr('filledBy', $this.attr('id'));
  179. bottomControlsContainer.removeClass('hidden');
  180. // inform, that it is showed
  181. $this.trigger('controlsShowed');
  182. });
  183. $('input#hide-bottom-controls-container').on('click', function() {
  184. hideBottomControlsContainer();
  185. });
  186. $('div#menu-buttons-small-devices input').on('click', function() {
  187. var $this = $(this),
  188. target = $this.attr('data'),
  189. $target = $('#' + target),
  190. $overlay = $('div#overlay-small-devices'),
  191. $content = $('div#content-small-devices');
  192. $overlay.attr('source', target);
  193. $content.append($target.children());
  194. $overlay.show();
  195. });
  196. $('input#hide-content-small-devices').on('click', function() {
  197. var $overlay = $('div#overlay-small-devices'),
  198. $content = $('div#content-small-devices'),
  199. source = $overlay.attr('source'),
  200. $source = $('#' + source);
  201. $overlay.hide();
  202. $overlay.attr('source', '');
  203. $source.append($content.children());
  204. });
  205. var buttonAdvCons = $('input#show-adv-con');
  206. buttonAdvCons.on('click', function() {
  207. var advCons = $('div#advanced-controls');
  208. if(advCons.hasClass('hidden')) {
  209. advCons.removeClass('hidden');
  210. buttonAdvCons.val('hide adv cons');
  211. } else {
  212. advCons.addClass('hidden');
  213. buttonAdvCons.val('show adv cons');
  214. }
  215. });
  216. }
  217. }
  218. function initTextures(imgInfo, imageParams, whileInit) {
  219. // set initial array to index
  220. if(textures[imageParams.textureIndex] == undefined
  221. || textures[imageParams.textureIndex] == null) {
  222. textures[imageParams.textureIndex] = [];
  223. }
  224. // using texture
  225. texture = initTexture(imageParams.texture);
  226. textures[imageParams.textureIndex].push(texture);
  227. // fetch new sprites of same time frame
  228. if(imageParams.spriteIndex < imgInfo.numberOfSprites - 1) {
  229. nextSpriteIndex = imageParams.spriteIndex + 1;
  230. nextSpriteId = textureInfo.sprites[imageParams.textureIndex][nextSpriteIndex].$oid
  231. helper.downloadImage(spriteUrl + nextSpriteId, imageParams.textureIndex, nextSpriteIndex, whileInit);
  232. return;
  233. }
  234. // inform the rest, that the first frame is loaded completely
  235. if(whileInit && imageParams.textureIndex == 0) {
  236. $(document).trigger('firstFrameSpritesCompleted');
  237. }
  238. // todo some logic
  239. if(!imgInfo.multipleFrames) {
  240. currentTexture = 0;
  241. return;
  242. } else {
  243. var numberOfFrames = Object.keys(textureInfo.sprites).length,
  244. nextIndex = null,
  245. nextFrameName = null,
  246. nextFramePath = null;
  247. framesDownloaded++;
  248. if(framesDownloaded == 1) {
  249. currentTexture = 0;
  250. }
  251. currentMaxFrame = imgInfo.frameFrom + framesDownloaded - 1;
  252. if(framesDownloaded > 1) {
  253. // updating frame control maximums
  254. updateFrameControlsMaxFrame();
  255. }
  256. if(numberOfFrames == framesDownloaded) {
  257. return;
  258. } else {
  259. nextIndex = framesDownloaded;
  260. nextFrameName = textureInfo.sprites[nextIndex][0].$oid;
  261. var framePath = spriteUrl + nextFrameName;
  262. helper.downloadImage(framePath, nextIndex, false);
  263. }
  264. }
  265. }
  266. function initTexture(texture) {
  267. texture.magFilter = THREE.LinearFilter;
  268. texture.minFilter = THREE.LinearFilter;
  269. texture.needsUpdate = true;
  270. return texture;
  271. }
  272. function getCurrentTexture() {
  273. return textures[currentTexture];
  274. }
  275. function useFrameControls() {
  276. return (imgInfo.multipleFrames && (imgInfo.frameTo - imgInfo.frameFrom) != 0);
  277. }
  278. function initFrameControls() {
  279. if(!useFrameControls()) {
  280. return;
  281. }
  282. $('#frame-controls').removeClass('hidden');
  283. var $frameSlider = $('#frame-slider'),
  284. $playButton = $('#frame-play'),
  285. $pauseButton = $('#frame-pause'),
  286. $currentFrameInput = $('#currentFrame'),
  287. playId = $playButton.attr('id'),
  288. pauseId = $pauseButton.attr('id'),
  289. minFrame = imgInfo.frameFrom;
  290. $currentFrameInput.val(minFrame);
  291. var play = function() {
  292. if(Object.keys(textures).length == 1) {
  293. console.warn('only one texture loaded, can not play yet');
  294. return;
  295. }
  296. $playButton.addClass('hidden');
  297. $pauseButton.removeClass('hidden');
  298. playFrames = true;
  299. $frameSlider.slider({disabled: true});
  300. $currentFrameInput.prop('disabled', true);
  301. }
  302. var pause = function() {
  303. $playButton.removeClass('hidden');
  304. $pauseButton.addClass('hidden');
  305. playFrames = false;
  306. $frameSlider.slider({disabled: false});
  307. $currentFrameInput.prop('disabled', false);
  308. }
  309. $('.frame-button').click(function() {
  310. var $this = $(this),
  311. thisId = $this.attr('id');
  312. if(thisId == playId) {
  313. play();
  314. } else if(thisId == pauseId) {
  315. pause();
  316. }
  317. });
  318. $(document).on('zoomActionFinished', function(e, params) {
  319. zoomedIn = params.zoomAction == 'zoomIn';
  320. if(zoomedIn) {
  321. pause();
  322. currentTexture = minFrame + params.textureNumber;
  323. updateFrameControls();
  324. $frameSlider.slider({disabled: true});
  325. $currentFrameInput.prop('disabled', true);
  326. $playButton.prop('disabled', true);
  327. $pauseButton.prop('disabled', true);
  328. } else {
  329. $frameSlider.slider({disabled: false});
  330. $currentFrameInput.prop('disabled', false);
  331. $playButton.prop('disabled', false);
  332. $pauseButton.prop('disabled', false);
  333. }
  334. });
  335. $frameSlider.slider(
  336. {
  337. min: minFrame,
  338. max: currentMaxFrame,
  339. slide: function( event, ui ) {
  340. currentTexture = ui.value - minFrame;
  341. updateTexture();
  342. $currentFrameInput.val(ui.value);
  343. }
  344. }
  345. );
  346. $currentFrameInput.change(function() {
  347. var value = parseInt($(this).val());
  348. if(value >= imgInfo.frameFrom && currentMaxFrame >= value) {
  349. currentTexture = value - minFrame;
  350. updateTexture();
  351. $frameSlider.slider('value', value);
  352. } else {
  353. $(this).val($frameSlider.slider('value'));
  354. }
  355. });
  356. }
  357. function updateFrameControlsMaxFrame() {
  358. if(!useFrameControls()) {
  359. return;
  360. }
  361. var $frameSlider = $('#frame-slider');
  362. $frameSlider.slider('option', 'max', currentMaxFrame);
  363. }
  364. function updateFrameControls() {
  365. if(!useFrameControls()) {
  366. return;
  367. }
  368. var $frameSlider = $('#frame-slider'),
  369. $currentFrameInput = $('#currentFrame'),
  370. minFrame = imgInfo.frameFrom,
  371. value = currentTexture + minFrame;
  372. $frameSlider.slider('value', value);
  373. $currentFrameInput.val(value);
  374. }
  375. function init() {
  376. rendererSizeHolder = calculateWidthHeight();
  377. width = rendererSizeHolder.width.px;
  378. height = rendererSizeHolder.height.px;
  379. //width = window.innerWidth;
  380. //height = window.innerHeight;
  381. camera = new THREE.PerspectiveCamera( 45, width / height, .1, 1000 );
  382. camera.position.z = 2;
  383. cameraRTT = new THREE.PerspectiveCamera( 45, width / height, .1, 1000 );
  384. cameraRTT.position.z = 2;
  385. scene = new THREE.Scene();
  386. sceneRTT = new THREE.Scene();
  387. rtTexture = new THREE.WebGLRenderTarget( width, height, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat } );
  388. var geometry = geometryHelper.createBoxGeometry(originalDimension, currentVolumeDimension);
  389. var attributes = {
  390. frontColor: {type: 'c', value: [] }
  391. }
  392. material = new THREE.ShaderMaterial({
  393. attributes: attributes,
  394. vertexShader: vertexShader,
  395. fragmentShader: fragmentSimleShader,
  396. side: THREE.FrontSide
  397. });
  398. var spriteMaps = getCurrentTexture();
  399. var transferImageData = transferHelper.getCurrentTransferFunction();
  400. var transferTexture = new THREE.Texture(transferImageData);
  401. transferTexture.needsUpdate = true;
  402. var uniforms = {
  403. tBackground: {type: 't', value: rtTexture},
  404. tvSlices: {type: 'tv', value: spriteMaps},
  405. tTransfer: { type: 't', value: transferTexture},
  406. steps: {type: 'f', value: 100},
  407. numberOfSlices: {type: 'f', value: imgInfo.numberOfSlices },
  408. numberOfSprites: {type: 'f', value: imgInfo.numberOfSprites },
  409. slicesPerSprite: {type: 'f', value: imgInfo.slicesPerSprite },
  410. slicesOverX: {type: 'f', value: imgInfo.slicesOverX },
  411. slicesOverY: {type: 'f', value: imgInfo.slicesOverY },
  412. };
  413. materialScreen = new THREE.ShaderMaterial({
  414. attributes: attributes,
  415. uniforms: uniforms,
  416. vertexShader: vertexShader,
  417. fragmentShader: fragmentShader,
  418. side: THREE.BackSide,
  419. transparent: true
  420. });
  421. backgroundBox = new THREE.Mesh(geometry, material);
  422. sceneRTT.add(backgroundBox);
  423. frontBox = new THREE.Mesh(geometry, materialScreen);//
  424. scene.add(frontBox);
  425. objectsToIntersect.push(frontBox);
  426. translateBoxes(-0.5, -0.5, -0.5);
  427. rotateBoxesX(Math.PI / -2);
  428. //rotateBoxesY(Math.PI);
  429. //rotateBoxesZ(Math.PI);
  430. renderer = new THREE.WebGLRenderer();
  431. renderer.setSize(width, height);
  432. renderer.domElement.style.width = rendererSizeHolder.width.percent + '%';
  433. renderer.domElement.style.height = rendererSizeHolder.height.percent + '%';
  434. renderer.setClearColor(0xffffff, 1);
  435. container.appendChild(renderer.domElement);
  436. maximumTextureSize = renderer.context.getParameter(renderer.context.MAX_TEXTURE_SIZE);
  437. // we have to take an power of 2 less
  438. maximumTextureSize /= 2;
  439. $canvas = $('canvas', $container);
  440. controls1 = new THREE.OrbitControls( camera, renderer.domElement );
  441. controls1.damping = 0.2;
  442. controls2 = new THREE.OrbitControls( cameraRTT, renderer.domElement );
  443. controls2.damping = 0.2;
  444. rendererContext = renderer.context;
  445. raycaster = new THREE.Raycaster();
  446. }
  447. function rotateBoxesX(radian) {
  448. rotationMatrix = new THREE.Matrix4().makeRotationX(radian);
  449. rotateBoxes(rotationMatrix);
  450. }
  451. function rotateBoxesY(radian) {
  452. rotationMatrix = new THREE.Matrix4().makeRotationY(radian);
  453. rotateBoxes(rotationMatrix);
  454. }
  455. function rotateBoxesZ(radian) {
  456. rotationMatrix = new THREE.Matrix4().makeRotationZ(radian);
  457. rotateBoxes(rotationMatrix);
  458. }
  459. function rotateBoxes(matrix) {
  460. backgroundBox.applyMatrix(rotationMatrix);
  461. frontBox.applyMatrix(rotationMatrix);
  462. }
  463. function translateBoxes(x, y, z) {
  464. translationMatrix = new THREE.Matrix4().makeTranslation(x, y, z);
  465. backgroundBox.applyMatrix(translationMatrix);
  466. frontBox.applyMatrix(translationMatrix);
  467. }
  468. function initSliders() {
  469. initLayerSliders();
  470. // init gray value slider
  471. GenericSlider.initSlider(
  472. slider = $( "#gray-slider" ),
  473. sliderInputs = $('input.gray'),
  474. minGray,
  475. maxGray,
  476. function(values) {
  477. $(document).trigger(
  478. 'opacityBordersChanged',
  479. {
  480. minGray: values[0],
  481. maxGray : values[1]
  482. }
  483. );
  484. }
  485. );
  486. $('#gray-slider-container').on('controlsShowed', function() {
  487. var values = $("#gray-slider").slider('values');
  488. $(document).trigger('opacityBordersChanged', { minGray: values[0], maxGray: values[1] });
  489. });
  490. GenericSlider.initSimpleSlider(
  491. slider = $('#background-slider'),
  492. sliderInput = $('#background-input'),
  493. startVal = 255,
  494. 0,
  495. 255,
  496. function(value) {
  497. var colorFloat = calculateGrayFloat(value);
  498. renderer.setClearColor(
  499. new THREE.Color(colorFloat, colorFloat, colorFloat),
  500. 1
  501. );
  502. }
  503. );
  504. }
  505. function initLayerSliders() {
  506. // init xlayer slider
  507. GenericSlider.initSlider(
  508. $( "#xlayer-slider" ),
  509. sliderInputs = $('input.xlayer'),
  510. currentVolumeDimension.xmin,
  511. currentVolumeDimension.xmax,
  512. function(values) {
  513. dimMin = currentVolumeDimension.xmin;
  514. dimMax = currentVolumeDimension.xmax;
  515. currentDimension.xmin = calculateLayerFloat(values[0], dimMin, dimMax);
  516. currentDimension.xmax = calculateLayerFloat(values[1], dimMin, dimMax);
  517. updateCubeLayers(currentDimension);
  518. },
  519. function() {
  520. values = Array(2);
  521. values[0] = calculateLayerInt(currentDimension.xmin, currentVolumeDimension.xmin, currentVolumeDimension.xmax );
  522. values[1] = calculateLayerInt(currentDimension.xmax, currentVolumeDimension.xmin, currentVolumeDimension.xmax );
  523. return values;
  524. }
  525. );
  526. // init ylayer slider
  527. GenericSlider.initSlider(
  528. $( "#ylayer-slider" ),
  529. sliderInputs = $('input.ylayer'),
  530. currentVolumeDimension.ymin,
  531. currentVolumeDimension.ymax,
  532. function(values) {
  533. dimMin = currentVolumeDimension.ymin;
  534. dimMax = currentVolumeDimension.ymax;
  535. currentDimension.ymin = calculateLayerFloat(values[0], dimMin, dimMax);
  536. currentDimension.ymax = calculateLayerFloat(values[1], dimMin, dimMax);
  537. updateCubeLayers(currentDimension);
  538. },
  539. function() {
  540. values = Array(2);
  541. values[0] = calculateLayerInt(currentDimension.ymin, currentVolumeDimension.ymin, currentVolumeDimension.ymax );
  542. values[1] = calculateLayerInt(currentDimension.ymax, currentVolumeDimension.ymin, currentVolumeDimension.ymax );
  543. return values;
  544. }
  545. );
  546. // init zlayer slider
  547. GenericSlider.initSlider(
  548. $( "#zlayer-slider" ),
  549. sliderInputs = $('input.zlayer'),
  550. currentVolumeDimension.zmin,
  551. currentVolumeDimension.zmax,
  552. function(values) {
  553. dimMin = currentVolumeDimension.zmin;
  554. dimMax = currentVolumeDimension.zmax;
  555. currentDimension.zmin = calculateLayerFloat(values[0], dimMin, dimMax),
  556. currentDimension.zmax = calculateLayerFloat(values[1], dimMin, dimMax);
  557. updateCubeLayers(currentDimension);
  558. },
  559. function() {
  560. values = Array(2);
  561. values[0] = calculateLayerInt(currentDimension.zmin, currentVolumeDimension.zmin, currentVolumeDimension.zmax );
  562. values[1] = calculateLayerInt(currentDimension.zmax, currentVolumeDimension.zmin, currentVolumeDimension.zmax );
  563. return values;
  564. }
  565. );
  566. }
  567. function repositionLayerSliders() {
  568. initLayerSliders();
  569. $.each($('.slider.layer'), function(index, value) {
  570. $(value).trigger('reposition');
  571. });
  572. updateCubeLayers(currentDimension);
  573. }
  574. var prevTime = Date.now();
  575. var fps = 0;
  576. var frames = 0;
  577. function animate() {
  578. requestAnimationFrame( animate );
  579. $container.trigger('animation');
  580. var numberOfTextures = Object.keys(textures).length;
  581. var now = Date.now();
  582. frames++;
  583. if(now > prevTime + 1000) {
  584. fps = (frames * 1000) / (now - prevTime);
  585. if(adjustSteps) {
  586. if(fps < 10) {
  587. stepHelper.decreaseSteps();
  588. } else if(fps > 15) {
  589. stepHelper.increaseSteps();
  590. }
  591. }
  592. prevTime = now;
  593. frames = 0;
  594. }
  595. if(playFrames && numberOfTextures > 1) {
  596. var timeStamp = (new Date()).getTime();
  597. if(timeStamp - textureTimestamp > 400) {
  598. currentTexture++;
  599. if(currentTexture >= numberOfTextures) {
  600. currentTexture = 0;
  601. }
  602. updateTexture();
  603. textureTimestamp = timeStamp;
  604. updateFrameControls();
  605. }
  606. }
  607. if(nextCubeDeletionTimeStamp == null && intersectCubesTimeStamps.length != 0) {
  608. nextCubeDeletionTimeStamp = intersectCubesTimeStamps.shift();
  609. }
  610. if((Date.now() - nextCubeDeletionTimeStamp) > 1500) {
  611. cubeToDelete = intersectCubes.shift();
  612. scene.remove(cubeToDelete);
  613. nextCubeDeletionTimeStamp = null;
  614. }
  615. if(transferHelper.transferFunctionChanged()) {
  616. var transfer = new THREE.Texture(transferHelper.getCurrentTransferFunction());
  617. transfer.needsUpdate = true;
  618. materialScreen.uniforms.tTransfer.value = transfer;
  619. }
  620. cameraPoint = camera.position.clone();
  621. overviewHelper.updateCameraPosition(cameraPoint);
  622. statsHelper.update();
  623. controls1.update();
  624. controls2.update();
  625. render();
  626. if(saveImage) {
  627. $('#save-canvas').trigger('click', { source: 'animate-function', imageUrl: renderer.domElement.toDataURL() });
  628. saveImage = false;
  629. }
  630. }
  631. function updateTexture(textures) {
  632. if(textures == undefined || textures == null) {
  633. textures = getCurrentTexture();
  634. }
  635. $.each(textures, function(index, texture) {
  636. value.needsUpdate = true;
  637. });
  638. materialScreen.uniforms.tvSlices.value = textures;
  639. }
  640. function render() {
  641. renderer.clear();
  642. renderer.context.clearDepth(-50.0);
  643. renderer.context.depthFunc(renderer.context.GEQUAL);
  644. renderer.render(sceneRTT, cameraRTT, rtTexture, true);
  645. renderer.context.clearDepth(50.0);
  646. renderer.context.depthFunc(renderer.context.LEQUAL);
  647. renderer.render(scene, camera);
  648. overviewHelper.render();
  649. }
  650. function updateCubeLayers(geometryDimension) {
  651. var geometry = geometryHelper.createBoxGeometry(geometryDimension, currentVolumeDimension);
  652. var colorArray = geometry.attributes.frontColor.array,
  653. positionArray = geometry.attributes.position.array;
  654. frontBox.geometry.attributes.frontColor.array = colorArray;
  655. frontBox.geometry.attributes.frontColor.needsUpdate = true;
  656. frontBox.geometry.attributes.position.array = positionArray;
  657. frontBox.geometry.attributes.position.needsUpdate = true;
  658. }
  659. // invert function of calculateLayerFloat
  660. function calculateLayerInt(position, dimMin, dimMax) {
  661. if(position <= 0.005) {
  662. return dimMin;
  663. }
  664. if(position >= 0.995) {
  665. return dimMax;
  666. }
  667. value = Math.round(position * (dimMax - dimMin) + dimMin);
  668. return value;
  669. }
  670. // calculate the float value for a layer input integer
  671. // 150 of [0, 299] will be 0.5
  672. function calculateLayerFloat(value, dimMin, dimMax) {
  673. var floatVal = (value - dimMin) / (dimMax - dimMin);
  674. if (floatVal == 0) {
  675. return 0.005;
  676. }
  677. if (floatVal == 1) {
  678. return 0.995;
  679. }
  680. return floatVal;
  681. }
  682. function calculateGrayFloat(value) {
  683. return value / 255.0;
  684. }
  685. function distance (v1, v2) {
  686. dx = v1.x - v2.x;
  687. dy = v1.y - v2.y;
  688. dz = v1.z - v2.z;
  689. return Math.sqrt(dx*dx+dy*dy+dz*dz);
  690. }
  691. function calculateWidthHeight() {
  692. downScaleFactor = 0.66;
  693. valueholder = {
  694. height: {},
  695. width: {}
  696. }
  697. containerHeight = $container.height();
  698. volumeInfoHeight = $('#volume-information').height();
  699. headerHeight = $('header').height();
  700. valueholder.height.px = (containerHeight - volumeInfoHeight) * downScaleFactor;
  701. volumeInfoHeightPercent = Math.floor(volumeInfoHeight / containerHeight * 100);
  702. valueholder.height.percent = 100 - volumeInfoHeightPercent;
  703. valueholder.width.px = $container.width() * downScaleFactor;
  704. valueholder.width.percent = 100;
  705. return valueholder;
  706. }
  707. function hideBottomControlsContainer() {
  708. var bottomControlsContainer = $('div#bottom-controls-container'),
  709. bottomControls = $('div#bottom-controls'),
  710. filledById = bottomControls.attr('filledBy'),
  711. filledBy = $('#' + filledById);
  712. // writing data back to original, because append MOVES the children
  713. if(filledBy.length == 1) {
  714. filledBy = $(filledBy[0]);
  715. filledByControlHolder = filledBy.children('.control-holder')[0];
  716. $(filledByControlHolder).append(bottomControls.children());
  717. }
  718. bottomControls.attr('filledBy', '');
  719. bottomControlsContainer.addClass('hidden');
  720. return filledById;
  721. }
  722. function addResolutionLinks() {
  723. $resSpan.text(config.defaultSize);
  724. textureSizes = config.textureSizes;
  725. textureSizes.forEach(function(size) {
  726. if(size > maximumTextureSize) {
  727. return;
  728. }
  729. href = size == config.defaultSize ? '' : 'href="#"';
  730. $resolutionLinks.append('<a '+href+' class="res-link" data="'+size+'">'+size+'</a> ');
  731. });
  732. }
  733. ;var volumeId;
  734. var stats, container, $container, containerHeader, $containerHeader, $canvas, cameraRTT, camera, sceneRTT, scene, renderer, controls, controls2;
  735. var maximumTextureSize;
  736. var containerOverview, $containerOverview;
  737. var $resSpan;
  738. var $resolutionLinks;
  739. var raycaster;
  740. var width, height;
  741. var steps, adjustSteps;
  742. var rtTexture, material;
  743. var backgroundBox, frontBox;
  744. var objectsToIntersect = [];
  745. var minGray = 5, maxGray = 255;
  746. var originalDimension,
  747. zoomedDimension,
  748. currentDimension,
  749. originalVolumeDimension,
  750. zoomedVolumeDimension,
  751. currentVolumeDimension,
  752. volumeUrl,
  753. infoUrl,
  754. spriteUrl,
  755. imgInfo = null,
  756. textureInfo = null,
  757. originalSizeArray = Array(3),
  758. zoomedInfo,
  759. rotationMatrix;
  760. var textures = {},
  761. currentTexture = 0,
  762. useDownloadedTextureImmediately = false,
  763. textureTimestamp = (new Date()).getTime(),
  764. playFrames = false,
  765. currentMaxFrame = 0;
  766. var framesDownloaded = 0,
  767. cachedImages = {};
  768. var vertexShader = null,
  769. fragmentSimleShader = null,
  770. fragmentShader = null;
  771. var intersectCubes = [],
  772. intersectCubesTimeStamps = []
  773. nextCubeDeletionTimeStamp = null,
  774. zoomedIn = false;
  775. var helper,
  776. geometryHelper,
  777. stepHelper,
  778. overviewHelper,
  779. transferHelper,
  780. zoomHelper,
  781. opacityPlotter,
  782. statsHelper;
  783. var waitDiv;
  784. var saveImage = false;
  785. // prefetch first image to cache it
  786. var progressContainer,
  787. imageProgress,
  788. progressSpan;
  789. var Globals = (function() {
  790. return {
  791. init: function() {
  792. originalDimension = new GeometryDimension();
  793. zoomedDimension = new GeometryDimension();
  794. currentDimension = originalDimension;
  795. originalVolumeDimension = new VolumeDimension();
  796. zoomedVolumeDimension = new VolumeDimension();
  797. currentVolumeDimension = originalVolumeDimension;
  798. $resolutionLinks = $('#resolution-links');
  799. }
  800. }
  801. }());
  802. ;var GeometryHelper = function() {
  803. return {
  804. createBoxGeometry: function(dimension, volumeDimension) {
  805. var vertexPos = [
  806. //front face first
  807. [dimension.xmin, dimension.ymin, dimension.zmax],
  808. [dimension.xmax, dimension.ymin, dimension.zmax],
  809. [dimension.xmax, dimension.ymax, dimension.zmax],
  810. //front face second
  811. [dimension.xmin, dimension.ymin, dimension.zmax],
  812. [dimension.xmax, dimension.ymax, dimension.zmax],
  813. [dimension.xmin, dimension.ymax, dimension.zmax],
  814. // back face first
  815. [dimension.xmin, dimension.ymin, dimension.zmin],
  816. [dimension.xmin, dimension.ymax, dimension.zmin],
  817. [dimension.xmax, dimension.ymax, dimension.zmin],
  818. // back face second
  819. [dimension.xmin, dimension.ymin, dimension.zmin],
  820. [dimension.xmax, dimension.ymax, dimension.zmin],
  821. [dimension.xmax, dimension.ymin, dimension.zmin],
  822. // top face first
  823. [dimension.xmin, dimension.ymax, dimension.zmin],
  824. [dimension.xmin, dimension.ymax, dimension.zmax],
  825. [dimension.xmax, dimension.ymax, dimension.zmax],
  826. // top face second
  827. [dimension.xmin, dimension.ymax, dimension.zmin],
  828. [dimension.xmax, dimension.ymax, dimension.zmax],
  829. [dimension.xmax, dimension.ymax, dimension.zmin],
  830. // bottom face first
  831. [dimension.xmin, dimension.ymin, dimension.zmin],
  832. [dimension.xmax, dimension.ymin, dimension.zmin],
  833. [dimension.xmax, dimension.ymin, dimension.zmax],
  834. // bottom face second
  835. [dimension.xmin, dimension.ymin, dimension.zmin],
  836. [dimension.xmax, dimension.ymin, dimension.zmax],
  837. [dimension.xmin, dimension.ymin, dimension.zmax],
  838. // right face first
  839. [dimension.xmax, dimension.ymin, dimension.zmin],
  840. [dimension.xmax, dimension.ymax, dimension.zmin],
  841. [dimension.xmax, dimension.ymax, dimension.zmax],
  842. // right face second
  843. [dimension.xmax, dimension.ymin, dimension.zmin],
  844. [dimension.xmax, dimension.ymax, dimension.zmax],
  845. [dimension.xmax, dimension.ymin, dimension.zmax],
  846. // left face first
  847. [dimension.xmin, dimension.ymin, dimension.zmin],
  848. [dimension.xmin, dimension.ymin, dimension.zmax],
  849. [dimension.xmin, dimension.ymax, dimension.zmax],
  850. // left face second
  851. [dimension.xmin, dimension.ymin, dimension.zmin],
  852. [dimension.xmin, dimension.ymax, dimension.zmax],
  853. [dimension.xmin, dimension.ymax, dimension.zmin]
  854. ];
  855. var positions = [];
  856. var colors = [];
  857. for(var i = 0; i < vertexPos.length; i++) {
  858. var backCounter = vertexPos.length - 1 - i,
  859. x = vertexPos[backCounter][0],
  860. y = vertexPos[backCounter][1],
  861. z = vertexPos[backCounter][2];
  862. positions.push(x);
  863. positions.push(y);
  864. positions.push(z * volumeDimension.getZStretchFactor());
  865. colors.push(x);
  866. colors.push(y);
  867. colors.push(z);
  868. colors.push(1.0);
  869. }
  870. var geometry = new THREE.BufferGeometry();
  871. var bufferPositions = new Float32Array(positions);
  872. geometry.addAttribute( 'position', new THREE.BufferAttribute( bufferPositions, 3 ) );
  873. geometry.addAttribute( 'frontColor', new THREE.BufferAttribute(new Float32Array(colors), 4));
  874. geometry.computeBoundingSphere();
  875. return geometry;
  876. }
  877. }
  878. }
  879. var GeometryDimension = function() {
  880. this.xmin = 0.005;
  881. this.xmax = 0.995;
  882. this.ymin = 0.005;
  883. this.ymax = 0.995;
  884. this.zmin = 0.005;
  885. this.zmax = 0.995;
  886. }
  887. var VolumeDimension = function() {
  888. this.xmin;
  889. this.xmax;
  890. this.ymin;
  891. this.ymax;
  892. this.zmin;
  893. this.zmax;
  894. return {
  895. getZStretchFactor: function() {
  896. return (this.zmax - this.zmin + 1) / (this.xmax - this.xmin);
  897. }
  898. }
  899. }
  900. ;var Helper = function() {
  901. var messagePopup = $('#popup'),
  902. popupVisible = messagePopup.hasClass('hidden'),
  903. progressContainer = $('#progress-container'),
  904. imageProgress = $('#image-progress'),
  905. progressSpan = $('#texturePath');
  906. return {
  907. initializeShaders: function(url, callback) {
  908. $.ajax({
  909. url: url,
  910. error: function() {
  911. console.error('failed to load shader file from: ' + url);
  912. },
  913. success: callback
  914. });
  915. },
  916. downloadImage: function (texturePath, textureIndex, spriteIndex, whileInit) {
  917. me = this;
  918. onProgressHolder = me.showProgress(texturePath);
  919. if(!texturePath.endsWith('/')) {
  920. texturePath += '/';
  921. }
  922. var xmlHttp = new XMLHttpRequest();
  923. xmlHttp.open('GET', texturePath, true);
  924. xmlHttp.onprogress = onProgressHolder.onProgressFunction;
  925. xmlHttp.onload = function(e) {
  926. var blob = new Blob([xmlHttp.response], {
  927. type: this.getResponseHeader('content-type')
  928. });
  929. var blobSrc = window.URL.createObjectURL(blob);
  930. var image = new Image();
  931. var texture = new THREE.Texture(image);
  932. image.onload = function() {
  933. me.hideProgress();
  934. texture.needsUpdate = true;
  935. var params = {
  936. textureIndex: textureIndex,
  937. spriteIndex: spriteIndex,
  938. texture: texture
  939. };
  940. if(textureIndex == 0 && whileInit) {
  941. $(document).trigger('firstImageOnLoad', params);
  942. } else {
  943. $(document).trigger('imageOnLoad', params);
  944. }
  945. }
  946. image.src = blobSrc;
  947. };
  948. xmlHttp.responseType = 'blob';
  949. xmlHttp.send();
  950. },
  951. showProgress: function(texturePath) {
  952. progressContainer.removeClass('hidden');
  953. progressSpan.text(texturePath);
  954. return {
  955. onProgressFunction: function(e) {
  956. if (e.lengthComputable) {
  957. value = Math.floor(e.loaded / e.total * 100);
  958. imageProgress.val(value);
  959. }
  960. }
  961. }
  962. },
  963. hideProgress: function() {
  964. imageProgress.val(0);
  965. progressSpan.text('');
  966. progressContainer.addClass('hidden');
  967. },
  968. displayMessage: function(message, fadeOutAutomatically, callback, timeout) {
  969. var me = this;
  970. messagePopup.html(message);
  971. messagePopup.show();
  972. if(fadeOutAutomatically) {
  973. this.fadeoutMessage(callback, timeout);
  974. }
  975. },
  976. fadeoutMessage: function(callback, timeout) {
  977. if(timeout == undefined) {
  978. timeout = 0;
  979. }
  980. setTimeout(function() {
  981. messagePopup.fadeOut(400, function() {
  982. $(this).html('');
  983. if(callback) {
  984. callback();
  985. }
  986. });
  987. }, timeout);
  988. }
  989. };
  990. }
  991. ;var OpacityPlotter = function() {
  992. // we have 255 colors
  993. var coordinateLength = 255;
  994. // set with respect on plotter height
  995. var height = 40;
  996. // array for holding the x coordinates
  997. var coordinates = Array(coordinateLength);
  998. // array for holding the y coordinates values elementOf [0, height]
  999. var linePosition = Array(coordinateLength);
  1000. // array holding the resulting opacities, that will be generated
  1001. // of line position, values elementof [0, 255]
  1002. var opacities = Array(coordinateLength);
  1003. for(counter = 0; counter < coordinateLength; counter++) {
  1004. coordinates[counter] = counter;
  1005. linePosition[counter] = 0;
  1006. opacities[counter] = 255;
  1007. }
  1008. var stage = new Kinetic.Stage({
  1009. container : 'opacity-plot',
  1010. width : coordinateLength,
  1011. height: height
  1012. });
  1013. var layer = new Kinetic.Layer();
  1014. var rect = new Kinetic.Rect({
  1015. x: 0,
  1016. y: 0,
  1017. width: stage.getWidth(),
  1018. height: stage.getHeight(),
  1019. fill: '#cccccc'
  1020. });
  1021. layer.add(rect);
  1022. var spline = new Kinetic.Line({
  1023. points: getResultingPoints(),
  1024. stroke: 'red',
  1025. strokeWidth: 3,
  1026. lineCap: 'round'
  1027. });
  1028. layer.add(spline);
  1029. stage.add(layer);
  1030. stage.on("mousedown", function() {
  1031. processEvent();
  1032. });
  1033. stage.on("mousemove", function(e) {
  1034. if(e.evt.which == 1) {
  1035. processEvent();
  1036. }
  1037. });
  1038. $('#transfer-function-definition').on('controlsShowed', function() {
  1039. populateOpacities();
  1040. });
  1041. $('input#opacity-visible').on('click', function() {
  1042. setToFixedValue(255);
  1043. });
  1044. $('input#opacity-invisible').on('click', function() {
  1045. setToFixedValue(0);
  1046. });
  1047. function setToFixedValue(value) {
  1048. var opacityValue = value;
  1049. var yValue = height - ((value / 255) * height)
  1050. for(counter = 0; counter < opacities.length; counter++) {
  1051. opacities[counter] = opacityValue ;
  1052. linePosition[counter] = yValue;
  1053. }
  1054. populateOpacities();
  1055. spline.setPoints(getResultingPoints());
  1056. layer.draw();
  1057. }
  1058. function populateOpacities() {
  1059. $(document).trigger('opacityChanged', { opacities: opacities.slice() });
  1060. }
  1061. function processEvent() {
  1062. var mousePosition = stage.getPointerPosition();
  1063. calculateOpacities(mousePosition);
  1064. spline.setPoints(getResultingPoints());
  1065. layer.draw();
  1066. }
  1067. function calculateOpacities(mousePosition) {
  1068. // Set area of click to this value
  1069. var xMin = (mousePosition.x - 2 >= 0) ? mousePosition.x - 2 : 0;
  1070. var xMax = (mousePosition.x + 2 <= 255) ? mousePosition.x + 2 : 255;
  1071. var opacityValue = (height - mousePosition.y) / height;
  1072. opacityValue *= 255;
  1073. for(counter = xMin; counter <= xMax; counter++) {
  1074. linePosition[counter] = mousePosition.y;
  1075. opacities[counter] = opacityValue;
  1076. }
  1077. populateOpacities();
  1078. }
  1079. function getResultingPoints() {
  1080. return combineArrays(coordinates, linePosition);
  1081. }
  1082. function combineArrays(array1, array2) {
  1083. return $.map(array1, function(v, i) { return [v, array2[i]]; });
  1084. }
  1085. }
  1086. ;var StatsHelper = function(parentElement) {
  1087. if(IPE.environment != 'dev') {
  1088. // fill parentElement with emptyness
  1089. parentElement.append('&nbsp;');
  1090. // we don't want to do display anything
  1091. // in production
  1092. return {
  1093. update: function() {}
  1094. };
  1095. }
  1096. var stats = new Stats();
  1097. var parentElement = parentElement;
  1098. parentElement.append(stats.domElement);
  1099. return {
  1100. update: function() {
  1101. stats.update();
  1102. }
  1103. }
  1104. };
  1105. ;var StepHelper = function() {
  1106. // default is the step 100
  1107. currentStepIndex = 2;
  1108. // steps just defined
  1109. availableSteps = [10, 20, 50, 80, 100, 150, 200];
  1110. return {
  1111. decreaseSteps: function() {
  1112. var currentStepIndex = this.determineCurrentStepIndex();
  1113. if(currentStepIndex > 0) {
  1114. this.updateStepValue(availableSteps[currentStepIndex - 1], true);
  1115. }
  1116. },
  1117. increaseSteps: function() {
  1118. var currentStepIndex = this.determineCurrentStepIndex();
  1119. if(currentStepIndex > -1 && currentStepIndex < availableSteps.length - 1) {
  1120. this.updateStepValue(availableSteps[currentStepIndex + 1], true);
  1121. }
  1122. },
  1123. determineCurrentStepIndex: function() {
  1124. var minDeviation = null,
  1125. minDeviationIndex;
  1126. // first we have to find an appropiate predefined stepValue for input stepvalue
  1127. for(var index = 0; index < availableSteps.length; index++) {
  1128. deviation = Math.abs(steps - availableSteps[index]);
  1129. if(minDeviation == null || deviation < minDeviation) {
  1130. minDeviation = deviation;
  1131. minDeviationIndex = index;
  1132. }
  1133. }
  1134. if(minDeviation !== null) {
  1135. return minDeviationIndex;
  1136. } else {
  1137. return -1;
  1138. }
  1139. },
  1140. updateStepValue: function(stepValue, updateInputField) {
  1141. steps = stepValue;
  1142. materialScreen.uniforms.steps.value = steps;
  1143. if(updateInputField) {
  1144. $('#steps').val(stepValue);
  1145. }
  1146. },
  1147. initStepControls: function() {
  1148. var me = this,
  1149. stepsInput = $('#steps'),
  1150. stepsAdjustInput = $('#steps-adjust');
  1151. steps = stepsInput.val();
  1152. stepsInput.change(function() {
  1153. steps = stepsInput.val();
  1154. me.updateStepValue(steps, false);
  1155. });
  1156. adjustSteps = stepsAdjustInput.is(':checked');
  1157. stepsAdjustInput.change(function() {
  1158. adjustSteps = $(this).is(':checked');
  1159. if(adjustSteps) {
  1160. stepsInput.prop('disabled', true);
  1161. } else {
  1162. stepsInput.prop('disabled', false);
  1163. }
  1164. });
  1165. }
  1166. };
  1167. };
  1168. ;var TransferHelper = function() {
  1169. var me = this,
  1170. changed = false,
  1171. canvas = document.getElementById('transfer-function'),
  1172. $canvas = $(canvas),
  1173. context = canvas.getContext('2d'),
  1174. hiddenCanvas = document.getElementById('hidden-transfer'),
  1175. hiddenContext = hiddenCanvas.getContext('2d'),
  1176. transferSpanHolder = $('#transfer-span-holder'),
  1177. transfer = $('#transfer'),
  1178. disabled = true,
  1179. handles = $('span.transfer'),
  1180. $standardTf = $('img#standard-tf').get(0),
  1181. offsetLeft = {
  1182. blue: 0,
  1183. turquois: 0.25,
  1184. green: 0.5,
  1185. orange: 0.75,
  1186. red: 1
  1187. },
  1188. colorCodes = {
  1189. blue: '#0000FF',
  1190. turquois: '#00FFFF',
  1191. green: '#00FF00',
  1192. orange: '#FFFF00',
  1193. red: '#FF0000'
  1194. },
  1195. opacities = Array(255);
  1196. //black values are disabled defaultly
  1197. opacities[0] = 0;
  1198. for(counter = 0; counter < opacities.length; counter++) {
  1199. opacities[counter] = 255;
  1200. if (counter <= minGray) {
  1201. opacities[counter] = 0;
  1202. }
  1203. }
  1204. $('input#toggle-transfer').on('click', function() {
  1205. if(disabled) {
  1206. enableTransferFunction();
  1207. } else {
  1208. disableTransferFunction();
  1209. }
  1210. });
  1211. var getOffsetLeft = function() {
  1212. return transfer.offset().left - transfer.parent().offset().left;
  1213. }
  1214. var removePxOffString = function(str) {
  1215. return parseInt(str.replace('px', ''));
  1216. }
  1217. var updateGradient = function() {
  1218. // Create gradient
  1219. var grd = context.createLinearGradient(0,0,255,0);
  1220. $.each(handles, function(index, value) {
  1221. var $value = $(value),
  1222. colorName = $value.attr('color'),
  1223. colorOffsetLeft = offsetLeft[colorName],
  1224. colorCode = colorCodes[colorName];
  1225. grd.addColorStop(colorOffsetLeft, colorCode);
  1226. });
  1227. // Fill with gradient
  1228. context.fillStyle = grd;
  1229. context.fillRect(0,0,255, 10);
  1230. applyOpacities();
  1231. changed = true;
  1232. };
  1233. var applyOpacities = function() {
  1234. var imageData = context.getImageData(0, 0, 255, 1),
  1235. data = imageData.data;
  1236. for(counter = 0; counter < opacities.length; counter++) {
  1237. data[(counter * 4) + 3] = opacities[counter];
  1238. }
  1239. hiddenContext.putImageData(imageData, 0, 0, 0, 0, 255, 1);
  1240. }
  1241. var updateHandlePosition = function(element) {
  1242. var colorLeft = removePxOffString($(element).css('left')) - getOffsetLeft(),
  1243. colorOffsetLeft = colorLeft / $canvas.width(),
  1244. colorName = $(element).attr('color');
  1245. if(colorOffsetLeft > 1.0) {
  1246. colorOffsetLeft = 1.0;
  1247. }
  1248. if(colorOffsetLeft < 0.0) {
  1249. colorOffsetLeft = 0.0;
  1250. }
  1251. offsetLeft[colorName] = colorOffsetLeft;
  1252. updateGradient();
  1253. };
  1254. var enableTransferFunction = function() {
  1255. $.each(handles, function(index, value) {
  1256. var $value = $(value),
  1257. colorName = $value.attr('color'),
  1258. colorOffsetLeft = offsetLeft[colorName],
  1259. colorLeft = getOffsetLeft() + ($canvas.width() * colorOffsetLeft),
  1260. colorCode = colorCodes[colorName];
  1261. $value.css({left: colorLeft, 'background-color': colorCode });
  1262. $(value).draggable({
  1263. containment: '#transfer-span-holder',
  1264. scroll: false,
  1265. axis: 'x',
  1266. cursor: "crosshair",
  1267. stop: function() {
  1268. updateHandlePosition(this);
  1269. },
  1270. drag: function() {
  1271. updateHandlePosition(this);
  1272. }
  1273. });
  1274. });
  1275. showHandles();
  1276. updateGradient();
  1277. disabled = false;
  1278. };
  1279. var disableTransferFunction = function() {
  1280. context.drawImage($standardTf, 0, 0, 255, 10);
  1281. applyOpacities();
  1282. hideHandles();
  1283. disabled = true;
  1284. changed = true;
  1285. };
  1286. var showHandles = function() {
  1287. $.each(handles, function(index, value) {
  1288. $(value).removeClass('hidden');
  1289. });
  1290. };
  1291. var hideHandles = function() {
  1292. $.each(handles, function(index, value) {
  1293. $(value).addClass('hidden');
  1294. });
  1295. };
  1296. //canvas.setAttribute('width', $canvas.width());
  1297. //canvas.setAttribute('height', $canvas.height());
  1298. disableTransferFunction();
  1299. $(document).on('opacityChanged', function(e, params) {
  1300. if(params != undefined && params.opacities != undefined) {
  1301. opacities = params.opacities;
  1302. applyOpacities();
  1303. changed = true;
  1304. }
  1305. });
  1306. $(document).on('opacityBordersChanged', function(e, params) {
  1307. var minGray = 0,
  1308. maxGray = 255;
  1309. if(params != undefined && params.minGray != undefined && params.maxGray != undefined) {
  1310. minGray = params.minGray;
  1311. maxGray = params.maxGray;
  1312. for(counter = 0; counter < 255; counter++) {
  1313. var opacity = 255;
  1314. if(counter < minGray || counter > maxGray) {
  1315. opacity = 1;
  1316. }
  1317. opacities[counter] = opacity;
  1318. }
  1319. applyOpacities();
  1320. changed = true;
  1321. }
  1322. });
  1323. return {
  1324. transferFunctionChanged : function() {
  1325. return changed;
  1326. },
  1327. getCurrentTransferFunction : function() {
  1328. changed = false;
  1329. return hiddenContext.getImageData(0, 0, 255, 1);
  1330. }
  1331. };
  1332. }
  1333. ;var OverviewHelper = function() {
  1334. var sceneOveriew, rendererOverview, cameraOverview, innerCubeOverview;
  1335. //private method
  1336. var addInnerCubeOverView = function(x, y, z) {
  1337. var innerCubeGeometry = new THREE.BoxGeometry( x, y, z );
  1338. var innerCubeMaterial = new THREE.MeshBasicMaterial( {color: 0xaaaaaa} );
  1339. innerCubeOverview = new THREE.Mesh( innerCubeGeometry, innerCubeMaterial );
  1340. sceneOverview.add( innerCubeOverview );
  1341. }
  1342. var initiateEventListener = function(containerOverviewElement) {
  1343. // change overview box
  1344. $(document).on('zoomActionFinished', function(e, params) {
  1345. zoomedIn = params.zoomAction == 'zoomIn' || zoomedInfo != null;
  1346. sceneOverview.remove(innerCubeOverview);
  1347. if(zoomedIn) {
  1348. xWidth = zoomedInfo.dimension.xywidth / textureInfo.originalSize.sizex;
  1349. yWidth = zoomedInfo.dimension.xywidth / textureInfo.originalSize.sizey;
  1350. zWidth = zoomedInfo.numberOfSlices / textureInfo.originalSize.sizez;
  1351. xOffset = zoomedInfo.dimension.xmin / textureInfo.originalSize.sizex;
  1352. yOffset = zoomedInfo.dimension.ymin / textureInfo.originalSize.sizey;
  1353. zOffset = zoomedInfo.dimension.zmin / textureInfo.originalSize.sizez;
  1354. addInnerCubeOverView(xWidth, yWidth, zWidth);
  1355. // main cube was rotated around x axis, so have to swap y and z coordinates
  1356. // for the overview
  1357. innerCubeOverview.position.x = -0.5 + xOffset + xWidth / 2;
  1358. innerCubeOverview.position.y = (-0.5 + zOffset + zWidth / 2);
  1359. innerCubeOverview.position.z = (-0.5 + yOffset + yWidth / 2) * -1;
  1360. //innerCubeOverview.applyMatrix((new THREE.Matrix4()).makeRotationX(Math.PI / -2))
  1361. } else {
  1362. addInnerCubeOverView(1,1,1);
  1363. }
  1364. });
  1365. var headerHeight = $('header').height();
  1366. $(window).on('scroll', function(e) {
  1367. $containerOverviewElement = $(containerOverviewElement)
  1368. if($(this).scrollTop() >= headerHeight) {
  1369. $containerOverviewElement.css('position', 'relative');
  1370. $containerOverviewElement.css('top', $(this).scrollTop() - headerHeight);
  1371. } else {
  1372. $containerOverviewElement.css('top', 0);
  1373. }
  1374. });
  1375. }
  1376. var addTextsToScene = function() {
  1377. var shapeParameters = {font: 'helvetiker', size: 0.2, height: 0.05},
  1378. shape = new THREE.TextGeometry("0", shapeParameters),
  1379. wrapper = new THREE.MeshBasicMaterial({color: 0x000000}),
  1380. words = new THREE.Mesh(shape, wrapper);
  1381. words.position.x = -0.6;
  1382. words.position.y = -0.6;
  1383. words.position.z = 0.52;
  1384. sceneOverview.add(words);
  1385. }
  1386. var addCubeEdges = function() {
  1387. // fix for cube
  1388. var numberOfEdges = 12;
  1389. var xColorEdge = new THREE.Color(1,0,0);
  1390. var yColorEdge = new THREE.Color(0,1,0);
  1391. var zColorEdge = new THREE.Color(0,0,1);
  1392. var geometry = new THREE.BufferGeometry();
  1393. var material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors });
  1394. var colors = new Float32Array( numberOfEdges * 2 * 3 );
  1395. var positions = new Float32Array([
  1396. // edges in x direction
  1397. // front face
  1398. -0.5, -0.5, -0.5, 0.5, -0.5, -0.5,
  1399. -0.5, 0.5, -0.5, 0.5, 0.5, -0.5,
  1400. // back face
  1401. -0.5, -0.5, 0.5, 0.5, -0.5, 0.5,
  1402. -0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
  1403. // edges in y direction
  1404. // front face
  1405. -0.5, -0.5, -0.5, -0.5, 0.5, -0.5,
  1406. 0.5, -0.5, -0.5, 0.5, 0.5, -0.5,
  1407. // back face
  1408. -0.5, -0.5, 0.5, -0.5, 0.5, 0.5,
  1409. 0.5, -0.5, 0.5, 0.5, 0.5, 0.5,
  1410. // edges in z direction
  1411. // left side
  1412. -0.5, -0.5, -0.5, -0.5, -0.5, 0.5,
  1413. -0.5, 0.5, -0.5, -0.5, 0.5, 0.5,
  1414. // right side
  1415. 0.5, -0.5, -0.5, 0.5, -0.5, 0.5,
  1416. 0.5, 0.5, -0.5, 0.5, 0.5, 0.5
  1417. ]);
  1418. for(edgeCounter = 0; edgeCounter < 12 * 2; edgeCounter++) {
  1419. var colorToUse = null
  1420. if(edgeCounter <= 7) {
  1421. colorToUse = xColorEdge;
  1422. } else if(edgeCounter <= 15) {
  1423. colorToUse = zColorEdge;
  1424. } else {
  1425. colorToUse = yColorEdge;
  1426. }
  1427. colors[edgeCounter * 3 + 0] = colorToUse.r;
  1428. colors[edgeCounter * 3 + 1] = colorToUse.g;
  1429. colors[edgeCounter * 3 + 2] = colorToUse.b;
  1430. }
  1431. geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
  1432. geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
  1433. var lines = new THREE.Line( geometry, material, THREE.LinePieces );
  1434. sceneOverview.add( lines );
  1435. }
  1436. return {
  1437. initOverview: function(containerOverviewElement) {
  1438. sceneOverview = new THREE.Scene();
  1439. cameraOverview = new THREE.PerspectiveCamera( 45, 150 / 150, .1, 1000 );
  1440. cameraOverview.position.z = 2;
  1441. var cubeGeometry = new THREE.BoxGeometry( 1, 1, 1 );
  1442. var cubeMaterial = new THREE.MeshBasicMaterial( {color: 0x000000} );
  1443. var cubeOverview = new THREE.Mesh( cubeGeometry, cubeMaterial );
  1444. var edgesHelper = new THREE.EdgesHelper(cubeOverview, 0x000000);
  1445. edgesHelper.material.linewidth = 2;
  1446. //sceneOverview.add( edgesHelper );
  1447. addInnerCubeOverView(1,1,1);
  1448. addCubeEdges();
  1449. addTextsToScene();
  1450. rendererOverview = new THREE.WebGLRenderer();
  1451. rendererOverview.setSize(200, 200);
  1452. rendererOverview.setClearColor(0xffffff, 1);
  1453. containerOverviewElement.appendChild(rendererOverview.domElement);
  1454. initiateEventListener(containerOverviewElement);
  1455. },
  1456. updateCameraPosition: function(position) {
  1457. cameraPoint.normalize().multiplyScalar(4);
  1458. cameraPoint = sceneOverview.position.clone().add(cameraPoint);
  1459. cameraOverview.position.x = cameraPoint.x;
  1460. cameraOverview.position.y = cameraPoint.y;
  1461. cameraOverview.position.z = cameraPoint.z;
  1462. cameraOverview.lookAt(sceneOverview.position);
  1463. },
  1464. render: function() {
  1465. rendererOverview.render(sceneOverview, cameraOverview);
  1466. }
  1467. }
  1468. }
  1469. ;var VolumeFace = function(orientation, direction) {
  1470. this.orientation = orientation;
  1471. this.direction = direction;
  1472. }
  1473. VolumeFace.prototype = {
  1474. constructor: VolumeFace,
  1475. orientation: 0,
  1476. direction: 0,
  1477. getAxisOfNaviation: function() {
  1478. var axis = {
  1479. plane: {
  1480. ver: null,
  1481. hor: null
  1482. },
  1483. slider: null
  1484. };
  1485. if(this.orientation == VolumeFaceOrientation.XY) {
  1486. axis.plane.ver = new Orientation(Axis.Y);
  1487. axis.plane.hor = new Orientation(Axis.X);
  1488. axis.slider = new Orientation(Axis.Z);
  1489. } else if(this.orientation == VolumeFaceOrientation.YZ) {
  1490. axis.plane.ver = new Orientation(Axis.Z);
  1491. axis.plane.hor = new Orientation(Axis.Y);
  1492. axis.slider = new Orientation(Axis.X);
  1493. } else if(this.orientation == VolumeFaceOrientation.XZ) {
  1494. axis.plane.ver = new Orientation(Axis.Z);
  1495. axis.plane.hor = new Orientation(Axis.X);
  1496. axis.slider = new Orientation(Axis.Y);
  1497. }
  1498. return axis;
  1499. },
  1500. getIdentifier: function() {
  1501. return this.orientation + '-' + this.direction;
  1502. }
  1503. };
  1504. var VolumeFaceOrientation = {
  1505. XY: 0,
  1506. XZ: 1,
  1507. YZ: 2
  1508. }
  1509. var VolumeFaceDirection = {
  1510. FRONT: 0,
  1511. BACK: 1
  1512. }
  1513. function determineVolumeFace(cubeFaceNormal) {
  1514. var orientation, direction;
  1515. if(cubeFaceNormal.x != 0) {
  1516. orientation = VolumeFaceOrientation.YZ;
  1517. direction = determineFaceOrientation(cubeFaceNormal.x);
  1518. } else if(cubeFaceNormal.y != 0) {
  1519. orientation = VolumeFaceOrientation.XZ;
  1520. direction = determineFaceOrientation(cubeFaceNormal.y);
  1521. } else if(cubeFaceNormal.z != 0) {
  1522. orientation = VolumeFaceOrientation.XY;
  1523. direction = determineFaceOrientation(cubeFaceNormal.z);
  1524. }
  1525. return new VolumeFace(orientation, direction);
  1526. }
  1527. function determineFaceOrientation(normalComp) {
  1528. return normalComp > 0 ? VolumeFaceDirection.FRONT : VolumeFaceDirection.BACK;
  1529. }
  1530. function isFrontFace(orientation, direction) {
  1531. return orientation == VolumeFaceOrientation.XY
  1532. && direction == VolumeFaceDirection.FRONT;
  1533. }
  1534. function isBackFace(orientation, direction) {
  1535. return orientation == VolumeFaceOrientation.XY
  1536. && direction == VolumeFaceDirection.BACK;
  1537. }
  1538. function isLeftFace(orientation, direction) {
  1539. return orientation == VolumeFaceOrientation.YZ
  1540. && direction == VolumeFaceDirection.FRONT;
  1541. }
  1542. function isRightFace(orientation, direction) {
  1543. return orientation == VolumeFaceOrientation.YZ
  1544. && direction == VolumeFaceDirection.BACK;
  1545. }
  1546. function isTopFace(orientation, direction) {
  1547. return orientation == VolumeFaceOrientation.XZ
  1548. && direction == VolumeFaceDirection.FRONT;
  1549. }
  1550. function isBottomFace(orientation, direction) {
  1551. return orientation == VolumeFaceOrientation.XZ
  1552. && direction == VolumeFaceDirection.BACK;
  1553. }
  1554. ;var ZoomHelper = function() {
  1555. var navigationPlaneHorLabel = $('#navigation-plane-hor-label'),
  1556. navigationPlaneVerLabel = $('#navigation-plane-ver-label'),
  1557. navigationSliderLabel = $('#navigation-slider-label'),
  1558. zoomStatus = $('#zoom-status'),
  1559. zoomInButton = $('input#zoomin'),
  1560. zoomOutButton = $('input#zoomout'),
  1561. navigationPlane = $('div#navigation-plane'),
  1562. navigationPlaneParent = navigationPlane.parent(),
  1563. navigationSlider = $('div#navigation-slider'),
  1564. navigationSliderParent = navigationSlider.parent(),
  1565. displayTimestamp = null,
  1566. planeOrientation = {
  1567. ver: new Orientation(Axis.Y, OffsetTo.LEFT),
  1568. hor: new Orientation(Axis.X, OffsetTo.TOP),
  1569. direction: VolumeFaceDirection.BACK,
  1570. orientation: VolumeFaceOrientation.XY
  1571. },
  1572. sliderOrientation = {axis: new Orientation(Axis.Z, OffsetTo.TOP) },
  1573. zoomedIn,
  1574. zoomedInfoArray = {
  1575. dimension: Array(3),
  1576. offset: Array(3)
  1577. },
  1578. oldZoomedInfos = [];
  1579. var lastExecutionTime = Date.now();
  1580. // adjust navigation related navigations
  1581. $container.on('animation', function() {
  1582. determineAxisLabels();
  1583. determinePlanePosition();
  1584. determineSliderPosition();
  1585. });
  1586. // one has to press ctrl AND alt while clicking
  1587. $container.on('click', 'canvas', function(event){
  1588. event.stopPropagation();
  1589. event.preventDefault();
  1590. // keyboard shortcut activated or button zoom in pressed before?
  1591. if((event.ctrlKey == false || event.altKey == false)
  1592. && !zoomInActivated) {
  1593. return;
  1594. }
  1595. var mouseX = ( (event.clientX - $canvas.offset().left) / ($canvas.width()) ) * 2 - 1,
  1596. mouseY = - ( (event.clientY - $canvas.offset().top) / ($canvas.height()) ) * 2 + 1;
  1597. var vector = new THREE.Vector3( mouseX, mouseY, camera.near);
  1598. vector = vector.unproject( camera );
  1599. var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
  1600. var intersects = raycaster.intersectObjects( [frontBox] );
  1601. if(intersects.length > 0) {
  1602. if(!handleZoomStatus(true)) {
  1603. return false;
  1604. }
  1605. var intersect = intersects[0],
  1606. point = intersect.point;
  1607. var geometry = new THREE.BoxGeometry( 0.1, 0.1, 0.1 );
  1608. var material = new THREE.MeshBasicMaterial( {
  1609. color: new THREE.Color( 0xaaaaaa ),
  1610. opacity: 0.3
  1611. });
  1612. mesh = new THREE.Mesh( geometry, material );
  1613. mesh.position.x = point.x;
  1614. mesh.position.y = point.y;
  1615. mesh.position.z = point.z;
  1616. scene.add(mesh);
  1617. intersectCubes[intersectCubes.length] = mesh;
  1618. intersectCubesTimeStamps[intersectCubesTimeStamps.length] = Date.now();
  1619. var realPoint = point.clone();
  1620. getSubvolume(point, false, 'zoomIn', false);
  1621. }
  1622. });
  1623. function getSubvolume(realPoint, alreadyTranslated, zoomAction, sameDepth, fromDraggable) {
  1624. if(alreadyTranslated == undefined || !alreadyTranslated) {
  1625. realPoint = realPoint.applyMatrix4((new THREE.Matrix4).makeRotationX(Math.PI / -2));
  1626. // retranslate the point into original position beginning from 0,0,0
  1627. realPoint.add(new THREE.Vector3(0.5, 0.5, 0.5));
  1628. }
  1629. volumePointArray = realPoint.toArray();
  1630. var processingUrl = IPE.util.buildUrl('volumes/' + volumeId + '/processing/sub/');
  1631. $.each(volumePointArray, function(index, value) {
  1632. dimWidth = null;
  1633. // have to decide, whether we in zoomed in or zoomed out status
  1634. if(zoomedInfo == undefined || zoomedInfo == null || fromDraggable) {
  1635. if(index == 0) {
  1636. dimWidth = textureInfo.originalSize.sizex;
  1637. } else if(index == 1) {
  1638. dimWidth = textureInfo.originalSize.sizey;
  1639. } else {
  1640. dimWidth = textureInfo.originalSize.sizez;
  1641. }
  1642. } else {
  1643. if(index < 2) {
  1644. dimWidth = zoomedInfo.dimension.xywidth;
  1645. } else {
  1646. dimWidth = zoomedInfo.numberOfSlices;
  1647. }
  1648. }
  1649. value *= dimWidth;
  1650. // due to interpolation algorithm, we had to rotate the whole cube, that it matches
  1651. // the display of imagej
  1652. // so we have to map the current pointer values to the real volume values
  1653. // but only for the y and z direction --> the x direction is all right
  1654. if(index > 0) {
  1655. value = dimWidth - value;
  1656. }
  1657. if(!fromDraggable && zoomedInfo) {
  1658. if(index == 0) {
  1659. value = value + zoomedInfo.dimension.xmin;
  1660. } else if(index == 1) {
  1661. value = value + zoomedInfo.dimension.ymin;
  1662. } else {
  1663. value = value + zoomedInfo.dimension.zmin;
  1664. }
  1665. }
  1666. value = Math.floor(value);
  1667. volumePointArray[index] = value;
  1668. processingUrl += value + '/';
  1669. });
  1670. frameNumber = imgInfo.frameFrom + currentTexture;
  1671. processingUrl += frameNumber + '/';
  1672. depth = 1;
  1673. if(zoomAction == 'zoomIn') {
  1674. if(zoomedInfo != null){
  1675. if(sameDepth) {
  1676. depth = zoomedInfo.depth;
  1677. } else {
  1678. depth = zoomedInfo.depth + 1;
  1679. }
  1680. }
  1681. } else if(zoomAction == 'zoomOut') {
  1682. if(zoomedInfo.depth > 1) {
  1683. depth = zoomedInfo.depth - 1;
  1684. }
  1685. }
  1686. while(oldZoomedInfos.length > 0
  1687. && oldZoomedInfos.last().zoomedInfo.depth >= depth)
  1688. {
  1689. oldZoomedInfos.pop();
  1690. }
  1691. processingUrl += depth + '/';
  1692. $.ajax({
  1693. url: processingUrl,
  1694. success: function(data) {
  1695. var available = false;
  1696. var availableTestCounter = 0;
  1697. zoomedInfo = data;
  1698. oldZoomedInfos.push({
  1699. point: realPoint,
  1700. translated: true,
  1701. zoomedInfo: zoomedInfo
  1702. });
  1703. // this function is called recursive by the settimeout statement
  1704. availableTest = function() {
  1705. $.ajax({
  1706. url: IPE.util.buildUrl('volumes/' + volumeId + '/processing/sprite/' + zoomedInfo.spriteId + '/available/'),
  1707. success: function(data) {
  1708. available = data.available;
  1709. },
  1710. dataType: 'json',
  1711. async: false
  1712. });
  1713. if(available) {
  1714. // subvolume available: fetch it
  1715. fetchSubVolume(zoomAction);
  1716. } else if(availableTestCounter < 80) {
  1717. // abort condition not reached --> try again
  1718. setTimeout(availableTest, 500);
  1719. availableTestCounter++;
  1720. } else {
  1721. oldZoomedInfos.pop();
  1722. // abort condition reached --> error handling
  1723. $(document).trigger('zoomActionFinished', { zoomAction: zoomAction, error: true });
  1724. }
  1725. };
  1726. setTimeout(availableTest, 500);
  1727. },
  1728. dataType: 'json',
  1729. async: true,
  1730. error: function(data) {
  1731. helper.displayMessage('Sorry, an error occured during processing zoom', true, null, 2500);
  1732. }
  1733. });
  1734. };
  1735. var fetchSubVolume = function(zoomAction) {
  1736. imageSrc = IPE.util.buildUrl('volumes/' + volumeId + '/processing/sprite/' + zoomedInfo.spriteId + '/show/');
  1737. var image = new Image();
  1738. var texture = initTexture(new THREE.Texture(image));
  1739. image.onload = function() {
  1740. materialScreen.uniforms.numberOfSlices.value = zoomedInfo.numberOfSlices;
  1741. materialScreen.uniforms.numberOfSlices.needsupdate = true;
  1742. materialScreen.uniforms.slicesOverX.value = zoomedInfo.slicesOverX;
  1743. materialScreen.uniforms.slicesOverX.needsUpdate = true;
  1744. materialScreen.uniforms.slicesOverY.value = zoomedInfo.slicesOverY;
  1745. materialScreen.uniforms.slicesOverY.needsUpdate = true;
  1746. materialScreen.uniforms.numberOfSprites.value = 1;
  1747. materialScreen.uniforms.numberOfSprites.needsUpdate = true;
  1748. materialScreen.uniforms.slicesPerSprite.value = zoomedInfo.numberOfSlices;
  1749. materialScreen.uniforms.slicesPerSprite.needsUpdate = true;
  1750. updateTexture([texture]);
  1751. zoomedVolumeDimension.xmin = zoomedInfo.dimension.xmin;
  1752. zoomedVolumeDimension.xmax = zoomedInfo.dimension.xmin + zoomedInfo.dimension.xywidth - 1;
  1753. zoomedVolumeDimension.ymin = zoomedInfo.dimension.ymin;
  1754. zoomedVolumeDimension.ymax = zoomedInfo.dimension.ymin + zoomedInfo.dimension.xywidth - 1;
  1755. zoomedVolumeDimension.zmin = zoomedInfo.dimension.zmin;
  1756. zoomedVolumeDimension.zmax = zoomedInfo.dimension.zmin + zoomedInfo.numberOfSlices - 1;
  1757. originalVolumeDimension = currentVolumeDimension;
  1758. originalDimension = currentDimension;
  1759. currentVolumeDimension = zoomedVolumeDimension;
  1760. repositionLayerSliders();
  1761. $(document).trigger('zoomActionFinished', {
  1762. zoomAction: zoomAction, textureNumber: frameNumber
  1763. });
  1764. }
  1765. image.src = imageSrc;
  1766. };
  1767. $container.on('contextmenu', function(event){
  1768. if(event.ctrlKey == false) {
  1769. return;
  1770. }
  1771. if(event.altKey == false) {
  1772. return;
  1773. }
  1774. if(!handleZoomStatus(false)) {
  1775. return false;
  1776. }
  1777. return zoomOut();
  1778. });
  1779. function zoomOut() {
  1780. currentZoomPoint = oldZoomedInfos.pop().point;
  1781. if(oldZoomedInfos.length > 0) {
  1782. // using the current point to get a new subvolume
  1783. getSubvolume(currentZoomPoint, true, 'zoomOut', true);
  1784. return false;
  1785. }
  1786. else
  1787. {
  1788. zoomedInfo = null;
  1789. materialScreen.uniforms.numberOfSlices.value = textureInfo.info.numberOfSlices;
  1790. materialScreen.uniforms.numberOfSlices.needsupdate = true;
  1791. materialScreen.uniforms.slicesOverX.value = textureInfo.info.slicesOverX;
  1792. materialScreen.uniforms.slicesOverX.needsUpdate = true;
  1793. materialScreen.uniforms.slicesOverY.value = textureInfo.info.slicesOverY;
  1794. materialScreen.uniforms.slicesOverY.needsUpdate = true;
  1795. materialScreen.uniforms.numberOfSprites.value = imgInfo.numberOfSprites;
  1796. materialScreen.uniforms.numberOfSprites.needsUpdate = true;
  1797. materialScreen.uniforms.slicesPerSprite.value = imgInfo.slicesPerSprite;
  1798. materialScreen.uniforms.slicesPerSprite.needsUpdate = true;
  1799. updateTexture();
  1800. currentVolumeDimension = originalVolumeDimension;
  1801. currentDimension = originalDimension;
  1802. repositionLayerSliders();
  1803. }
  1804. $(document).trigger('zoomActionFinished', {
  1805. zoomAction: 'zoomOut'
  1806. });
  1807. return false;
  1808. }
  1809. function zoomInAllowed() {
  1810. return !zoomedIn || zoomedInfo.dimension.xywidth > 300;
  1811. }
  1812. /**
  1813. * return: procceed or not
  1814. */
  1815. function handleZoomStatus(zoomIn) {
  1816. zoomInButton.removeClass('red');
  1817. zoomInActivated = false;
  1818. if(zoomIn && !zoomInAllowed()) {
  1819. return false;
  1820. } else if(!zoomIn && !zoomedIn) {
  1821. return false;
  1822. }
  1823. waitDiv.removeClass('hidden');
  1824. displayMessage = zoomIn ? 'Generating zoomed subvolume, please wait a moment' : 'Zooming out';
  1825. helper.displayMessage(displayMessage);
  1826. displayTimestamp = Date.now();
  1827. return true;
  1828. }
  1829. // general function to disable stuff like messages etc.
  1830. $(document).on('zoomActionFinished', function(e, params) {
  1831. zoomedIn = zoomedInfo != null;
  1832. timeout = 2000 - (Date.now() - displayTimestamp);
  1833. if(timeout < 0) {
  1834. timeout = 0;
  1835. }
  1836. helper.fadeoutMessage(null, timeout);
  1837. zoomedStatusText = '';
  1838. if(zoomedIn) {
  1839. zoomStatus.addClass('green-background');
  1840. zoomedStatusText = 'zoomed in';
  1841. $.each($('.res-link'), function(index, value) {
  1842. $(value).addClass('disabled');
  1843. });
  1844. if(zoomedInfo.dimension.xywidth <= 300) {
  1845. zoomInButton.prop('disabled', true);
  1846. }
  1847. } else {
  1848. zoomStatus.removeClass('green-background');
  1849. zoomedStatusText = 'zoomed out';
  1850. if(params.error) {
  1851. errorMessage = 'Error during subvolume generation - zoomed out again';
  1852. helper.displayMessage(errorMessage, true, null, 5000);
  1853. }
  1854. $.each($('.res-link'), function(index, value) {
  1855. $(value).removeClass('disabled');
  1856. });
  1857. zoomInButton.prop('disabled', false);
  1858. }
  1859. zoomStatus.html(zoomedStatusText);
  1860. waitDiv.addClass('hidden');
  1861. });
  1862. // draggable related stuff
  1863. // TODO for multilevel zooming
  1864. $(document).on('zoomActionFinished', function(e, params) {
  1865. zoomedIn = zoomedInfo != null;
  1866. if(zoomedIn) {
  1867. zoomedInfoArray.offset[Axis.X] = zoomedVolumeDimension.xmin;
  1868. zoomedInfoArray.offset[Axis.Y] = zoomedVolumeDimension.ymin;
  1869. zoomedInfoArray.offset[Axis.Z] = zoomedVolumeDimension.zmin;
  1870. zoomedInfoArray.dimension[Axis.X] = zoomedInfo.dimension.xywidth;
  1871. zoomedInfoArray.dimension[Axis.Y] = zoomedInfo.dimension.xywidth;
  1872. zoomedInfoArray.dimension[Axis.Z] = zoomedInfo.numberOfSlices;
  1873. } else {
  1874. navigationPlane.hide();
  1875. navigationPlaneParent.removeClass('white');
  1876. navigationSlider.hide();
  1877. navigationSliderParent.removeClass('white');
  1878. }
  1879. navigationPlane.removeClass('no-pos-set');
  1880. navigationSlider.removeClass('no-pos-set');
  1881. });
  1882. navigationPlane.draggable({
  1883. containment: '#navigation-plane-container',
  1884. scroll: false,
  1885. stop: function() {
  1886. zoomedDraggableChanged();
  1887. }
  1888. });
  1889. navigationSlider.draggable({
  1890. containment: '#navigation-slider-container',
  1891. scroll: false,
  1892. stop: function() {
  1893. zoomedDraggableChanged();
  1894. }
  1895. });
  1896. function zoomedDraggableChanged() {
  1897. waitDiv.removeClass('hidden');
  1898. var planeWidthHalf = navigationPlane.width() / 2,
  1899. planeHeightHalf = navigationPlane.height() / 2,
  1900. planeOffsetLeft = navigationPlane.offset().left - navigationPlaneParent.offset().left - 1,
  1901. planeOffsetTop = navigationPlane.offset().top - navigationPlaneParent.offset().top - 1,
  1902. sliderHeightHalf = navigationSlider.height() / 2,
  1903. sliderOffsetTop = navigationSlider.offset().top - navigationSliderParent.offset().top - 1,
  1904. orientation = planeOrientation.orientation,
  1905. direction = planeOrientation.direction;
  1906. // set correct border values due to messure errors
  1907. if(planeOffsetLeft < 0) {
  1908. planeOffsetLeft = 0;
  1909. } else if(planeOffsetLeft > navigationPlaneParent.width() - navigationPlane.width()) {
  1910. planeOffsetLeft = navigationPlaneParent.width() - navigationPlane.width();
  1911. }
  1912. if(planeOffsetTop < 0) {
  1913. planeOffsetTop = 0;
  1914. } else if(planeOffsetTop > navigationPlaneParent.height() - navigationPlane.height()) {
  1915. planeOffsetTop = navigationPlaneParent.height() - navigationPlane.height();
  1916. }
  1917. if(sliderOffsetTop < 0) {
  1918. sliderOffsetTop = 0;
  1919. } else if(sliderOffsetTop > navigationSliderParent.height() - navigationSlider.height()) {
  1920. sliderOffsetTop = navigationSliderParent.height() - navigationSlider.height();
  1921. }
  1922. planeOffsetLeft = planeOffsetLeft + planeWidthHalf;
  1923. planeOffsetTop = planeOffsetTop + planeHeightHalf;
  1924. sliderOffsetTop = sliderOffsetTop + sliderHeightHalf;
  1925. horAxis = planeOrientation.hor.axis;
  1926. verAxis = planeOrientation.ver.axis;
  1927. pointAsArray = Array(3);
  1928. pointAsArray[horAxis] = planeOffsetLeft / navigationPlaneParent.width();
  1929. pointAsArray[verAxis] = planeOffsetTop / navigationPlaneParent.height();
  1930. /*if(planeOrientation.direction == VolumeFaceDirection.BACK) {
  1931. pointAsArray[horAxis] = 1.0 - pointAsArray[horAxis];
  1932. } else if(planeOrientation.orientation == VolumeFaceOrientation.XZ) {
  1933. pointAsArray[horAxis] = 1.0 - pointAsArray[horAxis];
  1934. }*/
  1935. if((planeOrientation.orientation == VolumeFaceOrientation.XY
  1936. && planeOrientation.direction == VolumeFaceDirection.BACK)
  1937. || (planeOrientation.orientation == VolumeFaceOrientation.YZ
  1938. && planeOrientation.direction == VolumeFaceDirection.BACK)
  1939. || (planeOrientation.orientation == VolumeFaceOrientation.XZ
  1940. && planeOrientation.direction == VolumeFaceDirection.BACK)) {
  1941. pointAsArray[horAxis] = 1.0 - pointAsArray[horAxis];
  1942. }
  1943. pointAsArray[sliderOrientation.axis] = sliderOffsetTop / navigationSliderParent.height();
  1944. /*if((sliderOrientation.axis == Axis.Z
  1945. && planeOrientation.direction == VolumeFaceDirection.FRONT)
  1946. || (sliderOrientation.axis == Axis.Y
  1947. && planeOrientation.direction == VolumeFaceDirection.FRONT)
  1948. || (sliderOrientation.axis == Axis.X
  1949. && planeOrientation.direction == VolumeFaceDirection.BACK)) {
  1950. pointAsArray[sliderOrientation.axis] = 1.0 - pointAsArray[sliderOrientation.axis];
  1951. }*/
  1952. if((sliderOrientation.axis == Axis.X
  1953. && planeOrientation.direction == VolumeFaceDirection.FRONT)
  1954. || (sliderOrientation.axis == Axis.Y
  1955. && planeOrientation.direction == VolumeFaceDirection.BACK)
  1956. || (sliderOrientation.axis == Axis.Z
  1957. && planeOrientation.direction == VolumeFaceDirection.BACK)) {
  1958. pointAsArray[sliderOrientation.axis] = 1.0 - pointAsArray[sliderOrientation.axis];
  1959. }
  1960. point = new THREE.Vector3(pointAsArray[0], pointAsArray[1], pointAsArray[2]);
  1961. getSubvolume(point, true, 'zoomIn', true, true);
  1962. };
  1963. var zoomInActivated = false;
  1964. zoomInButton.on('click', function() {
  1965. zoomInActivated = !zoomInActivated;
  1966. if(zoomInActivated) {
  1967. $(this).addClass('red');
  1968. } else {
  1969. $(this).removeClass('red');
  1970. }
  1971. });
  1972. zoomOutButton.on('click', function() {
  1973. zoomInButton.removeClass('red');
  1974. if(!handleZoomStatus(false)) {
  1975. return false;
  1976. }
  1977. return zoomOut();
  1978. });
  1979. function determineAxisLabels() {
  1980. if(Date.now() - lastExecutionTime > 100) {
  1981. var lookAtVector = new THREE.Vector3(0,0, -1);
  1982. lookAtVector.applyQuaternion(camera.quaternion);
  1983. xIterator = -0.4;
  1984. yIterator = -0.4;
  1985. facesIntersect = {};
  1986. interSectStartingPoint = new THREE.Vector3(xIterator, yIterator, camera.near);
  1987. for(xIterator = -0.4; xIterator <= 0.4; xIterator += 0.2) {
  1988. for(yIterator = -0.4; yIterator <= 0.4; yIterator += 0.2) {
  1989. interSectStartingPoint.x = xIterator;
  1990. interSectStartingPoint.y = yIterator;
  1991. vector = interSectStartingPoint.unproject( camera );
  1992. var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
  1993. var intersects = raycaster.intersectObjects( [frontBox] );
  1994. if(intersects.length > 0) {
  1995. var intersect = intersects[0],
  1996. point = intersect.point,
  1997. face = intersect.face,
  1998. faceObject = determineVolumeFace(face.normal),
  1999. faceIdent = faceObject.getIdentifier();
  2000. alreadyAdded = Object.keys(facesIntersect).indexOf(faceIdent) >= 0;
  2001. if(alreadyAdded) {
  2002. facesIntersect[faceIdent].count++;
  2003. } else {
  2004. facesIntersect[faceIdent] = { faceObject: faceObject, count: 1};
  2005. }
  2006. }
  2007. }
  2008. }
  2009. frontFace = { count: 0 };
  2010. for(faceIdent in facesIntersect) {
  2011. if(facesIntersect[faceIdent].count > frontFace.count) {
  2012. frontFace = facesIntersect[faceIdent];
  2013. }
  2014. }
  2015. if(frontFace.faceObject != undefined) {
  2016. volumeFace = frontFace.faceObject;
  2017. axisOfNaviation = volumeFace.getAxisOfNaviation();
  2018. planeOrientation = axisOfNaviation.plane;
  2019. planeOrientation.hor.offsetTo = OffsetTo.LEFT;
  2020. planeOrientation.ver.offsetTo = OffsetTo.TOP;
  2021. planeOrientation.direction = volumeFace.direction;
  2022. planeOrientation.orientation = volumeFace.orientation;
  2023. sliderOrientation = axisOfNaviation.slider;
  2024. sliderOrientation.offsetTo = OffsetTo.TOP;
  2025. navigationPlaneHorLabel.html(planeOrientation.hor.getLabel());
  2026. navigationPlaneVerLabel.html(planeOrientation.ver.getLabel());
  2027. navigationSliderLabel.html(sliderOrientation.getLabel());
  2028. }
  2029. lastExecutionTime = Date.now();
  2030. }
  2031. }
  2032. function determinePlanePosition() {
  2033. if(!zoomedIn) {
  2034. return;
  2035. }
  2036. if(navigationPlane.hasClass('ui-draggable-dragging')
  2037. || navigationPlane.hasClass('no-pos-set')) {
  2038. navigationPlane.addClass('no-pos-set');
  2039. return;
  2040. }
  2041. horAxis = planeOrientation.hor.axis;
  2042. verAxis = planeOrientation.ver.axis;
  2043. planeRelativeX = navigationPlaneParent.width() / originalSizeArray[horAxis];
  2044. planeRelativeY = navigationPlaneParent.height() / originalSizeArray[verAxis];
  2045. planeWidth = planeRelativeX * zoomedInfoArray.dimension[horAxis];
  2046. planeHeight = planeRelativeY * zoomedInfoArray.dimension[verAxis];
  2047. planeWidth = Math.ceil(planeWidth);
  2048. planeHeight = Math.ceil(planeHeight);
  2049. planeOffsetLeft = zoomedInfoArray.offset[horAxis] * planeRelativeX;
  2050. if((planeOrientation.direction == VolumeFaceDirection.BACK
  2051. && planeOrientation.orientation == VolumeFaceOrientation.XZ)
  2052. || (planeOrientation.direction == VolumeFaceDirection.FRONT
  2053. && planeOrientation.orientation == VolumeFaceOrientation.YZ)) {
  2054. planeOffsetLeft = navigationPlaneParent.width() - (planeOffsetLeft + navigationPlane.width());
  2055. }
  2056. planeOffsetTop = zoomedInfoArray.offset[verAxis] * planeRelativeY;
  2057. if(planeOrientation.orientation == VolumeFaceOrientation.XZ
  2058. || planeOrientation.orientation == VolumeFaceOrientation.YZ){
  2059. planeOffsetTop = navigationPlaneParent.height() - (planeOffsetTop + navigationPlane.height());
  2060. }
  2061. navigationPlane.css({
  2062. 'top': planeOffsetTop + 'px',
  2063. 'left' : planeOffsetLeft + 'px',
  2064. 'width': planeWidth + 'px',
  2065. 'height': planeHeight + 'px'
  2066. });
  2067. navigationPlane.show();
  2068. navigationPlaneParent.addClass('white');
  2069. }
  2070. function determineSliderPosition() {
  2071. if(!zoomedIn) {
  2072. return;
  2073. }
  2074. if(navigationSlider.hasClass('ui-draggable-dragging')
  2075. || navigationSlider.hasClass('no-pos-set')) {
  2076. navigationSlider.addClass('no-pos-set');
  2077. return;
  2078. }
  2079. sliderRelative = navigationSliderParent.height() / originalSizeArray[sliderOrientation.axis];
  2080. sliderOffsetTop = zoomedInfoArray.offset[sliderOrientation.axis] * sliderRelative;
  2081. sliderHeight = Math.ceil(sliderRelative * zoomedInfoArray.dimension[sliderOrientation.axis]);
  2082. if(planeOrientation.direction == VolumeFaceDirection.FRONT) {
  2083. sliderOffsetTop = navigationSliderParent.height() - (navigationSlider.height() + sliderOffsetTop);
  2084. }
  2085. navigationSlider.css({
  2086. 'top': sliderOffsetTop + 'px',
  2087. 'height': sliderHeight + 'px'
  2088. });
  2089. navigationSlider.show();
  2090. navigationSliderParent.addClass('white');
  2091. }
  2092. };
  2093. function radToDeg(rad) {
  2094. return rad * 180 / Math.PI;
  2095. }
  2096. ;var Orientation = function(axis, offsetTo) {
  2097. this._axis = axis;
  2098. this._offsetTo = null;
  2099. }
  2100. Orientation.prototype = {
  2101. constructor: Orientation,
  2102. getLabel: function() {
  2103. switch(this._axis) {
  2104. case(Axis.X):
  2105. return 'x-axis';
  2106. case(Axis.Y):
  2107. return 'y-axis';
  2108. case(Axis.Z):
  2109. return 'z-axis';
  2110. }
  2111. },
  2112. get axis() {
  2113. return this._axis;
  2114. },
  2115. get offsetTo() {
  2116. return this._offsetTo;
  2117. },
  2118. set offsetTo(value) {
  2119. this._offsetTo = value;
  2120. }
  2121. }
  2122. var Axis = {
  2123. X: 0,
  2124. Y: 1,
  2125. Z: 2
  2126. }
  2127. var OffsetTo = {
  2128. TOP: 0,
  2129. LEFT: 1,
  2130. BOTTOM: 2,
  2131. RIGHT: 3
  2132. }
  2133. ;IPE.interceptors.SendInterceptor = (function() {
  2134. return {
  2135. init: function() {
  2136. $(document).ajaxSend(function (e, xhr, settings) {
  2137. if(settings.url.indexOf('/static/') === -1) {
  2138. if(!settings.url.endsWith('/')) {
  2139. settings.url += '/';
  2140. }
  2141. }
  2142. });
  2143. }
  2144. };
  2145. }())
  2146. ;var NavigationPlane = function(element, horizontalLabel, verticalLabel) {
  2147. this._element = element;
  2148. this._parent = element.parent();
  2149. this._horizontalLabel = horizontalLabel;
  2150. this._verticalLabel = verticalLabel;
  2151. this._zoomedInfoArray = null;
  2152. this._volumeFace = null;
  2153. }
  2154. NavigationPlane.prototype = {
  2155. constructor: NavigationPlane,
  2156. set zoomedInfoArray(value) {
  2157. this._zoomedInfoArray = value;
  2158. },
  2159. set volumeFace(value) {
  2160. this._volumeFace = value;
  2161. },
  2162. }
  2163. ;