playground:test_3js

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revisionBoth sides next revision
playground:test_3js [2020/08/19 17:59] hnagelplayground:test_3js [2020/08/20 08:46] hnagel
Line 3: Line 3:
 </code> </code>
 <HTML> <HTML>
-<div class="threejs_output"><!--+<!--
 polymake for knusper polymake for knusper
-Wed Aug 19 21:27:01 2020+Thu Aug 20 12:35:04 2020
 unnamed unnamed
 --> -->
Line 25: Line 25:
          .group{padding-bottom: 15px;}          .group{padding-bottom: 15px;}
          .settings * {z-index: 11; }          .settings * {z-index: 11; }
-         .settings{z-index: 10; font-family: Arial, Helvetica, sans-serif; margin-left: 30px; visibility: hidden; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white; position: absolute }+         .settings{z-index: 10; font-family: Arial, Helvetica, sans-serif; margin-left: 30px; visibility: hidden; width: 14em; height: 96%; border: solid 1px silver; padding: 2px; overflow-y: scroll; box-sizing: border-box; background-color: white; position: absolute;}
          .indented{margin-left: 20px; margin-top: 10px; padding-bottom: 0px;}           .indented{margin-left: 20px; margin-top: 10px; padding-bottom: 0px;} 
          .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;}          .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;}
          .showSettingsButton{visibility: visible; z-index: 12; position: absolute }          .showSettingsButton{visibility: visible; z-index: 12; position: absolute }
          .hideSettingsButton{visibility: hidden; z-index: 12; position: absolute; opacity: 0.5}          .hideSettingsButton{visibility: hidden; z-index: 12; position: absolute; opacity: 0.5}
-         .resetButton{margin-top10px;+         button{margin-left0; margin-top10px}
-         button{margin-left0;}+
          img{cursor: pointer;}          img{cursor: pointer;}
          .suboption{padding-top: 15px;}          .suboption{padding-top: 15px;}
-         #model95738212468 positionrelative width: 100%; height: 70vh; }+         #model76216027194 width100%height: 100%; } 
 +         .threejs_container { width: 100%; height: 75vhmax-height: 75vh} 
 +         .settings{max-height: inherit
          input[type=range] {          input[type=range] {
            -webkit-appearance: none;            -webkit-appearance: none;
Line 130: Line 131:
    </head>    </head>
 <body> <body>
 +   <div class='threejs_container'>
  <div id='settings_0' class='settings'>  <div id='settings_0' class='settings'>
  <div class=group id='transparency_0' class='transparency'>  <div class=group id='transparency_0' class='transparency'>
Line 143: Line 144:
  <div><input type='checkbox' id='changeRotationY_0'> y-axis</div>  <div><input type='checkbox' id='changeRotationY_0'> y-axis</div>
  <div><input type='checkbox' id='changeRotationZ_0'> z-axis</div>  <div><input type='checkbox' id='changeRotationZ_0'> z-axis</div>
- <button id='resetButton_0' class='resetButton' >Reset</button>+ <button id='resetButton_0'>Reset</button>
  </div>  </div>
  
Line 155: Line 156:
  <strong>Display</strong>  <strong>Display</strong>
  <div class=indented>  <div class=indented>
- <div><input type='checkbox' id='labelsCheckboxInput_0checked>Labels</div> + <div id='shownObjectTypesList_0class='shownObjectsList'></div>
- <div><input type='checkbox' id='pointsCheckboxInput_0' checked>Points</div> +
- <div><input type='checkbox' id='edgesCheckboxInput_0' checked>Edges</div> +
- <div><input type='checkbox' id='facesCheckboxInput_0' checked>Faces</div> +
- <div><input type='checkbox' id='arrowheadsCheckboxInput_0checked>Arrowheads</div>+
  </div>  </div>
  <div class=suboption>Objects</div>  <div class=suboption>Objects</div>
Line 182: Line 179:
  <img id='hideSettingsButton_0' class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px">  <img id='hideSettingsButton_0' class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px">
  <img id='showSettingsButton_0' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px">  <img id='showSettingsButton_0' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px">
-   <div id="model95738212468"></div>+<div id="model76216027194"></div> 
 +</div>
    <script>    <script>
     requirejs.config({     requirejs.config({
Line 190: Line 188:
         Projector: '/kernelspecs/polymake/Projector',         Projector: '/kernelspecs/polymake/Projector',
         SVGRenderer: '/kernelspecs/polymake/SVGRenderer',         SVGRenderer: '/kernelspecs/polymake/SVGRenderer',
-        WEBGL: '/kernelspecs/polymake/WebGL', 
       },       },
       shim: {       shim: {
         'three': { exports: 'THREE'},         'three': { exports: 'THREE'},
         'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' },         'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' },
-        'WEBGL': { deps: [ 'three' ], exports: 'THREE.WEBGL' }, 
         'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' },         'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' },
         'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' }         'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' }
Line 203: Line 199:
     require(['three'],function(THREE){     require(['three'],function(THREE){
         window.THREE = THREE;         window.THREE = THREE;
-      require(['TrackballControls','Projector','SVGRenderer','WEBGL'],function(TrackballControls,Projector,SVGRenderer,WEBGL) {+      require(['TrackballControls','Projector','SVGRenderer'],function(TrackballControls,Projector,SVGRenderer) {
     THREE.TrackballControls = TrackballControls;     THREE.TrackballControls = TrackballControls;
     THREE.Projector = Projector;     THREE.Projector = Projector;
     THREE.SVGRenderer = SVGRenderer;     THREE.SVGRenderer = SVGRenderer;
-    THREE.WEBGL = WEBGL;+ 
 +// COMMON_CODE_BLOCK_BEGIN
  
 const intervalLength = 25; // for automatic animations const intervalLength = 25; // for automatic animations
 const explodableModel = false;  const explodableModel = false; 
-var foldables = []; +const modelContains = { points: false, pointlabels: false, lines: false, edgelabels: false, faces: false, arrowheads: false }; 
-var three = document.getElementById("model95738212468");+const foldables = []; 
 + 
 +var three = document.getElementById("model76216027194");
 var scene = new THREE.Scene(); var scene = new THREE.Scene();
  
Line 274: Line 273:
 }; };
 // select the target node // select the target node
-var target = document.querySelector('#model95738212468');+var target = document.querySelector('#model76216027194');
  
 // create an observer instance // create an observer instance
Line 320: Line 319:
 obj0.userData.edgeindices = [0, 1, 0, 2, 1, 3, 2, 3, 0, 4, 1, 5, 4, 5, 2, 6, 4, 6, 3, 7, 5, 7, 6, 7]; obj0.userData.edgeindices = [0, 1, 0, 2, 1, 3, 2, 3, 0, 4, 1, 5, 4, 5, 2, 6, 4, 6, 3, 7, 5, 7, 6, 7];
    <!-- Edge style -->    <!-- Edge style -->
-obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, depthTest: true, transparent: false, linewidth: 1.5 } );+obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, depthTest: true, linewidth: 1.5, transparent: false } );
 obj0.userData.facets = [[0, 4, 6, 2], [7, 5, 1, 3], [5, 4, 0, 1], [2, 6, 7, 3], [0, 2, 3, 1], [6, 4, 5, 7]]; obj0.userData.facets = [[0, 4, 6, 2], [7, 5, 1, 3], [5, 4, 0, 1], [2, 6, 7, 3], [0, 2, 3, 1], [6, 4, 5, 7]];
    <!-- Facet style -->    <!-- Facet style -->
-obj0.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, side: THREE.DoubleSide, depthFunc: THREE.LessDepth, polygonOffsetFactor: 1, polygonOffset: true, depthWritetruetransparent: true, opacity: 1, polygonOffsetUnits: 1 } ); +obj0.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, depthWrite: true, opacity1polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 1, side: THREE.DoubleSide, transparent: true } ); 
-init_object(obj0);+//init_object(obj0);
 scene.add(obj0); scene.add(obj0);
 // COMMON_CODE_BLOCK_BEGIN // COMMON_CODE_BLOCK_BEGIN
