Sfoglia il codice sorgente

Cleaned .gitignore file from unneccessary excludes and add lost files

Felix Schultze 9 anni fa
parent
commit
dab5ce7db8
37 ha cambiato i file con 20151 aggiunte e 29 eliminazioni
  1. 0 29
      .gitignore
  2. BIN
      static/css/lib/images/ui-bg_diagonals-thick_18_b81900_40x40.png
  3. BIN
      static/css/lib/images/ui-bg_diagonals-thick_20_666666_40x40.png
  4. BIN
      static/css/lib/images/ui-bg_flat_10_000000_40x100.png
  5. BIN
      static/css/lib/images/ui-bg_glass_100_f6f6f6_1x400.png
  6. BIN
      static/css/lib/images/ui-bg_glass_100_fdf5ce_1x400.png
  7. BIN
      static/css/lib/images/ui-bg_glass_65_ffffff_1x400.png
  8. BIN
      static/css/lib/images/ui-bg_gloss-wave_35_f6a828_500x100.png
  9. BIN
      static/css/lib/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
  10. BIN
      static/css/lib/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
  11. BIN
      static/css/lib/images/ui-icons_222222_256x240.png
  12. BIN
      static/css/lib/images/ui-icons_228ef1_256x240.png
  13. BIN
      static/css/lib/images/ui-icons_ef8c08_256x240.png
  14. BIN
      static/css/lib/images/ui-icons_ffd27a_256x240.png
  15. BIN
      static/css/lib/images/ui-icons_ffffff_256x240.png
  16. 5 0
      static/css/lib/jquery-ui.min.css
  17. 4 0
      static/css/lib/jquery-ui.structure.min.css
  18. 410 0
      static/css/lib/jquery-ui.theme.css
  19. 259 0
      static/css/lib/jquery.jqplot.css
  20. 59 0
      static/js/lib/Detector.js
  21. 651 0
      static/js/lib/OrbitControls.js
  22. 4 0
      static/js/lib/head.core.min.js.map
  23. 1 0
      static/js/lib/head.load.min.js
  24. 0 0
      static/js/lib/helvetiker_regular.typeface.js
  25. 2 0
      static/js/lib/jqplot.dragable.min.js
  26. 1 0
      static/js/lib/jquery-2.1.1.min.js
  27. 5 0
      static/js/lib/jquery-ui.min.js
  28. 2 0
      static/js/lib/jquery.jqplot.min.js
  29. 11 0
      static/js/lib/jquery.ui.touch-punch.min.js
  30. 1 0
      static/js/lib/kinetic-v5.0.2.min.js
  31. 6 0
      static/js/lib/stats.min.js
  32. 15957 0
      static/js/lib/three.js
  33. 372 0
      static/js/lib/three.min.js
  34. 2398 0
      static/js/threeJsHelper/dist/threeJsHelper.js
  35. 1 0
      visualization/settings_env.py.dev
  36. 1 0
      visualization/settings_env.py.prod
  37. 1 0
      visualization/settings_env.py.staging

+ 0 - 29
.gitignore

@@ -1,40 +1,11 @@
 *.py[cod]
 
-# C extensions
-*.so
-
 # Packages
-*.egg
-*.egg-info
-dist
-build
-eggs
-parts
-bin
-var
-sdist
-develop-eggs
-.installed.cfg
-lib
-lib64
 __pycache__
 
 # Installer logs
 pip-log.txt
 
-# Unit test / coverage reports
-.coverage
-.tox
-nosetests.xml
-
-# Translations
-*.mo
-
-# Mr Developer
-.mr.developer.cfg
-.project
-.pydevproject
-
 .swp
 .pyc
 node_modules/

BIN
static/css/lib/images/ui-bg_diagonals-thick_18_b81900_40x40.png


BIN
static/css/lib/images/ui-bg_diagonals-thick_20_666666_40x40.png


BIN
static/css/lib/images/ui-bg_flat_10_000000_40x100.png


BIN
static/css/lib/images/ui-bg_glass_100_f6f6f6_1x400.png


BIN
static/css/lib/images/ui-bg_glass_100_fdf5ce_1x400.png


BIN
static/css/lib/images/ui-bg_glass_65_ffffff_1x400.png


BIN
static/css/lib/images/ui-bg_gloss-wave_35_f6a828_500x100.png


BIN
static/css/lib/images/ui-bg_highlight-soft_100_eeeeee_1x100.png


BIN
static/css/lib/images/ui-bg_highlight-soft_75_ffe45c_1x100.png


BIN
static/css/lib/images/ui-icons_222222_256x240.png


BIN
static/css/lib/images/ui-icons_228ef1_256x240.png


BIN
static/css/lib/images/ui-icons_ef8c08_256x240.png


BIN
static/css/lib/images/ui-icons_ffd27a_256x240.png


BIN
static/css/lib/images/ui-icons_ffffff_256x240.png


File diff suppressed because it is too large
+ 5 - 0
static/css/lib/jquery-ui.min.css


File diff suppressed because it is too large
+ 4 - 0
static/css/lib/jquery-ui.structure.min.css


+ 410 - 0
static/css/lib/jquery-ui.theme.css

