This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ====== Tutorial for Visualization ====== This tutorial contains some examples for the visualization of the different objects dealt with in polymake. ===== Intro ===== The most straighforward way of visualizing things in ''%%polymake%%'' is by using the ''%%VISUAL%%'' method that visualizable objects provide. For example, you can look at the 3-simplex by doing this: <code perl> > simplex(3)->VISUAL; </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 unnamed --> <html> <head> <title>unnamed</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_0' class='settings'> <div class=group id='transparency_0' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_0' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_0'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_0'> x-axis</div> <div><input type='checkbox' id='changeRotationY_0'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_0'> z-axis</div> <button id='resetButton_0' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_0' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_0'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_0' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_0' checked>Labels</div> </div> </div> <div class=group id='svg_0'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_0' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_0' > New tab<br> </form> <button id='takeScreenshot_0'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_0' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_0' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model38053289435"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model38053289435' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model38053289435'); // 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 objectnames = ["unnamed__1"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(1, 0, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(0, 0, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0xFF0000, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.02,points_material); allpoints[1].makesphere(0.02,points_material); allpoints[2].makesphere(0.02,points_material); allpoints[3].makesphere(0.02,points_material); allpoints[0].makelabel("0"); allpoints[1].makelabel("1"); allpoints[2].makelabel("2"); allpoints[3].makelabel("3"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 2, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(3, 2, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(1, 2, 3, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[3].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_0').style.position = 'absolute'; document.getElementById('settings_0').style.display = 'block'; document.getElementById('showSettingsButton_0').style.display = 'none'; document.getElementById('hideSettingsButton_0').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_0').style.display = 'none'; document.getElementById('hideSettingsButton_0').style.display = 'none'; document.getElementById('showSettingsButton_0').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } 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 showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_0').style.display = 'block'; document.getElementById('transparencyRange_0').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_0').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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 = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_0'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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('labelsCheckboxInput_0').onchange = displayOrHideLabels; 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); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> By default, this will open ''%%jReality%%'' and show you a tetrahedron in a pretty color. See the [[visual_tutorial#backends|visual_tutorial#Backends]] section for more information on using other backends. To get a list of visualization methods available, you can use the build-in help system. To obtain the visualization possibilities for, e.g., Polytopes in application ''%%polytope%%'', type: <code perl> > help 'objects/Polytope/methods/Visualization'; These methods are for visualization. ------------------- Subtopics of polytope/objects/Polytope/methods/Visualization: GALE, SCHLEGEL, VISUAL, VISUAL_DUAL, VISUAL_DUAL_FACE_LATTICE, VISUAL_DUAL_GRAPH, VISUAL_FACE_LATTICE, VISUAL_GRAPH, VISUAL_ORBIT_COLORED_GRAPH, write_stl Subtopics of objects/Polytope/methods/Visualization: GALE, SCHLEGEL, VISUAL, VISUAL_BOUNDED_GRAPH, VISUAL_DUAL, VISUAL_DUAL_FACE_LATTICE, VISUAL_DUAL_GRAPH, VISUAL_FACE_LATTICE, VISUAL_GRAPH, VISUAL_TRIANGULATION_BOUNDARY </code> Most visualization methods provide a variety of parameters. Get a list for the method of yout choice (here: ''%%VISUAL%%'') by typing <code perl> > help 'objects/Polytope/methods/Visualization/VISUAL'; VISUAL(Options) -> Visual::Polytope Visualize a polytope as a graph (if 1d), or as a solid object (if 2d or 3d), or as a Schlegel diagram (4d). Options: Attributes modifying the appearance of a set of polygons (like a polygonal surface). [4mFacetColor[24m => Flexible<Color> filling color of the polygons [4mFacetTransparency[24m => Flexible<Float> transparency factor of the polygons between 0 (opaque) and 1 (completely translucent) [4mFacetStyle[24m => Flexible<String> if set to "hidden", the inner area of the polygons are not rendered at all [4mFacetLabels[24m => String if set to "hidden", the facet labels are not displayed (in the most cases this is the default behavior) [4mEdgeColor[24m => Color color of the boundary lines [4mEdgeThickness[24m => Float scaling factor for the thickness of the boundary lines [4mEdgeStyle[24m => String if set to "hidden", the boundary lines are not rendered [4mTitle[24m => String the name of the drawing [4mName[24m => String the name of this visual object in the drawing [4mHidden[24m => Bool if set to true, the visual object is not rendered (useful for interactive visualization programs allowing for switching details on and off) [4mPointLabels[24m => String if set to "hidden", no point labels are displayed [4mVertexLabels[24m => String alias for PointLabels [4mPointColor[24m => Flexible<Color> color of the spheres or rectangles representing the points [4mVertexColor[24m => Flexible<Color> alias for PointColor [4mPointThickness[24m => Flexible<Float> scaling factor for the size of the spheres or rectangles representing the points [4mVertexThickness[24m => Flexible<Float> alias for PointThickness [4mPointBorderColor[24m => Flexible<Color> color of the border line of rectangles representing the points [4mVertexBorderColor[24m => Flexible<Float> alias for PointBorderColor [4mPointBorderThickness[24m => Flexible<Float> scaling factor for the thickness of the border line of rectangles representing the points [4mVertexBorderThickness[24m => Flexible<Float> alias for PointBorderThickness [4mPointStyle[24m => Flexible<String> if set to "hidden", neither point nor its label is rendered [4mVertexStyle[24m => Flexible<String> alias for PointStyle [4mViewPoint[24m => Vector<Float> ViewPoint for Sketch visualization [4mViewDirection[24m => Vector<Float> ViewDirection for Sketch visualization [4mViewUp[24m => Vector<Float> ViewUp for Sketch visualization [4mScale[24m => Float scale for Sketch visualization [4mLabelAlignment[24m => Flexible<String> Defines the alignment of the vertex labels: left, right or center Options: Attributes modifying the appearance of "wire frameworks". Unlike the rest, the flexible edge attributes are retrieved using the [4medge iterator[24m as an index/key/argument. [4mEdgeColor[24m => Flexible<Color> color of the lines representing the edges [4mEdgeThickness[24m => Flexible<Float> scaling factor for the thickness of the lines representing the edges [4mEdgeLabels[24m => EdgeMap<String> textual labels to be placed along the edges [4mEdgeStyle[24m => Flexible<String> if set to "hidden", neither the edge nor its label is rendered [4mTitle[24m => String the name of the drawing [4mName[24m => String the name of this visual object in the drawing [4mHidden[24m => Bool if set to true, the visual object is not rendered (useful for interactive visualization programs allowing for switching details on and off) [4mPointLabels[24m => String if set to "hidden", no point labels are displayed [4mVertexLabels[24m => String alias for PointLabels [4mPointColor[24m => Flexible<Color> color of the spheres or rectangles representing the points [4mVertexColor[24m => Flexible<Color> alias for PointColor [4mPointThickness[24m => Flexible<Float> scaling factor for the size of the spheres or rectangles representing the points [4mVertexThickness[24m => Flexible<Float> alias for PointThickness [4mPointBorderColor[24m => Flexible<Color> color of the border line of rectangles representing the points [4mVertexBorderColor[24m => Flexible<Float> alias for PointBorderColor [4mPointBorderThickness[24m => Flexible<Float> scaling factor for the thickness of the border line of rectangles representing the points [4mVertexBorderThickness[24m => Flexible<Float> alias for PointBorderThickness [4mPointStyle[24m => Flexible<String> if set to "hidden", neither point nor its label is rendered [4mVertexStyle[24m => Flexible<String> alias for PointStyle [4mViewPoint[24m => Vector<Float> ViewPoint for Sketch visualization [4mViewDirection[24m => Vector<Float> ViewDirection for Sketch visualization [4mViewUp[24m => Vector<Float> ViewUp for Sketch visualization [4mScale[24m => Float scale for Sketch visualization [4mLabelAlignment[24m => Flexible<String> Defines the alignment of the vertex labels: left, right or center Options: Common attributes modifying the appearance of PointSets and all visual objects derived thereof. Please be aware that no one visualization program interfaced to polymake supports all of them. Unsupported options are normally ignored. [4mTitle[24m => String the name of the drawing [4mName[24m => String the name of this visual object in the drawing [4mHidden[24m => Bool if set to true, the visual object is not rendered (useful for interactive visualization programs allowing for switching details on and off) [4mPointLabels[24m => String if set to "hidden", no point labels are displayed [4mVertexLabels[24m => String alias for PointLabels [4mPointColor[24m => Flexible<Color> color of the spheres or rectangles representing the points [4mVertexColor[24m => Flexible<Color> alias for PointColor [4mPointThickness[24m => Flexible<Float> scaling factor for the size of the spheres or rectangles representing the points [4mVertexThickness[24m => Flexible<Float> alias for PointThickness [4mPointBorderColor[24m => Flexible<Color> color of the border line of rectangles representing the points [4mVertexBorderColor[24m => Flexible<Float> alias for PointBorderColor [4mPointBorderThickness[24m => Flexible<Float> scaling factor for the thickness of the border line of rectangles representing the points [4mVertexBorderThickness[24m => Flexible<Float> alias for PointBorderThickness [4mPointStyle[24m => Flexible<String> if set to "hidden", neither point nor its label is rendered [4mVertexStyle[24m => Flexible<String> alias for PointStyle [4mViewPoint[24m => Vector<Float> ViewPoint for Sketch visualization [4mViewDirection[24m => Vector<Float> ViewDirection for Sketch visualization [4mViewUp[24m => Vector<Float> ViewUp for Sketch visualization [4mScale[24m => Float scale for Sketch visualization [4mLabelAlignment[24m => Flexible<String> Defines the alignment of the vertex labels: left, right or center Options: Options for visualizing objects with homogeneous coordinates like Polytope, PolyhedralComplex, SubdivisionOfPoints and PointConfiguration. [4mBoundingFacets[24m => Matrix useful for unbounded polyhedra [4mTransformation[24m => Matrix<Float> linear transformation, to be applied after dehomogenization [4mOffset[24m => Vector<Float> shift, to be applied after dehomogenization and the linear transformation Returns Visual::Polytope </code> The syntax for passing parameters can be seen in this example: <code> simplex(3)->VISUAL(EdgeThickness => 10); </code> It visualizes a tetrahedron with really thick edges. See the section on [[visual_tutorial#application%20polytope|visual_tutorial#application polytope]] for more. ==== Specifying colors ==== Some visualization methods requite you to specify colors. There are various ways of doing this in polymake, i.e. the color red may be given by * the String ''%%'red%%''', which will be looked up in rgb.txt to obtain the rgb values, * the String ''%%'1 0 0%%''', which contains three decimal values in the interval [0,1] corresponding to the 'r g b'-values of the color, * the String ''%%'255 0 0%%''', which contains three integer values in the interval [0,255] corresponding to the 'r g b'-values of the color, * an object ''%%new RGB(1,0,0)%%'' of polymake's RGB class. ===== application polytope ===== The application 'polytope' contains a large amount of visualization routines. Most\\ of them allow you to change the way things look a various ways. See the following\\ subsections for examples. ==== Changing vertex attributes ==== It is possible to change the way the vertices are displayed directly from the command line. In the following we will explain how to change the color, labels, and size of the vertices. === Colors === There are different ways to specify the colors of the vertices. You may choose a single color for all vertices or set each vertex color individually. **Single color**: To specify one color for all vertices use the //VertexColor// attribute of the //VISUAL// method: <code perl> > simplex(3)->VISUAL(VertexColor=> '0 100 200'); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 unnamed --> <html> <head> <title>unnamed</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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 id='shownObjectsList_1' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_1' checked>Labels</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' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_1' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model47485370314"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model47485370314' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model47485370314'); // 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 objectnames = ["unnamed__1"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(1, 0, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(0, 0, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0x0064C8, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.02,points_material); allpoints[1].makesphere(0.02,points_material); allpoints[2].makesphere(0.02,points_material); allpoints[3].makesphere(0.02,points_material); allpoints[0].makelabel("0"); allpoints[1].makelabel("1"); allpoints[2].makelabel("2"); allpoints[3].makelabel("3"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 2, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(3, 2, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(1, 2, 3, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[3].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_1').style.position = 'absolute'; document.getElementById('settings_1').style.display = 'block'; document.getElementById('showSettingsButton_1').style.display = 'none'; document.getElementById('hideSettingsButton_1').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_1').style.display = 'none'; document.getElementById('hideSettingsButton_1').style.display = 'none'; document.getElementById('showSettingsButton_1').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } 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); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_1').style.display = 'block'; document.getElementById('transparencyRange_1').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_1').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_1').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_1').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_1'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_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('labelsCheckboxInput_1').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_1').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_1').onclick = showSettings; document.getElementById('hideSettingsButton_1').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_1').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_1').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> You can also change the colors in the visualization backends (e.g. jReality). How to do this is explained below. To set the colors of the vertices individually, you can either specify an array that contains a color for each of the vertices or a perl function, i.e. ''%%sub {...}%%'', that returns a color depending on the vertex index. **Array of colors**: Instead of passing one color to the //VertexColor// attribute, you can pass an array of colors: <code perl> > simplex(3)->VISUAL(VertexColor=>['red','green','blue','yellow']); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 unnamed --> <html> <head> <title>unnamed</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_2' class='settings'> <div class=group id='transparency_2' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_2' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_2'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_2'> x-axis</div> <div><input type='checkbox' id='changeRotationY_2'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_2'> z-axis</div> <button id='resetButton_2' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_2' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_2'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_2' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_2' checked>Labels</div> </div> </div> <div class=group id='svg_2'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_2' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_2' > New tab<br> </form> <button id='takeScreenshot_2'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_2' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_2' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model41099076931"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model41099076931' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model41099076931'); // 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 objectnames = ["unnamed__1"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(1, 0, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(0, 0, 1)); <!-- Vertex style --> var materials = [ new THREE.MeshBasicMaterial({ color: 0xFF0000, }), new THREE.MeshBasicMaterial({ color: 0x00FF00, }), new THREE.MeshBasicMaterial({ color: 0x0000FF, }), new THREE.MeshBasicMaterial({ color: 0xFFFF00, }), ]; for (index = 0; index < materials.length; ++index) { materials[index].side = THREE.DoubleSide; } var points_material = new THREE.MeshFaceMaterial ( materials ); <!-- POINTS --> allpoints[0].makesphere(0.02,materials[0]); allpoints[1].makesphere(0.02,materials[1]); allpoints[2].makesphere(0.02,materials[2]); allpoints[3].makesphere(0.02,materials[3]); allpoints[0].makelabel("0"); allpoints[1].makelabel("1"); allpoints[2].makelabel("2"); allpoints[3].makelabel("3"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 2, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(3, 2, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(1, 2, 3, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[3].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_2').style.position = 'absolute'; document.getElementById('settings_2').style.display = 'block'; document.getElementById('showSettingsButton_2').style.display = 'none'; document.getElementById('hideSettingsButton_2').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_2').style.display = 'none'; document.getElementById('hideSettingsButton_2').style.display = 'none'; document.getElementById('showSettingsButton_2').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab_2').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_2').style.display = 'block'; document.getElementById('transparencyRange_2').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_2').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_2').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_2').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_2'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_2'); if (tempobj) { tempobj.oninput = triggerExplode; document.getElementById('explodeCheckbox_2').onchange = triggerAutomaticExplode; document.getElementById('explodingSpeedRange_2').oninput = setExplodingSpeed; } tempobj = document.getElementById('foldRange_2'); if (tempobj) { tempobj.oninput = fold; } document.getElementById('transparencyRange_2').oninput = changeTransparency; document.getElementById('changeRotationX_2').onchange = changeRotationX; document.getElementById('changeRotationY_2').onchange = changeRotationY; document.getElementById('changeRotationZ_2').onchange = changeRotationZ; document.getElementById('resetButton_2').onclick = resetScene; document.getElementById('rotationSpeedRange_2').oninput = changeRotationSpeedFactor; document.getElementById('labelsCheckboxInput_2').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_2').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_2').onclick = showSettings; document.getElementById('hideSettingsButton_2').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_2').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_2').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> The following line produces the same picture but each color is specified using a different color format: <code> polytope > simplex(3)->VISUAL(VertexColor=>['red','0 1 0',new RGB(0,0,1),'255 255 0']); </code> See [[visual_tutorial#Specifying%20Colors|]] for different ways to specify colors. **Function**: You may also pass a function, i.e. a perl ''%%sub%%'', to the //VertexColors// attribute that returns a color depending on the vertex index. The following line produces a tetrahedron with colors ranging from black for vertex 0 to yellow for vertex 3: <code> polytope > simplex(3)->VISUAL(VertexColor=> sub { $i = shift; new RGB($i*0.33,$i*0.33,0); }); </code> {{:tutorials:release:4.1:visual_tutorial:visual_vertexcolor_sub.jpg}} === Labels === The labels can be specified either by an array or a function that returns a label depending on the index of the vertex. %%**%% Array of labels %%**%%: To label the vertices of a tetrahedron by A, B, C, and D we just pass the array ''%%["A", "B", "C", "D"]%%'' to the //VertexLabels// attribute: <code perl> > simplex(3)->VISUAL(VertexLabels=>["A", "B", "C", "D"]); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 unnamed --> <html> <head> <title>unnamed</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_3' class='settings'> <div class=group id='transparency_3' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_3' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_3'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_3'> x-axis</div> <div><input type='checkbox' id='changeRotationY_3'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_3'> z-axis</div> <button id='resetButton_3' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_3' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_3'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_3' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_3' checked>Labels</div> </div> </div> <div class=group id='svg_3'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_3' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_3' > New tab<br> </form> <button id='takeScreenshot_3'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_3' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_3' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model4454048871"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model4454048871' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model4454048871'); // 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 objectnames = ["unnamed__1"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(1, 0, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(0, 0, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0xFF0000, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.02,points_material); allpoints[1].makesphere(0.02,points_material); allpoints[2].makesphere(0.02,points_material); allpoints[3].makesphere(0.02,points_material); allpoints[0].makelabel("A"); allpoints[1].makelabel("B"); allpoints[2].makelabel("C"); allpoints[3].makelabel("D"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 2, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(3, 2, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(1, 2, 3, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[3].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_3').style.position = 'absolute'; document.getElementById('settings_3').style.display = 'block'; document.getElementById('showSettingsButton_3').style.display = 'none'; document.getElementById('hideSettingsButton_3').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_3').style.display = 'none'; document.getElementById('hideSettingsButton_3').style.display = 'none'; document.getElementById('showSettingsButton_3').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab_3').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_3').style.display = 'block'; document.getElementById('transparencyRange_3').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_3').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_3').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_3').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_3'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_3'); if (tempobj) { tempobj.oninput = triggerExplode; document.getElementById('explodeCheckbox_3').onchange = triggerAutomaticExplode; document.getElementById('explodingSpeedRange_3').oninput = setExplodingSpeed; } tempobj = document.getElementById('foldRange_3'); if (tempobj) { tempobj.oninput = fold; } document.getElementById('transparencyRange_3').oninput = changeTransparency; document.getElementById('changeRotationX_3').onchange = changeRotationX; document.getElementById('changeRotationY_3').onchange = changeRotationY; document.getElementById('changeRotationZ_3').onchange = changeRotationZ; document.getElementById('resetButton_3').onclick = resetScene; document.getElementById('rotationSpeedRange_3').oninput = changeRotationSpeedFactor; document.getElementById('labelsCheckboxInput_3').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_3').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_3').onclick = showSettings; document.getElementById('hideSettingsButton_3').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_3').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_3').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> If you want to set only one label for example, you can do so by passing the empty string ''%%""%%'' for the other vertices: <code perl> > simplex(3)->VISUAL(VertexLabels=>["", "", "My favorite vertex", ""]); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 unnamed --> <html> <head> <title>unnamed</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_4' class='settings'> <div class=group id='transparency_4' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_4' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_4'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_4'> x-axis</div> <div><input type='checkbox' id='changeRotationY_4'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_4'> z-axis</div> <button id='resetButton_4' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_4' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_4'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_4' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_4' checked>Labels</div> </div> </div> <div class=group id='svg_4'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_4' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_4' > New tab<br> </form> <button id='takeScreenshot_4'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_4' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_4' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model41028836871"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model41028836871' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model41028836871'); // 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 objectnames = ["unnamed__1"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(1, 0, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(0, 0, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0xFF0000, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.02,points_material); allpoints[1].makesphere(0.02,points_material); allpoints[2].makesphere(0.02,points_material); allpoints[3].makesphere(0.02,points_material); allpoints[0].makelabel(""); allpoints[1].makelabel(""); allpoints[2].makelabel("My favorite vertex"); allpoints[3].makelabel(""); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 2, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(3, 2, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(1, 2, 3, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[3].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_4').style.position = 'absolute'; document.getElementById('settings_4').style.display = 'block'; document.getElementById('showSettingsButton_4').style.display = 'none'; document.getElementById('hideSettingsButton_4').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_4').style.display = 'none'; document.getElementById('hideSettingsButton_4').style.display = 'none'; document.getElementById('showSettingsButton_4').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab_4').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_4').style.display = 'block'; document.getElementById('transparencyRange_4').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_4').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_4').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_4').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_4'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_4'); if (tempobj) { tempobj.oninput = triggerExplode; document.getElementById('explodeCheckbox_4').onchange = triggerAutomaticExplode; document.getElementById('explodingSpeedRange_4').oninput = setExplodingSpeed; } tempobj = document.getElementById('foldRange_4'); if (tempobj) { tempobj.oninput = fold; } document.getElementById('transparencyRange_4').oninput = changeTransparency; document.getElementById('changeRotationX_4').onchange = changeRotationX; document.getElementById('changeRotationY_4').onchange = changeRotationY; document.getElementById('changeRotationZ_4').onchange = changeRotationZ; document.getElementById('resetButton_4').onclick = resetScene; document.getElementById('rotationSpeedRange_4').oninput = changeRotationSpeedFactor; document.getElementById('labelsCheckboxInput_4').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_4').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_4').onclick = showSettings; document.getElementById('hideSettingsButton_4').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_4').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_4').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> %%**%% Function %%**%%: We may also write a perl function that returns a label depending on the index of the vertex. For example, if we want to label the vertices by their coordinates, we can use the following commands: <code perl> > $tet = simplex(3); > $tet->VISUAL(VertexLabels=> sub { my $i = shift; return $tet->VERTICES->[$i]; }); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 tet --> <html> <head> <title>tet</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_5' class='settings'> <div class=group id='transparency_5' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_5' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_5'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_5'> x-axis</div> <div><input type='checkbox' id='changeRotationY_5'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_5'> z-axis</div> <button id='resetButton_5' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_5' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_5'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_5' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_5' checked>Labels</div> </div> </div> <div class=group id='svg_5'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_5' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_5' > New tab<br> </form> <button id='takeScreenshot_5'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_5' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_5' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model35848103695"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model35848103695' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model35848103695'); // 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 objectnames = ["tet"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(1, 0, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(0, 0, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0xFF0000, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.02,points_material); allpoints[1].makesphere(0.02,points_material); allpoints[2].makesphere(0.02,points_material); allpoints[3].makesphere(0.02,points_material); allpoints[0].makelabel("(4) (0 1)"); allpoints[1].makelabel("1 1 0 0"); allpoints[2].makelabel("1 0 1 0"); allpoints[3].makelabel("1 0 0 1"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 2, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(3, 2, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(1, 2, 3, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[3].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_5').style.position = 'absolute'; document.getElementById('settings_5').style.display = 'block'; document.getElementById('showSettingsButton_5').style.display = 'none'; document.getElementById('hideSettingsButton_5').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_5').style.display = 'none'; document.getElementById('hideSettingsButton_5').style.display = 'none'; document.getElementById('showSettingsButton_5').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab_5').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_5').style.display = 'block'; document.getElementById('transparencyRange_5').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_5').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_5').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_5').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_5'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_5'); if (tempobj) { tempobj.oninput = triggerExplode; document.getElementById('explodeCheckbox_5').onchange = triggerAutomaticExplode; document.getElementById('explodingSpeedRange_5').oninput = setExplodingSpeed; } tempobj = document.getElementById('foldRange_5'); if (tempobj) { tempobj.oninput = fold; } document.getElementById('transparencyRange_5').oninput = changeTransparency; document.getElementById('changeRotationX_5').onchange = changeRotationX; document.getElementById('changeRotationY_5').onchange = changeRotationY; document.getElementById('changeRotationZ_5').onchange = changeRotationZ; document.getElementById('resetButton_5').onclick = resetScene; document.getElementById('rotationSpeedRange_5').oninput = changeRotationSpeedFactor; document.getElementById('labelsCheckboxInput_5').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_5').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_5').onclick = showSettings; document.getElementById('hideSettingsButton_5').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_5').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_5').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> If you prefer dehomogenized float coordinates, then you need to use: <code perl> > $tet->VISUAL(VertexLabels=> sub { my $i = shift; return convert_to<Float>(dehomogenize($tet->VERTICES->[$i]));}); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 tet --> <html> <head> <title>tet</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_6' class='settings'> <div class=group id='transparency_6' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_6' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_6'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_6'> x-axis</div> <div><input type='checkbox' id='changeRotationY_6'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_6'> z-axis</div> <button id='resetButton_6' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_6' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_6'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_6' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_6' checked>Labels</div> </div> </div> <div class=group id='svg_6'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_6' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_6' > New tab<br> </form> <button id='takeScreenshot_6'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_6' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_6' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model76677303937"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model76677303937' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model76677303937'); // 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 objectnames = ["tet"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(1, 0, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(0, 0, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0xFF0000, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.02,points_material); allpoints[1].makesphere(0.02,points_material); allpoints[2].makesphere(0.02,points_material); allpoints[3].makesphere(0.02,points_material); allpoints[0].makelabel("(3)"); allpoints[1].makelabel("(3) (0 1)"); allpoints[2].makelabel("(3) (1 1)"); allpoints[3].makelabel("(3) (2 1)"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 2, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(3, 2, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(1, 2, 3, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[3].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_6').style.position = 'absolute'; document.getElementById('settings_6').style.display = 'block'; document.getElementById('showSettingsButton_6').style.display = 'none'; document.getElementById('hideSettingsButton_6').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_6').style.display = 'none'; document.getElementById('hideSettingsButton_6').style.display = 'none'; document.getElementById('showSettingsButton_6').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab_6').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_6').style.display = 'block'; document.getElementById('transparencyRange_6').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_6').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_6').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_6').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_6'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_6'); if (tempobj) { tempobj.oninput = triggerExplode; document.getElementById('explodeCheckbox_6').onchange = triggerAutomaticExplode; document.getElementById('explodingSpeedRange_6').oninput = setExplodingSpeed; } tempobj = document.getElementById('foldRange_6'); if (tempobj) { tempobj.oninput = fold; } document.getElementById('transparencyRange_6').oninput = changeTransparency; document.getElementById('changeRotationX_6').onchange = changeRotationX; document.getElementById('changeRotationY_6').onchange = changeRotationY; document.getElementById('changeRotationZ_6').onchange = changeRotationZ; document.getElementById('resetButton_6').onclick = resetScene; document.getElementById('rotationSpeedRange_6').oninput = changeRotationSpeedFactor; document.getElementById('labelsCheckboxInput_6').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_6').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_6').onclick = showSettings; document.getElementById('hideSettingsButton_6').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_6').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_6').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> === Vertex Size === Similar to changing the colors using the //VertexColor// attribute you are able to change the sizes of the vertices via the //VertexThickness//\\ attribute. Again, you may set the sizes of all vertices by a single value or use an array or a function to specify individual sizes. %%**%% Single size %%**%%: To increase the size of the vertices, just pass a number larger than 1 to the //VertexThickness// <code perl> > simplex(3)->VISUAL(VertexThickness=>2); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 unnamed --> <html> <head> <title>unnamed</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_7' class='settings'> <div class=group id='transparency_7' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_7' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_7'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_7'> x-axis</div> <div><input type='checkbox' id='changeRotationY_7'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_7'> z-axis</div> <button id='resetButton_7' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_7' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_7'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_7' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_7' checked>Labels</div> </div> </div> <div class=group id='svg_7'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_7' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_7' > New tab<br> </form> <button id='takeScreenshot_7'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_7' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_7' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model8718930957"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model8718930957' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model8718930957'); // 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 objectnames = ["unnamed__1"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(1, 0, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(0, 0, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0xFF0000, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.04,points_material); allpoints[1].makesphere(0.04,points_material); allpoints[2].makesphere(0.04,points_material); allpoints[3].makesphere(0.04,points_material); allpoints[0].makelabel("0"); allpoints[1].makelabel("1"); allpoints[2].makelabel("2"); allpoints[3].makelabel("3"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 2, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(3, 2, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(1, 2, 3, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[3].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_7').style.position = 'absolute'; document.getElementById('settings_7').style.display = 'block'; document.getElementById('showSettingsButton_7').style.display = 'none'; document.getElementById('hideSettingsButton_7').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_7').style.display = 'none'; document.getElementById('hideSettingsButton_7').style.display = 'none'; document.getElementById('showSettingsButton_7').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab_7').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_7').style.display = 'block'; document.getElementById('transparencyRange_7').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_7').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_7').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_7').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_7'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_7'); if (tempobj) { tempobj.oninput = triggerExplode; document.getElementById('explodeCheckbox_7').onchange = triggerAutomaticExplode; document.getElementById('explodingSpeedRange_7').oninput = setExplodingSpeed; } tempobj = document.getElementById('foldRange_7'); if (tempobj) { tempobj.oninput = fold; } document.getElementById('transparencyRange_7').oninput = changeTransparency; document.getElementById('changeRotationX_7').onchange = changeRotationX; document.getElementById('changeRotationY_7').onchange = changeRotationY; document.getElementById('changeRotationZ_7').onchange = changeRotationZ; document.getElementById('resetButton_7').onclick = resetScene; document.getElementById('rotationSpeedRange_7').oninput = changeRotationSpeedFactor; document.getElementById('labelsCheckboxInput_7').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_7').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_7').onclick = showSettings; document.getElementById('hideSettingsButton_7').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_7').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_7').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> %%**%% Array of sizes %%**%%: As in the case of colors and labels, you may also specify individual sizes using an array: <code perl> > simplex(3)->VISUAL(VertexThickness=>[1,2,3,4]); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 unnamed --> <html> <head> <title>unnamed</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_8' class='settings'> <div class=group id='transparency_8' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_8' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_8'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_8'> x-axis</div> <div><input type='checkbox' id='changeRotationY_8'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_8'> z-axis</div> <button id='resetButton_8' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_8' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_8'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_8' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_8' checked>Labels</div> </div> </div> <div class=group id='svg_8'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_8' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_8' > New tab<br> </form> <button id='takeScreenshot_8'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_8' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_8' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model46843192958"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model46843192958' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model46843192958'); // 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 objectnames = ["unnamed__1"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(1, 0, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(0, 0, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0xFF0000, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.02,points_material); allpoints[1].makesphere(0.04,points_material); allpoints[2].makesphere(0.06,points_material); allpoints[3].makesphere(0.08,points_material); allpoints[0].makelabel("0"); allpoints[1].makelabel("1"); allpoints[2].makelabel("2"); allpoints[3].makelabel("3"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 2, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(3, 2, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(1, 2, 3, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[3].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_8').style.position = 'absolute'; document.getElementById('settings_8').style.display = 'block'; document.getElementById('showSettingsButton_8').style.display = 'none'; document.getElementById('hideSettingsButton_8').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_8').style.display = 'none'; document.getElementById('hideSettingsButton_8').style.display = 'none'; document.getElementById('showSettingsButton_8').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab_8').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_8').style.display = 'block'; document.getElementById('transparencyRange_8').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_8').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_8').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_8').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_8'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_8'); if (tempobj) { tempobj.oninput = triggerExplode; document.getElementById('explodeCheckbox_8').onchange = triggerAutomaticExplode; document.getElementById('explodingSpeedRange_8').oninput = setExplodingSpeed; } tempobj = document.getElementById('foldRange_8'); if (tempobj) { tempobj.oninput = fold; } document.getElementById('transparencyRange_8').oninput = changeTransparency; document.getElementById('changeRotationX_8').onchange = changeRotationX; document.getElementById('changeRotationY_8').onchange = changeRotationY; document.getElementById('changeRotationZ_8').onchange = changeRotationZ; document.getElementById('resetButton_8').onclick = resetScene; document.getElementById('rotationSpeedRange_8').oninput = changeRotationSpeedFactor; document.getElementById('labelsCheckboxInput_8').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_8').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_8').onclick = showSettings; document.getElementById('hideSettingsButton_8').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_8').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_8').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> %%**%% Function %%**%%: You may define a function that returns the size of the vertex depending on the vertex index. The following\\ example sets the size of the odd vertices to 1 and the sizes of the even vertices to 2: <code perl> > cube(3)->VISUAL(VertexThickness=> sub { my $i = shift; if($i%2 == 0) { return 2; } else {return 1;} }); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 unnamed --> <html> <head> <title>unnamed</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_9' class='settings'> <div class=group id='transparency_9' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_9' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_9'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_9'> x-axis</div> <div><input type='checkbox' id='changeRotationY_9'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_9'> z-axis</div> <button id='resetButton_9' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_9' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_9'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_9' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_9' checked>Labels</div> </div> </div> <div class=group id='svg_9'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_9' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_9' > New tab<br> </form> <button id='takeScreenshot_9'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_9' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_9' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model9835514711"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model9835514711' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model9835514711'); // 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 objectnames = ["unnamed__1"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(-1, -1, -1)); allpoints.push(new PMPoint(1, -1, -1)); allpoints.push(new PMPoint(-1, 1, -1)); allpoints.push(new PMPoint(1, 1, -1)); allpoints.push(new PMPoint(-1, -1, 1)); allpoints.push(new PMPoint(1, -1, 1)); allpoints.push(new PMPoint(-1, 1, 1)); allpoints.push(new PMPoint(1, 1, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0xFF0000, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.04,points_material); allpoints[1].makesphere(0.02,points_material); allpoints[2].makesphere(0.04,points_material); allpoints[3].makesphere(0.02,points_material); allpoints[4].makesphere(0.04,points_material); allpoints[5].makesphere(0.02,points_material); allpoints[6].makesphere(0.04,points_material); allpoints[7].makesphere(0.02,points_material); allpoints[0].makelabel("0"); allpoints[1].makelabel("1"); allpoints[2].makelabel("2"); allpoints[3].makelabel("3"); allpoints[4].makelabel("4"); allpoints[5].makelabel("5"); allpoints[6].makelabel("6"); allpoints[7].makelabel("7"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); faces.vertices.push(allpoints[4].vector); faces.vertices.push(allpoints[5].vector); faces.vertices.push(allpoints[6].vector); faces.vertices.push(allpoints[7].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 4, 6, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 6, 2, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(7, 5, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(7, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(5, 4, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(5, 0, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(2, 6, 7, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(2, 7, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 2, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 3, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(6, 4, 5, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(6, 5, 7, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[7].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[5].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[6].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_9').style.position = 'absolute'; document.getElementById('settings_9').style.display = 'block'; document.getElementById('showSettingsButton_9').style.display = 'none'; document.getElementById('hideSettingsButton_9').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_9').style.display = 'none'; document.getElementById('hideSettingsButton_9').style.display = 'none'; document.getElementById('showSettingsButton_9').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab_9').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_9').style.display = 'block'; document.getElementById('transparencyRange_9').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_9').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_9').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_9').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_9'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_9'); if (tempobj) { tempobj.oninput = triggerExplode; document.getElementById('explodeCheckbox_9').onchange = triggerAutomaticExplode; document.getElementById('explodingSpeedRange_9').oninput = setExplodingSpeed; } tempobj = document.getElementById('foldRange_9'); if (tempobj) { tempobj.oninput = fold; } document.getElementById('transparencyRange_9').oninput = changeTransparency; document.getElementById('changeRotationX_9').onchange = changeRotationX; document.getElementById('changeRotationY_9').onchange = changeRotationY; document.getElementById('changeRotationZ_9').onchange = changeRotationZ; document.getElementById('resetButton_9').onclick = resetScene; document.getElementById('rotationSpeedRange_9').oninput = changeRotationSpeedFactor; document.getElementById('labelsCheckboxInput_9').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_9').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_9').onclick = showSettings; document.getElementById('hideSettingsButton_9').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_9').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_9').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> If you do not want to display the vertices at all, you can use the //VertexStyle// attribute and set it to ''%%hidden%%'': <code perl> > cube(3)->VISUAL(VertexStyle=>"hidden"); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 unnamed --> <html> <head> <title>unnamed</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_10' class='settings'> <div class=group id='transparency_10' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_10' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_10'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_10'> x-axis</div> <div><input type='checkbox' id='changeRotationY_10'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_10'> z-axis</div> <button id='resetButton_10' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_10' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_10'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_10' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_10' checked>Labels</div> </div> </div> <div class=group id='svg_10'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_10' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_10' > New tab<br> </form> <button id='takeScreenshot_10'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_10' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_10' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model25144528692"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model25144528692' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model25144528692'); // 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 objectnames = ["unnamed__1"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(-1, -1, -1)); allpoints.push(new PMPoint(1, -1, -1)); allpoints.push(new PMPoint(-1, 1, -1)); allpoints.push(new PMPoint(1, 1, -1)); allpoints.push(new PMPoint(-1, -1, 1)); allpoints.push(new PMPoint(1, -1, 1)); allpoints.push(new PMPoint(-1, 1, 1)); allpoints.push(new PMPoint(1, 1, 1)); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); faces.vertices.push(allpoints[4].vector); faces.vertices.push(allpoints[5].vector); faces.vertices.push(allpoints[6].vector); faces.vertices.push(allpoints[7].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 4, 6, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 6, 2, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(7, 5, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(7, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(5, 4, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(5, 0, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(2, 6, 7, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(2, 7, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 2, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 3, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(6, 4, 5, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(6, 5, 7, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[7].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[5].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[6].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_10').style.position = 'absolute'; document.getElementById('settings_10').style.display = 'block'; document.getElementById('showSettingsButton_10').style.display = 'none'; document.getElementById('hideSettingsButton_10').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_10').style.display = 'none'; document.getElementById('hideSettingsButton_10').style.display = 'none'; document.getElementById('showSettingsButton_10').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab_10').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_10').style.display = 'block'; document.getElementById('transparencyRange_10').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_10').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_10').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_10').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_10'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_10'); if (tempobj) { tempobj.oninput = triggerExplode; document.getElementById('explodeCheckbox_10').onchange = triggerAutomaticExplode; document.getElementById('explodingSpeedRange_10').oninput = setExplodingSpeed; } tempobj = document.getElementById('foldRange_10'); if (tempobj) { tempobj.oninput = fold; } document.getElementById('transparencyRange_10').oninput = changeTransparency; document.getElementById('changeRotationX_10').onchange = changeRotationX; document.getElementById('changeRotationY_10').onchange = changeRotationY; document.getElementById('changeRotationZ_10').onchange = changeRotationZ; document.getElementById('resetButton_10').onclick = resetScene; document.getElementById('rotationSpeedRange_10').oninput = changeRotationSpeedFactor; document.getElementById('labelsCheckboxInput_10').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_10').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_10').onclick = showSettings; document.getElementById('hideSettingsButton_10').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_10').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_10').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> ==== Visualizing multiple polytopes ==== The following sequence creates a 0/1-cube and a translate. The final command triggers the joint visualization of both. <code perl> > $c1=cube(3,0); > $c2=transform($c1,new Matrix<Rational>([[1,-1,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]])); > compose($c1->VISUAL,$c2->VISUAL); </code> <HTML> <div class="threejs_output"><!-- polymake for knusper Sun May 10 04:34:00 2020 c1 --> <html> <head> <title>c1</title> <style> /* // COMMON_CODE_BLOCK_BEGIN */ html{overflow: scroll;} .threejs_output { font-family: Arial, Helvetica, sans-serif} strong{font-size: 18px;} canvas { z-index: 8; } input[type='range'] {} input[type='radio'] {margin-left:0;} input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;} .group{padding-bottom: 40px;} .settings * {z-index: 11; } .settings{z-index: 10; margin-left: 30px; display: none; width: 14em; height: 90%; border: solid 1px silver; padding: 2px; overflow-y: scroll; background-color: white } .indented{margin-left: 20px; margin-top: 15px; padding-bottom: 0px;} .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;} .showSettingsButton{display: block; z-index: 12; position: absolute } .hideSettingsButton{display: none; z-index: 12; position: absolute; opacity: 0.5} .resetButton{margin-top: 20px;} button{margin-left: 0;} img{cursor: pointer;} .suboption{padding-top: 30px;} .transparency{display: none;} .labelsCheckbox{margin-top: 10px;} input[type=range] { -webkit-appearance: none; padding:0; width:90%; margin-left: auto; margin-right: auto; margin-top: 20px; 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_11' class='settings'> <div class=group id='explode_11'> <strong>Explode</strong> <input id='explodeRange_11' type='range' min=0 max=6 step=0.01 value=0> <div class=indented><input id='explodeCheckbox_11' type='checkbox'>Automatic explosion</div> <div class=suboption>Exploding speed</div> <input id='explodingSpeedRange_11' type='range' min=0 max=0.5 step=0.001 value=0.05> </div> <div class=group id='transparency_11' class='transparency'> <strong>Transparency</strong> <input id='transparencyRange_11' type='range' min=0 max=1 step=0.01 value=0> </div> <div class=group id='rotation_11'> <strong>Rotation</strong> <div class=indented> <div><input type='checkbox' id='changeRotationX_11'> x-axis</div> <div><input type='checkbox' id='changeRotationY_11'> y-axis</div> <div><input type='checkbox' id='changeRotationZ_11'> z-axis</div> <button id='resetButton_11' class='resetButton' >Reset</button> </div> <div class=suboption>Rotation speed</div> <input id='rotationSpeedRange_11' type='range' min=0 max=5 step=0.01 value=2> </div> <div class=group id='display_11'> <strong>Display</strong> <div class=indented> <div id='shownObjectsList_11' class='shownObjectsList'></div> <div class='labelsCheckbox'><input type='checkbox' id='labelsCheckboxInput_11' checked>Labels</div> </div> </div> <div class=group id='svg_11'> <strong>SVG</strong> <div class=indented> <form> <input type="radio" name='screenshotMode' value='download' id='download_11' checked> Download<br> <input type="radio" name='screenshotMode' value='tab' id='tab_11' > New tab<br> </form> <button id='takeScreenshot_11'>Screenshot</button> </div> </div> </div> <!-- end of settings --> <img id='hideSettingsButton_11' style="display: none" class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px"> <img id='showSettingsButton_11' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px"> <div id="model15699227060"></div> <script> requirejs.config({ paths: { three: '/kernelspecs/polymake/three', Detector: '/kernelspecs/polymake/Detector', SVGRenderer: '/kernelspecs/polymake/SVGRenderer', CanvasRenderer: '/kernelspecs/polymake/CanvasRenderer', Projector: '/kernelspecs/polymake/Projector', TrackballControls: '/kernelspecs/polymake/TrackballControls' }, shim: { 'three': { exports: 'THREE' }, 'Detector': { deps: [ 'three' ], exports: 'Detector' }, 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' }, 'CanvasRenderer': { deps: [ 'three' ], exports: 'THREE.CanvasRenderer' }, 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' }, 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' } } }); require(['three'],function(THREE){ window.THREE = THREE; require(['Detector','SVGRenderer','CanvasRenderer','Projector','TrackballControls'],function(Detector,SVGRenderer,CanvasRenderer,Projector,TrackballControls){ THREE.SVGRenderer = SVGRenderer; THREE.CanvasRenderer = CanvasRenderer; THREE.Projector = Projector; THREE.TrackballControls = TrackballControls; // COMMON_CODE_BLOCK_BEGIN var foldable = false; var container = document.getElementById( 'model15699227060' ); var renderer = Detector.webgl? new THREE.WebGLRenderer({antialias: true}): new THREE.CanvasRenderer({antialias: true}); var svgRenderer = new THREE.SVGRenderer({antialias: true}); var box = document.getElementsByClassName( 'threejs_output' )[0]; var width = box.clientWidth; var height = box.clientHeight; renderer.setSize(width, height); svgRenderer.setSize(width, height); renderer.setClearColor(0xFFFFFF, 1); svgRenderer.setClearColor(0xFFFFFF, 1); container.appendChild(renderer.domElement); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); var renderid; camera.position.set(0, 0, 5); camera.lookAt(0, 0, 0); camera.up.set(0, 1, 0); // 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.makelabel = function(label) { this.sprite = textSprite( label ); this.sprite.position.copy(this.vector); } PMPoint.prototype.makesphere = function(radius,material) { this.sphere = new THREE.Mesh(new THREE.SphereGeometry(radius), material); this.sphere.position.copy(this.vector); } PMPoint.prototype.setX = function(x) { this.vector.setX(x); if (this.sprite) { this.sprite.position.setX(x); } if (this.sphere) { this.sphere.position.setX(x); } }; PMPoint.prototype.setY = function(y) { this.vector.setY(y); if (this.sprite) { this.sprite.position.setY(y); } if (this.sphere) { this.sphere.position.setY(y); } }; PMPoint.prototype.setZ = function(z) { this.vector.setZ(z); if (this.sprite) { this.sprite.position.setZ(z); } if (this.sphere) { this.sphere.position.setZ(z); } }; PMPoint.prototype.set = function(x,y,z) { this.vector.set(x,y,z); if (this.sprite) { this.sprite.position.set(x,y,z); } if (this.sphere) { this.sphere.position.set(x,y,z); } }; PMPoint.prototype.add = function(o) { if (this.sprite) { o.add(this.sprite); } if (this.sphere) { o.add(this.sphere); } }; var controls = new THREE.TrackballControls(camera, container); controls.zoomSpeed = 0.2; controls.rotateSpeed = 4; var all_objects = []; var centroids = []; // select the target node var target = document.querySelector('#model15699227060'); // 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 objectnames = ["c1","c2"]; var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(1, 0, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(1, 1, 0)); allpoints.push(new PMPoint(0, 0, 1)); allpoints.push(new PMPoint(1, 0, 1)); allpoints.push(new PMPoint(0, 1, 1)); allpoints.push(new PMPoint(1, 1, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0xFF0000, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.02,points_material); allpoints[1].makesphere(0.02,points_material); allpoints[2].makesphere(0.02,points_material); allpoints[3].makesphere(0.02,points_material); allpoints[4].makesphere(0.02,points_material); allpoints[5].makesphere(0.02,points_material); allpoints[6].makesphere(0.02,points_material); allpoints[7].makesphere(0.02,points_material); allpoints[0].makelabel("0"); allpoints[1].makelabel("1"); allpoints[2].makelabel("2"); allpoints[3].makelabel("3"); allpoints[4].makelabel("4"); allpoints[5].makelabel("5"); allpoints[6].makelabel("6"); allpoints[7].makelabel("7"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); faces.vertices.push(allpoints[4].vector); faces.vertices.push(allpoints[5].vector); faces.vertices.push(allpoints[6].vector); faces.vertices.push(allpoints[7].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 4, 6, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 6, 2, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(7, 5, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(7, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(5, 4, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(5, 0, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(2, 6, 7, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(2, 7, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 2, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 3, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(6, 4, 5, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(6, 5, 7, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[7].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[5].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[6].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); var obj = new THREE.Object3D(); var allpoints = []; allpoints.push(new PMPoint(-1, 0, 0)); allpoints.push(new PMPoint(0, 0, 0)); allpoints.push(new PMPoint(-1, 1, 0)); allpoints.push(new PMPoint(0, 1, 0)); allpoints.push(new PMPoint(-1, 0, 1)); allpoints.push(new PMPoint(0, 0, 1)); allpoints.push(new PMPoint(-1, 1, 1)); allpoints.push(new PMPoint(0, 1, 1)); <!-- Vertex style --> var points_material = new THREE.MeshBasicMaterial ( {color: 0xFF0000, } ); points_material.side = THREE.DoubleSide; points_material.transparent = true; <!-- POINTS --> allpoints[0].makesphere(0.02,points_material); allpoints[1].makesphere(0.02,points_material); allpoints[2].makesphere(0.02,points_material); allpoints[3].makesphere(0.02,points_material); allpoints[4].makesphere(0.02,points_material); allpoints[5].makesphere(0.02,points_material); allpoints[6].makesphere(0.02,points_material); allpoints[7].makesphere(0.02,points_material); allpoints[0].makelabel("0"); allpoints[1].makelabel("1"); allpoints[2].makelabel("2"); allpoints[3].makelabel("3"); allpoints[4].makelabel("4"); allpoints[5].makelabel("5"); allpoints[6].makelabel("6"); allpoints[7].makelabel("7"); for (index = 0; index < allpoints.length; ++index) { allpoints[index].add(obj); } var faces = new THREE.Geometry(); <!-- VERTICES --> faces.vertices.push(allpoints[0].vector); faces.vertices.push(allpoints[1].vector); faces.vertices.push(allpoints[2].vector); faces.vertices.push(allpoints[3].vector); faces.vertices.push(allpoints[4].vector); faces.vertices.push(allpoints[5].vector); faces.vertices.push(allpoints[6].vector); faces.vertices.push(allpoints[7].vector); centroids.push(computeCentroid(faces)); <!-- Facet style --> var faces_material = new THREE.MeshBasicMaterial ( {color: 0x77EC9E, transparent: true, opacity: 1, side: THREE.DoubleSide , depthWrite: true, depthTest: true, } ); faces_material.side = THREE.DoubleSide; faces_material.transparent = true; <!-- FACETS --> faces.faces.push(new THREE.Face3(0, 4, 6, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 6, 2, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(7, 5, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(7, 1, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(5, 4, 0, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(5, 0, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(2, 6, 7, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(2, 7, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 2, 3, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(0, 3, 1, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(6, 4, 5, undefined, undefined, 0)); faces.faces.push(new THREE.Face3(6, 5, 7, undefined, undefined, 0)); faces.computeFaceNormals(); faces.computeVertexNormals(); var object = new THREE.Mesh(faces, faces_material); obj.add(object); <!-- Edge style --> var line_material = new THREE.LineBasicMaterial ( {color: 0x000000, linewidth: 1.5, } ); line_material.side = THREE.DoubleSide; line_material.transparent = true; <!-- EDGES --> var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[7].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[5].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[2].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[0].vector); line.vertices.push(allpoints[2].vector); line.vertices.push(allpoints[3].vector); line.vertices.push(allpoints[1].vector); line.vertices.push(allpoints[0].vector); obj.add(new THREE.Line(line, line_material)); var line = new THREE.Geometry(); line.vertices.push(allpoints[6].vector); line.vertices.push(allpoints[4].vector); line.vertices.push(allpoints[5].vector); line.vertices.push(allpoints[7].vector); line.vertices.push(allpoints[6].vector); obj.add(new THREE.Line(line, line_material)); scene.add(obj); all_objects.push(obj); // COMMON_CODE_BLOCK_BEGIN 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; } controls.update(); renderer.render(scene, camera); }; render(); function computeCentroid(geom) { centroid = new THREE.Vector3(); geom.vertices.forEach(function(v) { centroid.add(v); }); centroid.divideScalar(geom.vertices.length); return centroid; } function changeTransparency(event){ var opacity = 1-Number(event.currentTarget.value); for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ if (all_objects[i].children[j].material.type == "MultiMaterial") { for (var k=0; k<all_objects[i].children[j].material.materials.length; k++){ all_objects[i].children[j].material.materials[k].opacity = opacity; all_objects[i].children[j].material.materials[k].depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.materials[k].depthTest = opacity < 0.5 ? false : true; } } else if (all_objects[i].children[j].material.transparent && all_objects[i].children[j].material.type == "MeshBasicMaterial" && all_objects[i].children[j].geometry.type == "Geometry"){ all_objects[i].children[j].material.opacity = opacity; all_objects[i].children[j].material.depthWrite = opacity < 0.5 ? false : true; all_objects[i].children[j].material.depthTest = opacity < 0.5 ? false : true; } } } } 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){ event.currentTarget.style.display = 'none'; document.getElementById('settings_11').style.position = 'absolute'; document.getElementById('settings_11').style.display = 'block'; document.getElementById('showSettingsButton_11').style.display = 'none'; document.getElementById('hideSettingsButton_11').style.display = 'block'; settingsShown = true; } function hideSettings(event){ event.currentTarget.style.display = 'none'; document.getElementById('settings_11').style.display = 'none'; document.getElementById('hideSettingsButton_11').style.display = 'none'; document.getElementById('showSettingsButton_11').style.display = 'block'; settingsShown = false; } var pos = 150* Math.PI; function updateFactor() { pos++; return Math.sin(.01*pos)+1; } function makelabel(message, x, y, z, params) { var spritey = textSprite( message, params ); spritey.position.set(x, y, z); obj.add(spritey); } function textSprite(message, parameters) { if ( parameters === undefined ) parameters = {}; var fontface = "Helvetica"; var fontsize = parameters.hasOwnProperty("fontsize") ? parameters["fontsize"] : 18; fontsize = fontsize*10; var canvas = document.createElement('canvas'); var size = 1024; canvas.width = size; canvas.height = size; var context = canvas.getContext('2d'); context.font = fontsize + "px " + fontface; // text color context.fillStyle = "rgba(0, 0, 0, 1.0)"; context.fillText(message, size/2, size/2); // canvas contents will be used for a texture var texture = new THREE.Texture(canvas); texture.needsUpdate = true; var spriteMaterial = new THREE.SpriteMaterial( {map: texture, useScreenCoordinates: false}); var sprite = new THREE.Sprite(spriteMaterial); return sprite; } function takeSvgScreenshot(){ if (labelsShown){ hideLabels(); } svgRenderer.render(scene,camera); svgElement = XMLS.serializeToString(svgRenderer.domElement); if (labelsShown){ displayLabels(); } if (document.getElementById('tab_11').checked){ //show in new tab var myWindow = window.open("",""); myWindow.document.body.innerHTML = svgElement; } else{ // download svg file download("screenshot.svg", svgElement); } } function showOrHideObject(event){ var nr = Number(event.currentTarget.name); all_objects[nr].visible = event.currentTarget.checked; } function displayOrHideOptionsRecursive( obj ) { for (var j=0; j<obj.children.length; j++) { var child = obj.children[j]; if (child.material===undefined && child) { displayOrHideOptionsRecursive( child ); } else { if (child.material.type == "MultiMaterial") { for (var k=0; k<child.material.materials.length; k++) { if (child.material.materials[k].transparent) { document.getElementById('transparency_11').style.display = 'block'; document.getElementById('transparencyRange_11').value = 1 - child.material.materials[k].opacity; return; } } } else if ( child.material.transparent && child.material.type == "MeshBasicMaterial" && child.geometry.type == "Geometry"){ document.getElementById('transparency_11').style.display = 'block'; return; } } } } function displayOrHideOptions() { for (var i=0; i<all_objects.length; i++) { var obj = all_objects[i]; displayOrHideOptionsRecursive( obj ); } } displayOrHideOptions() // ---------------------- EXPLOSION ------------------------------------------------ // --------------------------------------------------------------------------------- function explode(factor) { var obj, c; var c0 = centroids[0]; for (var i = 0; i<centroids.length; ++i) { c = centroids[i]; obj = all_objects[all_objects.length - centroids.length + i]; 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_11').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_11').value = explodeScale; } function clearIntervals(){ intervals.forEach(function(interval){ clearInterval(interval); }); intervals = []; timeouts.forEach(function(timeout){ clearTimeout(timeout); }); timeouts = []; } // append checkboxes for displaying or hiding objects var shownObjectsList = document.getElementById('shownObjectsList_11'); for (var i=0; i<all_objects.length; i++){ var objNode = document.createElement('span'); objNode.innerHTML = objectnames[i] + '<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 displayLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = true; } } } } function hideLabels(){ for (var i=0; i<all_objects.length; i++){ for (var j=0; j<all_objects[i].children.length; j++){ var child = all_objects[i].children[j]; if (child.type == 'Sprite'){ child.visible = false; } } } } function displayOrHideLabels(event){ if (event.currentTarget.checked){ displayLabels(); labelsShown = true; } else { hideLabels(); labelsShown = false; } } 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_11'); if (tempobj) { tempobj.oninput = triggerExplode; document.getElementById('explodeCheckbox_11').onchange = triggerAutomaticExplode; document.getElementById('explodingSpeedRange_11').oninput = setExplodingSpeed; } tempobj = document.getElementById('foldRange_11'); if (tempobj) { tempobj.oninput = fold; } document.getElementById('transparencyRange_11').oninput = changeTransparency; document.getElementById('changeRotationX_11').onchange = changeRotationX; document.getElementById('changeRotationY_11').onchange = changeRotationY; document.getElementById('changeRotationZ_11').onchange = changeRotationZ; document.getElementById('resetButton_11').onclick = resetScene; document.getElementById('rotationSpeedRange_11').oninput = changeRotationSpeedFactor; document.getElementById('labelsCheckboxInput_11').onchange = displayOrHideLabels; document.getElementById('takeScreenshot_11').onclick = takeSvgScreenshot; document.getElementById('showSettingsButton_11').onclick = showSettings; document.getElementById('hideSettingsButton_11').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_11').dispatchEvent(event); } else{ document.getElementById('showSettingsButton_11').dispatchEvent(event); } }); if (foldable) moveToBaryCenter(); });}); // COMMON_CODE_BLOCK_END </script> </body> </html> </div> </HTML> If ''%%JavaView%%'' is used for visualization then ''%%Method:Effect:Explode Group of Geometries...%%'' allows to show an explosion. ===== application topaz ===== For information on how to visualize simlicial complexes and other topology-related objects, see [[apps_topaz#visualization|here]]. ===== Backends ===== 'polymake' provides different visualization backends: threejs, svg, jReality, JavaView, povray, postscript and even TikZ and Sketch are supported. ==== TikZ and Sketch ==== Sketch is a script language which produces TikZ output. It is quite sophisticated. There is a interface from polymake to Sketch. <code> :::perl > $my_polytope = cube(3); > sketch($my_polytope->VISUAL,File=>"myfile.sketch"); </code> When you downloaded the Sketch interpreter ([[http://sketch4latex.sourceforge.net/|link]]) you can use it to create your TikZ file via: <code> :::perl sketch myfile.sketch > myfile.tikz </code> The drawback is that the produced TikZ code is quite cryptic and not really readable or editable anymore. If you do want to create TikZ code which is easier to edit afterwards, you might want to use polymake's TikZ interface via: <code> :::perl > tikz($my_polytope->VISUAL,File=>"myfile.tikz"); </code> For a different viewing angle you may use jReality. Rotate the polytope into the position you want and click the ''%%'save view%%''' button on the bottom of the jReality window. Then produce the TikZ or Sketch output. ==== jReality ==== The jReality viewer offers a versatile perspective for your favourite tools on 4 Panel which may be enabled/disabled on the toolbar or using\\ the keyboard shortcuts Alt+Shift+(Up|Down|Left|Right) or the window menu. The "Visualization", "Split geometries", "Content Appearance",\\ and "Navigator" Plugin(usually in the Left- resp. Right-Slot) may be used to change the appearance of the displayed geometry. How to achieve your desired parameters is explained in the following section. === Appearance === There are several objects which control the appearance of a geometry in jreality: - geometry attributes, - appearances at a specific scene graph nodes, and - the content appearance. The most versatile point to set different parameters for the appearance is via geometry attributes. This is needed, for example, if every vertex of the displayed\\ geometry should have its own thickness or color like in VISUAL_GRAPH->VERTEX_COLORS. These may only be edited via jreality's bean-shell, which requires\\ knowledge of the jreality API and in particular the attribute handling. An appearance at a scene graph node (every VISUAL object is put into one of these) may have its own appearance which stores single values for colors/thicknesses\\ of vertices/edges/faces. Hence this does not allow, e.g., to assign a different color to each vertex. But editing is a little easier, since it is possible to use jreality's\\ navigator. The navigator displays the entire scene graph. The polymake part of the scene graph starts with "root->content->Polymake Root". The VISUALs are stored\\ in seperate geometry nodes with its appearances. In each of the appearance you find the RenderingHints and Shader that either inherit properties of the content\\ appearance or override them with their own values. This is already much less tedious than using the beanshell. The content appearance comes into play if no other appearances exist in the content subtree, i.e. neither specific node appearances nor geometry attributes. The\\ sizes/thicknesses set in the content appearance are multiplied with the values of the specified values deeper in the tree, but colors will only apply if nothing else is\\ set. So to be able to change the colors of the faces/edges/vertices of the geometry using the content appearance you need to get rid settings in the other appearances\\ and geometry attributes. This may be done using the "clear attributes" and "clear appearance" item of the polymake menu. === Save View === Clicking the "Save View" button on the bottom of the jReality window attaches a "ViewTransformation" matrix to your object (read [[reference/clients#attachments|this]] if you don't know how attachments work). It contains the transformaiton necessary to convert the coordinates of your object to the coordinates of the (possibly rotated, translated etc. by you in the interactive visualization) object as you currently see it. This information is then used by jReality and Sketch to display the object in exactly that way if you visualize it the next time. user_guide/tutorials/release/4.1/visual_tutorial.txt Last modified: 2020/06/15 13:05by 127.0.0.1