ZoomHelper.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. var ZoomHelper = function() {
  2. var navigationPlaneHorLabel = $('#navigation-plane-hor-label'),
  3. navigationPlaneVerLabel = $('#navigation-plane-ver-label'),
  4. navigationSliderLabel = $('#navigation-slider-label'),
  5. zoomStatus = $('#zoom-status'),
  6. zoomInButton = $('input#zoomin'),
  7. zoomOutButton = $('input#zoomout'),
  8. navigationPlane = $('div#navigation-plane'),
  9. navigationPlaneParent = navigationPlane.parent(),
  10. navigationSlider = $('div#navigation-slider'),
  11. navigationSliderParent = navigationSlider.parent(),
  12. displayTimestamp = null,
  13. planeOrientation = {
  14. ver: new Orientation(Axis.Y, OffsetTo.LEFT),
  15. hor: new Orientation(Axis.X, OffsetTo.TOP),
  16. direction: VolumeFaceDirection.BACK,
  17. orientation: VolumeFaceOrientation.XY
  18. },
  19. sliderOrientation = {axis: new Orientation(Axis.Z, OffsetTo.TOP) },
  20. zoomedIn,
  21. zoomedInfoArray = {
  22. dimension: Array(3),
  23. offset: Array(3)
  24. },
  25. oldZoomedInfos = [];
  26. var lastExecutionTime = Date.now();
  27. // adjust navigation related navigations
  28. $container.on('animation', function() {
  29. determineAxisLabels();
  30. determinePlanePosition();
  31. determineSliderPosition();
  32. });
  33. // one has to press ctrl AND alt while clicking
  34. $container.on('click', 'canvas', function(event){
  35. event.stopPropagation();
  36. event.preventDefault();
  37. // keyboard shortcut activated or button zoom in pressed before?
  38. if((event.ctrlKey == false || event.altKey == false)
  39. && !zoomInActivated) {
  40. return;
  41. }
  42. var mouseX = ( (event.clientX - $canvas.offset().left) / ($canvas.width()) ) * 2 - 1,
  43. mouseY = - ( (event.clientY - $canvas.offset().top) / ($canvas.height()) ) * 2 + 1;
  44. var vector = new THREE.Vector3( mouseX, mouseY, camera.near);
  45. vector = vector.unproject( camera );
  46. var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
  47. var intersects = raycaster.intersectObjects( [frontBox] );
  48. if(intersects.length > 0) {
  49. if(!handleZoomStatus(true)) {
  50. return false;
  51. }
  52. var intersect = intersects[0],
  53. point = intersect.point;
  54. var geometry = new THREE.BoxGeometry( 0.1, 0.1, 0.1 );
  55. var material = new THREE.MeshBasicMaterial( {
  56. color: new THREE.Color( 0xaaaaaa ),
  57. opacity: 0.3
  58. });
  59. mesh = new THREE.Mesh( geometry, material );
  60. mesh.position.x = point.x;
  61. mesh.position.y = point.y;
  62. mesh.position.z = point.z;
  63. scene.add(mesh);
  64. intersectCubes[intersectCubes.length] = mesh;
  65. intersectCubesTimeStamps[intersectCubesTimeStamps.length] = Date.now();
  66. var realPoint = point.clone();
  67. getSubvolume(point, false, 'zoomIn', false);
  68. }
  69. });
  70. function getSubvolume(realPoint, alreadyTranslated, zoomAction, sameDepth, fromDraggable) {
  71. var requestedRes = typeof(window.requestedSize)=="undefined" ? config.defaultSize : requestedSize;
  72. if(alreadyTranslated == undefined || !alreadyTranslated) {
  73. realPoint = realPoint.applyMatrix4((new THREE.Matrix4).makeRotationX(Math.PI / -2));
  74. // retranslate the point into original position beginning from 0,0,0
  75. realPoint.add(new THREE.Vector3(0.5, 0.5, 0.5));
  76. }
  77. volumePointArray = realPoint.toArray();
  78. var processingUrl = IPE.util.buildUrl('volumes/' + volumeId + '/processing/sub/');
  79. $.each(volumePointArray, function(index, value) {
  80. dimWidth = null;
  81. // have to decide, whether we in zoomed in or zoomed out status
  82. if(zoomedInfo == undefined || zoomedInfo == null || fromDraggable) {
  83. if(index == 0) {
  84. dimWidth = textureInfo.originalSize.sizex;
  85. } else if(index == 1) {
  86. dimWidth = textureInfo.originalSize.sizey;
  87. } else {
  88. dimWidth = textureInfo.originalSize.sizez;
  89. }
  90. } else {
  91. if(index < 2) {
  92. dimWidth = zoomedInfo.dimension.xywidth;
  93. } else {
  94. dimWidth = zoomedInfo.numberOfSlices;
  95. }
  96. }
  97. value *= dimWidth;
  98. // due to interpolation algorithm, we had to rotate the whole cube, that it matches
  99. // the display of imagej
  100. // so we have to map the current pointer values to the real volume values
  101. // but only for the y and z direction --> the x direction is all right
  102. if(index > 0) {
  103. value = dimWidth - value;
  104. }
  105. if(!fromDraggable && zoomedInfo) {
  106. if(index == 0) {
  107. value = value + zoomedInfo.dimension.xmin;
  108. } else if(index == 1) {
  109. value = value + zoomedInfo.dimension.ymin;
  110. } else {
  111. value = value + zoomedInfo.dimension.zmin;
  112. }
  113. }
  114. value = Math.floor(value);
  115. volumePointArray[index] = value;
  116. processingUrl += value + '/';
  117. });
  118. frameNumber = imgInfo.frameFrom + currentTexture;
  119. processingUrl += frameNumber + '/';
  120. depth = 1;
  121. if(zoomAction == 'zoomIn') {
  122. if(zoomedInfo != null){
  123. if(sameDepth) {
  124. depth = zoomedInfo.depth;
  125. } else {
  126. depth = zoomedInfo.depth + 1;
  127. }
  128. }
  129. } else if(zoomAction == 'zoomOut') {
  130. if(zoomedInfo.depth > 1) {
  131. depth = zoomedInfo.depth - 1;
  132. }
  133. }
  134. while(oldZoomedInfos.length > 0
  135. && oldZoomedInfos.last().zoomedInfo.depth >= depth)
  136. {
  137. oldZoomedInfos.pop();
  138. }
  139. processingUrl += depth + '/';
  140. processingUrl += requestedRes + '/';
  141. $.ajax({
  142. url: processingUrl,
  143. success: function(data) {
  144. var available = false;
  145. var availableTestCounter = 0;
  146. zoomedInfo = data;
  147. oldZoomedInfos.push({
  148. point: realPoint,
  149. translated: true,
  150. zoomedInfo: zoomedInfo
  151. });
  152. // this function is called recursive by the settimeout statement
  153. availableTest = function() {
  154. $.ajax({
  155. url: IPE.util.buildUrl('volumes/' + volumeId + '/processing/sprite/' + zoomedInfo.spriteId + '/available/'),
  156. success: function(data) {
  157. available = data.available;
  158. },
  159. dataType: 'json',
  160. async: false
  161. });
  162. if(available) {
  163. // subvolume available: fetch it
  164. fetchSubVolume(zoomAction);
  165. } else if(availableTestCounter < 80) {
  166. // abort condition not reached --> try again
  167. setTimeout(availableTest, 500);
  168. availableTestCounter++;
  169. } else {
  170. oldZoomedInfos.pop();
  171. // abort condition reached --> error handling
  172. $(document).trigger('zoomActionFinished', { zoomAction: zoomAction, error: true });
  173. }
  174. };
  175. setTimeout(availableTest, 500);
  176. },
  177. dataType: 'json',
  178. async: true,
  179. error: function(data) {
  180. helper.displayMessage('Sorry, an error occured during processing zoom', true, null, 2500);
  181. }
  182. });
  183. };
  184. var fetchSubVolume = function(zoomAction) {
  185. imageSrc = IPE.util.buildUrl('volumes/' + volumeId + '/processing/sprite/' + zoomedInfo.spriteId + '/show/');
  186. var image = new Image();
  187. var texture = initTexture(new THREE.Texture(image));
  188. image.onload = function() {
  189. materialScreen.uniforms.numberOfSlices.value = zoomedInfo.numberOfSlices;
  190. materialScreen.uniforms.numberOfSlices.needsupdate = true;
  191. materialScreen.uniforms.slicesOverX.value = zoomedInfo.slicesOverX;
  192. materialScreen.uniforms.slicesOverX.needsUpdate = true;
  193. materialScreen.uniforms.slicesOverY.value = zoomedInfo.slicesOverY;
  194. materialScreen.uniforms.slicesOverY.needsUpdate = true;
  195. materialScreen.uniforms.numberOfSprites.value = 1;
  196. materialScreen.uniforms.numberOfSprites.needsUpdate = true;
  197. materialScreen.uniforms.slicesPerSprite.value = zoomedInfo.numberOfSlices;
  198. materialScreen.uniforms.slicesPerSprite.needsUpdate = true;
  199. updateTexture([texture]);
  200. zoomedVolumeDimension.xmin = zoomedInfo.dimension.xmin;
  201. zoomedVolumeDimension.xmax = zoomedInfo.dimension.xmin + zoomedInfo.dimension.xywidth - 1;
  202. zoomedVolumeDimension.ymin = zoomedInfo.dimension.ymin;
  203. zoomedVolumeDimension.ymax = zoomedInfo.dimension.ymin + zoomedInfo.dimension.xywidth - 1;
  204. zoomedVolumeDimension.zmin = zoomedInfo.dimension.zmin;
  205. zoomedVolumeDimension.zmax = zoomedInfo.dimension.zmin + zoomedInfo.numberOfSlices - 1;
  206. originalVolumeDimension = currentVolumeDimension;
  207. originalDimension = currentDimension;
  208. currentVolumeDimension = zoomedVolumeDimension;
  209. repositionLayerSliders();
  210. $(document).trigger('zoomActionFinished', {
  211. zoomAction: zoomAction, textureNumber: frameNumber
  212. });
  213. }
  214. image.src = imageSrc;
  215. };
  216. $container.on('contextmenu', function(event){
  217. if(event.ctrlKey == false) {
  218. return;
  219. }
  220. if(event.altKey == false) {
  221. return;
  222. }
  223. if(!handleZoomStatus(false)) {
  224. return false;
  225. }
  226. return zoomOut();
  227. });
  228. function zoomOut() {
  229. currentZoomPoint = oldZoomedInfos.pop().point;
  230. if(oldZoomedInfos.length > 0) {
  231. // using the current point to get a new subvolume
  232. getSubvolume(currentZoomPoint, true, 'zoomOut', true);
  233. return false;
  234. }
  235. else
  236. {
  237. zoomedInfo = null;
  238. materialScreen.uniforms.numberOfSlices.value = textureInfo.info.numberOfSlices;
  239. materialScreen.uniforms.numberOfSlices.needsupdate = true;
  240. materialScreen.uniforms.slicesOverX.value = textureInfo.info.slicesOverX;
  241. materialScreen.uniforms.slicesOverX.needsUpdate = true;
  242. materialScreen.uniforms.slicesOverY.value = textureInfo.info.slicesOverY;
  243. materialScreen.uniforms.slicesOverY.needsUpdate = true;
  244. materialScreen.uniforms.numberOfSprites.value = imgInfo.numberOfSprites;
  245. materialScreen.uniforms.numberOfSprites.needsUpdate = true;
  246. materialScreen.uniforms.slicesPerSprite.value = imgInfo.slicesPerSprite;
  247. materialScreen.uniforms.slicesPerSprite.needsUpdate = true;
  248. updateTexture();
  249. currentVolumeDimension = originalVolumeDimension;
  250. currentDimension = originalDimension;
  251. repositionLayerSliders();
  252. }
  253. $(document).trigger('zoomActionFinished', {
  254. zoomAction: 'zoomOut'
  255. });
  256. return false;
  257. }
  258. function zoomInAllowed() {
  259. return !zoomedIn || zoomedInfo.dimension.xywidth > 300;
  260. }
  261. /**
  262. * return: procceed or not
  263. */
  264. function handleZoomStatus(zoomIn) {
  265. zoomInButton.removeClass('red');
  266. zoomInActivated = false;
  267. if(zoomIn && !zoomInAllowed()) {
  268. return false;
  269. } else if(!zoomIn && !zoomedIn) {
  270. return false;
  271. }
  272. waitDiv.removeClass('hidden');
  273. displayMessage = zoomIn ? 'Generating zoomed subvolume, please wait a moment' : 'Zooming out';
  274. helper.displayMessage(displayMessage);
  275. displayTimestamp = Date.now();
  276. return true;
  277. }
  278. // general function to disable stuff like messages etc.
  279. $(document).on('zoomActionFinished', function(e, params) {
  280. zoomedIn = zoomedInfo != null;
  281. timeout = 2000 - (Date.now() - displayTimestamp);
  282. if(timeout < 0) {
  283. timeout = 0;
  284. }
  285. helper.fadeoutMessage(null, timeout);
  286. zoomedStatusText = '';
  287. if(zoomedIn) {
  288. zoomStatus.addClass('green-background');
  289. zoomedStatusText = 'zoomed in';
  290. $.each($('.res-link'), function(index, value) {
  291. $(value).addClass('disabled');
  292. });
  293. if(zoomedInfo.dimension.xywidth <= 300) {
  294. zoomInButton.prop('disabled', true);
  295. }
  296. } else {
  297. zoomStatus.removeClass('green-background');
  298. zoomedStatusText = 'zoomed out';
  299. if(params.error) {
  300. errorMessage = 'Error during subvolume generation - zoomed out again';
  301. helper.displayMessage(errorMessage, true, null, 5000);
  302. }
  303. $.each($('.res-link'), function(index, value) {
  304. $(value).removeClass('disabled');
  305. });
  306. zoomInButton.prop('disabled', false);
  307. }
  308. zoomStatus.html(zoomedStatusText);
  309. waitDiv.addClass('hidden');
  310. });
  311. // draggable related stuff
  312. // TODO for multilevel zooming
  313. $(document).on('zoomActionFinished', function(e, params) {
  314. zoomedIn = zoomedInfo != null;
  315. if(zoomedIn) {
  316. zoomedInfoArray.offset[Axis.X] = zoomedVolumeDimension.xmin;
  317. zoomedInfoArray.offset[Axis.Y] = zoomedVolumeDimension.ymin;
  318. zoomedInfoArray.offset[Axis.Z] = zoomedVolumeDimension.zmin;
  319. zoomedInfoArray.dimension[Axis.X] = zoomedInfo.dimension.xywidth;
  320. zoomedInfoArray.dimension[Axis.Y] = zoomedInfo.dimension.xywidth;
  321. zoomedInfoArray.dimension[Axis.Z] = zoomedInfo.numberOfSlices;
  322. } else {
  323. navigationPlane.hide();
  324. navigationPlaneParent.removeClass('white');
  325. navigationSlider.hide();
  326. navigationSliderParent.removeClass('white');
  327. }
  328. navigationPlane.removeClass('no-pos-set');
  329. navigationSlider.removeClass('no-pos-set');
  330. });
  331. navigationPlane.draggable({
  332. containment: '#navigation-plane-container',
  333. scroll: false,
  334. stop: function() {
  335. zoomedDraggableChanged();
  336. }
  337. });
  338. navigationSlider.draggable({
  339. containment: '#navigation-slider-container',
  340. scroll: false,
  341. stop: function() {
  342. zoomedDraggableChanged();
  343. }
  344. });
  345. function zoomedDraggableChanged() {
  346. waitDiv.removeClass('hidden');
  347. var planeWidthHalf = navigationPlane.width() / 2,
  348. planeHeightHalf = navigationPlane.height() / 2,
  349. planeOffsetLeft = navigationPlane.offset().left - navigationPlaneParent.offset().left - 1,
  350. planeOffsetTop = navigationPlane.offset().top - navigationPlaneParent.offset().top - 1,
  351. sliderHeightHalf = navigationSlider.height() / 2,
  352. sliderOffsetTop = navigationSlider.offset().top - navigationSliderParent.offset().top - 1,
  353. orientation = planeOrientation.orientation,
  354. direction = planeOrientation.direction;
  355. // set correct border values due to messure errors
  356. if(planeOffsetLeft < 0) {
  357. planeOffsetLeft = 0;
  358. } else if(planeOffsetLeft > navigationPlaneParent.width() - navigationPlane.width()) {
  359. planeOffsetLeft = navigationPlaneParent.width() - navigationPlane.width();
  360. }
  361. if(planeOffsetTop < 0) {
  362. planeOffsetTop = 0;
  363. } else if(planeOffsetTop > navigationPlaneParent.height() - navigationPlane.height()) {
  364. planeOffsetTop = navigationPlaneParent.height() - navigationPlane.height();
  365. }
  366. if(sliderOffsetTop < 0) {
  367. sliderOffsetTop = 0;
  368. } else if(sliderOffsetTop > navigationSliderParent.height() - navigationSlider.height()) {
  369. sliderOffsetTop = navigationSliderParent.height() - navigationSlider.height();
  370. }
  371. planeOffsetLeft = planeOffsetLeft + planeWidthHalf;
  372. planeOffsetTop = planeOffsetTop + planeHeightHalf;
  373. sliderOffsetTop = sliderOffsetTop + sliderHeightHalf;
  374. horAxis = planeOrientation.hor.axis;
  375. verAxis = planeOrientation.ver.axis;
  376. pointAsArray = Array(3);
  377. pointAsArray[horAxis] = planeOffsetLeft / navigationPlaneParent.width();
  378. pointAsArray[verAxis] = planeOffsetTop / navigationPlaneParent.height();
  379. /*if(planeOrientation.direction == VolumeFaceDirection.BACK) {
  380. pointAsArray[horAxis] = 1.0 - pointAsArray[horAxis];
  381. } else if(planeOrientation.orientation == VolumeFaceOrientation.XZ) {
  382. pointAsArray[horAxis] = 1.0 - pointAsArray[horAxis];
  383. }*/
  384. if((planeOrientation.orientation == VolumeFaceOrientation.XY
  385. && planeOrientation.direction == VolumeFaceDirection.BACK)
  386. || (planeOrientation.orientation == VolumeFaceOrientation.YZ
  387. && planeOrientation.direction == VolumeFaceDirection.BACK)
  388. || (planeOrientation.orientation == VolumeFaceOrientation.XZ
  389. && planeOrientation.direction == VolumeFaceDirection.BACK)) {
  390. pointAsArray[horAxis] = 1.0 - pointAsArray[horAxis];
  391. }
  392. pointAsArray[sliderOrientation.axis] = sliderOffsetTop / navigationSliderParent.height();
  393. /*if((sliderOrientation.axis == Axis.Z
  394. && planeOrientation.direction == VolumeFaceDirection.FRONT)
  395. || (sliderOrientation.axis == Axis.Y
  396. && planeOrientation.direction == VolumeFaceDirection.FRONT)
  397. || (sliderOrientation.axis == Axis.X
  398. && planeOrientation.direction == VolumeFaceDirection.BACK)) {
  399. pointAsArray[sliderOrientation.axis] = 1.0 - pointAsArray[sliderOrientation.axis];
  400. }*/
  401. if((sliderOrientation.axis == Axis.X
  402. && planeOrientation.direction == VolumeFaceDirection.FRONT)
  403. || (sliderOrientation.axis == Axis.Y
  404. && planeOrientation.direction == VolumeFaceDirection.BACK)
  405. || (sliderOrientation.axis == Axis.Z
  406. && planeOrientation.direction == VolumeFaceDirection.BACK)) {
  407. pointAsArray[sliderOrientation.axis] = 1.0 - pointAsArray[sliderOrientation.axis];
  408. }
  409. point = new THREE.Vector3(pointAsArray[0], pointAsArray[1], pointAsArray[2]);
  410. getSubvolume(point, true, 'zoomIn', true, true);
  411. };
  412. var zoomInActivated = false;
  413. zoomInButton.on('click', function() {
  414. zoomInActivated = !zoomInActivated;
  415. if(zoomInActivated) {
  416. $(this).addClass('red');
  417. } else {
  418. $(this).removeClass('red');
  419. }
  420. });
  421. zoomOutButton.on('click', function() {
  422. zoomInButton.removeClass('red');
  423. if(!handleZoomStatus(false)) {
  424. return false;
  425. }
  426. return zoomOut();
  427. });
  428. function determineAxisLabels() {
  429. if(Date.now() - lastExecutionTime > 100) {
  430. var lookAtVector = new THREE.Vector3(0,0, -1);
  431. lookAtVector.applyQuaternion(camera.quaternion);
  432. xIterator = -0.4;
  433. yIterator = -0.4;
  434. facesIntersect = {};
  435. interSectStartingPoint = new THREE.Vector3(xIterator, yIterator, camera.near);
  436. for(xIterator = -0.4; xIterator <= 0.4; xIterator += 0.2) {
  437. for(yIterator = -0.4; yIterator <= 0.4; yIterator += 0.2) {
  438. interSectStartingPoint.x = xIterator;
  439. interSectStartingPoint.y = yIterator;
  440. vector = interSectStartingPoint.unproject( camera );
  441. var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
  442. var intersects = raycaster.intersectObjects( [frontBox] );
  443. if(intersects.length > 0) {
  444. var intersect = intersects[0],
  445. point = intersect.point,
  446. face = intersect.face,
  447. faceObject = determineVolumeFace(face.normal),
  448. faceIdent = faceObject.getIdentifier();
  449. alreadyAdded = Object.keys(facesIntersect).indexOf(faceIdent) >= 0;
  450. if(alreadyAdded) {
  451. facesIntersect[faceIdent].count++;
  452. } else {
  453. facesIntersect[faceIdent] = { faceObject: faceObject, count: 1};
  454. }
  455. }
  456. }
  457. }
  458. frontFace = { count: 0 };
  459. for(faceIdent in facesIntersect) {
  460. if(facesIntersect[faceIdent].count > frontFace.count) {
  461. frontFace = facesIntersect[faceIdent];
  462. }
  463. }
  464. if(frontFace.faceObject != undefined) {
  465. volumeFace = frontFace.faceObject;
  466. axisOfNaviation = volumeFace.getAxisOfNaviation();
  467. planeOrientation = axisOfNaviation.plane;
  468. planeOrientation.hor.offsetTo = OffsetTo.LEFT;
  469. planeOrientation.ver.offsetTo = OffsetTo.TOP;
  470. planeOrientation.direction = volumeFace.direction;
  471. planeOrientation.orientation = volumeFace.orientation;
  472. sliderOrientation = axisOfNaviation.slider;
  473. sliderOrientation.offsetTo = OffsetTo.TOP;
  474. navigationPlaneHorLabel.html(planeOrientation.hor.getLabel());
  475. navigationPlaneVerLabel.html(planeOrientation.ver.getLabel());
  476. navigationSliderLabel.html(sliderOrientation.getLabel());
  477. }
  478. lastExecutionTime = Date.now();
  479. }
  480. }
  481. function determinePlanePosition() {
  482. if(!zoomedIn) {
  483. return;
  484. }
  485. if(navigationPlane.hasClass('ui-draggable-dragging')
  486. || navigationPlane.hasClass('no-pos-set')) {
  487. navigationPlane.addClass('no-pos-set');
  488. return;
  489. }
  490. horAxis = planeOrientation.hor.axis;
  491. verAxis = planeOrientation.ver.axis;
  492. planeRelativeX = navigationPlaneParent.width() / originalSizeArray[horAxis];
  493. planeRelativeY = navigationPlaneParent.height() / originalSizeArray[verAxis];
  494. planeWidth = planeRelativeX * zoomedInfoArray.dimension[horAxis];
  495. planeHeight = planeRelativeY * zoomedInfoArray.dimension[verAxis];
  496. planeWidth = Math.ceil(planeWidth);
  497. planeHeight = Math.ceil(planeHeight);
  498. planeOffsetLeft = zoomedInfoArray.offset[horAxis] * planeRelativeX;
  499. if((planeOrientation.direction == VolumeFaceDirection.BACK
  500. && planeOrientation.orientation == VolumeFaceOrientation.XZ)
  501. || (planeOrientation.direction == VolumeFaceDirection.FRONT
  502. && planeOrientation.orientation == VolumeFaceOrientation.YZ)) {
  503. planeOffsetLeft = navigationPlaneParent.width() - (planeOffsetLeft + navigationPlane.width());
  504. }
  505. planeOffsetTop = zoomedInfoArray.offset[verAxis] * planeRelativeY;
  506. if(planeOrientation.orientation == VolumeFaceOrientation.XZ
  507. || planeOrientation.orientation == VolumeFaceOrientation.YZ){
  508. planeOffsetTop = navigationPlaneParent.height() - (planeOffsetTop + navigationPlane.height());
  509. }
  510. navigationPlane.css({
  511. 'top': planeOffsetTop + 'px',
  512. 'left' : planeOffsetLeft + 'px',
  513. 'width': planeWidth + 'px',
  514. 'height': planeHeight + 'px'
  515. });
  516. navigationPlane.show();
  517. navigationPlaneParent.addClass('white');
  518. }
  519. function determineSliderPosition() {
  520. if(!zoomedIn) {
  521. return;
  522. }
  523. if(navigationSlider.hasClass('ui-draggable-dragging')
  524. || navigationSlider.hasClass('no-pos-set')) {
  525. navigationSlider.addClass('no-pos-set');
  526. return;
  527. }
  528. sliderRelative = navigationSliderParent.height() / originalSizeArray[sliderOrientation.axis];
  529. sliderOffsetTop = zoomedInfoArray.offset[sliderOrientation.axis] * sliderRelative;
  530. sliderHeight = Math.ceil(sliderRelative * zoomedInfoArray.dimension[sliderOrientation.axis]);
  531. if(planeOrientation.direction == VolumeFaceDirection.FRONT) {
  532. sliderOffsetTop = navigationSliderParent.height() - (navigationSlider.height() + sliderOffsetTop);
  533. }
  534. navigationSlider.css({
  535. 'top': sliderOffsetTop + 'px',
  536. 'height': sliderHeight + 'px'
  537. });
  538. navigationSlider.show();
  539. navigationSliderParent.addClass('white');
  540. }
  541. };
  542. function radToDeg(rad) {
  543. return rad * 180 / Math.PI;
  544. }