@@ -0,0 +1,410 @@
+/*!
+ * jQuery UI CSS Framework 1.11.1
+ * http://jqueryui.com
+ *
+ * Copyright 2014 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/category/theming/
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget {
+	font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;
+	font-size: 1.1em;
+}
+.ui-widget .ui-widget {
+	font-size: 1em;
+}
+.ui-widget input,
+.ui-widget select,
+.ui-widget textarea,
+.ui-widget button {
+	font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;
+	font-size: 1em;
+}
+.ui-widget-content {
+	border: 1px solid #dddddd;
+	background: #eeeeee url("images/ui-bg_highlight-soft_100_eeeeee_1x100.png") 50% top repeat-x;
+	color: #333333;
+}
+.ui-widget-content a {
+	color: #333333;
+}
+.ui-widget-header {
+	border: 1px solid #e78f08;
+	background: #f6a828 url("images/ui-bg_gloss-wave_35_f6a828_500x100.png") 50% 50% repeat-x;
+	color: #ffffff;
+	font-weight: bold;
+}
+.ui-widget-header a {
+	color: #ffffff;
+}
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default {
+	border: 1px solid #cccccc;
+	background: #f6f6f6 url("images/ui-bg_glass_100_f6f6f6_1x400.png") 50% 50% repeat-x;
+	font-weight: bold;
+	color: #1c94c4;
+}
+.ui-state-default a,
+.ui-state-default a:link,
+.ui-state-default a:visited {
+	color: #1c94c4;
+	text-decoration: none;
+}
+.ui-state-hover,
+.ui-widget-content .ui-state-hover,
+.ui-widget-header .ui-state-hover,
+.ui-state-focus,
+.ui-widget-content .ui-state-focus,
+.ui-widget-header .ui-state-focus {
+	border: 1px solid #fbcb09;
+	background: #fdf5ce url("images/ui-bg_glass_100_fdf5ce_1x400.png") 50% 50% repeat-x;
+	font-weight: bold;
+	color: #c77405;
+}
+.ui-state-hover a,
+.ui-state-hover a:hover,
+.ui-state-hover a:link,
+.ui-state-hover a:visited,
+.ui-state-focus a,
+.ui-state-focus a:hover,
+.ui-state-focus a:link,
+.ui-state-focus a:visited {
+	color: #c77405;
+	text-decoration: none;
+}
+.ui-state-active,
+.ui-widget-content .ui-state-active,
+.ui-widget-header .ui-state-active {
+	border: 1px solid #fbd850;
+	background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
+	font-weight: bold;
+	color: #eb8f00;
+}
+.ui-state-active a,
+.ui-state-active a:link,
+.ui-state-active a:visited {
+	color: #eb8f00;
+	text-decoration: none;
+}
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight,
+.ui-widget-content .ui-state-highlight,
+.ui-widget-header .ui-state-highlight {
+	border: 1px solid #fed22f;
+	background: #ffe45c url("images/ui-bg_highlight-soft_75_ffe45c_1x100.png") 50% top repeat-x;
+	color: #363636;
+}
+.ui-state-highlight a,
+.ui-widget-content .ui-state-highlight a,
+.ui-widget-header .ui-state-highlight a {
+	color: #363636;
+}
+.ui-state-error,
+.ui-widget-content .ui-state-error,
+.ui-widget-header .ui-state-error {
+	border: 1px solid #cd0a0a;
+	background: #b81900 url("images/ui-bg_diagonals-thick_18_b81900_40x40.png") 50% 50% repeat;
+	color: #ffffff;
+}
+.ui-state-error a,
+.ui-widget-content .ui-state-error a,
+.ui-widget-header .ui-state-error a {
+	color: #ffffff;
+}
+.ui-state-error-text,
+.ui-widget-content .ui-state-error-text,
+.ui-widget-header .ui-state-error-text {
+	color: #ffffff;
+}
+.ui-priority-primary,
+.ui-widget-content .ui-priority-primary,
+.ui-widget-header .ui-priority-primary {
+	font-weight: bold;
+}
+.ui-priority-secondary,
+.ui-widget-content .ui-priority-secondary,
+.ui-widget-header .ui-priority-secondary {
+	opacity: .7;
+	filter:Alpha(Opacity=70); /* support: IE8 */
+	font-weight: normal;
+}
+.ui-state-disabled,
+.ui-widget-content .ui-state-disabled,
+.ui-widget-header .ui-state-disabled {
+	opacity: .35;
+	filter:Alpha(Opacity=35); /* support: IE8 */
+	background-image: none;
+}
+.ui-state-disabled .ui-icon {
+	filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
+}
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon {
+	width: 16px;
+	height: 16px;
+}
+.ui-icon,
+.ui-widget-content .ui-icon {
+	background-image: url("images/ui-icons_222222_256x240.png");
+}
+.ui-widget-header .ui-icon {
+	background-image: url("images/ui-icons_ffffff_256x240.png");
+}
+.ui-state-default .ui-icon {
+	background-image: url("images/ui-icons_ef8c08_256x240.png");
+}
+.ui-state-hover .ui-icon,
+.ui-state-focus .ui-icon {
+	background-image: url("images/ui-icons_ef8c08_256x240.png");
+}
+.ui-state-active .ui-icon {
+	background-image: url("images/ui-icons_ef8c08_256x240.png");
+}
+.ui-state-highlight .ui-icon {
+	background-image: url("images/ui-icons_228ef1_256x240.png");
+}
+.ui-state-error .ui-icon,
+.ui-state-error-text .ui-icon {
+	background-image: url("images/ui-icons_ffd27a_256x240.png");
+}
+
+/* positioning */
+.ui-icon-blank { background-position: 16px 16px; }
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-on { background-position: -96px -144px; }
+.ui-icon-radio-off { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-left,
+.ui-corner-tl {
+	border-top-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-top,
+.ui-corner-right,
+.ui-corner-tr {
+	border-top-right-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-left,
+.ui-corner-bl {
+	border-bottom-left-radius: 4px;
+}
+.ui-corner-all,
+.ui-corner-bottom,
+.ui-corner-right,
+.ui-corner-br {
+	border-bottom-right-radius: 4px;
+}
+
+/* Overlays */
+.ui-widget-overlay {
+	background: #666666 url("images/ui-bg_diagonals-thick_20_666666_40x40.png") 50% 50% repeat;
+	opacity: .5;
+	filter: Alpha(Opacity=50); /* support: IE8 */
+}
+.ui-widget-shadow {
+	margin: -5px 0 0 -5px;
+	padding: 5px;
+	background: #000000 url("images/ui-bg_flat_10_000000_40x100.png") 50% 50% repeat-x;
+	opacity: .2;
+	filter: Alpha(Opacity=20); /* support: IE8 */
+	border-radius: 5px;
+}

+ 259 - 0
static/css/lib/jquery.jqplot.css

@@ -0,0 +1,259 @@
+/*rules for the plot target div.  These will be cascaded down to all plot elements according to css rules*/
+.jqplot-target {
+    position: relative;
+    color: #666666;
+    font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
+    font-size: 1em;
+/*    height: 300px;
+    width: 400px;*/
+}
+
+/*rules applied to all axes*/
+.jqplot-axis {
+    font-size: 0.75em;
+}
+
+.jqplot-xaxis {
+    margin-top: 10px;
+}
+
+.jqplot-x2axis {
+    margin-bottom: 10px;
+}
+
+.jqplot-yaxis {
+    margin-right: 10px;
+}
+
+.jqplot-y2axis, .jqplot-y3axis, .jqplot-y4axis, .jqplot-y5axis, .jqplot-y6axis, .jqplot-y7axis, .jqplot-y8axis, .jqplot-y9axis, .jqplot-yMidAxis {
+    margin-left: 10px;
+    margin-right: 10px;
+}
+
+/*rules applied to all axis tick divs*/
+.jqplot-axis-tick, .jqplot-xaxis-tick, .jqplot-yaxis-tick, .jqplot-x2axis-tick, .jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick, .jqplot-yMidAxis-tick {
+    position: absolute;
+    white-space: pre;
+}
+
+
+.jqplot-xaxis-tick {
+    top: 0px;
+    /* initial position untill tick is drawn in proper place */
+    left: 15px;
+/*    padding-top: 10px;*/
+    vertical-align: top;
+}
+
+.jqplot-x2axis-tick {
+    bottom: 0px;
+    /* initial position untill tick is drawn in proper place */
+    left: 15px;
+/*    padding-bottom: 10px;*/
+    vertical-align: bottom;
+}
+
+.jqplot-yaxis-tick {
+    right: 0px;
+    /* initial position untill tick is drawn in proper place */
+    top: 15px;
+/*    padding-right: 10px;*/
+    text-align: right;
+}
+
+.jqplot-yaxis-tick.jqplot-breakTick {
+    right: -20px;
+    margin-right: 0px;
+    padding:1px 5px 1px 5px;
+    /*background-color: white;*/
+    z-index: 2;
+    font-size: 1.5em;
+}
+
+.jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick {
+    left: 0px;
+    /* initial position untill tick is drawn in proper place */
+    top: 15px;
+/*    padding-left: 10px;*/
+/*    padding-right: 15px;*/
+    text-align: left;
+}
+
+.jqplot-yMidAxis-tick {
+    text-align: center;
+    white-space: nowrap;
+}
+
+.jqplot-xaxis-label {
+    margin-top: 10px;
+    font-size: 11pt;
+    position: absolute;
+}
+
+.jqplot-x2axis-label {
+    margin-bottom: 10px;
+    font-size: 11pt;
+    position: absolute;
+}
+
+.jqplot-yaxis-label {
+    margin-right: 10px;
+/*    text-align: center;*/
+    font-size: 11pt;
+    position: absolute;
+}
+
+.jqplot-yMidAxis-label {
+    font-size: 11pt;
+    position: absolute;
+}
+
+.jqplot-y2axis-label, .jqplot-y3axis-label, .jqplot-y4axis-label, .jqplot-y5axis-label, .jqplot-y6axis-label, .jqplot-y7axis-label, .jqplot-y8axis-label, .jqplot-y9axis-label {
+/*    text-align: center;*/
+    font-size: 11pt;
+    margin-left: 10px;
+    position: absolute;
+}
+
+.jqplot-meterGauge-tick {
+    font-size: 0.75em;
+    color: #999999;
+}
+
+.jqplot-meterGauge-label {
+    font-size: 1em;
+    color: #999999;
+}
+
+table.jqplot-table-legend {
+    margin-top: 12px;
+    margin-bottom: 12px;
+    margin-left: 12px;
+    margin-right: 12px;
+}
+
+table.jqplot-table-legend, table.jqplot-cursor-legend {
+    background-color: rgba(255,255,255,0.6);
+    border: 1px solid #cccccc;
+    position: absolute;
+    font-size: 0.75em;
+}
+
+td.jqplot-table-legend {
+    vertical-align:middle;
+}
+
+/*
+These rules could be used instead of assigning
+element styles and relying on js object properties.
+*/
+
+/*
+td.jqplot-table-legend-swatch {
+    padding-top: 0.5em;
+    text-align: center;
+}
+
+tr.jqplot-table-legend:first td.jqplot-table-legend-swatch {
+    padding-top: 0px;
+}
+*/
+
+td.jqplot-seriesToggle:hover, td.jqplot-seriesToggle:active {
+    cursor: pointer;
+}
+
+.jqplot-table-legend .jqplot-series-hidden {
+    text-decoration: line-through;
+}
+
+div.jqplot-table-legend-swatch-outline {
+    border: 1px solid #cccccc;
+    padding:1px;
+}
+
+div.jqplot-table-legend-swatch {
+    width:0px;
+    height:0px;
+    border-top-width: 5px;
+    border-bottom-width: 5px;
+    border-left-width: 6px;
+    border-right-width: 6px;
+    border-top-style: solid;
+    border-bottom-style: solid;
+    border-left-style: solid;
+    border-right-style: solid;
+}
+
+.jqplot-title {
+    top: 0px;
+    left: 0px;
+    padding-bottom: 0.5em;
+    font-size: 1.2em;
+}
+
+table.jqplot-cursor-tooltip {
+    border: 1px solid #cccccc;
+    font-size: 0.75em;
+}
+
+
+.jqplot-cursor-tooltip {
+    border: 1px solid #cccccc;
+    font-size: 0.75em;
+    white-space: nowrap;
+    background: rgba(208,208,208,0.5);
+    padding: 1px;
+}
+
+.jqplot-highlighter-tooltip, .jqplot-canvasOverlay-tooltip {
+    border: 1px solid #cccccc;
+    font-size: 0.75em;
+    white-space: nowrap;
+    background: rgba(208,208,208,0.5);
+    padding: 1px;
+}
+
+.jqplot-point-label {
+    font-size: 0.75em;
+    z-index: 2;
+}
+      
+td.jqplot-cursor-legend-swatch {
+    vertical-align: middle;
+    text-align: center;
+}
+
+div.jqplot-cursor-legend-swatch {
+    width: 1.2em;
+    height: 0.7em;
+}
+
+.jqplot-error {
+/*   Styles added to the plot target container when there is an error go here.*/
+    text-align: center;
+}
+
+.jqplot-error-message {
+/*    Styling of the custom error message div goes here.*/
+    position: relative;
+    top: 46%;
+    display: inline-block;
+}
+
+div.jqplot-bubble-label {
+    font-size: 0.8em;
+/*    background: rgba(90%, 90%, 90%, 0.15);*/
+    padding-left: 2px;
+    padding-right: 2px;
+    color: rgb(20%, 20%, 20%);
+}
+
+div.jqplot-bubble-label.jqplot-bubble-label-highlight {
+    background: rgba(90%, 90%, 90%, 0.7);
+}
+
+div.jqplot-noData-container {
+    text-align: center;
+    background-color: rgba(96%, 96%, 96%, 0.3);
+}

+ 59 - 0
static/js/lib/Detector.js

@@ -0,0 +1,59 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ * @author mr.doob / http://mrdoob.com/
+ */
+
+var Detector = {
+
+	canvas: !! window.CanvasRenderingContext2D,
+	webgl: ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )(),
+	workers: !! window.Worker,
+	fileapi: window.File && window.FileReader && window.FileList && window.Blob,
+
+	getWebGLErrorMessage: function () {
+
+		var element = document.createElement( 'div' );
+		element.id = 'webgl-error-message';
+		element.style.fontFamily = 'monospace';
+		element.style.fontSize = '13px';
+		element.style.fontWeight = 'normal';
+		element.style.textAlign = 'center';
+		element.style.background = '#fff';
+		element.style.color = '#000';
+		element.style.padding = '1.5em';
+		element.style.width = '400px';
+		element.style.margin = '5em auto 0';
+
+		if ( ! this.webgl ) {
+
+			element.innerHTML = window.WebGLRenderingContext ? [
+				'Your graphics card does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br />',
+				'Find out how to get it <a href="http://get.webgl.org/" style="color:#000">here</a>.'
+			].join( '\n' ) : [
+				'Your browser does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br/>',
+				'Find out how to get it <a href="http://get.webgl.org/" style="color:#000">here</a>.'
+			].join( '\n' );
+
+		}
+
+		return element;
+
+	},
+
+	addGetWebGLMessage: function ( parameters ) {
+
+		var parent, id, element;
+
+		parameters = parameters || {};
+
+		parent = parameters.parent !== undefined ? parameters.parent : document.body;
+		id = parameters.id !== undefined ? parameters.id : 'oldie';
+
+		element = Detector.getWebGLErrorMessage();
+		element.id = id;
+
+		parent.appendChild( element );
+
+	}
+
+};

+ 651 - 0
static/js/lib/OrbitControls.js

@@ -0,0 +1,651 @@
+/**
+ * @author qiao / https://github.com/qiao
+ * @author mrdoob / http://mrdoob.com
+ * @author alteredq / http://alteredqualia.com/
+ * @author WestLangley / http://github.com/WestLangley
+ * @author erich666 / http://erichaines.com
+ */
+/*global THREE, console */
+
+// This set of controls performs orbiting, dollying (zooming), and panning. It maintains
+// the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is
+// supported.
+//
+//    Orbit - left mouse / touch: one finger move
+//    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
+//    Pan - right mouse, or arrow keys / touch: three finter swipe
+//
+// This is a drop-in replacement for (most) TrackballControls used in examples.
+// That is, include this js file and wherever you see:
+//      controls = new THREE.TrackballControls( camera );
+//      controls.target.z = 150;
+// Simple substitute "OrbitControls" and the control should work as-is.
+
+THREE.OrbitControls = function ( object, domElement ) {
+
+    this.object = object;
+    this.domElement = ( domElement !== undefined ) ? domElement : document;
+
+    // API
+
+    // Set to false to disable this control
+    this.enabled = true;
+
+    // "target" sets the location of focus, where the control orbits around
+    // and where it pans with respect to.
+    this.target = new THREE.Vector3();
+
+    // center is old, deprecated; use "target" instead
+    this.center = this.target;
+
+    // This option actually enables dollying in and out; left as "zoom" for
+    // backwards compatibility
+    this.noZoom = false;
+    this.zoomSpeed = 1.0;
+
+    // Limits to how far you can dolly in and out
+    this.minDistance = 0;
+    this.maxDistance = Infinity;
+
+    // Set to true to disable this control
+    this.noRotate = false;
+    this.rotateSpeed = 1.0;
+
+    // Set to true to disable this control
+    this.noPan = false;
+    this.keyPanSpeed = 7.0; // pixels moved per arrow key push
+
+    // Set to true to automatically rotate around the target
+    this.autoRotate = false;
+    this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
+
+    // How far you can orbit vertically, upper and lower limits.
+    // Range is 0 to Math.PI radians.
+    this.minPolarAngle = 0; // radians
+    this.maxPolarAngle = Math.PI; // radians
+
+    // Set to true to disable use of the keys
+    this.noKeys = true;
+
+    // The four arrow keys
+    this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
+
+    ////////////
+    // internals
+
+    var scope = this;
+
+    var EPS = 0.000001;
+
+    var rotateStart = new THREE.Vector2();
+    var rotateEnd = new THREE.Vector2();
+    var rotateDelta = new THREE.Vector2();
+
+    var panStart = new THREE.Vector2();
+    var panEnd = new THREE.Vector2();
+    var panDelta = new THREE.Vector2();
+    var panOffset = new THREE.Vector3();
+
+    var offset = new THREE.Vector3();
+
+    var dollyStart = new THREE.Vector2();
+    var dollyEnd = new THREE.Vector2();
+    var dollyDelta = new THREE.Vector2();
+
+    var phiDelta = 0;
+    var thetaDelta = 0;
+    var scale = 1;
+    var pan = new THREE.Vector3();
+
+    var lastPosition = new THREE.Vector3();
+    var lastQuaternion = new THREE.Quaternion();
+
+    var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };
+
+    var state = STATE.NONE;
+
+    // for reset
+
+    this.target0 = this.target.clone();
+    this.position0 = this.object.position.clone();
+
+    // so camera.up is the orbit axis
+
+    var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
+    var quatInverse = quat.clone().inverse();
+
+    // events
+
+    var changeEvent = { type: 'change' };
+    var startEvent = { type: 'start'};
+    var endEvent = { type: 'end'};
+
+    this.rotateLeft = function ( angle ) {
+
+        if ( angle === undefined ) {
+
+            angle = getAutoRotationAngle();
+
+        }
+
+        thetaDelta -= angle;
+
+    };
+
+    this.rotateUp = function ( angle ) {
+
+        if ( angle === undefined ) {
+
+            angle = getAutoRotationAngle();
+
+        }
+
+        phiDelta -= angle;
+
+    };
+
+    // pass in distance in world space to move left
+    this.panLeft = function ( distance ) {
+
+        var te = this.object.matrix.elements;
+
+        // get X column of matrix
+        panOffset.set( te[ 0 ], te[ 1 ], te[ 2 ] );
+        panOffset.multiplyScalar( - distance );
+
+        pan.add( panOffset );
+
+    };
+
+    // pass in distance in world space to move up
+    this.panUp = function ( distance ) {
+
+        var te = this.object.matrix.elements;
+
+        // get Y column of matrix
+        panOffset.set( te[ 4 ], te[ 5 ], te[ 6 ] );
+        panOffset.multiplyScalar( distance );
+
+        pan.add( panOffset );
+
+    };
+
+    // pass in x,y of change desired in pixel space,
+    // right and down are positive
+    this.pan = function ( deltaX, deltaY ) {
+
+        var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+
+        if ( scope.object.fov !== undefined ) {
+
+            // perspective
+            var position = scope.object.position;
+            var offset = position.clone().sub( scope.target );
+            var targetDistance = offset.length();
+
+            // half of the fov is center to top of screen
+            targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
+
+            // we actually don't use screenWidth, since perspective camera is fixed to screen height
+            scope.panLeft( 2 * deltaX * targetDistance / element.clientHeight );
+            scope.panUp( 2 * deltaY * targetDistance / element.clientHeight );
+
+        } else if ( scope.object.top !== undefined ) {
+
+            // orthographic
+            scope.panLeft( deltaX * (scope.object.right - scope.object.left) / element.clientWidth );
+            scope.panUp( deltaY * (scope.object.top - scope.object.bottom) / element.clientHeight );
+
+        } else {
+
+            // camera neither orthographic or perspective
+            console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
+
+        }
+
+    };
+
+    this.dollyIn = function ( dollyScale ) {
+
+        if ( dollyScale === undefined ) {
+
+            dollyScale = getZoomScale();
+
+        }
+
+        scale /= dollyScale;
+
+    };
+
+    this.dollyOut = function ( dollyScale ) {
+
+        if ( dollyScale === undefined ) {
+
+            dollyScale = getZoomScale();
+
+        }
+
+        scale *= dollyScale;
+
+    };
+
+    this.update = function () {
+
+        var position = this.object.position;
+
+        offset.copy( position ).sub( this.target );
+
+        // rotate offset to "y-axis-is-up" space
+        offset.applyQuaternion( quat );
+
+        // angle from z-axis around y-axis
+
+        var theta = Math.atan2( offset.x, offset.z );
+
+        // angle from y-axis
+
+        var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
+
+        if ( this.autoRotate ) {
+
+            this.rotateLeft( getAutoRotationAngle() );
+
+        }
+
+        theta += thetaDelta;
+        phi += phiDelta;
+
+        // restrict phi to be between desired limits
+        phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
+
+        // restrict phi to be betwee EPS and PI-EPS
+        phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
+
+        var radius = offset.length() * scale;
+
+        // restrict radius to be between desired limits
+        radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
+
+        // move target to panned location
+        this.target.add( pan );
+
+        offset.x = radius * Math.sin( phi ) * Math.sin( theta );
+        offset.y = radius * Math.cos( phi );
+        offset.z = radius * Math.sin( phi ) * Math.cos( theta );
+
+        // rotate offset back to "camera-up-vector-is-up" space
+        offset.applyQuaternion( quatInverse );
+
+        position.copy( this.target ).add( offset );
+
+        this.object.lookAt( this.target );
+
+        thetaDelta = 0;
+        phiDelta = 0;
+        scale = 1;
+        pan.set( 0, 0, 0 );
+
+        // update condition is:
+        // min(camera displacement, camera rotation in radians)^2 > EPS
+        // using small-angle approximation cos(x/2) = 1 - x^2 / 8
+
+        if ( lastPosition.distanceToSquared( this.object.position ) > EPS
+            || 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS ) {
+
+            this.dispatchEvent( changeEvent );
+
+            lastPosition.copy( this.object.position );
+            lastQuaternion.copy (this.object.quaternion );
+
+        }
+
+    };
+
+
+    this.reset = function () {
+
+        state = STATE.NONE;
+
+        this.target.copy( this.target0 );
+        this.object.position.copy( this.position0 );
+
+        this.update();
+
+    };
+
+    function getAutoRotationAngle() {
+
+        return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
+
+    }
+
+    function getZoomScale() {
+
+        return Math.pow( 0.95, scope.zoomSpeed );
+
+    }
+
+    function onMouseDown( event ) {
+
+        if ( scope.enabled === false ) return;
+        event.preventDefault();
+
+        if ( event.button === 0 ) {
+            if ( scope.noRotate === true ) return;
+
+            state = STATE.ROTATE;
+
+            rotateStart.set( event.clientX, event.clientY );
+
+        } else if ( event.button === 1 ) {
+            if ( scope.noZoom === true ) return;
+
+            state = STATE.DOLLY;
+
+            dollyStart.set( event.clientX, event.clientY );
+
+        } else if ( event.button === 2 ) {
+            if ( scope.noPan === true ) return;
+
+            state = STATE.PAN;
+
+            panStart.set( event.clientX, event.clientY );
+
+        }
+
+        document.addEventListener( 'mousemove', onMouseMove, false );
+        document.addEventListener( 'mouseup', onMouseUp, false );
+        scope.dispatchEvent( startEvent );
+
+    }
+
+    function onMouseMove( event ) {
+
+        if ( scope.enabled === false ) return;
+
+        event.preventDefault();
+
+        var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+
+        if ( state === STATE.ROTATE ) {
+
+            if ( scope.noRotate === true ) return;
+
+            rotateEnd.set( event.clientX, event.clientY );
+            rotateDelta.subVectors( rotateEnd, rotateStart );
+
+            // rotating across whole screen goes 360 degrees around
+            scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
+
+            // rotating up and down along whole screen attempts to go 360, but limited to 180
+            scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
+
+            rotateStart.copy( rotateEnd );
+
+        } else if ( state === STATE.DOLLY ) {
+
+            if ( scope.noZoom === true ) return;
+
+            dollyEnd.set( event.clientX, event.clientY );
+            dollyDelta.subVectors( dollyEnd, dollyStart );
+
+            if ( dollyDelta.y > 0 ) {
+
+                scope.dollyIn();
+
+            } else {
+
+                scope.dollyOut();
+
+            }
+
+            dollyStart.copy( dollyEnd );
+
+        } else if ( state === STATE.PAN ) {
+
+            if ( scope.noPan === true ) return;
+
+            panEnd.set( event.clientX, event.clientY );
+            panDelta.subVectors( panEnd, panStart );
+
+            scope.pan( panDelta.x, panDelta.y );
+
+            panStart.copy( panEnd );
+
+        }
+
+        scope.update();
+
+    }
+
+    function onMouseUp( /* event */ ) {
+
+        if ( scope.enabled === false ) return;
+
+        document.removeEventListener( 'mousemove', onMouseMove, false );
+        document.removeEventListener( 'mouseup', onMouseUp, false );
+        scope.dispatchEvent( endEvent );
+        state = STATE.NONE;
+
+    }
+
+    function onMouseWheel( event ) {
+        if(event.ctrlKey == true) {
+            return;
+        }
+
+
+        if ( scope.enabled === false || scope.noZoom === true ) return;
+
+        event.preventDefault();
+        event.stopPropagation();
+
+        var delta = 0;
+
+        if ( event.wheelDelta !== undefined ) { // WebKit / Opera / Explorer 9
+
+            delta = event.wheelDelta;
+
+        } else if ( event.detail !== undefined ) { // Firefox
+
+            delta = - event.detail;
+
+        }
+
+        if ( delta > 0 ) {
+
+            scope.dollyOut();
+
+        } else {
+
+            scope.dollyIn();
+
+        }
+
+        scope.update();
+        scope.dispatchEvent( startEvent );
+        scope.dispatchEvent( endEvent );
+
+    }
+
+    function onKeyDown( event ) {
+
+        if ( scope.enabled === false || scope.noKeys === true || scope.noPan === true ) return;
+
+        switch ( event.keyCode ) {
+
+            case scope.keys.UP:
+                scope.pan( 0, scope.keyPanSpeed );
+                scope.update();
+                break;
+
+            case scope.keys.BOTTOM:
+                scope.pan( 0, - scope.keyPanSpeed );
+                scope.update();
+                break;
+
+            case scope.keys.LEFT:
+                scope.pan( scope.keyPanSpeed, 0 );
+                scope.update();
+                break;
+
+            case scope.keys.RIGHT:
+                scope.pan( - scope.keyPanSpeed, 0 );
+                scope.update();
+                break;
+
+        }
+
+    }
+
+    function touchstart( event ) {
+
+        if ( scope.enabled === false ) return;
+
+        switch ( event.touches.length ) {
+
+            case 1: // one-fingered touch: rotate
+
+                if ( scope.noRotate === true ) return;
+
+                state = STATE.TOUCH_ROTATE;
+
+                rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+                break;
+
+            case 2: // two-fingered touch: dolly
+
+                if ( scope.noZoom === true ) return;
+
+                state = STATE.TOUCH_DOLLY;
+
+                var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+                var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+                var distance = Math.sqrt( dx * dx + dy * dy );
+                dollyStart.set( 0, distance );
+                break;
+
+            case 3: // three-fingered touch: pan
+
+                if ( scope.noPan === true ) return;
+
+                state = STATE.TOUCH_PAN;
+
+                panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+                break;
+
+            default:
+
+                state = STATE.NONE;
+
+        }
+
+        scope.dispatchEvent( startEvent );
+
+    }
+
+    function touchmove( event ) {
+
+        if ( scope.enabled === false ) return;
+
+        event.preventDefault();
+        event.stopPropagation();
+
+        var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+
+        switch ( event.touches.length ) {
+
+            case 1: // one-fingered touch: rotate
+
+                if ( scope.noRotate === true ) return;
+                if ( state !== STATE.TOUCH_ROTATE ) return;
+
+                rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+                rotateDelta.subVectors( rotateEnd, rotateStart );
+
+                // rotating across whole screen goes 360 degrees around
+                scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
+                // rotating up and down along whole screen attempts to go 360, but limited to 180
+                scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
+
+                rotateStart.copy( rotateEnd );
+
+                scope.update();
+                break;
+
+            case 2: // two-fingered touch: dolly
+
+                if ( scope.noZoom === true ) return;
+                if ( state !== STATE.TOUCH_DOLLY ) return;
+
+                var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+                var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+                var distance = Math.sqrt( dx * dx + dy * dy );
+
+                dollyEnd.set( 0, distance );
+                dollyDelta.subVectors( dollyEnd, dollyStart );
+
+                if ( dollyDelta.y > 0 ) {
+
+                    scope.dollyOut();
+
+                } else {
+
+                    scope.dollyIn();
+
+                }
+
+                dollyStart.copy( dollyEnd );
+
+                scope.update();
+                break;
+
+            case 3: // three-fingered touch: pan
+
+                if ( scope.noPan === true ) return;
+                if ( state !== STATE.TOUCH_PAN ) return;
+
+                panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+                panDelta.subVectors( panEnd, panStart );
+
+                scope.pan( panDelta.x, panDelta.y );
+
+                panStart.copy( panEnd );
+
+                scope.update();
+                break;
+
+            default:
+
+                state = STATE.NONE;
+
+        }
+
+    }
+
+    function touchend( /* event */ ) {
+
+        if ( scope.enabled === false ) return;
+
+        scope.dispatchEvent( endEvent );
+        state = STATE.NONE;
+
+    }
+
+    this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
+    this.domElement.addEventListener( 'mousedown', onMouseDown, false );
+    this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
+    this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
+
+    this.domElement.addEventListener( 'touchstart', touchstart, false );
+    this.domElement.addEventListener( 'touchend', touchend, false );
+    this.domElement.addEventListener( 'touchmove', touchmove, false );
+
+    window.addEventListener( 'keydown', onKeyDown, false );
+
+    // force an update at start
+    this.update();
+
+};
+
+THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );

