threeJsHelper.js 85 KB

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