Line 368: Line 367:
  
 function init_object(obj) { function init_object(obj) {
-   if (obj.userData.hasOwnProperty("pointmaterial")) { +    if (obj.userData.hasOwnProperty("pointmaterial")) { 
-      init_points(obj); +        init_points(obj); 
-   +        modelContains.points = true; 
-   if (obj.userData.hasOwnProperty("pointlabels")) { +    
-      init_pointlabels(obj); +    if (obj.userData.hasOwnProperty("pointlabels")) { 
-   +        init_pointlabels(obj); 
-   if (obj.userData.hasOwnProperty("edgematerial")) { +        modelContains.pointlabels = true; 
-      init_lines(obj); +    
-   +    if (obj.userData.hasOwnProperty("edgematerial")) { 
-   if (obj.userData.hasOwnProperty("edgelabels")) { +        init_lines(obj); 
-      init_edgelabels(obj); +        modelContains.lines = true; 
-   +    
-   if (obj.userData.hasOwnProperty("arrowstyle")) { +    if (obj.userData.hasOwnProperty("edgelabels")) { 
-      init_arrowheads(obj); +        init_edgelabels(obj); 
-   +        modelContains.edgelabels = true; 
-   if (obj.userData.hasOwnProperty("facetmaterial")) { +    
-      init_faces(obj); +    if (obj.userData.hasOwnProperty("arrowstyle")) { 
-   }+        init_arrowheads(obj); 
 +        modelContains.arrowheads = true; 
 +    
 +    if (obj.userData.hasOwnProperty("facetmaterial")) { 
 +        init_faces(obj); 
 +        modelContains.faces = true; 
 +    }
 } }
  
Line 586: Line 591:
  
  
-// ------------------------ FOLDING ------------------------------------------------ 
-// --------------------------------------------------------------------------------- 
-// rotate point p around axis defined by points p1 and p2 by given angle 
-function rotate(p, p1, p2, angle ){    
-   angle = -angle; 
-   var x = p.x, y = p.y, z = p.z,  
-   a = p1.x, b = p1.y, c = p1.z,  
-   u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z; 
-   var result = []; 
-   var L = u*u + v*v + w*w; 
-   var sqrt = Math.sqrt; 
-   var cos = Math.cos; 
-   var sin = Math.sin; 
- 
-   result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/L; 
-   result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/L; 
-   result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/L; 
- 
-   return result; 
-} 
- 
-var fold = function(event){ 
-    var obj = foldables[Number(event.currentTarget.name)]; 
-    var foldvalue = Number(event.currentTarget.value); 
-    var scale = foldvalue - obj.userData.oldscale; 
- 
-    for (var j=0; j<obj.userData.axes.length; j++) { 
-        rotateVertices(obj, j, scale); 
-    } 
-    update(obj); 
-    obj.userData.oldscale += scale; 
-    lookAtBarycenter(obj); 
-} 
- 
-function lookAtBarycenter(obj){ 
-    control.target = barycenter(obj); 
-} 
- 
-function barycenter(obj) { 
-   var center = new THREE.Vector3(0,0,0); 
-   var points = obj.userData.points; 
-   for (var i=0; i<points.length; i++){ 
-      center.add(points[i].vector); 
-   } 
-   center.divideScalar(points.length); 
-   return center; 
-} 
- 
-function rotateVertices(obj, edge, scale) { 
-   var axes = obj.userData.axes; 
-   var subtrees = obj.userData.subtrees; 
-   var points = obj.userData.points; 
-   var angles = obj.userData.angles; 
-   if (edge < axes.length){ 
-      for (var j=0; j<subtrees[edge].length; j++){ 
-         var rotP = rotate(points[subtrees[edge][j]].vector, points[axes[edge][0]].vector,points[axes[edge][1]].vector, scale * (Math.PI - angles[edge])); 
-         points[subtrees[edge][j]].set(rotP[0],rotP[1],rotP[2]); 
-      } 
-   } 
-} 
- 
-function update(obj) { 
-   updateFacesPosition(obj); 
-   updateEdgesPosition(obj); 
-} 
- 
-if (foldables.length) { 
-    var settings = document.getElementById('settings_0'); 
-    var foldDiv = document.createElement('div'); 
-    foldDiv.id = 'fold_0'; 
-    var title = document.createElement('strong'); 
-    title.innerHTML = 'Fold'; 
-    foldDiv.appendChild(title); 
-    foldDiv.className = 'group'; 
-    for (var i=0; i<foldables.length; i++) { 
-        var range = document.createElement('input'); 
-        range.type = 'range'; 
-        range.min = 0; 
-        range.max = 1; 
-        range.value = 0; 
-        range.step = 0.001; 
-        range.name = String(i); 
-        range.oninput = fold; 
-        foldDiv.appendChild(range); 
-    } 
-    lookAtBarycenter(foldables[0]); 
-    settings.insertBefore(foldDiv,settings.childNodes[0]); 
-} 
  
 var xRotationEnabled = false; var xRotationEnabled = false;
Line 712: Line 629:
 }; };
  
 +render();
          
-render(); 
- 
-if (explodableModel) { 
-    for (var i=0; i<scene.children.length; i++) { 
-        obj = scene.children[i]; 
-        if ( obj.userData.explodable ) { 
-            computeCentroid(obj); 
-        } 
-    } 
-} 
-function computeCentroid(obj) { 
-    centroid = new THREE.Vector3(); 
-    obj.userData.points.forEach(function(pmpoint) { 
-        centroid.add(pmpoint.vector);  
-    }); 
-    centroid.divideScalar(obj.userData.points.length); 
-    obj.userData.centroid = centroid; 
-} 
- 
 function changeTransparency() { function changeTransparency() {
     var opacity = 1-Number(event.currentTarget.value);     var opacity = 1-Number(event.currentTarget.value);
Line 794: Line 692:
     return Math.sin(.01*pos)+1;     return Math.sin(.01*pos)+1;
 } }
- 
-function takeSvgScreenshot(){ 
-    var labelsShown = document.getElementById('labelsCheckboxInput_0').checked; 
-    if (labelsShown){ 
-        setVisibility(false,"pointlabels"); 
-        setVisibility(false,"edgelabels"); 
-    } 
-    svgRenderer.render(scene,camera); 
-    svgElement = XMLS.serializeToString(svgRenderer.domElement); 
-     
-    if (labelsShown){ 
-        setVisibility(true,"pointlabels"); 
-        setVisibility(true,"edgelabels"); 
-    } 
- 
-    if (document.getElementById('tab_0').checked){ 
-        //show in new tab 
-        var myWindow = window.open("",""); 
-        myWindow.document.body.innerHTML = svgElement; 
-    } else{ 
-        // download svg file  
-        download("screenshot.svg", svgElement); 
-    } 
-} 
-     
-// ---------------------- EXPLOSION ------------------------------------------------ 
-// --------------------------------------------------------------------------------- 
- 
-function explode(factor) { 
-    for (var i=0; i<scene.children.length; i++) { 
-        var obj = scene.children[i]; 
-        if (obj.userData.hasOwnProperty("centroid")) {  
-            var c = obj.userData.centroid; 
-            obj.position.set(c.x*factor, c.y*factor, c.z*factor); 
-        } 
-    }  
-} 
- 
-function triggerExplode(event){ 
-    explodeScale = Number(event.currentTarget.value); 
-    explode(explodeScale); 
-} 
- 
-function setExplodingSpeed(event){ 
-    explodingSpeed = Number(event.currentTarget.value); 
-} 
- 
-function triggerAutomaticExplode(event){ 
-    if (event.currentTarget.checked){ 
-        startExploding(); 
-    } else { 
-        clearIntervals(); 
-    }  
-} 
- 
-function startExploding(){ 
-    intervals.push(setInterval(explodingInterval, 25)); 
-} 
- 
- 
-function explodingInterval(){ 
-    explodeScale += explodingSpeed; 
-    if (explodeScale <= 6){  
-        explode(explodeScale); 
-    } 
-    else{ 
-        explode(6); 
-        explodeScale = 6; 
-        clearIntervals(); 
-        timeouts.push(setTimeout(startUnexploding, 3000)); 
-    } 
-    document.getElementById('explodeRange_0').value = explodeScale; 
-} 
- 
- 
-function startUnexploding(){ 
-    intervals.push(setInterval(unexplodingInterval, 25)); 
-} 
- 
-function unexplodingInterval(){ 
-    explodeScale -= explodingSpeed; 
-    if (explodeScale >= 0){  
-        explode(explodeScale); 
-    } 
-    else { 
-        explode(0); 
-        explodeScale = 0; 
-        clearIntervals(); 
-        timeouts.push(setTimeout(startExploding, 3000)); 
-    } 
-    document.getElementById('explodeRange_0').value = explodeScale; 
-} 
- 
-function clearIntervals(){ 
-    intervals.forEach(function(interval){ 
-        clearInterval(interval); 
-    }); 
-    intervals = []; 
-    timeouts.forEach(function(timeout){ 
-        clearTimeout(timeout); 
-    }); 
-    timeouts = []; 
-} 
- 
-function showOrHideObject(event){ 
-    var nr = Number(event.currentTarget.name); 
-    scene.children[nr].visible = event.currentTarget.checked; 
-} 
-     
- 
-// append checkboxes for displaying or hiding objects 
-var shownObjectsList = document.getElementById('shownObjectsList_0'); 
-for (var i=0; i<scene.children.length; i++){ 
-    obj = scene.children[i]; 
-    var objNode = document.createElement('span'); 
-    objNode.innerHTML = obj.name + '<br>'; 
-    var checkbox = document.createElement('input'); 
-    checkbox.type = 'checkbox'; 
-    checkbox.checked = true; 
-    checkbox.name = String(i); 
-    checkbox.onchange = showOrHideObject; 
-    shownObjectsList.appendChild(checkbox); 
-    shownObjectsList.appendChild(objNode); 
-} 
- 
-function setVisibility(bool,objname) { 
-    for (var i=0; i<scene.children.length; i++){ 
-        var obj = scene.children[i].getObjectByName(objname); 
-        if (obj) { 
-            obj.visible = bool; 
-        } 
-    } 
-} 
- 
-function toggleLabels(event) { 
-    setVisibility(event.currentTarget.checked,"pointlabels"); 
-    setVisibility(event.currentTarget.checked,"edgelabels"); 
-} 
- 
-function toggleFaces(event) { 
-    setVisibility(event.currentTarget.checked,"faces"); 
-} 
- 
-function toggleEdges(event) { 
-    setVisibility(event.currentTarget.checked,"lines"); 
-} 
- 
-function togglePoints(event) { 
-    setVisibility(event.currentTarget.checked,"points"); 
-} 
- 
-function toggleArrowheads(event) { 
-    setVisibility(event.currentTarget.checked,"arrowheads"); 
-} 
- 
-document.getElementById('labelsCheckboxInput_0').onchange = toggleLabels; 
-document.getElementById('pointsCheckboxInput_0').onchange = togglePoints; 
-document.getElementById('facesCheckboxInput_0').onchange = toggleFaces; 
-document.getElementById('edgesCheckboxInput_0').onchange = toggleEdges; 
-document.getElementById('arrowheadsCheckboxInput_0').onchange = toggleArrowheads; 
- 
- 
- 
-function download(filename, text) { 
-  var element = document.createElement('a'); 
-  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); 
-  element.setAttribute('download', filename); 
- 
-  element.style.display = 'none'; 
-  document.body.appendChild(element); 
- 
-  element.click(); 
- 
-  document.body.removeChild(element); 
-} 
- 
-var tempobj; 
-tempobj = document.getElementById('explodeRange_0'); 
-if (tempobj) { 
-   tempobj.oninput = triggerExplode; 
-   document.getElementById('explodeCheckbox_0').onchange = triggerAutomaticExplode; 
-   document.getElementById('explodingSpeedRange_0').oninput = setExplodingSpeed; 
-} 
-tempobj = document.getElementById('foldRange_0'); 
-if (tempobj) { 
-   tempobj.oninput = fold; 
-} 
-document.getElementById('transparencyRange_0').oninput = changeTransparency; 
-document.getElementById('changeRotationX_0').onchange = changeRotationX; 
-document.getElementById('changeRotationY_0').onchange = changeRotationY; 
-document.getElementById('changeRotationZ_0').onchange = changeRotationZ; 
-document.getElementById('resetButton_0').onclick = resetScene; 
-document.getElementById('rotationSpeedRange_0').oninput = changeRotationSpeedFactor; 
-document.getElementById('takeScreenshot_0').onclick = takeSvgScreenshot; 
-document.getElementById('showSettingsButton_0').onclick = showSettings; 
-document.getElementById('hideSettingsButton_0').onclick = hideSettings; 
- 
-  
- 
-// ------------------ SHORTCUTS -------------------------------------------- 
-// ------------------------------------------------------------------------- 
- 
-/** 
- * http://www.openjs.com/scripts/events/keyboard_shortcuts/ 
- * Version : 2.01.B 
- * By Binny V A 
- * License : BSD 
- */ 
-shortcut = { 
- 'all_shortcuts':{},//All the shortcuts are stored in this array 
- 'add': function(shortcut_combination,callback,opt) { 
- //Provide a set of default options 
- var default_options = { 
- 'type':'keydown', 
- 'propagate':false, 
- 'disable_in_input':false, 
- 'target':document, 
- 'keycode':false 
- } 
- if(!opt) opt = default_options; 
- else { 
- for(var dfo in default_options) { 
- if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo]; 
- } 
- } 
- 
- var ele = opt.target; 
- if(typeof opt.target == 'string') ele = document.getElementById(opt.target); 
- var ths = this; 
- shortcut_combination = shortcut_combination.toLowerCase(); 
- 
- //The function to be called at keypress 
- var func = function(e) { 
- e = e || window.event; 
-  
- if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields 
- var element; 
- if(e.target) element=e.target; 
- else if(e.srcElement) element=e.srcElement; 
- if(element.nodeType==3) element=element.parentNode; 
- 
- if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return; 
- } 
-  
- //Find Which key is pressed 
- if (e.keyCode) code = e.keyCode; 
- else if (e.which) code = e.which; 
- var character = String.fromCharCode(code).toLowerCase(); 
-  
- if(code == 188) character=","; //If the user presses , when the type is onkeydown 
- if(code == 190) character="."; //If the user presses , when the type is onkeydown 
- 
- var keys = shortcut_combination.split("+"); 
- //Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked 
- var kp = 0; 
-  
- //Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken 
- var shift_nums = { 
- "`":"~", 
- "1":"!", 
- "2":"@", 
- "3":"#", 
- "4":"$", 
- "5":"%", 
- "6":"^", 
- "7":"&", 
- "8":"*", 
- "9":"(", 
- "0":")", 
- "-":"_", 
- "=":"+", 
- ";":":", 
- "'":"\"", 
- ",":"<", 
- ".":">", 
- "/":"?", 
- "\\":"|" 
- } 
- //Special Keys - and their codes 
- var special_keys = { 
- 'esc':27, 
- 'escape':27, 
- 'tab':9, 
- 'space':32, 
- 'return':13, 
- 'enter':13, 
- 'backspace':8, 
-  
- 'scrolllock':145, 
- 'scroll_lock':145, 
- 'scroll':145, 
- 'capslock':20, 
- 'caps_lock':20, 
- 'caps':20, 
- 'numlock':144, 
- 'num_lock':144, 
- 'num':144, 
-  
- 'pause':19, 
- 'break':19, 
-  
- 'insert':45, 
- 'home':36, 
- 'delete':46, 
- 'end':35, 
-  
- 'pageup':33, 
- 'page_up':33, 
- 'pu':33, 
-  
- 'pagedown':34, 
- 'page_down':34, 
- 'pd':34, 
-  
- 'left':37, 
- 'up':38, 
- 'right':39, 
- 'down':40, 
-  
- 'f1':112, 
- 'f2':113, 
- 'f3':114, 
- 'f4':115, 
- 'f5':116, 
- 'f6':117, 
- 'f7':118, 
- 'f8':119, 
- 'f9':120, 
- 'f10':121, 
- 'f11':122, 
- 'f12':123 
- } 
-  
- var modifiers = {  
- shift: { wanted:false, pressed:false}, 
- ctrl : { wanted:false, pressed:false}, 
- alt  : { wanted:false, pressed:false}, 
- meta : { wanted:false, pressed:false} //Meta is Mac specific 
- }; 
-                         
- if(e.ctrlKey) modifiers.ctrl.pressed = true; 
- if(e.shiftKey) modifiers.shift.pressed = true; 
- if(e.altKey) modifiers.alt.pressed = true; 
- if(e.metaKey)   modifiers.meta.pressed = true; 
-                         
- for(var i=0; k=keys[i],i<keys.length; i++) { 
- //Modifiers 
- if(k == 'ctrl' || k == 'control') { 
- kp++; 
- modifiers.ctrl.wanted = true; 
- 
- } else if(k == 'shift') { 
- kp++; 
- modifiers.shift.wanted = true; 
- 
- } else if(k == 'alt') { 
- kp++; 
- modifiers.alt.wanted = true; 
- } else if(k == 'meta') { 
- kp++; 
- modifiers.meta.wanted = true; 
- } else if(k.length > 1) { //If it is a special key 
- if(special_keys[k] == code) kp++; 
-  
- } else if(opt['keycode']) { 
- if(opt['keycode'] == code) kp++; 
- 
- } else { //The special keys did not match 
- if(character == k) kp++; 
- else { 
- if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase 
- character = shift_nums[character];  
- if(character == k) kp++; 
- } 
- } 
- } 
- } 
-  
- if(kp == keys.length &&  
- modifiers.ctrl.pressed == modifiers.ctrl.wanted && 
- modifiers.shift.pressed == modifiers.shift.wanted && 
- modifiers.alt.pressed == modifiers.alt.wanted && 
- modifiers.meta.pressed == modifiers.meta.wanted) { 
- callback(e); 
-  
- if(!opt['propagate']) { //Stop the event 
- //e.cancelBubble is supported by IE - this will kill the bubbling process. 
- e.cancelBubble = true; 
- e.returnValue = false; 
-  
- //e.stopPropagation works in Firefox. 
- if (e.stopPropagation) { 
- e.stopPropagation(); 
- e.preventDefault(); 
- } 
- return false; 
- } 
- } 
- } 
- this.all_shortcuts[shortcut_combination] = { 
- 'callback':func,  
- 'target':ele,  
- 'event': opt['type'] 
- }; 
- //Attach the function with the event 
- if(ele.addEventListener) ele.addEventListener(opt['type'], func, false); 
- else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func); 
- else ele['on'+opt['type']] = func; 
- }, 
- 
- //Remove the shortcut - just specify the shortcut and I will remove the binding 
- 'remove':function(shortcut_combination) { 
- shortcut_combination = shortcut_combination.toLowerCase(); 
- var binding = this.all_shortcuts[shortcut_combination]; 
- delete(this.all_shortcuts[shortcut_combination]) 
- if(!binding) return; 
- var type = binding['event']; 
- var ele = binding['target']; 
- var callback = binding['callback']; 
- 
- if(ele.detachEvent) ele.detachEvent('on'+type, callback); 
- else if(ele.removeEventListener) ele.removeEventListener(type, callback, false); 
- else ele['on'+type] = false; 
- } 
-} 
- 
-shortcut.add("Alt+Left",function() { 
- var event = new Event('click'); 
- if (settingsShown){ 
- document.getElementById('hideSettingsButton_0').dispatchEvent(event); 
- } else{ 
- document.getElementById('showSettingsButton_0').dispatchEvent(event); 
- } 
-}); 
- 
- 
-// COMMON_CODE_BLOCK_END 
- 
-});}); 
-      </script> 
-   </body> 
-</html> 
-</div> 
-</HTML> 
-<code perl> 
-> fan::planar_net(cube(3))->VISUAL; 
-</code> 
-<HTML> 
-<div class="threejs_output"><!-- 
-polymake for knusper 
-Wed Aug 19 21:27:01 2020 
-planar_net_ 
---> 
- 
- 
-<html> 
-   <head> 
-      <meta charset=utf-8> 
-      <title>planar_net_</title> 
-      <style> 
-/* 
-// COMMON_CODE_BLOCK_BEGIN 
-*/ 
-         html {overflow: scroll;} 
-         strong{font-size: 18px;} 
-         canvas { z-index: 8; } 
-         input[type='radio'] {margin-left:0;} 
-         input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} 
-         .group{padding-bottom: 15px;} 
-         .settings * {z-index: 11; } 
-         .settings{z-index: 10; font-family: Arial, Helvetica, sans-serif; margin-left: 30px; visibility: hidden; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white; position: absolute } 
-         .indented{margin-left: 20px; margin-top: 10px; padding-bottom: 0px;}  
-         .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} 
-         .showSettingsButton{visibility: visible; z-index: 12; position: absolute } 
-         .hideSettingsButton{visibility: hidden; z-index: 12; position: absolute; opacity: 0.5} 
-         .resetButton{margin-top: 10px;} 
-         button{margin-left: 0;} 
-         img{cursor: pointer;} 
-         .suboption{padding-top: 15px;} 
-         #model89920187284 { position: relative;  width: 100%; height: 70vh; } 
-         input[type=range] { 
-           -webkit-appearance: none; 
-           padding:0;  
-           width:90%;  
-           margin-left: auto; 
-           margin-right: auto; 
-           margin-top: 15px; 
-           margin-bottom: 15px; 
-           display: block;  
-         } 
-         input[type=range]:focus { 
-           outline: none; 
-         } 
-         input[type=range]::-webkit-slider-runnable-track { 
-           height: 4px; 
-           cursor: pointer; 
-           animate: 0.2s; 
-           box-shadow: 0px 0px 0px #000000; 
-           background: #E3E3E3; 
-           border-radius: 0px; 
-           border: 0px solid #000000; 
-         } 
-         input[type=range]::-webkit-slider-thumb { 
-           box-shadow: 1px 1px 2px #B8B8B8; 
-           border: 1px solid #ABABAB; 
-           height: 13px; 
-           width: 25px; 
-           border-radius: 20px; 
-           background: #E0E0E0; 
-           cursor: pointer; 
-           -webkit-appearance: none; 
-           margin-top: -5px; 
-         } 
-         input[type=range]:focus::-webkit-slider-runnable-track { 
-           background: #E3E3E3; 
-         } 
-         input[type=range]::-moz-range-track { 
-           height: 4px; 
-           cursor: pointer; 
-           animate: 0.2s; 
-           box-shadow: 0px 0px 0px #000000; 
-           background: #E3E3E3; 
-           border-radius: 0px; 
-           border: 0px solid #000000; 
-         } 
-         input[type=range]::-moz-range-thumb { 
-           box-shadow: 1px 1px 2px #B8B8B8; 
-           border: 1px solid #ABABAB; 
-           height: 13px; 
-           width: 25px; 
-           border-radius: 20px; 
-           background: #E0E0E0; 
-           cursor: pointer; 
-         } 
-         input[type=range]::-ms-track { 
-           height: 4px; 
-           cursor: pointer; 
-           animate: 0.2s; 
-           background: transparent; 
-           border-color: transparent; 
-           color: transparent; 
-         } 
-         input[type=range]::-ms-fill-lower { 
-           background: #E3E3E3; 
-           border: 0px solid #000000; 
-           border-radius: 0px; 
-           box-shadow: 0px 0px 0px #000000; 
-         } 
-         input[type=range]::-ms-fill-upper { 
-           background: #E3E3E3; 
-           border: 0px solid #000000; 
-           border-radius: 0px; 
-           box-shadow: 0px 0px 0px #000000; 
-         } 
-         input[type=range]::-ms-thumb { 
-           box-shadow: 1px 1px 2px #B8B8B8; 
-           border: 1px solid #ABABAB; 
-           height: 13px; 
-           width: 25px; 
-           border-radius: 20px; 
-           background: #E0E0E0; 
-           cursor: pointer; 
-         } 
-         input[type=range]:focus::-ms-fill-lower { 
-           background: #E3E3E3; 
-         } 
-         input[type=range]:focus::-ms-fill-upper { 
-           background: #E3E3E3; 
-         } 
-/* 
-// COMMON_CODE_BLOCK_END 
-*/ 
- </style> 
-   </head> 
-<body> 
- 
- <div id='settings_1' class='settings'> 
- <div class=group id='transparency_1' class='transparency'> 
- <strong>Transparency</strong> 
- <input id='transparencyRange_1' type='range' min=0 max=1 step=0.01 value=0> 
- </div> 
-  
- <div class=group id='rotation_1'> 
- <strong>Rotation</strong> 
- <div class=indented> 
- <div><input type='checkbox' id='changeRotationX_1'> x-axis</div> 
- <div><input type='checkbox' id='changeRotationY_1'> y-axis</div> 
- <div><input type='checkbox' id='changeRotationZ_1'> z-axis</div> 
- <button id='resetButton_1' class='resetButton' >Reset</button> 
- </div> 
- 
- <div class=suboption>Rotation speed</div> 
- <input id='rotationSpeedRange_1' type='range' min=0 max=5 step=0.01 value=2> 
- 
- </div> 
- 
- 
- <div class=group id='display_1'> 
- <strong>Display</strong> 
- <div class=indented> 
- <div><input type='checkbox' id='labelsCheckboxInput_1' checked>Labels</div> 
- <div><input type='checkbox' id='pointsCheckboxInput_1' checked>Points</div> 
- <div><input type='checkbox' id='edgesCheckboxInput_1' checked>Edges</div> 
- <div><input type='checkbox' id='facesCheckboxInput_1' checked>Faces</div> 
- <div><input type='checkbox' id='arrowheadsCheckboxInput_1' checked>Arrowheads</div> 
- </div> 
- <div class=suboption>Objects</div> 
- <div class=indented> 
- <div id='shownObjectsList_1' class='shownObjectsList'></div> 
- </div> 
- </div> 
- 
- 
- <div class=group id='svg_1'> 
- <strong>SVG</strong> 
- <div class=indented> 
- <form> 
- <input type="radio" name='screenshotMode' value='download' id='download_1' checked> Download<br> 
- <input type="radio" name='screenshotMode' value='tab' id='tab_1' > New tab<br> 
- </form> 
- <button id='takeScreenshot_1'>Screenshot</button> 
- </div> 
- </div> 
- 
- </div> <!-- end of settings --> 
- <img id='hideSettingsButton_1' class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> 
- <img id='showSettingsButton_1' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> 
-   <div id="model89920187284"></div> 
-   <script> 
-    requirejs.config({ 
-      paths: { 
-        three: '/kernelspecs/polymake/three', 
-        TrackballControls: '/kernelspecs/polymake/TrackballControls', 
-        Projector: '/kernelspecs/polymake/Projector', 
-        SVGRenderer: '/kernelspecs/polymake/SVGRenderer', 
-        WEBGL: '/kernelspecs/polymake/WebGL', 
-      }, 
-      shim: { 
-        'three': { exports: 'THREE'}, 
-        'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 
-        'WEBGL': { deps: [ 'three' ], exports: 'THREE.WEBGL' }, 
-        'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 
-        'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } 
-      } 
-    }); 
-     
-    require(['three'],function(THREE){ 
-        window.THREE = THREE; 
-      require(['TrackballControls','Projector','SVGRenderer','WEBGL'],function(TrackballControls,Projector,SVGRenderer,WEBGL) { 
-    THREE.TrackballControls = TrackballControls; 
-    THREE.Projector = Projector; 
-    THREE.SVGRenderer = SVGRenderer; 
-    THREE.WEBGL = WEBGL; 
- 
-const intervalLength = 25; // for automatic animations 
-const explodableModel = false;  
-var foldables = []; 
-var three = document.getElementById("model89920187284"); 
-var scene = new THREE.Scene(); 
- 
-var camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000); 
-camera.position.set(0, 0, 5); 
-camera.lookAt(0, 0, 0); 
-camera.up.set(0, 1, 0); 
- 
-var renderer = new THREE.WebGLRenderer( { antialias: true } ); 
-var svgRenderer = new THREE.SVGRenderer({antialias: true}); 
-renderer.setPixelRatio( window.devicePixelRatio ); 
-renderer.setClearColor(0xFFFFFF, 1); 
-svgRenderer.setClearColor(0xFFFFFF, 1); 
-three.appendChild(renderer.domElement); 
- 
-var control = new THREE.TrackballControls(camera, three); 
-control.zoomSpeed = 0.2; 
-control.rotateSpeed = 4; 
- 
-function onWindowResize() { 
-    var width = three.clientWidth; 
-    var height = three.clientHeight; 
-    renderer.setSize( width, height ); 
-    svgRenderer.setSize( width, height ); 
-    camera.aspect = width / height; 
-    camera.updateProjectionMatrix(); 
-} 
- 
-onWindowResize(); 
-window.addEventListener('resize', onWindowResize);  
- 
-// class to allow move points together with labels and spheres 
-var PMPoint = function (x,y,z) { 
-   this.vector = new THREE.Vector3(x,y,z); 
-   this.sprite = null; 
-   this.sphere = null; 
-} 
-PMPoint.prototype.addLabel = function(labelsprite) { 
-   this.sprite = labelsprite; 
-   this.sprite.position.copy(this.vector); 
-} 
-PMPoint.prototype.addSphere = function(spheremesh) { 
-   this.sphere = spheremesh; 
-   this.sphere.position.copy(this.vector); 
-} 
-PMPoint.prototype.set = function(x,y,z) { 
-   this.vector.set(x,y,z); 
-   if (this.sprite) { 
-      this.sprite.position.copy(this.vector); 
-   } 
-   if (this.sphere) { 
-      this.sphere.position.copy(this.vector); 
-   } 
-} 
-PMPoint.prototype.radius = function() { 
-   if (this.sphere) { 
-      return this.sphere.geometry.parameters.radius; 
-   } else { 
-      return 0; 
-   } 
-}; 
-// select the target node 
-var target = document.querySelector('#model89920187284'); 
- 
-// create an observer instance 
-var observer = new MutationObserver(function(mutations) { 
-   mutations.forEach(function(mutation) { 
-      if (mutation.removedNodes && mutation.removedNodes.length > 0) { 
-         cancelAnimationFrame(renderId); 
-         observer.disconnect(); 
-         console.log("cancelled frame "+renderId); 
-      } 
-   }); 
-}); 
- 
-// configuration of the observer: 
-var config = { childList: true, characterData: true } 
- 
-// pass in the target node, as well as the observer options 
-while (target) { 
-   if (target.className=="output") { 
-      observer.observe(target, config); 
-      break; 
-   } 
-   target = target.parentNode; 
-} 
- 
-// COMMON_CODE_BLOCK_END 
- 
-var obj0 = new THREE.Object3D(); 
-obj0.name = "planar_net_"; 
-obj0.userData.explodable = 1; 
-obj0.userData.points = []; 
-obj0.userData.points.push(new PMPoint(0, 0, 0)); 
-obj0.userData.points.push(new PMPoint(2, 0, 0)); 
-obj0.userData.points.push(new PMPoint(2, 2, 0)); 
-obj0.userData.points.push(new PMPoint(0, 2, 0)); 
-obj0.userData.points.push(new PMPoint(0, -2, 0)); 
-obj0.userData.points.push(new PMPoint(2, -2, 0)); 
-obj0.userData.points.push(new PMPoint(2, 4, 0)); 
-obj0.userData.points.push(new PMPoint(0, 4, 0)); 
-obj0.userData.points.push(new PMPoint(-2, 2, 0)); 
-obj0.userData.points.push(new PMPoint(-2, 0, 0)); 
-obj0.userData.points.push(new PMPoint(4, 0, 0)); 
-obj0.userData.points.push(new PMPoint(4, 2, 0)); 
-obj0.userData.points.push(new PMPoint(0, -4, 0)); 
-obj0.userData.points.push(new PMPoint(2, -4, 0)); 
- 
-obj0.userData.pointradii = 0.02; 
-   <!-- Vertex style --> 
-obj0.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ); 
-obj0.userData.pointlabels = ["0", "4", "6", "2", "1", "5", "7", "3", "3", "1", "5", "7", "3", "7"]; 
-obj0.userData.edgeindices = [0, 1, 1, 2, 0, 3, 2, 3, 0, 4, 1, 5, 4, 5, 2, 6, 3, 7, 6, 7, 3, 8, 0, 9, 8, 9, 1, 10, 2, 11, 10, 11, 4, 12, 5, 13, 12, 13]; 
-   <!-- Edge style --> 
-obj0.userData.edgematerial = new THREE.LineBasicMaterial( { transparent: false, linewidth: 1.5, depthTest: true, color: 0x000000 } ); 
-obj0.userData.facets = [[0, 1, 2, 3], [13, 5, 4, 12], [5, 1, 0, 4], [3, 2, 6, 7], [0, 3, 8, 9], [2, 1, 10, 11]]; 
-   <!-- Facet style --> 
-obj0.userData.facetmaterial = new THREE.MeshBasicMaterial( { transparent: true, opacity: 1, polygonOffsetUnits: 1, polygonOffset: true, depthWrite: true, depthFunc: THREE.LessDepth, polygonOffsetFactor: 1, side: THREE.DoubleSide, color: 0x77EC9E } ); 
-obj0.userData.axes = [[5,4], 
-      [2,1], 
-      [0,3], 
-      [3,2], 
-      [1,0]]; 
- 
-obj0.userData.angles = [1.5707963267949, 
-      1.5707963267949, 
-      1.5707963267949, 
-      1.5707963267949, 
-      1.5707963267949]; 
- 
-obj0.userData.subtrees = [[12,13], 
-      [10,11], 
-      [8,9], 
-      [6,7], 
-      [4,5,12,13]]; 
- 
-obj0.userData.polytoperoot = [[-1,-1,-1], 
-      [-1,0,0], 
-      [0,2,0]]; 
- 
-obj0.userData.oldscale = 0; 
-foldables.push(obj0); 
-init_object(obj0); 
-scene.add(obj0); 
-// COMMON_CODE_BLOCK_BEGIN 
-function textSpriteMaterial(message, parameters) { 
-    if ( parameters === undefined ) parameters = {}; 
-    var fontface = "Helvetica"; 
-    var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; 
-    fontsize = fontsize*10; 
-    var lines = message.split('\\n'); 
-    var size = 512; 
-    for(var i = 0; i<lines.length; i++){ 
-        var tmp = lines[i].length; 
-        while(tmp*fontsize > size){ 
-           fontsize--; 
-        } 
-    } 
-     
-    var canvas = document.createElement('canvas'); 
-    canvas.width = size; 
-    canvas.height = size; 
-    var context = canvas.getContext('2d'); 
-    context.fillStyle = "rgba(255, 255, 255, 0)"; 
-    context.fill(); 
-    context.font = fontsize + "px " + fontface; 
-     
-    // text color 
-    context.fillStyle = "rgba(0, 0, 0, 1.0)"; 
-     for(var i = 0; i<lines.length; i++){ 
-        context.fillText(lines[i], size/2, size/2+i*fontsize); 
-     } 
-     
-    // canvas contents will be used for a texture 
-    var texture = new THREE.Texture(canvas); 
-    texture.needsUpdate = true; 
-     
-    var spriteMaterial = new THREE.SpriteMaterial({map: texture, depthTest: true, depthWrite: false, depthFunc: THREE.LessEqualDepth}); 
-    return spriteMaterial; 
-} 
- 
- 
-// ---------------------- INITIALIZING OBJECTS-------------------------------------- 
-// --------------------------------------------------------------------------------- 
- 
-function init_object(obj) { 
-   if (obj.userData.hasOwnProperty("pointmaterial")) { 
-      init_points(obj); 
-   } 
-   if (obj.userData.hasOwnProperty("pointlabels")) { 
-      init_pointlabels(obj); 
-   } 
-   if (obj.userData.hasOwnProperty("edgematerial")) { 
-      init_lines(obj); 
-   } 
-   if (obj.userData.hasOwnProperty("edgelabels")) { 
-      init_edgelabels(obj); 
-   } 
-   if (obj.userData.hasOwnProperty("arrowstyle")) { 
-      init_arrowheads(obj); 
-   } 
-   if (obj.userData.hasOwnProperty("facetmaterial")) { 
-      init_faces(obj); 
-   } 
-} 
- 
-function init_points(obj) { 
-   var pointgroup = new THREE.Group(); 
-   pointgroup.name = "points"; 
-   var points = obj.userData.points; 
-   var radii = obj.userData.pointradii; 
-   var materials = obj.userData.pointmaterial; 
-   var geometry,material; 
-   if (!Array.isArray(radii)) { 
-      geometry = new THREE.SphereBufferGeometry(radii);   
-   } 
-   if (!Array.isArray(materials)) { 
-      material = materials; 
-   } 
-   for (var i=0; i<points.length; i++) { 
-      var point = points[i]; 
-      if (Array.isArray(radii)) { 
-         if (radii[i] == 0) { 
-            continue; 
-         } 
-         geometry = new THREE.SphereBufferGeometry(radii[i]);   
-      }  
-      if (Array.isArray(materials)) { 
-         material = materials[i];     
-      }  
-      var sphere = new THREE.Mesh(geometry, material); 
-      point.addSphere(sphere); 
-      pointgroup.add(sphere); 
-   } 
-   obj.add(pointgroup); 
-} 
- 
-function init_pointlabels(obj) { 
-   var points = obj.userData.points; 
-   var labels = obj.userData.pointlabels; 
-   var pointlabels = new THREE.Group(); 
-   pointlabels.name = "pointlabels"; 
-   if (Array.isArray(labels)) { 
-      for (var i=0; i<points.length; i++) { 
-         var point = points[i]; 
-         var spriteMaterial = textSpriteMaterial( labels[i] ); 
-       var sprite = new THREE.Sprite(spriteMaterial); 
-         point.addLabel(sprite); 
-         pointlabels.add(sprite); 
-      } 
-   } else { 
-      var spriteMaterial = textSpriteMaterial( labels ); 
-      for (var i=0; i<points.length; i++) { 
-         var point = points[i]; 
-       var sprite = new THREE.Sprite(spriteMaterial); 
-         point.addLabel(sprite); 
-         pointlabels.add(sprite); 
-      } 
-   } 
-   obj.add(pointlabels); 
-} 
- 
-function init_lines(obj) { 
-   var edgeindices = obj.userData.edgeindices; 
-   var points = obj.userData.points; 
-   var materials = obj.userData.edgematerial; 
-   var geometry = new THREE.BufferGeometry(); 
-   var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 ); 
-   var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 ); 
-   var geometry = new THREE.BufferGeometry(); 
-   geometry.setAttribute('position', bufattr); 
-   if (Array.isArray(materials)) {      
-      for (var i=0; i<materials.length; i++) { 
-         geometry.addGroup(2*i,2,i); 
-      } 
-   } 
-   var lines = new THREE.LineSegments(geometry, materials); 
-   lines.name = "lines"; 
-   obj.add(lines); 
-   updateEdgesPosition(obj); 
-} 
- 
-function init_edgelabels(obj) { 
-   var points = obj.userData.points; 
-   var edgeindices = obj.userData.edgeindices; 
-   var labels = obj.userData.edgelabels; 
-   var edgelabels = new THREE.Group(); 
-   edgelabels.name = "edgelabels"; 
-   if (Array.isArray(labels)) { 
-      for (var i=0; i<edgeindices.length; i=i+2) { 
-         var point = points[i]; 
-         var spriteMaterial = textSpriteMaterial( labels[i] ); 
-      var sprite = new THREE.Sprite(spriteMaterial); 
-         sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[i]].vector,points[edgeindices[i+1]].vector).multiplyScalar(0.5)); 
-         edgelabels.add(sprite); 
-      } 
-   } else { 
-      var spriteMaterial = textSpriteMaterial( labels ); 
-      for (var i=0; i<points.length; i++) { 
-         var point = points[i]; 
-      var sprite = new THREE.Sprite(spriteMaterial); 
-         sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[i]].vector,points[edgeindices[i+1]].vector).multiplyScalar(0.5)); 
-         pointlabels.add(sprite); 
-      } 
-   } 
-   obj.add(edgelabels); 
-} 
- 
-function init_arrowheads(obj) { 
-    var arrowheads = new THREE.Group(); 
-    arrowheads.name = "arrowheads"; 
-    var arrowstyle = obj.userData.arrowstyle; 
-    var edgeindices = obj.userData.edgeindices; 
-    var edgematerials = obj.userData.edgematerial; 
-    var points = obj.userData.points; 
-    var material; 
-    if (!Array.isArray(edgematerials)) { 
-        material = new THREE.MeshBasicMaterial( {color: edgematerials.color} ); 
-    } 
- 
-    for (var i=0; i<edgeindices.length; i=i+2) { 
-        var start = points[edgeindices[i]]; 
-        var end = points[edgeindices[i+1]]; 
-        var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius(); 
-        if (dist <= 0) { 
-            continue; 
-        } 
-        var dir = new THREE.Vector3().subVectors(end.vector,start.vector); 
-        dir.normalize(); 
-        var axis = new THREE.Vector3().set(dir.z,0,-dir.x); 
-        axis.normalize(); 
-        var radians = Math.acos( dir.y ); 
-        var radius = dist/25; 
-        var height = dist/5; 
-        var geometry = new THREE.ConeBufferGeometry(radius,height); 
-        var position = new THREE.Vector3().addVectors(start.vector,dir.clone().multiplyScalar(start.radius()+dist-height/2)); 
-        if (Array.isArray(edgematerials)) { 
-            material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} ); 
-        } 
-        var cone = new THREE.Mesh( geometry, material ); 
-        cone.quaternion.setFromAxisAngle(axis,radians);; 
-        cone.position.copy(position);; 
-        arrowheads.add(cone); 
-    } 
-    obj.add(arrowheads); 
-} 
- 
-function init_faces(obj) { 
-   var points = obj.userData.points; 
-   var facets = obj.userData.facets; 
-   obj.userData.triangleindices = []; 
-   for (var i=0; i<facets.length; i++) { 
-      facet = facets[i]; 
-      for (var t=0; t<facet.length-2; t++) { 
-         obj.userData.triangleindices.push(facet[0],facet[t+1],facet[t+2]);   
-      } 
-   } 
-   var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 ); 
-   var bufattr = new THREE.Float32BufferAttribute(bufarr,3); 
-    
-   var materials = obj.userData.facetmaterial; 
-   var geometry = new THREE.BufferGeometry(); 
-   geometry.setAttribute('position',bufattr); 
-   if (Array.isArray(materials)) { 
-      var tricount = 0; 
-      var facet; 
-      for (var i=0; i<facets.length; i++) { 
-         facet = facets[i]; 
-         geometry.addGroup(tricount,(facet.length-2)*3,i); 
-         tricount += (facet.length-2)*3; 
-      } 
-   } 
-   var mesh = new THREE.Mesh(geometry, materials); 
-   mesh.name = "faces"; 
-   obj.add(mesh);  
-   updateFacesPosition(obj); 
-} 
-// //INITIALIZING 
- 
- 
-function updateFacesPosition(obj) { 
-   var points = obj.userData.points; 
-   var indices = obj.userData.triangleindices; 
-   var faces = obj.getObjectByName("faces"); 
-   var ba = faces.geometry.getAttribute("position"); 
-   for (var i=0; i<indices.length; i++) { 
-      ba.setXYZ(i, points[indices[i]].vector.x, points[indices[i]].vector.y ,points[indices[i]].vector.z);  
-   } 
-   faces.geometry.attributes.position.needsUpdate = true; 
-    
-} 
- 
-function updateEdgesPosition(obj) { 
-   var points = obj.userData.points; 
-   var indices = obj.userData.edgeindices; 
-   var lines = obj.getObjectByName("lines"); 
-   var ba = lines.geometry.getAttribute("position");  
-   for (var i=0; i<indices.length; i++) { 
-      ba.setXYZ(i, points[indices[i]].vector.x, points[indices[i]].vector.y ,points[indices[i]].vector.z);  
-   } 
-   lines.geometry.attributes.position.needsUpdate = true; 
-} 
- 
  
 // ------------------------ FOLDING ------------------------------------------------ // ------------------------ FOLDING ------------------------------------------------
