1{ 2 "cells": [ 3 { 4 "cell_type": "markdown", 5 "metadata": {}, 6 "source": [ 7 "## ILP and Hilbert bases\n", 8 "\n", 9 "### A first example\n", 10 "\n", 11 "First we will construct a new rational polytope:\n", 12 "\n", 13 " \n" 14 ] 15 }, 16 { 17 "cell_type": "code", 18 "execution_count": 1, 19 "metadata": {}, 20 "outputs": [], 21 "source": [ 22 "$p=new Polytope<Rational>;" 23 ] 24 }, 25 { 26 "cell_type": "markdown", 27 "metadata": {}, 28 "source": [ 29 " \n" 30 ] 31 }, 32 { 33 "cell_type": "code", 34 "execution_count": 2, 35 "metadata": {}, 36 "outputs": [], 37 "source": [ 38 "$p->POINTS=<<\".\";\n", 39 "1 0 0 0\n", 40 "1 1 0 0\n", 41 "1 0 1 0\n", 42 "1 1 1 0\n", 43 "1 0 0 1\n", 44 "1 1 0 1\n", 45 "1 0 1 1\n", 46 "1 1 1 1\n", 47 "." 48 ] 49 }, 50 { 51 "cell_type": "markdown", 52 "metadata": {}, 53 "source": [ 54 "\n", 55 "Note that points in `polymake` are always given in homogenous coordinates. I.e., the point (a,b,c) in R<sup>3</sup> is represented as `1 a b c` in `polymake`.\n", 56 "\n", 57 "Now we can examine some properties of `$p`. For instance we can determine the number of facets or whether `$p` is simple:\n", 58 "\n", 59 " \n" 60 ] 61 }, 62 { 63 "cell_type": "code", 64 "execution_count": 3, 65 "metadata": {}, 66 "outputs": [ 67 { 68 "data": { 69 "text/plain": [ 70 "6" 71 ] 72 }, 73 "execution_count": 3, 74 "metadata": {}, 75 "output_type": "execute_result" 76 }, 77 { 78 "data": { 79 "text/html": [ 80 "<details><summary><pre style=\"display:inline\"><small>Click here for additional output</small></pre></summary>\n", 81 "<pre>\n", 82 "polymake: used package cdd\n", 83 " cddlib\n", 84 " Implementation of the double description method of Motzkin et al.\n", 85 " Copyright by Komei Fukuda.\n", 86 " http://www-oldurls.inf.ethz.ch/personal/fukudak/cdd_home/\n", 87 "\n", 88 "polymake: used package lrs\n", 89 " Implementation of the reverse search algorithm of Avis and Fukuda.\n", 90 " Copyright by David Avis.\n", 91 " http://cgm.cs.mcgill.ca/~avis/C/lrs.html\n", 92 "\n", 93 "</pre>\n", 94 "</details>\n" 95 ] 96 }, 97 "metadata": {}, 98 "output_type": "display_data" 99 } 100 ], 101 "source": [ 102 "print $p->N_FACETS;" 103 ] 104 }, 105 { 106 "cell_type": "code", 107 "execution_count": 4, 108 "metadata": {}, 109 "outputs": [ 110 { 111 "data": { 112 "text/plain": [ 113 "true" 114 ] 115 }, 116 "execution_count": 4, 117 "metadata": {}, 118 "output_type": "execute_result" 119 } 120 ], 121 "source": [ 122 "print $p->SIMPLE;" 123 ] 124 }, 125 { 126 "cell_type": "markdown", 127 "metadata": {}, 128 "source": [ 129 "\n", 130 "As you might already have noticed, our polytope is just a 3-dimensional cube. So there would have been an easier way to create it using the client `cube`:\n", 131 "\n", 132 " \n" 133 ] 134 }, 135 { 136 "cell_type": "code", 137 "execution_count": 5, 138 "metadata": {}, 139 "outputs": [], 140 "source": [ 141 "$c = cube(3,0);" 142 ] 143 }, 144 { 145 "cell_type": "markdown", 146 "metadata": {}, 147 "source": [ 148 "(You can check out the details of any function in the [documentation](https://polymake.org/doku.php/documentation/latest/polytope).)\n", 149 "\n", 150 "And we can also verify that the two polytopes are actually equal:" 151 ] 152 }, 153 { 154 "cell_type": "code", 155 "execution_count": 6, 156 "metadata": {}, 157 "outputs": [ 158 { 159 "data": { 160 "text/plain": [ 161 "true" 162 ] 163 }, 164 "execution_count": 6, 165 "metadata": {}, 166 "output_type": "execute_result" 167 } 168 ], 169 "source": [ 170 "print equal_polyhedra($p,$c);" 171 ] 172 }, 173 { 174 "cell_type": "markdown", 175 "metadata": {}, 176 "source": [ 177 "### Another example\n", 178 "\n", 179 "Now let us proceed with a somewhat more interesting example: The convex hull of 20 randomly chosen points on the 2-dimensional sphere." 180 ] 181 }, 182 { 183 "cell_type": "code", 184 "execution_count": 7, 185 "metadata": {}, 186 "outputs": [], 187 "source": [ 188 "$rs = rand_sphere(3,20);" 189 ] 190 }, 191 { 192 "cell_type": "markdown", 193 "metadata": {}, 194 "source": [ 195 "\n", 196 "\n", 197 "`polymake` can of course visualise this polytope:\n", 198 "\n", 199 " \n" 200 ] 201 }, 202 { 203 "cell_type": "code", 204 "execution_count": 8, 205 "metadata": {}, 206 "outputs": [ 207 { 208 "data": { 209 "text/html": [ 210 "<!--\n", 211 "polymake for knusper\n", 212 "Thu Aug 27 11:38:20 2020\n", 213 "rs\n", 214 "-->\n", 215 "\n", 216 "\n", 217 "<html>\n", 218 " <head>\n", 219 " <meta charset=utf-8>\n", 220 " <title>rs</title>\n", 221 " <style>\n", 222 "/*\n", 223 "// COMMON_CODE_BLOCK_BEGIN\n", 224 "*/\n", 225 " html {overflow: scroll;}\n", 226 " strong{font-size: 18px;}\n", 227 " canvas { z-index: 8; }\n", 228 " input[type='radio'] {margin-left:0;}\n", 229 " input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;}\n", 230 " .group{padding-bottom: 15px;}\n", 231 " .settings * {z-index: 11; }\n", 232 " .settings{z-index: 10; font-family: Arial, Helvetica, sans-serif; margin-left: 30px; visibility: hidden; width: 14em; height: 96%; border: solid 1px silver; padding: 2px; overflow-y: scroll; box-sizing: border-box; background-color: white; position: absolute;}\n", 233 " .indented{margin-left: 20px; margin-top: 10px; padding-bottom: 0px;} \n", 234 " .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;}\n", 235 " .showSettingsButton{visibility: visible; z-index: 12; position: absolute }\n", 236 " .hideSettingsButton{visibility: hidden; z-index: 12; position: absolute; opacity: 0.5}\n", 237 " button{margin-left: 0; margin-top: 10px}\n", 238 " img{cursor: pointer;}\n", 239 " .suboption{padding-top: 15px;}\n", 240 " #model333753212 { width: 100%; height: 100%; }\n", 241 " .threejs_container { width: 100%; height: 75vh;}\n", 242 " .settings{max-height: 74vh} \n", 243 " input[type=range] {\n", 244 " -webkit-appearance: none;\n", 245 " padding:0; \n", 246 " width:90%; \n", 247 " margin-left: auto;\n", 248 " margin-right: auto;\n", 249 " margin-top: 15px;\n", 250 " margin-bottom: 15px;\n", 251 " display: block;\t\n", 252 " }\n", 253 " input[type=range]:focus {\n", 254 " outline: none;\n", 255 " }\n", 256 " input[type=range]::-webkit-slider-runnable-track {\n", 257 " height: 4px;\n", 258 " cursor: pointer;\n", 259 " animate: 0.2s;\n", 260 " box-shadow: 0px 0px 0px #000000;\n", 261 " background: #E3E3E3;\n", 262 " border-radius: 0px;\n", 263 " border: 0px solid #000000;\n", 264 " }\n", 265 " input[type=range]::-webkit-slider-thumb {\n", 266 " box-shadow: 1px 1px 2px #B8B8B8;\n", 267 " border: 1px solid #ABABAB;\n", 268 " height: 13px;\n", 269 " width: 25px;\n", 270 " border-radius: 20px;\n", 271 " background: #E0E0E0;\n", 272 " cursor: pointer;\n", 273 " -webkit-appearance: none;\n", 274 " margin-top: -5px;\n", 275 " }\n", 276 " input[type=range]:focus::-webkit-slider-runnable-track {\n", 277 " background: #E3E3E3;\n", 278 " }\n", 279 " input[type=range]::-moz-range-track {\n", 280 " height: 4px;\n", 281 " cursor: pointer;\n", 282 " animate: 0.2s;\n", 283 " box-shadow: 0px 0px 0px #000000;\n", 284 " background: #E3E3E3;\n", 285 " border-radius: 0px;\n", 286 " border: 0px solid #000000;\n", 287 " }\n", 288 " input[type=range]::-moz-range-thumb {\n", 289 " box-shadow: 1px 1px 2px #B8B8B8;\n", 290 " border: 1px solid #ABABAB;\n", 291 " height: 13px;\n", 292 " width: 25px;\n", 293 " border-radius: 20px;\n", 294 " background: #E0E0E0;\n", 295 " cursor: pointer;\n", 296 " }\n", 297 " input[type=range]::-ms-track {\n", 298 " height: 4px;\n", 299 " cursor: pointer;\n", 300 " animate: 0.2s;\n", 301 " background: transparent;\n", 302 " border-color: transparent;\n", 303 " color: transparent;\n", 304 " }\n", 305 " input[type=range]::-ms-fill-lower {\n", 306 " background: #E3E3E3;\n", 307 " border: 0px solid #000000;\n", 308 " border-radius: 0px;\n", 309 " box-shadow: 0px 0px 0px #000000;\n", 310 " }\n", 311 " input[type=range]::-ms-fill-upper {\n", 312 " background: #E3E3E3;\n", 313 " border: 0px solid #000000;\n", 314 " border-radius: 0px;\n", 315 " box-shadow: 0px 0px 0px #000000;\n", 316 " }\n", 317 " input[type=range]::-ms-thumb {\n", 318 " box-shadow: 1px 1px 2px #B8B8B8;\n", 319 " border: 1px solid #ABABAB;\n", 320 " height: 13px;\n", 321 " width: 25px;\n", 322 " border-radius: 20px;\n", 323 " background: #E0E0E0;\n", 324 " cursor: pointer;\n", 325 " }\n", 326 " input[type=range]:focus::-ms-fill-lower {\n", 327 " background: #E3E3E3;\n", 328 " }\n", 329 " input[type=range]:focus::-ms-fill-upper {\n", 330 " background: #E3E3E3;\n", 331 " }\n", 332 "/*\n", 333 "// COMMON_CODE_BLOCK_END\n", 334 "*/\n", 335 "\t\t</style>\n", 336 " </head>\n", 337 "<body>\n", 338 " <div class='threejs_container'>\n", 339 "\t\t<div id='settings_0' class='settings'>\n", 340 "\t\t\t<div class=group id='transparency_0' class='transparency'>\n", 341 "\t\t\t\t<strong>Transparency</strong>\n", 342 "\t\t\t\t<input id='transparencyRange_0' type='range' min=0 max=1 step=0.01 value=0>\n", 343 "\t\t\t</div>\n", 344 "\t\t\t\n", 345 "\t\t\t<div class=group id='rotation_0'>\n", 346 "\t\t\t\t<strong>Rotation</strong>\n", 347 "\t\t\t\t<div class=indented>\n", 348 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationX_0'> x-axis</div>\n", 349 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationY_0'> y-axis</div>\n", 350 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationZ_0'> z-axis</div>\n", 351 "\t\t\t\t\t<button id='resetButton_0'>Reset</button>\n", 352 "\t\t\t\t</div>\n", 353 "\n", 354 "\t\t\t\t<div class=suboption>Rotation speed</div>\n", 355 "\t\t\t\t<input id='rotationSpeedRange_0' type='range' min=0 max=5 step=0.01 value=2>\n", 356 "\t\t\t</div>\n", 357 "\n", 358 "\n", 359 "\t\t\t<div class=group id='display_0'>\n", 360 "\t\t\t\t<strong>Display</strong>\n", 361 "\t\t\t\t<div class=indented>\n", 362 "\t\t\t\t\t<div id='shownObjectTypesList_0' class='shownObjectsList'></div>\n", 363 "\t\t\t\t</div>\n", 364 "\t\t\t\t<div class=suboption>Objects</div>\n", 365 "\t\t\t\t<div class=indented>\n", 366 "\t\t\t\t <div id='shownObjectsList_0' class='shownObjectsList'></div>\n", 367 "\t\t\t\t</div>\n", 368 "\t\t\t</div>\n", 369 " \n", 370 " <div class=group id='camera_0'>\n", 371 " <strong>Camera</strong>\n", 372 " <div class=indented>\n", 373 " <form>\n", 374 " <select id=\"cameraType_0\">\n", 375 " <option value='perspective' selected> Perspective<br></option>\n", 376 " <option value='orthographic' > Orthographic<br></option>\n", 377 " </select>\n", 378 " </form>\n", 379 " </div>\n", 380 " </div>\n", 381 "\n", 382 "\t\t\t<div class=group id='svg_0'>\n", 383 "\t\t\t\t<strong>SVG</strong>\n", 384 "\t\t\t\t<div class=indented>\n", 385 "\t\t\t\t\t<form>\n", 386 "\t\t\t\t\t\t<input type=\"radio\" name='screenshotMode' value='download' id='download_0' checked> Download<br>\n", 387 "\t\t\t\t\t\t<input type=\"radio\" name='screenshotMode' value='tab' id='tab_0' > New tab<br>\n", 388 "\t\t\t\t\t</form>\n", 389 "\t\t\t\t\t<button id='takeScreenshot_0'>Screenshot</button>\n", 390 "\t\t\t\t</div>\n", 391 "\t\t\t</div>\n", 392 "\n", 393 "\t\t</div>\t<!-- end of settings -->\n", 394 "\t\t<img id='hideSettingsButton_0' class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px\">\n", 395 "\t\t<img id='showSettingsButton_0' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px\">\n", 396 "<div id=\"model333753212\"></div>\n", 397 "</div>\n", 398 " <script>\n", 399 " requirejs.config({\n", 400 " paths: {\n", 401 " three: '/kernelspecs/polymake/three',\n", 402 " TrackballControls: '/kernelspecs/polymake/TrackballControls',\n", 403 " OrbitControls: '/kernelspecs/polymake/OrbitControls',\n", 404 " Projector: '/kernelspecs/polymake/Projector',\n", 405 " SVGRenderer: '/kernelspecs/polymake/SVGRenderer',\n", 406 " WEBGL: '/kernelspecs/polymake/WebGL',\n", 407 " },\n", 408 " shim: {\n", 409 " 'three': { exports: 'THREE'},\n", 410 " 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' },\n", 411 " 'WEBGL': { deps: [ 'three' ], exports: 'THREE.WEBGL' },\n", 412 " 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' },\n", 413 " 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' },\n", 414 " 'OrbitControls': { deps: [ 'three' ], exports: 'THREE.OrbitControls' },\n", 415 " }\n", 416 " });\n", 417 " \n", 418 " require(['three'],function(THREE){\n", 419 " window.THREE = THREE;\n", 420 " require(['TrackballControls', 'OrbitControls', 'Projector', 'SVGRenderer', 'WEBGL'],\n", 421 " function(TrackballControls, OrbitControls, Projector, SVGRenderer, WEBGL) {\n", 422 " THREE.TrackballControls = TrackballControls;\n", 423 " THREE.OrbitControls = OrbitControls;\n", 424 " THREE.Projector = Projector;\n", 425 " THREE.SVGRenderer = SVGRenderer;\n", 426 " THREE.WEBGL = WEBGL;\n", 427 "\n", 428 "// COMMON_CODE_BLOCK_BEGIN\n", 429 "\n", 430 "const intervalLength = 25; // for automatic animations\n", 431 "const explodableModel = false; \n", 432 "const modelContains = { points: false, pointlabels: false, lines: false, edgelabels: false, faces: false, arrowheads: false };\n", 433 "const foldables = [];\n", 434 "\n", 435 "var three = document.getElementById(\"model333753212\");\n", 436 "var scene = new THREE.Scene();\n", 437 "var renderer = new THREE.WebGLRenderer( { antialias: true } );\n", 438 "var svgRenderer = new THREE.SVGRenderer( { antialias: true } );\n", 439 "renderer.setPixelRatio( window.devicePixelRatio );\n", 440 "renderer.setClearColor(0xFFFFFF, 1);\n", 441 "svgRenderer.setClearColor(0xFFFFFF, 1);\n", 442 "three.appendChild(renderer.domElement);\n", 443 "\n", 444 "var frustumSize = 4;\n", 445 "var cameras = [new THREE.PerspectiveCamera(75, 1, 0.1, 1000), new THREE.OrthographicCamera()];\n", 446 "cameras.forEach(function(cam) {\n", 447 " cam.position.set(0, 0, 5);\n", 448 " cam.lookAt(0, 0, 0); \n", 449 " cam.up.set(0, 1, 0); \n", 450 "});\n", 451 "var controls = [new THREE.TrackballControls(cameras[0], three), new THREE.OrbitControls(cameras[1], three)];\n", 452 "var camera, control;\n", 453 "\n", 454 "controls[0].zoomSpeed = 0.2;\n", 455 "controls[0].rotateSpeed = 4;\n", 456 "\n", 457 "\n", 458 "// class to allow move points together with labels and spheres\n", 459 "var PMPoint = function (x,y,z) {\n", 460 " this.vector = new THREE.Vector3(x,y,z);\n", 461 " this.sprite = null;\n", 462 " this.sphere = null;\n", 463 "}\n", 464 "PMPoint.prototype.addLabel = function(labelsprite) {\n", 465 " this.sprite = labelsprite;\n", 466 " this.sprite.position.copy(this.vector);\n", 467 "}\n", 468 "PMPoint.prototype.addSphere = function(spheremesh) {\n", 469 " this.sphere = spheremesh;\n", 470 " this.sphere.position.copy(this.vector);\n", 471 "}\n", 472 "PMPoint.prototype.set = function(x,y,z) {\n", 473 " this.vector.set(x,y,z);\n", 474 " if (this.sprite) {\n", 475 " this.sprite.position.copy(this.vector);\n", 476 " }\n", 477 " if (this.sphere) {\n", 478 " this.sphere.position.copy(this.vector);\n", 479 " }\n", 480 "}\n", 481 "PMPoint.prototype.radius = function() {\n", 482 " if (this.sphere) {\n", 483 " return this.sphere.geometry.parameters.radius;\n", 484 " } else {\n", 485 " return 0;\n", 486 " }\n", 487 "};\n", 488 "// select the target node\n", 489 "var target = document.querySelector('#model333753212');\n", 490 "\n", 491 "// create an observer instance\n", 492 "var observer = new MutationObserver(function(mutations) {\n", 493 " mutations.forEach(function(mutation) {\n", 494 " if (mutation.removedNodes && mutation.removedNodes.length > 0) {\n", 495 " cancelAnimationFrame(renderId);\n", 496 " observer.disconnect();\n", 497 " console.log(\"cancelled frame \"+renderId);\n", 498 " }\n", 499 " });\n", 500 "});\n", 501 "\n", 502 "// configuration of the observer:\n", 503 "var config = { childList: true, characterData: true }\n", 504 "\n", 505 "// pass in the target node, as well as the observer options\n", 506 "while (target) {\n", 507 " if (target.className==\"output\") {\n", 508 " observer.observe(target, config);\n", 509 " break;\n", 510 " }\n", 511 " target = target.parentNode;\n", 512 "}\n", 513 "\n", 514 "// COMMON_CODE_BLOCK_END\n", 515 "\n", 516 "var obj0 = new THREE.Object3D();\n", 517 "obj0.name = \"rs\";\n", 518 "obj0.userData.explodable = 1;\n", 519 "obj0.userData.points = [];\n", 520 "obj0.userData.points.push(new PMPoint(-0.504544, -0.245877, 0.827635));\n", 521 "obj0.userData.points.push(new PMPoint(-0.171247, -0.983096, 0.0647788));\n", 522 "obj0.userData.points.push(new PMPoint(0.397165, -0.503251, 0.767462));\n", 523 "obj0.userData.points.push(new PMPoint(-0.818591, -0.555017, -0.14787));\n", 524 "obj0.userData.points.push(new PMPoint(-0.63444, -0.162518, -0.755695));\n", 525 "obj0.userData.points.push(new PMPoint(-0.255875, 0.908972, -0.329087));\n", 526 "obj0.userData.points.push(new PMPoint(-0.272367, 0.0328207, -0.961633));\n", 527 "obj0.userData.points.push(new PMPoint(0.877439, 0.3782, 0.295069));\n", 528 "obj0.userData.points.push(new PMPoint(0.431367, 0.406399, -0.805458));\n", 529 "obj0.userData.points.push(new PMPoint(-0.977942, 0.158118, 0.136482));\n", 530 "obj0.userData.points.push(new PMPoint(0.266113, 0.0658087, 0.961693));\n", 531 "obj0.userData.points.push(new PMPoint(-0.554078, -0.390684, -0.735094));\n", 532 "obj0.userData.points.push(new PMPoint(0.795907, 0.0333783, -0.604498));\n", 533 "obj0.userData.points.push(new PMPoint(0.0805864, 0.981181, 0.17547));\n", 534 "obj0.userData.points.push(new PMPoint(-0.940302, -0.334343, 0.0636122));\n", 535 "obj0.userData.points.push(new PMPoint(-0.204604, 0.111891, 0.972429));\n", 536 "obj0.userData.points.push(new PMPoint(-0.446011, -0.474317, -0.759011));\n", 537 "obj0.userData.points.push(new PMPoint(-0.949291, 0.215985, -0.228466));\n", 538 "obj0.userData.points.push(new PMPoint(-0.583256, -0.0822278, -0.808115));\n", 539 "obj0.userData.points.push(new PMPoint(0.166539, 0.0625275, 0.98405));\n", 540 "\n", 541 "obj0.userData.pointradii = 0.02;\n", 542 " <!-- Vertex style -->\n", 543 "obj0.userData.pointmaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } );\n", 544 "obj0.userData.pointlabels = [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", \"19\"];\n", 545 "obj0.userData.edgeindices = [0, 1, 0, 2, 1, 2, 1, 3, 3, 4, 5, 6, 2, 7, 5, 8, 6, 8, 7, 8, 0, 9, 5, 9, 2, 10, 7, 10, 3, 11, 4, 11, 1, 12, 2, 12, 6, 12, 7, 12, 8, 12, 5, 13, 7, 13, 8, 13, 9, 13, 10, 13, 0, 14, 1, 14, 3, 14, 9, 14, 0, 15, 9, 15, 13, 15, 1, 16, 3, 16, 6, 16, 11, 16, 12, 16, 3, 17, 4, 17, 5, 17, 9, 17, 14, 17, 4, 18, 5, 18, 6, 18, 11, 18, 16, 18, 17, 18, 0, 19, 2, 19, 10, 19, 13, 19, 15, 19];\n", 546 " <!-- Edge style -->\n", 547 "obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, depthTest: true, linewidth: 1.5, transparent: false } );\n", 548 "obj0.userData.facets = [[12, 6, 8], [16, 6, 12], [12, 1, 16], [12, 2, 1], [2, 10, 19], [2, 19, 0], [1, 2, 0], [13, 15, 19], [15, 0, 19], [16, 1, 3], [1, 0, 14], [1, 14, 3], [5, 6, 18], [5, 18, 17], [5, 17, 9], [11, 16, 3], [18, 16, 11], [18, 11, 4], [11, 3, 4], [17, 4, 3], [17, 3, 14], [9, 17, 14], [17, 18, 4], [9, 14, 0], [18, 6, 16], [15, 9, 0], [13, 5, 9], [13, 9, 15], [10, 13, 19], [8, 6, 5], [8, 5, 13], [7, 8, 13], [7, 13, 10], [2, 7, 10], [12, 7, 2], [12, 8, 7]];\n", 549 " <!-- Facet style -->\n", 550 "obj0.userData.facetmaterial = new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } );\n", 551 "init_object(obj0);\n", 552 "scene.add(obj0);\n", 553 "\n", 554 "// COMMON_CODE_BLOCK_BEGIN\n", 555 "function textSpriteMaterial(message, parameters) {\n", 556 " if ( parameters === undefined ) parameters = {};\n", 557 " var fontface = \"Helvetica\";\n", 558 " var fontsize = parameters.hasOwnProperty(\"fontsize\") ? parameters[\"fontsize\"] : 15;\n", 559 " fontsize = fontsize*10;\n", 560 " var lines = message.split('\\\\n');\n", 561 " var size = 512;\n", 562 " for(var i = 0; i<lines.length; i++){\n", 563 " var tmp = lines[i].length;\n", 564 " while(tmp*fontsize > size){\n", 565 " fontsize--;\n", 566 " }\n", 567 " }\n", 568 " \n", 569 " var canvas = document.createElement('canvas');\n", 570 " canvas.width = size;\n", 571 " canvas.height = size;\n", 572 " var context = canvas.getContext('2d');\n", 573 " context.fillStyle = \"rgba(255, 255, 255, 0)\";\n", 574 " context.fill();\n", 575 " context.font = fontsize + \"px \" + fontface;\n", 576 " \n", 577 " // text color\n", 578 " context.fillStyle = \"rgba(0, 0, 0, 1.0)\";\n", 579 " for(var i = 0; i<lines.length; i++){\n", 580 " context.fillText(lines[i], size/2, size/2+i*fontsize);\n", 581 " }\n", 582 " \n", 583 " // canvas contents will be used for a texture\n", 584 " var texture = new THREE.Texture(canvas);\n", 585 " texture.needsUpdate = true;\n", 586 " \n", 587 " var spriteMaterial = new THREE.SpriteMaterial({map: texture, depthTest: true, depthWrite: false, polygonOffset: true, polygonOffsetFactor: -1, polygonOffsetUnits: 1 });\n", 588 " return spriteMaterial;\n", 589 "}\n", 590 "\n", 591 "\n", 592 "// ---------------------- INITIALIZING OBJECTS--------------------------------------\n", 593 "// ---------------------------------------------------------------------------------\n", 594 "\n", 595 "function init_object(obj) {\n", 596 " if (obj.userData.hasOwnProperty(\"pointmaterial\")) {\n", 597 " init_points(obj);\n", 598 " modelContains.points = true;\n", 599 " }\n", 600 " if (obj.userData.hasOwnProperty(\"pointlabels\")) {\n", 601 " init_pointlabels(obj);\n", 602 " modelContains.pointlabels = true;\n", 603 " }\n", 604 " if (obj.userData.hasOwnProperty(\"edgematerial\")) {\n", 605 " init_lines(obj);\n", 606 " modelContains.lines = true;\n", 607 " }\n", 608 " if (obj.userData.hasOwnProperty(\"edgelabels\")) {\n", 609 " init_edgelabels(obj);\n", 610 " modelContains.edgelabels = true;\n", 611 " }\n", 612 " if (obj.userData.hasOwnProperty(\"arrowstyle\")) {\n", 613 " init_arrowheads(obj);\n", 614 " modelContains.arrowheads = true;\n", 615 " }\n", 616 " if (obj.userData.hasOwnProperty(\"facetmaterial\")) {\n", 617 " init_faces(obj);\n", 618 " modelContains.faces = true;\n", 619 " }\n", 620 "}\n", 621 "\n", 622 "function init_points(obj) {\n", 623 " var pointgroup = new THREE.Group();\n", 624 " pointgroup.name = \"points\";\n", 625 " var points = obj.userData.points;\n", 626 " var radii = obj.userData.pointradii;\n", 627 " var materials = obj.userData.pointmaterial;\n", 628 " var geometry,material;\n", 629 " if (!Array.isArray(radii)) {\n", 630 " geometry = new THREE.SphereBufferGeometry(radii); \n", 631 " }\n", 632 " if (!Array.isArray(materials)) {\n", 633 " material = materials;\n", 634 " }\n", 635 " for (var i=0; i<points.length; i++) {\n", 636 " var point = points[i];\n", 637 " if (Array.isArray(radii)) {\n", 638 " if (radii[i] == 0) {\n", 639 " continue;\n", 640 " }\n", 641 " geometry = new THREE.SphereBufferGeometry(radii[i]); \n", 642 " } \n", 643 " if (Array.isArray(materials)) {\n", 644 " material = materials[i]; \n", 645 " } \n", 646 " var sphere = new THREE.Mesh(geometry, material);\n", 647 " point.addSphere(sphere);\n", 648 " pointgroup.add(sphere);\n", 649 " }\n", 650 " obj.add(pointgroup);\n", 651 "}\n", 652 "\n", 653 "function init_pointlabels(obj) {\n", 654 " var points = obj.userData.points;\n", 655 " var labels = obj.userData.pointlabels;\n", 656 " var pointlabels = new THREE.Group();\n", 657 " pointlabels.name = \"pointlabels\";\n", 658 " if (Array.isArray(labels)) {\n", 659 " for (var i=0; i<points.length; i++) {\n", 660 " var point = points[i];\n", 661 " var spriteMaterial = textSpriteMaterial( labels[i] );\n", 662 "\t var sprite = new THREE.Sprite(spriteMaterial);\n", 663 " point.addLabel(sprite);\n", 664 " pointlabels.add(sprite);\n", 665 " }\n", 666 " } else {\n", 667 " var spriteMaterial = textSpriteMaterial( labels );\n", 668 " for (var i=0; i<points.length; i++) {\n", 669 " var point = points[i];\n", 670 "\t var sprite = new THREE.Sprite(spriteMaterial);\n", 671 " point.addLabel(sprite);\n", 672 " pointlabels.add(sprite);\n", 673 " }\n", 674 " }\n", 675 " obj.add(pointlabels);\n", 676 "}\n", 677 "\n", 678 "function init_lines(obj) {\n", 679 " var edgeindices = obj.userData.edgeindices;\n", 680 " var points = obj.userData.points;\n", 681 " var materials = obj.userData.edgematerial;\n", 682 " var geometry = new THREE.BufferGeometry();\n", 683 " var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 );\n", 684 " var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 );\n", 685 " var geometry = new THREE.BufferGeometry();\n", 686 " geometry.setAttribute('position', bufattr);\n", 687 " if (Array.isArray(materials)) { \n", 688 " for (var i=0; i<materials.length; i++) {\n", 689 " geometry.addGroup(2*i,2,i);\n", 690 " }\n", 691 " }\n", 692 " var lines = new THREE.LineSegments(geometry, materials);\n", 693 " lines.name = \"lines\";\n", 694 " obj.add(lines);\n", 695 " updateEdgesPosition(obj);\n", 696 "}\n", 697 "\n", 698 "function init_edgelabels(obj) {\n", 699 " var points = obj.userData.points;\n", 700 " var edgeindices = obj.userData.edgeindices;\n", 701 " var labels = obj.userData.edgelabels;\n", 702 " var edgelabels = new THREE.Group();\n", 703 " edgelabels.name = \"edgelabels\";\n", 704 " if (Array.isArray(labels)) {\n", 705 " for (var i=0; i<edgeindices.length; i=i+2) {\n", 706 " var point = points[i];\n", 707 " var spriteMaterial = textSpriteMaterial( labels[i] );\n", 708 " var sprite = new THREE.Sprite(spriteMaterial);\n", 709 " sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[i]].vector,points[edgeindices[i+1]].vector).multiplyScalar(0.5));\n", 710 " edgelabels.add(sprite);\n", 711 " }\n", 712 " } else {\n", 713 " var spriteMaterial = textSpriteMaterial( labels );\n", 714 " for (var i=0; i<points.length; i++) {\n", 715 " var point = points[i];\n", 716 " var sprite = new THREE.Sprite(spriteMaterial);\n", 717 " sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[i]].vector,points[edgeindices[i+1]].vector).multiplyScalar(0.5));\n", 718 " pointlabels.add(sprite);\n", 719 " }\n", 720 " }\n", 721 " obj.add(edgelabels);\n", 722 "}\n", 723 "\n", 724 "function init_arrowheads(obj) {\n", 725 " var arrowheads = new THREE.Group();\n", 726 " arrowheads.name = \"arrowheads\";\n", 727 " var arrowstyle = obj.userData.arrowstyle;\n", 728 " var edgeindices = obj.userData.edgeindices;\n", 729 " var edgematerials = obj.userData.edgematerial;\n", 730 " var points = obj.userData.points;\n", 731 " var material;\n", 732 " if (!Array.isArray(edgematerials)) {\n", 733 " material = new THREE.MeshBasicMaterial( {color: edgematerials.color} );\n", 734 " }\n", 735 "\n", 736 " for (var i=0; i<edgeindices.length; i=i+2) {\n", 737 " var start = points[edgeindices[i]];\n", 738 " var end = points[edgeindices[i+1]];\n", 739 " var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius();\n", 740 " if (dist <= 0) {\n", 741 " continue;\n", 742 " }\n", 743 " var dir = new THREE.Vector3().subVectors(end.vector,start.vector);\n", 744 " dir.normalize();\n", 745 " var axis = new THREE.Vector3().set(dir.z,0,-dir.x);\n", 746 " axis.normalize();\n", 747 " var radians = Math.acos( dir.y );\n", 748 " var radius = dist/25;\n", 749 " var height = dist/5;\n", 750 " var geometry = new THREE.ConeBufferGeometry(radius,height);\n", 751 " var position = new THREE.Vector3().addVectors(start.vector,dir.clone().multiplyScalar(start.radius()+dist-height/2));\n", 752 " if (Array.isArray(edgematerials)) {\n", 753 " material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} );\n", 754 " }\n", 755 " var cone = new THREE.Mesh( geometry, material );\n", 756 " cone.quaternion.setFromAxisAngle(axis,radians);;\n", 757 " cone.position.copy(position);;\n", 758 " arrowheads.add(cone);\n", 759 " }\n", 760 " obj.add(arrowheads);\n", 761 "}\n", 762 "\n", 763 "function init_faces(obj) {\n", 764 " var points = obj.userData.points;\n", 765 " var facets = obj.userData.facets;\n", 766 " obj.userData.triangleindices = [];\n", 767 " for (var i=0; i<facets.length; i++) {\n", 768 " facet = facets[i];\n", 769 " for (var t=0; t<facet.length-2; t++) {\n", 770 " obj.userData.triangleindices.push(facet[0],facet[t+1],facet[t+2]); \n", 771 " }\n", 772 " }\n", 773 " var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 );\n", 774 " var bufattr = new THREE.Float32BufferAttribute(bufarr,3);\n", 775 " \n", 776 " var materials = obj.userData.facetmaterial;\n", 777 " var geometry = new THREE.BufferGeometry();\n", 778 " geometry.setAttribute('position',bufattr);\n", 779 " if (Array.isArray(materials)) {\n", 780 " var tricount = 0;\n", 781 " var facet;\n", 782 " for (var i=0; i<facets.length; i++) {\n", 783 " facet = facets[i];\n", 784 " geometry.addGroup(tricount,(facet.length-2)*3,i);\n", 785 " tricount += (facet.length-2)*3;\n", 786 " }\n", 787 " }\n", 788 " var mesh = new THREE.Mesh(geometry, materials);\n", 789 " mesh.name = \"faces\";\n", 790 " obj.add(mesh); \n", 791 " updateFacesPosition(obj);\n", 792 "}\n", 793 "// //INITIALIZING\n", 794 "\n", 795 "\n", 796 "function updateFacesPosition(obj) {\n", 797 " var points = obj.userData.points;\n", 798 " var indices = obj.userData.triangleindices;\n", 799 " var faces = obj.getObjectByName(\"faces\");\n", 800 " var ba = faces.geometry.getAttribute(\"position\");\n", 801 " for (var i=0; i<indices.length; i++) {\n", 802 " ba.setXYZ(i, points[indices[i]].vector.x, points[indices[i]].vector.y ,points[indices[i]].vector.z); \n", 803 " }\n", 804 " faces.geometry.attributes.position.needsUpdate = true;\n", 805 " \n", 806 "}\n", 807 "\n", 808 "function updateEdgesPosition(obj) {\n", 809 " var points = obj.userData.points;\n", 810 " var indices = obj.userData.edgeindices;\n", 811 " var lines = obj.getObjectByName(\"lines\");\n", 812 " var ba = lines.geometry.getAttribute(\"position\"); \n", 813 " for (var i=0; i<indices.length; i++) {\n", 814 " ba.setXYZ(i, points[indices[i]].vector.x, points[indices[i]].vector.y ,points[indices[i]].vector.z); \n", 815 " }\n", 816 " lines.geometry.attributes.position.needsUpdate = true;\n", 817 "}\n", 818 "\n", 819 "function onWindowResize() {\n", 820 " renderer.setSize( three.clientWidth, three.clientHeight );\n", 821 " svgRenderer.setSize( three.clientWidth, three.clientHeight );\n", 822 " updateCamera();\n", 823 "}\n", 824 "\n", 825 "function updateCamera() {\n", 826 " var width = three.clientWidth;\n", 827 " var height = three.clientHeight;\n", 828 " var aspect = width / height;\n", 829 " if (camera.type == \"OrthographicCamera\") {\n", 830 " camera.left = frustumSize * aspect / - 2;\n", 831 " camera.right = frustumSize * aspect / 2;\n", 832 " camera.top = frustumSize / 2;\n", 833 " camera.bottom = - frustumSize / 2;\n", 834 " } else if (camera.type == \"PerspectiveCamera\") {\n", 835 " camera.aspect = aspect;\n", 836 " }\n", 837 " camera.updateProjectionMatrix();\n", 838 "}\n", 839 "\n", 840 "function changeCamera(event) {\n", 841 " var selindex = event.currentTarget.selectedIndex;\n", 842 " camera = cameras[selindex];\n", 843 " control = controls[selindex];\n", 844 " control.enabled = true; \n", 845 " for (var i=0; i<controls.length; i++) {\n", 846 " if (i!=selindex) {\n", 847 " controls[i].enabled = false;\n", 848 " }\n", 849 " }\n", 850 " updateCamera();\n", 851 "}\n", 852 "\n", 853 "var camtypenode = document.getElementById('cameraType_0');\n", 854 "camtypenode.onchange = changeCamera;\n", 855 "camtypenode.dispatchEvent(new Event('change'));\n", 856 "\n", 857 "onWindowResize();\n", 858 "window.addEventListener('resize', onWindowResize);\t\n", 859 "\n", 860 "\n", 861 "var xRotationEnabled = false;\n", 862 "var yRotationEnabled = false;\n", 863 "var zRotationEnabled = false;\n", 864 "var rotationSpeedFactor = 1;\n", 865 "var settingsShown = false;\n", 866 "var labelsShown = true;\n", 867 "var intervals = [];\n", 868 "var timeouts = [];\n", 869 "var explodingSpeed = 0.05;\n", 870 "var explodeScale = 0;\n", 871 "var XMLS = new XMLSerializer();\n", 872 "var svgElement;\n", 873 "var renderId;\n", 874 "\n", 875 "var render = function () {\n", 876 "\n", 877 "\trenderId = requestAnimationFrame(render);\n", 878 "\n", 879 "//\tcomment in for automatic explosion\n", 880 "//\texplode(updateFactor());\n", 881 "\n", 882 " var phi = 0.02 * rotationSpeedFactor;\n", 883 "\n", 884 " if (xRotationEnabled) {\n", 885 " scene.rotation.x += phi;\n", 886 " }\n", 887 " if (yRotationEnabled) {\n", 888 " scene.rotation.y += phi;\n", 889 " }\n", 890 " if (zRotationEnabled) {\n", 891 " scene.rotation.z += phi;\n", 892 " }\n", 893 "\n", 894 " control.update();\n", 895 " renderer.render(scene, camera);\n", 896 "};\n", 897 "\n", 898 "if ( THREE.WEBGL.isWebGLAvailable() ) {\n", 899 "\trender();\n", 900 "} else {\n", 901 "\tvar warning = WEBGL.getWebGLErrorMessage();\n", 902 "\tthree.appendChild( warning );\n", 903 "}\n", 904 " \n", 905 "function changeTransparency() {\n", 906 " var opacity = 1-Number(event.currentTarget.value);\n", 907 " for (var i=0; i<scene.children.length; i++) {\n", 908 " child = scene.children[i];\n", 909 " if ( child.userData.hasOwnProperty(\"facetmaterial\") ) {\n", 910 " if (Array.isArray(child.userData.facetmaterial)) {\n", 911 " for (var j=0; j<child.userData.facetmaterial.length; j++) {\n", 912 " child.userData.facetmaterial[j].opacity = opacity;\n", 913 " }\n", 914 " } else {\n", 915 " child.userData.facetmaterial.opacity = opacity;\n", 916 " } \n", 917 " }\n", 918 " }\n", 919 "}\n", 920 "\n", 921 "function changeRotationX(event){\n", 922 " xRotationEnabled = event.currentTarget.checked;\n", 923 "}\t\n", 924 "\n", 925 "function changeRotationY(event){\n", 926 " yRotationEnabled = event.currentTarget.checked;\n", 927 "}\t\n", 928 "\n", 929 "function changeRotationZ(event){\n", 930 " zRotationEnabled = event.currentTarget.checked;\n", 931 "}\t\n", 932 "\n", 933 "\n", 934 "function changeRotationSpeedFactor(event){\n", 935 " rotationSpeedFactor = Number(event.currentTarget.value);\n", 936 "}\n", 937 "\n", 938 "function resetScene(){\n", 939 " scene.rotation.set(0,0,0);\n", 940 " camera.position.set(0,0,5);\n", 941 " camera.up.set(0,1,0);\n", 942 "}\n", 943 "\n", 944 "function showSettings(event){\n", 945 " document.getElementById('settings_0').style.visibility = 'visible';\n", 946 " document.getElementById('showSettingsButton_0').style.visibility = 'hidden';\n", 947 " document.getElementById('hideSettingsButton_0').style.visibility = 'visible';\n", 948 " settingsShown = true;\n", 949 "}\n", 950 "\n", 951 "function hideSettings(event){\n", 952 " document.getElementById('settings_0').style.visibility = 'hidden';\n", 953 " document.getElementById('showSettingsButton_0').style.visibility = 'visible';\n", 954 " document.getElementById('hideSettingsButton_0').style.visibility = 'hidden';\n", 955 " settingsShown = false;\n", 956 "}\n", 957 "\n", 958 "\n", 959 "\n", 960 "var pos = 150* Math.PI;\n", 961 "\n", 962 "function updateFactor() {\n", 963 " pos++;\n", 964 " return Math.sin(.01*pos)+1;\n", 965 "}\n", 966 "\n", 967 "// ------------------------ FOLDING ------------------------------------------------\n", 968 "// ---------------------------------------------------------------------------------\n", 969 "// rotate point p around axis defined by points p1 and p2 by given angle\n", 970 "function rotate(p, p1, p2, angle ){ \n", 971 " angle = -angle;\n", 972 " var x = p.x, y = p.y, z = p.z, \n", 973 " a = p1.x, b = p1.y, c = p1.z, \n", 974 " u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z;\n", 975 " var result = [];\n", 976 " var L = u*u + v*v + w*w;\n", 977 " var sqrt = Math.sqrt;\n", 978 " var cos = Math.cos;\n", 979 " var sin = Math.sin;\n", 980 "\n", 981 " result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/L;\n", 982 " result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/L;\n", 983 " result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/L;\n", 984 "\n", 985 " return result;\n", 986 "}\n", 987 "\n", 988 "var fold = function(event){\n", 989 " var obj = foldables[Number(event.currentTarget.name)];\n", 990 " var foldvalue = Number(event.currentTarget.value);\n", 991 " var scale = foldvalue - obj.userData.oldscale;\n", 992 "\n", 993 " for (var j=0; j<obj.userData.axes.length; j++) {\n", 994 " rotateVertices(obj, j, scale);\n", 995 " }\n", 996 " update(obj);\n", 997 " obj.userData.oldscale += scale;\n", 998 " lookAtBarycenter(obj);\n", 999 "}\n", 1000 "\n", 1001 "function lookAtBarycenter(obj){\n", 1002 " control.target = barycenter(obj);\n", 1003 "}\n", 1004 "\n", 1005 "function barycenter(obj) {\n", 1006 " var center = new THREE.Vector3(0,0,0);\n", 1007 " var points = obj.userData.points;\n", 1008 " for (var i=0; i<points.length; i++){\n", 1009 " center.add(points[i].vector);\n", 1010 " }\n", 1011 " center.divideScalar(points.length);\n", 1012 " return center;\n", 1013 "}\n", 1014 "\n", 1015 "function rotateVertices(obj, edge, scale) {\n", 1016 " var axes = obj.userData.axes;\n", 1017 " var subtrees = obj.userData.subtrees;\n", 1018 " var points = obj.userData.points;\n", 1019 " var angles = obj.userData.angles;\n", 1020 " if (edge < axes.length){\n", 1021 " for (var j=0; j<subtrees[edge].length; j++){\n", 1022 " var rotP = rotate(points[subtrees[edge][j]].vector, points[axes[edge][0]].vector,points[axes[edge][1]].vector, scale * (Math.PI - angles[edge]));\n", 1023 " points[subtrees[edge][j]].set(rotP[0],rotP[1],rotP[2]);\n", 1024 " }\n", 1025 " }\n", 1026 "}\n", 1027 "\n", 1028 "function update(obj) {\n", 1029 " updateFacesPosition(obj);\n", 1030 " updateEdgesPosition(obj);\n", 1031 "}\n", 1032 "\n", 1033 "if (foldables.length) {\n", 1034 " var settings = document.getElementById('settings_0');\n", 1035 " var foldDiv = document.createElement('div');\n", 1036 " foldDiv.id = 'fold_0';\n", 1037 " var title = document.createElement('strong');\n", 1038 " title.innerHTML = 'Fold';\n", 1039 " foldDiv.appendChild(title);\n", 1040 " foldDiv.className = 'group';\n", 1041 " for (var i=0; i<foldables.length; i++) {\n", 1042 " var range = document.createElement('input');\n", 1043 " range.type = 'range';\n", 1044 " range.min = 0;\n", 1045 " range.max = 1;\n", 1046 " range.value = 0;\n", 1047 " range.step = 0.001;\n", 1048 " range.name = String(i);\n", 1049 " range.oninput = fold;\n", 1050 " foldDiv.appendChild(range);\n", 1051 " }\n", 1052 " lookAtBarycenter(foldables[0]);\n", 1053 " settings.insertBefore(foldDiv,settings.childNodes[0]);\n", 1054 "}\n", 1055 "\n", 1056 " \n", 1057 "// ---------------------- EXPLOSION ------------------------------------------------\n", 1058 "// ---------------------------------------------------------------------------------\n", 1059 "\n", 1060 "if (explodableModel) {\n", 1061 " for (var i=0; i<scene.children.length; i++) {\n", 1062 " obj = scene.children[i];\n", 1063 " if ( obj.userData.explodable ) {\n", 1064 " computeCentroid(obj);\n", 1065 " }\n", 1066 " }\n", 1067 " document.getElementById('explodeRange_0').oninput = triggerExplode;\n", 1068 " document.getElementById('explodeCheckbox_0').onchange = triggerAutomaticExplode;\n", 1069 " document.getElementById('explodingSpeedRange_0').oninput = setExplodingSpeed;\n", 1070 "}\n", 1071 "\n", 1072 "function computeCentroid(obj) {\n", 1073 " centroid = new THREE.Vector3();\n", 1074 " obj.userData.points.forEach(function(pmpoint) {\n", 1075 " centroid.add(pmpoint.vector);\t\t\t\n", 1076 " });\n", 1077 " centroid.divideScalar(obj.userData.points.length);\n", 1078 " obj.userData.centroid = centroid;\n", 1079 "}\n", 1080 "\n", 1081 "function explode(factor) {\n", 1082 " for (var i=0; i<scene.children.length; i++) {\n", 1083 " var obj = scene.children[i];\n", 1084 " if (obj.userData.hasOwnProperty(\"centroid\")) { \n", 1085 " var c = obj.userData.centroid;\n", 1086 " obj.position.set(c.x*factor, c.y*factor, c.z*factor);\n", 1087 " }\n", 1088 " }\t\n", 1089 "}\n", 1090 "\n", 1091 "function triggerExplode(event){\n", 1092 " explodeScale = Number(event.currentTarget.value);\n", 1093 " explode(explodeScale);\n", 1094 "}\n", 1095 "\n", 1096 "function setExplodingSpeed(event){\n", 1097 " explodingSpeed = Number(event.currentTarget.value);\n", 1098 "}\n", 1099 "\n", 1100 "function triggerAutomaticExplode(event){\n", 1101 " if (event.currentTarget.checked){\n", 1102 " startExploding();\n", 1103 " } else {\n", 1104 " clearIntervals();\n", 1105 " }\t\n", 1106 "}\n", 1107 "\n", 1108 "function startExploding(){\n", 1109 " intervals.push(setInterval(explodingInterval, 25));\n", 1110 "}\n", 1111 "\n", 1112 "\n", 1113 "function explodingInterval(){\n", 1114 " explodeScale += explodingSpeed;\n", 1115 " if (explodeScale <= 6){ \n", 1116 " explode(explodeScale);\n", 1117 " }\n", 1118 " else{\n", 1119 " explode(6);\n", 1120 " explodeScale = 6;\n", 1121 " clearIntervals();\n", 1122 " timeouts.push(setTimeout(startUnexploding, 3000));\n", 1123 " }\n", 1124 " document.getElementById('explodeRange_0').value = explodeScale;\n", 1125 "}\n", 1126 "\n", 1127 "\n", 1128 "function startUnexploding(){\n", 1129 " intervals.push(setInterval(unexplodingInterval, 25));\n", 1130 "}\n", 1131 "\n", 1132 "function unexplodingInterval(){\n", 1133 " explodeScale -= explodingSpeed;\n", 1134 " if (explodeScale >= 0){\t\n", 1135 " explode(explodeScale);\n", 1136 " }\n", 1137 " else {\n", 1138 " explode(0);\n", 1139 " explodeScale = 0;\n", 1140 " clearIntervals();\n", 1141 " timeouts.push(setTimeout(startExploding, 3000));\n", 1142 " }\n", 1143 " document.getElementById('explodeRange_0').value = explodeScale;\n", 1144 "}\n", 1145 "\n", 1146 "function clearIntervals(){\n", 1147 " intervals.forEach(function(interval){\n", 1148 " clearInterval(interval);\n", 1149 " });\n", 1150 " intervals = [];\n", 1151 " timeouts.forEach(function(timeout){\n", 1152 " clearTimeout(timeout);\n", 1153 " });\n", 1154 " timeouts = [];\n", 1155 "}\n", 1156 "\n", 1157 "// ---------------------- DISPLAY --------------------------------------------------\n", 1158 "// ---------------------------------------------------------------------------------\n", 1159 "\n", 1160 "const objectTypeInnerHTMLs = { points: \"Points\", pointlabels: \"Point labels\", lines: \"Edges\", edgelabels: \"Edge labels\", faces: \"Faces\", arrowheads: \"Arrow heads\" };\n", 1161 "const objectTypeVisible = {};\n", 1162 "Object.assign(objectTypeVisible,modelContains);\n", 1163 "const sortedObjectTypeKeys = Object.keys(objectTypeInnerHTMLs).sort();\n", 1164 "const shownObjectTypesList = document.getElementById('shownObjectTypesList_0');\n", 1165 "\n", 1166 "function setVisibility(bool,objname) {\n", 1167 " for (var i=0; i<scene.children.length; i++){\n", 1168 " var obj = scene.children[i].getObjectByName(objname);\n", 1169 " if (obj) {\n", 1170 " obj.visible = bool;\n", 1171 " }\n", 1172 " }\n", 1173 "}\n", 1174 "\n", 1175 "function toggleObjectTypeVisibility(event){\n", 1176 " var name = event.currentTarget.name;\n", 1177 " var checked = event.currentTarget.checked;\n", 1178 " objectTypeVisible[name] = checked;\n", 1179 " setVisibility(checked,name);\n", 1180 "}\n", 1181 "\n", 1182 "for (var i=0; i<sortedObjectTypeKeys.length; i++){\n", 1183 " var key = sortedObjectTypeKeys[i];\n", 1184 " if (modelContains[key]) {\n", 1185 " var objTypeNode = document.createElement('span');\n", 1186 " objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '<br>';\n", 1187 " var checkbox = document.createElement('input');\n", 1188 " checkbox.type = 'checkbox';\n", 1189 " checkbox.checked = true;\n", 1190 " checkbox.name = key;\n", 1191 " checkbox.onchange = toggleObjectTypeVisibility;\n", 1192 " shownObjectTypesList.appendChild(checkbox);\n", 1193 " shownObjectTypesList.appendChild(objTypeNode);\n", 1194 " }\n", 1195 "}\n", 1196 "\n", 1197 "// ------------------------------------------------------\n", 1198 "\n", 1199 "function toggleObjectVisibility(event){\n", 1200 " var nr = Number(event.currentTarget.name);\n", 1201 " scene.children[nr].visible = event.currentTarget.checked;\n", 1202 "}\n", 1203 "\n", 1204 "// append checkboxes for displaying or hiding objects\n", 1205 "var shownObjectsList = document.getElementById('shownObjectsList_0');\n", 1206 "for (var i=0; i<scene.children.length; i++){\n", 1207 " obj = scene.children[i];\n", 1208 " var objNode = document.createElement('span');\n", 1209 " objNode.innerHTML = obj.name + '<br>';\n", 1210 " var checkbox = document.createElement('input');\n", 1211 " checkbox.type = 'checkbox';\n", 1212 " checkbox.checked = true;\n", 1213 " checkbox.name = String(i);\n", 1214 " checkbox.onchange = toggleObjectVisibility;\n", 1215 " shownObjectsList.appendChild(checkbox);\n", 1216 " shownObjectsList.appendChild(objNode);\n", 1217 "}\n", 1218 "\n", 1219 "// ---------------------- SVG ------------------------------------------------------\n", 1220 "// ---------------------------------------------------------------------------------\n", 1221 "\n", 1222 "function takeSvgScreenshot() {\n", 1223 " if (objectTypeVisible[\"pointlabels\"]) {\n", 1224 " setVisibility(false,\"pointlabels\");\n", 1225 " }\n", 1226 " if (objectTypeVisible[\"edgelabels\"]) {\n", 1227 " setVisibility(false,\"edgelabels\");\n", 1228 " }\n", 1229 " svgRenderer.render(scene,camera);\n", 1230 " svgElement = XMLS.serializeToString(svgRenderer.domElement);\n", 1231 " \n", 1232 " if (objectTypeVisible[\"pointlabels\"]) {\n", 1233 " setVisibility(true,\"pointlabels\");\n", 1234 " }\n", 1235 " if (objectTypeVisible[\"edgelabels\"]) {\n", 1236 " setVisibility(true,\"edgelabels\");\n", 1237 " }\n", 1238 "\n", 1239 " if (document.getElementById('tab_0').checked){\n", 1240 " //show in new tab\n", 1241 " var myWindow = window.open(\"\",\"\");\n", 1242 " myWindow.document.body.innerHTML = svgElement;\n", 1243 " } else{\n", 1244 " // download svg file \n", 1245 " download(\"screenshot.svg\", svgElement);\n", 1246 " }\n", 1247 "}\n", 1248 "\n", 1249 "function download(filename, text) {\n", 1250 " var element = document.createElement('a');\n", 1251 " element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));\n", 1252 " element.setAttribute('download', filename);\n", 1253 "\n", 1254 " element.style.display = 'none';\n", 1255 " document.body.appendChild(element);\n", 1256 "\n", 1257 " element.click();\n", 1258 "\n", 1259 " document.body.removeChild(element);\n", 1260 "}\n", 1261 "\n", 1262 "\n", 1263 "document.getElementById('transparencyRange_0').oninput = changeTransparency;\n", 1264 "document.getElementById('changeRotationX_0').onchange = changeRotationX;\n", 1265 "document.getElementById('changeRotationY_0').onchange = changeRotationY;\n", 1266 "document.getElementById('changeRotationZ_0').onchange = changeRotationZ;\n", 1267 "document.getElementById('resetButton_0').onclick = resetScene;\n", 1268 "document.getElementById('rotationSpeedRange_0').oninput = changeRotationSpeedFactor;\n", 1269 "document.getElementById('takeScreenshot_0').onclick = takeSvgScreenshot;\n", 1270 "document.getElementById('showSettingsButton_0').onclick = showSettings;\n", 1271 "document.getElementById('hideSettingsButton_0').onclick = hideSettings;\n", 1272 "\n", 1273 "\n", 1274 "// ------------------ SHORTCUTS --------------------------------------------\n", 1275 "// -------------------------------------------------------------------------\n", 1276 "\n", 1277 "/**\n", 1278 " * http://www.openjs.com/scripts/events/keyboard_shortcuts/\n", 1279 " * Version : 2.01.B\n", 1280 " * By Binny V A\n", 1281 " * License : BSD\n", 1282 " */\n", 1283 "shortcut = {\n", 1284 "\t'all_shortcuts':{},//All the shortcuts are stored in this array\n", 1285 "\t'add': function(shortcut_combination,callback,opt) {\n", 1286 "\t\t//Provide a set of default options\n", 1287 "\t\tvar default_options = {\n", 1288 "\t\t\t'type':'keydown',\n", 1289 "\t\t\t'propagate':false,\n", 1290 "\t\t\t'disable_in_input':false,\n", 1291 "\t\t\t'target':document,\n", 1292 "\t\t\t'keycode':false\n", 1293 "\t\t}\n", 1294 "\t\tif(!opt) opt = default_options;\n", 1295 "\t\telse {\n", 1296 "\t\t\tfor(var dfo in default_options) {\n", 1297 "\t\t\t\tif(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];\n", 1298 "\t\t\t}\n", 1299 "\t\t}\n", 1300 "\n", 1301 "\t\tvar ele = opt.target;\n", 1302 "\t\tif(typeof opt.target == 'string') ele = document.getElementById(opt.target);\n", 1303 "\t\tvar ths = this;\n", 1304 "\t\tshortcut_combination = shortcut_combination.toLowerCase();\n", 1305 "\n", 1306 "\t\t//The function to be called at keypress\n", 1307 "\t\tvar func = function(e) {\n", 1308 "\t\t\te = e || window.event;\n", 1309 "\t\t\t\n", 1310 "\t\t\tif(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields\n", 1311 "\t\t\t\tvar element;\n", 1312 "\t\t\t\tif(e.target) element=e.target;\n", 1313 "\t\t\t\telse if(e.srcElement) element=e.srcElement;\n", 1314 "\t\t\t\tif(element.nodeType==3) element=element.parentNode;\n", 1315 "\n", 1316 "\t\t\t\tif(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;\n", 1317 "\t\t\t}\n", 1318 "\t\n", 1319 "\t\t\t//Find Which key is pressed\n", 1320 "\t\t\tif (e.keyCode) code = e.keyCode;\n", 1321 "\t\t\telse if (e.which) code = e.which;\n", 1322 "\t\t\tvar character = String.fromCharCode(code).toLowerCase();\n", 1323 "\t\t\t\n", 1324 "\t\t\tif(code == 188) character=\",\"; //If the user presses , when the type is onkeydown\n", 1325 "\t\t\tif(code == 190) character=\".\"; //If the user presses , when the type is onkeydown\n", 1326 "\n", 1327 "\t\t\tvar keys = shortcut_combination.split(\"+\");\n", 1328 "\t\t\t//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked\n", 1329 "\t\t\tvar kp = 0;\n", 1330 "\t\t\t\n", 1331 "\t\t\t//Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken\n", 1332 "\t\t\tvar shift_nums = {\n", 1333 "\t\t\t\t\"`\":\"~\",\n", 1334 "\t\t\t\t\"1\":\"!\",\n", 1335 "\t\t\t\t\"2\":\"@\",\n", 1336 "\t\t\t\t\"3\":\"#\",\n", 1337 "\t\t\t\t\"4\":\"$\",\n", 1338 "\t\t\t\t\"5\":\"%\",\n", 1339 "\t\t\t\t\"6\":\"^\",\n", 1340 "\t\t\t\t\"7\":\"&\",\n", 1341 "\t\t\t\t\"8\":\"*\",\n", 1342 "\t\t\t\t\"9\":\"(\",\n", 1343 "\t\t\t\t\"0\":\")\",\n", 1344 "\t\t\t\t\"-\":\"_\",\n", 1345 "\t\t\t\t\"=\":\"+\",\n", 1346 "\t\t\t\t\";\":\":\",\n", 1347 "\t\t\t\t\"'\":\"\\\"\",\n", 1348 "\t\t\t\t\",\":\"<\",\n", 1349 "\t\t\t\t\".\":\">\",\n", 1350 "\t\t\t\t\"/\":\"?\",\n", 1351 "\t\t\t\t\"\\\\\":\"|\"\n", 1352 "\t\t\t}\n", 1353 "\t\t\t//Special Keys - and their codes\n", 1354 "\t\t\tvar special_keys = {\n", 1355 "\t\t\t\t'esc':27,\n", 1356 "\t\t\t\t'escape':27,\n", 1357 "\t\t\t\t'tab':9,\n", 1358 "\t\t\t\t'space':32,\n", 1359 "\t\t\t\t'return':13,\n", 1360 "\t\t\t\t'enter':13,\n", 1361 "\t\t\t\t'backspace':8,\n", 1362 "\t\n", 1363 "\t\t\t\t'scrolllock':145,\n", 1364 "\t\t\t\t'scroll_lock':145,\n", 1365 "\t\t\t\t'scroll':145,\n", 1366 "\t\t\t\t'capslock':20,\n", 1367 "\t\t\t\t'caps_lock':20,\n", 1368 "\t\t\t\t'caps':20,\n", 1369 "\t\t\t\t'numlock':144,\n", 1370 "\t\t\t\t'num_lock':144,\n", 1371 "\t\t\t\t'num':144,\n", 1372 "\t\t\t\t\n", 1373 "\t\t\t\t'pause':19,\n", 1374 "\t\t\t\t'break':19,\n", 1375 "\t\t\t\t\n", 1376 "\t\t\t\t'insert':45,\n", 1377 "\t\t\t\t'home':36,\n", 1378 "\t\t\t\t'delete':46,\n", 1379 "\t\t\t\t'end':35,\n", 1380 "\t\t\t\t\n", 1381 "\t\t\t\t'pageup':33,\n", 1382 "\t\t\t\t'page_up':33,\n", 1383 "\t\t\t\t'pu':33,\n", 1384 "\t\n", 1385 "\t\t\t\t'pagedown':34,\n", 1386 "\t\t\t\t'page_down':34,\n", 1387 "\t\t\t\t'pd':34,\n", 1388 "\t\n", 1389 "\t\t\t\t'left':37,\n", 1390 "\t\t\t\t'up':38,\n", 1391 "\t\t\t\t'right':39,\n", 1392 "\t\t\t\t'down':40,\n", 1393 "\t\n", 1394 "\t\t\t\t'f1':112,\n", 1395 "\t\t\t\t'f2':113,\n", 1396 "\t\t\t\t'f3':114,\n", 1397 "\t\t\t\t'f4':115,\n", 1398 "\t\t\t\t'f5':116,\n", 1399 "\t\t\t\t'f6':117,\n", 1400 "\t\t\t\t'f7':118,\n", 1401 "\t\t\t\t'f8':119,\n", 1402 "\t\t\t\t'f9':120,\n", 1403 "\t\t\t\t'f10':121,\n", 1404 "\t\t\t\t'f11':122,\n", 1405 "\t\t\t\t'f12':123\n", 1406 "\t\t\t}\n", 1407 "\t\n", 1408 "\t\t\tvar modifiers = { \n", 1409 "\t\t\t\tshift: { wanted:false, pressed:false},\n", 1410 "\t\t\t\tctrl : { wanted:false, pressed:false},\n", 1411 "\t\t\t\talt : { wanted:false, pressed:false},\n", 1412 "\t\t\t\tmeta : { wanted:false, pressed:false}\t//Meta is Mac specific\n", 1413 "\t\t\t};\n", 1414 " \n", 1415 "\t\t\tif(e.ctrlKey)\tmodifiers.ctrl.pressed = true;\n", 1416 "\t\t\tif(e.shiftKey)\tmodifiers.shift.pressed = true;\n", 1417 "\t\t\tif(e.altKey)\tmodifiers.alt.pressed = true;\n", 1418 "\t\t\tif(e.metaKey) modifiers.meta.pressed = true;\n", 1419 " \n", 1420 "\t\t\tfor(var i=0; k=keys[i],i<keys.length; i++) {\n", 1421 "\t\t\t\t//Modifiers\n", 1422 "\t\t\t\tif(k == 'ctrl' || k == 'control') {\n", 1423 "\t\t\t\t\tkp++;\n", 1424 "\t\t\t\t\tmodifiers.ctrl.wanted = true;\n", 1425 "\n", 1426 "\t\t\t\t} else if(k == 'shift') {\n", 1427 "\t\t\t\t\tkp++;\n", 1428 "\t\t\t\t\tmodifiers.shift.wanted = true;\n", 1429 "\n", 1430 "\t\t\t\t} else if(k == 'alt') {\n", 1431 "\t\t\t\t\tkp++;\n", 1432 "\t\t\t\t\tmodifiers.alt.wanted = true;\n", 1433 "\t\t\t\t} else if(k == 'meta') {\n", 1434 "\t\t\t\t\tkp++;\n", 1435 "\t\t\t\t\tmodifiers.meta.wanted = true;\n", 1436 "\t\t\t\t} else if(k.length > 1) { //If it is a special key\n", 1437 "\t\t\t\t\tif(special_keys[k] == code) kp++;\n", 1438 "\t\t\t\t\t\n", 1439 "\t\t\t\t} else if(opt['keycode']) {\n", 1440 "\t\t\t\t\tif(opt['keycode'] == code) kp++;\n", 1441 "\n", 1442 "\t\t\t\t} else { //The special keys did not match\n", 1443 "\t\t\t\t\tif(character == k) kp++;\n", 1444 "\t\t\t\t\telse {\n", 1445 "\t\t\t\t\t\tif(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase\n", 1446 "\t\t\t\t\t\t\tcharacter = shift_nums[character]; \n", 1447 "\t\t\t\t\t\t\tif(character == k) kp++;\n", 1448 "\t\t\t\t\t\t}\n", 1449 "\t\t\t\t\t}\n", 1450 "\t\t\t\t}\n", 1451 "\t\t\t}\n", 1452 "\t\t\t\n", 1453 "\t\t\tif(kp == keys.length && \n", 1454 "\t\t\t\t\t\tmodifiers.ctrl.pressed == modifiers.ctrl.wanted &&\n", 1455 "\t\t\t\t\t\tmodifiers.shift.pressed == modifiers.shift.wanted &&\n", 1456 "\t\t\t\t\t\tmodifiers.alt.pressed == modifiers.alt.wanted &&\n", 1457 "\t\t\t\t\t\tmodifiers.meta.pressed == modifiers.meta.wanted) {\n", 1458 "\t\t\t\tcallback(e);\n", 1459 "\t\n", 1460 "\t\t\t\tif(!opt['propagate']) { //Stop the event\n", 1461 "\t\t\t\t\t//e.cancelBubble is supported by IE - this will kill the bubbling process.\n", 1462 "\t\t\t\t\te.cancelBubble = true;\n", 1463 "\t\t\t\t\te.returnValue = false;\n", 1464 "\t\n", 1465 "\t\t\t\t\t//e.stopPropagation works in Firefox.\n", 1466 "\t\t\t\t\tif (e.stopPropagation) {\n", 1467 "\t\t\t\t\t\te.stopPropagation();\n", 1468 "\t\t\t\t\t\te.preventDefault();\n", 1469 "\t\t\t\t\t}\n", 1470 "\t\t\t\t\treturn false;\n", 1471 "\t\t\t\t}\n", 1472 "\t\t\t}\n", 1473 "\t\t}\n", 1474 "\t\tthis.all_shortcuts[shortcut_combination] = {\n", 1475 "\t\t\t'callback':func, \n", 1476 "\t\t\t'target':ele, \n", 1477 "\t\t\t'event': opt['type']\n", 1478 "\t\t};\n", 1479 "\t\t//Attach the function with the event\n", 1480 "\t\tif(ele.addEventListener) ele.addEventListener(opt['type'], func, false);\n", 1481 "\t\telse if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);\n", 1482 "\t\telse ele['on'+opt['type']] = func;\n", 1483 "\t},\n", 1484 "\n", 1485 "\t//Remove the shortcut - just specify the shortcut and I will remove the binding\n", 1486 "\t'remove':function(shortcut_combination) {\n", 1487 "\t\tshortcut_combination = shortcut_combination.toLowerCase();\n", 1488 "\t\tvar binding = this.all_shortcuts[shortcut_combination];\n", 1489 "\t\tdelete(this.all_shortcuts[shortcut_combination])\n", 1490 "\t\tif(!binding) return;\n", 1491 "\t\tvar type = binding['event'];\n", 1492 "\t\tvar ele = binding['target'];\n", 1493 "\t\tvar callback = binding['callback'];\n", 1494 "\n", 1495 "\t\tif(ele.detachEvent) ele.detachEvent('on'+type, callback);\n", 1496 "\t\telse if(ele.removeEventListener) ele.removeEventListener(type, callback, false);\n", 1497 "\t\telse ele['on'+type] = false;\n", 1498 "\t}\n", 1499 "}\n", 1500 "\n", 1501 "shortcut.add(\"Alt+Left\",function() {\n", 1502 "\tvar event = new Event('click');\n", 1503 "\tif (settingsShown){\n", 1504 "\t\tdocument.getElementById('hideSettingsButton_0').dispatchEvent(event);\n", 1505 "\t} else {\n", 1506 "\t\tdocument.getElementById('showSettingsButton_0').dispatchEvent(event);\n", 1507 "\t}\n", 1508 "});\n", 1509 "\n", 1510 "\n", 1511 "// COMMON_CODE_BLOCK_END\n", 1512 "\n", 1513 "});});\n", 1514 " </script>\n", 1515 " </body>\n", 1516 "</html>" 1517 ] 1518 }, 1519 "metadata": {}, 1520 "output_type": "display_data" 1521 }, 1522 { 1523 "data": { 1524 "text/html": [ 1525 "<details><summary><pre style=\"display:inline\"><small>Click here for additional output</small></pre></summary>\n", 1526 "<pre>\n", 1527 "polymake: used package threejs\n", 1528 " Three.js is a lightweight cross-browser JavaScript library/API used to create and display animated 3D computer graphics on a Web browser.\n", 1529 " See http://github.com/mrdoob for the source code.\n", 1530 "\n", 1531 "</pre>\n", 1532 "</details>\n" 1533 ] 1534 }, 1535 "metadata": {}, 1536 "output_type": "display_data" 1537 } 1538 ], 1539 "source": [ 1540 "$rs->VISUAL;" 1541 ] 1542 }, 1543 { 1544 "cell_type": "markdown", 1545 "metadata": {}, 1546 "source": [ 1547 "Now we will create yet another new polytope by scaling our random sphere by a factor lambda. (Otherwise there are rather few integral points contained in it.)\n", 1548 "\n", 1549 "To this end, we have to multiply every coordinate (except for the homogenising 1 in the beginning) of every vertex by lamda. Then we can create a new polytope by specifying its vertices.\n" 1550 ] 1551 }, 1552 { 1553 "cell_type": "code", 1554 "execution_count": 9, 1555 "metadata": {}, 1556 "outputs": [], 1557 "source": [ 1558 "$lambda=2;" 1559 ] 1560 }, 1561 { 1562 "cell_type": "markdown", 1563 "metadata": {}, 1564 "source": [ 1565 " \n" 1566 ] 1567 }, 1568 { 1569 "cell_type": "code", 1570 "execution_count": 10, 1571 "metadata": {}, 1572 "outputs": [], 1573 "source": [ 1574 "$s=new Matrix<Rational>([[1,0,0,0],[0,$lambda,0,0],[0,0,$lambda,0],[0,0,0,$lambda]]);" 1575 ] 1576 }, 1577 { 1578 "cell_type": "markdown", 1579 "metadata": {}, 1580 "source": [ 1581 " \n" 1582 ] 1583 }, 1584 { 1585 "cell_type": "code", 1586 "execution_count": 11, 1587 "metadata": {}, 1588 "outputs": [ 1589 { 1590 "data": { 1591 "text/plain": [ 1592 "1 0 0 0\n", 1593 "0 2 0 0\n", 1594 "0 0 2 0\n", 1595 "0 0 0 2\n" 1596 ] 1597 }, 1598 "execution_count": 11, 1599 "metadata": {}, 1600 "output_type": "execute_result" 1601 } 1602 ], 1603 "source": [ 1604 "print $s;" 1605 ] 1606 }, 1607 { 1608 "cell_type": "code", 1609 "execution_count": 12, 1610 "metadata": {}, 1611 "outputs": [], 1612 "source": [ 1613 "$scaled_rs=new Polytope<Rational>(VERTICES=>($rs->VERTICES * $s), LINEALITY_SPACE=>[]);" 1614 ] 1615 }, 1616 { 1617 "cell_type": "markdown", 1618 "metadata": {}, 1619 "source": [ 1620 "\n", 1621 "\n", 1622 "`polymake` can visualise the polytope together with its lattice points:\n", 1623 "\n", 1624 " \n" 1625 ] 1626 }, 1627 { 1628 "cell_type": "code", 1629 "execution_count": 13, 1630 "metadata": {}, 1631 "outputs": [ 1632 { 1633 "data": { 1634 "text/html": [ 1635 "<!--\n", 1636 "polymake for knusper\n", 1637 "Thu Aug 27 11:38:20 2020\n", 1638 "scaled_rs\n", 1639 "-->\n", 1640 "\n", 1641 "\n", 1642 "<html>\n", 1643 " <head>\n", 1644 " <meta charset=utf-8>\n", 1645 " <title>scaled_rs</title>\n", 1646 " <style>\n", 1647 "/*\n", 1648 "// COMMON_CODE_BLOCK_BEGIN\n", 1649 "*/\n", 1650 " html {overflow: scroll;}\n", 1651 " strong{font-size: 18px;}\n", 1652 " canvas { z-index: 8; }\n", 1653 " input[type='radio'] {margin-left:0;}\n", 1654 " input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;}\n", 1655 " .group{padding-bottom: 15px;}\n", 1656 " .settings * {z-index: 11; }\n", 1657 " .settings{z-index: 10; font-family: Arial, Helvetica, sans-serif; margin-left: 30px; visibility: hidden; width: 14em; height: 96%; border: solid 1px silver; padding: 2px; overflow-y: scroll; box-sizing: border-box; background-color: white; position: absolute;}\n", 1658 " .indented{margin-left: 20px; margin-top: 10px; padding-bottom: 0px;} \n", 1659 " .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;}\n", 1660 " .showSettingsButton{visibility: visible; z-index: 12; position: absolute }\n", 1661 " .hideSettingsButton{visibility: hidden; z-index: 12; position: absolute; opacity: 0.5}\n", 1662 " button{margin-left: 0; margin-top: 10px}\n", 1663 " img{cursor: pointer;}\n", 1664 " .suboption{padding-top: 15px;}\n", 1665 " #model79422509120 { width: 100%; height: 100%; }\n", 1666 " .threejs_container { width: 100%; height: 75vh;}\n", 1667 " .settings{max-height: 74vh} \n", 1668 " input[type=range] {\n", 1669 " -webkit-appearance: none;\n", 1670 " padding:0; \n", 1671 " width:90%; \n", 1672 " margin-left: auto;\n", 1673 " margin-right: auto;\n", 1674 " margin-top: 15px;\n", 1675 " margin-bottom: 15px;\n", 1676 " display: block;\t\n", 1677 " }\n", 1678 " input[type=range]:focus {\n", 1679 " outline: none;\n", 1680 " }\n", 1681 " input[type=range]::-webkit-slider-runnable-track {\n", 1682 " height: 4px;\n", 1683 " cursor: pointer;\n", 1684 " animate: 0.2s;\n", 1685 " box-shadow: 0px 0px 0px #000000;\n", 1686 " background: #E3E3E3;\n", 1687 " border-radius: 0px;\n", 1688 " border: 0px solid #000000;\n", 1689 " }\n", 1690 " input[type=range]::-webkit-slider-thumb {\n", 1691 " box-shadow: 1px 1px 2px #B8B8B8;\n", 1692 " border: 1px solid #ABABAB;\n", 1693 " height: 13px;\n", 1694 " width: 25px;\n", 1695 " border-radius: 20px;\n", 1696 " background: #E0E0E0;\n", 1697 " cursor: pointer;\n", 1698 " -webkit-appearance: none;\n", 1699 " margin-top: -5px;\n", 1700 " }\n", 1701 " input[type=range]:focus::-webkit-slider-runnable-track {\n", 1702 " background: #E3E3E3;\n", 1703 " }\n", 1704 " input[type=range]::-moz-range-track {\n", 1705 " height: 4px;\n", 1706 " cursor: pointer;\n", 1707 " animate: 0.2s;\n", 1708 " box-shadow: 0px 0px 0px #000000;\n", 1709 " background: #E3E3E3;\n", 1710 " border-radius: 0px;\n", 1711 " border: 0px solid #000000;\n", 1712 " }\n", 1713 " input[type=range]::-moz-range-thumb {\n", 1714 " box-shadow: 1px 1px 2px #B8B8B8;\n", 1715 " border: 1px solid #ABABAB;\n", 1716 " height: 13px;\n", 1717 " width: 25px;\n", 1718 " border-radius: 20px;\n", 1719 " background: #E0E0E0;\n", 1720 " cursor: pointer;\n", 1721 " }\n", 1722 " input[type=range]::-ms-track {\n", 1723 " height: 4px;\n", 1724 " cursor: pointer;\n", 1725 " animate: 0.2s;\n", 1726 " background: transparent;\n", 1727 " border-color: transparent;\n", 1728 " color: transparent;\n", 1729 " }\n", 1730 " input[type=range]::-ms-fill-lower {\n", 1731 " background: #E3E3E3;\n", 1732 " border: 0px solid #000000;\n", 1733 " border-radius: 0px;\n", 1734 " box-shadow: 0px 0px 0px #000000;\n", 1735 " }\n", 1736 " input[type=range]::-ms-fill-upper {\n", 1737 " background: #E3E3E3;\n", 1738 " border: 0px solid #000000;\n", 1739 " border-radius: 0px;\n", 1740 " box-shadow: 0px 0px 0px #000000;\n", 1741 " }\n", 1742 " input[type=range]::-ms-thumb {\n", 1743 " box-shadow: 1px 1px 2px #B8B8B8;\n", 1744 " border: 1px solid #ABABAB;\n", 1745 " height: 13px;\n", 1746 " width: 25px;\n", 1747 " border-radius: 20px;\n", 1748 " background: #E0E0E0;\n", 1749 " cursor: pointer;\n", 1750 " }\n", 1751 " input[type=range]:focus::-ms-fill-lower {\n", 1752 " background: #E3E3E3;\n", 1753 " }\n", 1754 " input[type=range]:focus::-ms-fill-upper {\n", 1755 " background: #E3E3E3;\n", 1756 " }\n", 1757 "/*\n", 1758 "// COMMON_CODE_BLOCK_END\n", 1759 "*/\n", 1760 "\t\t</style>\n", 1761 " </head>\n", 1762 "<body>\n", 1763 " <div class='threejs_container'>\n", 1764 "\t\t<div id='settings_1' class='settings'>\n", 1765 "\t\t\t<div class=group id='explode_1'>\n", 1766 "\t\t\t\t<strong>Explode</strong>\n", 1767 "\t\t\t\t<input id='explodeRange_1' type='range' min=0 max=6 step=0.01 value=0>\n", 1768 "\t\t\t\t<div class=indented><input id='explodeCheckbox_1' type='checkbox'>Automatic explosion</div>\n", 1769 "\t\t\t\t<div class=suboption>Exploding speed</div>\n", 1770 "\t\t\t\t<input id='explodingSpeedRange_1' type='range' min=0 max=0.5 step=0.001 value=0.05>\n", 1771 "\t\t\t</div>\n", 1772 "\t\n", 1773 "\t\t\t<div class=group id='transparency_1' class='transparency'>\n", 1774 "\t\t\t\t<strong>Transparency</strong>\n", 1775 "\t\t\t\t<input id='transparencyRange_1' type='range' min=0 max=1 step=0.01 value=0>\n", 1776 "\t\t\t</div>\n", 1777 "\t\t\t\n", 1778 "\t\t\t<div class=group id='rotation_1'>\n", 1779 "\t\t\t\t<strong>Rotation</strong>\n", 1780 "\t\t\t\t<div class=indented>\n", 1781 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationX_1'> x-axis</div>\n", 1782 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationY_1'> y-axis</div>\n", 1783 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationZ_1'> z-axis</div>\n", 1784 "\t\t\t\t\t<button id='resetButton_1'>Reset</button>\n", 1785 "\t\t\t\t</div>\n", 1786 "\n", 1787 "\t\t\t\t<div class=suboption>Rotation speed</div>\n", 1788 "\t\t\t\t<input id='rotationSpeedRange_1' type='range' min=0 max=5 step=0.01 value=2>\n", 1789 "\t\t\t</div>\n", 1790 "\n", 1791 "\n", 1792 "\t\t\t<div class=group id='display_1'>\n", 1793 "\t\t\t\t<strong>Display</strong>\n", 1794 "\t\t\t\t<div class=indented>\n", 1795 "\t\t\t\t\t<div id='shownObjectTypesList_1' class='shownObjectsList'></div>\n", 1796 "\t\t\t\t</div>\n", 1797 "\t\t\t\t<div class=suboption>Objects</div>\n", 1798 "\t\t\t\t<div class=indented>\n", 1799 "\t\t\t\t <div id='shownObjectsList_1' class='shownObjectsList'></div>\n", 1800 "\t\t\t\t</div>\n", 1801 "\t\t\t</div>\n", 1802 " \n", 1803 " <div class=group id='camera_1'>\n", 1804 " <strong>Camera</strong>\n", 1805 " <div class=indented>\n", 1806 " <form>\n", 1807 " <select id=\"cameraType_1\">\n", 1808 " <option value='perspective' selected> Perspective<br></option>\n", 1809 " <option value='orthographic' > Orthographic<br></option>\n", 1810 " </select>\n", 1811 " </form>\n", 1812 " </div>\n", 1813 " </div>\n", 1814 "\n", 1815 "\t\t\t<div class=group id='svg_1'>\n", 1816 "\t\t\t\t<strong>SVG</strong>\n", 1817 "\t\t\t\t<div class=indented>\n", 1818 "\t\t\t\t\t<form>\n", 1819 "\t\t\t\t\t\t<input type=\"radio\" name='screenshotMode' value='download' id='download_1' checked> Download<br>\n", 1820 "\t\t\t\t\t\t<input type=\"radio\" name='screenshotMode' value='tab' id='tab_1' > New tab<br>\n", 1821 "\t\t\t\t\t</form>\n", 1822 "\t\t\t\t\t<button id='takeScreenshot_1'>Screenshot</button>\n", 1823 "\t\t\t\t</div>\n", 1824 "\t\t\t</div>\n", 1825 "\n", 1826 "\t\t</div>\t<!-- end of settings -->\n", 1827 "\t\t<img id='hideSettingsButton_1' class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px\">\n", 1828 "\t\t<img id='showSettingsButton_1' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px\">\n", 1829 "<div id=\"model79422509120\"></div>\n", 1830 "</div>\n", 1831 " <script>\n", 1832 " requirejs.config({\n", 1833 " paths: {\n", 1834 " three: '/kernelspecs/polymake/three',\n", 1835 " TrackballControls: '/kernelspecs/polymake/TrackballControls',\n", 1836 " OrbitControls: '/kernelspecs/polymake/OrbitControls',\n", 1837 " Projector: '/kernelspecs/polymake/Projector',\n", 1838 " SVGRenderer: '/kernelspecs/polymake/SVGRenderer',\n", 1839 " WEBGL: '/kernelspecs/polymake/WebGL',\n", 1840 " },\n", 1841 " shim: {\n", 1842 " 'three': { exports: 'THREE'},\n", 1843 " 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' },\n", 1844 " 'WEBGL': { deps: [ 'three' ], exports: 'THREE.WEBGL' },\n", 1845 " 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' },\n", 1846 " 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' },\n", 1847 " 'OrbitControls': { deps: [ 'three' ], exports: 'THREE.OrbitControls' },\n", 1848 " }\n", 1849 " });\n", 1850 " \n", 1851 " require(['three'],function(THREE){\n", 1852 " window.THREE = THREE;\n", 1853 " require(['TrackballControls', 'OrbitControls', 'Projector', 'SVGRenderer', 'WEBGL'],\n", 1854 " function(TrackballControls, OrbitControls, Projector, SVGRenderer, WEBGL) {\n", 1855 " THREE.TrackballControls = TrackballControls;\n", 1856 " THREE.OrbitControls = OrbitControls;\n", 1857 " THREE.Projector = Projector;\n", 1858 " THREE.SVGRenderer = SVGRenderer;\n", 1859 " THREE.WEBGL = WEBGL;\n", 1860 "\n", 1861 "// COMMON_CODE_BLOCK_BEGIN\n", 1862 "\n", 1863 "const intervalLength = 25; // for automatic animations\n", 1864 "const explodableModel = true; \n", 1865 "const modelContains = { points: false, pointlabels: false, lines: false, edgelabels: false, faces: false, arrowheads: false };\n", 1866 "const foldables = [];\n", 1867 "\n", 1868 "var three = document.getElementById(\"model79422509120\");\n", 1869 "var scene = new THREE.Scene();\n", 1870 "var renderer = new THREE.WebGLRenderer( { antialias: true } );\n", 1871 "var svgRenderer = new THREE.SVGRenderer( { antialias: true } );\n", 1872 "renderer.setPixelRatio( window.devicePixelRatio );\n", 1873 "renderer.setClearColor(0xFFFFFF, 1);\n", 1874 "svgRenderer.setClearColor(0xFFFFFF, 1);\n", 1875 "three.appendChild(renderer.domElement);\n", 1876 "\n", 1877 "var frustumSize = 4;\n", 1878 "var cameras = [new THREE.PerspectiveCamera(75, 1, 0.1, 1000), new THREE.OrthographicCamera()];\n", 1879 "cameras.forEach(function(cam) {\n", 1880 " cam.position.set(0, 0, 5);\n", 1881 " cam.lookAt(0, 0, 0); \n", 1882 " cam.up.set(0, 1, 0); \n", 1883 "});\n", 1884 "var controls = [new THREE.TrackballControls(cameras[0], three), new THREE.OrbitControls(cameras[1], three)];\n", 1885 "var camera, control;\n", 1886 "\n", 1887 "controls[0].zoomSpeed = 0.2;\n", 1888 "controls[0].rotateSpeed = 4;\n", 1889 "\n", 1890 "\n", 1891 "// class to allow move points together with labels and spheres\n", 1892 "var PMPoint = function (x,y,z) {\n", 1893 " this.vector = new THREE.Vector3(x,y,z);\n", 1894 " this.sprite = null;\n", 1895 " this.sphere = null;\n", 1896 "}\n", 1897 "PMPoint.prototype.addLabel = function(labelsprite) {\n", 1898 " this.sprite = labelsprite;\n", 1899 " this.sprite.position.copy(this.vector);\n", 1900 "}\n", 1901 "PMPoint.prototype.addSphere = function(spheremesh) {\n", 1902 " this.sphere = spheremesh;\n", 1903 " this.sphere.position.copy(this.vector);\n", 1904 "}\n", 1905 "PMPoint.prototype.set = function(x,y,z) {\n", 1906 " this.vector.set(x,y,z);\n", 1907 " if (this.sprite) {\n", 1908 " this.sprite.position.copy(this.vector);\n", 1909 " }\n", 1910 " if (this.sphere) {\n", 1911 " this.sphere.position.copy(this.vector);\n", 1912 " }\n", 1913 "}\n", 1914 "PMPoint.prototype.radius = function() {\n", 1915 " if (this.sphere) {\n", 1916 " return this.sphere.geometry.parameters.radius;\n", 1917 " } else {\n", 1918 " return 0;\n", 1919 " }\n", 1920 "};\n", 1921 "// select the target node\n", 1922 "var target = document.querySelector('#model79422509120');\n", 1923 "\n", 1924 "// create an observer instance\n", 1925 "var observer = new MutationObserver(function(mutations) {\n", 1926 " mutations.forEach(function(mutation) {\n", 1927 " if (mutation.removedNodes && mutation.removedNodes.length > 0) {\n", 1928 " cancelAnimationFrame(renderId);\n", 1929 " observer.disconnect();\n", 1930 " console.log(\"cancelled frame \"+renderId);\n", 1931 " }\n", 1932 " });\n", 1933 "});\n", 1934 "\n", 1935 "// configuration of the observer:\n", 1936 "var config = { childList: true, characterData: true }\n", 1937 "\n", 1938 "// pass in the target node, as well as the observer options\n", 1939 "while (target) {\n", 1940 " if (target.className==\"output\") {\n", 1941 " observer.observe(target, config);\n", 1942 " break;\n", 1943 " }\n", 1944 " target = target.parentNode;\n", 1945 "}\n", 1946 "\n", 1947 "// COMMON_CODE_BLOCK_END\n", 1948 "\n", 1949 "var obj0 = new THREE.Object3D();\n", 1950 "obj0.name = \"scaled_rs\";\n", 1951 "obj0.userData.explodable = 1;\n", 1952 "obj0.userData.points = [];\n", 1953 "obj0.userData.points.push(new PMPoint(-1.00909, -0.491753, 1.65527));\n", 1954 "obj0.userData.points.push(new PMPoint(-0.342494, -1.96619, 0.129558));\n", 1955 "obj0.userData.points.push(new PMPoint(0.79433, -1.0065, 1.53492));\n", 1956 "obj0.userData.points.push(new PMPoint(-1.63718, -1.11003, -0.29574));\n", 1957 "obj0.userData.points.push(new PMPoint(-1.26888, -0.325036, -1.51139));\n", 1958 "obj0.userData.points.push(new PMPoint(-0.511749, 1.81794, -0.658173));\n", 1959 "obj0.userData.points.push(new PMPoint(-0.544735, 0.0656413, -1.92327));\n", 1960 "obj0.userData.points.push(new PMPoint(1.75488, 0.756399, 0.590139));\n", 1961 "obj0.userData.points.push(new PMPoint(0.862733, 0.812798, -1.61092));\n", 1962 "obj0.userData.points.push(new PMPoint(-1.95588, 0.316236, 0.272963));\n", 1963 "obj0.userData.points.push(new PMPoint(0.532226, 0.131617, 1.92339));\n", 1964 "obj0.userData.points.push(new PMPoint(-1.10816, -0.781368, -1.47019));\n", 1965 "obj0.userData.points.push(new PMPoint(1.59181, 0.0667565, -1.209));\n", 1966 "obj0.userData.points.push(new PMPoint(0.161173, 1.96236, 0.350941));\n", 1967 "obj0.userData.points.push(new PMPoint(-1.8806, -0.668687, 0.127224));\n", 1968 "obj0.userData.points.push(new PMPoint(-0.409209, 0.223782, 1.94486));\n", 1969 "obj0.userData.points.push(new PMPoint(-0.892021, -0.948635, -1.51802));\n", 1970 "obj0.userData.points.push(new PMPoint(-1.89858, 0.431969, -0.456932));\n", 1971 "obj0.userData.points.push(new PMPoint(-1.16651, -0.164456, -1.61623));\n", 1972 "obj0.userData.points.push(new PMPoint(0.333079, 0.125055, 1.9681));\n", 1973 "\n", 1974 "obj0.userData.edgeindices = [0, 1, 0, 2, 1, 2, 1, 3, 3, 4, 5, 6, 2, 7, 5, 8, 6, 8, 7, 8, 0, 9, 5, 9, 2, 10, 7, 10, 3, 11, 4, 11, 1, 12, 2, 12, 6, 12, 7, 12, 8, 12, 5, 13, 7, 13, 8, 13, 9, 13, 10, 13, 0, 14, 1, 14, 3, 14, 9, 14, 0, 15, 9, 15, 13, 15, 1, 16, 3, 16, 6, 16, 11, 16, 12, 16, 3, 17, 4, 17, 5, 17, 9, 17, 14, 17, 4, 18, 5, 18, 6, 18, 11, 18, 16, 18, 17, 18, 0, 19, 2, 19, 10, 19, 13, 19, 15, 19];\n", 1975 " <!-- Edge style -->\n", 1976 "obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, depthTest: true, linewidth: 1.5, transparent: false } );\n", 1977 "obj0.userData.facets = [[12, 6, 8], [16, 6, 12], [12, 1, 16], [12, 2, 1], [2, 10, 19], [2, 19, 0], [1, 2, 0], [13, 15, 19], [15, 0, 19], [16, 1, 3], [1, 0, 14], [1, 14, 3], [5, 6, 18], [5, 18, 17], [5, 17, 9], [11, 16, 3], [18, 16, 11], [18, 11, 4], [11, 3, 4], [17, 4, 3], [17, 3, 14], [9, 17, 14], [17, 18, 4], [9, 14, 0], [18, 6, 16], [15, 9, 0], [13, 5, 9], [13, 9, 15], [10, 13, 19], [8, 6, 5], [8, 5, 13], [7, 8, 13], [7, 13, 10], [2, 7, 10], [12, 7, 2], [12, 8, 7]];\n", 1978 "init_object(obj0);\n", 1979 "scene.add(obj0);\n", 1980 "\n", 1981 "var obj1 = new THREE.Object3D();\n", 1982 "obj1.name = \"Lattice points and vertices of scaled_rs\";\n", 1983 "obj1.userData.explodable = 1;\n", 1984 "obj1.userData.points = [];\n", 1985 "obj1.userData.points.push(new PMPoint(-1, -1, -1));\n", 1986 "obj1.userData.points.push(new PMPoint(-1, -1, 0));\n", 1987 "obj1.userData.points.push(new PMPoint(-1, 0, -1));\n", 1988 "obj1.userData.points.push(new PMPoint(-1, 0, 0));\n", 1989 "obj1.userData.points.push(new PMPoint(-1, 0, 1));\n", 1990 "obj1.userData.points.push(new PMPoint(-1, 1, 0));\n", 1991 "obj1.userData.points.push(new PMPoint(0, -1, 0));\n", 1992 "obj1.userData.points.push(new PMPoint(0, -1, 1));\n", 1993 "obj1.userData.points.push(new PMPoint(0, 0, -1));\n", 1994 "obj1.userData.points.push(new PMPoint(0, 0, 0));\n", 1995 "obj1.userData.points.push(new PMPoint(0, 0, 1));\n", 1996 "obj1.userData.points.push(new PMPoint(0, 1, -1));\n", 1997 "obj1.userData.points.push(new PMPoint(0, 1, 0));\n", 1998 "obj1.userData.points.push(new PMPoint(0, 1, 1));\n", 1999 "obj1.userData.points.push(new PMPoint(1, 0, -1));\n", 2000 "obj1.userData.points.push(new PMPoint(1, 0, 0));\n", 2001 "obj1.userData.points.push(new PMPoint(1, 0, 1));\n", 2002 "obj1.userData.points.push(new PMPoint(1, 1, 0));\n", 2003 "obj1.userData.points.push(new PMPoint(-1.00909, -0.491753, 1.65527));\n", 2004 "obj1.userData.points.push(new PMPoint(-0.342494, -1.96619, 0.129558));\n", 2005 "obj1.userData.points.push(new PMPoint(0.79433, -1.0065, 1.53492));\n", 2006 "obj1.userData.points.push(new PMPoint(-1.63718, -1.11003, -0.29574));\n", 2007 "obj1.userData.points.push(new PMPoint(-1.26888, -0.325036, -1.51139));\n", 2008 "obj1.userData.points.push(new PMPoint(-0.511749, 1.81794, -0.658173));\n", 2009 "obj1.userData.points.push(new PMPoint(-0.544735, 0.0656413, -1.92327));\n", 2010 "obj1.userData.points.push(new PMPoint(1.75488, 0.756399, 0.590139));\n", 2011 "obj1.userData.points.push(new PMPoint(0.862733, 0.812798, -1.61092));\n", 2012 "obj1.userData.points.push(new PMPoint(-1.95588, 0.316236, 0.272963));\n", 2013 "obj1.userData.points.push(new PMPoint(0.532226, 0.131617, 1.92339));\n", 2014 "obj1.userData.points.push(new PMPoint(-1.10816, -0.781368, -1.47019));\n", 2015 "obj1.userData.points.push(new PMPoint(1.59181, 0.0667565, -1.209));\n", 2016 "obj1.userData.points.push(new PMPoint(0.161173, 1.96236, 0.350941));\n", 2017 "obj1.userData.points.push(new PMPoint(-1.8806, -0.668687, 0.127224));\n", 2018 "obj1.userData.points.push(new PMPoint(-0.409209, 0.223782, 1.94486));\n", 2019 "obj1.userData.points.push(new PMPoint(-0.892021, -0.948635, -1.51802));\n", 2020 "obj1.userData.points.push(new PMPoint(-1.89858, 0.431969, -0.456932));\n", 2021 "obj1.userData.points.push(new PMPoint(-1.16651, -0.164456, -1.61623));\n", 2022 "obj1.userData.points.push(new PMPoint(0.333079, 0.125055, 1.9681));\n", 2023 "\n", 2024 "obj1.userData.pointradii = 0.02;\n", 2025 " <!-- Vertex style -->\n", 2026 "obj1.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2027 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2028 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2029 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2030 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2031 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2032 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2033 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2034 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2035 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2036 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2037 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2038 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2039 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2040 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2041 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2042 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2043 "new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 2044 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2045 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2046 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2047 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2048 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2049 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2050 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2051 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2052 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2053 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2054 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2055 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2056 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2057 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2058 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2059 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2060 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2061 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2062 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 2063 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } )];\n", 2064 "init_object(obj1);\n", 2065 "scene.add(obj1);\n", 2066 "\n", 2067 "// COMMON_CODE_BLOCK_BEGIN\n", 2068 "function textSpriteMaterial(message, parameters) {\n", 2069 " if ( parameters === undefined ) parameters = {};\n", 2070 " var fontface = \"Helvetica\";\n", 2071 " var fontsize = parameters.hasOwnProperty(\"fontsize\") ? parameters[\"fontsize\"] : 15;\n", 2072 " fontsize = fontsize*10;\n", 2073 " var lines = message.split('\\\\n');\n", 2074 " var size = 512;\n", 2075 " for(var i = 0; i<lines.length; i++){\n", 2076 " var tmp = lines[i].length;\n", 2077 " while(tmp*fontsize > size){\n", 2078 " fontsize--;\n", 2079 " }\n", 2080 " }\n", 2081 " \n", 2082 " var canvas = document.createElement('canvas');\n", 2083 " canvas.width = size;\n", 2084 " canvas.height = size;\n", 2085 " var context = canvas.getContext('2d');\n", 2086 " context.fillStyle = \"rgba(255, 255, 255, 0)\";\n", 2087 " context.fill();\n", 2088 " context.font = fontsize + \"px \" + fontface;\n", 2089 " \n", 2090 " // text color\n", 2091 " context.fillStyle = \"rgba(0, 0, 0, 1.0)\";\n", 2092 " for(var i = 0; i<lines.length; i++){\n", 2093 " context.fillText(lines[i], size/2, size/2+i*fontsize);\n", 2094 " }\n", 2095 " \n", 2096 " // canvas contents will be used for a texture\n", 2097 " var texture = new THREE.Texture(canvas);\n", 2098 " texture.needsUpdate = true;\n", 2099 " \n", 2100 " var spriteMaterial = new THREE.SpriteMaterial({map: texture, depthTest: true, depthWrite: false, polygonOffset: true, polygonOffsetFactor: -1, polygonOffsetUnits: 1 });\n", 2101 " return spriteMaterial;\n", 2102 "}\n", 2103 "\n", 2104 "\n", 2105 "// ---------------------- INITIALIZING OBJECTS--------------------------------------\n", 2106 "// ---------------------------------------------------------------------------------\n", 2107 "\n", 2108 "function init_object(obj) {\n", 2109 " if (obj.userData.hasOwnProperty(\"pointmaterial\")) {\n", 2110 " init_points(obj);\n", 2111 " modelContains.points = true;\n", 2112 " }\n", 2113 " if (obj.userData.hasOwnProperty(\"pointlabels\")) {\n", 2114 " init_pointlabels(obj);\n", 2115 " modelContains.pointlabels = true;\n", 2116 " }\n", 2117 " if (obj.userData.hasOwnProperty(\"edgematerial\")) {\n", 2118 " init_lines(obj);\n", 2119 " modelContains.lines = true;\n", 2120 " }\n", 2121 " if (obj.userData.hasOwnProperty(\"edgelabels\")) {\n", 2122 " init_edgelabels(obj);\n", 2123 " modelContains.edgelabels = true;\n", 2124 " }\n", 2125 " if (obj.userData.hasOwnProperty(\"arrowstyle\")) {\n", 2126 " init_arrowheads(obj);\n", 2127 " modelContains.arrowheads = true;\n", 2128 " }\n", 2129 " if (obj.userData.hasOwnProperty(\"facetmaterial\")) {\n", 2130 " init_faces(obj);\n", 2131 " modelContains.faces = true;\n", 2132 " }\n", 2133 "}\n", 2134 "\n", 2135 "function init_points(obj) {\n", 2136 " var pointgroup = new THREE.Group();\n", 2137 " pointgroup.name = \"points\";\n", 2138 " var points = obj.userData.points;\n", 2139 " var radii = obj.userData.pointradii;\n", 2140 " var materials = obj.userData.pointmaterial;\n", 2141 " var geometry,material;\n", 2142 " if (!Array.isArray(radii)) {\n", 2143 " geometry = new THREE.SphereBufferGeometry(radii); \n", 2144 " }\n", 2145 " if (!Array.isArray(materials)) {\n", 2146 " material = materials;\n", 2147 " }\n", 2148 " for (var i=0; i<points.length; i++) {\n", 2149 " var point = points[i];\n", 2150 " if (Array.isArray(radii)) {\n", 2151 " if (radii[i] == 0) {\n", 2152 " continue;\n", 2153 " }\n", 2154 " geometry = new THREE.SphereBufferGeometry(radii[i]); \n", 2155 " } \n", 2156 " if (Array.isArray(materials)) {\n", 2157 " material = materials[i]; \n", 2158 " } \n", 2159 " var sphere = new THREE.Mesh(geometry, material);\n", 2160 " point.addSphere(sphere);\n", 2161 " pointgroup.add(sphere);\n", 2162 " }\n", 2163 " obj.add(pointgroup);\n", 2164 "}\n", 2165 "\n", 2166 "function init_pointlabels(obj) {\n", 2167 " var points = obj.userData.points;\n", 2168 " var labels = obj.userData.pointlabels;\n", 2169 " var pointlabels = new THREE.Group();\n", 2170 " pointlabels.name = \"pointlabels\";\n", 2171 " if (Array.isArray(labels)) {\n", 2172 " for (var i=0; i<points.length; i++) {\n", 2173 " var point = points[i];\n", 2174 " var spriteMaterial = textSpriteMaterial( labels[i] );\n", 2175 "\t var sprite = new THREE.Sprite(spriteMaterial);\n", 2176 " point.addLabel(sprite);\n", 2177 " pointlabels.add(sprite);\n", 2178 " }\n", 2179 " } else {\n", 2180 " var spriteMaterial = textSpriteMaterial( labels );\n", 2181 " for (var i=0; i<points.length; i++) {\n", 2182 " var point = points[i];\n", 2183 "\t var sprite = new THREE.Sprite(spriteMaterial);\n", 2184 " point.addLabel(sprite);\n", 2185 " pointlabels.add(sprite);\n", 2186 " }\n", 2187 " }\n", 2188 " obj.add(pointlabels);\n", 2189 "}\n", 2190 "\n", 2191 "function init_lines(obj) {\n", 2192 " var edgeindices = obj.userData.edgeindices;\n", 2193 " var points = obj.userData.points;\n", 2194 " var materials = obj.userData.edgematerial;\n", 2195 " var geometry = new THREE.BufferGeometry();\n", 2196 " var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 );\n", 2197 " var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 );\n", 2198 " var geometry = new THREE.BufferGeometry();\n", 2199 " geometry.setAttribute('position', bufattr);\n", 2200 " if (Array.isArray(materials)) { \n", 2201 " for (var i=0; i<materials.length; i++) {\n", 2202 " geometry.addGroup(2*i,2,i);\n", 2203 " }\n", 2204 " }\n", 2205 " var lines = new THREE.LineSegments(geometry, materials);\n", 2206 " lines.name = \"lines\";\n", 2207 " obj.add(lines);\n", 2208 " updateEdgesPosition(obj);\n", 2209 "}\n", 2210 "\n", 2211 "function init_edgelabels(obj) {\n", 2212 " var points = obj.userData.points;\n", 2213 " var edgeindices = obj.userData.edgeindices;\n", 2214 " var labels = obj.userData.edgelabels;\n", 2215 " var edgelabels = new THREE.Group();\n", 2216 " edgelabels.name = \"edgelabels\";\n", 2217 " if (Array.isArray(labels)) {\n", 2218 " for (var i=0; i<edgeindices.length; i=i+2) {\n", 2219 " var point = points[i];\n", 2220 " var spriteMaterial = textSpriteMaterial( labels[i] );\n", 2221 " var sprite = new THREE.Sprite(spriteMaterial);\n", 2222 " sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[i]].vector,points[edgeindices[i+1]].vector).multiplyScalar(0.5));\n", 2223 " edgelabels.add(sprite);\n", 2224 " }\n", 2225 " } else {\n", 2226 " var spriteMaterial = textSpriteMaterial( labels );\n", 2227 " for (var i=0; i<points.length; i++) {\n", 2228 " var point = points[i];\n", 2229 " var sprite = new THREE.Sprite(spriteMaterial);\n", 2230 " sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[i]].vector,points[edgeindices[i+1]].vector).multiplyScalar(0.5));\n", 2231 " pointlabels.add(sprite);\n", 2232 " }\n", 2233 " }\n", 2234 " obj.add(edgelabels);\n", 2235 "}\n", 2236 "\n", 2237 "function init_arrowheads(obj) {\n", 2238 " var arrowheads = new THREE.Group();\n", 2239 " arrowheads.name = \"arrowheads\";\n", 2240 " var arrowstyle = obj.userData.arrowstyle;\n", 2241 " var edgeindices = obj.userData.edgeindices;\n", 2242 " var edgematerials = obj.userData.edgematerial;\n", 2243 " var points = obj.userData.points;\n", 2244 " var material;\n", 2245 " if (!Array.isArray(edgematerials)) {\n", 2246 " material = new THREE.MeshBasicMaterial( {color: edgematerials.color} );\n", 2247 " }\n", 2248 "\n", 2249 " for (var i=0; i<edgeindices.length; i=i+2) {\n", 2250 " var start = points[edgeindices[i]];\n", 2251 " var end = points[edgeindices[i+1]];\n", 2252 " var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius();\n", 2253 " if (dist <= 0) {\n", 2254 " continue;\n", 2255 " }\n", 2256 " var dir = new THREE.Vector3().subVectors(end.vector,start.vector);\n", 2257 " dir.normalize();\n", 2258 " var axis = new THREE.Vector3().set(dir.z,0,-dir.x);\n", 2259 " axis.normalize();\n", 2260 " var radians = Math.acos( dir.y );\n", 2261 " var radius = dist/25;\n", 2262 " var height = dist/5;\n", 2263 " var geometry = new THREE.ConeBufferGeometry(radius,height);\n", 2264 " var position = new THREE.Vector3().addVectors(start.vector,dir.clone().multiplyScalar(start.radius()+dist-height/2));\n", 2265 " if (Array.isArray(edgematerials)) {\n", 2266 " material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} );\n", 2267 " }\n", 2268 " var cone = new THREE.Mesh( geometry, material );\n", 2269 " cone.quaternion.setFromAxisAngle(axis,radians);;\n", 2270 " cone.position.copy(position);;\n", 2271 " arrowheads.add(cone);\n", 2272 " }\n", 2273 " obj.add(arrowheads);\n", 2274 "}\n", 2275 "\n", 2276 "function init_faces(obj) {\n", 2277 " var points = obj.userData.points;\n", 2278 " var facets = obj.userData.facets;\n", 2279 " obj.userData.triangleindices = [];\n", 2280 " for (var i=0; i<facets.length; i++) {\n", 2281 " facet = facets[i];\n", 2282 " for (var t=0; t<facet.length-2; t++) {\n", 2283 " obj.userData.triangleindices.push(facet[0],facet[t+1],facet[t+2]); \n", 2284 " }\n", 2285 " }\n", 2286 " var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 );\n", 2287 " var bufattr = new THREE.Float32BufferAttribute(bufarr,3);\n", 2288 " \n", 2289 " var materials = obj.userData.facetmaterial;\n", 2290 " var geometry = new THREE.BufferGeometry();\n", 2291 " geometry.setAttribute('position',bufattr);\n", 2292 " if (Array.isArray(materials)) {\n", 2293 " var tricount = 0;\n", 2294 " var facet;\n", 2295 " for (var i=0; i<facets.length; i++) {\n", 2296 " facet = facets[i];\n", 2297 " geometry.addGroup(tricount,(facet.length-2)*3,i);\n", 2298 " tricount += (facet.length-2)*3;\n", 2299 " }\n", 2300 " }\n", 2301 " var mesh = new THREE.Mesh(geometry, materials);\n", 2302 " mesh.name = \"faces\";\n", 2303 " obj.add(mesh); \n", 2304 " updateFacesPosition(obj);\n", 2305 "}\n", 2306 "// //INITIALIZING\n", 2307 "\n", 2308 "\n", 2309 "function updateFacesPosition(obj) {\n", 2310 " var points = obj.userData.points;\n", 2311 " var indices = obj.userData.triangleindices;\n", 2312 " var faces = obj.getObjectByName(\"faces\");\n", 2313 " var ba = faces.geometry.getAttribute(\"position\");\n", 2314 " for (var i=0; i<indices.length; i++) {\n", 2315 " ba.setXYZ(i, points[indices[i]].vector.x, points[indices[i]].vector.y ,points[indices[i]].vector.z); \n", 2316 " }\n", 2317 " faces.geometry.attributes.position.needsUpdate = true;\n", 2318 " \n", 2319 "}\n", 2320 "\n", 2321 "function updateEdgesPosition(obj) {\n", 2322 " var points = obj.userData.points;\n", 2323 " var indices = obj.userData.edgeindices;\n", 2324 " var lines = obj.getObjectByName(\"lines\");\n", 2325 " var ba = lines.geometry.getAttribute(\"position\"); \n", 2326 " for (var i=0; i<indices.length; i++) {\n", 2327 " ba.setXYZ(i, points[indices[i]].vector.x, points[indices[i]].vector.y ,points[indices[i]].vector.z); \n", 2328 " }\n", 2329 " lines.geometry.attributes.position.needsUpdate = true;\n", 2330 "}\n", 2331 "\n", 2332 "function onWindowResize() {\n", 2333 " renderer.setSize( three.clientWidth, three.clientHeight );\n", 2334 " svgRenderer.setSize( three.clientWidth, three.clientHeight );\n", 2335 " updateCamera();\n", 2336 "}\n", 2337 "\n", 2338 "function updateCamera() {\n", 2339 " var width = three.clientWidth;\n", 2340 " var height = three.clientHeight;\n", 2341 " var aspect = width / height;\n", 2342 " if (camera.type == \"OrthographicCamera\") {\n", 2343 " camera.left = frustumSize * aspect / - 2;\n", 2344 " camera.right = frustumSize * aspect / 2;\n", 2345 " camera.top = frustumSize / 2;\n", 2346 " camera.bottom = - frustumSize / 2;\n", 2347 " } else if (camera.type == \"PerspectiveCamera\") {\n", 2348 " camera.aspect = aspect;\n", 2349 " }\n", 2350 " camera.updateProjectionMatrix();\n", 2351 "}\n", 2352 "\n", 2353 "function changeCamera(event) {\n", 2354 " var selindex = event.currentTarget.selectedIndex;\n", 2355 " camera = cameras[selindex];\n", 2356 " control = controls[selindex];\n", 2357 " control.enabled = true; \n", 2358 " for (var i=0; i<controls.length; i++) {\n", 2359 " if (i!=selindex) {\n", 2360 " controls[i].enabled = false;\n", 2361 " }\n", 2362 " }\n", 2363 " updateCamera();\n", 2364 "}\n", 2365 "\n", 2366 "var camtypenode = document.getElementById('cameraType_1');\n", 2367 "camtypenode.onchange = changeCamera;\n", 2368 "camtypenode.dispatchEvent(new Event('change'));\n", 2369 "\n", 2370 "onWindowResize();\n", 2371 "window.addEventListener('resize', onWindowResize);\t\n", 2372 "\n", 2373 "\n", 2374 "var xRotationEnabled = false;\n", 2375 "var yRotationEnabled = false;\n", 2376 "var zRotationEnabled = false;\n", 2377 "var rotationSpeedFactor = 1;\n", 2378 "var settingsShown = false;\n", 2379 "var labelsShown = true;\n", 2380 "var intervals = [];\n", 2381 "var timeouts = [];\n", 2382 "var explodingSpeed = 0.05;\n", 2383 "var explodeScale = 0;\n", 2384 "var XMLS = new XMLSerializer();\n", 2385 "var svgElement;\n", 2386 "var renderId;\n", 2387 "\n", 2388 "var render = function () {\n", 2389 "\n", 2390 "\trenderId = requestAnimationFrame(render);\n", 2391 "\n", 2392 "//\tcomment in for automatic explosion\n", 2393 "//\texplode(updateFactor());\n", 2394 "\n", 2395 " var phi = 0.02 * rotationSpeedFactor;\n", 2396 "\n", 2397 " if (xRotationEnabled) {\n", 2398 " scene.rotation.x += phi;\n", 2399 " }\n", 2400 " if (yRotationEnabled) {\n", 2401 " scene.rotation.y += phi;\n", 2402 " }\n", 2403 " if (zRotationEnabled) {\n", 2404 " scene.rotation.z += phi;\n", 2405 " }\n", 2406 "\n", 2407 " control.update();\n", 2408 " renderer.render(scene, camera);\n", 2409 "};\n", 2410 "\n", 2411 "if ( THREE.WEBGL.isWebGLAvailable() ) {\n", 2412 "\trender();\n", 2413 "} else {\n", 2414 "\tvar warning = WEBGL.getWebGLErrorMessage();\n", 2415 "\tthree.appendChild( warning );\n", 2416 "}\n", 2417 " \n", 2418 "function changeTransparency() {\n", 2419 " var opacity = 1-Number(event.currentTarget.value);\n", 2420 " for (var i=0; i<scene.children.length; i++) {\n", 2421 " child = scene.children[i];\n", 2422 " if ( child.userData.hasOwnProperty(\"facetmaterial\") ) {\n", 2423 " if (Array.isArray(child.userData.facetmaterial)) {\n", 2424 " for (var j=0; j<child.userData.facetmaterial.length; j++) {\n", 2425 " child.userData.facetmaterial[j].opacity = opacity;\n", 2426 " }\n", 2427 " } else {\n", 2428 " child.userData.facetmaterial.opacity = opacity;\n", 2429 " } \n", 2430 " }\n", 2431 " }\n", 2432 "}\n", 2433 "\n", 2434 "function changeRotationX(event){\n", 2435 " xRotationEnabled = event.currentTarget.checked;\n", 2436 "}\t\n", 2437 "\n", 2438 "function changeRotationY(event){\n", 2439 " yRotationEnabled = event.currentTarget.checked;\n", 2440 "}\t\n", 2441 "\n", 2442 "function changeRotationZ(event){\n", 2443 " zRotationEnabled = event.currentTarget.checked;\n", 2444 "}\t\n", 2445 "\n", 2446 "\n", 2447 "function changeRotationSpeedFactor(event){\n", 2448 " rotationSpeedFactor = Number(event.currentTarget.value);\n", 2449 "}\n", 2450 "\n", 2451 "function resetScene(){\n", 2452 " scene.rotation.set(0,0,0);\n", 2453 " camera.position.set(0,0,5);\n", 2454 " camera.up.set(0,1,0);\n", 2455 "}\n", 2456 "\n", 2457 "function showSettings(event){\n", 2458 " document.getElementById('settings_1').style.visibility = 'visible';\n", 2459 " document.getElementById('showSettingsButton_1').style.visibility = 'hidden';\n", 2460 " document.getElementById('hideSettingsButton_1').style.visibility = 'visible';\n", 2461 " settingsShown = true;\n", 2462 "}\n", 2463 "\n", 2464 "function hideSettings(event){\n", 2465 " document.getElementById('settings_1').style.visibility = 'hidden';\n", 2466 " document.getElementById('showSettingsButton_1').style.visibility = 'visible';\n", 2467 " document.getElementById('hideSettingsButton_1').style.visibility = 'hidden';\n", 2468 " settingsShown = false;\n", 2469 "}\n", 2470 "\n", 2471 "\n", 2472 "\n", 2473 "var pos = 150* Math.PI;\n", 2474 "\n", 2475 "function updateFactor() {\n", 2476 " pos++;\n", 2477 " return Math.sin(.01*pos)+1;\n", 2478 "}\n", 2479 "\n", 2480 "// ------------------------ FOLDING ------------------------------------------------\n", 2481 "// ---------------------------------------------------------------------------------\n", 2482 "// rotate point p around axis defined by points p1 and p2 by given angle\n", 2483 "function rotate(p, p1, p2, angle ){ \n", 2484 " angle = -angle;\n", 2485 " var x = p.x, y = p.y, z = p.z, \n", 2486 " a = p1.x, b = p1.y, c = p1.z, \n", 2487 " u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z;\n", 2488 " var result = [];\n", 2489 " var L = u*u + v*v + w*w;\n", 2490 " var sqrt = Math.sqrt;\n", 2491 " var cos = Math.cos;\n", 2492 " var sin = Math.sin;\n", 2493 "\n", 2494 " result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/L;\n", 2495 " result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/L;\n", 2496 " result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/L;\n", 2497 "\n", 2498 " return result;\n", 2499 "}\n", 2500 "\n", 2501 "var fold = function(event){\n", 2502 " var obj = foldables[Number(event.currentTarget.name)];\n", 2503 " var foldvalue = Number(event.currentTarget.value);\n", 2504 " var scale = foldvalue - obj.userData.oldscale;\n", 2505 "\n", 2506 " for (var j=0; j<obj.userData.axes.length; j++) {\n", 2507 " rotateVertices(obj, j, scale);\n", 2508 " }\n", 2509 " update(obj);\n", 2510 " obj.userData.oldscale += scale;\n", 2511 " lookAtBarycenter(obj);\n", 2512 "}\n", 2513 "\n", 2514 "function lookAtBarycenter(obj){\n", 2515 " control.target = barycenter(obj);\n", 2516 "}\n", 2517 "\n", 2518 "function barycenter(obj) {\n", 2519 " var center = new THREE.Vector3(0,0,0);\n", 2520 " var points = obj.userData.points;\n", 2521 " for (var i=0; i<points.length; i++){\n", 2522 " center.add(points[i].vector);\n", 2523 " }\n", 2524 " center.divideScalar(points.length);\n", 2525 " return center;\n", 2526 "}\n", 2527 "\n", 2528 "function rotateVertices(obj, edge, scale) {\n", 2529 " var axes = obj.userData.axes;\n", 2530 " var subtrees = obj.userData.subtrees;\n", 2531 " var points = obj.userData.points;\n", 2532 " var angles = obj.userData.angles;\n", 2533 " if (edge < axes.length){\n", 2534 " for (var j=0; j<subtrees[edge].length; j++){\n", 2535 " var rotP = rotate(points[subtrees[edge][j]].vector, points[axes[edge][0]].vector,points[axes[edge][1]].vector, scale * (Math.PI - angles[edge]));\n", 2536 " points[subtrees[edge][j]].set(rotP[0],rotP[1],rotP[2]);\n", 2537 " }\n", 2538 " }\n", 2539 "}\n", 2540 "\n", 2541 "function update(obj) {\n", 2542 " updateFacesPosition(obj);\n", 2543 " updateEdgesPosition(obj);\n", 2544 "}\n", 2545 "\n", 2546 "if (foldables.length) {\n", 2547 " var settings = document.getElementById('settings_1');\n", 2548 " var foldDiv = document.createElement('div');\n", 2549 " foldDiv.id = 'fold_1';\n", 2550 " var title = document.createElement('strong');\n", 2551 " title.innerHTML = 'Fold';\n", 2552 " foldDiv.appendChild(title);\n", 2553 " foldDiv.className = 'group';\n", 2554 " for (var i=0; i<foldables.length; i++) {\n", 2555 " var range = document.createElement('input');\n", 2556 " range.type = 'range';\n", 2557 " range.min = 0;\n", 2558 " range.max = 1;\n", 2559 " range.value = 0;\n", 2560 " range.step = 0.001;\n", 2561 " range.name = String(i);\n", 2562 " range.oninput = fold;\n", 2563 " foldDiv.appendChild(range);\n", 2564 " }\n", 2565 " lookAtBarycenter(foldables[0]);\n", 2566 " settings.insertBefore(foldDiv,settings.childNodes[0]);\n", 2567 "}\n", 2568 "\n", 2569 " \n", 2570 "// ---------------------- EXPLOSION ------------------------------------------------\n", 2571 "// ---------------------------------------------------------------------------------\n", 2572 "\n", 2573 "if (explodableModel) {\n", 2574 " for (var i=0; i<scene.children.length; i++) {\n", 2575 " obj = scene.children[i];\n", 2576 " if ( obj.userData.explodable ) {\n", 2577 " computeCentroid(obj);\n", 2578 " }\n", 2579 " }\n", 2580 " document.getElementById('explodeRange_1').oninput = triggerExplode;\n", 2581 " document.getElementById('explodeCheckbox_1').onchange = triggerAutomaticExplode;\n", 2582 " document.getElementById('explodingSpeedRange_1').oninput = setExplodingSpeed;\n", 2583 "}\n", 2584 "\n", 2585 "function computeCentroid(obj) {\n", 2586 " centroid = new THREE.Vector3();\n", 2587 " obj.userData.points.forEach(function(pmpoint) {\n", 2588 " centroid.add(pmpoint.vector);\t\t\t\n", 2589 " });\n", 2590 " centroid.divideScalar(obj.userData.points.length);\n", 2591 " obj.userData.centroid = centroid;\n", 2592 "}\n", 2593 "\n", 2594 "function explode(factor) {\n", 2595 " for (var i=0; i<scene.children.length; i++) {\n", 2596 " var obj = scene.children[i];\n", 2597 " if (obj.userData.hasOwnProperty(\"centroid\")) { \n", 2598 " var c = obj.userData.centroid;\n", 2599 " obj.position.set(c.x*factor, c.y*factor, c.z*factor);\n", 2600 " }\n", 2601 " }\t\n", 2602 "}\n", 2603 "\n", 2604 "function triggerExplode(event){\n", 2605 " explodeScale = Number(event.currentTarget.value);\n", 2606 " explode(explodeScale);\n", 2607 "}\n", 2608 "\n", 2609 "function setExplodingSpeed(event){\n", 2610 " explodingSpeed = Number(event.currentTarget.value);\n", 2611 "}\n", 2612 "\n", 2613 "function triggerAutomaticExplode(event){\n", 2614 " if (event.currentTarget.checked){\n", 2615 " startExploding();\n", 2616 " } else {\n", 2617 " clearIntervals();\n", 2618 " }\t\n", 2619 "}\n", 2620 "\n", 2621 "function startExploding(){\n", 2622 " intervals.push(setInterval(explodingInterval, 25));\n", 2623 "}\n", 2624 "\n", 2625 "\n", 2626 "function explodingInterval(){\n", 2627 " explodeScale += explodingSpeed;\n", 2628 " if (explodeScale <= 6){ \n", 2629 " explode(explodeScale);\n", 2630 " }\n", 2631 " else{\n", 2632 " explode(6);\n", 2633 " explodeScale = 6;\n", 2634 " clearIntervals();\n", 2635 " timeouts.push(setTimeout(startUnexploding, 3000));\n", 2636 " }\n", 2637 " document.getElementById('explodeRange_1').value = explodeScale;\n", 2638 "}\n", 2639 "\n", 2640 "\n", 2641 "function startUnexploding(){\n", 2642 " intervals.push(setInterval(unexplodingInterval, 25));\n", 2643 "}\n", 2644 "\n", 2645 "function unexplodingInterval(){\n", 2646 " explodeScale -= explodingSpeed;\n", 2647 " if (explodeScale >= 0){\t\n", 2648 " explode(explodeScale);\n", 2649 " }\n", 2650 " else {\n", 2651 " explode(0);\n", 2652 " explodeScale = 0;\n", 2653 " clearIntervals();\n", 2654 " timeouts.push(setTimeout(startExploding, 3000));\n", 2655 " }\n", 2656 " document.getElementById('explodeRange_1').value = explodeScale;\n", 2657 "}\n", 2658 "\n", 2659 "function clearIntervals(){\n", 2660 " intervals.forEach(function(interval){\n", 2661 " clearInterval(interval);\n", 2662 " });\n", 2663 " intervals = [];\n", 2664 " timeouts.forEach(function(timeout){\n", 2665 " clearTimeout(timeout);\n", 2666 " });\n", 2667 " timeouts = [];\n", 2668 "}\n", 2669 "\n", 2670 "// ---------------------- DISPLAY --------------------------------------------------\n", 2671 "// ---------------------------------------------------------------------------------\n", 2672 "\n", 2673 "const objectTypeInnerHTMLs = { points: \"Points\", pointlabels: \"Point labels\", lines: \"Edges\", edgelabels: \"Edge labels\", faces: \"Faces\", arrowheads: \"Arrow heads\" };\n", 2674 "const objectTypeVisible = {};\n", 2675 "Object.assign(objectTypeVisible,modelContains);\n", 2676 "const sortedObjectTypeKeys = Object.keys(objectTypeInnerHTMLs).sort();\n", 2677 "const shownObjectTypesList = document.getElementById('shownObjectTypesList_1');\n", 2678 "\n", 2679 "function setVisibility(bool,objname) {\n", 2680 " for (var i=0; i<scene.children.length; i++){\n", 2681 " var obj = scene.children[i].getObjectByName(objname);\n", 2682 " if (obj) {\n", 2683 " obj.visible = bool;\n", 2684 " }\n", 2685 " }\n", 2686 "}\n", 2687 "\n", 2688 "function toggleObjectTypeVisibility(event){\n", 2689 " var name = event.currentTarget.name;\n", 2690 " var checked = event.currentTarget.checked;\n", 2691 " objectTypeVisible[name] = checked;\n", 2692 " setVisibility(checked,name);\n", 2693 "}\n", 2694 "\n", 2695 "for (var i=0; i<sortedObjectTypeKeys.length; i++){\n", 2696 " var key = sortedObjectTypeKeys[i];\n", 2697 " if (modelContains[key]) {\n", 2698 " var objTypeNode = document.createElement('span');\n", 2699 " objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '<br>';\n", 2700 " var checkbox = document.createElement('input');\n", 2701 " checkbox.type = 'checkbox';\n", 2702 " checkbox.checked = true;\n", 2703 " checkbox.name = key;\n", 2704 " checkbox.onchange = toggleObjectTypeVisibility;\n", 2705 " shownObjectTypesList.appendChild(checkbox);\n", 2706 " shownObjectTypesList.appendChild(objTypeNode);\n", 2707 " }\n", 2708 "}\n", 2709 "\n", 2710 "// ------------------------------------------------------\n", 2711 "\n", 2712 "function toggleObjectVisibility(event){\n", 2713 " var nr = Number(event.currentTarget.name);\n", 2714 " scene.children[nr].visible = event.currentTarget.checked;\n", 2715 "}\n", 2716 "\n", 2717 "// append checkboxes for displaying or hiding objects\n", 2718 "var shownObjectsList = document.getElementById('shownObjectsList_1');\n", 2719 "for (var i=0; i<scene.children.length; i++){\n", 2720 " obj = scene.children[i];\n", 2721 " var objNode = document.createElement('span');\n", 2722 " objNode.innerHTML = obj.name + '<br>';\n", 2723 " var checkbox = document.createElement('input');\n", 2724 " checkbox.type = 'checkbox';\n", 2725 " checkbox.checked = true;\n", 2726 " checkbox.name = String(i);\n", 2727 " checkbox.onchange = toggleObjectVisibility;\n", 2728 " shownObjectsList.appendChild(checkbox);\n", 2729 " shownObjectsList.appendChild(objNode);\n", 2730 "}\n", 2731 "\n", 2732 "// ---------------------- SVG ------------------------------------------------------\n", 2733 "// ---------------------------------------------------------------------------------\n", 2734 "\n", 2735 "function takeSvgScreenshot() {\n", 2736 " if (objectTypeVisible[\"pointlabels\"]) {\n", 2737 " setVisibility(false,\"pointlabels\");\n", 2738 " }\n", 2739 " if (objectTypeVisible[\"edgelabels\"]) {\n", 2740 " setVisibility(false,\"edgelabels\");\n", 2741 " }\n", 2742 " svgRenderer.render(scene,camera);\n", 2743 " svgElement = XMLS.serializeToString(svgRenderer.domElement);\n", 2744 " \n", 2745 " if (objectTypeVisible[\"pointlabels\"]) {\n", 2746 " setVisibility(true,\"pointlabels\");\n", 2747 " }\n", 2748 " if (objectTypeVisible[\"edgelabels\"]) {\n", 2749 " setVisibility(true,\"edgelabels\");\n", 2750 " }\n", 2751 "\n", 2752 " if (document.getElementById('tab_1').checked){\n", 2753 " //show in new tab\n", 2754 " var myWindow = window.open(\"\",\"\");\n", 2755 " myWindow.document.body.innerHTML = svgElement;\n", 2756 " } else{\n", 2757 " // download svg file \n", 2758 " download(\"screenshot.svg\", svgElement);\n", 2759 " }\n", 2760 "}\n", 2761 "\n", 2762 "function download(filename, text) {\n", 2763 " var element = document.createElement('a');\n", 2764 " element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));\n", 2765 " element.setAttribute('download', filename);\n", 2766 "\n", 2767 " element.style.display = 'none';\n", 2768 " document.body.appendChild(element);\n", 2769 "\n", 2770 " element.click();\n", 2771 "\n", 2772 " document.body.removeChild(element);\n", 2773 "}\n", 2774 "\n", 2775 "\n", 2776 "document.getElementById('transparencyRange_1').oninput = changeTransparency;\n", 2777 "document.getElementById('changeRotationX_1').onchange = changeRotationX;\n", 2778 "document.getElementById('changeRotationY_1').onchange = changeRotationY;\n", 2779 "document.getElementById('changeRotationZ_1').onchange = changeRotationZ;\n", 2780 "document.getElementById('resetButton_1').onclick = resetScene;\n", 2781 "document.getElementById('rotationSpeedRange_1').oninput = changeRotationSpeedFactor;\n", 2782 "document.getElementById('takeScreenshot_1').onclick = takeSvgScreenshot;\n", 2783 "document.getElementById('showSettingsButton_1').onclick = showSettings;\n", 2784 "document.getElementById('hideSettingsButton_1').onclick = hideSettings;\n", 2785 "\n", 2786 "\n", 2787 "// ------------------ SHORTCUTS --------------------------------------------\n", 2788 "// -------------------------------------------------------------------------\n", 2789 "\n", 2790 "/**\n", 2791 " * http://www.openjs.com/scripts/events/keyboard_shortcuts/\n", 2792 " * Version : 2.01.B\n", 2793 " * By Binny V A\n", 2794 " * License : BSD\n", 2795 " */\n", 2796 "shortcut = {\n", 2797 "\t'all_shortcuts':{},//All the shortcuts are stored in this array\n", 2798 "\t'add': function(shortcut_combination,callback,opt) {\n", 2799 "\t\t//Provide a set of default options\n", 2800 "\t\tvar default_options = {\n", 2801 "\t\t\t'type':'keydown',\n", 2802 "\t\t\t'propagate':false,\n", 2803 "\t\t\t'disable_in_input':false,\n", 2804 "\t\t\t'target':document,\n", 2805 "\t\t\t'keycode':false\n", 2806 "\t\t}\n", 2807 "\t\tif(!opt) opt = default_options;\n", 2808 "\t\telse {\n", 2809 "\t\t\tfor(var dfo in default_options) {\n", 2810 "\t\t\t\tif(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];\n", 2811 "\t\t\t}\n", 2812 "\t\t}\n", 2813 "\n", 2814 "\t\tvar ele = opt.target;\n", 2815 "\t\tif(typeof opt.target == 'string') ele = document.getElementById(opt.target);\n", 2816 "\t\tvar ths = this;\n", 2817 "\t\tshortcut_combination = shortcut_combination.toLowerCase();\n", 2818 "\n", 2819 "\t\t//The function to be called at keypress\n", 2820 "\t\tvar func = function(e) {\n", 2821 "\t\t\te = e || window.event;\n", 2822 "\t\t\t\n", 2823 "\t\t\tif(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields\n", 2824 "\t\t\t\tvar element;\n", 2825 "\t\t\t\tif(e.target) element=e.target;\n", 2826 "\t\t\t\telse if(e.srcElement) element=e.srcElement;\n", 2827 "\t\t\t\tif(element.nodeType==3) element=element.parentNode;\n", 2828 "\n", 2829 "\t\t\t\tif(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;\n", 2830 "\t\t\t}\n", 2831 "\t\n", 2832 "\t\t\t//Find Which key is pressed\n", 2833 "\t\t\tif (e.keyCode) code = e.keyCode;\n", 2834 "\t\t\telse if (e.which) code = e.which;\n", 2835 "\t\t\tvar character = String.fromCharCode(code).toLowerCase();\n", 2836 "\t\t\t\n", 2837 "\t\t\tif(code == 188) character=\",\"; //If the user presses , when the type is onkeydown\n", 2838 "\t\t\tif(code == 190) character=\".\"; //If the user presses , when the type is onkeydown\n", 2839 "\n", 2840 "\t\t\tvar keys = shortcut_combination.split(\"+\");\n", 2841 "\t\t\t//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked\n", 2842 "\t\t\tvar kp = 0;\n", 2843 "\t\t\t\n", 2844 "\t\t\t//Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken\n", 2845 "\t\t\tvar shift_nums = {\n", 2846 "\t\t\t\t\"`\":\"~\",\n", 2847 "\t\t\t\t\"1\":\"!\",\n", 2848 "\t\t\t\t\"2\":\"@\",\n", 2849 "\t\t\t\t\"3\":\"#\",\n", 2850 "\t\t\t\t\"4\":\"$\",\n", 2851 "\t\t\t\t\"5\":\"%\",\n", 2852 "\t\t\t\t\"6\":\"^\",\n", 2853 "\t\t\t\t\"7\":\"&\",\n", 2854 "\t\t\t\t\"8\":\"*\",\n", 2855 "\t\t\t\t\"9\":\"(\",\n", 2856 "\t\t\t\t\"0\":\")\",\n", 2857 "\t\t\t\t\"-\":\"_\",\n", 2858 "\t\t\t\t\"=\":\"+\",\n", 2859 "\t\t\t\t\";\":\":\",\n", 2860 "\t\t\t\t\"'\":\"\\\"\",\n", 2861 "\t\t\t\t\",\":\"<\",\n", 2862 "\t\t\t\t\".\":\">\",\n", 2863 "\t\t\t\t\"/\":\"?\",\n", 2864 "\t\t\t\t\"\\\\\":\"|\"\n", 2865 "\t\t\t}\n", 2866 "\t\t\t//Special Keys - and their codes\n", 2867 "\t\t\tvar special_keys = {\n", 2868 "\t\t\t\t'esc':27,\n", 2869 "\t\t\t\t'escape':27,\n", 2870 "\t\t\t\t'tab':9,\n", 2871 "\t\t\t\t'space':32,\n", 2872 "\t\t\t\t'return':13,\n", 2873 "\t\t\t\t'enter':13,\n", 2874 "\t\t\t\t'backspace':8,\n", 2875 "\t\n", 2876 "\t\t\t\t'scrolllock':145,\n", 2877 "\t\t\t\t'scroll_lock':145,\n", 2878 "\t\t\t\t'scroll':145,\n", 2879 "\t\t\t\t'capslock':20,\n", 2880 "\t\t\t\t'caps_lock':20,\n", 2881 "\t\t\t\t'caps':20,\n", 2882 "\t\t\t\t'numlock':144,\n", 2883 "\t\t\t\t'num_lock':144,\n", 2884 "\t\t\t\t'num':144,\n", 2885 "\t\t\t\t\n", 2886 "\t\t\t\t'pause':19,\n", 2887 "\t\t\t\t'break':19,\n", 2888 "\t\t\t\t\n", 2889 "\t\t\t\t'insert':45,\n", 2890 "\t\t\t\t'home':36,\n", 2891 "\t\t\t\t'delete':46,\n", 2892 "\t\t\t\t'end':35,\n", 2893 "\t\t\t\t\n", 2894 "\t\t\t\t'pageup':33,\n", 2895 "\t\t\t\t'page_up':33,\n", 2896 "\t\t\t\t'pu':33,\n", 2897 "\t\n", 2898 "\t\t\t\t'pagedown':34,\n", 2899 "\t\t\t\t'page_down':34,\n", 2900 "\t\t\t\t'pd':34,\n", 2901 "\t\n", 2902 "\t\t\t\t'left':37,\n", 2903 "\t\t\t\t'up':38,\n", 2904 "\t\t\t\t'right':39,\n", 2905 "\t\t\t\t'down':40,\n", 2906 "\t\n", 2907 "\t\t\t\t'f1':112,\n", 2908 "\t\t\t\t'f2':113,\n", 2909 "\t\t\t\t'f3':114,\n", 2910 "\t\t\t\t'f4':115,\n", 2911 "\t\t\t\t'f5':116,\n", 2912 "\t\t\t\t'f6':117,\n", 2913 "\t\t\t\t'f7':118,\n", 2914 "\t\t\t\t'f8':119,\n", 2915 "\t\t\t\t'f9':120,\n", 2916 "\t\t\t\t'f10':121,\n", 2917 "\t\t\t\t'f11':122,\n", 2918 "\t\t\t\t'f12':123\n", 2919 "\t\t\t}\n", 2920 "\t\n", 2921 "\t\t\tvar modifiers = { \n", 2922 "\t\t\t\tshift: { wanted:false, pressed:false},\n", 2923 "\t\t\t\tctrl : { wanted:false, pressed:false},\n", 2924 "\t\t\t\talt : { wanted:false, pressed:false},\n", 2925 "\t\t\t\tmeta : { wanted:false, pressed:false}\t//Meta is Mac specific\n", 2926 "\t\t\t};\n", 2927 " \n", 2928 "\t\t\tif(e.ctrlKey)\tmodifiers.ctrl.pressed = true;\n", 2929 "\t\t\tif(e.shiftKey)\tmodifiers.shift.pressed = true;\n", 2930 "\t\t\tif(e.altKey)\tmodifiers.alt.pressed = true;\n", 2931 "\t\t\tif(e.metaKey) modifiers.meta.pressed = true;\n", 2932 " \n", 2933 "\t\t\tfor(var i=0; k=keys[i],i<keys.length; i++) {\n", 2934 "\t\t\t\t//Modifiers\n", 2935 "\t\t\t\tif(k == 'ctrl' || k == 'control') {\n", 2936 "\t\t\t\t\tkp++;\n", 2937 "\t\t\t\t\tmodifiers.ctrl.wanted = true;\n", 2938 "\n", 2939 "\t\t\t\t} else if(k == 'shift') {\n", 2940 "\t\t\t\t\tkp++;\n", 2941 "\t\t\t\t\tmodifiers.shift.wanted = true;\n", 2942 "\n", 2943 "\t\t\t\t} else if(k == 'alt') {\n", 2944 "\t\t\t\t\tkp++;\n", 2945 "\t\t\t\t\tmodifiers.alt.wanted = true;\n", 2946 "\t\t\t\t} else if(k == 'meta') {\n", 2947 "\t\t\t\t\tkp++;\n", 2948 "\t\t\t\t\tmodifiers.meta.wanted = true;\n", 2949 "\t\t\t\t} else if(k.length > 1) { //If it is a special key\n", 2950 "\t\t\t\t\tif(special_keys[k] == code) kp++;\n", 2951 "\t\t\t\t\t\n", 2952 "\t\t\t\t} else if(opt['keycode']) {\n", 2953 "\t\t\t\t\tif(opt['keycode'] == code) kp++;\n", 2954 "\n", 2955 "\t\t\t\t} else { //The special keys did not match\n", 2956 "\t\t\t\t\tif(character == k) kp++;\n", 2957 "\t\t\t\t\telse {\n", 2958 "\t\t\t\t\t\tif(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase\n", 2959 "\t\t\t\t\t\t\tcharacter = shift_nums[character]; \n", 2960 "\t\t\t\t\t\t\tif(character == k) kp++;\n", 2961 "\t\t\t\t\t\t}\n", 2962 "\t\t\t\t\t}\n", 2963 "\t\t\t\t}\n", 2964 "\t\t\t}\n", 2965 "\t\t\t\n", 2966 "\t\t\tif(kp == keys.length && \n", 2967 "\t\t\t\t\t\tmodifiers.ctrl.pressed == modifiers.ctrl.wanted &&\n", 2968 "\t\t\t\t\t\tmodifiers.shift.pressed == modifiers.shift.wanted &&\n", 2969 "\t\t\t\t\t\tmodifiers.alt.pressed == modifiers.alt.wanted &&\n", 2970 "\t\t\t\t\t\tmodifiers.meta.pressed == modifiers.meta.wanted) {\n", 2971 "\t\t\t\tcallback(e);\n", 2972 "\t\n", 2973 "\t\t\t\tif(!opt['propagate']) { //Stop the event\n", 2974 "\t\t\t\t\t//e.cancelBubble is supported by IE - this will kill the bubbling process.\n", 2975 "\t\t\t\t\te.cancelBubble = true;\n", 2976 "\t\t\t\t\te.returnValue = false;\n", 2977 "\t\n", 2978 "\t\t\t\t\t//e.stopPropagation works in Firefox.\n", 2979 "\t\t\t\t\tif (e.stopPropagation) {\n", 2980 "\t\t\t\t\t\te.stopPropagation();\n", 2981 "\t\t\t\t\t\te.preventDefault();\n", 2982 "\t\t\t\t\t}\n", 2983 "\t\t\t\t\treturn false;\n", 2984 "\t\t\t\t}\n", 2985 "\t\t\t}\n", 2986 "\t\t}\n", 2987 "\t\tthis.all_shortcuts[shortcut_combination] = {\n", 2988 "\t\t\t'callback':func, \n", 2989 "\t\t\t'target':ele, \n", 2990 "\t\t\t'event': opt['type']\n", 2991 "\t\t};\n", 2992 "\t\t//Attach the function with the event\n", 2993 "\t\tif(ele.addEventListener) ele.addEventListener(opt['type'], func, false);\n", 2994 "\t\telse if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);\n", 2995 "\t\telse ele['on'+opt['type']] = func;\n", 2996 "\t},\n", 2997 "\n", 2998 "\t//Remove the shortcut - just specify the shortcut and I will remove the binding\n", 2999 "\t'remove':function(shortcut_combination) {\n", 3000 "\t\tshortcut_combination = shortcut_combination.toLowerCase();\n", 3001 "\t\tvar binding = this.all_shortcuts[shortcut_combination];\n", 3002 "\t\tdelete(this.all_shortcuts[shortcut_combination])\n", 3003 "\t\tif(!binding) return;\n", 3004 "\t\tvar type = binding['event'];\n", 3005 "\t\tvar ele = binding['target'];\n", 3006 "\t\tvar callback = binding['callback'];\n", 3007 "\n", 3008 "\t\tif(ele.detachEvent) ele.detachEvent('on'+type, callback);\n", 3009 "\t\telse if(ele.removeEventListener) ele.removeEventListener(type, callback, false);\n", 3010 "\t\telse ele['on'+type] = false;\n", 3011 "\t}\n", 3012 "}\n", 3013 "\n", 3014 "shortcut.add(\"Alt+Left\",function() {\n", 3015 "\tvar event = new Event('click');\n", 3016 "\tif (settingsShown){\n", 3017 "\t\tdocument.getElementById('hideSettingsButton_1').dispatchEvent(event);\n", 3018 "\t} else {\n", 3019 "\t\tdocument.getElementById('showSettingsButton_1').dispatchEvent(event);\n", 3020 "\t}\n", 3021 "});\n", 3022 "\n", 3023 "\n", 3024 "// COMMON_CODE_BLOCK_END\n", 3025 "\n", 3026 "});});\n", 3027 " </script>\n", 3028 " </body>\n", 3029 "</html>" 3030 ] 3031 }, 3032 "metadata": {}, 3033 "output_type": "display_data" 3034 } 3035 ], 3036 "source": [ 3037 "$scaled_rs->VISUAL->LATTICE_COLORED;" 3038 ] 3039 }, 3040 { 3041 "cell_type": "markdown", 3042 "metadata": {}, 3043 "source": [ 3044 "Now will construct the integer hull of `$scaled_rs` and visualise it:" 3045 ] 3046 }, 3047 { 3048 "cell_type": "code", 3049 "execution_count": 14, 3050 "metadata": {}, 3051 "outputs": [ 3052 { 3053 "data": { 3054 "text/html": [ 3055 "<!--\n", 3056 "polymake for knusper\n", 3057 "Thu Aug 27 11:38:20 2020\n", 3058 "integer_hull\n", 3059 "-->\n", 3060 "\n", 3061 "\n", 3062 "<html>\n", 3063 " <head>\n", 3064 " <meta charset=utf-8>\n", 3065 " <title>integer_hull</title>\n", 3066 " <style>\n", 3067 "/*\n", 3068 "// COMMON_CODE_BLOCK_BEGIN\n", 3069 "*/\n", 3070 " html {overflow: scroll;}\n", 3071 " strong{font-size: 18px;}\n", 3072 " canvas { z-index: 8; }\n", 3073 " input[type='radio'] {margin-left:0;}\n", 3074 " input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;}\n", 3075 " .group{padding-bottom: 15px;}\n", 3076 " .settings * {z-index: 11; }\n", 3077 " .settings{z-index: 10; font-family: Arial, Helvetica, sans-serif; margin-left: 30px; visibility: hidden; width: 14em; height: 96%; border: solid 1px silver; padding: 2px; overflow-y: scroll; box-sizing: border-box; background-color: white; position: absolute;}\n", 3078 " .indented{margin-left: 20px; margin-top: 10px; padding-bottom: 0px;} \n", 3079 " .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;}\n", 3080 " .showSettingsButton{visibility: visible; z-index: 12; position: absolute }\n", 3081 " .hideSettingsButton{visibility: hidden; z-index: 12; position: absolute; opacity: 0.5}\n", 3082 " button{margin-left: 0; margin-top: 10px}\n", 3083 " img{cursor: pointer;}\n", 3084 " .suboption{padding-top: 15px;}\n", 3085 " #model20732307065 { width: 100%; height: 100%; }\n", 3086 " .threejs_container { width: 100%; height: 75vh;}\n", 3087 " .settings{max-height: 74vh} \n", 3088 " input[type=range] {\n", 3089 " -webkit-appearance: none;\n", 3090 " padding:0; \n", 3091 " width:90%; \n", 3092 " margin-left: auto;\n", 3093 " margin-right: auto;\n", 3094 " margin-top: 15px;\n", 3095 " margin-bottom: 15px;\n", 3096 " display: block;\t\n", 3097 " }\n", 3098 " input[type=range]:focus {\n", 3099 " outline: none;\n", 3100 " }\n", 3101 " input[type=range]::-webkit-slider-runnable-track {\n", 3102 " height: 4px;\n", 3103 " cursor: pointer;\n", 3104 " animate: 0.2s;\n", 3105 " box-shadow: 0px 0px 0px #000000;\n", 3106 " background: #E3E3E3;\n", 3107 " border-radius: 0px;\n", 3108 " border: 0px solid #000000;\n", 3109 " }\n", 3110 " input[type=range]::-webkit-slider-thumb {\n", 3111 " box-shadow: 1px 1px 2px #B8B8B8;\n", 3112 " border: 1px solid #ABABAB;\n", 3113 " height: 13px;\n", 3114 " width: 25px;\n", 3115 " border-radius: 20px;\n", 3116 " background: #E0E0E0;\n", 3117 " cursor: pointer;\n", 3118 " -webkit-appearance: none;\n", 3119 " margin-top: -5px;\n", 3120 " }\n", 3121 " input[type=range]:focus::-webkit-slider-runnable-track {\n", 3122 " background: #E3E3E3;\n", 3123 " }\n", 3124 " input[type=range]::-moz-range-track {\n", 3125 " height: 4px;\n", 3126 " cursor: pointer;\n", 3127 " animate: 0.2s;\n", 3128 " box-shadow: 0px 0px 0px #000000;\n", 3129 " background: #E3E3E3;\n", 3130 " border-radius: 0px;\n", 3131 " border: 0px solid #000000;\n", 3132 " }\n", 3133 " input[type=range]::-moz-range-thumb {\n", 3134 " box-shadow: 1px 1px 2px #B8B8B8;\n", 3135 " border: 1px solid #ABABAB;\n", 3136 " height: 13px;\n", 3137 " width: 25px;\n", 3138 " border-radius: 20px;\n", 3139 " background: #E0E0E0;\n", 3140 " cursor: pointer;\n", 3141 " }\n", 3142 " input[type=range]::-ms-track {\n", 3143 " height: 4px;\n", 3144 " cursor: pointer;\n", 3145 " animate: 0.2s;\n", 3146 " background: transparent;\n", 3147 " border-color: transparent;\n", 3148 " color: transparent;\n", 3149 " }\n", 3150 " input[type=range]::-ms-fill-lower {\n", 3151 " background: #E3E3E3;\n", 3152 " border: 0px solid #000000;\n", 3153 " border-radius: 0px;\n", 3154 " box-shadow: 0px 0px 0px #000000;\n", 3155 " }\n", 3156 " input[type=range]::-ms-fill-upper {\n", 3157 " background: #E3E3E3;\n", 3158 " border: 0px solid #000000;\n", 3159 " border-radius: 0px;\n", 3160 " box-shadow: 0px 0px 0px #000000;\n", 3161 " }\n", 3162 " input[type=range]::-ms-thumb {\n", 3163 " box-shadow: 1px 1px 2px #B8B8B8;\n", 3164 " border: 1px solid #ABABAB;\n", 3165 " height: 13px;\n", 3166 " width: 25px;\n", 3167 " border-radius: 20px;\n", 3168 " background: #E0E0E0;\n", 3169 " cursor: pointer;\n", 3170 " }\n", 3171 " input[type=range]:focus::-ms-fill-lower {\n", 3172 " background: #E3E3E3;\n", 3173 " }\n", 3174 " input[type=range]:focus::-ms-fill-upper {\n", 3175 " background: #E3E3E3;\n", 3176 " }\n", 3177 "/*\n", 3178 "// COMMON_CODE_BLOCK_END\n", 3179 "*/\n", 3180 "\t\t</style>\n", 3181 " </head>\n", 3182 "<body>\n", 3183 " <div class='threejs_container'>\n", 3184 "\t\t<div id='settings_2' class='settings'>\n", 3185 "\t\t\t<div class=group id='explode_2'>\n", 3186 "\t\t\t\t<strong>Explode</strong>\n", 3187 "\t\t\t\t<input id='explodeRange_2' type='range' min=0 max=6 step=0.01 value=0>\n", 3188 "\t\t\t\t<div class=indented><input id='explodeCheckbox_2' type='checkbox'>Automatic explosion</div>\n", 3189 "\t\t\t\t<div class=suboption>Exploding speed</div>\n", 3190 "\t\t\t\t<input id='explodingSpeedRange_2' type='range' min=0 max=0.5 step=0.001 value=0.05>\n", 3191 "\t\t\t</div>\n", 3192 "\t\n", 3193 "\t\t\t<div class=group id='transparency_2' class='transparency'>\n", 3194 "\t\t\t\t<strong>Transparency</strong>\n", 3195 "\t\t\t\t<input id='transparencyRange_2' type='range' min=0 max=1 step=0.01 value=0>\n", 3196 "\t\t\t</div>\n", 3197 "\t\t\t\n", 3198 "\t\t\t<div class=group id='rotation_2'>\n", 3199 "\t\t\t\t<strong>Rotation</strong>\n", 3200 "\t\t\t\t<div class=indented>\n", 3201 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationX_2'> x-axis</div>\n", 3202 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationY_2'> y-axis</div>\n", 3203 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationZ_2'> z-axis</div>\n", 3204 "\t\t\t\t\t<button id='resetButton_2'>Reset</button>\n", 3205 "\t\t\t\t</div>\n", 3206 "\n", 3207 "\t\t\t\t<div class=suboption>Rotation speed</div>\n", 3208 "\t\t\t\t<input id='rotationSpeedRange_2' type='range' min=0 max=5 step=0.01 value=2>\n", 3209 "\t\t\t</div>\n", 3210 "\n", 3211 "\n", 3212 "\t\t\t<div class=group id='display_2'>\n", 3213 "\t\t\t\t<strong>Display</strong>\n", 3214 "\t\t\t\t<div class=indented>\n", 3215 "\t\t\t\t\t<div id='shownObjectTypesList_2' class='shownObjectsList'></div>\n", 3216 "\t\t\t\t</div>\n", 3217 "\t\t\t\t<div class=suboption>Objects</div>\n", 3218 "\t\t\t\t<div class=indented>\n", 3219 "\t\t\t\t <div id='shownObjectsList_2' class='shownObjectsList'></div>\n", 3220 "\t\t\t\t</div>\n", 3221 "\t\t\t</div>\n", 3222 " \n", 3223 " <div class=group id='camera_2'>\n", 3224 " <strong>Camera</strong>\n", 3225 " <div class=indented>\n", 3226 " <form>\n", 3227 " <select id=\"cameraType_2\">\n", 3228 " <option value='perspective' selected> Perspective<br></option>\n", 3229 " <option value='orthographic' > Orthographic<br></option>\n", 3230 " </select>\n", 3231 " </form>\n", 3232 " </div>\n", 3233 " </div>\n", 3234 "\n", 3235 "\t\t\t<div class=group id='svg_2'>\n", 3236 "\t\t\t\t<strong>SVG</strong>\n", 3237 "\t\t\t\t<div class=indented>\n", 3238 "\t\t\t\t\t<form>\n", 3239 "\t\t\t\t\t\t<input type=\"radio\" name='screenshotMode' value='download' id='download_2' checked> Download<br>\n", 3240 "\t\t\t\t\t\t<input type=\"radio\" name='screenshotMode' value='tab' id='tab_2' > New tab<br>\n", 3241 "\t\t\t\t\t</form>\n", 3242 "\t\t\t\t\t<button id='takeScreenshot_2'>Screenshot</button>\n", 3243 "\t\t\t\t</div>\n", 3244 "\t\t\t</div>\n", 3245 "\n", 3246 "\t\t</div>\t<!-- end of settings -->\n", 3247 "\t\t<img id='hideSettingsButton_2' class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px\">\n", 3248 "\t\t<img id='showSettingsButton_2' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px\">\n", 3249 "<div id=\"model20732307065\"></div>\n", 3250 "</div>\n", 3251 " <script>\n", 3252 " requirejs.config({\n", 3253 " paths: {\n", 3254 " three: '/kernelspecs/polymake/three',\n", 3255 " TrackballControls: '/kernelspecs/polymake/TrackballControls',\n", 3256 " OrbitControls: '/kernelspecs/polymake/OrbitControls',\n", 3257 " Projector: '/kernelspecs/polymake/Projector',\n", 3258 " SVGRenderer: '/kernelspecs/polymake/SVGRenderer',\n", 3259 " WEBGL: '/kernelspecs/polymake/WebGL',\n", 3260 " },\n", 3261 " shim: {\n", 3262 " 'three': { exports: 'THREE'},\n", 3263 " 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' },\n", 3264 " 'WEBGL': { deps: [ 'three' ], exports: 'THREE.WEBGL' },\n", 3265 " 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' },\n", 3266 " 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' },\n", 3267 " 'OrbitControls': { deps: [ 'three' ], exports: 'THREE.OrbitControls' },\n", 3268 " }\n", 3269 " });\n", 3270 " \n", 3271 " require(['three'],function(THREE){\n", 3272 " window.THREE = THREE;\n", 3273 " require(['TrackballControls', 'OrbitControls', 'Projector', 'SVGRenderer', 'WEBGL'],\n", 3274 " function(TrackballControls, OrbitControls, Projector, SVGRenderer, WEBGL) {\n", 3275 " THREE.TrackballControls = TrackballControls;\n", 3276 " THREE.OrbitControls = OrbitControls;\n", 3277 " THREE.Projector = Projector;\n", 3278 " THREE.SVGRenderer = SVGRenderer;\n", 3279 " THREE.WEBGL = WEBGL;\n", 3280 "\n", 3281 "// COMMON_CODE_BLOCK_BEGIN\n", 3282 "\n", 3283 "const intervalLength = 25; // for automatic animations\n", 3284 "const explodableModel = true; \n", 3285 "const modelContains = { points: false, pointlabels: false, lines: false, edgelabels: false, faces: false, arrowheads: false };\n", 3286 "const foldables = [];\n", 3287 "\n", 3288 "var three = document.getElementById(\"model20732307065\");\n", 3289 "var scene = new THREE.Scene();\n", 3290 "var renderer = new THREE.WebGLRenderer( { antialias: true } );\n", 3291 "var svgRenderer = new THREE.SVGRenderer( { antialias: true } );\n", 3292 "renderer.setPixelRatio( window.devicePixelRatio );\n", 3293 "renderer.setClearColor(0xFFFFFF, 1);\n", 3294 "svgRenderer.setClearColor(0xFFFFFF, 1);\n", 3295 "three.appendChild(renderer.domElement);\n", 3296 "\n", 3297 "var frustumSize = 4;\n", 3298 "var cameras = [new THREE.PerspectiveCamera(75, 1, 0.1, 1000), new THREE.OrthographicCamera()];\n", 3299 "cameras.forEach(function(cam) {\n", 3300 " cam.position.set(0, 0, 5);\n", 3301 " cam.lookAt(0, 0, 0); \n", 3302 " cam.up.set(0, 1, 0); \n", 3303 "});\n", 3304 "var controls = [new THREE.TrackballControls(cameras[0], three), new THREE.OrbitControls(cameras[1], three)];\n", 3305 "var camera, control;\n", 3306 "\n", 3307 "controls[0].zoomSpeed = 0.2;\n", 3308 "controls[0].rotateSpeed = 4;\n", 3309 "\n", 3310 "\n", 3311 "// class to allow move points together with labels and spheres\n", 3312 "var PMPoint = function (x,y,z) {\n", 3313 " this.vector = new THREE.Vector3(x,y,z);\n", 3314 " this.sprite = null;\n", 3315 " this.sphere = null;\n", 3316 "}\n", 3317 "PMPoint.prototype.addLabel = function(labelsprite) {\n", 3318 " this.sprite = labelsprite;\n", 3319 " this.sprite.position.copy(this.vector);\n", 3320 "}\n", 3321 "PMPoint.prototype.addSphere = function(spheremesh) {\n", 3322 " this.sphere = spheremesh;\n", 3323 " this.sphere.position.copy(this.vector);\n", 3324 "}\n", 3325 "PMPoint.prototype.set = function(x,y,z) {\n", 3326 " this.vector.set(x,y,z);\n", 3327 " if (this.sprite) {\n", 3328 " this.sprite.position.copy(this.vector);\n", 3329 " }\n", 3330 " if (this.sphere) {\n", 3331 " this.sphere.position.copy(this.vector);\n", 3332 " }\n", 3333 "}\n", 3334 "PMPoint.prototype.radius = function() {\n", 3335 " if (this.sphere) {\n", 3336 " return this.sphere.geometry.parameters.radius;\n", 3337 " } else {\n", 3338 " return 0;\n", 3339 " }\n", 3340 "};\n", 3341 "// select the target node\n", 3342 "var target = document.querySelector('#model20732307065');\n", 3343 "\n", 3344 "// create an observer instance\n", 3345 "var observer = new MutationObserver(function(mutations) {\n", 3346 " mutations.forEach(function(mutation) {\n", 3347 " if (mutation.removedNodes && mutation.removedNodes.length > 0) {\n", 3348 " cancelAnimationFrame(renderId);\n", 3349 " observer.disconnect();\n", 3350 " console.log(\"cancelled frame \"+renderId);\n", 3351 " }\n", 3352 " });\n", 3353 "});\n", 3354 "\n", 3355 "// configuration of the observer:\n", 3356 "var config = { childList: true, characterData: true }\n", 3357 "\n", 3358 "// pass in the target node, as well as the observer options\n", 3359 "while (target) {\n", 3360 " if (target.className==\"output\") {\n", 3361 " observer.observe(target, config);\n", 3362 " break;\n", 3363 " }\n", 3364 " target = target.parentNode;\n", 3365 "}\n", 3366 "\n", 3367 "// COMMON_CODE_BLOCK_END\n", 3368 "\n", 3369 "var obj0 = new THREE.Object3D();\n", 3370 "obj0.name = \"integer_hull\";\n", 3371 "obj0.userData.explodable = 1;\n", 3372 "obj0.userData.points = [];\n", 3373 "obj0.userData.points.push(new PMPoint(-1, -1, -1));\n", 3374 "obj0.userData.points.push(new PMPoint(-1, -1, 0));\n", 3375 "obj0.userData.points.push(new PMPoint(-1, 0, -1));\n", 3376 "obj0.userData.points.push(new PMPoint(-1, 0, 1));\n", 3377 "obj0.userData.points.push(new PMPoint(-1, 1, 0));\n", 3378 "obj0.userData.points.push(new PMPoint(0, -1, 0));\n", 3379 "obj0.userData.points.push(new PMPoint(0, -1, 1));\n", 3380 "obj0.userData.points.push(new PMPoint(0, 1, -1));\n", 3381 "obj0.userData.points.push(new PMPoint(0, 1, 1));\n", 3382 "obj0.userData.points.push(new PMPoint(1, 0, -1));\n", 3383 "obj0.userData.points.push(new PMPoint(1, 0, 1));\n", 3384 "obj0.userData.points.push(new PMPoint(1, 1, 0));\n", 3385 "\n", 3386 "obj0.userData.edgeindices = [0, 1, 0, 2, 1, 3, 2, 4, 3, 4, 0, 5, 1, 6, 3, 6, 5, 6, 2, 7, 4, 7, 3, 8, 4, 8, 0, 9, 5, 9, 7, 9, 6, 10, 8, 10, 9, 10, 7, 11, 8, 11, 9, 11, 10, 11];\n", 3387 " <!-- Edge style -->\n", 3388 "obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, depthTest: true, linewidth: 1.5, transparent: false } );\n", 3389 "obj0.userData.facets = [[10, 6, 5, 9], [3, 6, 10, 8], [4, 3, 8], [5, 6, 1, 0], [1, 6, 3], [0, 1, 3, 4, 2], [2, 4, 7], [9, 5, 0], [9, 0, 2, 7], [11, 9, 7], [10, 11, 8], [10, 9, 11], [11, 7, 4, 8]];\n", 3390 "init_object(obj0);\n", 3391 "scene.add(obj0);\n", 3392 "\n", 3393 "var obj1 = new THREE.Object3D();\n", 3394 "obj1.name = \"Lattice points and vertices of integer_hull\";\n", 3395 "obj1.userData.explodable = 1;\n", 3396 "obj1.userData.points = [];\n", 3397 "obj1.userData.points.push(new PMPoint(0, 0, 0));\n", 3398 "obj1.userData.points.push(new PMPoint(-1, -1, -1));\n", 3399 "obj1.userData.points.push(new PMPoint(-1, -1, 0));\n", 3400 "obj1.userData.points.push(new PMPoint(-1, 0, -1));\n", 3401 "obj1.userData.points.push(new PMPoint(-1, 0, 0));\n", 3402 "obj1.userData.points.push(new PMPoint(-1, 0, 1));\n", 3403 "obj1.userData.points.push(new PMPoint(-1, 1, 0));\n", 3404 "obj1.userData.points.push(new PMPoint(0, -1, 0));\n", 3405 "obj1.userData.points.push(new PMPoint(0, -1, 1));\n", 3406 "obj1.userData.points.push(new PMPoint(0, 0, -1));\n", 3407 "obj1.userData.points.push(new PMPoint(0, 0, 1));\n", 3408 "obj1.userData.points.push(new PMPoint(0, 1, -1));\n", 3409 "obj1.userData.points.push(new PMPoint(0, 1, 0));\n", 3410 "obj1.userData.points.push(new PMPoint(0, 1, 1));\n", 3411 "obj1.userData.points.push(new PMPoint(1, 0, -1));\n", 3412 "obj1.userData.points.push(new PMPoint(1, 0, 0));\n", 3413 "obj1.userData.points.push(new PMPoint(1, 0, 1));\n", 3414 "obj1.userData.points.push(new PMPoint(1, 1, 0));\n", 3415 "\n", 3416 "obj1.userData.pointradii = 0.02;\n", 3417 " <!-- Vertex style -->\n", 3418 "obj1.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0x1EFA1E, side: THREE.DoubleSide, transparent: false } ),\n", 3419 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3420 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3421 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3422 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3423 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3424 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3425 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3426 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3427 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3428 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3429 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3430 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3431 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3432 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3433 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3434 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } ),\n", 3435 "new THREE.MeshBasicMaterial( { color: 0x469646, side: THREE.DoubleSide, transparent: false } )];\n", 3436 "init_object(obj1);\n", 3437 "scene.add(obj1);\n", 3438 "\n", 3439 "// COMMON_CODE_BLOCK_BEGIN\n", 3440 "function textSpriteMaterial(message, parameters) {\n", 3441 " if ( parameters === undefined ) parameters = {};\n", 3442 " var fontface = \"Helvetica\";\n", 3443 " var fontsize = parameters.hasOwnProperty(\"fontsize\") ? parameters[\"fontsize\"] : 15;\n", 3444 " fontsize = fontsize*10;\n", 3445 " var lines = message.split('\\\\n');\n", 3446 " var size = 512;\n", 3447 " for(var i = 0; i<lines.length; i++){\n", 3448 " var tmp = lines[i].length;\n", 3449 " while(tmp*fontsize > size){\n", 3450 " fontsize--;\n", 3451 " }\n", 3452 " }\n", 3453 " \n", 3454 " var canvas = document.createElement('canvas');\n", 3455 " canvas.width = size;\n", 3456 " canvas.height = size;\n", 3457 " var context = canvas.getContext('2d');\n", 3458 " context.fillStyle = \"rgba(255, 255, 255, 0)\";\n", 3459 " context.fill();\n", 3460 " context.font = fontsize + \"px \" + fontface;\n", 3461 " \n", 3462 " // text color\n", 3463 " context.fillStyle = \"rgba(0, 0, 0, 1.0)\";\n", 3464 " for(var i = 0; i<lines.length; i++){\n", 3465 " context.fillText(lines[i], size/2, size/2+i*fontsize);\n", 3466 " }\n", 3467 " \n", 3468 " // canvas contents will be used for a texture\n", 3469 " var texture = new THREE.Texture(canvas);\n", 3470 " texture.needsUpdate = true;\n", 3471 " \n", 3472 " var spriteMaterial = new THREE.SpriteMaterial({map: texture, depthTest: true, depthWrite: false, polygonOffset: true, polygonOffsetFactor: -1, polygonOffsetUnits: 1 });\n", 3473 " return spriteMaterial;\n", 3474 "}\n", 3475 "\n", 3476 "\n", 3477 "// ---------------------- INITIALIZING OBJECTS--------------------------------------\n", 3478 "// ---------------------------------------------------------------------------------\n", 3479 "\n", 3480 "function init_object(obj) {\n", 3481 " if (obj.userData.hasOwnProperty(\"pointmaterial\")) {\n", 3482 " init_points(obj);\n", 3483 " modelContains.points = true;\n", 3484 " }\n", 3485 " if (obj.userData.hasOwnProperty(\"pointlabels\")) {\n", 3486 " init_pointlabels(obj);\n", 3487 " modelContains.pointlabels = true;\n", 3488 " }\n", 3489 " if (obj.userData.hasOwnProperty(\"edgematerial\")) {\n", 3490 " init_lines(obj);\n", 3491 " modelContains.lines = true;\n", 3492 " }\n", 3493 " if (obj.userData.hasOwnProperty(\"edgelabels\")) {\n", 3494 " init_edgelabels(obj);\n", 3495 " modelContains.edgelabels = true;\n", 3496 " }\n", 3497 " if (obj.userData.hasOwnProperty(\"arrowstyle\")) {\n", 3498 " init_arrowheads(obj);\n", 3499 " modelContains.arrowheads = true;\n", 3500 " }\n", 3501 " if (obj.userData.hasOwnProperty(\"facetmaterial\")) {\n", 3502 " init_faces(obj);\n", 3503 " modelContains.faces = true;\n", 3504 " }\n", 3505 "}\n", 3506 "\n", 3507 "function init_points(obj) {\n", 3508 " var pointgroup = new THREE.Group();\n", 3509 " pointgroup.name = \"points\";\n", 3510 " var points = obj.userData.points;\n", 3511 " var radii = obj.userData.pointradii;\n", 3512 " var materials = obj.userData.pointmaterial;\n", 3513 " var geometry,material;\n", 3514 " if (!Array.isArray(radii)) {\n", 3515 " geometry = new THREE.SphereBufferGeometry(radii); \n", 3516 " }\n", 3517 " if (!Array.isArray(materials)) {\n", 3518 " material = materials;\n", 3519 " }\n", 3520 " for (var i=0; i<points.length; i++) {\n", 3521 " var point = points[i];\n", 3522 " if (Array.isArray(radii)) {\n", 3523 " if (radii[i] == 0) {\n", 3524 " continue;\n", 3525 " }\n", 3526 " geometry = new THREE.SphereBufferGeometry(radii[i]); \n", 3527 " } \n", 3528 " if (Array.isArray(materials)) {\n", 3529 " material = materials[i]; \n", 3530 " } \n", 3531 " var sphere = new THREE.Mesh(geometry, material);\n", 3532 " point.addSphere(sphere);\n", 3533 " pointgroup.add(sphere);\n", 3534 " }\n", 3535 " obj.add(pointgroup);\n", 3536 "}\n", 3537 "\n", 3538 "function init_pointlabels(obj) {\n", 3539 " var points = obj.userData.points;\n", 3540 " var labels = obj.userData.pointlabels;\n", 3541 " var pointlabels = new THREE.Group();\n", 3542 " pointlabels.name = \"pointlabels\";\n", 3543 " if (Array.isArray(labels)) {\n", 3544 " for (var i=0; i<points.length; i++) {\n", 3545 " var point = points[i];\n", 3546 " var spriteMaterial = textSpriteMaterial( labels[i] );\n", 3547 "\t var sprite = new THREE.Sprite(spriteMaterial);\n", 3548 " point.addLabel(sprite);\n", 3549 " pointlabels.add(sprite);\n", 3550 " }\n", 3551 " } else {\n", 3552 " var spriteMaterial = textSpriteMaterial( labels );\n", 3553 " for (var i=0; i<points.length; i++) {\n", 3554 " var point = points[i];\n", 3555 "\t var sprite = new THREE.Sprite(spriteMaterial);\n", 3556 " point.addLabel(sprite);\n", 3557 " pointlabels.add(sprite);\n", 3558 " }\n", 3559 " }\n", 3560 " obj.add(pointlabels);\n", 3561 "}\n", 3562 "\n", 3563 "function init_lines(obj) {\n", 3564 " var edgeindices = obj.userData.edgeindices;\n", 3565 " var points = obj.userData.points;\n", 3566 " var materials = obj.userData.edgematerial;\n", 3567 " var geometry = new THREE.BufferGeometry();\n", 3568 " var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 );\n", 3569 " var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 );\n", 3570 " var geometry = new THREE.BufferGeometry();\n", 3571 " geometry.setAttribute('position', bufattr);\n", 3572 " if (Array.isArray(materials)) { \n", 3573 " for (var i=0; i<materials.length; i++) {\n", 3574 " geometry.addGroup(2*i,2,i);\n", 3575 " }\n", 3576 " }\n", 3577 " var lines = new THREE.LineSegments(geometry, materials);\n", 3578 " lines.name = \"lines\";\n", 3579 " obj.add(lines);\n", 3580 " updateEdgesPosition(obj);\n", 3581 "}\n", 3582 "\n", 3583 "function init_edgelabels(obj) {\n", 3584 " var points = obj.userData.points;\n", 3585 " var edgeindices = obj.userData.edgeindices;\n", 3586 " var labels = obj.userData.edgelabels;\n", 3587 " var edgelabels = new THREE.Group();\n", 3588 " edgelabels.name = \"edgelabels\";\n", 3589 " if (Array.isArray(labels)) {\n", 3590 " for (var i=0; i<edgeindices.length; i=i+2) {\n", 3591 " var point = points[i];\n", 3592 " var spriteMaterial = textSpriteMaterial( labels[i] );\n", 3593 " var sprite = new THREE.Sprite(spriteMaterial);\n", 3594 " sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[i]].vector,points[edgeindices[i+1]].vector).multiplyScalar(0.5));\n", 3595 " edgelabels.add(sprite);\n", 3596 " }\n", 3597 " } else {\n", 3598 " var spriteMaterial = textSpriteMaterial( labels );\n", 3599 " for (var i=0; i<points.length; i++) {\n", 3600 " var point = points[i];\n", 3601 " var sprite = new THREE.Sprite(spriteMaterial);\n", 3602 " sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[i]].vector,points[edgeindices[i+1]].vector).multiplyScalar(0.5));\n", 3603 " pointlabels.add(sprite);\n", 3604 " }\n", 3605 " }\n", 3606 " obj.add(edgelabels);\n", 3607 "}\n", 3608 "\n", 3609 "function init_arrowheads(obj) {\n", 3610 " var arrowheads = new THREE.Group();\n", 3611 " arrowheads.name = \"arrowheads\";\n", 3612 " var arrowstyle = obj.userData.arrowstyle;\n", 3613 " var edgeindices = obj.userData.edgeindices;\n", 3614 " var edgematerials = obj.userData.edgematerial;\n", 3615 " var points = obj.userData.points;\n", 3616 " var material;\n", 3617 " if (!Array.isArray(edgematerials)) {\n", 3618 " material = new THREE.MeshBasicMaterial( {color: edgematerials.color} );\n", 3619 " }\n", 3620 "\n", 3621 " for (var i=0; i<edgeindices.length; i=i+2) {\n", 3622 " var start = points[edgeindices[i]];\n", 3623 " var end = points[edgeindices[i+1]];\n", 3624 " var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius();\n", 3625 " if (dist <= 0) {\n", 3626 " continue;\n", 3627 " }\n", 3628 " var dir = new THREE.Vector3().subVectors(end.vector,start.vector);\n", 3629 " dir.normalize();\n", 3630 " var axis = new THREE.Vector3().set(dir.z,0,-dir.x);\n", 3631 " axis.normalize();\n", 3632 " var radians = Math.acos( dir.y );\n", 3633 " var radius = dist/25;\n", 3634 " var height = dist/5;\n", 3635 " var geometry = new THREE.ConeBufferGeometry(radius,height);\n", 3636 " var position = new THREE.Vector3().addVectors(start.vector,dir.clone().multiplyScalar(start.radius()+dist-height/2));\n", 3637 " if (Array.isArray(edgematerials)) {\n", 3638 " material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} );\n", 3639 " }\n", 3640 " var cone = new THREE.Mesh( geometry, material );\n", 3641 " cone.quaternion.setFromAxisAngle(axis,radians);;\n", 3642 " cone.position.copy(position);;\n", 3643 " arrowheads.add(cone);\n", 3644 " }\n", 3645 " obj.add(arrowheads);\n", 3646 "}\n", 3647 "\n", 3648 "function init_faces(obj) {\n", 3649 " var points = obj.userData.points;\n", 3650 " var facets = obj.userData.facets;\n", 3651 " obj.userData.triangleindices = [];\n", 3652 " for (var i=0; i<facets.length; i++) {\n", 3653 " facet = facets[i];\n", 3654 " for (var t=0; t<facet.length-2; t++) {\n", 3655 " obj.userData.triangleindices.push(facet[0],facet[t+1],facet[t+2]); \n", 3656 " }\n", 3657 " }\n", 3658 " var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 );\n", 3659 " var bufattr = new THREE.Float32BufferAttribute(bufarr,3);\n", 3660 " \n", 3661 " var materials = obj.userData.facetmaterial;\n", 3662 " var geometry = new THREE.BufferGeometry();\n", 3663 " geometry.setAttribute('position',bufattr);\n", 3664 " if (Array.isArray(materials)) {\n", 3665 " var tricount = 0;\n", 3666 " var facet;\n", 3667 " for (var i=0; i<facets.length; i++) {\n", 3668 " facet = facets[i];\n", 3669 " geometry.addGroup(tricount,(facet.length-2)*3,i);\n", 3670 " tricount += (facet.length-2)*3;\n", 3671 " }\n", 3672 " }\n", 3673 " var mesh = new THREE.Mesh(geometry, materials);\n", 3674 " mesh.name = \"faces\";\n", 3675 " obj.add(mesh); \n", 3676 " updateFacesPosition(obj);\n", 3677 "}\n", 3678 "// //INITIALIZING\n", 3679 "\n", 3680 "\n", 3681 "function updateFacesPosition(obj) {\n", 3682 " var points = obj.userData.points;\n", 3683 " var indices = obj.userData.triangleindices;\n", 3684 " var faces = obj.getObjectByName(\"faces\");\n", 3685 " var ba = faces.geometry.getAttribute(\"position\");\n", 3686 " for (var i=0; i<indices.length; i++) {\n", 3687 " ba.setXYZ(i, points[indices[i]].vector.x, points[indices[i]].vector.y ,points[indices[i]].vector.z); \n", 3688 " }\n", 3689 " faces.geometry.attributes.position.needsUpdate = true;\n", 3690 " \n", 3691 "}\n", 3692 "\n", 3693 "function updateEdgesPosition(obj) {\n", 3694 " var points = obj.userData.points;\n", 3695 " var indices = obj.userData.edgeindices;\n", 3696 " var lines = obj.getObjectByName(\"lines\");\n", 3697 " var ba = lines.geometry.getAttribute(\"position\"); \n", 3698 " for (var i=0; i<indices.length; i++) {\n", 3699 " ba.setXYZ(i, points[indices[i]].vector.x, points[indices[i]].vector.y ,points[indices[i]].vector.z); \n", 3700 " }\n", 3701 " lines.geometry.attributes.position.needsUpdate = true;\n", 3702 "}\n", 3703 "\n", 3704 "function onWindowResize() {\n", 3705 " renderer.setSize( three.clientWidth, three.clientHeight );\n", 3706 " svgRenderer.setSize( three.clientWidth, three.clientHeight );\n", 3707 " updateCamera();\n", 3708 "}\n", 3709 "\n", 3710 "function updateCamera() {\n", 3711 " var width = three.clientWidth;\n", 3712 " var height = three.clientHeight;\n", 3713 " var aspect = width / height;\n", 3714 " if (camera.type == \"OrthographicCamera\") {\n", 3715 " camera.left = frustumSize * aspect / - 2;\n", 3716 " camera.right = frustumSize * aspect / 2;\n", 3717 " camera.top = frustumSize / 2;\n", 3718 " camera.bottom = - frustumSize / 2;\n", 3719 " } else if (camera.type == \"PerspectiveCamera\") {\n", 3720 " camera.aspect = aspect;\n", 3721 " }\n", 3722 " camera.updateProjectionMatrix();\n", 3723 "}\n", 3724 "\n", 3725 "function changeCamera(event) {\n", 3726 " var selindex = event.currentTarget.selectedIndex;\n", 3727 " camera = cameras[selindex];\n", 3728 " control = controls[selindex];\n", 3729 " control.enabled = true; \n", 3730 " for (var i=0; i<controls.length; i++) {\n", 3731 " if (i!=selindex) {\n", 3732 " controls[i].enabled = false;\n", 3733 " }\n", 3734 " }\n", 3735 " updateCamera();\n", 3736 "}\n", 3737 "\n", 3738 "var camtypenode = document.getElementById('cameraType_2');\n", 3739 "camtypenode.onchange = changeCamera;\n", 3740 "camtypenode.dispatchEvent(new Event('change'));\n", 3741 "\n", 3742 "onWindowResize();\n", 3743 "window.addEventListener('resize', onWindowResize);\t\n", 3744 "\n", 3745 "\n", 3746 "var xRotationEnabled = false;\n", 3747 "var yRotationEnabled = false;\n", 3748 "var zRotationEnabled = false;\n", 3749 "var rotationSpeedFactor = 1;\n", 3750 "var settingsShown = false;\n", 3751 "var labelsShown = true;\n", 3752 "var intervals = [];\n", 3753 "var timeouts = [];\n", 3754 "var explodingSpeed = 0.05;\n", 3755 "var explodeScale = 0;\n", 3756 "var XMLS = new XMLSerializer();\n", 3757 "var svgElement;\n", 3758 "var renderId;\n", 3759 "\n", 3760 "var render = function () {\n", 3761 "\n", 3762 "\trenderId = requestAnimationFrame(render);\n", 3763 "\n", 3764 "//\tcomment in for automatic explosion\n", 3765 "//\texplode(updateFactor());\n", 3766 "\n", 3767 " var phi = 0.02 * rotationSpeedFactor;\n", 3768 "\n", 3769 " if (xRotationEnabled) {\n", 3770 " scene.rotation.x += phi;\n", 3771 " }\n", 3772 " if (yRotationEnabled) {\n", 3773 " scene.rotation.y += phi;\n", 3774 " }\n", 3775 " if (zRotationEnabled) {\n", 3776 " scene.rotation.z += phi;\n", 3777 " }\n", 3778 "\n", 3779 " control.update();\n", 3780 " renderer.render(scene, camera);\n", 3781 "};\n", 3782 "\n", 3783 "if ( THREE.WEBGL.isWebGLAvailable() ) {\n", 3784 "\trender();\n", 3785 "} else {\n", 3786 "\tvar warning = WEBGL.getWebGLErrorMessage();\n", 3787 "\tthree.appendChild( warning );\n", 3788 "}\n", 3789 " \n", 3790 "function changeTransparency() {\n", 3791 " var opacity = 1-Number(event.currentTarget.value);\n", 3792 " for (var i=0; i<scene.children.length; i++) {\n", 3793 " child = scene.children[i];\n", 3794 " if ( child.userData.hasOwnProperty(\"facetmaterial\") ) {\n", 3795 " if (Array.isArray(child.userData.facetmaterial)) {\n", 3796 " for (var j=0; j<child.userData.facetmaterial.length; j++) {\n", 3797 " child.userData.facetmaterial[j].opacity = opacity;\n", 3798 " }\n", 3799 " } else {\n", 3800 " child.userData.facetmaterial.opacity = opacity;\n", 3801 " } \n", 3802 " }\n", 3803 " }\n", 3804 "}\n", 3805 "\n", 3806 "function changeRotationX(event){\n", 3807 " xRotationEnabled = event.currentTarget.checked;\n", 3808 "}\t\n", 3809 "\n", 3810 "function changeRotationY(event){\n", 3811 " yRotationEnabled = event.currentTarget.checked;\n", 3812 "}\t\n", 3813 "\n", 3814 "function changeRotationZ(event){\n", 3815 " zRotationEnabled = event.currentTarget.checked;\n", 3816 "}\t\n", 3817 "\n", 3818 "\n", 3819 "function changeRotationSpeedFactor(event){\n", 3820 " rotationSpeedFactor = Number(event.currentTarget.value);\n", 3821 "}\n", 3822 "\n", 3823 "function resetScene(){\n", 3824 " scene.rotation.set(0,0,0);\n", 3825 " camera.position.set(0,0,5);\n", 3826 " camera.up.set(0,1,0);\n", 3827 "}\n", 3828 "\n", 3829 "function showSettings(event){\n", 3830 " document.getElementById('settings_2').style.visibility = 'visible';\n", 3831 " document.getElementById('showSettingsButton_2').style.visibility = 'hidden';\n", 3832 " document.getElementById('hideSettingsButton_2').style.visibility = 'visible';\n", 3833 " settingsShown = true;\n", 3834 "}\n", 3835 "\n", 3836 "function hideSettings(event){\n", 3837 " document.getElementById('settings_2').style.visibility = 'hidden';\n", 3838 " document.getElementById('showSettingsButton_2').style.visibility = 'visible';\n", 3839 " document.getElementById('hideSettingsButton_2').style.visibility = 'hidden';\n", 3840 " settingsShown = false;\n", 3841 "}\n", 3842 "\n", 3843 "\n", 3844 "\n", 3845 "var pos = 150* Math.PI;\n", 3846 "\n", 3847 "function updateFactor() {\n", 3848 " pos++;\n", 3849 " return Math.sin(.01*pos)+1;\n", 3850 "}\n", 3851 "\n", 3852 "// ------------------------ FOLDING ------------------------------------------------\n", 3853 "// ---------------------------------------------------------------------------------\n", 3854 "// rotate point p around axis defined by points p1 and p2 by given angle\n", 3855 "function rotate(p, p1, p2, angle ){ \n", 3856 " angle = -angle;\n", 3857 " var x = p.x, y = p.y, z = p.z, \n", 3858 " a = p1.x, b = p1.y, c = p1.z, \n", 3859 " u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z;\n", 3860 " var result = [];\n", 3861 " var L = u*u + v*v + w*w;\n", 3862 " var sqrt = Math.sqrt;\n", 3863 " var cos = Math.cos;\n", 3864 " var sin = Math.sin;\n", 3865 "\n", 3866 " result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/L;\n", 3867 " result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/L;\n", 3868 " result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/L;\n", 3869 "\n", 3870 " return result;\n", 3871 "}\n", 3872 "\n", 3873 "var fold = function(event){\n", 3874 " var obj = foldables[Number(event.currentTarget.name)];\n", 3875 " var foldvalue = Number(event.currentTarget.value);\n", 3876 " var scale = foldvalue - obj.userData.oldscale;\n", 3877 "\n", 3878 " for (var j=0; j<obj.userData.axes.length; j++) {\n", 3879 " rotateVertices(obj, j, scale);\n", 3880 " }\n", 3881 " update(obj);\n", 3882 " obj.userData.oldscale += scale;\n", 3883 " lookAtBarycenter(obj);\n", 3884 "}\n", 3885 "\n", 3886 "function lookAtBarycenter(obj){\n", 3887 " control.target = barycenter(obj);\n", 3888 "}\n", 3889 "\n", 3890 "function barycenter(obj) {\n", 3891 " var center = new THREE.Vector3(0,0,0);\n", 3892 " var points = obj.userData.points;\n", 3893 " for (var i=0; i<points.length; i++){\n", 3894 " center.add(points[i].vector);\n", 3895 " }\n", 3896 " center.divideScalar(points.length);\n", 3897 " return center;\n", 3898 "}\n", 3899 "\n", 3900 "function rotateVertices(obj, edge, scale) {\n", 3901 " var axes = obj.userData.axes;\n", 3902 " var subtrees = obj.userData.subtrees;\n", 3903 " var points = obj.userData.points;\n", 3904 " var angles = obj.userData.angles;\n", 3905 " if (edge < axes.length){\n", 3906 " for (var j=0; j<subtrees[edge].length; j++){\n", 3907 " var rotP = rotate(points[subtrees[edge][j]].vector, points[axes[edge][0]].vector,points[axes[edge][1]].vector, scale * (Math.PI - angles[edge]));\n", 3908 " points[subtrees[edge][j]].set(rotP[0],rotP[1],rotP[2]);\n", 3909 " }\n", 3910 " }\n", 3911 "}\n", 3912 "\n", 3913 "function update(obj) {\n", 3914 " updateFacesPosition(obj);\n", 3915 " updateEdgesPosition(obj);\n", 3916 "}\n", 3917 "\n", 3918 "if (foldables.length) {\n", 3919 " var settings = document.getElementById('settings_2');\n", 3920 " var foldDiv = document.createElement('div');\n", 3921 " foldDiv.id = 'fold_2';\n", 3922 " var title = document.createElement('strong');\n", 3923 " title.innerHTML = 'Fold';\n", 3924 " foldDiv.appendChild(title);\n", 3925 " foldDiv.className = 'group';\n", 3926 " for (var i=0; i<foldables.length; i++) {\n", 3927 " var range = document.createElement('input');\n", 3928 " range.type = 'range';\n", 3929 " range.min = 0;\n", 3930 " range.max = 1;\n", 3931 " range.value = 0;\n", 3932 " range.step = 0.001;\n", 3933 " range.name = String(i);\n", 3934 " range.oninput = fold;\n", 3935 " foldDiv.appendChild(range);\n", 3936 " }\n", 3937 " lookAtBarycenter(foldables[0]);\n", 3938 " settings.insertBefore(foldDiv,settings.childNodes[0]);\n", 3939 "}\n", 3940 "\n", 3941 " \n", 3942 "// ---------------------- EXPLOSION ------------------------------------------------\n", 3943 "// ---------------------------------------------------------------------------------\n", 3944 "\n", 3945 "if (explodableModel) {\n", 3946 " for (var i=0; i<scene.children.length; i++) {\n", 3947 " obj = scene.children[i];\n", 3948 " if ( obj.userData.explodable ) {\n", 3949 " computeCentroid(obj);\n", 3950 " }\n", 3951 " }\n", 3952 " document.getElementById('explodeRange_2').oninput = triggerExplode;\n", 3953 " document.getElementById('explodeCheckbox_2').onchange = triggerAutomaticExplode;\n", 3954 " document.getElementById('explodingSpeedRange_2').oninput = setExplodingSpeed;\n", 3955 "}\n", 3956 "\n", 3957 "function computeCentroid(obj) {\n", 3958 " centroid = new THREE.Vector3();\n", 3959 " obj.userData.points.forEach(function(pmpoint) {\n", 3960 " centroid.add(pmpoint.vector);\t\t\t\n", 3961 " });\n", 3962 " centroid.divideScalar(obj.userData.points.length);\n", 3963 " obj.userData.centroid = centroid;\n", 3964 "}\n", 3965 "\n", 3966 "function explode(factor) {\n", 3967 " for (var i=0; i<scene.children.length; i++) {\n", 3968 " var obj = scene.children[i];\n", 3969 " if (obj.userData.hasOwnProperty(\"centroid\")) { \n", 3970 " var c = obj.userData.centroid;\n", 3971 " obj.position.set(c.x*factor, c.y*factor, c.z*factor);\n", 3972 " }\n", 3973 " }\t\n", 3974 "}\n", 3975 "\n", 3976 "function triggerExplode(event){\n", 3977 " explodeScale = Number(event.currentTarget.value);\n", 3978 " explode(explodeScale);\n", 3979 "}\n", 3980 "\n", 3981 "function setExplodingSpeed(event){\n", 3982 " explodingSpeed = Number(event.currentTarget.value);\n", 3983 "}\n", 3984 "\n", 3985 "function triggerAutomaticExplode(event){\n", 3986 " if (event.currentTarget.checked){\n", 3987 " startExploding();\n", 3988 " } else {\n", 3989 " clearIntervals();\n", 3990 " }\t\n", 3991 "}\n", 3992 "\n", 3993 "function startExploding(){\n", 3994 " intervals.push(setInterval(explodingInterval, 25));\n", 3995 "}\n", 3996 "\n", 3997 "\n", 3998 "function explodingInterval(){\n", 3999 " explodeScale += explodingSpeed;\n", 4000 " if (explodeScale <= 6){ \n", 4001 " explode(explodeScale);\n", 4002 " }\n", 4003 " else{\n", 4004 " explode(6);\n", 4005 " explodeScale = 6;\n", 4006 " clearIntervals();\n", 4007 " timeouts.push(setTimeout(startUnexploding, 3000));\n", 4008 " }\n", 4009 " document.getElementById('explodeRange_2').value = explodeScale;\n", 4010 "}\n", 4011 "\n", 4012 "\n", 4013 "function startUnexploding(){\n", 4014 " intervals.push(setInterval(unexplodingInterval, 25));\n", 4015 "}\n", 4016 "\n", 4017 "function unexplodingInterval(){\n", 4018 " explodeScale -= explodingSpeed;\n", 4019 " if (explodeScale >= 0){\t\n", 4020 " explode(explodeScale);\n", 4021 " }\n", 4022 " else {\n", 4023 " explode(0);\n", 4024 " explodeScale = 0;\n", 4025 " clearIntervals();\n", 4026 " timeouts.push(setTimeout(startExploding, 3000));\n", 4027 " }\n", 4028 " document.getElementById('explodeRange_2').value = explodeScale;\n", 4029 "}\n", 4030 "\n", 4031 "function clearIntervals(){\n", 4032 " intervals.forEach(function(interval){\n", 4033 " clearInterval(interval);\n", 4034 " });\n", 4035 " intervals = [];\n", 4036 " timeouts.forEach(function(timeout){\n", 4037 " clearTimeout(timeout);\n", 4038 " });\n", 4039 " timeouts = [];\n", 4040 "}\n", 4041 "\n", 4042 "// ---------------------- DISPLAY --------------------------------------------------\n", 4043 "// ---------------------------------------------------------------------------------\n", 4044 "\n", 4045 "const objectTypeInnerHTMLs = { points: \"Points\", pointlabels: \"Point labels\", lines: \"Edges\", edgelabels: \"Edge labels\", faces: \"Faces\", arrowheads: \"Arrow heads\" };\n", 4046 "const objectTypeVisible = {};\n", 4047 "Object.assign(objectTypeVisible,modelContains);\n", 4048 "const sortedObjectTypeKeys = Object.keys(objectTypeInnerHTMLs).sort();\n", 4049 "const shownObjectTypesList = document.getElementById('shownObjectTypesList_2');\n", 4050 "\n", 4051 "function setVisibility(bool,objname) {\n", 4052 " for (var i=0; i<scene.children.length; i++){\n", 4053 " var obj = scene.children[i].getObjectByName(objname);\n", 4054 " if (obj) {\n", 4055 " obj.visible = bool;\n", 4056 " }\n", 4057 " }\n", 4058 "}\n", 4059 "\n", 4060 "function toggleObjectTypeVisibility(event){\n", 4061 " var name = event.currentTarget.name;\n", 4062 " var checked = event.currentTarget.checked;\n", 4063 " objectTypeVisible[name] = checked;\n", 4064 " setVisibility(checked,name);\n", 4065 "}\n", 4066 "\n", 4067 "for (var i=0; i<sortedObjectTypeKeys.length; i++){\n", 4068 " var key = sortedObjectTypeKeys[i];\n", 4069 " if (modelContains[key]) {\n", 4070 " var objTypeNode = document.createElement('span');\n", 4071 " objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '<br>';\n", 4072 " var checkbox = document.createElement('input');\n", 4073 " checkbox.type = 'checkbox';\n", 4074 " checkbox.checked = true;\n", 4075 " checkbox.name = key;\n", 4076 " checkbox.onchange = toggleObjectTypeVisibility;\n", 4077 " shownObjectTypesList.appendChild(checkbox);\n", 4078 " shownObjectTypesList.appendChild(objTypeNode);\n", 4079 " }\n", 4080 "}\n", 4081 "\n", 4082 "// ------------------------------------------------------\n", 4083 "\n", 4084 "function toggleObjectVisibility(event){\n", 4085 " var nr = Number(event.currentTarget.name);\n", 4086 " scene.children[nr].visible = event.currentTarget.checked;\n", 4087 "}\n", 4088 "\n", 4089 "// append checkboxes for displaying or hiding objects\n", 4090 "var shownObjectsList = document.getElementById('shownObjectsList_2');\n", 4091 "for (var i=0; i<scene.children.length; i++){\n", 4092 " obj = scene.children[i];\n", 4093 " var objNode = document.createElement('span');\n", 4094 " objNode.innerHTML = obj.name + '<br>';\n", 4095 " var checkbox = document.createElement('input');\n", 4096 " checkbox.type = 'checkbox';\n", 4097 " checkbox.checked = true;\n", 4098 " checkbox.name = String(i);\n", 4099 " checkbox.onchange = toggleObjectVisibility;\n", 4100 " shownObjectsList.appendChild(checkbox);\n", 4101 " shownObjectsList.appendChild(objNode);\n", 4102 "}\n", 4103 "\n", 4104 "// ---------------------- SVG ------------------------------------------------------\n", 4105 "// ---------------------------------------------------------------------------------\n", 4106 "\n", 4107 "function takeSvgScreenshot() {\n", 4108 " if (objectTypeVisible[\"pointlabels\"]) {\n", 4109 " setVisibility(false,\"pointlabels\");\n", 4110 " }\n", 4111 " if (objectTypeVisible[\"edgelabels\"]) {\n", 4112 " setVisibility(false,\"edgelabels\");\n", 4113 " }\n", 4114 " svgRenderer.render(scene,camera);\n", 4115 " svgElement = XMLS.serializeToString(svgRenderer.domElement);\n", 4116 " \n", 4117 " if (objectTypeVisible[\"pointlabels\"]) {\n", 4118 " setVisibility(true,\"pointlabels\");\n", 4119 " }\n", 4120 " if (objectTypeVisible[\"edgelabels\"]) {\n", 4121 " setVisibility(true,\"edgelabels\");\n", 4122 " }\n", 4123 "\n", 4124 " if (document.getElementById('tab_2').checked){\n", 4125 " //show in new tab\n", 4126 " var myWindow = window.open(\"\",\"\");\n", 4127 " myWindow.document.body.innerHTML = svgElement;\n", 4128 " } else{\n", 4129 " // download svg file \n", 4130 " download(\"screenshot.svg\", svgElement);\n", 4131 " }\n", 4132 "}\n", 4133 "\n", 4134 "function download(filename, text) {\n", 4135 " var element = document.createElement('a');\n", 4136 " element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));\n", 4137 " element.setAttribute('download', filename);\n", 4138 "\n", 4139 " element.style.display = 'none';\n", 4140 " document.body.appendChild(element);\n", 4141 "\n", 4142 " element.click();\n", 4143 "\n", 4144 " document.body.removeChild(element);\n", 4145 "}\n", 4146 "\n", 4147 "\n", 4148 "document.getElementById('transparencyRange_2').oninput = changeTransparency;\n", 4149 "document.getElementById('changeRotationX_2').onchange = changeRotationX;\n", 4150 "document.getElementById('changeRotationY_2').onchange = changeRotationY;\n", 4151 "document.getElementById('changeRotationZ_2').onchange = changeRotationZ;\n", 4152 "document.getElementById('resetButton_2').onclick = resetScene;\n", 4153 "document.getElementById('rotationSpeedRange_2').oninput = changeRotationSpeedFactor;\n", 4154 "document.getElementById('takeScreenshot_2').onclick = takeSvgScreenshot;\n", 4155 "document.getElementById('showSettingsButton_2').onclick = showSettings;\n", 4156 "document.getElementById('hideSettingsButton_2').onclick = hideSettings;\n", 4157 "\n", 4158 "\n", 4159 "// ------------------ SHORTCUTS --------------------------------------------\n", 4160 "// -------------------------------------------------------------------------\n", 4161 "\n", 4162 "/**\n", 4163 " * http://www.openjs.com/scripts/events/keyboard_shortcuts/\n", 4164 " * Version : 2.01.B\n", 4165 " * By Binny V A\n", 4166 " * License : BSD\n", 4167 " */\n", 4168 "shortcut = {\n", 4169 "\t'all_shortcuts':{},//All the shortcuts are stored in this array\n", 4170 "\t'add': function(shortcut_combination,callback,opt) {\n", 4171 "\t\t//Provide a set of default options\n", 4172 "\t\tvar default_options = {\n", 4173 "\t\t\t'type':'keydown',\n", 4174 "\t\t\t'propagate':false,\n", 4175 "\t\t\t'disable_in_input':false,\n", 4176 "\t\t\t'target':document,\n", 4177 "\t\t\t'keycode':false\n", 4178 "\t\t}\n", 4179 "\t\tif(!opt) opt = default_options;\n", 4180 "\t\telse {\n", 4181 "\t\t\tfor(var dfo in default_options) {\n", 4182 "\t\t\t\tif(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];\n", 4183 "\t\t\t}\n", 4184 "\t\t}\n", 4185 "\n", 4186 "\t\tvar ele = opt.target;\n", 4187 "\t\tif(typeof opt.target == 'string') ele = document.getElementById(opt.target);\n", 4188 "\t\tvar ths = this;\n", 4189 "\t\tshortcut_combination = shortcut_combination.toLowerCase();\n", 4190 "\n", 4191 "\t\t//The function to be called at keypress\n", 4192 "\t\tvar func = function(e) {\n", 4193 "\t\t\te = e || window.event;\n", 4194 "\t\t\t\n", 4195 "\t\t\tif(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields\n", 4196 "\t\t\t\tvar element;\n", 4197 "\t\t\t\tif(e.target) element=e.target;\n", 4198 "\t\t\t\telse if(e.srcElement) element=e.srcElement;\n", 4199 "\t\t\t\tif(element.nodeType==3) element=element.parentNode;\n", 4200 "\n", 4201 "\t\t\t\tif(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;\n", 4202 "\t\t\t}\n", 4203 "\t\n", 4204 "\t\t\t//Find Which key is pressed\n", 4205 "\t\t\tif (e.keyCode) code = e.keyCode;\n", 4206 "\t\t\telse if (e.which) code = e.which;\n", 4207 "\t\t\tvar character = String.fromCharCode(code).toLowerCase();\n", 4208 "\t\t\t\n", 4209 "\t\t\tif(code == 188) character=\",\"; //If the user presses , when the type is onkeydown\n", 4210 "\t\t\tif(code == 190) character=\".\"; //If the user presses , when the type is onkeydown\n", 4211 "\n", 4212 "\t\t\tvar keys = shortcut_combination.split(\"+\");\n", 4213 "\t\t\t//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked\n", 4214 "\t\t\tvar kp = 0;\n", 4215 "\t\t\t\n", 4216 "\t\t\t//Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken\n", 4217 "\t\t\tvar shift_nums = {\n", 4218 "\t\t\t\t\"`\":\"~\",\n", 4219 "\t\t\t\t\"1\":\"!\",\n", 4220 "\t\t\t\t\"2\":\"@\",\n", 4221 "\t\t\t\t\"3\":\"#\",\n", 4222 "\t\t\t\t\"4\":\"$\",\n", 4223 "\t\t\t\t\"5\":\"%\",\n", 4224 "\t\t\t\t\"6\":\"^\",\n", 4225 "\t\t\t\t\"7\":\"&\",\n", 4226 "\t\t\t\t\"8\":\"*\",\n", 4227 "\t\t\t\t\"9\":\"(\",\n", 4228 "\t\t\t\t\"0\":\")\",\n", 4229 "\t\t\t\t\"-\":\"_\",\n", 4230 "\t\t\t\t\"=\":\"+\",\n", 4231 "\t\t\t\t\";\":\":\",\n", 4232 "\t\t\t\t\"'\":\"\\\"\",\n", 4233 "\t\t\t\t\",\":\"<\",\n", 4234 "\t\t\t\t\".\":\">\",\n", 4235 "\t\t\t\t\"/\":\"?\",\n", 4236 "\t\t\t\t\"\\\\\":\"|\"\n", 4237 "\t\t\t}\n", 4238 "\t\t\t//Special Keys - and their codes\n", 4239 "\t\t\tvar special_keys = {\n", 4240 "\t\t\t\t'esc':27,\n", 4241 "\t\t\t\t'escape':27,\n", 4242 "\t\t\t\t'tab':9,\n", 4243 "\t\t\t\t'space':32,\n", 4244 "\t\t\t\t'return':13,\n", 4245 "\t\t\t\t'enter':13,\n", 4246 "\t\t\t\t'backspace':8,\n", 4247 "\t\n", 4248 "\t\t\t\t'scrolllock':145,\n", 4249 "\t\t\t\t'scroll_lock':145,\n", 4250 "\t\t\t\t'scroll':145,\n", 4251 "\t\t\t\t'capslock':20,\n", 4252 "\t\t\t\t'caps_lock':20,\n", 4253 "\t\t\t\t'caps':20,\n", 4254 "\t\t\t\t'numlock':144,\n", 4255 "\t\t\t\t'num_lock':144,\n", 4256 "\t\t\t\t'num':144,\n", 4257 "\t\t\t\t\n", 4258 "\t\t\t\t'pause':19,\n", 4259 "\t\t\t\t'break':19,\n", 4260 "\t\t\t\t\n", 4261 "\t\t\t\t'insert':45,\n", 4262 "\t\t\t\t'home':36,\n", 4263 "\t\t\t\t'delete':46,\n", 4264 "\t\t\t\t'end':35,\n", 4265 "\t\t\t\t\n", 4266 "\t\t\t\t'pageup':33,\n", 4267 "\t\t\t\t'page_up':33,\n", 4268 "\t\t\t\t'pu':33,\n", 4269 "\t\n", 4270 "\t\t\t\t'pagedown':34,\n", 4271 "\t\t\t\t'page_down':34,\n", 4272 "\t\t\t\t'pd':34,\n", 4273 "\t\n", 4274 "\t\t\t\t'left':37,\n", 4275 "\t\t\t\t'up':38,\n", 4276 "\t\t\t\t'right':39,\n", 4277 "\t\t\t\t'down':40,\n", 4278 "\t\n", 4279 "\t\t\t\t'f1':112,\n", 4280 "\t\t\t\t'f2':113,\n", 4281 "\t\t\t\t'f3':114,\n", 4282 "\t\t\t\t'f4':115,\n", 4283 "\t\t\t\t'f5':116,\n", 4284 "\t\t\t\t'f6':117,\n", 4285 "\t\t\t\t'f7':118,\n", 4286 "\t\t\t\t'f8':119,\n", 4287 "\t\t\t\t'f9':120,\n", 4288 "\t\t\t\t'f10':121,\n", 4289 "\t\t\t\t'f11':122,\n", 4290 "\t\t\t\t'f12':123\n", 4291 "\t\t\t}\n", 4292 "\t\n", 4293 "\t\t\tvar modifiers = { \n", 4294 "\t\t\t\tshift: { wanted:false, pressed:false},\n", 4295 "\t\t\t\tctrl : { wanted:false, pressed:false},\n", 4296 "\t\t\t\talt : { wanted:false, pressed:false},\n", 4297 "\t\t\t\tmeta : { wanted:false, pressed:false}\t//Meta is Mac specific\n", 4298 "\t\t\t};\n", 4299 " \n", 4300 "\t\t\tif(e.ctrlKey)\tmodifiers.ctrl.pressed = true;\n", 4301 "\t\t\tif(e.shiftKey)\tmodifiers.shift.pressed = true;\n", 4302 "\t\t\tif(e.altKey)\tmodifiers.alt.pressed = true;\n", 4303 "\t\t\tif(e.metaKey) modifiers.meta.pressed = true;\n", 4304 " \n", 4305 "\t\t\tfor(var i=0; k=keys[i],i<keys.length; i++) {\n", 4306 "\t\t\t\t//Modifiers\n", 4307 "\t\t\t\tif(k == 'ctrl' || k == 'control') {\n", 4308 "\t\t\t\t\tkp++;\n", 4309 "\t\t\t\t\tmodifiers.ctrl.wanted = true;\n", 4310 "\n", 4311 "\t\t\t\t} else if(k == 'shift') {\n", 4312 "\t\t\t\t\tkp++;\n", 4313 "\t\t\t\t\tmodifiers.shift.wanted = true;\n", 4314 "\n", 4315 "\t\t\t\t} else if(k == 'alt') {\n", 4316 "\t\t\t\t\tkp++;\n", 4317 "\t\t\t\t\tmodifiers.alt.wanted = true;\n", 4318 "\t\t\t\t} else if(k == 'meta') {\n", 4319 "\t\t\t\t\tkp++;\n", 4320 "\t\t\t\t\tmodifiers.meta.wanted = true;\n", 4321 "\t\t\t\t} else if(k.length > 1) { //If it is a special key\n", 4322 "\t\t\t\t\tif(special_keys[k] == code) kp++;\n", 4323 "\t\t\t\t\t\n", 4324 "\t\t\t\t} else if(opt['keycode']) {\n", 4325 "\t\t\t\t\tif(opt['keycode'] == code) kp++;\n", 4326 "\n", 4327 "\t\t\t\t} else { //The special keys did not match\n", 4328 "\t\t\t\t\tif(character == k) kp++;\n", 4329 "\t\t\t\t\telse {\n", 4330 "\t\t\t\t\t\tif(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase\n", 4331 "\t\t\t\t\t\t\tcharacter = shift_nums[character]; \n", 4332 "\t\t\t\t\t\t\tif(character == k) kp++;\n", 4333 "\t\t\t\t\t\t}\n", 4334 "\t\t\t\t\t}\n", 4335 "\t\t\t\t}\n", 4336 "\t\t\t}\n", 4337 "\t\t\t\n", 4338 "\t\t\tif(kp == keys.length && \n", 4339 "\t\t\t\t\t\tmodifiers.ctrl.pressed == modifiers.ctrl.wanted &&\n", 4340 "\t\t\t\t\t\tmodifiers.shift.pressed == modifiers.shift.wanted &&\n", 4341 "\t\t\t\t\t\tmodifiers.alt.pressed == modifiers.alt.wanted &&\n", 4342 "\t\t\t\t\t\tmodifiers.meta.pressed == modifiers.meta.wanted) {\n", 4343 "\t\t\t\tcallback(e);\n", 4344 "\t\n", 4345 "\t\t\t\tif(!opt['propagate']) { //Stop the event\n", 4346 "\t\t\t\t\t//e.cancelBubble is supported by IE - this will kill the bubbling process.\n", 4347 "\t\t\t\t\te.cancelBubble = true;\n", 4348 "\t\t\t\t\te.returnValue = false;\n", 4349 "\t\n", 4350 "\t\t\t\t\t//e.stopPropagation works in Firefox.\n", 4351 "\t\t\t\t\tif (e.stopPropagation) {\n", 4352 "\t\t\t\t\t\te.stopPropagation();\n", 4353 "\t\t\t\t\t\te.preventDefault();\n", 4354 "\t\t\t\t\t}\n", 4355 "\t\t\t\t\treturn false;\n", 4356 "\t\t\t\t}\n", 4357 "\t\t\t}\n", 4358 "\t\t}\n", 4359 "\t\tthis.all_shortcuts[shortcut_combination] = {\n", 4360 "\t\t\t'callback':func, \n", 4361 "\t\t\t'target':ele, \n", 4362 "\t\t\t'event': opt['type']\n", 4363 "\t\t};\n", 4364 "\t\t//Attach the function with the event\n", 4365 "\t\tif(ele.addEventListener) ele.addEventListener(opt['type'], func, false);\n", 4366 "\t\telse if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);\n", 4367 "\t\telse ele['on'+opt['type']] = func;\n", 4368 "\t},\n", 4369 "\n", 4370 "\t//Remove the shortcut - just specify the shortcut and I will remove the binding\n", 4371 "\t'remove':function(shortcut_combination) {\n", 4372 "\t\tshortcut_combination = shortcut_combination.toLowerCase();\n", 4373 "\t\tvar binding = this.all_shortcuts[shortcut_combination];\n", 4374 "\t\tdelete(this.all_shortcuts[shortcut_combination])\n", 4375 "\t\tif(!binding) return;\n", 4376 "\t\tvar type = binding['event'];\n", 4377 "\t\tvar ele = binding['target'];\n", 4378 "\t\tvar callback = binding['callback'];\n", 4379 "\n", 4380 "\t\tif(ele.detachEvent) ele.detachEvent('on'+type, callback);\n", 4381 "\t\telse if(ele.removeEventListener) ele.removeEventListener(type, callback, false);\n", 4382 "\t\telse ele['on'+type] = false;\n", 4383 "\t}\n", 4384 "}\n", 4385 "\n", 4386 "shortcut.add(\"Alt+Left\",function() {\n", 4387 "\tvar event = new Event('click');\n", 4388 "\tif (settingsShown){\n", 4389 "\t\tdocument.getElementById('hideSettingsButton_2').dispatchEvent(event);\n", 4390 "\t} else {\n", 4391 "\t\tdocument.getElementById('showSettingsButton_2').dispatchEvent(event);\n", 4392 "\t}\n", 4393 "});\n", 4394 "\n", 4395 "\n", 4396 "// COMMON_CODE_BLOCK_END\n", 4397 "\n", 4398 "});});\n", 4399 " </script>\n", 4400 " </body>\n", 4401 "</html>" 4402 ] 4403 }, 4404 "metadata": {}, 4405 "output_type": "display_data" 4406 } 4407 ], 4408 "source": [ 4409 "$integer_hull=new Polytope<Rational>(POINTS=>$scaled_rs->LATTICE_POINTS);\n", 4410 "$integer_hull->VISUAL->LATTICE_COLORED;" 4411 ] 4412 }, 4413 { 4414 "cell_type": "markdown", 4415 "metadata": {}, 4416 "source": [ 4417 " \n" 4418 ] 4419 }, 4420 { 4421 "cell_type": "markdown", 4422 "metadata": {}, 4423 "source": [ 4424 "\n", 4425 "In order to obtain the integer hull we simply define a new polytope `$integer_hull` as the convex hull of all `LATTICE_POINTS` contained in `$scaled_rs`.\n", 4426 "\n", 4427 "Note that if we give `POINTS` (in contrast to `VERTICES`) `polymake` constructs a polytope that is the convex hull of the given points regardless of whether they are vertices or not. I.e., redundacies are allowed here.\n", 4428 "\n", 4429 "If you specify `VERTICES` you have to make sure yourself that your points are actually vertices since `polymake` does not check this. You also need to specify the `LINEALITY_SPACE`, see [ Tutorial on polytopes](apps_polytope.ipynb).\n", 4430 "\n", 4431 "### Linear Programming\n", 4432 "\n", 4433 "Now that we have constructed a nice integral polytope we want to apply some linear program to it.\n", 4434 "\n", 4435 "First we define a `LinearProgram` with our favourite `LINEAR_OBJECTIVE`. The linear objective is an given as a vector of length d+1, d being the dimension of the space. The vector [c<sub>0</sub>,c<sub>1</sub>, ..., c<sub>d</sub>] corresponds to the linear objective c<sub>0</sub> + c<sub>1</sub>x<sub>1</sub> + ... + c<sub>d</sub>x<sub>d</sub>.\n", 4436 "\n", 4437 " \n" 4438 ] 4439 }, 4440 { 4441 "cell_type": "code", 4442 "execution_count": 15, 4443 "metadata": {}, 4444 "outputs": [], 4445 "source": [ 4446 "$objective=new LinearProgram<Rational>(LINEAR_OBJECTIVE=>[0,1,1,1]);" 4447 ] 4448 }, 4449 { 4450 "cell_type": "markdown", 4451 "metadata": {}, 4452 "source": [ 4453 "\n", 4454 "Then we define a new polytope, which is a copy of our old one (`$inter_hull`) with the LP as an additional property.\n", 4455 "\n", 4456 " \n" 4457 ] 4458 }, 4459 { 4460 "cell_type": "code", 4461 "execution_count": 16, 4462 "metadata": {}, 4463 "outputs": [], 4464 "source": [ 4465 "$ilp=new Polytope<Rational>(VERTICES=>$integer_hull->VERTICES, LP=>$objective);" 4466 ] 4467 }, 4468 { 4469 "attachments": { 4470 "ilp_max_face.png": { 4471 "image/png": "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" 4472 }, 4473 "ilp_min_face.png": { 4474 "image/png": "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" 4475 } 4476 }, 4477 "cell_type": "markdown", 4478 "metadata": {}, 4479 "source": [ 4480 "![ilp_min_face.png](attachment:ilp_min_face.png)\n", 4481 "![ilp_max_face.png](attachment:ilp_max_face.png)\n", 4482 "\n", 4483 "And now we can perform some computations:" 4484 ] 4485 }, 4486 { 4487 "cell_type": "code", 4488 "execution_count": 17, 4489 "metadata": {}, 4490 "outputs": [ 4491 { 4492 "data": { 4493 "text/plain": [ 4494 "2" 4495 ] 4496 }, 4497 "execution_count": 17, 4498 "metadata": {}, 4499 "output_type": "execute_result" 4500 } 4501 ], 4502 "source": [ 4503 "print $ilp->LP->MAXIMAL_VALUE;" 4504 ] 4505 }, 4506 { 4507 "cell_type": "code", 4508 "execution_count": 18, 4509 "metadata": {}, 4510 "outputs": [ 4511 { 4512 "data": { 4513 "text/plain": [ 4514 "{8 10 11}" 4515 ] 4516 }, 4517 "execution_count": 18, 4518 "metadata": {}, 4519 "output_type": "execute_result" 4520 } 4521 ], 4522 "source": [ 4523 "print $ilp->LP->MAXIMAL_FACE;" 4524 ] 4525 }, 4526 { 4527 "cell_type": "code", 4528 "execution_count": 19, 4529 "metadata": {}, 4530 "outputs": [ 4531 { 4532 "data": { 4533 "text/html": [ 4534 "<!--\n", 4535 "polymake for knusper\n", 4536 "Thu Aug 27 11:38:20 2020\n", 4537 "ilp\n", 4538 "-->\n", 4539 "\n", 4540 "\n", 4541 "<html>\n", 4542 " <head>\n", 4543 " <meta charset=utf-8>\n", 4544 " <title>ilp</title>\n", 4545 " <style>\n", 4546 "/*\n", 4547 "// COMMON_CODE_BLOCK_BEGIN\n", 4548 "*/\n", 4549 " html {overflow: scroll;}\n", 4550 " strong{font-size: 18px;}\n", 4551 " canvas { z-index: 8; }\n", 4552 " input[type='radio'] {margin-left:0;}\n", 4553 " input[type='checkbox'] {margin-right:7px; margin-left: 0px; padding-left:0px;}\n", 4554 " .group{padding-bottom: 15px;}\n", 4555 " .settings * {z-index: 11; }\n", 4556 " .settings{z-index: 10; font-family: Arial, Helvetica, sans-serif; margin-left: 30px; visibility: hidden; width: 14em; height: 96%; border: solid 1px silver; padding: 2px; overflow-y: scroll; box-sizing: border-box; background-color: white; position: absolute;}\n", 4557 " .indented{margin-left: 20px; margin-top: 10px; padding-bottom: 0px;} \n", 4558 " .shownObjectsList{overflow: auto; max-width: 150px; max-height: 150px;}\n", 4559 " .showSettingsButton{visibility: visible; z-index: 12; position: absolute }\n", 4560 " .hideSettingsButton{visibility: hidden; z-index: 12; position: absolute; opacity: 0.5}\n", 4561 " button{margin-left: 0; margin-top: 10px}\n", 4562 " img{cursor: pointer;}\n", 4563 " .suboption{padding-top: 15px;}\n", 4564 " #model31430920245 { width: 100%; height: 100%; }\n", 4565 " .threejs_container { width: 100%; height: 75vh;}\n", 4566 " .settings{max-height: 74vh} \n", 4567 " input[type=range] {\n", 4568 " -webkit-appearance: none;\n", 4569 " padding:0; \n", 4570 " width:90%; \n", 4571 " margin-left: auto;\n", 4572 " margin-right: auto;\n", 4573 " margin-top: 15px;\n", 4574 " margin-bottom: 15px;\n", 4575 " display: block;\t\n", 4576 " }\n", 4577 " input[type=range]:focus {\n", 4578 " outline: none;\n", 4579 " }\n", 4580 " input[type=range]::-webkit-slider-runnable-track {\n", 4581 " height: 4px;\n", 4582 " cursor: pointer;\n", 4583 " animate: 0.2s;\n", 4584 " box-shadow: 0px 0px 0px #000000;\n", 4585 " background: #E3E3E3;\n", 4586 " border-radius: 0px;\n", 4587 " border: 0px solid #000000;\n", 4588 " }\n", 4589 " input[type=range]::-webkit-slider-thumb {\n", 4590 " box-shadow: 1px 1px 2px #B8B8B8;\n", 4591 " border: 1px solid #ABABAB;\n", 4592 " height: 13px;\n", 4593 " width: 25px;\n", 4594 " border-radius: 20px;\n", 4595 " background: #E0E0E0;\n", 4596 " cursor: pointer;\n", 4597 " -webkit-appearance: none;\n", 4598 " margin-top: -5px;\n", 4599 " }\n", 4600 " input[type=range]:focus::-webkit-slider-runnable-track {\n", 4601 " background: #E3E3E3;\n", 4602 " }\n", 4603 " input[type=range]::-moz-range-track {\n", 4604 " height: 4px;\n", 4605 " cursor: pointer;\n", 4606 " animate: 0.2s;\n", 4607 " box-shadow: 0px 0px 0px #000000;\n", 4608 " background: #E3E3E3;\n", 4609 " border-radius: 0px;\n", 4610 " border: 0px solid #000000;\n", 4611 " }\n", 4612 " input[type=range]::-moz-range-thumb {\n", 4613 " box-shadow: 1px 1px 2px #B8B8B8;\n", 4614 " border: 1px solid #ABABAB;\n", 4615 " height: 13px;\n", 4616 " width: 25px;\n", 4617 " border-radius: 20px;\n", 4618 " background: #E0E0E0;\n", 4619 " cursor: pointer;\n", 4620 " }\n", 4621 " input[type=range]::-ms-track {\n", 4622 " height: 4px;\n", 4623 " cursor: pointer;\n", 4624 " animate: 0.2s;\n", 4625 " background: transparent;\n", 4626 " border-color: transparent;\n", 4627 " color: transparent;\n", 4628 " }\n", 4629 " input[type=range]::-ms-fill-lower {\n", 4630 " background: #E3E3E3;\n", 4631 " border: 0px solid #000000;\n", 4632 " border-radius: 0px;\n", 4633 " box-shadow: 0px 0px 0px #000000;\n", 4634 " }\n", 4635 " input[type=range]::-ms-fill-upper {\n", 4636 " background: #E3E3E3;\n", 4637 " border: 0px solid #000000;\n", 4638 " border-radius: 0px;\n", 4639 " box-shadow: 0px 0px 0px #000000;\n", 4640 " }\n", 4641 " input[type=range]::-ms-thumb {\n", 4642 " box-shadow: 1px 1px 2px #B8B8B8;\n", 4643 " border: 1px solid #ABABAB;\n", 4644 " height: 13px;\n", 4645 " width: 25px;\n", 4646 " border-radius: 20px;\n", 4647 " background: #E0E0E0;\n", 4648 " cursor: pointer;\n", 4649 " }\n", 4650 " input[type=range]:focus::-ms-fill-lower {\n", 4651 " background: #E3E3E3;\n", 4652 " }\n", 4653 " input[type=range]:focus::-ms-fill-upper {\n", 4654 " background: #E3E3E3;\n", 4655 " }\n", 4656 "/*\n", 4657 "// COMMON_CODE_BLOCK_END\n", 4658 "*/\n", 4659 "\t\t</style>\n", 4660 " </head>\n", 4661 "<body>\n", 4662 " <div class='threejs_container'>\n", 4663 "\t\t<div id='settings_3' class='settings'>\n", 4664 "\t\t\t<div class=group id='transparency_3' class='transparency'>\n", 4665 "\t\t\t\t<strong>Transparency</strong>\n", 4666 "\t\t\t\t<input id='transparencyRange_3' type='range' min=0 max=1 step=0.01 value=0>\n", 4667 "\t\t\t</div>\n", 4668 "\t\t\t\n", 4669 "\t\t\t<div class=group id='rotation_3'>\n", 4670 "\t\t\t\t<strong>Rotation</strong>\n", 4671 "\t\t\t\t<div class=indented>\n", 4672 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationX_3'> x-axis</div>\n", 4673 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationY_3'> y-axis</div>\n", 4674 "\t\t\t\t\t<div><input type='checkbox' id='changeRotationZ_3'> z-axis</div>\n", 4675 "\t\t\t\t\t<button id='resetButton_3'>Reset</button>\n", 4676 "\t\t\t\t</div>\n", 4677 "\n", 4678 "\t\t\t\t<div class=suboption>Rotation speed</div>\n", 4679 "\t\t\t\t<input id='rotationSpeedRange_3' type='range' min=0 max=5 step=0.01 value=2>\n", 4680 "\t\t\t</div>\n", 4681 "\n", 4682 "\n", 4683 "\t\t\t<div class=group id='display_3'>\n", 4684 "\t\t\t\t<strong>Display</strong>\n", 4685 "\t\t\t\t<div class=indented>\n", 4686 "\t\t\t\t\t<div id='shownObjectTypesList_3' class='shownObjectsList'></div>\n", 4687 "\t\t\t\t</div>\n", 4688 "\t\t\t\t<div class=suboption>Objects</div>\n", 4689 "\t\t\t\t<div class=indented>\n", 4690 "\t\t\t\t <div id='shownObjectsList_3' class='shownObjectsList'></div>\n", 4691 "\t\t\t\t</div>\n", 4692 "\t\t\t</div>\n", 4693 " \n", 4694 " <div class=group id='camera_3'>\n", 4695 " <strong>Camera</strong>\n", 4696 " <div class=indented>\n", 4697 " <form>\n", 4698 " <select id=\"cameraType_3\">\n", 4699 " <option value='perspective' selected> Perspective<br></option>\n", 4700 " <option value='orthographic' > Orthographic<br></option>\n", 4701 " </select>\n", 4702 " </form>\n", 4703 " </div>\n", 4704 " </div>\n", 4705 "\n", 4706 "\t\t\t<div class=group id='svg_3'>\n", 4707 "\t\t\t\t<strong>SVG</strong>\n", 4708 "\t\t\t\t<div class=indented>\n", 4709 "\t\t\t\t\t<form>\n", 4710 "\t\t\t\t\t\t<input type=\"radio\" name='screenshotMode' value='download' id='download_3' checked> Download<br>\n", 4711 "\t\t\t\t\t\t<input type=\"radio\" name='screenshotMode' value='tab' id='tab_3' > New tab<br>\n", 4712 "\t\t\t\t\t</form>\n", 4713 "\t\t\t\t\t<button id='takeScreenshot_3'>Screenshot</button>\n", 4714 "\t\t\t\t</div>\n", 4715 "\t\t\t</div>\n", 4716 "\n", 4717 "\t\t</div>\t<!-- end of settings -->\n", 4718 "\t\t<img id='hideSettingsButton_3' class='hideSettingsButton' src='/kernelspecs/polymake/close.svg' width=20px\">\n", 4719 "\t\t<img id='showSettingsButton_3' class='showSettingsButton' src='/kernelspecs/polymake/menu.svg' width=20px\">\n", 4720 "<div id=\"model31430920245\"></div>\n", 4721 "</div>\n", 4722 " <script>\n", 4723 " requirejs.config({\n", 4724 " paths: {\n", 4725 " three: '/kernelspecs/polymake/three',\n", 4726 " TrackballControls: '/kernelspecs/polymake/TrackballControls',\n", 4727 " OrbitControls: '/kernelspecs/polymake/OrbitControls',\n", 4728 " Projector: '/kernelspecs/polymake/Projector',\n", 4729 " SVGRenderer: '/kernelspecs/polymake/SVGRenderer',\n", 4730 " WEBGL: '/kernelspecs/polymake/WebGL',\n", 4731 " },\n", 4732 " shim: {\n", 4733 " 'three': { exports: 'THREE'},\n", 4734 " 'SVGRenderer': { deps: [ 'three' ], exports: 'THREE.SVGRenderer' },\n", 4735 " 'WEBGL': { deps: [ 'three' ], exports: 'THREE.WEBGL' },\n", 4736 " 'Projector': { deps: [ 'three' ], exports: 'THREE.Projector' },\n", 4737 " 'TrackballControls': { deps: [ 'three' ], exports: 'THREE.TrackballControls' },\n", 4738 " 'OrbitControls': { deps: [ 'three' ], exports: 'THREE.OrbitControls' },\n", 4739 " }\n", 4740 " });\n", 4741 " \n", 4742 " require(['three'],function(THREE){\n", 4743 " window.THREE = THREE;\n", 4744 " require(['TrackballControls', 'OrbitControls', 'Projector', 'SVGRenderer', 'WEBGL'],\n", 4745 " function(TrackballControls, OrbitControls, Projector, SVGRenderer, WEBGL) {\n", 4746 " THREE.TrackballControls = TrackballControls;\n", 4747 " THREE.OrbitControls = OrbitControls;\n", 4748 " THREE.Projector = Projector;\n", 4749 " THREE.SVGRenderer = SVGRenderer;\n", 4750 " THREE.WEBGL = WEBGL;\n", 4751 "\n", 4752 "// COMMON_CODE_BLOCK_BEGIN\n", 4753 "\n", 4754 "const intervalLength = 25; // for automatic animations\n", 4755 "const explodableModel = false; \n", 4756 "const modelContains = { points: false, pointlabels: false, lines: false, edgelabels: false, faces: false, arrowheads: false };\n", 4757 "const foldables = [];\n", 4758 "\n", 4759 "var three = document.getElementById(\"model31430920245\");\n", 4760 "var scene = new THREE.Scene();\n", 4761 "var renderer = new THREE.WebGLRenderer( { antialias: true } );\n", 4762 "var svgRenderer = new THREE.SVGRenderer( { antialias: true } );\n", 4763 "renderer.setPixelRatio( window.devicePixelRatio );\n", 4764 "renderer.setClearColor(0xFFFFFF, 1);\n", 4765 "svgRenderer.setClearColor(0xFFFFFF, 1);\n", 4766 "three.appendChild(renderer.domElement);\n", 4767 "\n", 4768 "var frustumSize = 4;\n", 4769 "var cameras = [new THREE.PerspectiveCamera(75, 1, 0.1, 1000), new THREE.OrthographicCamera()];\n", 4770 "cameras.forEach(function(cam) {\n", 4771 " cam.position.set(0, 0, 5);\n", 4772 " cam.lookAt(0, 0, 0); \n", 4773 " cam.up.set(0, 1, 0); \n", 4774 "});\n", 4775 "var controls = [new THREE.TrackballControls(cameras[0], three), new THREE.OrbitControls(cameras[1], three)];\n", 4776 "var camera, control;\n", 4777 "\n", 4778 "controls[0].zoomSpeed = 0.2;\n", 4779 "controls[0].rotateSpeed = 4;\n", 4780 "\n", 4781 "\n", 4782 "// class to allow move points together with labels and spheres\n", 4783 "var PMPoint = function (x,y,z) {\n", 4784 " this.vector = new THREE.Vector3(x,y,z);\n", 4785 " this.sprite = null;\n", 4786 " this.sphere = null;\n", 4787 "}\n", 4788 "PMPoint.prototype.addLabel = function(labelsprite) {\n", 4789 " this.sprite = labelsprite;\n", 4790 " this.sprite.position.copy(this.vector);\n", 4791 "}\n", 4792 "PMPoint.prototype.addSphere = function(spheremesh) {\n", 4793 " this.sphere = spheremesh;\n", 4794 " this.sphere.position.copy(this.vector);\n", 4795 "}\n", 4796 "PMPoint.prototype.set = function(x,y,z) {\n", 4797 " this.vector.set(x,y,z);\n", 4798 " if (this.sprite) {\n", 4799 " this.sprite.position.copy(this.vector);\n", 4800 " }\n", 4801 " if (this.sphere) {\n", 4802 " this.sphere.position.copy(this.vector);\n", 4803 " }\n", 4804 "}\n", 4805 "PMPoint.prototype.radius = function() {\n", 4806 " if (this.sphere) {\n", 4807 " return this.sphere.geometry.parameters.radius;\n", 4808 " } else {\n", 4809 " return 0;\n", 4810 " }\n", 4811 "};\n", 4812 "// select the target node\n", 4813 "var target = document.querySelector('#model31430920245');\n", 4814 "\n", 4815 "// create an observer instance\n", 4816 "var observer = new MutationObserver(function(mutations) {\n", 4817 " mutations.forEach(function(mutation) {\n", 4818 " if (mutation.removedNodes && mutation.removedNodes.length > 0) {\n", 4819 " cancelAnimationFrame(renderId);\n", 4820 " observer.disconnect();\n", 4821 " console.log(\"cancelled frame \"+renderId);\n", 4822 " }\n", 4823 " });\n", 4824 "});\n", 4825 "\n", 4826 "// configuration of the observer:\n", 4827 "var config = { childList: true, characterData: true }\n", 4828 "\n", 4829 "// pass in the target node, as well as the observer options\n", 4830 "while (target) {\n", 4831 " if (target.className==\"output\") {\n", 4832 " observer.observe(target, config);\n", 4833 " break;\n", 4834 " }\n", 4835 " target = target.parentNode;\n", 4836 "}\n", 4837 "\n", 4838 "// COMMON_CODE_BLOCK_END\n", 4839 "\n", 4840 "var obj0 = new THREE.Object3D();\n", 4841 "obj0.name = \"ilp\";\n", 4842 "obj0.userData.explodable = 1;\n", 4843 "obj0.userData.points = [];\n", 4844 "obj0.userData.points.push(new PMPoint(-1, -1, -1));\n", 4845 "obj0.userData.points.push(new PMPoint(-1, -1, 0));\n", 4846 "obj0.userData.points.push(new PMPoint(-1, 0, -1));\n", 4847 "obj0.userData.points.push(new PMPoint(-1, 0, 1));\n", 4848 "obj0.userData.points.push(new PMPoint(-1, 1, 0));\n", 4849 "obj0.userData.points.push(new PMPoint(0, -1, 0));\n", 4850 "obj0.userData.points.push(new PMPoint(0, -1, 1));\n", 4851 "obj0.userData.points.push(new PMPoint(0, 1, -1));\n", 4852 "obj0.userData.points.push(new PMPoint(0, 1, 1));\n", 4853 "obj0.userData.points.push(new PMPoint(1, 0, -1));\n", 4854 "obj0.userData.points.push(new PMPoint(1, 0, 1));\n", 4855 "obj0.userData.points.push(new PMPoint(1, 1, 0));\n", 4856 "\n", 4857 "obj0.userData.pointradii = 0.02;\n", 4858 " <!-- Vertex style -->\n", 4859 "obj0.userData.pointmaterial = [new THREE.MeshBasicMaterial( { color: 0xFFFF00, side: THREE.DoubleSide, transparent: false } ),\n", 4860 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 4861 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 4862 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 4863 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 4864 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 4865 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 4866 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 4867 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 4868 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 4869 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } ),\n", 4870 "new THREE.MeshBasicMaterial( { color: 0xFF0000, side: THREE.DoubleSide, transparent: false } )];\n", 4871 "obj0.userData.pointlabels = [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"11\"];\n", 4872 "obj0.userData.edgeindices = [0, 1, 0, 2, 1, 3, 2, 4, 3, 4, 0, 5, 1, 6, 3, 6, 5, 6, 2, 7, 4, 7, 3, 8, 4, 8, 0, 9, 5, 9, 7, 9, 6, 10, 8, 10, 9, 10, 7, 11, 8, 11, 9, 11, 10, 11];\n", 4873 " <!-- Edge style -->\n", 4874 "obj0.userData.edgematerial = new THREE.LineBasicMaterial( { color: 0x000000, depthTest: true, linewidth: 1.5, transparent: false } );\n", 4875 "obj0.userData.facets = [[10, 6, 5, 9], [3, 6, 10, 8], [4, 3, 8], [5, 6, 1, 0], [1, 6, 3], [0, 1, 3, 4, 2], [2, 4, 7], [9, 5, 0], [9, 0, 2, 7], [11, 9, 7], [10, 11, 8], [10, 9, 11], [11, 7, 4, 8]];\n", 4876 " <!-- Facet style -->\n", 4877 "obj0.userData.facetmaterial = [new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4878 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4879 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4880 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4881 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4882 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4883 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4884 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4885 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4886 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4887 "new THREE.MeshBasicMaterial( { color: 0xFF0000, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4888 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } ),\n", 4889 "new THREE.MeshBasicMaterial( { color: 0x77EC9E, depthFunc: THREE.LessDepth, opacity: 1, polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 0.5, side: THREE.DoubleSide, transparent: true } )];\n", 4890 "init_object(obj0);\n", 4891 "scene.add(obj0);\n", 4892 "\n", 4893 "// COMMON_CODE_BLOCK_BEGIN\n", 4894 "function textSpriteMaterial(message, parameters) {\n", 4895 " if ( parameters === undefined ) parameters = {};\n", 4896 " var fontface = \"Helvetica\";\n", 4897 " var fontsize = parameters.hasOwnProperty(\"fontsize\") ? parameters[\"fontsize\"] : 15;\n", 4898 " fontsize = fontsize*10;\n", 4899 " var lines = message.split('\\\\n');\n", 4900 " var size = 512;\n", 4901 " for(var i = 0; i<lines.length; i++){\n", 4902 " var tmp = lines[i].length;\n", 4903 " while(tmp*fontsize > size){\n", 4904 " fontsize--;\n", 4905 " }\n", 4906 " }\n", 4907 " \n", 4908 " var canvas = document.createElement('canvas');\n", 4909 " canvas.width = size;\n", 4910 " canvas.height = size;\n", 4911 " var context = canvas.getContext('2d');\n", 4912 " context.fillStyle = \"rgba(255, 255, 255, 0)\";\n", 4913 " context.fill();\n", 4914 " context.font = fontsize + \"px \" + fontface;\n", 4915 " \n", 4916 " // text color\n", 4917 " context.fillStyle = \"rgba(0, 0, 0, 1.0)\";\n", 4918 " for(var i = 0; i<lines.length; i++){\n", 4919 " context.fillText(lines[i], size/2, size/2+i*fontsize);\n", 4920 " }\n", 4921 " \n", 4922 " // canvas contents will be used for a texture\n", 4923 " var texture = new THREE.Texture(canvas);\n", 4924 " texture.needsUpdate = true;\n", 4925 " \n", 4926 " var spriteMaterial = new THREE.SpriteMaterial({map: texture, depthTest: true, depthWrite: false, polygonOffset: true, polygonOffsetFactor: -1, polygonOffsetUnits: 1 });\n", 4927 " return spriteMaterial;\n", 4928 "}\n", 4929 "\n", 4930 "\n", 4931 "// ---------------------- INITIALIZING OBJECTS--------------------------------------\n", 4932 "// ---------------------------------------------------------------------------------\n", 4933 "\n", 4934 "function init_object(obj) {\n", 4935 " if (obj.userData.hasOwnProperty(\"pointmaterial\")) {\n", 4936 " init_points(obj);\n", 4937 " modelContains.points = true;\n", 4938 " }\n", 4939 " if (obj.userData.hasOwnProperty(\"pointlabels\")) {\n", 4940 " init_pointlabels(obj);\n", 4941 " modelContains.pointlabels = true;\n", 4942 " }\n", 4943 " if (obj.userData.hasOwnProperty(\"edgematerial\")) {\n", 4944 " init_lines(obj);\n", 4945 " modelContains.lines = true;\n", 4946 " }\n", 4947 " if (obj.userData.hasOwnProperty(\"edgelabels\")) {\n", 4948 " init_edgelabels(obj);\n", 4949 " modelContains.edgelabels = true;\n", 4950 " }\n", 4951 " if (obj.userData.hasOwnProperty(\"arrowstyle\")) {\n", 4952 " init_arrowheads(obj);\n", 4953 " modelContains.arrowheads = true;\n", 4954 " }\n", 4955 " if (obj.userData.hasOwnProperty(\"facetmaterial\")) {\n", 4956 " init_faces(obj);\n", 4957 " modelContains.faces = true;\n", 4958 " }\n", 4959 "}\n", 4960 "\n", 4961 "function init_points(obj) {\n", 4962 " var pointgroup = new THREE.Group();\n", 4963 " pointgroup.name = \"points\";\n", 4964 " var points = obj.userData.points;\n", 4965 " var radii = obj.userData.pointradii;\n", 4966 " var materials = obj.userData.pointmaterial;\n", 4967 " var geometry,material;\n", 4968 " if (!Array.isArray(radii)) {\n", 4969 " geometry = new THREE.SphereBufferGeometry(radii); \n", 4970 " }\n", 4971 " if (!Array.isArray(materials)) {\n", 4972 " material = materials;\n", 4973 " }\n", 4974 " for (var i=0; i<points.length; i++) {\n", 4975 " var point = points[i];\n", 4976 " if (Array.isArray(radii)) {\n", 4977 " if (radii[i] == 0) {\n", 4978 " continue;\n", 4979 " }\n", 4980 " geometry = new THREE.SphereBufferGeometry(radii[i]); \n", 4981 " } \n", 4982 " if (Array.isArray(materials)) {\n", 4983 " material = materials[i]; \n", 4984 " } \n", 4985 " var sphere = new THREE.Mesh(geometry, material);\n", 4986 " point.addSphere(sphere);\n", 4987 " pointgroup.add(sphere);\n", 4988 " }\n", 4989 " obj.add(pointgroup);\n", 4990 "}\n", 4991 "\n", 4992 "function init_pointlabels(obj) {\n", 4993 " var points = obj.userData.points;\n", 4994 " var labels = obj.userData.pointlabels;\n", 4995 " var pointlabels = new THREE.Group();\n", 4996 " pointlabels.name = \"pointlabels\";\n", 4997 " if (Array.isArray(labels)) {\n", 4998 " for (var i=0; i<points.length; i++) {\n", 4999 " var point = points[i];\n", 5000 " var spriteMaterial = textSpriteMaterial( labels[i] );\n", 5001 "\t var sprite = new THREE.Sprite(spriteMaterial);\n", 5002 " point.addLabel(sprite);\n", 5003 " pointlabels.add(sprite);\n", 5004 " }\n", 5005 " } else {\n", 5006 " var spriteMaterial = textSpriteMaterial( labels );\n", 5007 " for (var i=0; i<points.length; i++) {\n", 5008 " var point = points[i];\n", 5009 "\t var sprite = new THREE.Sprite(spriteMaterial);\n", 5010 " point.addLabel(sprite);\n", 5011 " pointlabels.add(sprite);\n", 5012 " }\n", 5013 " }\n", 5014 " obj.add(pointlabels);\n", 5015 "}\n", 5016 "\n", 5017 "function init_lines(obj) {\n", 5018 " var edgeindices = obj.userData.edgeindices;\n", 5019 " var points = obj.userData.points;\n", 5020 " var materials = obj.userData.edgematerial;\n", 5021 " var geometry = new THREE.BufferGeometry();\n", 5022 " var bufarr = new Float32Array( obj.userData.edgeindices.length * 3 );\n", 5023 " var bufattr = new THREE.Float32BufferAttribute( bufarr, 3 );\n", 5024 " var geometry = new THREE.BufferGeometry();\n", 5025 " geometry.setAttribute('position', bufattr);\n", 5026 " if (Array.isArray(materials)) { \n", 5027 " for (var i=0; i<materials.length; i++) {\n", 5028 " geometry.addGroup(2*i,2,i);\n", 5029 " }\n", 5030 " }\n", 5031 " var lines = new THREE.LineSegments(geometry, materials);\n", 5032 " lines.name = \"lines\";\n", 5033 " obj.add(lines);\n", 5034 " updateEdgesPosition(obj);\n", 5035 "}\n", 5036 "\n", 5037 "function init_edgelabels(obj) {\n", 5038 " var points = obj.userData.points;\n", 5039 " var edgeindices = obj.userData.edgeindices;\n", 5040 " var labels = obj.userData.edgelabels;\n", 5041 " var edgelabels = new THREE.Group();\n", 5042 " edgelabels.name = \"edgelabels\";\n", 5043 " if (Array.isArray(labels)) {\n", 5044 " for (var i=0; i<edgeindices.length; i=i+2) {\n", 5045 " var point = points[i];\n", 5046 " var spriteMaterial = textSpriteMaterial( labels[i] );\n", 5047 " var sprite = new THREE.Sprite(spriteMaterial);\n", 5048 " sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[i]].vector,points[edgeindices[i+1]].vector).multiplyScalar(0.5));\n", 5049 " edgelabels.add(sprite);\n", 5050 " }\n", 5051 " } else {\n", 5052 " var spriteMaterial = textSpriteMaterial( labels );\n", 5053 " for (var i=0; i<points.length; i++) {\n", 5054 " var point = points[i];\n", 5055 " var sprite = new THREE.Sprite(spriteMaterial);\n", 5056 " sprite.position.copy(new THREE.Vector3().addVectors(points[edgeindices[i]].vector,points[edgeindices[i+1]].vector).multiplyScalar(0.5));\n", 5057 " pointlabels.add(sprite);\n", 5058 " }\n", 5059 " }\n", 5060 " obj.add(edgelabels);\n", 5061 "}\n", 5062 "\n", 5063 "function init_arrowheads(obj) {\n", 5064 " var arrowheads = new THREE.Group();\n", 5065 " arrowheads.name = \"arrowheads\";\n", 5066 " var arrowstyle = obj.userData.arrowstyle;\n", 5067 " var edgeindices = obj.userData.edgeindices;\n", 5068 " var edgematerials = obj.userData.edgematerial;\n", 5069 " var points = obj.userData.points;\n", 5070 " var material;\n", 5071 " if (!Array.isArray(edgematerials)) {\n", 5072 " material = new THREE.MeshBasicMaterial( {color: edgematerials.color} );\n", 5073 " }\n", 5074 "\n", 5075 " for (var i=0; i<edgeindices.length; i=i+2) {\n", 5076 " var start = points[edgeindices[i]];\n", 5077 " var end = points[edgeindices[i+1]];\n", 5078 " var dist = start.vector.distanceTo( end.vector ) - start.radius() - end.radius();\n", 5079 " if (dist <= 0) {\n", 5080 " continue;\n", 5081 " }\n", 5082 " var dir = new THREE.Vector3().subVectors(end.vector,start.vector);\n", 5083 " dir.normalize();\n", 5084 " var axis = new THREE.Vector3().set(dir.z,0,-dir.x);\n", 5085 " axis.normalize();\n", 5086 " var radians = Math.acos( dir.y );\n", 5087 " var radius = dist/25;\n", 5088 " var height = dist/5;\n", 5089 " var geometry = new THREE.ConeBufferGeometry(radius,height);\n", 5090 " var position = new THREE.Vector3().addVectors(start.vector,dir.clone().multiplyScalar(start.radius()+dist-height/2));\n", 5091 " if (Array.isArray(edgematerials)) {\n", 5092 " material = new THREE.MeshBasicMaterial( {color: edgematerials[i].color} );\n", 5093 " }\n", 5094 " var cone = new THREE.Mesh( geometry, material );\n", 5095 " cone.quaternion.setFromAxisAngle(axis,radians);;\n", 5096 " cone.position.copy(position);;\n", 5097 " arrowheads.add(cone);\n", 5098 " }\n", 5099 " obj.add(arrowheads);\n", 5100 "}\n", 5101 "\n", 5102 "function init_faces(obj) {\n", 5103 " var points = obj.userData.points;\n", 5104 " var facets = obj.userData.facets;\n", 5105 " obj.userData.triangleindices = [];\n", 5106 " for (var i=0; i<facets.length; i++) {\n", 5107 " facet = facets[i];\n", 5108 " for (var t=0; t<facet.length-2; t++) {\n", 5109 " obj.userData.triangleindices.push(facet[0],facet[t+1],facet[t+2]); \n", 5110 " }\n", 5111 " }\n", 5112 " var bufarr = new Float32Array( obj.userData.triangleindices.length * 3 );\n", 5113 " var bufattr = new THREE.Float32BufferAttribute(bufarr,3);\n", 5114 " \n", 5115 " var materials = obj.userData.facetmaterial;\n", 5116 " var geometry = new THREE.BufferGeometry();\n", 5117 " geometry.setAttribute('position',bufattr);\n", 5118 " if (Array.isArray(materials)) {\n", 5119 " var tricount = 0;\n", 5120 " var facet;\n", 5121 " for (var i=0; i<facets.length; i++) {\n", 5122 " facet = facets[i];\n", 5123 " geometry.addGroup(tricount,(facet.length-2)*3,i);\n", 5124 " tricount += (facet.length-2)*3;\n", 5125 " }\n", 5126 " }\n", 5127 " var mesh = new THREE.Mesh(geometry, materials);\n", 5128 " mesh.name = \"faces\";\n", 5129 " obj.add(mesh); \n", 5130 " updateFacesPosition(obj);\n", 5131 "}\n", 5132 "// //INITIALIZING\n", 5133 "\n", 5134 "\n", 5135 "function updateFacesPosition(obj) {\n", 5136 " var points = obj.userData.points;\n", 5137 " var indices = obj.userData.triangleindices;\n", 5138 " var faces = obj.getObjectByName(\"faces\");\n", 5139 " var ba = faces.geometry.getAttribute(\"position\");\n", 5140 " for (var i=0; i<indices.length; i++) {\n", 5141 " ba.setXYZ(i, points[indices[i]].vector.x, points[indices[i]].vector.y ,points[indices[i]].vector.z); \n", 5142 " }\n", 5143 " faces.geometry.attributes.position.needsUpdate = true;\n", 5144 " \n", 5145 "}\n", 5146 "\n", 5147 "function updateEdgesPosition(obj) {\n", 5148 " var points = obj.userData.points;\n", 5149 " var indices = obj.userData.edgeindices;\n", 5150 " var lines = obj.getObjectByName(\"lines\");\n", 5151 " var ba = lines.geometry.getAttribute(\"position\"); \n", 5152 " for (var i=0; i<indices.length; i++) {\n", 5153 " ba.setXYZ(i, points[indices[i]].vector.x, points[indices[i]].vector.y ,points[indices[i]].vector.z); \n", 5154 " }\n", 5155 " lines.geometry.attributes.position.needsUpdate = true;\n", 5156 "}\n", 5157 "\n", 5158 "function onWindowResize() {\n", 5159 " renderer.setSize( three.clientWidth, three.clientHeight );\n", 5160 " svgRenderer.setSize( three.clientWidth, three.clientHeight );\n", 5161 " updateCamera();\n", 5162 "}\n", 5163 "\n", 5164 "function updateCamera() {\n", 5165 " var width = three.clientWidth;\n", 5166 " var height = three.clientHeight;\n", 5167 " var aspect = width / height;\n", 5168 " if (camera.type == \"OrthographicCamera\") {\n", 5169 " camera.left = frustumSize * aspect / - 2;\n", 5170 " camera.right = frustumSize * aspect / 2;\n", 5171 " camera.top = frustumSize / 2;\n", 5172 " camera.bottom = - frustumSize / 2;\n", 5173 " } else if (camera.type == \"PerspectiveCamera\") {\n", 5174 " camera.aspect = aspect;\n", 5175 " }\n", 5176 " camera.updateProjectionMatrix();\n", 5177 "}\n", 5178 "\n", 5179 "function changeCamera(event) {\n", 5180 " var selindex = event.currentTarget.selectedIndex;\n", 5181 " camera = cameras[selindex];\n", 5182 " control = controls[selindex];\n", 5183 " control.enabled = true; \n", 5184 " for (var i=0; i<controls.length; i++) {\n", 5185 " if (i!=selindex) {\n", 5186 " controls[i].enabled = false;\n", 5187 " }\n", 5188 " }\n", 5189 " updateCamera();\n", 5190 "}\n", 5191 "\n", 5192 "var camtypenode = document.getElementById('cameraType_3');\n", 5193 "camtypenode.onchange = changeCamera;\n", 5194 "camtypenode.dispatchEvent(new Event('change'));\n", 5195 "\n", 5196 "onWindowResize();\n", 5197 "window.addEventListener('resize', onWindowResize);\t\n", 5198 "\n", 5199 "\n", 5200 "var xRotationEnabled = false;\n", 5201 "var yRotationEnabled = false;\n", 5202 "var zRotationEnabled = false;\n", 5203 "var rotationSpeedFactor = 1;\n", 5204 "var settingsShown = false;\n", 5205 "var labelsShown = true;\n", 5206 "var intervals = [];\n", 5207 "var timeouts = [];\n", 5208 "var explodingSpeed = 0.05;\n", 5209 "var explodeScale = 0;\n", 5210 "var XMLS = new XMLSerializer();\n", 5211 "var svgElement;\n", 5212 "var renderId;\n", 5213 "\n", 5214 "var render = function () {\n", 5215 "\n", 5216 "\trenderId = requestAnimationFrame(render);\n", 5217 "\n", 5218 "//\tcomment in for automatic explosion\n", 5219 "//\texplode(updateFactor());\n", 5220 "\n", 5221 " var phi = 0.02 * rotationSpeedFactor;\n", 5222 "\n", 5223 " if (xRotationEnabled) {\n", 5224 " scene.rotation.x += phi;\n", 5225 " }\n", 5226 " if (yRotationEnabled) {\n", 5227 " scene.rotation.y += phi;\n", 5228 " }\n", 5229 " if (zRotationEnabled) {\n", 5230 " scene.rotation.z += phi;\n", 5231 " }\n", 5232 "\n", 5233 " control.update();\n", 5234 " renderer.render(scene, camera);\n", 5235 "};\n", 5236 "\n", 5237 "if ( THREE.WEBGL.isWebGLAvailable() ) {\n", 5238 "\trender();\n", 5239 "} else {\n", 5240 "\tvar warning = WEBGL.getWebGLErrorMessage();\n", 5241 "\tthree.appendChild( warning );\n", 5242 "}\n", 5243 " \n", 5244 "function changeTransparency() {\n", 5245 " var opacity = 1-Number(event.currentTarget.value);\n", 5246 " for (var i=0; i<scene.children.length; i++) {\n", 5247 " child = scene.children[i];\n", 5248 " if ( child.userData.hasOwnProperty(\"facetmaterial\") ) {\n", 5249 " if (Array.isArray(child.userData.facetmaterial)) {\n", 5250 " for (var j=0; j<child.userData.facetmaterial.length; j++) {\n", 5251 " child.userData.facetmaterial[j].opacity = opacity;\n", 5252 " }\n", 5253 " } else {\n", 5254 " child.userData.facetmaterial.opacity = opacity;\n", 5255 " } \n", 5256 " }\n", 5257 " }\n", 5258 "}\n", 5259 "\n", 5260 "function changeRotationX(event){\n", 5261 " xRotationEnabled = event.currentTarget.checked;\n", 5262 "}\t\n", 5263 "\n", 5264 "function changeRotationY(event){\n", 5265 " yRotationEnabled = event.currentTarget.checked;\n", 5266 "}\t\n", 5267 "\n", 5268 "function changeRotationZ(event){\n", 5269 " zRotationEnabled = event.currentTarget.checked;\n", 5270 "}\t\n", 5271 "\n", 5272 "\n", 5273 "function changeRotationSpeedFactor(event){\n", 5274 " rotationSpeedFactor = Number(event.currentTarget.value);\n", 5275 "}\n", 5276 "\n", 5277 "function resetScene(){\n", 5278 " scene.rotation.set(0,0,0);\n", 5279 " camera.position.set(0,0,5);\n", 5280 " camera.up.set(0,1,0);\n", 5281 "}\n", 5282 "\n", 5283 "function showSettings(event){\n", 5284 " document.getElementById('settings_3').style.visibility = 'visible';\n", 5285 " document.getElementById('showSettingsButton_3').style.visibility = 'hidden';\n", 5286 " document.getElementById('hideSettingsButton_3').style.visibility = 'visible';\n", 5287 " settingsShown = true;\n", 5288 "}\n", 5289 "\n", 5290 "function hideSettings(event){\n", 5291 " document.getElementById('settings_3').style.visibility = 'hidden';\n", 5292 " document.getElementById('showSettingsButton_3').style.visibility = 'visible';\n", 5293 " document.getElementById('hideSettingsButton_3').style.visibility = 'hidden';\n", 5294 " settingsShown = false;\n", 5295 "}\n", 5296 "\n", 5297 "\n", 5298 "\n", 5299 "var pos = 150* Math.PI;\n", 5300 "\n", 5301 "function updateFactor() {\n", 5302 " pos++;\n", 5303 " return Math.sin(.01*pos)+1;\n", 5304 "}\n", 5305 "\n", 5306 "// ------------------------ FOLDING ------------------------------------------------\n", 5307 "// ---------------------------------------------------------------------------------\n", 5308 "// rotate point p around axis defined by points p1 and p2 by given angle\n", 5309 "function rotate(p, p1, p2, angle ){ \n", 5310 " angle = -angle;\n", 5311 " var x = p.x, y = p.y, z = p.z, \n", 5312 " a = p1.x, b = p1.y, c = p1.z, \n", 5313 " u = p2.x-p1.x, v = p2.y-p1.y, w = p2.z-p1.z;\n", 5314 " var result = [];\n", 5315 " var L = u*u + v*v + w*w;\n", 5316 " var sqrt = Math.sqrt;\n", 5317 " var cos = Math.cos;\n", 5318 " var sin = Math.sin;\n", 5319 "\n", 5320 " result[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*x*cos(angle)+sqrt(L)*(-c*v+b*w-w*y+v*z)*sin(angle))/L;\n", 5321 " result[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(angle))+L*y*cos(angle)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(angle))/L;\n", 5322 " result[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(angle))+L*z*cos(angle)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(angle))/L;\n", 5323 "\n", 5324 " return result;\n", 5325 "}\n", 5326 "\n", 5327 "var fold = function(event){\n", 5328 " var obj = foldables[Number(event.currentTarget.name)];\n", 5329 " var foldvalue = Number(event.currentTarget.value);\n", 5330 " var scale = foldvalue - obj.userData.oldscale;\n", 5331 "\n", 5332 " for (var j=0; j<obj.userData.axes.length; j++) {\n", 5333 " rotateVertices(obj, j, scale);\n", 5334 " }\n", 5335 " update(obj);\n", 5336 " obj.userData.oldscale += scale;\n", 5337 " lookAtBarycenter(obj);\n", 5338 "}\n", 5339 "\n", 5340 "function lookAtBarycenter(obj){\n", 5341 " control.target = barycenter(obj);\n", 5342 "}\n", 5343 "\n", 5344 "function barycenter(obj) {\n", 5345 " var center = new THREE.Vector3(0,0,0);\n", 5346 " var points = obj.userData.points;\n", 5347 " for (var i=0; i<points.length; i++){\n", 5348 " center.add(points[i].vector);\n", 5349 " }\n", 5350 " center.divideScalar(points.length);\n", 5351 " return center;\n", 5352 "}\n", 5353 "\n", 5354 "function rotateVertices(obj, edge, scale) {\n", 5355 " var axes = obj.userData.axes;\n", 5356 " var subtrees = obj.userData.subtrees;\n", 5357 " var points = obj.userData.points;\n", 5358 " var angles = obj.userData.angles;\n", 5359 " if (edge < axes.length){\n", 5360 " for (var j=0; j<subtrees[edge].length; j++){\n", 5361 " var rotP = rotate(points[subtrees[edge][j]].vector, points[axes[edge][0]].vector,points[axes[edge][1]].vector, scale * (Math.PI - angles[edge]));\n", 5362 " points[subtrees[edge][j]].set(rotP[0],rotP[1],rotP[2]);\n", 5363 " }\n", 5364 " }\n", 5365 "}\n", 5366 "\n", 5367 "function update(obj) {\n", 5368 " updateFacesPosition(obj);\n", 5369 " updateEdgesPosition(obj);\n", 5370 "}\n", 5371 "\n", 5372 "if (foldables.length) {\n", 5373 " var settings = document.getElementById('settings_3');\n", 5374 " var foldDiv = document.createElement('div');\n", 5375 " foldDiv.id = 'fold_3';\n", 5376 " var title = document.createElement('strong');\n", 5377 " title.innerHTML = 'Fold';\n", 5378 " foldDiv.appendChild(title);\n", 5379 " foldDiv.className = 'group';\n", 5380 " for (var i=0; i<foldables.length; i++) {\n", 5381 " var range = document.createElement('input');\n", 5382 " range.type = 'range';\n", 5383 " range.min = 0;\n", 5384 " range.max = 1;\n", 5385 " range.value = 0;\n", 5386 " range.step = 0.001;\n", 5387 " range.name = String(i);\n", 5388 " range.oninput = fold;\n", 5389 " foldDiv.appendChild(range);\n", 5390 " }\n", 5391 " lookAtBarycenter(foldables[0]);\n", 5392 " settings.insertBefore(foldDiv,settings.childNodes[0]);\n", 5393 "}\n", 5394 "\n", 5395 " \n", 5396 "// ---------------------- EXPLOSION ------------------------------------------------\n", 5397 "// ---------------------------------------------------------------------------------\n", 5398 "\n", 5399 "if (explodableModel) {\n", 5400 " for (var i=0; i<scene.children.length; i++) {\n", 5401 " obj = scene.children[i];\n", 5402 " if ( obj.userData.explodable ) {\n", 5403 " computeCentroid(obj);\n", 5404 " }\n", 5405 " }\n", 5406 " document.getElementById('explodeRange_3').oninput = triggerExplode;\n", 5407 " document.getElementById('explodeCheckbox_3').onchange = triggerAutomaticExplode;\n", 5408 " document.getElementById('explodingSpeedRange_3').oninput = setExplodingSpeed;\n", 5409 "}\n", 5410 "\n", 5411 "function computeCentroid(obj) {\n", 5412 " centroid = new THREE.Vector3();\n", 5413 " obj.userData.points.forEach(function(pmpoint) {\n", 5414 " centroid.add(pmpoint.vector);\t\t\t\n", 5415 " });\n", 5416 " centroid.divideScalar(obj.userData.points.length);\n", 5417 " obj.userData.centroid = centroid;\n", 5418 "}\n", 5419 "\n", 5420 "function explode(factor) {\n", 5421 " for (var i=0; i<scene.children.length; i++) {\n", 5422 " var obj = scene.children[i];\n", 5423 " if (obj.userData.hasOwnProperty(\"centroid\")) { \n", 5424 " var c = obj.userData.centroid;\n", 5425 " obj.position.set(c.x*factor, c.y*factor, c.z*factor);\n", 5426 " }\n", 5427 " }\t\n", 5428 "}\n", 5429 "\n", 5430 "function triggerExplode(event){\n", 5431 " explodeScale = Number(event.currentTarget.value);\n", 5432 " explode(explodeScale);\n", 5433 "}\n", 5434 "\n", 5435 "function setExplodingSpeed(event){\n", 5436 " explodingSpeed = Number(event.currentTarget.value);\n", 5437 "}\n", 5438 "\n", 5439 "function triggerAutomaticExplode(event){\n", 5440 " if (event.currentTarget.checked){\n", 5441 " startExploding();\n", 5442 " } else {\n", 5443 " clearIntervals();\n", 5444 " }\t\n", 5445 "}\n", 5446 "\n", 5447 "function startExploding(){\n", 5448 " intervals.push(setInterval(explodingInterval, 25));\n", 5449 "}\n", 5450 "\n", 5451 "\n", 5452 "function explodingInterval(){\n", 5453 " explodeScale += explodingSpeed;\n", 5454 " if (explodeScale <= 6){ \n", 5455 " explode(explodeScale);\n", 5456 " }\n", 5457 " else{\n", 5458 " explode(6);\n", 5459 " explodeScale = 6;\n", 5460 " clearIntervals();\n", 5461 " timeouts.push(setTimeout(startUnexploding, 3000));\n", 5462 " }\n", 5463 " document.getElementById('explodeRange_3').value = explodeScale;\n", 5464 "}\n", 5465 "\n", 5466 "\n", 5467 "function startUnexploding(){\n", 5468 " intervals.push(setInterval(unexplodingInterval, 25));\n", 5469 "}\n", 5470 "\n", 5471 "function unexplodingInterval(){\n", 5472 " explodeScale -= explodingSpeed;\n", 5473 " if (explodeScale >= 0){\t\n", 5474 " explode(explodeScale);\n", 5475 " }\n", 5476 " else {\n", 5477 " explode(0);\n", 5478 " explodeScale = 0;\n", 5479 " clearIntervals();\n", 5480 " timeouts.push(setTimeout(startExploding, 3000));\n", 5481 " }\n", 5482 " document.getElementById('explodeRange_3').value = explodeScale;\n", 5483 "}\n", 5484 "\n", 5485 "function clearIntervals(){\n", 5486 " intervals.forEach(function(interval){\n", 5487 " clearInterval(interval);\n", 5488 " });\n", 5489 " intervals = [];\n", 5490 " timeouts.forEach(function(timeout){\n", 5491 " clearTimeout(timeout);\n", 5492 " });\n", 5493 " timeouts = [];\n", 5494 "}\n", 5495 "\n", 5496 "// ---------------------- DISPLAY --------------------------------------------------\n", 5497 "// ---------------------------------------------------------------------------------\n", 5498 "\n", 5499 "const objectTypeInnerHTMLs = { points: \"Points\", pointlabels: \"Point labels\", lines: \"Edges\", edgelabels: \"Edge labels\", faces: \"Faces\", arrowheads: \"Arrow heads\" };\n", 5500 "const objectTypeVisible = {};\n", 5501 "Object.assign(objectTypeVisible,modelContains);\n", 5502 "const sortedObjectTypeKeys = Object.keys(objectTypeInnerHTMLs).sort();\n", 5503 "const shownObjectTypesList = document.getElementById('shownObjectTypesList_3');\n", 5504 "\n", 5505 "function setVisibility(bool,objname) {\n", 5506 " for (var i=0; i<scene.children.length; i++){\n", 5507 " var obj = scene.children[i].getObjectByName(objname);\n", 5508 " if (obj) {\n", 5509 " obj.visible = bool;\n", 5510 " }\n", 5511 " }\n", 5512 "}\n", 5513 "\n", 5514 "function toggleObjectTypeVisibility(event){\n", 5515 " var name = event.currentTarget.name;\n", 5516 " var checked = event.currentTarget.checked;\n", 5517 " objectTypeVisible[name] = checked;\n", 5518 " setVisibility(checked,name);\n", 5519 "}\n", 5520 "\n", 5521 "for (var i=0; i<sortedObjectTypeKeys.length; i++){\n", 5522 " var key = sortedObjectTypeKeys[i];\n", 5523 " if (modelContains[key]) {\n", 5524 " var objTypeNode = document.createElement('span');\n", 5525 " objTypeNode.innerHTML = objectTypeInnerHTMLs[key] + '<br>';\n", 5526 " var checkbox = document.createElement('input');\n", 5527 " checkbox.type = 'checkbox';\n", 5528 " checkbox.checked = true;\n", 5529 " checkbox.name = key;\n", 5530 " checkbox.onchange = toggleObjectTypeVisibility;\n", 5531 " shownObjectTypesList.appendChild(checkbox);\n", 5532 " shownObjectTypesList.appendChild(objTypeNode);\n", 5533 " }\n", 5534 "}\n", 5535 "\n", 5536 "// ------------------------------------------------------\n", 5537 "\n", 5538 "function toggleObjectVisibility(event){\n", 5539 " var nr = Number(event.currentTarget.name);\n", 5540 " scene.children[nr].visible = event.currentTarget.checked;\n", 5541 "}\n", 5542 "\n", 5543 "// append checkboxes for displaying or hiding objects\n", 5544 "var shownObjectsList = document.getElementById('shownObjectsList_3');\n", 5545 "for (var i=0; i<scene.children.length; i++){\n", 5546 " obj = scene.children[i];\n", 5547 " var objNode = document.createElement('span');\n", 5548 " objNode.innerHTML = obj.name + '<br>';\n", 5549 " var checkbox = document.createElement('input');\n", 5550 " checkbox.type = 'checkbox';\n", 5551 " checkbox.checked = true;\n", 5552 " checkbox.name = String(i);\n", 5553 " checkbox.onchange = toggleObjectVisibility;\n", 5554 " shownObjectsList.appendChild(checkbox);\n", 5555 " shownObjectsList.appendChild(objNode);\n", 5556 "}\n", 5557 "\n", 5558 "// ---------------------- SVG ------------------------------------------------------\n", 5559 "// ---------------------------------------------------------------------------------\n", 5560 "\n", 5561 "function takeSvgScreenshot() {\n", 5562 " if (objectTypeVisible[\"pointlabels\"]) {\n", 5563 " setVisibility(false,\"pointlabels\");\n", 5564 " }\n", 5565 " if (objectTypeVisible[\"edgelabels\"]) {\n", 5566 " setVisibility(false,\"edgelabels\");\n", 5567 " }\n", 5568 " svgRenderer.render(scene,camera);\n", 5569 " svgElement = XMLS.serializeToString(svgRenderer.domElement);\n", 5570 " \n", 5571 " if (objectTypeVisible[\"pointlabels\"]) {\n", 5572 " setVisibility(true,\"pointlabels\");\n", 5573 " }\n", 5574 " if (objectTypeVisible[\"edgelabels\"]) {\n", 5575 " setVisibility(true,\"edgelabels\");\n", 5576 " }\n", 5577 "\n", 5578 " if (document.getElementById('tab_3').checked){\n", 5579 " //show in new tab\n", 5580 " var myWindow = window.open(\"\",\"\");\n", 5581 " myWindow.document.body.innerHTML = svgElement;\n", 5582 " } else{\n", 5583 " // download svg file \n", 5584 " download(\"screenshot.svg\", svgElement);\n", 5585 " }\n", 5586 "}\n", 5587 "\n", 5588 "function download(filename, text) {\n", 5589 " var element = document.createElement('a');\n", 5590 " element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));\n", 5591 " element.setAttribute('download', filename);\n", 5592 "\n", 5593 " element.style.display = 'none';\n", 5594 " document.body.appendChild(element);\n", 5595 "\n", 5596 " element.click();\n", 5597 "\n", 5598 " document.body.removeChild(element);\n", 5599 "}\n", 5600 "\n", 5601 "\n", 5602 "document.getElementById('transparencyRange_3').oninput = changeTransparency;\n", 5603 "document.getElementById('changeRotationX_3').onchange = changeRotationX;\n", 5604 "document.getElementById('changeRotationY_3').onchange = changeRotationY;\n", 5605 "document.getElementById('changeRotationZ_3').onchange = changeRotationZ;\n", 5606 "document.getElementById('resetButton_3').onclick = resetScene;\n", 5607 "document.getElementById('rotationSpeedRange_3').oninput = changeRotationSpeedFactor;\n", 5608 "document.getElementById('takeScreenshot_3').onclick = takeSvgScreenshot;\n", 5609 "document.getElementById('showSettingsButton_3').onclick = showSettings;\n", 5610 "document.getElementById('hideSettingsButton_3').onclick = hideSettings;\n", 5611 "\n", 5612 "\n", 5613 "// ------------------ SHORTCUTS --------------------------------------------\n", 5614 "// -------------------------------------------------------------------------\n", 5615 "\n", 5616 "/**\n", 5617 " * http://www.openjs.com/scripts/events/keyboard_shortcuts/\n", 5618 " * Version : 2.01.B\n", 5619 " * By Binny V A\n", 5620 " * License : BSD\n", 5621 " */\n", 5622 "shortcut = {\n", 5623 "\t'all_shortcuts':{},//All the shortcuts are stored in this array\n", 5624 "\t'add': function(shortcut_combination,callback,opt) {\n", 5625 "\t\t//Provide a set of default options\n", 5626 "\t\tvar default_options = {\n", 5627 "\t\t\t'type':'keydown',\n", 5628 "\t\t\t'propagate':false,\n", 5629 "\t\t\t'disable_in_input':false,\n", 5630 "\t\t\t'target':document,\n", 5631 "\t\t\t'keycode':false\n", 5632 "\t\t}\n", 5633 "\t\tif(!opt) opt = default_options;\n", 5634 "\t\telse {\n", 5635 "\t\t\tfor(var dfo in default_options) {\n", 5636 "\t\t\t\tif(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];\n", 5637 "\t\t\t}\n", 5638 "\t\t}\n", 5639 "\n", 5640 "\t\tvar ele = opt.target;\n", 5641 "\t\tif(typeof opt.target == 'string') ele = document.getElementById(opt.target);\n", 5642 "\t\tvar ths = this;\n", 5643 "\t\tshortcut_combination = shortcut_combination.toLowerCase();\n", 5644 "\n", 5645 "\t\t//The function to be called at keypress\n", 5646 "\t\tvar func = function(e) {\n", 5647 "\t\t\te = e || window.event;\n", 5648 "\t\t\t\n", 5649 "\t\t\tif(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields\n", 5650 "\t\t\t\tvar element;\n", 5651 "\t\t\t\tif(e.target) element=e.target;\n", 5652 "\t\t\t\telse if(e.srcElement) element=e.srcElement;\n", 5653 "\t\t\t\tif(element.nodeType==3) element=element.parentNode;\n", 5654 "\n", 5655 "\t\t\t\tif(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;\n", 5656 "\t\t\t}\n", 5657 "\t\n", 5658 "\t\t\t//Find Which key is pressed\n", 5659 "\t\t\tif (e.keyCode) code = e.keyCode;\n", 5660 "\t\t\telse if (e.which) code = e.which;\n", 5661 "\t\t\tvar character = String.fromCharCode(code).toLowerCase();\n", 5662 "\t\t\t\n", 5663 "\t\t\tif(code == 188) character=\",\"; //If the user presses , when the type is onkeydown\n", 5664 "\t\t\tif(code == 190) character=\".\"; //If the user presses , when the type is onkeydown\n", 5665 "\n", 5666 "\t\t\tvar keys = shortcut_combination.split(\"+\");\n", 5667 "\t\t\t//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked\n", 5668 "\t\t\tvar kp = 0;\n", 5669 "\t\t\t\n", 5670 "\t\t\t//Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken\n", 5671 "\t\t\tvar shift_nums = {\n", 5672 "\t\t\t\t\"`\":\"~\",\n", 5673 "\t\t\t\t\"1\":\"!\",\n", 5674 "\t\t\t\t\"2\":\"@\",\n", 5675 "\t\t\t\t\"3\":\"#\",\n", 5676 "\t\t\t\t\"4\":\"$\",\n", 5677 "\t\t\t\t\"5\":\"%\",\n", 5678 "\t\t\t\t\"6\":\"^\",\n", 5679 "\t\t\t\t\"7\":\"&\",\n", 5680 "\t\t\t\t\"8\":\"*\",\n", 5681 "\t\t\t\t\"9\":\"(\",\n", 5682 "\t\t\t\t\"0\":\")\",\n", 5683 "\t\t\t\t\"-\":\"_\",\n", 5684 "\t\t\t\t\"=\":\"+\",\n", 5685 "\t\t\t\t\";\":\":\",\n", 5686 "\t\t\t\t\"'\":\"\\\"\",\n", 5687 "\t\t\t\t\",\":\"<\",\n", 5688 "\t\t\t\t\".\":\">\",\n", 5689 "\t\t\t\t\"/\":\"?\",\n", 5690 "\t\t\t\t\"\\\\\":\"|\"\n", 5691 "\t\t\t}\n", 5692 "\t\t\t//Special Keys - and their codes\n", 5693 "\t\t\tvar special_keys = {\n", 5694 "\t\t\t\t'esc':27,\n", 5695 "\t\t\t\t'escape':27,\n", 5696 "\t\t\t\t'tab':9,\n", 5697 "\t\t\t\t'space':32,\n", 5698 "\t\t\t\t'return':13,\n", 5699 "\t\t\t\t'enter':13,\n", 5700 "\t\t\t\t'backspace':8,\n", 5701 "\t\n", 5702 "\t\t\t\t'scrolllock':145,\n", 5703 "\t\t\t\t'scroll_lock':145,\n", 5704 "\t\t\t\t'scroll':145,\n", 5705 "\t\t\t\t'capslock':20,\n", 5706 "\t\t\t\t'caps_lock':20,\n", 5707 "\t\t\t\t'caps':20,\n", 5708 "\t\t\t\t'numlock':144,\n", 5709 "\t\t\t\t'num_lock':144,\n", 5710 "\t\t\t\t'num':144,\n", 5711 "\t\t\t\t\n", 5712 "\t\t\t\t'pause':19,\n", 5713 "\t\t\t\t'break':19,\n", 5714 "\t\t\t\t\n", 5715 "\t\t\t\t'insert':45,\n", 5716 "\t\t\t\t'home':36,\n", 5717 "\t\t\t\t'delete':46,\n", 5718 "\t\t\t\t'end':35,\n", 5719 "\t\t\t\t\n", 5720 "\t\t\t\t'pageup':33,\n", 5721 "\t\t\t\t'page_up':33,\n", 5722 "\t\t\t\t'pu':33,\n", 5723 "\t\n", 5724 "\t\t\t\t'pagedown':34,\n", 5725 "\t\t\t\t'page_down':34,\n", 5726 "\t\t\t\t'pd':34,\n", 5727 "\t\n", 5728 "\t\t\t\t'left':37,\n", 5729 "\t\t\t\t'up':38,\n", 5730 "\t\t\t\t'right':39,\n", 5731 "\t\t\t\t'down':40,\n", 5732 "\t\n", 5733 "\t\t\t\t'f1':112,\n", 5734 "\t\t\t\t'f2':113,\n", 5735 "\t\t\t\t'f3':114,\n", 5736 "\t\t\t\t'f4':115,\n", 5737 "\t\t\t\t'f5':116,\n", 5738 "\t\t\t\t'f6':117,\n", 5739 "\t\t\t\t'f7':118,\n", 5740 "\t\t\t\t'f8':119,\n", 5741 "\t\t\t\t'f9':120,\n", 5742 "\t\t\t\t'f10':121,\n", 5743 "\t\t\t\t'f11':122,\n", 5744 "\t\t\t\t'f12':123\n", 5745 "\t\t\t}\n", 5746 "\t\n", 5747 "\t\t\tvar modifiers = { \n", 5748 "\t\t\t\tshift: { wanted:false, pressed:false},\n", 5749 "\t\t\t\tctrl : { wanted:false, pressed:false},\n", 5750 "\t\t\t\talt : { wanted:false, pressed:false},\n", 5751 "\t\t\t\tmeta : { wanted:false, pressed:false}\t//Meta is Mac specific\n", 5752 "\t\t\t};\n", 5753 " \n", 5754 "\t\t\tif(e.ctrlKey)\tmodifiers.ctrl.pressed = true;\n", 5755 "\t\t\tif(e.shiftKey)\tmodifiers.shift.pressed = true;\n", 5756 "\t\t\tif(e.altKey)\tmodifiers.alt.pressed = true;\n", 5757 "\t\t\tif(e.metaKey) modifiers.meta.pressed = true;\n", 5758 " \n", 5759 "\t\t\tfor(var i=0; k=keys[i],i<keys.length; i++) {\n", 5760 "\t\t\t\t//Modifiers\n", 5761 "\t\t\t\tif(k == 'ctrl' || k == 'control') {\n", 5762 "\t\t\t\t\tkp++;\n", 5763 "\t\t\t\t\tmodifiers.ctrl.wanted = true;\n", 5764 "\n", 5765 "\t\t\t\t} else if(k == 'shift') {\n", 5766 "\t\t\t\t\tkp++;\n", 5767 "\t\t\t\t\tmodifiers.shift.wanted = true;\n", 5768 "\n", 5769 "\t\t\t\t} else if(k == 'alt') {\n", 5770 "\t\t\t\t\tkp++;\n", 5771 "\t\t\t\t\tmodifiers.alt.wanted = true;\n", 5772 "\t\t\t\t} else if(k == 'meta') {\n", 5773 "\t\t\t\t\tkp++;\n", 5774 "\t\t\t\t\tmodifiers.meta.wanted = true;\n", 5775 "\t\t\t\t} else if(k.length > 1) { //If it is a special key\n", 5776 "\t\t\t\t\tif(special_keys[k] == code) kp++;\n", 5777 "\t\t\t\t\t\n", 5778 "\t\t\t\t} else if(opt['keycode']) {\n", 5779 "\t\t\t\t\tif(opt['keycode'] == code) kp++;\n", 5780 "\n", 5781 "\t\t\t\t} else { //The special keys did not match\n", 5782 "\t\t\t\t\tif(character == k) kp++;\n", 5783 "\t\t\t\t\telse {\n", 5784 "\t\t\t\t\t\tif(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase\n", 5785 "\t\t\t\t\t\t\tcharacter = shift_nums[character]; \n", 5786 "\t\t\t\t\t\t\tif(character == k) kp++;\n", 5787 "\t\t\t\t\t\t}\n", 5788 "\t\t\t\t\t}\n", 5789 "\t\t\t\t}\n", 5790 "\t\t\t}\n", 5791 "\t\t\t\n", 5792 "\t\t\tif(kp == keys.length && \n", 5793 "\t\t\t\t\t\tmodifiers.ctrl.pressed == modifiers.ctrl.wanted &&\n", 5794 "\t\t\t\t\t\tmodifiers.shift.pressed == modifiers.shift.wanted &&\n", 5795 "\t\t\t\t\t\tmodifiers.alt.pressed == modifiers.alt.wanted &&\n", 5796 "\t\t\t\t\t\tmodifiers.meta.pressed == modifiers.meta.wanted) {\n", 5797 "\t\t\t\tcallback(e);\n", 5798 "\t\n", 5799 "\t\t\t\tif(!opt['propagate']) { //Stop the event\n", 5800 "\t\t\t\t\t//e.cancelBubble is supported by IE - this will kill the bubbling process.\n", 5801 "\t\t\t\t\te.cancelBubble = true;\n", 5802 "\t\t\t\t\te.returnValue = false;\n", 5803 "\t\n", 5804 "\t\t\t\t\t//e.stopPropagation works in Firefox.\n", 5805 "\t\t\t\t\tif (e.stopPropagation) {\n", 5806 "\t\t\t\t\t\te.stopPropagation();\n", 5807 "\t\t\t\t\t\te.preventDefault();\n", 5808 "\t\t\t\t\t}\n", 5809 "\t\t\t\t\treturn false;\n", 5810 "\t\t\t\t}\n", 5811 "\t\t\t}\n", 5812 "\t\t}\n", 5813 "\t\tthis.all_shortcuts[shortcut_combination] = {\n", 5814 "\t\t\t'callback':func, \n", 5815 "\t\t\t'target':ele, \n", 5816 "\t\t\t'event': opt['type']\n", 5817 "\t\t};\n", 5818 "\t\t//Attach the function with the event\n", 5819 "\t\tif(ele.addEventListener) ele.addEventListener(opt['type'], func, false);\n", 5820 "\t\telse if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);\n", 5821 "\t\telse ele['on'+opt['type']] = func;\n", 5822 "\t},\n", 5823 "\n", 5824 "\t//Remove the shortcut - just specify the shortcut and I will remove the binding\n", 5825 "\t'remove':function(shortcut_combination) {\n", 5826 "\t\tshortcut_combination = shortcut_combination.toLowerCase();\n", 5827 "\t\tvar binding = this.all_shortcuts[shortcut_combination];\n", 5828 "\t\tdelete(this.all_shortcuts[shortcut_combination])\n", 5829 "\t\tif(!binding) return;\n", 5830 "\t\tvar type = binding['event'];\n", 5831 "\t\tvar ele = binding['target'];\n", 5832 "\t\tvar callback = binding['callback'];\n", 5833 "\n", 5834 "\t\tif(ele.detachEvent) ele.detachEvent('on'+type, callback);\n", 5835 "\t\telse if(ele.removeEventListener) ele.removeEventListener(type, callback, false);\n", 5836 "\t\telse ele['on'+type] = false;\n", 5837 "\t}\n", 5838 "}\n", 5839 "\n", 5840 "shortcut.add(\"Alt+Left\",function() {\n", 5841 "\tvar event = new Event('click');\n", 5842 "\tif (settingsShown){\n", 5843 "\t\tdocument.getElementById('hideSettingsButton_3').dispatchEvent(event);\n", 5844 "\t} else {\n", 5845 "\t\tdocument.getElementById('showSettingsButton_3').dispatchEvent(event);\n", 5846 "\t}\n", 5847 "});\n", 5848 "\n", 5849 "\n", 5850 "// COMMON_CODE_BLOCK_END\n", 5851 "\n", 5852 "});});\n", 5853 " </script>\n", 5854 " </body>\n", 5855 "</html>" 5856 ] 5857 }, 5858 "metadata": {}, 5859 "output_type": "display_data" 5860 } 5861 ], 5862 "source": [ 5863 "$ilp->VISUAL->MIN_MAX_FACE;" 5864 ] 5865 }, 5866 { 5867 "cell_type": "markdown", 5868 "metadata": {}, 5869 "source": [ 5870 "\n", 5871 "Hence the LP attains its maximal value 2 on the 2-face spanned by the vertices 6, 9 and 10.\n", 5872 "\n", 5873 "`polymake` can visualise the polytope and highlight both its maximal and minimal face in a different (by default admittedly almost painful ;-) ) colour. Here you see the maximal face `{6 9 10}` in red and the minimal face `{0 3}` (on the opposite side of the polytope) in yellow.\n", 5874 "\n", 5875 "\n", 5876 "Note though that since we started out with a random polytope these results may vary if we perform the same computations another time on a different random polytope.\n", 5877 "\n", 5878 " \n" 5879 ] 5880 }, 5881 { 5882 "cell_type": "code", 5883 "execution_count": 20, 5884 "metadata": {}, 5885 "outputs": [ 5886 { 5887 "data": { 5888 "text/plain": [ 5889 "1 -1 -1 -1\n", 5890 "1 -1 -1 0\n", 5891 "1 -1 0 -1\n", 5892 "1 -1 0 1\n", 5893 "1 -1 1 0\n", 5894 "1 0 -1 0\n", 5895 "1 0 -1 1\n", 5896 "1 0 1 -1\n", 5897 "1 0 1 1\n", 5898 "1 1 0 -1\n", 5899 "1 1 0 1\n", 5900 "1 1 1 0\n" 5901 ] 5902 }, 5903 "execution_count": 20, 5904 "metadata": {}, 5905 "output_type": "execute_result" 5906 } 5907 ], 5908 "source": [ 5909 "print $ilp->VERTICES;" 5910 ] 5911 }, 5912 { 5913 "cell_type": "markdown", 5914 "metadata": {}, 5915 "source": [ 5916 "\n", 5917 "### Hilbert bases\n", 5918 "\n", 5919 "Finally, we can have `polymake` compute and print a Hilbert basis for the cone spanned by `$ilp`. Notice that this requires normaliz or 4ti2 to be installed in order to work.\n", 5920 "\n", 5921 " \n" 5922 ] 5923 }, 5924 { 5925 "cell_type": "code", 5926 "execution_count": 21, 5927 "metadata": {}, 5928 "outputs": [ 5929 { 5930 "data": { 5931 "text/plain": [ 5932 "1 -1 -1 -1\n", 5933 "1 -1 -1 0\n", 5934 "1 -1 0 -1\n", 5935 "1 -1 0 0\n", 5936 "1 -1 0 1\n", 5937 "1 -1 1 0\n", 5938 "1 0 -1 0\n", 5939 "1 0 -1 1\n", 5940 "1 0 0 -1\n", 5941 "1 0 0 0\n", 5942 "1 0 0 1\n", 5943 "1 0 1 -1\n", 5944 "1 0 1 0\n", 5945 "1 0 1 1\n", 5946 "1 1 0 -1\n", 5947 "1 1 0 0\n", 5948 "1 1 0 1\n", 5949 "1 1 1 0\n" 5950 ] 5951 }, 5952 "execution_count": 21, 5953 "metadata": {}, 5954 "output_type": "execute_result" 5955 }, 5956 { 5957 "data": { 5958 "text/html": [ 5959 "<details><summary><pre style=\"display:inline\"><small>Click here for additional output</small></pre></summary>\n", 5960 "<pre>\n", 5961 "polymake: used package libnormaliz\n", 5962 " [[wiki:external_software#Normaliz]] is a tool for computations in affine monoids, vector configurations, lattice polytopes, and rational cones.\n", 5963 " Copyright by Winfried Bruns, Bogdan Ichim, Christof Soeger.\n", 5964 " http://www.math.uos.de/normaliz/\n", 5965 "\n", 5966 "</pre>\n", 5967 "</details>\n" 5968 ] 5969 }, 5970 "metadata": {}, 5971 "output_type": "display_data" 5972 } 5973 ], 5974 "source": [ 5975 "print $ilp->HILBERT_BASIS;" 5976 ] 5977 } 5978 ], 5979 "metadata": { 5980 "kernelspec": { 5981 "display_name": "polymake", 5982 "language": "polymake", 5983 "name": "polymake" 5984 }, 5985 "language_info": { 5986 "codemirror_mode": "perl", 5987 "file_extension": ".pl", 5988 "mimetype": "text/x-polymake", 5989 "name": "polymake" 5990 } 5991 }, 5992 "nbformat": 4, 5993 "nbformat_minor": 2 5994} 5995