3 Commits ba4ef91af2 ... 233784732a

Author SHA1 Message Date
  Raghav Arora 233784732a Added controls to Wave 6 years ago
  Raghav Arora 64bf738e06 Updated Wave to support CORS 6 years ago
  Raghav Arora 92d55257ce Changed wave to a nova-centric layout 6 years ago

+ 44 - 0
nova/static/css/custom.css

@@ -65,6 +65,7 @@ a:hover {
   font-size: smaller;
   color: #99979c;
   background-color: #222222;
+  z-index:150;
 }
 
 .clickable {
@@ -349,3 +350,46 @@ a:hover {
 .form-group>label {
   text-align:right;
 }
+
+#wave-container {
+  position: absolute;
+  float:left;
+  border: 1px solid #ddd;
+  height:512px;
+  width: 512px;
+  padding:0;
+  z-index:100;
+}
+
+#loading-wave {
+  display: block;
+  margin: 156px auto;
+}
+
+#wave-controls {
+  padding-left: 560px;
+  z-index:50;
+}
+
+.wave-control>div {
+  margin-bottom: 20px;
+}
+
+.slider-range-input {
+  max-width: 100%;
+  width:40px;
+  text-align:center;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+}
+
+.ui-slider {
+  margin-top: 10px;
+}
+
+#box-wireframe-input {
+  margin-left: 30px;
+  background-color: #fff;
+  width: 20px;
+  height: 20px;
+}

+ 4 - 3
nova/static/js/dataset.js