Line 1922: Line 760:
  
 if (foldables.length) { if (foldables.length) {
-    var settings = document.getElementById('settings_1');+    var settings = document.getElementById('settings_0');
     var foldDiv = document.createElement('div');     var foldDiv = document.createElement('div');
-    foldDiv.id = 'fold_1';+    foldDiv.id = 'fold_0';
     var title = document.createElement('strong');     var title = document.createElement('strong');
     title.innerHTML = 'Fold';     title.innerHTML = 'Fold';
Line 1943: Line 781:
     settings.insertBefore(foldDiv,settings.childNodes[0]);     settings.insertBefore(foldDiv,settings.childNodes[0]);
 } }
- 
-var xRotationEnabled = false; 
-var yRotationEnabled = false; 
-var zRotationEnabled = false; 
-var rotationSpeedFactor = 1; 
-var settingsShown = false; 
-var labelsShown = true; 
-var intervals = []; 
-var timeouts = []; 
-var explodingSpeed = 0.05; 
-var explodeScale = 0; 
-var XMLS = new XMLSerializer(); 
-var svgElement; 
-var renderId; 
- 
-var render = function () { 
- 
- renderId = requestAnimationFrame(render); 
- 
-// comment in for automatic explosion 
-// explode(updateFactor()); 
- 
-    var phi = 0.02 * rotationSpeedFactor; 
- 
-    if (xRotationEnabled) { 
-        scene.rotation.x += phi; 
-    } 
-    if (yRotationEnabled) { 
-        scene.rotation.y += phi; 
-    } 
-    if (zRotationEnabled) { 
-        scene.rotation.z += phi; 
-    } 
- 
-    control.update(); 
-    renderer.render(scene, camera); 
-}; 
- 
  
          
-render();+// ---------------------- EXPLOSION ------------------------------------------------ 
 +// ---------------------------------------------------------------------------------
  
 if (explodableModel) { if (explodableModel) {
Line 1992: Line 793:
         }         }
     }     }
 +    document.getElementById('explodeRange_0').oninput = triggerExplode;
 +    document.getElementById('explodeCheckbox_0').onchange = triggerAutomaticExplode;
 +    document.getElementById('explodingSpeedRange_0').oninput = setExplodingSpeed;
 } }
 +
 function computeCentroid(obj) { function computeCentroid(obj) {
     centroid = new THREE.Vector3();     centroid = new THREE.Vector3();
Line 2001: Line 806:
     obj.userData.centroid = centroid;     obj.userData.centroid = centroid;
 } }