File diff suppressed because it is too large
+ 4 - 0
static/js/lib/head.core.min.js.map


File diff suppressed because it is too large
+ 1 - 0
static/js/lib/head.load.min.js


File diff suppressed because it is too large
+ 0 - 0
static/js/lib/helvetiker_regular.typeface.js


File diff suppressed because it is too large
+ 2 - 0
static/js/lib/jqplot.dragable.min.js


File diff suppressed because it is too large
+ 1 - 0
static/js/lib/jquery-2.1.1.min.js


File diff suppressed because it is too large
+ 5 - 0
static/js/lib/jquery-ui.min.js


File diff suppressed because it is too large
+ 2 - 0
static/js/lib/jquery.jqplot.min.js


+ 11 - 0
static/js/lib/jquery.ui.touch-punch.min.js

@@ -0,0 +1,11 @@
+/*!
+ * jQuery UI Touch Punch 0.2.3
+ *
+ * Copyright 2011–2014, Dave Furfero
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ * Depends:
+ *  jquery.ui.widget.js
+ *  jquery.ui.mouse.js
+ */
+!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);

File diff suppressed because it is too large
+ 1 - 0
static/js/lib/kinetic-v5.0.2.min.js


+ 6 - 0
static/js/lib/stats.min.js

@@ -0,0 +1,6 @@
+// stats.js - http://github.com/mrdoob/stats.js
+var Stats=function(){var l=Date.now(),m=l,g=0,n=Infinity,o=0,h=0,p=Infinity,q=0,r=0,s=0,f=document.createElement("div");f.id="stats";f.addEventListener("mousedown",function(b){b.preventDefault();t(++s%2)},!1);f.style.cssText="width:80px;opacity:0.9;cursor:pointer";var a=document.createElement("div");a.id="fps";a.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#002";f.appendChild(a);var i=document.createElement("div");i.id="fpsText";i.style.cssText="color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px";
+i.innerHTML="FPS";a.appendChild(i);var c=document.createElement("div");c.id="fpsGraph";c.style.cssText="position:relative;width:74px;height:30px;background-color:#0ff";for(a.appendChild(c);74>c.children.length;){var j=document.createElement("span");j.style.cssText="width:1px;height:30px;float:left;background-color:#113";c.appendChild(j)}var d=document.createElement("div");d.id="ms";d.style.cssText="padding:0 0 3px 3px;text-align:left;background-color:#020;display:none";f.appendChild(d);var k=document.createElement("div");
+k.id="msText";k.style.cssText="color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px";k.innerHTML="MS";d.appendChild(k);var e=document.createElement("div");e.id="msGraph";e.style.cssText="position:relative;width:74px;height:30px;background-color:#0f0";for(d.appendChild(e);74>e.children.length;)j=document.createElement("span"),j.style.cssText="width:1px;height:30px;float:left;background-color:#131",e.appendChild(j);var t=function(b){s=b;switch(s){case 0:a.style.display=
+"block";d.style.display="none";break;case 1:a.style.display="none",d.style.display="block"}};return{REVISION:12,domElement:f,setMode:t,begin:function(){l=Date.now()},end:function(){var b=Date.now();g=b-l;n=Math.min(n,g);o=Math.max(o,g);k.textContent=g+" MS ("+n+"-"+o+")";var a=Math.min(30,30-30*(g/200));e.appendChild(e.firstChild).style.height=a+"px";r++;b>m+1E3&&(h=Math.round(1E3*r/(b-m)),p=Math.min(p,h),q=Math.max(q,h),i.textContent=h+" FPS ("+p+"-"+q+")",a=Math.min(30,30-30*(h/100)),c.appendChild(c.firstChild).style.height=
+a+"px",m=b,r=0);return b},update:function(){l=this.end()}}};"object"===typeof module&&(module.exports=Stats);

File diff suppressed because it is too large
+ 15957 - 0
static/js/lib/three.js


File diff suppressed because it is too large
+ 372 - 0
static/js/lib/three.min.js


+ 2398 - 0
static/js/threeJsHelper/dist/threeJsHelper.js