@@ -18,7 +18,8 @@ var meta = new Vue ({
     derived_read: true,
     derived_interact: true,
     derived_fork: false,
-    derived_name_available: false
+    derived_name_available: false,
+    show_wave_option: true
   },
   created: function() {
     var user_id = this.token.split('.')[0]
@@ -30,6 +31,7 @@ var meta = new Vue ({
     this.$http.get(api_str, {headers: headers}).then((response) => {
       this.bookmarked = response.body.hasOwnProperty("collection")
     })
+    if (is_wave) this.show_wave_option = false
   },
   watch: {
     derived_dataset_name: function (value) {
@@ -95,8 +97,7 @@ var meta = new Vue ({
       }
     },
     openWave: function () {
-        window.open('/wave?user='+user_name+'&dataset='+dataset_name,'_blank',
-        'location=no, width=275, height=275, scrollbars=no, status=no')
+        window.location.href='/wave?user='+user_name+'&dataset='+dataset_name+'&collection='+collection_name
     },
   }
 })

+ 54 - 102
nova/static/js/wave/volumeRaycaster.js

@@ -1,26 +1,7 @@
-/**
- * @classdesc
- * NamespaceKTV
- *
- * @class NamespaceKTV
- * @this NamespaceKTV;
- * @author sogimu@nxt.ru Aleksandr Lizin aka sogimu
- * @version 0.1
- *
- */
-
 (function(namespace) {
 
 	namespace.VRC = {};
 })(window);
-/**
- * @classdesc
- * EventDispatcher
- *
- * @class EventDispatcher
- * @this {RC.EventDispatcher}
- * @author sogimu@nxt.ru Aleksandr Lizin aka sogimu
- */
 
 (function(namespace) {
     var EventDispatcher = function(O) {
@@ -109,15 +90,6 @@
     namespace.EventDispatcher = EventDispatcher;
 
 })(window.VRC);
-/**
- * @classdesc
- * AdaptationManager
- *
- * @class AdaptationManager
- * @this {AdaptationManager}
- * @author sogimu@nxt.ru Aleksandr Lizin aka sogimu
- *
- */
 
 (function(namespace) {
     var AdaptationManager = function() {
@@ -273,15 +245,6 @@
 
 })(window.VRC);
 
-/**
- * @classdesc
- * Core
- *
- * @class Core
- * @this {Core}
- * @author sogimu@nxt.ru Aleksandr Lizin aka sogimu
- */
-
 (function(namespace) {
     var GeometryHelper = function() {
 
@@ -539,7 +502,6 @@ var Core = function(conf) {
         }
     };
 
-
     this._materialFirstPass = {};
     this._materialSecondPass = {};
 
@@ -880,72 +842,74 @@ Core.prototype._secondPassSetUniformValue = function(key, value) {
 };
 
 
-Core.prototype._setSlicemapsTextures = function(images) {
-    var textures = [];
-
-    for(var i=0; i<images.length; i++) {
-        var texture = new THREE.Texture( images[i] );
-        texture.magFilter = THREE.LinearFilter;
-        texture.minFilter = THREE.LinearFilter;
-        texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
-        texture.generateMipmaps = false;
-        texture.flipY = false;
-        texture.needsUpdate = true;
-
-        textures.push(texture);
-    };
-    this._slicemaps_textures = textures;
-};
+	Core.prototype._setSlicemapsTextures = function(images) {
+	    var textures = [];
+            var loader = new THREE.TextureLoader();
+            loader.crossOrigin = '';
+            for(var i=0; i<images.length; i++) {
+                this_img = images[i];
+                loader.load(this_img.src, function (texture) {
+                    texture.magFilter = THREE.LinearFilter;
+		    texture.minFilter = THREE.LinearFilter;
+                    texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
+		    texture.generateMipmaps = false;
+		    texture.flipY = false;
+		    texture.needsUpdate = true;
+                    textures.push(texture);
+	        }, function (err) { console.log("error");} );
+            }
+	    this._slicemaps_textures = textures;
+	};
 
 
-Core.prototype.setTransferFunctionByImage = function(image) {
-    this._transfer_function_as_image = image;
-    var texture = new THREE.Texture(image);
-    texture.magFilter = THREE.LinearFilter;
-    texture.minFilter = THREE.LinearFilter;
-    texture.wrapS = texture.wrapT =  THREE.ClampToEdgeWrapping;
-    texture.generateMipmaps = false;
-    texture.flipY = true;
-    texture.needsUpdate = true;
+	Core.prototype.setTransferFunctionByImage = function(image) {
+	    this._transfer_function_as_image = image;
+	    var texture = new THREE.Texture(image);
+	    texture.magFilter = THREE.LinearFilter;
+	    texture.minFilter = THREE.LinearFilter;
+	    texture.wrapS = texture.wrapT =  THREE.ClampToEdgeWrapping;
+	    texture.generateMipmaps = false;
+	    texture.flipY = true;
+	    texture.needsUpdate = true;
 
-    if(this._mode == "3d") {
-        this._secondPassSetUniformValue("uTransferFunction", texture);
-    }
-    this.onChangeTransferFunction.call(image);
-};
+	    if(this._mode == "3d") {
+		this._secondPassSetUniformValue("uTransferFunction", texture);
+	    }
+	    this.onChangeTransferFunction.call(image);
+	};
 
 
-Core.prototype.setTransferFunctionByColors = function(colors) {
-    this._transfer_function_colors = colors;
+	Core.prototype.setTransferFunctionByColors = function(colors) {
+	    this._transfer_function_colors = colors;
 
-    var canvas = document.createElement('canvas');
-    canvas.width  = 512;
-    canvas.height = 2;
+	    var canvas = document.createElement('canvas');
+	    canvas.width  = 512;
+	    canvas.height = 2;
 
-    var ctx = canvas.getContext('2d');
+	    var ctx = canvas.getContext('2d');
 
-    var grd = ctx.createLinearGradient(0, 0, canvas.width -1 , canvas.height - 1);
+	    var grd = ctx.createLinearGradient(0, 0, canvas.width -1 , canvas.height - 1);
 
-    for(var i=0; i<colors.length; i++) {
-        grd.addColorStop(colors[i].pos, colors[i].color);
-    }
+	    for(var i=0; i<colors.length; i++) {
+		grd.addColorStop(colors[i].pos, colors[i].color);
+	    }
 
-    ctx.fillStyle = grd;
-    ctx.fillRect(0,0,canvas.width ,canvas.height);
-    var image = new Image();
-    image.src = canvas.toDataURL();
-    image.style.width = 20 + " px";
-    image.style.height = 512 + " px";
+	    ctx.fillStyle = grd;
+	    ctx.fillRect(0,0,canvas.width ,canvas.height);
+	    var image = new Image();
+	    image.src = canvas.toDataURL();
+	    image.style.width = 20 + " px";
+	    image.style.height = 512 + " px";
 
-    var transferTexture = this.setTransferFunctionByImage(image);
+	    var transferTexture = this.setTransferFunctionByImage(image);
 
-    this.onChangeTransferFunction.call(image);
-};
+	    this.onChangeTransferFunction.call(image);
+	};
 
 
-Core.prototype.getTransferFunctionAsImage = function() {
-    return this._transfer_function_as_image;
-};
+	Core.prototype.getTransferFunctionAsImage = function() {
+	    return this._transfer_function_as_image;
+	};
 
 
 Core.prototype.getBase64 = function() {
@@ -1022,7 +986,6 @@ Core.prototype.setZoom = function(x1, x2, y1, y2) {
 }
 
 Core.prototype.set2DTexture = function(urls) {
-    THREE.ImageUtils.crossOrigin = '';
     var chosen_cm = THREE.ImageUtils.loadTexture( urls[0] );
     var chosen_cm2 = THREE.ImageUtils.loadTexture( urls[1] );
 
@@ -5076,17 +5039,6 @@ window.VRC.Core.prototype._shaders.secondPassStevenTri = {
 		'}'].join("\n")
 };
 
-/**
- * @classdesc
- * RaycasterLib
- *
- * @class RaycasterLib
- * @this {RaycasterLib}
- * @author sogimu@nxt.ru Aleksandr Lizin aka sogimu
- * @version 0.1
- *
- */
-
 (function(namespace) {
     var VolumeRaycaster = function(config) {
 

+ 1 - 0
nova/templates/dataset/detail.html

@@ -250,6 +250,7 @@
   var collection_name = '{{ collection.name }}';
   var dataset_name = '{{ dataset.name }}';
   var user_name = '{{ user.name }}';
+  var is_wave = false;
 </script>
 <script>System.import('dataset.js')</script>
 {% endblock %}

+ 1 - 1
nova/templates/dataset/header.html

@@ -50,7 +50,7 @@
 – <a href="{{ url_for("show_collection", collection_name=dataset.collection.name) }}">{{ dataset.collection.name }}</a> / {{ dataset.name }}
         <i class="clickable pull-right" :class="{ 'fa fa-bookmark': bookmarked, 'fa fa-bookmark-o': !bookmarked }" @click="bookmark"></i>
         <i class="clickable pull-right fa fa-clone" @click="beginDatasetDerive"></i>
-        <i class="clickable pull-right fa fa-eye" @click="openWave"></i>
+        <i v-if="show_wave_option" class="clickable pull-right fa fa-eye" @click="openWave"></i>
       </h2>
     </div>
   </div>

+ 173 - 29
nova/templates/dataset/wave.html

@@ -1,31 +1,68 @@
-<!doctype html>
-
-<html lang="en">
-<head>
-  <meta charset="utf-8">
-  <title>Wave</title>
-</head>
-
-<body style="background-color: #000;">
-    <div id="container" style="width:256px; height: 256px; background-color: #aaa;"></div>
-    <script
-        src="https://code.jquery.com/jquery-3.3.1.min.js"
-        crossorigin="anonymous"></script>
-    <script src="{{ url_for('static', filename='js/wave/three.min.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/wave/TrackballControls.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/wave/ejs.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/wave/volumeRaycaster.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/wave/stats.min.js') }}"></script>
-    <script>
+{% extends "dataset/header.html" %}
+{% block dataset_content %}
+  <div class="col-md-12">
+    <div id="wave-container">
+      <img id="loading-wave" src={{ url_for('static', filename='img/spinner.gif')}} />
+    </div>
+    <div id="wave-controls" class="col-md-12">
+      <h3>Controls</h3>
+      <div class="wave-control">
+        <p>Gray Value Threshold</p>
+        <div class="col-sm-12">
+          <div class="col-sm-2"><input type="text" class="slider-range-input pull-right" id="gray-threshold-min-input" /></div>
+          <div class="col-sm-8" id="slider-gray-threshold"></div>
+          <div class="col-sm-2"><input type="text" class="slider-range-input" id="gray-threshold-max-input" /></div>
+        </div>
+      </div>
+      <div class="wave-control">
+        <p>X axis slicing</p>
+        <div class="col-sm-12">
+          <div class="col-sm-2"><input type="text" class="slider-range-input pull-right" id="x-min-input" /></div>
+          <div class="col-sm-8" id="slider-X"></div>
+          <div class="col-sm-2"><input type="text" class="slider-range-input" id="x-max-input" /></div>
+        </div>
+      </div>
+      <div class="wave-control">
+        <p>Y axis slicing</p>
+        <div class="col-sm-12">
+          <div class="col-sm-2"><input type="text" class="slider-range-input pull-right" id="y-min-input" /></div>
+          <div class="col-sm-8" id="slider-Y"></div>
+          <div class="col-sm-2"><input type="text" class="slider-range-input" id="y-max-input" /></div>
+        </div>
+      </div>
+      <div class="wave-control">
+        <p>Z axis slicing</p>
+        <div class="col-sm-12">
+          <div class="col-sm-2"><input type="text" class="slider-range-input pull-right" id="z-min-input" /></div>
+          <div class="col-sm-8" id="slider-Z"></div>
+          <div class="col-sm-2"><input type="text" class="slider-range-input" id="z-max-input" /></div>
+        </div>
+      </div>
+    </div>
+  </div>
+  <script
+  src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
+  integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
+  crossorigin="anonymous"></script>
+  <script src="{{ url_for('static', filename='js/wave/three.min.js') }}"></script>
+  <script src="{{ url_for('static', filename='js/wave/TrackballControls.js') }}"></script>
+  <script src="{{ url_for('static', filename='js/wave/ejs.js') }}"></script>
+  <script src="{{ url_for('static', filename='js/wave/volumeRaycaster.js') }}"></script>
+  <script src="{{ url_for('static', filename='js/wave/stats.min.js') }}"></script>
+  <script>
+        var collection_name = '{{ collection }}';
+        var dataset_name = '{{ dataset.name }}';
+        var user_name = '{{ owner.name }}';
+        var is_wave = true;
         function beginWave(slicemaps) {
             config = {
-                "dom_container": "container",
+                "dom_container": "wave-container",
                 "slicemaps_paths": slicemaps,
                 "steps" : 144,
                 "shader_name": "secondPassSoebel",
                 "slices_range": [0, 255],
                 "row_col": [16, 16],
-                "renderer_size": [256, 256],
+                "renderer_size": [512, 512],
                 "renderer_canvas_size": ['*','*'],
             };
 
@@ -43,25 +80,132 @@
                 } else {
                     $location = jqXHR.getResponseHeader('location');
                     slicemaps = [$location];
+                    $( "#loading-wave" ).remove();
                     beginWave(slicemaps)
                 }
             });
         }
         $( document ).ready(function() {
+            $("#wave-container").height($("#wave-container").width());
             $params = JSON.stringify({
                 "token": "{{token|safe}}",
-                "user": "{{owner}}",
-                "dataset": "{{dataset}}"
+                "user": user_name,
+                "dataset": dataset_name
             });
             $.ajax("http://localhost:5001/maps", {
-                data:$params, 
-                contentType:"application/json", 
-                method:"POST", crossDomain:true, 
+                data:$params,
+                contentType:"application/json",
+                method:"POST"
             }).done(function(data, textStatus, jqXHR){
                 $location = jqXHR.getResponseHeader('location');
                 sendContinuousGetToLocationUntilDone($location)
             }).fail(function() { alert( "An error occured" ); });
+            $("#slider-gray-threshold").slider ({
+                range: true,
+                min: 0,
+                max: 255,
+                values: [0, 255],
+                slide: function( event, ui ) {
+                    $min = ui.values[0];
+                    $max = ui.values[1];
+                    rcl2.setGrayMinValue($min/255);
+                    $("#gray-threshold-min-input").val($min);
+                    rcl2.setGrayMaxValue($max/255);
+                    $("#gray-threshold-max-input").val($max);
+                }
+            });
+            $("#slider-X").slider ({
+                range: true,
+                min: 0,
+                max: 100,
+                values: [0, 100],
+                slide: function( event, ui ) {
+                    $min = ui.values[0];
+                    $max = ui.values[1];
+                    rcl2.setGeometryMinX($min/100);
+                    $("#x-min-input").val($min);
+                    rcl2.setGeometryMaxX($max/100);
+                    $("#x-max-input").val($max);
+                }
+            });
+            $("#slider-Y").slider ({
+                range: true,
+                min: 0,
+                max: 100,
+                values: [0, 100],
+                slide: function( event, ui ) {
+                    $min = ui.values[0];
+                    $max = ui.values[1];
+                    rcl2.setGeometryMinY($min/100);
+                    $("#y-min-input").val($min);
+                    rcl2.setGeometryMaxY($max/100);
+                    $("#y-max-input").val($max);
+                }
+            });
+            $("#slider-Z").slider ({
+                range: true,
+                min: 0,
+                max: 100,
+                values: [0, 100],
+                slide: function( event, ui ) {
+                    $min = ui.values[0];
+                    $max = ui.values[1];
+                    rcl2.setGeometryMinZ($min/100);
+                    $("#z-min-input").val($min);
+                    rcl2.setGeometryMaxZ($max/100);
+                    $("#z-max-input").val($max);
+                }
+            });
+            $("#gray-threshold-min-input").val(0);
+            $("#gray-threshold-max-input").val(255);
+            $("#x-min-input").val(0);
+            $("#x-max-input").val(100);
+            $("#y-min-input").val(0);
+            $("#y-max-input").val(100);
+            $("#z-min-input").val(0);
+            $("#z-max-input").val(100);
+            $("#gray-threshold-min-input").change(function() {
+                $values = [$(this).val(), $("#slider-gray-threshold" ).slider("option", "values")[1]];
+                $("#slider-gray-threshold").slider("option", "values", $values);
+                rcl2.setGrayMinValue($(this).val()/255);
+            });
+            $("#gray-threshold-max-input").change(function() {
+                $values = [$("#slider-gray-threshold" ).slider("option", "values")[0], $(this).val()];
+                $("#slider-gray-threshold").slider("option", "values", $values);
+                rcl2.setGrayMaxValue($(this).val()/255);
+            });
+            $("#x-min-input").change(function() {
+                $values = [$(this).val(), $("#slider-X" ).slider("option", "values")[1]];
+                $("#slider-X").slider("option", "values", $values);
+                rcl2.setGeometryMinX($(this).val()/100);
+            });
+            $("#x-max-input").change(function() {
+                $values = [$("#slider-X" ).slider("option", "values")[0], $(this).val()];
+                $("#slider-X").slider("option", "values", $values);
+                rcl2.setGeometryMaxX($(this).val()/100);
+            });
+            $("#y-min-input").change(function() {
+                $values = [$(this).val(), $("#slider-Y" ).slider("option", "values")[1]];
+                $("#slider-Y").slider("option", "values", $values);
+                rcl2.setGeometryMinY($(this).val()/100);
+            });
+            $("#y-max-input").change(function() {
+                $values = [$("#slider-Y" ).slider("option", "values")[0], $(this).val()];
+                $("#slider-Y").slider("option", "values", $values);
+                rcl2.setGeometryMaxY($(this).val()/100);
+            });
+            $("#z-min-input").change(function() {
+                $values = [$(this).val(), $("#slider-Z" ).slider("option", "values")[1]];
+                $("#slider-Z").slider("option", "values", $values);
+                rcl2.setGeometryMinZ($(this).val()/100);
+            });
+            $("#z-max-input").change(function() {
+                $values = [$("#slider-Z" ).slider("option", "values")[0], $(this).val()];
+                $("#slider-Z").slider("option", "values", $values);
+                rcl2.setGeometryMaxZ($(this).val()/100);
+            });
          });
-    </script>
-</body>
-</html>
+  </script>
+  <script>System.import('dataset.js')</script>
+  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+{% endblock %}

+ 32 - 1
nova/views.py

@@ -561,4 +561,35 @@ def wave_it():
     token = current_user.token
     owner = request.args['user']
     dataset_name = request.args['dataset']
-    return render_template('dataset/wave.html', owner=owner, dataset=dataset_name, token=token) 
+    collection_name = request.args['collection']
+
+    user = User.query.filter(User.name == owner).first()
+    dataset = Dataset.query.join(Permission).filter(Dataset.name == dataset_name).\
+            filter(Permission.owner == user).first()
+    if dataset is None:
+        abort(404, 'dataset {} not found'.format(dataset))
+    dataset_permissions = {}
+    name = None
+    permission = Permission.query.filter(Permission.dataset == dataset).first()
+    if permission:
+        if permission.can_read == True or permission.owner==current_user:
+            dataset_permissions = {'read': permission.can_read,
+                           'interact': permission.can_interact,
+                           'fork': permission.can_fork}
+    if dataset_permissions == {}:
+        direct_access = DirectAccess.query.\
+                      filter(DirectAccess.dataset == dataset).\
+                      filter(DirectAccess.user == current_user).\
+                      filter(DirectAccess.can_read == True).first()
+        if direct_access is None:
+            return render_template('base/accessrequest.html', access_name='read',
+                                   user=user, dataset=dataset,
+                                   collection=dataset.collection,
+                                   item={'type':'dataset', 'name':dataset,
+                                         'description':dataset.description,
+                                         'id':dataset.id,})
+        dataset_permissions = {'read': direct_access.can_read,
+                               'interact': direct_access.can_interact,
+                               'fork': direct_access.can_fork}
+    return render_template('dataset/wave.html', owner=user, dataset=dataset,
+                           collection=collection_name, token=token)