- 
-function changeTransparency() { 
-    var opacity = 1-Number(event.currentTarget.value); 
-    for (var i=0; i<scene.children.length; i++) { 
-        child = scene.children[i]; 
-        if ( child.userData.hasOwnProperty("facetmaterial") ) { 
-            if (Array.isArray(child.userData.facetmaterial)) { 
-                for (var j=0; j<child.userData.facetmaterial.length; j++) { 
-                    child.userData.facetmaterial[j].opacity = opacity; 
-                } 
-            } else { 
-                child.userData.facetmaterial.opacity = opacity; 
-            }     
-        } 
-    } 
-} 
- 
-function changeRotationX(event){ 
-    xRotationEnabled = event.currentTarget.checked; 
-}  
- 
-function changeRotationY(event){ 
-    yRotationEnabled = event.currentTarget.checked; 
-}  
- 
-function changeRotationZ(event){ 
-    zRotationEnabled = event.currentTarget.checked; 
-}  
- 
- 
-function changeRotationSpeedFactor(event){ 
-    rotationSpeedFactor = Number(event.currentTarget.value); 
-} 
- 
-function resetScene(){ 
-    scene.rotation.set(0,0,0); 
-    camera.position.set(0,0,5); 
-    camera.up.set(0,1,0); 
-} 
- 
-function showSettings(event){ 
-    document.getElementById('settings_1').style.visibility = 'visible'; 
-    document.getElementById('showSettingsButton_1').style.visibility = 'hidden'; 
-    document.getElementById('hideSettingsButton_1').style.visibility = 'visible'; 
-    settingsShown = true; 
-} 
- 
-function hideSettings(event){ 
-    document.getElementById('settings_1').style.visibility = 'hidden'; 
-    document.getElementById('showSettingsButton_1').style.visibility = 'visible'; 
-    document.getElementById('hideSettingsButton_1').style.visibility = 'hidden'; 
-    settingsShown = false; 
-} 
- 
- 
- 
-var pos = 150* Math.PI; 
- 
-function updateFactor() { 
-    pos++; 
-    return Math.sin(.01*pos)+1; 
-} 
- 
-function takeSvgScreenshot(){ 
-    var labelsShown = document.getElementById('labelsCheckboxInput_1').checked; 
-    if (labelsShown){ 
-        setVisibility(false,"pointlabels"); 
-        setVisibility(false,"edgelabels"); 
-    } 
-    svgRenderer.render(scene,camera); 
-    svgElement = XMLS.serializeToString(svgRenderer.domElement); 
-     
-    if (labelsShown){ 
-        setVisibility(true,"pointlabels"); 
-        setVisibility(true,"edgelabels"); 
-    } 
- 
-    if (document.getElementById('tab_1').checked){ 
-        //show in new tab 
-        var myWindow = window.open("",""); 
-        myWindow.document.body.innerHTML = svgElement; 
-    } else{ 
-        // download svg file  
-        download("screenshot.svg", svgElement); 
-    } 
-} 
-     
-// ---------------------- EXPLOSION ------------------------------------------------ 
-// --------------------------------------------------------------------------------- 
  
 function explode(factor) { function explode(factor) {
Line 2134: Line 850:
         timeouts.push(setTimeout(startUnexploding, 3000));         timeouts.push(setTimeout(startUnexploding, 3000));
     }     }
