Differences
This shows you the differences between two versions of the page.
— | user_guide:tutorials:latest:regular_subdivisions [2023/11/06 10:57] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ===== Regular subdivisons ===== | ||
+ | |||
+ | //Regular subdivsions// | ||
+ | |||
+ | <code perl> | ||
+ | > $M = new Matrix< | ||
+ | > $w = new Vector< | ||
+ | > $S = new fan:: | ||
+ | > print $S-> | ||
+ | {3 4 5} | ||
+ | {0 1 3 4} | ||
+ | </ | ||
+ | The six points (given by the six rows of the matrix '' | ||
+ | |||
+ | We may visualize the regular subdivision if it is at most three-dimensional. | ||
+ | |||
+ | <code perl> | ||
+ | > $S-> | ||
+ | </ | ||
+ | < | ||
+ | <!-- | ||
+ | polymake for knusper | ||
+ | Thu Mar 3 00:43:52 2022 | ||
+ | pcom:S | ||
+ | --> | ||
+ | |||
+ | |||
+ | < | ||
+ | < | ||
+ | <meta charset=utf-8> | ||
+ | < | ||
+ | < | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | */ | ||
+ | html {overflow: scroll;} | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | # | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_END | ||
+ | */ | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | <div id=' | ||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | <div class=suboption> | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | <select id=" | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | <img id=' | ||
+ | <img id=' | ||
+ | <div id=" | ||
+ | </ | ||
+ | < | ||
+ | requirejs.config({ | ||
+ | paths: { | ||
+ | three: '/ | ||
+ | TrackballControls: | ||
+ | OrbitControls: | ||
+ | Projector: '/ | ||
+ | SVGRenderer: | ||
+ | WEBGL: '/ | ||
+ | }, | ||
+ | shim: { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | }); | ||
+ | | ||
+ | require([' | ||
+ | window.THREE = THREE; | ||
+ | require([' | ||
+ | | ||
+ | THREE.TrackballControls = TrackballControls; | ||
+ | THREE.OrbitControls = OrbitControls; | ||
+ | THREE.Projector = Projector; | ||
+ | THREE.SVGRenderer = SVGRenderer; | ||
+ | THREE.WEBGL = WEBGL; | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | |||
+ | const intervalLength = 25; // for automatic animations | ||
+ | const explodableModel = true; | ||
+ | const modelContains = { points: false, pointlabels: | ||
+ | const foldables = []; | ||
+ | |||
+ | var three = document.getElementById(" | ||
+ | var scene = new THREE.Scene(); | ||
+ | var renderer = new THREE.WebGLRenderer( { antialias: true } ); | ||
+ | var svgRenderer = new THREE.SVGRenderer( { antialias: true } ); | ||
+ | renderer.setPixelRatio( window.devicePixelRatio ); | ||
+ | renderer.setClearColor(0xFFFFFF, | ||
+ | svgRenderer.setClearColor(0xFFFFFF, | ||
+ | three.appendChild(renderer.domElement); | ||
+ | |||
+ | var frustumSize = 4; | ||
+ | var cameras = [new THREE.PerspectiveCamera(75, | ||
+ | cameras.forEach(function(cam) { | ||
+ | cam.position.set(0, | ||
+ | cam.lookAt(0, | ||
+ | cam.up.set(0, | ||
+ | }); | ||
+ | var controls = [new THREE.TrackballControls(cameras[0], | ||
+ | var camera, control; | ||
+ | |||
+ | controls[0].zoomSpeed = 0.2; | ||
+ | controls[0].rotateSpeed = 4; | ||
+ | |||
+ | |||
+ | // class to allow move points together with labels and spheres | ||
+ | var PMPoint = function (x,y,z) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addLabel = function(labelsprite) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addSphere = function(spheremesh) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.set = function(x, | ||
+ | | ||
+ | if (this.sprite) { | ||
+ | this.sprite.position.copy(this.vector); | ||
+ | } | ||
+ | if (this.sphere) { | ||
+ | this.sphere.position.copy(this.vector); | ||
+ | } | ||
+ | } | ||
+ | PMPoint.prototype.radius = function() { | ||
+ | if (this.sphere) { | ||
+ | return this.sphere.geometry.parameters.radius; | ||
+ | } else { | ||
+ | return 0; | ||
+ | } | ||
+ | }; | ||
+ | // select the target node | ||
+ | var target = document.querySelector('# | ||
+ | |||
+ | // create an observer instance | ||
+ | var observer = new MutationObserver(function(mutations) { | ||
+ | | ||
+ | if (mutation.removedNodes && mutation.removedNodes.length > 0) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | }); | ||
+ | }); | ||
+ | |||
+ | // configuration of the observer: | ||
+ | var config = { childList: true, characterData: | ||
+ | |||
+ | // pass in the target node, as well as the observer options | ||
+ | while (target) { | ||
+ | if (target.className==" | ||
+ | observer.observe(target, | ||
+ | break; | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | var obj0 = new THREE.Object3D(); | ||
+ | obj0.name = " | ||
+ | obj0.userData.explodable = 1; | ||
+ | obj0.userData.points = []; | ||
+ | obj0.userData.points.push(new PMPoint(1, 1, 0)); | ||
+ | |||
+ | obj0.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj0.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0x000000, side: THREE.DoubleSide, | ||
+ | obj0.userData.pointlabels = [" | ||
+ | init_object(obj0); | ||
+ | scene.add(obj0); | ||
+ | |||
+ | var obj1 = new THREE.Object3D(); | ||
+ | obj1.name = " | ||
+ | obj1.userData.explodable = 1; | ||
+ | obj1.userData.points = []; | ||
+ | obj1.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(2, 2, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(1, 3, 0)); | ||
+ | |||
+ | obj1.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj1.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj1.userData.pointlabels = [" | ||
+ | obj1.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj1.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj1.userData.facets = [[2, 0, 1]]; | ||
+ | < | ||
+ | obj1.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj1); | ||
+ | scene.add(obj1); | ||
+ | |||
+ | var obj2 = new THREE.Object3D(); | ||
+ | obj2.name = " | ||
+ | obj2.userData.explodable = 1; | ||
+ | obj2.userData.points = []; | ||
+ | obj2.userData.points.push(new PMPoint(0, 0, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(2, 0, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(2, 2, 0)); | ||
+ | |||
+ | obj2.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj2.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj2.userData.pointlabels = [" | ||
+ | obj2.userData.edgeindices = [0, 1, 0, 2, 1, 3, 2, 3]; | ||
+ | < | ||
+ | obj2.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj2.userData.facets = [[1, 3, 2, 0]]; | ||
+ | < | ||
+ | obj2.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj2); | ||
+ | scene.add(obj2); | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | function textSpriteMaterial(message, | ||
+ | if ( parameters === undefined ) parameters = {}; | ||
+ | var fontface = " | ||
+ | var fontsize = parameters.hasOwnProperty(" | ||
+ | fontsize = fontsize*10; | ||
+ | var lines = message.split(' | ||
+ | var size = 512; | ||
+ | for(var i = 0; i< | ||
+ | var tmp = lines[i].length; | ||
+ | while(tmp*fontsize > size){ | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | var canvas = document.createElement(' | ||
+ | canvas.width = size; | ||
+ | canvas.height = size; | ||
+ | var context = canvas.getContext(' | ||
+ | context.fillStyle = " | ||
+ | context.fill(); | ||
+ | context.font = fontsize + "px " + fontface; | ||
+ | | ||
+ | // text color | ||
+ | context.fillStyle = " | ||
+ | | ||
+ | context.fillText(lines[i], | ||
+ | } | ||
+ | | ||
+ | // canvas contents will be used for a texture | ||
+ | var texture = new THREE.Texture(canvas); | ||
+ | texture.needsUpdate = true; | ||
+ | | ||
+ | var spriteMaterial = new THREE.SpriteMaterial({map: | ||
+ | return spriteMaterial; | ||
+ | } | ||
+ | |||
+ | |||
+ | // ---------------------- INITIALIZING OBJECTS-------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function init_object(obj) { | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_points(obj); | ||
+ | modelContains.points = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_pointlabels(obj); | ||
+ | modelContains.pointlabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_lines(obj); | ||
+ | modelContains.lines = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_edgelabels(obj); | ||
+ | modelContains.edgelabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_arrowheads(obj); | ||
+ | modelContains.arrowheads = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_faces(obj); | ||
+ | modelContains.faces = true; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function init_points(obj) { | ||
+ | var pointgroup = new THREE.Group(); | ||
+ | pointgroup.name = " | ||
+ | var points = obj.userData.points; | ||
+ | var radii = obj.userData.pointradii; | ||
+ | var materials = obj.userData.pointmaterial; | ||
+ | var geometry, | ||
+ | if (!Array.isArray(radii)) { | ||
+ | geometry = new THREE.SphereBufferGeometry(radii); | ||
+ | } | ||
+ | if (!Array.isArray(materials)) { | ||
+ | material = materials; | ||
+ | } | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | if (Array.isArray(radii)) { | ||
+ | if (radii[i] == 0) { | ||
+ | continue; | ||
+ | } | ||
+ | geometry = new THREE.SphereBufferGeometry(radii[i]); | ||
+ | } | ||
+ | if (Array.isArray(materials)) { | ||
+ | material = materials[i]; | ||
+ | } | ||
+ | var sphere = new THREE.Mesh(geometry, | ||
+ | point.addSphere(sphere); | ||
+ | pointgroup.add(sphere); | ||
+ | } | ||
+ | obj.add(pointgroup); | ||
+ | } | ||
+ | |||
+ | function init_pointlabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var labels = obj.userData.pointlabels; | ||
+ | var pointlabels = new THREE.Group(); | ||
+ | pointlabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(pointlabels); | ||
+ | } | ||
+ | |||
+ | function init_lines(obj) { | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var points = obj.userData.points; | ||
+ | var materials = obj.userData.edgematerial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 ); | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | for (var i=0; i< | ||
+ | geometry.addGroup(2*i, | ||
+ | } | ||
+ | } | ||
+ | var lines = new THREE.LineSegments(geometry, | ||
+ | lines.name = " | ||
+ | obj.add(lines); | ||
+ | updateEdgesPosition(obj); | ||
+ | } | ||
+ | |||
+ | function init_edgelabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var labels = obj.userData.edgelabels; | ||
+ | var edgelabels = new THREE.Group(); | ||
+ | edgelabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(edgelabels); | ||
+ | } | ||
+ | |||
+ | function init_arrowheads(obj) { | ||
+ | var arrowheads = new THREE.Group(); | ||
+ | arrowheads.name = " | ||
+ | var arrowstyle = obj.userData.arrowstyle; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var edgematerials = obj.userData.edgematerial; | ||
+ | var points = obj.userData.points; | ||
+ | var material; | ||
+ | if (!Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials.color} ); | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var start = points[edgeindices[i]]; | ||
+ | var end = points[edgeindices[i+1]]; | ||
+ | var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius(); | ||
+ | if (dist <= 0) { | ||
+ | continue; | ||
+ | } | ||
+ | var dir = new THREE.Vector3().subVectors(end.vector, | ||
+ | dir.normalize(); | ||
+ | var axis = new THREE.Vector3().set(dir.z, | ||
+ | axis.normalize(); | ||
+ | var radians = Math.acos( dir.y ); | ||
+ | var radius = dist/25; | ||
+ | var height = dist/5; | ||
+ | var geometry = new THREE.ConeBufferGeometry(radius, | ||
+ | var position = new THREE.Vector3().addVectors(start.vector, | ||
+ | if (Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} ); | ||
+ | } | ||
+ | var cone = new THREE.Mesh( geometry, material ); | ||
+ | cone.quaternion.setFromAxisAngle(axis, | ||
+ | cone.position.copy(position);; | ||
+ | arrowheads.add(cone); | ||
+ | } | ||
+ | obj.add(arrowheads); | ||
+ | } | ||
+ | |||
+ | function init_faces(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var facets = obj.userData.facets; | ||
+ | obj.userData.triangleindices = []; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | for (var t=0; t< | ||
+ | obj.userData.triangleindices.push(facet[0], | ||
+ | } | ||
+ | } | ||
+ | var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute(bufarr, | ||
+ | | ||
+ | var materials = obj.userData.facetmaterial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var frontmaterials = []; | ||
+ | var backmaterials = []; | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | var tricount = 0; | ||
+ | var facet; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | geometry.addGroup(tricount, | ||
+ | tricount += (facet.length-2)*3; | ||
+ | } | ||
+ | for (var j=0; j< | ||
+ | var fmat = materials[j].clone() | ||
+ | fmat.side = THREE.FrontSide; | ||
+ | frontmaterials.push(fmat); | ||
+ | var bmat = materials[j].clone() | ||
+ | bmat.side = THREE.BackSide; | ||
+ | backmaterials.push(bmat); | ||
+ | obj.userData.facetmaterial = frontmaterials.concat(backmaterials); | ||
+ | } | ||
+ | } else if (materials instanceof THREE.Material) { | ||
+ | frontmaterials = materials.clone() | ||
+ | frontmaterials.side = THREE.FrontSide; | ||
+ | backmaterials = materials.clone() | ||
+ | backmaterials.side = THREE.BackSide; | ||
+ | obj.userData.facetmaterial = [frontmaterials, | ||
+ | } | ||
+ | // duplicating the object with front and back should avoid transparency issues | ||
+ | var backmesh = new THREE.Mesh(geometry, | ||
+ | // meshname is used to show/hide objects | ||
+ | backmesh.name = " | ||
+ | obj.add(backmesh); | ||
+ | var frontmesh = new THREE.Mesh(geometry, | ||
+ | frontmesh.name = " | ||
+ | obj.add(frontmesh); | ||
+ | updateFacesPosition(obj); | ||
+ | } | ||
+ | // // | ||
+ | |||
+ | |||
+ | function updateFacesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.triangleindices; | ||
+ | var faces = obj.getObjectByName(" | ||
+ | var ba = faces.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | faces.geometry.attributes.position.needsUpdate = true; | ||
+ | | ||
+ | } | ||
+ | |||
+ | function updateEdgesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.edgeindices; | ||
+ | var lines = obj.getObjectByName(" | ||
+ | var ba = lines.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | lines.geometry.attributes.position.needsUpdate = true; | ||
+ | } | ||
+ | |||
+ | function onWindowResize() { | ||
+ | renderer.setSize( three.clientWidth, | ||
+ | svgRenderer.setSize( three.clientWidth, | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | function updateCamera() { | ||
+ | var width = three.clientWidth; | ||
+ | var height = three.clientHeight; | ||
+ | var aspect = width / height; | ||
+ | if (camera.type == " | ||
+ | camera.left = frustumSize * aspect / - 2; | ||
+ | camera.right = frustumSize * aspect / 2; | ||
+ | camera.top = frustumSize / 2; | ||
+ | camera.bottom = - frustumSize / 2; | ||
+ | } else if (camera.type == " | ||
+ | camera.aspect = aspect; | ||
+ | } | ||
+ | camera.updateProjectionMatrix(); | ||
+ | } | ||
+ | |||
+ | function changeCamera(event) { | ||
+ | var selindex = event.currentTarget.selectedIndex; | ||
+ | camera = cameras[selindex]; | ||
+ | control = controls[selindex]; | ||
+ | control.enabled = true; | ||
+ | for (var i=0; i< | ||
+ | if (i!=selindex) { | ||
+ | controls[i].enabled = false; | ||
+ | } | ||
+ | } | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | var camtypenode = document.getElementById(' | ||
+ | camtypenode.onchange = changeCamera; | ||
+ | camtypenode.dispatchEvent(new Event(' | ||
+ | |||
+ | onWindowResize(); | ||
+ | window.addEventListener(' | ||
+ | |||
+ | |||
+ | 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.000001; | ||
+ | var XMLS = new XMLSerializer(); | ||
+ | var svgElement; | ||
+ | var renderId; | ||
+ | |||
+ | var render = function () { | ||
+ | |||
+ | renderId = requestAnimationFrame(render); | ||
+ | |||
+ | // comment in for automatic explosion | ||
+ | // | ||
+ | |||
+ | var phi = 0.02 * rotationSpeedFactor; | ||
+ | |||
+ | if (xRotationEnabled) { | ||
+ | scene.rotation.x += phi; | ||
+ | } | ||
+ | if (yRotationEnabled) { | ||
+ | scene.rotation.y += phi; | ||
+ | } | ||
+ | if (zRotationEnabled) { | ||
+ | scene.rotation.z += phi; | ||
+ | } | ||
+ | |||
+ | control.update(); | ||
+ | renderer.render(scene, | ||
+ | }; | ||
+ | |||
+ | if ( THREE.WEBGL.isWebGLAvailable() ) { | ||
+ | render(); | ||
+ | } else { | ||
+ | var warning = WEBGL.getWebGLErrorMessage(); | ||
+ | three.appendChild( warning ); | ||
+ | } | ||
+ | | ||
+ | function changeTransparency() { | ||
+ | var opacity = 1-Number(event.currentTarget.value); | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].opacity = opacity; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.opacity = opacity; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleDepthWrite(event) { | ||
+ | depthwrite = event.currentTarget.checked; | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].depthWrite = depthwrite; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.depthWrite = depthWrite; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | 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, | ||
+ | camera.position.set(0, | ||
+ | camera.up.set(0, | ||
+ | } | ||
+ | |||
+ | function showSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = true; | ||
+ | } | ||
+ | |||
+ | function hideSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = false; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | var pos = 150* Math.PI; | ||
+ | |||
+ | function updateFactor() { | ||
+ | pos++; | ||
+ | return Math.sin(.01*pos)+1; | ||
+ | } | ||
+ | |||
+ | // ------------------------ FOLDING ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | // rotate point p around axis defined by points p1 and p2 by given angle | ||
+ | function rotate(p, p1, p2, angle ){ | ||
+ | angle = -angle; | ||
+ | var x = p.x, y = p.y, z = p.z, | ||
+ | a = p1.x, b = p1.y, c = p1.z, | ||
+ | u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z; | ||
+ | var result = []; | ||
+ | var L = u*u + v*v + w*w; | ||
+ | var sqrt = Math.sqrt; | ||
+ | var cos = Math.cos; | ||
+ | var sin = Math.sin; | ||
+ | |||
+ | result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/ | ||
+ | result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/ | ||
+ | result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/ | ||
+ | |||
+ | return result; | ||
+ | } | ||
+ | |||
+ | var fold = function(event){ | ||
+ | var obj = foldables[Number(event.currentTarget.name)]; | ||
+ | var foldvalue = Number(event.currentTarget.value); | ||
+ | var scale = foldvalue - obj.userData.oldscale; | ||
+ | |||
+ | for (var j=0; j< | ||
+ | rotateVertices(obj, | ||
+ | } | ||
+ | update(obj); | ||
+ | obj.userData.oldscale += scale; | ||
+ | lookAtBarycenter(obj); | ||
+ | } | ||
+ | |||
+ | function lookAtBarycenter(obj){ | ||
+ | control.target = barycenter(obj); | ||
+ | } | ||
+ | |||
+ | function barycenter(obj) { | ||
+ | var center = new THREE.Vector3(0, | ||
+ | var points = obj.userData.points; | ||
+ | for (var i=0; i< | ||
+ | center.add(points[i].vector); | ||
+ | } | ||
+ | center.divideScalar(points.length); | ||
+ | return center; | ||
+ | } | ||
+ | |||
+ | function rotateVertices(obj, | ||
+ | var axes = obj.userData.axes; | ||
+ | var subtrees = obj.userData.subtrees; | ||
+ | var points = obj.userData.points; | ||
+ | var angles = obj.userData.angles; | ||
+ | if (edge < axes.length){ | ||
+ | for (var j=0; j< | ||
+ | var rotP = rotate(points[subtrees[edge][j]].vector, | ||
+ | points[subtrees[edge][j]].set(rotP[0], | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function update(obj) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | if (foldables.length) { | ||
+ | var settings = document.getElementById(' | ||
+ | var foldDiv = document.createElement(' | ||
+ | foldDiv.id = ' | ||
+ | var title = document.createElement(' | ||
+ | title.innerHTML = ' | ||
+ | foldDiv.appendChild(title); | ||
+ | foldDiv.className = ' | ||
+ | for (var i=0; i< | ||
+ | var range = document.createElement(' | ||
+ | range.type = ' | ||
+ | range.min = 0; | ||
+ | range.max = 1; | ||
+ | range.value = 0; | ||
+ | range.step = 0.001; | ||
+ | range.name = String(i); | ||
+ | range.oninput = fold; | ||
+ | foldDiv.appendChild(range); | ||
+ | } | ||
+ | lookAtBarycenter(foldables[0]); | ||
+ | settings.insertBefore(foldDiv, | ||
+ | } | ||
+ | |||
+ | | ||
+ | // ---------------------- EXPLOSION ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | if (explodableModel) { | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | if ( obj.userData.explodable ) { | ||
+ | computeCentroid(obj); | ||
+ | } | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | explode(0.000001); | ||
+ | } | ||
+ | |||
+ | function computeCentroid(obj) { | ||
+ | centroid = new THREE.Vector3(); | ||
+ | obj.userData.points.forEach(function(pmpoint) { | ||
+ | centroid.add(pmpoint.vector); | ||
+ | }); | ||
+ | centroid.divideScalar(obj.userData.points.length); | ||
+ | obj.userData.centroid = centroid; | ||
+ | } | ||
+ | |||
+ | function explode(factor) { | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i]; | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | var c = obj.userData.centroid; | ||
+ | obj.position.set(c.x*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, | ||
+ | } | ||
+ | |||
+ | |||
+ | function explodingInterval(){ | ||
+ | explodeScale += explodingSpeed; | ||
+ | if (explodeScale <= 6){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else{ | ||
+ | explode(6); | ||
+ | explodeScale = 6; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startUnexploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | |||
+ | function startUnexploding(){ | ||
+ | intervals.push(setInterval(unexplodingInterval, | ||
+ | } | ||
+ | |||
+ | function unexplodingInterval(){ | ||
+ | explodeScale -= explodingSpeed; | ||
+ | if (explodeScale >= 0){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else { | ||
+ | explode(0); | ||
+ | explodeScale = 0; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startExploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | function clearIntervals(){ | ||
+ | intervals.forEach(function(interval){ | ||
+ | clearInterval(interval); | ||
+ | }); | ||
+ | intervals = []; | ||
+ | timeouts.forEach(function(timeout){ | ||
+ | clearTimeout(timeout); | ||
+ | }); | ||
+ | timeouts = []; | ||
+ | } | ||
+ | |||
+ | // ---------------------- DISPLAY -------------------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | const objectTypeInnerHTMLs = { points: " | ||
+ | const objectTypeVisible = {}; | ||
+ | Object.assign(objectTypeVisible, | ||
+ | const sortedObjectTypeKeys = Object.keys(objectTypeInnerHTMLs).sort(); | ||
+ | const shownObjectTypesList = document.getElementById(' | ||
+ | |||
+ | function setVisibility(bool, | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i].getObjectByName(objname); | ||
+ | if (obj) { | ||
+ | obj.visible = bool; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleObjectTypeVisibility(event){ | ||
+ | var name = event.currentTarget.name; | ||
+ | var checked = event.currentTarget.checked; | ||
+ | objectTypeVisible[name] = checked; | ||
+ | if (name == " | ||
+ | setVisibility(checked," | ||
+ | setVisibility(checked," | ||
+ | } else { | ||
+ | setVisibility(checked, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var key = sortedObjectTypeKeys[i]; | ||
+ | if (modelContains[key]) { | ||
+ | var objTypeNode = document.createElement(' | ||
+ | objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = key; | ||
+ | checkbox.onchange = toggleObjectTypeVisibility; | ||
+ | shownObjectTypesList.appendChild(checkbox); | ||
+ | shownObjectTypesList.appendChild(objTypeNode); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // ------------------------------------------------------ | ||
+ | |||
+ | function toggleObjectVisibility(event){ | ||
+ | var nr = Number(event.currentTarget.name); | ||
+ | scene.children[nr].visible = event.currentTarget.checked; | ||
+ | } | ||
+ | |||
+ | // append checkboxes for displaying or hiding objects | ||
+ | var shownObjectsList = document.getElementById(' | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | var objNode = document.createElement(' | ||
+ | objNode.innerHTML = obj.name + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = String(i); | ||
+ | checkbox.onchange = toggleObjectVisibility; | ||
+ | shownObjectsList.appendChild(checkbox); | ||
+ | shownObjectsList.appendChild(objNode); | ||
+ | } | ||
+ | |||
+ | // ---------------------- SVG ------------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function takeSvgScreenshot() { | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | svgRenderer.render(scene, | ||
+ | svgElement = XMLS.serializeToString(svgRenderer.domElement); | ||
+ | | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | |||
+ | if (document.getElementById(' | ||
+ | //show in new tab | ||
+ | var myWindow = window.open("","" | ||
+ | myWindow.document.body.innerHTML = svgElement; | ||
+ | } else{ | ||
+ | // download svg file | ||
+ | download(" | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function download(filename, | ||
+ | var element = document.createElement(' | ||
+ | element.setAttribute(' | ||
+ | element.setAttribute(' | ||
+ | |||
+ | element.style.display = ' | ||
+ | document.body.appendChild(element); | ||
+ | |||
+ | element.click(); | ||
+ | |||
+ | document.body.removeChild(element); | ||
+ | } | ||
+ | |||
+ | |||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | |||
+ | |||
+ | // ------------------ SHORTCUTS -------------------------------------------- | ||
+ | // ------------------------------------------------------------------------- | ||
+ | |||
+ | /** | ||
+ | * http:// | ||
+ | * Version : 2.01.B | ||
+ | * By Binny V A | ||
+ | * License : BSD | ||
+ | */ | ||
+ | shortcut = { | ||
+ | ' | ||
+ | ' | ||
+ | //Provide a set of default options | ||
+ | var default_options = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | if(!opt) opt = default_options; | ||
+ | else { | ||
+ | for(var dfo in default_options) { | ||
+ | if(typeof opt[dfo] == ' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | var ele = opt.target; | ||
+ | if(typeof 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[' | ||
+ | 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 == ' | ||
+ | } | ||
+ | |||
+ | //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(code == 190) character=" | ||
+ | |||
+ | 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 = { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | ";":":", | ||
+ | "'":" | ||
+ | ",":"<", | ||
+ | " | ||
+ | "/":"?", | ||
+ | " | ||
+ | } | ||
+ | // | ||
+ | var special_keys = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | |||
+ | var modifiers = { | ||
+ | shift: { wanted: | ||
+ | ctrl : { wanted: | ||
+ | alt | ||
+ | meta : { wanted: | ||
+ | }; | ||
+ | | ||
+ | if(e.ctrlKey) modifiers.ctrl.pressed = true; | ||
+ | if(e.shiftKey) modifiers.shift.pressed = true; | ||
+ | if(e.altKey) modifiers.alt.pressed = true; | ||
+ | if(e.metaKey) | ||
+ | | ||
+ | for(var i=0; k=keys[i], | ||
+ | // | ||
+ | if(k == ' | ||
+ | kp++; | ||
+ | modifiers.ctrl.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.shift.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.alt.wanted = true; | ||
+ | } else if(k == ' | ||
+ | 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[' | ||
+ | if(opt[' | ||
+ | |||
+ | } 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[' | ||
+ | // | ||
+ | e.cancelBubble = true; | ||
+ | e.returnValue = false; | ||
+ | |||
+ | // | ||
+ | if (e.stopPropagation) { | ||
+ | e.stopPropagation(); | ||
+ | e.preventDefault(); | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | this.all_shortcuts[shortcut_combination] = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | }; | ||
+ | //Attach the function with the event | ||
+ | if(ele.addEventListener) ele.addEventListener(opt[' | ||
+ | else if(ele.attachEvent) ele.attachEvent(' | ||
+ | else ele[' | ||
+ | }, | ||
+ | |||
+ | //Remove the shortcut - just specify the shortcut and I will remove the binding | ||
+ | ' | ||
+ | shortcut_combination = shortcut_combination.toLowerCase(); | ||
+ | var binding = this.all_shortcuts[shortcut_combination]; | ||
+ | delete(this.all_shortcuts[shortcut_combination]) | ||
+ | if(!binding) return; | ||
+ | var type = binding[' | ||
+ | var ele = binding[' | ||
+ | var callback = binding[' | ||
+ | |||
+ | if(ele.detachEvent) ele.detachEvent(' | ||
+ | else if(ele.removeEventListener) ele.removeEventListener(type, | ||
+ | else ele[' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | shortcut.add(" | ||
+ | var event = new Event(' | ||
+ | if (settingsShown){ | ||
+ | document.getElementById(' | ||
+ | } else { | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | });}); | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | Note that the quadrilateral contains point 2 in its interior and that this point is colored black. This corresponds to the fact that the lifted point 2 lies above the convex hull of the lifted points 0,1,3 and 4. Therefore the maximal cell describing the quadrilateral does not contain the point 2. We may change the lifting function by giving point 2 height '' | ||
+ | |||
+ | <code perl> | ||
+ | > $w = new Vector< | ||
+ | > $S = new fan:: | ||
+ | > print $S-> | ||
+ | {3 4 5} | ||
+ | {0 1 2 3 4} | ||
+ | > $S-> | ||
+ | </ | ||
+ | < | ||
+ | <!-- | ||
+ | polymake for knusper | ||
+ | Thu Mar 3 00:43:52 2022 | ||
+ | pcom:S | ||
+ | --> | ||
+ | |||
+ | |||
+ | < | ||
+ | < | ||
+ | <meta charset=utf-8> | ||
+ | < | ||
+ | < | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | */ | ||
+ | html {overflow: scroll;} | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | # | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_END | ||
+ | */ | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | <div id=' | ||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | <div class=suboption> | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | <select id=" | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | <img id=' | ||
+ | <img id=' | ||
+ | <div id=" | ||
+ | </ | ||
+ | < | ||
+ | requirejs.config({ | ||
+ | paths: { | ||
+ | three: '/ | ||
+ | TrackballControls: | ||
+ | OrbitControls: | ||
+ | Projector: '/ | ||
+ | SVGRenderer: | ||
+ | WEBGL: '/ | ||
+ | }, | ||
+ | shim: { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | }); | ||
+ | | ||
+ | require([' | ||
+ | window.THREE = THREE; | ||
+ | require([' | ||
+ | | ||
+ | THREE.TrackballControls = TrackballControls; | ||
+ | THREE.OrbitControls = OrbitControls; | ||
+ | THREE.Projector = Projector; | ||
+ | THREE.SVGRenderer = SVGRenderer; | ||
+ | THREE.WEBGL = WEBGL; | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | |||
+ | const intervalLength = 25; // for automatic animations | ||
+ | const explodableModel = true; | ||
+ | const modelContains = { points: false, pointlabels: | ||
+ | const foldables = []; | ||
+ | |||
+ | var three = document.getElementById(" | ||
+ | var scene = new THREE.Scene(); | ||
+ | var renderer = new THREE.WebGLRenderer( { antialias: true } ); | ||
+ | var svgRenderer = new THREE.SVGRenderer( { antialias: true } ); | ||
+ | renderer.setPixelRatio( window.devicePixelRatio ); | ||
+ | renderer.setClearColor(0xFFFFFF, | ||
+ | svgRenderer.setClearColor(0xFFFFFF, | ||
+ | three.appendChild(renderer.domElement); | ||
+ | |||
+ | var frustumSize = 4; | ||
+ | var cameras = [new THREE.PerspectiveCamera(75, | ||
+ | cameras.forEach(function(cam) { | ||
+ | cam.position.set(0, | ||
+ | cam.lookAt(0, | ||
+ | cam.up.set(0, | ||
+ | }); | ||
+ | var controls = [new THREE.TrackballControls(cameras[0], | ||
+ | var camera, control; | ||
+ | |||
+ | controls[0].zoomSpeed = 0.2; | ||
+ | controls[0].rotateSpeed = 4; | ||
+ | |||
+ | |||
+ | // class to allow move points together with labels and spheres | ||
+ | var PMPoint = function (x,y,z) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addLabel = function(labelsprite) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addSphere = function(spheremesh) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.set = function(x, | ||
+ | | ||
+ | if (this.sprite) { | ||
+ | this.sprite.position.copy(this.vector); | ||
+ | } | ||
+ | if (this.sphere) { | ||
+ | this.sphere.position.copy(this.vector); | ||
+ | } | ||
+ | } | ||
+ | PMPoint.prototype.radius = function() { | ||
+ | if (this.sphere) { | ||
+ | return this.sphere.geometry.parameters.radius; | ||
+ | } else { | ||
+ | return 0; | ||
+ | } | ||
+ | }; | ||
+ | // select the target node | ||
+ | var target = document.querySelector('# | ||
+ | |||
+ | // create an observer instance | ||
+ | var observer = new MutationObserver(function(mutations) { | ||
+ | | ||
+ | if (mutation.removedNodes && mutation.removedNodes.length > 0) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | }); | ||
+ | }); | ||
+ | |||
+ | // configuration of the observer: | ||
+ | var config = { childList: true, characterData: | ||
+ | |||
+ | // pass in the target node, as well as the observer options | ||
+ | while (target) { | ||
+ | if (target.className==" | ||
+ | observer.observe(target, | ||
+ | break; | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | var obj0 = new THREE.Object3D(); | ||
+ | obj0.name = " | ||
+ | obj0.userData.explodable = 1; | ||
+ | obj0.userData.points = []; | ||
+ | obj0.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(2, 2, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(1, 3, 0)); | ||
+ | |||
+ | obj0.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj0.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj0.userData.pointlabels = [" | ||
+ | obj0.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj0.userData.facets = [[2, 0, 1]]; | ||
+ | < | ||
+ | obj0.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj0); | ||
+ | scene.add(obj0); | ||
+ | |||
+ | var obj1 = new THREE.Object3D(); | ||
+ | obj1.name = " | ||
+ | obj1.userData.explodable = 1; | ||
+ | obj1.userData.points = []; | ||
+ | obj1.userData.points.push(new PMPoint(0, 0, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(2, 0, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(1, 1, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(2, 2, 0)); | ||
+ | |||
+ | obj1.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj1.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFFFF00, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj1.userData.pointlabels = [" | ||
+ | obj1.userData.edgeindices = [0, 1, 0, 3, 1, 4, 3, 4]; | ||
+ | < | ||
+ | obj1.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj1.userData.facets = [[1, 4, 3, 0]]; | ||
+ | < | ||
+ | obj1.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj1); | ||
+ | scene.add(obj1); | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | function textSpriteMaterial(message, | ||
+ | if ( parameters === undefined ) parameters = {}; | ||
+ | var fontface = " | ||
+ | var fontsize = parameters.hasOwnProperty(" | ||
+ | fontsize = fontsize*10; | ||
+ | var lines = message.split(' | ||
+ | var size = 512; | ||
+ | for(var i = 0; i< | ||
+ | var tmp = lines[i].length; | ||
+ | while(tmp*fontsize > size){ | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | var canvas = document.createElement(' | ||
+ | canvas.width = size; | ||
+ | canvas.height = size; | ||
+ | var context = canvas.getContext(' | ||
+ | context.fillStyle = " | ||
+ | context.fill(); | ||
+ | context.font = fontsize + "px " + fontface; | ||
+ | | ||
+ | // text color | ||
+ | context.fillStyle = " | ||
+ | | ||
+ | context.fillText(lines[i], | ||
+ | } | ||
+ | | ||
+ | // canvas contents will be used for a texture | ||
+ | var texture = new THREE.Texture(canvas); | ||
+ | texture.needsUpdate = true; | ||
+ | | ||
+ | var spriteMaterial = new THREE.SpriteMaterial({map: | ||
+ | return spriteMaterial; | ||
+ | } | ||
+ | |||
+ | |||
+ | // ---------------------- INITIALIZING OBJECTS-------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function init_object(obj) { | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_points(obj); | ||
+ | modelContains.points = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_pointlabels(obj); | ||
+ | modelContains.pointlabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_lines(obj); | ||
+ | modelContains.lines = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_edgelabels(obj); | ||
+ | modelContains.edgelabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_arrowheads(obj); | ||
+ | modelContains.arrowheads = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_faces(obj); | ||
+ | modelContains.faces = true; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function init_points(obj) { | ||
+ | var pointgroup = new THREE.Group(); | ||
+ | pointgroup.name = " | ||
+ | var points = obj.userData.points; | ||
+ | var radii = obj.userData.pointradii; | ||
+ | var materials = obj.userData.pointmaterial; | ||
+ | var geometry, | ||
+ | if (!Array.isArray(radii)) { | ||
+ | geometry = new THREE.SphereBufferGeometry(radii); | ||
+ | } | ||
+ | if (!Array.isArray(materials)) { | ||
+ | material = materials; | ||
+ | } | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | if (Array.isArray(radii)) { | ||
+ | if (radii[i] == 0) { | ||
+ | continue; | ||
+ | } | ||
+ | geometry = new THREE.SphereBufferGeometry(radii[i]); | ||
+ | } | ||
+ | if (Array.isArray(materials)) { | ||
+ | material = materials[i]; | ||
+ | } | ||
+ | var sphere = new THREE.Mesh(geometry, | ||
+ | point.addSphere(sphere); | ||
+ | pointgroup.add(sphere); | ||
+ | } | ||
+ | obj.add(pointgroup); | ||
+ | } | ||
+ | |||
+ | function init_pointlabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var labels = obj.userData.pointlabels; | ||
+ | var pointlabels = new THREE.Group(); | ||
+ | pointlabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(pointlabels); | ||
+ | } | ||
+ | |||
+ | function init_lines(obj) { | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var points = obj.userData.points; | ||
+ | var materials = obj.userData.edgematerial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 ); | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | for (var i=0; i< | ||
+ | geometry.addGroup(2*i, | ||
+ | } | ||
+ | } | ||
+ | var lines = new THREE.LineSegments(geometry, | ||
+ | lines.name = " | ||
+ | obj.add(lines); | ||
+ | updateEdgesPosition(obj); | ||
+ | } | ||
+ | |||
+ | function init_edgelabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var labels = obj.userData.edgelabels; | ||
+ | var edgelabels = new THREE.Group(); | ||
+ | edgelabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(edgelabels); | ||
+ | } | ||
+ | |||
+ | function init_arrowheads(obj) { | ||
+ | var arrowheads = new THREE.Group(); | ||
+ | arrowheads.name = " | ||
+ | var arrowstyle = obj.userData.arrowstyle; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var edgematerials = obj.userData.edgematerial; | ||
+ | var points = obj.userData.points; | ||
+ | var material; | ||
+ | if (!Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials.color} ); | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var start = points[edgeindices[i]]; | ||
+ | var end = points[edgeindices[i+1]]; | ||
+ | var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius(); | ||
+ | if (dist <= 0) { | ||
+ | continue; | ||
+ | } | ||
+ | var dir = new THREE.Vector3().subVectors(end.vector, | ||
+ | dir.normalize(); | ||
+ | var axis = new THREE.Vector3().set(dir.z, | ||
+ | axis.normalize(); | ||
+ | var radians = Math.acos( dir.y ); | ||
+ | var radius = dist/25; | ||
+ | var height = dist/5; | ||
+ | var geometry = new THREE.ConeBufferGeometry(radius, | ||
+ | var position = new THREE.Vector3().addVectors(start.vector, | ||
+ | if (Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} ); | ||
+ | } | ||
+ | var cone = new THREE.Mesh( geometry, material ); | ||
+ | cone.quaternion.setFromAxisAngle(axis, | ||
+ | cone.position.copy(position);; | ||
+ | arrowheads.add(cone); | ||
+ | } | ||
+ | obj.add(arrowheads); | ||
+ | } | ||
+ | |||
+ | function init_faces(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var facets = obj.userData.facets; | ||
+ | obj.userData.triangleindices = []; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | for (var t=0; t< | ||
+ | obj.userData.triangleindices.push(facet[0], | ||
+ | } | ||
+ | } | ||
+ | var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute(bufarr, | ||
+ | | ||
+ | var materials = obj.userData.facetmaterial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var frontmaterials = []; | ||
+ | var backmaterials = []; | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | var tricount = 0; | ||
+ | var facet; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | geometry.addGroup(tricount, | ||
+ | tricount += (facet.length-2)*3; | ||
+ | } | ||
+ | for (var j=0; j< | ||
+ | var fmat = materials[j].clone() | ||
+ | fmat.side = THREE.FrontSide; | ||
+ | frontmaterials.push(fmat); | ||
+ | var bmat = materials[j].clone() | ||
+ | bmat.side = THREE.BackSide; | ||
+ | backmaterials.push(bmat); | ||
+ | obj.userData.facetmaterial = frontmaterials.concat(backmaterials); | ||
+ | } | ||
+ | } else if (materials instanceof THREE.Material) { | ||
+ | frontmaterials = materials.clone() | ||
+ | frontmaterials.side = THREE.FrontSide; | ||
+ | backmaterials = materials.clone() | ||
+ | backmaterials.side = THREE.BackSide; | ||
+ | obj.userData.facetmaterial = [frontmaterials, | ||
+ | } | ||
+ | // duplicating the object with front and back should avoid transparency issues | ||
+ | var backmesh = new THREE.Mesh(geometry, | ||
+ | // meshname is used to show/hide objects | ||
+ | backmesh.name = " | ||
+ | obj.add(backmesh); | ||
+ | var frontmesh = new THREE.Mesh(geometry, | ||
+ | frontmesh.name = " | ||
+ | obj.add(frontmesh); | ||
+ | updateFacesPosition(obj); | ||
+ | } | ||
+ | // // | ||
+ | |||
+ | |||
+ | function updateFacesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.triangleindices; | ||
+ | var faces = obj.getObjectByName(" | ||
+ | var ba = faces.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | faces.geometry.attributes.position.needsUpdate = true; | ||
+ | | ||
+ | } | ||
+ | |||
+ | function updateEdgesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.edgeindices; | ||
+ | var lines = obj.getObjectByName(" | ||
+ | var ba = lines.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | lines.geometry.attributes.position.needsUpdate = true; | ||
+ | } | ||
+ | |||
+ | function onWindowResize() { | ||
+ | renderer.setSize( three.clientWidth, | ||
+ | svgRenderer.setSize( three.clientWidth, | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | function updateCamera() { | ||
+ | var width = three.clientWidth; | ||
+ | var height = three.clientHeight; | ||
+ | var aspect = width / height; | ||
+ | if (camera.type == " | ||
+ | camera.left = frustumSize * aspect / - 2; | ||
+ | camera.right = frustumSize * aspect / 2; | ||
+ | camera.top = frustumSize / 2; | ||
+ | camera.bottom = - frustumSize / 2; | ||
+ | } else if (camera.type == " | ||
+ | camera.aspect = aspect; | ||
+ | } | ||
+ | camera.updateProjectionMatrix(); | ||
+ | } | ||
+ | |||
+ | function changeCamera(event) { | ||
+ | var selindex = event.currentTarget.selectedIndex; | ||
+ | camera = cameras[selindex]; | ||
+ | control = controls[selindex]; | ||
+ | control.enabled = true; | ||
+ | for (var i=0; i< | ||
+ | if (i!=selindex) { | ||
+ | controls[i].enabled = false; | ||
+ | } | ||
+ | } | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | var camtypenode = document.getElementById(' | ||
+ | camtypenode.onchange = changeCamera; | ||
+ | camtypenode.dispatchEvent(new Event(' | ||
+ | |||
+ | onWindowResize(); | ||
+ | window.addEventListener(' | ||
+ | |||
+ | |||
+ | 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.000001; | ||
+ | var XMLS = new XMLSerializer(); | ||
+ | var svgElement; | ||
+ | var renderId; | ||
+ | |||
+ | var render = function () { | ||
+ | |||
+ | renderId = requestAnimationFrame(render); | ||
+ | |||
+ | // comment in for automatic explosion | ||
+ | // | ||
+ | |||
+ | var phi = 0.02 * rotationSpeedFactor; | ||
+ | |||
+ | if (xRotationEnabled) { | ||
+ | scene.rotation.x += phi; | ||
+ | } | ||
+ | if (yRotationEnabled) { | ||
+ | scene.rotation.y += phi; | ||
+ | } | ||
+ | if (zRotationEnabled) { | ||
+ | scene.rotation.z += phi; | ||
+ | } | ||
+ | |||
+ | control.update(); | ||
+ | renderer.render(scene, | ||
+ | }; | ||
+ | |||
+ | if ( THREE.WEBGL.isWebGLAvailable() ) { | ||
+ | render(); | ||
+ | } else { | ||
+ | var warning = WEBGL.getWebGLErrorMessage(); | ||
+ | three.appendChild( warning ); | ||
+ | } | ||
+ | | ||
+ | function changeTransparency() { | ||
+ | var opacity = 1-Number(event.currentTarget.value); | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].opacity = opacity; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.opacity = opacity; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleDepthWrite(event) { | ||
+ | depthwrite = event.currentTarget.checked; | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].depthWrite = depthwrite; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.depthWrite = depthWrite; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | 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, | ||
+ | camera.position.set(0, | ||
+ | camera.up.set(0, | ||
+ | } | ||
+ | |||
+ | function showSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = true; | ||
+ | } | ||
+ | |||
+ | function hideSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = false; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | var pos = 150* Math.PI; | ||
+ | |||
+ | function updateFactor() { | ||
+ | pos++; | ||
+ | return Math.sin(.01*pos)+1; | ||
+ | } | ||
+ | |||
+ | // ------------------------ FOLDING ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | // rotate point p around axis defined by points p1 and p2 by given angle | ||
+ | function rotate(p, p1, p2, angle ){ | ||
+ | angle = -angle; | ||
+ | var x = p.x, y = p.y, z = p.z, | ||
+ | a = p1.x, b = p1.y, c = p1.z, | ||
+ | u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z; | ||
+ | var result = []; | ||
+ | var L = u*u + v*v + w*w; | ||
+ | var sqrt = Math.sqrt; | ||
+ | var cos = Math.cos; | ||
+ | var sin = Math.sin; | ||
+ | |||
+ | result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/ | ||
+ | result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/ | ||
+ | result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/ | ||
+ | |||
+ | return result; | ||
+ | } | ||
+ | |||
+ | var fold = function(event){ | ||
+ | var obj = foldables[Number(event.currentTarget.name)]; | ||
+ | var foldvalue = Number(event.currentTarget.value); | ||
+ | var scale = foldvalue - obj.userData.oldscale; | ||
+ | |||
+ | for (var j=0; j< | ||
+ | rotateVertices(obj, | ||
+ | } | ||
+ | update(obj); | ||
+ | obj.userData.oldscale += scale; | ||
+ | lookAtBarycenter(obj); | ||
+ | } | ||
+ | |||
+ | function lookAtBarycenter(obj){ | ||
+ | control.target = barycenter(obj); | ||
+ | } | ||
+ | |||
+ | function barycenter(obj) { | ||
+ | var center = new THREE.Vector3(0, | ||
+ | var points = obj.userData.points; | ||
+ | for (var i=0; i< | ||
+ | center.add(points[i].vector); | ||
+ | } | ||
+ | center.divideScalar(points.length); | ||
+ | return center; | ||
+ | } | ||
+ | |||
+ | function rotateVertices(obj, | ||
+ | var axes = obj.userData.axes; | ||
+ | var subtrees = obj.userData.subtrees; | ||
+ | var points = obj.userData.points; | ||
+ | var angles = obj.userData.angles; | ||
+ | if (edge < axes.length){ | ||
+ | for (var j=0; j< | ||
+ | var rotP = rotate(points[subtrees[edge][j]].vector, | ||
+ | points[subtrees[edge][j]].set(rotP[0], | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function update(obj) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | if (foldables.length) { | ||
+ | var settings = document.getElementById(' | ||
+ | var foldDiv = document.createElement(' | ||
+ | foldDiv.id = ' | ||
+ | var title = document.createElement(' | ||
+ | title.innerHTML = ' | ||
+ | foldDiv.appendChild(title); | ||
+ | foldDiv.className = ' | ||
+ | for (var i=0; i< | ||
+ | var range = document.createElement(' | ||
+ | range.type = ' | ||
+ | range.min = 0; | ||
+ | range.max = 1; | ||
+ | range.value = 0; | ||
+ | range.step = 0.001; | ||
+ | range.name = String(i); | ||
+ | range.oninput = fold; | ||
+ | foldDiv.appendChild(range); | ||
+ | } | ||
+ | lookAtBarycenter(foldables[0]); | ||
+ | settings.insertBefore(foldDiv, | ||
+ | } | ||
+ | |||
+ | | ||
+ | // ---------------------- EXPLOSION ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | if (explodableModel) { | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | if ( obj.userData.explodable ) { | ||
+ | computeCentroid(obj); | ||
+ | } | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | explode(0.000001); | ||
+ | } | ||
+ | |||
+ | function computeCentroid(obj) { | ||
+ | centroid = new THREE.Vector3(); | ||
+ | obj.userData.points.forEach(function(pmpoint) { | ||
+ | centroid.add(pmpoint.vector); | ||
+ | }); | ||
+ | centroid.divideScalar(obj.userData.points.length); | ||
+ | obj.userData.centroid = centroid; | ||
+ | } | ||
+ | |||
+ | function explode(factor) { | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i]; | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | var c = obj.userData.centroid; | ||
+ | obj.position.set(c.x*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, | ||
+ | } | ||
+ | |||
+ | |||
+ | function explodingInterval(){ | ||
+ | explodeScale += explodingSpeed; | ||
+ | if (explodeScale <= 6){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else{ | ||
+ | explode(6); | ||
+ | explodeScale = 6; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startUnexploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | |||
+ | function startUnexploding(){ | ||
+ | intervals.push(setInterval(unexplodingInterval, | ||
+ | } | ||
+ | |||
+ | function unexplodingInterval(){ | ||
+ | explodeScale -= explodingSpeed; | ||
+ | if (explodeScale >= 0){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else { | ||
+ | explode(0); | ||
+ | explodeScale = 0; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startExploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | function clearIntervals(){ | ||
+ | intervals.forEach(function(interval){ | ||
+ | clearInterval(interval); | ||
+ | }); | ||
+ | intervals = []; | ||
+ | timeouts.forEach(function(timeout){ | ||
+ | clearTimeout(timeout); | ||
+ | }); | ||
+ | timeouts = []; | ||
+ | } | ||
+ | |||
+ | // ---------------------- DISPLAY -------------------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | const objectTypeInnerHTMLs = { points: " | ||
+ | const objectTypeVisible = {}; | ||
+ | Object.assign(objectTypeVisible, | ||
+ | const sortedObjectTypeKeys = Object.keys(objectTypeInnerHTMLs).sort(); | ||
+ | const shownObjectTypesList = document.getElementById(' | ||
+ | |||
+ | function setVisibility(bool, | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i].getObjectByName(objname); | ||
+ | if (obj) { | ||
+ | obj.visible = bool; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleObjectTypeVisibility(event){ | ||
+ | var name = event.currentTarget.name; | ||
+ | var checked = event.currentTarget.checked; | ||
+ | objectTypeVisible[name] = checked; | ||
+ | if (name == " | ||
+ | setVisibility(checked," | ||
+ | setVisibility(checked," | ||
+ | } else { | ||
+ | setVisibility(checked, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var key = sortedObjectTypeKeys[i]; | ||
+ | if (modelContains[key]) { | ||
+ | var objTypeNode = document.createElement(' | ||
+ | objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = key; | ||
+ | checkbox.onchange = toggleObjectTypeVisibility; | ||
+ | shownObjectTypesList.appendChild(checkbox); | ||
+ | shownObjectTypesList.appendChild(objTypeNode); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // ------------------------------------------------------ | ||
+ | |||
+ | function toggleObjectVisibility(event){ | ||
+ | var nr = Number(event.currentTarget.name); | ||
+ | scene.children[nr].visible = event.currentTarget.checked; | ||
+ | } | ||
+ | |||
+ | // append checkboxes for displaying or hiding objects | ||
+ | var shownObjectsList = document.getElementById(' | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | var objNode = document.createElement(' | ||
+ | objNode.innerHTML = obj.name + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = String(i); | ||
+ | checkbox.onchange = toggleObjectVisibility; | ||
+ | shownObjectsList.appendChild(checkbox); | ||
+ | shownObjectsList.appendChild(objNode); | ||
+ | } | ||
+ | |||
+ | // ---------------------- SVG ------------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function takeSvgScreenshot() { | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | svgRenderer.render(scene, | ||
+ | svgElement = XMLS.serializeToString(svgRenderer.domElement); | ||
+ | | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | |||
+ | if (document.getElementById(' | ||
+ | //show in new tab | ||
+ | var myWindow = window.open("","" | ||
+ | myWindow.document.body.innerHTML = svgElement; | ||
+ | } else{ | ||
+ | // download svg file | ||
+ | download(" | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function download(filename, | ||
+ | var element = document.createElement(' | ||
+ | element.setAttribute(' | ||
+ | element.setAttribute(' | ||
+ | |||
+ | element.style.display = ' | ||
+ | document.body.appendChild(element); | ||
+ | |||
+ | element.click(); | ||
+ | |||
+ | document.body.removeChild(element); | ||
+ | } | ||
+ | |||
+ | |||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | |||
+ | |||
+ | // ------------------ SHORTCUTS -------------------------------------------- | ||
+ | // ------------------------------------------------------------------------- | ||
+ | |||
+ | /** | ||
+ | * http:// | ||
+ | * Version : 2.01.B | ||
+ | * By Binny V A | ||
+ | * License : BSD | ||
+ | */ | ||
+ | shortcut = { | ||
+ | ' | ||
+ | ' | ||
+ | //Provide a set of default options | ||
+ | var default_options = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | if(!opt) opt = default_options; | ||
+ | else { | ||
+ | for(var dfo in default_options) { | ||
+ | if(typeof opt[dfo] == ' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | var ele = opt.target; | ||
+ | if(typeof 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[' | ||
+ | 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 == ' | ||
+ | } | ||
+ | |||
+ | //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(code == 190) character=" | ||
+ | |||
+ | 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 = { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | ";":":", | ||
+ | "'":" | ||
+ | ",":"<", | ||
+ | " | ||
+ | "/":"?", | ||
+ | " | ||
+ | } | ||
+ | // | ||
+ | var special_keys = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | |||
+ | var modifiers = { | ||
+ | shift: { wanted: | ||
+ | ctrl : { wanted: | ||
+ | alt | ||
+ | meta : { wanted: | ||
+ | }; | ||
+ | | ||
+ | if(e.ctrlKey) modifiers.ctrl.pressed = true; | ||
+ | if(e.shiftKey) modifiers.shift.pressed = true; | ||
+ | if(e.altKey) modifiers.alt.pressed = true; | ||
+ | if(e.metaKey) | ||
+ | | ||
+ | for(var i=0; k=keys[i], | ||
+ | // | ||
+ | if(k == ' | ||
+ | kp++; | ||
+ | modifiers.ctrl.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.shift.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.alt.wanted = true; | ||
+ | } else if(k == ' | ||
+ | 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[' | ||
+ | if(opt[' | ||
+ | |||
+ | } 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[' | ||
+ | // | ||
+ | e.cancelBubble = true; | ||
+ | e.returnValue = false; | ||
+ | |||
+ | // | ||
+ | if (e.stopPropagation) { | ||
+ | e.stopPropagation(); | ||
+ | e.preventDefault(); | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | this.all_shortcuts[shortcut_combination] = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | }; | ||
+ | //Attach the function with the event | ||
+ | if(ele.addEventListener) ele.addEventListener(opt[' | ||
+ | else if(ele.attachEvent) ele.attachEvent(' | ||
+ | else ele[' | ||
+ | }, | ||
+ | |||
+ | //Remove the shortcut - just specify the shortcut and I will remove the binding | ||
+ | ' | ||
+ | shortcut_combination = shortcut_combination.toLowerCase(); | ||
+ | var binding = this.all_shortcuts[shortcut_combination]; | ||
+ | delete(this.all_shortcuts[shortcut_combination]) | ||
+ | if(!binding) return; | ||
+ | var type = binding[' | ||
+ | var ele = binding[' | ||
+ | var callback = binding[' | ||
+ | |||
+ | if(ele.detachEvent) ele.detachEvent(' | ||
+ | else if(ele.removeEventListener) ele.removeEventListener(type, | ||
+ | else ele[' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | shortcut.add(" | ||
+ | var event = new Event(' | ||
+ | if (settingsShown){ | ||
+ | document.getElementById(' | ||
+ | } else { | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | });}); | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | This new height function generates the same polyhedral complex, yet a different subdivision of the point set. Note that the maximal cell that describes the quadrilateral now contains the point 2, but it is not a vertex of that cell. This is the reason for the yellow coloring. This corresponds to the fact that its lifting lies in the convex hull of the lifted quadrilateral, | ||
+ | |||
+ | <code perl> | ||
+ | > $w = new Vector< | ||
+ | > $S = new fan:: | ||
+ | > print $S-> | ||
+ | {0 1 2} | ||
+ | {0 2 3} | ||
+ | {2 3 4} | ||
+ | {3 4 5} | ||
+ | {1 2 4} | ||
+ | > $S-> | ||
+ | </ | ||
+ | < | ||
+ | <!-- | ||
+ | polymake for knusper | ||
+ | Thu Mar 3 00:43:53 2022 | ||
+ | pcom:S | ||
+ | --> | ||
+ | |||
+ | |||
+ | < | ||
+ | < | ||
+ | <meta charset=utf-8> | ||
+ | < | ||
+ | < | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | */ | ||
+ | html {overflow: scroll;} | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | # | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_END | ||
+ | */ | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | <div id=' | ||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | <div class=suboption> | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | <select id=" | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | <img id=' | ||
+ | <img id=' | ||
+ | <div id=" | ||
+ | </ | ||
+ | < | ||
+ | requirejs.config({ | ||
+ | paths: { | ||
+ | three: '/ | ||
+ | TrackballControls: | ||
+ | OrbitControls: | ||
+ | Projector: '/ | ||
+ | SVGRenderer: | ||
+ | WEBGL: '/ | ||
+ | }, | ||
+ | shim: { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | }); | ||
+ | | ||
+ | require([' | ||
+ | window.THREE = THREE; | ||
+ | require([' | ||
+ | | ||
+ | THREE.TrackballControls = TrackballControls; | ||
+ | THREE.OrbitControls = OrbitControls; | ||
+ | THREE.Projector = Projector; | ||
+ | THREE.SVGRenderer = SVGRenderer; | ||
+ | THREE.WEBGL = WEBGL; | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | |||
+ | const intervalLength = 25; // for automatic animations | ||
+ | const explodableModel = true; | ||
+ | const modelContains = { points: false, pointlabels: | ||
+ | const foldables = []; | ||
+ | |||
+ | var three = document.getElementById(" | ||
+ | var scene = new THREE.Scene(); | ||
+ | var renderer = new THREE.WebGLRenderer( { antialias: true } ); | ||
+ | var svgRenderer = new THREE.SVGRenderer( { antialias: true } ); | ||
+ | renderer.setPixelRatio( window.devicePixelRatio ); | ||
+ | renderer.setClearColor(0xFFFFFF, | ||
+ | svgRenderer.setClearColor(0xFFFFFF, | ||
+ | three.appendChild(renderer.domElement); | ||
+ | |||
+ | var frustumSize = 4; | ||
+ | var cameras = [new THREE.PerspectiveCamera(75, | ||
+ | cameras.forEach(function(cam) { | ||
+ | cam.position.set(0, | ||
+ | cam.lookAt(0, | ||
+ | cam.up.set(0, | ||
+ | }); | ||
+ | var controls = [new THREE.TrackballControls(cameras[0], | ||
+ | var camera, control; | ||
+ | |||
+ | controls[0].zoomSpeed = 0.2; | ||
+ | controls[0].rotateSpeed = 4; | ||
+ | |||
+ | |||
+ | // class to allow move points together with labels and spheres | ||
+ | var PMPoint = function (x,y,z) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addLabel = function(labelsprite) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addSphere = function(spheremesh) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.set = function(x, | ||
+ | | ||
+ | if (this.sprite) { | ||
+ | this.sprite.position.copy(this.vector); | ||
+ | } | ||
+ | if (this.sphere) { | ||
+ | this.sphere.position.copy(this.vector); | ||
+ | } | ||
+ | } | ||
+ | PMPoint.prototype.radius = function() { | ||
+ | if (this.sphere) { | ||
+ | return this.sphere.geometry.parameters.radius; | ||
+ | } else { | ||
+ | return 0; | ||
+ | } | ||
+ | }; | ||
+ | // select the target node | ||
+ | var target = document.querySelector('# | ||
+ | |||
+ | // create an observer instance | ||
+ | var observer = new MutationObserver(function(mutations) { | ||
+ | | ||
+ | if (mutation.removedNodes && mutation.removedNodes.length > 0) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | }); | ||
+ | }); | ||
+ | |||
+ | // configuration of the observer: | ||
+ | var config = { childList: true, characterData: | ||
+ | |||
+ | // pass in the target node, as well as the observer options | ||
+ | while (target) { | ||
+ | if (target.className==" | ||
+ | observer.observe(target, | ||
+ | break; | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | var obj0 = new THREE.Object3D(); | ||
+ | obj0.name = " | ||
+ | obj0.userData.explodable = 1; | ||
+ | obj0.userData.points = []; | ||
+ | obj0.userData.points.push(new PMPoint(0, 0, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(2, 0, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(1, 1, 0)); | ||
+ | |||
+ | obj0.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj0.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj0.userData.pointlabels = [" | ||
+ | obj0.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj0.userData.facets = [[2, 0, 1]]; | ||
+ | < | ||
+ | obj0.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj0); | ||
+ | scene.add(obj0); | ||
+ | |||
+ | var obj1 = new THREE.Object3D(); | ||
+ | obj1.name = " | ||
+ | obj1.userData.explodable = 1; | ||
+ | obj1.userData.points = []; | ||
+ | obj1.userData.points.push(new PMPoint(0, 0, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(1, 1, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | |||
+ | obj1.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj1.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj1.userData.pointlabels = [" | ||
+ | obj1.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj1.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj1.userData.facets = [[2, 0, 1]]; | ||
+ | < | ||
+ | obj1.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj1); | ||
+ | scene.add(obj1); | ||
+ | |||
+ | var obj2 = new THREE.Object3D(); | ||
+ | obj2.name = " | ||
+ | obj2.userData.explodable = 1; | ||
+ | obj2.userData.points = []; | ||
+ | obj2.userData.points.push(new PMPoint(1, 1, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(2, 2, 0)); | ||
+ | |||
+ | obj2.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj2.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj2.userData.pointlabels = [" | ||
+ | obj2.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj2.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj2.userData.facets = [[2, 1, 0]]; | ||
+ | < | ||
+ | obj2.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj2); | ||
+ | scene.add(obj2); | ||
+ | |||
+ | var obj3 = new THREE.Object3D(); | ||
+ | obj3.name = " | ||
+ | obj3.userData.explodable = 1; | ||
+ | obj3.userData.points = []; | ||
+ | obj3.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj3.userData.points.push(new PMPoint(2, 2, 0)); | ||
+ | obj3.userData.points.push(new PMPoint(1, 3, 0)); | ||
+ | |||
+ | obj3.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj3.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj3.userData.pointlabels = [" | ||
+ | obj3.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj3.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj3.userData.facets = [[2, 0, 1]]; | ||
+ | < | ||
+ | obj3.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj3); | ||
+ | scene.add(obj3); | ||
+ | |||
+ | var obj4 = new THREE.Object3D(); | ||
+ | obj4.name = " | ||
+ | obj4.userData.explodable = 1; | ||
+ | obj4.userData.points = []; | ||
+ | obj4.userData.points.push(new PMPoint(2, 0, 0)); | ||
+ | obj4.userData.points.push(new PMPoint(1, 1, 0)); | ||
+ | obj4.userData.points.push(new PMPoint(2, 2, 0)); | ||
+ | |||
+ | obj4.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj4.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj4.userData.pointlabels = [" | ||
+ | obj4.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj4.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj4.userData.facets = [[2, 1, 0]]; | ||
+ | < | ||
+ | obj4.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj4); | ||
+ | scene.add(obj4); | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | function textSpriteMaterial(message, | ||
+ | if ( parameters === undefined ) parameters = {}; | ||
+ | var fontface = " | ||
+ | var fontsize = parameters.hasOwnProperty(" | ||
+ | fontsize = fontsize*10; | ||
+ | var lines = message.split(' | ||
+ | var size = 512; | ||
+ | for(var i = 0; i< | ||
+ | var tmp = lines[i].length; | ||
+ | while(tmp*fontsize > size){ | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | var canvas = document.createElement(' | ||
+ | canvas.width = size; | ||
+ | canvas.height = size; | ||
+ | var context = canvas.getContext(' | ||
+ | context.fillStyle = " | ||
+ | context.fill(); | ||
+ | context.font = fontsize + "px " + fontface; | ||
+ | | ||
+ | // text color | ||
+ | context.fillStyle = " | ||
+ | | ||
+ | context.fillText(lines[i], | ||
+ | } | ||
+ | | ||
+ | // canvas contents will be used for a texture | ||
+ | var texture = new THREE.Texture(canvas); | ||
+ | texture.needsUpdate = true; | ||
+ | | ||
+ | var spriteMaterial = new THREE.SpriteMaterial({map: | ||
+ | return spriteMaterial; | ||
+ | } | ||
+ | |||
+ | |||
+ | // ---------------------- INITIALIZING OBJECTS-------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function init_object(obj) { | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_points(obj); | ||
+ | modelContains.points = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_pointlabels(obj); | ||
+ | modelContains.pointlabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_lines(obj); | ||
+ | modelContains.lines = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_edgelabels(obj); | ||
+ | modelContains.edgelabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_arrowheads(obj); | ||
+ | modelContains.arrowheads = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_faces(obj); | ||
+ | modelContains.faces = true; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function init_points(obj) { | ||
+ | var pointgroup = new THREE.Group(); | ||
+ | pointgroup.name = " | ||
+ | var points = obj.userData.points; | ||
+ | var radii = obj.userData.pointradii; | ||
+ | var materials = obj.userData.pointmaterial; | ||
+ | var geometry, | ||
+ | if (!Array.isArray(radii)) { | ||
+ | geometry = new THREE.SphereBufferGeometry(radii); | ||
+ | } | ||
+ | if (!Array.isArray(materials)) { | ||
+ | material = materials; | ||
+ | } | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | if (Array.isArray(radii)) { | ||
+ | if (radii[i] == 0) { | ||
+ | continue; | ||
+ | } | ||
+ | geometry = new THREE.SphereBufferGeometry(radii[i]); | ||
+ | } | ||
+ | if (Array.isArray(materials)) { | ||
+ | material = materials[i]; | ||
+ | } | ||
+ | var sphere = new THREE.Mesh(geometry, | ||
+ | point.addSphere(sphere); | ||
+ | pointgroup.add(sphere); | ||
+ | } | ||
+ | obj.add(pointgroup); | ||
+ | } | ||
+ | |||
+ | function init_pointlabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var labels = obj.userData.pointlabels; | ||
+ | var pointlabels = new THREE.Group(); | ||
+ | pointlabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(pointlabels); | ||
+ | } | ||
+ | |||
+ | function init_lines(obj) { | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var points = obj.userData.points; | ||
+ | var materials = obj.userData.edgematerial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 ); | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | for (var i=0; i< | ||
+ | geometry.addGroup(2*i, | ||
+ | } | ||
+ | } | ||
+ | var lines = new THREE.LineSegments(geometry, | ||
+ | lines.name = " | ||
+ | obj.add(lines); | ||
+ | updateEdgesPosition(obj); | ||
+ | } | ||
+ | |||
+ | function init_edgelabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var labels = obj.userData.edgelabels; | ||
+ | var edgelabels = new THREE.Group(); | ||
+ | edgelabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(edgelabels); | ||
+ | } | ||
+ | |||
+ | function init_arrowheads(obj) { | ||
+ | var arrowheads = new THREE.Group(); | ||
+ | arrowheads.name = " | ||
+ | var arrowstyle = obj.userData.arrowstyle; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var edgematerials = obj.userData.edgematerial; | ||
+ | var points = obj.userData.points; | ||
+ | var material; | ||
+ | if (!Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials.color} ); | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var start = points[edgeindices[i]]; | ||
+ | var end = points[edgeindices[i+1]]; | ||
+ | var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius(); | ||
+ | if (dist <= 0) { | ||
+ | continue; | ||
+ | } | ||
+ | var dir = new THREE.Vector3().subVectors(end.vector, | ||
+ | dir.normalize(); | ||
+ | var axis = new THREE.Vector3().set(dir.z, | ||
+ | axis.normalize(); | ||
+ | var radians = Math.acos( dir.y ); | ||
+ | var radius = dist/25; | ||
+ | var height = dist/5; | ||
+ | var geometry = new THREE.ConeBufferGeometry(radius, | ||
+ | var position = new THREE.Vector3().addVectors(start.vector, | ||
+ | if (Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} ); | ||
+ | } | ||
+ | var cone = new THREE.Mesh( geometry, material ); | ||
+ | cone.quaternion.setFromAxisAngle(axis, | ||
+ | cone.position.copy(position);; | ||
+ | arrowheads.add(cone); | ||
+ | } | ||
+ | obj.add(arrowheads); | ||
+ | } | ||
+ | |||
+ | function init_faces(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var facets = obj.userData.facets; | ||
+ | obj.userData.triangleindices = []; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | for (var t=0; t< | ||
+ | obj.userData.triangleindices.push(facet[0], | ||
+ | } | ||
+ | } | ||
+ | var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute(bufarr, | ||
+ | | ||
+ | var materials = obj.userData.facetmaterial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var frontmaterials = []; | ||
+ | var backmaterials = []; | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | var tricount = 0; | ||
+ | var facet; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | geometry.addGroup(tricount, | ||
+ | tricount += (facet.length-2)*3; | ||
+ | } | ||
+ | for (var j=0; j< | ||
+ | var fmat = materials[j].clone() | ||
+ | fmat.side = THREE.FrontSide; | ||
+ | frontmaterials.push(fmat); | ||
+ | var bmat = materials[j].clone() | ||
+ | bmat.side = THREE.BackSide; | ||
+ | backmaterials.push(bmat); | ||
+ | obj.userData.facetmaterial = frontmaterials.concat(backmaterials); | ||
+ | } | ||
+ | } else if (materials instanceof THREE.Material) { | ||
+ | frontmaterials = materials.clone() | ||
+ | frontmaterials.side = THREE.FrontSide; | ||
+ | backmaterials = materials.clone() | ||
+ | backmaterials.side = THREE.BackSide; | ||
+ | obj.userData.facetmaterial = [frontmaterials, | ||
+ | } | ||
+ | // duplicating the object with front and back should avoid transparency issues | ||
+ | var backmesh = new THREE.Mesh(geometry, | ||
+ | // meshname is used to show/hide objects | ||
+ | backmesh.name = " | ||
+ | obj.add(backmesh); | ||
+ | var frontmesh = new THREE.Mesh(geometry, | ||
+ | frontmesh.name = " | ||
+ | obj.add(frontmesh); | ||
+ | updateFacesPosition(obj); | ||
+ | } | ||
+ | // // | ||
+ | |||
+ | |||
+ | function updateFacesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.triangleindices; | ||
+ | var faces = obj.getObjectByName(" | ||
+ | var ba = faces.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | faces.geometry.attributes.position.needsUpdate = true; | ||
+ | | ||
+ | } | ||
+ | |||
+ | function updateEdgesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.edgeindices; | ||
+ | var lines = obj.getObjectByName(" | ||
+ | var ba = lines.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | lines.geometry.attributes.position.needsUpdate = true; | ||
+ | } | ||
+ | |||
+ | function onWindowResize() { | ||
+ | renderer.setSize( three.clientWidth, | ||
+ | svgRenderer.setSize( three.clientWidth, | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | function updateCamera() { | ||
+ | var width = three.clientWidth; | ||
+ | var height = three.clientHeight; | ||
+ | var aspect = width / height; | ||
+ | if (camera.type == " | ||
+ | camera.left = frustumSize * aspect / - 2; | ||
+ | camera.right = frustumSize * aspect / 2; | ||
+ | camera.top = frustumSize / 2; | ||
+ | camera.bottom = - frustumSize / 2; | ||
+ | } else if (camera.type == " | ||
+ | camera.aspect = aspect; | ||
+ | } | ||
+ | camera.updateProjectionMatrix(); | ||
+ | } | ||
+ | |||
+ | function changeCamera(event) { | ||
+ | var selindex = event.currentTarget.selectedIndex; | ||
+ | camera = cameras[selindex]; | ||
+ | control = controls[selindex]; | ||
+ | control.enabled = true; | ||
+ | for (var i=0; i< | ||
+ | if (i!=selindex) { | ||
+ | controls[i].enabled = false; | ||
+ | } | ||
+ | } | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | var camtypenode = document.getElementById(' | ||
+ | camtypenode.onchange = changeCamera; | ||
+ | camtypenode.dispatchEvent(new Event(' | ||
+ | |||
+ | onWindowResize(); | ||
+ | window.addEventListener(' | ||
+ | |||
+ | |||
+ | 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.000001; | ||
+ | var XMLS = new XMLSerializer(); | ||
+ | var svgElement; | ||
+ | var renderId; | ||
+ | |||
+ | var render = function () { | ||
+ | |||
+ | renderId = requestAnimationFrame(render); | ||
+ | |||
+ | // comment in for automatic explosion | ||
+ | // | ||
+ | |||
+ | var phi = 0.02 * rotationSpeedFactor; | ||
+ | |||
+ | if (xRotationEnabled) { | ||
+ | scene.rotation.x += phi; | ||
+ | } | ||
+ | if (yRotationEnabled) { | ||
+ | scene.rotation.y += phi; | ||
+ | } | ||
+ | if (zRotationEnabled) { | ||
+ | scene.rotation.z += phi; | ||
+ | } | ||
+ | |||
+ | control.update(); | ||
+ | renderer.render(scene, | ||
+ | }; | ||
+ | |||
+ | if ( THREE.WEBGL.isWebGLAvailable() ) { | ||
+ | render(); | ||
+ | } else { | ||
+ | var warning = WEBGL.getWebGLErrorMessage(); | ||
+ | three.appendChild( warning ); | ||
+ | } | ||
+ | | ||
+ | function changeTransparency() { | ||
+ | var opacity = 1-Number(event.currentTarget.value); | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].opacity = opacity; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.opacity = opacity; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleDepthWrite(event) { | ||
+ | depthwrite = event.currentTarget.checked; | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].depthWrite = depthwrite; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.depthWrite = depthWrite; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | 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, | ||
+ | camera.position.set(0, | ||
+ | camera.up.set(0, | ||
+ | } | ||
+ | |||
+ | function showSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = true; | ||
+ | } | ||
+ | |||
+ | function hideSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = false; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | var pos = 150* Math.PI; | ||
+ | |||
+ | function updateFactor() { | ||
+ | pos++; | ||
+ | return Math.sin(.01*pos)+1; | ||
+ | } | ||
+ | |||
+ | // ------------------------ FOLDING ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | // rotate point p around axis defined by points p1 and p2 by given angle | ||
+ | function rotate(p, p1, p2, angle ){ | ||
+ | angle = -angle; | ||
+ | var x = p.x, y = p.y, z = p.z, | ||
+ | a = p1.x, b = p1.y, c = p1.z, | ||
+ | u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z; | ||
+ | var result = []; | ||
+ | var L = u*u + v*v + w*w; | ||
+ | var sqrt = Math.sqrt; | ||
+ | var cos = Math.cos; | ||
+ | var sin = Math.sin; | ||
+ | |||
+ | result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/ | ||
+ | result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/ | ||
+ | result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/ | ||
+ | |||
+ | return result; | ||
+ | } | ||
+ | |||
+ | var fold = function(event){ | ||
+ | var obj = foldables[Number(event.currentTarget.name)]; | ||
+ | var foldvalue = Number(event.currentTarget.value); | ||
+ | var scale = foldvalue - obj.userData.oldscale; | ||
+ | |||
+ | for (var j=0; j< | ||
+ | rotateVertices(obj, | ||
+ | } | ||
+ | update(obj); | ||
+ | obj.userData.oldscale += scale; | ||
+ | lookAtBarycenter(obj); | ||
+ | } | ||
+ | |||
+ | function lookAtBarycenter(obj){ | ||
+ | control.target = barycenter(obj); | ||
+ | } | ||
+ | |||
+ | function barycenter(obj) { | ||
+ | var center = new THREE.Vector3(0, | ||
+ | var points = obj.userData.points; | ||
+ | for (var i=0; i< | ||
+ | center.add(points[i].vector); | ||
+ | } | ||
+ | center.divideScalar(points.length); | ||
+ | return center; | ||
+ | } | ||
+ | |||
+ | function rotateVertices(obj, | ||
+ | var axes = obj.userData.axes; | ||
+ | var subtrees = obj.userData.subtrees; | ||
+ | var points = obj.userData.points; | ||
+ | var angles = obj.userData.angles; | ||
+ | if (edge < axes.length){ | ||
+ | for (var j=0; j< | ||
+ | var rotP = rotate(points[subtrees[edge][j]].vector, | ||
+ | points[subtrees[edge][j]].set(rotP[0], | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function update(obj) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | if (foldables.length) { | ||
+ | var settings = document.getElementById(' | ||
+ | var foldDiv = document.createElement(' | ||
+ | foldDiv.id = ' | ||
+ | var title = document.createElement(' | ||
+ | title.innerHTML = ' | ||
+ | foldDiv.appendChild(title); | ||
+ | foldDiv.className = ' | ||
+ | for (var i=0; i< | ||
+ | var range = document.createElement(' | ||
+ | range.type = ' | ||
+ | range.min = 0; | ||
+ | range.max = 1; | ||
+ | range.value = 0; | ||
+ | range.step = 0.001; | ||
+ | range.name = String(i); | ||
+ | range.oninput = fold; | ||
+ | foldDiv.appendChild(range); | ||
+ | } | ||
+ | lookAtBarycenter(foldables[0]); | ||
+ | settings.insertBefore(foldDiv, | ||
+ | } | ||
+ | |||
+ | | ||
+ | // ---------------------- EXPLOSION ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | if (explodableModel) { | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | if ( obj.userData.explodable ) { | ||
+ | computeCentroid(obj); | ||
+ | } | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | explode(0.000001); | ||
+ | } | ||
+ | |||
+ | function computeCentroid(obj) { | ||
+ | centroid = new THREE.Vector3(); | ||
+ | obj.userData.points.forEach(function(pmpoint) { | ||
+ | centroid.add(pmpoint.vector); | ||
+ | }); | ||
+ | centroid.divideScalar(obj.userData.points.length); | ||
+ | obj.userData.centroid = centroid; | ||
+ | } | ||
+ | |||
+ | function explode(factor) { | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i]; | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | var c = obj.userData.centroid; | ||
+ | obj.position.set(c.x*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, | ||
+ | } | ||
+ | |||
+ | |||
+ | function explodingInterval(){ | ||
+ | explodeScale += explodingSpeed; | ||
+ | if (explodeScale <= 6){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else{ | ||
+ | explode(6); | ||
+ | explodeScale = 6; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startUnexploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | |||
+ | function startUnexploding(){ | ||
+ | intervals.push(setInterval(unexplodingInterval, | ||
+ | } | ||
+ | |||
+ | function unexplodingInterval(){ | ||
+ | explodeScale -= explodingSpeed; | ||
+ | if (explodeScale >= 0){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else { | ||
+ | explode(0); | ||
+ | explodeScale = 0; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startExploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | function clearIntervals(){ | ||
+ | intervals.forEach(function(interval){ | ||
+ | clearInterval(interval); | ||
+ | }); | ||
+ | intervals = []; | ||
+ | timeouts.forEach(function(timeout){ | ||
+ | clearTimeout(timeout); | ||
+ | }); | ||
+ | timeouts = []; | ||
+ | } | ||
+ | |||
+ | // ---------------------- DISPLAY -------------------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | const objectTypeInnerHTMLs = { points: " | ||
+ | const objectTypeVisible = {}; | ||
+ | Object.assign(objectTypeVisible, | ||
+ | const sortedObjectTypeKeys = Object.keys(objectTypeInnerHTMLs).sort(); | ||
+ | const shownObjectTypesList = document.getElementById(' | ||
+ | |||
+ | function setVisibility(bool, | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i].getObjectByName(objname); | ||
+ | if (obj) { | ||
+ | obj.visible = bool; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleObjectTypeVisibility(event){ | ||
+ | var name = event.currentTarget.name; | ||
+ | var checked = event.currentTarget.checked; | ||
+ | objectTypeVisible[name] = checked; | ||
+ | if (name == " | ||
+ | setVisibility(checked," | ||
+ | setVisibility(checked," | ||
+ | } else { | ||
+ | setVisibility(checked, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var key = sortedObjectTypeKeys[i]; | ||
+ | if (modelContains[key]) { | ||
+ | var objTypeNode = document.createElement(' | ||
+ | objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = key; | ||
+ | checkbox.onchange = toggleObjectTypeVisibility; | ||
+ | shownObjectTypesList.appendChild(checkbox); | ||
+ | shownObjectTypesList.appendChild(objTypeNode); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // ------------------------------------------------------ | ||
+ | |||
+ | function toggleObjectVisibility(event){ | ||
+ | var nr = Number(event.currentTarget.name); | ||
+ | scene.children[nr].visible = event.currentTarget.checked; | ||
+ | } | ||
+ | |||
+ | // append checkboxes for displaying or hiding objects | ||
+ | var shownObjectsList = document.getElementById(' | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | var objNode = document.createElement(' | ||
+ | objNode.innerHTML = obj.name + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = String(i); | ||
+ | checkbox.onchange = toggleObjectVisibility; | ||
+ | shownObjectsList.appendChild(checkbox); | ||
+ | shownObjectsList.appendChild(objNode); | ||
+ | } | ||
+ | |||
+ | // ---------------------- SVG ------------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function takeSvgScreenshot() { | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | svgRenderer.render(scene, | ||
+ | svgElement = XMLS.serializeToString(svgRenderer.domElement); | ||
+ | | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | |||
+ | if (document.getElementById(' | ||
+ | //show in new tab | ||
+ | var myWindow = window.open("","" | ||
+ | myWindow.document.body.innerHTML = svgElement; | ||
+ | } else{ | ||
+ | // download svg file | ||
+ | download(" | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function download(filename, | ||
+ | var element = document.createElement(' | ||
+ | element.setAttribute(' | ||
+ | element.setAttribute(' | ||
+ | |||
+ | element.style.display = ' | ||
+ | document.body.appendChild(element); | ||
+ | |||
+ | element.click(); | ||
+ | |||
+ | document.body.removeChild(element); | ||
+ | } | ||
+ | |||
+ | |||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | |||
+ | |||
+ | // ------------------ SHORTCUTS -------------------------------------------- | ||
+ | // ------------------------------------------------------------------------- | ||
+ | |||
+ | /** | ||
+ | * http:// | ||
+ | * Version : 2.01.B | ||
+ | * By Binny V A | ||
+ | * License : BSD | ||
+ | */ | ||
+ | shortcut = { | ||
+ | ' | ||
+ | ' | ||
+ | //Provide a set of default options | ||
+ | var default_options = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | if(!opt) opt = default_options; | ||
+ | else { | ||
+ | for(var dfo in default_options) { | ||
+ | if(typeof opt[dfo] == ' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | var ele = opt.target; | ||
+ | if(typeof 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[' | ||
+ | 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 == ' | ||
+ | } | ||
+ | |||
+ | //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(code == 190) character=" | ||
+ | |||
+ | 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 = { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | ";":":", | ||
+ | "'":" | ||
+ | ",":"<", | ||
+ | " | ||
+ | "/":"?", | ||
+ | " | ||
+ | } | ||
+ | // | ||
+ | var special_keys = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | |||
+ | var modifiers = { | ||
+ | shift: { wanted: | ||
+ | ctrl : { wanted: | ||
+ | alt | ||
+ | meta : { wanted: | ||
+ | }; | ||
+ | | ||
+ | if(e.ctrlKey) modifiers.ctrl.pressed = true; | ||
+ | if(e.shiftKey) modifiers.shift.pressed = true; | ||
+ | if(e.altKey) modifiers.alt.pressed = true; | ||
+ | if(e.metaKey) | ||
+ | | ||
+ | for(var i=0; k=keys[i], | ||
+ | // | ||
+ | if(k == ' | ||
+ | kp++; | ||
+ | modifiers.ctrl.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.shift.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.alt.wanted = true; | ||
+ | } else if(k == ' | ||
+ | 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[' | ||
+ | if(opt[' | ||
+ | |||
+ | } 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[' | ||
+ | // | ||
+ | e.cancelBubble = true; | ||
+ | e.returnValue = false; | ||
+ | |||
+ | // | ||
+ | if (e.stopPropagation) { | ||
+ | e.stopPropagation(); | ||
+ | e.preventDefault(); | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | this.all_shortcuts[shortcut_combination] = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | }; | ||
+ | //Attach the function with the event | ||
+ | if(ele.addEventListener) ele.addEventListener(opt[' | ||
+ | else if(ele.attachEvent) ele.attachEvent(' | ||
+ | else ele[' | ||
+ | }, | ||
+ | |||
+ | //Remove the shortcut - just specify the shortcut and I will remove the binding | ||
+ | ' | ||
+ | shortcut_combination = shortcut_combination.toLowerCase(); | ||
+ | var binding = this.all_shortcuts[shortcut_combination]; | ||
+ | delete(this.all_shortcuts[shortcut_combination]) | ||
+ | if(!binding) return; | ||
+ | var type = binding[' | ||
+ | var ele = binding[' | ||
+ | var callback = binding[' | ||
+ | |||
+ | if(ele.detachEvent) ele.detachEvent(' | ||
+ | else if(ele.removeEventListener) ele.removeEventListener(type, | ||
+ | else ele[' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | shortcut.add(" | ||
+ | var event = new Event(' | ||
+ | if (settingsShown){ | ||
+ | document.getElementById(' | ||
+ | } else { | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | });}); | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | Indeed, the regular subdivision arising from this height function is a triangulation. Since in this case point 2 is a vertex of the subdivision it is colored red as well. | ||
+ | |||
+ | ==== Generic Weights ==== | ||
+ | |||
+ | The weights '' | ||
+ | |||
+ | <code perl> | ||
+ | > $SC = new topaz:: | ||
+ | </ | ||
+ | Note that '' | ||
+ | |||
+ | <code perl> | ||
+ | > print $SC-> | ||
+ | 6 10 5 | ||
+ | > print $SC-> | ||
+ | 1 3 1 0 | ||
+ | </ | ||
+ | Check the properties of '' | ||
+ | |||
+ | ==== Non-generic Weights ==== | ||
+ | |||
+ | If your weights are not generic or you are unsure, then you should create a '' | ||
+ | |||
+ | <code perl> | ||
+ | > $M = new Matrix< | ||
+ | > $w = new Vector< | ||
+ | > $S = new fan:: | ||
+ | > $PC = $S-> | ||
+ | > print $PC-> | ||
+ | {0 1 2 4} | ||
+ | {1 2 4 7} | ||
+ | {1 4 6 7 8} | ||
+ | {2 4 5 7 8} | ||
+ | {1 2 3 7} | ||
+ | </ | ||
+ | As with an simplicial complex you can do some computation with it. For example: | ||
+ | |||
+ | <code perl> | ||
+ | > print $PC-> | ||
+ | 9 20 17 5 | ||
+ | > print $PC-> | ||
+ | false | ||
+ | > $PC-> | ||
+ | </ | ||
+ | < | ||
+ | <!-- | ||
+ | polymake for knusper | ||
+ | Thu Mar 3 00:43:53 2022 | ||
+ | pcom: | ||
+ | --> | ||
+ | |||
+ | |||
+ | < | ||
+ | < | ||
+ | <meta charset=utf-8> | ||
+ | < | ||
+ | < | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | */ | ||
+ | html {overflow: scroll;} | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | # | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_END | ||
+ | */ | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | <div id=' | ||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | <div class=suboption> | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | <select id=" | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | <img id=' | ||
+ | <img id=' | ||
+ | <div id=" | ||
+ | </ | ||
+ | < | ||
+ | requirejs.config({ | ||
+ | paths: { | ||
+ | three: '/ | ||
+ | TrackballControls: | ||
+ | OrbitControls: | ||
+ | Projector: '/ | ||
+ | SVGRenderer: | ||
+ | WEBGL: '/ | ||
+ | }, | ||
+ | shim: { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | }); | ||
+ | | ||
+ | require([' | ||
+ | window.THREE = THREE; | ||
+ | require([' | ||
+ | | ||
+ | THREE.TrackballControls = TrackballControls; | ||
+ | THREE.OrbitControls = OrbitControls; | ||
+ | THREE.Projector = Projector; | ||
+ | THREE.SVGRenderer = SVGRenderer; | ||
+ | THREE.WEBGL = WEBGL; | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | |||
+ | const intervalLength = 25; // for automatic animations | ||
+ | const explodableModel = true; | ||
+ | const modelContains = { points: false, pointlabels: | ||
+ | const foldables = []; | ||
+ | |||
+ | var three = document.getElementById(" | ||
+ | var scene = new THREE.Scene(); | ||
+ | var renderer = new THREE.WebGLRenderer( { antialias: true } ); | ||
+ | var svgRenderer = new THREE.SVGRenderer( { antialias: true } ); | ||
+ | renderer.setPixelRatio( window.devicePixelRatio ); | ||
+ | renderer.setClearColor(0xFFFFFF, | ||
+ | svgRenderer.setClearColor(0xFFFFFF, | ||
+ | three.appendChild(renderer.domElement); | ||
+ | |||
+ | var frustumSize = 4; | ||
+ | var cameras = [new THREE.PerspectiveCamera(75, | ||
+ | cameras.forEach(function(cam) { | ||
+ | cam.position.set(0, | ||
+ | cam.lookAt(0, | ||
+ | cam.up.set(0, | ||
+ | }); | ||
+ | var controls = [new THREE.TrackballControls(cameras[0], | ||
+ | var camera, control; | ||
+ | |||
+ | controls[0].zoomSpeed = 0.2; | ||
+ | controls[0].rotateSpeed = 4; | ||
+ | |||
+ | |||
+ | // class to allow move points together with labels and spheres | ||
+ | var PMPoint = function (x,y,z) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addLabel = function(labelsprite) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addSphere = function(spheremesh) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.set = function(x, | ||
+ | | ||
+ | if (this.sprite) { | ||
+ | this.sprite.position.copy(this.vector); | ||
+ | } | ||
+ | if (this.sphere) { | ||
+ | this.sphere.position.copy(this.vector); | ||
+ | } | ||
+ | } | ||
+ | PMPoint.prototype.radius = function() { | ||
+ | if (this.sphere) { | ||
+ | return this.sphere.geometry.parameters.radius; | ||
+ | } else { | ||
+ | return 0; | ||
+ | } | ||
+ | }; | ||
+ | // select the target node | ||
+ | var target = document.querySelector('# | ||
+ | |||
+ | // create an observer instance | ||
+ | var observer = new MutationObserver(function(mutations) { | ||
+ | | ||
+ | if (mutation.removedNodes && mutation.removedNodes.length > 0) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | }); | ||
+ | }); | ||
+ | |||
+ | // configuration of the observer: | ||
+ | var config = { childList: true, characterData: | ||
+ | |||
+ | // pass in the target node, as well as the observer options | ||
+ | while (target) { | ||
+ | if (target.className==" | ||
+ | observer.observe(target, | ||
+ | break; | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | var obj0 = new THREE.Object3D(); | ||
+ | obj0.name = " | ||
+ | obj0.userData.explodable = 1; | ||
+ | obj0.userData.points = []; | ||
+ | obj0.userData.points.push(new PMPoint(0, 0, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(0, 0, 1)); | ||
+ | |||
+ | obj0.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj0.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj0.userData.pointlabels = [" | ||
+ | obj0.userData.edgeindices = [0, 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3]; | ||
+ | < | ||
+ | obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj0.userData.facets = [[1, 3, 2], [0, 3, 1], [2, 3, 0], [1, 2, 0]]; | ||
+ | < | ||
+ | obj0.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj0); | ||
+ | scene.add(obj0); | ||
+ | |||
+ | var obj1 = new THREE.Object3D(); | ||
+ | obj1.name = " | ||
+ | obj1.userData.explodable = 1; | ||
+ | obj1.userData.points = []; | ||
+ | obj1.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(0, 0, 1)); | ||
+ | obj1.userData.points.push(new PMPoint(1, 1, 1)); | ||
+ | |||
+ | obj1.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj1.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj1.userData.pointlabels = [" | ||
+ | obj1.userData.edgeindices = [0, 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3]; | ||
+ | < | ||
+ | obj1.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj1.userData.facets = [[0, 3, 1], [2, 3, 0], [1, 3, 2], [0, 1, 2]]; | ||
+ | < | ||
+ | obj1.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj1); | ||
+ | scene.add(obj1); | ||
+ | |||
+ | var obj2 = new THREE.Object3D(); | ||
+ | obj2.name = " | ||
+ | obj2.userData.explodable = 1; | ||
+ | obj2.userData.points = []; | ||
+ | obj2.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(0, 0, 1)); | ||
+ | obj2.userData.points.push(new PMPoint(0, 1, 1)); | ||
+ | obj2.userData.points.push(new PMPoint(1, 1, 1)); | ||
+ | obj2.userData.points.push(new PMPoint(0, 0, 2)); | ||
+ | |||
+ | obj2.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj2.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj2.userData.pointlabels = [" | ||
+ | obj2.userData.edgeindices = [0, 1, 0, 2, 0, 3, 1, 3, 2, 3, 1, 4, 2, 4, 3, 4]; | ||
+ | < | ||
+ | obj2.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj2.userData.facets = [[3, 1, 0], [4, 1, 3], [2, 4, 3], [3, 0, 2], [0, 1, 4, 2]]; | ||
+ | < | ||
+ | obj2.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj2); | ||
+ | scene.add(obj2); | ||
+ | |||
+ | var obj3 = new THREE.Object3D(); | ||
+ | obj3.name = " | ||
+ | obj3.userData.explodable = 1; | ||
+ | obj3.userData.points = []; | ||
+ | obj3.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | obj3.userData.points.push(new PMPoint(0, 0, 1)); | ||
+ | obj3.userData.points.push(new PMPoint(1, 0, 1)); | ||
+ | obj3.userData.points.push(new PMPoint(1, 1, 1)); | ||
+ | obj3.userData.points.push(new PMPoint(0, 0, 2)); | ||
+ | |||
+ | obj3.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj3.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj3.userData.pointlabels = [" | ||
+ | obj3.userData.edgeindices = [0, 1, 0, 2, 0, 3, 1, 3, 2, 3, 1, 4, 2, 4, 3, 4]; | ||
+ | < | ||
+ | obj3.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj3.userData.facets = [[1, 3, 0], [1, 4, 3], [2, 3, 4], [0, 3, 2], [1, 0, 2, 4]]; | ||
+ | < | ||
+ | obj3.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj3); | ||
+ | scene.add(obj3); | ||
+ | |||
+ | var obj4 = new THREE.Object3D(); | ||
+ | obj4.name = " | ||
+ | obj4.userData.explodable = 1; | ||
+ | obj4.userData.points = []; | ||
+ | obj4.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | obj4.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | obj4.userData.points.push(new PMPoint(1, 1, 0)); | ||
+ | obj4.userData.points.push(new PMPoint(1, 1, 1)); | ||
+ | |||
+ | obj4.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj4.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj4.userData.pointlabels = [" | ||
+ | obj4.userData.edgeindices = [0, 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3]; | ||
+ | < | ||
+ | obj4.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj4.userData.facets = [[2, 3, 1], [0, 3, 2], [1, 3, 0], [2, 1, 0]]; | ||
+ | < | ||
+ | obj4.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj4); | ||
+ | scene.add(obj4); | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | function textSpriteMaterial(message, | ||
+ | if ( parameters === undefined ) parameters = {}; | ||
+ | var fontface = " | ||
+ | var fontsize = parameters.hasOwnProperty(" | ||
+ | fontsize = fontsize*10; | ||
+ | var lines = message.split(' | ||
+ | var size = 512; | ||
+ | for(var i = 0; i< | ||
+ | var tmp = lines[i].length; | ||
+ | while(tmp*fontsize > size){ | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | var canvas = document.createElement(' | ||
+ | canvas.width = size; | ||
+ | canvas.height = size; | ||
+ | var context = canvas.getContext(' | ||
+ | context.fillStyle = " | ||
+ | context.fill(); | ||
+ | context.font = fontsize + "px " + fontface; | ||
+ | | ||
+ | // text color | ||
+ | context.fillStyle = " | ||
+ | | ||
+ | context.fillText(lines[i], | ||
+ | } | ||
+ | | ||
+ | // canvas contents will be used for a texture | ||
+ | var texture = new THREE.Texture(canvas); | ||
+ | texture.needsUpdate = true; | ||
+ | | ||
+ | var spriteMaterial = new THREE.SpriteMaterial({map: | ||
+ | return spriteMaterial; | ||
+ | } | ||
+ | |||
+ | |||
+ | // ---------------------- INITIALIZING OBJECTS-------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function init_object(obj) { | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_points(obj); | ||
+ | modelContains.points = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_pointlabels(obj); | ||
+ | modelContains.pointlabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_lines(obj); | ||
+ | modelContains.lines = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_edgelabels(obj); | ||
+ | modelContains.edgelabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_arrowheads(obj); | ||
+ | modelContains.arrowheads = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_faces(obj); | ||
+ | modelContains.faces = true; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function init_points(obj) { | ||
+ | var pointgroup = new THREE.Group(); | ||
+ | pointgroup.name = " | ||
+ | var points = obj.userData.points; | ||
+ | var radii = obj.userData.pointradii; | ||
+ | var materials = obj.userData.pointmaterial; | ||
+ | var geometry, | ||
+ | if (!Array.isArray(radii)) { | ||
+ | geometry = new THREE.SphereBufferGeometry(radii); | ||
+ | } | ||
+ | if (!Array.isArray(materials)) { | ||
+ | material = materials; | ||
+ | } | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | if (Array.isArray(radii)) { | ||
+ | if (radii[i] == 0) { | ||
+ | continue; | ||
+ | } | ||
+ | geometry = new THREE.SphereBufferGeometry(radii[i]); | ||
+ | } | ||
+ | if (Array.isArray(materials)) { | ||
+ | material = materials[i]; | ||
+ | } | ||
+ | var sphere = new THREE.Mesh(geometry, | ||
+ | point.addSphere(sphere); | ||
+ | pointgroup.add(sphere); | ||
+ | } | ||
+ | obj.add(pointgroup); | ||
+ | } | ||
+ | |||
+ | function init_pointlabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var labels = obj.userData.pointlabels; | ||
+ | var pointlabels = new THREE.Group(); | ||
+ | pointlabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(pointlabels); | ||
+ | } | ||
+ | |||
+ | function init_lines(obj) { | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var points = obj.userData.points; | ||
+ | var materials = obj.userData.edgematerial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 ); | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | for (var i=0; i< | ||
+ | geometry.addGroup(2*i, | ||
+ | } | ||
+ | } | ||
+ | var lines = new THREE.LineSegments(geometry, | ||
+ | lines.name = " | ||
+ | obj.add(lines); | ||
+ | updateEdgesPosition(obj); | ||
+ | } | ||
+ | |||
+ | function init_edgelabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var labels = obj.userData.edgelabels; | ||
+ | var edgelabels = new THREE.Group(); | ||
+ | edgelabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(edgelabels); | ||
+ | } | ||
+ | |||
+ | function init_arrowheads(obj) { | ||
+ | var arrowheads = new THREE.Group(); | ||
+ | arrowheads.name = " | ||
+ | var arrowstyle = obj.userData.arrowstyle; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var edgematerials = obj.userData.edgematerial; | ||
+ | var points = obj.userData.points; | ||
+ | var material; | ||
+ | if (!Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials.color} ); | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var start = points[edgeindices[i]]; | ||
+ | var end = points[edgeindices[i+1]]; | ||
+ | var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius(); | ||
+ | if (dist <= 0) { | ||
+ | continue; | ||
+ | } | ||
+ | var dir = new THREE.Vector3().subVectors(end.vector, | ||
+ | dir.normalize(); | ||
+ | var axis = new THREE.Vector3().set(dir.z, | ||
+ | axis.normalize(); | ||
+ | var radians = Math.acos( dir.y ); | ||
+ | var radius = dist/25; | ||
+ | var height = dist/5; | ||
+ | var geometry = new THREE.ConeBufferGeometry(radius, | ||
+ | var position = new THREE.Vector3().addVectors(start.vector, | ||
+ | if (Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} ); | ||
+ | } | ||
+ | var cone = new THREE.Mesh( geometry, material ); | ||
+ | cone.quaternion.setFromAxisAngle(axis, | ||
+ | cone.position.copy(position);; | ||
+ | arrowheads.add(cone); | ||
+ | } | ||
+ | obj.add(arrowheads); | ||
+ | } | ||
+ | |||
+ | function init_faces(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var facets = obj.userData.facets; | ||
+ | obj.userData.triangleindices = []; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | for (var t=0; t< | ||
+ | obj.userData.triangleindices.push(facet[0], | ||
+ | } | ||
+ | } | ||
+ | var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute(bufarr, | ||
+ | | ||
+ | var materials = obj.userData.facetmaterial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var frontmaterials = []; | ||
+ | var backmaterials = []; | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | var tricount = 0; | ||
+ | var facet; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | geometry.addGroup(tricount, | ||
+ | tricount += (facet.length-2)*3; | ||
+ | } | ||
+ | for (var j=0; j< | ||
+ | var fmat = materials[j].clone() | ||
+ | fmat.side = THREE.FrontSide; | ||
+ | frontmaterials.push(fmat); | ||
+ | var bmat = materials[j].clone() | ||
+ | bmat.side = THREE.BackSide; | ||
+ | backmaterials.push(bmat); | ||
+ | obj.userData.facetmaterial = frontmaterials.concat(backmaterials); | ||
+ | } | ||
+ | } else if (materials instanceof THREE.Material) { | ||
+ | frontmaterials = materials.clone() | ||
+ | frontmaterials.side = THREE.FrontSide; | ||
+ | backmaterials = materials.clone() | ||
+ | backmaterials.side = THREE.BackSide; | ||
+ | obj.userData.facetmaterial = [frontmaterials, | ||
+ | } | ||
+ | // duplicating the object with front and back should avoid transparency issues | ||
+ | var backmesh = new THREE.Mesh(geometry, | ||
+ | // meshname is used to show/hide objects | ||
+ | backmesh.name = " | ||
+ | obj.add(backmesh); | ||
+ | var frontmesh = new THREE.Mesh(geometry, | ||
+ | frontmesh.name = " | ||
+ | obj.add(frontmesh); | ||
+ | updateFacesPosition(obj); | ||
+ | } | ||
+ | // // | ||
+ | |||
+ | |||
+ | function updateFacesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.triangleindices; | ||
+ | var faces = obj.getObjectByName(" | ||
+ | var ba = faces.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | faces.geometry.attributes.position.needsUpdate = true; | ||
+ | | ||
+ | } | ||
+ | |||
+ | function updateEdgesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.edgeindices; | ||
+ | var lines = obj.getObjectByName(" | ||
+ | var ba = lines.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | lines.geometry.attributes.position.needsUpdate = true; | ||
+ | } | ||
+ | |||
+ | function onWindowResize() { | ||
+ | renderer.setSize( three.clientWidth, | ||
+ | svgRenderer.setSize( three.clientWidth, | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | function updateCamera() { | ||
+ | var width = three.clientWidth; | ||
+ | var height = three.clientHeight; | ||
+ | var aspect = width / height; | ||
+ | if (camera.type == " | ||
+ | camera.left = frustumSize * aspect / - 2; | ||
+ | camera.right = frustumSize * aspect / 2; | ||
+ | camera.top = frustumSize / 2; | ||
+ | camera.bottom = - frustumSize / 2; | ||
+ | } else if (camera.type == " | ||
+ | camera.aspect = aspect; | ||
+ | } | ||
+ | camera.updateProjectionMatrix(); | ||
+ | } | ||
+ | |||
+ | function changeCamera(event) { | ||
+ | var selindex = event.currentTarget.selectedIndex; | ||
+ | camera = cameras[selindex]; | ||
+ | control = controls[selindex]; | ||
+ | control.enabled = true; | ||
+ | for (var i=0; i< | ||
+ | if (i!=selindex) { | ||
+ | controls[i].enabled = false; | ||
+ | } | ||
+ | } | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | var camtypenode = document.getElementById(' | ||
+ | camtypenode.onchange = changeCamera; | ||
+ | camtypenode.dispatchEvent(new Event(' | ||
+ | |||
+ | onWindowResize(); | ||
+ | window.addEventListener(' | ||
+ | |||
+ | |||
+ | 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.000001; | ||
+ | var XMLS = new XMLSerializer(); | ||
+ | var svgElement; | ||
+ | var renderId; | ||
+ | |||
+ | var render = function () { | ||
+ | |||
+ | renderId = requestAnimationFrame(render); | ||
+ | |||
+ | // comment in for automatic explosion | ||
+ | // | ||
+ | |||
+ | var phi = 0.02 * rotationSpeedFactor; | ||
+ | |||
+ | if (xRotationEnabled) { | ||
+ | scene.rotation.x += phi; | ||
+ | } | ||
+ | if (yRotationEnabled) { | ||
+ | scene.rotation.y += phi; | ||
+ | } | ||
+ | if (zRotationEnabled) { | ||
+ | scene.rotation.z += phi; | ||
+ | } | ||
+ | |||
+ | control.update(); | ||
+ | renderer.render(scene, | ||
+ | }; | ||
+ | |||
+ | if ( THREE.WEBGL.isWebGLAvailable() ) { | ||
+ | render(); | ||
+ | } else { | ||
+ | var warning = WEBGL.getWebGLErrorMessage(); | ||
+ | three.appendChild( warning ); | ||
+ | } | ||
+ | | ||
+ | function changeTransparency() { | ||
+ | var opacity = 1-Number(event.currentTarget.value); | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].opacity = opacity; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.opacity = opacity; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleDepthWrite(event) { | ||
+ | depthwrite = event.currentTarget.checked; | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].depthWrite = depthwrite; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.depthWrite = depthWrite; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | 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, | ||
+ | camera.position.set(0, | ||
+ | camera.up.set(0, | ||
+ | } | ||
+ | |||
+ | function showSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = true; | ||
+ | } | ||
+ | |||
+ | function hideSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = false; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | var pos = 150* Math.PI; | ||
+ | |||
+ | function updateFactor() { | ||
+ | pos++; | ||
+ | return Math.sin(.01*pos)+1; | ||
+ | } | ||
+ | |||
+ | // ------------------------ FOLDING ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | // rotate point p around axis defined by points p1 and p2 by given angle | ||
+ | function rotate(p, p1, p2, angle ){ | ||
+ | angle = -angle; | ||
+ | var x = p.x, y = p.y, z = p.z, | ||
+ | a = p1.x, b = p1.y, c = p1.z, | ||
+ | u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z; | ||
+ | var result = []; | ||
+ | var L = u*u + v*v + w*w; | ||
+ | var sqrt = Math.sqrt; | ||
+ | var cos = Math.cos; | ||
+ | var sin = Math.sin; | ||
+ | |||
+ | result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/ | ||
+ | result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/ | ||
+ | result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/ | ||
+ | |||
+ | return result; | ||
+ | } | ||
+ | |||
+ | var fold = function(event){ | ||
+ | var obj = foldables[Number(event.currentTarget.name)]; | ||
+ | var foldvalue = Number(event.currentTarget.value); | ||
+ | var scale = foldvalue - obj.userData.oldscale; | ||
+ | |||
+ | for (var j=0; j< | ||
+ | rotateVertices(obj, | ||
+ | } | ||
+ | update(obj); | ||
+ | obj.userData.oldscale += scale; | ||
+ | lookAtBarycenter(obj); | ||
+ | } | ||
+ | |||
+ | function lookAtBarycenter(obj){ | ||
+ | control.target = barycenter(obj); | ||
+ | } | ||
+ | |||
+ | function barycenter(obj) { | ||
+ | var center = new THREE.Vector3(0, | ||
+ | var points = obj.userData.points; | ||
+ | for (var i=0; i< | ||
+ | center.add(points[i].vector); | ||
+ | } | ||
+ | center.divideScalar(points.length); | ||
+ | return center; | ||
+ | } | ||
+ | |||
+ | function rotateVertices(obj, | ||
+ | var axes = obj.userData.axes; | ||
+ | var subtrees = obj.userData.subtrees; | ||
+ | var points = obj.userData.points; | ||
+ | var angles = obj.userData.angles; | ||
+ | if (edge < axes.length){ | ||
+ | for (var j=0; j< | ||
+ | var rotP = rotate(points[subtrees[edge][j]].vector, | ||
+ | points[subtrees[edge][j]].set(rotP[0], | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function update(obj) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | if (foldables.length) { | ||
+ | var settings = document.getElementById(' | ||
+ | var foldDiv = document.createElement(' | ||
+ | foldDiv.id = ' | ||
+ | var title = document.createElement(' | ||
+ | title.innerHTML = ' | ||
+ | foldDiv.appendChild(title); | ||
+ | foldDiv.className = ' | ||
+ | for (var i=0; i< | ||
+ | var range = document.createElement(' | ||
+ | range.type = ' | ||
+ | range.min = 0; | ||
+ | range.max = 1; | ||
+ | range.value = 0; | ||
+ | range.step = 0.001; | ||
+ | range.name = String(i); | ||
+ | range.oninput = fold; | ||
+ | foldDiv.appendChild(range); | ||
+ | } | ||
+ | lookAtBarycenter(foldables[0]); | ||
+ | settings.insertBefore(foldDiv, | ||
+ | } | ||
+ | |||
+ | | ||
+ | // ---------------------- EXPLOSION ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | if (explodableModel) { | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | if ( obj.userData.explodable ) { | ||
+ | computeCentroid(obj); | ||
+ | } | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | explode(0.000001); | ||
+ | } | ||
+ | |||
+ | function computeCentroid(obj) { | ||
+ | centroid = new THREE.Vector3(); | ||
+ | obj.userData.points.forEach(function(pmpoint) { | ||
+ | centroid.add(pmpoint.vector); | ||
+ | }); | ||
+ | centroid.divideScalar(obj.userData.points.length); | ||
+ | obj.userData.centroid = centroid; | ||
+ | } | ||
+ | |||
+ | function explode(factor) { | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i]; | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | var c = obj.userData.centroid; | ||
+ | obj.position.set(c.x*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, | ||
+ | } | ||
+ | |||
+ | |||
+ | function explodingInterval(){ | ||
+ | explodeScale += explodingSpeed; | ||
+ | if (explodeScale <= 6){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else{ | ||
+ | explode(6); | ||
+ | explodeScale = 6; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startUnexploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | |||
+ | function startUnexploding(){ | ||
+ | intervals.push(setInterval(unexplodingInterval, | ||
+ | } | ||
+ | |||
+ | function unexplodingInterval(){ | ||
+ | explodeScale -= explodingSpeed; | ||
+ | if (explodeScale >= 0){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else { | ||
+ | explode(0); | ||
+ | explodeScale = 0; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startExploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | function clearIntervals(){ | ||
+ | intervals.forEach(function(interval){ | ||
+ | clearInterval(interval); | ||
+ | }); | ||
+ | intervals = []; | ||
+ | timeouts.forEach(function(timeout){ | ||
+ | clearTimeout(timeout); | ||
+ | }); | ||
+ | timeouts = []; | ||
+ | } | ||
+ | |||
+ | // ---------------------- DISPLAY -------------------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | const objectTypeInnerHTMLs = { points: " | ||
+ | const objectTypeVisible = {}; | ||
+ | Object.assign(objectTypeVisible, | ||
+ | const sortedObjectTypeKeys = Object.keys(objectTypeInnerHTMLs).sort(); | ||
+ | const shownObjectTypesList = document.getElementById(' | ||
+ | |||
+ | function setVisibility(bool, | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i].getObjectByName(objname); | ||
+ | if (obj) { | ||
+ | obj.visible = bool; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleObjectTypeVisibility(event){ | ||
+ | var name = event.currentTarget.name; | ||
+ | var checked = event.currentTarget.checked; | ||
+ | objectTypeVisible[name] = checked; | ||
+ | if (name == " | ||
+ | setVisibility(checked," | ||
+ | setVisibility(checked," | ||
+ | } else { | ||
+ | setVisibility(checked, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var key = sortedObjectTypeKeys[i]; | ||
+ | if (modelContains[key]) { | ||
+ | var objTypeNode = document.createElement(' | ||
+ | objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = key; | ||
+ | checkbox.onchange = toggleObjectTypeVisibility; | ||
+ | shownObjectTypesList.appendChild(checkbox); | ||
+ | shownObjectTypesList.appendChild(objTypeNode); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // ------------------------------------------------------ | ||
+ | |||
+ | function toggleObjectVisibility(event){ | ||
+ | var nr = Number(event.currentTarget.name); | ||
+ | scene.children[nr].visible = event.currentTarget.checked; | ||
+ | } | ||
+ | |||
+ | // append checkboxes for displaying or hiding objects | ||
+ | var shownObjectsList = document.getElementById(' | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | var objNode = document.createElement(' | ||
+ | objNode.innerHTML = obj.name + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = String(i); | ||
+ | checkbox.onchange = toggleObjectVisibility; | ||
+ | shownObjectsList.appendChild(checkbox); | ||
+ | shownObjectsList.appendChild(objNode); | ||
+ | } | ||
+ | |||
+ | // ---------------------- SVG ------------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function takeSvgScreenshot() { | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | svgRenderer.render(scene, | ||
+ | svgElement = XMLS.serializeToString(svgRenderer.domElement); | ||
+ | | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | |||
+ | if (document.getElementById(' | ||
+ | //show in new tab | ||
+ | var myWindow = window.open("","" | ||
+ | myWindow.document.body.innerHTML = svgElement; | ||
+ | } else{ | ||
+ | // download svg file | ||
+ | download(" | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function download(filename, | ||
+ | var element = document.createElement(' | ||
+ | element.setAttribute(' | ||
+ | element.setAttribute(' | ||
+ | |||
+ | element.style.display = ' | ||
+ | document.body.appendChild(element); | ||
+ | |||
+ | element.click(); | ||
+ | |||
+ | document.body.removeChild(element); | ||
+ | } | ||
+ | |||
+ | |||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | |||
+ | |||
+ | // ------------------ SHORTCUTS -------------------------------------------- | ||
+ | // ------------------------------------------------------------------------- | ||
+ | |||
+ | /** | ||
+ | * http:// | ||
+ | * Version : 2.01.B | ||
+ | * By Binny V A | ||
+ | * License : BSD | ||
+ | */ | ||
+ | shortcut = { | ||
+ | ' | ||
+ | ' | ||
+ | //Provide a set of default options | ||
+ | var default_options = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | if(!opt) opt = default_options; | ||
+ | else { | ||
+ | for(var dfo in default_options) { | ||
+ | if(typeof opt[dfo] == ' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | var ele = opt.target; | ||
+ | if(typeof 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[' | ||
+ | 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 == ' | ||
+ | } | ||
+ | |||
+ | //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(code == 190) character=" | ||
+ | |||
+ | 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 = { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | ";":":", | ||
+ | "'":" | ||
+ | ",":"<", | ||
+ | " | ||
+ | "/":"?", | ||
+ | " | ||
+ | } | ||
+ | // | ||
+ | var special_keys = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | |||
+ | var modifiers = { | ||
+ | shift: { wanted: | ||
+ | ctrl : { wanted: | ||
+ | alt | ||
+ | meta : { wanted: | ||
+ | }; | ||
+ | | ||
+ | if(e.ctrlKey) modifiers.ctrl.pressed = true; | ||
+ | if(e.shiftKey) modifiers.shift.pressed = true; | ||
+ | if(e.altKey) modifiers.alt.pressed = true; | ||
+ | if(e.metaKey) | ||
+ | | ||
+ | for(var i=0; k=keys[i], | ||
+ | // | ||
+ | if(k == ' | ||
+ | kp++; | ||
+ | modifiers.ctrl.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.shift.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.alt.wanted = true; | ||
+ | } else if(k == ' | ||
+ | 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[' | ||
+ | if(opt[' | ||
+ | |||
+ | } 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[' | ||
+ | // | ||
+ | e.cancelBubble = true; | ||
+ | e.returnValue = false; | ||
+ | |||
+ | // | ||
+ | if (e.stopPropagation) { | ||
+ | e.stopPropagation(); | ||
+ | e.preventDefault(); | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | this.all_shortcuts[shortcut_combination] = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | }; | ||
+ | //Attach the function with the event | ||
+ | if(ele.addEventListener) ele.addEventListener(opt[' | ||
+ | else if(ele.attachEvent) ele.attachEvent(' | ||
+ | else ele[' | ||
+ | }, | ||
+ | |||
+ | //Remove the shortcut - just specify the shortcut and I will remove the binding | ||
+ | ' | ||
+ | shortcut_combination = shortcut_combination.toLowerCase(); | ||
+ | var binding = this.all_shortcuts[shortcut_combination]; | ||
+ | delete(this.all_shortcuts[shortcut_combination]) | ||
+ | if(!binding) return; | ||
+ | var type = binding[' | ||
+ | var ele = binding[' | ||
+ | var callback = binding[' | ||
+ | |||
+ | if(ele.detachEvent) ele.detachEvent(' | ||
+ | else if(ele.removeEventListener) ele.removeEventListener(type, | ||
+ | else ele[' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | shortcut.add(" | ||
+ | var event = new Event(' | ||
+ | if (settingsShown){ | ||
+ | document.getElementById(' | ||
+ | } else { | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | });}); | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | Check the interactive help to get more information. | ||
+ | |||
+ | ==== Tropical Plücker Vectors and Matroid Decompositions of Hypersimplices ==== | ||
+ | |||
+ | A //tropical Plücker vector// (which is a special lifting function on the vertices of the // | ||
+ | |||
+ | <code perl> | ||
+ | > $p=new Vector< | ||
+ | > $msd=regular_subdivision(hypersimplex(2, | ||
+ | </ | ||
+ | Each cell of this subdivision is a //matroid polytope//, that is, the convex hull of characteristic vectors of the bases of some matroid on //n// elements of rank //d//. The vertices of the hypersimplices happen to be listed in lexicographical ordering. With this extra knowledge we can cook up suitable labels for pretty-printing the maximal cells. | ||
+ | |||
+ | <code perl> | ||
+ | > print rows_labeled($msd, | ||
+ | 0:13 14 23 24 34 | ||
+ | 1:12 13 14 23 24 | ||
+ | </ | ||
+ | In this case the // | ||
+ | |||
+ | ===== Secondary cone and regularity of subdivisions ===== | ||
+ | |||
+ | The set of all the weight vectors which induce the same regular subdivision form a convex cone. In this section we will learn how to compute that cone with polymake and even how we can check whether a given subdivision is regular or not. | ||
+ | |||
+ | ==== Secondary Cone of a Regular Subdivision ==== | ||
+ | |||
+ | Let us look at the following regular subdivision (using homogeneous coordinates): | ||
+ | |||
+ | <code perl> | ||
+ | > $points = new Matrix([[1, | ||
+ | > $cells = new Array< | ||
+ | > $S = new fan:: | ||
+ | </ | ||
+ | we can visualize the subdivision with the following command: | ||
+ | |||
+ | <code perl> | ||
+ | > $S-> | ||
+ | </ | ||
+ | < | ||
+ | <!-- | ||
+ | polymake for knusper | ||
+ | Thu Mar 3 00:43:53 2022 | ||
+ | pcom:S | ||
+ | --> | ||
+ | |||
+ | |||
+ | < | ||
+ | < | ||
+ | <meta charset=utf-8> | ||
+ | < | ||
+ | < | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | */ | ||
+ | html {overflow: scroll;} | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | # | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_END | ||
+ | */ | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | <div id=' | ||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | <div class=suboption> | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | <select id=" | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | <img id=' | ||
+ | <img id=' | ||
+ | <div id=" | ||
+ | </ | ||
+ | < | ||
+ | requirejs.config({ | ||
+ | paths: { | ||
+ | three: '/ | ||
+ | TrackballControls: | ||
+ | OrbitControls: | ||
+ | Projector: '/ | ||
+ | SVGRenderer: | ||
+ | WEBGL: '/ | ||
+ | }, | ||
+ | shim: { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | }); | ||
+ | | ||
+ | require([' | ||
+ | window.THREE = THREE; | ||
+ | require([' | ||
+ | | ||
+ | THREE.TrackballControls = TrackballControls; | ||
+ | THREE.OrbitControls = OrbitControls; | ||
+ | THREE.Projector = Projector; | ||
+ | THREE.SVGRenderer = SVGRenderer; | ||
+ | THREE.WEBGL = WEBGL; | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | |||
+ | const intervalLength = 25; // for automatic animations | ||
+ | const explodableModel = true; | ||
+ | const modelContains = { points: false, pointlabels: | ||
+ | const foldables = []; | ||
+ | |||
+ | var three = document.getElementById(" | ||
+ | var scene = new THREE.Scene(); | ||
+ | var renderer = new THREE.WebGLRenderer( { antialias: true } ); | ||
+ | var svgRenderer = new THREE.SVGRenderer( { antialias: true } ); | ||
+ | renderer.setPixelRatio( window.devicePixelRatio ); | ||
+ | renderer.setClearColor(0xFFFFFF, | ||
+ | svgRenderer.setClearColor(0xFFFFFF, | ||
+ | three.appendChild(renderer.domElement); | ||
+ | |||
+ | var frustumSize = 4; | ||
+ | var cameras = [new THREE.PerspectiveCamera(75, | ||
+ | cameras.forEach(function(cam) { | ||
+ | cam.position.set(0, | ||
+ | cam.lookAt(0, | ||
+ | cam.up.set(0, | ||
+ | }); | ||
+ | var controls = [new THREE.TrackballControls(cameras[0], | ||
+ | var camera, control; | ||
+ | |||
+ | controls[0].zoomSpeed = 0.2; | ||
+ | controls[0].rotateSpeed = 4; | ||
+ | |||
+ | |||
+ | // class to allow move points together with labels and spheres | ||
+ | var PMPoint = function (x,y,z) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addLabel = function(labelsprite) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addSphere = function(spheremesh) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.set = function(x, | ||
+ | | ||
+ | if (this.sprite) { | ||
+ | this.sprite.position.copy(this.vector); | ||
+ | } | ||
+ | if (this.sphere) { | ||
+ | this.sphere.position.copy(this.vector); | ||
+ | } | ||
+ | } | ||
+ | PMPoint.prototype.radius = function() { | ||
+ | if (this.sphere) { | ||
+ | return this.sphere.geometry.parameters.radius; | ||
+ | } else { | ||
+ | return 0; | ||
+ | } | ||
+ | }; | ||
+ | // select the target node | ||
+ | var target = document.querySelector('# | ||
+ | |||
+ | // create an observer instance | ||
+ | var observer = new MutationObserver(function(mutations) { | ||
+ | | ||
+ | if (mutation.removedNodes && mutation.removedNodes.length > 0) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | }); | ||
+ | }); | ||
+ | |||
+ | // configuration of the observer: | ||
+ | var config = { childList: true, characterData: | ||
+ | |||
+ | // pass in the target node, as well as the observer options | ||
+ | while (target) { | ||
+ | if (target.className==" | ||
+ | observer.observe(target, | ||
+ | break; | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | var obj0 = new THREE.Object3D(); | ||
+ | obj0.name = " | ||
+ | obj0.userData.explodable = 1; | ||
+ | obj0.userData.points = []; | ||
+ | obj0.userData.points.push(new PMPoint(2, 0, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | |||
+ | obj0.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj0.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj0.userData.pointlabels = [" | ||
+ | obj0.userData.edgeindices = [0, 1, 0, 2, 1, 3, 2, 3]; | ||
+ | < | ||
+ | obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj0.userData.facets = [[2, 0, 1, 3]]; | ||
+ | < | ||
+ | obj0.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj0); | ||
+ | scene.add(obj0); | ||
+ | |||
+ | var obj1 = new THREE.Object3D(); | ||
+ | obj1.name = " | ||
+ | obj1.userData.explodable = 1; | ||
+ | obj1.userData.points = []; | ||
+ | obj1.userData.points.push(new PMPoint(2, 0, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(0, -2, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(0, -1, 0)); | ||
+ | |||
+ | obj1.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj1.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj1.userData.pointlabels = [" | ||
+ | obj1.userData.edgeindices = [0, 1, 0, 2, 1, 3, 2, 3]; | ||
+ | < | ||
+ | obj1.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj1.userData.facets = [[1, 0, 2, 3]]; | ||
+ | < | ||
+ | obj1.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj1); | ||
+ | scene.add(obj1); | ||
+ | |||
+ | var obj2 = new THREE.Object3D(); | ||
+ | obj2.name = " | ||
+ | obj2.userData.explodable = 1; | ||
+ | obj2.userData.points = []; | ||
+ | obj2.userData.points.push(new PMPoint(-2, 0, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(0, -2, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(-1, 0, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(0, -1, 0)); | ||
+ | |||
+ | obj2.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj2.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj2.userData.pointlabels = [" | ||
+ | obj2.userData.edgeindices = [0, 1, 0, 2, 1, 3, 2, 3]; | ||
+ | < | ||
+ | obj2.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj2.userData.facets = [[0, 1, 3, 2]]; | ||
+ | < | ||
+ | obj2.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj2); | ||
+ | scene.add(obj2); | ||
+ | |||
+ | var obj3 = new THREE.Object3D(); | ||
+ | obj3.name = " | ||
+ | obj3.userData.explodable = 1; | ||
+ | obj3.userData.points = []; | ||
+ | obj3.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj3.userData.points.push(new PMPoint(-2, 0, 0)); | ||
+ | obj3.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | obj3.userData.points.push(new PMPoint(-1, 0, 0)); | ||
+ | |||
+ | obj3.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj3.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj3.userData.pointlabels = [" | ||
+ | obj3.userData.edgeindices = [0, 1, 0, 2, 1, 3, 2, 3]; | ||
+ | < | ||
+ | obj3.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj3.userData.facets = [[3, 2, 0, 1]]; | ||
+ | < | ||
+ | obj3.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj3); | ||
+ | scene.add(obj3); | ||
+ | |||
+ | var obj4 = new THREE.Object3D(); | ||
+ | obj4.name = " | ||
+ | obj4.userData.explodable = 1; | ||
+ | obj4.userData.points = []; | ||
+ | obj4.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | obj4.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | obj4.userData.points.push(new PMPoint(-1, 0, 0)); | ||
+ | obj4.userData.points.push(new PMPoint(0, -1, 0)); | ||
+ | |||
+ | obj4.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj4.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj4.userData.pointlabels = [" | ||
+ | obj4.userData.edgeindices = [0, 1, 1, 2, 0, 3, 2, 3]; | ||
+ | < | ||
+ | obj4.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj4.userData.facets = [[3, 0, 1, 2]]; | ||
+ | < | ||
+ | obj4.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj4); | ||
+ | scene.add(obj4); | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | function textSpriteMaterial(message, | ||
+ | if ( parameters === undefined ) parameters = {}; | ||
+ | var fontface = " | ||
+ | var fontsize = parameters.hasOwnProperty(" | ||
+ | fontsize = fontsize*10; | ||
+ | var lines = message.split(' | ||
+ | var size = 512; | ||
+ | for(var i = 0; i< | ||
+ | var tmp = lines[i].length; | ||
+ | while(tmp*fontsize > size){ | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | var canvas = document.createElement(' | ||
+ | canvas.width = size; | ||
+ | canvas.height = size; | ||
+ | var context = canvas.getContext(' | ||
+ | context.fillStyle = " | ||
+ | context.fill(); | ||
+ | context.font = fontsize + "px " + fontface; | ||
+ | | ||
+ | // text color | ||
+ | context.fillStyle = " | ||
+ | | ||
+ | context.fillText(lines[i], | ||
+ | } | ||
+ | | ||
+ | // canvas contents will be used for a texture | ||
+ | var texture = new THREE.Texture(canvas); | ||
+ | texture.needsUpdate = true; | ||
+ | | ||
+ | var spriteMaterial = new THREE.SpriteMaterial({map: | ||
+ | return spriteMaterial; | ||
+ | } | ||
+ | |||
+ | |||
+ | // ---------------------- INITIALIZING OBJECTS-------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function init_object(obj) { | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_points(obj); | ||
+ | modelContains.points = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_pointlabels(obj); | ||
+ | modelContains.pointlabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_lines(obj); | ||
+ | modelContains.lines = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_edgelabels(obj); | ||
+ | modelContains.edgelabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_arrowheads(obj); | ||
+ | modelContains.arrowheads = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_faces(obj); | ||
+ | modelContains.faces = true; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function init_points(obj) { | ||
+ | var pointgroup = new THREE.Group(); | ||
+ | pointgroup.name = " | ||
+ | var points = obj.userData.points; | ||
+ | var radii = obj.userData.pointradii; | ||
+ | var materials = obj.userData.pointmaterial; | ||
+ | var geometry, | ||
+ | if (!Array.isArray(radii)) { | ||
+ | geometry = new THREE.SphereBufferGeometry(radii); | ||
+ | } | ||
+ | if (!Array.isArray(materials)) { | ||
+ | material = materials; | ||
+ | } | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | if (Array.isArray(radii)) { | ||
+ | if (radii[i] == 0) { | ||
+ | continue; | ||
+ | } | ||
+ | geometry = new THREE.SphereBufferGeometry(radii[i]); | ||
+ | } | ||
+ | if (Array.isArray(materials)) { | ||
+ | material = materials[i]; | ||
+ | } | ||
+ | var sphere = new THREE.Mesh(geometry, | ||
+ | point.addSphere(sphere); | ||
+ | pointgroup.add(sphere); | ||
+ | } | ||
+ | obj.add(pointgroup); | ||
+ | } | ||
+ | |||
+ | function init_pointlabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var labels = obj.userData.pointlabels; | ||
+ | var pointlabels = new THREE.Group(); | ||
+ | pointlabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(pointlabels); | ||
+ | } | ||
+ | |||
+ | function init_lines(obj) { | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var points = obj.userData.points; | ||
+ | var materials = obj.userData.edgematerial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 ); | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | for (var i=0; i< | ||
+ | geometry.addGroup(2*i, | ||
+ | } | ||
+ | } | ||
+ | var lines = new THREE.LineSegments(geometry, | ||
+ | lines.name = " | ||
+ | obj.add(lines); | ||
+ | updateEdgesPosition(obj); | ||
+ | } | ||
+ | |||
+ | function init_edgelabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var labels = obj.userData.edgelabels; | ||
+ | var edgelabels = new THREE.Group(); | ||
+ | edgelabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(edgelabels); | ||
+ | } | ||
+ | |||
+ | function init_arrowheads(obj) { | ||
+ | var arrowheads = new THREE.Group(); | ||
+ | arrowheads.name = " | ||
+ | var arrowstyle = obj.userData.arrowstyle; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var edgematerials = obj.userData.edgematerial; | ||
+ | var points = obj.userData.points; | ||
+ | var material; | ||
+ | if (!Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials.color} ); | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var start = points[edgeindices[i]]; | ||
+ | var end = points[edgeindices[i+1]]; | ||
+ | var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius(); | ||
+ | if (dist <= 0) { | ||
+ | continue; | ||
+ | } | ||
+ | var dir = new THREE.Vector3().subVectors(end.vector, | ||
+ | dir.normalize(); | ||
+ | var axis = new THREE.Vector3().set(dir.z, | ||
+ | axis.normalize(); | ||
+ | var radians = Math.acos( dir.y ); | ||
+ | var radius = dist/25; | ||
+ | var height = dist/5; | ||
+ | var geometry = new THREE.ConeBufferGeometry(radius, | ||
+ | var position = new THREE.Vector3().addVectors(start.vector, | ||
+ | if (Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} ); | ||
+ | } | ||
+ | var cone = new THREE.Mesh( geometry, material ); | ||
+ | cone.quaternion.setFromAxisAngle(axis, | ||
+ | cone.position.copy(position);; | ||
+ | arrowheads.add(cone); | ||
+ | } | ||
+ | obj.add(arrowheads); | ||
+ | } | ||
+ | |||
+ | function init_faces(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var facets = obj.userData.facets; | ||
+ | obj.userData.triangleindices = []; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | for (var t=0; t< | ||
+ | obj.userData.triangleindices.push(facet[0], | ||
+ | } | ||
+ | } | ||
+ | var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute(bufarr, | ||
+ | | ||
+ | var materials = obj.userData.facetmaterial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var frontmaterials = []; | ||
+ | var backmaterials = []; | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | var tricount = 0; | ||
+ | var facet; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | geometry.addGroup(tricount, | ||
+ | tricount += (facet.length-2)*3; | ||
+ | } | ||
+ | for (var j=0; j< | ||
+ | var fmat = materials[j].clone() | ||
+ | fmat.side = THREE.FrontSide; | ||
+ | frontmaterials.push(fmat); | ||
+ | var bmat = materials[j].clone() | ||
+ | bmat.side = THREE.BackSide; | ||
+ | backmaterials.push(bmat); | ||
+ | obj.userData.facetmaterial = frontmaterials.concat(backmaterials); | ||
+ | } | ||
+ | } else if (materials instanceof THREE.Material) { | ||
+ | frontmaterials = materials.clone() | ||
+ | frontmaterials.side = THREE.FrontSide; | ||
+ | backmaterials = materials.clone() | ||
+ | backmaterials.side = THREE.BackSide; | ||
+ | obj.userData.facetmaterial = [frontmaterials, | ||
+ | } | ||
+ | // duplicating the object with front and back should avoid transparency issues | ||
+ | var backmesh = new THREE.Mesh(geometry, | ||
+ | // meshname is used to show/hide objects | ||
+ | backmesh.name = " | ||
+ | obj.add(backmesh); | ||
+ | var frontmesh = new THREE.Mesh(geometry, | ||
+ | frontmesh.name = " | ||
+ | obj.add(frontmesh); | ||
+ | updateFacesPosition(obj); | ||
+ | } | ||
+ | // // | ||
+ | |||
+ | |||
+ | function updateFacesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.triangleindices; | ||
+ | var faces = obj.getObjectByName(" | ||
+ | var ba = faces.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | faces.geometry.attributes.position.needsUpdate = true; | ||
+ | | ||
+ | } | ||
+ | |||
+ | function updateEdgesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.edgeindices; | ||
+ | var lines = obj.getObjectByName(" | ||
+ | var ba = lines.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | lines.geometry.attributes.position.needsUpdate = true; | ||
+ | } | ||
+ | |||
+ | function onWindowResize() { | ||
+ | renderer.setSize( three.clientWidth, | ||
+ | svgRenderer.setSize( three.clientWidth, | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | function updateCamera() { | ||
+ | var width = three.clientWidth; | ||
+ | var height = three.clientHeight; | ||
+ | var aspect = width / height; | ||
+ | if (camera.type == " | ||
+ | camera.left = frustumSize * aspect / - 2; | ||
+ | camera.right = frustumSize * aspect / 2; | ||
+ | camera.top = frustumSize / 2; | ||
+ | camera.bottom = - frustumSize / 2; | ||
+ | } else if (camera.type == " | ||
+ | camera.aspect = aspect; | ||
+ | } | ||
+ | camera.updateProjectionMatrix(); | ||
+ | } | ||
+ | |||
+ | function changeCamera(event) { | ||
+ | var selindex = event.currentTarget.selectedIndex; | ||
+ | camera = cameras[selindex]; | ||
+ | control = controls[selindex]; | ||
+ | control.enabled = true; | ||
+ | for (var i=0; i< | ||
+ | if (i!=selindex) { | ||
+ | controls[i].enabled = false; | ||
+ | } | ||
+ | } | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | var camtypenode = document.getElementById(' | ||
+ | camtypenode.onchange = changeCamera; | ||
+ | camtypenode.dispatchEvent(new Event(' | ||
+ | |||
+ | onWindowResize(); | ||
+ | window.addEventListener(' | ||
+ | |||
+ | |||
+ | 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.000001; | ||
+ | var XMLS = new XMLSerializer(); | ||
+ | var svgElement; | ||
+ | var renderId; | ||
+ | |||
+ | var render = function () { | ||
+ | |||
+ | renderId = requestAnimationFrame(render); | ||
+ | |||
+ | // comment in for automatic explosion | ||
+ | // | ||
+ | |||
+ | var phi = 0.02 * rotationSpeedFactor; | ||
+ | |||
+ | if (xRotationEnabled) { | ||
+ | scene.rotation.x += phi; | ||
+ | } | ||
+ | if (yRotationEnabled) { | ||
+ | scene.rotation.y += phi; | ||
+ | } | ||
+ | if (zRotationEnabled) { | ||
+ | scene.rotation.z += phi; | ||
+ | } | ||
+ | |||
+ | control.update(); | ||
+ | renderer.render(scene, | ||
+ | }; | ||
+ | |||
+ | if ( THREE.WEBGL.isWebGLAvailable() ) { | ||
+ | render(); | ||
+ | } else { | ||
+ | var warning = WEBGL.getWebGLErrorMessage(); | ||
+ | three.appendChild( warning ); | ||
+ | } | ||
+ | | ||
+ | function changeTransparency() { | ||
+ | var opacity = 1-Number(event.currentTarget.value); | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].opacity = opacity; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.opacity = opacity; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleDepthWrite(event) { | ||
+ | depthwrite = event.currentTarget.checked; | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].depthWrite = depthwrite; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.depthWrite = depthWrite; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | 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, | ||
+ | camera.position.set(0, | ||
+ | camera.up.set(0, | ||
+ | } | ||
+ | |||
+ | function showSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = true; | ||
+ | } | ||
+ | |||
+ | function hideSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = false; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | var pos = 150* Math.PI; | ||
+ | |||
+ | function updateFactor() { | ||
+ | pos++; | ||
+ | return Math.sin(.01*pos)+1; | ||
+ | } | ||
+ | |||
+ | // ------------------------ FOLDING ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | // rotate point p around axis defined by points p1 and p2 by given angle | ||
+ | function rotate(p, p1, p2, angle ){ | ||
+ | angle = -angle; | ||
+ | var x = p.x, y = p.y, z = p.z, | ||
+ | a = p1.x, b = p1.y, c = p1.z, | ||
+ | u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z; | ||
+ | var result = []; | ||
+ | var L = u*u + v*v + w*w; | ||
+ | var sqrt = Math.sqrt; | ||
+ | var cos = Math.cos; | ||
+ | var sin = Math.sin; | ||
+ | |||
+ | result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/ | ||
+ | result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/ | ||
+ | result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/ | ||
+ | |||
+ | return result; | ||
+ | } | ||
+ | |||
+ | var fold = function(event){ | ||
+ | var obj = foldables[Number(event.currentTarget.name)]; | ||
+ | var foldvalue = Number(event.currentTarget.value); | ||
+ | var scale = foldvalue - obj.userData.oldscale; | ||
+ | |||
+ | for (var j=0; j< | ||
+ | rotateVertices(obj, | ||
+ | } | ||
+ | update(obj); | ||
+ | obj.userData.oldscale += scale; | ||
+ | lookAtBarycenter(obj); | ||
+ | } | ||
+ | |||
+ | function lookAtBarycenter(obj){ | ||
+ | control.target = barycenter(obj); | ||
+ | } | ||
+ | |||
+ | function barycenter(obj) { | ||
+ | var center = new THREE.Vector3(0, | ||
+ | var points = obj.userData.points; | ||
+ | for (var i=0; i< | ||
+ | center.add(points[i].vector); | ||
+ | } | ||
+ | center.divideScalar(points.length); | ||
+ | return center; | ||
+ | } | ||
+ | |||
+ | function rotateVertices(obj, | ||
+ | var axes = obj.userData.axes; | ||
+ | var subtrees = obj.userData.subtrees; | ||
+ | var points = obj.userData.points; | ||
+ | var angles = obj.userData.angles; | ||
+ | if (edge < axes.length){ | ||
+ | for (var j=0; j< | ||
+ | var rotP = rotate(points[subtrees[edge][j]].vector, | ||
+ | points[subtrees[edge][j]].set(rotP[0], | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function update(obj) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | if (foldables.length) { | ||
+ | var settings = document.getElementById(' | ||
+ | var foldDiv = document.createElement(' | ||
+ | foldDiv.id = ' | ||
+ | var title = document.createElement(' | ||
+ | title.innerHTML = ' | ||
+ | foldDiv.appendChild(title); | ||
+ | foldDiv.className = ' | ||
+ | for (var i=0; i< | ||
+ | var range = document.createElement(' | ||
+ | range.type = ' | ||
+ | range.min = 0; | ||
+ | range.max = 1; | ||
+ | range.value = 0; | ||
+ | range.step = 0.001; | ||
+ | range.name = String(i); | ||
+ | range.oninput = fold; | ||
+ | foldDiv.appendChild(range); | ||
+ | } | ||
+ | lookAtBarycenter(foldables[0]); | ||
+ | settings.insertBefore(foldDiv, | ||
+ | } | ||
+ | |||
+ | | ||
+ | // ---------------------- EXPLOSION ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | if (explodableModel) { | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | if ( obj.userData.explodable ) { | ||
+ | computeCentroid(obj); | ||
+ | } | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | explode(0.000001); | ||
+ | } | ||
+ | |||
+ | function computeCentroid(obj) { | ||
+ | centroid = new THREE.Vector3(); | ||
+ | obj.userData.points.forEach(function(pmpoint) { | ||
+ | centroid.add(pmpoint.vector); | ||
+ | }); | ||
+ | centroid.divideScalar(obj.userData.points.length); | ||
+ | obj.userData.centroid = centroid; | ||
+ | } | ||
+ | |||
+ | function explode(factor) { | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i]; | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | var c = obj.userData.centroid; | ||
+ | obj.position.set(c.x*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, | ||
+ | } | ||
+ | |||
+ | |||
+ | function explodingInterval(){ | ||
+ | explodeScale += explodingSpeed; | ||
+ | if (explodeScale <= 6){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else{ | ||
+ | explode(6); | ||
+ | explodeScale = 6; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startUnexploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | |||
+ | function startUnexploding(){ | ||
+ | intervals.push(setInterval(unexplodingInterval, | ||
+ | } | ||
+ | |||
+ | function unexplodingInterval(){ | ||
+ | explodeScale -= explodingSpeed; | ||
+ | if (explodeScale >= 0){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else { | ||
+ | explode(0); | ||
+ | explodeScale = 0; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startExploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | function clearIntervals(){ | ||
+ | intervals.forEach(function(interval){ | ||
+ | clearInterval(interval); | ||
+ | }); | ||
+ | intervals = []; | ||
+ | timeouts.forEach(function(timeout){ | ||
+ | clearTimeout(timeout); | ||
+ | }); | ||
+ | timeouts = []; | ||
+ | } | ||
+ | |||
+ | // ---------------------- DISPLAY -------------------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | const objectTypeInnerHTMLs = { points: " | ||
+ | const objectTypeVisible = {}; | ||
+ | Object.assign(objectTypeVisible, | ||
+ | const sortedObjectTypeKeys = Object.keys(objectTypeInnerHTMLs).sort(); | ||
+ | const shownObjectTypesList = document.getElementById(' | ||
+ | |||
+ | function setVisibility(bool, | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i].getObjectByName(objname); | ||
+ | if (obj) { | ||
+ | obj.visible = bool; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleObjectTypeVisibility(event){ | ||
+ | var name = event.currentTarget.name; | ||
+ | var checked = event.currentTarget.checked; | ||
+ | objectTypeVisible[name] = checked; | ||
+ | if (name == " | ||
+ | setVisibility(checked," | ||
+ | setVisibility(checked," | ||
+ | } else { | ||
+ | setVisibility(checked, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var key = sortedObjectTypeKeys[i]; | ||
+ | if (modelContains[key]) { | ||
+ | var objTypeNode = document.createElement(' | ||
+ | objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = key; | ||
+ | checkbox.onchange = toggleObjectTypeVisibility; | ||
+ | shownObjectTypesList.appendChild(checkbox); | ||
+ | shownObjectTypesList.appendChild(objTypeNode); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // ------------------------------------------------------ | ||
+ | |||
+ | function toggleObjectVisibility(event){ | ||
+ | var nr = Number(event.currentTarget.name); | ||
+ | scene.children[nr].visible = event.currentTarget.checked; | ||
+ | } | ||
+ | |||
+ | // append checkboxes for displaying or hiding objects | ||
+ | var shownObjectsList = document.getElementById(' | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | var objNode = document.createElement(' | ||
+ | objNode.innerHTML = obj.name + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = String(i); | ||
+ | checkbox.onchange = toggleObjectVisibility; | ||
+ | shownObjectsList.appendChild(checkbox); | ||
+ | shownObjectsList.appendChild(objNode); | ||
+ | } | ||
+ | |||
+ | // ---------------------- SVG ------------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function takeSvgScreenshot() { | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | svgRenderer.render(scene, | ||
+ | svgElement = XMLS.serializeToString(svgRenderer.domElement); | ||
+ | | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | |||
+ | if (document.getElementById(' | ||
+ | //show in new tab | ||
+ | var myWindow = window.open("","" | ||
+ | myWindow.document.body.innerHTML = svgElement; | ||
+ | } else{ | ||
+ | // download svg file | ||
+ | download(" | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function download(filename, | ||
+ | var element = document.createElement(' | ||
+ | element.setAttribute(' | ||
+ | element.setAttribute(' | ||
+ | |||
+ | element.style.display = ' | ||
+ | document.body.appendChild(element); | ||
+ | |||
+ | element.click(); | ||
+ | |||
+ | document.body.removeChild(element); | ||
+ | } | ||
+ | |||
+ | |||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | |||
+ | |||
+ | // ------------------ SHORTCUTS -------------------------------------------- | ||
+ | // ------------------------------------------------------------------------- | ||
+ | |||
+ | /** | ||
+ | * http:// | ||
+ | * Version : 2.01.B | ||
+ | * By Binny V A | ||
+ | * License : BSD | ||
+ | */ | ||
+ | shortcut = { | ||
+ | ' | ||
+ | ' | ||
+ | //Provide a set of default options | ||
+ | var default_options = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | if(!opt) opt = default_options; | ||
+ | else { | ||
+ | for(var dfo in default_options) { | ||
+ | if(typeof opt[dfo] == ' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | var ele = opt.target; | ||
+ | if(typeof 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[' | ||
+ | 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 == ' | ||
+ | } | ||
+ | |||
+ | //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(code == 190) character=" | ||
+ | |||
+ | 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 = { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | ";":":", | ||
+ | "'":" | ||
+ | ",":"<", | ||
+ | " | ||
+ | "/":"?", | ||
+ | " | ||
+ | } | ||
+ | // | ||
+ | var special_keys = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | |||
+ | var modifiers = { | ||
+ | shift: { wanted: | ||
+ | ctrl : { wanted: | ||
+ | alt | ||
+ | meta : { wanted: | ||
+ | }; | ||
+ | | ||
+ | if(e.ctrlKey) modifiers.ctrl.pressed = true; | ||
+ | if(e.shiftKey) modifiers.shift.pressed = true; | ||
+ | if(e.altKey) modifiers.alt.pressed = true; | ||
+ | if(e.metaKey) | ||
+ | | ||
+ | for(var i=0; k=keys[i], | ||
+ | // | ||
+ | if(k == ' | ||
+ | kp++; | ||
+ | modifiers.ctrl.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.shift.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.alt.wanted = true; | ||
+ | } else if(k == ' | ||
+ | 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[' | ||
+ | if(opt[' | ||
+ | |||
+ | } 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[' | ||
+ | // | ||
+ | e.cancelBubble = true; | ||
+ | e.returnValue = false; | ||
+ | |||
+ | // | ||
+ | if (e.stopPropagation) { | ||
+ | e.stopPropagation(); | ||
+ | e.preventDefault(); | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | this.all_shortcuts[shortcut_combination] = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | }; | ||
+ | //Attach the function with the event | ||
+ | if(ele.addEventListener) ele.addEventListener(opt[' | ||
+ | else if(ele.attachEvent) ele.attachEvent(' | ||
+ | else ele[' | ||
+ | }, | ||
+ | |||
+ | //Remove the shortcut - just specify the shortcut and I will remove the binding | ||
+ | ' | ||
+ | shortcut_combination = shortcut_combination.toLowerCase(); | ||
+ | var binding = this.all_shortcuts[shortcut_combination]; | ||
+ | delete(this.all_shortcuts[shortcut_combination]) | ||
+ | if(!binding) return; | ||
+ | var type = binding[' | ||
+ | var ele = binding[' | ||
+ | var callback = binding[' | ||
+ | |||
+ | if(ele.detachEvent) ele.detachEvent(' | ||
+ | else if(ele.removeEventListener) ele.removeEventListener(type, | ||
+ | else ele[' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | shortcut.add(" | ||
+ | var event = new Event(' | ||
+ | if (settingsShown){ | ||
+ | document.getElementById(' | ||
+ | } else { | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | });}); | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | As one can see, this subdivision should be regular, since we can easily find a weight vector which induces this subdivision. Just lift all the points in the inner square to 0 and the points on the outer square to 1. But now we want to take a look at all vectors which induce this subdivision. This can be achieved by using the method '' | ||
+ | |||
+ | <code perl> | ||
+ | > $sc = $S-> | ||
+ | > print $sc-> | ||
+ | 4 | ||
+ | > print $sc-> | ||
+ | 1 1 1 1 0 0 0 0 | ||
+ | > print $sc-> | ||
+ | 3/2 3/2 -1/2 -1/2 1 1 0 0 | ||
+ | -13/14 15/14 23/14 -5/14 -2/7 5/7 1 0 | ||
+ | 5/9 -1/3 5/9 13/9 5/9 1/9 5/9 1 | ||
+ | </ | ||
+ | We see that this cone is 4-dimensional with a 3-dimensional lineality space. Every vector of the **interior** of that cone induces weights that produces the same regular subdivision. The vectors on the boundary give rise to a coarsening. As you see by looking at the coordinates, | ||
+ | |||
+ | With the options '' | ||
+ | |||
+ | <code perl> | ||
+ | > $sc_fixed = $S-> | ||
+ | > print $sc_fixed-> | ||
+ | 1 | ||
+ | > print $sc_fixed-> | ||
+ | 1 1 1 1 0 0 0 0 | ||
+ | > print $sc_fixed-> | ||
+ | </ | ||
+ | Now you see that the lineality space of that cone is gone. The only way to lift our points now is by raising all points on the outer square to the same height which should be greater than 0. | ||
+ | |||
+ | ==== Regularity of Subdivisions ==== | ||
+ | |||
+ | You might run into the situation where you want to check whether a subdivision is regular or not. Don't worry, polymake comes to rescue along with it's side-kick the '' | ||
+ | |||
+ | <code perl> | ||
+ | > print is_regular($points, | ||
+ | 1 <0 0 1 1 0 0 1/2 1/2> | ||
+ | > $lambda = new Vector(" | ||
+ | > print regular_subdivision($points, | ||
+ | {4 5 6 7} | ||
+ | {2 3 6 7} | ||
+ | {1 2 5 6} | ||
+ | {0 3 4 7} | ||
+ | {0 1 4 5} | ||
+ | </ | ||
+ | As you can see polymake tells us that our subdivision is indeed regular. And the vector '' | ||
+ | |||
+ | <code perl> | ||
+ | > $nreg_cells = new Array< | ||
+ | > $nreg_pc = new fan:: | ||
+ | > $nreg_pc-> | ||
+ | </ | ||
+ | < | ||
+ | <!-- | ||
+ | polymake for knusper | ||
+ | Thu Mar 3 00:43:53 2022 | ||
+ | pcom: | ||
+ | --> | ||
+ | |||
+ | |||
+ | < | ||
+ | < | ||
+ | <meta charset=utf-8> | ||
+ | < | ||
+ | < | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | */ | ||
+ | html {overflow: scroll;} | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | # | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | } | ||
+ | /* | ||
+ | // COMMON_CODE_BLOCK_END | ||
+ | */ | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | <div id=' | ||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | < | ||
+ | <div class=indented>< | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <div class=suboption> | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | <div class=suboption> | ||
+ | <div class=indented> | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | <select id=" | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <div class=group id=' | ||
+ | < | ||
+ | <div class=indented> | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | <img id=' | ||
+ | <img id=' | ||
+ | <div id=" | ||
+ | </ | ||
+ | < | ||
+ | requirejs.config({ | ||
+ | paths: { | ||
+ | three: '/ | ||
+ | TrackballControls: | ||
+ | OrbitControls: | ||
+ | Projector: '/ | ||
+ | SVGRenderer: | ||
+ | WEBGL: '/ | ||
+ | }, | ||
+ | shim: { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | }); | ||
+ | | ||
+ | require([' | ||
+ | window.THREE = THREE; | ||
+ | require([' | ||
+ | | ||
+ | THREE.TrackballControls = TrackballControls; | ||
+ | THREE.OrbitControls = OrbitControls; | ||
+ | THREE.Projector = Projector; | ||
+ | THREE.SVGRenderer = SVGRenderer; | ||
+ | THREE.WEBGL = WEBGL; | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | |||
+ | const intervalLength = 25; // for automatic animations | ||
+ | const explodableModel = true; | ||
+ | const modelContains = { points: false, pointlabels: | ||
+ | const foldables = []; | ||
+ | |||
+ | var three = document.getElementById(" | ||
+ | var scene = new THREE.Scene(); | ||
+ | var renderer = new THREE.WebGLRenderer( { antialias: true } ); | ||
+ | var svgRenderer = new THREE.SVGRenderer( { antialias: true } ); | ||
+ | renderer.setPixelRatio( window.devicePixelRatio ); | ||
+ | renderer.setClearColor(0xFFFFFF, | ||
+ | svgRenderer.setClearColor(0xFFFFFF, | ||
+ | three.appendChild(renderer.domElement); | ||
+ | |||
+ | var frustumSize = 4; | ||
+ | var cameras = [new THREE.PerspectiveCamera(75, | ||
+ | cameras.forEach(function(cam) { | ||
+ | cam.position.set(0, | ||
+ | cam.lookAt(0, | ||
+ | cam.up.set(0, | ||
+ | }); | ||
+ | var controls = [new THREE.TrackballControls(cameras[0], | ||
+ | var camera, control; | ||
+ | |||
+ | controls[0].zoomSpeed = 0.2; | ||
+ | controls[0].rotateSpeed = 4; | ||
+ | |||
+ | |||
+ | // class to allow move points together with labels and spheres | ||
+ | var PMPoint = function (x,y,z) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addLabel = function(labelsprite) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.addSphere = function(spheremesh) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | PMPoint.prototype.set = function(x, | ||
+ | | ||
+ | if (this.sprite) { | ||
+ | this.sprite.position.copy(this.vector); | ||
+ | } | ||
+ | if (this.sphere) { | ||
+ | this.sphere.position.copy(this.vector); | ||
+ | } | ||
+ | } | ||
+ | PMPoint.prototype.radius = function() { | ||
+ | if (this.sphere) { | ||
+ | return this.sphere.geometry.parameters.radius; | ||
+ | } else { | ||
+ | return 0; | ||
+ | } | ||
+ | }; | ||
+ | // select the target node | ||
+ | var target = document.querySelector('# | ||
+ | |||
+ | // create an observer instance | ||
+ | var observer = new MutationObserver(function(mutations) { | ||
+ | | ||
+ | if (mutation.removedNodes && mutation.removedNodes.length > 0) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | }); | ||
+ | }); | ||
+ | |||
+ | // configuration of the observer: | ||
+ | var config = { childList: true, characterData: | ||
+ | |||
+ | // pass in the target node, as well as the observer options | ||
+ | while (target) { | ||
+ | if (target.className==" | ||
+ | observer.observe(target, | ||
+ | break; | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | var obj0 = new THREE.Object3D(); | ||
+ | obj0.name = " | ||
+ | obj0.userData.explodable = 1; | ||
+ | obj0.userData.points = []; | ||
+ | obj0.userData.points.push(new PMPoint(2, 0, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj0.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | |||
+ | obj0.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj0.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj0.userData.pointlabels = [" | ||
+ | obj0.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj0.userData.facets = [[1, 2, 0]]; | ||
+ | < | ||
+ | obj0.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj0); | ||
+ | scene.add(obj0); | ||
+ | |||
+ | var obj1 = new THREE.Object3D(); | ||
+ | obj1.name = " | ||
+ | obj1.userData.explodable = 1; | ||
+ | obj1.userData.points = []; | ||
+ | obj1.userData.points.push(new PMPoint(2, 0, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | obj1.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | |||
+ | obj1.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj1.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj1.userData.pointlabels = [" | ||
+ | obj1.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj1.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj1.userData.facets = [[0, 1, 2]]; | ||
+ | < | ||
+ | obj1.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj1); | ||
+ | scene.add(obj1); | ||
+ | |||
+ | var obj2 = new THREE.Object3D(); | ||
+ | obj2.name = " | ||
+ | obj2.userData.explodable = 1; | ||
+ | obj2.userData.points = []; | ||
+ | obj2.userData.points.push(new PMPoint(2, 0, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | obj2.userData.points.push(new PMPoint(0, -2, 0)); | ||
+ | |||
+ | obj2.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj2.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj2.userData.pointlabels = [" | ||
+ | obj2.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj2.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj2.userData.facets = [[1, 2, 0]]; | ||
+ | < | ||
+ | obj2.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj2); | ||
+ | scene.add(obj2); | ||
+ | |||
+ | var obj3 = new THREE.Object3D(); | ||
+ | obj3.name = " | ||
+ | obj3.userData.explodable = 1; | ||
+ | obj3.userData.points = []; | ||
+ | obj3.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | obj3.userData.points.push(new PMPoint(0, -2, 0)); | ||
+ | obj3.userData.points.push(new PMPoint(0, -1, 0)); | ||
+ | |||
+ | obj3.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj3.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj3.userData.pointlabels = [" | ||
+ | obj3.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj3.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj3.userData.facets = [[2, 1, 0]]; | ||
+ | < | ||
+ | obj3.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj3); | ||
+ | scene.add(obj3); | ||
+ | |||
+ | var obj4 = new THREE.Object3D(); | ||
+ | obj4.name = " | ||
+ | obj4.userData.explodable = 1; | ||
+ | obj4.userData.points = []; | ||
+ | obj4.userData.points.push(new PMPoint(0, -2, 0)); | ||
+ | obj4.userData.points.push(new PMPoint(0, -1, 0)); | ||
+ | obj4.userData.points.push(new PMPoint(-2, 0, 0)); | ||
+ | |||
+ | obj4.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj4.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj4.userData.pointlabels = [" | ||
+ | obj4.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj4.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj4.userData.facets = [[1, 2, 0]]; | ||
+ | < | ||
+ | obj4.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj4); | ||
+ | scene.add(obj4); | ||
+ | |||
+ | var obj5 = new THREE.Object3D(); | ||
+ | obj5.name = " | ||
+ | obj5.userData.explodable = 1; | ||
+ | obj5.userData.points = []; | ||
+ | obj5.userData.points.push(new PMPoint(0, -1, 0)); | ||
+ | obj5.userData.points.push(new PMPoint(-2, 0, 0)); | ||
+ | obj5.userData.points.push(new PMPoint(-1, 0, 0)); | ||
+ | |||
+ | obj5.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj5.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj5.userData.pointlabels = [" | ||
+ | obj5.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj5.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj5.userData.facets = [[2, 1, 0]]; | ||
+ | < | ||
+ | obj5.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj5); | ||
+ | scene.add(obj5); | ||
+ | |||
+ | var obj6 = new THREE.Object3D(); | ||
+ | obj6.name = " | ||
+ | obj6.userData.explodable = 1; | ||
+ | obj6.userData.points = []; | ||
+ | obj6.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj6.userData.points.push(new PMPoint(-2, 0, 0)); | ||
+ | obj6.userData.points.push(new PMPoint(-1, 0, 0)); | ||
+ | |||
+ | obj6.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj6.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj6.userData.pointlabels = [" | ||
+ | obj6.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj6.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj6.userData.facets = [[0, 1, 2]]; | ||
+ | < | ||
+ | obj6.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj6); | ||
+ | scene.add(obj6); | ||
+ | |||
+ | var obj7 = new THREE.Object3D(); | ||
+ | obj7.name = " | ||
+ | obj7.userData.explodable = 1; | ||
+ | obj7.userData.points = []; | ||
+ | obj7.userData.points.push(new PMPoint(0, 2, 0)); | ||
+ | obj7.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | obj7.userData.points.push(new PMPoint(-1, 0, 0)); | ||
+ | |||
+ | obj7.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj7.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj7.userData.pointlabels = [" | ||
+ | obj7.userData.edgeindices = [0, 1, 0, 2, 1, 2]; | ||
+ | < | ||
+ | obj7.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj7.userData.facets = [[0, 2, 1]]; | ||
+ | < | ||
+ | obj7.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj7); | ||
+ | scene.add(obj7); | ||
+ | |||
+ | var obj8 = new THREE.Object3D(); | ||
+ | obj8.name = " | ||
+ | obj8.userData.explodable = 1; | ||
+ | obj8.userData.points = []; | ||
+ | obj8.userData.points.push(new PMPoint(0, 1, 0)); | ||
+ | obj8.userData.points.push(new PMPoint(1, 0, 0)); | ||
+ | obj8.userData.points.push(new PMPoint(0, -1, 0)); | ||
+ | obj8.userData.points.push(new PMPoint(-1, 0, 0)); | ||
+ | |||
+ | obj8.userData.pointradii = 0.02; | ||
+ | < | ||
+ | obj8.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, | ||
+ | obj8.userData.pointlabels = [" | ||
+ | obj8.userData.edgeindices = [0, 1, 1, 2, 0, 3, 2, 3]; | ||
+ | < | ||
+ | obj8.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1.5, transparent: | ||
+ | obj8.userData.facets = [[2, 1, 0, 3]]; | ||
+ | < | ||
+ | obj8.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, | ||
+ | init_object(obj8); | ||
+ | scene.add(obj8); | ||
+ | |||
+ | // COMMON_CODE_BLOCK_BEGIN | ||
+ | function textSpriteMaterial(message, | ||
+ | if ( parameters === undefined ) parameters = {}; | ||
+ | var fontface = " | ||
+ | var fontsize = parameters.hasOwnProperty(" | ||
+ | fontsize = fontsize*10; | ||
+ | var lines = message.split(' | ||
+ | var size = 512; | ||
+ | for(var i = 0; i< | ||
+ | var tmp = lines[i].length; | ||
+ | while(tmp*fontsize > size){ | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | var canvas = document.createElement(' | ||
+ | canvas.width = size; | ||
+ | canvas.height = size; | ||
+ | var context = canvas.getContext(' | ||
+ | context.fillStyle = " | ||
+ | context.fill(); | ||
+ | context.font = fontsize + "px " + fontface; | ||
+ | | ||
+ | // text color | ||
+ | context.fillStyle = " | ||
+ | | ||
+ | context.fillText(lines[i], | ||
+ | } | ||
+ | | ||
+ | // canvas contents will be used for a texture | ||
+ | var texture = new THREE.Texture(canvas); | ||
+ | texture.needsUpdate = true; | ||
+ | | ||
+ | var spriteMaterial = new THREE.SpriteMaterial({map: | ||
+ | return spriteMaterial; | ||
+ | } | ||
+ | |||
+ | |||
+ | // ---------------------- INITIALIZING OBJECTS-------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function init_object(obj) { | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_points(obj); | ||
+ | modelContains.points = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_pointlabels(obj); | ||
+ | modelContains.pointlabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_lines(obj); | ||
+ | modelContains.lines = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_edgelabels(obj); | ||
+ | modelContains.edgelabels = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_arrowheads(obj); | ||
+ | modelContains.arrowheads = true; | ||
+ | } | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | init_faces(obj); | ||
+ | modelContains.faces = true; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function init_points(obj) { | ||
+ | var pointgroup = new THREE.Group(); | ||
+ | pointgroup.name = " | ||
+ | var points = obj.userData.points; | ||
+ | var radii = obj.userData.pointradii; | ||
+ | var materials = obj.userData.pointmaterial; | ||
+ | var geometry, | ||
+ | if (!Array.isArray(radii)) { | ||
+ | geometry = new THREE.SphereBufferGeometry(radii); | ||
+ | } | ||
+ | if (!Array.isArray(materials)) { | ||
+ | material = materials; | ||
+ | } | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | if (Array.isArray(radii)) { | ||
+ | if (radii[i] == 0) { | ||
+ | continue; | ||
+ | } | ||
+ | geometry = new THREE.SphereBufferGeometry(radii[i]); | ||
+ | } | ||
+ | if (Array.isArray(materials)) { | ||
+ | material = materials[i]; | ||
+ | } | ||
+ | var sphere = new THREE.Mesh(geometry, | ||
+ | point.addSphere(sphere); | ||
+ | pointgroup.add(sphere); | ||
+ | } | ||
+ | obj.add(pointgroup); | ||
+ | } | ||
+ | |||
+ | function init_pointlabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var labels = obj.userData.pointlabels; | ||
+ | var pointlabels = new THREE.Group(); | ||
+ | pointlabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var point = points[i]; | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | point.addLabel(sprite); | ||
+ | pointlabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(pointlabels); | ||
+ | } | ||
+ | |||
+ | function init_lines(obj) { | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var points = obj.userData.points; | ||
+ | var materials = obj.userData.edgematerial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 ); | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | for (var i=0; i< | ||
+ | geometry.addGroup(2*i, | ||
+ | } | ||
+ | } | ||
+ | var lines = new THREE.LineSegments(geometry, | ||
+ | lines.name = " | ||
+ | obj.add(lines); | ||
+ | updateEdgesPosition(obj); | ||
+ | } | ||
+ | |||
+ | function init_edgelabels(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var labels = obj.userData.edgelabels; | ||
+ | var edgelabels = new THREE.Group(); | ||
+ | edgelabels.name = " | ||
+ | if (Array.isArray(labels)) { | ||
+ | for (var i=0; i< | ||
+ | var spriteMaterial = textSpriteMaterial( labels[i] ); | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } else { | ||
+ | var spriteMaterial = textSpriteMaterial( labels ); | ||
+ | for (var i=0; i< | ||
+ | var sprite = new THREE.Sprite(spriteMaterial); | ||
+ | sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[2*i]].vector, | ||
+ | edgelabels.add(sprite); | ||
+ | } | ||
+ | } | ||
+ | obj.add(edgelabels); | ||
+ | } | ||
+ | |||
+ | function init_arrowheads(obj) { | ||
+ | var arrowheads = new THREE.Group(); | ||
+ | arrowheads.name = " | ||
+ | var arrowstyle = obj.userData.arrowstyle; | ||
+ | var edgeindices = obj.userData.edgeindices; | ||
+ | var edgematerials = obj.userData.edgematerial; | ||
+ | var points = obj.userData.points; | ||
+ | var material; | ||
+ | if (!Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials.color} ); | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var start = points[edgeindices[i]]; | ||
+ | var end = points[edgeindices[i+1]]; | ||
+ | var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius(); | ||
+ | if (dist <= 0) { | ||
+ | continue; | ||
+ | } | ||
+ | var dir = new THREE.Vector3().subVectors(end.vector, | ||
+ | dir.normalize(); | ||
+ | var axis = new THREE.Vector3().set(dir.z, | ||
+ | axis.normalize(); | ||
+ | var radians = Math.acos( dir.y ); | ||
+ | var radius = dist/25; | ||
+ | var height = dist/5; | ||
+ | var geometry = new THREE.ConeBufferGeometry(radius, | ||
+ | var position = new THREE.Vector3().addVectors(start.vector, | ||
+ | if (Array.isArray(edgematerials)) { | ||
+ | material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} ); | ||
+ | } | ||
+ | var cone = new THREE.Mesh( geometry, material ); | ||
+ | cone.quaternion.setFromAxisAngle(axis, | ||
+ | cone.position.copy(position);; | ||
+ | arrowheads.add(cone); | ||
+ | } | ||
+ | obj.add(arrowheads); | ||
+ | } | ||
+ | |||
+ | function init_faces(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var facets = obj.userData.facets; | ||
+ | obj.userData.triangleindices = []; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | for (var t=0; t< | ||
+ | obj.userData.triangleindices.push(facet[0], | ||
+ | } | ||
+ | } | ||
+ | var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 ); | ||
+ | var bufattr = new THREE.Float32BufferAttribute(bufarr, | ||
+ | | ||
+ | var materials = obj.userData.facetmaterial; | ||
+ | var geometry = new THREE.BufferGeometry(); | ||
+ | var frontmaterials = []; | ||
+ | var backmaterials = []; | ||
+ | geometry.setAttribute(' | ||
+ | if (Array.isArray(materials)) { | ||
+ | var tricount = 0; | ||
+ | var facet; | ||
+ | for (var i=0; i< | ||
+ | facet = facets[i]; | ||
+ | geometry.addGroup(tricount, | ||
+ | tricount += (facet.length-2)*3; | ||
+ | } | ||
+ | for (var j=0; j< | ||
+ | var fmat = materials[j].clone() | ||
+ | fmat.side = THREE.FrontSide; | ||
+ | frontmaterials.push(fmat); | ||
+ | var bmat = materials[j].clone() | ||
+ | bmat.side = THREE.BackSide; | ||
+ | backmaterials.push(bmat); | ||
+ | obj.userData.facetmaterial = frontmaterials.concat(backmaterials); | ||
+ | } | ||
+ | } else if (materials instanceof THREE.Material) { | ||
+ | frontmaterials = materials.clone() | ||
+ | frontmaterials.side = THREE.FrontSide; | ||
+ | backmaterials = materials.clone() | ||
+ | backmaterials.side = THREE.BackSide; | ||
+ | obj.userData.facetmaterial = [frontmaterials, | ||
+ | } | ||
+ | // duplicating the object with front and back should avoid transparency issues | ||
+ | var backmesh = new THREE.Mesh(geometry, | ||
+ | // meshname is used to show/hide objects | ||
+ | backmesh.name = " | ||
+ | obj.add(backmesh); | ||
+ | var frontmesh = new THREE.Mesh(geometry, | ||
+ | frontmesh.name = " | ||
+ | obj.add(frontmesh); | ||
+ | updateFacesPosition(obj); | ||
+ | } | ||
+ | // // | ||
+ | |||
+ | |||
+ | function updateFacesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.triangleindices; | ||
+ | var faces = obj.getObjectByName(" | ||
+ | var ba = faces.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | faces.geometry.attributes.position.needsUpdate = true; | ||
+ | | ||
+ | } | ||
+ | |||
+ | function updateEdgesPosition(obj) { | ||
+ | var points = obj.userData.points; | ||
+ | var indices = obj.userData.edgeindices; | ||
+ | var lines = obj.getObjectByName(" | ||
+ | var ba = lines.geometry.getAttribute(" | ||
+ | for (var i=0; i< | ||
+ | ba.setXYZ(i, | ||
+ | } | ||
+ | lines.geometry.attributes.position.needsUpdate = true; | ||
+ | } | ||
+ | |||
+ | function onWindowResize() { | ||
+ | renderer.setSize( three.clientWidth, | ||
+ | svgRenderer.setSize( three.clientWidth, | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | function updateCamera() { | ||
+ | var width = three.clientWidth; | ||
+ | var height = three.clientHeight; | ||
+ | var aspect = width / height; | ||
+ | if (camera.type == " | ||
+ | camera.left = frustumSize * aspect / - 2; | ||
+ | camera.right = frustumSize * aspect / 2; | ||
+ | camera.top = frustumSize / 2; | ||
+ | camera.bottom = - frustumSize / 2; | ||
+ | } else if (camera.type == " | ||
+ | camera.aspect = aspect; | ||
+ | } | ||
+ | camera.updateProjectionMatrix(); | ||
+ | } | ||
+ | |||
+ | function changeCamera(event) { | ||
+ | var selindex = event.currentTarget.selectedIndex; | ||
+ | camera = cameras[selindex]; | ||
+ | control = controls[selindex]; | ||
+ | control.enabled = true; | ||
+ | for (var i=0; i< | ||
+ | if (i!=selindex) { | ||
+ | controls[i].enabled = false; | ||
+ | } | ||
+ | } | ||
+ | updateCamera(); | ||
+ | } | ||
+ | |||
+ | var camtypenode = document.getElementById(' | ||
+ | camtypenode.onchange = changeCamera; | ||
+ | camtypenode.dispatchEvent(new Event(' | ||
+ | |||
+ | onWindowResize(); | ||
+ | window.addEventListener(' | ||
+ | |||
+ | |||
+ | 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.000001; | ||
+ | var XMLS = new XMLSerializer(); | ||
+ | var svgElement; | ||
+ | var renderId; | ||
+ | |||
+ | var render = function () { | ||
+ | |||
+ | renderId = requestAnimationFrame(render); | ||
+ | |||
+ | // comment in for automatic explosion | ||
+ | // | ||
+ | |||
+ | var phi = 0.02 * rotationSpeedFactor; | ||
+ | |||
+ | if (xRotationEnabled) { | ||
+ | scene.rotation.x += phi; | ||
+ | } | ||
+ | if (yRotationEnabled) { | ||
+ | scene.rotation.y += phi; | ||
+ | } | ||
+ | if (zRotationEnabled) { | ||
+ | scene.rotation.z += phi; | ||
+ | } | ||
+ | |||
+ | control.update(); | ||
+ | renderer.render(scene, | ||
+ | }; | ||
+ | |||
+ | if ( THREE.WEBGL.isWebGLAvailable() ) { | ||
+ | render(); | ||
+ | } else { | ||
+ | var warning = WEBGL.getWebGLErrorMessage(); | ||
+ | three.appendChild( warning ); | ||
+ | } | ||
+ | | ||
+ | function changeTransparency() { | ||
+ | var opacity = 1-Number(event.currentTarget.value); | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].opacity = opacity; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.opacity = opacity; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleDepthWrite(event) { | ||
+ | depthwrite = event.currentTarget.checked; | ||
+ | for (var i=0; i< | ||
+ | child = scene.children[i]; | ||
+ | if ( child.userData.hasOwnProperty(" | ||
+ | if (Array.isArray(child.userData.facetmaterial)) { | ||
+ | for (var j=0; j< | ||
+ | child.userData.facetmaterial[j].depthWrite = depthwrite; | ||
+ | } | ||
+ | } else { | ||
+ | child.userData.facetmaterial.depthWrite = depthWrite; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | 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, | ||
+ | camera.position.set(0, | ||
+ | camera.up.set(0, | ||
+ | } | ||
+ | |||
+ | function showSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = true; | ||
+ | } | ||
+ | |||
+ | function hideSettings(event){ | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | settingsShown = false; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | var pos = 150* Math.PI; | ||
+ | |||
+ | function updateFactor() { | ||
+ | pos++; | ||
+ | return Math.sin(.01*pos)+1; | ||
+ | } | ||
+ | |||
+ | // ------------------------ FOLDING ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | // rotate point p around axis defined by points p1 and p2 by given angle | ||
+ | function rotate(p, p1, p2, angle ){ | ||
+ | angle = -angle; | ||
+ | var x = p.x, y = p.y, z = p.z, | ||
+ | a = p1.x, b = p1.y, c = p1.z, | ||
+ | u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z; | ||
+ | var result = []; | ||
+ | var L = u*u + v*v + w*w; | ||
+ | var sqrt = Math.sqrt; | ||
+ | var cos = Math.cos; | ||
+ | var sin = Math.sin; | ||
+ | |||
+ | result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/ | ||
+ | result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/ | ||
+ | result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/ | ||
+ | |||
+ | return result; | ||
+ | } | ||
+ | |||
+ | var fold = function(event){ | ||
+ | var obj = foldables[Number(event.currentTarget.name)]; | ||
+ | var foldvalue = Number(event.currentTarget.value); | ||
+ | var scale = foldvalue - obj.userData.oldscale; | ||
+ | |||
+ | for (var j=0; j< | ||
+ | rotateVertices(obj, | ||
+ | } | ||
+ | update(obj); | ||
+ | obj.userData.oldscale += scale; | ||
+ | lookAtBarycenter(obj); | ||
+ | } | ||
+ | |||
+ | function lookAtBarycenter(obj){ | ||
+ | control.target = barycenter(obj); | ||
+ | } | ||
+ | |||
+ | function barycenter(obj) { | ||
+ | var center = new THREE.Vector3(0, | ||
+ | var points = obj.userData.points; | ||
+ | for (var i=0; i< | ||
+ | center.add(points[i].vector); | ||
+ | } | ||
+ | center.divideScalar(points.length); | ||
+ | return center; | ||
+ | } | ||
+ | |||
+ | function rotateVertices(obj, | ||
+ | var axes = obj.userData.axes; | ||
+ | var subtrees = obj.userData.subtrees; | ||
+ | var points = obj.userData.points; | ||
+ | var angles = obj.userData.angles; | ||
+ | if (edge < axes.length){ | ||
+ | for (var j=0; j< | ||
+ | var rotP = rotate(points[subtrees[edge][j]].vector, | ||
+ | points[subtrees[edge][j]].set(rotP[0], | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function update(obj) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | if (foldables.length) { | ||
+ | var settings = document.getElementById(' | ||
+ | var foldDiv = document.createElement(' | ||
+ | foldDiv.id = ' | ||
+ | var title = document.createElement(' | ||
+ | title.innerHTML = ' | ||
+ | foldDiv.appendChild(title); | ||
+ | foldDiv.className = ' | ||
+ | for (var i=0; i< | ||
+ | var range = document.createElement(' | ||
+ | range.type = ' | ||
+ | range.min = 0; | ||
+ | range.max = 1; | ||
+ | range.value = 0; | ||
+ | range.step = 0.001; | ||
+ | range.name = String(i); | ||
+ | range.oninput = fold; | ||
+ | foldDiv.appendChild(range); | ||
+ | } | ||
+ | lookAtBarycenter(foldables[0]); | ||
+ | settings.insertBefore(foldDiv, | ||
+ | } | ||
+ | |||
+ | | ||
+ | // ---------------------- EXPLOSION ------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | if (explodableModel) { | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | if ( obj.userData.explodable ) { | ||
+ | computeCentroid(obj); | ||
+ | } | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | explode(0.000001); | ||
+ | } | ||
+ | |||
+ | function computeCentroid(obj) { | ||
+ | centroid = new THREE.Vector3(); | ||
+ | obj.userData.points.forEach(function(pmpoint) { | ||
+ | centroid.add(pmpoint.vector); | ||
+ | }); | ||
+ | centroid.divideScalar(obj.userData.points.length); | ||
+ | obj.userData.centroid = centroid; | ||
+ | } | ||
+ | |||
+ | function explode(factor) { | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i]; | ||
+ | if (obj.userData.hasOwnProperty(" | ||
+ | var c = obj.userData.centroid; | ||
+ | obj.position.set(c.x*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, | ||
+ | } | ||
+ | |||
+ | |||
+ | function explodingInterval(){ | ||
+ | explodeScale += explodingSpeed; | ||
+ | if (explodeScale <= 6){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else{ | ||
+ | explode(6); | ||
+ | explodeScale = 6; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startUnexploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | |||
+ | function startUnexploding(){ | ||
+ | intervals.push(setInterval(unexplodingInterval, | ||
+ | } | ||
+ | |||
+ | function unexplodingInterval(){ | ||
+ | explodeScale -= explodingSpeed; | ||
+ | if (explodeScale >= 0){ | ||
+ | explode(explodeScale); | ||
+ | } | ||
+ | else { | ||
+ | explode(0); | ||
+ | explodeScale = 0; | ||
+ | clearIntervals(); | ||
+ | timeouts.push(setTimeout(startExploding, | ||
+ | } | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | |||
+ | function clearIntervals(){ | ||
+ | intervals.forEach(function(interval){ | ||
+ | clearInterval(interval); | ||
+ | }); | ||
+ | intervals = []; | ||
+ | timeouts.forEach(function(timeout){ | ||
+ | clearTimeout(timeout); | ||
+ | }); | ||
+ | timeouts = []; | ||
+ | } | ||
+ | |||
+ | // ---------------------- DISPLAY -------------------------------------------------- | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | const objectTypeInnerHTMLs = { points: " | ||
+ | const objectTypeVisible = {}; | ||
+ | Object.assign(objectTypeVisible, | ||
+ | const sortedObjectTypeKeys = Object.keys(objectTypeInnerHTMLs).sort(); | ||
+ | const shownObjectTypesList = document.getElementById(' | ||
+ | |||
+ | function setVisibility(bool, | ||
+ | for (var i=0; i< | ||
+ | var obj = scene.children[i].getObjectByName(objname); | ||
+ | if (obj) { | ||
+ | obj.visible = bool; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function toggleObjectTypeVisibility(event){ | ||
+ | var name = event.currentTarget.name; | ||
+ | var checked = event.currentTarget.checked; | ||
+ | objectTypeVisible[name] = checked; | ||
+ | if (name == " | ||
+ | setVisibility(checked," | ||
+ | setVisibility(checked," | ||
+ | } else { | ||
+ | setVisibility(checked, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | for (var i=0; i< | ||
+ | var key = sortedObjectTypeKeys[i]; | ||
+ | if (modelContains[key]) { | ||
+ | var objTypeNode = document.createElement(' | ||
+ | objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = key; | ||
+ | checkbox.onchange = toggleObjectTypeVisibility; | ||
+ | shownObjectTypesList.appendChild(checkbox); | ||
+ | shownObjectTypesList.appendChild(objTypeNode); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // ------------------------------------------------------ | ||
+ | |||
+ | function toggleObjectVisibility(event){ | ||
+ | var nr = Number(event.currentTarget.name); | ||
+ | scene.children[nr].visible = event.currentTarget.checked; | ||
+ | } | ||
+ | |||
+ | // append checkboxes for displaying or hiding objects | ||
+ | var shownObjectsList = document.getElementById(' | ||
+ | for (var i=0; i< | ||
+ | obj = scene.children[i]; | ||
+ | var objNode = document.createElement(' | ||
+ | objNode.innerHTML = obj.name + '< | ||
+ | var checkbox = document.createElement(' | ||
+ | checkbox.type = ' | ||
+ | checkbox.checked = true; | ||
+ | checkbox.name = String(i); | ||
+ | checkbox.onchange = toggleObjectVisibility; | ||
+ | shownObjectsList.appendChild(checkbox); | ||
+ | shownObjectsList.appendChild(objNode); | ||
+ | } | ||
+ | |||
+ | // ---------------------- SVG ------------------------------------------------------ | ||
+ | // --------------------------------------------------------------------------------- | ||
+ | |||
+ | function takeSvgScreenshot() { | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(false," | ||
+ | } | ||
+ | svgRenderer.render(scene, | ||
+ | svgElement = XMLS.serializeToString(svgRenderer.domElement); | ||
+ | | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | if (objectTypeVisible[" | ||
+ | setVisibility(true," | ||
+ | } | ||
+ | |||
+ | if (document.getElementById(' | ||
+ | //show in new tab | ||
+ | var myWindow = window.open("","" | ||
+ | myWindow.document.body.innerHTML = svgElement; | ||
+ | } else{ | ||
+ | // download svg file | ||
+ | download(" | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function download(filename, | ||
+ | var element = document.createElement(' | ||
+ | element.setAttribute(' | ||
+ | element.setAttribute(' | ||
+ | |||
+ | element.style.display = ' | ||
+ | document.body.appendChild(element); | ||
+ | |||
+ | element.click(); | ||
+ | |||
+ | document.body.removeChild(element); | ||
+ | } | ||
+ | |||
+ | |||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | document.getElementById(' | ||
+ | |||
+ | |||
+ | // ------------------ SHORTCUTS -------------------------------------------- | ||
+ | // ------------------------------------------------------------------------- | ||
+ | |||
+ | /** | ||
+ | * http:// | ||
+ | * Version : 2.01.B | ||
+ | * By Binny V A | ||
+ | * License : BSD | ||
+ | */ | ||
+ | shortcut = { | ||
+ | ' | ||
+ | ' | ||
+ | //Provide a set of default options | ||
+ | var default_options = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | if(!opt) opt = default_options; | ||
+ | else { | ||
+ | for(var dfo in default_options) { | ||
+ | if(typeof opt[dfo] == ' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | var ele = opt.target; | ||
+ | if(typeof 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[' | ||
+ | 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 == ' | ||
+ | } | ||
+ | |||
+ | //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(code == 190) character=" | ||
+ | |||
+ | 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 = { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | ";":":", | ||
+ | "'":" | ||
+ | ",":"<", | ||
+ | " | ||
+ | "/":"?", | ||
+ | " | ||
+ | } | ||
+ | // | ||
+ | var special_keys = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | |||
+ | var modifiers = { | ||
+ | shift: { wanted: | ||
+ | ctrl : { wanted: | ||
+ | alt | ||
+ | meta : { wanted: | ||
+ | }; | ||
+ | | ||
+ | if(e.ctrlKey) modifiers.ctrl.pressed = true; | ||
+ | if(e.shiftKey) modifiers.shift.pressed = true; | ||
+ | if(e.altKey) modifiers.alt.pressed = true; | ||
+ | if(e.metaKey) | ||
+ | | ||
+ | for(var i=0; k=keys[i], | ||
+ | // | ||
+ | if(k == ' | ||
+ | kp++; | ||
+ | modifiers.ctrl.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.shift.wanted = true; | ||
+ | |||
+ | } else if(k == ' | ||
+ | kp++; | ||
+ | modifiers.alt.wanted = true; | ||
+ | } else if(k == ' | ||
+ | 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[' | ||
+ | if(opt[' | ||
+ | |||
+ | } 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[' | ||
+ | // | ||
+ | e.cancelBubble = true; | ||
+ | e.returnValue = false; | ||
+ | |||
+ | // | ||
+ | if (e.stopPropagation) { | ||
+ | e.stopPropagation(); | ||
+ | e.preventDefault(); | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | this.all_shortcuts[shortcut_combination] = { | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | }; | ||
+ | //Attach the function with the event | ||
+ | if(ele.addEventListener) ele.addEventListener(opt[' | ||
+ | else if(ele.attachEvent) ele.attachEvent(' | ||
+ | else ele[' | ||
+ | }, | ||
+ | |||
+ | //Remove the shortcut - just specify the shortcut and I will remove the binding | ||
+ | ' | ||
+ | shortcut_combination = shortcut_combination.toLowerCase(); | ||
+ | var binding = this.all_shortcuts[shortcut_combination]; | ||
+ | delete(this.all_shortcuts[shortcut_combination]) | ||
+ | if(!binding) return; | ||
+ | var type = binding[' | ||
+ | var ele = binding[' | ||
+ | var callback = binding[' | ||
+ | |||
+ | if(ele.detachEvent) ele.detachEvent(' | ||
+ | else if(ele.removeEventListener) ele.removeEventListener(type, | ||
+ | else ele[' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | shortcut.add(" | ||
+ | var event = new Event(' | ||
+ | if (settingsShown){ | ||
+ | document.getElementById(' | ||
+ | } else { | ||
+ | document.getElementById(' | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | |||
+ | // COMMON_CODE_BLOCK_END | ||
+ | |||
+ | });}); | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | This is quite similar to the '' | ||
+ | |||
+ | <code perl> | ||
+ | > print is_regular($points, | ||
+ | 0 <> | ||
+ | </ | ||
+ | Just as expected polymake tells us that the subdivision is not regular. But although there is no weight function which induces this particular subdivision we can still create a '' | ||
+ | |||
+ | <code perl> | ||
+ | > $nreg_sub = new fan:: | ||
+ | > $nreg_sc = $nreg_sub-> | ||
+ | > print $nreg_sc-> | ||
+ | 4 | ||
+ | </ | ||
+ | This might be weird at first. Although our subdivision is not regular (meaning there does not exist a secondary cone for that subdivision) the secondary cone seems to be 4 dimensional. Let us investigate. | ||
+ | |||
+ | <code perl> | ||
+ | > print $nreg_sc-> | ||
+ | 1 1 1 1 0 0 0 0 | ||
+ | > print $nreg_sc-> | ||
+ | 3/2 3/2 -1/2 -1/2 1 1 0 0 | ||
+ | -13/14 15/14 23/14 -5/14 -2/7 5/7 1 0 | ||
+ | 5/9 -1/3 5/9 13/9 5/9 1/9 5/9 1 | ||
+ | </ | ||
+ | This looks familiar, doesn' | ||
+ | |||