@@ -0,0 +1,2398 @@
+var IPE = {
+    app : {},
+    helper : {},
+    interceptors : {}
+}
+
+String.prototype.endsWith = function(suffix) {
+    return this.indexOf(suffix, this.length - suffix.length) !== -1;
+};
+
+IPE.app = {
+    init : function(config) {
+        $.each(IPE.interceptors, function(index, interceptor) {
+            interceptor.init();
+        });
+
+        Globals.init();
+
+        IPE.app.initializeHelper();
+        IPE.app.bindEvents();
+        IPE.app.initData();
+
+        $resSpan.text(config.defaultSize);
+        textureSizes = config.textureSizes;
+        for (key in textureSizes) {
+            size = textureSizes[key];
+            href = size == config.defaultSize ? '' : 'href="#"';
+
+            $resLinkHolder.append('<a '+href+' class="res-link" data="'+size+'">'+size+'</a>  ');
+        }
+
+        // Getting info file
+        $.ajax({
+            url: infoUrl + config.defaultSize,
+            success: function (data) {
+                textureInfo = data;
+
+                originalSizeArray[0] = textureInfo.originalSize.sizex;
+                originalSizeArray[1] = textureInfo.originalSize.sizey;
+                originalSizeArray[2] = textureInfo.originalSize.sizez;
+
+                imgInfo = data.info;
+
+                currentVolumeDimension.xmin = 0;
+                currentVolumeDimension.xmax = textureInfo.originalSize.sizex;
+                currentVolumeDimension.ymin = 0;
+                currentVolumeDimension.ymax = textureInfo.originalSize.sizey;
+                currentVolumeDimension.zmin = imgInfo.imgMin;
+                currentVolumeDimension.zmax = imgInfo.imgMax;
+
+                // downloading first image and starting
+                helper.downloadImage(spriteUrl + textureInfo.sprites[0][0].$oid, 0, 0, true);
+
+                $(document).trigger('basicsReady');
+            },
+            dataType: 'json'
+        });
+
+
+        container = document.getElementById( 'container' );
+        $container = $(container);
+        containerHeader = document.getElementById( 'container-header' );
+        $containerHeader = $(containerHeader);
+
+        containerOverview = document.getElementById('container-overview');
+        $containerOverview = $(containerOverview);
+
+        stats = new Stats();
+        $containerHeader.children('#container-stats').append( stats.domElement );
+
+        // until now, it has to be initialized here, needs a new internal structure
+        zoomHelper = new ZoomHelper();
+    },
+    initializeHelper: function() {
+        helper = new Helper();
+        geometryHelper = new GeometryHelper();
+        stepHelper = new StepHelper();
+        overviewHelper = new OverviewHelper();
+        transferHelper = new TransferHelper();
+        opacityPlotter = new OpacityPlotter();
+    },
+
+    initData: function() {
+        volumeId = $('#volumeId').val();
+
+        $resSpan = $('span#currentRes');
+        $resLinkHolder = $('#resolution-link-holder');
+
+        volumeUrl = homeUrl + 'volumes/' + volumeId + '/';
+        infoUrl = volumeUrl + 'texture-info/';
+        spriteUrl = volumeUrl + 'sprite/';
+
+        waitDiv = $('div#wait');
+
+        helper.initializeShaders(homeUrl + 'static/shaders/three-shader.vert', function(script) {
+            vertexShader = script
+        });
+        helper.initializeShaders(homeUrl + 'static/shaders/three-shader-simple.frag', function(script) {
+            fragmentSimleShader = script
+        });
+        helper.initializeShaders(homeUrl + 'static/shaders/three-shader.frag', function(script) {
+            fragmentShader = script
+        });
+    },
+
+    bindEvents : function() {
+        $(document).on('firstImageOnLoad',function (e, firstImageParams){
+            initTextures(imgInfo, firstImageParams, true);
+
+            initFrameControls();
+
+            stepHelper.initStepControls();
+
+            initSliders();
+        });
+
+        $(document).on('imageOnLoad', function(e, imageParams) {
+            initTextures(imgInfo, imageParams, false);
+
+            if(useDownloadedTextureImmediately) {
+                updateTexture();
+                useDownloadedTextureImmediately = false;
+                updateFrameControls();
+            }
+        });
+
+        $(document).on('firstFrameSpritesCompleted', function() {
+            init();
+
+            overviewHelper.initOverview(containerOverview);
+
+            animate();
+        });
+
+        showPopup = false;
+        $('#save-canvas').click(function(e, params) {
+            if(params != undefined && params.source != undefined && params.source == 'animate-function') {
+                window.open(params.imageUrl);
+                return false;
+            } else {
+                saveImage = true;
+                return false;
+            }
+        });
+
+        $(window).on('resize', function() {
+            var rendererSizeHolder = calculateWidthHeight();
+            width = rendererSizeHolder.width.px;
+            height = rendererSizeHolder.height.px;
+
+            cameraRTT.aspect = width / height;
+            cameraRTT.updateProjectionMatrix();
+
+            camera.aspect = width / height;
+            camera.updateProjectionMatrix();
+
+            renderer.setSize( width, height );
+            renderer.domElement.style.width = rendererSizeHolder.width.percent + '%';
+            renderer.domElement.style.height = rendererSizeHolder.height.percent + '%';
+        });
+
+
+        $('#resolution-link-holder').on('click', 'a', function(e) {
+            e.preventDefault();
+            e.stopPropagation();
+
+            if($(this).attr('href') == undefined) {
+                return false;
+            }
+            requestedSize = $(this).attr('data');
+
+            $('.res-link').each(function(index, value) {
+                $(value).attr('href', '#');
+            });
+            $(this).removeAttr('href');
+
+            $.ajax({
+                // todo test after remove of sync flag
+                url: infoUrl + requestedSize,
+                success: function (data) {
+                    framesDownloaded = 0;
+                    textures = {};
+                    currentTexture = 0;
+
+                    textureInfo = data;
+                    imgInfo = data.info;
+                    imgMin = imgInfo.imgMin;
+                    imgMax = imgInfo.imgMax;
+                    useDownloadedTextureImmediately = true;
+                    helper.downloadImage(spriteUrl + textureInfo.sprites[0][0].$oid, 0, 0, false);
+                    $resSpan.text(requestedSize);
+                },
+                dataType: 'json'
+            });
+
+            return false;
+        });
+
+        $('div.controls').on('click', function() {
+            var $this = $(this),
+                controlFillerContainer = $('div#control-filler-container'),
+                controlFiller = $('div#control-filler'),
+                filledById = '',
+                thisControlHolder = null;
+
+            filledById = hideControlFillerContainer();
+            if(filledById === $this.attr('id')) {
+                return;
+            }
+
+            thisControlHolder = $this.children('.control-holder')[0];
+            thisControlHolder = $(thisControlHolder);
+
+            controlFiller.append(thisControlHolder.children());
+            controlFiller.attr('filledBy', $this.attr('id'));
+            controlFillerContainer.removeClass('hidden');
+        });
+
+        $('input#hide-control-filler-container').on('click', function() {
+            hideControlFillerContainer();
+        });
+
+
+
+        $('div#menu-buttons-small-devices input').on('click', function() {
+            var $this = $(this),
+                target = $this.attr('data'),
+                $target = $('#' + target),
+                $overlay = $('div#overlay-small-devices'),
+                $content = $('div#content-small-devices');
+
+            $overlay.attr('source', target);
+            $content.append($target.children());
+            $overlay.show();
+        });
+
+
+        $('input#hide-content-small-devices').on('click', function() {
+            var $this = $(this)
+            $overlay = $('div#overlay-small-devices'),
+                $content = $('div#content-small-devices'),
+                source = $overlay.attr('source'),
+                $source = $('#' + source);
+
+            $overlay.hide();
+            $overlay.attr('source', '');
+            $source.append($content.children());
+        });
+
+        var buttonAdvCons = $('input#show-adv-con');
+        buttonAdvCons.on('click', function() {
+            var advCons = $('div#advanced-controls');
+
+            if(advCons.hasClass('hidden')) {
+                advCons.removeClass('hidden');
+                buttonAdvCons.val('hide adv cons');
+
+            } else {
+                advCons.addClass('hidden');
+                buttonAdvCons.val('show adv cons');
+            }
+        });
+    }
+}
+
+function initTextures(imgInfo, imageParams, whileInit) {
+    // set initial array to index
+    if(textures[imageParams.textureIndex] == undefined
+       || textures[imageParams.textureIndex] == null) {
+        textures[imageParams.textureIndex] = [];
+    }
+
+    // using texture
+    texture = initTexture(imageParams.texture);
+    textures[imageParams.textureIndex].push(texture);
+
+    // fetch new sprites of same time frame
+    if(imageParams.spriteIndex < imgInfo.numberOfSprites - 1) {
+        nextSpriteIndex = imageParams.spriteIndex + 1;
+        nextSpriteId = textureInfo.sprites[imageParams.textureIndex][nextSpriteIndex].$oid
+        helper.downloadImage(spriteUrl + nextSpriteId, imageParams.textureIndex, nextSpriteIndex, false);
+        return;
+    }
+
+    // inform the rest, that the first frame is loaded completely
+    if(whileInit && imageParams.textureIndex == 0) {
+        $(document).trigger('firstFrameSpritesCompleted');
+    }
+
+    // todo some logic
+    if(!imgInfo.multipleFrames) {
+        currentTexture = 0;
+        return;
+    } else {
+        var numberOfFrames = Object.keys(textureInfo.sprites).length,
+            nextIndex = null,
+            nextFrameName = null,
+            nextFramePath = null;
+
+        framesDownloaded++;
+
+        if(framesDownloaded == 1) {
+            currentTexture = 0;
+        }
+
+        currentMaxFrame = imgInfo.frameFrom + framesDownloaded - 1;
+
+        if(framesDownloaded > 1) {
+            // updating frame control maximums
+            updateFrameControlsMaxFrame();
+        }
+
+        if(numberOfFrames == framesDownloaded) {
+            return;
+        } else {
+            nextIndex = framesDownloaded;
+            nextFrameName = textureInfo.sprites[nextIndex].$oid;
+            var framePath = spriteUrl + nextFrameName;
+            helper.downloadImage(framePath, nextIndex, false);
+        }
+    }
+}
+
+function initTexture(texture) {
+    texture.magFilter = THREE.LinearFilter;
+    texture.minFilter = THREE.LinearFilter;
+    texture.needsUpdate = true;
+
+    return texture;
+}
+
+function getCurrentTexture() {
+    return textures[currentTexture];
+}
+
+function initFrameControls() {
+    if(!imgInfo.multipleFrames && (imgInfo.frameTo - imgInfo.frameFrom) > 0) {
+        return;
+    }
+
+    $('#frame-controls').removeClass('hidden');
+
+    var $frameSlider = $('#frame-slider'),
+        $playButton = $('#frame-play'),
+        $pauseButton = $('#frame-pause'),
+        $currentFrameInput = $('#currentFrame'),
+        playId = $playButton.attr('id'),
+        pauseId = $pauseButton.attr('id'),
+        minFrame = imgInfo.frameFrom;
+
+    $currentFrameInput.val(minFrame);
+    var play = function() {
+        if(Object.keys(textures).length == 1) {
+            console.warn('only one texture loaded, can not play yet');
+            return;
+        }
+        $playButton.addClass('hidden');
+        $pauseButton.removeClass('hidden');
+        playFrames = true;
+        $frameSlider.slider({disabled: true});
+        $currentFrameInput.prop('disabled', true);
+    }
+    var pause = function() {
+        $playButton.removeClass('hidden');
+        $pauseButton.addClass('hidden');
+        playFrames = false;
+        $frameSlider.slider({disabled: false});
+        $currentFrameInput.prop('disabled', false);
+    }
+
+    $('.frame-button').click(function() {
+        var $this = $(this),
+            thisId = $this.attr('id');
+        if(thisId == playId) {
+            play();
+        } else if(thisId == pauseId) {
+            pause();
+        }
+
+    });
+
+    $(document).on('zoomActionFinished', function(e, params) {
+        zoomedIn = params.zoomAction == 'zoomIn';
+        if(zoomedIn) {
+            pause();
+            currentTexture = minFrame + params.textureNumber;
+            updateFrameControls();
+            $frameSlider.slider({disabled: true});
+            $currentFrameInput.prop('disabled', true);
+            $playButton.prop('disabled', true);
+            $pauseButton.prop('disabled', true);
+        } else {
+            $frameSlider.slider({disabled: false});
+            $currentFrameInput.prop('disabled', false);
+            $playButton.prop('disabled', false);
+            $pauseButton.prop('disabled', false);
+        }
+    });
+
+    $frameSlider.slider(
+        {
+            min: minFrame,
+            max: currentMaxFrame,
+            slide: function( event, ui ) {
+                currentTexture = ui.value - minFrame;
+                updateTexture();
+                $currentFrameInput.val(ui.value);
+            }
+        }
+    );
+
+    $currentFrameInput.change(function() {
+        var value = parseInt($(this).val());
+        if(value  >= imgInfo.frameFrom && currentMaxFrame >= value) {
+            currentTexture = value - minFrame;
+            updateTexture();
+            $frameSlider.slider('value', value);
+        } else {
+            $(this).val($frameSlider.slider('value'));
+        }
+
+    });
+}
+
+function updateFrameControlsMaxFrame() {
+    if(!imgInfo.multipleFrames) {
+        return;
+    }
+
+    var $frameSlider = $('#frame-slider');
+
+    $frameSlider.slider('option', 'max', currentMaxFrame);
+}
+
+function updateFrameControls() {
+    if(!imgInfo.multipleFrames) {
+        return;
+    }
+
+    var $frameSlider = $('#frame-slider'),
+        $currentFrameInput = $('#currentFrame'),
+        minFrame = imgInfo.frameFrom,
+        value = currentTexture + minFrame;
+
+
+    $frameSlider.slider('value', value);
+    $currentFrameInput.val(value);
+}
+
+
+function init() {
+    $statsDom = $(stats.domElement);
+
+    rendererSizeHolder = calculateWidthHeight();
+
+    width = rendererSizeHolder.width.px;
+    height = rendererSizeHolder.height.px;
+
+    //width = window.innerWidth;
+    //height = window.innerHeight;
+
+    camera = new THREE.PerspectiveCamera( 45, width / height, .1, 1000 );
+    camera.position.z = 2;
+
+    cameraRTT = new THREE.PerspectiveCamera( 45, width / height, .1, 1000 );
+    cameraRTT.position.z = 2;
+
+    scene = new THREE.Scene();
+    sceneRTT = new THREE.Scene();
+
+    rtTexture = new THREE.WebGLRenderTarget( width, height, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat } );
+
+    var geometry = geometryHelper.createBoxGeometry(originalDimension);
+
+    var attributes = {
+        frontColor: {type: 'c', value: [] }
+    }
+
+    material = new THREE.ShaderMaterial({
+        attributes: attributes,
+        vertexShader: vertexShader,
+        fragmentShader: fragmentSimleShader,
+        side: THREE.FrontSide
+    });
+
+    var spriteMaps = getCurrentTexture();
+
+    var transferImageData = transferHelper.getCurrentTransferFunction();
+    var transferTexture = new THREE.Texture(transferImageData);
+    transferTexture.needsUpdate = true;
+
+    var uniforms = {
+        tBackground: {type: 't', value: rtTexture},
+        tvSlices: {type: 'tv', value: spriteMaps},
+        tTransfer: { type: 't', value: transferTexture},
+        minGray: {type: 'f', value: minGray },
+        maxGray: {type: 'f', value: maxGray },
+        steps: {type: 'f', value: 100},
+        numberOfSlices: {type: 'f', value: imgInfo.numberOfSlices },
+        numberOfSprites: {type: 'f', value: imgInfo.numberOfSprites },
+        slicesPerSprite: {type: 'f', value: imgInfo.slicesPerSprite },
+        slicesOverX: {type: 'f', value: imgInfo.slicesOverX },
+        slicesOverY: {type: 'f', value: imgInfo.slicesOverY },
+    };
+
+    materialScreen = new THREE.ShaderMaterial({
+        attributes: attributes,
+        uniforms: uniforms,
+        vertexShader: vertexShader,
+        fragmentShader: fragmentShader,
+        side: THREE.BackSide,
+        transparent: true
+    });
+
+
+    backgroundBox = new THREE.Mesh(geometry, material);
+    sceneRTT.add(backgroundBox);
+
+    frontBox = new THREE.Mesh(geometry, materialScreen);//
+    scene.add(frontBox);
+    objectsToIntersect.push(frontBox);
+
+    translateBoxes(-0.5, -0.5, -0.5);
+    rotateBoxesY(Math.PI);
+    rotateBoxesZ(Math.PI);
+
+    //renderer = new THREE.WebGLRenderer( {  antialias: false, alpha: true });
+    renderer = new THREE.WebGLRenderer();
+    renderer.setSize(width, height);
+    renderer.domElement.style.width = rendererSizeHolder.width.percent + '%';
+    renderer.domElement.style.height = rendererSizeHolder.height.percent + '%';
+    renderer.setClearColor(0xffffff, 1);
+    container.appendChild(renderer.domElement);
+
+    $canvas = $('canvas', $container);
+
+    controls1 = new THREE.OrbitControls( camera, renderer.domElement );
+    controls1.damping = 0.2;
+
+    controls2 = new THREE.OrbitControls( cameraRTT, renderer.domElement );
+    controls2.damping = 0.2;
+
+    rendererContext = renderer.context;
+
+    raycaster = new THREE.Raycaster();
+}
+
+function rotateBoxesY(radian) {
+    rotationMatrix = new THREE.Matrix4().makeRotationY(radian);
+    rotateBoxes(rotationMatrix);
+}
+
+function rotateBoxesZ(radian) {
+    rotationMatrix = new THREE.Matrix4().makeRotationZ(radian);
+    rotateBoxes(rotationMatrix);
+}
+
+function rotateBoxes(matrix) {
+    backgroundBox.applyMatrix(rotationMatrix);
+    frontBox.applyMatrix(rotationMatrix);
+}
+
+function translateBoxes(x, y, z) {
+    translationMatrix = new THREE.Matrix4().makeTranslation(x, y, z);
+    backgroundBox.applyMatrix(translationMatrix);
+    frontBox.applyMatrix(translationMatrix);
+}
+
+function initSliders() {
+    initLayerSliders();
+
+    // init gray value slider
+    GenericSlider.initSlider(
+        slider = $( "#gray-slider" ),
+        sliderInputs = $('input.gray'),
+        minGray,
+        maxGray,
+        function(values) {
+            var minGray = calculateGrayFloat(values[0]),
+                maxGray = calculateGrayFloat(values[1]);
+            updateGrayBorders(minGray, maxGray);
+        }
+    );
+}
+
+function initLayerSliders() {
+    // init xlayer slider
+    GenericSlider.initSlider(
+        $( "#xlayer-slider" ),
+        sliderInputs = $('input.xlayer'),
+        currentVolumeDimension.xmin,
+        currentVolumeDimension.xmax,
+        function(values) {
+            dimMin = currentVolumeDimension.xmin;
+            dimMax = currentVolumeDimension.xmax;
+            currentDimension.xmin = calculateLayerFloat(values[0], dimMin, dimMax);
+            currentDimension.xmax = calculateLayerFloat(values[1], dimMin, dimMax);
+            updateCubeLayers(currentDimension);
+        },
+        function() {
+            values = Array(2);
+            values[0] = calculateLayerInt(currentDimension.xmin, currentVolumeDimension.xmin, currentVolumeDimension.xmax );
+            values[1] = calculateLayerInt(currentDimension.xmax, currentVolumeDimension.xmin, currentVolumeDimension.xmax );
+
+            return values;
+        }
+    );
+    // init ylayer slider
+    GenericSlider.initSlider(
+        $( "#ylayer-slider" ),
+        sliderInputs = $('input.ylayer'),
+        currentVolumeDimension.ymin,
+        currentVolumeDimension.ymax,
+        function(values) {
+            dimMin = currentVolumeDimension.ymin;
+            dimMax = currentVolumeDimension.ymax;
+            currentDimension.ymin = calculateLayerFloat(values[0], dimMin, dimMax);
+            currentDimension.ymax = calculateLayerFloat(values[1], dimMin, dimMax);
+            updateCubeLayers(currentDimension);
+        },
+        function() {
+            values = Array(2);
+            values[0] = calculateLayerInt(currentDimension.ymin, currentVolumeDimension.ymin, currentVolumeDimension.ymax );
+            values[1] = calculateLayerInt(currentDimension.ymax, currentVolumeDimension.ymin, currentVolumeDimension.ymax );
+
+            return values;
+        }
+    );
+    // init zlayer slider
+    GenericSlider.initSlider(
+        $( "#zlayer-slider" ),
+        sliderInputs = $('input.zlayer'),
+        currentVolumeDimension.zmin,
+        currentVolumeDimension.zmax,
+        function(values) {
+            dimMin = currentVolumeDimension.zmin;
+            dimMax = currentVolumeDimension.zmax;
+            currentDimension.zmin = calculateLayerFloat(values[0], dimMin, dimMax),
+                currentDimension.zmax = calculateLayerFloat(values[1], dimMin, dimMax);
+            updateCubeLayers(currentDimension);
+        },
+        function() {
+            values = Array(2);
+            values[0] = calculateLayerInt(currentDimension.zmin, currentVolumeDimension.zmin, currentVolumeDimension.zmax );
+            values[1] = calculateLayerInt(currentDimension.zmax, currentVolumeDimension.zmin, currentVolumeDimension.zmax );
+
+            return values;
+        }
+    );
+}
+
+function repositionLayerSliders() {
+    initLayerSliders();
+
+    $.each($('.slider.layer'), function(index, value) {
+        $(value).trigger('reposition');
+    });
+    updateCubeLayers(currentDimension);
+}
+
+var prevTime = Date.now();
+var fps = 0;
+var frames = 0;
+
+
+function animate() {
+    requestAnimationFrame( animate );
+
+
+    $container.trigger('animation');
+
+    var numberOfTextures = Object.keys(textures).length;
+    var now = Date.now();
+    frames++;
+
+    if(now > prevTime + 1000) {
+        fps = (frames * 1000) / (now - prevTime);
+        if(adjustSteps) {
+            if(fps < 10) {
+                stepHelper.decreaseSteps();
+            } else if(fps > 15) {
+                stepHelper.increaseSteps();
+            }
+        }
+
+        prevTime = now;
+        frames = 0;
+    }
+
+    if(playFrames && numberOfTextures > 1) {
+
+        var timeStamp = (new Date()).getTime();
+        if(timeStamp - textureTimestamp > 400) {
+            currentTexture++;
+            if(currentTexture >= numberOfTextures) {
+                currentTexture = 0;
+            }
+
+            updateTexture();
+            textureTimestamp = timeStamp;
+            updateFrameControls();
+        }
+    }
+
+    if(nextCubeDeletionTimeStamp == null && intersectCubesTimeStamps.length != 0) {
+        nextCubeDeletionTimeStamp = intersectCubesTimeStamps.shift();
+    }
+
+    if((Date.now() - nextCubeDeletionTimeStamp) > 1500) {
+        cubeToDelete = intersectCubes.shift();
+        scene.remove(cubeToDelete);
+
+        nextCubeDeletionTimeStamp = null;
+    }
+
+    if(transferHelper.transferFunctionChanged()) {
+        var transfer = new THREE.Texture(transferHelper.getCurrentTransferFunction());
+        transfer.needsUpdate = true;
+        materialScreen.uniforms.tTransfer.value = transfer;
+    }
+
+    cameraPoint = camera.position.clone();
+    overviewHelper.updateCameraPosition(cameraPoint);
+
+    stats.update();
+    controls1.update();
+    controls2.update();
+
+    render();
+    if(saveImage) {
+        $('#save-canvas').trigger('click', { source: 'animate-function', imageUrl: renderer.domElement.toDataURL() });
+        saveImage = false;
+    }
+
+
+}
+
+function updateTexture(textures) {
+    if(textures == undefined || textures == null) {
+        textures = getCurrentTexture();
+    }
+    $.each(textures, function(index, texture) {
+        value.needsUpdate = true;
+    });
+
+    materialScreen.uniforms.tvSlices.value = textures;
+}
+
+function render() {
+    renderer.clear();
+
+    renderer.context.clearDepth(-50.0);
+    renderer.context.depthFunc(renderer.context.GEQUAL);
+    renderer.render(sceneRTT, cameraRTT, rtTexture, true);
+
+    renderer.context.clearDepth(50.0);
+    renderer.context.depthFunc(renderer.context.LEQUAL);
+    renderer.render(scene, camera);
+
+    overviewHelper.render();
+}
+
+
+function updateCubeLayers(geometryDimension) {
+    var geometry = geometryHelper.createBoxGeometry(geometryDimension);
+    var colorArray = geometry.attributes.frontColor.array,
+        positionArray = geometry.attributes.position.array;
+
+    frontBox.geometry.attributes.frontColor.array = colorArray;
+    frontBox.geometry.attributes.frontColor.needsUpdate = true;
+    frontBox.geometry.attributes.position.array = positionArray;
+    frontBox.geometry.attributes.position.needsUpdate = true;
+}
+
+function updateGrayBorders(minGray, maxGray) {
+    materialScreen.uniforms.minGray.value = minGray;
+    materialScreen.uniforms.maxGray.value = maxGray;
+}
+
+// invert function of calculateLayerFloat
+function calculateLayerInt(position, dimMin, dimMax) {
+    if(position <= 0.005) {
+        return dimMin;
+    }
+    if(position >= 0.995) {
+        return dimMax;
+    }
+
+    return Math.round(position * (dimMax - dimMin) + dimMin);
+}
+
+// calculate the float value for a layer input integer
+// 150 of [0, 299] will be 0.5
+function calculateLayerFloat(value, dimMin, dimMax) {
+    var floatVal = (value - dimMin) / (dimMax - dimMin);
+
+    if (floatVal == 0) {
+        return 0.005;
+    }
+    if (floatVal == 255) {
+        return 0.995;
+    }
+
+    return floatVal;
+}
+
+function calculateGrayFloat(value) {
+    return value / 255.0;
+}
+
+function distance (v1, v2) {
+    dx = v1.x - v2.x;
+    dy = v1.y - v2.y;
+    dz = v1.z - v2.z;
+
+    return Math.sqrt(dx*dx+dy*dy+dz*dz);
+}
+
+function calculateWidthHeight() {
+    downScaleFactor = 0.66;
+    valueholder = {
+        height: {},
+        width: {}
+    }
+    containerHeight = $container.height();
+    volumeInfoHeight = $('#volume-information').height();
+    valueholder.height.px = (containerHeight - volumeInfoHeight) * downScaleFactor;
+    volumeInfoHeightPercent = Math.floor(volumeInfoHeight / containerHeight * 100);
+    valueholder.height.percent = 100 - volumeInfoHeightPercent;
+
+    valueholder.width.px = $container.width() * downScaleFactor;
+    valueholder.width.percent = 100;
+
+    return valueholder;
+}
+
+function hideControlFillerContainer() {
+    var controlFillerContainer = $('div#control-filler-container'),
+        controlFiller = $('div#control-filler'),
+        filledById = controlFiller.attr('filledBy'),
+        filledBy = $('#' + filledById);
+
+    // writing data back to original, because append MOVES the children
+    if(filledBy.length == 1) {
+        filledBy = $(filledBy[0]);
+        filledByControlHolder = filledBy.children('.control-holder')[0];
+        $(filledByControlHolder).append(controlFiller.children());
+    }
+
+    controlFiller.attr('filledBy', '');
+    controlFillerContainer.addClass('hidden');
+
+    return filledById;
+}
+;var volumeId;
+var stats, container, $container, containerHeader, $containerHeader, $canvas, cameraRTT, camera, sceneRTT, scene, renderer, controls, controls2;
+var containerOverview, $containerOverview;
+var $resSpan;
+var $resLinkHolder;
+var raycaster;
+var width, height;
+var steps, adjustSteps;
+var rtTexture, material;
+
+var backgroundBox, frontBox;
+var objectsToIntersect = [];
+var minGray = 0, maxGray = 255;
+var originalDimension,
+    zoomedDimension,
+    currentDimension,
+    originalVolumeDimension,
+    zoomedVolumeDimension,
+    currentVolumeDimension,
+    volumeUrl,
+    infoUrl,
+    spriteUrl,
+    imgInfo = null,
+    textureInfo = null,
+    originalSizeArray = Array(3),
+    zoomedInfo;
+
+var textures = {},
+    currentTexture = 0,
+    useDownloadedTextureImmediately = false,
+    textureTimestamp = (new Date()).getTime(),
+    playFrames = false,
+    currentMaxFrame = 0;
+
+var framesDownloaded = 0,
+    cachedImages = {};
+
+var vertexShader = null,
+    fragmentSimleShader = null,
+    fragmentShader = null;
+
+var intersectCubes = [],
+    intersectCubesTimeStamps = []
+    nextCubeDeletionTimeStamp = null,
+    zoomedIn = false;
+
+var helper,
+    geometryHelper,
+    stepHelper,
+    overviewHelper,
+    transferHelper,
+    zoomHelper,
+    opacityPlotter;
+
+var waitDiv;
+var saveImage = false;
+
+// prefetch first image to cache it
+var progressContainer,
+    imageProgress,
+    progressSpan;
+
+var Globals = (function() {
+    return {
+        init: function() {
+            originalDimension = new GeometryDimension();
+            zoomedDimension = new GeometryDimension();
+            currentDimension = originalDimension;
+            originalVolumeDimension = new VolumeDimension();
+            zoomedVolumeDimension = new VolumeDimension();
+            currentVolumeDimension = originalVolumeDimension;
+        }
+    }
+}());
+;var GeometryHelper = function() {
+    return {
+        createBoxGeometry: function(dimension) {
+            var vertexPos = [
+                //front face first
+                [dimension.xmin, dimension.ymin, dimension.zmax],
+                [dimension.xmax, dimension.ymin, dimension.zmax],
+                [dimension.xmax, dimension.ymax, dimension.zmax],
+                //front face second
+                [dimension.xmin, dimension.ymin, dimension.zmax],
+                [dimension.xmax, dimension.ymax, dimension.zmax],
+                [dimension.xmin, dimension.ymax, dimension.zmax],
+
+                // back face first
+                [dimension.xmin, dimension.ymin, dimension.zmin],
+                [dimension.xmin, dimension.ymax, dimension.zmin],
+                [dimension.xmax, dimension.ymax, dimension.zmin],
+                // back face second
+                [dimension.xmin, dimension.ymin, dimension.zmin],
+                [dimension.xmax, dimension.ymax, dimension.zmin],
+                [dimension.xmax, dimension.ymin, dimension.zmin],
+
+                // top face first
+                [dimension.xmin, dimension.ymax, dimension.zmin],
+                [dimension.xmin, dimension.ymax, dimension.zmax],
+                [dimension.xmax, dimension.ymax, dimension.zmax],
+                // top face second
+                [dimension.xmin, dimension.ymax, dimension.zmin],
+                [dimension.xmax, dimension.ymax, dimension.zmax],
+                [dimension.xmax, dimension.ymax, dimension.zmin],
+
+                // bottom face first
+                [dimension.xmin, dimension.ymin, dimension.zmin],
+                [dimension.xmax, dimension.ymin, dimension.zmin],
+                [dimension.xmax, dimension.ymin, dimension.zmax],
+                // bottom face second
+                [dimension.xmin, dimension.ymin, dimension.zmin],
+                [dimension.xmax, dimension.ymin, dimension.zmax],
+                [dimension.xmin, dimension.ymin, dimension.zmax],
+
+                // right face first
+                [dimension.xmax, dimension.ymin, dimension.zmin],
+                [dimension.xmax, dimension.ymax, dimension.zmin],
+                [dimension.xmax, dimension.ymax, dimension.zmax],
+                // right face second
+                [dimension.xmax, dimension.ymin, dimension.zmin],
+                [dimension.xmax, dimension.ymax, dimension.zmax],
+                [dimension.xmax, dimension.ymin, dimension.zmax],
+
+                // left face first
+                [dimension.xmin, dimension.ymin, dimension.zmin],
+                [dimension.xmin, dimension.ymin, dimension.zmax],
+                [dimension.xmin, dimension.ymax, dimension.zmax],
+                // left face second
+                [dimension.xmin, dimension.ymin, dimension.zmin],
+                [dimension.xmin, dimension.ymax, dimension.zmax],
+                [dimension.xmin, dimension.ymax, dimension.zmin]
+            ];
+
+            var positions = [];
+            var colors = [];
+
+            for(var i = 0; i < vertexPos.length; i++) {
+                var backCounter = vertexPos.length - 1 - i,
+                    x = vertexPos[backCounter][0],
+                    y = vertexPos[backCounter][1],
+                    z = vertexPos[backCounter][2];
+
+                positions.push(x);
+                positions.push(y);
+                positions.push(z);
+
+                colors.push(x);
+                colors.push(y);
+                colors.push(z);
+                colors.push(1.0);
+            }
+
+            var geometry = new THREE.BufferGeometry();
+            var bufferPositions = new Float32Array(positions);
+            geometry.addAttribute( 'position', new THREE.BufferAttribute( bufferPositions, 3 ) );
+            geometry.addAttribute( 'frontColor', new THREE.BufferAttribute(new Float32Array(colors), 4));
+            geometry.computeBoundingSphere();
+
+            return geometry;
+        }
+    }
+}
+
+var GeometryDimension = function() {
+    this.xmin = 0.005;
+    this.xmax = 0.995;
+    this.ymin = 0.005;
+    this.ymax = 0.995;
+    this.zmin = 0.005;
+    this.zmax = 0.995;
+}
+
+var VolumeDimension = function() {
+    this.xmin;
+    this.xmax;
+    this.ymin;
+    this.ymax;
+    this.zmin;
+    this.zmax;
+}
+;var Helper = function() {
+    var messagePopup = $('#popup'),
+        popupVisible = messagePopup.hasClass('hidden'),
+        progressContainer = $('#progress-container'),
+        imageProgress = $('#image-progress'),
+        progressSpan = $('#texturePath');
+
+    return {
+        initializeShaders: function(url, callback) {
+            $.ajax({
+                url: url,
+                error: function() {
+                    console.error('failed to load shader file from: ' + url);
+                },
+                success: callback
+            });
+        },
+
+        downloadImage: function (texturePath, textureIndex, spriteIndex, whileInit) {
+            progressContainer.removeClass('hidden');
+            progressSpan.text(texturePath);
+
+            if(!texturePath.endsWith('/')) {
+                texturePath += '/';
+            }
+
+            var xmlHttp = new XMLHttpRequest();
+            xmlHttp.open('GET', texturePath, true);
+            xmlHttp.onprogress = function(e) {
+                if (e.lengthComputable) {
+                    value = Math.floor(e.loaded / e.total * 100);
+                    imageProgress.val(value);
+                }
+            };
+            xmlHttp.onload = function(e) {
+                var blob = new Blob([xmlHttp.response], {
+                    type: this.getResponseHeader('content-type')
+                });
+
+                var blobSrc = window.URL.createObjectURL(blob);
+
+                var image = new Image();
+                var texture = new THREE.Texture(image);
+
+                image.onload = function() {
+                    imageProgress.val(0);
+                    progressSpan.text('');
+                    progressContainer.addClass('hidden');
+
+                    texture.needsUpdate = true;
+                    var params = {
+                        textureIndex: textureIndex,
+                        spriteIndex: spriteIndex,
+                        texture: texture
+                    };
+
+                    if(textureIndex == 0 && whileInit) {
+                        $(document).trigger('firstImageOnLoad', params);
+                    } else {
+                        $(document).trigger('imageOnLoad', params);
+                    }
+                }
+
+                image.src = blobSrc;
+            };
+
+            xmlHttp.responseType = 'blob';
+            xmlHttp.send();
+        },
+
+        displayMessage: function(message, fadeOutAutomatically, callback, timeout) {
+            var me = this;
+            console.log('display messge');
+            messagePopup.html(message);
+            messagePopup.show();
+
+            if(fadeOutAutomatically) {
+                this.fadeoutMessage(callback, timeout);
+            }
+        },
+
+        fadeoutMessage: function(callback, timeout) {
+            if(timeout == undefined) {
+                timeout = 0;
+            }
+
+            setTimeout(function() {
+                messagePopup.fadeOut(400, function() {
+                    $(this).html('');
+                    if(callback) {
+                        callback();
+                    }
+                });
+            }, timeout);
+
+        }
+
+
+    };
+}
+;var OpacityPlotter = function() {
+
+    var opacities = Array(255);
+    var height = 40;
+    for(counter = 0; counter < 255; counter++) {
+        opacities[counter] = 1;
+    }
+
+    var stage = new Kinetic.Stage({
+        container : 'opacity-plot',
+        width : 255,
+        height: height
+    });
+
+    var layer = new Kinetic.Layer();
+    var rect = new Kinetic.Rect({
+        x: 0,
+        y: 0,
+        width: stage.getWidth(),
+        height: stage.getHeight(),
+        fill: '#cccccc'
+    });
+    layer.add(rect);
+
+    var spline = new Kinetic.Line({
+        points: [0, 0, 255, 0],
+        stroke: 'red',
+        strokeWidth: 3,
+        lineCap: 'round'
+    });
+    layer.add(spline);
+
+    stage.add(layer);
+
+    var calculateOpacities = function(points) {
+        var opacityCounter = 0;
+        for(counter = 2; counter < points.length; counter += 2) {
+            var x1 = points[counter - 2],
+                y1 = points[counter - 1],
+                x2 = points[counter],
+                y2 = points[counter + 1],
+                y1Height = (height - y1) / height,
+                y2Height = (height - y2) / height,
+                dy = (y2Height - y1Height) / (x2 - x1),
+                currentHeight = y1Height;
+
+            opacities[x1] = y1Height;
+
+            for(opacityCounter = (x1 + 1); opacityCounter <= x2; opacityCounter++) {
+                currentHeight += dy;
+                if(currentHeight < 0.0) {
+                    currentHeight = 0.0;
+                } else if(currentHeight > 1.0) {
+                    currentHeight = 1.0;
+                }
+                opacities[opacityCounter] = currentHeight * 255;
+            }
+        }
+    };
+
+    stage.on("mousedown", function() {
+        var mousePos = stage.getPointerPosition(),
+            points = spline.getPoints(),
+            pointsLength = points.length;
+
+        for(counter = 0; counter < pointsLength; counter += 2) {
+            if(points[counter] == mousePos.x){
+                points[counter + 1] = mousePos.y;
+            } else if(points[counter] > mousePos.x) {
+                points.splice(counter, 0, mousePos.x);
+                points.splice(counter + 1, 0, mousePos.y);
+            }
+        }
+
+        calculateOpacities(points);
+        $(document).trigger('opacityChanged', { opacities: opacities });
+        spline.setPoints(points);
+        layer.draw();
+    });
+
+
+}
+;var OverviewHelper = function() {
+    var sceneOveriew, rendererOverview, cameraOverview, innerCubeOverview;
+
+    //private method
+    var addInnerCubeOverView = function(x, y, z) {
+        var innerCubeGeometry = new THREE.BoxGeometry( x, y, z );
+        var innerCubeMaterial = new THREE.MeshBasicMaterial( {color: 0xaaaaaa} );
+        innerCubeOverview = new THREE.Mesh( innerCubeGeometry, innerCubeMaterial );
+        sceneOverview.add( innerCubeOverview );
+    }
+
+    var initiateEventListener = function() {
+        // change overview box
+        $(document).on('zoomActionFinished', function(e, params) {
+
+            zoomedIn = params.zoomAction == 'zoomIn';
+            sceneOverview.remove(innerCubeOverview);
+
+            if(zoomedIn) {
+                xWidth = zoomedInfo.dimension.xywidth / textureInfo.originalSize.sizex;
+                yWidth = zoomedInfo.dimension.xywidth / textureInfo.originalSize.sizey;
+                zWidth = zoomedInfo.numberOfSlices / textureInfo.originalSize.sizez;
+
+                xOffset = zoomedInfo.dimension.xmin / textureInfo.originalSize.sizex;
+                yOffset = zoomedInfo.dimension.ymin / textureInfo.originalSize.sizey;
+                zOffset = zoomedInfo.dimension.zmin / textureInfo.info.numberOfSlices;
+
+                addInnerCubeOverView(xWidth, yWidth, zWidth);
+
+                innerCubeOverview.position.x = -0.5 + xOffset + xWidth / 2;
+                innerCubeOverview.position.y = (-0.5 + yOffset + yWidth / 2) * -1;
+                innerCubeOverview.position.z = (-0.5 + zOffset + zWidth / 2) * -1;
+            } else {
+                addInnerCubeOverView(1,1,1);
+            }
+        });
+    }
+
+    var addTextsToScene = function() {
+        var shapeParameters = {font: 'helvetiker', size: 0.2, height: 0.05},
+            shape = new THREE.TextGeometry("0", shapeParameters),
+            wrapper = new THREE.MeshBasicMaterial({color: 0x000000}),
+            words = new THREE.Mesh(shape, wrapper);
+
+        words.position.x = -0.6;
+        words.position.y = 0.52;
+        words.position.z = 0.52;
+        sceneOverview.add(words);
+    }
+
+    var addCubeEdges = function() {
+        // fix for cube
+        var numberOfEdges = 12;
+        var xColorEdge = new THREE.Color(1,0,0);
+        var yColorEdge = new THREE.Color(0,1,0);
+        var zColorEdge = new THREE.Color(0,0,1);
+
+        var geometry = new THREE.BufferGeometry();
+        var material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors });
+
+        var colors = new Float32Array( numberOfEdges * 2 * 3 );
+        var positions = new Float32Array([
+            // edges in x direction
+            // front face
+            -0.5, -0.5, -0.5,  0.5, -0.5, -0.5,
+            -0.5,  0.5, -0.5,  0.5,  0.5, -0.5,
+            // back face
+            -0.5, -0.5,  0.5,  0.5, -0.5,  0.5,
+            -0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
+
+            // edges in y direction
+            // front face
+            -0.5, -0.5, -0.5, -0.5,  0.5, -0.5,
+             0.5, -0.5, -0.5,  0.5,  0.5, -0.5,
+            // back face
+            -0.5, -0.5,  0.5, -0.5,  0.5,  0.5,
+             0.5, -0.5,  0.5,  0.5,  0.5,  0.5,
+
+            // edges in z direction
+            // left side
+            -0.5, -0.5, -0.5, -0.5, -0.5,  0.5,
+            -0.5,  0.5, -0.5, -0.5,  0.5,  0.5,
+            // right side
+             0.5, -0.5, -0.5,  0.5, -0.5,  0.5,
+             0.5,  0.5, -0.5,  0.5,  0.5,  0.5
+        ]);
+
+        for(edgeCounter = 0; edgeCounter < 12 * 2; edgeCounter++) {
+            var colorToUse = null
+            if(edgeCounter <= 7) {
+                colorToUse = xColorEdge;
+            } else if(edgeCounter <= 15) {
+                colorToUse = yColorEdge;
+            } else {
+                colorToUse = zColorEdge;
+            }
+
+            colors[edgeCounter * 3 + 0] = colorToUse.r;
+            colors[edgeCounter * 3 + 1] = colorToUse.g;
+            colors[edgeCounter * 3 + 2] = colorToUse.b;
+        }
+
+        geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+        geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
+
+        var lines = new THREE.Line( geometry, material, THREE.LinePieces );
+        sceneOverview.add( lines );
+    }
+
+    return {
+        initOverview: function(containerOverviewElement) {
+            sceneOverview = new THREE.Scene();
+            cameraOverview = new THREE.PerspectiveCamera( 45, 150 / 150, .1, 1000 );
+            cameraOverview.position.z = 2;
+
+            var cubeGeometry = new THREE.BoxGeometry( 1, 1, 1 );
+            var cubeMaterial = new THREE.MeshBasicMaterial( {color: 0x000000} );
+            var cubeOverview = new THREE.Mesh( cubeGeometry, cubeMaterial );
+            var edgesHelper = new THREE.EdgesHelper(cubeOverview, 0x000000);
+            edgesHelper.material.linewidth = 2;
+            //sceneOverview.add( edgesHelper );
+
+            addInnerCubeOverView(1,1,1);
+            addCubeEdges();
+            addTextsToScene();
+
+            rendererOverview = new THREE.WebGLRenderer();
+            rendererOverview.setSize(200, 200);
+            rendererOverview.setClearColor(0xffffff, 1);
+            containerOverviewElement.appendChild(rendererOverview.domElement);
+
+            initiateEventListener();
+        },
+
+        updateCameraPosition: function(position) {
+            cameraPoint.normalize().multiplyScalar(4);
+            cameraPoint = sceneOverview.position.clone().add(cameraPoint);
+
+            cameraOverview.position.x = cameraPoint.x;
+            cameraOverview.position.y = cameraPoint.y;
+            cameraOverview.position.z = cameraPoint.z;
+            cameraOverview.lookAt(sceneOverview.position);
+        },
+
+        render: function() {
+            rendererOverview.render(sceneOverview, cameraOverview);
+        }
+    }
+}
+;var StepHelper = function() {
+    // default is the step 100
+    currentStepIndex = 2;
+    // steps just defined
+    availableSteps = [10, 20, 50, 80, 100, 150, 200];
+
+    return {
+        decreaseSteps: function() {
+            var currentStepIndex = this.determineCurrentStepIndex();
+
+            if(currentStepIndex > 0) {
+                this.updateStepValue(availableSteps[currentStepIndex - 1], true);
+            }
+        },
+
+        increaseSteps: function() {
+            var currentStepIndex = this.determineCurrentStepIndex();
+
+            if(currentStepIndex > -1 && currentStepIndex < availableSteps.length - 1) {
+                this.updateStepValue(availableSteps[currentStepIndex + 1], true);
+            }
+        },
+
+        determineCurrentStepIndex: function() {
+            var minDeviation = null,
+                minDeviationIndex;
+
+            // first we have to find an appropiate predefined stepValue for input stepvalue
+            for(var index = 0; index < availableSteps.length; index++) {
+                deviation = Math.abs(steps - availableSteps[index]);
+                if(minDeviation == null || deviation < minDeviation) {
+                    minDeviation = deviation;
+                    minDeviationIndex = index;
+                }
+            }
+
+            if(minDeviation !== null) {
+                return minDeviationIndex;
+            } else {
+                return -1;
+            }
+        },
+
+        updateStepValue: function(stepValue, updateInputField) {
+            steps = stepValue;
+            materialScreen.uniforms.steps.value = steps;
+            if(updateInputField) {
+                $('#steps').val(stepValue);
+            }
+        },
+
+        initStepControls: function() {
+            var me = this,
+                stepsInput = $('#steps'),
+                stepsAdjustInput = $('#steps-adjust');
+
+            steps = stepsInput.val();
+            stepsInput.change(function() {
+                steps = stepsInput.val();
+                me.updateStepValue(steps, false);
+            });
+
+            adjustSteps = stepsAdjustInput.is(':checked');
+
+            stepsAdjustInput.change(function() {
+                adjustSteps = $(this).is(':checked');
+                if(adjustSteps) {
+                    stepsInput.prop('disabled', true);
+                } else {
+                    stepsInput.prop('disabled', false);
+                }
+            });
+        }
+
+    };
+};
+;var TransferHelper = function() {
+    var me = this,
+        changed = false,
+        canvas = document.getElementById('transfer-function'),
+        $canvas = $(canvas),
+        context = canvas.getContext('2d'),
+        hiddenCanvas = document.getElementById('hidden-transfer'),
+        hiddenContext = hiddenCanvas.getContext('2d'),
+        transferSpanHolder = $('#transfer-span-holder'),
+        transfer = $('#transfer'),
+        disabled = true,
+        handles = $('span.transfer'),
+        $standardTf = $('img#standard-tf').get(0),
+        offsetLeft = {
+            blue: 0,
+            turquois: 0.25,
+            green: 0.5,
+            orange: 0.75,
+            red: 1
+        },
+        colorCodes = {
+            blue: '#0000FF',
+            turquois: '#00FFFF',
+            green: '#00FF00',
+            orange: '#FFFF00',
+            red: '#FF0000'
+        },
+        opacities = Array(255);
+
+    for(counter = 0; counter < opacities.length; counter++) {
+        opacities[counter] = 255;
+    }
+
+
+    $('input#toggle-transfer').on('click', function() {
+        if(disabled) {
+            enableTransferFunction();
+        } else {
+            disableTransferFunction();
+        }
+    });
+
+    var getOffsetLeft = function() {
+        return transfer.offset().left - transfer.parent().offset().left;
+    }
+
+    var removePxOffString = function(str) {
+        return parseInt(str.replace('px', ''));
+    }
+
+    var updateGradient = function() {
+        // Create gradient
+
+        var grd = context.createLinearGradient(0,0,255,0);
+
+        $.each(handles, function(index, value) {
+            var $value = $(value),
+                colorName = $value.attr('color'),
+                colorOffsetLeft = offsetLeft[colorName],
+                colorCode = colorCodes[colorName];
+
+            grd.addColorStop(colorOffsetLeft, colorCode);
+        });
+        // Fill with gradient
+        context.fillStyle = grd;
+        context.fillRect(0,0,255, 10);
+
+        applyOpacities();
+
+        changed = true;
+    };
+
+    var applyOpacities = function() {
+        var imageData = context.getImageData(0, 0, 255, 1),
+            data = imageData.data;
+
+        for(counter = 0; counter < opacities.length; counter++) {
+            data[(counter * 4) + 3] = opacities[counter];
+        }
+
+        hiddenContext.putImageData(imageData, 0, 0, 0, 0, 255, 1);
+    }
+
+    var updateHandlePosition = function(element) {
+        var colorLeft = removePxOffString($(element).css('left')) - getOffsetLeft(),
+            colorOffsetLeft = colorLeft / $canvas.width(),
+            colorName = $(element).attr('color');
+
+        if(colorOffsetLeft > 1.0) {
+            colorOffsetLeft = 1.0;
+        }
+        if(colorOffsetLeft < 0.0) {
+            colorOffsetLeft = 0.0;
+        }
+        offsetLeft[colorName] = colorOffsetLeft;
+        updateGradient();
+    };
+
+    var enableTransferFunction = function() {
+        $.each(handles, function(index, value) {
+            var $value = $(value),
+                colorName = $value.attr('color'),
+                colorOffsetLeft = offsetLeft[colorName],
+                colorLeft = getOffsetLeft() + ($canvas.width() * colorOffsetLeft),
+                colorCode = colorCodes[colorName];
+
+            $value.css({left: colorLeft, 'background-color': colorCode });
+            $(value).draggable({
+                containment: '#transfer-span-holder',
+                scroll: false,
+                axis: 'x',
+                cursor: "crosshair",
+                stop: function() {
+                    updateHandlePosition(this);
+                },
+                drag: function() {
+                    updateHandlePosition(this);
+                }
+            });
+        });
+
+        showHandles();
+        updateGradient();
+        disabled = false;
+    };
+
+    var disableTransferFunction = function() {
+        context.drawImage($standardTf, 0, 0, 255, 10);
+        applyOpacities();
+        hideHandles();
+        disabled = true;
+        changed = true;
+    };
+
+    var showHandles = function() {
+        $.each(handles, function(index, value) {
+            $(value).removeClass('hidden');
+        });
+    };
+
+    var hideHandles = function() {
+        $.each(handles, function(index, value) {
+            $(value).addClass('hidden');
+        });
+    };
+
+
+    //canvas.setAttribute('width', $canvas.width());
+    //canvas.setAttribute('height', $canvas.height());
+    disableTransferFunction();
+
+    $(document).on('opacityChanged', function(e, params) {
+        if(params != undefined && params.opacities != undefined) {
+            opacities = params.opacities;
+            applyOpacities();
+            changed = true;
+        }
+    });
+
+    return {
+        transferFunctionChanged : function() {
+            return changed;
+        },
+
+        getCurrentTransferFunction : function() {
+            changed = false;
+            return hiddenContext.getImageData(0, 0, 255, 1);
+        }
+    };
+}
+;var VolumeFace = function(orientation, direction) {
+    this.orientation = orientation;
+    this.direction = direction;
+}
+
+VolumeFace.prototype = {
+    constructor: VolumeFace,
+    orientation: 0,
+    direction: 0,
+
+    getAxisOfNaviation: function() {
+        var axis = {
+                plane: {
+                    ver: null,
+                    hor: null
+                },
+                slider: null
+            };
+
+        if(this.orientation == VolumeFaceOrientation.XY) {
+            axis.plane.ver = new Orientation(Axis.Y);
+            axis.plane.hor = new Orientation(Axis.X);
+            axis.slider = new Orientation(Axis.Z);
+        } else if(this.orientation == VolumeFaceOrientation.YZ) {
+            axis.plane.ver = new Orientation(Axis.Y);
+            axis.plane.hor = new Orientation(Axis.Z);
+            axis.slider = new Orientation(Axis.X);
+        } else if(this.orientation == VolumeFaceOrientation.XZ) {
+            axis.plane.ver = new Orientation(Axis.Z);
+            axis.plane.hor = new Orientation(Axis.X);
+            axis.slider = new Orientation(Axis.Y);
+        }
+
+        return axis;
+    },
+
+    getIdentifier: function() {
+        return this.orientation + '-' + this.direction;
+    }
+
+};
+
+var VolumeFaceOrientation = {
+    XY: 0,
+    XZ: 1,
+    YZ: 2
+}
+
+var VolumeFaceDirection = {
+    FRONT: 0,
+    BACK: 1
+}
+
+function determineVolumeFace(cubeFaceNormal) {
+    var orientation, direction;
+    if(cubeFaceNormal.x != 0) {
+        orientation = VolumeFaceOrientation.YZ;
+        direction = determineFaceOrientation(cubeFaceNormal.x);
+    } else if(cubeFaceNormal.y != 0) {
+        orientation = VolumeFaceOrientation.XZ;
+        direction = determineFaceOrientation(cubeFaceNormal.y);
+    } else if(cubeFaceNormal.z != 0) {
+        orientation = VolumeFaceOrientation.XY;
+        direction = determineFaceOrientation(cubeFaceNormal.z);
+    }
+    return new VolumeFace(orientation, direction);
+}
+
+function determineFaceOrientation(normalComp) {
+    return normalComp > 0 ? VolumeFaceDirection.FRONT : VolumeFaceDirection.BACK;
+}
+
+
+function isFrontFace(orientation, direction) {
+    return orientation == VolumeFaceOrientation.XY
+           && direction == VolumeFaceDirection.FRONT;
+}
+
+function isBackFace(orientation, direction) {
+    return orientation == VolumeFaceOrientation.XY
+           && direction == VolumeFaceDirection.BACK;
+}
+
+function isLeftFace(orientation, direction) {
+    return orientation == VolumeFaceOrientation.YZ
+           && direction == VolumeFaceDirection.FRONT;
+}
+
+function isRightFace(orientation, direction) {
+    return orientation == VolumeFaceOrientation.YZ
+           && direction == VolumeFaceDirection.BACK;
+}
+
+function isTopFace(orientation, direction) {
+    return orientation == VolumeFaceOrientation.XZ
+           && direction == VolumeFaceDirection.FRONT;
+}
+
+function isBottomFace(orientation, direction) {
+    return orientation == VolumeFaceOrientation.XZ
+           && direction == VolumeFaceDirection.BACK;
+}
+;var ZoomHelper = function() {
+    var navigationPlaneHorLabel = $('#navigation-plane-hor-label'),
+        navigationPlaneVerLabel = $('#navigation-plane-ver-label'),
+        navigationSliderLabel = $('#navigation-slider-label'),
+        zoomStatus = $('#zoom-status'),
+        zoomInButton = $('input#zoomin'),
+        zoomOutButton = $('input#zoomout'),
+        navigationPlane = $('div#navigation-plane'),
+        navigationPlaneParent = navigationPlane.parent(),
+        navigationSlider = $('div#navigation-slider'),
+        navigationSliderParent = navigationSlider.parent(),
+        displayTimestamp = null,
+        planeOrientation = {
+            ver: new Orientation(Axis.Y, OffsetTo.LEFT),
+            hor: new Orientation(Axis.X, OffsetTo.TOP),
+            direction: VolumeFaceDirection.BACK,
+            orientation: VolumeFaceOrientation.XY
+        },
+        sliderOrientation = {axis: new Orientation(Axis.Z, OffsetTo.TOP) },
+        zoomedIn,
+        zoomedInfoArray = {
+            dimension: Array(3),
+            offset: Array(3)
+        };
+
+    var lastExecutionTime = Date.now();
+    // adjust navigation related navigations
+    $container.on('animation', function() {
+        determineAxisLabels();
+        determinePlanePosition();
+        determineSliderPosition();
+    });
+
+    // one has to press ctrl AND alt while clicking
+    $container.on('click', 'canvas', function(event){
+        event.stopPropagation();
+        event.preventDefault();
+
+        // keyboard shortcut activated or button zoom in pressed before?
+        if((event.ctrlKey == false || event.altKey == false)
+           && !zoomInActivated) {
+            return;
+        }
+
+        var mouseX = ( (event.clientX - $canvas.offset().left)  / ($canvas.width())  ) * 2 - 1,
+            mouseY = - ( (event.clientY - $canvas.offset().top) / ($canvas.height()) ) * 2 + 1;
+
+        var vector = new THREE.Vector3( mouseX, mouseY, camera.near);
+
+        vector = vector.unproject( camera );
+
+        var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
+
+        var intersects = raycaster.intersectObjects( [frontBox] );
+
+        if(intersects.length > 0) {
+            if(!handleZoomStatus(true)) {
+                return false;
+            }
+
+            var intersect = intersects[0],
+                point = intersect.point;
+
+            var geometry = new THREE.BoxGeometry( 0.1, 0.1, 0.1 );
+
+            var material = new THREE.MeshBasicMaterial( {
+                color: new THREE.Color( 0xaaaaaa ),
+                opacity: 0.3
+            });
+
+            mesh = new THREE.Mesh( geometry, material );
+            mesh.position.x = point.x;
+            mesh.position.y = point.y;
+            mesh.position.z = point.z;
+            scene.add(mesh);
+            intersectCubes[intersectCubes.length] = mesh;
+            intersectCubesTimeStamps[intersectCubesTimeStamps.length] = Date.now();
+
+            var realPoint = point.clone();
+            zoomIn(point);
+        }
+
+
+    });
+
+    function zoomIn(realPoint, alreadyTranslated) {
+        if(alreadyTranslated == undefined || !alreadyTranslated) {
+            // retranslate the point into original position beginning from 0,0,0
+            realPoint.add(new THREE.Vector3(0.5, 0.5, 0.5));
+        }
+
+        volumePointArray = realPoint.toArray();
+
+        var processingUrl = homeUrl + 'volumes/' + volumeId + '/processing/sub/';
+        $.each(volumePointArray, function(index, value) {
+            dimWidth = null;
+            if(index == 0) {
+                dimWidth = textureInfo.originalSize.sizex;
+            } else if(index == 1) {
+                dimWidth = textureInfo.originalSize.sizey;
+            } else {
+                dimWidth = textureInfo.originalSize.sizez;
+            }
+            value *= dimWidth;
+            // due to interpolation algorithm, we had to rotate the whole cube, that it matches
+            // the display of imagej
+            // so we have to map the current pointer values to the real volume values
+            // but only for the y and z direction --> the x direction is all right
+            if(index > 0) {
+                value = dimWidth - value;
+            }
+
+            value = Math.floor(value);
+            volumePointArray[index] = value;
+            processingUrl += value + '/';
+        });
+
+        frameNumber = imgInfo.frameFrom + currentTexture;
+
+        processingUrl += frameNumber + '/';
+
+        $.ajax({
+            url: processingUrl,
+            success: function(data) {
+                var available = false;
+                var availableTestCounter = 0;
+                zoomedInfo = data;
+
+                // this function is called recursive by the settimeout statement
+                availableTest = function() {
+                    $.ajax({
+                        url: homeUrl + 'volumes/' + volumeId + '/processing/sprite/' + zoomedInfo.spriteId + '/available/',
+                        success: function(data) {
+                            available = data.available;
+                        },
+                        dataType: 'json',
+                        async: false
+                    });
+
+                    if(available) {
+                        // subvolume available: fetch it
+                        fetchZoomedVolume();
+                    } else if(availableTestCounter < 20) {
+                        // abort condition not reached --> try again
+                        setTimeout(availableTest, 2000);
+                        availableTestCounter++;
+                    } else {
+                        // abort condition reached --> error handling
+                        $(document).trigger('zoomActionFinished', { zoomAction: 'zoomOut', error: true });
+                    }
+                };
+                setTimeout(availableTest, 2000);
+            },
+            dataType: 'json',
+            async: true,
+            error: function(data) {
+                helper.displayMessage('Sorry, an error occured during processing zoom', true, null, 2500);
+            }
+        });
+    };
+
+    var fetchZoomedVolume = function() {
+        imageSrc = homeUrl + 'volumes/' + volumeId + '/processing/sprite/' + zoomedInfo.spriteId + '/show/';
+
+        var image = new Image();
+        var texture = initTexture(new THREE.Texture(image));
+
+        image.onload = function() {
+
+            materialScreen.uniforms.numberOfSlices.value = zoomedInfo.numberOfSlices;
+            materialScreen.uniforms.numberOfSlices.needsupdate = true;
+            materialScreen.uniforms.slicesOverX.value = zoomedInfo.slicesOverX;
+            materialScreen.uniforms.slicesOverX.needsUpdate = true;
+            materialScreen.uniforms.slicesOverY.value = zoomedInfo.slicesOverY;
+            materialScreen.uniforms.slicesOverY.needsUpdate = true;
+            materialScreen.uniforms.numberOfSprites.value = 1;
+            materialScreen.uniforms.numberOfSprites.needsUpdate = true;
+            materialScreen.uniforms.slicesPerSprite.value = zoomedInfo.numberOfSlices;
+            materialScreen.uniforms.slicesPerSprite.needsUpdate = true;
+
+            updateTexture([texture]);
+
+            zoomedVolumeDimension.xmin = zoomedInfo.dimension.xmin;
+            zoomedVolumeDimension.xmax = zoomedInfo.dimension.xmin + zoomedInfo.dimension.xywidth - 1;
+            zoomedVolumeDimension.ymin = zoomedInfo.dimension.ymin;
+            zoomedVolumeDimension.ymax = zoomedInfo.dimension.ymin + zoomedInfo.dimension.xywidth - 1;
+            zoomedVolumeDimension.zmin = zoomedInfo.dimension.zmin;
+            zoomedVolumeDimension.zmax = zoomedInfo.dimension.zmin + zoomedInfo.numberOfSlices - 1;
+
+            originalVolumeDimension = currentVolumeDimension;
+            originalDimension = currentDimension;
+
+            currentVolumeDimension = zoomedVolumeDimension;
+
+            repositionLayerSliders();
+
+            $(document).trigger('zoomActionFinished', { zoomAction: 'zoomIn', textureNumber: frameNumber });
+        }
+
+        image.src = imageSrc;
+    };
+
+    $container.on('contextmenu', function(event){
+        if(event.ctrlKey == false) {
+            return;
+        }
+
+        if(event.altKey == false) {
+            return;
+        }
+
+        if(!handleZoomStatus(false)) {
+            return false;
+        }
+
+        return zoomOut();
+    });
+
+
+    function zoomOut() {
+        materialScreen.uniforms.numberOfSlices.value = textureInfo.info.numberOfSlices;
+        materialScreen.uniforms.numberOfSlices.needsupdate = true;
+        materialScreen.uniforms.slicesOverX.value = textureInfo.info.slicesOverX;
+        materialScreen.uniforms.slicesOverX.needsUpdate = true;
+        materialScreen.uniforms.slicesOverY.value = textureInfo.info.slicesOverY;
+        materialScreen.uniforms.slicesOverY.needsUpdate = true;
+        materialScreen.uniforms.numberOfSprites.value = imgInfo.numberOfSprites;
+        materialScreen.uniforms.numberOfSprites.needsUpdate = true;
+        materialScreen.uniforms.slicesPerSprite.value = imgInfo.slicesPerSprite;
+        materialScreen.uniforms.slicesPerSprite.needsUpdate = true;
+
+        updateTexture();
+
+        currentVolumeDimension = originalVolumeDimension;
+        currentDimension = originalDimension;
+
+        repositionLayerSliders();
+
+        $(document).trigger('zoomActionFinished', { zoomAction: 'zoomOut' });
+        return false;
+    }
+
+
+    /**
+    * return: procceed or not
+    */
+    function handleZoomStatus(zoomIn) {
+        zoomInButton.removeClass('red');
+        zoomInActivated = false;
+
+        if(zoomIn && zoomedIn) {
+            return false;
+        } else if(!zoomIn && !zoomedIn) {
+            return false;
+        }
+
+        waitDiv.removeClass('hidden');
+
+        if(zoomIn) {
+            zoomInButton.prop('disabled', true);
+        } else {
+            zoomInButton.prop('disabled', false);
+        }
+
+        displayMessage = zoomIn ? 'Generating zoomed subvolume, please wait a moment' : 'Zooming out';
+        helper.displayMessage(displayMessage);
+        displayTimestamp = Date.now();
+
+        return true;
+    }
+
+    // general function to disable stuff like messages etc.
+    $(document).on('zoomActionFinished', function(e, params) {
+        zoomedIn = params.zoomAction == 'zoomIn';
+
+        timeout = 2000 - (Date.now() - displayTimestamp);
+        if(timeout < 0) {
+            timeout = 0;
+        }
+        helper.fadeoutMessage(null, timeout);
+
+        zoomedStatusText = '';
+        if(zoomedIn) {
+            zoomStatus.addClass('green-background');
+            zoomedStatusText = 'zoomed in';
+
+            $.each($('.res-link'), function(index, value) {
+                $(value).addClass('disabled');
+            });
+        } else {
+            zoomStatus.removeClass('green-background');
+            zoomedStatusText = 'zoomed out';
+            console.log(params);
+            if(params.error) {
+                console.log('error handling');
+                errorMessage = 'Error during subvolume generation - zoomed out again';
+                helper.displayMessage(errorMessage, true, null, 5000);
+            }
+
+            $.each($('.res-link'), function(index, value) {
+                $(value).removeClass('disabled');
+            });
+        }
+
+        zoomStatus.html(zoomedStatusText);
+        waitDiv.addClass('hidden');
+    });
+
+    // draggable related stuff
+    $(document).on('zoomActionFinished', function(e, params) {
+
+        zoomedIn = params.zoomAction == 'zoomIn';
+
+        if(zoomedIn) {
+            zoomedInfoArray.offset[Axis.X] = zoomedVolumeDimension.xmin;
+            zoomedInfoArray.offset[Axis.Y] = zoomedVolumeDimension.ymin;
+            zoomedInfoArray.offset[Axis.Z] = zoomedVolumeDimension.zmin;
+
+            zoomedInfoArray.dimension[Axis.X] = zoomedInfo.dimension.xywidth;
+            zoomedInfoArray.dimension[Axis.Y] = zoomedInfo.dimension.xywidth;
+            zoomedInfoArray.dimension[Axis.Z] = zoomedInfo.numberOfSlices;
+        } else {
+            navigationPlane.hide();
+            navigationPlaneParent.removeClass('white');
+
+            navigationSlider.hide();
+            navigationSliderParent.removeClass('white');
+        }
+
+        navigationPlane.removeClass('no-pos-set');
+        navigationSlider.removeClass('no-pos-set');
+    });
+
+    navigationPlane.draggable({
+        containment: '#navigation-plane-container',
+        scroll: false,
+        stop: function() {
+            zoomedDraggableChanged();
+        }
+    });
+
+    navigationSlider.draggable({
+        containment: '#navigation-slider-container',
+        scroll: false,
+        stop: function() {
+            zoomedDraggableChanged();
+        }
+    });
+
+
+    function zoomedDraggableChanged() {
+        waitDiv.removeClass('hidden');
+        var planeWidthHalf = navigationPlane.width() / 2,
+            planeHeightHalf = navigationPlane.height() / 2,
+            planeOffsetLeft = navigationPlane.offset().left - navigationPlaneParent.offset().left - 1,
+            planeOffsetTop = navigationPlane.offset().top - navigationPlaneParent.offset().top - 1,
+
+            sliderHeightHalf = navigationSlider.height() / 2,
+            sliderOffsetTop = navigationSlider.offset().top - navigationSliderParent.offset().top - 1,
+            orientation = planeOrientation.orientation,
+            direction = planeOrientation.direction;
+
+
+        // set correct border values due to messure errors
+        if(planeOffsetLeft < 0) {
+            planeOffsetLeft = 0;
+        } else if(planeOffsetLeft > navigationPlaneParent.width() - navigationPlane.width()) {
+            planeOffsetLeft = navigationPlaneParent.width() - navigationPlane.width();
+        }
+
+        if(planeOffsetTop < 0) {
+            planeOffsetTop = 0;
+        } else if(planeOffsetTop > navigationPlaneParent.height() - navigationPlane.height()) {
+            planeOffsetTop = navigationPlaneParent.height() - navigationPlane.height();
+        }
+
+        if(sliderOffsetTop < 0) {
+            sliderOffsetTop = 0;
+        } else if(sliderOffsetTop > navigationSliderParent.height() - navigationSlider.height()) {
+            sliderOffsetTop = navigationSliderParent.height() - navigationSlider.height();
+        }
+
+        planeOffsetLeft = planeOffsetLeft + planeWidthHalf;
+        planeOffsetTop = planeOffsetTop + planeHeightHalf;
+        sliderOffsetTop = sliderOffsetTop + sliderHeightHalf;
+
+        horAxis = planeOrientation.hor.axis;
+        verAxis = planeOrientation.ver.axis;
+        console.log('orientation ', planeOrientation.orientation);
+        console.log('direction ', planeOrientation.direction);
+        pointAsArray = Array(3);
+
+        pointAsArray[horAxis] = planeOffsetLeft / navigationPlaneParent.width();
+        pointAsArray[verAxis] = 1.0 - (planeOffsetTop / navigationPlaneParent.height());
+
+        if(planeOrientation.direction == VolumeFaceDirection.BACK) {
+            pointAsArray[horAxis] = 1.0 - pointAsArray[horAxis];
+        } else if(planeOrientation.orientation == VolumeFaceOrientation.XZ) {
+            pointAsArray[horAxis] = 1.0 - pointAsArray[horAxis];
+        }
+
+        pointAsArray[sliderOrientation.axis] = 1.0 - (sliderOffsetTop / navigationSliderParent.height());
+
+        if((sliderOrientation.axis == Axis.Z
+            && planeOrientation.direction == VolumeFaceDirection.FRONT)
+           || (sliderOrientation.axis == Axis.Y
+            && planeOrientation.direction == VolumeFaceDirection.FRONT)
+           || (sliderOrientation.axis == Axis.X
+            && planeOrientation.direction == VolumeFaceDirection.BACK)) {
+
+            pointAsArray[sliderOrientation.axis] = 1.0 - pointAsArray[sliderOrientation.axis];
+        }
+
+        point = new THREE.Vector3(pointAsArray[0], pointAsArray[1], pointAsArray[2]);
+
+        zoomIn(point, true);
+    };
+
+    var zoomInActivated = false;
+    zoomInButton.on('click', function() {
+        zoomInActivated = !zoomInActivated;
+
+        if(zoomInActivated) {
+            $(this).addClass('red');
+        } else {
+            $(this).removeClass('red');
+        }
+    });
+
+    zoomOutButton.on('click', function() {
+        zoomInButton.removeClass('red');
+
+        if(!handleZoomStatus(false)) {
+            return false;
+        }
+
+        return zoomOut();
+    });
+
+    function determineAxisLabels() {
+        if(Date.now() - lastExecutionTime > 100) {
+            var lookAtVector = new THREE.Vector3(0,0, -1);
+            lookAtVector.applyQuaternion(camera.quaternion);
+
+            xIterator = -0.4;
+            yIterator = -0.4;
+            facesIntersect = {};
+            interSectStartingPoint = new THREE.Vector3(xIterator, yIterator, camera.near);
+            for(xIterator = -0.4; xIterator <= 0.4; xIterator += 0.2) {
+                for(yIterator = -0.4; yIterator <= 0.4; yIterator += 0.2) {
+                    interSectStartingPoint.x = xIterator;
+                    interSectStartingPoint.y = yIterator;
+
+
+                    vector = interSectStartingPoint.unproject( camera );
+
+                    var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
+
+                    var intersects = raycaster.intersectObjects( [frontBox] );
+
+                    if(intersects.length > 0) {
+                        var intersect = intersects[0],
+                            point = intersect.point,
+                            face = intersect.face,
+                            faceObject = determineVolumeFace(face.normal),
+                            faceIdent = faceObject.getIdentifier();
+                            alreadyAdded = Object.keys(facesIntersect).indexOf(faceIdent) >= 0;
+
+                        if(alreadyAdded) {
+                            facesIntersect[faceIdent].count++;
+                        } else {
+                            facesIntersect[faceIdent] = { faceObject: faceObject, count: 1};
+                        }
+                    }
+                }
+            }
+
+            frontFace = { count: 0 };
+            for(faceIdent in facesIntersect) {
+                if(facesIntersect[faceIdent].count > frontFace.count) {
+                    frontFace = facesIntersect[faceIdent];
+                }
+            }
+
+            if(frontFace.faceObject != undefined) {
+                volumeFace = frontFace.faceObject;
+
+                if(volumeFace.orientation == VolumeFaceOrientation.XZ) {
+                    //console.log(volumeFace.direction, lookAtVector);
+                    //console.log(lookAtVector.x < 0.015, lookAtVector.z < 0.015);
+                }
+
+                axisOfNaviation = volumeFace.getAxisOfNaviation();
+
+                planeOrientation = axisOfNaviation.plane;
+                planeOrientation.hor.offsetTo = OffsetTo.LEFT;
+                planeOrientation.ver.offsetTo = OffsetTo.TOP;
+                planeOrientation.direction = volumeFace.direction;
+                planeOrientation.orientation = volumeFace.orientation;
+
+                sliderOrientation = axisOfNaviation.slider;
+                sliderOrientation.offsetTo = OffsetTo.TOP;
+
+                navigationPlaneHorLabel.html(planeOrientation.hor.getLabel());
+                navigationPlaneVerLabel.html(planeOrientation.ver.getLabel());
+                navigationSliderLabel.html(sliderOrientation.getLabel());
+            }
+
+            lastExecutionTime = Date.now();
+        }
+    }
+
+    function determinePlanePosition() {
+        if(!zoomedIn) {
+            return;
+        }
+
+        if(navigationPlane.hasClass('ui-draggable-dragging')
+          || navigationPlane.hasClass('no-pos-set')) {
+            navigationPlane.addClass('no-pos-set');
+            return;
+        }
+
+        horAxis = planeOrientation.hor.axis;
+        verAxis = planeOrientation.ver.axis;
+
+        planeRelativeX = navigationPlaneParent.width() / originalSizeArray[horAxis];
+        planeRelativeY = navigationPlaneParent.height() / originalSizeArray[verAxis];
+
+        planeWidth = planeRelativeX * zoomedInfoArray.dimension[horAxis];
+        planeHeight = planeRelativeY * zoomedInfoArray.dimension[verAxis];
+
+        planeWidth = Math.ceil(planeWidth);
+        planeHeight = Math.ceil(planeHeight);
+
+        planeOffsetLeft = zoomedInfoArray.offset[horAxis] * planeRelativeX;
+        if((planeOrientation.direction == VolumeFaceDirection.BACK
+            && planeOrientation.orientation == VolumeFaceOrientation.XY)
+           || (planeOrientation.direction == VolumeFaceDirection.FRONT
+              && planeOrientation.orientation == VolumeFaceOrientation.YZ)) {
+
+            planeOffsetLeft = navigationPlaneParent.width() - (planeOffsetLeft + navigationPlane.width());
+        }
+
+        planeOffsetTop = zoomedInfoArray.offset[verAxis] * planeRelativeY;
+
+
+        navigationPlane.css({
+            'top': planeOffsetTop + 'px',
+            'left' : planeOffsetLeft + 'px',
+            'width': planeWidth + 'px',
+            'height': planeHeight + 'px'
+        });
+
+        navigationPlane.show();
+        navigationPlaneParent.addClass('white');
+    }
+
+    function determineSliderPosition() {
+        if(!zoomedIn) {
+            return;
+        }
+
+        if(navigationSlider.hasClass('ui-draggable-dragging')
+          || navigationSlider.hasClass('no-pos-set')) {
+            navigationSlider.addClass('no-pos-set');
+            return;
+        }
+
+        sliderRelative = navigationSliderParent.height() / originalSizeArray[sliderOrientation.axis];
+        sliderOffsetTop = zoomedInfoArray.offset[sliderOrientation.axis] * sliderRelative;
+
+        sliderHeight = Math.ceil(sliderRelative * zoomedInfoArray.dimension[sliderOrientation.axis]);
+
+        if(planeOrientation.direction == VolumeFaceDirection.FRONT) {
+            sliderOffsetTop = navigationSliderParent.height() - (navigationSlider.height() + sliderOffsetTop);
+        }
+
+        navigationSlider.css({
+            'top': sliderOffsetTop + 'px',
+            'height': sliderHeight + 'px'
+        });
+
+        navigationSlider.show();
+        navigationSliderParent.addClass('white');
+    }
+};
+
+//$(document).on('basicsReady', function() {
+//    var zoomHelper = new ZoomHelper();
+//});
+
+function radToDeg(rad) {
+    return rad * 180 / Math.PI;
+}
+
+
+
+
+
+
+;var Orientation = function(axis, offsetTo) {
+    this._axis = axis;
+    this._offsetTo = null;
+}
+
+Orientation.prototype = {
+    constructor: Orientation,
+
+    getLabel: function() {
+        switch(this._axis) {
+            case(Axis.X):
+                return 'x-axis';
+            case(Axis.Y):
+                return 'y-axis';
+            case(Axis.Z):
+                return 'z-axis';
+        }
+    },
+
+    get axis() {
+        return this._axis;
+    },
+
+    get offsetTo() {
+        return this._offsetTo;
+    },
+
+    set offsetTo(value) {
+        this._offsetTo = value;
+    }
+}
+
+var Axis = {
+    X: 0,
+    Y: 1,
+    Z: 2
+}
+
+var OffsetTo = {
+    TOP: 0,
+    LEFT: 1,
+    BOTTOM: 2,
+    RIGHT: 3
+}
+;IPE.interceptors.SendInterceptor = (function() {
+    return {
+        init: function() {
+            $(document).ajaxSend(function (e, xhr, settings) {
+                if(settings.url.indexOf('/static/') === -1) {
+                    if(!settings.url.endsWith('/')) {
+                       settings.url += '/';
+                    }
+                }
+            });
+        }
+    };
+}())
+;var NavigationPlane = function(element, horizontalLabel, verticalLabel) {
+    this._element = element;
+    this._parent = element.parent();
+    this._horizontalLabel = horizontalLabel;
+    this._verticalLabel = verticalLabel;
+
+    this._zoomedInfoArray = null;
+    this._volumeFace = null;
+}
+
+NavigationPlane.prototype = {
+    constructor: NavigationPlane,
+
+    set zoomedInfoArray(value) {
+        this._zoomedInfoArray = value;
+    },
+
+    set volumeFace(value) {
+        this._volumeFace = value;
+    },
+
+
+
+
+
+}
+;

+ 1 - 0
visualization/settings_env.py.dev

@@ -1,3 +1,4 @@
+import os
 '''
     define, where this application runs
     prod, staging, dev

+ 1 - 0
visualization/settings_env.py.prod

@@ -1,3 +1,4 @@
+import os
 '''
     define, where this application runs
     prod, staging, dev

+ 1 - 0
visualization/settings_env.py.staging

@@ -1,3 +1,4 @@
+import os
 '''
     define, where this application runs
     prod, staging, dev

Some files were not shown because too many files changed in this diff