-    document.getElementById('explodeRange_1').value = explodeScale;+    document.getElementById('explodeRange_0').value = explodeScale;
 } }
  
Line 2153: Line 869:
         timeouts.push(setTimeout(startExploding, 3000));         timeouts.push(setTimeout(startExploding, 3000));
     }     }
-    document.getElementById('explodeRange_1').value = explodeScale;+    document.getElementById('explodeRange_0').value = explodeScale;
 } }
  
Line 2167: Line 883:
 } }
  
-function showOrHideObject(event){ +// ---------------------- DISPLAY -------------------------------------------------- 
-    var nr = Number(event.currentTarget.name); +// ---------------------------------------------------------------------------------
-    scene.children[nr].visible = event.currentTarget.checked; +
-+
-    +
  
-// append checkboxes for displaying or hiding objects +const objectTypeInnerHTMLs { points: "Points", pointlabels: "Point labels", lines: "Edges", edgelabels: "Edge labels", faces: "Faces", arrowheads: "Arrow heads" }
-var shownObjectsList document.getElementById('shownObjectsList_1')+const objectTypeVisible = {}
-for (var i=0; i<scene.children.length; i++){ +Object.assign(objectTypeVisible,modelContains); 
-    obj = scene.children[i]+const sortedObjectTypeKeys Object.keys(objectTypeInnerHTMLs).sort(); 
-    var objNode = document.createElement('span'); +const shownObjectTypesList document.getElementById('shownObjectTypesList_0');
-    objNode.innerHTML obj.name + '<br>'; +
-    var checkbox = document.createElement('input')+
-    checkbox.type = 'checkbox'; +
-    checkbox.checked = true; +
-    checkbox.name = String(i); +
-    checkbox.onchange showOrHideObject; +
-    shownObjectsList.appendChild(checkbox); +
-    shownObjectsList.appendChild(objNode); +
-}+
  
 function setVisibility(bool,objname) { function setVisibility(bool,objname) {
Line 2197: Line 901:
 } }
  
-function toggleLabels(event) { +function toggleObjectTypeVisibility(event){ 
-    setVisibility(event.currentTarget.checked,"pointlabels")+    var name = event.currentTarget.name
-    setVisibility(event.currentTarget.checked,"edgelabels");+    var checked = event.currentTarget.checked; 
 +    objectTypeVisible[name] = checked; 
 +    setVisibility(checked,name);
 } }
  
-function toggleFaces(event) { +for (var i=0; i<sortedObjectTypeKeys.length; i++){ 
-    setVisibility(event.currentTarget.checked,"faces");+    var key = sortedObjectTypeKeys[i]; 
 +    if (modelContains[key]) { 
 +        var objTypeNode = document.createElement('span'); 
 +        objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '<br>'; 
 +        var checkbox = document.createElement('input'); 
 +        checkbox.type = 'checkbox'; 
 +        checkbox.checked = true; 
 +        checkbox.name = key; 
 +        checkbox.onchange = toggleObjectTypeVisibility; 
 +        shownObjectTypesList.appendChild(checkbox); 
 +        shownObjectTypesList.appendChild(objTypeNode); 
 +    }
 } }
  
-function toggleEdges(event) { +// ------------------------------------------------------
-    setVisibility(event.currentTarget.checked,"lines"); +
-}+
  
-function togglePoints(event) { +function toggleObjectVisibility(event){ 
-    setVisibility(event.currentTarget.checked,"points");+    var nr = Number(event.currentTarget.name)
 +    scene.children[nr].visible = event.currentTarget.checked;
 } }
  
-function toggleArrowheads(event) { +// append checkboxes for displaying or hiding objects 
-    setVisibility(event.currentTarget.checked,"arrowheads");+var shownObjectsList = document.getElementById('shownObjectsList_0'); 
 +for (var i=0; i<scene.children.length; i++){ 
 +    obj = scene.children[i]; 
 +    var objNode = document.createElement('span'); 
 +    objNode.innerHTML = obj.name + '<br>'; 
 +    var checkbox = document.createElement('input'); 
 +    checkbox.type = 'checkbox'; 
 +    checkbox.checked = true; 
 +    checkbox.name = String(i); 
 +    checkbox.onchange = toggleObjectVisibility; 
 +    shownObjectsList.appendChild(checkbox); 
 +    shownObjectsList.appendChild(objNode);
 } }
  
-document.getElementById('labelsCheckboxInput_1').onchange = toggleLabels; +// ---------------------- SVG ------------------------------------------------------ 
-document.getElementById('pointsCheckboxInput_1').onchange = togglePoints; +// ---------------------------------------------------------------------------------
-document.getElementById('facesCheckboxInput_1').onchange = toggleFaces; +
-document.getElementById('edgesCheckboxInput_1').onchange = toggleEdges; +
-document.getElementById('arrowheadsCheckboxInput_1').onchange = toggleArrowheads;+
  
 +function takeSvgScreenshot() {
 +    if (objectTypeVisible["pointlabels"]) {
 +        setVisibility(false,"pointlabels");
 +    }
 +    if (objectTypeVisible["edgelabels"]) {
 +        setVisibility(false,"edgelabels");
 +    }
 +    svgRenderer.render(scene,camera);
 +    svgElement = XMLS.serializeToString(svgRenderer.domElement);
 +    
 +    if (objectTypeVisible["pointlabels"]) {
 +        setVisibility(true,"pointlabels");
 +    }
 +    if (objectTypeVisible["edgelabels"]) {
 +        setVisibility(true,"edgelabels");
 +    }
  
 +    if (document.getElementById('tab_0').checked){
 +        //show in new tab
 +        var myWindow = window.open("","");
 +        myWindow.document.body.innerHTML = svgElement;
 +    } else{
 +        // download svg file 
 +        download("screenshot.svg", svgElement);
 +    }
 +}
  
 function download(filename, text) { function download(filename, text) {
Line 2239: Line 988:
 } }
  
-var tempobj; 
-tempobj = document.getElementById('explodeRange_1'); 
-if (tempobj) { 
-   tempobj.oninput = triggerExplode; 
-   document.getElementById('explodeCheckbox_1').onchange = triggerAutomaticExplode; 
-   document.getElementById('explodingSpeedRange_1').oninput = setExplodingSpeed; 
-} 
-tempobj = document.getElementById('foldRange_1'); 
-if (tempobj) { 
-   tempobj.oninput = fold; 
-} 
-document.getElementById('transparencyRange_1').oninput = changeTransparency; 
-document.getElementById('changeRotationX_1').onchange = changeRotationX; 
-document.getElementById('changeRotationY_1').onchange = changeRotationY; 
-document.getElementById('changeRotationZ_1').onchange = changeRotationZ; 
-document.getElementById('resetButton_1').onclick = resetScene; 
-document.getElementById('rotationSpeedRange_1').oninput = changeRotationSpeedFactor; 
-document.getElementById('takeScreenshot_1').onclick = takeSvgScreenshot; 
-document.getElementById('showSettingsButton_1').onclick = showSettings; 
-document.getElementById('hideSettingsButton_1').onclick = hideSettings; 
  
- +document.getElementById('transparencyRange_0').oninput = changeTransparency; 
 +document.getElementById('changeRotationX_0').onchange = changeRotationX; 
 +document.getElementById('changeRotationY_0').onchange = changeRotationY; 
 +document.getElementById('changeRotationZ_0').onchange = changeRotationZ; 
 +document.getElementById('resetButton_0').onclick = resetScene; 
 +document.getElementById('rotationSpeedRange_0').oninput = changeRotationSpeedFactor; 
 +document.getElementById('takeScreenshot_0').onclick = takeSvgScreenshot; 
 +document.getElementById('showSettingsButton_0').onclick = showSettings; 
 +document.getElementById('hideSettingsButton_0').onclick = hideSettings; 
  
 // ------------------ SHORTCUTS -------------------------------------------- // ------------------ SHORTCUTS --------------------------------------------
Line 2492: Line 1230:
  var event = new Event('click');  var event = new Event('click');
  if (settingsShown){  if (settingsShown){
- document.getElementById('hideSettingsButton_1').dispatchEvent(event); + document.getElementById('hideSettingsButton_0').dispatchEvent(event); 
- } else{ + } else { 
- document.getElementById('showSettingsButton_1').dispatchEvent(event);+ document.getElementById('showSettingsButton_0').dispatchEvent(event);
  }  }
 }); });
Line 2505: Line 1243:
    </body>    </body>
 </html> </html>
-</div> 
 </HTML> </HTML>
  
  • playground/test_3js.txt
  • Last modified: 2020/08/20 10:17
  • by hnagel